mirror of
https://github.com/moodle/moodle.git
synced 2025-04-14 13:02:07 +02:00
MDL-63457 block_myoverview: JS update to avoid constant network requests
* Expose paged content factory to trigger last page updates * Remove repetitive network requests on hide/show courses * Manually do paged dataset modification
This commit is contained in:
parent
7dcb274c9e
commit
fd955097e4
2
blocks/myoverview/amd/build/main.min.js
vendored
2
blocks/myoverview/amd/build/main.min.js
vendored
@ -1 +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}});
|
||||
define(["jquery","block_myoverview/view","block_myoverview/view_nav"],function(a,b,c){var d=function(d){d=a(d),c.init(d),b.init(d)};return{init:d}});
|
1
blocks/myoverview/amd/build/selectors.min.js
vendored
Normal file
1
blocks/myoverview/amd/build/selectors.min.js
vendored
Normal file
@ -0,0 +1 @@
|
||||
define([],function(){return{courseView:{region:'[data-region="courses-view"]',regionContent:'[data-region="course-view-content"]'}}});
|
2
blocks/myoverview/amd/build/view.min.js
vendored
2
blocks/myoverview/amd/build/view.min.js
vendored
File diff suppressed because one or more lines are too long
2
blocks/myoverview/amd/build/view_nav.min.js
vendored
2
blocks/myoverview/amd/build/view_nav.min.js
vendored
@ -1 +1 @@
|
||||
define(["jquery","core/custom_interaction_events","block_myoverview/repository","block_myoverview/view"],function(a,b,c,d){var e={FILTERS:'[data-region="filter"]',FILTER_OPTION:"[data-filter]",DISPLAY_OPTION:"[data-display-option]"},f=function(a,b){var d=null;d="display"==a?"block_myoverview_user_view_preference":"sort"==a?"block_myoverview_user_sort_preference":"block_myoverview_user_grouping_preference",c.updateUserPreferences({preferences:[{type:d,value:b}]})},g=function(c,g,h){var i=c.find(e.FILTERS);b.define(i,[b.events.activate]),i.on(b.events.activate,e.FILTER_OPTION,function(b,c){var e=a(b.target);if(!e.hasClass("active")){var i=e.attr("data-filter"),j="data-"+i,k=e.attr("data-value"),l=e.attr("data-pref");g.attr(j,k),f(i,l),d.init(g,h),c.originalEvent.preventDefault()}}),b.define(i,[b.events.activate]),i.on(b.events.activate,e.DISPLAY_OPTION,function(b,c){var e=a(b.target);if(!e.hasClass("active")){var i=e.attr("data-display-option"),j=e.attr("data-value"),k=e.attr("data-pref");f(i,k),g.attr("data-display",j),d.reset(g,h),c.originalEvent.preventDefault()}})},h=function(b,c,d){b=a(b),g(b,c,d)};return{init:h}});
|
||||
define(["jquery","core/custom_interaction_events","block_myoverview/repository","block_myoverview/view","block_myoverview/selectors"],function(a,b,c,d,e){var f={FILTERS:'[data-region="filter"]',FILTER_OPTION:"[data-filter]",DISPLAY_OPTION:"[data-display-option]"},g=function(a,b){var d=null;d="display"==a?"block_myoverview_user_view_preference":"sort"==a?"block_myoverview_user_sort_preference":"block_myoverview_user_grouping_preference",c.updateUserPreferences({preferences:[{type:d,value:b}]})},h=function(c){var h=c.find(f.FILTERS);b.define(h,[b.events.activate]),h.on(b.events.activate,f.FILTER_OPTION,function(b,f){var h=a(b.target);if(!h.hasClass("active")){var i=h.attr("data-filter"),j=h.attr("data-pref");c.find(e.courseView.region).attr("data-"+i,h.attr("data-value")),g(i,j),d.init(c),f.originalEvent.preventDefault()}}),b.define(h,[b.events.activate]),h.on(b.events.activate,f.DISPLAY_OPTION,function(b,f){var h=a(b.target);if(!h.hasClass("active")){var i=h.attr("data-display-option"),j=h.attr("data-pref");c.find(e.courseView.region).attr("data-display",h.attr("data-value")),g(i,j),d.reset(c),f.originalEvent.preventDefault()}})},i=function(b){b=a(b),h(b)};return{init:i}});
|
@ -32,12 +32,6 @@ 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.
|
||||
*
|
||||
@ -45,12 +39,10 @@ function(
|
||||
*/
|
||||
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);
|
||||
ViewNav.init(root);
|
||||
// Initialise the courses view modules.
|
||||
View.init(coursesViewRoot, coursesViewContent);
|
||||
View.init(root);
|
||||
};
|
||||
|
||||
return {
|
||||
|
31
blocks/myoverview/amd/src/selectors.js
Normal file
31
blocks/myoverview/amd/src/selectors.js
Normal file
@ -0,0 +1,31 @@
|
||||
// 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 <http://www.gnu.org/licenses/>.
|
||||
|
||||
/**
|
||||
* Javascript to initialise the selectors for the myoverview block.
|
||||
*
|
||||
* @package block_myoverview
|
||||
* @copyright 2018 Peter Dias <peter@moodle.com>
|
||||
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
|
||||
*/
|
||||
|
||||
define([], function() {
|
||||
return {
|
||||
courseView: {
|
||||
region: '[data-region="courses-view"]',
|
||||
regionContent: '[data-region="course-view-content"]'
|
||||
}
|
||||
};
|
||||
});
|
@ -29,6 +29,7 @@ define(
|
||||
'core/custom_interaction_events',
|
||||
'core/notification',
|
||||
'core/templates',
|
||||
'block_myoverview/selectors'
|
||||
],
|
||||
function(
|
||||
$,
|
||||
@ -36,7 +37,8 @@ function(
|
||||
PagedContentFactory,
|
||||
CustomEvents,
|
||||
Notification,
|
||||
Templates
|
||||
Templates,
|
||||
Selectors
|
||||
) {
|
||||
|
||||
var SELECTORS = {
|
||||
@ -63,6 +65,10 @@ function(
|
||||
|
||||
var loadedPages = [];
|
||||
|
||||
var courseOffset = 0;
|
||||
|
||||
var lastPage = 0;
|
||||
|
||||
/**
|
||||
* Get filter values from DOM.
|
||||
*
|
||||
@ -70,11 +76,12 @@ function(
|
||||
* @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;
|
||||
var courseRegion = root.find(Selectors.courseView.region);
|
||||
return {
|
||||
display: courseRegion.attr('data-display'),
|
||||
grouping: courseRegion.attr('data-grouping'),
|
||||
sort: courseRegion.attr('data-sort')
|
||||
};
|
||||
};
|
||||
|
||||
// We want the paged content controls below the paged content area.
|
||||
@ -89,13 +96,12 @@ function(
|
||||
*
|
||||
* @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) {
|
||||
var getMyCourses = function(filters, limit) {
|
||||
|
||||
return Repository.getEnrolledCoursesByTimeline({
|
||||
offset: pageNumber * limit,
|
||||
offset: courseOffset,
|
||||
limit: limit,
|
||||
classification: filters.grouping,
|
||||
sort: filters.sort
|
||||
@ -233,17 +239,58 @@ function(
|
||||
};
|
||||
|
||||
/**
|
||||
* Initialize the Paged Content and jump to the active Page.
|
||||
* Reset the loadedPages dataset to take into account the hidden element
|
||||
*
|
||||
* @param {Object} root The course overview container
|
||||
* @param {object} content The content element for the courses view.
|
||||
* @param {Object} target The course that you want to hide
|
||||
*/
|
||||
var initializeJumpto = function(root, content) {
|
||||
var hideElement = function(root, target) {
|
||||
var id = getCourseId(target);
|
||||
|
||||
var pagingBar = root.find('[data-region="paging-bar"]');
|
||||
var jumpto = pagingBar.attr('data-active-page-number');
|
||||
var jumpto = parseInt(pagingBar.attr('data-active-page-number'));
|
||||
|
||||
initializePagedContent(root, content, jumpto);
|
||||
// Get a reduced dataset for the current page.
|
||||
var courseList = loadedPages[jumpto];
|
||||
var reducedCourse = courseList.courses.reduce(function(accumulator, current) {
|
||||
if (id != current.id) {
|
||||
accumulator.push(current);
|
||||
}
|
||||
return accumulator;
|
||||
}, []);
|
||||
|
||||
// Get the next page's data if loaded and pop the first element from it
|
||||
if (loadedPages[jumpto + 1] != undefined) {
|
||||
var newElement = loadedPages[jumpto + 1].courses.slice(0, 1);
|
||||
loadedPages[jumpto + 1].courses = loadedPages[jumpto + 1].courses.slice(1);
|
||||
|
||||
reducedCourse = $.merge(reducedCourse, newElement);
|
||||
}
|
||||
|
||||
// Check if the next page is the last page and if it still has data associated to it
|
||||
if (lastPage == jumpto + 1 && loadedPages[jumpto + 1].courses.length == 0) {
|
||||
var pagedContentContainer = root.find('[data-region="paged-content-container"]');
|
||||
PagedContentFactory.resetLastPageNumber($(pagedContentContainer).attr('id'), jumpto);
|
||||
}
|
||||
|
||||
loadedPages[jumpto].courses = reducedCourse;
|
||||
|
||||
// Reduce the course offset
|
||||
courseOffset--;
|
||||
|
||||
// Render the paged content for the current
|
||||
var pagedContentPage = getPagedContentContainer(root, jumpto);
|
||||
renderCourses(root, loadedPages[jumpto]).then(function(html, js) {
|
||||
return Templates.replaceNodeContents(pagedContentPage, html, js);
|
||||
}).catch(Notification.exception);
|
||||
|
||||
// Delete subsequent pages in order to trigger the callback
|
||||
loadedPages.forEach(function(courseList, index) {
|
||||
if (index > jumpto) {
|
||||
var page = getPagedContentContainer(root, index);
|
||||
page.remove();
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
/**
|
||||
@ -303,7 +350,7 @@ function(
|
||||
courses: coursesData.courses
|
||||
});
|
||||
} else {
|
||||
var nocoursesimg = root.attr('data-nocoursesimg');
|
||||
var nocoursesimg = root.find(Selectors.courseView.region).attr('data-nocoursesimg');
|
||||
return Templates.render(TEMPLATES.NOCOURSES, {
|
||||
nocoursesimg: nocoursesimg
|
||||
});
|
||||
@ -316,7 +363,7 @@ function(
|
||||
* @param {object} root The root element for the courses view.
|
||||
* @param {object} content The content element for the courses view.
|
||||
*/
|
||||
var initializePagedContent = function(root, content, jumpto) {
|
||||
var initializePagedContent = function(root) {
|
||||
var filters = getFilterValues(root);
|
||||
|
||||
var pagedContentPromise = PagedContentFactory.createWithLimit(
|
||||
@ -326,32 +373,78 @@ function(
|
||||
|
||||
pagesData.forEach(function(pageData) {
|
||||
var currentPage = pageData.pageNumber;
|
||||
var pageNumber = pageData.pageNumber - 1;
|
||||
var limit = pageData.limit;
|
||||
|
||||
if (lastPage == currentPage) {
|
||||
// If we are on the last page and have it's data then load it from cache
|
||||
actions.allItemsLoaded(lastPage);
|
||||
promises.push(renderCourses(root, loadedPages[currentPage]));
|
||||
return true;
|
||||
}
|
||||
|
||||
// Get 2 pages worth of data as we will need it for the hidden functionality.
|
||||
if (loadedPages[currentPage + 1] == undefined) {
|
||||
if (loadedPages[currentPage] == undefined) {
|
||||
limit *= 2;
|
||||
}
|
||||
}
|
||||
|
||||
var pagePromise = getMyCourses(
|
||||
filters,
|
||||
pageData.limit,
|
||||
pageNumber
|
||||
limit
|
||||
).then(function(coursesData) {
|
||||
if (coursesData.courses.length < pageData.limit) {
|
||||
actions.allItemsLoaded(pageData.pageNumber);
|
||||
var courses = coursesData.courses;
|
||||
var nextPageStart = 0;
|
||||
var pageCourses = [];
|
||||
|
||||
// If current page's data is loaded make sure we max it to page limit
|
||||
if (loadedPages[currentPage] != undefined) {
|
||||
pageCourses = loadedPages[currentPage].courses;
|
||||
var currentPageLength = pageCourses.length;
|
||||
if (currentPageLength < pageData.limit) {
|
||||
nextPageStart = pageData.limit - currentPageLength;
|
||||
pageCourses = $.merge(loadedPages[currentPage].courses, courses.slice(0, nextPageStart));
|
||||
}
|
||||
} else {
|
||||
nextPageStart = pageData.limit;
|
||||
pageCourses = courses.slice(0, pageData.limit);
|
||||
}
|
||||
loadedPages[currentPage] = coursesData;
|
||||
return renderCourses(root, coursesData);
|
||||
|
||||
// Finished setting up the current page
|
||||
loadedPages[currentPage] = {
|
||||
courses: pageCourses
|
||||
};
|
||||
|
||||
// Set up the next page
|
||||
var remainingCourses = courses.slice(nextPageStart, courses.length);
|
||||
loadedPages[currentPage + 1] = {
|
||||
courses: remainingCourses
|
||||
};
|
||||
|
||||
// Set the last page to either the current or next page
|
||||
if (loadedPages[currentPage].courses.length < pageData.limit) {
|
||||
lastPage = currentPage;
|
||||
actions.allItemsLoaded(currentPage);
|
||||
} else if (loadedPages[currentPage + 1] != undefined
|
||||
&& loadedPages[currentPage + 1].courses.length < pageData.limit) {
|
||||
lastPage = currentPage + 1;
|
||||
}
|
||||
|
||||
courseOffset = coursesData.nextoffset;
|
||||
return renderCourses(root, loadedPages[currentPage]);
|
||||
})
|
||||
.catch(Notification.exception);
|
||||
.catch(Notification.exception);
|
||||
|
||||
promises.push(pagePromise);
|
||||
});
|
||||
|
||||
return promises;
|
||||
},
|
||||
DEFAULT_PAGED_CONTENT_CONFIG,
|
||||
jumpto
|
||||
DEFAULT_PAGED_CONTENT_CONFIG
|
||||
);
|
||||
|
||||
pagedContentPromise.then(function(html, js) {
|
||||
return Templates.replaceNodeContents(content, html, js);
|
||||
return Templates.replaceNodeContents(root.find(Selectors.courseView.region), html, js);
|
||||
}).catch(Notification.exception);
|
||||
};
|
||||
|
||||
@ -360,7 +453,7 @@ function(
|
||||
*
|
||||
* @param {Object} root The myoverview block container element.
|
||||
*/
|
||||
var registerEventListeners = function(root, content) {
|
||||
var registerEventListeners = function(root) {
|
||||
CustomEvents.define(root, [
|
||||
CustomEvents.events.activate
|
||||
]);
|
||||
@ -397,7 +490,7 @@ function(
|
||||
};
|
||||
Repository.updateUserPreferences(request);
|
||||
|
||||
initializeJumpto(root, content);
|
||||
hideElement(root, target);
|
||||
data.originalEvent.preventDefault();
|
||||
});
|
||||
|
||||
@ -416,7 +509,7 @@ function(
|
||||
|
||||
Repository.updateUserPreferences(request);
|
||||
|
||||
initializeJumpto(root, content);
|
||||
hideElement(root, target);
|
||||
data.originalEvent.preventDefault();
|
||||
});
|
||||
};
|
||||
@ -425,33 +518,32 @@ function(
|
||||
* 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) {
|
||||
|
||||
var init = function(root) {
|
||||
root = $(root);
|
||||
loadedPages = [];
|
||||
lastPage = 0;
|
||||
courseOffset = 0;
|
||||
|
||||
if (!root.attr('data-init')) {
|
||||
registerEventListeners(root, content);
|
||||
registerEventListeners(root);
|
||||
root.attr('data-init', true);
|
||||
}
|
||||
|
||||
initializePagedContent(root, content);
|
||||
initializePagedContent(root);
|
||||
};
|
||||
|
||||
/**
|
||||
|
||||
* Reset the courses views to their original
|
||||
* state on first page load.
|
||||
* state on first page load.courseOffset
|
||||
*
|
||||
* 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 reset = function(root) {
|
||||
if (loadedPages.length > 0) {
|
||||
loadedPages.forEach(function(courseList, index) {
|
||||
var pagedContentPage = getPagedContentContainer(root, index);
|
||||
@ -460,7 +552,7 @@ function(
|
||||
}).catch(Notification.exception);
|
||||
});
|
||||
} else {
|
||||
init(root, content);
|
||||
init(root);
|
||||
}
|
||||
};
|
||||
|
||||
|
@ -26,13 +26,15 @@ define(
|
||||
'jquery',
|
||||
'core/custom_interaction_events',
|
||||
'block_myoverview/repository',
|
||||
'block_myoverview/view'
|
||||
'block_myoverview/view',
|
||||
'block_myoverview/selectors'
|
||||
],
|
||||
function(
|
||||
$,
|
||||
CustomEvents,
|
||||
Repository,
|
||||
View
|
||||
View,
|
||||
Selectors
|
||||
) {
|
||||
|
||||
var SELECTORS = {
|
||||
@ -71,10 +73,8 @@ function(
|
||||
* 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 registerSelector = function(root) {
|
||||
|
||||
var Selector = root.find(SELECTORS.FILTERS);
|
||||
|
||||
@ -91,16 +91,13 @@ function(
|
||||
}
|
||||
|
||||
var filter = option.attr('data-filter');
|
||||
var attributename = 'data-' + filter;
|
||||
var value = option.attr('data-value');
|
||||
var pref = option.attr('data-pref');
|
||||
|
||||
viewRoot.attr(attributename, value);
|
||||
|
||||
root.find(Selectors.courseView.region).attr('data-' + filter, option.attr('data-value'));
|
||||
updatePreferences(filter, pref);
|
||||
|
||||
// Reset the views.
|
||||
View.init(viewRoot, viewContent);
|
||||
View.init(root);
|
||||
|
||||
data.originalEvent.preventDefault();
|
||||
}
|
||||
@ -118,12 +115,11 @@ function(
|
||||
}
|
||||
|
||||
var filter = option.attr('data-display-option');
|
||||
var value = option.attr('data-value');
|
||||
var pref = option.attr('data-pref');
|
||||
|
||||
root.find(Selectors.courseView.region).attr('data-display', option.attr('data-value'));
|
||||
updatePreferences(filter, pref);
|
||||
viewRoot.attr('data-display', value);
|
||||
View.reset(viewRoot, viewContent);
|
||||
View.reset(root);
|
||||
data.originalEvent.preventDefault();
|
||||
}
|
||||
);
|
||||
@ -134,12 +130,10 @@ function(
|
||||
* 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) {
|
||||
var init = function(root) {
|
||||
root = $(root);
|
||||
registerSelector(root, viewRoot, viewContent);
|
||||
registerSelector(root);
|
||||
};
|
||||
|
||||
return {
|
||||
|
@ -26,6 +26,7 @@ namespace block_myoverview\privacy;
|
||||
|
||||
use core_privacy\local\request\user_preference_provider;
|
||||
use core_privacy\local\metadata\collection;
|
||||
use \core_privacy\local\request\writer;
|
||||
|
||||
defined('MOODLE_INTERNAL') || die();
|
||||
|
||||
@ -58,14 +59,14 @@ class provider implements \core_privacy\local\metadata\provider, user_preference
|
||||
public static function export_user_preferences(int $userid) {
|
||||
$preference = get_user_preferences('block_myoverview_user_sort_preference', null, $userid);
|
||||
if (isset($preference)) {
|
||||
\core_privacy\local\request\writer::export_user_preference('block_myoverview',
|
||||
writer::export_user_preference('block_myoverview',
|
||||
'block_myoverview_user_sort_preference', get_string($preference, 'block_myoverview'),
|
||||
get_string('privacy:metadata:overviewsortpreference', 'block_myoverview'));
|
||||
}
|
||||
|
||||
$preference = get_user_preferences('block_myoverview_user_view_preference', null, $userid);
|
||||
if (isset($preference)) {
|
||||
\core_privacy\local\request\writer::export_user_preference('block_myoverview',
|
||||
writer::export_user_preference('block_myoverview',
|
||||
'block_myoverview_user_view_preference',
|
||||
get_string($preference, 'block_myoverview'),
|
||||
get_string('privacy:metadata:overviewviewpreference', 'block_myoverview'));
|
||||
@ -73,7 +74,7 @@ class provider implements \core_privacy\local\metadata\provider, user_preference
|
||||
|
||||
$preference = get_user_preferences('block_myoverview_user_grouping_preference', null, $userid);
|
||||
if (isset($preference)) {
|
||||
\core_privacy\local\request\writer::export_user_preference('block_myoverview',
|
||||
writer::export_user_preference('block_myoverview',
|
||||
'block_myoverview_user_grouping_preference',
|
||||
get_string($preference, 'block_myoverview'),
|
||||
get_string('privacy:metadata:overviewgroupingpreference', 'block_myoverview'));
|
||||
|
@ -1,5 +1,5 @@
|
||||
@block @block_myoverview @javascript
|
||||
Feature: The my overview block allows users to favourite their courses
|
||||
Feature: The my overview block allows users to hide their courses
|
||||
In order to enable the my overview block in a course
|
||||
As a student
|
||||
I can add the my overview block to my dashboard
|
||||
|
2
lib/amd/build/paged_content.min.js
vendored
2
lib/amd/build/paged_content.min.js
vendored
@ -1 +1 @@
|
||||
define(["jquery","core/paged_content_pages","core/paged_content_paging_bar","core/paged_content_paging_bar_limit_selector","core/paged_content_paging_dropdown"],function(a,b,c,d,e){var f=function(f,g,h){f=a(f);var i=f.find(b.rootSelector),j=f.find(c.rootSelector),k=f.find(e.rootSelector),l=f.find(d.rootSelector),m=f.attr("id");b.init(i,m,g,h),j.length&&(c.init(j,m),h>1&&c.showPage(j,h,m)),l.length&&d.init(l,m),k.length&&e.init(k,m)};return{init:f,rootSelector:'[data-region="paged-content-container"]'}});
|
||||
define(["jquery","core/paged_content_pages","core/paged_content_paging_bar","core/paged_content_paging_bar_limit_selector","core/paged_content_paging_dropdown"],function(a,b,c,d,e){var f=function(f,g){f=a(f);var h=f.find(b.rootSelector),i=f.find(c.rootSelector),j=f.find(e.rootSelector),k=f.find(d.rootSelector),l=f.attr("id");b.init(h,l,g),i.length&&c.init(i,l),k.length&&d.init(k,l),j.length&&e.init(j,l)};return{init:f,rootSelector:'[data-region="paged-content-container"]'}});
|
2
lib/amd/build/paged_content_factory.min.js
vendored
2
lib/amd/build/paged_content_factory.min.js
vendored
@ -1 +1 @@
|
||||
define(["jquery","core/templates","core/notification","core/paged_content"],function(a,b,c,d){var e={PAGED_CONTENT:"core/paged_content"},f={ITEMS_PER_PAGE_SINGLE:25,ITEMS_PER_PAGE_ARRAY:[25,50,100,0],MAX_PAGES:3},g=function(){return{pagingbar:!1,pagingdropdown:!1,skipjs:!0,ignorecontrolwhileloading:!0,controlplacementbottom:!1}},h=function(){return{showitemsperpageselector:!1,itemsperpage:35,previous:!0,next:!0,activepagenumber:1,hidecontrolonsinglepage:!0,pages:[]}},i=function(a,b){var c=1;if(a>0){var d=a%b;d?(a-=d,c=a/b+1):c=a/b}return c},j=function(b,c){null===c&&(c=f.ITEMS_PER_PAGE_SINGLE),a.isArray(c)&&(c=c[0]);var d=h();d.itemsperpage=c;for(var e=i(b,c),g=1;g<=e;g++){var j={number:g,page:""+g};1===g&&(j.active=!0),d.pages.push(j)}return d},k=function(b){if(a.isArray(b)){var c=b.map(function(a){return"number"==typeof a?{value:a,active:!1}:a}),d=c.filter(function(a){return a.active});return d.length||(c[0].active=!0),c}return b},l=function(b){null===b&&(b=f.ITEMS_PER_PAGE_ARRAY);var c=h();return c.itemsperpage=k(b),c.showitemsperpageselector=a.isArray(b),c},m=function(a,b){return a?j(a,b):l(b)},n=function(b,c){if(null===b&&(b=f.ITEMS_PER_PAGE_SINGLE),a.isArray(b))return{options:b};var d={options:[]},e=0,g=0,h=f.MAX_PAGES;c.hasOwnProperty("maxPages")&&(h=c.maxPages);for(var i=1;i<=h;i++){var j=0;i<=2?(j=b,g=b):(g=2*g,j=g),e+=j;var k={itemcount:j,content:e};1===i&&(k.active=!0),d.options.push(k)}return d},o=function(a,b,c){var d=g();return c.hasOwnProperty("ignoreControlWhileLoading")&&(d.ignorecontrolwhileloading=c.ignoreControlWhileLoading),c.hasOwnProperty("controlPlacementBottom")&&(d.controlplacementbottom=c.controlPlacementBottom),c.hasOwnProperty("hideControlOnSinglePage")&&(d.hidecontrolonsinglepage=c.hideControlOnSinglePage),c.hasOwnProperty("ariaLabels")&&(d.arialabels=c.ariaLabels),c.hasOwnProperty("dropdown")&&c.dropdown?d.pagingdropdown=n(b,c):d.pagingbar=m(a,b),d},p=function(a,b){return r(null,null,a,b)},q=function(a,b,c,d){return r(null,a,b,c,d)},r=function(f,g,h,i,j){i=i||{};var k=a.Deferred(),l=o(f,g,i);return b.render(e.PAGED_CONTENT,l).then(function(b,c){b=a(b);var e=b;d.init(e,h,j),k.resolve(b,c)}).fail(function(a){k.reject(a)}).fail(c.exception),k.promise()},s=function(a,b,c,d){"undefined"==typeof d&&(d={});var e=a.length;return r(e,b,function(b){var d=[];return b.forEach(function(b){var c=b.offset,f=b.limit?c+b.limit:e,g=a.slice(c,f);d.push(g)}),c(d)},d)};return{create:p,createWithLimit:q,createWithTotalAndLimit:r,createFromStaticList:s,createFromAjax:r}});
|
||||
define(["jquery","core/templates","core/notification","core/paged_content","core/paged_content_events","core/pubsub"],function(a,b,c,d,e,f){var g={PAGED_CONTENT:"core/paged_content"},h={ITEMS_PER_PAGE_SINGLE:25,ITEMS_PER_PAGE_ARRAY:[25,50,100,0],MAX_PAGES:3},i=function(){return{pagingbar:!1,pagingdropdown:!1,skipjs:!0,ignorecontrolwhileloading:!0,controlplacementbottom:!1}},j=function(){return{showitemsperpageselector:!1,itemsperpage:35,previous:!0,next:!0,activepagenumber:1,hidecontrolonsinglepage:!0,pages:[]}},k=function(a,b){var c=1;if(a>0){var d=a%b;d?(a-=d,c=a/b+1):c=a/b}return c},l=function(b,c){null===c&&(c=h.ITEMS_PER_PAGE_SINGLE),a.isArray(c)&&(c=c[0]);var d=j();d.itemsperpage=c;for(var e=k(b,c),f=1;f<=e;f++){var g={number:f,page:""+f};1===f&&(g.active=!0),d.pages.push(g)}return d},m=function(b){if(a.isArray(b)){var c=b.map(function(a){return"number"==typeof a?{value:a,active:!1}:a}),d=c.filter(function(a){return a.active});return d.length||(c[0].active=!0),c}return b},n=function(b){null===b&&(b=h.ITEMS_PER_PAGE_ARRAY);var c=j();return c.itemsperpage=m(b),c.showitemsperpageselector=a.isArray(b),c},o=function(a,b){return a?l(a,b):n(b)},p=function(b,c){if(null===b&&(b=h.ITEMS_PER_PAGE_SINGLE),a.isArray(b))return{options:b};var d={options:[]},e=0,f=0,g=h.MAX_PAGES;c.hasOwnProperty("maxPages")&&(g=c.maxPages);for(var i=1;i<=g;i++){var j=0;i<=2?(j=b,f=b):(f=2*f,j=f),e+=j;var k={itemcount:j,content:e};1===i&&(k.active=!0),d.options.push(k)}return d},q=function(a,b,c){var d=i();return c.hasOwnProperty("ignoreControlWhileLoading")&&(d.ignorecontrolwhileloading=c.ignoreControlWhileLoading),c.hasOwnProperty("controlPlacementBottom")&&(d.controlplacementbottom=c.controlPlacementBottom),c.hasOwnProperty("hideControlOnSinglePage")&&(d.hidecontrolonsinglepage=c.hideControlOnSinglePage),c.hasOwnProperty("ariaLabels")&&(d.arialabels=c.ariaLabels),c.hasOwnProperty("dropdown")&&c.dropdown?d.pagingdropdown=p(b,c):d.pagingbar=o(a,b),d},r=function(a,b){return t(null,null,a,b)},s=function(a,b,c){return t(null,a,b,c)},t=function(e,f,h,i){i=i||{};var j=a.Deferred(),k=q(e,f,i);return b.render(g.PAGED_CONTENT,k).then(function(b,c){b=a(b);var e=b;d.init(e,h),j.resolve(b,c)}).fail(function(a){j.reject(a)}).fail(c.exception),j.promise()},u=function(a,b,c,d){"undefined"==typeof d&&(d={});var e=a.length;return t(e,b,function(b){var d=[];return b.forEach(function(b){var c=b.offset,f=b.limit?c+b.limit:e,g=a.slice(c,f);d.push(g)}),c(d)},d)},v=function(a,b){f.publish(a+e.ALL_ITEMS_LOADED,b)};return{create:r,createWithLimit:s,createWithTotalAndLimit:t,createFromStaticList:u,createFromAjax:t,resetLastPageNumber:v}});
|
2
lib/amd/build/paged_content_pages.min.js
vendored
2
lib/amd/build/paged_content_pages.min.js
vendored
@ -1 +1 @@
|
||||
define(["jquery","core/templates","core/notification","core/pubsub","core/paged_content_events"],function(a,b,c,d,e){var f={ROOT:'[data-region="page-container"]',PAGE_REGION:'[data-region="paged-content-page"]',ACTIVE_PAGE_REGION:'[data-region="paged-content-page"].active'},g={PAGING_CONTENT_ITEM:"core/paged_content_page",LOADING:"core/overlay_loading"},h=300,i=function(a,b){return a.find('[data-page="'+b+'"]')},j=function(d){var e=a.Deferred();return d.attr("aria-busy",!0),b.render(g.LOADING,{visible:!0}).then(function(b){var c=a(b),f=setTimeout(function(){d.css("position","relative"),c.appendTo(d)},h);e.always(function(){clearTimeout(f),c.remove(),d.css("position",""),d.removeAttr("aria-busy")})}).fail(c.exception),e},k=function(d,e,f){var h=a.Deferred();return e.then(function(a,e){e=e||"",b.render(g.PAGING_CONTENT_ITEM,{page:f,content:a}).then(function(a){b.appendNodeContents(d,a,e);var c=i(d,f);h.resolve(c)}).fail(function(a){h.reject(a)}).fail(c.exception)}).fail(function(a){h.reject(a)}).fail(c.exception),h.promise()},l=function(b,g,h,l,m){var n=[],o=[],p=a.Deferred(),q=!0;if(g.forEach(function(a){m>1&&a.pageNumber!=m&&(q=!1);var c=a.pageNumber,d=i(b,c);d.length?n.push(d):o.push(a)}),o.length&&"function"==typeof l){var r=l(o,{allItemsLoaded:function(a){d.publish(h+e.ALL_ITEMS_LOADED,a)}}),s=r.map(function(a,c){return k(b,a,o[c].pageNumber)});a.when.apply(a,s).then(function(){var a=Array.prototype.slice.call(arguments);p.resolve(a)}).fail(function(a){p.reject(a)}).fail(c.exception)}else p.resolve([]);var t=j(b);p.then(function(a){var c=n.concat(a);b.find(f.PAGE_REGION).addClass("hidden"),c.forEach(function(a){q&&a.removeClass("hidden")})}).then(function(){d.publish(h+e.PAGES_SHOWN,g)}).fail(c.exception).always(function(){t.resolve()})},m=function(b,c,f,g){b=a(b),d.subscribe(c+e.SHOW_PAGES,function(a){l(b,a,c,f,g),g=0}),d.subscribe(c+e.SET_ITEMS_PER_PAGE_LIMIT,function(){b.empty()})};return{init:m,rootSelector:f.ROOT}});
|
||||
define(["jquery","core/templates","core/notification","core/pubsub","core/paged_content_events"],function(a,b,c,d,e){var f={ROOT:'[data-region="page-container"]',PAGE_REGION:'[data-region="paged-content-page"]',ACTIVE_PAGE_REGION:'[data-region="paged-content-page"].active'},g={PAGING_CONTENT_ITEM:"core/paged_content_page",LOADING:"core/overlay_loading"},h=300,i=function(a,b){return a.find('[data-page="'+b+'"]')},j=function(d){var e=a.Deferred();return d.attr("aria-busy",!0),b.render(g.LOADING,{visible:!0}).then(function(b){var c=a(b),f=setTimeout(function(){d.css("position","relative"),c.appendTo(d)},h);e.always(function(){clearTimeout(f),c.remove(),d.css("position",""),d.removeAttr("aria-busy")})}).fail(c.exception),e},k=function(d,e,f){var h=a.Deferred();return e.then(function(a,e){e=e||"",b.render(g.PAGING_CONTENT_ITEM,{page:f,content:a}).then(function(a){b.appendNodeContents(d,a,e);var c=i(d,f);h.resolve(c)}).fail(function(a){h.reject(a)}).fail(c.exception)}).fail(function(a){h.reject(a)}).fail(c.exception),h.promise()},l=function(b,g,h,l){var m=[],n=[],o=a.Deferred(),p=!0;if(g.forEach(function(a){var c=a.pageNumber,d=i(b,c);d.length?m.push(d):n.push(a)}),n.length&&"function"==typeof l){var q=l(n,{allItemsLoaded:function(a){d.publish(h+e.ALL_ITEMS_LOADED,a)}}),r=q.map(function(a,c){return k(b,a,n[c].pageNumber)});a.when.apply(a,r).then(function(){var a=Array.prototype.slice.call(arguments);o.resolve(a)}).fail(function(a){o.reject(a)}).fail(c.exception)}else o.resolve([]);var s=j(b);o.then(function(a){var c=m.concat(a);b.find(f.PAGE_REGION).addClass("hidden"),c.forEach(function(a){p&&a.removeClass("hidden")})}).then(function(){d.publish(h+e.PAGES_SHOWN,g)}).fail(c.exception).always(function(){s.resolve()})},m=function(b,c,f){b=a(b),d.subscribe(c+e.SHOW_PAGES,function(a){l(b,a,c,f)}),d.subscribe(c+e.SET_ITEMS_PER_PAGE_LIMIT,function(){b.empty()})};return{init:m,rootSelector:f.ROOT}});
|
@ -45,7 +45,7 @@ function(
|
||||
* content page. See core/paged_content_pages for
|
||||
* more defails.
|
||||
*/
|
||||
var init = function(root, renderPagesContentCallback, jumpto) {
|
||||
var init = function(root, renderPagesContentCallback) {
|
||||
root = $(root);
|
||||
var pagesContainer = root.find(Pages.rootSelector);
|
||||
var pagingBarContainer = root.find(PagingBar.rootSelector);
|
||||
@ -53,13 +53,10 @@ function(
|
||||
var pagingBarLimitSelectorContainer = root.find(PagingBarLimitSelector.rootSelector);
|
||||
var id = root.attr('id');
|
||||
|
||||
Pages.init(pagesContainer, id, renderPagesContentCallback, jumpto);
|
||||
Pages.init(pagesContainer, id, renderPagesContentCallback);
|
||||
|
||||
if (pagingBarContainer.length) {
|
||||
PagingBar.init(pagingBarContainer, id);
|
||||
if (jumpto > 1) {
|
||||
PagingBar.showPage(pagingBarContainer, jumpto, id);
|
||||
}
|
||||
}
|
||||
|
||||
if (pagingBarLimitSelectorContainer.length) {
|
||||
|
@ -25,13 +25,17 @@ define(
|
||||
'jquery',
|
||||
'core/templates',
|
||||
'core/notification',
|
||||
'core/paged_content'
|
||||
'core/paged_content',
|
||||
'core/paged_content_events',
|
||||
'core/pubsub'
|
||||
],
|
||||
function(
|
||||
$,
|
||||
Templates,
|
||||
Notification,
|
||||
PagedContent
|
||||
PagedContent,
|
||||
PagedContentEvents,
|
||||
PubSub
|
||||
) {
|
||||
var TEMPLATES = {
|
||||
PAGED_CONTENT: 'core/paged_content'
|
||||
@ -386,8 +390,8 @@ function(
|
||||
* @param {object} config Configuration options provided by the client.
|
||||
* @return {promise} Resolved with jQuery HTML and string JS.
|
||||
*/
|
||||
var createWithLimit = function(itemsPerPage, renderPagesContentCallback, config, jumpto) {
|
||||
return createWithTotalAndLimit(null, itemsPerPage, renderPagesContentCallback, config, jumpto);
|
||||
var createWithLimit = function(itemsPerPage, renderPagesContentCallback, config) {
|
||||
return createWithTotalAndLimit(null, itemsPerPage, renderPagesContentCallback, config);
|
||||
};
|
||||
|
||||
/**
|
||||
@ -412,7 +416,7 @@ function(
|
||||
* @param {object} config Configuration options provided by the client.
|
||||
* @return {promise} Resolved with jQuery HTML and string JS.
|
||||
*/
|
||||
var createWithTotalAndLimit = function(numberOfItems, itemsPerPage, renderPagesContentCallback, config, jumpto) {
|
||||
var createWithTotalAndLimit = function(numberOfItems, itemsPerPage, renderPagesContentCallback, config) {
|
||||
config = config || {};
|
||||
|
||||
var deferred = $.Deferred();
|
||||
@ -424,7 +428,7 @@ function(
|
||||
|
||||
var container = html;
|
||||
|
||||
PagedContent.init(container, renderPagesContentCallback, jumpto);
|
||||
PagedContent.init(container, renderPagesContentCallback);
|
||||
|
||||
deferred.resolve(html, js);
|
||||
return;
|
||||
@ -479,12 +483,24 @@ function(
|
||||
}, config);
|
||||
};
|
||||
|
||||
/**
|
||||
* Reset the last page number for the generated paged-content
|
||||
* This is used when we need a way to update the last page number outside of the getters callback
|
||||
*
|
||||
* @param {String} id ID of the paged content container
|
||||
* @param {Int} lastPageNumber The last page number
|
||||
*/
|
||||
var resetLastPageNumber = function(id, lastPageNumber) {
|
||||
PubSub.publish(id + PagedContentEvents.ALL_ITEMS_LOADED, lastPageNumber);
|
||||
};
|
||||
|
||||
return {
|
||||
create: create,
|
||||
createWithLimit: createWithLimit,
|
||||
createWithTotalAndLimit: createWithTotalAndLimit,
|
||||
createFromStaticList: createFromStaticList,
|
||||
// Backwards compatibility just in case anyone was using this.
|
||||
createFromAjax: createWithTotalAndLimit
|
||||
createFromAjax: createWithTotalAndLimit,
|
||||
resetLastPageNumber: resetLastPageNumber
|
||||
};
|
||||
});
|
||||
|
@ -181,7 +181,7 @@ define(
|
||||
* @param {string} id A unique id for this instance.
|
||||
* @param {function} renderPagesContentCallback Render pages content.
|
||||
*/
|
||||
var showPages = function(root, pagesData, id, renderPagesContentCallback, jumpto) {
|
||||
var showPages = function(root, pagesData, id, renderPagesContentCallback) {
|
||||
var existingPages = [];
|
||||
var newPageData = [];
|
||||
var newPagesPromise = $.Deferred();
|
||||
@ -189,9 +189,6 @@ define(
|
||||
// Check which of the pages being requests have previously been rendered
|
||||
// so that we only ask for new pages to be rendered by the callback.
|
||||
pagesData.forEach(function(pageData) {
|
||||
if ((jumpto > 1) && (pageData.pageNumber != jumpto)) {
|
||||
shownewpage = false;
|
||||
}
|
||||
var pageNumber = pageData.pageNumber;
|
||||
var existingPage = findPage(root, pageNumber);
|
||||
if (existingPage.length) {
|
||||
@ -294,13 +291,11 @@ define(
|
||||
* @param {string} id A unique id for this instance.
|
||||
* @param {function} renderPagesContentCallback Render pages content.
|
||||
*/
|
||||
var init = function(root, id, renderPagesContentCallback, jumpto) {
|
||||
var init = function(root, id, renderPagesContentCallback) {
|
||||
root = $(root);
|
||||
|
||||
PubSub.subscribe(id + PagedContentEvents.SHOW_PAGES, function(pagesData) {
|
||||
showPages(root, pagesData, id, renderPagesContentCallback, jumpto);
|
||||
// Reset the jumpto number after using it once else it will only ever show the one page.
|
||||
jumpto = 0;
|
||||
showPages(root, pagesData, id, renderPagesContentCallback);
|
||||
});
|
||||
|
||||
PubSub.subscribe(id + PagedContentEvents.SET_ITEMS_PER_PAGE_LIMIT, function() {
|
||||
|
Loading…
x
Reference in New Issue
Block a user