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
 * Reactive module for category manager
18
 *
19
 * @module qbank_managecategories/categorymanager
20
 */
21
 
22
import {Reactive} from 'core/reactive';
23
import {get_string as getString} from 'core/str';
24
import {mutations} from 'qbank_managecategories/mutations';
25
import {eventTypes, notifyQbankManagecategoriesStateUpdated} from 'qbank_managecategories/events';
26
import Ajax from "core/ajax";
27
import Notification from "core/notification";
28
import ModalForm from 'core_form/modalform';
29
 
30
const SELECTORS = {
31
    CATEGORY_LIST: '.qbank_managecategories-categorylist',
32
    CONTEXT: '.qbank_managecategories-categorylist[data-contextid]',
33
    CATEGORY_ITEM: '.qbank_managecategories-item[data-categoryid]',
34
    CATEGORY_ROOT: '#categoryroot',
35
    SHOWDESCRIPTIONS_TOGGLE: '#showdescriptions-toggle',
36
    ADD_EDIT_BUTTON: '[data-action="addeditcategory"]',
37
};
38
 
39
const CLASSES = {
40
    DRAGHANDLE: 'draghandle',
41
    DANGER: 'alert-danger',
42
};
43
 
44
/**
45
 * Load the initial state.
46
 *
47
 * This iterates over the initial tree of category items, and captures the data required for the state from each category.
48
 * It also captures a count of the number of children in each list.
49
 *
50
 * @param {Reactive} reactive
51
 * @return {Promise<void>}
52
 */
53
const loadState = async(reactive) => {
54
    const rootElement = document.querySelector(SELECTORS.CATEGORY_ROOT);
55
    const stateData = {
56
        page: {
57
            contextid: rootElement.dataset.contextid,
58
            showdescriptions: document.querySelector(SELECTORS.SHOWDESCRIPTIONS_TOGGLE).checked,
59
        },
60
        categories: [],
61
        categoryLists: [],
62
    };
63
    const listItems = document.querySelectorAll(SELECTORS.CATEGORY_ITEM);
64
    listItems.forEach(item => {
65
        stateData.categories.push({
66
            id: item.dataset.categoryid,
67
            name: item.dataset.categoryname,
68
            parent: item.dataset.parent,
69
            contextid: item.dataset.contextid,
70
            sortorder: item.dataset.sortorder,
71
            draghandle: item.classList.contains(CLASSES.DRAGHANDLE),
72
        });
73
    });
74
    const categoryLists = document.querySelectorAll(SELECTORS.CATEGORY_LIST);
75
    categoryLists.forEach(categoryList => {
76
        stateData.categoryLists.push({
77
            id: categoryList.dataset.categoryid,
78
            childCount: categoryList.querySelectorAll(SELECTORS.CATEGORY_ITEM).length,
79
        });
80
    });
81
    reactive.setInitialState(stateData);
82
};
83
 
84
/**
85
 * Reactive instance for the category manager.
86
 */
87
class CategoryManager extends Reactive {
88
    /**
89
     * Move a category to a new position within the given parent.
90
     *
91
     * This will call the move_category web service function to re-order the categories, then update
92
     * the state with the returned updates.
93
     *
94
     * @param {Number} categoryId The ID of the category being moved.
95
     * @param {Number} targetParentId The ID of the destination parent category (this may not have changed).
96
     * @param {Number} precedingSiblingId The ID of the category to put the moved category after.
97
     *     This may be null if moving to the top of a list.
98
     */
99
    moveCategory(
100
        categoryId,
101
        targetParentId,
102
        precedingSiblingId = null,
103
    ) {
104
        const call = {
105
            methodname: 'qbank_managecategories_move_category',
106
            args: {
107
                pagecontextid: this.state.page.contextid,
108
                categoryid: categoryId,
109
                targetparentid: targetParentId,
110
                precedingsiblingid: precedingSiblingId,
111
            }
112
        };
113
        Ajax.call([call])[0]
114
            .then((stateUpdates) => {
115
                this.stateManager.processUpdates(stateUpdates);
116
                return stateUpdates;
117
            })
118
            .catch(error => {
119
                Notification.addNotification({
120
                    message: error.message,
121
                    type: 'error',
122
                });
123
                document.getElementsByClassName(CLASSES.DANGER)[0]?.scrollIntoView();
124
            });
125
    }
126
 
127
    /**
128
     * Return title for the add/edit modal.
129
     *
130
     * @param {boolean} isEdit is 'add' or 'edit' form
131
     * @returns {String} title string
132
     */
133
    getTitle(isEdit) {
134
        return getString(isEdit ? 'editcategory' : 'addcategory', 'question');
135
    }
136
 
137
    /**
138
     * Return save button label for the add/edit modal.
139
     *
140
     * @param {boolean} isEdit is 'add' or 'edit' form
141
     * @returns {String} save string
142
     */
143
    getSave(isEdit) {
144
        return isEdit ? getString('savechanges', 'core') : getString('addcategory', 'question');
145
    }
146
 
147
    /**
148
     * Function handling display of modal form.
149
     *
150
     * @param {Event} e The click event triggering the modal.
151
     */
152
    showEditModal(e) {
153
        const addEditButton = e.target.closest(SELECTORS.ADD_EDIT_BUTTON);
154
 
155
        // Return if it is not 'addeditcategory' button.
156
        if (!addEditButton) {
157
            return;
158
        }
159
 
160
        // Return if the action type is not specified.
161
        if (!addEditButton.dataset.actiontype) {
162
            return;
163
        }
164
 
165
        e.preventDefault();
166
        // Data for the modal.
167
        const title = categorymanager.getTitle(addEditButton.dataset.actiontype === 'edit');
168
        const save = categorymanager.getSave(addEditButton.dataset.actiontype === 'edit');
169
        const cmid = addEditButton.dataset.cmid;
170
        const courseid = addEditButton.dataset.courseid;
171
        const questioncount = addEditButton.dataset.questioncount;
172
        let contextid = addEditButton.dataset.contextid;
173
        let categoryid = null;
174
        let sortorder = null;
175
        let parent = null;
176
        const categoryItem = e.target.closest(SELECTORS.CATEGORY_ITEM);
177
        if (categoryItem) {
178
            contextid = categoryItem.dataset.contextid;
179
            categoryid = categoryItem.dataset.categoryid;
180
            sortorder = categoryItem.dataset.sortorder;
181
            const parentContext = categoryItem.closest(SELECTORS.CONTEXT);
182
            parent = categoryItem.dataset.parent + ',' + parentContext.dataset.contextid;
183
        }
184
 
185
        // Call the modal.
186
        const modalForm = new ModalForm({
187
            formClass: "qbank_managecategories\\form\\question_category_edit_form",
188
            args: {
189
                cmid,
190
                courseid,
191
                questioncount,
192
                contextid,
193
                categoryid,
194
                sortorder,
195
                parent,
196
            },
197
            modalConfig: {
198
                title: title,
199
                large: true,
200
            },
201
            saveButtonText: save,
202
            returnFocus: addEditButton,
203
        });
204
        // Once the form has been submitted via the web service, update the state with the new or updated
205
        // category based on the web service response.
206
        modalForm.addEventListener(modalForm.events.FORM_SUBMITTED, (response) => {
207
            categorymanager.stateManager.processUpdates(response.detail);
208
        });
209
        // Show the form.
210
        modalForm.show();
211
    }
212
}
213
 
214
export const categorymanager = new CategoryManager({
215
    name: 'qtype_managecategories_categorymanager',
216
    eventName: eventTypes.qbankManagecategoriesStateUpdated,
217
    eventDispatch: notifyQbankManagecategoriesStateUpdated,
218
    mutations,
219
});
220
 
221
/**
222
 * Load the initial state.
223
 */
224
export const init = () => {
225
    loadState(categorymanager);
226
};