{"version":3,"file":"debug.min.js","sources":["https:\/\/www.alsg.org\/home\/lib\/amd\/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 .\n\n\/**\n * Reactive module debug tools.\n *\n * @module core\/reactive\/local\/reactive\/debug\n * @copyright 2021 Ferran Recio \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 \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 \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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"}