From 11988d74b42980e62dd81f022dc96dbe1e2dc6b8 Mon Sep 17 00:00:00 2001 From: Peter Date: Tue, 30 Oct 2018 13:42:14 +0800 Subject: [PATCH] MDL-63793 block_myoverview: Persist the user's paging limit preference * providers for paging preferences * Moved the user pref persistence to the factory * Added client defined namespace in config * Define custom client events in the client instead of passing to the factory --- blocks/myoverview/amd/build/view.min.js | 2 +- blocks/myoverview/amd/src/view.js | 59 +++++++++++++++++-- blocks/myoverview/block_myoverview.php | 3 +- blocks/myoverview/classes/output/main.php | 13 +++- .../myoverview/classes/privacy/provider.php | 10 ++++ .../myoverview/lang/en/block_myoverview.php | 1 + blocks/myoverview/lib.php | 18 ++++++ .../templates/courses-view.mustache | 1 + ...k_myoverview_pagelimit_persistence.feature | 57 ++++++++++++++++++ blocks/myoverview/tests/privacy_test.php | 26 ++++---- lib/amd/build/paged_content.min.js | 2 +- lib/amd/build/paged_content_factory.min.js | 2 +- lib/amd/src/paged_content.js | 9 ++- lib/amd/src/paged_content_factory.js | 57 +++++++++++++++++- 14 files changed, 233 insertions(+), 27 deletions(-) create mode 100644 blocks/myoverview/tests/behat/block_myoverview_pagelimit_persistence.feature diff --git a/blocks/myoverview/amd/build/view.min.js b/blocks/myoverview/amd/build/view.min.js index 02121189aa0a5..dbce038b3f703 100644 --- a/blocks/myoverview/amd/build/view.min.js +++ b/blocks/myoverview/amd/build/view.min.js @@ -1 +1 @@ -define(["jquery","block_myoverview/repository","core/paged_content_factory","core/pubsub","core/custom_interaction_events","core/notification","core/templates","core_course/events","block_myoverview/selectors"],function(a,b,c,d,e,f,g,h,i){var j={COURSE_REGION:'[data-region="course-view-content"]',ACTION_HIDE_COURSE:'[data-action="hide-course"]',ACTION_SHOW_COURSE:'[data-action="show-course"]',ACTION_ADD_FAVOURITE:'[data-action="add-favourite"]',ACTION_REMOVE_FAVOURITE:'[data-action="remove-favourite"]',FAVOURITE_ICON:'[data-region="favourite-icon"]',ICON_IS_FAVOURITE:'[data-region="is-favourite"]',ICON_NOT_FAVOURITE:'[data-region="not-favourite"]',PAGED_CONTENT_CONTAINER:'[data-region="page-container"]'},k={COURSES_CARDS:"block_myoverview/view-cards",COURSES_LIST:"block_myoverview/view-list",COURSES_SUMMARY:"block_myoverview/view-summary",NOCOURSES:"block_myoverview/no-courses"},l=[12,24,48],m=[],n=0,o=0,p=0,q=function(a){var b=a.find(i.courseView.region);return{display:b.attr("data-display"),grouping:b.attr("data-grouping"),sort:b.attr("data-sort")}},r={ignoreControlWhileLoading:!0,controlPlacementBottom:!0},s=function(a,c){return b.getEnrolledCoursesByTimeline({offset:n,limit:c,classification:a.grouping,sort:a.sort})},t=function(a,b){return a.find(j.FAVOURITE_ICON+'[data-course-id="'+b+'"]')},u=function(a,b){return a.find('[data-region="paged-content-page"][data-page="'+b+'"]')},v=function(a){return a.attr("data-course-id")},w=function(a,b){var c=t(a,b),d=c.find(j.ICON_IS_FAVOURITE);d.addClass("hidden"),d.attr("aria-hidden",!0);var e=c.find(j.ICON_NOT_FAVOURITE);e.removeClass("hidden"),e.attr("aria-hidden",!1)},x=function(a,b){var c=t(a,b),d=c.find(j.ICON_IS_FAVOURITE);d.removeClass("hidden"),d.attr("aria-hidden",!1);var e=c.find(j.ICON_NOT_FAVOURITE);e.addClass("hidden"),e.attr("aria-hidden",!0)},y=function(a,b){return a.find('[data-action="add-favourite"][data-course-id="'+b+'"]')},z=function(a,b){return a.find('[data-action="remove-favourite"][data-course-id="'+b+'"]')},A=function(a,b){var c=z(a,b),e=y(a,b);D(b,!0).then(function(g){g?(d.publish(h.favourited),c.removeClass("hidden"),e.addClass("hidden"),x(a,b)):f.alert("Starring course failed","Could not change favourite state")})["catch"](f.exception)},B=function(a,b){var c=z(a,b),e=y(a,b);D(b,!1).then(function(g){g?(d.publish(h.unfavorited),c.addClass("hidden"),e.removeClass("hidden"),w(a,b)):f.alert("Starring course failed","Could not change favourite state")})["catch"](f.exception)},C=function(b,d){var e=v(d),h=b.find('[data-region="paging-bar"]'),i=parseInt(h.attr("data-active-page-number")),j=m[i],k=j.courses.reduce(function(a,b){return e!=b.id&&a.push(b),a},[]);if(void 0!=m[i+1]){var l=m[i+1].courses.slice(0,1);m.forEach(function(b,c){if(c>i){var d=[];void 0!=m[c+1]&&(d=m[c+1].courses.slice(0,1)),m[c].courses=a.merge(m[c].courses.slice(1),d)}}),k=a.merge(k,l)}if(o==i+1&&0==m[i+1].courses.length){var p=b.find('[data-region="paged-content-container"]');c.resetLastPageNumber(a(p).attr("id"),i)}m[i].courses=k,n--;var q=u(b,i);E(b,m[i]).then(function(a,b){return g.replaceNodeContents(q,a,b)})["catch"](f.exception),m.forEach(function(a,c){if(c>i){var d=u(b,c);d.remove()}})},D=function(a,c){return b.setFavouriteCourses({courses:[{id:a,favourite:c}]}).then(function(b){return 0==b.warnings.length&&(m.forEach(function(b){b.courses.forEach(function(d,e){d.id==a&&(b.courses[e].isfavourite=c)})}),!0)})["catch"](f.exception)},E=function(a,b){var c=q(a),d="";if(d="cards"==c.display?k.COURSES_CARDS:"list"==c.display?k.COURSES_LIST:k.COURSES_SUMMARY,b.courses.length)return g.render(d,{courses:b.courses});var e=a.find(i.courseView.region).attr("data-nocoursesimg");return g.render(k.NOCOURSES,{nocoursesimg:e})},F=function(b){var d=q(b),e=c.createWithLimit(l,function(c,e){var g=[];return c.forEach(function(c){var h=c.pageNumber,i=c.limit;if(p!=i&&(m=[],n=0,o=0),o==h)return e.allItemsLoaded(o),void g.push(E(b,m[h]));p=i,void 0==m[h+1]&&void 0==m[h]&&(i*=2);var j=s(d,i).then(function(d){var f=d.courses,g=0,i=[];if(void 0!=m[h]){i=m[h].courses;var j=i.length;j0?m.forEach(function(b,c){var d=u(a,c);E(a,b).then(function(a,b){return g.replaceNodeContents(d,a,b)})["catch"](f.exception)}):H(a)};return{init:H,reset:I}}); \ No newline at end of file +define(["jquery","block_myoverview/repository","core/paged_content_factory","core/pubsub","core/custom_interaction_events","core/notification","core/templates","core_course/events","block_myoverview/selectors","core/paged_content_events"],function(a,b,c,d,e,f,g,h,i,j){var k={COURSE_REGION:'[data-region="course-view-content"]',ACTION_HIDE_COURSE:'[data-action="hide-course"]',ACTION_SHOW_COURSE:'[data-action="show-course"]',ACTION_ADD_FAVOURITE:'[data-action="add-favourite"]',ACTION_REMOVE_FAVOURITE:'[data-action="remove-favourite"]',FAVOURITE_ICON:'[data-region="favourite-icon"]',ICON_IS_FAVOURITE:'[data-region="is-favourite"]',ICON_NOT_FAVOURITE:'[data-region="not-favourite"]',PAGED_CONTENT_CONTAINER:'[data-region="page-container"]'},l={COURSES_CARDS:"block_myoverview/view-cards",COURSES_LIST:"block_myoverview/view-list",COURSES_SUMMARY:"block_myoverview/view-summary",NOCOURSES:"block_myoverview/no-courses"},m=[12,24,48],n=[],o=0,p=0,q=0,r=null,s=function(a){var b=a.find(i.courseView.region);return{display:b.attr("data-display"),grouping:b.attr("data-grouping"),sort:b.attr("data-sort")}},t={ignoreControlWhileLoading:!0,controlPlacementBottom:!0,persistentLimitKey:"block_myoverview_user_paging_preference"},u=function(a,c){return b.getEnrolledCoursesByTimeline({offset:o,limit:c,classification:a.grouping,sort:a.sort})},v=function(a,b){return a.find(k.FAVOURITE_ICON+'[data-course-id="'+b+'"]')},w=function(a,b){return a.find('[data-region="paged-content-page"][data-page="'+b+'"]')},x=function(a){return a.attr("data-course-id")},y=function(a,b){var c=v(a,b),d=c.find(k.ICON_IS_FAVOURITE);d.addClass("hidden"),d.attr("aria-hidden",!0);var e=c.find(k.ICON_NOT_FAVOURITE);e.removeClass("hidden"),e.attr("aria-hidden",!1)},z=function(a,b){var c=v(a,b),d=c.find(k.ICON_IS_FAVOURITE);d.removeClass("hidden"),d.attr("aria-hidden",!1);var e=c.find(k.ICON_NOT_FAVOURITE);e.addClass("hidden"),e.attr("aria-hidden",!0)},A=function(a,b){return a.find('[data-action="add-favourite"][data-course-id="'+b+'"]')},B=function(a,b){return a.find('[data-action="remove-favourite"][data-course-id="'+b+'"]')},C=function(a,b){var c=B(a,b),e=A(a,b);F(b,!0).then(function(g){g?(d.publish(h.favourited),c.removeClass("hidden"),e.addClass("hidden"),z(a,b)):f.alert("Starring course failed","Could not change favourite state")})["catch"](f.exception)},D=function(a,b){var c=B(a,b),e=A(a,b);F(b,!1).then(function(g){g?(d.publish(h.unfavorited),c.addClass("hidden"),e.removeClass("hidden"),y(a,b)):f.alert("Starring course failed","Could not change favourite state")})["catch"](f.exception)},E=function(b,d){var e=x(d),h=b.find('[data-region="paging-bar"]'),i=parseInt(h.attr("data-active-page-number")),j=n[i],k=j.courses.reduce(function(a,b){return e!=b.id&&a.push(b),a},[]);if(void 0!=n[i+1]){var l=n[i+1].courses.slice(0,1);n.forEach(function(b,c){if(c>i){var d=[];void 0!=n[c+1]&&(d=n[c+1].courses.slice(0,1)),n[c].courses=a.merge(n[c].courses.slice(1),d)}}),k=a.merge(k,l)}if(p==i+1&&0==n[i+1].courses.length){var m=b.find('[data-region="paged-content-container"]');c.resetLastPageNumber(a(m).attr("id"),i)}n[i].courses=k,o--;var q=w(b,i);G(b,n[i]).then(function(a,b){return g.replaceNodeContents(q,a,b)})["catch"](f.exception),n.forEach(function(a,c){if(c>i){var d=w(b,c);d.remove()}})},F=function(a,c){return b.setFavouriteCourses({courses:[{id:a,favourite:c}]}).then(function(b){return 0==b.warnings.length&&(n.forEach(function(b){b.courses.forEach(function(d,e){d.id==a&&(b.courses[e].isfavourite=c)})}),!0)})["catch"](f.exception)},G=function(a,b){var c=s(a),d="";if(d="cards"==c.display?l.COURSES_CARDS:"list"==c.display?l.COURSES_LIST:l.COURSES_SUMMARY,b.courses.length)return g.render(d,{courses:b.courses});var e=a.find(i.courseView.region).attr("data-nocoursesimg");return g.render(l.NOCOURSES,{nocoursesimg:e})},H=function(a){this.find(i.courseView.region).attr("data-paging",a)},I=function(a,b){var c=b+j.SET_ITEMS_PER_PAGE_LIMIT;d.subscribe(c,H.bind(a))},J=function(b){r="block_myoverview_"+b.attr("id")+"_"+Math.random();var d=m,e=parseInt(b.find(i.courseView.region).attr("data-paging"),10);e&&(d=m.map(function(a){var b=!1;return a==e&&(b=!0),{value:a,active:b}}));var h=s(b),j=a.extend({},t);j.eventNamespace=r;var k=c.createWithLimit(d,function(c,d){var e=[];return c.forEach(function(c){var g=c.pageNumber,i=c.limit;if(q!=i&&(n=[],o=0,p=0),p==g)return d.allItemsLoaded(p),void e.push(G(b,n[g]));q=i,void 0==n[g+1]&&void 0==n[g]&&(i*=2);var j=u(h,i).then(function(e){var f=e.courses,h=0,i=[];if(void 0!=n[g]){i=n[g].courses;var j=i.length;j0?n.forEach(function(b,c){var d=w(a,c);G(a,b).then(function(a,b){return g.replaceNodeContents(d,a,b)})["catch"](f.exception)}):L(a)};return{init:L,reset:M}}); \ No newline at end of file diff --git a/blocks/myoverview/amd/src/view.js b/blocks/myoverview/amd/src/view.js index 62f44a830ef72..f9d0e1db54028 100644 --- a/blocks/myoverview/amd/src/view.js +++ b/blocks/myoverview/amd/src/view.js @@ -31,7 +31,8 @@ define( 'core/notification', 'core/templates', 'core_course/events', - 'block_myoverview/selectors' + 'block_myoverview/selectors', + 'core/paged_content_events', ], function( $, @@ -42,7 +43,8 @@ function( Notification, Templates, CourseEvents, - Selectors + Selectors, + PagedContentEvents ) { var SELECTORS = { @@ -75,6 +77,8 @@ function( var lastLimit = 0; + var namespace = null; + /** * Get filter values from DOM. * @@ -95,6 +99,7 @@ function( var DEFAULT_PAGED_CONTENT_CONFIG = { ignoreControlWhileLoading: true, controlPlacementBottom: true, + persistentLimitKey: 'block_myoverview_user_paging_preference' }; /** @@ -377,17 +382,58 @@ function( } }; + /** + * Return the callback to be passed to the subscribe event + * + * @param {Number} limit The paged limit that is passed through the event + */ + var setLimit = function(limit) { + this.find(Selectors.courseView.region).attr('data-paging', limit); + }; + /** * Intialise the paged list and cards views on page load. + * Returns an array of paged contents that we would like to handle here + * + * @param {object} root The root element for the courses view + * @param {string} namespace The namespace for all the events attached + */ + var registerPagedEventHandlers = function(root, namespace) { + var event = namespace + PagedContentEvents.SET_ITEMS_PER_PAGE_LIMIT; + PubSub.subscribe(event, setLimit.bind(root)); + }; + + /** + * 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 initializePagedContent = function(root) { + namespace = "block_myoverview_" + root.attr('id') + "_" + Math.random(); + + var itemsPerPage = NUMCOURSES_PERPAGE; + var pagingLimit = parseInt(root.find(Selectors.courseView.region).attr('data-paging'), 10); + if (pagingLimit) { + itemsPerPage = NUMCOURSES_PERPAGE.map(function(value) { + var active = false; + if (value == pagingLimit) { + active = true; + } + + return { + value: value, + active: active + }; + }); + } + var filters = getFilterValues(root); + var config = $.extend({}, DEFAULT_PAGED_CONTENT_CONFIG); + config.eventNamespace = namespace; var pagedContentPromise = PagedContentFactory.createWithLimit( - NUMCOURSES_PERPAGE, + itemsPerPage, function(pagesData, actions) { var promises = []; @@ -471,10 +517,11 @@ function( return promises; }, - DEFAULT_PAGED_CONTENT_CONFIG + config ); pagedContentPromise.then(function(html, js) { + registerPagedEventHandlers(root, namespace); return Templates.replaceNodeContents(root.find(Selectors.courseView.region), html, js); }).catch(Notification.exception); }; @@ -556,12 +603,12 @@ function( lastPage = 0; courseOffset = 0; + initializePagedContent(root); + if (!root.attr('data-init')) { registerEventListeners(root); root.attr('data-init', true); } - - initializePagedContent(root); }; /** diff --git a/blocks/myoverview/block_myoverview.php b/blocks/myoverview/block_myoverview.php index cbd2f9db53cb5..85c208e2d5cc5 100644 --- a/blocks/myoverview/block_myoverview.php +++ b/blocks/myoverview/block_myoverview.php @@ -52,8 +52,9 @@ public function get_content() { $group = get_user_preferences('block_myoverview_user_grouping_preference'); $sort = get_user_preferences('block_myoverview_user_sort_preference'); $view = get_user_preferences('block_myoverview_user_view_preference'); + $paging = get_user_preferences('block_myoverview_user_paging_preference'); - $renderable = new \block_myoverview\output\main($group, $sort, $view); + $renderable = new \block_myoverview\output\main($group, $sort, $view, $paging); $renderer = $this->page->get_renderer('block_myoverview'); $this->content = new stdClass(); diff --git a/blocks/myoverview/classes/output/main.php b/blocks/myoverview/classes/output/main.php index 7cd6d1e0c9abd..eb28dce8bf912 100644 --- a/blocks/myoverview/classes/output/main.php +++ b/blocks/myoverview/classes/output/main.php @@ -59,6 +59,13 @@ class main implements renderable, templatable { */ private $view; + /** + * Store the paging preference + * + * @var string String matching the paging constants defined in myoverview/lib.php + */ + private $paging; + /** * main constructor. * Initialize the user preferences @@ -67,10 +74,11 @@ class main implements renderable, templatable { * @param string $sort Sort user preference * @param string $view Display user preference */ - public function __construct($grouping, $sort, $view) { + public function __construct($grouping, $sort, $view, $paging) { $this->grouping = $grouping ? $grouping : BLOCK_MYOVERVIEW_GROUPING_ALL; $this->sort = $sort ? $sort : BLOCK_MYOVERVIEW_SORTING_TITLE; $this->view = $view ? $view : BLOCK_MYOVERVIEW_VIEW_CARD; + $this->paging = $paging ? $paging : BLOCK_MYOVERVIEW_PAGING_12; } /** @@ -101,7 +109,8 @@ public function export_for_template(renderer_base $output) { 'nocoursesimg' => $nocoursesurl, 'grouping' => $this->grouping, 'sort' => $this->sort == BLOCK_MYOVERVIEW_SORTING_TITLE ? 'fullname' : 'ul.timeaccess desc', - 'view' => $this->view + 'view' => $this->view, + 'paging' => $this->paging ]; $preferences = $this->get_preferences_as_booleans(); diff --git a/blocks/myoverview/classes/privacy/provider.php b/blocks/myoverview/classes/privacy/provider.php index be95345fc4f03..729bbce37f1df 100644 --- a/blocks/myoverview/classes/privacy/provider.php +++ b/blocks/myoverview/classes/privacy/provider.php @@ -49,6 +49,8 @@ public static function get_metadata(collection $collection) : collection { $collection->add_user_preference('block_myoverview_user_view_preference', 'privacy:metadata:overviewviewpreference'); $collection->add_user_preference('block_myoverview_user_grouping_preference', 'privacy:metadata:overviewgroupingpreference'); + $collection->add_user_preference('block_myoverview_user_paging_preference', + 'privacy:metadata:overviewpagingpreference'); return $collection; } /** @@ -94,5 +96,13 @@ public static function export_user_preferences(int $userid) { ); } } + + $preference = get_user_preferences('block_myoverview_user_paging_preference', null, $userid); + if (isset($preference)) { + \core_privacy\local\request\writer::export_user_preference('block_myoverview', + 'block_myoverview_user_paging_preference', + $preference, + get_string('privacy:metadata:overviewpagingpreference', 'block_myoverview')); + } } } \ No newline at end of file diff --git a/blocks/myoverview/lang/en/block_myoverview.php b/blocks/myoverview/lang/en/block_myoverview.php index 7a7e2e2163440..3bd06316a433d 100644 --- a/blocks/myoverview/lang/en/block_myoverview.php +++ b/blocks/myoverview/lang/en/block_myoverview.php @@ -60,6 +60,7 @@ $string['privacy:metadata:overviewsortpreference'] = 'The Course overview block sort preference.'; $string['privacy:metadata:overviewviewpreference'] = 'The Course overview block view preference.'; $string['privacy:metadata:overviewgroupingpreference'] = 'The Course overview block grouping preference.'; +$string['privacy:metadata:overviewpagingpreference'] = 'The Course overview block paging preference.'; $string['removefromfavourites'] = 'Unstar this course'; $string['summary'] = 'Summary'; $string['title'] = 'Title'; diff --git a/blocks/myoverview/lib.php b/blocks/myoverview/lib.php index 3244e4cbe7003..ed7334abeecdc 100644 --- a/blocks/myoverview/lib.php +++ b/blocks/myoverview/lib.php @@ -48,6 +48,13 @@ define('BLOCK_MYOVERVIEW_VIEW_LIST', 'list'); define('BLOCK_MYOVERVIEW_VIEW_SUMMARY', 'summary'); +/** + * Constants for the user paging preferences + */ +define('BLOCK_MYOVERVIEW_PAGING_12', 12); +define('BLOCK_MYOVERVIEW_PAGING_24', 24); +define('BLOCK_MYOVERVIEW_PAGING_48', 48); + /** * Get the current user preferences that are available * @@ -95,5 +102,16 @@ function block_myoverview_user_preferences() { 'default' => 'none' ); + $preferences['block_myoverview_user_paging_preference'] = array( + 'null' => NULL_NOT_ALLOWED, + 'default' => BLOCK_MYOVERVIEW_PAGING_12, + 'type' => PARAM_INT, + 'choices' => array( + BLOCK_MYOVERVIEW_PAGING_12, + BLOCK_MYOVERVIEW_PAGING_24, + BLOCK_MYOVERVIEW_PAGING_48 + ) + ); + return $preferences; } diff --git a/blocks/myoverview/templates/courses-view.mustache b/blocks/myoverview/templates/courses-view.mustache index c5be1e801e283..d58425c059bd4 100644 --- a/blocks/myoverview/templates/courses-view.mustache +++ b/blocks/myoverview/templates/courses-view.mustache @@ -33,6 +33,7 @@ data-grouping="{{grouping}}" data-sort="{{sort}}" data-prev-display="{{view}}" + data-paging="{{paging}}" data-nocoursesimg="{{nocoursesimg}}">
diff --git a/blocks/myoverview/tests/behat/block_myoverview_pagelimit_persistence.feature b/blocks/myoverview/tests/behat/block_myoverview_pagelimit_persistence.feature new file mode 100644 index 0000000000000..4135c0a357290 --- /dev/null +++ b/blocks/myoverview/tests/behat/block_myoverview_pagelimit_persistence.feature @@ -0,0 +1,57 @@ +@block @block_myoverview @javascript +Feature: The my overview block allows users to persistence of their page limits + + Background: + Given the following "users" exist: + | username | firstname | lastname | email | idnumber | + | student1 | Student | X | student1@example.com | S1 | + And the following "courses" exist: + | fullname | shortname | category | + | Course 1 | C1 | 0 | + | Course 2 | C2 | 0 | + | Course 3 | C3 | 0 | + | Course 4 | C4 | 0 | + | Course 5 | C5 | 0 | + | Course 6 | C6 | 0 | + | Course 7 | C7 | 0 | + | Course 8 | C8 | 0 | + | Course 9 | C9 | 0 | + | Course 10 | C10 | 0 | + | Course 11 | C11 | 0 | + | Course 12 | C12 | 0 | + | Course 13 | C13 | 0 | + And the following "course enrolments" exist: + | user | course | role | + | student1 | C1 | student | + | student1 | C2 | student | + | student1 | C3 | student | + | student1 | C4 | student | + | student1 | C5 | student | + | student1 | C6 | student | + | student1 | C7 | student | + | student1 | C8 | student | + | student1 | C9 | student | + | student1 | C10 | student | + | student1 | C11 | student | + | student1 | C12 | student | + | student1 | C13 | student | + + Scenario: Toggle the page limit between page reloads + Given I log in as "student1" + When I click on "Show 12 items per page" "button" in the "Course overview" "block" + And I click on "24" "link" + Then I should see "Course 9" + And I reload the page + Then I should see "Course 9" + And I should see "24" in the "[data-action='limit-toggle']" "css_element" + And I log out + + Scenario: Toggle the page limit between grouping changes + Given I log in as "student1" + When I click on "Show 12 items per page" "button" in the "Course overview" "block" + And I click on "24" "link" + And I click on "All" "button" in the "Course overview" "block" + And I click on "In progress" "link" in the "Course overview" "block" + Then I should see "Course 9" + And I should see "24" in the "[data-action='limit-toggle']" "css_element" + And I log out diff --git a/blocks/myoverview/tests/privacy_test.php b/blocks/myoverview/tests/privacy_test.php index 2ccd331bac6f0..5b5b48803b5c8 100644 --- a/blocks/myoverview/tests/privacy_test.php +++ b/blocks/myoverview/tests/privacy_test.php @@ -50,14 +50,17 @@ public function test_export_user_preferences_no_pref() { * * @dataProvider user_preference_provider */ - public function test_export_user_preferences($type, $value) { + public function test_export_user_preferences($type, $value, $expected) { $this->resetAfterTest(); $user = $this->getDataGenerator()->create_user(); set_user_preference($type, $value, $user); provider::export_user_preferences($user->id); $writer = writer::with_context(\context_system::instance()); $blockpreferences = $writer->get_user_preferences('block_myoverview'); - $this->assertEquals(get_string($value, 'block_myoverview'), $blockpreferences->{$type}->value); + if (!$expected) { + $expected = get_string($value, 'block_myoverview'); + } + $this->assertEquals($expected, $blockpreferences->{$type}->value); } /** @@ -67,15 +70,16 @@ public function test_export_user_preferences($type, $value) { */ public function user_preference_provider() { return array( - array('block_myoverview_user_sort_preference', 'lastaccessed'), - array('block_myoverview_user_sort_preference', 'title'), - array('block_myoverview_user_grouping_preference', 'all'), - array('block_myoverview_user_grouping_preference', 'inprogress'), - array('block_myoverview_user_grouping_preference', 'future'), - array('block_myoverview_user_grouping_preference', 'past'), - array('block_myoverview_user_view_preference', 'card'), - array('block_myoverview_user_view_preference', 'list'), - array('block_myoverview_user_view_preference', 'summary') + array('block_myoverview_user_sort_preference', 'lastaccessed', ''), + array('block_myoverview_user_sort_preference', 'title', ''), + array('block_myoverview_user_grouping_preference', 'all', ''), + array('block_myoverview_user_grouping_preference', 'inprogress', ''), + array('block_myoverview_user_grouping_preference', 'future', ''), + array('block_myoverview_user_grouping_preference', 'past', ''), + array('block_myoverview_user_view_preference', 'card', ''), + array('block_myoverview_user_view_preference', 'list', ''), + array('block_myoverview_user_view_preference', 'summary', ''), + array('block_myoverview_user_paging_preference', 12, 12) ); } diff --git a/lib/amd/build/paged_content.min.js b/lib/amd/build/paged_content.min.js index 860f755172374..626b4e331caa5 100644 --- a/lib/amd/build/paged_content.min.js +++ b/lib/amd/build/paged_content.min.js @@ -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){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"]'}}); \ No newline at end of file +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");h&&(m=h),b.init(i,m,g),j.length&&c.init(j,m),l.length&&d.init(l,m),k.length&&e.init(k,m)};return{init:f,rootSelector:'[data-region="paged-content-container"]'}}); \ No newline at end of file diff --git a/lib/amd/build/paged_content_factory.min.js b/lib/amd/build/paged_content_factory.min.js index a7caeac11fea1..938b4424f9842 100644 --- a/lib/amd/build/paged_content_factory.min.js +++ b/lib/amd/build/paged_content_factory.min.js @@ -1 +1 @@ -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}}); \ No newline at end of file +define(["jquery","core/templates","core/notification","core/paged_content","core/paged_content_events","core/pubsub","core/ajax"],function(a,b,c,d,e,f,g){var h={PAGED_CONTENT:"core/paged_content"},i={ITEMS_PER_PAGE_SINGLE:25,ITEMS_PER_PAGE_ARRAY:[25,50,100,0],MAX_PAGES:3},j=function(){return{pagingbar:!1,pagingdropdown:!1,skipjs:!0,ignorecontrolwhileloading:!0,controlplacementbottom:!1}},k=function(){return{showitemsperpageselector:!1,itemsperpage:35,previous:!0,next:!0,activepagenumber:1,hidecontrolonsinglepage:!0,pages:[]}},l=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},m=function(b,c){null===c&&(c=i.ITEMS_PER_PAGE_SINGLE),a.isArray(c)&&(c=c[0]);var d=k();d.itemsperpage=c;for(var e=l(b,c),f=1;f<=e;f++){var g={number:f,page:""+f};1===f&&(g.active=!0),d.pages.push(g)}return d},n=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},o=function(b){null===b&&(b=i.ITEMS_PER_PAGE_ARRAY);var c=k();return c.itemsperpage=n(b),c.showitemsperpageselector=a.isArray(b),c},p=function(a,b){return a?m(a,b):o(b)},q=function(b,c){if(null===b&&(b=i.ITEMS_PER_PAGE_SINGLE),a.isArray(b))return{options:b};var d={options:[]},e=0,f=0,g=i.MAX_PAGES;c.hasOwnProperty("maxPages")&&(g=c.maxPages);for(var h=1;h<=g;h++){var j=0;h<=2?(j=b,f=b):(f=2*f,j=f),e+=j;var k={itemcount:j,content:e};1===h&&(k.active=!0),d.options.push(k)}return d},r=function(a,b,c){var d=j();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=q(b,c):d.pagingbar=p(a,b),d},s=function(a,b){return u(null,null,a,b)},t=function(a,b,c){return u(null,a,b,c)},u=function(e,f,g,i){i=i||{};var j=a.Deferred(),k=r(e,f,i);return b.render(h.PAGED_CONTENT,k).then(function(b,c){b=a(b);var e=b.attr("id");i.hasOwnProperty("eventNamespace")&&(e=i.eventNamespace);var f=b;d.init(f,g,e),y(e,i),j.resolve(b,c)}).fail(function(a){j.reject(a)}).fail(c.exception),j.promise()},v=function(a,b,c,d){"undefined"==typeof d&&(d={});var e=a.length;return u(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)},w=function(a,b){f.publish(a+e.ALL_ITEMS_LOADED,b)},x=function(a){var b=function(b){var c={preferences:[{type:a,value:b}]},d={methodname:"core_user_update_user_preferences",args:c};g.call([d])};return b},y=function(a,b){b.hasOwnProperty("persistentLimitKey")&&f.subscribe(a+e.SET_ITEMS_PER_PAGE_LIMIT,x(b.persistentLimitKey))};return{create:s,createWithLimit:t,createWithTotalAndLimit:u,createFromStaticList:v,createFromAjax:u,resetLastPageNumber:w}}); \ No newline at end of file diff --git a/lib/amd/src/paged_content.js b/lib/amd/src/paged_content.js index 9067ca5d10d2b..282be2cbadf3e 100644 --- a/lib/amd/src/paged_content.js +++ b/lib/amd/src/paged_content.js @@ -44,8 +44,10 @@ function( * @param {function} renderPagesContentCallback (optional) A callback function to render a * content page. See core/paged_content_pages for * more defails. + * @param {string} namespaceOverride (optional) Provide a unique namespace override. If none provided defaults + * to generate html's id */ - var init = function(root, renderPagesContentCallback) { + var init = function(root, renderPagesContentCallback, namespaceOverride) { root = $(root); var pagesContainer = root.find(Pages.rootSelector); var pagingBarContainer = root.find(PagingBar.rootSelector); @@ -53,6 +55,11 @@ function( var pagingBarLimitSelectorContainer = root.find(PagingBarLimitSelector.rootSelector); var id = root.attr('id'); + // Set the id to the custom namespace provided + if (namespaceOverride) { + id = namespaceOverride; + } + Pages.init(pagesContainer, id, renderPagesContentCallback); if (pagingBarContainer.length) { diff --git a/lib/amd/src/paged_content_factory.js b/lib/amd/src/paged_content_factory.js index c8eb0a6205ce0..82671cf2b46ff 100644 --- a/lib/amd/src/paged_content_factory.js +++ b/lib/amd/src/paged_content_factory.js @@ -27,7 +27,8 @@ define( 'core/notification', 'core/paged_content', 'core/paged_content_events', - 'core/pubsub' + 'core/pubsub', + 'core/ajax' ], function( $, @@ -35,7 +36,8 @@ function( Notification, PagedContent, PagedContentEvents, - PubSub + PubSub, + Ajax ) { var TEMPLATES = { PAGED_CONTENT: 'core/paged_content' @@ -425,10 +427,18 @@ function( Templates.render(TEMPLATES.PAGED_CONTENT, templateContext) .then(function(html, js) { html = $(html); + var id = html.attr('id'); + + // Set the id to the custom namespace provided + if (config.hasOwnProperty('eventNamespace')) { + id = config.eventNamespace; + } var container = html; - PagedContent.init(container, renderPagesContentCallback); + PagedContent.init(container, renderPagesContentCallback, id); + + registerEvents(id, config); deferred.resolve(html, js); return; @@ -494,6 +504,47 @@ function( PubSub.publish(id + PagedContentEvents.ALL_ITEMS_LOADED, lastPageNumber); }; + /** + * Generate the callback handler for the page limit persistence functionality + * + * @param {String} persistentLimitKey + * @return {callback} + */ + var generateLimitHandler = function(persistentLimitKey) { + var callback = function(limit) { + var args = { + preferences: [ + { + type: persistentLimitKey, + value: limit + } + ] + }; + + var request = { + methodname: 'core_user_update_user_preferences', + args: args + }; + + Ajax.call([request]); + }; + + return callback; + }; + + /** + * Set up any events based on config key values + * + * @param {string} namespace The namespace for this component + * @param {object} config Config options passed to the factory + */ + var registerEvents = function(namespace, config) { + if (config.hasOwnProperty('persistentLimitKey')) { + PubSub.subscribe(namespace + PagedContentEvents.SET_ITEMS_PER_PAGE_LIMIT, + generateLimitHandler(config.persistentLimitKey)); + } + }; + return { create: create, createWithLimit: createWithLimit,