MDL-59393 calendar: add update_event_start_day external function
[moodle.git] / calendar / amd / src / calendar.js
CommitLineData
3b0738f0
SL
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/**
aa091225
RW
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.
3b0738f0
SL
22 *
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
27 */
aa091225
RW
28define([
29 'jquery',
30 'core/ajax',
31 'core/str',
32 'core/templates',
33 'core/notification',
34 'core/custom_interaction_events',
35 'core/modal_events',
36 'core/modal_factory',
37 'core_calendar/modal_event_form',
38 'core_calendar/summary_modal',
39 'core_calendar/repository',
695c5726
AN
40 'core_calendar/events',
41 'core_calendar/view_manager'
aa091225
RW
42 ],
43 function(
44 $,
45 Ajax,
46 Str,
47 Templates,
48 Notification,
49 CustomEvents,
50 ModalEvents,
51 ModalFactory,
52 ModalEventForm,
53 SummaryModal,
54 CalendarRepository,
695c5726
AN
55 CalendarEvents,
56 CalendarViewManager
aa091225
RW
57 ) {
58
59 var SELECTORS = {
60 ROOT: "[data-region='calendar']",
61 EVENT_LINK: "[data-action='view-event']",
62 NEW_EVENT_BUTTON: "[data-action='new-event-button']"
63 };
64
65 /**
66 * Get the event type lang string.
67 *
68 * @param {String} eventType The event type.
69 * @return {promise} The lang string promise.
70 */
71 var getEventType = function(eventType) {
72 var lang = 'type' + eventType;
73 return Str.get_string(lang, 'core_calendar').then(function(langStr) {
74 return langStr;
75 });
76 };
77
78 /**
79 * Get the event source.
80 *
81 * @param {Object} subscription The event subscription object.
82 * @return {promise} The lang string promise.
83 */
84 var getEventSource = function(subscription) {
85 return Str.get_string('subsource', 'core_calendar', subscription).then(function(langStr) {
86 if (subscription.url) {
87 return '<a href="' + subscription.url + '">' + langStr + '</a>';
88 }
89 return langStr;
90 });
91 };
a43ec9eb 92
aa091225
RW
93 /**
94 * Render the event summary modal.
95 *
96 * @param {Number} eventId The calendar event id.
97 */
98 var renderEventSummaryModal = function(eventId) {
99 // Calendar repository promise.
100 CalendarRepository.getEventById(eventId).then(function(getEventResponse) {
101 if (!getEventResponse.event) {
102 throw new Error('Error encountered while trying to fetch calendar event with ID: ' + eventId);
103 }
104 var eventData = getEventResponse.event;
105 var eventTypePromise = getEventType(eventData.eventtype);
106
107 // If the calendar event has event source, get the source's language string/link.
108 if (eventData.displayeventsource) {
109 eventData.subscription = JSON.parse(eventData.subscription);
110 var eventSourceParams = {
111 url: eventData.subscription.url,
112 name: eventData.subscription.name
113 };
114 var eventSourcePromise = getEventSource(eventSourceParams);
115
116 // Return event data with event type and event source info.
117 return $.when(eventTypePromise, eventSourcePromise).then(function(eventType, eventSource) {
a43ec9eb 118 eventData.eventtype = eventType;
aa091225 119 eventData.source = eventSource;
a43ec9eb 120 return eventData;
3b0738f0 121 });
aa091225 122 }
3d67e83f 123
aa091225
RW
124 // Return event data with event type info.
125 return eventTypePromise.then(function(eventType) {
126 eventData.eventtype = eventType;
127 return eventData;
128 });
129
130 }).then(function(eventData) {
131 // Build the modal parameters from the event data.
132 var modalParams = {
133 title: eventData.name,
134 type: SummaryModal.TYPE,
4df03a27
SL
135 body: Templates.render('core_calendar/event_summary_body', eventData),
136 templateContext: {
137 canedit: eventData.canedit,
138 candelete: eventData.candelete
139 }
aa091225 140 };
4df03a27 141
aa091225
RW
142 // Create the modal.
143 return ModalFactory.create(modalParams);
144
145 }).done(function(modal) {
146 // Handle hidden event.
147 modal.getRoot().on(ModalEvents.hidden, function() {
148 // Destroy when hidden.
149 modal.destroy();
150 });
151
152 // Finally, render the modal!
153 modal.show();
154
155 }).fail(Notification.exception);
156 };
157
158 /**
159 * Create the event form modal for creating new events and
160 * editing existing events.
161 *
162 * @method registerEventFormModal
163 * @param {object} root The calendar root element
164 * @return {object} The create modal promise
165 */
166 var registerEventFormModal = function(root) {
167 var newEventButton = root.find(SELECTORS.NEW_EVENT_BUTTON);
168 var contextId = newEventButton.attr('data-context-id');
169
170 return ModalFactory.create(
171 {
172 type: ModalEventForm.TYPE,
173 large: true,
174 templateContext: {
175 contextid: contextId
3d67e83f 176 }
aa091225 177 },
6a7ad2cb 178 [root, SELECTORS.NEW_EVENT_BUTTON]
aa091225
RW
179 );
180 };
a43ec9eb 181
aa091225
RW
182 /**
183 * Listen to and handle any calendar events fired by the calendar UI.
184 *
185 * @method registerCalendarEventListeners
186 * @param {object} root The calendar root element
187 * @param {object} eventFormModalPromise A promise reolved with the event form modal
188 */
189 var registerCalendarEventListeners = function(root, eventFormModalPromise) {
190 var body = $('body');
191
192 // TODO: Replace these with actual logic to update
193 // the UI without having to force a page reload.
d6942fb5
RW
194 body.on(CalendarEvents.created, function() {
195 window.location.reload();
196 });
197 body.on(CalendarEvents.deleted, function() {
516e7444 198 CalendarViewManager.reloadCurrentMonth();
d6942fb5
RW
199 });
200 body.on(CalendarEvents.updated, function() {
201 window.location.reload();
202 });
c34e2002
SL
203 body.on(CalendarEvents.editActionEvent, function(e, url) {
204 // Action events needs to be edit directly on the course module.
205 window.location.assign(url);
206 });
a43ec9eb 207
aa091225
RW
208 eventFormModalPromise.then(function(modal) {
209 // When something within the calendar tells us the user wants
210 // to edit an event then show the event form modal.
211 body.on(CalendarEvents.editEvent, function(e, eventId) {
212 modal.setEventId(eventId);
213 modal.show();
3b0738f0 214 });
3b0738f0 215
aa091225
RW
216 return;
217 });
218 };
219
220 /**
221 * Register event listeners for the module.
222 */
223 var registerEventListeners = function() {
224 var root = $(SELECTORS.ROOT);
225
226 // Bind click events to event links.
6a7ad2cb 227 root.on('click', SELECTORS.EVENT_LINK, function(e) {
aa091225
RW
228 e.preventDefault();
229 var eventId = $(this).attr('data-event-id');
230 renderEventSummaryModal(eventId);
231 });
232
233 var eventFormPromise = registerEventFormModal(root);
234 registerCalendarEventListeners(root, eventFormPromise);
235 };
236
237 return {
238 init: function() {
695c5726 239 CalendarViewManager.init();
aa091225
RW
240 registerEventListeners();
241 }
242 };
243});