diff --git a/blocks/myoverview/amd/build/main.min.js b/blocks/myoverview/amd/build/main.min.js new file mode 100644 index 00000000000..ce2592db083 --- /dev/null +++ b/blocks/myoverview/amd/build/main.min.js @@ -0,0 +1 @@ +define(["jquery","block_myoverview/view","block_myoverview/view_nav"],function(a,b,c){var d={COURSES_VIEW:'[data-region="courses-view"]',COURSES_VIEW_CONTENT:'[data-region="course-view-content"]'},e=function(e){e=a(e);var f=e.find(d.COURSES_VIEW),g=e.find(d.COURSES_VIEW_CONTENT);c.init(e,f,g),b.init(f,g)};return{init:e}}); \ No newline at end of file diff --git a/blocks/myoverview/amd/build/paging_bar.min.js b/blocks/myoverview/amd/build/paging_bar.min.js deleted file mode 100644 index 40e8b6d9b2c..00000000000 --- a/blocks/myoverview/amd/build/paging_bar.min.js +++ /dev/null @@ -1 +0,0 @@ -define(["jquery","core/custom_interaction_events"],function(a,b){var c={ROOT:'[data-region="paging-bar"]',PAGE_ITEM:'[data-region="page-item"]',ACTIVE_PAGE_ITEM:'[data-region="page-item"].active'},d={PAGE_SELECTED:"block_myoverview-paging-bar-page-selected"},e=function(a,b){return a.find(c.PAGE_ITEM+'[data-page-number="'+b+'"]')},f=function(a,b){var c=b.attr("data-page-number");return"first"==c?c=1:"last"==c&&(c=a.attr("data-page-count")),c},g=function(g){g=a(g),b.define(g,[b.events.activate]),g.on(b.events.activate,c.PAGE_ITEM,function(b,h){var i=a(b.target).closest(c.PAGE_ITEM),j=g.find(c.ACTIVE_PAGE_ITEM),k=f(g,i),l=k==f(g,j);l||(g.find(c.PAGE_ITEM).removeClass("active"),e(g,k).addClass("active")),g.trigger(d.PAGE_SELECTED,[{pageNumber:k,isSamePage:l}]),h.originalEvent.preventDefault()})};return{registerEventListeners:g,events:d,rootSelector:c.ROOT}}); \ No newline at end of file diff --git a/blocks/myoverview/amd/build/paging_content.min.js b/blocks/myoverview/amd/build/paging_content.min.js deleted file mode 100644 index 97da2cac13e..00000000000 --- a/blocks/myoverview/amd/build/paging_content.min.js +++ /dev/null @@ -1 +0,0 @@ -define(["jquery","core/templates","block_myoverview/paging_bar"],function(a,b,c){var d={ROOT:'[data-region="paging-content"]',PAGE_REGION:'[data-region="paging-content-item"]'},e=function(b,c){this.root=a(b),this.pagingBar=a(c)};return e.rootSelector=d.ROOT,e.prototype.createPage=function(a){return this.loadContent(a).then(function(a,c){b.appendNodeContents(this.root,a,c)}.bind(this)).then(function(){return this.findPage(a)}.bind(this))},e.prototype.findPage=function(a){return this.root.find('[data-page="'+a+'"]')},e.prototype.showPage=function(a){var b=this.findPage(a);this.root.find(d.PAGE_REGION).addClass("hidden"),b.length?b.removeClass("hidden"):this.createPage(a).done(function(a){a.removeClass("hidden")})},e.prototype.registerEventListeners=function(){this.pagingBar.on(c.events.PAGE_SELECTED,function(a,b){b.isSamePage||this.showPage(b.pageNumber)}.bind(this))},e}); \ No newline at end of file diff --git a/blocks/myoverview/amd/build/repository.min.js b/blocks/myoverview/amd/build/repository.min.js new file mode 100644 index 00000000000..ab272626367 --- /dev/null +++ b/blocks/myoverview/amd/build/repository.min.js @@ -0,0 +1 @@ +define(["core/ajax"],function(a){var b=function(b){var c={methodname:"core_course_get_enrolled_courses_by_timeline_classification",args:b},d=a.call([c])[0];return d};return{getEnrolledCoursesByTimeline:b}}); \ No newline at end of file diff --git a/blocks/myoverview/amd/build/view.min.js b/blocks/myoverview/amd/build/view.min.js new file mode 100644 index 00000000000..1d9b2147efd --- /dev/null +++ b/blocks/myoverview/amd/build/view.min.js @@ -0,0 +1 @@ +define(["jquery","core/notification","block_myoverview/repository","core/paged_content_factory","core/templates"],function(a,b,c,d,e){var f={COURSES_CARDS:"block_myoverview/view-cards",COURSES_LIST:"block_myoverview/view-list",COURSES_SUMMARY:"block_myoverview/view-summary",NOCOURSES:"block_myoverview/no-courses"},g=[12,24],h=[],i=function(a){var b={};return b.display=a.attr("data-display"),b.grouping=a.attr("data-grouping"),b.sort=a.attr("data-sort"),b},j={ignoreControlWhileLoading:!0,controlPlacementBottom:!0},k=function(a,b,d){return c.getEnrolledCoursesByTimeline({offset:d*b,limit:b,classification:a.grouping,sort:a.sort})},l=function(a,b,c){var d="";if(d="cards"==c.display?f.COURSES_CARDS:"list"==c.display?f.COURSES_LIST:f.COURSES_SUMMARY,b.courses.length)return e.render(d,{courses:b.courses});var g=a.attr("data-nocoursesimg");return e.render(f.NOCOURSES,{nocoursesimg:g})},m=function(c,f){c=a(c);var m=i(c),n=d.createWithLimit(g,function(a,d){var e=[];return a.forEach(function(a){var f=a.pageNumber-1,g=k(m,a.limit,f).then(function(b){return b.courses.length. + +/** + * Javascript to initialise the myoverview block. + * + * @package block_myoverview + * @copyright 2018 Bas Brands + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +define( +[ + 'jquery', + 'block_myoverview/view', + 'block_myoverview/view_nav' +], +function( + $, + View, + ViewNav +) { + + var SELECTORS = { + COURSES_VIEW: '[data-region="courses-view"]', + COURSES_VIEW_CONTENT: '[data-region="course-view-content"]' + }; + /** + * Initialise all of the modules for the overview block. + * + * @param {object} root The root element for the overview block. + */ + var init = function(root) { + root = $(root); + var coursesViewRoot = root.find(SELECTORS.COURSES_VIEW); + var coursesViewContent = root.find(SELECTORS.COURSES_VIEW_CONTENT); + // Initialise the course navigation elements. + ViewNav.init(root, coursesViewRoot, coursesViewContent); + // Initialise the courses view modules. + View.init(coursesViewRoot, coursesViewContent); + }; + + return { + init: init + }; +}); diff --git a/blocks/myoverview/amd/src/paging_bar.js b/blocks/myoverview/amd/src/paging_bar.js deleted file mode 100644 index e153e2d5762..00000000000 --- a/blocks/myoverview/amd/src/paging_bar.js +++ /dev/null @@ -1,102 +0,0 @@ -// This file is part of Moodle - http://moodle.org/ -// -// Moodle is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Moodle is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Moodle. If not, see . - -/** - * Javascript to load and render the paging bar. - * - * @module block_myoverview/paging_bar - * @package block_myoverview - * @copyright 2016 Ryan Wyllie - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -define(['jquery', 'core/custom_interaction_events'], - function($, CustomEvents) { - - var SELECTORS = { - ROOT: '[data-region="paging-bar"]', - PAGE_ITEM: '[data-region="page-item"]', - ACTIVE_PAGE_ITEM: '[data-region="page-item"].active' - }; - - var EVENTS = { - PAGE_SELECTED: 'block_myoverview-paging-bar-page-selected', - }; - - /** - * Get the page element by number. - * - * @param {object} root The root element. - * @param {Number} pageNumber The page number. - * @returns {*} - */ - var getPageByNumber = function(root, pageNumber) { - return root.find(SELECTORS.PAGE_ITEM + '[data-page-number="' + pageNumber + '"]'); - }; - - /** - * Get the page number. - * - * @param {object} root The root element. - * @param {object} page The page. - * @returns {*} the page number - */ - var getPageNumber = function(root, page) { - var pageNumber = page.attr('data-page-number'); - - if (pageNumber == 'first') { - pageNumber = 1; - } else if (pageNumber == 'last') { - pageNumber = root.attr('data-page-count'); - } - - return pageNumber; - }; - - /** - * Register event listeners for the module. - * @param {object} root The root element. - */ - var registerEventListeners = function(root) { - root = $(root); - CustomEvents.define(root, [ - CustomEvents.events.activate - ]); - - root.on(CustomEvents.events.activate, SELECTORS.PAGE_ITEM, function(e, data) { - var page = $(e.target).closest(SELECTORS.PAGE_ITEM); - var activePage = root.find(SELECTORS.ACTIVE_PAGE_ITEM); - var pageNumber = getPageNumber(root, page); - var isSamePage = pageNumber == getPageNumber(root, activePage); - - if (!isSamePage) { - root.find(SELECTORS.PAGE_ITEM).removeClass('active'); - getPageByNumber(root, pageNumber).addClass('active'); - } - - root.trigger(EVENTS.PAGE_SELECTED, [{ - pageNumber: pageNumber, - isSamePage: isSamePage, - }]); - - data.originalEvent.preventDefault(); - }); - }; - - return { - registerEventListeners: registerEventListeners, - events: EVENTS, - rootSelector: SELECTORS.ROOT, - }; -}); diff --git a/blocks/myoverview/amd/src/paging_content.js b/blocks/myoverview/amd/src/paging_content.js deleted file mode 100644 index 1e33daef02d..00000000000 --- a/blocks/myoverview/amd/src/paging_content.js +++ /dev/null @@ -1,105 +0,0 @@ -// This file is part of Moodle - http://moodle.org/ -// -// Moodle is free software: you can redistribute it and/or modify -// it under the terms of the GNU General Public License as published by -// the Free Software Foundation, either version 3 of the License, or -// (at your option) any later version. -// -// Moodle is distributed in the hope that it will be useful, -// but WITHOUT ANY WARRANTY; without even the implied warranty of -// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the -// GNU General Public License for more details. -// -// You should have received a copy of the GNU General Public License -// along with Moodle. If not, see . - -/** - * Paging content module. - * - * @module block_myoverview/paging_content - * @package block_myoverview - * @copyright 2016 Ryan Wyllie - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -define(['jquery', 'core/templates', 'block_myoverview/paging_bar'], - function($, Templates, PagingBar) { - - var SELECTORS = { - ROOT: '[data-region="paging-content"]', - PAGE_REGION: '[data-region="paging-content-item"]' - }; - - /** - * Constructor of the paging content module. - * - * @param {object} root - * @param {object} pagingBarElement - * @constructor - */ - var PagingContent = function(root, pagingBarElement) { - this.root = $(root); - this.pagingBar = $(pagingBarElement); - - }; - - PagingContent.rootSelector = SELECTORS.ROOT; - - /** - * Load content and create page. - * - * @param {Number} pageNumber - * @returns {*|Promise} - */ - PagingContent.prototype.createPage = function(pageNumber) { - - return this.loadContent(pageNumber).then(function(html, js) { - Templates.appendNodeContents(this.root, html, js); - }.bind(this)).then(function() { - return this.findPage(pageNumber); - }.bind(this) - ); - }; - - /** - * Find a page by the number. - * - * @param {Number} pageNumber The number of the page to be found. - * @returns {*} Page root - */ - PagingContent.prototype.findPage = function(pageNumber) { - return this.root.find('[data-page="' + pageNumber + '"]'); - }; - - /** - * Make a page visible. - * - * @param {Number} pageNumber The number of the page to be visible. - */ - PagingContent.prototype.showPage = function(pageNumber) { - - var existingPage = this.findPage(pageNumber); - this.root.find(SELECTORS.PAGE_REGION).addClass('hidden'); - - if (existingPage.length) { - existingPage.removeClass('hidden'); - } else { - this.createPage(pageNumber).done(function(newPage) { - newPage.removeClass('hidden'); - }); - } - }; - - /** - * Event listeners. - */ - PagingContent.prototype.registerEventListeners = function() { - - this.pagingBar.on(PagingBar.events.PAGE_SELECTED, function(e, data) { - if (!data.isSamePage) { - this.showPage(data.pageNumber); - } - }.bind(this)); - }; - - return PagingContent; -}); diff --git a/blocks/myoverview/amd/src/repository.js b/blocks/myoverview/amd/src/repository.js new file mode 100644 index 00000000000..b4f7b5d83e5 --- /dev/null +++ b/blocks/myoverview/amd/src/repository.js @@ -0,0 +1,53 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * A javascript module to retrieve enrolled coruses from the server. + * + * @package block_myoverview + * @copyright 2018 Bas Brands + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ +define(['core/ajax'], function(Ajax) { + + /** + * Retrieve a list of enrolled courses. + * + * Valid args are: + * string classification future, inprogress, past + * int limit number of records to retreive + * int Offset offset for pagination + * int sort sort by lastaccess or name + * + * @method getEnrolledCoursesByTimeline + * @param {object} args The request arguments + * @return {promise} Resolved with an array of courses + */ + var getEnrolledCoursesByTimeline = function(args) { + + var request = { + methodname: 'core_course_get_enrolled_courses_by_timeline_classification', + args: args + }; + + var promise = Ajax.call([request])[0]; + + return promise; + }; + + return { + getEnrolledCoursesByTimeline: getEnrolledCoursesByTimeline + }; +}); diff --git a/blocks/myoverview/amd/src/view.js b/blocks/myoverview/amd/src/view.js new file mode 100644 index 00000000000..b6b6c626dff --- /dev/null +++ b/blocks/myoverview/amd/src/view.js @@ -0,0 +1,188 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Manage the courses view for the overview block. + * + * @package block_myoverview + * @copyright 2018 Bas Brands + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +define( +[ + 'jquery', + 'core/notification', + 'block_myoverview/repository', + 'core/paged_content_factory', + 'core/templates', +], +function( + $, + Notification, + Repository, + PagedContentFactory, + Templates +) { + + var TEMPLATES = { + COURSES_CARDS: 'block_myoverview/view-cards', + COURSES_LIST: 'block_myoverview/view-list', + COURSES_SUMMARY: 'block_myoverview/view-summary', + NOCOURSES: 'block_myoverview/no-courses' + }; + + var NUMCOURSES_PERPAGE = [12, 24]; + + var currentCourseList = []; + + /** + * Get filter values from DOM. + * + * @param {object} root The root element for the courses view. + * @return {filters} Set filters. + */ + var getFilterValues = function(root) { + var filters = {}; + filters.display = root.attr('data-display'); + filters.grouping = root.attr('data-grouping'); + filters.sort = root.attr('data-sort'); + return filters; + }; + + // We want the paged content controls below the paged content area + // and the controls should be ignored while data is loading. + var DEFAULT_PAGED_CONTENT_CONFIG = { + ignoreControlWhileLoading: true, + controlPlacementBottom: true, + }; + + /** + * Get enrolled courses from backend. + * + * @param {object} filters The filters for this view. + * @param {int} limit The number of courses to show. + * @param {int} pageNumber The pagenumber to view. + * @return {promise} Resolved with an array of courses. + */ + var getMyCourses = function(filters, limit, pageNumber) { + return Repository.getEnrolledCoursesByTimeline({ + offset: pageNumber * limit, + limit: limit, + classification: filters.grouping, + sort: filters.sort + }); + }; + + /** + * Render the dashboard courses. + * + * @param {object} root The root element for the courses view. + * @param {array} coursesData containing array of returned courses. + * @param {object} filters The filters for this view. + * @return {promise} jQuery promise resolved after rendering is complete. + */ + var renderCourses = function(root, coursesData, filters) { + + var currentTemplate = ''; + if (filters.display == 'cards') { + currentTemplate = TEMPLATES.COURSES_CARDS; + } else if (filters.display == 'list') { + currentTemplate = TEMPLATES.COURSES_LIST; + } else { + currentTemplate = TEMPLATES.COURSES_SUMMARY; + } + + if (coursesData.courses.length) { + return Templates.render(currentTemplate, { + courses: coursesData.courses + }); + } else { + var nocoursesimg = root.attr('data-nocoursesimg'); + return Templates.render(TEMPLATES.NOCOURSES, { + nocoursesimg: nocoursesimg + }); + } + }; + + /** + * Intialise the courses list and cards views on page load. + * + * @param {object} root The root element for the courses view. + * @param {object} content The content element for the courses view. + */ + var init = function(root, content) { + + root = $(root); + + var filters = getFilterValues(root); + + var pagedContentPromise = PagedContentFactory.createWithLimit( + NUMCOURSES_PERPAGE, + function(pagesData, actions) { + var promises = []; + + pagesData.forEach(function(pageData) { + var pageNumber = pageData.pageNumber - 1; + + var pagePromise = getMyCourses( + filters, + pageData.limit, + pageNumber + ).then(function(coursesData) { + if (coursesData.courses.length < pageData.limit) { + actions.allItemsLoaded(pageData.pageNumber); + } + currentCourseList = coursesData; + return renderCourses(root, coursesData, filters); + }) + .catch(Notification.exception); + + promises.push(pagePromise); + }); + + return promises; + }, + DEFAULT_PAGED_CONTENT_CONFIG + ); + + pagedContentPromise.then(function(html, js) { + return Templates.replaceNodeContents(content, html, js); + }).catch(Notification.exception); + }; + + /** + * Reset the courses views to their original + * state on first page load. + * + * This is called when configuration has changed for the event lists + * to cause them to reload their data. + * + * @param {object} root The root element for the timeline view. + * @param {object} content The content element for the timeline view. + */ + var reset = function(root, content) { + var filters = getFilterValues(root); + renderCourses(root, currentCourseList, filters) + .then(function(html, js) { + return Templates.replaceNodeContents(content, html, js); + }).catch(Notification.exception); + }; + + return { + init: init, + reset: reset + }; +}); diff --git a/blocks/myoverview/amd/src/view_nav.js b/blocks/myoverview/amd/src/view_nav.js new file mode 100644 index 00000000000..131c3865f5a --- /dev/null +++ b/blocks/myoverview/amd/src/view_nav.js @@ -0,0 +1,109 @@ +// This file is part of Moodle - http://moodle.org/ +// +// Moodle is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, either version 3 of the License, or +// (at your option) any later version. +// +// Moodle is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License for more details. +// +// You should have received a copy of the GNU General Public License +// along with Moodle. If not, see . + +/** + * Manage the timeline view navigation for the overview block. + * + * @package block_myoverview + * @copyright 2018 Bas Brands + * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later + */ + +define( +[ + 'jquery', + 'core/custom_interaction_events', + 'block_myoverview/view' +], +function( + $, + CustomEvents, + View +) { + + var SELECTORS = { + FILTERS: '[data-region="filter"]', + FILTER_OPTION: '[data-filter]', + DISPLAY_OPTION: '[data-display-option]' + }; + + /** + * Event listener for the Display filter (cards, list). + * + * @param {object} root The root element for the overview block + * @param {object} viewRoot The root element for displaying courses. + * @param {object} viewContent content The content element for the courses view. + */ + var registerSelector = function(root, viewRoot, viewContent) { + + var Selector = root.find(SELECTORS.FILTERS); + + CustomEvents.define(Selector, [CustomEvents.events.activate]); + Selector.on( + CustomEvents.events.activate, + SELECTORS.FILTER_OPTION, + function(e, data) { + var option = $(e.target); + + if (option.hasClass('active')) { + // If it's already active then we don't need to do anything. + return; + } + + var attributename = 'data-' + option.attr('data-filter'); + viewRoot.attr(attributename, option.attr('data-value')); + + // Reset the views. + View.init(viewRoot, viewContent); + + data.originalEvent.preventDefault(); + } + ); + + CustomEvents.define(Selector, [CustomEvents.events.activate]); + Selector.on( + CustomEvents.events.activate, + SELECTORS.DISPLAY_OPTION, + function(e, data) { + var option = $(e.target); + + if (option.hasClass('active')) { + return; + } + + viewRoot.attr('data-display', option.attr('data-value')); + View.reset(viewRoot, viewContent); + data.originalEvent.preventDefault(); + } + ); + }; + + /** + * Initialise the timeline view navigation by adding event listeners to + * the navigation elements. + * + * @param {object} root The root element for the myoverview block + * @param {object} viewRoot The root element for the myoverview block + * @param {object} viewContent The content element for the myoverview block + */ + var init = function(root, viewRoot, viewContent) { + root = $(root); + registerSelector(root, viewRoot, viewContent); + }; + + return { + init: init + }; +}); diff --git a/blocks/myoverview/classes/output/courses_view.php b/blocks/myoverview/classes/output/courses_view.php deleted file mode 100644 index 2c6027e0436..00000000000 --- a/blocks/myoverview/classes/output/courses_view.php +++ /dev/null @@ -1,189 +0,0 @@ -. - -/** - * Class containing data for courses view in the myoverview block. - * - * @package block_myoverview - * @copyright 2017 Ryan Wyllie - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -namespace block_myoverview\output; -defined('MOODLE_INTERNAL') || die(); - -use renderable; -use renderer_base; -use templatable; -use core_course\external\course_summary_exporter; - -/** - * Class containing data for courses view in the myoverview block. - * - * @copyright 2017 Simey Lameze - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ -class courses_view implements renderable, templatable { - /** Quantity of courses per page. */ - const COURSES_PER_PAGE = 6; - - /** @var array $courses List of courses the user is enrolled in. */ - protected $courses = []; - - /** @var array $coursesprogress List of progress percentage for each course. */ - protected $coursesprogress = []; - - /** - * The courses_view constructor. - * - * @param array $courses list of courses. - * @param array $coursesprogress list of courses progress. - */ - public function __construct($courses, $coursesprogress) { - $this->courses = $courses; - $this->coursesprogress = $coursesprogress; - } - - /** - * Export this data so it can be used as the context for a mustache template. - * - * @param \renderer_base $output - * @return array - */ - public function export_for_template(renderer_base $output) { - global $CFG; - require_once($CFG->dirroot.'/course/lib.php'); - - // Build courses view data structure. - $coursesview = [ - 'hascourses' => !empty($this->courses) - ]; - - // How many courses we have per status? - $coursesbystatus = ['past' => 0, 'inprogress' => 0, 'future' => 0]; - foreach ($this->courses as $course) { - $courseid = $course->id; - $context = \context_course::instance($courseid); - $exporter = new course_summary_exporter($course, [ - 'context' => $context - ]); - $exportedcourse = $exporter->export($output); - // Convert summary to plain text. - $exportedcourse->summary = content_to_text($exportedcourse->summary, $exportedcourse->summaryformat); - - $course = new \core_course_list_element($course); - foreach ($course->get_course_overviewfiles() as $file) { - $isimage = $file->is_valid_image(); - if ($isimage) { - $url = file_encode_url("$CFG->wwwroot/pluginfile.php", - '/'. $file->get_contextid(). '/'. $file->get_component(). '/'. - $file->get_filearea(). $file->get_filepath(). $file->get_filename(), !$isimage); - $exportedcourse->courseimage = $url; - $exportedcourse->classes = 'courseimage'; - break; - } - } - - $exportedcourse->color = $this->coursecolor($course->id); - - if (!isset($exportedcourse->courseimage)) { - $pattern = new \core_geopattern(); - $pattern->setColor($exportedcourse->color); - $pattern->patternbyid($courseid); - $exportedcourse->classes = 'coursepattern'; - $exportedcourse->courseimage = $pattern->datauri(); - } - - // Include course visibility. - $exportedcourse->visible = (bool)$course->visible; - - $courseprogress = null; - - $classified = course_classify_for_timeline($course); - - if (isset($this->coursesprogress[$courseid])) { - $courseprogress = $this->coursesprogress[$courseid]['progress']; - $exportedcourse->hasprogress = !is_null($courseprogress); - $exportedcourse->progress = $courseprogress; - } - - if ($classified == COURSE_TIMELINE_PAST) { - // Courses that have already ended. - $pastpages = floor($coursesbystatus['past'] / $this::COURSES_PER_PAGE); - - $coursesview['past']['pages'][$pastpages]['courses'][] = $exportedcourse; - $coursesview['past']['pages'][$pastpages]['active'] = ($pastpages == 0 ? true : false); - $coursesview['past']['pages'][$pastpages]['page'] = $pastpages + 1; - $coursesview['past']['haspages'] = true; - $coursesbystatus['past']++; - } else if ($classified == COURSE_TIMELINE_FUTURE) { - // Courses that have not started yet. - $futurepages = floor($coursesbystatus['future'] / $this::COURSES_PER_PAGE); - - $coursesview['future']['pages'][$futurepages]['courses'][] = $exportedcourse; - $coursesview['future']['pages'][$futurepages]['active'] = ($futurepages == 0 ? true : false); - $coursesview['future']['pages'][$futurepages]['page'] = $futurepages + 1; - $coursesview['future']['haspages'] = true; - $coursesbystatus['future']++; - } else { - // Courses still in progress. Either their end date is not set, or the end date is not yet past the current date. - $inprogresspages = floor($coursesbystatus['inprogress'] / $this::COURSES_PER_PAGE); - - $coursesview['inprogress']['pages'][$inprogresspages]['courses'][] = $exportedcourse; - $coursesview['inprogress']['pages'][$inprogresspages]['active'] = ($inprogresspages == 0 ? true : false); - $coursesview['inprogress']['pages'][$inprogresspages]['page'] = $inprogresspages + 1; - $coursesview['inprogress']['haspages'] = true; - $coursesbystatus['inprogress']++; - } - } - - // Build courses view paging bar structure. - foreach ($coursesbystatus as $status => $total) { - $quantpages = ceil($total / $this::COURSES_PER_PAGE); - - if ($quantpages) { - $coursesview[$status]['pagingbar']['disabled'] = ($quantpages <= 1); - $coursesview[$status]['pagingbar']['pagecount'] = $quantpages; - $coursesview[$status]['pagingbar']['first'] = ['page' => '«', 'url' => '#']; - $coursesview[$status]['pagingbar']['last'] = ['page' => '»', 'url' => '#']; - for ($page = 0; $page < $quantpages; $page++) { - $coursesview[$status]['pagingbar']['pages'][$page] = [ - 'number' => $page + 1, - 'page' => $page + 1, - 'url' => '#', - 'active' => ($page == 0 ? true : false) - ]; - } - } - } - - return $coursesview; - } - - /** - * Generate a semi-random color based on the courseid number (so it will always return - * the same color for a course) - * - * @param int $courseid - * @return string $color, hexvalue color code. - */ - protected function coursecolor($courseid) { - // The colour palette is hardcoded for now. It would make sense to combine it with theme settings. - $basecolors = ['#81ecec', '#74b9ff', '#a29bfe', '#dfe6e9', '#00b894', '#0984e3', '#b2bec3', '#fdcb6e', '#fd79a8', '#6c5ce7']; - - $color = $basecolors[$courseid % 10]; - return $color; - } -} diff --git a/blocks/myoverview/classes/output/main.php b/blocks/myoverview/classes/output/main.php index 46834f318b3..c734468c192 100644 --- a/blocks/myoverview/classes/output/main.php +++ b/blocks/myoverview/classes/output/main.php @@ -27,14 +27,13 @@ defined('MOODLE_INTERNAL') || die(); use renderable; use renderer_base; use templatable; -use core_completion\progress; require_once($CFG->libdir . '/completionlib.php'); /** * Class containing data for my overview block. * - * @copyright 2017 Simey Lameze + * @copyright 2018 Bas Brands * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ class main implements renderable, templatable { @@ -45,38 +44,11 @@ class main implements renderable, templatable { * @return stdClass */ public function export_for_template(renderer_base $output) { - global $USER; - $courses = enrol_get_my_courses('*'); - $coursesprogress = []; - - foreach ($courses as $course) { - - $completion = new \completion_info($course); - - // First, let's make sure completion is enabled. - if (!$completion->is_enabled()) { - continue; - } - - $percentage = progress::get_course_progress_percentage($course); - if (!is_null($percentage)) { - $percentage = floor($percentage); - } - - $coursesprogress[$course->id]['completed'] = $completion->is_course_complete($USER->id); - $coursesprogress[$course->id]['progress'] = $percentage; - } - - $coursesview = new courses_view($courses, $coursesprogress); $nocoursesurl = $output->image_url('courses', 'block_myoverview')->out(); - return [ - 'midnight' => usergetmidnight(time()), - 'coursesview' => $coursesview->export_for_template($output), - 'urls' => [ - 'nocourses' => $nocoursesurl, - ], + return (object) [ + 'nocoursesimg' => $nocoursesurl ]; } } diff --git a/blocks/myoverview/db/upgrade.php b/blocks/myoverview/db/upgrade.php deleted file mode 100644 index b91cb9613a3..00000000000 --- a/blocks/myoverview/db/upgrade.php +++ /dev/null @@ -1,41 +0,0 @@ -. - -/** - * This file keeps track of upgrades to the myoverview block - * - * @package block_myoverview - * @copyright 2018 Ryan Wyllie - * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later - */ - -defined('MOODLE_INTERNAL') || die(); - -/** - * Upgrade code for the myoverview block. - * - * @param int $oldversion - */ -function xmldb_block_myoverview_upgrade($oldversion) { - global $DB; - - if ($oldversion < 2018092700) { - $DB->delete_records('user_preferences', ['name' => 'block_myoverview_last_tab']); - upgrade_block_savepoint(true, 2018092700, 'myoverview'); - } - - return true; -} diff --git a/blocks/myoverview/lang/en/block_myoverview.php b/blocks/myoverview/lang/en/block_myoverview.php index df3ae6652b4..49fe21c2907 100644 --- a/blocks/myoverview/lang/en/block_myoverview.php +++ b/blocks/myoverview/lang/en/block_myoverview.php @@ -22,17 +22,48 @@ * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ +$string['all'] = 'All'; +$string['aria:allcourses'] = 'All courses'; +$string['aria:card'] = 'Switch to card view'; +$string['aria:controls'] = 'Course overview controls'; +$string['aria:courseimage'] = 'Course image:'; +$string['aria:coursename'] = 'Course name:'; +$string['aria:coursesummary'] = 'Course summary text:'; +$string['aria:courseprogress'] = 'Course progress:'; +$string['aria:displaydropdown'] = 'Display dropdown'; +$string['aria:future'] = 'Show future courses'; +$string['aria:groupingdropdown'] = 'Grouping dropdown'; +$string['aria:inprogress'] = 'Show in courses in progress'; +$string['aria:lastaccessed'] = 'Sort courses by last accessed date'; +$string['aria:list'] = 'Switch to list view'; +$string['aria:title'] = 'Sort courses by title'; +$string['aria:past'] = 'Show past courses'; +$string['aria:summary'] = 'Switch to summary view'; +$string['aria:sortingdropdown'] = 'Sorting dropdown'; +$string['card'] = 'Card'; +$string['courseprogress'] = 'Course progress:'; +$string['complete'] = 'Complete'; +$string['favorite'] = 'Favorite'; $string['future'] = 'Future'; +$string['future:aria'] = 'View future courses'; +$string['hidden'] = 'Hidden'; $string['inprogress'] = 'In progress'; +$string['inprogress:aria'] = 'View in progress courses'; +$string['lastaccessed'] = 'Last accessed'; +$string['lastaccessed:aria'] = 'Sort course by lastaccessed'; +$string['list'] = 'List'; $string['morecourses'] = 'More courses'; $string['myoverview:addinstance'] = 'Add a new course overview block'; $string['myoverview:myaddinstance'] = 'Add a new course overview block to Dashboard'; -$string['nocourses'] = 'No courses'; -$string['nocoursesinprogress'] = 'No in progress courses'; $string['nocoursesfuture'] = 'No future courses'; +$string['nocoursesinprogress'] = 'No in progress courses'; +$string['nocourses'] = 'No courses'; $string['nocoursespast'] = 'No past courses'; $string['past'] = 'Past'; $string['pluginname'] = 'Course overview'; -$string['viewcourse'] = 'View course'; -$string['viewcoursename'] = 'View course {$a}'; $string['privacy:metadata'] = 'The myoverview block does not store any personal data.'; +$string['summary'] = 'Summary'; +$string['title'] = 'Title'; +$string['viewcoursename'] = 'View course {$a}'; +$string['viewcourse'] = 'View course'; + diff --git a/blocks/myoverview/templates/course-paging-content-item.mustache b/blocks/myoverview/templates/course-paging-content-item.mustache deleted file mode 100644 index bbaa63715af..00000000000 --- a/blocks/myoverview/templates/course-paging-content-item.mustache +++ /dev/null @@ -1,47 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template block_myoverview/course-paging-content-item - - This template renders each course block. - - Example context (json): - { - "page": 1, - "active": true, - "courses": [ - { - "fullnamedisplay": "course 1", - "viewurl": "https://www.google.com", - "summary": "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout." - }, - { - "fullnamedisplay": "course 2", - "viewurl": "https://www.google.com", - "summary": "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout." - } - ] - } -}} -{{< block_myoverview/paging-content-item }} - {{$classes}}row card-deck{{/classes}} - {{$content}} - {{#courses}} - {{> block_myoverview/courses-view-course-item }} - {{/courses}} - {{/content}} -{{/ block_myoverview/paging-content-item }} diff --git a/blocks/myoverview/templates/course-paging-content.mustache b/blocks/myoverview/templates/course-paging-content.mustache deleted file mode 100644 index 85ee437df13..00000000000 --- a/blocks/myoverview/templates/course-paging-content.mustache +++ /dev/null @@ -1,48 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template block_myoverview/course-paging-content - - This template renders the each course block containing a summary and calendar events. - - Example context (json): - { - "pages": [ - { - "page": 1, - "active": true, - "courses": [ - { - "fullnamedisplay": "course 1", - "viewurl": "https://www.google.com", - "summary": "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout." - }, - { - "fullnamedisplay": "course 2", - "viewurl": "https://www.google.com", - "summary": "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout." - } - ] - } - ] - } -}} -{{< block_myoverview/paging-content }} - {{$paging-content-item}} - {{> block_myoverview/course-paging-content-item }} - {{/paging-content-item}} -{{/ block_myoverview/paging-content }} diff --git a/blocks/myoverview/templates/courses-view-by-status.mustache b/blocks/myoverview/templates/courses-view-by-status.mustache deleted file mode 100644 index 3360d55db46..00000000000 --- a/blocks/myoverview/templates/courses-view-by-status.mustache +++ /dev/null @@ -1,45 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template block_myoverview/courses-view-by-status - - This template renders the courses view for the myoverview block. - - Example context (json): - {} -}} -
- - {{> block_myoverview/course-paging-content }} - -
- {{> block_myoverview/paging-bar }} -
-
-{{#js}} -require(['jquery', 'block_myoverview/paging_bar', 'block_myoverview/paging_content'], - function($, PagingBar, PagingContent) { - - var root = $('#{{$id}}courses-view-status-{{uniqid}}{{/id}}'); - var pagingBarElement = root.find(PagingBar.rootSelector); - var pagingContentElement = root.find(PagingContent.rootSelector); - - var content = new PagingContent(pagingContentElement, pagingBarElement); - content.registerEventListeners(); -}); -{{/js}} diff --git a/blocks/myoverview/templates/courses-view-course-item.mustache b/blocks/myoverview/templates/courses-view-course-item.mustache deleted file mode 100644 index db2034d70fc..00000000000 --- a/blocks/myoverview/templates/courses-view-course-item.mustache +++ /dev/null @@ -1,49 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template block_myoverview/courses-view-course-item - - This template renders the course summary (view by courses) for the myoverview block. - - Example context (json): - { - "fullnamedisplay": "course 3", - "viewurl": "https://www.google.com", - "summary": "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout." - } -}} -
- -
-
-
-
- -
-
- {{> block_myoverview/progress-chart}} -
- -
- -

- {{#shortentext}} 140, {{summary}}{{/shortentext}} -

-
-
\ No newline at end of file diff --git a/blocks/myoverview/templates/courses-view-nav-grouping-display-filter.mustache b/blocks/myoverview/templates/courses-view-nav-grouping-display-filter.mustache deleted file mode 100644 index f7aa27534b4..00000000000 --- a/blocks/myoverview/templates/courses-view-nav-grouping-display-filter.mustache +++ /dev/null @@ -1,40 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template block_myoverview/courses-view-nav-grouping-display-filter - - This template renders the main content area for the myoverview block. - - Example context (json): - {} -}} - diff --git a/blocks/myoverview/templates/courses-view.mustache b/blocks/myoverview/templates/courses-view.mustache index cb5b9261a5f..ab97aa4b5e3 100644 --- a/blocks/myoverview/templates/courses-view.mustache +++ b/blocks/myoverview/templates/courses-view.mustache @@ -20,77 +20,24 @@ This template renders the courses view for the myoverview block. Example context (json): - {} + { + "nocoursesimg": "https://moodlesite/theme/image.php/boost/block_myoverview/1535727318/courses" + } }} -
- {{#hascourses}} -
-
- {{#inprogress}} - {{< block_myoverview/courses-view-by-status }} - {{$id}}courses-view-in-progress{{/id}} - {{$status}}1{{/status}} - {{$pagingbarid}}pb-for-in-progress{{/pagingbarid}} - {{$pagingcontentid}}pc-for-in-progress{{/pagingcontentid}} - {{/ block_myoverview/courses-view-by-status }} - {{/inprogress}} - {{^inprogress}} -
- {{#str}} nocoursesinprogress, block_myoverview {{/str}} -

{{#str}} nocoursesinprogress, block_myoverview {{/str}}

-
- {{/inprogress}} -
-
- {{#future}} - {{< block_myoverview/courses-view-by-status }} - {{$id}}courses-view-future{{/id}} - {{$status}}2{{/status}} - {{$pagingbarid}}pb-for-future{{/pagingbarid}} - {{$pagingcontentid}}pc-for-in-progress{{/pagingcontentid}} - {{/ block_myoverview/courses-view-by-status }} - {{/future}} - {{^future}} -
- {{#str}} nocoursesfuture, block_myoverview {{/str}} -

{{#str}} nocoursesfuture, block_myoverview {{/str}}

-
- {{/future}} -
-
- {{#past}} - {{< block_myoverview/courses-view-by-status }} - {{$id}}courses-view-past{{/id}} - {{$status}}0{{/status}} - {{$pagingbarid}}pb-for-past{{/pagingbarid}} - {{$pagingcontentid}}pc-for-in-progress{{/pagingcontentid}} - {{/ block_myoverview/courses-view-by-status }} - {{/past}} - {{^past}} -
- {{#str}} nocoursespast, block_myoverview {{/str}} -

{{#str}} nocoursespast, block_myoverview {{/str}}

-
- {{/past}} +
+
+
+
+ {{> block_myoverview/placeholder-course }} + {{> block_myoverview/placeholder-course }} + {{> block_myoverview/placeholder-course }} + {{> block_myoverview/placeholder-course }} +
- {{/hascourses}} - {{^hascourses}} -
- {{#str}} nocourses, block_myoverview {{/str}} -

{{#str}} nocourses, block_myoverview {{/str}}

-
- {{/hascourses}} -
\ No newline at end of file +
diff --git a/blocks/myoverview/templates/main.mustache b/blocks/myoverview/templates/main.mustache index fef8e9f3db9..1d593e8da46 100644 --- a/blocks/myoverview/templates/main.mustache +++ b/blocks/myoverview/templates/main.mustache @@ -23,21 +23,31 @@ {} }} -
-
-
- {{#coursesview}} - {{#hascourses}} -
- {{> block_myoverview/courses-view-nav-grouping-display-filter }} -
- {{/hascourses}} - {{/coursesview}} -
-
-
- {{#coursesview}} + +{{#js}} +require( +[ + 'jquery', + 'block_myoverview/main', +], +function( + $, + Main +) { + var root = $('#block-myoverview-{{uniqid}}'); + Main.init(root); +}); +{{/js}} diff --git a/blocks/myoverview/templates/nav-display-selector.mustache b/blocks/myoverview/templates/nav-display-selector.mustache new file mode 100644 index 00000000000..e5661dcc473 --- /dev/null +++ b/blocks/myoverview/templates/nav-display-selector.mustache @@ -0,0 +1,47 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template block_myoverview/nav-display-selector + + This template renders display dropdown. + + Example context (json): + {} +}} + \ No newline at end of file diff --git a/blocks/myoverview/templates/nav-grouping-selector.mustache b/blocks/myoverview/templates/nav-grouping-selector.mustache new file mode 100644 index 00000000000..ac57aa7bb3b --- /dev/null +++ b/blocks/myoverview/templates/nav-grouping-selector.mustache @@ -0,0 +1,51 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template block_myoverview/nav-grouping-selector + + This template renders grouping dropdown. + + Example context (json): + {} +}} + diff --git a/blocks/myoverview/templates/nav-sort-selector.mustache b/blocks/myoverview/templates/nav-sort-selector.mustache new file mode 100644 index 00000000000..e647be94e50 --- /dev/null +++ b/blocks/myoverview/templates/nav-sort-selector.mustache @@ -0,0 +1,43 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template block_myoverview/nav-sort-selector + + This template renders sorting dropdown. + + Example context (json): + {} +}} + + \ No newline at end of file diff --git a/blocks/myoverview/templates/paging-bar-item.mustache b/blocks/myoverview/templates/no-courses.mustache similarity index 57% rename from blocks/myoverview/templates/paging-bar-item.mustache rename to blocks/myoverview/templates/no-courses.mustache index 955ff02d991..46fab9f1ffe 100644 --- a/blocks/myoverview/templates/paging-bar-item.mustache +++ b/blocks/myoverview/templates/no-courses.mustache @@ -15,27 +15,19 @@ along with Moodle. If not, see . }} {{! - @template block_myoverview/paging-bar-item + @template block_myoverview/no-courses - This template renders a single item in the paging bar. + This template renders the no courses message. Example context (json): { - "url": "#", - "number": 1, - "page": "1", - "active": true + "nocoursesimg": "https://moodlesite/theme/image.php/boost/block_myoverview/1535727318/courses" } }} -
  • - - - {{$item-content}} - {{{page}}} - {{/item-content}} - -
  • +
    + {{#str}} nocourses, block_myoverview {{/str}} +

    {{#str}} nocourses, block_myoverview {{/str}}

    +
    \ No newline at end of file diff --git a/blocks/myoverview/templates/paging-bar.mustache b/blocks/myoverview/templates/paging-bar.mustache deleted file mode 100644 index 71ffecffcd4..00000000000 --- a/blocks/myoverview/templates/paging-bar.mustache +++ /dev/null @@ -1,96 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template block_myoverview/paging-bar - - This template renders the bootstrap style paging bar. - - Example context (json): - { - "pagingbar": { - "pagecount": 2, - "previous": {}, - "next": {}, - "first": { - "url": "#", - "page": "first" - }, - "last": { - "url": "#", - "page": "last" - }, - "pages": [ - { - "url": "#", - "number": 1, - "page": "1", - "active": true - }, - { - "url": "#", - "number": 2, - "page": "2" - } - ] - } - } -}} -{{#pagingbar}} - -{{#js}} -require(['jquery', 'block_myoverview/paging_bar'], function($, PagingBar) { - var root = $('#{{$pagingbarid}}paging-bar-{{uniqid}}{{/pagingbarid}}'); - PagingBar.registerEventListeners(root); -}); -{{/js}} -{{/pagingbar}} diff --git a/blocks/myoverview/templates/paging-content.mustache b/blocks/myoverview/templates/paging-content.mustache deleted file mode 100644 index 83a9cdd799b..00000000000 --- a/blocks/myoverview/templates/paging-content.mustache +++ /dev/null @@ -1,44 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template block_myoverview/paging-content - - This template renders each of the content regions for a paginated - content section. - - Example context (json): - { - "pages": [ - { - "active": true, - "page": 1, - "content": "

    Some page content

    " - }, - { - "page": 2, - "content": "

    Some page content

    " - } - ] - } -}} -
    - {{#pages}} - {{$paging-content-item}} - {{> block_myoverview/paging-content-item }} - {{/paging-content-item}} - {{/pages}} -
    diff --git a/theme/bootstrapbase/templates/block_myoverview/paging-content-item.mustache b/blocks/myoverview/templates/placeholder-course.mustache similarity index 59% rename from theme/bootstrapbase/templates/block_myoverview/paging-content-item.mustache rename to blocks/myoverview/templates/placeholder-course.mustache index b70a1d25034..9b4aad34f80 100644 --- a/theme/bootstrapbase/templates/block_myoverview/paging-content-item.mustache +++ b/blocks/myoverview/templates/placeholder-course.mustache @@ -15,22 +15,19 @@ along with Moodle. If not, see . }} {{! - @template block_myoverview/paging-content-item + @template block_myoverview/placeholder-course - This template renders the content of a page. It is to be used with - the paging bar to toggle visibility of the content items. + This template renders an course card item loading placeholder for the myoverview block. Example context (json): - { - "active": true, - "page": 1, - "content": "

    Some page content

    " - } + {} }} -
    - {{$content}} - {{{content}}} - {{/content}} -
    +
    +
    +
    +
    +
    +
    +
    +
    +
    \ No newline at end of file diff --git a/blocks/myoverview/templates/paging-content-item.mustache b/blocks/myoverview/templates/progress-bar.mustache similarity index 60% rename from blocks/myoverview/templates/paging-content-item.mustache rename to blocks/myoverview/templates/progress-bar.mustache index 82e73e19bde..c95f8c9f1a5 100644 --- a/blocks/myoverview/templates/paging-content-item.mustache +++ b/blocks/myoverview/templates/progress-bar.mustache @@ -15,22 +15,20 @@ along with Moodle. If not, see . }} {{! - @template block_myoverview/paging-content-item + @template block_myoverview/progress-bar - This template renders the content of a page. It is to be used with - the paging bar to toggle visibility of the content items. + This template renders a simple progress bar. Example context (json): { - "active": true, - "page": 1, - "content": "

    Some page content

    " + "progress": 50 } }} -
    - {{$content}} - {{{content}}} - {{/content}} + +
    +
    +
    + {{#str}}aria:courseprogress, block_myoverview{{/str}} + {{progress}}% {{#str}}complete, block_myoverview{{/str}} +
    \ No newline at end of file diff --git a/blocks/myoverview/templates/progress-chart.mustache b/blocks/myoverview/templates/progress-chart.mustache deleted file mode 100644 index 18ff2a40890..00000000000 --- a/blocks/myoverview/templates/progress-chart.mustache +++ /dev/null @@ -1,50 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template block_myoverview/progress-chart - - This template renders a doughnut chart to show course progress. - - Example context (json): - { - "hasprogress": true, - "progress": "60" - } -}} -
    - {{#hasprogress}} -
    -
    {{progress}}%
    -
    - - - - - - -
    -
    - {{/hasprogress}} - {{^hasprogress}} -
    - {{#pix}} i/course {{/pix}} -
    - {{/hasprogress}} -
    diff --git a/blocks/myoverview/templates/view-cards.mustache b/blocks/myoverview/templates/view-cards.mustache new file mode 100644 index 00000000000..8b0eaa312c8 --- /dev/null +++ b/blocks/myoverview/templates/view-cards.mustache @@ -0,0 +1,62 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template block_myoverview/view-cards + + This template renders the cards view for the myoverview block. + + Example context (json): + { + "courses": [ + { + "name": "Assignment due 1", + "viewurl": "https://moodlesite/course/view.php?id=2", + "courseimage": "https://moodlesite/pluginfile/123/course/overviewfiles/123.jpg", + "fullname": "course 3", + "hasprogress": true, + "progress": 10 + } + ] + } +}} + +
    +{{#courses}} + +{{/courses}} +
    \ No newline at end of file diff --git a/blocks/myoverview/templates/view-list.mustache b/blocks/myoverview/templates/view-list.mustache new file mode 100644 index 00000000000..799c5246c8e --- /dev/null +++ b/blocks/myoverview/templates/view-list.mustache @@ -0,0 +1,55 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template block_myoverview/view-list + + This template renders the list view for the myoverview block. + + Example context (json): + { + "courses": [ + { + "name": "Assignment due 1", + "viewurl": "https://moodlesite/course/view.php?id=2", + "courseimage": "https://moodlesite/pluginfile/123/course/overviewfiles/123.jpg", + "fullname": "course 3", + "hasprogress": true, + "progress": 10 + } + ] + } +}} + + \ No newline at end of file diff --git a/blocks/myoverview/templates/view-summary.mustache b/blocks/myoverview/templates/view-summary.mustache new file mode 100644 index 00000000000..8f9531c50c7 --- /dev/null +++ b/blocks/myoverview/templates/view-summary.mustache @@ -0,0 +1,62 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template block_myoverview/view-summary + + This template renders the list view for the myoverview block. + + Example context (json): + { + "courses": [ + { + "name": "Assignment due 1", + "viewurl": "https://moodlesite/course/view.php?id=2", + "courseimage": "https://moodlesite/pluginfile/123/course/overviewfiles/123.jpg", + "fullname": "course 3", + "summary": "This course is about assignments", + "hasprogress": true, + "progress": 10 + } + ] + } +}} +
    +{{#courses}} +
    +
    + + {{#str}}aria:courseimage, block_myoverview{{/str}} + +
    + + {{#str}}aria:coursename, block_myoverview{{/str}} +

    {{{fullname}}}

    +
    +
    + {{#str}}aria:coursesummary, block_myoverview{{/str}} + {{{summary}}} +
    +
    + {{#hasprogress}} + {{> block_myoverview/progress-bar}} + {{/hasprogress}} +
    +
    +
    +
    +{{/courses}} +
    \ No newline at end of file diff --git a/blocks/myoverview/tests/behat/block_myoverview_dashboard.feature b/blocks/myoverview/tests/behat/block_myoverview_dashboard.feature index de3735901bb..760705265b8 100644 --- a/blocks/myoverview/tests/behat/block_myoverview_dashboard.feature +++ b/blocks/myoverview/tests/behat/block_myoverview_dashboard.feature @@ -7,30 +7,62 @@ Feature: The my overview block allows users to easily access their courses Background: Given the following "users" exist: | username | firstname | lastname | email | idnumber | - | student1 | Student | 1 | student1@example.com | S1 | - | student2 | Student | 2 | student2@example.com | S2 | + | student1 | Student | X | student1@example.com | S1 | And the following "courses" exist: | fullname | shortname | category | startdate | enddate | | Course 1 | C1 | 0 | ##1 month ago## | ##15 days ago## | | Course 2 | C2 | 0 | ##yesterday## | ##tomorrow## | - | Course 3 | C3 | 0 | ##first day of next month## | ##last day of next month## | + | Course 3 | C3 | 0 | ##yesterday## | ##tomorrow## | + | Course 4 | C4 | 0 | ##yesterday## | ##tomorrow## | + | Course 5 | C5 | 0 | ##first day of next month## | ##last day of next month## | And the following "course enrolments" exist: | user | course | role | | student1 | C1 | student | | student1 | C2 | student | | student1 | C3 | student | + | student1 | C4 | student | + | student1 | C5 | student | - Scenario: See the courses I am enrolled by their status on courses view + Scenario: View past courses Given I log in as "student1" - And I should see "Course 2" in the "Course overview" "block" - And I should not see "Course 1" in the "Course overview" "block" - And I click on "In progress" "button" in the "Course overview" "block" - And I click on "Future" "link" in the "Course overview" "block" - And I should see "Course 3" in the "Course overview" "block" - And I should not see "Course 1" in the "Course overview" "block" - And I click on "Future" "button" in the "Course overview" "block" + And I click on "All" "button" in the "Course overview" "block" When I click on "Past" "link" in the "Course overview" "block" Then I should see "Course 1" in the "Course overview" "block" And I should not see "Course 2" in the "Course overview" "block" And I should not see "Course 3" in the "Course overview" "block" + And I should not see "Course 4" in the "Course overview" "block" + And I should not see "Course 5" in the "Course overview" "block" And I log out + + Scenario: View future courses + Given I log in as "student1" + And I click on "All" "button" in the "Course overview" "block" + When I click on "Future" "link" in the "Course overview" "block" + Then I should see "Course 5" in the "Course overview" "block" + And I should not see "Course 1" in the "Course overview" "block" + And I should not see "Course 2" in the "Course overview" "block" + And I should not see "Course 3" in the "Course overview" "block" + And I should not see "Course 4" in the "Course overview" "block" + And I log out + + Scenario: View inprogress courses + Given I log in as "student1" + And I click on "All" "button" in the "Course overview" "block" + When I click on "In progress" "link" in the "Course overview" "block" + Then I should see "Course 2" in the "Course overview" "block" + Then I should see "Course 3" in the "Course overview" "block" + Then I should see "Course 4" in the "Course overview" "block" + And I should not see "Course 1" in the "Course overview" "block" + And I should not see "Course 5" in the "Course overview" "block" + And I log out + + Scenario: View all courses + Given I log in as "student1" + And I click on "All" "button" in the "Course overview" "block" + When I click on "All" "link" in the "Course overview" "block" + Then I should see "Course 1" in the "Course overview" "block" + Then I should see "Course 2" in the "Course overview" "block" + Then I should see "Course 3" in the "Course overview" "block" + Then I should see "Course 4" in the "Course overview" "block" + Then I should see "Course 5" in the "Course overview" "block" + And I log out \ No newline at end of file diff --git a/blocks/myoverview/tests/behat/block_myoverview_progress.feature b/blocks/myoverview/tests/behat/block_myoverview_progress.feature index 5ed56564e80..06813f56483 100644 --- a/blocks/myoverview/tests/behat/block_myoverview_progress.feature +++ b/blocks/myoverview/tests/behat/block_myoverview_progress.feature @@ -20,6 +20,13 @@ Feature: Course overview block show users their progress on courses | teacher1 | C1 | editingteacher | | student1 | C1 | student | + Scenario: Course progress percentage should not be displayed if completion is not enabled + Given I log in as "student1" + And I click on "All" "button" in the "Course overview" "block" + When I click on "All" "link" in the "Course overview" "block" + Then I should not see "0%" in the "Course overview" "block" + And I log out + Scenario: User complete activity and verify his progress Given I log in as "teacher1" And I am on "Course 1" course homepage with editing mode on @@ -30,12 +37,13 @@ Feature: Course overview block show users their progress on courses | id_completionview | 1 | And I press "Save and return to course" And I log out - And I log in as "student1" + When I log in as "student1" + And I click on "All" "button" in the "Course overview" "block" Then I should see "Course 1" in the "Course overview" "block" And I should see "0%" in the "Course overview" "block" And I am on "Course 1" course homepage And I follow "Test choice 1" And I follow "Dashboard" in the user menu - And I should see "Course 1" in the "Course overview" "block" + And I click on "All" "button" in the "Course overview" "block" And I should see "100%" in the "Course overview" "block" And I log out diff --git a/blocks/myoverview/version.php b/blocks/myoverview/version.php index 6b8960ce85a..14b42c41dd0 100644 --- a/blocks/myoverview/version.php +++ b/blocks/myoverview/version.php @@ -24,6 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2018092700; // The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2018100100; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2018050800; // Requires this Moodle version. $plugin->component = 'block_myoverview'; // Full name of the plugin (used for diagnostics). diff --git a/course/classes/external/course_summary_exporter.php b/course/classes/external/course_summary_exporter.php index 342296ea83d..032c018e47e 100644 --- a/course/classes/external/course_summary_exporter.php +++ b/course/classes/external/course_summary_exporter.php @@ -41,9 +41,22 @@ class course_summary_exporter extends \core\external\exporter { } protected function get_other_values(renderer_base $output) { + $courseimage = self::get_course_image($this->data); + if (!$courseimage) { + $courseimage = self::get_course_pattern($this->data); + } + $progress = self::get_course_progress($this->data); + $hasprogress = false; + if ($progress === 0 || $progress > 0) { + $hasprogress = true; + } + $progress = floor($progress); return array( 'fullnamedisplay' => get_course_display_name_for_list($this->data), - 'viewurl' => (new moodle_url('/course/view.php', array('id' => $this->data->id)))->out(false) + 'viewurl' => (new moodle_url('/course/view.php', array('id' => $this->data->id)))->out(false), + 'courseimage' => $courseimage, + 'progress' => $progress, + 'hasprogress' => $hasprogress ); } @@ -96,7 +109,81 @@ class course_summary_exporter extends \core\external\exporter { ), 'viewurl' => array( 'type' => PARAM_URL, + ), + 'courseimage' => array( + 'type' => PARAM_RAW, + ), + 'progress' => array( + 'type' => PARAM_INT, + 'optional' => true + ), + 'hasprogress' => array( + 'type' => PARAM_BOOL ) ); } + + /** + * Get the course image if added to course. + * + * @param object $course + * @return string url of course image + */ + public static function get_course_image($course) { + global $CFG; + $courseinlist = new \core_course_list_element($course); + foreach ($courseinlist->get_course_overviewfiles() as $file) { + if ($file->is_valid_image()) { + $pathcomponents = [ + '/pluginfile.php', + $file->get_contextid(), + $file->get_component(), + $file->get_filearea() . $file->get_filepath() . $file->get_filename() + ]; + $path = implode('/', $pathcomponents); + return (new moodle_url($path))->out(); + } + } + return false; + } + + /** + * Get the course pattern datauri. + * + * The datauri is an encoded svg that can be passed as a url. + * @param object $course + * @return string datauri + */ + public static function get_course_pattern($course) { + $color = self::coursecolor($course->id); + $pattern = new \core_geopattern(); + $pattern->setColor($color); + $pattern->patternbyid($course->id); + return $pattern->datauri(); + } + + /** + * Get the course progress percentage. + * + * @param object $course + * @return int progress + */ + public static function get_course_progress($course) { + return \core_completion\progress::get_course_progress_percentage($course); + } + + /** + * Get the course color. + * + * @param int $courseid + * @return string hex color code. + */ + public static function coursecolor($courseid) { + // The colour palette is hardcoded for now. It would make sense to combine it with theme settings. + $basecolors = ['#81ecec', '#74b9ff', '#a29bfe', '#dfe6e9', '#00b894', + '#0984e3', '#b2bec3', '#fdcb6e', '#fd79a8', '#6c5ce7']; + + $color = $basecolors[$courseid % 10]; + return $color; + } } diff --git a/course/externallib.php b/course/externallib.php index 0aadfaedad3..08c35bfbe01 100644 --- a/course/externallib.php +++ b/course/externallib.php @@ -3654,6 +3654,8 @@ class core_course_external extends external_api { $sort = $params['sort']; switch($classification) { + case COURSE_TIMELINE_ALL: + break; case COURSE_TIMELINE_PAST: break; case COURSE_TIMELINE_INPROGRESS: diff --git a/course/lib.php b/course/lib.php index c255e555347..a1d9680ec5c 100644 --- a/course/lib.php +++ b/course/lib.php @@ -55,6 +55,7 @@ define('FIRSTUSEDEXCELROW', 3); define('MOD_CLASS_ACTIVITY', 0); define('MOD_CLASS_RESOURCE', 1); +define('COURSE_TIMELINE_ALL', 'all'); define('COURSE_TIMELINE_PAST', 'past'); define('COURSE_TIMELINE_INPROGRESS', 'inprogress'); define('COURSE_TIMELINE_FUTURE', 'future'); @@ -4204,8 +4205,9 @@ function course_filter_courses_by_timeline_classification( int $limit = 0 ) : array { - if (!in_array($classification, [COURSE_TIMELINE_PAST, COURSE_TIMELINE_INPROGRESS, COURSE_TIMELINE_FUTURE])) { - $message = 'Classification must be one of COURSE_TIMELINE_PAST, ' + if (!in_array($classification, + [COURSE_TIMELINE_ALL, COURSE_TIMELINE_PAST, COURSE_TIMELINE_INPROGRESS, COURSE_TIMELINE_FUTURE])) { + $message = 'Classification must be one of COURSE_TIMELINE_ALL, COURSE_TIMELINE_PAST, ' . 'COURSE_TIMELINE_INPROGRESS or COURSE_TIMELINE_FUTURE'; throw new moodle_exception($message); } @@ -4217,7 +4219,7 @@ function course_filter_courses_by_timeline_classification( foreach ($courses as $course) { $numberofcoursesprocessed++; - if ($classification == course_classify_for_timeline($course)) { + if ($classification == COURSE_TIMELINE_ALL || $classification == course_classify_for_timeline($course)) { $filteredcourses[] = $course; $filtermatches++; } diff --git a/course/tests/externallib_test.php b/course/tests/externallib_test.php index abde22da1cf..e7759b05647 100644 --- a/course/tests/externallib_test.php +++ b/course/tests/externallib_test.php @@ -2556,6 +2556,66 @@ class core_course_externallib_testcase extends externallib_advanced_testcase { 'expectedcourses' => ['cfuture', 'dfuture', 'efuture'], 'expectednextoffset' => 15 ], + 'all no limit or offset' => [ + 'coursedata' => $coursedata, + 'classification' => 'all', + 'limit' => 0, + 'offset' => 0, + 'expectedcourses' => [ + 'afuture', + 'ainprogress', + 'apast', + 'bfuture', + 'binprogress', + 'bpast', + 'cfuture', + 'cinprogress', + 'cpast', + 'dfuture', + 'dinprogress', + 'dpast', + 'efuture', + 'einprogress', + 'epast' + ], + 'expectednextoffset' => 15 + ], + 'all limit no offset' => [ + 'coursedata' => $coursedata, + 'classification' => 'all', + 'limit' => 5, + 'offset' => 0, + 'expectedcourses' => [ + 'afuture', + 'ainprogress', + 'apast', + 'bfuture', + 'binprogress' + ], + 'expectednextoffset' => 5 + ], + 'all limit and offset' => [ + 'coursedata' => $coursedata, + 'classification' => 'all', + 'limit' => 5, + 'offset' => 5, + 'expectedcourses' => [ + 'bpast', + 'cfuture', + 'cinprogress', + 'cpast', + 'dfuture' + ], + 'expectednextoffset' => 10 + ], + 'all offset past result set' => [ + 'coursedata' => $coursedata, + 'classification' => 'all', + 'limit' => 5, + 'offset' => 50, + 'expectedcourses' => [], + 'expectednextoffset' => 50 + ], ]; } diff --git a/enrol/tests/enrollib_test.php b/enrol/tests/enrollib_test.php index 0cabb962360..34b5b48a520 100644 --- a/enrol/tests/enrollib_test.php +++ b/enrol/tests/enrollib_test.php @@ -792,4 +792,186 @@ class core_enrollib_testcase extends advanced_testcase { // There are still only two distinct users. $this->assertEquals(2, count_enrolled_users($context)); } + + /** + * Test cases for the test_enrol_get_my_courses_sort_by_last_access test. + */ + public function get_enrol_get_my_courses_sort_by_last_access_test_cases() { + $now = time(); + + $enrolledcoursesdata = [ + ['shortname' => 'a', 'lastaccess' => $now - 2], + ['shortname' => 'b', 'lastaccess' => $now - 1], + ['shortname' => 'c', 'lastaccess' => $now], + ['shortname' => 'd', 'lastaccess' => $now - 1], + ['shortname' => 'e'] + ]; + $unenrolledcoursesdata = [ + ['shortname' => 'x', 'lastaccess' => $now - 2], + ['shortname' => 'y', 'lastaccess' => $now - 1], + ['shortname' => 'z', 'lastaccess' => $now] + ]; + + return [ + 'empty set' => [ + 'enrolledcoursesdata' => [], + 'unenrolledcoursesdata' => $unenrolledcoursesdata, + 'sort' => 'ul.timeaccess asc', + 'limit' => 0, + 'offset' => 0, + 'expectedcourses' => [] + ], + 'ul.timeaccess asc, shortname asc no limit or offset' => [ + 'enrolledcoursesdata' => $enrolledcoursesdata, + 'unenrolledcoursesdata' => $unenrolledcoursesdata, + 'sort' => 'ul.timeaccess asc, shortname asc', + 'limit' => 0, + 'offset' => 0, + 'expectedcourses' => ['e', 'a', 'b', 'd', 'c'] + ], + 'ul.timeaccess asc, shortname asc with limit no offset' => [ + 'enrolledcoursesdata' => $enrolledcoursesdata, + 'unenrolledcoursesdata' => $unenrolledcoursesdata, + 'sort' => 'ul.timeaccess asc, shortname asc', + 'limit' => 2, + 'offset' => 0, + 'expectedcourses' => ['e', 'a'] + ], + 'ul.timeaccess asc, shortname asc with limit and offset' => [ + 'enrolledcoursesdata' => $enrolledcoursesdata, + 'unenrolledcoursesdata' => $unenrolledcoursesdata, + 'sort' => 'ul.timeaccess asc, shortname asc', + 'limit' => 2, + 'offset' => 2, + 'expectedcourses' => ['b', 'd'] + ], + 'ul.timeaccess asc, shortname asc with limit and offset beyond end of data set' => [ + 'enrolledcoursesdata' => $enrolledcoursesdata, + 'unenrolledcoursesdata' => $unenrolledcoursesdata, + 'sort' => 'ul.timeaccess asc, shortname asc', + 'limit' => 2, + 'offset' => 4, + 'expectedcourses' => ['c'] + ], + 'ul.timeaccess desc, shortname asc no limit or offset' => [ + 'enrolledcoursesdata' => $enrolledcoursesdata, + 'unenrolledcoursesdata' => $unenrolledcoursesdata, + 'sort' => 'ul.timeaccess desc, shortname asc', + 'limit' => 0, + 'offset' => 0, + 'expectedcourses' => ['c', 'b', 'd', 'a', 'e'] + ], + 'ul.timeaccess desc, shortname desc, no limit or offset' => [ + 'enrolledcoursesdata' => $enrolledcoursesdata, + 'unenrolledcoursesdata' => $unenrolledcoursesdata, + 'sort' => 'ul.timeaccess desc, shortname desc', + 'limit' => 0, + 'offset' => 0, + 'expectedcourses' => ['c', 'd', 'b', 'a', 'e'] + ], + 'ul.timeaccess asc, shortname desc, no limit or offset' => [ + 'enrolledcoursesdata' => $enrolledcoursesdata, + 'unenrolledcoursesdata' => $unenrolledcoursesdata, + 'sort' => 'ul.timeaccess asc, shortname desc', + 'limit' => 0, + 'offset' => 0, + 'expectedcourses' => ['e', 'a', 'd', 'b', 'c'] + ], + 'shortname asc, no limit or offset' => [ + 'enrolledcoursesdata' => $enrolledcoursesdata, + 'unenrolledcoursesdata' => $unenrolledcoursesdata, + 'sort' => 'shortname asc', + 'limit' => 0, + 'offset' => 0, + 'expectedcourses' => ['a', 'b', 'c', 'd', 'e'] + ], + 'shortname desc, no limit or offset' => [ + 'enrolledcoursesdata' => $enrolledcoursesdata, + 'unenrolledcoursesdata' => $unenrolledcoursesdata, + 'sort' => 'shortname desc', + 'limit' => 0, + 'offset' => 0, + 'expectedcourses' => ['e', 'd', 'c', 'b', 'a'] + ], + ]; + } + + /** + * Test the get_enrolled_courses_by_timeline_classification function. + * + * @dataProvider get_enrol_get_my_courses_sort_by_last_access_test_cases() + * @param array $enrolledcoursesdata Courses to create and enrol the user in + * @param array $unenrolledcoursesdata Courses to create nut not enrol the user in + * @param string $sort Sort string for the enrol function + * @param int $limit Maximum number of results + * @param int $offset Offset the courses result set by this amount + * @param array $expectedcourses Expected courses in result + */ + public function test_enrol_get_my_courses_sort_by_last_access( + $enrolledcoursesdata, + $unenrolledcoursesdata, + $sort, + $limit, + $offset, + $expectedcourses + ) { + global $DB, $CFG; + + $this->resetAfterTest(); + $generator = $this->getDataGenerator(); + $student = $generator->create_user(); + $lastaccessrecords = []; + + foreach ($enrolledcoursesdata as $coursedata) { + $lastaccess = null; + + if (isset($coursedata['lastaccess'])) { + $lastaccess = $coursedata['lastaccess']; + unset($coursedata['lastaccess']); + } + + $course = $generator->create_course($coursedata); + $generator->enrol_user($student->id, $course->id, 'student'); + + if (!is_null($lastaccess)) { + $lastaccessrecords[] = [ + 'userid' => $student->id, + 'courseid' => $course->id, + 'timeaccess' => $lastaccess + ]; + } + } + + foreach ($unenrolledcoursesdata as $coursedata) { + $lastaccess = null; + + if (isset($coursedata['lastaccess'])) { + $lastaccess = $coursedata['lastaccess']; + unset($coursedata['lastaccess']); + } + + $course = $generator->create_course($coursedata); + + if (!is_null($lastaccess)) { + $lastaccessrecords[] = [ + 'userid' => $student->id, + 'courseid' => $course->id, + 'timeaccess' => $lastaccess + ]; + } + } + + if (!empty($lastaccessrecords)) { + $DB->insert_records('user_lastaccess', $lastaccessrecords); + } + + $this->setUser($student); + + $result = enrol_get_my_courses('shortname', $sort, $limit, [], false, $offset); + $actual = array_map(function($course) { + return $course->shortname; + }, array_values($result)); + + $this->assertEquals($expectedcourses, $actual); + } } diff --git a/lib/enrollib.php b/lib/enrollib.php index fa20f6535f4..5ddf497dbf2 100644 --- a/lib/enrollib.php +++ b/lib/enrollib.php @@ -554,6 +554,8 @@ function enrol_add_course_navigation(navigation_node $coursenode, $course) { * * @param string|array $fields Extra fields to be returned (array or comma-separated list). * @param string|null $sort Comma separated list of fields to sort by, defaults to respecting navsortmycoursessort. + * Allowed prefixes for sort fields are: "ul" for the user_lastaccess table, "c" for the courses table, + * "ue" for the user_enrolments table. * @param int $limit max number of courses * @param array $courseids the list of course ids to filter by * @param bool $allaccessible Include courses user is not enrolled in, but can access @@ -599,17 +601,32 @@ function enrol_get_my_courses($fields = null, $sort = null, $limit = 0, $coursei $orderby = ""; $sort = trim($sort); + $sorttimeaccess = false; + $allowedsortprefixes = array('c', 'ul', 'ue'); if (!empty($sort)) { $rawsorts = explode(',', $sort); $sorts = array(); foreach ($rawsorts as $rawsort) { $rawsort = trim($rawsort); - if (strpos($rawsort, 'c.') === 0) { - $rawsort = substr($rawsort, 2); + if (preg_match('/^ul\.(\S*)\s(asc|desc)/i', $rawsort, $matches)) { + if (strcasecmp($matches[2], 'asc') == 0) { + $sorts[] = 'COALESCE(ul.' . $matches[1] . ', 0) ASC'; + } else { + $sorts[] = 'COALESCE(ul.' . $matches[1] . ', 0) DESC'; + } + $sorttimeaccess = true; + } else if (strpos($rawsort, '.') !== false) { + $prefix = explode('.', $rawsort); + if (in_array($prefix[0], $allowedsortprefixes)) { + $sorts[] = trim($rawsort); + } else { + throw new coding_exception('Invalid $sort parameter in enrol_get_my_courses()'); + } + } else { + $sorts[] = 'c.'.trim($rawsort); } - $sorts[] = trim($rawsort); } - $sort = 'c.'.implode(',c.', $sorts); + $sort = implode(',', $sorts); $orderby = "ORDER BY $sort"; } @@ -628,6 +645,9 @@ function enrol_get_my_courses($fields = null, $sort = null, $limit = 0, $coursei $params['contextlevel'] = CONTEXT_COURSE; $wheres = implode(" AND ", $wheres); + $timeaccessselect = ""; + $timeaccessjoin = ""; + if (!empty($courseids)) { list($courseidssql, $courseidsparams) = $DB->get_in_or_equal($courseids, SQL_PARAMS_NAMED); $wheres = sprintf("%s AND c.id %s", $wheres, $courseidssql); @@ -640,14 +660,20 @@ function enrol_get_my_courses($fields = null, $sort = null, $limit = 0, $coursei $courseidsql .= " SELECT DISTINCT e.courseid FROM {enrol} e - JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = :userid) + JOIN {user_enrolments} ue ON (ue.enrolid = e.id AND ue.userid = :userid1) WHERE ue.status = :active AND e.status = :enabled AND ue.timestart < :now1 AND (ue.timeend = 0 OR ue.timeend > :now2)"; - $params['userid'] = $USER->id; + $params['userid1'] = $USER->id; $params['active'] = ENROL_USER_ACTIVE; $params['enabled'] = ENROL_INSTANCE_ENABLED; $params['now1'] = round(time(), -2); // Improves db caching. $params['now2'] = $params['now1']; + + if ($sorttimeaccess) { + $params['userid2'] = $USER->id; + $timeaccessselect = ', ul.timeaccess as lastaccessed'; + $timeaccessjoin = "LEFT JOIN {user_lastaccess} ul ON (ul.courseid = c.id AND ul.userid = :userid2)"; + } } // When including non-enrolled but accessible courses... @@ -708,9 +734,10 @@ function enrol_get_my_courses($fields = null, $sort = null, $limit = 0, $coursei // Note: we can not use DISTINCT + text fields due to Oracle and MS limitations, that is why // we have the subselect there. - $sql = "SELECT $coursefields $ccselect + $sql = "SELECT $coursefields $ccselect $timeaccessselect FROM {course} c JOIN ($courseidsql) en ON (en.courseid = c.id) + $timeaccessjoin $ccjoin WHERE $wheres $orderby"; diff --git a/theme/boost/scss/moodle/blocks.scss b/theme/boost/scss/moodle/blocks.scss index 4ab424ae658..980888cbce0 100644 --- a/theme/boost/scss/moodle/blocks.scss +++ b/theme/boost/scss/moodle/blocks.scss @@ -72,113 +72,94 @@ $blocks-plus-gutter: $blocks-column-width + ( $grid-gutter-width / 2 ); } } -$chart-size: 70px; -$doughnut-border-size: 15px; -$doughnut-dasharray: 173; -$doughnut-empty-colour: $gray-lighter; -$doughnut-fill-colour: $brand-warning; - -.progress-chart-container { - height: $chart-size; - width: $chart-size; - - .progress-doughnut { - position: relative; - height: $chart-size; - width: $chart-size; - background-clip: padding-box; - border: $doughnut-border-size solid $doughnut-empty-colour; - border-radius: 50%; - box-sizing: border-box; - - .progress-text { - position: absolute; - top: 50%; - /*rtl:ignore*/ - left: 50%; - transform: translate(-50%, -50%); - color: $doughnut-empty-colour; - - &.has-percent { - color: $doughnut-fill-colour; - } - } - - .progress-indicator { - position: absolute; - top: ($doughnut-border-size * -1); - left: ($doughnut-border-size * -1); - height: $chart-size; - width: $chart-size; - - svg { - position: relative; - height: 100%; - width: 100%; - - .circle { - stroke-width: $doughnut-border-size; - stroke: $doughnut-fill-colour; - fill: none; - stroke-dasharray: $doughnut-dasharray; - stroke-dashoffset: $doughnut-dasharray; - transform: rotate(-90deg); - transform-origin: center center; - - @for $i from 1 through 100 { - &.percent-#{$i} { - stroke-dashoffset: $doughnut-dasharray - ($i / 100 * $doughnut-dasharray); - } - } - } - } - } - } - - .no-progress { - height: $chart-size; - width: $chart-size; - background-color: $doughnut-empty-colour; - border-radius: 50%; - position: relative; - - .icon { - position: absolute; - top: 50%; - /*rtl:ignore*/ - left: 50%; - margin: 0; - transform: translate(-63%, -50%); - color: #fff; - height: ($chart-size / 2) + 10px; - width: ($chart-size / 2) + 10px; - font-size: ($chart-size / 2) + 10px; - } - } -} +$card-gutter : $card-deck-margin * 2; .block_myoverview { - .empty-placeholder-image-sm { - height: 50px; - } - .empty-placeholder-image-lg { height: 125px; } -} - -.card-deck { - .card { - $card-gutter : $card-deck-margin * 2; - flex-grow: 0; - flex-shrink: 0; - flex-basis: calc(50% - #{$card-gutter}); + .course-card { + margin-bottom: $card-gutter; + flex-basis: 100%; + } + .course-info-container { + padding: 0.8rem; + } + .course-card-footer { + padding: 0.8rem; + } + .progress { + height: 0.5rem; } .myoverviewimg { - height: 150px; - &.courseimage { - background-position: center; - background-size: cover; + height: 7rem; + background-position: center; + background-size: cover; + } + .course-summaryitem { + border: $border-width solid $border-color; + background-color: $body-bg; + } + .summary img { + max-width: 100%; + } + @include media-breakpoint-down(sm) { + .summaryimage { + max-height: 7rem; + } + } +} + +#region-main { + .block_myoverview { + .course-card { + flex-grow: 0; + flex-shrink: 0; + flex-basis: calc(50% - #{$card-gutter}); + } + @include media-breakpoint-up(sm) { + .course-card { + flex-basis: calc(50% - #{$card-gutter}); + } + } + @include media-breakpoint-up(md) { + .course-card { + flex-basis: calc(33.33% - #{$card-gutter}); + } + } + @include media-breakpoint-up(lg) { + .course-card { + flex-basis: calc(25% - #{$card-gutter}); + } + } + @include media-breakpoint-up(xl) { + .course-card { + flex-basis: calc(20% - #{$card-gutter}); + } + } + } +} + +#region-main.has-blocks .block_myoverview { + @include media-breakpoint-up(lg) { + .course-card { + flex-basis: calc(33.33% - #{$card-gutter}); + } + } + @include media-breakpoint-up(xl) { + .course-card { + flex-basis: calc(25% - #{$card-gutter}); + } + } +} + +body.drawer-open-left #region-main.has-blocks .block_myoverview { + .course-card { + flex-basis: calc(50% - #{$card-gutter}); + } + @include media-breakpoint-up(lg) { + .course-card { + flex-basis: calc(33.33% - #{$card-gutter}); } } } diff --git a/theme/boost/scss/preset/default.scss b/theme/boost/scss/preset/default.scss index cd04cd51c8a..d11f963a71b 100644 --- a/theme/boost/scss/preset/default.scss +++ b/theme/boost/scss/preset/default.scss @@ -58,6 +58,8 @@ $breadcrumb-divider-rtl: "/" !default; // Alerts $alert-border-width: 0 !default; +$card-group-margin: .25rem; + $theme-colors: ( primary: $primary, secondary: $gray-200, diff --git a/theme/boost/style/moodle.css b/theme/boost/style/moodle.css index a9b1453cffb..6e3e54f4976 100644 --- a/theme/boost/style/moodle.css +++ b/theme/boost/style/moodle.css @@ -5576,25 +5576,25 @@ tbody.collapse.show { display: flex; flex-direction: column; } .card-deck .card, .card-deck #page-enrol-users #filterform, #page-enrol-users .card-deck #filterform, .card-deck .que .history, .que .card-deck .history, .card-deck .userprofile .profile_tree section, .userprofile .profile_tree .card-deck section, .card-deck .groupinfobox, .card-deck .well { - margin-bottom: 15px; } + margin-bottom: 0.25rem; } @media (min-width: 576px) { .card-deck { flex-flow: row wrap; - margin-right: -15px; - margin-left: -15px; } + margin-right: -0.25rem; + margin-left: -0.25rem; } .card-deck .card, .card-deck #page-enrol-users #filterform, #page-enrol-users .card-deck #filterform, .card-deck .que .history, .que .card-deck .history, .card-deck .userprofile .profile_tree section, .userprofile .profile_tree .card-deck section, .card-deck .groupinfobox, .card-deck .well { display: flex; flex: 1 0 0%; flex-direction: column; - margin-right: 15px; + margin-right: 0.25rem; margin-bottom: 0; - margin-left: 15px; } } + margin-left: 0.25rem; } } .card-group { display: flex; flex-direction: column; } .card-group > .card, #page-enrol-users .card-group > #filterform, .que .card-group > .history, .userprofile .profile_tree .card-group > section, .card-group > .groupinfobox, .card-group > .well { - margin-bottom: 15px; } + margin-bottom: 0.25rem; } @media (min-width: 576px) { .card-group { flex-flow: row wrap; } @@ -11131,278 +11131,73 @@ div.editor_atto_toolbar button .icon { [data-region="blocks-column"] { width: 100%; } } -.progress-chart-container { - height: 70px; - width: 70px; } - .progress-chart-container .progress-doughnut { - position: relative; - height: 70px; - width: 70px; - background-clip: padding-box; - border: 15px solid #dee2e6; - border-radius: 50%; - box-sizing: border-box; } - .progress-chart-container .progress-doughnut .progress-text { - position: absolute; - top: 50%; - /*rtl:ignore*/ - left: 50%; - transform: translate(-50%, -50%); - color: #dee2e6; } - .progress-chart-container .progress-doughnut .progress-text.has-percent { - color: #ff7518; } - .progress-chart-container .progress-doughnut .progress-indicator { - position: absolute; - top: -15px; - left: -15px; - height: 70px; - width: 70px; } - .progress-chart-container .progress-doughnut .progress-indicator svg { - position: relative; - height: 100%; - width: 100%; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle { - stroke-width: 15px; - stroke: #ff7518; - fill: none; - stroke-dasharray: 173; - stroke-dashoffset: 173; - transform: rotate(-90deg); - transform-origin: center center; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-1 { - stroke-dashoffset: 171.27; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-2 { - stroke-dashoffset: 169.54; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-3 { - stroke-dashoffset: 167.81; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-4 { - stroke-dashoffset: 166.08; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-5 { - stroke-dashoffset: 164.35; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-6 { - stroke-dashoffset: 162.62; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-7 { - stroke-dashoffset: 160.89; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-8 { - stroke-dashoffset: 159.16; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-9 { - stroke-dashoffset: 157.43; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-10 { - stroke-dashoffset: 155.7; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-11 { - stroke-dashoffset: 153.97; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-12 { - stroke-dashoffset: 152.24; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-13 { - stroke-dashoffset: 150.51; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-14 { - stroke-dashoffset: 148.78; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-15 { - stroke-dashoffset: 147.05; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-16 { - stroke-dashoffset: 145.32; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-17 { - stroke-dashoffset: 143.59; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-18 { - stroke-dashoffset: 141.86; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-19 { - stroke-dashoffset: 140.13; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-20 { - stroke-dashoffset: 138.4; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-21 { - stroke-dashoffset: 136.67; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-22 { - stroke-dashoffset: 134.94; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-23 { - stroke-dashoffset: 133.21; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-24 { - stroke-dashoffset: 131.48; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-25 { - stroke-dashoffset: 129.75; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-26 { - stroke-dashoffset: 128.02; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-27 { - stroke-dashoffset: 126.29; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-28 { - stroke-dashoffset: 124.56; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-29 { - stroke-dashoffset: 122.83; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-30 { - stroke-dashoffset: 121.1; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-31 { - stroke-dashoffset: 119.37; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-32 { - stroke-dashoffset: 117.64; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-33 { - stroke-dashoffset: 115.91; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-34 { - stroke-dashoffset: 114.18; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-35 { - stroke-dashoffset: 112.45; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-36 { - stroke-dashoffset: 110.72; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-37 { - stroke-dashoffset: 108.99; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-38 { - stroke-dashoffset: 107.26; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-39 { - stroke-dashoffset: 105.53; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-40 { - stroke-dashoffset: 103.8; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-41 { - stroke-dashoffset: 102.07; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-42 { - stroke-dashoffset: 100.34; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-43 { - stroke-dashoffset: 98.61; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-44 { - stroke-dashoffset: 96.88; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-45 { - stroke-dashoffset: 95.15; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-46 { - stroke-dashoffset: 93.42; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-47 { - stroke-dashoffset: 91.69; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-48 { - stroke-dashoffset: 89.96; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-49 { - stroke-dashoffset: 88.23; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-50 { - stroke-dashoffset: 86.5; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-51 { - stroke-dashoffset: 84.77; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-52 { - stroke-dashoffset: 83.04; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-53 { - stroke-dashoffset: 81.31; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-54 { - stroke-dashoffset: 79.58; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-55 { - stroke-dashoffset: 77.85; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-56 { - stroke-dashoffset: 76.12; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-57 { - stroke-dashoffset: 74.39; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-58 { - stroke-dashoffset: 72.66; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-59 { - stroke-dashoffset: 70.93; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-60 { - stroke-dashoffset: 69.2; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-61 { - stroke-dashoffset: 67.47; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-62 { - stroke-dashoffset: 65.74; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-63 { - stroke-dashoffset: 64.01; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-64 { - stroke-dashoffset: 62.28; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-65 { - stroke-dashoffset: 60.55; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-66 { - stroke-dashoffset: 58.82; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-67 { - stroke-dashoffset: 57.09; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-68 { - stroke-dashoffset: 55.36; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-69 { - stroke-dashoffset: 53.63; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-70 { - stroke-dashoffset: 51.9; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-71 { - stroke-dashoffset: 50.17; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-72 { - stroke-dashoffset: 48.44; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-73 { - stroke-dashoffset: 46.71; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-74 { - stroke-dashoffset: 44.98; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-75 { - stroke-dashoffset: 43.25; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-76 { - stroke-dashoffset: 41.52; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-77 { - stroke-dashoffset: 39.79; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-78 { - stroke-dashoffset: 38.06; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-79 { - stroke-dashoffset: 36.33; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-80 { - stroke-dashoffset: 34.6; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-81 { - stroke-dashoffset: 32.87; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-82 { - stroke-dashoffset: 31.14; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-83 { - stroke-dashoffset: 29.41; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-84 { - stroke-dashoffset: 27.68; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-85 { - stroke-dashoffset: 25.95; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-86 { - stroke-dashoffset: 24.22; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-87 { - stroke-dashoffset: 22.49; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-88 { - stroke-dashoffset: 20.76; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-89 { - stroke-dashoffset: 19.03; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-90 { - stroke-dashoffset: 17.3; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-91 { - stroke-dashoffset: 15.57; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-92 { - stroke-dashoffset: 13.84; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-93 { - stroke-dashoffset: 12.11; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-94 { - stroke-dashoffset: 10.38; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-95 { - stroke-dashoffset: 8.65; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-96 { - stroke-dashoffset: 6.92; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-97 { - stroke-dashoffset: 5.19; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-98 { - stroke-dashoffset: 3.46; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-99 { - stroke-dashoffset: 1.73; } - .progress-chart-container .progress-doughnut .progress-indicator svg .circle.percent-100 { - stroke-dashoffset: 0; } - .progress-chart-container .no-progress { - height: 70px; - width: 70px; - background-color: #dee2e6; - border-radius: 50%; - position: relative; } - .progress-chart-container .no-progress .icon { - position: absolute; - top: 50%; - /*rtl:ignore*/ - left: 50%; - margin: 0; - transform: translate(-63%, -50%); - color: #fff; - height: 45px; - width: 45px; - font-size: 45px; } - -.block_myoverview .empty-placeholder-image-sm { - height: 50px; } - .block_myoverview .empty-placeholder-image-lg { height: 125px; } -.card-deck .card, .card-deck #page-enrol-users #filterform, #page-enrol-users .card-deck #filterform, .card-deck .que .history, .que .card-deck .history, .card-deck .userprofile .profile_tree section, .userprofile .profile_tree .card-deck section, .card-deck .groupinfobox, .card-deck .well { +.block_myoverview .course-card { + margin-bottom: 0.5rem; + flex-basis: 100%; } + +.block_myoverview .course-info-container { + padding: 0.8rem; } + +.block_myoverview .course-card-footer { + padding: 0.8rem; } + +.block_myoverview .progress { + height: 0.5rem; } + +.block_myoverview .myoverviewimg { + height: 7rem; + background-position: center; + background-size: cover; } + +.block_myoverview .course-summaryitem { + border: 1px solid #dee2e6; + background-color: #fff; } + +.block_myoverview .summary img { + max-width: 100%; } + +@media (max-width: 767.98px) { + .block_myoverview .summaryimage { + max-height: 7rem; } } + +#region-main .block_myoverview .course-card { flex-grow: 0; flex-shrink: 0; - flex-basis: calc(50% - 30px); } + flex-basis: calc(50% - 0.5rem); } -.card-deck .myoverviewimg { - height: 150px; } - .card-deck .myoverviewimg.courseimage { - background-position: center; - background-size: cover; } +@media (min-width: 576px) { + #region-main .block_myoverview .course-card { + flex-basis: calc(50% - 0.5rem); } } + +@media (min-width: 768px) { + #region-main .block_myoverview .course-card { + flex-basis: calc(33.33% - 0.5rem); } } + +@media (min-width: 992px) { + #region-main .block_myoverview .course-card { + flex-basis: calc(25% - 0.5rem); } } + +@media (min-width: 1200px) { + #region-main .block_myoverview .course-card { + flex-basis: calc(20% - 0.5rem); } } + +@media (min-width: 992px) { + #region-main.has-blocks .block_myoverview .course-card { + flex-basis: calc(33.33% - 0.5rem); } } + +@media (min-width: 1200px) { + #region-main.has-blocks .block_myoverview .course-card { + flex-basis: calc(25% - 0.5rem); } } + +body.drawer-open-left #region-main.has-blocks .block_myoverview .course-card { + flex-basis: calc(50% - 0.5rem); } + +@media (min-width: 992px) { + body.drawer-open-left #region-main.has-blocks .block_myoverview .course-card { + flex-basis: calc(33.33% - 0.5rem); } } .block_settings .block_tree [aria-expanded="true"], .block_settings .block_tree [aria-expanded="true"].emptybranch, diff --git a/theme/bootstrapbase/less/moodle/blocks.less b/theme/bootstrapbase/less/moodle/blocks.less index 79229ac3cda..936abbc8116 100644 --- a/theme/bootstrapbase/less/moodle/blocks.less +++ b/theme/bootstrapbase/less/moodle/blocks.less @@ -341,39 +341,86 @@ } .block_myoverview { - background-color: transparent; - - .row-fluid [class*="span"] { - margin-left: 0; + *, + *::before, + *::after { + box-sizing: border-box; } - - .empty-placeholder-image-sm { - height: 50px; - } - .empty-placeholder-image-lg { height: 125px; } - - .courses-view-course-item { - height: 220px; - overflow-y: hidden; + .course-card { + .border-radius(@baseBorderRadius); + margin-bottom: 0.5rem; + flex-grow: 0; + flex-shrink: 0; + flex-basis: ~"calc(50% - 0.6rem)"; } - - h4 { - font-weight: normal; + .course-info-container { + flex: 1 1 auto; + padding: 0.8rem; } - - .well { - background-color: @white; - box-shadow: none; - margin: 0 5px 10px; + .course-card-footer { + padding: 0.8rem; + background-color: @wellBackground; + border-top: 1px solid darken(@wellBackground, 7%); + .border-bottom-radius(@baseBorderRadius); + } + .progress { + height: 0.5rem; + margin-bottom: 0; } .myoverviewimg { - height: 150px; - &.courseimage { - background-position: center; - background-size: cover; + height: 7rem; + background-position: center; + background-size: cover; + .border-top-radius(@baseBorderRadius); + } + .list-group { + margin: 0; + } + .course-listitem { + display: block; + padding: 0.75rem 1.25rem; + margin-bottom: 0.5rem; + background-color: @white; + border: 1px solid @tableBorder; + .border-radius(@baseBorderRadius); + } + .course-summaryitem { + padding: 0.5rem; + background-color: @white; + border: 1px solid @tableBorder; + .border-radius(@baseBorderRadius); + } + .summary img { + max-width: 100%; + } + + @media (max-width: 576px) { + .summaryimage { + max-height: 7rem; } } -} + + @media (min-width: 576px) { + .card-deck { + display: flex; + flex-flow: row wrap; + margin-right: -.25rem; + margin-left: -.25rem; + } + .course-card { + display: flex; + flex-direction: column; + margin-right: 0.25rem; + margin-left: 0.25rem; + } + } + + @media (min-width: 1200px) { + .course-card { + flex-basis: ~"calc(33% - 0.5rem)"; + } + } +} \ No newline at end of file diff --git a/theme/bootstrapbase/less/moodle/bs4-compat.less b/theme/bootstrapbase/less/moodle/bs4-compat.less index 3fd60ca87de..a2a23345fd4 100644 --- a/theme/bootstrapbase/less/moodle/bs4-compat.less +++ b/theme/bootstrapbase/less/moodle/bs4-compat.less @@ -324,3 +324,23 @@ .w-25 { width: 25%; } + +.d-flex { + display: flex !important; +} + +.flex-column { + flex-direction: column !important; +} + +.align-self-stretch { + align-self: stretch; +} + +.ml-auto { + margin-left: auto; +} + +.mt-auto { + margin-top: auto; +} diff --git a/theme/bootstrapbase/style/moodle.css b/theme/bootstrapbase/style/moodle.css index 79dd22b5076..25b62eded44 100644 --- a/theme/bootstrapbase/style/moodle.css +++ b/theme/bootstrapbase/style/moodle.css @@ -16536,36 +16536,100 @@ body { height: 35px; width: 35px; } -.block_myoverview { - background-color: transparent; -} -.block_myoverview .row-fluid [class*="span"] { - margin-left: 0; -} -.block_myoverview .empty-placeholder-image-sm { - height: 50px; +.block_myoverview *, +.block_myoverview *::before, +.block_myoverview *::after { + box-sizing: border-box; } .block_myoverview .empty-placeholder-image-lg { height: 125px; } -.block_myoverview .courses-view-course-item { - height: 220px; - overflow-y: hidden; +.block_myoverview .course-card { + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; + margin-bottom: 0.5rem; + flex-grow: 0; + flex-shrink: 0; + flex-basis: calc(50% - 0.6rem); } -.block_myoverview h4 { - font-weight: normal; +.block_myoverview .course-info-container { + flex: 1 1 auto; + padding: 0.8rem; } -.block_myoverview .well { - background-color: #fff; - box-shadow: none; - margin: 0 5px 10px; +.block_myoverview .course-card-footer { + padding: 0.8rem; + background-color: #f5f5f5; + border-top: 1px solid #e3e3e3; + -webkit-border-bottom-right-radius: 4px; + -moz-border-radius-bottomright: 4px; + border-bottom-right-radius: 4px; + -webkit-border-bottom-left-radius: 4px; + -moz-border-radius-bottomleft: 4px; + border-bottom-left-radius: 4px; +} +.block_myoverview .progress { + height: 0.5rem; + margin-bottom: 0; } .block_myoverview .myoverviewimg { - height: 150px; -} -.block_myoverview .myoverviewimg.courseimage { + height: 7rem; background-position: center; background-size: cover; + -webkit-border-top-right-radius: 4px; + -moz-border-radius-topright: 4px; + border-top-right-radius: 4px; + -webkit-border-top-left-radius: 4px; + -moz-border-radius-topleft: 4px; + border-top-left-radius: 4px; +} +.block_myoverview .list-group { + margin: 0; +} +.block_myoverview .course-listitem { + display: block; + padding: 0.75rem 1.25rem; + margin-bottom: 0.5rem; + background-color: #fff; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.block_myoverview .course-summaryitem { + padding: 0.5rem; + background-color: #fff; + border: 1px solid #ddd; + -webkit-border-radius: 4px; + -moz-border-radius: 4px; + border-radius: 4px; +} +.block_myoverview .summary img { + max-width: 100%; +} +@media (max-width: 576px) { + .block_myoverview .summaryimage { + max-height: 7rem; + } +} +@media (min-width: 576px) { + .block_myoverview .card-deck { + display: flex; + flex-flow: row wrap; + margin-right: -0.25rem; + margin-left: -0.25rem; + } + .block_myoverview .course-card { + display: flex; + flex-direction: column; + margin-right: 0.25rem; + margin-left: 0.25rem; + } +} +@media (min-width: 1200px) { + .block_myoverview .course-card { + flex-basis: calc(33% - 0.5rem); + } } /** * Moodle forms HTML isn't changeable via renderers (yet?) so this @@ -22107,3 +22171,18 @@ ul.indented-list { .w-25 { width: 25%; } +.d-flex { + display: flex !important; +} +.flex-column { + flex-direction: column !important; +} +.align-self-stretch { + align-self: stretch; +} +.ml-auto { + margin-left: auto; +} +.mt-auto { + margin-top: auto; +} diff --git a/theme/bootstrapbase/templates/block_myoverview/course-paging-content-item.mustache b/theme/bootstrapbase/templates/block_myoverview/course-paging-content-item.mustache deleted file mode 100644 index 75fe6c8cf53..00000000000 --- a/theme/bootstrapbase/templates/block_myoverview/course-paging-content-item.mustache +++ /dev/null @@ -1,47 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template block_myoverview/course-paging-content-item - - This template renders each course block. - - Example context (json): - { - "page": 1, - "active": true, - "courses": [ - { - "fullnamedisplay": "course 1", - "viewurl": "https://www.google.com", - "summary": "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout." - }, - { - "fullnamedisplay": "course 2", - "viewurl": "https://www.google.com", - "summary": "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout." - } - ] - } -}} -{{< block_myoverview/paging-content-item }} - {{$content}} - {{#courses}} - {{> block_myoverview/courses-view-course-item }} - {{/courses}} -
    - {{/content}} -{{/ block_myoverview/paging-content-item }} diff --git a/theme/bootstrapbase/templates/block_myoverview/courses-view-course-item.mustache b/theme/bootstrapbase/templates/block_myoverview/courses-view-course-item.mustache deleted file mode 100644 index d9fd70ec02b..00000000000 --- a/theme/bootstrapbase/templates/block_myoverview/courses-view-course-item.mustache +++ /dev/null @@ -1,53 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template block_myoverview/course-view-course-item - - This template renders the course summary (view by courses) for the myoverview block. - - Example context (json): - { - "shortname": "course 3", - "viewurl": "https://www.google.com", - "summary": "It is a long established fact that a reader will be distracted by the readable content of a page when looking at its layout." - } -}} -
    -
    - -
    -
    -
    -
    -
    -
    -
    - {{> block_myoverview/progress-chart}} -
    -
    - -
    -

    - {{#shortentext}} 140, {{{summary}}}{{/shortentext}} -

    -
    -
    -
    diff --git a/theme/bootstrapbase/templates/block_myoverview/courses-view-nav-grouping-display-filter.mustache b/theme/bootstrapbase/templates/block_myoverview/courses-view-nav-grouping-display-filter.mustache deleted file mode 100644 index 0cd929cd0ff..00000000000 --- a/theme/bootstrapbase/templates/block_myoverview/courses-view-nav-grouping-display-filter.mustache +++ /dev/null @@ -1,41 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template block_myoverview/courses-view-nav-grouping-display-filter - - This template renders the main content area for the myoverview block. - - Example context (json): - {} -}} - diff --git a/theme/bootstrapbase/templates/block_myoverview/courses-view.mustache b/theme/bootstrapbase/templates/block_myoverview/courses-view.mustache deleted file mode 100644 index 5bfc78dea49..00000000000 --- a/theme/bootstrapbase/templates/block_myoverview/courses-view.mustache +++ /dev/null @@ -1,105 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template block_myoverview/courses-view - - This template renders the courses view for the myoverview block. - - Example context (json): - {} -}} -
    - {{#hascourses}} -
    -
    - {{#inprogress}} - {{< block_myoverview/courses-view-by-status }} - {{$id}}courses-view-in-progress{{/id}} - {{$status}}1{{/status}} - {{$pagingbarid}}pb-for-in-progress{{/pagingbarid}} - {{$pagingcontentid}}pc-for-in-progress{{/pagingcontentid}} - {{/ block_myoverview/courses-view-by-status }} - {{/inprogress}} - {{^inprogress}} -
    - {{#str}} nocoursesinprogress, block_myoverview {{/str}} -

    {{#str}} nocoursesinprogress, block_myoverview {{/str}}

    -
    - {{/inprogress}} -
    -
    - {{#future}} - {{< block_myoverview/courses-view-by-status }} - {{$id}}courses-view-future{{/id}} - {{$status}}2{{/status}} - {{$pagingbarid}}pb-for-future{{/pagingbarid}} - {{$pagingcontentid}}pc-for-in-progress{{/pagingcontentid}} - {{/ block_myoverview/courses-view-by-status }} - {{/future}} - {{^future}} -
    - {{#str}} nocoursesfuture, block_myoverview {{/str}} -

    {{#str}} nocoursesfuture, block_myoverview {{/str}}

    -
    - {{/future}} -
    -
    - {{#past}} - {{< block_myoverview/courses-view-by-status }} - {{$id}}courses-view-past{{/id}} - {{$status}}0{{/status}} - {{$pagingbarid}}pb-for-past{{/pagingbarid}} - {{$pagingcontentid}}pc-for-in-progress{{/pagingcontentid}} - {{/ block_myoverview/courses-view-by-status }} - {{/past}} - {{^past}} -
    - {{#str}} nocoursespast, block_myoverview {{/str}} -

    {{#str}} nocoursespast, block_myoverview {{/str}}

    -
    - {{/past}} -
    -
    - {{/hascourses}} - {{^hascourses}} -
    - {{#str}} nocourses, block_myoverview {{/str}} -

    {{#str}} nocourses, block_myoverview {{/str}}

    -
    - {{/hascourses}} -
    -{{#js}} -require(['jquery', 'core/custom_interaction_events'], function($, customEvents) { - var root = $('#courses-view-{{uniqid}}'); - customEvents.define(root, [customEvents.events.activate]); - root.on(customEvents.events.activate, '[data-toggle="btns"] > .btn', function(e) { - root.find('.btn.active').removeClass('active'); - $(e.target).closest('.btn').addClass('active'); - }); -}); -{{/js}} diff --git a/theme/bootstrapbase/templates/block_myoverview/main.mustache b/theme/bootstrapbase/templates/block_myoverview/main.mustache deleted file mode 100644 index 3a8a005509d..00000000000 --- a/theme/bootstrapbase/templates/block_myoverview/main.mustache +++ /dev/null @@ -1,43 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template block_myoverview/main - - This template renders the main content area for the myoverview block. - - Example context (json): - {} -}} - -
    -
    -
    - {{#coursesview}} - {{#hascourses}} -
    - {{> block_myoverview/courses-view-nav-grouping-display-filter }} -
    - {{/hascourses}} - {{/coursesview}} -
    -
    -
    - {{#coursesview}} - {{> block_myoverview/courses-view }} - {{/coursesview}} -
    -
    diff --git a/theme/bootstrapbase/templates/block_myoverview/paging-bar.mustache b/theme/bootstrapbase/templates/block_myoverview/paging-bar.mustache deleted file mode 100644 index 96d44d1f071..00000000000 --- a/theme/bootstrapbase/templates/block_myoverview/paging-bar.mustache +++ /dev/null @@ -1,97 +0,0 @@ -{{! - This file is part of Moodle - http://moodle.org/ - - Moodle is free software: you can redistribute it and/or modify - it under the terms of the GNU General Public License as published by - the Free Software Foundation, either version 3 of the License, or - (at your option) any later version. - - Moodle is distributed in the hope that it will be useful, - but WITHOUT ANY WARRANTY; without even the implied warranty of - MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - GNU General Public License for more details. - - You should have received a copy of the GNU General Public License - along with Moodle. If not, see . -}} -{{! - @template block_myoverview/paging-bar - - This template renders the bootstrap style paging bar. - - Example context (json): - { - "pagingbar": { - "pagecount": 2, - "previous": {}, - "next": {}, - "first": { - "url": "#", - "page": "first" - }, - "last": { - "url": "#", - "page": "last" - }, - "pages": [ - { - "url": "#", - "number": 1, - "page": "1", - "active": true - }, - { - "url": "#", - "number": 2, - "page": "2" - } - ] - } - } -}} -{{#pagingbar}} - -{{#js}} -require(['jquery', 'block_myoverview/paging_bar'], function($, PagingBar) { - var root = $('#{{$pagingbarid}}paging-bar-{{uniqid}}{{/pagingbarid}}'); - PagingBar.registerEventListeners(root); -}); -{{/js}} -{{/pagingbar}}