diff --git a/mod/forum/amd/build/discussion_modern.min.js b/mod/forum/amd/build/discussion_modern.min.js index 00c1fd6513c..294fa113641 100644 --- a/mod/forum/amd/build/discussion_modern.min.js +++ b/mod/forum/amd/build/discussion_modern.min.js @@ -1,2 +1,2 @@ -define ("mod_forum/discussion_modern",["exports","jquery","mod_forum/discussion","mod_forum/lock_toggle","mod_forum/favourite_toggle","mod_forum/pin_toggle"],function(a,b,c,d,e,f){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=g(b);c=g(c);d=g(d);e=g(e);f=g(f);function g(a){return a&&a.__esModule?a:{default:a}}var h=function(a){c.default.init(a);var g=(0,b.default)("[data-container=\"discussion-tools\"]");d.default.init(g);e.default.init(g);f.default.init(g)};a.init=h}); +define ("mod_forum/discussion_modern",["exports","jquery","core/auto_rows","core/custom_interaction_events","core/notification","core/templates","mod_forum/discussion","mod_forum/inpage_reply","mod_forum/lock_toggle","mod_forum/favourite_toggle","mod_forum/pin_toggle","mod_forum/selectors"],function(a,b,c,d,f,g,h,i,j,k,l,m){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.init=void 0;b=n(b);c=n(c);d=n(d);f=n(f);g=n(g);h=n(h);i=n(i);j=n(j);k=n(k);l=n(l);m=n(m);function n(a){return a&&a.__esModule?a:{default:a}}function o(a,b,c,d,e,f,g){try{var h=a[f](g),i=h.value}catch(a){c(a);return}if(h.done){b(i)}else{Promise.resolve(i).then(d,e)}}function p(a){return function(){var b=this,c=arguments;return new Promise(function(d,e){var h=a.apply(b,c);function f(a){o(h,d,e,f,g,"next",a)}function g(a){o(h,d,e,f,g,"throw",a)}f(void 0)})}}function q(a){for(var b=1;b.\n\n/**\n * Module for viewing a discussion.\n *\n * @module mod_forum/discussion_new\n * @package mod_forum\n * @copyright 2019 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport $ from 'jquery';\nimport Discussion from 'mod_forum/discussion';\nimport LockToggle from 'mod_forum/lock_toggle';\nimport FavouriteToggle from 'mod_forum/favourite_toggle';\nimport Pin from 'mod_forum/pin_toggle';\n\nexport const init = (root) => {\n Discussion.init(root);\n\n var discussionToolsContainer = $('[data-container=\"discussion-tools\"]');\n LockToggle.init(discussionToolsContainer);\n FavouriteToggle.init(discussionToolsContainer);\n Pin.init(discussionToolsContainer);\n};\n"],"file":"discussion_modern.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/discussion_modern.js"],"names":["getPostContainer","element","closest","Selectors","post","getPostContentContainer","postContainer","children","not","repliesContainer","find","forumCoreContent","getInPageReplyContainer","filter","inpageReplyContainer","showInPageReplyForm","inPageReplyContainer","afterAnimationCallback","form","inpageReplyContent","slideDown","duration","queue","complete","css","fadeIn","hideInPageReplyForm","slideUp","fadeOut","hasInPageReplyForm","length","renderInPageReplyTemplate","additionalTemplateContext","button","postContentContainer","currentSubject","forumSubject","text","currentAuthorName","authorName","context","postid","data","attr","sesskey","M","cfg","parentsubject","parentauthorname","canreplyprivately","postformat","InPageReply","CONTENT_FORMATS","MOODLE","Templates","render","registerEventListeners","root","CustomEvents","define","events","activate","AutoRows","init","on","inpageReplyCreateButton","e","originalEvent","preventDefault","currentTarget","html","appendNodeContents","Notification","exception","focus","inpageReplyCancelButton","inPageReplyCreateButton","Discussion","discussionToolsContainer","LockToggle","FavouriteToggle","Pin"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Module for viewing a discussion in modern view.\n *\n * @copyright 2019 Ryan Wyllie \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport $ from 'jquery';\nimport AutoRows from 'core/auto_rows';\nimport CustomEvents from 'core/custom_interaction_events';\nimport Notification from 'core/notification';\nimport Templates from 'core/templates';\nimport Discussion from 'mod_forum/discussion';\nimport InPageReply from 'mod_forum/inpage_reply';\nimport LockToggle from 'mod_forum/lock_toggle';\nimport FavouriteToggle from 'mod_forum/favourite_toggle';\nimport Pin from 'mod_forum/pin_toggle';\nimport Selectors from 'mod_forum/selectors';\n\nconst ANIMATION_DURATION = 150;\n\n/**\n * Get the closest post container element from the given element.\n *\n * @param {Object} element jQuery element to search from\n * @return {Object} jQuery element\n */\nconst getPostContainer = (element) => {\n return element.closest(Selectors.post.post);\n};\n\n/**\n * Get the post content container element from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getPostContentContainer = (postContainer) => {\n return postContainer.children().not(Selectors.post.repliesContainer).find(Selectors.post.forumCoreContent);\n};\n\n/**\n * Get the in page reply container element from the post container element.\n *\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery element\n */\nconst getInPageReplyContainer = (postContainer) => {\n return postContainer.children().filter(Selectors.post.inpageReplyContainer);\n};\n\n/**\n * Show the in page reply form in the given in page reply container. The form\n * display will be animated.\n *\n * @param {Object} inPageReplyContainer jQuery element for the in page reply container\n * @param {Function} afterAnimationCallback Callback after animation completes\n */\nconst showInPageReplyForm = (inPageReplyContainer, afterAnimationCallback) => {\n const form = inPageReplyContainer.find(Selectors.post.inpageReplyContent);\n\n form.slideDown({\n duration: ANIMATION_DURATION,\n queue: false,\n complete: afterAnimationCallback\n }).css('display', 'none').fadeIn(ANIMATION_DURATION);\n};\n\n/**\n * Hide the in page reply form in the given in page reply container. The form\n * display will be animated.\n *\n * @param {Object} inPageReplyContainer jQuery element for the in page reply container\n * @param {Function} afterAnimationCallback Callback after animation completes\n */\nconst hideInPageReplyForm = (inPageReplyContainer, afterAnimationCallback) => {\n const form = inPageReplyContainer.find(Selectors.post.inpageReplyContent);\n\n form.slideUp({\n duration: ANIMATION_DURATION,\n queue: false,\n complete: afterAnimationCallback\n }).fadeOut(200);\n};\n\n/**\n * Check if the in page reply container contains the in page reply form.\n *\n * @param {Object} inPageReplyContainer jQuery element for the in page reply container\n * @return {Bool}\n */\nconst hasInPageReplyForm = (inPageReplyContainer) => {\n return inPageReplyContainer.find(Selectors.post.inpageReplyContent).length > 0;\n};\n\n/**\n * Render the template to generate the in page reply form HTML.\n *\n * @param {Object} additionalTemplateContext Additional render context for the in page reply template\n * @param {Object} button jQuery element for the reply button that was clicked\n * @param {Object} postContainer jQuery element for the post container\n * @return {Object} jQuery promise\n */\nconst renderInPageReplyTemplate = (additionalTemplateContext, button, postContainer) => {\n const postContentContainer = getPostContentContainer(postContainer);\n const currentSubject = postContentContainer.find(Selectors.post.forumSubject).text();\n const currentAuthorName = postContentContainer.find(Selectors.post.authorName).text();\n const context = {\n postid: postContainer.data('post-id'),\n \"reply_url\": button.attr('data-href'),\n sesskey: M.cfg.sesskey,\n parentsubject: currentSubject,\n parentauthorname: currentAuthorName,\n canreplyprivately: button.data('can-reply-privately'),\n postformat: InPageReply.CONTENT_FORMATS.MOODLE,\n ...additionalTemplateContext\n };\n\n return Templates.render('mod_forum/inpage_reply_modern', context);\n};\n\n/**\n * Create all of the event listeners for the discussion.\n *\n * @param {Object} root jQuery element for the discussion container\n * @param {Object} additionalTemplateContext Additional render context for the in page reply template\n */\nconst registerEventListeners = (root, additionalTemplateContext) => {\n CustomEvents.define(root, [CustomEvents.events.activate]);\n // Auto expanding text area for in page reply.\n AutoRows.init(root);\n\n // Reply button is clicked.\n root.on(CustomEvents.events.activate, Selectors.post.inpageReplyCreateButton, async (e, data) => {\n data.originalEvent.preventDefault();\n\n const button = $(e.currentTarget);\n const postContainer = getPostContainer(button);\n const inPageReplyContainer = getInPageReplyContainer(postContainer);\n\n if (!hasInPageReplyForm(inPageReplyContainer)) {\n try {\n const html = await renderInPageReplyTemplate(additionalTemplateContext, button, postContainer);\n Templates.appendNodeContents(inPageReplyContainer, html, '');\n } catch (e) {\n Notification.exception(e);\n }\n }\n\n button.fadeOut(ANIMATION_DURATION, () => {\n showInPageReplyForm(inPageReplyContainer, () => {\n inPageReplyContainer.find(Selectors.post.inpageReplyContent).find('textarea').focus();\n });\n });\n });\n\n // Cancel in page reply button.\n root.on(CustomEvents.events.activate, Selectors.post.inpageReplyCancelButton, (e, data) => {\n data.originalEvent.preventDefault();\n\n const button = $(e.currentTarget);\n const postContainer = getPostContainer(button);\n const postContentContainer = getPostContentContainer(postContainer);\n const inPageReplyContainer = getInPageReplyContainer(postContainer);\n const inPageReplyCreateButton = postContentContainer.find(Selectors.post.inpageReplyCreateButton);\n hideInPageReplyForm(inPageReplyContainer, () => {\n inPageReplyCreateButton.fadeIn(ANIMATION_DURATION);\n });\n });\n};\n\n/**\n * Initialise the javascript for the discussion in modern display mode.\n *\n * @param {Object} root jQuery element for the discussion container\n * @param {Object} context Additional render context for the in page reply template\n */\nexport const init = (root, context) => {\n // Add discussion event listeners.\n registerEventListeners(root, context);\n // Add default discussion javascript (keyboard nav etc).\n Discussion.init(root);\n // Add in page reply javascript.\n InPageReply.init(root);\n\n // Initialise the settings menu javascript.\n const discussionToolsContainer = root.find('[data-container=\"discussion-tools\"]');\n LockToggle.init(discussionToolsContainer);\n FavouriteToggle.init(discussionToolsContainer);\n Pin.init(discussionToolsContainer);\n};\n"],"file":"discussion_modern.min.js"} \ No newline at end of file diff --git a/mod/forum/amd/build/inpage_reply.min.js b/mod/forum/amd/build/inpage_reply.min.js index dd77ba3f24c..25220460da6 100644 --- a/mod/forum/amd/build/inpage_reply.min.js +++ b/mod/forum/amd/build/inpage_reply.min.js @@ -1,2 +1,2 @@ -define ("mod_forum/inpage_reply",["jquery","core/templates","core/notification","mod_forum/repository","mod_forum/selectors"],function(a,b,c,d,f){var g={THREADED:2,NESTED:3,FLAT_OLDEST_FIRST:1,FLAT_NEWEST_FIRST:-1},h={MOODLE:0},i=function(a){var b=a.find(f.post.inpageSubmitBtnText),c=a.find(f.post.loadingIconContainer),d=a.outerWidth();a.css("width",d);b.addClass("hidden");c.removeClass("hidden")},j=function(a){var b=a.find(f.post.inpageSubmitBtnText),c=a.find(f.post.loadingIconContainer);a.css("width","");b.removeClass("hidden");c.addClass("hidden")},k=function(k){k.on("click",f.post.inpageSubmitBtn,function(l){l.preventDefault();var e=a(l.currentTarget),m=e.parent().find(f.post.inpageReplyButton),n=e.parents(f.post.inpageReplyForm).get(0),o=n.elements.post.value.trim(),p=h.MOODLE,q=n.elements.reply.value,r=n.elements.subject.value,s=e.parents(f.post.forumContent),t=n.elements.privatereply!=void 0?n.elements.privatereply.checked:!1,u=parseInt(k.find(f.post.modeSelect).get(0).value),v;if(o.length){i(e);m.prop("disabled",!0);d.addDiscussionPost(q,r,o,p,t,!0).then(function(a){var b=a.messages.reduce(function(a,b){if("success"==b.type){a+="

"+b.message+"

"}return a},"");c.addNotification({message:b,type:"success"});return a}).then(function(a){n.reset();var c=a.post;v=c.id;switch(u){case g.THREADED:return b.render("mod_forum/forum_discussion_threaded_post",c);case g.NESTED:return b.render("mod_forum/forum_discussion_nested_post",c);default:return b.render("mod_forum/forum_discussion_post",c);}}).then(function(a,c){var d;if(u==g.FLAT_OLDEST_FIRST||u==g.FLAT_NEWEST_FIRST){d=s.parents(f.post.repliesContainer).children().get(0)}if(d==void 0){d=s.siblings(f.post.repliesContainer).children().get(0)}if(u==g.FLAT_NEWEST_FIRST){return b.prependNodeContents(d,a,c)}else{return b.appendNodeContents(d,a,c)}}).then(function(){j(e);m.prop("disabled",!1);return s.find(f.post.inpageReplyContent).hide()}).then(function(){location.href="#p"+v}).catch(function(a){j(e);m.prop("disabled",!1);return c.exception(a)})}})};return{init:function init(a){k(a)},CONTENT_FORMATS:h}}); +define ("mod_forum/inpage_reply",["jquery","core/templates","core/notification","mod_forum/repository","mod_forum/selectors"],function(a,b,c,d,f){var g={MODERN:4,THREADED:2,NESTED:3,FLAT_OLDEST_FIRST:1,FLAT_NEWEST_FIRST:-1},h={MOODLE:0},i=function(a){var b=a.find(f.post.inpageSubmitBtnText),c=a.find(f.post.loadingIconContainer),d=a.outerWidth();a.css("width",d);b.addClass("hidden");c.removeClass("hidden")},j=function(a){var b=a.find(f.post.inpageSubmitBtnText),c=a.find(f.post.loadingIconContainer);a.css("width","");b.removeClass("hidden");c.addClass("hidden")},k=function(k){k.on("click",f.post.inpageSubmitBtn,function(l){l.preventDefault();var e=a(l.currentTarget),m=e.parent().find(f.post.inpageReplyButton),n=e.parents(f.post.inpageReplyForm).get(0),o=n.elements.post.value.trim(),p=h.MOODLE,q=n.elements.reply.value,r=n.elements.subject.value,s=e.closest(f.post.post),t=n.elements.privatereply!=void 0?n.elements.privatereply.checked:!1,u=k.find(f.post.modeSelect),v=u.length?parseInt(u.get(0).value):null,w;if(o.length){i(e);m.prop("disabled",!0);d.addDiscussionPost(q,r,o,p,t,!0).then(function(a){var b=a.messages.reduce(function(a,b){if("success"==b.type){a+="

"+b.message+"

"}return a},"");c.addNotification({message:b,type:"success"});return a}).then(function(a){n.reset();var c=a.post;w=c.id;switch(v){case g.MODERN:var d=c.capabilities;c.showactionmenu=d.controlreadstatus||d.edit||d.split||d.delete||d.export||c.urls.viewparent;return b.render("mod_forum/forum_discussion_modern_post_reply",c);case g.THREADED:return b.render("mod_forum/forum_discussion_threaded_post",c);case g.NESTED:return b.render("mod_forum/forum_discussion_nested_post",c);default:return b.render("mod_forum/forum_discussion_post",c);}}).then(function(a,c){var d=s.find(f.post.repliesContainer).first();if(v==g.FLAT_NEWEST_FIRST){return b.prependNodeContents(d,a,c)}else{return b.appendNodeContents(d,a,c)}}).then(function(){j(e);m.prop("disabled",!1);return s.find(f.post.inpageReplyContent).hide()}).then(function(){location.href="#p"+w}).catch(function(a){j(e);m.prop("disabled",!1);return c.exception(a)})}})};return{init:function init(a){k(a)},CONTENT_FORMATS:h}}); //# sourceMappingURL=inpage_reply.min.js.map diff --git a/mod/forum/amd/build/inpage_reply.min.js.map b/mod/forum/amd/build/inpage_reply.min.js.map index 74436752025..a5ea0044d45 100644 --- a/mod/forum/amd/build/inpage_reply.min.js.map +++ b/mod/forum/amd/build/inpage_reply.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/inpage_reply.js"],"names":["define","$","Templates","Notification","Repository","Selectors","DISPLAYCONSTANTS","THREADED","NESTED","FLAT_OLDEST_FIRST","FLAT_NEWEST_FIRST","CONTENT_FORMATS","MOODLE","showSubmitButtonLoadingIcon","button","textContainer","find","post","inpageSubmitBtnText","loadingIconContainer","width","outerWidth","css","addClass","removeClass","hideSubmitButtonLoadingIcon","registerEventListeners","root","on","inpageSubmitBtn","e","preventDefault","submitButton","currentTarget","allButtons","parent","inpageReplyButton","form","parents","inpageReplyForm","get","message","elements","value","trim","messageformat","postid","reply","subject","currentRoot","forumContent","isprivatereply","privatereply","checked","mode","parseInt","modeSelect","newid","length","prop","addDiscussionPost","then","context","messages","reduce","carry","type","addNotification","reset","id","render","html","js","repliesnode","repliesContainer","children","siblings","prependNodeContents","appendNodeContents","inpageReplyContent","hide","location","href","catch","error","exception","init"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * This module handles the in page replying to forum posts.\n *\n * @module mod_forum/inpage_reply\n * @package mod_forum\n * @copyright 2019 Peter Dias\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/templates',\n 'core/notification',\n 'mod_forum/repository',\n 'mod_forum/selectors',\n ], function(\n $,\n Templates,\n Notification,\n Repository,\n Selectors\n ) {\n\n var DISPLAYCONSTANTS = {\n THREADED: 2,\n NESTED: 3,\n FLAT_OLDEST_FIRST: 1,\n FLAT_NEWEST_FIRST: -1\n };\n\n /**\n * Moodle formats taken from the FORMAT_* constants declared in lib/weblib.php.\n * @type {Object}\n */\n var CONTENT_FORMATS = {\n MOODLE: 0\n };\n /**\n * Show the loading icon for the submit button.\n *\n * @param {Object} button The submit button element\n */\n var showSubmitButtonLoadingIcon = function(button) {\n var textContainer = button.find(Selectors.post.inpageSubmitBtnText);\n var loadingIconContainer = button.find(Selectors.post.loadingIconContainer);\n var width = button.outerWidth();\n // Fix the width so that the button size doesn't change when we show the loading icon.\n button.css('width', width);\n textContainer.addClass('hidden');\n loadingIconContainer.removeClass('hidden');\n };\n\n /**\n * Hide the loading icon for the submit button.\n *\n * @param {Object} button The submit button element\n */\n var hideSubmitButtonLoadingIcon = function(button) {\n var textContainer = button.find(Selectors.post.inpageSubmitBtnText);\n var loadingIconContainer = button.find(Selectors.post.loadingIconContainer);\n // Reset the width back to it's default.\n button.css('width', '');\n textContainer.removeClass('hidden');\n loadingIconContainer.addClass('hidden');\n };\n\n /**\n * Register the event listeners for the submit button of the in page reply.\n *\n * @param {Object} root The discussion container element.\n */\n var registerEventListeners = function(root) {\n root.on('click', Selectors.post.inpageSubmitBtn, function(e) {\n e.preventDefault();\n var submitButton = $(e.currentTarget);\n var allButtons = submitButton.parent().find(Selectors.post.inpageReplyButton);\n var form = submitButton.parents(Selectors.post.inpageReplyForm).get(0);\n var message = form.elements.post.value.trim();\n // For now, we consider the inline reply post written using the FORMAT_MOODLE (because a textarea is displayed).\n // In the future, other formats should be supported, letting users to use their preferred editor and format.\n var messageformat = CONTENT_FORMATS.MOODLE;\n // The message post will be converted from messageformat to FORMAT_HTML.\n var topreferredformat = true;\n var postid = form.elements.reply.value;\n var subject = form.elements.subject.value;\n var currentRoot = submitButton.parents(Selectors.post.forumContent);\n var isprivatereply = form.elements.privatereply != undefined ? form.elements.privatereply.checked : false;\n var mode = parseInt(root.find(Selectors.post.modeSelect).get(0).value);\n var newid;\n\n if (message.length) {\n showSubmitButtonLoadingIcon(submitButton);\n allButtons.prop('disabled', true);\n\n Repository.addDiscussionPost(postid, subject, message, messageformat, isprivatereply, topreferredformat)\n .then(function(context) {\n var message = context.messages.reduce(function(carry, message) {\n if (message.type == 'success') {\n carry += '

' + message.message + '

';\n }\n return carry;\n }, '');\n Notification.addNotification({\n message: message,\n type: \"success\"\n });\n\n return context;\n })\n .then(function(context) {\n form.reset();\n var post = context.post;\n newid = post.id;\n switch (mode) {\n case DISPLAYCONSTANTS.THREADED:\n return Templates.render('mod_forum/forum_discussion_threaded_post', post);\n case DISPLAYCONSTANTS.NESTED:\n return Templates.render('mod_forum/forum_discussion_nested_post', post);\n default:\n return Templates.render('mod_forum/forum_discussion_post', post);\n }\n })\n .then(function(html, js) {\n var repliesnode;\n\n // Try and get the replies-container which can either be a sibling OR parent if it's flat\n if (mode == DISPLAYCONSTANTS.FLAT_OLDEST_FIRST || mode == DISPLAYCONSTANTS.FLAT_NEWEST_FIRST) {\n repliesnode = currentRoot.parents(Selectors.post.repliesContainer).children().get(0);\n }\n\n if (repliesnode == undefined) {\n repliesnode = currentRoot.siblings(Selectors.post.repliesContainer).children().get(0);\n }\n\n if (mode == DISPLAYCONSTANTS.FLAT_NEWEST_FIRST) {\n return Templates.prependNodeContents(repliesnode, html, js);\n } else {\n return Templates.appendNodeContents(repliesnode, html, js);\n }\n })\n .then(function() {\n hideSubmitButtonLoadingIcon(submitButton);\n allButtons.prop('disabled', false);\n return currentRoot.find(Selectors.post.inpageReplyContent).hide();\n })\n .then(function() {\n location.href = \"#p\" + newid;\n return;\n })\n .catch(function(error) {\n hideSubmitButtonLoadingIcon(submitButton);\n allButtons.prop('disabled', false);\n return Notification.exception(error);\n });\n }\n });\n };\n\n return {\n init: function(root) {\n registerEventListeners(root);\n },\n CONTENT_FORMATS: CONTENT_FORMATS\n };\n});\n"],"file":"inpage_reply.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/inpage_reply.js"],"names":["define","$","Templates","Notification","Repository","Selectors","DISPLAYCONSTANTS","MODERN","THREADED","NESTED","FLAT_OLDEST_FIRST","FLAT_NEWEST_FIRST","CONTENT_FORMATS","MOODLE","showSubmitButtonLoadingIcon","button","textContainer","find","post","inpageSubmitBtnText","loadingIconContainer","width","outerWidth","css","addClass","removeClass","hideSubmitButtonLoadingIcon","registerEventListeners","root","on","inpageSubmitBtn","e","preventDefault","submitButton","currentTarget","allButtons","parent","inpageReplyButton","form","parents","inpageReplyForm","get","message","elements","value","trim","messageformat","postid","reply","subject","currentRoot","closest","isprivatereply","privatereply","checked","modeSelector","modeSelect","mode","length","parseInt","newid","prop","addDiscussionPost","then","context","messages","reduce","carry","type","addNotification","reset","id","capabilities","showactionmenu","controlreadstatus","edit","split","delete","export","urls","viewparent","render","html","js","repliesnode","repliesContainer","first","prependNodeContents","appendNodeContents","inpageReplyContent","hide","location","href","catch","error","exception","init"],"mappings":"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","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * This module handles the in page replying to forum posts.\n *\n * @module mod_forum/inpage_reply\n * @package mod_forum\n * @copyright 2019 Peter Dias\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([\n 'jquery',\n 'core/templates',\n 'core/notification',\n 'mod_forum/repository',\n 'mod_forum/selectors',\n ], function(\n $,\n Templates,\n Notification,\n Repository,\n Selectors\n ) {\n\n var DISPLAYCONSTANTS = {\n MODERN: 4,\n THREADED: 2,\n NESTED: 3,\n FLAT_OLDEST_FIRST: 1,\n FLAT_NEWEST_FIRST: -1\n };\n\n /**\n * Moodle formats taken from the FORMAT_* constants declared in lib/weblib.php.\n * @type {Object}\n */\n var CONTENT_FORMATS = {\n MOODLE: 0\n };\n /**\n * Show the loading icon for the submit button.\n *\n * @param {Object} button The submit button element\n */\n var showSubmitButtonLoadingIcon = function(button) {\n var textContainer = button.find(Selectors.post.inpageSubmitBtnText);\n var loadingIconContainer = button.find(Selectors.post.loadingIconContainer);\n var width = button.outerWidth();\n // Fix the width so that the button size doesn't change when we show the loading icon.\n button.css('width', width);\n textContainer.addClass('hidden');\n loadingIconContainer.removeClass('hidden');\n };\n\n /**\n * Hide the loading icon for the submit button.\n *\n * @param {Object} button The submit button element\n */\n var hideSubmitButtonLoadingIcon = function(button) {\n var textContainer = button.find(Selectors.post.inpageSubmitBtnText);\n var loadingIconContainer = button.find(Selectors.post.loadingIconContainer);\n // Reset the width back to it's default.\n button.css('width', '');\n textContainer.removeClass('hidden');\n loadingIconContainer.addClass('hidden');\n };\n\n /**\n * Register the event listeners for the submit button of the in page reply.\n *\n * @param {Object} root The discussion container element.\n */\n var registerEventListeners = function(root) {\n root.on('click', Selectors.post.inpageSubmitBtn, function(e) {\n e.preventDefault();\n var submitButton = $(e.currentTarget);\n var allButtons = submitButton.parent().find(Selectors.post.inpageReplyButton);\n var form = submitButton.parents(Selectors.post.inpageReplyForm).get(0);\n var message = form.elements.post.value.trim();\n // For now, we consider the inline reply post written using the FORMAT_MOODLE (because a textarea is displayed).\n // In the future, other formats should be supported, letting users to use their preferred editor and format.\n var messageformat = CONTENT_FORMATS.MOODLE;\n // The message post will be converted from messageformat to FORMAT_HTML.\n var topreferredformat = true;\n var postid = form.elements.reply.value;\n var subject = form.elements.subject.value;\n var currentRoot = submitButton.closest(Selectors.post.post);\n var isprivatereply = form.elements.privatereply != undefined ? form.elements.privatereply.checked : false;\n var modeSelector = root.find(Selectors.post.modeSelect);\n var mode = modeSelector.length ? parseInt(modeSelector.get(0).value) : null;\n var newid;\n\n if (message.length) {\n showSubmitButtonLoadingIcon(submitButton);\n allButtons.prop('disabled', true);\n\n Repository.addDiscussionPost(postid, subject, message, messageformat, isprivatereply, topreferredformat)\n .then(function(context) {\n var message = context.messages.reduce(function(carry, message) {\n if (message.type == 'success') {\n carry += '

' + message.message + '

';\n }\n return carry;\n }, '');\n Notification.addNotification({\n message: message,\n type: \"success\"\n });\n\n return context;\n })\n .then(function(context) {\n form.reset();\n var post = context.post;\n newid = post.id;\n\n switch (mode) {\n case DISPLAYCONSTANTS.MODERN:\n var capabilities = post.capabilities;\n post.showactionmenu = capabilities.controlreadstatus ||\n capabilities.edit ||\n capabilities.split ||\n capabilities.delete ||\n capabilities.export ||\n post.urls.viewparent;\n return Templates.render('mod_forum/forum_discussion_modern_post_reply', post);\n case DISPLAYCONSTANTS.THREADED:\n return Templates.render('mod_forum/forum_discussion_threaded_post', post);\n case DISPLAYCONSTANTS.NESTED:\n return Templates.render('mod_forum/forum_discussion_nested_post', post);\n default:\n return Templates.render('mod_forum/forum_discussion_post', post);\n }\n })\n .then(function(html, js) {\n var repliesnode = currentRoot.find(Selectors.post.repliesContainer).first();\n\n if (mode == DISPLAYCONSTANTS.FLAT_NEWEST_FIRST) {\n return Templates.prependNodeContents(repliesnode, html, js);\n } else {\n return Templates.appendNodeContents(repliesnode, html, js);\n }\n })\n .then(function() {\n hideSubmitButtonLoadingIcon(submitButton);\n allButtons.prop('disabled', false);\n return currentRoot.find(Selectors.post.inpageReplyContent).hide();\n })\n .then(function() {\n location.href = \"#p\" + newid;\n return;\n })\n .catch(function(error) {\n hideSubmitButtonLoadingIcon(submitButton);\n allButtons.prop('disabled', false);\n return Notification.exception(error);\n });\n }\n });\n };\n\n return {\n init: function(root) {\n registerEventListeners(root);\n },\n CONTENT_FORMATS: CONTENT_FORMATS\n };\n});\n"],"file":"inpage_reply.min.js"} \ No newline at end of file diff --git a/mod/forum/amd/build/selectors.min.js b/mod/forum/amd/build/selectors.min.js index 93b115305ef..777f585f8b8 100644 --- a/mod/forum/amd/build/selectors.min.js +++ b/mod/forum/amd/build/selectors.min.js @@ -1,2 +1,2 @@ -define ("mod_forum/selectors",[],function(){return{subscription:{toggle:"[data-type='subscription-toggle'][data-action='toggle']"},summary:{actions:"[data-container='discussion-summary-actions']"},post:{post:"[data-region=\"post\"]",action:"[data-region=\"post-action\"]",actionsContainer:"[data-region=\"post-actions-container\"]",forumCoreContent:"[data-region-content='forum-post-core']",forumContent:"[data-content='forum-post']",forumSubject:"[data-region-content='forum-post-core-subject']",inpageReplyButton:"button",inpageReplyLink:"[data-action='collapsible-link']",inpageReplyContent:"[data-content='inpage-reply-content']",inpageReplyForm:"form[data-content='inpage-reply-form']",inpageSubmitBtn:"[data-action='forum-inpage-submit']",inpageSubmitBtnText:"[data-region='submit-text']",loadingIconContainer:"[data-region='loading-icon-container']",repliesContainer:"[data-region='replies-container']",modeSelect:"select[name='mode']"},lock:{toggle:"[data-action='toggle'][data-type='lock-toggle']",icon:"[data-region='locked-icon']"},favourite:{toggle:"[data-type='favorite-toggle'][data-action='toggle']"},pin:{toggle:"[data-type='pin-toggle'][data-action='toggle']"}}}); +define ("mod_forum/selectors",[],function(){return{subscription:{toggle:"[data-type='subscription-toggle'][data-action='toggle']"},summary:{actions:"[data-container='discussion-summary-actions']"},post:{post:"[data-region=\"post\"]",action:"[data-region=\"post-action\"]",actionsContainer:"[data-region=\"post-actions-container\"]",authorName:"[data-region=\"author-name\"]",forumCoreContent:"[data-region-content='forum-post-core']",forumContent:"[data-content='forum-post']",forumSubject:"[data-region-content='forum-post-core-subject']",inpageReplyButton:"button",inpageReplyLink:"[data-action='collapsible-link']",inpageReplyCancelButton:"[data-action='cancel-inpage-reply']",inpageReplyCreateButton:"[data-action='create-inpage-reply']",inpageReplyContainer:"[data-region=\"inpage-reply-container\"]",inpageReplyContent:"[data-content='inpage-reply-content']",inpageReplyForm:"form[data-content='inpage-reply-form']",inpageSubmitBtn:"[data-action='forum-inpage-submit']",inpageSubmitBtnText:"[data-region='submit-text']",loadingIconContainer:"[data-region='loading-icon-container']",repliesContainer:"[data-region='replies-container']",modeSelect:"select[name='mode']"},lock:{toggle:"[data-action='toggle'][data-type='lock-toggle']",icon:"[data-region='locked-icon']"},favourite:{toggle:"[data-type='favorite-toggle'][data-action='toggle']"},pin:{toggle:"[data-type='pin-toggle'][data-action='toggle']"}}}); //# sourceMappingURL=selectors.min.js.map diff --git a/mod/forum/amd/build/selectors.min.js.map b/mod/forum/amd/build/selectors.min.js.map index e1d393c0d4c..89f36caf74c 100644 --- a/mod/forum/amd/build/selectors.min.js.map +++ b/mod/forum/amd/build/selectors.min.js.map @@ -1 +1 @@ -{"version":3,"sources":["../src/selectors.js"],"names":["define","subscription","toggle","summary","actions","post","action","actionsContainer","forumCoreContent","forumContent","forumSubject","inpageReplyButton","inpageReplyLink","inpageReplyContent","inpageReplyForm","inpageSubmitBtn","inpageSubmitBtnText","loadingIconContainer","repliesContainer","modeSelect","lock","icon","favourite","pin"],"mappings":"AAuBAA,OAAM,uBAAC,EAAD,CAAK,UAAW,CAClB,MAAO,CACHC,YAAY,CAAE,CACVC,MAAM,CAAE,yDADE,CADX,CAIHC,OAAO,CAAE,CACLC,OAAO,CAAE,+CADJ,CAJN,CAOHC,IAAI,CAAE,CACFA,IAAI,CAAE,wBADJ,CAEFC,MAAM,CAAE,+BAFN,CAGFC,gBAAgB,CAAE,0CAHhB,CAIFC,gBAAgB,CAAE,yCAJhB,CAKFC,YAAY,CAAE,6BALZ,CAMFC,YAAY,CAAE,iDANZ,CAOFC,iBAAiB,CAAE,QAPjB,CAQFC,eAAe,CAAE,kCARf,CASFC,kBAAkB,CAAE,uCATlB,CAUFC,eAAe,CAAE,wCAVf,CAWFC,eAAe,CAAE,qCAXf,CAYFC,mBAAmB,CAAE,6BAZnB,CAaFC,oBAAoB,CAAE,wCAbpB,CAcFC,gBAAgB,CAAE,mCAdhB,CAeFC,UAAU,CAAE,qBAfV,CAPH,CAwBHC,IAAI,CAAE,CACFlB,MAAM,CAAE,iDADN,CAEFmB,IAAI,CAAE,6BAFJ,CAxBH,CA4BHC,SAAS,CAAE,CACPpB,MAAM,CAAE,qDADD,CA5BR,CA+BHqB,GAAG,CAAE,CACDrB,MAAM,CAAE,gDADP,CA/BF,CAmCV,CApCK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Common CSS selectors for the forum UI.\n *\n * @module mod_forum/selectors\n * @package mod_forum\n * @copyright 2019 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n subscription: {\n toggle: \"[data-type='subscription-toggle'][data-action='toggle']\",\n },\n summary: {\n actions: \"[data-container='discussion-summary-actions']\"\n },\n post: {\n post: '[data-region=\"post\"]',\n action: '[data-region=\"post-action\"]',\n actionsContainer: '[data-region=\"post-actions-container\"]',\n forumCoreContent: \"[data-region-content='forum-post-core']\",\n forumContent: \"[data-content='forum-post']\",\n forumSubject: \"[data-region-content='forum-post-core-subject']\",\n inpageReplyButton: \"button\",\n inpageReplyLink: \"[data-action='collapsible-link']\",\n inpageReplyContent: \"[data-content='inpage-reply-content']\",\n inpageReplyForm: \"form[data-content='inpage-reply-form']\",\n inpageSubmitBtn: \"[data-action='forum-inpage-submit']\",\n inpageSubmitBtnText: \"[data-region='submit-text']\",\n loadingIconContainer: \"[data-region='loading-icon-container']\",\n repliesContainer: \"[data-region='replies-container']\",\n modeSelect: \"select[name='mode']\"\n },\n lock: {\n toggle: \"[data-action='toggle'][data-type='lock-toggle']\",\n icon: \"[data-region='locked-icon']\"\n },\n favourite: {\n toggle: \"[data-type='favorite-toggle'][data-action='toggle']\",\n },\n pin: {\n toggle: \"[data-type='pin-toggle'][data-action='toggle']\",\n },\n };\n});\n"],"file":"selectors.min.js"} \ No newline at end of file +{"version":3,"sources":["../src/selectors.js"],"names":["define","subscription","toggle","summary","actions","post","action","actionsContainer","authorName","forumCoreContent","forumContent","forumSubject","inpageReplyButton","inpageReplyLink","inpageReplyCancelButton","inpageReplyCreateButton","inpageReplyContainer","inpageReplyContent","inpageReplyForm","inpageSubmitBtn","inpageSubmitBtnText","loadingIconContainer","repliesContainer","modeSelect","lock","icon","favourite","pin"],"mappings":"AAuBAA,OAAM,uBAAC,EAAD,CAAK,UAAW,CAClB,MAAO,CACHC,YAAY,CAAE,CACVC,MAAM,CAAE,yDADE,CADX,CAIHC,OAAO,CAAE,CACLC,OAAO,CAAE,+CADJ,CAJN,CAOHC,IAAI,CAAE,CACFA,IAAI,CAAE,wBADJ,CAEFC,MAAM,CAAE,+BAFN,CAGFC,gBAAgB,CAAE,0CAHhB,CAIFC,UAAU,CAAE,+BAJV,CAKFC,gBAAgB,CAAE,yCALhB,CAMFC,YAAY,CAAE,6BANZ,CAOFC,YAAY,CAAE,iDAPZ,CAQFC,iBAAiB,CAAE,QARjB,CASFC,eAAe,CAAE,kCATf,CAUFC,uBAAuB,CAAE,qCAVvB,CAWFC,uBAAuB,CAAE,qCAXvB,CAYFC,oBAAoB,CAAE,0CAZpB,CAaFC,kBAAkB,CAAE,uCAblB,CAcFC,eAAe,CAAE,wCAdf,CAeFC,eAAe,CAAE,qCAff,CAgBFC,mBAAmB,CAAE,6BAhBnB,CAiBFC,oBAAoB,CAAE,wCAjBpB,CAkBFC,gBAAgB,CAAE,mCAlBhB,CAmBFC,UAAU,CAAE,qBAnBV,CAPH,CA4BHC,IAAI,CAAE,CACFtB,MAAM,CAAE,iDADN,CAEFuB,IAAI,CAAE,6BAFJ,CA5BH,CAgCHC,SAAS,CAAE,CACPxB,MAAM,CAAE,qDADD,CAhCR,CAmCHyB,GAAG,CAAE,CACDzB,MAAM,CAAE,gDADP,CAnCF,CAuCV,CAxCK,CAAN","sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle. If not, see .\n\n/**\n * Common CSS selectors for the forum UI.\n *\n * @module mod_forum/selectors\n * @package mod_forum\n * @copyright 2019 Andrew Nicols \n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\ndefine([], function() {\n return {\n subscription: {\n toggle: \"[data-type='subscription-toggle'][data-action='toggle']\",\n },\n summary: {\n actions: \"[data-container='discussion-summary-actions']\"\n },\n post: {\n post: '[data-region=\"post\"]',\n action: '[data-region=\"post-action\"]',\n actionsContainer: '[data-region=\"post-actions-container\"]',\n authorName: '[data-region=\"author-name\"]',\n forumCoreContent: \"[data-region-content='forum-post-core']\",\n forumContent: \"[data-content='forum-post']\",\n forumSubject: \"[data-region-content='forum-post-core-subject']\",\n inpageReplyButton: \"button\",\n inpageReplyLink: \"[data-action='collapsible-link']\",\n inpageReplyCancelButton: \"[data-action='cancel-inpage-reply']\",\n inpageReplyCreateButton: \"[data-action='create-inpage-reply']\",\n inpageReplyContainer: '[data-region=\"inpage-reply-container\"]',\n inpageReplyContent: \"[data-content='inpage-reply-content']\",\n inpageReplyForm: \"form[data-content='inpage-reply-form']\",\n inpageSubmitBtn: \"[data-action='forum-inpage-submit']\",\n inpageSubmitBtnText: \"[data-region='submit-text']\",\n loadingIconContainer: \"[data-region='loading-icon-container']\",\n repliesContainer: \"[data-region='replies-container']\",\n modeSelect: \"select[name='mode']\"\n },\n lock: {\n toggle: \"[data-action='toggle'][data-type='lock-toggle']\",\n icon: \"[data-region='locked-icon']\"\n },\n favourite: {\n toggle: \"[data-type='favorite-toggle'][data-action='toggle']\",\n },\n pin: {\n toggle: \"[data-type='pin-toggle'][data-action='toggle']\",\n },\n };\n});\n"],"file":"selectors.min.js"} \ No newline at end of file diff --git a/mod/forum/amd/src/discussion_modern.js b/mod/forum/amd/src/discussion_modern.js index 7d91b09688b..1e71dcf47a3 100644 --- a/mod/forum/amd/src/discussion_modern.js +++ b/mod/forum/amd/src/discussion_modern.js @@ -14,23 +14,191 @@ // along with Moodle. If not, see . /** - * Module for viewing a discussion. + * Module for viewing a discussion in modern view. * - * @module mod_forum/discussion_new - * @package mod_forum * @copyright 2019 Ryan Wyllie * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later */ import $ from 'jquery'; +import AutoRows from 'core/auto_rows'; +import CustomEvents from 'core/custom_interaction_events'; +import Notification from 'core/notification'; +import Templates from 'core/templates'; import Discussion from 'mod_forum/discussion'; +import InPageReply from 'mod_forum/inpage_reply'; import LockToggle from 'mod_forum/lock_toggle'; import FavouriteToggle from 'mod_forum/favourite_toggle'; import Pin from 'mod_forum/pin_toggle'; +import Selectors from 'mod_forum/selectors'; -export const init = (root) => { +const ANIMATION_DURATION = 150; + +/** + * Get the closest post container element from the given element. + * + * @param {Object} element jQuery element to search from + * @return {Object} jQuery element + */ +const getPostContainer = (element) => { + return element.closest(Selectors.post.post); +}; + +/** + * Get the post content container element from the post container element. + * + * @param {Object} postContainer jQuery element for the post container + * @return {Object} jQuery element + */ +const getPostContentContainer = (postContainer) => { + return postContainer.children().not(Selectors.post.repliesContainer).find(Selectors.post.forumCoreContent); +}; + +/** + * Get the in page reply container element from the post container element. + * + * @param {Object} postContainer jQuery element for the post container + * @return {Object} jQuery element + */ +const getInPageReplyContainer = (postContainer) => { + return postContainer.children().filter(Selectors.post.inpageReplyContainer); +}; + +/** + * Show the in page reply form in the given in page reply container. The form + * display will be animated. + * + * @param {Object} inPageReplyContainer jQuery element for the in page reply container + * @param {Function} afterAnimationCallback Callback after animation completes + */ +const showInPageReplyForm = (inPageReplyContainer, afterAnimationCallback) => { + const form = inPageReplyContainer.find(Selectors.post.inpageReplyContent); + + form.slideDown({ + duration: ANIMATION_DURATION, + queue: false, + complete: afterAnimationCallback + }).css('display', 'none').fadeIn(ANIMATION_DURATION); +}; + +/** + * Hide the in page reply form in the given in page reply container. The form + * display will be animated. + * + * @param {Object} inPageReplyContainer jQuery element for the in page reply container + * @param {Function} afterAnimationCallback Callback after animation completes + */ +const hideInPageReplyForm = (inPageReplyContainer, afterAnimationCallback) => { + const form = inPageReplyContainer.find(Selectors.post.inpageReplyContent); + + form.slideUp({ + duration: ANIMATION_DURATION, + queue: false, + complete: afterAnimationCallback + }).fadeOut(200); +}; + +/** + * Check if the in page reply container contains the in page reply form. + * + * @param {Object} inPageReplyContainer jQuery element for the in page reply container + * @return {Bool} + */ +const hasInPageReplyForm = (inPageReplyContainer) => { + return inPageReplyContainer.find(Selectors.post.inpageReplyContent).length > 0; +}; + +/** + * Render the template to generate the in page reply form HTML. + * + * @param {Object} additionalTemplateContext Additional render context for the in page reply template + * @param {Object} button jQuery element for the reply button that was clicked + * @param {Object} postContainer jQuery element for the post container + * @return {Object} jQuery promise + */ +const renderInPageReplyTemplate = (additionalTemplateContext, button, postContainer) => { + const postContentContainer = getPostContentContainer(postContainer); + const currentSubject = postContentContainer.find(Selectors.post.forumSubject).text(); + const currentAuthorName = postContentContainer.find(Selectors.post.authorName).text(); + const context = { + postid: postContainer.data('post-id'), + "reply_url": button.attr('data-href'), + sesskey: M.cfg.sesskey, + parentsubject: currentSubject, + parentauthorname: currentAuthorName, + canreplyprivately: button.data('can-reply-privately'), + postformat: InPageReply.CONTENT_FORMATS.MOODLE, + ...additionalTemplateContext + }; + + return Templates.render('mod_forum/inpage_reply_modern', context); +}; + +/** + * Create all of the event listeners for the discussion. + * + * @param {Object} root jQuery element for the discussion container + * @param {Object} additionalTemplateContext Additional render context for the in page reply template + */ +const registerEventListeners = (root, additionalTemplateContext) => { + CustomEvents.define(root, [CustomEvents.events.activate]); + // Auto expanding text area for in page reply. + AutoRows.init(root); + + // Reply button is clicked. + root.on(CustomEvents.events.activate, Selectors.post.inpageReplyCreateButton, async (e, data) => { + data.originalEvent.preventDefault(); + + const button = $(e.currentTarget); + const postContainer = getPostContainer(button); + const inPageReplyContainer = getInPageReplyContainer(postContainer); + + if (!hasInPageReplyForm(inPageReplyContainer)) { + try { + const html = await renderInPageReplyTemplate(additionalTemplateContext, button, postContainer); + Templates.appendNodeContents(inPageReplyContainer, html, ''); + } catch (e) { + Notification.exception(e); + } + } + + button.fadeOut(ANIMATION_DURATION, () => { + showInPageReplyForm(inPageReplyContainer, () => { + inPageReplyContainer.find(Selectors.post.inpageReplyContent).find('textarea').focus(); + }); + }); + }); + + // Cancel in page reply button. + root.on(CustomEvents.events.activate, Selectors.post.inpageReplyCancelButton, (e, data) => { + data.originalEvent.preventDefault(); + + const button = $(e.currentTarget); + const postContainer = getPostContainer(button); + const postContentContainer = getPostContentContainer(postContainer); + const inPageReplyContainer = getInPageReplyContainer(postContainer); + const inPageReplyCreateButton = postContentContainer.find(Selectors.post.inpageReplyCreateButton); + hideInPageReplyForm(inPageReplyContainer, () => { + inPageReplyCreateButton.fadeIn(ANIMATION_DURATION); + }); + }); +}; + +/** + * Initialise the javascript for the discussion in modern display mode. + * + * @param {Object} root jQuery element for the discussion container + * @param {Object} context Additional render context for the in page reply template + */ +export const init = (root, context) => { + // Add discussion event listeners. + registerEventListeners(root, context); + // Add default discussion javascript (keyboard nav etc). Discussion.init(root); + // Add in page reply javascript. + InPageReply.init(root); - var discussionToolsContainer = $('[data-container="discussion-tools"]'); + // Initialise the settings menu javascript. + const discussionToolsContainer = root.find('[data-container="discussion-tools"]'); LockToggle.init(discussionToolsContainer); FavouriteToggle.init(discussionToolsContainer); Pin.init(discussionToolsContainer); diff --git a/mod/forum/amd/src/inpage_reply.js b/mod/forum/amd/src/inpage_reply.js index 014e64669ce..3646dbc1499 100644 --- a/mod/forum/amd/src/inpage_reply.js +++ b/mod/forum/amd/src/inpage_reply.js @@ -36,6 +36,7 @@ define([ ) { var DISPLAYCONSTANTS = { + MODERN: 4, THREADED: 2, NESTED: 3, FLAT_OLDEST_FIRST: 1, @@ -97,9 +98,10 @@ define([ var topreferredformat = true; var postid = form.elements.reply.value; var subject = form.elements.subject.value; - var currentRoot = submitButton.parents(Selectors.post.forumContent); + var currentRoot = submitButton.closest(Selectors.post.post); var isprivatereply = form.elements.privatereply != undefined ? form.elements.privatereply.checked : false; - var mode = parseInt(root.find(Selectors.post.modeSelect).get(0).value); + var modeSelector = root.find(Selectors.post.modeSelect); + var mode = modeSelector.length ? parseInt(modeSelector.get(0).value) : null; var newid; if (message.length) { @@ -125,7 +127,17 @@ define([ form.reset(); var post = context.post; newid = post.id; + switch (mode) { + case DISPLAYCONSTANTS.MODERN: + var capabilities = post.capabilities; + post.showactionmenu = capabilities.controlreadstatus || + capabilities.edit || + capabilities.split || + capabilities.delete || + capabilities.export || + post.urls.viewparent; + return Templates.render('mod_forum/forum_discussion_modern_post_reply', post); case DISPLAYCONSTANTS.THREADED: return Templates.render('mod_forum/forum_discussion_threaded_post', post); case DISPLAYCONSTANTS.NESTED: @@ -135,16 +147,7 @@ define([ } }) .then(function(html, js) { - var repliesnode; - - // Try and get the replies-container which can either be a sibling OR parent if it's flat - if (mode == DISPLAYCONSTANTS.FLAT_OLDEST_FIRST || mode == DISPLAYCONSTANTS.FLAT_NEWEST_FIRST) { - repliesnode = currentRoot.parents(Selectors.post.repliesContainer).children().get(0); - } - - if (repliesnode == undefined) { - repliesnode = currentRoot.siblings(Selectors.post.repliesContainer).children().get(0); - } + var repliesnode = currentRoot.find(Selectors.post.repliesContainer).first(); if (mode == DISPLAYCONSTANTS.FLAT_NEWEST_FIRST) { return Templates.prependNodeContents(repliesnode, html, js); diff --git a/mod/forum/amd/src/selectors.js b/mod/forum/amd/src/selectors.js index a4cd6e10a04..baf62df696d 100644 --- a/mod/forum/amd/src/selectors.js +++ b/mod/forum/amd/src/selectors.js @@ -33,11 +33,15 @@ define([], function() { post: '[data-region="post"]', action: '[data-region="post-action"]', actionsContainer: '[data-region="post-actions-container"]', + authorName: '[data-region="author-name"]', forumCoreContent: "[data-region-content='forum-post-core']", forumContent: "[data-content='forum-post']", forumSubject: "[data-region-content='forum-post-core-subject']", inpageReplyButton: "button", inpageReplyLink: "[data-action='collapsible-link']", + inpageReplyCancelButton: "[data-action='cancel-inpage-reply']", + inpageReplyCreateButton: "[data-action='create-inpage-reply']", + inpageReplyContainer: '[data-region="inpage-reply-container"]', inpageReplyContent: "[data-content='inpage-reply-content']", inpageReplyForm: "form[data-content='inpage-reply-form']", inpageSubmitBtn: "[data-action='forum-inpage-submit']", diff --git a/mod/forum/classes/local/renderers/discussion.php b/mod/forum/classes/local/renderers/discussion.php index a1f30392f30..4c0f95e3ecf 100644 --- a/mod/forum/classes/local/renderers/discussion.php +++ b/mod/forum/classes/local/renderers/discussion.php @@ -184,7 +184,6 @@ class discussion { $capabilitymanager = $this->capabilitymanager; $urlfactory = $this->urlfactory; $entityfactory = $this->entityfactory; - $loggedinauthor = $entityfactory->get_author_from_stdClass($user); // Make sure we can render. if (!$capabilitymanager->can_view_discussions($user)) { @@ -205,11 +204,6 @@ class discussion { $hasanyactions = $hasanyactions || $capabilitymanager->can_manage_forum($user); $exporteddiscussion = array_merge($exporteddiscussion, [ - 'loggedinuser' => [ - 'firstname' => $loggedinauthor->get_first_name(), - 'fullname' => $loggedinauthor->get_full_name(), - 'profileimageurl' => ($urlfactory->get_author_profile_image_url($loggedinauthor, null))->out(false) - ], 'notifications' => $this->get_notifications($user), 'html' => [ 'hasanyactions' => $hasanyactions, @@ -233,6 +227,15 @@ class discussion { $exporteddiscussion['html']['movediscussion'] = $this->get_move_discussion_html(); } + if (!empty($user->id)) { + $loggedinuser = $entityfactory->get_author_from_stdClass($user); + $exporteddiscussion['loggedinuser'] = [ + 'firstname' => $loggedinuser->get_first_name(), + 'fullname' => $loggedinuser->get_full_name(), + 'profileimageurl' => ($urlfactory->get_author_profile_image_url($loggedinuser, null))->out(false) + ]; + } + if ($this->displaymode === FORUM_MODE_MODERN) { $template = 'mod_forum/forum_discussion_modern'; } else { diff --git a/mod/forum/lang/en/forum.php b/mod/forum/lang/en/forum.php index fec328c1f9c..84d75977db3 100644 --- a/mod/forum/lang/en/forum.php +++ b/mod/forum/lang/en/forum.php @@ -59,6 +59,7 @@ $string['blogforum'] = 'Standard forum displayed in a blog-like format'; $string['bynameondate'] = 'by {$a->name} - {$a->date}'; $string['cachedef_forum_is_tracked'] = 'Forum tracking status for user'; $string['calendardue'] = '{$a} is due'; +$string['cancelreply'] = 'Cancel reply'; $string['cannotadd'] = 'Could not add the discussion for this forum'; $string['cannotadddiscussion'] = 'Adding discussions to this forum requires group membership.'; $string['cannotadddiscussionall'] = 'You do not have permission to add a new discussion topic for all participants.'; @@ -555,6 +556,8 @@ $string['replies'] = 'Replies'; $string['repliesmany'] = '{$a} replies so far'; $string['repliesone'] = '{$a} reply so far'; $string['reply'] = 'Reply'; +$string['replyauthorself'] = '{$a} (you)'; +$string['replyingtoauthor'] = 'Replying to {$a}...'; $string['replyplaceholder'] = 'Write your reply...'; $string['replyforum'] = 'Reply to forum'; $string['replytopostbyemail'] = 'You can reply to this via email.'; diff --git a/mod/forum/templates/forum_discussion_modern.mustache b/mod/forum/templates/forum_discussion_modern.mustache index a4e8b1ad5e9..5d1b997772c 100644 --- a/mod/forum/templates/forum_discussion_modern.mustache +++ b/mod/forum/templates/forum_discussion_modern.mustache @@ -57,6 +57,14 @@ {{#js}} require(['jquery', 'mod_forum/discussion_modern'], function($, Discussion) { var root = $('#discussion-container-{{uniqid}}'); - Discussion.init(root); + Discussion.init(root, { + {{#loggedinuser}} + loggedinuser: { + profileimageurl: '{{{profileimageurl}}}', + fullname: '{{fullname}}', + firstname: '{{firstname}}' + } + {{/loggedinuser}} + }); }); {{/js}} diff --git a/mod/forum/templates/forum_discussion_modern_first_post.mustache b/mod/forum/templates/forum_discussion_modern_first_post.mustache index 5d23e0826e0..7abcf15bb3e 100644 --- a/mod/forum/templates/forum_discussion_modern_first_post.mustache +++ b/mod/forum/templates/forum_discussion_modern_first_post.mustache @@ -325,7 +325,7 @@ class="btn btn-primary btn-lg" data-href="{{{urls.reply}}}" data-post-id="{{id}}" - data-action="collapsible-link" + data-action="create-inpage-reply" data-can-reply-privately="{{capabilities.canreplyprivately}}" > {{#str}} reply, mod_forum {{/str}} @@ -354,9 +354,7 @@
{{#hasreplies}} {{#replies}} -
- {{> mod_forum/forum_discussion_modern_post_reply }} -
+ {{> mod_forum/forum_discussion_modern_post_reply }} {{/replies}} {{/hasreplies}}
diff --git a/mod/forum/templates/forum_discussion_nested_post.mustache b/mod/forum/templates/forum_discussion_nested_post.mustache index 2edca4ebe5b..e501b945d29 100644 --- a/mod/forum/templates/forum_discussion_nested_post.mustache +++ b/mod/forum/templates/forum_discussion_nested_post.mustache @@ -31,7 +31,7 @@ }} {{< mod_forum/forum_discussion_post }} {{$replies}} -
+
{{#replies}} {{> mod_forum/forum_discussion_nested_post }} {{/replies}} diff --git a/mod/forum/templates/forum_discussion_post.mustache b/mod/forum/templates/forum_discussion_post.mustache index 5023af89beb..fbc1f6b59dd 100644 --- a/mod/forum/templates/forum_discussion_post.mustache +++ b/mod/forum/templates/forum_discussion_post.mustache @@ -314,15 +314,13 @@
-
{{$replies}} -
- {{#hasreplies}} - {{#replies}} - {{> mod_forum/forum_discussion_post }} - {{/replies}} - {{/hasreplies}} +
+ {{#hasreplies}} + {{#replies}} + {{> mod_forum/forum_discussion_post }} + {{/replies}} + {{/hasreplies}}
{{/replies}} -
diff --git a/mod/forum/templates/forum_discussion_threaded_posts.mustache b/mod/forum/templates/forum_discussion_threaded_posts.mustache index a9eee4cb6ec..83098ff5555 100644 --- a/mod/forum/templates/forum_discussion_threaded_posts.mustache +++ b/mod/forum/templates/forum_discussion_threaded_posts.mustache @@ -34,7 +34,7 @@ {{< mod_forum/forum_discussion_post }} {{$replies}} -
+
{{#replies}} {{> mod_forum/forum_discussion_threaded_post }} {{/replies}} diff --git a/mod/forum/templates/inpage_reply_modern.mustache b/mod/forum/templates/inpage_reply_modern.mustache new file mode 100644 index 00000000000..9984ba321f8 --- /dev/null +++ b/mod/forum/templates/inpage_reply_modern.mustache @@ -0,0 +1,104 @@ +{{! + This file is part of Moodle - http://moodle.org/ + + Moodle is free software: you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation, either version 3 of the License, or + (at your option) any later version. + + Moodle is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. + + You should have received a copy of the GNU General Public License + along with Moodle. If not, see . +}} +{{! + @template mod_forum/inpage_reply_modern + + In page reply HTML for the "modern" discussion display mode. + + Classes required for JS: + * none + + Data attributes required for JS: + * none + + Example context (json): + { + "postid": 0, + "reply_url": "", + "sesskey": "", + "parentsubject": "" + } +}} +