Sindbad~EG File Manager

Current Path : /var/www/html/aprender.faexito.org/grade/report/grader/amd/build/
Upload File :
Current File : /var/www/html/aprender.faexito.org/grade/report/grader/amd/build/collapse.min.js.map

{"version":3,"file":"collapse.min.js","sources":["../src/collapse.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 * Allow the user to show and hide columns of the report at will.\n *\n * @module    gradereport_grader/collapse\n * @copyright 2023 Mathew May <mathew.solutions>\n * @license   http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nimport * as Repository from 'gradereport_grader/collapse/repository';\nimport search_combobox from 'core/comboboxsearch/search_combobox';\nimport {renderForPromise, replaceNodeContents, replaceNode} from 'core/templates';\nimport {debounce} from 'core/utils';\nimport $ from 'jquery';\nimport {getStrings} from 'core/str';\nimport CustomEvents from \"core/custom_interaction_events\";\nimport storage from 'core/localstorage';\nimport {addIconToContainer} from 'core/loadingicon';\nimport Notification from 'core/notification';\nimport Pending from 'core/pending';\n\n// Contain our selectors within this file until they could be of use elsewhere.\nconst selectors = {\n    component: '.collapse-columns',\n    formDropdown: '.columnsdropdownform',\n    formItems: {\n        cancel: 'cancel',\n        save: 'save',\n        checked: 'input[type=\"checkbox\"]:checked',\n        currentlyUnchecked: 'input[type=\"checkbox\"]:not([data-action=\"selectall\"])',\n    },\n    hider: 'hide',\n    expand: 'expand',\n    colVal: '[data-col]',\n    itemVal: '[data-itemid]',\n    content: '[data-collapse=\"content\"]',\n    sort: '[data-collapse=\"sort\"]',\n    expandbutton: '[data-collapse=\"expandbutton\"]',\n    rangerowcell: '[data-collapse=\"rangerowcell\"]',\n    avgrowcell: '[data-collapse=\"avgrowcell\"]',\n    menu: '[data-collapse=\"menu\"]',\n    icons: '.data-collapse_gradeicons',\n    count: '[data-collapse=\"count\"]',\n    placeholder: '.collapsecolumndropdown [data-region=\"placeholder\"]',\n    fullDropdown: '.collapsecolumndropdown',\n    cellMenuButton: '.cellmenubtn',\n};\n\nconst countIndicator = document.querySelector(selectors.count);\n\nexport default class ColumnSearch extends search_combobox {\n\n    userID = -1;\n    courseID = null;\n    defaultSort = '';\n\n    nodes = [];\n\n    gradeStrings = null;\n    userStrings = null;\n    stringMap = [];\n\n    static init(userID, courseID, defaultSort) {\n        return new ColumnSearch(userID, courseID, defaultSort);\n    }\n\n    constructor(userID, courseID, defaultSort) {\n        super();\n        this.userID = userID;\n        this.courseID = courseID;\n        this.defaultSort = defaultSort;\n        this.component = document.querySelector(selectors.component);\n\n        const pendingPromise = new Pending();\n        // Display a loader whilst collapsing appropriate columns (based on the locally stored state for the current user).\n        addIconToContainer(document.querySelector('.gradeparent')).then((loader) => {\n            setTimeout(() => {\n                // Get the users' checked columns to change.\n                this.getDataset().forEach((item) => {\n                    this.nodesUpdate(item);\n                });\n                this.renderDefault();\n\n                // Once the grade categories have been re-collapsed, remove the loader and display the Gradebook setup content.\n                loader.remove();\n                document.querySelector('.gradereport-grader-table').classList.remove('d-none');\n            }, 10);\n        }).then(() => pendingPromise.resolve()).catch(Notification.exception);\n    }\n\n    /**\n     * The overall div that contains the searching widget.\n     *\n     * @returns {string}\n     */\n    componentSelector() {\n        return '.collapse-columns';\n    }\n\n    /**\n     * The dropdown div that contains the searching widget result space.\n     *\n     * @returns {string}\n     */\n    dropdownSelector() {\n        return '.searchresultitemscontainer';\n    }\n\n    /**\n     * The triggering div that contains the searching widget.\n     *\n     * @returns {string}\n     */\n    triggerSelector() {\n        return '.collapsecolumn';\n    }\n\n    /**\n     * Return the dataset that we will be searching upon.\n     *\n     * @returns {Array}\n     */\n    getDataset() {\n        if (!this.dataset) {\n            const cols = this.fetchDataset();\n            this.dataset = JSON.parse(cols) ? JSON.parse(cols).split(',') : [];\n        }\n        this.datasetSize = this.dataset.length;\n        return this.dataset;\n    }\n\n    /**\n     * Get the data we will be searching against in this component.\n     *\n     * @returns {string}\n     */\n    fetchDataset() {\n        return storage.get(`gradereport_grader_collapseditems_${this.courseID}_${this.userID}`);\n    }\n\n    /**\n     * Given a user performs an action, update the users' preferences.\n     */\n    setPreferences() {\n        storage.set(`gradereport_grader_collapseditems_${this.courseID}_${this.userID}`,\n            JSON.stringify(this.getDataset().join(','))\n        );\n    }\n\n    /**\n     * Register clickable event listeners.\n     */\n    registerClickHandlers() {\n        // Register click events within the component.\n        this.component.addEventListener('click', this.clickHandler.bind(this));\n\n        document.addEventListener('click', this.docClickHandler.bind(this));\n    }\n\n    /**\n     * The handler for when a user interacts with the component.\n     *\n     * @param {MouseEvent} e The triggering event that we are working with.\n     */\n    clickHandler(e) {\n        super.clickHandler(e);\n        // Prevent BS from closing the dropdown if they click elsewhere within the dropdown besides the form.\n        if (e.target.closest(selectors.fullDropdown)) {\n            e.stopPropagation();\n        }\n    }\n\n    /**\n     * Externally defined click function to improve memory handling.\n     *\n     * @param {MouseEvent} e\n     * @returns {Promise<void>}\n     */\n    async docClickHandler(e) {\n        if (e.target.dataset.hider === selectors.hider) {\n            e.preventDefault();\n            const pendingPromise = new Pending('gradereport_grader/collapse:docClickHandler:hide');\n            const desiredToHide = e.target.closest(selectors.colVal) ?\n                e.target.closest(selectors.colVal)?.dataset.col :\n                e.target.closest(selectors.itemVal)?.dataset.itemid;\n            const idx = this.getDataset().indexOf(desiredToHide);\n            if (idx === -1) {\n                this.getDataset().push(desiredToHide);\n            }\n            await this.prefcountpipe();\n\n            await this.nodesUpdate(desiredToHide);\n            pendingPromise.resolve();\n        }\n\n        if (e.target.closest('button')?.dataset.hider === selectors.expand) {\n            e.preventDefault();\n            const pendingPromise = new Pending('gradereport_grader/collapse:docClickHandler:expand');\n            const desiredToHide = e.target.closest(selectors.colVal) ?\n                e.target.closest(selectors.colVal)?.dataset.col :\n                e.target.closest(selectors.itemVal)?.dataset.itemid;\n            const idx = this.getDataset().indexOf(desiredToHide);\n            this.getDataset().splice(idx, 1);\n\n            await this.prefcountpipe();\n\n            await this.nodesUpdate(e.target.closest(selectors.colVal)?.dataset.col);\n            await this.nodesUpdate(e.target.closest(selectors.colVal)?.dataset.itemid);\n            pendingPromise.resolve();\n        }\n    }\n\n    /**\n     * The handler for when a user presses a key within the component.\n     *\n     * @param {KeyboardEvent} e The triggering event that we are working with.\n     */\n    async keyHandler(e) {\n        super.keyHandler(e);\n\n        // Switch the key presses to handle keyboard nav.\n        switch (e.key) {\n            case 'Tab':\n                if (e.target.closest(this.selectors.input)) {\n                    e.preventDefault();\n                    this.clearSearchButton.focus({preventScroll: true});\n                }\n                break;\n        }\n    }\n\n    /**\n     * Handle any keyboard inputs.\n     */\n    registerInputEvents() {\n        // Register & handle the text input.\n        this.searchInput.addEventListener('input', debounce(async() => {\n            if (this.getSearchTerm() === this.searchInput.value && this.searchResultsVisible()) {\n                window.console.warn(`Search term matches input value - skipping`);\n                // Debounce can happen multiple times quickly.\n                return;\n            }\n            this.setSearchTerms(this.searchInput.value);\n            // We can also require a set amount of input before search.\n            if (this.searchInput.value === '') {\n                // Hide the \"clear\" search button in the search bar.\n                this.clearSearchButton.classList.add('d-none');\n            } else {\n                // Display the \"clear\" search button in the search bar.\n                this.clearSearchButton.classList.remove('d-none');\n            }\n            const pendingPromise = new Pending();\n            // User has given something for us to filter against.\n            await this.filterrenderpipe().then(() => {\n                pendingPromise.resolve();\n                return true;\n            });\n        }, 300, {pending: true}));\n    }\n\n    /**\n     * Handle the form submission within the dropdown.\n     */\n    registerFormEvents() {\n        const form = this.component.querySelector(selectors.formDropdown);\n        const events = [\n            'click',\n            CustomEvents.events.activate,\n            CustomEvents.events.keyboardActivate\n        ];\n        CustomEvents.define(document, events);\n\n        const selectall = form.querySelector('[data-action=\"selectall\"]');\n\n        // Register clicks & keyboard form handling.\n        events.forEach((event) => {\n            const submitBtn = form.querySelector(`[data-action=\"${selectors.formItems.save}\"`);\n            form.addEventListener(event, (e) => {\n                // Stop Bootstrap from being clever.\n                e.stopPropagation();\n                const input = e.target.closest('input');\n                if (input) {\n                    // If the user is unchecking an item, we need to uncheck the select all if it's checked.\n                    if (selectall.checked && !input.checked) {\n                        selectall.checked = false;\n                    }\n                    const checkedCount = Array.from(form.querySelectorAll(selectors.formItems.checked)).length;\n                    // Check if any are clicked or not then change disabled.\n                    submitBtn.disabled = checkedCount <= 0;\n                }\n            }, false);\n\n            // Stop Bootstrap from being clever.\n            this.searchInput.addEventListener(event, e => e.stopPropagation());\n            this.clearSearchButton.addEventListener(event, async(e) => {\n                e.stopPropagation();\n                this.searchInput.value = '';\n                this.setSearchTerms(this.searchInput.value);\n                await this.filterrenderpipe();\n            });\n            selectall.addEventListener(event, (e) => {\n                // Stop Bootstrap from being clever.\n                e.stopPropagation();\n                if (!selectall.checked) {\n                    const touncheck = Array.from(form.querySelectorAll(selectors.formItems.checked));\n                    touncheck.forEach(item => {\n                        item.checked = false;\n                    });\n                    submitBtn.disabled = true;\n                } else {\n                    const currentUnchecked = Array.from(form.querySelectorAll(selectors.formItems.currentlyUnchecked));\n                    currentUnchecked.forEach(item => {\n                        item.checked = true;\n                    });\n                    submitBtn.disabled = false;\n                }\n            });\n        });\n\n        form.addEventListener('submit', async(e) => {\n            e.preventDefault();\n            if (e.submitter.dataset.action === selectors.formItems.cancel) {\n                $(this.component).dropdown('toggle');\n                return;\n            }\n            // Get the users' checked columns to change.\n            const checkedItems = [...form.elements].filter(item => item.checked);\n            checkedItems.forEach((item) => {\n                const idx = this.getDataset().indexOf(item.dataset.collapse);\n                this.getDataset().splice(idx, 1);\n                this.nodesUpdate(item.dataset.collapse);\n            });\n            // Reset the check all & submit to false just in case.\n            selectall.checked = false;\n            e.submitter.disabled = true;\n            await this.prefcountpipe();\n        });\n    }\n\n    async nodesUpdate(item) {\n        const colNodesToHide = [...document.querySelectorAll(`[data-col=\"${item}\"]`)];\n        const itemIDNodesToHide = [...document.querySelectorAll(`[data-itemid=\"${item}\"]`)];\n        const elements = [...colNodesToHide, ...itemIDNodesToHide];\n        if (elements && elements.length) {\n            const pendingPromise = new Pending('gradereport_grader/collapse:nodesUpdate:' + item);\n            this.updateDisplay(elements).then(() => pendingPromise.resolve()).catch(Notification.exception);\n        }\n    }\n\n    /**\n     * Update the user preferences, count display then render the results.\n     *\n     * @returns {Promise<void>}\n     */\n    async prefcountpipe() {\n        this.setPreferences();\n        this.countUpdate();\n        await this.filterrenderpipe();\n    }\n\n    /**\n     * Dictate to the search component how and what we want to match upon.\n     *\n     * @param {Array} filterableData\n     * @returns {Array} An array of objects containing the system reference and the user readable value.\n     */\n    async filterDataset(filterableData) {\n        const stringUserMap = await this.fetchRequiredUserStrings();\n        const stringGradeMap = await this.fetchRequiredGradeStrings();\n        // Custom user profile fields are not in our string map and need a bit of extra love.\n        const customFieldMap = this.fetchCustomFieldValues();\n        this.stringMap = new Map([...stringGradeMap, ...stringUserMap, ...customFieldMap]);\n\n        const searching = filterableData.map(s => {\n            const mapObj = this.stringMap.get(s);\n            if (mapObj === undefined) {\n                return {key: s, string: s};\n            }\n            return {\n                key: s,\n                string: mapObj.itemname ?? this.stringMap.get(s),\n                category: mapObj.category ?? '',\n            };\n        });\n        // Sometimes we just want to show everything.\n        if (this.getPreppedSearchTerm() === '') {\n            return searching;\n        }\n        // Other times we want to actually filter the content.\n        return searching.filter((col) => {\n            return col.string.toString().toLowerCase().includes(this.getPreppedSearchTerm());\n        });\n    }\n\n    /**\n     * Given we have a subset of the dataset, set the field that we matched upon to inform the end user.\n     */\n    filterMatchDataset() {\n        this.setMatchedResults(\n            this.getMatchedResults().map((column) => {\n                return {\n                    name: column.key,\n                    displayName: column.string ?? column.key,\n                    category: column.category ?? '',\n                };\n            })\n        );\n    }\n\n    /**\n     * With an array of nodes, switch their classes and values.\n     *\n     * @param {Array} elements The elements to update.\n     */\n    async updateDisplay(elements) {\n        const promises = [];\n        elements.forEach((element) => {\n            promises.push(this.updateDisplayForElement(element));\n        });\n\n        await Promise.all(promises);\n    }\n\n    /**\n     * Update display for given element, switch its classes and values.\n     *\n     * @param {HTMLElement} element The element to update.\n     */\n    async updateDisplayForElement(element) {\n        const content = element.querySelector(selectors.content);\n        const sort = element.querySelector(selectors.sort);\n        const expandButton = element.querySelector(selectors.expandbutton);\n        const rangeRowCell = element.querySelector(selectors.rangerowcell);\n        const avgRowCell = element.querySelector(selectors.avgrowcell);\n        const cellMenuButton = element.querySelector(selectors.cellMenuButton);\n        const nodeSet = [\n            element.querySelector(selectors.menu),\n            element.querySelector(selectors.icons),\n            content\n        ];\n\n        // This can be further improved to reduce redundant similar calls.\n        if (element.classList.contains('cell')) {\n            // The column is actively being sorted, lets reset that and reload the page.\n            if (sort !== null) {\n                window.location = this.defaultSort;\n            }\n            if (content === null) {\n                // If it's not a content cell, it must be an overall average or a range cell.\n                const rowCell = avgRowCell ?? rangeRowCell;\n\n                rowCell?.classList.toggle('d-none');\n            } else if (content.classList.contains('d-none')) {\n                // We should always have content but some cells do not contain menus or other actions.\n                element.classList.remove('collapsed');\n                // If there are many nodes, apply the following.\n                if (content.childNodes.length > 1) {\n                    content.classList.add('d-flex');\n                }\n                nodeSet.forEach(node => {\n                    node?.classList.remove('d-none');\n                });\n                expandButton?.classList.add('d-none');\n                cellMenuButton?.focus();\n            } else {\n                element.classList.add('collapsed');\n                content.classList.remove('d-flex');\n                nodeSet.forEach(node => {\n                    node?.classList.add('d-none');\n                });\n                expandButton?.classList.remove('d-none');\n            }\n        }\n    }\n\n    /**\n     * Update the visual count of collapsed columns or hide the count all together.\n     */\n    countUpdate() {\n        countIndicator.textContent = this.getDatasetSize();\n        if (this.getDatasetSize() > 0) {\n            this.component.parentElement.classList.add('d-flex');\n            this.component.parentElement.classList.remove('d-none');\n        } else {\n            this.component.parentElement.classList.remove('d-flex');\n            this.component.parentElement.classList.add('d-none');\n        }\n    }\n\n    /**\n     * Build the content then replace the node by default we want our form to exist.\n     */\n    async renderDefault() {\n        this.setMatchedResults(await this.filterDataset(this.getDataset()));\n        this.filterMatchDataset();\n\n        // Update the collapsed button pill.\n        this.countUpdate();\n        const {html, js} = await renderForPromise('gradereport_grader/collapse/collapsebody', {\n            'results': this.getMatchedResults(),\n            'userid': this.userID,\n        });\n        replaceNode(selectors.placeholder, html, js);\n        this.updateNodes();\n\n        // Given we now have the body, we can set up more triggers.\n        this.registerFormEvents();\n        this.registerInputEvents();\n\n        // Add a small BS listener so that we can set the focus correctly on open.\n        this.$component.on('shown.bs.dropdown', () => {\n            this.searchInput.focus({preventScroll: true});\n        });\n    }\n\n    /**\n     * Build the content then replace the node.\n     */\n    async renderDropdown() {\n        const form = this.component.querySelector(selectors.formDropdown);\n        const selectall = form.querySelector('[data-action=\"selectall\"]');\n        const {html, js} = await renderForPromise('gradereport_grader/collapse/collapseresults', {\n            'results': this.getMatchedResults(),\n            'searchTerm': this.getSearchTerm(),\n        });\n        selectall.disabled = this.getMatchedResults().length === 0;\n        replaceNodeContents(this.getHTMLElements().searchDropdown, html, js);\n    }\n\n    /**\n     * If we have any custom user profile fields, grab their system & readable names to add to our string map.\n     *\n     * @returns {array<string,*>} An array of associated string arrays ready for our map.\n     */\n    fetchCustomFieldValues() {\n        const customFields = document.querySelectorAll('[data-collapse-name]');\n        // Cast from NodeList to array to grab all the values.\n        return [...customFields].map(field => [field.parentElement.dataset.col, field.dataset.collapseName]);\n    }\n\n    /**\n     * Given the set of profile fields we can possibly search, fetch their strings,\n     * so we can report to screen readers the field that matched.\n     *\n     * @returns {Promise<void>}\n     */\n    fetchRequiredUserStrings() {\n        if (!this.userStrings) {\n            const requiredStrings = [\n                'username',\n                'firstname',\n                'lastname',\n                'email',\n                'city',\n                'country',\n                'department',\n                'institution',\n                'idnumber',\n                'phone1',\n                'phone2',\n            ];\n            this.userStrings = getStrings(requiredStrings.map((key) => ({key})))\n                .then((stringArray) => new Map(\n                    requiredStrings.map((key, index) => ([key, stringArray[index]]))\n                ));\n        }\n        return this.userStrings;\n    }\n\n    /**\n     * Given the set of gradable items we can possibly search, fetch their strings,\n     * so we can report to screen readers the field that matched.\n     *\n     * @returns {Promise<void>}\n     */\n    fetchRequiredGradeStrings() {\n        if (!this.gradeStrings) {\n            this.gradeStrings = Repository.gradeItems(this.courseID)\n                .then((result) => new Map(\n                    result.gradeItems.map(key => ([key.id, key]))\n                ));\n        }\n        return this.gradeStrings;\n    }\n}\n"],"names":["selectors","cancel","save","checked","currentlyUnchecked","countIndicator","document","querySelector","ColumnSearch","search_combobox","userID","courseID","defaultSort","constructor","component","pendingPromise","Pending","then","loader","setTimeout","getDataset","forEach","item","nodesUpdate","renderDefault","remove","classList","resolve","catch","Notification","exception","componentSelector","dropdownSelector","triggerSelector","this","dataset","cols","fetchDataset","JSON","parse","split","datasetSize","length","storage","get","setPreferences","set","stringify","join","registerClickHandlers","addEventListener","clickHandler","bind","docClickHandler","e","target","closest","stopPropagation","hider","preventDefault","desiredToHide","_e$target$closest","col","_e$target$closest2","itemid","indexOf","push","prefcountpipe","_e$target$closest4","_e$target$closest5","idx","splice","_e$target$closest6","_e$target$closest7","keyHandler","key","input","clearSearchButton","focus","preventScroll","registerInputEvents","searchInput","async","getSearchTerm","value","searchResultsVisible","window","console","warn","setSearchTerms","add","filterrenderpipe","pending","registerFormEvents","form","events","CustomEvents","activate","keyboardActivate","define","selectall","event","submitBtn","checkedCount","Array","from","querySelectorAll","disabled","submitter","action","dropdown","elements","filter","collapse","updateDisplay","countUpdate","filterableData","stringUserMap","fetchRequiredUserStrings","stringGradeMap","fetchRequiredGradeStrings","customFieldMap","fetchCustomFieldValues","stringMap","Map","searching","map","s","mapObj","undefined","string","itemname","category","getPreppedSearchTerm","toString","toLowerCase","includes","filterMatchDataset","setMatchedResults","getMatchedResults","column","name","displayName","promises","element","updateDisplayForElement","Promise","all","content","sort","expandButton","rangeRowCell","avgRowCell","cellMenuButton","nodeSet","contains","location","rowCell","toggle","childNodes","node","textContent","getDatasetSize","parentElement","filterDataset","html","js","updateNodes","$component","on","getHTMLElements","searchDropdown","field","collapseName","userStrings","requiredStrings","stringArray","index","gradeStrings","Repository","gradeItems","result","id"],"mappings":"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"}

Sindbad File Manager Version 1.0, Coded By Sindbad EG ~ The Terrorists