1 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
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.
23 * @module core_calendar/calendar
24 * @package core_calendar
25 * @copyright 2017 Simey Lameze <simey@moodle.com>
26 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
34 'core/custom_interaction_events',
37 'core_calendar/modal_event_form',
38 'core_calendar/summary_modal',
39 'core_calendar/repository',
40 'core_calendar/events',
41 'core_calendar/view_manager',
43 'core_calendar/selectors',
64 ROOT: "[data-region='calendar']",
65 DAY: "[data-region='day']",
66 NEW_EVENT_BUTTON: "[data-action='new-event-button']",
67 DAY_CONTENT: "[data-region='day-content']",
68 LOADING_ICON: '.loading-icon',
69 VIEW_DAY_LINK: "[data-action='view-day-link']",
70 CALENDAR_MONTH_WRAPPER: ".calendarwrapper",
75 * Handler for the drag and drop move event. Provides a loading indicator
76 * while the request is sent to the server to update the event start date.
78 * Triggers a eventMoved calendar javascript event if the event was successfully
81 * @param {event} e The calendar move event
82 * @param {int} eventId The event id being moved
83 * @param {object|null} originElement The jQuery element for where the event is moving from
84 * @param {object} destinationElement The jQuery element for where the event is moving to
86 var handleMoveEvent = function(e, eventId, originElement, destinationElement) {
87 var originTimestamp = null;
88 var destinationTimestamp = destinationElement.attr('data-day-timestamp');
91 originTimestamp = originElement.attr('data-day-timestamp');
94 // If the event has actually changed day.
95 if (!originElement || originTimestamp != destinationTimestamp) {
96 Templates.render('core/loading', {})
97 .then(function(html, js) {
98 // First we show some loading icons in each of the days being affected.
99 destinationElement.find(SELECTORS.DAY_CONTENT).addClass('hidden');
100 Templates.appendNodeContents(destinationElement, html, js);
103 originElement.find(SELECTORS.DAY_CONTENT).addClass('hidden');
104 Templates.appendNodeContents(originElement, html, js);
109 // Send a request to the server to make the change.
110 return CalendarRepository.updateEventStartDay(eventId, destinationTimestamp);
113 // If the update was successful then broadcast an event letting the calendar
114 // know that an event has been moved.
115 $('body').trigger(CalendarEvents.eventMoved, [eventId, originElement, destinationElement]);
119 // Always remove the loading icons regardless of whether the update
120 // request was successful or not.
121 var destinationLoadingElement = destinationElement.find(SELECTORS.LOADING_ICON);
122 destinationElement.find(SELECTORS.DAY_CONTENT).removeClass('hidden');
123 Templates.replaceNode(destinationLoadingElement, '', '');
126 var originLoadingElement = originElement.find(SELECTORS.LOADING_ICON);
127 originElement.find(SELECTORS.DAY_CONTENT).removeClass('hidden');
128 Templates.replaceNode(originLoadingElement, '', '');
132 .fail(Notification.exception);
137 * Listen to and handle any calendar events fired by the calendar UI.
139 * @method registerCalendarEventListeners
140 * @param {object} root The calendar root element
141 * @param {object} eventFormModalPromise A promise reolved with the event form modal
143 var registerCalendarEventListeners = function(root, eventFormModalPromise) {
144 var body = $('body');
146 body.on(CalendarEvents.created, function() {
147 CalendarViewManager.reloadCurrentMonth(root);
149 body.on(CalendarEvents.deleted, function() {
150 CalendarViewManager.reloadCurrentMonth(root);
152 body.on(CalendarEvents.updated, function() {
153 CalendarViewManager.reloadCurrentMonth(root);
155 body.on(CalendarEvents.editActionEvent, function(e, url) {
156 // Action events needs to be edit directly on the course module.
157 window.location.assign(url);
159 // Handle the event fired by the drag and drop code.
160 body.on(CalendarEvents.moveEvent, handleMoveEvent);
161 // When an event is successfully moved we should updated the UI.
162 body.on(CalendarEvents.eventMoved, function() {
163 CalendarViewManager.reloadCurrentMonth(root);
166 CalendarCrud.registerEditListeners(root, eventFormModalPromise);
170 * Register event listeners for the module.
172 * @param {object} root The calendar root element
174 var registerEventListeners = function(root) {
175 root.on('change', CalendarSelectors.elements.courseSelector, function() {
176 var selectElement = $(this);
177 var courseId = selectElement.val();
178 CalendarViewManager.reloadCurrentMonth(root, courseId, null)
180 // We need to get the selector again because the content has changed.
181 return root.find(CalendarSelectors.elements.courseSelector).val(courseId);
183 .fail(Notification.exception);
186 var eventFormPromise = CalendarCrud.registerEventFormModal(root),
187 contextId = $(SELECTORS.CALENDAR_MONTH_WRAPPER).data('context-id');
188 registerCalendarEventListeners(root, eventFormPromise);
191 // Bind click events to calendar days.
192 root.on('click', SELECTORS.DAY, function (e) {
194 var target = $(e.target);
196 if (!target.is(SELECTORS.VIEW_DAY_LINK)) {
197 var startTime = $(this).attr('data-new-event-timestamp');
198 eventFormPromise.then(function (modal) {
199 var wrapper = target.closest(CalendarSelectors.wrapper);
200 modal.setCourseId(wrapper.data('courseid'));
202 var categoryId = wrapper.data('categoryid');
203 if (typeof categoryId !== 'undefined') {
204 modal.setCategoryId(categoryId);
207 modal.setContextId(wrapper.data('contextId'));
208 modal.setStartTime(startTime);
212 .fail(Notification.exception);
221 init: function(root) {
223 CalendarViewManager.init(root);
224 registerEventListeners(root);