From 7ba7333310882ab666160b659d02e3106d47b00c Mon Sep 17 00:00:00 2001 From: GogoVega <92022724+GogoVega@users.noreply.github.com> Date: Sun, 10 Nov 2024 17:14:02 +0100 Subject: [PATCH] Improve docs and comments --- .../@node-red/editor-client/src/js/history.js | 321 +++++++++++------- 1 file changed, 199 insertions(+), 122 deletions(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/history.js b/packages/node_modules/@node-red/editor-client/src/js/history.js index 8b28ac1ae..e129353e2 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/history.js +++ b/packages/node_modules/@node-red/editor-client/src/js/history.js @@ -19,7 +19,36 @@ * @namespace RED.history */ RED.history = (function () { + /** + * GLOBAL NOTE: Handle event and users ONLY for edit/change event + * TODO: Import types from RED.nodes + * + * @typedef {object} Node + * @typedef {{ source: Node; sourcePort: number; target: Node; }} Link + * @typedef {Node & { env?: Array; }} Group + * @typedef {Node & {}} Junction + * @typedef {Node & { in: Array; out: Array; + * instances: Array; env?: Array; }} Subflow + * @typedef {Node & { type: "subflow"; direction: "in"|"out"; }} SubflowNode + * @typedef {Node & {}} Workspace + * + * @typedef {"add"|"delete"|"edit"|"move"|"multi"|"reorder"|"replace"| + * "createSubflow"|"deleteSubflow"|"addToGroup"|"createGroup"|"ungroup"| + * "removeFromGroup"} HistoryType + * @typedef {{ t: HistoryType; dirty: boolean; callback?: (ev: HistoryEvent) => void; } + * & (AddEvent | DeleteEvent | EditEvent | MoveEvent | MultiEvent | ReorderEvent | + * ReplaceEvent | CreateSubflowEvent | DeleteSubflowEvent | AddToGroupEvent | + * CreateGroupEvent | UngroupEvent | RemoveFromGroupEvent) } HistoryEvent + */ + + /** + * @type {Array} + */ let undoHistory = []; + + /** + * @type {Array} + */ let redoHistory = []; function nodeOrJunction(id) { @@ -39,32 +68,23 @@ RED.history = (function () { } } - /** - * @typedef {"add"|"delete"|"edit"|"move"|"multi"|"remove"|"reorder"|"replace"| - * "createSubflow"|"deleteSubflow"|"addToGroup"|"createGroup"|"ungroup"|"removeFromGroup"} HistoryType - * @typedef {{ t: HistoryType; dirty: boolean; callback?: (ev: HistoryEvent) => void; } & {}} HistoryEvent - * - * @typedef {{ source: Node; sourcePort: number; target: Node; }} Link - * @typedef {Node & {}} Group - * @typedef {Node & {}} Junction - * @typedef {Node & { instances: Array; }} Subflow - * @typedef {Node & {}} Workspace - */ - /** * Called on the `add` history event - * @param {object} ev The history event to undo - * @param {"add"} ev.t The history event type - * @param {Array} [ev.groups] - * @param {Array} [ev.junctions] - * @param {Array} [ev.links] - * @param {Array} [ev.nodes] - * @param {Array} [ev.removedLinks] - * @param {Subflow} [ev.subflow] - * @param {Array} [ev.subflows] - * @param {Array} [ev.workspaces] + * + * @typedef {object} AddEvent + * @property {"add"} t The history event type + * @property {Array} [groups] An array with added groups + * @property {Array} [junctions] An array with added junctions + * @property {Array} [links] An array with added links + * @property {Array} [nodes] An array with added nodes + * @property {Array} [removedLinks] An array with removed links + * @property {{ id: string; changed?: boolean; instances: Array; }} [subflow] + * @property {Array} [subflows] An array with added subflows (tabs) + * @property {Array} [workspaces] An array with added workspaces + * + * @param {AddEvent} ev The history event to undo * @param {object} [modifiedTabs] - * @returns {HistoryEvent} The generated history event to redo + * @returns {DeleteEvent} The generated history event to redo */ function onAdd(ev, modifiedTabs) { const inverseEv = { @@ -157,7 +177,6 @@ RED.history = (function () { } } - // Mark each nodes which use this subflow has changed // TODO: why? if (ev.subflow) { inverseEv.subflow = {}; @@ -195,22 +214,25 @@ RED.history = (function () { /** * Called on the `delete` history event - * @param {object} ev The history event to undo - * @param {"delete"} ev.t The history event type - * @param {Record} [ev.changes] - * @param {Array} [ev.createdLinks] - * @param {boolean} [ev.dirty] - * @param {Array} [ev.groups] - * @param {Array} [ev.junctions] - * @param {Array} [ev.links] - * @param {Array} [ev.nodes] - * @param {Subflow} [ev.subflow] - * @param {Array} [ev.subflowInputs] - * @param {Array} [ev.subflowOutputs] - * @param {Array} [ev.subflows] - * @param {Array} [ev.workspaces] + * + * @typedef {object} DeleteEvent + * @property {"delete"} t The history event type + * @property {Record} [changes] An object with changes. + * The key is the id of a node and the value is an object with the changes to apply + * @property {Array} [createdLinks] An array with created links + * @property {Array} [groups] An array with removed groups + * @property {Array} [junctions] An array with removed junctions + * @property {Array} [links] An array with removed links + * @property {Array} [nodes] An array with removed nodes + * @property {{ id?: string; instances?: Array; status?: string;}} [subflow] + * @property {Array} [subflowInputs] An array with removed subflow input + * @property {Array} [subflowOutputs] An array with removed subflow outputs + * @property {Array} [subflows] An array with removed subflows (tabs) + * @property {Array} [workspaces] An array with removed workspace + * + * @param {DeleteEvent} ev The history event to undo * @param {object} [modifiedTabs] - * @returns {HistoryEvent} The generated history event to redo + * @returns {AddEvent} The generated history event to redo */ function onDelete(ev, modifiedTabs) { // TODO: check why global @@ -266,6 +288,7 @@ RED.history = (function () { } } + // TODO: why? if (ev.subflow) { inverseEv.subflow = {}; if (ev.subflow.hasOwnProperty("instances")) { @@ -400,14 +423,18 @@ RED.history = (function () { /** * Called on the `move` history event - * @param {object} ev The history event to undo - * @param {"move"} ev.t The history event type - * @param {Group} [ev.addToGroup] - * @param {Array} [ev.links] - * @param {Array<{ n: Group; ox: number; oy: number; dx: number; dy: number; }>} ev.nodes - * @param {Array} [ev.removedLinks] - * @param {Group} [ev.removeFromGroup] - * @returns {HistoryEvent} The generated history event to redo + * + * @typedef {object} MoveEvent + * @property {"move"} t The history event type + * @property {Group} [addToGroup] The group in which the nodes were added + * @property {Array} [links] + * @property {Array<{ n: Node; ox: number; oy: number; dx: number; + * dy: number; }>} nodes An array with nodes moved + * @property {Array} [removedLinks] + * @property {Group} [removeFromGroup] The group in which the nodes were removed + * + * @param {MoveEvent} ev The history event to undo + * @returns {MoveEvent} The generated history event to redo */ function onMove(ev) { const inverseEv = { @@ -428,7 +455,7 @@ RED.history = (function () { } // A move could have caused a link splice - // So remove each links then readd them + // TODO: still used? Ctrl + X ? if (ev.links) { inverseEv.removedLinks = []; for (let i = 0; i < ev.links.length; i++) { @@ -462,14 +489,20 @@ RED.history = (function () { /** * Called on the `createSubflow` history event - * @param {object} ev The history event to undo - * @param {"createSubflow"} ev.t The history event type - * @param {string} ev.activeWorkspace - * @param {Array} [ev.links] - * @param {Array} [ev.nodes] - * @param {Array} [ev.removedLinks] - * @param {{ subflow: Subflow; offsetX?: number; offsetY?: number; }} ev.subflow - * @returns {HistoryEvent} The generated history event to redo + * + * @typedef {object} CreateSubflowEvent + * @property {"createSubflow"} t The history event type + * @property {string} activeWorkspace The id of the active workspace + * @property {Array} [links] An array with added links (during + * conversion to Subflow - links inside the subflow) + * @property {Array} [nodes] An array with subflow node ids + * @property {Array} [removedLinks] An array with removed links + * (during conversion to Subflow - links from active workspace) + * @property {{ subflow: Subflow; offsetX?: number; + * offsetY?: number; }} subflow The subflow created to delete + * + * @param {CreateSubflowEvent} ev The history event to undo + * @returns {DeleteSubflowEvent} The generated history event to redo */ function onCreateSubflow(ev) { const inverseEv = { @@ -478,11 +511,12 @@ RED.history = (function () { dirty: RED.nodes.dirty() }; - // Remove all nodes from the subflow + // Remove all subflow nodes and move all nodes from subflow definition + // to the active workspace if (ev.nodes) { inverseEv.movedNodes = []; const z = ev.activeWorkspace; - // Get all nodes from the subflow defiition + // Get all nodes from the subflow definition let fullNodeList = RED.nodes.filterNodes({ z: ev.subflow.subflow.id }); fullNodeList = fullNodeList.concat(RED.nodes.groups(ev.subflow.subflow.id)); fullNodeList = fullNodeList.concat(RED.nodes.junctions(ev.subflow.subflow.id)); @@ -500,7 +534,7 @@ RED.history = (function () { } } - // Remove each links + // Remove each links (from the conversion - inside the subflow) if (ev.links) { inverseEv.links = []; for (let i = 0; i < ev.links.length; i++) { @@ -514,7 +548,7 @@ RED.history = (function () { RED.nodes.removeSubflow(ev.subflow.subflow); RED.workspaces.remove(ev.subflow.subflow); - // Add each links + // Add each links (from the undo of conversion - active workspace) if (ev.removedLinks) { inverseEv.createdLinks = []; for (let i = 0; i < ev.removedLinks.length; i++) { @@ -528,15 +562,23 @@ RED.history = (function () { /** * Called on the `deleteSubflow` history event - * @param {object} ev The history event to undo - * @param {"deleteSubflow"} ev.t The history event type - * @param {string} ev.activeWorkspace - * @param {Array} [ev.createdLinks] - * @param {Array} [ev.links] - * @param {Array} [ev.movedNodes] - * @param {{ subflow: Subflow; offsetX?: number; offsetY?: number; }} ev.subflow - * @param {Array} [ev.subflows] - * @returns {HistoryEvent} The generated history event to redo + * + * @typedef {object} DeleteSubflowEvent + * @property {"deleteSubflow"} t The history event type + * @property {string} activeWorkspace The id of the active workspace + * @property {Array} [createdLinks] An array with added links + * (during undo conversion to Subflow - links from active workspace) + * @property {Array} [links] An array with removed links (during + * undo conversion to Subflow - links inside the subflow) + * @property {Array} [movedNodes] An array with nodes to move to the + * subflow to create + * @property {{ subflow: Subflow; offsetX?: number; + * offsetY?: number; }} subflow The deleted subflow to create + * @property {Array} [subflows] An array with subflow nodes + * (redo conversion to subflow) + * + * @param {DeleteSubflowEvent} ev The history event to undo + * @returns {CreateSubflowEvent} The generated history event to redo */ function onDeleteSubflow(ev) { const inverseEv = { @@ -555,7 +597,7 @@ RED.history = (function () { } } - // Create all nodes of the subflow + // Create all subflow nodes if (ev.subflows) { inverseEv.nodes = []; for (let i = 0; i < ev.subflows.length; i++) { @@ -564,6 +606,8 @@ RED.history = (function () { } } + // Move each node from the active workspace to the subflow created + // Nodes selected for the conversion to subflow if (ev.movedNodes) { ev.movedNodes.forEach(function (nid) { let nn = RED.nodes.node(nid); @@ -577,7 +621,7 @@ RED.history = (function () { }); } - // Add each links + // Add each links (from redo of conversion - inside the subflow) if (ev.links) { inverseEv.links = []; for (let i = 0; i < ev.links.length; i++) { @@ -586,7 +630,7 @@ RED.history = (function () { } } - // Remove each links + // Remove each links (from redo of conversion - on active workspace) if (ev.createdLinks) { inverseEv.removedLinks = []; for (let i = 0; i < ev.createdLinks.length; i++) { @@ -600,11 +644,14 @@ RED.history = (function () { /** * Called on the `reorder` history event - * @param {object} ev The history event to undo - * @param {"reorder"} ev.t The history event type - * @param {{ from: string; to: string; z: string; }} [ev.nodes] - * @param {{ from: Array; to: Array; }} [ev.workspaces] - * @returns {HistoryEvent} The generated history event to redo + * + * @typedef {object} ReorderEvent + * @property {"reorder"} t The history event type + * @property {{ from: string; to: string; z: string; }} [nodes] + * @property {{ from: Array; to: Array; }} [workspaces] + * + * @param {ReorderEvent} ev The history event to undo + * @returns {ReorderEvent} The generated history event to redo */ function onReoder(ev) { const inverseEv = { @@ -634,10 +681,13 @@ RED.history = (function () { /** * Called on the `createGroup` history event - * @param {object} ev The history event to undo - * @param {"createGroup"} ev.t The history event type - * @param {Array} [ev.groups] - * @returns {HistoryEvent} The generated history event to redo + * + * @typedef {object} CreateGroupEvent + * @property {"createGroup"} t The history event type + * @property {Array} [groups] An array with groups to remove + * + * @param {CreateGroupEvent} ev The history event to undo + * @returns {UngroupEvent} The generated history event to redo */ function onCreateGroup(ev) { const inverseEv = { @@ -659,10 +709,13 @@ RED.history = (function () { /** * Called on the `ungroup` history event - * @param {object} ev The history event to undo - * @param {"ungroup"} ev.t The history event type - * @param {Array} [ev.groups] - * @returns {HistoryEvent} The generated history event to redo + * + * @typedef {object} UngroupEvent + * @property {"ungroup"} t The history event type + * @property {Array} [groups] An array with groups to create + * + * @param {UngroupEvent} ev The history event to undo + * @returns {CreateGroupEvent} The generated history event to redo */ function onUngroup(ev) { const inverseEv = { @@ -695,12 +748,16 @@ RED.history = (function () { /** * Called on the `addToGroup` history event - * @param {object} ev The history event to undo - * @param {"addToGroup"} ev.t The history event type - * @param {Group} [ev.group] - * @param {Array | Node} [ev.nodes] - * @param {boolean} [ev.reparent] - * @returns {HistoryEvent} The generated history event to redo + * + * @typedef {object} AddToGroupEvent + * @property {"addToGroup"} t The history event type + * @property {Group} group The group in which remove nodes + * @property {Array | Node} [nodes] An array of nodes or one node + * to remove from the group + * @property {boolean} [reparent] + * + * @param {AddToGroupEvent} ev The history event to undo + * @returns {RemoveFromGroupEvent} The generated history event to redo */ function onAddTogroup(ev) { const inverseEv = { @@ -721,12 +778,16 @@ RED.history = (function () { /** * Called on the `removeFromGroup` history event - * @param {object} ev The history event to undo - * @param {"removeFromGroup"} ev.t The history event type - * @param {Group} [ev.group] - * @param {Array | Node} [ev.nodes] - * @param {boolean} [ev.reparent] - * @returns {HistoryEvent} The generated history event to redo + * + * @typedef {object} RemoveFromGroupEvent + * @property {"removeFromGroup"} t The history event type + * @property {Group} group The group in which add nodes + * @property {Array | Node} [nodes] An array of nodes or one node + * to add to the group + * @property {boolean} [reparent] + * + * @param {RemoveFromGroupEvent} ev The history event to undo + * @returns {AddToGroupEvent} The generated history event to redo */ function onRemoveFromgroup(ev) { const inverseEv = { @@ -747,17 +808,20 @@ RED.history = (function () { /** * Called on the `edit` history event - * @param {object} ev The history event to undo - * @param {"edit"} ev.t The history event type - * @param {boolean} ev.changed - * @param {object} ev.changes - * @param {Array} [ev.createdLinks] - * @param {Array} [ev.links] - * @param {Node} ev.node - * @param {object} [ev.outputMap] - * @param {{ instances?: Array; inputCount?: number; - * outputCount?: number; status?: string; }} [ev.subflow] - * @returns {HistoryEvent} The generated history event to redo + * + * @typedef {object} EditEvent + * @property {"edit"} t The history event type + * @property {boolean} changed The changed node state before modifications + * @property {object} changes An object with previous node properties value + * @property {Array} [createdLinks] An array with links to create (redo) + * @property {Array} [links] An array with removed links + * @property {Node} node The current node + * @property {object} [outputMap] + * @property {{ instances?: Array; inputCount?: number; + * outputCount?: number; status?: string; }} [subflow] + * + * @param {EditEvent} ev The history event to undo + * @returns {EditEvent} The generated history event to redo */ function onEdit(ev) { const inverseEv = { @@ -769,7 +833,7 @@ RED.history = (function () { }; // Apply old values to the current node - // And saves values ​​changed by old values + // And saves values ​​changed by old values for the redo for (const i in ev.changes) { if (ev.changes.hasOwnProperty(i)) { inverseEv.changes[i] = ev.node[i]; @@ -908,7 +972,7 @@ RED.history = (function () { } } - // Remove links previously created (undo) + // Remove links previously created (redo) if (ev.createdLinks) { inverseEv.links = []; for (let i = 0; i < ev.createdLinks.length; i++) { @@ -922,14 +986,22 @@ RED.history = (function () { /** * Called on the `replace` history event - * @param {object} ev The history event to undo - * @param {"replace"} ev.t The history event type - * @param {Record} ev.changed - * @param {boolean} [ev.complete] - * @param {Array} ev.config - * @param {Record} ev.moved - * @param {string} [ev.rev] - * @returns {HistoryEvent} The generated history event to redo + * + * @typedef {object} ReplaceEvent + * @property {"replace"} t The history event type + * @property {Record} [changed] An object with a node id + * as key and the node changed property as value + * @property {boolean} [complete] If the {@link ReplaceEvent.config} + * property contains the complete flows + * @property {Array} config An array with config nodes and/or + * subflow definitions to replace. Can be the complete flows too + * @property {boolean} [dirty] The dirty state before replacement + * @property {Record} [moved] An object with a node id + * as key and the node moved property as value + * @property {string} [rev] A revision version + * + * @param {ReplaceEvent} ev The history event to undo + * @returns {ReplaceEvent} The generated history event to redo */ function onReplace(ev) { let inverseEv; @@ -954,6 +1026,7 @@ RED.history = (function () { const node = RED.nodes.node(n.id); if (node) { inverseEv.changed[n.id] = node.changed; + // TODO: Why moved? inverseEv.moved[n.id] = node.moved; } }); @@ -1005,10 +1078,13 @@ RED.history = (function () { /** * Called on the `multi` history event - * @param {object} ev The history event to undo - * @param {"multi"} ev.t The history event type - * @param {Array} ev.events - * @returns {HistoryEvent} The generated history event to redo + * + * @typedef {object} MultiEvent + * @property {"multi"} t The history event type + * @property {Array} events An array with events + * + * @param {MultiEvent} ev The history event to undo + * @returns {MultiEvent} The generated history event to redo */ function onMultipleEvents(ev) { const inverseEv = { @@ -1027,6 +1103,7 @@ RED.history = (function () { /** * Called to undo the history event + * * @param {HistoryEvent} ev The history event to undo * @returns {HistoryEvent} The generated history event to redo */