Proyectos de Subversion Moodle

Rev

Ir a la última revisión | | Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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/>.
15
 
16
/**
17
 * This module is the highest level module for the calendar. It is
18
 * responsible for initialising all of the components required for
19
 * the calendar to run. It also coordinates the interaction between
20
 * components by listening for and responding to different events
21
 * triggered within the calendar UI.
22
 *
23
 * @module     core_calendar/calendar
24
 * @copyright  2017 Simey Lameze <simey@moodle.com>
25
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26
 */
27
define([
28
    'jquery',
29
    'core/templates',
30
    'core/notification',
31
    'core_calendar/repository',
32
    'core_calendar/events',
33
    'core_calendar/view_manager',
34
    'core_calendar/crud',
35
    'core_calendar/selectors',
36
    'core/config',
37
    'core/url',
38
    'core/str',
39
],
40
function(
41
    $,
42
    Templates,
43
    Notification,
44
    CalendarRepository,
45
    CalendarEvents,
46
    CalendarViewManager,
47
    CalendarCrud,
48
    CalendarSelectors,
49
    Config,
50
    Url,
51
    Str,
52
) {
53
 
54
    var SELECTORS = {
55
        ROOT: "[data-region='calendar']",
56
        DAY: "[data-region='day']",
57
        NEW_EVENT_BUTTON: "[data-action='new-event-button']",
58
        DAY_CONTENT: "[data-region='day-content']",
59
        LOADING_ICON: '.loading-icon',
60
        VIEW_DAY_LINK: "[data-action='view-day-link']",
61
        CALENDAR_MONTH_WRAPPER: ".calendarwrapper",
62
        TODAY: '.today',
63
        DAY_NUMBER_CIRCLE: '.day-number-circle',
64
        DAY_NUMBER: '.day-number',
65
        SCREEN_READER_ANNOUNCEMENTS: '.calendar-announcements',
66
        CURRENT_MONTH: '.calendar-controls .current'
67
    };
68
 
69
    /**
70
     * Handler for the drag and drop move event. Provides a loading indicator
71
     * while the request is sent to the server to update the event start date.
72
     *
73
     * Triggers a eventMoved calendar javascript event if the event was successfully
74
     * updated.
75
     *
76
     * @param {event} e The calendar move event
77
     * @param {int} eventId The event id being moved
78
     * @param {object|null} originElement The jQuery element for where the event is moving from
79
     * @param {object} destinationElement The jQuery element for where the event is moving to
80
     */
81
    var handleMoveEvent = function(e, eventId, originElement, destinationElement) {
82
        var originTimestamp = null;
83
        var destinationTimestamp = destinationElement.attr('data-day-timestamp');
84
 
85
        if (originElement) {
86
            originTimestamp = originElement.attr('data-day-timestamp');
87
        }
88
 
89
        // If the event has actually changed day.
90
        if (!originElement || originTimestamp != destinationTimestamp) {
91
            Templates.render('core/loading', {})
92
                .then(function(html, js) {
93
                    // First we show some loading icons in each of the days being affected.
94
                    destinationElement.find(SELECTORS.DAY_CONTENT).addClass('hidden');
95
                    Templates.appendNodeContents(destinationElement, html, js);
96
 
97
                    if (originElement) {
98
                        originElement.find(SELECTORS.DAY_CONTENT).addClass('hidden');
99
                        Templates.appendNodeContents(originElement, html, js);
100
                    }
101
                    return;
102
                })
103
                .then(function() {
104
                    // Send a request to the server to make the change.
105
                    return CalendarRepository.updateEventStartDay(eventId, destinationTimestamp);
106
                })
107
                .then(function() {
108
                    // If the update was successful then broadcast an event letting the calendar
109
                    // know that an event has been moved.
110
                    $('body').trigger(CalendarEvents.eventMoved, [eventId, originElement, destinationElement]);
111
                    return;
112
                })
113
                .always(function() {
114
                    // Always remove the loading icons regardless of whether the update
115
                    // request was successful or not.
116
                    var destinationLoadingElement = destinationElement.find(SELECTORS.LOADING_ICON);
117
                    destinationElement.find(SELECTORS.DAY_CONTENT).removeClass('hidden');
118
                    Templates.replaceNode(destinationLoadingElement, '', '');
119
 
120
                    if (originElement) {
121
                        var originLoadingElement = originElement.find(SELECTORS.LOADING_ICON);
122
                        originElement.find(SELECTORS.DAY_CONTENT).removeClass('hidden');
123
                        Templates.replaceNode(originLoadingElement, '', '');
124
                    }
125
                    return;
126
                })
127
                .catch(Notification.exception);
128
        }
129
    };
130
 
131
    /**
132
     * Listen to and handle any calendar events fired by the calendar UI.
133
     *
134
     * @method registerCalendarEventListeners
135
     * @param {object} root The calendar root element
136
     * @param {object} eventFormModalPromise A promise reolved with the event form modal
137
     */
138
    var registerCalendarEventListeners = function(root, eventFormModalPromise) {
139
        var body = $('body');
140
 
141
        body.on(CalendarEvents.created, function() {
142
            CalendarViewManager.reloadCurrentMonth(root);
143
        });
144
        body.on(CalendarEvents.deleted, function() {
145
            CalendarViewManager.reloadCurrentMonth(root);
146
        });
147
        body.on(CalendarEvents.updated, function() {
148
            CalendarViewManager.reloadCurrentMonth(root);
149
        });
150
        body.on(CalendarEvents.editActionEvent, function(e, url) {
151
            // Action events needs to be edit directly on the course module.
152
            window.location.assign(url);
153
        });
154
        // Handle the event fired by the drag and drop code.
155
        body.on(CalendarEvents.moveEvent, handleMoveEvent);
156
        // When an event is successfully moved we should updated the UI.
157
        body.on(CalendarEvents.eventMoved, function() {
158
            CalendarViewManager.reloadCurrentMonth(root);
159
        });
160
        // Announce the newly loaded month to screen readers.
161
        body.on(CalendarEvents.monthChanged, root, async function() {
162
            const monthName = body.find(SELECTORS.CURRENT_MONTH).text();
163
            const monthAnnoucement = await Str.get_string('newmonthannouncement', 'calendar', monthName);
164
            body.find(SELECTORS.SCREEN_READER_ANNOUNCEMENTS).html(monthAnnoucement);
165
        });
166
 
167
        CalendarCrud.registerEditListeners(root, eventFormModalPromise);
168
    };
169
 
170
    /**
171
     * Register event listeners for the module.
172
     *
173
     * @param {object} root The calendar root element
174
     */
175
    var registerEventListeners = function(root) {
176
        const viewingFullCalendar = document.getElementById(CalendarSelectors.fullCalendarView);
177
        // Listen the click on the day link to render the day view.
178
        root.on('click', SELECTORS.VIEW_DAY_LINK, function(e) {
179
            var dayLink = $(e.target).closest(SELECTORS.VIEW_DAY_LINK);
180
            var year = dayLink.data('year'),
181
                month = dayLink.data('month'),
182
                day = dayLink.data('day'),
183
                courseId = dayLink.data('courseid'),
184
                categoryId = dayLink.data('categoryid');
185
            const urlParams = {
186
                view: 'day',
187
                time: dayLink.data('timestamp'),
188
                course: courseId,
189
            };
190
            if (viewingFullCalendar) {
191
                // Construct the URL parameter string from the urlParams object.
192
                const urlParamString = Object.entries(urlParams)
193
                    .map(([key, value]) => `${encodeURIComponent(key)}=${encodeURIComponent(value)}`)
194
                    .join('&');
195
                CalendarViewManager.refreshDayContent(root, year, month, day, courseId, categoryId, root,
196
                    'core_calendar/calendar_day').then(function() {
197
                    e.preventDefault();
198
                    return CalendarViewManager.updateUrl(urlParamString);
199
                }).catch(Notification.exception);
200
            } else {
201
                window.location.assign(Url.relativeUrl('calendar/view.php', urlParams));
202
            }
203
        });
204
 
205
        root.on('change', CalendarSelectors.elements.courseSelector, function() {
206
            var selectElement = $(this);
207
            var courseId = selectElement.val();
208
            const courseName = $("option:selected", selectElement).text();
209
            CalendarViewManager.reloadCurrentMonth(root, courseId, null)
210
                .then(function() {
211
                    // We need to get the selector again because the content has changed.
212
                    return root.find(CalendarSelectors.elements.courseSelector).val(courseId);
213
                })
214
                .then(function() {
215
                    CalendarViewManager.updateUrl('?view=month&course=' + courseId);
216
                    CalendarViewManager.handleCourseChange(Number(courseId), courseName);
217
                    return;
218
                })
219
                .catch(Notification.exception);
220
        });
221
 
222
        var eventFormPromise = CalendarCrud.registerEventFormModal(root),
223
            contextId = $(SELECTORS.CALENDAR_MONTH_WRAPPER).data('context-id');
224
        registerCalendarEventListeners(root, eventFormPromise);
225
 
226
        if (contextId) {
227
            // Bind click events to calendar days.
228
            root.on('click', SELECTORS.DAY, function(e) {
229
                var target = $(e.target);
230
                const displayingSmallBlockCalendar = root.parents('aside').data('blockregion') === 'side-pre';
231
 
232
                if (!viewingFullCalendar && displayingSmallBlockCalendar) {
233
                    const dateContainer = target.closest(SELECTORS.DAY);
234
                    const wrapper = target.closest(CalendarSelectors.wrapper);
235
                    const courseId = wrapper.data('courseid');
236
                    const params = {
237
                        view: 'day',
238
                        time: dateContainer.data('day-timestamp'),
239
                        course: courseId,
240
                    };
241
                    window.location.assign(Url.relativeUrl('calendar/view.php', params));
242
                } else {
243
                    const hasViewDayLink = target.closest(SELECTORS.VIEW_DAY_LINK).length;
244
                    const shouldShowNewEventModal = !hasViewDayLink;
245
                    if (shouldShowNewEventModal) {
246
                        var startTime = $(this).attr('data-new-event-timestamp');
247
                        eventFormPromise.then(function(modal) {
248
                            var wrapper = target.closest(CalendarSelectors.wrapper);
249
                            modal.setCourseId(wrapper.data('courseid'));
250
 
251
                            var categoryId = wrapper.data('categoryid');
252
                            if (typeof categoryId !== 'undefined') {
253
                                modal.setCategoryId(categoryId);
254
                            }
255
 
256
                            modal.setContextId(wrapper.data('contextId'));
257
                            modal.setStartTime(startTime);
258
                            modal.show();
259
                            return;
260
                        }).catch(Notification.exception);
261
                    }
262
                }
263
                e.preventDefault();
264
            });
265
        }
266
    };
267
 
268
    return {
269
        init: function(root) {
270
            root = $(root);
271
            CalendarViewManager.init(root);
272
            registerEventListeners(root);
273
        }
274
    };
275
});