weekly release 4.0dev
[moodle.git] / mod / forum / amd / src / inpage_reply.js
CommitLineData
9b4f09ba
P
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/**
902c8f58 17 * This module handles the in page replying to forum posts.
9b4f09ba 18 *
902c8f58 19 * @module mod_forum/inpage_reply
9b4f09ba
P
20 * @copyright 2019 Peter Dias
21 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
22 */
23define([
24 'jquery',
25 'core/templates',
26 'core/notification',
27 'mod_forum/repository',
28 'mod_forum/selectors',
29 ], function(
30 $,
31 Templates,
32 Notification,
33 Repository,
34 Selectors
35 ) {
36
37 var DISPLAYCONSTANTS = {
2602c7bf 38 NESTED_V2: 4,
9b4f09ba
P
39 THREADED: 2,
40 NESTED: 3,
41 FLAT_OLDEST_FIRST: 1,
42 FLAT_NEWEST_FIRST: -1
43 };
44
7902e4dc
RW
45 var EVENTS = {
46 POST_CREATED: 'mod_forum-post-created'
47 };
48
88f6ca6c
SA
49 /**
50 * Moodle formats taken from the FORMAT_* constants declared in lib/weblib.php.
51 * @type {Object}
52 */
53 var CONTENT_FORMATS = {
54 MOODLE: 0
55 };
902c8f58
RW
56 /**
57 * Show the loading icon for the submit button.
58 *
59 * @param {Object} button The submit button element
60 */
61 var showSubmitButtonLoadingIcon = function(button) {
62 var textContainer = button.find(Selectors.post.inpageSubmitBtnText);
63 var loadingIconContainer = button.find(Selectors.post.loadingIconContainer);
64 var width = button.outerWidth();
65 // Fix the width so that the button size doesn't change when we show the loading icon.
66 button.css('width', width);
67 textContainer.addClass('hidden');
68 loadingIconContainer.removeClass('hidden');
69 };
70
71 /**
72 * Hide the loading icon for the submit button.
73 *
74 * @param {Object} button The submit button element
75 */
76 var hideSubmitButtonLoadingIcon = function(button) {
77 var textContainer = button.find(Selectors.post.inpageSubmitBtnText);
78 var loadingIconContainer = button.find(Selectors.post.loadingIconContainer);
79 // Reset the width back to it's default.
80 button.css('width', '');
81 textContainer.removeClass('hidden');
82 loadingIconContainer.addClass('hidden');
83 };
84
85 /**
86 * Register the event listeners for the submit button of the in page reply.
87 *
88 * @param {Object} root The discussion container element.
89 */
9b4f09ba
P
90 var registerEventListeners = function(root) {
91 root.on('click', Selectors.post.inpageSubmitBtn, function(e) {
92 e.preventDefault();
902c8f58
RW
93 var submitButton = $(e.currentTarget);
94 var allButtons = submitButton.parent().find(Selectors.post.inpageReplyButton);
95 var form = submitButton.parents(Selectors.post.inpageReplyForm).get(0);
a0c9b6af 96 var message = form.elements.post.value.trim();
88f6ca6c
SA
97 // For now, we consider the inline reply post written using the FORMAT_MOODLE (because a textarea is displayed).
98 // In the future, other formats should be supported, letting users to use their preferred editor and format.
99 var messageformat = CONTENT_FORMATS.MOODLE;
100 // The message post will be converted from messageformat to FORMAT_HTML.
117e4bd4 101 var topreferredformat = true;
9b4f09ba
P
102 var postid = form.elements.reply.value;
103 var subject = form.elements.subject.value;
38d96b65 104 var currentRoot = submitButton.closest(Selectors.post.post);
cee572aa 105 var isprivatereply = form.elements.privatereply != undefined ? form.elements.privatereply.checked : false;
38d96b65
RW
106 var modeSelector = root.find(Selectors.post.modeSelect);
107 var mode = modeSelector.length ? parseInt(modeSelector.get(0).value) : null;
9b4f09ba
P
108 var newid;
109
a0c9b6af 110 if (message.length) {
902c8f58
RW
111 showSubmitButtonLoadingIcon(submitButton);
112 allButtons.prop('disabled', true);
113
117e4bd4 114 Repository.addDiscussionPost(postid, subject, message, messageformat, isprivatereply, topreferredformat)
a0c9b6af
P
115 .then(function(context) {
116 var message = context.messages.reduce(function(carry, message) {
117 if (message.type == 'success') {
118 carry += '<p>' + message.message + '</p>';
119 }
120 return carry;
121 }, '');
122 Notification.addNotification({
123 message: message,
124 type: "success"
125 });
9b4f09ba 126
a0c9b6af
P
127 return context;
128 })
129 .then(function(context) {
130 form.reset();
131 var post = context.post;
132 newid = post.id;
38d96b65 133
a0c9b6af 134 switch (mode) {
2602c7bf 135 case DISPLAYCONSTANTS.NESTED_V2:
38d96b65 136 var capabilities = post.capabilities;
1aac58b2
RW
137 var currentAuthorName = currentRoot.children()
138 .not(Selectors.post.repliesContainer)
139 .find(Selectors.post.authorName)
140 .text();
141 post.parentauthorname = currentAuthorName;
142 post.showactionmenu = capabilities.view ||
143 capabilities.controlreadstatus ||
38d96b65
RW
144 capabilities.edit ||
145 capabilities.split ||
146 capabilities.delete ||
147 capabilities.export ||
148 post.urls.viewparent;
2602c7bf 149 return Templates.render('mod_forum/forum_discussion_nested_v2_post_reply', post);
a0c9b6af
P
150 case DISPLAYCONSTANTS.THREADED:
151 return Templates.render('mod_forum/forum_discussion_threaded_post', post);
152 case DISPLAYCONSTANTS.NESTED:
153 return Templates.render('mod_forum/forum_discussion_nested_post', post);
154 default:
155 return Templates.render('mod_forum/forum_discussion_post', post);
156 }
157 })
158 .then(function(html, js) {
38d96b65 159 var repliesnode = currentRoot.find(Selectors.post.repliesContainer).first();
a0c9b6af
P
160
161 if (mode == DISPLAYCONSTANTS.FLAT_NEWEST_FIRST) {
162 return Templates.prependNodeContents(repliesnode, html, js);
163 } else {
164 return Templates.appendNodeContents(repliesnode, html, js);
165 }
166 })
167 .then(function() {
7902e4dc 168 submitButton.trigger(EVENTS.POST_CREATED, newid);
902c8f58
RW
169 hideSubmitButtonLoadingIcon(submitButton);
170 allButtons.prop('disabled', false);
bdfe918b
PH
171
172 // Tell formchangechecker we submitted the form.
173 if (typeof M.core_formchangechecker !== 'undefined') {
174 M.core_formchangechecker.reset_form_dirty_state();
175 }
176
a0c9b6af
P
177 return currentRoot.find(Selectors.post.inpageReplyContent).hide();
178 })
179 .then(function() {
180 location.href = "#p" + newid;
181 return;
182 })
902c8f58
RW
183 .catch(function(error) {
184 hideSubmitButtonLoadingIcon(submitButton);
185 allButtons.prop('disabled', false);
186 return Notification.exception(error);
187 });
a0c9b6af 188 }
9b4f09ba
P
189 });
190 };
191
192 return {
193 init: function(root) {
194 registerEventListeners(root);
88f6ca6c 195 },
7902e4dc
RW
196 CONTENT_FORMATS: CONTENT_FORMATS,
197 EVENTS: EVENTS
9b4f09ba
P
198 };
199});