diff --git a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json index c8abada3e..1cc571200 100755 --- a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json +++ b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json @@ -683,7 +683,8 @@ "empty": "empty", "globalConfig": "Global Configuration Nodes", "triggerAction": "Trigger action", - "find": "Find in workspace" + "find": "Find in workspace", + "copyItemUrl": "Copy item url" }, "help": { "name": "Help", diff --git a/packages/node_modules/@node-red/editor-client/src/js/red.js b/packages/node_modules/@node-red/editor-client/src/js/red.js index 55446418b..129c46799 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/red.js +++ b/packages/node_modules/@node-red/editor-client/src/js/red.js @@ -249,8 +249,35 @@ var RED = (function() { RED.nodes.import(nodes.flows); RED.nodes.dirty(false); RED.view.redraw(true); - if (/^#flow\/.+$/.test(currentHash)) { - RED.workspaces.show(currentHash.substring(6),true); + if (/^#(flow|node|group)\/.+$/.test(currentHash)) { + const hashParts = currentHash.split('/') + const showEditDialog = hashParts.length > 2 && hashParts[2] === 'edit' + if (hashParts[0] === '#flow') { + RED.workspaces.show(hashParts[1], true); + if (showEditDialog) { + RED.workspaces.edit() + } + } else if (hashParts[0] === '#node') { + const nodeToShow = RED.nodes.node(hashParts[1]) + if (nodeToShow) { + setTimeout(() => { + RED.view.reveal(nodeToShow.id) + window.location.hash = currentHash + if (showEditDialog) { + RED.editor.edit(nodeToShow) + } + }, 50) + } + } else if (hashParts[0] === '#group') { + const nodeToShow = RED.nodes.group(hashParts[1]) + if (nodeToShow) { + RED.view.reveal(nodeToShow.id) + window.location.hash = currentHash + if (showEditDialog) { + RED.editor.editGroup(nodeToShow) + } + } + } } if (RED.workspaces.count() > 0) { const hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}"); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js index dfd4b1e43..c46aa97e8 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js @@ -25,6 +25,7 @@ RED.sidebar.info = (function() { var propertiesPanelHeaderLabel; var propertiesPanelHeaderReveal; var propertiesPanelHeaderHelp; + var propertiesPanelHeaderCopyLink; var selectedObject; @@ -67,10 +68,20 @@ RED.sidebar.info = (function() { propertiesPanelHeaderIcon = $("").appendTo(propertiesPanelHeader); propertiesPanelHeaderLabel = $("").appendTo(propertiesPanelHeader); - propertiesPanelHeaderHelp = $('').css({ + + propertiesPanelHeaderCopyLink = $('').css({ position: 'absolute', top: '12px', right: '32px' + }).on("click", function(evt) { + RED.actions.invoke('core:copy-item-url',selectedObject) + }).appendTo(propertiesPanelHeader); + RED.popover.tooltip(propertiesPanelHeaderCopyLink,RED._("sidebar.info.copyItemUrl")); + + propertiesPanelHeaderHelp = $('').css({ + position: 'absolute', + top: '12px', + right: '56px' }).on("click", function(evt) { evt.preventDefault(); evt.stopPropagation(); @@ -80,8 +91,7 @@ RED.sidebar.info = (function() { }).appendTo(propertiesPanelHeader); RED.popover.tooltip(propertiesPanelHeaderHelp,RED._("sidebar.help.showHelp")); - - propertiesPanelHeaderReveal = $('').css({ + propertiesPanelHeaderReveal = $('').css({ position: 'absolute', top: '12px', right: '8px' @@ -185,6 +195,7 @@ RED.sidebar.info = (function() { propertiesPanelHeaderLabel.text(""); propertiesPanelHeaderReveal.hide(); propertiesPanelHeaderHelp.hide(); + propertiesPanelHeaderCopyLink.hide(); return; } else if (Array.isArray(node)) { // Multiple things selected @@ -196,6 +207,7 @@ RED.sidebar.info = (function() { propertiesPanelHeaderLabel.text("Selection"); propertiesPanelHeaderReveal.hide(); propertiesPanelHeaderHelp.hide(); + propertiesPanelHeaderCopyLink.hide(); selectedObject = null; var types = { @@ -277,9 +289,11 @@ RED.sidebar.info = (function() { if (node.type === "tab" || node.type === "subflow") { // If nothing is selected, but we're on a flow or subflow tab. propertiesPanelHeaderHelp.hide(); + propertiesPanelHeaderCopyLink.show(); } else if (node.type === "group") { propertiesPanelHeaderHelp.hide(); + propertiesPanelHeaderCopyLink.show(); propRow = $(' ').appendTo(tableBody); @@ -304,8 +318,10 @@ RED.sidebar.info = (function() { } } else if (node.type === 'junction') { propertiesPanelHeaderHelp.hide(); + propertiesPanelHeaderCopyLink.hide(); } else { propertiesPanelHeaderHelp.show(); + propertiesPanelHeaderCopyLink.show(); if (!subflowRegex) { propRow = $(''+RED._("sidebar.info.type")+'').appendTo(tableBody); 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 bc81d4a43..1ed5791a6 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 @@ -1192,6 +1192,30 @@ RED.view.tools = (function() { RED.view.redraw(true); } + function copyItemUrl(node, isEdit) { + if (!node) { + const selection = RED.view.selection(); + if (selection.nodes && selection.nodes.length > 0) { + node = selection.nodes[0] + } + } + if (node) { + let thingType = 'node' + if (node.type === 'group') { + thingType = 'group' + } else if (node.type === 'tab' || node.type === 'subflow') { + thingType = 'flow' + } + let url = `${window.location.origin}${window.location.pathname}#${thingType}/${node.id}` + if (isEdit) { + url += '/edit' + } + if (RED.clipboard.copyText(url)) { + RED.notify('Copied url to clipboard', { timeout: 2000 }) + } + } + } + return { init: function() { RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); }) @@ -1258,6 +1282,9 @@ RED.view.tools = (function() { RED.actions.add("core:generate-node-names", generateNodeNames ) + RED.actions.add("core:copy-item-url", function (node) { copyItemUrl(node) }) + RED.actions.add("core:copy-item-edit-url", function (node) { copyItemUrl(node, true) }) + // 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 8c7ea22a3..c6c49c942 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 @@ -6137,7 +6137,9 @@ RED.view = (function() { if (node.z && (node.type === "group" || node._def.category !== 'config')) { node.dirty = true; RED.workspaces.show(node.z); - + if (node.type === "group" && !node.w && !node.h) { + _redraw(); + } var screenSize = [chart[0].clientWidth/scaleFactor,chart[0].clientHeight/scaleFactor]; var scrollPos = [chart.scrollLeft()/scaleFactor,chart.scrollTop()/scaleFactor]; var cx = node.x; diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js b/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js index 1f5cdf0f1..ae38f2c4d 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js @@ -138,7 +138,7 @@ RED.workspaces = (function() { activeWorkspace = tab.id; window.location.hash = 'flow/'+tab.id; $("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!tab.disabled); - } else { + } else { $("#red-ui-workspace-chart").hide(); activeWorkspace = 0; window.location.hash = '';