Your IP : 216.73.216.95


Current Path : /var/www/ljmtc/cbt/mod/forum/amd/build/local/grades/
Upload File :
Current File : /var/www/ljmtc/cbt/mod/forum/amd/build/local/grades/grader.min.js.map

{"version":3,"sources":["../../../src/local/grades/grader.js"],"names":["templateNames","grader","app","gradingPanel","error","searchResults","status","displayUserPicker","root","html","pickerRegion","querySelector","Selectors","regions","Templates","replaceNodeContents","fetchContentFromRender","js","getUpdateUserContentFunction","getContentForUser","getGradeForUser","saveGradeForUser","firstLoad","user","spinner","Promise","all","id","then","userGrade","moduleReplace","render","templatename","grade","gradingPanelHtml","gradingPanelJS","panelContainer","gradingPanelContainer","panel","form","addEventListener","event","preventDefault","scrollTop","resolve","showSearchResultContainer","bodyContainer","userPickerContainer","searchResultsContainer","classList","add","remove","hideSearchResultContainer","showUserSearchInput","toggleSearchButton","searchContainer","searchInput","setAttribute","gradingInfoContainer","parentElement","collapseGradingDrawer","buttons","focus","hideUserSearchInput","removeAttribute","value","searchForUsers","userList","searchTerm","toLowerCase","filter","fullname","includes","renderSearchResults","users","renderForPromise","registerEventListeners","graderLayout","userPicker","saveGradeFunction","graderContainer","getContainer","toggleSearch","searchInputContainer","userSearchContainer","userSearchInput","e","target","closest","toggleFullscreen","stopImmediatePropagation","closeGrader","close","saveGrade","currentUser","getAttribute","innerHTML","selectUserButton","selectUser","userId","find","setUserId","showUser","DrawerEvents","DRAWER_HIDDEN","drawerRoot","setContentContainerMargin","DRAWER_SHOWN","offsetWidth","rightMargin","contentContainer","moduleContainer","style","marginRight","getSaveUserGradeFunction","setGradeForUser","gradingPanelErrors","values","sendStudentNotifications","result","success","addToast","failed","displayGradingError","err","message","errorString","launch","getListOfUsers","initialUserId","moduleName","courseName","courseUrl","focusOnClose","length","addNotification","type","fullscreen","showLoader","drawer","show","defaultsendnotifications","updateUserContent","userIds","map","statusContainer","renderContext","hasgrade","index","indexOf","total","catch","rootNode","view","userid","Modal","create","title","large","types","CANCEL","modal","getRoot","on","ModalEvents","hidden","destroy","output","document","createElement","renderGradeTemplate","gradeHTML","gradeJS","gradeReplace","setBody","outerHTML"],"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/grader\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 */\nimport Templates from 'core/templates';\nimport Selectors from './local/grader/selectors';\nimport getUserPicker from './local/grader/user_picker';\nimport {createLayout as createFullScreenWindow} from 'mod_forum/local/layout/fullscreen';\nimport getGradingPanelFunctions from './local/grader/gradingpanel';\nimport {add as addToast} from 'core/toast';\nimport {addNotification} from 'core/notification';\nimport {get_string as getString} from 'core/str';\nimport {failedUpdate} from 'core_grades/grades/grader/gradingpanel/normalise';\nimport {addIconToContainerWithPromise} from 'core/loadingicon';\nimport {debounce} from 'core/utils';\nimport {fillInitialValues} from 'core_grades/grades/grader/gradingpanel/comparison';\nimport * as Modal from 'core/modal_factory';\nimport * as ModalEvents from 'core/modal_events';\nimport {subscribe} from 'core/pubsub';\nimport DrawerEvents from 'core/drawer_events';\n\nconst templateNames = {\n    grader: {\n        app: 'mod_forum/local/grades/grader',\n        gradingPanel: {\n            error: 'mod_forum/local/grades/local/grader/gradingpanel/error',\n        },\n        searchResults: 'mod_forum/local/grades/local/grader/user_picker/user_search',\n        status: 'mod_forum/local/grades/local/grader/status',\n    },\n};\n\n/**\n * Helper function that replaces the user picker placeholder with what we get back from the user picker class.\n *\n * @param {HTMLElement} root\n * @param {String} html\n */\nconst displayUserPicker = (root, html) => {\n    const pickerRegion = root.querySelector(Selectors.regions.pickerRegion);\n    Templates.replaceNodeContents(pickerRegion, html, '');\n};\n\n/**\n * To be removed, this is now done as a part of Templates.renderForPromise()\n *\n * @param {String} html\n * @param {String} js\n * @return {[*, *]}\n */\nconst fetchContentFromRender = (html, js) => {\n    return [html, js];\n};\n\n/**\n * Here we build the function that is passed to the user picker that'll handle updating the user content area\n * of the grading interface.\n *\n * @param {HTMLElement} root\n * @param {Function} getContentForUser\n * @param {Function} getGradeForUser\n * @param {Function} saveGradeForUser\n * @return {Function}\n */\nconst getUpdateUserContentFunction = (root, getContentForUser, getGradeForUser, saveGradeForUser) => {\n    let firstLoad = true;\n\n    return async(user) => {\n        const spinner = firstLoad ? null : addIconToContainerWithPromise(root);\n        const [\n            [html, js],\n            userGrade,\n        ] = await Promise.all([\n            getContentForUser(user.id).then(fetchContentFromRender),\n            getGradeForUser(user.id),\n        ]);\n        Templates.replaceNodeContents(root.querySelector(Selectors.regions.moduleReplace), html, js);\n\n        const [\n            gradingPanelHtml,\n            gradingPanelJS\n        ] = await Templates.render(userGrade.templatename, userGrade.grade).then(fetchContentFromRender);\n        const panelContainer = root.querySelector(Selectors.regions.gradingPanelContainer);\n        const panel = panelContainer.querySelector(Selectors.regions.gradingPanel);\n        Templates.replaceNodeContents(panel, gradingPanelHtml, gradingPanelJS);\n\n        const form = panel.querySelector('form');\n        fillInitialValues(form);\n\n        form.addEventListener('submit', event => {\n            saveGradeForUser(user);\n            event.preventDefault();\n        });\n\n        panelContainer.scrollTop = 0;\n        firstLoad = false;\n\n        if (spinner) {\n            spinner.resolve();\n        }\n        return userGrade;\n    };\n};\n\n/**\n * Show the search results container and hide the user picker and body content.\n *\n * @param {HTMLElement} bodyContainer The container element for the body content\n * @param {HTMLElement} userPickerContainer The container element for the user picker\n * @param {HTMLElement} searchResultsContainer The container element for the search results\n */\nconst showSearchResultContainer = (bodyContainer, userPickerContainer, searchResultsContainer) => {\n    bodyContainer.classList.add('hidden');\n    userPickerContainer.classList.add('hidden');\n    searchResultsContainer.classList.remove('hidden');\n};\n\n/**\n * Hide the search results container and show the user picker and body content.\n *\n * @param {HTMLElement} bodyContainer The container element for the body content\n * @param {HTMLElement} userPickerContainer The container element for the user picker\n * @param {HTMLElement} searchResultsContainer The container element for the search results\n */\nconst hideSearchResultContainer = (bodyContainer, userPickerContainer, searchResultsContainer) => {\n    bodyContainer.classList.remove('hidden');\n    userPickerContainer.classList.remove('hidden');\n    searchResultsContainer.classList.add('hidden');\n};\n\n/**\n * Toggles the visibility of the user search.\n *\n * @param {HTMLElement} toggleSearchButton The button that toggles the search\n * @param {HTMLElement} searchContainer The container element for the user search\n * @param {HTMLElement} searchInput The input element for searching\n */\nconst showUserSearchInput = (toggleSearchButton, searchContainer, searchInput) => {\n    searchContainer.classList.remove('collapsed');\n    toggleSearchButton.setAttribute('aria-expanded', 'true');\n    toggleSearchButton.classList.add('expand');\n    toggleSearchButton.classList.remove('collapse');\n\n    // Hide the grading info container from screen reader.\n    const gradingInfoContainer = searchContainer.parentElement.querySelector(Selectors.regions.gradingInfoContainer);\n    gradingInfoContainer.setAttribute('aria-hidden', 'true');\n\n    // Hide the collapse grading drawer button from screen reader.\n    const collapseGradingDrawer = searchContainer.parentElement.querySelector(Selectors.buttons.collapseGradingDrawer);\n    collapseGradingDrawer.setAttribute('aria-hidden', 'true');\n    collapseGradingDrawer.setAttribute('tabindex', '-1');\n\n    searchInput.focus();\n};\n\n/**\n * Toggles the visibility of the user search.\n *\n * @param {HTMLElement} toggleSearchButton The button that toggles the search\n * @param {HTMLElement} searchContainer The container element for the user search\n * @param {HTMLElement} searchInput The input element for searching\n */\nconst hideUserSearchInput = (toggleSearchButton, searchContainer, searchInput) => {\n    searchContainer.classList.add('collapsed');\n    toggleSearchButton.setAttribute('aria-expanded', 'false');\n    toggleSearchButton.classList.add('collapse');\n    toggleSearchButton.classList.remove('expand');\n    toggleSearchButton.focus();\n\n    // Show the grading info container to screen reader.\n    const gradingInfoContainer = searchContainer.parentElement.querySelector(Selectors.regions.gradingInfoContainer);\n    gradingInfoContainer.removeAttribute('aria-hidden');\n\n    // Show the collapse grading drawer button from screen reader.\n    const collapseGradingDrawer = searchContainer.parentElement.querySelector(Selectors.buttons.collapseGradingDrawer);\n    collapseGradingDrawer.removeAttribute('aria-hidden');\n    collapseGradingDrawer.setAttribute('tabindex', '0');\n\n    searchInput.value = '';\n};\n\n/**\n * Find the list of users who's names include the given search term.\n *\n * @param {Array} userList List of users for the grader\n * @param {String} searchTerm The search term to match\n * @return {Array}\n */\nconst searchForUsers = (userList, searchTerm) => {\n    if (searchTerm === '') {\n        return userList;\n    }\n\n    searchTerm = searchTerm.toLowerCase();\n\n    return userList.filter((user) => {\n        return user.fullname.toLowerCase().includes(searchTerm);\n    });\n};\n\n/**\n * Render the list of users in the search results area.\n *\n * @param {HTMLElement} searchResultsContainer The container element for search results\n * @param {Array} users The list of users to display\n */\nconst renderSearchResults = async(searchResultsContainer, users) => {\n    const {html, js} = await Templates.renderForPromise(templateNames.grader.searchResults, {users});\n    Templates.replaceNodeContents(searchResultsContainer, html, js);\n};\n\n/**\n * Add click handlers to the buttons in the header of the grading interface.\n *\n * @param {HTMLElement} graderLayout\n * @param {Object} userPicker\n * @param {Function} saveGradeFunction\n * @param {Array} userList List of users for the grader.\n */\nconst registerEventListeners = (graderLayout, userPicker, saveGradeFunction, userList) => {\n    const graderContainer = graderLayout.getContainer();\n    const toggleSearchButton = graderContainer.querySelector(Selectors.buttons.toggleSearch);\n    const searchInputContainer = graderContainer.querySelector(Selectors.regions.userSearchContainer);\n    const searchInput = searchInputContainer.querySelector(Selectors.regions.userSearchInput);\n    const bodyContainer = graderContainer.querySelector(Selectors.regions.bodyContainer);\n    const userPickerContainer = graderContainer.querySelector(Selectors.regions.pickerRegion);\n    const searchResultsContainer = graderContainer.querySelector(Selectors.regions.searchResultsContainer);\n\n    graderContainer.addEventListener('click', (e) => {\n        if (e.target.closest(Selectors.buttons.toggleFullscreen)) {\n            e.stopImmediatePropagation();\n            e.preventDefault();\n            graderLayout.toggleFullscreen();\n\n            return;\n        }\n\n        if (e.target.closest(Selectors.buttons.closeGrader)) {\n            e.stopImmediatePropagation();\n            e.preventDefault();\n\n            graderLayout.close();\n\n            return;\n        }\n\n        if (e.target.closest(Selectors.buttons.saveGrade)) {\n            saveGradeFunction(userPicker.currentUser);\n        }\n\n        if (e.target.closest(Selectors.buttons.toggleSearch)) {\n            if (toggleSearchButton.getAttribute('aria-expanded') === 'true') {\n                // Search is open so let's close it.\n                hideUserSearchInput(toggleSearchButton, searchInputContainer, searchInput);\n                hideSearchResultContainer(bodyContainer, userPickerContainer, searchResultsContainer);\n                searchResultsContainer.innerHTML = '';\n            } else {\n                // Search is closed so let's open it.\n                showUserSearchInput(toggleSearchButton, searchInputContainer, searchInput);\n                showSearchResultContainer(bodyContainer, userPickerContainer, searchResultsContainer);\n                renderSearchResults(searchResultsContainer, userList);\n            }\n\n            return;\n        }\n\n        const selectUserButton = e.target.closest(Selectors.buttons.selectUser);\n        if (selectUserButton) {\n            const userId = selectUserButton.getAttribute('data-userid');\n            const user = userList.find(user => user.id == userId);\n            userPicker.setUserId(userId);\n            userPicker.showUser(user);\n            hideUserSearchInput(toggleSearchButton, searchInputContainer, searchInput);\n            hideSearchResultContainer(bodyContainer, userPickerContainer, searchResultsContainer);\n            searchResultsContainer.innerHTML = '';\n        }\n    });\n\n    // Debounce the search input so that it only executes 300 milliseconds after the user has finished typing.\n    searchInput.addEventListener('input', debounce(() => {\n        const users = searchForUsers(userList, searchInput.value);\n        renderSearchResults(searchResultsContainer, users);\n    }, 300));\n\n    // Remove the right margin of the content container when the grading panel is hidden so that it expands to full-width.\n    subscribe(DrawerEvents.DRAWER_HIDDEN, (drawerRoot) => {\n        const gradingPanel = drawerRoot[0];\n        if (gradingPanel.querySelector(Selectors.regions.gradingPanel)) {\n            setContentContainerMargin(graderContainer, 0);\n        }\n    });\n\n    // Bring back the right margin of the content container when the grading panel is shown to give space for the grading panel.\n    subscribe(DrawerEvents.DRAWER_SHOWN, (drawerRoot) => {\n        const gradingPanel = drawerRoot[0];\n        if (gradingPanel.querySelector(Selectors.regions.gradingPanel)) {\n            setContentContainerMargin(graderContainer, gradingPanel.offsetWidth);\n        }\n    });\n};\n\n/**\n * Adjusts the right margin of the content container.\n *\n * @param {HTMLElement} graderContainer The container for the grader app.\n * @param {Number} rightMargin The right margin value.\n */\nconst setContentContainerMargin = (graderContainer, rightMargin) => {\n    const contentContainer = graderContainer.querySelector(Selectors.regions.moduleContainer);\n    if (contentContainer) {\n        contentContainer.style.marginRight = `${rightMargin}px`;\n    }\n};\n\n/**\n * Get the function used to save a user grade.\n *\n * @param {HTMLElement} root The container for the grader\n * @param {Function} setGradeForUser The function that will be called.\n * @return {Function}\n */\nconst getSaveUserGradeFunction = (root, setGradeForUser) => {\n    return async(user) => {\n        try {\n            root.querySelector(Selectors.regions.gradingPanelErrors).innerHTML = '';\n            const result = await setGradeForUser(\n                user.id,\n                root.querySelector(Selectors.values.sendStudentNotifications).value,\n                root.querySelector(Selectors.regions.gradingPanel)\n            );\n            if (result.success) {\n                addToast(await getString('grades:gradesavedfor', 'mod_forum', user));\n            }\n            if (result.failed) {\n                displayGradingError(root, user, result.error);\n            }\n\n            return result;\n        } catch (err) {\n            displayGradingError(root, user, err);\n\n            return failedUpdate(err);\n        }\n    };\n};\n\n/**\n * Display a grading error, typically from a failed save.\n *\n * @param {HTMLElement} root The container for the grader\n * @param {Object} user The user who was errored\n * @param {Object} err The details of the error\n */\nconst displayGradingError = async(root, user, err) => {\n    const [\n        {html, js},\n        errorString\n    ] = await Promise.all([\n        Templates.renderForPromise(templateNames.grader.gradingPanel.error, {error: err}),\n        await getString('grades:gradesavefailed', 'mod_forum', {error: err.message, ...user}),\n    ]);\n\n    Templates.replaceNodeContents(root.querySelector(Selectors.regions.gradingPanelErrors), html, js);\n    addToast(errorString);\n};\n\n/**\n * Launch the grader interface with the specified parameters.\n *\n * @param {Function} getListOfUsers A function to get the list of users\n * @param {Function} getContentForUser A function to get the content for a specific user\n * @param {Function} getGradeForUser A function get the grade details for a specific user\n * @param {Function} setGradeForUser A function to set the grade for a specific user\n * @param {Object} Preferences for the launch function\n */\nexport const launch = async(getListOfUsers, getContentForUser, getGradeForUser, setGradeForUser, {\n    initialUserId = null,\n    moduleName,\n    courseName,\n    courseUrl,\n    sendStudentNotifications,\n    focusOnClose = null,\n} = {}) => {\n\n    // We need all of these functions to be executed in series, if one step runs before another the interface\n    // will not work.\n\n    // We need this promise to resolve separately so that we can avoid loading the whole interface if there are no users.\n    const userList = await getListOfUsers();\n    if (!userList.length) {\n        addNotification({\n            message: await getString('nouserstograde', 'core_grades'),\n            type: \"error\",\n        });\n        return;\n    }\n\n    // Now that we have confirmed there are at least some users let's boot up the grader interface.\n    const [\n        graderLayout,\n        {html, js},\n    ] = await Promise.all([\n        createFullScreenWindow({\n            fullscreen: false,\n            showLoader: false,\n            focusOnClose,\n        }),\n        Templates.renderForPromise(templateNames.grader.app, {\n            moduleName,\n            courseName,\n            courseUrl,\n            drawer: {show: true},\n            defaultsendnotifications: sendStudentNotifications,\n        }),\n    ]);\n\n    const graderContainer = graderLayout.getContainer();\n\n    const saveGradeFunction = getSaveUserGradeFunction(graderContainer, setGradeForUser);\n\n    Templates.replaceNodeContents(graderContainer, html, js);\n    const updateUserContent = getUpdateUserContentFunction(graderContainer, getContentForUser, getGradeForUser, saveGradeFunction);\n\n    const userIds = userList.map(user => user.id);\n    const statusContainer = graderContainer.querySelector(Selectors.regions.statusContainer);\n    // Fetch the userpicker for display.\n    const userPicker = await getUserPicker(\n        userList,\n        async(user) => {\n            const userGrade = await updateUserContent(user);\n            const renderContext = {\n                status: userGrade.hasgrade,\n                index: userIds.indexOf(user.id) + 1,\n                total: userList.length\n            };\n            Templates.render(templateNames.grader.status, renderContext).then(html => {\n                statusContainer.innerHTML = html;\n                return html;\n            }).catch();\n        },\n        saveGradeFunction,\n        {\n            initialUserId,\n        },\n    );\n\n    // Register all event listeners.\n    registerEventListeners(graderLayout, userPicker, saveGradeFunction, userList);\n\n    // Display the newly created user picker.\n    displayUserPicker(graderContainer, userPicker.rootNode);\n};\n\n/**\n * Show the grade for a specific user.\n *\n * @param {Function} getGradeForUser A function get the grade details for a specific user\n * @param {Number} userid The ID of a specific user\n * @param {String} moduleName the name of the module\n */\nexport const view = async(getGradeForUser, userid, moduleName, {\n    focusOnClose = null,\n} = {}) => {\n\n    const [\n        userGrade,\n        modal,\n    ] = await Promise.all([\n        getGradeForUser(userid),\n        Modal.create({\n            title: moduleName,\n            large: true,\n            type: Modal.types.CANCEL\n        }),\n    ]);\n\n    const spinner = addIconToContainerWithPromise(modal.getRoot());\n\n    // Handle hidden event.\n    modal.getRoot().on(ModalEvents.hidden, function() {\n        // Destroy when hidden.\n        modal.destroy();\n        if (focusOnClose) {\n            try {\n                focusOnClose.focus();\n            } catch (e) {\n                // eslint-disable-line\n            }\n        }\n    });\n\n    modal.show();\n    const output = document.createElement('div');\n    const {html, js} = await Templates.renderForPromise('mod_forum/local/grades/view_grade', userGrade);\n    Templates.replaceNodeContents(output, html, js);\n\n    // Note: We do not use await here because it messes with the Modal transitions.\n    const [gradeHTML, gradeJS] = await renderGradeTemplate(userGrade);\n    const gradeReplace = output.querySelector('[data-region=\"grade-template\"]');\n    Templates.replaceNodeContents(gradeReplace, gradeHTML, gradeJS);\n    modal.setBody(output.outerHTML);\n    spinner.resolve();\n};\n\nconst renderGradeTemplate = async(userGrade) => {\n    const {html, js} = await Templates.renderForPromise(userGrade.templatename, userGrade.grade);\n    return [html, js];\n};\nexport {getGradingPanelFunctions};\n"],"file":"grader.min.js"}