MDL-71779 core_courseformat: reactive add and delete sections

This commit is contained in:
Ferran Recio 2021-07-13 17:54:51 +02:00
parent a9d44b0f75
commit 3d2a6eacae
57 changed files with 883 additions and 140 deletions

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

View file

@ -1,2 +1,2 @@
define ("core_course/events",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;a.default={favourited:"core_course:favourited",unfavorited:"core_course:unfavorited",manualCompletionToggled:"core_course:manualcompletiontoggled",stateChanged:"core_course:stateChanged"};return a.default});
define ("core_course/events",["exports"],function(a){"use strict";Object.defineProperty(a,"__esModule",{value:!0});a.default=void 0;a.default={favourited:"core_course:favourited",unfavorited:"core_course:unfavorited",manualCompletionToggled:"core_course:manualcompletiontoggled",stateChanged:"core_course:stateChanged",sectionRefreshed:"core_course:sectionRefreshed"};return a.default});
//# sourceMappingURL=events.min.js.map

View file

@ -1 +1 @@
{"version":3,"sources":["../src/events.js"],"names":["favourited","unfavorited","manualCompletionToggled","stateChanged"],"mappings":"8IAsBe,CACXA,UAAU,CAAE,wBADD,CAEXC,WAAW,CAAE,yBAFF,CAGXC,uBAAuB,CAAE,qCAHd,CAIXC,YAAY,CAAE,0BAJH,C","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 <http://www.gnu.org/licenses/>.\n\n/**\n * Contain the events the course component can trigger.\n *\n * @module core_course/events\n * @copyright 2018 Simey Lameze <simey@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nexport default {\n favourited: 'core_course:favourited',\n unfavorited: 'core_course:unfavorited',\n manualCompletionToggled: 'core_course:manualcompletiontoggled',\n stateChanged: 'core_course:stateChanged',\n};\n"],"file":"events.min.js"}
{"version":3,"sources":["../src/events.js"],"names":["favourited","unfavorited","manualCompletionToggled","stateChanged","sectionRefreshed"],"mappings":"8IAsBe,CACXA,UAAU,CAAE,wBADD,CAEXC,WAAW,CAAE,yBAFF,CAGXC,uBAAuB,CAAE,qCAHd,CAIXC,YAAY,CAAE,0BAJH,CAKXC,gBAAgB,CAAE,8BALP,C","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 <http://www.gnu.org/licenses/>.\n\n/**\n * Contain the events the course component can trigger.\n *\n * @module core_course/events\n * @copyright 2018 Simey Lameze <simey@moodle.com>\n * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nexport default {\n favourited: 'core_course:favourited',\n unfavorited: 'core_course:unfavorited',\n manualCompletionToggled: 'core_course:manualcompletiontoggled',\n stateChanged: 'core_course:stateChanged',\n sectionRefreshed: 'core_course:sectionRefreshed',\n};\n"],"file":"events.min.js"}

View file

@ -21,18 +21,51 @@
* @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
* @since 3.3
*/
define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str', 'core/url', 'core/yui',
'core/modal_factory', 'core/modal_events', 'core/key_codes', 'core/log', 'core_courseformat/courseeditor'],
function($, ajax, templates, notification, str, url, Y, ModalFactory, ModalEvents, KeyCodes, log, editor) {
define(
[
'jquery',
'core/ajax',
'core/templates',
'core/notification',
'core/str',
'core/url',
'core/yui',
'core/modal_factory',
'core/modal_events',
'core/key_codes',
'core/log',
'core_courseformat/courseeditor',
'core/event_dispatcher',
'core_course/events'
],
function(
$,
ajax,
templates,
notification,
str,
url,
Y,
ModalFactory,
ModalEvents,
KeyCodes,
log,
editor,
EventDispatcher,
CourseEvents
) {
// Eventually, core_courseformat/local/content/actions will handle all actions for
// component compatible formats and the default actions.js won't be necessary anymore.
// Meanwhile, we filter the migrated actions.
const componentActions = ['moveSection', 'moveCm'];
const componentActions = ['moveSection', 'moveCm', 'addSection', 'deleteSection'];
// The course reactive instance.
const courseeditor = editor.getCurrentCourseEditor();
// The current course format name (loaded on init).
let formatname;
var CSS = {
EDITINPROGRESS: 'editinprogress',
SECTIONDRAGGABLE: 'sectiondraggable',
@ -46,7 +79,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
TOGGLE: '.toggle-display,.dropdown-toggle',
SECTIONLI: 'li.section',
SECTIONACTIONMENU: '.section_action_menu',
ADDSECTIONS: '#changenumsections [data-add-sections]'
ADDSECTIONS: '.changenumsections [data-add-sections]'
};
Y.use('moodle-course-coursebase', function() {
@ -56,6 +89,29 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
}
});
/**
* Dispatch event wrapper.
*
* Old jQuery events will be replaced by native events gradually.
*
* @method dispatchEvent
* @param {String} eventName The name of the event
* @param {Object} detail Any additional details to pass into the eveent
* @param {Node|HTMLElement} container The point at which to dispatch the event
* @param {Object} options
* @param {Boolean} options.bubbles Whether to bubble up the DOM
* @param {Boolean} options.cancelable Whether preventDefault() can be called
* @param {Boolean} options.composed Whether the event can bubble across the ShadowDOM boundary
* @returns {CustomEvent}
*/
const dispatchEvent = function(eventName, detail, container, options) {
// Most actions still uses jQuery node instead of regular HTMLElement.
if (!(container instanceof Element) && container.get !== undefined) {
container = container.get(0);
}
return EventDispatcher.dispatchEvent(eventName, detail, container, options);
};
/**
* Wrapper for Y.Moodle.core_course.util.cm.getId
*
@ -238,6 +294,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
foundElement = this;
return false; // Returning false in .each() is equivalent to "break;" inside the loop in php.
}
return true;
});
return foundElement;
};
@ -316,6 +373,11 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
* @return {Promise} the refresh promise
*/
var refreshModule = function(element, cmid, sectionreturn) {
if (sectionreturn === undefined) {
sectionreturn = courseeditor.sectionReturn;
}
const activityElement = $(element);
var spinner = addActivitySpinner(activityElement);
var promises = ajax.call([{
@ -336,6 +398,80 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
});
};
/**
* Requests html for the section via WS core_course_edit_section and updates the section on the course page
*
* @param {JQuery|Element} element
* @param {Number} sectionid
* @param {Number} sectionreturn
* @return {Promise} the refresh promise
*/
var refreshSection = function(element, sectionid, sectionreturn) {
if (sectionreturn === undefined) {
sectionreturn = courseeditor.sectionReturn;
}
const sectionElement = $(element);
const action = 'refresh';
const promises = ajax.call([{
methodname: 'core_course_edit_section',
args: {id: sectionid, action, sectionreturn},
}], true);
var spinner = addSectionSpinner(sectionElement);
return new Promise((resolve, reject) => {
$.when.apply($, promises)
.done(dataencoded => {
removeSpinner(sectionElement, spinner);
const data = $.parseJSON(dataencoded);
const newSectionElement = $(data.content);
sectionElement.replaceWith(newSectionElement);
// Init modules menus.
$(`${SELECTOR.SECTIONLI}#${sectionid} ${SELECTOR.ACTIVITYLI}`).each(
(index, activity) => {
initActionMenu(activity.data('id'));
}
);
// Trigger event that can be observed by course formats.
const event = dispatchEvent(
CourseEvents.sectionRefreshed,
{
ajaxreturn: data,
action: action,
newSectionElement: newSectionElement.get(0),
},
newSectionElement
);
if (!event.defaultPrevented) {
defaultEditSectionHandler(
newSectionElement, $(SELECTOR.SECTIONLI + '#' + sectionid),
data,
formatname,
sectionid
);
}
resolve(data);
}).fail(ex => {
// Trigger event that can be observed by course formats.
const event = dispatchEvent(
'coursesectionrefreshfailed',
{exception: ex, action: action},
sectionElement
);
if (!event.defaultPrevented) {
notification.exception(ex);
}
reject();
});
});
};
/**
* Displays the delete confirmation to delete a module
*
@ -352,7 +488,7 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
name: modulename
};
str.get_strings([
{key: 'confirm'},
{key: 'confirm', component: 'core'},
{key: modulename === null ? 'deletechecktype' : 'deletechecktypename', param: plugindata},
{key: 'yes'},
{key: 'no'}
@ -699,6 +835,8 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
*/
initCoursePage: function(courseformat) {
formatname = courseformat;
// Add a handler for course module actions.
$('body').on('click keypress', SELECTOR.ACTIVITYLI + ' ' +
SELECTOR.ACTIVITYACTION + '[data-action]', function(e) {
@ -782,6 +920,11 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
}
});
// Component-based formats don't use modals to create sections.
if (courseeditor.supportComponents && componentActions.includes('addSection')) {
return;
}
// Add a handler for "Add sections" link to ask for a number of sections to add.
str.get_string('numberweeks').done(function(strNumberSections) {
var trigger = $(SELECTOR.ADDSECTIONS),
@ -843,5 +986,6 @@ define(['jquery', 'core/ajax', 'core/templates', 'core/notification', 'core/str'
},
// Method to refresh a module.
refreshModule,
refreshSection,
};
});

View file

@ -25,4 +25,5 @@ export default {
unfavorited: 'core_course:unfavorited',
manualCompletionToggled: 'core_course:manualcompletiontoggled',
stateChanged: 'core_course:stateChanged',
sectionRefreshed: 'core_course:sectionRefreshed',
};