MDL-63352 block_timeline: Persist user preference on timeline
[moodle.git] / blocks / timeline / amd / src / view_nav.js
1 // This file is part of Moodle - http://moodle.org/
2 //
3 // Moodle is free software: you can redistribute it and/or modify
4 // it under the terms of the GNU General Public License as published by
5 // the Free Software Foundation, either version 3 of the License, or
6 // (at your option) any later version.
7 //
8 // Moodle is distributed in the hope that it will be useful,
9 // but WITHOUT ANY WARRANTY; without even the implied warranty of
10 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11 // GNU General Public License for more details.
12 //
13 // You should have received a copy of the GNU General Public License
14 // along with Moodle.  If not, see <http://www.gnu.org/licenses/>.
16 /**
17  * Manage the timeline view navigation for the timeline block.
18  *
19  * @package    block_timeline
20  * @copyright  2018 Ryan Wyllie <ryan@moodle.com>
21  * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22  */
24 define(
25 [
26     'jquery',
27     'core/custom_interaction_events',
28     'block_timeline/view',
29     'core/ajax',
30     'core/notification'
31 ],
32 function(
33     $,
34     CustomEvents,
35     View,
36     Ajax,
37     Notification
38 ) {
40     var SELECTORS = {
41         TIMELINE_DAY_FILTER: '[data-region="day-filter"]',
42         TIMELINE_DAY_FILTER_OPTION: '[data-from]',
43         TIMELINE_VIEW_SELECTOR: '[data-region="view-selector"]',
44         DATA_DAYS_OFFSET: '[data-days-offset]',
45         DATA_DAYS_LIMIT: '[data-days-limit]',
46     };
48     /**
49      * Generic handler to persist user preferences
50      *
51      * @param {string} type The name of the attribute you're updating
52      * @param {string} value The value of the attribute you're updating
53      */
54     var updateUserPreferences = function(type, value) {
55         var request = {
56             methodname: 'core_user_update_user_preferences',
57             args: {
58                 preferences: [
59                     {
60                         type: type,
61                         value: value
62                     }
63                 ]
64             }
65         };
67         Ajax.call([request])[0]
68             .fail(Notification.exception);
69     };
71     /**
72      * Event listener for the day selector ("Next 7 days", "Next 30 days", etc).
73      *
74      * @param {object} root The root element for the timeline block
75      * @param {object} timelineViewRoot The root element for the timeline view
76      */
77     var registerTimelineDaySelector = function(root, timelineViewRoot) {
78         var timelineDaySelectorContainer = root.find(SELECTORS.TIMELINE_DAY_FILTER);
80         CustomEvents.define(timelineDaySelectorContainer, [CustomEvents.events.activate]);
81         timelineDaySelectorContainer.on(
82             CustomEvents.events.activate,
83             SELECTORS.TIMELINE_DAY_FILTER_OPTION,
84             function(e, data) {
85                 // Update the user preference
86                 var filtername = $(e.currentTarget).data('filtername');
87                 var type = 'block_timeline_user_filter_preference';
88                 updateUserPreferences(type, filtername);
90                 var option = $(e.target).closest(SELECTORS.TIMELINE_DAY_FILTER_OPTION);
92                 if (option.hasClass('active')) {
93                     // If it's already active then we don't need to do anything.
94                     return;
95                 }
97                 var daysOffset = option.attr('data-from');
98                 var daysLimit = option.attr('data-to');
99                 var elementsWithDaysOffset = root.find(SELECTORS.DATA_DAYS_OFFSET);
101                 elementsWithDaysOffset.attr('data-days-offset', daysOffset);
103                 if (daysLimit != undefined) {
104                     elementsWithDaysOffset.attr('data-days-limit', daysLimit);
105                 } else {
106                     elementsWithDaysOffset.removeAttr('data-days-limit');
107                 }
109                 // Reset the views to reinitialise the event lists now that we've
110                 // updated the day limits.
111                 View.reset(timelineViewRoot);
113                 data.originalEvent.preventDefault();
114             }
115         );
116     };
118     /**
119      * Event listener for the "sort" button in the timeline navigation that allows for
120      * changing between the timeline dates and courses views.
121      *
122      * On a view change we tell the timeline view module that the view has been shown
123      * so that it can handle how to display the appropriate view.
124      *
125      * @param {object} root The root element for the timeline block
126      * @param {object} timelineViewRoot The root element for the timeline view
127      */
128     var registerViewSelector = function(root, timelineViewRoot) {
129         var viewSelector = root.find(SELECTORS.TIMELINE_VIEW_SELECTOR);
131         // Listen for when the user changes tab so that we can show the first set of courses
132         // and load their events when they request the sort by courses view for the first time.
133         viewSelector.on('shown shown.bs.tab', function() {
134             View.shown(timelineViewRoot);
135         });
137         // Event selector for user_sort
138         CustomEvents.define(viewSelector, [CustomEvents.events.activate]);
139         viewSelector.on(CustomEvents.events.activate, "[data-toggle='tab']", function(e) {
140             var filtername = $(e.currentTarget).data('filtername');
141             var type = 'block_timeline_user_sort_preference';
142             updateUserPreferences(type, filtername);
143         });
144     };
146     /**
147      * Initialise the timeline view navigation by adding event listeners to
148      * the navigation elements.
149      *
150      * @param {object} root The root element for the timeline block
151      * @param {object} timelineViewRoot The root element for the timeline view
152      */
153     var init = function(root, timelineViewRoot) {
154         root = $(root);
155         registerTimelineDaySelector(root, timelineViewRoot);
156         registerViewSelector(root, timelineViewRoot);
157     };
159     return {
160         init: init
161     };
162 });