Proyectos de Subversion Moodle

Rev

| Ultima modificación | Ver Log |

Rev Autor Línea Nro. Línea
1 efrain 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
 * Course section header component.
18
 *
19
 * This component is used to control specific course section interactions like drag and drop.
20
 *
21
 * @module     core_courseformat/local/content/section/header
22
 * @class      core_courseformat/local/content/section/header
23
 * @copyright  2021 Ferran Recio <ferran@moodle.com>
24
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
25
 */
26
 
27
import DndSectionItem from 'core_courseformat/local/courseeditor/dndsectionitem';
28
 
29
export default class extends DndSectionItem {
30
 
31
    /**
32
     * Constructor hook.
33
     *
34
     * @param {Object} descriptor
35
     */
36
    create(descriptor) {
37
        // Optional component name for debugging.
38
        this.name = 'content_section_header';
39
        // Default query selectors.
40
        this.selectors = {
41
            ACTIONSMENU: `.section_action_menu`,
42
            BULKSELECT: `[data-for='sectionBulkSelect']`,
43
            BULKCHECKBOX: `[data-bulkcheckbox]`,
44
            CHEVRON: `[data-for='sectiontoggler']`,
45
        };
46
        this.classes = {
47
            HIDE: 'd-none',
48
            SELECTED: 'selected',
49
        };
50
        // Get main info from the descriptor.
51
        this.id = descriptor.id;
52
        this.section = descriptor.section;
53
        this.course = descriptor.course;
54
        this.fullregion = descriptor.fullregion;
55
    }
56
 
57
    /**
58
     * Initial state ready method.
59
     *
60
     * @param {Object} state the initial state
61
     */
62
    stateReady(state) {
63
        this.configDragDrop(this.id, state, this.fullregion);
64
        this._refreshBulk({state});
65
    }
66
 
67
    /**
68
     * Component watchers.
69
     *
70
     * @returns {Array} of watchers
71
     */
72
    getWatchers() {
73
        return [
74
            {watch: `bulk:updated`, handler: this._refreshBulk},
75
            {watch: `section[${this.id}].title:updated`, handler: this._refreshSectionTitle},
76
        ];
77
    }
78
 
79
    /**
80
     * Update the section when the section name changes.
81
     *
82
     * The section header have several HTML that uses the section name
83
     * for accessibility and behat tests. This method updates them all.
84
     *
85
     * @param {object} param
86
     * @param {Object} param.element the section info
87
     */
88
    _refreshSectionTitle(param) {
89
        const element = param.element;
90
        this.getElement(this.selectors.CHEVRON)?.setAttribute("aria-label", element.title);
91
        this._refreshSectionBulkSelector(param);
92
    }
93
 
94
    /**
95
     * Update the bulk checkbox when the section name changes.
96
     *
97
     * @param {object} param
98
     * @param {Object} param.element the section info
99
     */
100
    async _refreshSectionBulkSelector({element}) {
101
        const checkbox = this.getElement(this.selectors.BULKCHECKBOX);
102
        if (!checkbox) {
103
            return;
104
        }
105
        const newLabel = await this.reactive.getFormatString('selectsection', element.title);
106
        checkbox.title = newLabel;
107
        const label = this.getElement(`label[for='${checkbox.id}']`);
108
        if (label) {
109
            label.innerText = newLabel;
110
        }
111
    }
112
 
113
    /**
114
     * Update a bulk options.
115
     *
116
     * @param {object} param
117
     * @param {Object} param.state the state data
118
     */
119
    _refreshBulk({state}) {
120
        const bulk = state.bulk;
121
        if (!this._isSectionBulkEditable()) {
122
            return;
123
        }
124
        // For now, dragging elements in bulk is not possible.
125
        this.setDraggable(!bulk.enabled);
126
        this.getElement(this.selectors.BULKSELECT)?.classList.toggle(this.classes.HIDE, !bulk.enabled);
127
 
128
        const disabled = !this._isSectionBulkEnabled(bulk);
129
        const selected = this._isSelected(bulk);
130
        this.element.classList.toggle(this.classes.SELECTED, selected);
131
        this._setCheckboxValue(selected, disabled);
132
    }
133
 
134
    /**
135
     * Modify the checkbox element.
136
     * @param {Boolean} checked the new checked value
137
     * @param {Boolean} disabled the new disabled value
138
     */
139
    _setCheckboxValue(checked, disabled) {
140
        const checkbox = this.getElement(this.selectors.BULKCHECKBOX);
141
        if (!checkbox) {
142
            return;
143
        }
144
        checkbox.checked = checked;
145
        checkbox.disabled = disabled;
146
        // Is selectable is used to easily scan the page for bulk checkboxes.
147
        if (disabled) {
148
            checkbox.removeAttribute('data-is-selectable');
149
        } else {
150
            checkbox.dataset.isSelectable = 1;
151
        }
152
    }
153
 
154
    /**
155
     * Check if cm bulk selection is available.
156
     * @param {Object} bulk the current state bulk attribute
157
     * @returns {Boolean}
158
     */
159
    _isSectionBulkEnabled(bulk) {
160
        if (!bulk.enabled) {
161
            return false;
162
        }
163
        return (bulk.selectedType === '' || bulk.selectedType === 'section');
164
    }
165
 
166
    /**
167
     * Check if the section is bulk editable.
168
     * @return {Boolean}
169
     */
170
    _isSectionBulkEditable() {
171
        const section = this.reactive.get('section', this.id);
172
        return section?.bulkeditable ?? false;
173
    }
174
 
175
    /**
176
     * Check if the cm id is part of the current bulk selection.
177
     * @param {Object} bulk the current state bulk attribute
178
     * @returns {Boolean}
179
     */
180
    _isSelected(bulk) {
181
        if (bulk.selectedType !== 'section') {
182
            return false;
183
        }
184
        return bulk.selection.includes(this.id);
185
    }
186
}