MDL-66074 mod_forum: Implement spinner for user change
[moodle.git] / mod / forum / amd / build / local / grades / local / grader / user_picker.min.js.map
1 {"version":3,"sources":["../../../../../src/local/grades/local/grader/user_picker.js"],"names":["UserPicker","userList","showUserCallback","preChangeUserCallback","currentUserIndex","render","bind","setUserId","userId","userIndex","findIndex","user","id","parseInt","Error","root","document","createElement","renderNavigator","html","js","Templates","replaceNodeContents","showUser","currentUser","registerEventListeners","renderForPromise","context","Promise","all","renderUserChange","userRegion","querySelector","Selectors","regions","addEventListener","e","button","target","closest","actions","changeUser","whole","spinner","updateIndex","dataset","direction","resolve","length","total","displayIndex","users","initialUserId","userPicker"],"mappings":"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","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 * This module will tie together all of the different calls the gradable module will make.\n *\n * @module     mod_forum/local/grades/local/grader/user_picker\n * @package    mod_forum\n * @copyright  2019 Mathew May <mathew.solutions>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Templates from 'core/templates';\nimport Selectors from './user_picker/selectors';\nimport {addIconToContainerWithPromise} from 'core/loadingicon';\n\nconst templatePath = 'mod_forum/local/grades/local/grader';\n\nclass UserPicker {\n\n    /**\n     * Constructor for the User Picker.\n     *\n     * @param {Array} userList List of users\n     * @param {Function} showUserCallback The callback used to display the user\n     * @param {Function} preChangeUserCallback The callback to use before changing user\n     */\n    constructor(userList, showUserCallback, preChangeUserCallback) {\n        this.userList = userList;\n        this.showUserCallback = showUserCallback;\n        this.preChangeUserCallback = preChangeUserCallback;\n        this.currentUserIndex = 0;\n\n        // Ensure that render is bound correctly.\n        this.render = this.render.bind(this);\n        this.setUserId = this.setUserId.bind(this);\n    }\n\n    /**\n     * Set the current userid without rendering the change.\n     * To show the user, call showUser too.\n     *\n     * @param {Number} userId\n     */\n    setUserId(userId) {\n        // Determine the current index based on the user ID.\n        const userIndex = this.userList.findIndex(user => {\n            return user.id === parseInt(userId);\n        });\n\n        if (userIndex === -1) {\n            throw Error(`User with id ${userId} not found`);\n        }\n\n        this.currentUserIndex = userIndex;\n    }\n\n    /**\n     * Render the user picker.\n     */\n    async render() {\n        // Create the root node.\n        this.root = document.createElement('div');\n\n        const {html, js} = await this.renderNavigator();\n        Templates.replaceNodeContents(this.root, html, js);\n\n        // Call the showUser function to show the first user immediately.\n        await this.showUser(this.currentUser);\n\n        // Ensure that the event listeners are all bound.\n        this.registerEventListeners();\n    }\n\n    /**\n     * Render the navigator itself.\n     *\n     * @returns {Promise}\n     */\n    renderNavigator() {\n        return Templates.renderForPromise(`${templatePath}/user_picker`, {});\n    }\n\n    /**\n     * Render the current user details for the picker.\n     *\n     * @param {Object} context The data used to render the user picker.\n     * @returns {Promise}\n     */\n    renderUserChange(context) {\n        return Templates.renderForPromise(`${templatePath}/user_picker/user`, context);\n    }\n\n    /**\n     * Show the specified user in the picker.\n     *\n     * @param {Object} user\n     */\n    async showUser(user) {\n        const [{html, js}] = await Promise.all([this.renderUserChange(user), this.showUserCallback(user)]);\n        const userRegion = this.root.querySelector(Selectors.regions.userRegion);\n        Templates.replaceNodeContents(userRegion, html, js);\n    }\n\n    /**\n     * Register the event listeners for the user picker.\n     */\n    registerEventListeners() {\n        this.root.addEventListener('click', async e => {\n            const button = e.target.closest(Selectors.actions.changeUser);\n            if (button) {\n                const whole = document.querySelector('[data-region=\"unified-grader\"]');\n                const spinner = addIconToContainerWithPromise(whole);\n\n                await this.preChangeUserCallback(this.currentUser);\n                this.updateIndex(parseInt(button.dataset.direction));\n                await this.showUser(this.currentUser);\n\n                spinner.resolve();\n            }\n        });\n    }\n\n    /**\n     * Update the current user index.\n     *\n     * @param {Number} direction\n     * @returns {Number}}\n     */\n    updateIndex(direction) {\n        this.currentUserIndex += direction;\n\n        // Loop around the edges.\n        if (this.currentUserIndex < 0) {\n            this.currentUserIndex = this.userList.length - 1;\n        } else if (this.currentUserIndex > this.userList.length - 1) {\n            this.currentUserIndex = 0;\n        }\n\n        return this.currentUserIndex;\n    }\n\n    /**\n     * Get the details of the user currently shown with the total number of users, and the 1-indexed count of the\n     * current user.\n     *\n     * @returns {Object}\n     */\n    get currentUser() {\n        return {\n            ...this.userList[this.currentUserIndex],\n            total: this.userList.length,\n            displayIndex: this.currentUserIndex + 1,\n        };\n    }\n\n    /**\n     * Get the root node for the User Picker.\n     *\n     * @returns {HTMLElement}\n     */\n    get rootNode() {\n        return this.root;\n    }\n}\n\n/**\n * Create a new user picker.\n *\n * @param {Array} users The list of users\n * @param {Function} showUserCallback The function to call to show a specific user\n * @param {Function} preChangeUserCallback The fucntion to call to save the grade for the current user\n * @param {Number} [currentUserID] The userid of the current user\n * @returns {UserPicker}\n */\nexport default async(users, showUserCallback, preChangeUserCallback, {\n        initialUserId = null,\n    } = {}\n) => {\n    const userPicker = new UserPicker(users, showUserCallback, preChangeUserCallback);\n    if (initialUserId) {\n        userPicker.setUserId(initialUserId);\n    }\n    await userPicker.render();\n\n    return userPicker;\n};\n"],"file":"user_picker.min.js"}