diff --git a/blocks/myoverview/amd/build/view.min.js b/blocks/myoverview/amd/build/view.min.js index 90bf1953ad8..e113a14a355 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","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:"core_course/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"),displaycategories:b.attr("data-displaycategories")}},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,b),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,b),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,"on"!=c.displaycategories&&(b.courses=b.courses.map(function(a){return delete a.coursecategory,a})),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 +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:"core_course/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"),displaycategories:b.attr("data-displaycategories")}},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,b),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,b),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="card"==c.display?l.COURSES_CARDS:"list"==c.display?l.COURSES_LIST:l.COURSES_SUMMARY,"on"!=c.displaycategories&&(b.courses=b.courses.map(function(a){return delete a.coursecategory,a})),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 6a836464609..0dc37ba13e7 100644 --- a/blocks/myoverview/amd/src/view.js +++ b/blocks/myoverview/amd/src/view.js @@ -363,7 +363,7 @@ function( var filters = getFilterValues(root); var currentTemplate = ''; - if (filters.display == 'cards') { + if (filters.display == 'card') { currentTemplate = TEMPLATES.COURSES_CARDS; } else if (filters.display == 'list') { currentTemplate = TEMPLATES.COURSES_LIST; diff --git a/blocks/myoverview/block_myoverview.php b/blocks/myoverview/block_myoverview.php index 617771902fa..01744b96149 100644 --- a/blocks/myoverview/block_myoverview.php +++ b/blocks/myoverview/block_myoverview.php @@ -74,7 +74,7 @@ class block_myoverview extends block_base { } /** - * Allow the block to have a configuration page + * Allow the block to have a configuration page. * * @return boolean */ diff --git a/blocks/myoverview/classes/output/main.php b/blocks/myoverview/classes/output/main.php index 7ef8c386e72..8df2b478a59 100644 --- a/blocks/myoverview/classes/output/main.php +++ b/blocks/myoverview/classes/output/main.php @@ -27,6 +27,7 @@ defined('MOODLE_INTERNAL') || die(); use renderable; use renderer_base; use templatable; +use stdClass; require_once($CFG->dirroot . '/blocks/myoverview/lib.php'); @@ -39,40 +40,47 @@ require_once($CFG->dirroot . '/blocks/myoverview/lib.php'); class main implements renderable, templatable { /** - * Store the grouping preference + * Store the grouping preference. * * @var string String matching the grouping constants defined in myoverview/lib.php */ private $grouping; /** - * Store the sort preference + * Store the sort preference. * * @var string String matching the sort constants defined in myoverview/lib.php */ private $sort; /** - * Store the view preference + * Store the view preference. * * @var string String matching the view/display constants defined in myoverview/lib.php */ private $view; /** - * Store the paging preference + * Store the paging preference. * * @var string String matching the paging constants defined in myoverview/lib.php */ private $paging; /** - * Store the display categories config setting + * Store the display categories config setting. * * @var boolean */ private $displaycategories; + /** + * Store the configuration values for the myoverview block. + * + * @var array Array of available layouts matching view/display constants defined in myoverview/lib.php + */ + private $layouts; + /** * main constructor. * Initialize the user preferences @@ -80,34 +88,91 @@ class main implements renderable, templatable { * @param string $grouping Grouping user preference * @param string $sort Sort user preference * @param string $view Display user preference + * + * @throws \dml_exception */ 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; + $config = get_config('block_myoverview'); if (!$config->displaycategories) { $this->displaycategories = BLOCK_MYOVERVIEW_DISPLAY_CATEGORIES_OFF; } else { $this->displaycategories = BLOCK_MYOVERVIEW_DISPLAY_CATEGORIES_ON; } + + $this->set_available_layouts(); + $this->view = $view ? $view : reset($this->layouts); + } + + + /** + * Set the available layouts based on the config table settings, + * if none are available, defaults to the cards view. + * + * @throws \dml_exception + * + */ + public function set_available_layouts() { + + if ($config = get_config('block_myoverview', 'layouts')) { + $this->layouts = explode(',', $config); + } else { + $this->layouts = array(BLOCK_MYOVERVIEW_VIEW_CARD); + } } /** - * Get the user preferences as an array to figure out what has been selected + * Get the user preferences as an array to figure out what has been selected. * * @return array $preferences Array with the pref as key and value set to true */ public function get_preferences_as_booleans() { $preferences = []; - $preferences[$this->view] = true; $preferences[$this->sort] = true; $preferences[$this->grouping] = true; + // Only use the user view/display preference if it is in available layouts. + if (in_array($this->view, $this->layouts)) { + $preferences[$this->view] = true; + } else { + $preferences[reset($this->layouts)] = true; + } return $preferences; } + /** + * Format a layout into an object for export as a Context variable to template. + * + * @param string $layoutname + * + * @return \stdClass $layout an object representation of a layout + * @throws \coding_exception + */ + public function format_layout_for_export($layoutname) { + $layout = new stdClass(); + + $layout->id = $layoutname; + $layout->name = get_string($layoutname, 'block_myoverview'); + $layout->active = $this->view == $layoutname ? true : false; + $layout->arialabel = get_string('aria:' . $layoutname, 'block_myoverview'); + + return $layout; + } + + /** + * Get the available layouts formatted for export. + * + * @return array an array of objects representing available layouts + */ + public function get_formatted_available_layouts_for_export() { + + return array_map(array($this, 'format_layout_for_export'), $this->layouts); + + } + /** * Export this data so it can be used as the context for a mustache template. * @@ -118,16 +183,20 @@ class main implements renderable, templatable { $nocoursesurl = $output->image_url('courses', 'block_myoverview')->out(); + $preferences = $this->get_preferences_as_booleans(); + $availablelayouts = $this->get_formatted_available_layouts_for_export(); + $defaultvariables = [ 'nocoursesimg' => $nocoursesurl, 'grouping' => $this->grouping, 'sort' => $this->sort == BLOCK_MYOVERVIEW_SORTING_TITLE ? 'fullname' : 'ul.timeaccess desc', - 'view' => $this->view, + // If the user preference display option is not available, default to first available layout. + 'view' => in_array($this->view, $this->layouts) ? $this->view : reset($this->layouts), 'paging' => $this->paging, + 'layouts' => $availablelayouts, 'displaycategories' => $this->displaycategories, + 'displaydropdown' => (count($availablelayouts) > 1) ? true : false, ]; - - $preferences = $this->get_preferences_as_booleans(); return array_merge($defaultvariables, $preferences); } diff --git a/blocks/myoverview/lang/en/block_myoverview.php b/blocks/myoverview/lang/en/block_myoverview.php index 79a0b786dd6..637368ba2dc 100644 --- a/blocks/myoverview/lang/en/block_myoverview.php +++ b/blocks/myoverview/lang/en/block_myoverview.php @@ -55,6 +55,8 @@ $string['favourites'] = 'Starred'; $string['future'] = 'Future'; $string['inprogress'] = 'In progress'; $string['lastaccessed'] = 'Last accessed'; +$string['layouts'] = 'Available Layouts'; +$string['layouts_help'] = 'The layouts which are available for selection by users'; $string['list'] = 'List'; $string['myoverview:myaddinstance'] = 'Add a new course overview block to Dashboard'; $string['past'] = 'Past'; diff --git a/blocks/myoverview/lib.php b/blocks/myoverview/lib.php index d5bc9e23f19..652177f0fa3 100644 --- a/blocks/myoverview/lib.php +++ b/blocks/myoverview/lib.php @@ -44,7 +44,7 @@ define('BLOCK_MYOVERVIEW_SORTING_LASTACCESSED', 'lastaccessed'); /** * Constants for the user preferences view options */ -define('BLOCK_MYOVERVIEW_VIEW_CARD', 'cards'); +define('BLOCK_MYOVERVIEW_VIEW_CARD', 'card'); define('BLOCK_MYOVERVIEW_VIEW_LIST', 'list'); define('BLOCK_MYOVERVIEW_VIEW_SUMMARY', 'summary'); diff --git a/blocks/myoverview/settings.php b/blocks/myoverview/settings.php index f3b2edf8a56..b17ea4e0f6e 100644 --- a/blocks/myoverview/settings.php +++ b/blocks/myoverview/settings.php @@ -34,4 +34,15 @@ if ($ADMIN->fulltree) { get_string('displaycategories_help', 'block_myoverview'), 1)); + $choices = array(BLOCK_MYOVERVIEW_VIEW_CARD => get_string('card', 'block_myoverview'), + BLOCK_MYOVERVIEW_VIEW_LIST => get_string('list', 'block_myoverview'), + BLOCK_MYOVERVIEW_VIEW_SUMMARY => get_string('summary', 'block_myoverview')); + + $settings->add(new admin_setting_configmulticheckbox( + 'block_myoverview/layouts', + get_string('layouts', 'block_myoverview'), + get_string('layouts_help', 'block_myoverview'), + $choices, + $choices)); + } diff --git a/blocks/myoverview/templates/main.mustache b/blocks/myoverview/templates/main.mustache index 059263cf7ba..d575234de21 100644 --- a/blocks/myoverview/templates/main.mustache +++ b/blocks/myoverview/templates/main.mustache @@ -29,8 +29,9 @@ {{> block_myoverview/nav-grouping-selector }} {{> block_myoverview/nav-sort-selector }} - - {{> block_myoverview/nav-display-selector }} + {{#displaydropdown}} + {{> block_myoverview/nav-display-selector }} + {{/displaydropdown}}
diff --git a/blocks/myoverview/templates/nav-display-selector.mustache b/blocks/myoverview/templates/nav-display-selector.mustache index ce8555b1a04..8a1cb325a30 100644 --- a/blocks/myoverview/templates/nav-display-selector.mustache +++ b/blocks/myoverview/templates/nav-display-selector.mustache @@ -31,26 +31,18 @@ aria-label="{{#str}} aria:displaydropdown, block_myoverview {{/str}}"> {{#pix}} a/view_icon_active {{/pix}} - {{#cards}}{{#str}} card, block_myoverview {{/str}}{{/cards}} + {{#card}}{{#str}} card, block_myoverview {{/str}}{{/card}} {{#list}}{{#str}} list, block_myoverview {{/str}}{{/list}} {{#summary}}{{#str}} summary, block_myoverview {{/str}}{{/summary}}
diff --git a/blocks/myoverview/version.php b/blocks/myoverview/version.php index bc9f9836674..25b71946d99 100644 --- a/blocks/myoverview/version.php +++ b/blocks/myoverview/version.php @@ -24,6 +24,6 @@ defined('MOODLE_INTERNAL') || die(); -$plugin->version = 2019052000; // The current plugin version (Date: YYYYMMDDXX). +$plugin->version = 2019060400; // The current plugin version (Date: YYYYMMDDXX). $plugin->requires = 2019051100; // Requires this Moodle version. $plugin->component = 'block_myoverview'; // Full name of the plugin (used for diagnostics).