From e6f03948d7f1f19bb3127bdcc998d8e2898540fa Mon Sep 17 00:00:00 2001 From: Peter Date: Tue, 16 Oct 2018 15:19:19 +0800 Subject: [PATCH 1/5] MDL-63457 block_myoverview: Hide courses from individual overview blocks * add new preferences for hidden courses * Modified course filter to use the user preference * Behat test * Regex update * Toggle hide/show * Update enrolled_course getter to pass hidden value * provider * unit tests --- blocks/myoverview/amd/build/view.min.js | 2 +- blocks/myoverview/amd/src/view.js | 85 +++++-- .../myoverview/classes/privacy/provider.php | 15 ++ .../myoverview/lang/en/block_myoverview.php | 11 +- blocks/myoverview/lib.php | 15 +- .../templates/course-action-menu.mustache | 22 ++ .../templates/courses-view.mustache | 1 + .../templates/nav-grouping-selector.mustache | 6 + .../behat/block_myoverview_dashboard.feature | 44 +++- .../behat/block_myoverview_hidden.feature | 83 +++++++ blocks/myoverview/tests/privacy_test.php | 19 ++ .../external/course_summary_exporter.php | 6 +- course/externallib.php | 3 +- course/lib.php | 12 +- course/tests/courselib_test.php | 212 ++++++++++++++++++ .../course-action-menu.mustache | 13 +- 16 files changed, 523 insertions(+), 26 deletions(-) create mode 100644 blocks/myoverview/tests/behat/block_myoverview_hidden.feature diff --git a/blocks/myoverview/amd/build/view.min.js b/blocks/myoverview/amd/build/view.min.js index 5f3fb07be37..53c65f1b58d 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/custom_interaction_events","core/notification","core/templates"],function(a,b,c,d,e,f){var g={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"]'},h={COURSES_CARDS:"block_myoverview/view-cards",COURSES_LIST:"block_myoverview/view-list",COURSES_SUMMARY:"block_myoverview/view-summary",NOCOURSES:"block_myoverview/no-courses"},i=[12,24,48],j=[],k=function(a){var b={};return b.display=a.attr("data-display"),b.grouping=a.attr("data-grouping"),b.sort=a.attr("data-sort"),b},l={ignoreControlWhileLoading:!0,controlPlacementBottom:!0},m=function(a,c,d){return b.getEnrolledCoursesByTimeline({offset:d*c,limit:c,classification:a.grouping,sort:a.sort})},n=function(a,b){return a.find(g.FAVOURITE_ICON+'[data-course-id="'+b+'"]')},o=function(a,b){return a.find('[data-region="paged-content-page"][data-page="'+b+'"]')},p=function(a){return a.attr("data-course-id")},q=function(a,b){var c=n(a,b),d=c.find(g.ICON_IS_FAVOURITE);d.addClass("hidden"),d.attr("aria-hidden",!0);var e=c.find(g.ICON_NOT_FAVOURITE);e.removeClass("hidden"),e.attr("aria-hidden",!1)},r=function(a,b){var c=n(a,b),d=c.find(g.ICON_IS_FAVOURITE);d.removeClass("hidden"),d.attr("aria-hidden",!1);var e=c.find(g.ICON_NOT_FAVOURITE);e.addClass("hidden"),e.attr("aria-hidden",!0)},s=function(a,b){return a.find('[data-action="add-favourite"][data-course-id="'+b+'"]')},t=function(a,b){return a.find('[data-action="remove-favourite"][data-course-id="'+b+'"]')},u=function(a,b){var c=t(a,b),d=s(a,b);w(b,!0).then(function(f){f?(c.removeClass("hidden"),d.addClass("hidden"),r(a,b)):e.alert("Starring course failed","Could not change favourite state")})["catch"](e.exception)},v=function(a,b){var c=t(a,b),d=s(a,b);w(b,!1).then(function(f){f?(c.addClass("hidden"),d.removeClass("hidden"),q(a,b)):e.alert("Starring course failed","Could not change favourite state")})["catch"](e.exception)},w=function(a,c){return b.setFavouriteCourses({courses:[{id:a,favourite:c}]}).then(function(b){return 0==b.warnings.length&&(j.forEach(function(b){b.courses.forEach(function(d,e){d.id==a&&(b.courses[e].isfavourite=c)})}),!0)})["catch"](e.exception)},x=function(a,b){var c=k(a),d="";if(d="cards"==c.display?h.COURSES_CARDS:"list"==c.display?h.COURSES_LIST:h.COURSES_SUMMARY,b.courses.length)return f.render(d,{courses:b.courses});var e=a.attr("data-nocoursesimg");return f.render(h.NOCOURSES,{nocoursesimg:e})},y=function(b,d){b=a(b),b.attr("data-init")||(z(b),b.attr("data-init",!0));var g=k(b),h=c.createWithLimit(i,function(a,c){var d=[];return a.forEach(function(a){var f=a.pageNumber,h=a.pageNumber-1,i=m(g,a.limit,h).then(function(d){return d.courses.length0?j.forEach(function(b,c){var d=o(a,c);x(a,b).then(function(a,b){return f.replaceNodeContents(d,a,b)})["catch"](e.exception)}):y(a,b)};return{init:y,reset:A}}); \ No newline at end of file +define(["jquery","block_myoverview/repository","core/paged_content_factory","core/custom_interaction_events","core/notification","core/ajax","core/templates"],function(a,b,c,d,e,f,g){var h={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"]'},i={COURSES_CARDS:"block_myoverview/view-cards",COURSES_LIST:"block_myoverview/view-list",COURSES_SUMMARY:"block_myoverview/view-summary",NOCOURSES:"block_myoverview/no-courses"},j=[12,24,48],k=[],l=function(a){var b={};return b.display=a.attr("data-display"),b.grouping=a.attr("data-grouping"),b.sort=a.attr("data-sort"),b},m={ignoreControlWhileLoading:!0,controlPlacementBottom:!0},n=function(a,c,d){return b.getEnrolledCoursesByTimeline({offset:d*c,limit:c,classification:a.grouping,sort:a.sort})},o=function(a,b){return a.find(h.FAVOURITE_ICON+'[data-course-id="'+b+'"]')},p=function(a,b){return a.find('[data-region="paged-content-page"][data-page="'+b+'"]')},q=function(a){return a.attr("data-course-id")},r=function(a,b){var c=o(a,b),d=c.find(h.ICON_IS_FAVOURITE);d.addClass("hidden"),d.attr("aria-hidden",!0);var e=c.find(h.ICON_NOT_FAVOURITE);e.removeClass("hidden"),e.attr("aria-hidden",!1)},s=function(a,b){var c=o(a,b),d=c.find(h.ICON_IS_FAVOURITE);d.removeClass("hidden"),d.attr("aria-hidden",!1);var e=c.find(h.ICON_NOT_FAVOURITE);e.addClass("hidden"),e.attr("aria-hidden",!0)},t=function(a,b){return a.find('[data-action="add-favourite"][data-course-id="'+b+'"]')},u=function(a,b){return a.find('[data-action="remove-favourite"][data-course-id="'+b+'"]')},v=function(a,b){var c=u(a,b),d=t(a,b);x(b,!0).then(function(f){f?(c.removeClass("hidden"),d.addClass("hidden"),s(a,b)):e.alert("Starring course failed","Could not change favourite state")})["catch"](e.exception)},w=function(a,b){var c=u(a,b),d=t(a,b);x(b,!1).then(function(f){f?(c.addClass("hidden"),d.removeClass("hidden"),r(a,b)):e.alert("Starring course failed","Could not change favourite state")})["catch"](e.exception)},x=function(a,c){return b.setFavouriteCourses({courses:[{id:a,favourite:c}]}).then(function(b){return 0==b.warnings.length&&(k.forEach(function(b){b.courses.forEach(function(d,e){d.id==a&&(b.courses[e].isfavourite=c)})}),!0)})["catch"](e.exception)},y=function(a,b){var c=l(a),d="";if(d="cards"==c.display?i.COURSES_CARDS:"list"==c.display?i.COURSES_LIST:i.COURSES_SUMMARY,b.courses.length)return g.render(d,{courses:b.courses});var e=a.attr("data-nocoursesimg");return g.render(i.NOCOURSES,{nocoursesimg:e})},z=function(a,b){var d=l(a),f=c.createWithLimit(j,function(b,c){var f=[];return b.forEach(function(b){var g=b.pageNumber,h=b.pageNumber-1,i=n(d,b.limit,h).then(function(d){return d.courses.length0?k.forEach(function(b,c){var d=p(a,c);y(a,b).then(function(a,b){return g.replaceNodeContents(d,a,b)})["catch"](e.exception)}):B(a,b)};return{init:B,reset:C}}); \ No newline at end of file diff --git a/blocks/myoverview/amd/src/view.js b/blocks/myoverview/amd/src/view.js index f4304fadb36..e7997759cc3 100644 --- a/blocks/myoverview/amd/src/view.js +++ b/blocks/myoverview/amd/src/view.js @@ -28,6 +28,7 @@ define( 'core/paged_content_factory', 'core/custom_interaction_events', 'core/notification', + 'core/ajax', 'core/templates', ], function( @@ -36,10 +37,14 @@ function( PagedContentFactory, CustomEvents, Notification, + Ajax, Templates ) { var SELECTORS = { + 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"]', @@ -127,7 +132,7 @@ function( * @param {Object} root The favourite icon container element. * @return {Number} Course id. */ - var getFavouriteCourseId = function(root) { + var getCourseId = function(root) { return root.attr('data-course-id'); }; @@ -294,20 +299,12 @@ function( }; /** - * Intialise the courses list and cards views on page load. + * Intialise the paged 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); - - if (!root.attr('data-init')) { - registerEventListeners(root); - root.attr('data-init', true); - } - + var initializePagedContent = function(root, content) { var filters = getFilterValues(root); var pagedContentPromise = PagedContentFactory.createWithLimit( @@ -330,7 +327,7 @@ function( loadedPages[currentPage] = coursesData; return renderCourses(root, coursesData); }) - .catch(Notification.exception); + .catch(Notification.exception); promises.push(pagePromise); }); @@ -350,21 +347,21 @@ function( * * @param {Object} root The myoverview block container element. */ - var registerEventListeners = function(root) { + var registerEventListeners = function(root, content) { CustomEvents.define(root, [ CustomEvents.events.activate ]); root.on(CustomEvents.events.activate, SELECTORS.ACTION_ADD_FAVOURITE, function(e, data) { var favourite = $(e.target).closest(SELECTORS.ACTION_ADD_FAVOURITE); - var courseId = getFavouriteCourseId(favourite); + var courseId = getCourseId(favourite); addToFavourites(root, courseId); data.originalEvent.preventDefault(); }); root.on(CustomEvents.events.activate, SELECTORS.ACTION_REMOVE_FAVOURITE, function(e, data) { var favourite = $(e.target).closest(SELECTORS.ACTION_REMOVE_FAVOURITE); - var courseId = getFavouriteCourseId(favourite); + var courseId = getCourseId(favourite); removeFromFavourites(root, courseId); data.originalEvent.preventDefault(); }); @@ -372,9 +369,67 @@ function( root.on(CustomEvents.events.activate, SELECTORS.FAVOURITE_ICON, function(e, data) { data.originalEvent.preventDefault(); }); + + root.on(CustomEvents.events.activate, SELECTORS.ACTION_HIDE_COURSE, function(e, data) { + var target = $(e.target).closest(SELECTORS.ACTION_HIDE_COURSE); + var id = getCourseId(target); + + var request = { + preferences: [ + { + type: 'block_myoverview_hidden_course_' + id, + value: true + } + ] + }; + Repository.updateUserPreferences(request); + + // Reload the paged content based on the hidden course + initializePagedContent(root, content); + data.originalEvent.preventDefault(); + }); + + root.on(CustomEvents.events.activate, SELECTORS.ACTION_SHOW_COURSE, function(e, data) { + var target = $(e.target).closest(SELECTORS.ACTION_SHOW_COURSE); + var id = getCourseId(target); + + var request = { + preferences: [ + { + type: 'block_myoverview_hidden_course_' + id, + value: null + } + ] + }; + + Repository.updateUserPreferences(request); + + // Reload the paged content based on the hidden course + initializePagedContent(root, content); + data.originalEvent.preventDefault(); + }); }; /** + * 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); + + if (!root.attr('data-init')) { + registerEventListeners(root, content); + root.attr('data-init', true); + } + + initializePagedContent(root, content); + }; + + /** + * Reset the courses views to their original * state on first page load. * diff --git a/blocks/myoverview/classes/privacy/provider.php b/blocks/myoverview/classes/privacy/provider.php index 34463a101ab..2d10e2be3a1 100644 --- a/blocks/myoverview/classes/privacy/provider.php +++ b/blocks/myoverview/classes/privacy/provider.php @@ -78,5 +78,20 @@ class provider implements \core_privacy\local\metadata\provider, user_preference get_string($preference, 'block_myoverview'), get_string('privacy:metadata:overviewgroupingpreference', 'block_myoverview')); } + + $preferences = get_user_preferences(null, null, $userid); + foreach ($preferences as $name => $value) { + if ((substr($name, 0, 30) == 'block_myoverview_hidden_course')) { + writer::export_user_preference( + 'block_myoverview', + $name, + $value, + get_string('privacy:request:preference:set', 'block_myoverview', (object) [ + 'name' => $name, + 'value' => $value, + ]) + ); + } + } } } \ 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 6de059d056d..1b723ff6f6f 100644 --- a/blocks/myoverview/lang/en/block_myoverview.php +++ b/blocks/myoverview/lang/en/block_myoverview.php @@ -48,6 +48,7 @@ $string['aria:summary'] = 'Switch to summary view'; $string['aria:sortingdropdown'] = 'Sorting dropdown'; $string['card'] = 'Card'; $string['cards'] = 'Cards'; +$string['courseprogress'] = 'Course progress:'; $string['complete'] = 'Complete'; $string['favourite'] = 'Starred course'; $string['favourites'] = 'Starred'; @@ -67,6 +68,14 @@ $string['privacy:metadata:overviewgroupingpreference'] = 'The myoverview block g $string['removefromfavourites'] = 'Unstar this course'; $string['summary'] = 'Summary'; $string['title'] = 'Title'; +$string['aria:hidecourse'] = 'Hide {$a} from view'; +$string['aria:showcourse'] = 'Show {$a} in view'; +$string['aria:hiddencourses'] = 'Show hidden courses'; +$string['hidden'] = 'Hidden courses'; +$string['hidecourse'] = 'Hide from view'; +$string['hiddencourses'] = 'Hidden'; +$string['show'] = 'Show this course'; +$string['privacy:request:preference:set'] = 'The value of the setting \'{$a->name}\' was \'{$a->value}\''; // Deprecated since Moodle 3.6. $string['defaulttab'] = 'Default tab'; @@ -84,4 +93,4 @@ $string['sortbydates'] = 'Sort by dates'; $string['timeline'] = 'Timeline'; $string['viewcoursename'] = 'View course {$a}'; $string['privacy:metadata:overviewlasttab'] = 'This stores the last tab selected by the user on the overview block.'; - +$string['viewcourse'] = 'View course'; diff --git a/blocks/myoverview/lib.php b/blocks/myoverview/lib.php index bc0530e19ac..3244e4cbe70 100644 --- a/blocks/myoverview/lib.php +++ b/blocks/myoverview/lib.php @@ -32,6 +32,7 @@ define('BLOCK_MYOVERVIEW_GROUPING_INPROGRESS', 'inprogress'); define('BLOCK_MYOVERVIEW_GROUPING_FUTURE', 'future'); define('BLOCK_MYOVERVIEW_GROUPING_PAST', 'past'); define('BLOCK_MYOVERVIEW_GROUPING_FAVOURITES', 'favourites'); +define('BLOCK_MYOVERVIEW_GROUPING_HIDDEN', 'hidden'); /** * Constants for the user preferences sorting options @@ -62,7 +63,8 @@ function block_myoverview_user_preferences() { BLOCK_MYOVERVIEW_GROUPING_INPROGRESS, BLOCK_MYOVERVIEW_GROUPING_FUTURE, BLOCK_MYOVERVIEW_GROUPING_PAST, - BLOCK_MYOVERVIEW_GROUPING_FAVOURITES + BLOCK_MYOVERVIEW_GROUPING_FAVOURITES, + BLOCK_MYOVERVIEW_GROUPING_HIDDEN ) ); $preferences['block_myoverview_user_sort_preference'] = array( @@ -84,5 +86,14 @@ function block_myoverview_user_preferences() { BLOCK_MYOVERVIEW_VIEW_SUMMARY ) ); + + $preferences['/^block_myoverview_hidden_course_(\d)+$/'] = array( + 'isregex' => true, + 'choices' => array(0, 1), + 'type' => PARAM_INT, + 'null' => NULL_NOT_ALLOWED, + 'default' => 'none' + ); + return $preferences; -} \ No newline at end of file +} diff --git a/blocks/myoverview/templates/course-action-menu.mustache b/blocks/myoverview/templates/course-action-menu.mustache index 027bdab3ded..d137472750a 100644 --- a/blocks/myoverview/templates/course-action-menu.mustache +++ b/blocks/myoverview/templates/course-action-menu.mustache @@ -57,5 +57,27 @@ {{#str}} aria:removefromfavourites, block_myoverview {{/str}} {{{fullname}}} + + {{#pix}} i/show, core, {{#str}} hidden, block_myoverview {{/str}} {{/pix}} + {{#str}} show, block_myoverview {{/str}} +
+ {{#str}} aria:showcourse, block_myoverview, {{fullname}} {{/str}} +
+
+ + {{#pix}} i/hide, core, {{#str}} hidden, block_myoverview {{/str}} {{/pix}} + {{#str}} hidecourse, block_myoverview {{/str}} +
+ {{#str}} aria:hidecourse, block_myoverview, {{fullname}} {{/str}} +
+
\ No newline at end of file diff --git a/blocks/myoverview/templates/courses-view.mustache b/blocks/myoverview/templates/courses-view.mustache index d8f2aa4ad79..c5be1e801e2 100644 --- a/blocks/myoverview/templates/courses-view.mustache +++ b/blocks/myoverview/templates/courses-view.mustache @@ -32,6 +32,7 @@ data-display="{{view}}" data-grouping="{{grouping}}" data-sort="{{sort}}" + data-prev-display="{{view}}" data-nocoursesimg="{{nocoursesimg}}">
diff --git a/blocks/myoverview/templates/nav-grouping-selector.mustache b/blocks/myoverview/templates/nav-grouping-selector.mustache index 9e341a68e01..687e1a376d1 100644 --- a/blocks/myoverview/templates/nav-grouping-selector.mustache +++ b/blocks/myoverview/templates/nav-grouping-selector.mustache @@ -36,6 +36,7 @@ {{#future}}{{#str}} future, block_myoverview {{/str}}{{/future}} {{#past}}{{#str}} past, block_myoverview {{/str}}{{/past}} {{#favourites}}{{#str}} favourites, block_myoverview {{/str}}{{/favourites}} + {{#hidden}}{{#str}} hiddencourses, block_myoverview {{/str}}{{/hidden}}
diff --git a/blocks/myoverview/tests/behat/block_myoverview_dashboard.feature b/blocks/myoverview/tests/behat/block_myoverview_dashboard.feature index f63c118ab95..e67576a5499 100644 --- a/blocks/myoverview/tests/behat/block_myoverview_dashboard.feature +++ b/blocks/myoverview/tests/behat/block_myoverview_dashboard.feature @@ -157,4 +157,46 @@ Feature: The my overview block allows users to easily access their courses And I click on "Last accessed" "link" in the "Course overview" "block" And I reload the page Then I should see "Last accessed" in the "Course overview" "block" - And "[data-sort='ul.timeaccess desc']" "css_element" in the "Course overview" "block" should be visible \ No newline at end of file + And "[data-sort='ul.timeaccess desc']" "css_element" in the "Course overview" "block" should be visible + + Scenario: View inprogress courses with hide persistent functionality + 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" + And I click on ".coursemenubtn" "css_element" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + And I click on "Hide from view" "link" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + And I reload the page + 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 2" 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 past courses with hide persistent functionality + Given I log in as "student1" + And I click on "All" "button" in the "Course overview" "block" + When I click on "Past" "link" in the "Course overview" "block" + And I click on ".coursemenubtn" "css_element" in the "//div[@class='card course-card' and contains(.,'Course 1')]" "xpath_element" + And I click on "Hide from view" "link" in the "//div[@class='card course-card' and contains(.,'Course 1')]" "xpath_element" + And I reload the page + Then 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 should not see "Course 5" in the "Course overview" "block" + And I log out + + Scenario: View future courses with hide persistent functionality + 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" + And I click on ".coursemenubtn" "css_element" in the "//div[@class='card course-card' and contains(.,'Course 5')]" "xpath_element" + And I click on "Hide from view" "link" in the "//div[@class='card course-card' and contains(.,'Course 5')]" "xpath_element" + And I reload the page + Then I should not 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 diff --git a/blocks/myoverview/tests/behat/block_myoverview_hidden.feature b/blocks/myoverview/tests/behat/block_myoverview_hidden.feature new file mode 100644 index 00000000000..9a604379196 --- /dev/null +++ b/blocks/myoverview/tests/behat/block_myoverview_hidden.feature @@ -0,0 +1,83 @@ +@block @block_myoverview @javascript +Feature: The my overview block allows users to favourite 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 + + 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 | + 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: Test hide toggle functionality + Given I log in as "student1" + When I click on ".coursemenubtn" "css_element" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + And I click on "Hide from view" "link" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + And I reload the page + Then I should not see "Course 2" in the "Course overview" "block" + And I log out + + Scenario: Test hide toggle functionality w/ favorites + Given I log in as "student1" + And I click on ".coursemenubtn" "css_element" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + And I click on "Star this course" "link" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + And I click on ".coursemenubtn" "css_element" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + And I click on "Hide from view" "link" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + When I reload the page + Then I should not see "Course 2" in the "Course overview" "block" + And I click on "All" "button" in the "Course overview" "block" + And I click on "Starred" "link" in the "Course overview" "block" + Then I should not see "Course 2" in the "Course overview" "block" + And I click on "Starred" "button" in the "Course overview" "block" + And I click on "Hidden" "link" in the "Course overview" "block" + Then I should see "Course 2" in the "Course overview" "block" + And I log out + + Scenario: Test show toggle functionality + Given I log in as "student1" + And I click on ".coursemenubtn" "css_element" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + And I click on "Hide from view" "link" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + When I click on "All" "button" in the "Course overview" "block" + And I click on "Hidden" "link" in the "Course overview" "block" + When I click on ".coursemenubtn" "css_element" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + And I click on "Show this course" "link" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + And I reload the page + And I click on "Hidden" "button" in the "Course overview" "block" + When I click on "All" "link" in the "Course overview" "block" + Then I should see "Course 2" in the "Course overview" "block" + And I log out + + Scenario: Test show toggle functionality w/ favorites + Given I log in as "student1" + And I click on ".coursemenubtn" "css_element" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + And I click on "Star this course" "link" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + And I click on ".coursemenubtn" "css_element" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + And I click on "Hide from view" "link" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + And I click on "All" "button" in the "Course overview" "block" + And I click on "Hidden" "link" in the "Course overview" "block" + And I should see "Course 2" in the "Course overview" "block" + And I click on ".coursemenubtn" "css_element" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + And I click on "Show this course" "link" in the "//div[@class='card course-card' and contains(.,'Course 2')]" "xpath_element" + When I reload the page + Then I should not see "Course 2" in the "Course overview" "block" + And I click on "Hidden" "button" in the "Course overview" "block" + And I click on "All" "link" in the "Course overview" "block" + Then I should see "Course 2" in the "Course overview" "block" + And I click on "All" "button" in the "Course overview" "block" + And I click on "Starred" "link" in the "Course overview" "block" + Then I should see "Course 2" in the "Course overview" "block" + And I log out \ No newline at end of file diff --git a/blocks/myoverview/tests/privacy_test.php b/blocks/myoverview/tests/privacy_test.php index 5e2d031634a..2ccd331bac6 100644 --- a/blocks/myoverview/tests/privacy_test.php +++ b/blocks/myoverview/tests/privacy_test.php @@ -78,4 +78,23 @@ class block_myoverview_privacy_testcase extends \core_privacy\tests\provider_tes array('block_myoverview_user_view_preference', 'summary') ); } + + public function test_export_user_preferences_with_hidden_courses() { + $this->resetAfterTest(); + $user = $this->getDataGenerator()->create_user(); + $name = "block_myoverview_hidden_course_1"; + + set_user_preference($name, 1, $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("privacy:request:preference:set", 'block_myoverview', (object) [ + 'name' => $name, + 'value' => 1, + ]), + $blockpreferences->{$name}->description + ); + } } \ No newline at end of file diff --git a/course/classes/external/course_summary_exporter.php b/course/classes/external/course_summary_exporter.php index 9714b2dd72e..7b13d65a47c 100644 --- a/course/classes/external/course_summary_exporter.php +++ b/course/classes/external/course_summary_exporter.php @@ -71,7 +71,8 @@ class course_summary_exporter extends \core\external\exporter { 'courseimage' => $courseimage, 'progress' => $progress, 'hasprogress' => $hasprogress, - 'isfavourite' => $this->related['isfavourite'] + 'isfavourite' => $this->related['isfavourite'], + 'hidden' => boolval(get_user_preferences('block_myoverview_hidden_course_' . $this->data->id, 0)) ); } @@ -137,6 +138,9 @@ class course_summary_exporter extends \core\external\exporter { ), 'isfavourite' => array( 'type' => PARAM_BOOL + ), + 'hidden' => array( + 'type' => PARAM_BOOL ) ); } diff --git a/course/externallib.php b/course/externallib.php index 0873f466e3c..f315f8b1b14 100644 --- a/course/externallib.php +++ b/course/externallib.php @@ -3665,6 +3665,8 @@ class core_course_external extends external_api { break; case COURSE_FAVOURITES: break; + case COURSE_TIMELINE_HIDDEN: + break; default: throw new invalid_parameter_exception('Invalid classification'); } @@ -3692,7 +3694,6 @@ class core_course_external extends external_api { $favouritecourseids, $limit ); - } else { list($filteredcourses, $processedcount) = course_filter_courses_by_timeline_classification( $courses, diff --git a/course/lib.php b/course/lib.php index f06364980c4..e24ca5fb352 100644 --- a/course/lib.php +++ b/course/lib.php @@ -60,6 +60,7 @@ define('COURSE_TIMELINE_PAST', 'past'); define('COURSE_TIMELINE_INPROGRESS', 'inprogress'); define('COURSE_TIMELINE_FUTURE', 'future'); define('COURSE_FAVOURITES', 'favourites'); +define('COURSE_TIMELINE_HIDDEN', 'hidden'); define('COURSE_DB_QUERY_LIMIT', 1000); function make_log_url($module, $url) { @@ -4242,7 +4243,8 @@ function course_filter_courses_by_timeline_classification( ) : array { if (!in_array($classification, - [COURSE_TIMELINE_ALL, COURSE_TIMELINE_PAST, COURSE_TIMELINE_INPROGRESS, COURSE_TIMELINE_FUTURE])) { + [COURSE_TIMELINE_ALL, COURSE_TIMELINE_PAST, COURSE_TIMELINE_INPROGRESS, + COURSE_TIMELINE_FUTURE, COURSE_TIMELINE_HIDDEN])) { $message = 'Classification must be one of COURSE_TIMELINE_ALL, COURSE_TIMELINE_PAST, ' . 'COURSE_TIMELINE_INPROGRESS or COURSE_TIMELINE_FUTURE'; throw new moodle_exception($message); @@ -4254,8 +4256,11 @@ function course_filter_courses_by_timeline_classification( foreach ($courses as $course) { $numberofcoursesprocessed++; + $pref = get_user_preferences('block_myoverview_hidden_course_' . $course->id, 0); - if ($classification == COURSE_TIMELINE_ALL || $classification == course_classify_for_timeline($course)) { + // Added as of MDL-63457 toggle viewability for each user. + if (($classification == COURSE_TIMELINE_HIDDEN && $pref) || + (($classification == COURSE_TIMELINE_ALL || $classification == course_classify_for_timeline($course)) && !$pref)) { $filteredcourses[] = $course; $filtermatches++; } @@ -4299,8 +4304,9 @@ function course_filter_courses_by_favourites( foreach ($courses as $course) { $numberofcoursesprocessed++; + $pref = get_user_preferences('block_myoverview_hidden_course_' . $course->id, 0); - if (in_array($course->id, $favouritecourseids)) { + if (in_array($course->id, $favouritecourseids) && !$pref) { $filteredcourses[] = $course; $filtermatches++; } diff --git a/course/tests/courselib_test.php b/course/tests/courselib_test.php index 1bdf3b52d25..37ca6629042 100644 --- a/course/tests/courselib_test.php +++ b/course/tests/courselib_test.php @@ -4718,6 +4718,218 @@ class core_course_courselib_testcase extends advanced_testcase { $this->assertEquals($expectedprocessedcount, $processedcount); } + /** + * Test cases for the course_filter_courses_by_timeline_classification w/ hidden courses tests. + */ + public function get_course_filter_courses_by_timeline_classification_hidden_courses_test_cases() { + $now = time(); + $day = 86400; + + $coursedata = [ + [ + 'shortname' => 'apast', + 'startdate' => $now - ($day * 2), + 'enddate' => $now - $day + ], + [ + 'shortname' => 'bpast', + 'startdate' => $now - ($day * 2), + 'enddate' => $now - $day + ], + [ + 'shortname' => 'cpast', + 'startdate' => $now - ($day * 2), + 'enddate' => $now - $day + ], + [ + 'shortname' => 'dpast', + 'startdate' => $now - ($day * 2), + 'enddate' => $now - $day + ], + [ + 'shortname' => 'epast', + 'startdate' => $now - ($day * 2), + 'enddate' => $now - $day + ], + [ + 'shortname' => 'ainprogress', + 'startdate' => $now - $day, + 'enddate' => $now + $day + ], + [ + 'shortname' => 'binprogress', + 'startdate' => $now - $day, + 'enddate' => $now + $day + ], + [ + 'shortname' => 'cinprogress', + 'startdate' => $now - $day, + 'enddate' => $now + $day + ], + [ + 'shortname' => 'dinprogress', + 'startdate' => $now - $day, + 'enddate' => $now + $day + ], + [ + 'shortname' => 'einprogress', + 'startdate' => $now - $day, + 'enddate' => $now + $day + ], + [ + 'shortname' => 'afuture', + 'startdate' => $now + $day + ], + [ + 'shortname' => 'bfuture', + 'startdate' => $now + $day + ], + [ + 'shortname' => 'cfuture', + 'startdate' => $now + $day + ], + [ + 'shortname' => 'dfuture', + 'startdate' => $now + $day + ], + [ + 'shortname' => 'efuture', + 'startdate' => $now + $day + ] + ]; + + // Raw enrolled courses result set should be returned in this order: + // afuture, ainprogress, apast, bfuture, binprogress, bpast, cfuture, cinprogress, cpast, + // dfuture, dinprogress, dpast, efuture, einprogress, epast + // + // By classification the offset values for each record should be: + // COURSE_TIMELINE_FUTURE + // 0 (afuture), 3 (bfuture), 6 (cfuture), 9 (dfuture), 12 (efuture) + // COURSE_TIMELINE_INPROGRESS + // 1 (ainprogress), 4 (binprogress), 7 (cinprogress), 10 (dinprogress), 13 (einprogress) + // COURSE_TIMELINE_PAST + // 2 (apast), 5 (bpast), 8 (cpast), 11 (dpast), 14 (epast). + return [ + 'empty set' => [ + 'coursedata' => [], + 'classification' => COURSE_TIMELINE_FUTURE, + 'limit' => 2, + 'offset' => 0, + 'expectedcourses' => [], + 'expectedprocessedcount' => 0, + 'hiddencourse' => '' + ], + // COURSE_TIMELINE_FUTURE. + 'future not limit no offset' => [ + 'coursedata' => $coursedata, + 'classification' => COURSE_TIMELINE_FUTURE, + 'limit' => 0, + 'offset' => 0, + 'expectedcourses' => ['afuture', 'cfuture', 'dfuture', 'efuture'], + 'expectedprocessedcount' => 15, + 'hiddencourse' => 'bfuture' + ], + 'future no offset' => [ + 'coursedata' => $coursedata, + 'classification' => COURSE_TIMELINE_FUTURE, + 'limit' => 2, + 'offset' => 0, + 'expectedcourses' => ['afuture', 'cfuture'], + 'expectedprocessedcount' => 7, + 'hiddencourse' => 'bfuture' + ], + 'future offset' => [ + 'coursedata' => $coursedata, + 'classification' => COURSE_TIMELINE_FUTURE, + 'limit' => 2, + 'offset' => 2, + 'expectedcourses' => ['bfuture', 'dfuture'], + 'expectedprocessedcount' => 8, + 'hiddencourse' => 'cfuture' + ], + 'future exact limit' => [ + 'coursedata' => $coursedata, + 'classification' => COURSE_TIMELINE_FUTURE, + 'limit' => 5, + 'offset' => 0, + 'expectedcourses' => ['afuture', 'cfuture', 'dfuture', 'efuture'], + 'expectedprocessedcount' => 15, + 'hiddencourse' => 'bfuture' + ], + 'future limit less results' => [ + 'coursedata' => $coursedata, + 'classification' => COURSE_TIMELINE_FUTURE, + 'limit' => 10, + 'offset' => 0, + 'expectedcourses' => ['afuture', 'cfuture', 'dfuture', 'efuture'], + 'expectedprocessedcount' => 15, + 'hiddencourse' => 'bfuture' + ], + 'future limit less results with offset' => [ + 'coursedata' => $coursedata, + 'classification' => COURSE_TIMELINE_FUTURE, + 'limit' => 10, + 'offset' => 5, + 'expectedcourses' => ['cfuture', 'efuture'], + 'expectedprocessedcount' => 10, + 'hiddencourse' => 'dfuture' + ], + ]; + } + + /** + * Test the course_filter_courses_by_timeline_classification function hidden courses. + * + * @dataProvider get_course_filter_courses_by_timeline_classification_hidden_courses_test_cases() + * @param array $coursedata Course test data to create. + * @param string $classification Timeline classification. + * @param int $limit Maximum number of results to return. + * @param int $offset Results to skip at the start of the result set. + * @param string[] $expectedcourses Expected courses in results. + * @param int $expectedprocessedcount Expected number of course records to be processed. + * @param int $hiddencourse The course to hide as part of this process + */ + public function test_course_filter_courses_by_timeline_classification_with_hidden_courses( + $coursedata, + $classification, + $limit, + $offset, + $expectedcourses, + $expectedprocessedcount, + $hiddencourse + ) { + $this->resetAfterTest(); + $generator = $this->getDataGenerator(); + $student = $generator->create_user(); + $this->setUser($student); + + $courses = array_map(function($coursedata) use ($generator, $hiddencourse) { + $course = $generator->create_course($coursedata); + if ($course->shortname == $hiddencourse) { + set_user_preference('block_myoverview_hidden_course_' . $course->id, true); + } + return $course; + }, $coursedata); + + foreach ($courses as $course) { + $generator->enrol_user($student->id, $course->id, 'student'); + } + + $coursesgenerator = course_get_enrolled_courses_for_logged_in_user(0, $offset, 'shortname ASC', 'shortname'); + list($result, $processedcount) = course_filter_courses_by_timeline_classification( + $coursesgenerator, + $classification, + $limit + ); + + $actual = array_map(function($course) { + return $course->shortname; + }, $result); + + $this->assertEquals($expectedcourses, $actual); + $this->assertEquals($expectedprocessedcount, $processedcount); + } + /** * Testing core_course_core_calendar_get_valid_event_timestart_range when the course has no end date. diff --git a/theme/bootstrapbase/templates/block_myoverview/course-action-menu.mustache b/theme/bootstrapbase/templates/block_myoverview/course-action-menu.mustache index ddb9e4b1a65..6d0980a147f 100644 --- a/theme/bootstrapbase/templates/block_myoverview/course-action-menu.mustache +++ b/theme/bootstrapbase/templates/block_myoverview/course-action-menu.mustache @@ -21,7 +21,8 @@ Example context (json): { - "isfavourite": true + "isfavourite": true, + "hidden": true } }}
\ No newline at end of file From c896546ce71bc83089b90c215328d961c029fd79 Mon Sep 17 00:00:00 2001 From: Peter Date: Wed, 24 Oct 2018 10:23:47 +0800 Subject: [PATCH 2/5] MDL-63457 block_myoverview: Functionality and test updates * Add identifiers for each card in the view * Update js to hide instead of reload block * Behat test updates --- blocks/myoverview/amd/build/view.min.js | 2 +- blocks/myoverview/amd/src/view.js | 23 +++++++++---- .../myoverview/templates/view-cards.mustache | 4 ++- .../myoverview/templates/view-list.mustache | 4 ++- .../templates/view-summary.mustache | 4 ++- .../behat/block_myoverview_dashboard.feature | 12 +++---- .../behat/block_myoverview_favourite.feature | 10 +++--- .../behat/block_myoverview_hidden.feature | 32 +++++++++---------- 8 files changed, 53 insertions(+), 38 deletions(-) diff --git a/blocks/myoverview/amd/build/view.min.js b/blocks/myoverview/amd/build/view.min.js index 53c65f1b58d..4fec7f03f7d 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/custom_interaction_events","core/notification","core/ajax","core/templates"],function(a,b,c,d,e,f,g){var h={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"]'},i={COURSES_CARDS:"block_myoverview/view-cards",COURSES_LIST:"block_myoverview/view-list",COURSES_SUMMARY:"block_myoverview/view-summary",NOCOURSES:"block_myoverview/no-courses"},j=[12,24,48],k=[],l=function(a){var b={};return b.display=a.attr("data-display"),b.grouping=a.attr("data-grouping"),b.sort=a.attr("data-sort"),b},m={ignoreControlWhileLoading:!0,controlPlacementBottom:!0},n=function(a,c,d){return b.getEnrolledCoursesByTimeline({offset:d*c,limit:c,classification:a.grouping,sort:a.sort})},o=function(a,b){return a.find(h.FAVOURITE_ICON+'[data-course-id="'+b+'"]')},p=function(a,b){return a.find('[data-region="paged-content-page"][data-page="'+b+'"]')},q=function(a){return a.attr("data-course-id")},r=function(a,b){var c=o(a,b),d=c.find(h.ICON_IS_FAVOURITE);d.addClass("hidden"),d.attr("aria-hidden",!0);var e=c.find(h.ICON_NOT_FAVOURITE);e.removeClass("hidden"),e.attr("aria-hidden",!1)},s=function(a,b){var c=o(a,b),d=c.find(h.ICON_IS_FAVOURITE);d.removeClass("hidden"),d.attr("aria-hidden",!1);var e=c.find(h.ICON_NOT_FAVOURITE);e.addClass("hidden"),e.attr("aria-hidden",!0)},t=function(a,b){return a.find('[data-action="add-favourite"][data-course-id="'+b+'"]')},u=function(a,b){return a.find('[data-action="remove-favourite"][data-course-id="'+b+'"]')},v=function(a,b){var c=u(a,b),d=t(a,b);x(b,!0).then(function(f){f?(c.removeClass("hidden"),d.addClass("hidden"),s(a,b)):e.alert("Starring course failed","Could not change favourite state")})["catch"](e.exception)},w=function(a,b){var c=u(a,b),d=t(a,b);x(b,!1).then(function(f){f?(c.addClass("hidden"),d.removeClass("hidden"),r(a,b)):e.alert("Starring course failed","Could not change favourite state")})["catch"](e.exception)},x=function(a,c){return b.setFavouriteCourses({courses:[{id:a,favourite:c}]}).then(function(b){return 0==b.warnings.length&&(k.forEach(function(b){b.courses.forEach(function(d,e){d.id==a&&(b.courses[e].isfavourite=c)})}),!0)})["catch"](e.exception)},y=function(a,b){var c=l(a),d="";if(d="cards"==c.display?i.COURSES_CARDS:"list"==c.display?i.COURSES_LIST:i.COURSES_SUMMARY,b.courses.length)return g.render(d,{courses:b.courses});var e=a.attr("data-nocoursesimg");return g.render(i.NOCOURSES,{nocoursesimg:e})},z=function(a,b){var d=l(a),f=c.createWithLimit(j,function(b,c){var f=[];return b.forEach(function(b){var g=b.pageNumber,h=b.pageNumber-1,i=n(d,b.limit,h).then(function(d){return d.courses.length0?k.forEach(function(b,c){var d=p(a,c);y(a,b).then(function(a,b){return g.replaceNodeContents(d,a,b)})["catch"](e.exception)}):B(a,b)};return{init:B,reset:C}}); \ No newline at end of file +define(["jquery","block_myoverview/repository","core/paged_content_factory","core/custom_interaction_events","core/notification","core/templates"],function(a,b,c,d,e,f){var g={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"]'},h={COURSES_CARDS:"block_myoverview/view-cards",COURSES_LIST:"block_myoverview/view-list",COURSES_SUMMARY:"block_myoverview/view-summary",NOCOURSES:"block_myoverview/no-courses"},i=[12,24,48],j=[],k=function(a){var b={};return b.display=a.attr("data-display"),b.grouping=a.attr("data-grouping"),b.sort=a.attr("data-sort"),b},l={ignoreControlWhileLoading:!0,controlPlacementBottom:!0},m=function(a,c,d){return b.getEnrolledCoursesByTimeline({offset:d*c,limit:c,classification:a.grouping,sort:a.sort})},n=function(a,b){return a.find(g.FAVOURITE_ICON+'[data-course-id="'+b+'"]')},o=function(a,b){return a.find('[data-region="paged-content-page"][data-page="'+b+'"]')},p=function(a){return a.attr("data-course-id")},q=function(a,b){var c=n(a,b),d=c.find(g.ICON_IS_FAVOURITE);d.addClass("hidden"),d.attr("aria-hidden",!0);var e=c.find(g.ICON_NOT_FAVOURITE);e.removeClass("hidden"),e.attr("aria-hidden",!1)},r=function(a,b){var c=n(a,b),d=c.find(g.ICON_IS_FAVOURITE);d.removeClass("hidden"),d.attr("aria-hidden",!1);var e=c.find(g.ICON_NOT_FAVOURITE);e.addClass("hidden"),e.attr("aria-hidden",!0)},s=function(a,b){return a.find('[data-action="add-favourite"][data-course-id="'+b+'"]')},t=function(a,b){return a.find('[data-action="remove-favourite"][data-course-id="'+b+'"]')},u=function(a,b){var c=t(a,b),d=s(a,b);x(b,!0).then(function(f){f?(c.removeClass("hidden"),d.addClass("hidden"),r(a,b)):e.alert("Starring course failed","Could not change favourite state")})["catch"](e.exception)},v=function(a,b){var c=t(a,b),d=s(a,b);x(b,!1).then(function(f){f?(c.addClass("hidden"),d.removeClass("hidden"),q(a,b)):e.alert("Starring course failed","Could not change favourite state")})["catch"](e.exception)},w=function(a,b,c){var d=a.find('[data-course-id="'+b+'"][data-region="course-content"]');j.forEach(function(a){a.courses.forEach(function(e,f){e.id==b&&(a.courses[f].hidden=c,d.css("display","none"))})})},x=function(a,c){return b.setFavouriteCourses({courses:[{id:a,favourite:c}]}).then(function(b){return 0==b.warnings.length&&(j.forEach(function(b){b.courses.forEach(function(d,e){d.id==a&&(b.courses[e].isfavourite=c)})}),!0)})["catch"](e.exception)},y=function(a,b){var c=k(a),d="";if(d="cards"==c.display?h.COURSES_CARDS:"list"==c.display?h.COURSES_LIST:h.COURSES_SUMMARY,b.courses.length)return f.render(d,{courses:b.courses});var e=a.attr("data-nocoursesimg");return f.render(h.NOCOURSES,{nocoursesimg:e})},z=function(a,b){var d=k(a),g=c.createWithLimit(i,function(b,c){var f=[];return b.forEach(function(b){var g=b.pageNumber,h=b.pageNumber-1,i=m(d,b.limit,h).then(function(d){return d.courses.length0?j.forEach(function(b,c){var d=o(a,c);y(a,b).then(function(a,b){return f.replaceNodeContents(d,a,b)})["catch"](e.exception)}):B(a,b)};return{init:B,reset:C}}); \ No newline at end of file diff --git a/blocks/myoverview/amd/src/view.js b/blocks/myoverview/amd/src/view.js index e7997759cc3..91ce04631f9 100644 --- a/blocks/myoverview/amd/src/view.js +++ b/blocks/myoverview/amd/src/view.js @@ -28,7 +28,6 @@ define( 'core/paged_content_factory', 'core/custom_interaction_events', 'core/notification', - 'core/ajax', 'core/templates', ], function( @@ -37,7 +36,6 @@ function( PagedContentFactory, CustomEvents, Notification, - Ajax, Templates ) { @@ -234,6 +232,19 @@ function( }).catch(Notification.exception); }; + var toggleHiddenFromCard = function(root, courseId, status) { + var element = root.find('[data-course-id="' + courseId + '"][data-region="course-content"]'); + + loadedPages.forEach(function(courseList) { + courseList.courses.forEach(function(course, index) { + if (course.id == courseId) { + courseList.courses[index].hidden = status; + element.css('display', 'none'); + } + }); + }); + }; + /** * Set the courses favourite status and push to repository * @@ -347,7 +358,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 ]); @@ -384,8 +395,7 @@ function( }; Repository.updateUserPreferences(request); - // Reload the paged content based on the hidden course - initializePagedContent(root, content); + toggleHiddenFromCard(root, id, true); data.originalEvent.preventDefault(); }); @@ -404,8 +414,7 @@ function( Repository.updateUserPreferences(request); - // Reload the paged content based on the hidden course - initializePagedContent(root, content); + toggleHiddenFromCard(root, id, false); data.originalEvent.preventDefault(); }); }; diff --git a/blocks/myoverview/templates/view-cards.mustache b/blocks/myoverview/templates/view-cards.mustache index ce97c1f410d..7ff2b1ab5f9 100644 --- a/blocks/myoverview/templates/view-cards.mustache +++ b/blocks/myoverview/templates/view-cards.mustache @@ -36,7 +36,9 @@
{{#courses}} -
+
{{#str}}aria:courseimage, block_myoverview{{/str}} diff --git a/blocks/myoverview/templates/view-list.mustache b/blocks/myoverview/templates/view-list.mustache index 389036b1055..ea6bfa80231 100644 --- a/blocks/myoverview/templates/view-list.mustache +++ b/blocks/myoverview/templates/view-list.mustache @@ -36,7 +36,9 @@