Proyectos de Subversion Moodle

Rev

Rev 1 | | Comparar con el anterior | 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 index section title draggable component.
18
 *
19
 * This component is used to control specific course section interactions like drag and drop
20
 * in both course index and course content.
21
 *
22
 * @module     core_courseformat/local/courseeditor/dndsectionitem
23
 * @class      core_courseformat/local/courseeditor/dndsectionitem
24
 * @copyright  2021 Ferran Recio <ferran@moodle.com>
25
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
26
 */
27
 
28
import {BaseComponent, DragDrop} from 'core/reactive';
29
 
30
export default class extends BaseComponent {
31
 
32
    /**
33
     * Initial state ready method.
34
     *
35
     * @param {number} sectionid the section id
36
     * @param {Object} state the initial state
37
     * @param {Element} fullregion the complete section region to mark as dragged
1441 ariadna 38
     * @param {Boolean} isDndAllowed Whether drag and drop is allowed in this section.
1 efrain 39
     */
1441 ariadna 40
    configDragDrop(sectionid, state, fullregion, isDndAllowed = true) {
1 efrain 41
 
42
        this.id = sectionid;
43
        if (this.section === undefined) {
44
            this.section = state.section.get(this.id);
45
        }
46
        if (this.course === undefined) {
47
            this.course = state.course;
48
        }
49
 
1441 ariadna 50
        // Prevent topic zero and delegated sections from being draggable.
51
        if (this.section.number > 0 && this.section.component === null) {
1 efrain 52
            this.getDraggableData = this._getDraggableData;
53
        }
54
 
55
        this.fullregion = fullregion;
56
 
57
        // Drag and drop is only available for components compatible course formats.
1441 ariadna 58
        if (this.reactive.isEditing && this.reactive.supportComponents && isDndAllowed) {
1 efrain 59
            // Init the dropzone.
60
            this.dragdrop = new DragDrop(this);
61
            // Save dropzone classes.
62
            this.classes = this.dragdrop.getClasses();
63
        }
64
    }
65
 
66
    /**
67
     * Remove all subcomponents dependencies.
68
     */
69
    destroy() {
70
        if (this.dragdrop !== undefined) {
71
            this.dragdrop.unregister();
72
        }
73
    }
74
 
75
    /**
76
     * Enable or disable the draggable property.
77
     *
78
     * @param {bool} value the new draggable value
79
     */
80
    setDraggable(value) {
81
        if (this.getDraggableData) {
82
            this.dragdrop?.setDraggable(value);
83
        }
84
    }
85
 
86
    // Drag and drop methods.
87
 
88
    /**
89
     * The element drop start hook.
90
     *
91
     * @param {Object} dropdata the dropdata
92
     */
93
    dragStart(dropdata) {
94
        this.reactive.dispatch('sectionDrag', [dropdata.id], true);
95
    }
96
 
97
    /**
98
     * The element end start hook.
99
     *
100
     * @param {Object} dropdata the dropdata
101
     */
102
    dragEnd(dropdata) {
103
        this.reactive.dispatch('sectionDrag', [dropdata.id], false);
104
    }
105
 
106
    /**
107
     * Get the draggable data of this component.
108
     *
109
     * @returns {Object} exported course module drop data
110
     */
111
    _getDraggableData() {
112
        const exporter = this.reactive.getExporter();
113
        return exporter.sectionDraggableData(this.reactive.state, this.id);
114
    }
115
 
116
    /**
117
     * Validate if the drop data can be dropped over the component.
118
     *
119
     * @param {Object} dropdata the exported drop data.
120
     * @returns {boolean}
121
     */
122
    validateDropData(dropdata) {
123
        // Course module validation.
124
        if (dropdata?.type === 'cm') {
125
            // Prevent content loops with subsections.
1441 ariadna 126
            if (this.section?.component && dropdata?.hasdelegatedsection === true) {
1 efrain 127
                return false;
128
            }
129
            // The first section element is already there so we can ignore it.
130
            const firstcmid = this.section?.cmlist[0];
131
            return dropdata.id !== firstcmid;
132
        }
133
        return false;
134
    }
135
 
136
    /**
137
     * Display the component dropzone.
138
     */
139
    showDropZone() {
140
        this.element.classList.add(this.classes.DROPZONE);
141
    }
142
 
143
    /**
144
     * Hide the component dropzone.
145
     */
146
    hideDropZone() {
147
        this.element.classList.remove(this.classes.DROPZONE);
148
    }
149
 
150
    /**
151
     * Drop event handler.
152
     *
153
     * @param {Object} dropdata the accepted drop data
154
     * @param {Event} event the drop event
155
     */
156
    drop(dropdata, event) {
157
        // Call the move mutation.
158
        if (dropdata.type == 'cm') {
159
            const mutation = (event.altKey) ? 'cmDuplicate' : 'cmMove';
160
            this.reactive.dispatch(mutation, [dropdata.id], this.id, this.section?.cmlist[0]);
161
        }
162
    }
163
}