Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1441 ariadna 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
 * Schema selector javascript controls.
18
 *
19
 * This module controls:
20
 * - The select all feature.
21
 * - Disabling activities checkboxes when the section is not selected.
22
 *
23
 * @module     core_backup/schema_backup_form
24
 * @copyright  2024 Ferran Recio <ferran@moodle.com>
25
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26
 */
27
 
28
import Notification from 'core/notification';
29
import * as Templates from 'core/templates';
30
 
31
const Selectors = {
32
    action: '[data-mdl-action]',
33
    checkboxes: '#id_coursesettings input[type="checkbox"]',
34
    firstSection: 'fieldset#id_coursesettings .fcontainer .grouped_settings.section_level',
35
    modCheckboxes: (modName) => `setting_activity_${modName}_`,
36
};
37
 
38
const Suffixes = {
39
    userData: '_userdata',
40
    userInfo: '_userinfo',
41
    included: '_included',
42
};
43
 
44
/**
45
 * Adds select all/none links to the top of the backup/restore/import schema page.
46
 */
47
export default class BackupFormController {
48
 
49
    /**
50
     * Static module init method.
51
     * @param {Array<string>} modNames - The names of the modules.
52
     * @returns {BackupFormController}
53
     */
54
    static init(modNames) {
55
        return new BackupFormController(modNames);
56
    }
57
 
58
    /**
59
     * Creates a new instance of the SchemaBackupForm class.
60
     * @param {Array<string>} modNames - The names of the modules.
61
     */
62
    constructor(modNames) {
63
        this.modNames = modNames;
64
        this.scanFormUserData();
65
        this.addSelectorsToPage();
66
    }
67
 
68
    /**
69
     * Detect the user data attribute from the form.
70
     *
71
     * @private
72
     */
73
    scanFormUserData() {
74
        this.withuserdata = false;
75
        this.userDataSuffix = Suffixes.userData;
76
 
77
        const checkboxes = document.querySelectorAll(Selectors.checkboxes);
78
        if (!checkboxes) {
79
            return;
80
        }
81
        // Depending on the form, user data inclusion is called userinfo or userdata.
82
        for (const checkbox of checkboxes) {
83
            const name = checkbox.name;
84
            if (name.endsWith(Suffixes.userData)) {
85
                this.withuserdata = true;
86
                break;
87
            } else if (name.endsWith(Suffixes.userInfo)) {
88
                this.withuserdata = true;
89
                this.userDataSuffix = Suffixes.userInfo;
90
                break;
91
            }
92
        }
93
    }
94
 
95
    /**
96
     * Initializes all related events.
97
     *
98
     * @private
99
     * @param {HTMLElement} element - The element to attach the events to.
100
     */
101
    initEvents(element) {
102
        element.addEventListener('click', (event) => {
103
            const action = event.target.closest(Selectors.action);
104
            if (!action) {
105
                return;
106
            }
107
            event.preventDefault();
108
 
109
            const suffix = (action.dataset?.mdlType == 'userdata') ? this.userDataSuffix : Suffixes.included;
110
 
111
            this.changeSelection(
112
                action.dataset.mdlAction == 'selectall',
113
                suffix,
114
                action.dataset?.mdlMod ?? null
115
            );
116
        });
117
    }
118
 
119
    /**
120
     * Changes the selection according to the params.
121
     *
122
     * @private
123
     * @param {boolean} checked - The checked state for the checkboxes.
124
     * @param {string} suffix - The checkboxes suffix
125
     * @param {string} [modName] - The module name.
126
     */
127
    changeSelection(checked, suffix, modName) {
128
        const prefix = modName ? Selectors.modCheckboxes(modName) : null;
129
 
130
        let formId;
131
 
132
        const checkboxes = document.querySelectorAll(Selectors.checkboxes);
133
        for (const checkbox of checkboxes) {
134
            formId = formId ?? checkbox.closest('form').getAttribute('id');
135
 
136
            if (prefix && !checkbox.name.startsWith(prefix)) {
137
                continue;
138
            }
139
            if (checkbox.name.endsWith(suffix)) {
140
                checkbox.checked = checked;
141
            }
142
        }
143
 
144
        // At this point, we really need to persuade the form we are part of to
145
        // update all of its disabledIf rules. However, as far as I can see,
146
        // given the way that lib/form/form.js is written, that is impossible.
147
        if (formId && M.form) {
148
            M.form.updateFormState(formId);
149
        }
150
    }
151
 
152
    /**
153
     * Generates the full selectors element to add to the page.
154
     *
155
     * @private
156
     * @returns {HTMLElement} The selectors element.
157
     */
158
    generateSelectorsElement() {
159
        const links = document.createElement('div');
160
        links.id = 'backup_selectors';
161
        this.initEvents(links);
162
        this.renderSelectorsTemplate(links);
163
        return links;
164
    }
165
 
166
    /**
167
     * Load the select all template.
168
     *
169
     * @private
170
     * @param {HTMLElement} element the container
171
     */
172
    renderSelectorsTemplate(element) {
173
        const data = {
174
            modules: this.getModulesTemplateData(),
175
            withuserdata: (this.withuserdata) ? true : undefined,
176
        };
177
        Templates.renderForPromise(
178
            'core_backup/formselectall',
179
            data
180
        ).then(({html, js}) => {
181
            return Templates.replaceNodeContents(element, html, js);
182
        }).catch(Notification.exception);
183
    }
184
 
185
    /**
186
     * Generate the modules template data.
187
     *
188
     * @private
189
     * @returns {Array} of modules data.
190
     */
191
    getModulesTemplateData() {
192
        const modules = [];
193
        for (const modName in this.modNames) {
194
            if (!this.modNames.hasOwnProperty(modName)) {
195
                continue;
196
            }
197
            modules.push({
198
                modname: modName,
199
                heading: this.modNames[modName],
200
            });
201
        }
202
        return modules;
203
    }
204
 
205
    /**
206
     * Adds select all/none functionality to the backup form.
207
     *
208
     * @private
209
     */
210
    addSelectorsToPage() {
211
        const firstSection = document.querySelector(Selectors.firstSection);
212
        if (!firstSection) {
213
            // This is not a relevant page.
214
            return;
215
        }
216
        if (!firstSection.querySelector(Selectors.checkboxes)) {
217
            // No checkboxes.
218
            return;
219
        }
220
 
221
        // Add global select all/none options.
222
        const selector = this.generateSelectorsElement();
223
        firstSection.parentNode.insertBefore(selector, firstSection);
224
    }
225
}