on-demand release 4.0dev+
[moodle.git] / question / amd / src / edit_tags.js
CommitLineData
fd5e2ead
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/**
17 * A javascript module to handle question tags editing.
18 *
1db23e81
SS
19 * @deprecated since Moodle 4.0
20 * @todo Final deprecation on Moodle 4.4 MDL-72438
fd5e2ead
SL
21 * @module core_question/edit_tags
22 * @copyright 2018 Simey Lameze <simey@moodle.com>
23 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
24 */
25define([
26 'jquery',
27 'core/fragment',
28 'core/str',
29 'core/modal_events',
30 'core/modal_factory',
31 'core/notification',
32 'core/custom_interaction_events',
33 'core_question/repository',
d1db765a 34 'core_question/selectors',
fd5e2ead
SL
35 ],
36 function(
37 $,
38 Fragment,
39 Str,
40 ModalEvents,
41 ModalFactory,
42 Notification,
43 CustomEvents,
d1db765a
SL
44 Repository,
45 QuestionSelectors
fd5e2ead
SL
46 ) {
47
fd5e2ead
SL
48 /**
49 * Enable the save button in the footer.
50 *
51 * @param {object} root The container element.
52 * @method enableSaveButton
53 */
54 var enableSaveButton = function(root) {
d1db765a 55 root.find(QuestionSelectors.actions.save).prop('disabled', false);
fd5e2ead
SL
56 };
57
58 /**
59 * Disable the save button in the footer.
60 *
61 * @param {object} root The container element.
62 * @method disableSaveButton
63 */
64 var disableSaveButton = function(root) {
d1db765a 65 root.find(QuestionSelectors.actions.save).prop('disabled', true);
fd5e2ead
SL
66 };
67
68 /**
69 * Get the serialised form data.
70 *
71 * @method getFormData
72 * @param {object} modal The modal object.
73 * @return {string} serialised form data
74 */
75 var getFormData = function(modal) {
76 return modal.getBody().find('form').serialize();
77 };
78
79 /**
80 * Set the element state to loading.
81 *
82 * @param {object} root The container element
83 * @method startLoading
84 */
85 var startLoading = function(root) {
d1db765a 86 var loadingIconContainer = root.find(QuestionSelectors.containers.loadingIcon);
fd5e2ead
SL
87
88 loadingIconContainer.removeClass('hidden');
89 };
90
91 /**
92 * Remove the loading state from the element.
93 *
94 * @param {object} root The container element
95 * @method stopLoading
96 */
97 var stopLoading = function(root) {
d1db765a 98 var loadingIconContainer = root.find(QuestionSelectors.containers.loadingIcon);
fd5e2ead
SL
99
100 loadingIconContainer.addClass('hidden');
101 };
102
e6890b11
SL
103 /**
104 * Set the context Id data attribute on the modal.
105 *
106 * @param {Promise} modal The modal promise.
107 * @param {int} contextId The context id.
108 */
109 var setContextId = function(modal, contextId) {
110 modal.getBody().attr('data-contextid', contextId);
111 };
112
113 /**
114 * Get the context Id data attribute value from the modal body.
115 *
116 * @param {Promise} modal The modal promise.
117 * @return {int} The context id.
118 */
119 var getContextId = function(modal) {
120 return modal.getBody().data('contextid');
121 };
122
123 /**
124 * Set the question Id data attribute on the modal.
125 *
126 * @param {Promise} modal The modal promise.
127 * @param {int} questionId The question Id.
128 */
129 var setQuestionId = function(modal, questionId) {
130 modal.getBody().attr('data-questionid', questionId);
131 };
132
133 /**
134 * Get the question Id data attribute value from the modal body.
135 *
136 * @param {Promise} modal The modal promise.
137 * @return {int} The question Id.
138 */
139 var getQuestionId = function(modal) {
140 return modal.getBody().data('questionid');
141 };
142
fd5e2ead
SL
143 /**
144 * Register event listeners for the module.
145 *
146 * @param {object} root The calendar root element
147 */
148 var registerEventListeners = function(root) {
149 var modalPromise = ModalFactory.create(
150 {
151 type: ModalFactory.types.SAVE_CANCEL,
152 large: false
153 },
d1db765a 154 [root, QuestionSelectors.actions.edittags]
fd5e2ead
SL
155 ).then(function(modal) {
156 // All of this code only executes once, when the modal is
157 // first created. This allows us to add any code that should
158 // only be run once, such as adding event handlers to the modal.
159 Str.get_string('questiontags', 'question')
160 .then(function(string) {
161 modal.setTitle(string);
162 return string;
163 })
164 .fail(Notification.exception);
165
166 modal.getRoot().on(ModalEvents.save, function(e) {
167 var form = modal.getBody().find('form');
168 form.submit();
169 e.preventDefault();
170 });
171
172 modal.getRoot().on('submit', 'form', function(e) {
173 save(modal, root).then(function() {
174 modal.hide();
c91da280 175 location.reload();
fd5e2ead
SL
176 return;
177 }).fail(Notification.exception);
178
179 // Stop the form from actually submitting and prevent it's
180 // propagation because we have already handled the event.
181 e.preventDefault();
182 e.stopPropagation();
183 });
184
185 return modal;
186 });
187
188 // We need to add an event handler to the tags link because there are
189 // multiple links on the page and without adding a listener we don't know
190 // which one the user clicked on the show the modal.
d1db765a 191 root.on(CustomEvents.events.activate, QuestionSelectors.actions.edittags, function(e) {
fd5e2ead
SL
192 var currentTarget = $(e.currentTarget);
193
194 var questionId = currentTarget.data('questionid'),
e2795e86 195 canTag = !!currentTarget.data('cantag'),
fd5e2ead
SL
196 contextId = currentTarget.data('contextid');
197
198 // This code gets called each time the user clicks the tag link
199 // so we can use it to reload the contents of the tag modal.
200 modalPromise.then(function(modal) {
201 // Display spinner and disable save button.
202 disableSaveButton(root);
203 startLoading(root);
204
205 var args = {
206 id: questionId
207 };
208
209 var tagsFragment = Fragment.loadFragment('question', 'tags_form', contextId, args);
210 modal.setBody(tagsFragment);
211
212 tagsFragment.then(function() {
213 enableSaveButton(root);
214 return;
215 })
216 .always(function() {
217 // Always hide the loading spinner when the request
218 // has completed.
219 stopLoading(root);
220 return;
221 })
222 .fail(Notification.exception);
223
224 // Show or hide the save button depending on whether the user
225 // has the capability to edit the tags.
e2795e86 226 if (canTag) {
d1db765a 227 modal.getRoot().find(QuestionSelectors.actions.save).show();
fd5e2ead 228 } else {
d1db765a 229 modal.getRoot().find(QuestionSelectors.actions.save).hide();
fd5e2ead
SL
230 }
231
e6890b11
SL
232 setQuestionId(modal, questionId);
233 setContextId(modal, contextId);
234
fd5e2ead
SL
235 return modal;
236 }).fail(Notification.exception);
237
238 e.preventDefault();
239 });
240 };
241
242 /**
243 * Send the form data to the server to save question tags.
244 *
245 * @method save
246 * @param {object} modal The modal object.
247 * @param {object} root The container element.
248 * @return {object} A promise
249 */
250 var save = function(modal, root) {
251 // Display spinner and disable save button.
252 disableSaveButton(root);
253 startLoading(root);
254
255 var formData = getFormData(modal);
e6890b11
SL
256 var questionId = getQuestionId(modal);
257 var contextId = getContextId(modal);
fd5e2ead
SL
258
259 // Send the form data to the server for processing.
e6890b11 260 return Repository.submitTagCreateUpdateForm(questionId, contextId, formData)
fd5e2ead
SL
261 .always(function() {
262 // Regardless of success or error we should always stop
263 // the loading icon and re-enable the buttons.
264 stopLoading(root);
265 enableSaveButton(root);
266 return;
267 })
268 .fail(Notification.exception);
269 };
270
271 return {
272 init: function(root) {
1db23e81
SS
273 window.console.warn('warn: The core_question/repository has been deprecated.' +
274 'Please use qbank_tagquestion/repository instead.');
fd5e2ead
SL
275 root = $(root);
276 registerEventListeners(root);
277 }
278 };
279});