1 // This file is part of Moodle - http://moodle.org/
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.
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.
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/>.
17 * A type of dialogue used as for choosing modules in a course.
19 * @module core_course/activitychooser
20 * @package core_course
21 * @copyright 2020 Mathew May <mathew.solutions>
22 * @license http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25 import * as ChooserDialogue from 'core_course/local/activitychooser/dialogue';
26 import * as Repository from 'core_course/local/activitychooser/repository';
27 import selectors from 'core_course/local/activitychooser/selectors';
28 import CustomEvents from 'core/custom_interaction_events';
29 import * as Templates from 'core/templates';
30 import * as ModalFactory from 'core/modal_factory';
31 import {get_string as getString} from 'core/str';
32 import Pending from 'core/pending';
35 * Set up the activity chooser.
38 * @param {Number} courseId Course ID to use later on in fetchModules()
40 export const init = courseId => {
41 const pendingPromise = new Pending();
43 registerListenerEvents(courseId);
45 pendingPromise.resolve();
49 * Once a selection has been made make the modal & module information and pass it along
51 * @method registerListenerEvents
52 * @param {Number} courseId
54 const registerListenerEvents = (courseId) => {
57 CustomEvents.events.activate,
58 CustomEvents.events.keyboardActivate
61 const fetchModuleData = (() => {
62 let innerPromise = null;
66 innerPromise = new Promise((resolve) => {
67 resolve(Repository.activityModules(courseId));
75 CustomEvents.define(document, events);
77 // Display module chooser event listeners.
78 events.forEach((event) => {
79 document.addEventListener(event, async(e) => {
80 if (e.target.closest(selectors.elements.sectionmodchooser)) {
81 const caller = e.target.closest(selectors.elements.sectionmodchooser);
82 const builtModuleData = sectionIdMapper(await fetchModuleData(), caller.dataset.sectionid);
83 const sectionModal = await modalBuilder(builtModuleData);
85 ChooserDialogue.displayChooser(caller, sectionModal, builtModuleData);
92 * Given the web service data and an ID we want to make a deep copy
93 * of the WS data then add on the section ID to the addoption URL
95 * @method sectionIdMapper
96 * @param {Object} webServiceData Our original data from the Web service call
97 * @param {Array} id The ID of the section we need to append to the links
98 * @return {Array} [modules] with URL's built
100 const sectionIdMapper = (webServiceData, id) => {
101 // We need to take a fresh deep copy of the original data as an object is a reference type.
102 const newData = JSON.parse(JSON.stringify(webServiceData));
103 newData.allmodules.forEach((module) => {
104 module.urls.addoption += '§ion=' + id;
106 return newData.allmodules;
110 * Build a modal for each section ID and store it into a map for quick access
112 * @method modalBuilder
113 * @param {Map} data our map of section ID's & modules to generate modals for
114 * @return {Object} TODO
116 const modalBuilder = data => buildModal(templateDataBuilder(data));
119 * Given an array of modules we want to figure out where & how to place them into our template object
121 * @method templateDataBuilder
122 * @param {Array} data our modules to manipulate into a Templatable object
123 * @return {Object} Our built object ready to render out
125 const templateDataBuilder = (data) => {
132 * Given an object we want to prebuild a modal ready to store into a map
135 * @param {Object} data The template data which contains arrays of modules
136 * @return {Object} The modal for the calling section with everything already set up
138 const buildModal = data => {
139 return ModalFactory.create({
140 type: ModalFactory.types.DEFAULT,
141 title: getString('addresourceoractivity'),
142 body: Templates.render('core_course/chooser', data),
145 classes: 'modchooser'