Proyectos de Subversion Moodle

Rev

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

{"version":3,"file":"debug.min.js","sources":["../../../src/local/reactive/debug.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 * Reactive module debug tools.\n *\n * @module     core/local/reactive/debug\n * @copyright  2021 Ferran Recio <ferran@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\n\nimport Reactive from 'core/local/reactive/reactive';\nimport log from 'core/log';\n\n// The list of reactives instances.\nconst reactiveInstances = {};\n\n// The reactive debugging objects.\nconst reactiveDebuggers = {};\n\n/**\n * Reactive module debug tools.\n *\n * If debug is enabled, this reactive module will spy all the reactive instances and keep a record\n * of the changes and components they have.\n *\n * It is important to note that the Debug class is also a Reactive module. The debug instance keeps\n * the reactive instances data as its own state. This way it is possible to implement development tools\n * that whatches this data.\n *\n * @class      core/reactive/local/reactive/debug/Debug\n * @copyright  2021 Ferran Recio <ferran@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nclass Debug extends Reactive {\n\n    /**\n     * Set the initial state.\n     *\n     * @param {object} stateData the initial state data.\n     */\n    setInitialState(stateData) {\n        super.setInitialState(stateData);\n        log.debug(`Debug module \"M.reactive\" loaded.`);\n    }\n\n    /**\n     * List the currents page reactives instances.\n     */\n    get list() {\n        return JSON.parse(JSON.stringify(this.state.reactives));\n    }\n\n    /**\n     * Register a new Reactive instance.\n     *\n     * This method is called every time a \"new Reactive\" is executed.\n     *\n     * @param {Reactive} instance the reactive instance\n     */\n    registerNewInstance(instance) {\n\n        // Generate a valid variable name for that instance.\n        let name = instance.name ?? `instance${this.state.reactives.length}`;\n        name = name.replace(/\\W/g, '');\n\n        log.debug(`Registering new reactive instance \"M.reactive.${name}\"`);\n\n        reactiveInstances[name] = instance;\n        reactiveDebuggers[name] = new DebugInstance(reactiveInstances[name]);\n        // Register also in the state.\n        this.dispatch('putInstance', name, instance);\n        // Add debug watchers to instance.\n        const refreshMethod = () => {\n            this.dispatch('putInstance', name, instance);\n        };\n        instance.target.addEventListener('readmode:on', refreshMethod);\n        instance.target.addEventListener('readmode:off', refreshMethod);\n        instance.target.addEventListener('registerComponent:success', refreshMethod);\n        instance.target.addEventListener('transaction:end', refreshMethod);\n        // We store the last transaction into the state.\n        const storeTransaction = ({detail}) => {\n            const changes = detail?.changes;\n            this.dispatch('lastTransaction', name, changes);\n        };\n        instance.target.addEventListener('transaction:start', storeTransaction);\n    }\n\n    /**\n     * Returns a debugging object for a specific Reactive instance.\n     *\n     * A debugging object is a class that wraps a Reactive instance to quick access some of the\n     * reactive methods using the browser JS console.\n     *\n     * @param {string} name the Reactive instance name\n     * @returns {DebugInstance} a debug object wrapping the Reactive instance\n     */\n    debug(name) {\n        return reactiveDebuggers[name];\n    }\n}\n\n/**\n * The debug state mutations class.\n *\n * @class core/reactive/local/reactive/debug/Mutations\n */\nclass Mutations {\n\n    /**\n     * Insert or update a new instance into the debug state.\n     *\n     * @param {StateManager} stateManager the debug state manager\n     * @param {string} name the instance name\n     * @param {Reactive} instance the reactive instance\n     */\n    putInstance(stateManager, name, instance) {\n        const state = stateManager.state;\n\n        stateManager.setReadOnly(false);\n\n        if (state.reactives.has(name)) {\n            state.reactives.get(name).countcomponents = instance.components.length;\n            state.reactives.get(name).readOnly = instance.stateManager.readonly;\n            state.reactives.get(name).modified = new Date().getTime();\n        } else {\n            state.reactives.add({\n                id: name,\n                countcomponents: instance.components.length,\n                readOnly: instance.stateManager.readonly,\n                lastChanges: [],\n                modified: new Date().getTime(),\n            });\n        }\n        stateManager.setReadOnly(true);\n    }\n\n    /**\n     * Update the lastChanges attribute with a list of changes\n     *\n     * @param {StateManager} stateManager the debug reactive state\n     * @param {string} name tje instance name\n     * @param {array} changes the list of changes\n     */\n    lastTransaction(stateManager, name, changes) {\n        if (!changes || changes.length === 0) {\n            return;\n        }\n\n        const state = stateManager.state;\n        const lastChanges = ['transaction:start'];\n\n        changes.forEach(change => {\n            lastChanges.push(change.eventName);\n        });\n\n        lastChanges.push('transaction:end');\n\n        stateManager.setReadOnly(false);\n\n        state.reactives.get(name).lastChanges = lastChanges;\n\n        stateManager.setReadOnly(true);\n    }\n}\n\n/**\n * Class used to debug a specific instance and manipulate the state from the JS console.\n *\n * @class      core/reactive/local/reactive/debug/DebugInstance\n * @copyright  2021 Ferran Recio <ferran@moodle.com>\n * @license    http://www.gnu.org/copyleft/gpl.html GNU GPL v3 or later\n */\nclass DebugInstance {\n\n    /**\n     * Constructor.\n     *\n     * @param {Reactive} instance the reactive instance\n     */\n    constructor(instance) {\n        this.instance = instance;\n        // Add some debug data directly into the instance. This way we avoid having attributes\n        // that will confuse the console aoutocomplete.\n        if (instance._reactiveDebugData === undefined) {\n            instance._reactiveDebugData = {\n                highlighted: false,\n            };\n        }\n    }\n\n    /**\n     * Set the read only mode.\n     *\n     * Quick access to the instance setReadOnly method.\n     *\n     * @param {bool} value the new read only value\n     */\n    set readOnly(value) {\n        this.instance.stateManager.setReadOnly(value);\n    }\n\n    /**\n     * Get the read only value\n     *\n     * @returns {bool}\n     */\n    get readOnly() {\n        return this.instance.stateManager.readonly;\n    }\n\n    /**\n     * Return the current state object.\n     *\n     * @returns {object}\n     */\n    get state() {\n        return this.instance.state;\n    }\n\n    /**\n     * Tooggle the reactive HTML element highlight registered in this reactive instance.\n     *\n     * @param {bool} value the highlight value\n     */\n    set highlight(value) {\n        this.instance._reactiveDebugData.highlighted = value;\n        this.instance.components.forEach(({element}) => {\n            const border = (value) ? `thick solid #0000FF` : '';\n            element.style.border = border;\n        });\n    }\n\n    /**\n     * Get the current highligh value.\n     *\n     * @returns {bool}\n     */\n    get highlight() {\n        return this.instance._reactiveDebugData.highlighted;\n    }\n\n    /**\n     * List all the components registered in this instance.\n     *\n     * @returns {array}\n     */\n    get components() {\n        return [...this.instance.components];\n    }\n\n    /**\n     * List all the state changes evenet pending to dispatch.\n     *\n     * @returns {array}\n     */\n    get changes() {\n        const result = [];\n        this.instance.stateManager.eventsToPublish.forEach(\n            (element) => {\n                result.push(element.eventName);\n            }\n        );\n        return result;\n    }\n\n    /**\n     * Dispatch a change in the state.\n     *\n     * Usually reactive modules throw an error directly to the components when something\n     * goes wrong. However, course editor can directly display a notification.\n     *\n     * @method dispatch\n     * @param {*} args\n     */\n    async dispatch(...args) {\n        this.instance.dispatch(...args);\n    }\n\n    /**\n     * Return all the HTML elements registered in the instance components.\n     *\n     * @returns {array}\n     */\n    get elements() {\n        const result = [];\n        this.instance.components.forEach(({element}) => {\n            result.push(element);\n        });\n        return result;\n    }\n\n    /**\n     * Return a plain copy of the state data.\n     *\n     * @returns {object}\n     */\n    get stateData() {\n        return JSON.parse(JSON.stringify(this.state));\n    }\n\n    /**\n     * Process an update state array.\n     *\n     * @param {array} updates an array of update state messages\n     */\n    processUpdates(updates) {\n        this.instance.stateManager.processUpdates(updates);\n    }\n}\n\nconst stateChangedEventName = 'core_reactive_debug:stateChanged';\n\n/**\n * Internal state changed event.\n *\n * @method dispatchStateChangedEvent\n * @param {object} detail the full state\n * @param {object} target the custom event target (document if none provided)\n */\nfunction dispatchStateChangedEvent(detail, target) {\n    if (target === undefined) {\n        target = document;\n    }\n    target.dispatchEvent(\n        new CustomEvent(\n            stateChangedEventName,\n            {\n                bubbles: true,\n                detail: detail,\n            }\n        )\n    );\n}\n\n/**\n * The main init method to initialize the reactive debug.\n * @returns {object}\n */\nexport const initDebug = () => {\n    const debug = new Debug({\n        name: 'CoreReactiveDebug',\n        eventName: stateChangedEventName,\n        eventDispatch: dispatchStateChangedEvent,\n        mutations: new Mutations(),\n        state: {\n            reactives: [],\n        },\n    });\n\n    // The reactiveDebuggers will be used as a way of access the debug instances but also to register every new\n    // instance. To ensure this will update the reactive debug state we add the registerNewInstance method to it.\n    reactiveDebuggers.registerNewInstance = debug.registerNewInstance.bind(debug);\n\n    return {\n        debug,\n        debuggers: reactiveDebuggers,\n    };\n};\n"],"names":["reactiveInstances","reactiveDebuggers","Debug","Reactive","setInitialState","stateData","debug","list","JSON","parse","stringify","this","state","reactives","registerNewInstance","instance","name","length","replace","DebugInstance","dispatch","refreshMethod","target","addEventListener","_ref","detail","changes","Mutations","putInstance","stateManager","setReadOnly","has","get","countcomponents","components","readOnly","readonly","modified","Date","getTime","add","id","lastChanges","lastTransaction","forEach","change","push","eventName","constructor","undefined","_reactiveDebugData","highlighted","value","highlight","_ref2","element","border","style","result","eventsToPublish","elements","_ref3","processUpdates","updates","dispatchStateChangedEvent","document","dispatchEvent","CustomEvent","bubbles","eventDispatch","mutations","bind","debuggers"],"mappings":"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"}