Proyectos de Subversion Moodle

Rev

Autoría | Ultima modificación | Ver Log |

{"version":3,"file":"modal_question_bank_bulkmove.min.js","sources":["../src/modal_question_bank_bulkmove.js"],"sourcesContent":["// This file is part of Moodle - http://moodle.org/\n//\n// Moodle is free software: you can redistribute it and/or modify\n// it under the terms of the GNU General Public License as published by\n// the Free Software Foundation, either version 3 of the License, or\n// (at your option) any later version.\n//\n// Moodle is distributed in the hope that it will be useful,\n// but WITHOUT ANY WARRANTY; without even the implied warranty of\n// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the\n// GNU General Public License for more details.\n//\n// You should have received a copy of the GNU General Public License\n// along with Moodle.  If not, see <http://www.gnu.org/licenses/>.\n\n/**\n * Contain the logic for the bulkmove questions modal.\n *\n * @module     qbank_bulkmove/modal_question_bank_bulkmove\n * @copyright  2024 onwards Catalyst IT EU {@link https://catalyst-eu.net}\n * @author     Simon Adams <simon.adams@catalyst-eu.net>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Modal from 'core/modal';\nimport * as Fragment from 'core/fragment';\nimport {getString} from 'core/str';\nimport AutoComplete from 'core/form-autocomplete';\nimport {moveQuestions} from 'core_question/repository';\nimport Templates from 'core/templates';\nimport Notification from 'core/notification';\nimport Pending from 'core/pending';\n\n\nexport default class ModalQuestionBankBulkmove extends Modal {\n    static TYPE = 'qbank_bulkmove/bulkmove';\n\n    static SELECTORS = {\n        SAVE_BUTTON: '[data-action=\"bulkmovesave\"]',\n        SELECTED_QUESTIONS: 'table#categoryquestions input[id^=\"checkq\"]',\n        SEARCH_BANK: '#searchbanks',\n        SEARCH_CATEGORY: '.selectcategory',\n        QUESTION_CATEGORY_SELECTOR: '.question_category_selector',\n        CATEGORY_OPTIONS: '.selectcategory option',\n        BANK_OPTIONS: '#searchbanks option',\n        CATEGORY_ENHANCED_INPUT: '.search-categories input',\n        ORIGINAL_SELECTS: 'select.bulk-move',\n        CATEGORY_WARNING: '#searchcatwarning',\n        CATEGORY_SUGGESTION: '.search-categories span.form-autocomplete-downarrow',\n        CATEGORY_SELECTION: '.search-categories span[role=\"option\"][data-active-selection=\"true\"]',\n        CONFIRM_BUTTON: '.bulk-move-footer button[data-action=\"save\"]',\n        CANCEL_BUTTON: '.bulk-move-footer button[data-action=\"cancel\"]'\n    };\n\n    /**\n     * @param {integer} contextId The current bank context id.\n     * @param {integer} categoryId The current question category id.\n     */\n    static init(contextId, categoryId) {\n        document.addEventListener('click', (e) => {\n            const trigger = e.target;\n            if (trigger.className === 'dropdown-item' && trigger.getAttribute('name') === 'move') {\n                e.preventDefault();\n                ModalQuestionBankBulkmove.create({\n                    contextId,\n                    title: getString('bulkmoveheader', 'qbank_bulkmove'),\n                    show: true,\n                    categoryId: categoryId,\n                });\n            }\n        });\n    }\n\n    /**\n     * Set the initialised config on the class.\n     *\n     * @param {Object} modalConfig\n     */\n    configure(modalConfig) {\n        this.contextId = modalConfig.contextId;\n        this.targetBankContextId = modalConfig.contextId;\n        this.initSelectedCategoryId(modalConfig.categoryId);\n        modalConfig.removeOnClose = true;\n        super.configure(modalConfig);\n    }\n\n    /**\n     * Initialise the category select based on the data passed to the JS or if a filter is applied in the url.\n     * @param {integer} categoryId\n     */\n    initSelectedCategoryId(categoryId) {\n        const filter = new URLSearchParams(window.location.href).get('filter');\n        if (filter) {\n            const filteredCategoryId = JSON.parse(filter)?.category.values[0];\n            this.currentCategoryId = filteredCategoryId > 0 ? filteredCategoryId : null;\n            this.targetCategoryId = filteredCategoryId;\n            return;\n        }\n        this.currentCategoryId = categoryId;\n        this.targetCategoryId = categoryId;\n    }\n\n    /**\n     * Render the modal contents.\n     * @return {Promise}\n     */\n    show() {\n        void this.display(this.contextId, this.currentCategoryId);\n        return super.show();\n    }\n\n    /**\n     * Get the content to display and enhance the selects into auto complete fields.\n     * @param {integer} currentBankContextId\n     * @param {integer} currentCategoryId\n     */\n    async display(currentBankContextId, currentCategoryId) {\n        const displayPending = new Pending('qbank_bulkmove/bulk_move_modal');\n        this.bodyPromise = await Fragment.loadFragment(\n            'qbank_bulkmove',\n            'bulk_move',\n            currentBankContextId,\n            {\n                'categoryid': currentCategoryId,\n            }\n        );\n\n        await this.setBody(this.bodyPromise);\n        await this.enhanceSelects();\n        this.registerEnhancedEventListeners();\n        this.updateSaveButtonState();\n        displayPending.resolve();\n    }\n\n    /**\n     * Register event listeners on the enhanced selects. Must be done after they have been enhanced.\n     */\n    registerEnhancedEventListeners() {\n        document.querySelector(ModalQuestionBankBulkmove.SELECTORS.SEARCH_CATEGORY).addEventListener(\"change\", () => {\n            this.updateSaveButtonState();\n        });\n\n        document.querySelector(ModalQuestionBankBulkmove.SELECTORS.SEARCH_BANK).addEventListener(\"change\", async(e) => {\n            await this.updateCategorySelector(e.currentTarget.value);\n            this.updateSaveButtonState();\n        });\n\n        this.getModal().on(\"click\", ModalQuestionBankBulkmove.SELECTORS.SAVE_BUTTON, (e) => {\n            e.preventDefault();\n            void this.displayConfirmMove();\n        });\n    }\n\n    /**\n     * Update the body with a confirmation prompt and set confirm cancel buttons in the footer.\n     * @return {Promise<void>}\n     */\n    async displayConfirmMove() {\n        this.setTitle(getString('confirm', 'core'));\n        this.setBody(getString('confirmmove', 'qbank_bulkmove'));\n        if (!this.hasFooterContent()) {\n            // We don't have the footer yet so go grab it and register event listeners on the buttons.\n            this.setFooter(Templates.render('qbank_bulkmove/bulk_move_footer', {}));\n            await this.getFooterPromise();\n\n            document.querySelector(ModalQuestionBankBulkmove.SELECTORS.CONFIRM_BUTTON).addEventListener(\"click\", (e) => {\n                e.preventDefault();\n                this.moveQuestionsAfterConfirm(this.targetBankContextId, this.targetCategoryId);\n            });\n\n            document.querySelector(ModalQuestionBankBulkmove.SELECTORS.CANCEL_BUTTON).addEventListener(\"click\", (e) => {\n                e.preventDefault();\n                this.setTitle(getString('bulkmoveheader', 'qbank_bulkmove'));\n                this.setBodyContent(Templates.renderForPromise('core/loading', {}));\n                this.hideFooter();\n                this.display(this.targetBankContextId, this.targetCategoryId);\n            });\n        } else {\n            // We already have a footer so just show it.\n            this.showFooter();\n        }\n    }\n\n    /**\n     * Update the category selector based on the selected question bank.\n     *\n     * @param {Number} selectedBankCmId\n     * @return {Promise} Resolved when the update is complete.\n     */\n    updateCategorySelector(selectedBankCmId) {\n        if (!selectedBankCmId) {\n            this.updateCategorySelectorState(false);\n            return Promise.resolve();\n        } else {\n            return Fragment.loadFragment(\n                'core_question',\n                'category_selector',\n                this.contextId,\n                {\n                    'bankcmid': selectedBankCmId,\n                }\n            )\n            .then((html, js) => {\n                const categorySelector = document.querySelector(ModalQuestionBankBulkmove.SELECTORS.QUESTION_CATEGORY_SELECTOR);\n                return Templates.replaceNode(categorySelector, html, js);\n            })\n            .then(() => {\n                document.querySelector(ModalQuestionBankBulkmove.SELECTORS.CATEGORY_WARNING).classList.add('d-none');\n                return this.enhanceSelects();\n            })\n            .catch(Notification.exception);\n        }\n    }\n\n    /**\n     * Disable/enable the enhanced category selector field.\n     * @param {boolean} toEnable True to enable, false to disable the field.\n     */\n    updateCategorySelectorState(toEnable) {\n        const warning = document.querySelector(ModalQuestionBankBulkmove.SELECTORS.CATEGORY_WARNING);\n        const enhancedInput = document.querySelector(ModalQuestionBankBulkmove.SELECTORS.CATEGORY_ENHANCED_INPUT);\n        const suggestionButton = document.querySelector(ModalQuestionBankBulkmove.SELECTORS.CATEGORY_SUGGESTION);\n        const selection = document.querySelector(ModalQuestionBankBulkmove.SELECTORS.CATEGORY_SELECTION);\n\n        if (toEnable) {\n            warning.classList.add('d-none');\n            enhancedInput.removeAttribute('disabled');\n            suggestionButton.classList.remove('d-none');\n        } else {\n            warning.classList.remove('d-none');\n            enhancedInput.setAttribute('disabled', 'disabled');\n            suggestionButton.classList.add('d-none');\n            selection.click(); // Clear selected category.\n        }\n    }\n\n    /**\n     * Disable the button if the selected category is the same as the one the questions already belong to. Enable it otherwise.\n     */\n    updateSaveButtonState() {\n        const saveButton = document.querySelector(ModalQuestionBankBulkmove.SELECTORS.SAVE_BUTTON);\n        const categorySelector = document.querySelector(ModalQuestionBankBulkmove.SELECTORS.SEARCH_CATEGORY);\n        [this.targetCategoryId, this.targetBankContextId] = categorySelector.value.split(',');\n\n        if (this.targetCategoryId && this.targetCategoryId !== this.currentCategoryId) {\n            saveButton.removeAttribute('disabled');\n        } else {\n            saveButton.setAttribute('disabled', 'disabled');\n        }\n    }\n\n    /**\n     * Move the selected questions to their new target category.\n     * @param {integer} targetContextId the target bank context id.\n     * @param {integer} targetCategoryId the target question category id.\n     * @return {Promise<void>}\n     */\n    async moveQuestionsAfterConfirm(targetContextId, targetCategoryId) {\n        await this.setBody(Templates.render('core/loading', {}));\n        const qelements = document.querySelectorAll(ModalQuestionBankBulkmove.SELECTORS.SELECTED_QUESTIONS);\n        const questionids = [];\n        qelements.forEach((element) => {\n            if (element.checked) {\n                const name = element.getAttribute('name');\n                questionids.push(name.substr(1, name.length));\n            }\n        });\n        if (questionids.length === 0) {\n            await Notification.exception('No questions selected');\n        }\n\n        try {\n            window.location.href = await moveQuestions(\n                targetContextId,\n                targetCategoryId,\n                questionids.join(),\n                window.location.href\n            );\n        } catch (error) {\n            await Notification.exception(error);\n        }\n    }\n\n    /**\n     * Take the provided select options and enhance them into auto-complete fields.\n     *\n     * @return {Promise<Promise[]>}\n     */\n    async enhanceSelects() {\n        const placeholder = await getString('searchbyname', 'mod_quiz');\n\n        await AutoComplete.enhance(\n            ModalQuestionBankBulkmove.SELECTORS.SEARCH_BANK,\n            false,\n            'core_question/question_banks_datasource',\n            placeholder,\n            false,\n            true,\n            '',\n            true,\n        );\n\n        await AutoComplete.enhance(\n            ModalQuestionBankBulkmove.SELECTORS.SEARCH_CATEGORY,\n            false,\n            null,\n            placeholder,\n            false,\n            true,\n            '',\n            true,\n        );\n    }\n}\n"],"names":["ModalQuestionBankBulkmove","Modal","contextId","categoryId","document","addEventListener","e","trigger","target","className","getAttribute","preventDefault","create","title","show","configure","modalConfig","targetBankContextId","initSelectedCategoryId","removeOnClose","filter","URLSearchParams","window","location","href","get","filteredCategoryId","JSON","parse","_JSON$parse","category","values","currentCategoryId","targetCategoryId","this","display","super","currentBankContextId","displayPending","Pending","bodyPromise","Fragment","loadFragment","setBody","enhanceSelects","registerEnhancedEventListeners","updateSaveButtonState","resolve","querySelector","SELECTORS","SEARCH_CATEGORY","SEARCH_BANK","async","updateCategorySelector","currentTarget","value","getModal","on","SAVE_BUTTON","displayConfirmMove","setTitle","hasFooterContent","showFooter","setFooter","Templates","render","getFooterPromise","CONFIRM_BUTTON","moveQuestionsAfterConfirm","CANCEL_BUTTON","setBodyContent","renderForPromise","hideFooter","selectedBankCmId","then","html","js","categorySelector","QUESTION_CATEGORY_SELECTOR","replaceNode","CATEGORY_WARNING","classList","add","catch","Notification","exception","updateCategorySelectorState","Promise","toEnable","warning","enhancedInput","CATEGORY_ENHANCED_INPUT","suggestionButton","CATEGORY_SUGGESTION","selection","CATEGORY_SELECTION","removeAttribute","remove","setAttribute","click","saveButton","split","targetContextId","qelements","querySelectorAll","SELECTED_QUESTIONS","questionids","forEach","element","checked","name","push","substr","length","join","error","placeholder","AutoComplete","enhance","CATEGORY_OPTIONS","BANK_OPTIONS","ORIGINAL_SELECTS"],"mappings":"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"}