HEX
Server: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips PHP/8.0.30
System: Linux multiplicar 3.10.0-1160.102.1.el7.x86_64 #1 SMP Tue Oct 17 15:42:21 UTC 2023 x86_64
User: root (0)
PHP: 8.0.30
Disabled: NONE
Upload Files
File: /var/www/html/ceade.tocsa.com.py/course/amd/build/activitychooser.min.js.map
{"version":3,"file":"activitychooser.min.js","sources":["../src/activitychooser.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 * A type of dialogue used as for choosing modules in a course.\n *\n * @module     core_course/activitychooser\n * @copyright  2020 Mathew May <mathew.solutions>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport * as ChooserDialogue from 'core_course/local/activitychooser/dialogue';\nimport * as Repository from 'core_course/local/activitychooser/repository';\nimport selectors from 'core_course/local/activitychooser/selectors';\nimport CustomEvents from 'core/custom_interaction_events';\nimport * as Templates from 'core/templates';\nimport * as ModalFactory from 'core/modal_factory';\nimport {get_string as getString} from 'core/str';\nimport Pending from 'core/pending';\n\n// Set up some JS module wide constants that can be added to in the future.\n\n// Tab config options.\nconst ALLACTIVITIESRESOURCES = 0;\nconst ONLYALL = 1;\nconst ACTIVITIESRESOURCES = 2;\n\n// Module types.\nconst ACTIVITY = 0;\nconst RESOURCE = 1;\n\n/**\n * Set up the activity chooser.\n *\n * @method init\n * @param {Number} courseId Course ID to use later on in fetchModules()\n * @param {Object} chooserConfig Any PHP config settings that we may need to reference\n */\nexport const init = (courseId, chooserConfig) => {\n    const pendingPromise = new Pending();\n\n    registerListenerEvents(courseId, chooserConfig);\n\n    pendingPromise.resolve();\n};\n\n/**\n * Once a selection has been made make the modal & module information and pass it along\n *\n * @method registerListenerEvents\n * @param {Number} courseId\n * @param {Object} chooserConfig Any PHP config settings that we may need to reference\n */\nconst registerListenerEvents = (courseId, chooserConfig) => {\n    const events = [\n        'click',\n        CustomEvents.events.activate,\n        CustomEvents.events.keyboardActivate\n    ];\n\n    const fetchModuleData = (() => {\n        let innerPromise = null;\n\n        return () => {\n            if (!innerPromise) {\n                innerPromise = new Promise((resolve) => {\n                    resolve(Repository.activityModules(courseId));\n                });\n            }\n\n            return innerPromise;\n        };\n    })();\n\n    const fetchFooterData = (() => {\n        let footerInnerPromise = null;\n\n        return (sectionId) => {\n            if (!footerInnerPromise) {\n                footerInnerPromise = new Promise((resolve) => {\n                    resolve(Repository.fetchFooterData(courseId, sectionId));\n                });\n            }\n\n            return footerInnerPromise;\n        };\n    })();\n\n    CustomEvents.define(document, events);\n\n    // Display module chooser event listeners.\n    events.forEach((event) => {\n        document.addEventListener(event, async(e) => {\n            if (e.target.closest(selectors.elements.sectionmodchooser)) {\n                let caller;\n                // We need to know who called this.\n                // Standard courses use the ID in the main section info.\n                const sectionDiv = e.target.closest(selectors.elements.section);\n                // Front page courses need some special handling.\n                const button = e.target.closest(selectors.elements.sectionmodchooser);\n\n                // If we don't have a section ID use the fallback ID.\n                // We always want the sectionDiv caller first as it keeps track of section ID's after DnD changes.\n                // The button attribute is always just a fallback for us as the section div is not always available.\n                // A YUI change could be done maybe to only update the button attribute but we are going for minimal change here.\n                if (sectionDiv !== null && sectionDiv.hasAttribute('data-sectionid')) {\n                    // We check for attributes just in case of outdated contrib course formats.\n                    caller = sectionDiv;\n                } else {\n                    caller = button;\n                }\n\n                // We want to show the modal instantly but loading whilst waiting for our data.\n                let bodyPromiseResolver;\n                const bodyPromise = new Promise(resolve => {\n                    bodyPromiseResolver = resolve;\n                });\n\n                const footerData = await fetchFooterData(caller.dataset.sectionid);\n                const sectionModal = buildModal(bodyPromise, footerData);\n\n                // Now we have a modal we should start fetching data.\n                // If an error occurs while fetching the data, display the error within the modal.\n                const data = await fetchModuleData().catch(async(e) => {\n                    const errorTemplateData = {\n                        'errormessage': e.message\n                    };\n                    bodyPromiseResolver(await Templates.render('core_course/local/activitychooser/error', errorTemplateData));\n                });\n\n                // Early return if there is no module data.\n                if (!data) {\n                    return;\n                }\n\n                // Apply the section id to all the module instance links.\n                const builtModuleData = sectionIdMapper(data, caller.dataset.sectionid, caller.dataset.sectionreturnid);\n\n                ChooserDialogue.displayChooser(\n                    sectionModal,\n                    builtModuleData,\n                    partiallyAppliedFavouriteManager(data, caller.dataset.sectionid),\n                    footerData,\n                );\n\n                bodyPromiseResolver(await Templates.render(\n                    'core_course/activitychooser',\n                    templateDataBuilder(builtModuleData, chooserConfig)\n                ));\n            }\n        });\n    });\n};\n\n/**\n * Given the web service data and an ID we want to make a deep copy\n * of the WS data then add on the section ID to the addoption URL\n *\n * @method sectionIdMapper\n * @param {Object} webServiceData Our original data from the Web service call\n * @param {Number} id The ID of the section we need to append to the links\n * @param {Number|null} sectionreturnid The ID of the section return we need to append to the links\n * @return {Array} [modules] with URL's built\n */\nconst sectionIdMapper = (webServiceData, id, sectionreturnid) => {\n    // We need to take a fresh deep copy of the original data as an object is a reference type.\n    const newData = JSON.parse(JSON.stringify(webServiceData));\n    newData.content_items.forEach((module) => {\n        module.link += '&section=' + id + '&sr=' + (sectionreturnid ?? 0);\n    });\n    return newData.content_items;\n};\n\n/**\n * Given an array of modules we want to figure out where & how to place them into our template object\n *\n * @method templateDataBuilder\n * @param {Array} data our modules to manipulate into a Templatable object\n * @param {Object} chooserConfig Any PHP config settings that we may need to reference\n * @return {Object} Our built object ready to render out\n */\nconst templateDataBuilder = (data, chooserConfig) => {\n    // Setup of various bits and pieces we need to mutate before throwing it to the wolves.\n    let activities = [];\n    let resources = [];\n    let showAll = true;\n    let showActivities = false;\n    let showResources = false;\n\n    // Tab mode can be the following [All, Resources & Activities, All & Activities & Resources].\n    const tabMode = parseInt(chooserConfig.tabmode);\n\n    // Filter the incoming data to find favourite & recommended modules.\n    const favourites = data.filter(mod => mod.favourite === true);\n    const recommended = data.filter(mod => mod.recommended === true);\n\n    // Both of these modes need Activity & Resource tabs.\n    if ((tabMode === ALLACTIVITIESRESOURCES || tabMode === ACTIVITIESRESOURCES) && tabMode !== ONLYALL) {\n        // Filter the incoming data to find activities then resources.\n        activities = data.filter(mod => mod.archetype === ACTIVITY);\n        resources = data.filter(mod => mod.archetype === RESOURCE);\n        showActivities = true;\n        showResources = true;\n\n        // We want all of the previous information but no 'All' tab.\n        if (tabMode === ACTIVITIESRESOURCES) {\n            showAll = false;\n        }\n    }\n\n    // Given the results of the above filters lets figure out what tab to set active.\n    // We have some favourites.\n    const favouritesFirst = !!favourites.length;\n    // We are in tabMode 2 without any favourites.\n    const activitiesFirst = showAll === false && favouritesFirst === false;\n    // We have nothing fallback to show all modules.\n    const fallback = showAll === true && favouritesFirst === false;\n\n    return {\n        'default': data,\n        showAll: showAll,\n        activities: activities,\n        showActivities: showActivities,\n        activitiesFirst: activitiesFirst,\n        resources: resources,\n        showResources: showResources,\n        favourites: favourites,\n        recommended: recommended,\n        favouritesFirst: favouritesFirst,\n        fallback: fallback,\n    };\n};\n\n/**\n * Given an object we want to build a modal ready to show\n *\n * @method buildModal\n * @param {Promise} bodyPromise\n * @param {String|Boolean} footer Either a footer to add or nothing\n * @return {Object} The modal ready to display immediately and render body in later.\n */\nconst buildModal = (bodyPromise, footer) => {\n    return ModalFactory.create({\n        type: ModalFactory.types.DEFAULT,\n        title: getString('addresourceoractivity'),\n        body: bodyPromise,\n        footer: footer.customfootertemplate,\n        large: true,\n        scrollable: false,\n        templateContext: {\n            classes: 'modchooser'\n        }\n    })\n    .then(modal => {\n        modal.show();\n        return modal;\n    });\n};\n\n/**\n * A small helper function to handle the case where there are no more favourites\n * and we need to mess a bit with the available tabs in the chooser\n *\n * @method nullFavouriteDomManager\n * @param {HTMLElement} favouriteTabNav Dom node of the favourite tab nav\n * @param {HTMLElement} modalBody Our current modals' body\n */\nconst nullFavouriteDomManager = (favouriteTabNav, modalBody) => {\n    favouriteTabNav.tabIndex = -1;\n    favouriteTabNav.classList.add('d-none');\n    // Need to set active to an available tab.\n    if (favouriteTabNav.classList.contains('active')) {\n        favouriteTabNav.classList.remove('active');\n        favouriteTabNav.setAttribute('aria-selected', 'false');\n        const favouriteTab = modalBody.querySelector(selectors.regions.favouriteTab);\n        favouriteTab.classList.remove('active');\n        const defaultTabNav = modalBody.querySelector(selectors.regions.defaultTabNav);\n        const activitiesTabNav = modalBody.querySelector(selectors.regions.activityTabNav);\n        if (defaultTabNav.classList.contains('d-none') === false) {\n            defaultTabNav.classList.add('active');\n            defaultTabNav.setAttribute('aria-selected', 'true');\n            defaultTabNav.tabIndex = 0;\n            defaultTabNav.focus();\n            const defaultTab = modalBody.querySelector(selectors.regions.defaultTab);\n            defaultTab.classList.add('active');\n        } else {\n            activitiesTabNav.classList.add('active');\n            activitiesTabNav.setAttribute('aria-selected', 'true');\n            activitiesTabNav.tabIndex = 0;\n            activitiesTabNav.focus();\n            const activitiesTab = modalBody.querySelector(selectors.regions.activityTab);\n            activitiesTab.classList.add('active');\n        }\n\n    }\n};\n\n/**\n * Export a curried function where the builtModules has been applied.\n * We have our array of modules so we can rerender the favourites area and have all of the items sorted.\n *\n * @method partiallyAppliedFavouriteManager\n * @param {Array} moduleData This is our raw WS data that we need to manipulate\n * @param {Number} sectionId We need this to add the sectionID to the URL's in the faves area after rerender\n * @return {Function} partially applied function so we can manipulate DOM nodes easily & update our internal array\n */\nconst partiallyAppliedFavouriteManager = (moduleData, sectionId) => {\n    /**\n     * Curried function that is being returned.\n     *\n     * @param {String} internal Internal name of the module to manage\n     * @param {Boolean} favourite Is the caller adding a favourite or removing one?\n     * @param {HTMLElement} modalBody What we need to update whilst we are here\n     */\n    return async(internal, favourite, modalBody) => {\n        const favouriteArea = modalBody.querySelector(selectors.render.favourites);\n\n        // eslint-disable-next-line max-len\n        const favouriteButtons = modalBody.querySelectorAll(`[data-internal=\"${internal}\"] ${selectors.actions.optionActions.manageFavourite}`);\n        const favouriteTabNav = modalBody.querySelector(selectors.regions.favouriteTabNav);\n        const result = moduleData.content_items.find(({name}) => name === internal);\n        const newFaves = {};\n        if (result) {\n            if (favourite) {\n                result.favourite = true;\n\n                // eslint-disable-next-line camelcase\n                newFaves.content_items = moduleData.content_items.filter(mod => mod.favourite === true);\n\n                const builtFaves = sectionIdMapper(newFaves, sectionId);\n\n                const {html, js} = await Templates.renderForPromise('core_course/local/activitychooser/favourites',\n                    {favourites: builtFaves});\n\n                await Templates.replaceNodeContents(favouriteArea, html, js);\n\n                Array.from(favouriteButtons).forEach((element) => {\n                    element.classList.remove('text-muted');\n                    element.classList.add('text-primary');\n                    element.dataset.favourited = 'true';\n                    element.setAttribute('aria-pressed', true);\n                    element.firstElementChild.classList.remove('fa-star-o');\n                    element.firstElementChild.classList.add('fa-star');\n                });\n\n                favouriteTabNav.classList.remove('d-none');\n            } else {\n                result.favourite = false;\n\n                const nodeToRemove = favouriteArea.querySelector(`[data-internal=\"${internal}\"]`);\n\n                nodeToRemove.parentNode.removeChild(nodeToRemove);\n\n                Array.from(favouriteButtons).forEach((element) => {\n                    element.classList.add('text-muted');\n                    element.classList.remove('text-primary');\n                    element.dataset.favourited = 'false';\n                    element.setAttribute('aria-pressed', false);\n                    element.firstElementChild.classList.remove('fa-star');\n                    element.firstElementChild.classList.add('fa-star-o');\n                });\n                const newFaves = moduleData.content_items.filter(mod => mod.favourite === true);\n\n                if (newFaves.length === 0) {\n                    nullFavouriteDomManager(favouriteTabNav, modalBody);\n                }\n            }\n        }\n    };\n};\n"],"names":["courseId","chooserConfig","pendingPromise","Pending","registerListenerEvents","resolve","innerPromise","footerInnerPromise","events","CustomEvents","activate","keyboardActivate","fetchModuleData","Promise","Repository","activityModules","fetchFooterData","sectionId","define","document","forEach","event","addEventListener","e","target","closest","selectors","elements","sectionmodchooser","sectionDiv","section","button","caller","hasAttribute","bodyPromise","bodyPromiseResolver","dataset","sectionid","footerData","sectionModal","buildModal","catch","errorTemplateData","message","Templates","render","data","builtModuleData","sectionIdMapper","sectionreturnid","ChooserDialogue","displayChooser","partiallyAppliedFavouriteManager","templateDataBuilder","webServiceData","id","newData","JSON","parse","stringify","content_items","module","link","activities","resources","showAll","showActivities","showResources","tabMode","parseInt","tabmode","favourites","filter","mod","favourite","recommended","archetype","favouritesFirst","length","activitiesFirst","fallback","footer","ModalFactory","create","type","types","DEFAULT","title","body","customfootertemplate","large","scrollable","templateContext","classes","then","modal","show","nullFavouriteDomManager","favouriteTabNav","modalBody","tabIndex","classList","add","contains","remove","setAttribute","querySelector","regions","favouriteTab","defaultTabNav","activitiesTabNav","activityTabNav","focus","defaultTab","activityTab","moduleData","internal","favouriteArea","favouriteButtons","querySelectorAll","actions","optionActions","manageFavourite","result","find","name","newFaves","builtFaves","renderForPromise","html","js","replaceNodeContents","Array","from","element","favourited","firstElementChild","nodeToRemove","parentNode","removeChild"],"mappings":"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"}