From 3c0b74005b3cb4fabbda37d7846b228bf7367463 Mon Sep 17 00:00:00 2001 From: Nick O'Leary Date: Wed, 9 Mar 2022 11:32:37 +0000 Subject: [PATCH] Add core:generate-node-names action --- .../editor-client/src/js/ui/view-tools.js | 76 +++++++++++++++++-- .../@node-red/editor-client/src/js/ui/view.js | 2 +- .../@node-red/nodes/core/common/21-debug.html | 3 + .../@node-red/nodes/core/common/60-link.html | 7 +- 4 files changed, 81 insertions(+), 7 deletions(-) diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js index 3981892f4..0281ab94e 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js @@ -811,7 +811,7 @@ RED.view.tools = (function() { /** * Splits selected wires and re-joins them with link-out+link-in - * @param {Object || Object[]} wires The wire(s) to split and replace with link-out, link-in nodes. + * @param {Object || Object[]} wires The wire(s) to split and replace with link-out, link-in nodes. */ function splitWiresWithLinkNodes(wires) { let wiresToSplit = wires || RED.view.selection().links; @@ -868,7 +868,7 @@ RED.view.tools = (function() { nodeSrcMap[linkOutMapId] = nnLinkOut; let yOffset = 0; if(nSrc.outputs > 1) { - + const CENTER_PORT = (((nSrc.outputs-1) / 2) + 1); const offsetCount = Math.abs(CENTER_PORT - (srcPort + 1)); yOffset = (_gridSize * 2 * offsetCount); @@ -918,7 +918,7 @@ RED.view.tools = (function() { t: 'add', links: [link], }); - } + } //connect the link out/link in virtual wires if(nnLinkIn.links.indexOf(nnLinkOut.id) == -1) { @@ -937,9 +937,9 @@ RED.view.tools = (function() { } //add all history events to stack RED.history.push(history); - + //select all downstream of new link-in nodes so user can drag to new location - RED.view.clearSelection(); + RED.view.clearSelection(); RED.view.select({nodes: Object.values(nodeTrgMap) }); selectConnected("down"); @@ -970,6 +970,70 @@ RED.view.tools = (function() { return gridOffset; } + /** + * Generate names for the select nodes. + * - it only sets the name if it is currently blank + * - it uses ` ` - where N is the next available integer that + * doesn't clash with any existing nodes of that type + * @param {Object} node The node to set the name of - if not provided, uses current selection + */ + function generateNodeNames(node) { + const nodes = node?[node]:RED.view.selection().nodes; + if (nodes && nodes.length > 0) { + // Generate history event if using the workspace selection, + // or if the provided node already exists + const generateHistory = !node || !!RED.nodes.node(node.id) + const historyEvents = [] + const typeIndex = {} + let changed = false; + nodes.forEach(n => { + if (n._def && n._def.defaults && n._def.defaults.name) { + const paletteLabel = RED.utils.getPaletteLabel(n.type, n._def) + const defaultNodeNameRE = new RegExp('^'+paletteLabel+' (\\d+)$') + if (!typeIndex.hasOwnProperty(n.type)) { + const existingNodes = RED.nodes.filterNodes({type: n.type}) + let maxNameNumber = 0; + existingNodes.forEach(n => { + let match = defaultNodeNameRE.exec(n.name) + if (match) { + let nodeNumber = parseInt(match[1]) + if (nodeNumber > maxNameNumber) { + maxNameNumber = nodeNumber + } + } + }) + typeIndex[n.type] = maxNameNumber + 1 + } + if (n.name === '') { + if (generateHistory) { + historyEvents.push({ + t:'edit', + node: n, + changes: { name: n.name }, + dirty: RED.nodes.dirty(), + changed: n.changed + }) + } + n.name = paletteLabel+" "+typeIndex[n.type] + n.dirty = true + typeIndex[n.type]++ + changed = true + } + } + }) + if (changed) { + if (historyEvents.length > 0) { + RED.history.push({ + t: 'multi', + events: historyEvents + }) + } + RED.nodes.dirty(true) + RED.view.redraw() + } + } + } + return { init: function() { RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); }) @@ -1033,6 +1097,8 @@ RED.view.tools = (function() { RED.actions.add("core:split-wire-with-link-nodes", function () { splitWiresWithLinkNodes() }); + RED.actions.add("core:generate-node-names", generateNodeNames ) + // RED.actions.add("core:add-node", function() { addNode() }) }, /** diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js index 263e1880e..840a12791 100755 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js @@ -5419,7 +5419,7 @@ RED.view = (function() { } /** - * Create a node from a type string. + * Create a node from a type string. * **NOTE:** Can throw on error - use `try` `catch` block when calling * @param {string} type The node type to create * @param {number} [x] (optional) The horizontal position on the workspace diff --git a/packages/node_modules/@node-red/nodes/core/common/21-debug.html b/packages/node_modules/@node-red/nodes/core/common/21-debug.html index 195423482..c585fadc0 100644 --- a/packages/node_modules/@node-red/nodes/core/common/21-debug.html +++ b/packages/node_modules/@node-red/nodes/core/common/21-debug.html @@ -507,6 +507,9 @@ $("#node-input-complete").val($("#node-input-typed-complete").typedInput('value')); } $("#node-input-statusVal").val($("#node-input-typed-status").typedInput('value')); + }, + onadd: function() { + RED.actions.invoke("core:generate-node-names",this) } }); })(); diff --git a/packages/node_modules/@node-red/nodes/core/common/60-link.html b/packages/node_modules/@node-red/nodes/core/common/60-link.html index f3fabba59..98f0ddc25 100644 --- a/packages/node_modules/@node-red/nodes/core/common/60-link.html +++ b/packages/node_modules/@node-red/nodes/core/common/60-link.html @@ -209,6 +209,8 @@ } function onAdd() { + RED.actions.invoke("core:generate-node-names",this) + for (var i=0;i