From fb499be9795f667d2c0810dbd657d61dae6ed4a2 Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Tue, 25 Oct 2022 23:44:59 +0100
Subject: [PATCH 1/5] Add context menu to tab bar
---
.../editor-client/locales/en-US/editor.json | 4 +-
.../editor-client/src/js/ui/clipboard.js | 21 +-
.../editor-client/src/js/ui/common/menu.js | 4 +-
.../editor-client/src/js/ui/common/tabs.js | 49 +++-
.../editor-client/src/js/ui/contextMenu.js | 217 ++++++++---------
.../@node-red/editor-client/src/js/ui/view.js | 1 +
.../editor-client/src/js/ui/workspaces.js | 228 +++++++++++-------
7 files changed, 300 insertions(+), 224 deletions(-)
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 1cc571200..f226cb79e 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
@@ -57,11 +57,11 @@
"addFlowToRight": "Add flow to the right",
"hideFlow": "Hide flow",
"hideOtherFlows": "Hide other flows",
- "showAllFlows": "Show all flows",
+ "showAllFlows": "Show all flows (__count__ hidden)",
"hideAllFlows": "Hide all flows",
"hiddenFlows": "List __count__ hidden flow",
"hiddenFlows_plural": "List __count__ hidden flows",
- "showLastHiddenFlow": "Show last hidden flow",
+ "showLastHiddenFlow": "Reopen hidden flow",
"listFlows": "List flows",
"listSubflows": "List subflows",
"status": "Status",
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js b/packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js
index f547203d4..61435f6ad 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/clipboard.js
@@ -423,11 +423,10 @@ RED.clipboard = (function() {
}
}
- function showImportNodes(mode) {
+ function showImportNodes(library = 'clipboard') {
if (disabled) {
return;
}
- mode = mode || "clipboard";
dialogContainer.empty();
dialogContainer.append($(importNodesDialog));
@@ -533,8 +532,8 @@ RED.clipboard = (function() {
$("#red-ui-clipboard-dialog-import-file-upload").trigger("click");
})
- tabs.activateTab("red-ui-clipboard-dialog-import-tab-"+mode);
- if (mode === 'clipboard') {
+ tabs.activateTab("red-ui-clipboard-dialog-import-tab-"+library);
+ if (library === 'clipboard') {
setTimeout(function() {
$("#red-ui-clipboard-dialog-import-text").trigger("focus");
},100)
@@ -558,13 +557,16 @@ RED.clipboard = (function() {
});
}
- function showExportNodes(mode) {
+ /**
+ * Show the export dialog
+ * @params library which export destination to show
+ * @params mode whether to default to 'auto' (default) or 'flow'
+ **/
+ function showExportNodes(library = 'clipboard', mode = 'auto' ) {
if (disabled) {
return;
}
- mode = mode || "clipboard";
-
dialogContainer.empty();
dialogContainer.append($(exportNodesDialog));
@@ -766,12 +768,15 @@ RED.clipboard = (function() {
}
}
}
+ if (mode === 'flow' && !$("#red-ui-clipboard-dialog-export-rng-flow").hasClass('disabled')) {
+ $("#red-ui-clipboard-dialog-export-rng-flow").trigger("click");
+ }
if (format === "red-ui-clipboard-dialog-export-fmt-full") {
$("#red-ui-clipboard-dialog-export-fmt-full").trigger("click");
} else {
$("#red-ui-clipboard-dialog-export-fmt-mini").trigger("click");
}
- tabs.activateTab("red-ui-clipboard-dialog-export-tab-"+mode);
+ tabs.activateTab("red-ui-clipboard-dialog-export-tab-"+library);
var dialogHeight = 400;
var winHeight = $(window).height();
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/menu.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/menu.js
index 2d95f894a..8d0f1dbd3 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/menu.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/menu.js
@@ -94,8 +94,8 @@ RED.menu = (function() {
var link = $(linkContent).appendTo(item);
opt.link = link;
- if (typeof opt.onselect === 'string') {
- var shortcut = RED.keyboard.getShortcut(opt.onselect);
+ if (typeof opt.onselect === 'string' || opt.shortcut) {
+ var shortcut = opt.shortcut || RED.keyboard.getShortcut(opt.onselect);
if (shortcut && shortcut.key) {
opt.shortcutSpan = $(''+RED.keyboard.formatKey(shortcut.key, true)+'').appendTo(link.find(".red-ui-menu-label"));
}
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/tabs.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/tabs.js
index 8901cf11f..a8e7ea727 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/tabs.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/tabs.js
@@ -141,7 +141,29 @@ RED.tabs = (function() {
})
}
-
+ if (options.contextmenu) {
+ wrapper.on('contextmenu', function(evt) {
+ let clickedTab
+ let target = evt.target
+ while(target.nodeName !== 'A' && target.nodeName !== 'UL' && target.nodeName !== 'BODY') {
+ target = target.parentNode
+ }
+ if (target.nodeName === 'A') {
+ const href = target.getAttribute('href')
+ if (href) {
+ clickedTab = tabs[href.slice(1)]
+ }
+ }
+ evt.preventDefault()
+ evt.stopPropagation()
+ RED.contextMenu.show({
+ x:evt.clientX-5,
+ y:evt.clientY-5,
+ options: options.contextmenu(clickedTab)
+ })
+ return false
+ })
+ }
var scrollLeft;
var scrollRight;
@@ -809,17 +831,17 @@ RED.tabs = (function() {
});
RED.popover.tooltip(closeLink,RED._("workspace.hideFlow"));
}
- if (tab.hideable) {
- li.addClass("red-ui-tabs-closeable")
- var closeLink = $("",{href:"#",class:"red-ui-tab-close red-ui-tab-hide"}).appendTo(li);
- closeLink.append('');
- closeLink.append('');
- closeLink.on("click",function(event) {
- event.preventDefault();
- hideTab(tab.id);
- });
- RED.popover.tooltip(closeLink,RED._("workspace.hideFlow"));
- }
+ // if (tab.hideable) {
+ // li.addClass("red-ui-tabs-closeable")
+ // var closeLink = $("",{href:"#",class:"red-ui-tab-close red-ui-tab-hide"}).appendTo(li);
+ // closeLink.append('');
+ // closeLink.append('');
+ // closeLink.on("click",function(event) {
+ // event.preventDefault();
+ // hideTab(tab.id);
+ // });
+ // RED.popover.tooltip(closeLink,RED._("workspace.hideFlow"));
+ // }
var badges = $('').appendTo(li);
if (options.onselect) {
@@ -938,6 +960,9 @@ RED.tabs = (function() {
activeIndex: function() {
return ul.find("li.active").index()
},
+ getTabIndex: function (id) {
+ return ul.find("a[href='#"+id+"']").parent().index()
+ },
contains: function(id) {
return ul.find("a[href='#"+id+"']").length > 0;
},
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js b/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js
index 66ae2b943..8052d561f 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js
@@ -1,21 +1,6 @@
RED.contextMenu = (function () {
let menu;
- function createMenu() {
- // menu = RED.popover.menu({
- // options: [
- // {
- // label: 'delete selection',
- // onselect: function() {
- // RED.actions.invoke('core:delete-selection')
- // RED.view.focus()
- // }
- // },
- // { label: 'world' }
- // ],
- // width: 200,
- // })
- }
function disposeMenu() {
$(document).off("mousedown.red-ui-workspace-context-menu");
@@ -28,114 +13,118 @@ RED.contextMenu = (function () {
if (menu) {
menu.remove()
}
+ let menuItems = []
+ if (options.options) {
+ menuItems = options.options
+ } else if (options.type === 'workspace') {
+ const selection = RED.view.selection()
+ const noSelection = !selection || Object.keys(selection).length === 0
+ const hasSelection = (selection.nodes && selection.nodes.length > 0);
+ const hasMultipleSelection = hasSelection && selection.nodes.length > 1;
+ const virtulLinks = (selection.links && selection.links.filter(e => !!e.link)) || [];
+ const wireLinks = (selection.links && selection.links.filter(e => !e.link)) || [];
+ const hasLinks = wireLinks.length > 0;
+ const isSingleLink = !hasSelection && hasLinks && wireLinks.length === 1
+ const isMultipleLinks = !hasSelection && hasLinks && wireLinks.length > 1
+ const canDelete = hasSelection || hasLinks
+ const isGroup = hasSelection && selection.nodes.length === 1 && selection.nodes[0].type === 'group'
- const selection = RED.view.selection()
- const noSelection = !selection || Object.keys(selection).length === 0
- const hasSelection = (selection.nodes && selection.nodes.length > 0);
- const hasMultipleSelection = hasSelection && selection.nodes.length > 1;
- const virtulLinks = (selection.links && selection.links.filter(e => !!e.link)) || [];
- const wireLinks = (selection.links && selection.links.filter(e => !e.link)) || [];
- const hasLinks = wireLinks.length > 0;
- const isSingleLink = !hasSelection && hasLinks && wireLinks.length === 1
- const isMultipleLinks = !hasSelection && hasLinks && wireLinks.length > 1
- const canDelete = hasSelection || hasLinks
- const isGroup = hasSelection && selection.nodes.length === 1 && selection.nodes[0].type === 'group'
-
- const canRemoveFromGroup = hasSelection && !!selection.nodes[0].g
- const offset = $("#red-ui-workspace-chart").offset()
-
- let addX = options.x - offset.left + $("#red-ui-workspace-chart").scrollLeft()
- let addY = options.y - offset.top + $("#red-ui-workspace-chart").scrollTop()
-
- if (RED.view.snapGrid) {
- const gridSize = RED.view.gridSize()
- addX = gridSize * Math.floor(addX / gridSize)
- addY = gridSize * Math.floor(addY / gridSize)
- }
-
- const menuItems = [
- { onselect: 'core:show-action-list', onpostselect: function () { } },
- {
- label: RED._("contextMenu.insert"),
- options: [
- {
- label: RED._("contextMenu.node"),
- onselect: function () {
- RED.view.showQuickAddDialog({
- position: [addX, addY],
- touchTrigger: true,
- splice: isSingleLink ? selection.links[0] : undefined,
- // spliceMultiple: isMultipleLinks
- })
- }
- },
- (hasLinks) ? { // has least 1 wire selected
- label: RED._("contextMenu.junction"),
- onselect: 'core:split-wires-with-junctions',
- disabled: !hasLinks
- } : {
- label: RED._("contextMenu.junction"),
- onselect: function () {
- const nn = {
- _def: { defaults: {} },
- type: 'junction',
- z: RED.workspaces.active(),
- id: RED.nodes.id(),
- x: addX,
- y: addY,
- w: 0, h: 0,
- outputs: 1,
- inputs: 1,
- dirty: true
- }
- const historyEvent = {
- dirty: RED.nodes.dirty(),
- t: 'add',
- junctions: [nn]
- }
- RED.nodes.addJunction(nn);
- RED.history.push(historyEvent);
- RED.nodes.dirty(true);
- RED.view.select({nodes: [nn] });
- RED.view.redraw(true)
- }
- },
- {
- label: RED._("contextMenu.linkNodes"),
- onselect: 'core:split-wire-with-link-nodes',
- disabled: !hasLinks
- }
- ]
-
+ const canRemoveFromGroup = hasSelection && !!selection.nodes[0].g
+ const offset = $("#red-ui-workspace-chart").offset()
+ let addX = options.x - offset.left + $("#red-ui-workspace-chart").scrollLeft()
+ let addY = options.y - offset.top + $("#red-ui-workspace-chart").scrollTop()
+ if (RED.view.snapGrid) {
+ const gridSize = RED.view.gridSize()
+ addX = gridSize * Math.floor(addX / gridSize)
+ addY = gridSize * Math.floor(addY / gridSize)
}
- ]
- menuItems.push(
- null,
- { onselect: 'core:undo', disabled: RED.history.list().length === 0 },
- { onselect: 'core:redo', disabled: RED.history.listRedo().length === 0 },
- null,
- { onselect: 'core:cut-selection-to-internal-clipboard', label: RED._("keyboard.cutNode"), disabled: !hasSelection },
- { onselect: 'core:copy-selection-to-internal-clipboard', label: RED._("keyboard.copyNode"), disabled: !hasSelection },
- { onselect: 'core:paste-from-internal-clipboard', label: RED._("keyboard.pasteNode"), disabled: !RED.view.clipboard() },
- { onselect: 'core:delete-selection', disabled: !canDelete },
- { onselect: 'core:show-export-dialog', label: RED._("menu.label.export") },
- { onselect: 'core:select-all-nodes' }
- )
+ menuItems.push(
+ { onselect: 'core:show-action-list', onpostselect: function () { } },
+ {
+ label: RED._("contextMenu.insert"),
+ options: [
+ {
+ label: RED._("contextMenu.node"),
+ onselect: function () {
+ RED.view.showQuickAddDialog({
+ position: [addX, addY],
+ touchTrigger: true,
+ splice: isSingleLink ? selection.links[0] : undefined,
+ // spliceMultiple: isMultipleLinks
+ })
+ }
+ },
+ (hasLinks) ? { // has least 1 wire selected
+ label: RED._("contextMenu.junction"),
+ onselect: 'core:split-wires-with-junctions',
+ disabled: !hasLinks
+ } : {
+ label: RED._("contextMenu.junction"),
+ onselect: function () {
+ const nn = {
+ _def: { defaults: {} },
+ type: 'junction',
+ z: RED.workspaces.active(),
+ id: RED.nodes.id(),
+ x: addX,
+ y: addY,
+ w: 0, h: 0,
+ outputs: 1,
+ inputs: 1,
+ dirty: true
+ }
+ const historyEvent = {
+ dirty: RED.nodes.dirty(),
+ t: 'add',
+ junctions: [nn]
+ }
+ RED.nodes.addJunction(nn);
+ RED.history.push(historyEvent);
+ RED.nodes.dirty(true);
+ RED.view.select({nodes: [nn] });
+ RED.view.redraw(true)
+ }
+ },
+ {
+ label: RED._("contextMenu.linkNodes"),
+ onselect: 'core:split-wire-with-link-nodes',
+ disabled: !hasLinks
+ }
+ ]
+
+
+
+ }
+ )
- if (hasSelection) {
menuItems.push(
null,
- isGroup ?
- { onselect: 'core:ungroup-selection', disabled: !isGroup }
- : { onselect: 'core:group-selection', disabled: !hasSelection }
+ { onselect: 'core:undo', disabled: RED.history.list().length === 0 },
+ { onselect: 'core:redo', disabled: RED.history.listRedo().length === 0 },
+ null,
+ { onselect: 'core:cut-selection-to-internal-clipboard', label: RED._("keyboard.cutNode"), disabled: !hasSelection },
+ { onselect: 'core:copy-selection-to-internal-clipboard', label: RED._("keyboard.copyNode"), disabled: !hasSelection },
+ { onselect: 'core:paste-from-internal-clipboard', label: RED._("keyboard.pasteNode"), disabled: !RED.view.clipboard() },
+ { onselect: 'core:delete-selection', disabled: !canDelete },
+ { onselect: 'core:show-export-dialog', label: RED._("menu.label.export") },
+ { onselect: 'core:select-all-nodes' }
)
- if (canRemoveFromGroup) {
- menuItems.push({ onselect: 'core:remove-selection-from-group', label: RED._("menu.label.groupRemoveSelection") })
- }
+ if (hasSelection) {
+ menuItems.push(
+ null,
+ isGroup ?
+ { onselect: 'core:ungroup-selection', disabled: !isGroup }
+ : { onselect: 'core:group-selection', disabled: !hasSelection }
+ )
+ if (canRemoveFromGroup) {
+ menuItems.push({ onselect: 'core:remove-selection-from-group', label: RED._("menu.label.groupRemoveSelection") })
+ }
+
+ }
}
var direction = "right";
@@ -144,7 +133,7 @@ RED.contextMenu = (function () {
($(window).width() -MENU_WIDTH)) {
direction = "left";
}
-
+
menu = RED.menu.init({
direction: direction,
onpreselect: function() {
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 c6c49c942..83215afe4 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
@@ -211,6 +211,7 @@ RED.view = (function() {
evt.preventDefault()
evt.stopPropagation()
RED.contextMenu.show({
+ type: 'workspace',
x:evt.clientX-5,
y:evt.clientY-5
})
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 ae38f2c4d..a34f45b83 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
@@ -126,6 +126,113 @@ RED.workspaces = (function() {
var workspace_tabs;
var workspaceTabCount = 0;
+
+ function getMenuItems(isMenuButton, tab) {
+ let hiddenFlows = new Set()
+ for (let i = 0; i < hideStack.length; i++) {
+ let ids = hideStack[i]
+ if (!Array.isArray(ids)) {
+ ids = [ids]
+ }
+ ids.forEach(id => {
+ if (RED.nodes.workspace(id)) {
+ hiddenFlows.add(id)
+ }
+ })
+ }
+ const hiddenflowCount = hiddenFlows.size;
+
+ var menuItems = []
+ if (isMenuButton) {
+ menuItems.push({
+ id:"red-ui-tabs-menu-option-search-flows",
+ label: RED._("workspace.listFlows"),
+ onselect: "core:list-flows"
+ },
+ {
+ id:"red-ui-tabs-menu-option-search-subflows",
+ label: RED._("workspace.listSubflows"),
+ onselect: "core:list-subflows"
+ },
+ null)
+ }
+ menuItems.push(
+ {
+ id:"red-ui-tabs-menu-option-add-flow",
+ label: RED._("workspace.addFlow"),
+ onselect: "core:add-flow"
+ },
+ {
+ id:"red-ui-tabs-menu-option-add-flow-right",
+ label: RED._("workspace.addFlowToRight"),
+ shortcut: RED.keyboard.getShortcut("core:add-flow-to-right"),
+ onselect: function() {
+ RED.actions.invoke("core:add-flow-to-right", tab)
+ }
+ },
+ null,
+ {
+ id:"red-ui-tabs-menu-option-add-hide-flows",
+ label: RED._("workspace.hideFlow"),
+ shortcut: RED.keyboard.getShortcut("core:hide-flow"),
+ onselect: function() {
+ RED.actions.invoke("core:hide-flow", tab)
+ }
+ },
+ {
+ id:"red-ui-tabs-menu-option-add-hide-other-flows",
+ label: RED._("workspace.hideOtherFlows"),
+ shortcut: RED.keyboard.getShortcut("core:hide-other-flows"),
+ onselect: function() {
+ RED.actions.invoke("core:hide-other-flows", tab)
+ }
+ },
+ {
+ id:"red-ui-tabs-menu-option-add-hide-all-flows",
+ label: RED._("workspace.hideAllFlows"),
+ onselect: "core:hide-all-flows"
+ },
+ {
+ id:"red-ui-tabs-menu-option-add-show-all-flows",
+ disabled: hiddenflowCount === 0,
+ label: RED._("workspace.showAllFlows", { count: hiddenflowCount }),
+ onselect: "core:show-all-flows"
+ },
+ {
+ id:"red-ui-tabs-menu-option-add-show-last-flow",
+ disabled: hideStack.length === 0,
+ label: RED._("workspace.showLastHiddenFlow"),
+ onselect: "core:show-last-hidden-flow"
+ }
+ )
+ if (tab) {
+ menuItems.push(
+ null,
+ {
+ label: RED._("common.label.delete"),
+ disabled: tab.type !== 'tab',
+ onselect: function() {
+ RED.workspaces.delete(tab)
+ }
+ },
+ {
+ label: RED._("menu.label.export"),
+ shortcut: RED.keyboard.getShortcut("core:show-export-dialog"),
+ onselect: function() {
+ RED.workspaces.show(tab.id)
+ RED.actions.invoke('core:show-export-dialog', null, 'flow')
+ }
+ }
+ )
+ }
+ // if (isMenuButton && hiddenflowCount > 0) {
+ // menuItems.unshift({
+ // label: RED._("workspace.hiddenFlows",{count: hiddenflowCount}),
+ // onselect: "core:list-hidden-flows"
+ // })
+ // }
+ return menuItems;
+ }
function createWorkspaceTabs() {
workspace_tabs = RED.tabs.create({
id: "red-ui-workspace-tabs",
@@ -214,12 +321,12 @@ RED.workspaces = (function() {
},
onhide: function(tab) {
hideStack.push(tab.id);
-
- var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
- hiddenTabs[tab.id] = true;
- RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
-
- RED.events.emit("workspace:hide",{workspace: tab.id})
+ if (tab.type === "tab") {
+ var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
+ hiddenTabs[tab.id] = true;
+ RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
+ RED.events.emit("workspace:hide",{workspace: tab.id})
+ }
},
onshow: function(tab) {
removeFromHideStack(tab.id);
@@ -234,77 +341,8 @@ RED.workspaces = (function() {
scrollable: true,
addButton: "core:add-flow",
addButtonCaption: RED._("workspace.addFlow"),
- menu: function() {
- var menuItems = [
- {
- id:"red-ui-tabs-menu-option-search-flows",
- label: RED._("workspace.listFlows"),
- onselect: "core:list-flows"
- },
- {
- id:"red-ui-tabs-menu-option-search-subflows",
- label: RED._("workspace.listSubflows"),
- onselect: "core:list-subflows"
- },
- null,
- {
- id:"red-ui-tabs-menu-option-add-flow",
- label: RED._("workspace.addFlow"),
- onselect: "core:add-flow"
- },
- {
- id:"red-ui-tabs-menu-option-add-flow-right",
- label: RED._("workspace.addFlowToRight"),
- onselect: "core:add-flow-to-right"
- },
- null,
- {
- id:"red-ui-tabs-menu-option-add-hide-flows",
- label: RED._("workspace.hideFlow"),
- onselect: "core:hide-flow"
- },
- {
- id:"red-ui-tabs-menu-option-add-hide-other-flows",
- label: RED._("workspace.hideOtherFlows"),
- onselect: "core:hide-other-flows"
- },
- {
- id:"red-ui-tabs-menu-option-add-show-all-flows",
- label: RED._("workspace.showAllFlows"),
- onselect: "core:show-all-flows"
- },
- {
- id:"red-ui-tabs-menu-option-add-hide-all-flows",
- label: RED._("workspace.hideAllFlows"),
- onselect: "core:hide-all-flows"
- },
- {
- id:"red-ui-tabs-menu-option-add-show-last-flow",
- label: RED._("workspace.showLastHiddenFlow"),
- onselect: "core:show-last-hidden-flow"
- }
- ]
- let hiddenFlows = new Set()
- for (let i = 0; i < hideStack.length; i++) {
- let ids = hideStack[i]
- if (!Array.isArray(ids)) {
- ids = [ids]
- }
- ids.forEach(id => {
- if (RED.nodes.workspace(id)) {
- hiddenFlows.add(id)
- }
- })
- }
- const flowCount = hiddenFlows.size;
- if (flowCount > 0) {
- menuItems.unshift({
- label: RED._("workspace.hiddenFlows",{count: flowCount}),
- onselect: "core:list-hidden-flows"
- })
- }
- return menuItems;
- }
+ menu: function() { return getMenuItems(true) },
+ contextmenu: function(tab) { return getMenuItems(false, tab) }
});
workspaceTabCount = 0;
}
@@ -355,16 +393,29 @@ RED.workspaces = (function() {
});
RED.actions.add("core:add-flow",function(opts) { addWorkspace(undefined,undefined,opts?opts.index:undefined)});
- RED.actions.add("core:add-flow-to-right",function(opts) { addWorkspace(undefined,undefined,workspace_tabs.activeIndex()+1)});
+ RED.actions.add("core:add-flow-to-right",function(workspace) {
+ let index
+ if (workspace) {
+ index = workspace_tabs.getTabIndex(workspace.id)+1
+ } else {
+ index = workspace_tabs.activeIndex()+1
+ }
+ addWorkspace(undefined,undefined,index)
+ });
RED.actions.add("core:edit-flow",editWorkspace);
RED.actions.add("core:remove-flow",removeWorkspace);
RED.actions.add("core:enable-flow",enableWorkspace);
RED.actions.add("core:disable-flow",disableWorkspace);
- RED.actions.add("core:hide-flow", function() {
- var selection = workspace_tabs.selection();
- if (selection.length === 0) {
- selection = [{id:activeWorkspace}]
+ RED.actions.add("core:hide-flow", function(workspace) {
+ let selection
+ if (workspace) {
+ selection = [workspace]
+ } else {
+ selection = workspace_tabs.selection();
+ if (selection.length === 0) {
+ selection = [{id:activeWorkspace}]
+ }
}
var hiddenTabs = [];
selection.forEach(function(ws) {
@@ -378,10 +429,15 @@ RED.workspaces = (function() {
workspace_tabs.clearSelection();
})
- RED.actions.add("core:hide-other-flows", function() {
- var selection = workspace_tabs.selection();
- if (selection.length === 0) {
- selection = [{id:activeWorkspace}]
+ RED.actions.add("core:hide-other-flows", function(workspace) {
+ let selection
+ if (workspace) {
+ selection = [workspace]
+ } else {
+ selection = workspace_tabs.selection();
+ if (selection.length === 0) {
+ selection = [{id:activeWorkspace}]
+ }
}
var selected = new Set(selection.map(function(ws) { return ws.id }))
From 4cc18c25fe678b17c76aa5707a9143e4cc79aa7a Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Sat, 29 Oct 2022 17:34:29 +0100
Subject: [PATCH 2/5] Add drop mode to range node
and include tests
---
.../nodes/core/function/16-range.html | 1 +
.../@node-red/nodes/core/function/16-range.js | 8 +++++--
.../locales/en-US/function/16-range.html | 3 +++
.../nodes/locales/en-US/messages.json | 3 ++-
test/nodes/core/function/16-range_spec.js | 21 +++++++++++++++++++
5 files changed, 33 insertions(+), 3 deletions(-)
diff --git a/packages/node_modules/@node-red/nodes/core/function/16-range.html b/packages/node_modules/@node-red/nodes/core/function/16-range.html
index 07bb1f080..1652a91db 100644
--- a/packages/node_modules/@node-red/nodes/core/function/16-range.html
+++ b/packages/node_modules/@node-red/nodes/core/function/16-range.html
@@ -10,6 +10,7 @@
+
diff --git a/packages/node_modules/@node-red/nodes/core/function/16-range.js b/packages/node_modules/@node-red/nodes/core/function/16-range.js
index a5dede4ea..61ffd53fb 100644
--- a/packages/node_modules/@node-red/nodes/core/function/16-range.js
+++ b/packages/node_modules/@node-red/nodes/core/function/16-range.js
@@ -32,11 +32,15 @@ module.exports = function(RED) {
if (value !== undefined) {
var n = Number(value);
if (!isNaN(n)) {
- if (node.action == "clamp") {
+ if (node.action === "drop") {
+ if (n < node.minin) { done(); return; }
+ if (n > node.maxin) { done(); return; }
+ }
+ if (node.action === "clamp") {
if (n < node.minin) { n = node.minin; }
if (n > node.maxin) { n = node.maxin; }
}
- if (node.action == "roll") {
+ if (node.action === "roll") {
var divisor = node.maxin - node.minin;
n = ((n - node.minin) % divisor + divisor) % divisor + node.minin;
}
diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/function/16-range.html b/packages/node_modules/@node-red/nodes/locales/en-US/function/16-range.html
index b391f5c04..f25363565 100644
--- a/packages/node_modules/@node-red/nodes/locales/en-US/function/16-range.html
+++ b/packages/node_modules/@node-red/nodes/locales/en-US/function/16-range.html
@@ -34,11 +34,14 @@
the range specified within the target range.
Scale and wrap within the target range means that the result will
be wrapped within the target range.
+ Scale, but drop if outside input range means that the result will
+ be scaled, but any inputs outside of the inout range will be dropped.
For example an input 0 - 10 mapped to 0 - 100.
mode | input | output |
scale | 12 | 120 |
limit | 12 | 100 |
wrap | 12 | 20 |
+ drop | 12 | (no output) |
diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
index 62d5f351f..8b66bf5e9 100644
--- a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
+++ b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
@@ -813,7 +813,8 @@
"scale": {
"payload": "Scale the message property",
"limit": "Scale and limit to the target range",
- "wrap": "Scale and wrap within the target range"
+ "wrap": "Scale and wrap within the target range",
+ "drop": "Scale, but drop msg if outside input range"
},
"tip": "Tip: This node ONLY works with numbers.",
"errors": {
diff --git a/test/nodes/core/function/16-range_spec.js b/test/nodes/core/function/16-range_spec.js
index a0dcd0078..620d21b12 100644
--- a/test/nodes/core/function/16-range_spec.js
+++ b/test/nodes/core/function/16-range_spec.js
@@ -106,6 +106,27 @@ describe('range Node', function() {
genericRangeTest("clamp", 0, 10, 0, 1000, false, -1, 0, done);
});
+ it('drops msg if in drop mode and input outside range', function(done) {
+ var flow = [{"id":"rangeNode1","type":"range","minin":2,"maxin":8,"minout":20,"maxout":80,"action":"drop","round":true,"name":"rangeNode","wires":[["helperNode1"]]},
+ {id:"helperNode1", type:"helper", wires:[]}];
+ helper.load(rangeNode, flow, function() {
+ var rangeNode1 = helper.getNode("rangeNode1");
+ var helperNode1 = helper.getNode("helperNode1");
+ helperNode1.on("input", function(msg) {
+ try {
+ msg.should.have.property('payload');
+ msg.payload.should.equal(50);
+ done();
+ } catch(err) {
+ done(err);
+ }
+ });
+ rangeNode1.receive({payload:1});
+ rangeNode1.receive({payload:9});
+ rangeNode1.receive({payload:5});
+ });
+ });
+
it('just passes on msg if payload not present', function(done) {
var flow = [{"id":"rangeNode1","type":"range","minin":0,"maxin":100,"minout":0,"maxout":100,"action":"scale","round":true,"name":"rangeNode","wires":[["helperNode1"]]},
{id:"helperNode1", type:"helper", wires:[]}];
From d8e01584f33a3f8d205180d60ec80cf91a72399a Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Mon, 31 Oct 2022 20:20:05 +0000
Subject: [PATCH 3/5] Remove add-flow-to-right option if clicked in tab bar
---
.../editor-client/src/js/ui/workspaces.js | 22 ++++++++++++-------
1 file changed, 14 insertions(+), 8 deletions(-)
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 a34f45b83..5df1ca69c 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
@@ -161,15 +161,21 @@ RED.workspaces = (function() {
id:"red-ui-tabs-menu-option-add-flow",
label: RED._("workspace.addFlow"),
onselect: "core:add-flow"
- },
- {
- id:"red-ui-tabs-menu-option-add-flow-right",
- label: RED._("workspace.addFlowToRight"),
- shortcut: RED.keyboard.getShortcut("core:add-flow-to-right"),
- onselect: function() {
- RED.actions.invoke("core:add-flow-to-right", tab)
+ }
+ )
+ if (isMenuButton || !!tab) {
+ menuItems.push(
+ {
+ id:"red-ui-tabs-menu-option-add-flow-right",
+ label: RED._("workspace.addFlowToRight"),
+ shortcut: RED.keyboard.getShortcut("core:add-flow-to-right"),
+ onselect: function() {
+ RED.actions.invoke("core:add-flow-to-right", tab)
+ }
}
- },
+ )
+ }
+ menuItems.push(
null,
{
id:"red-ui-tabs-menu-option-add-hide-flows",
From a351cd9d9f58556e06f979867ba88ed5edb22d68 Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Tue, 1 Nov 2022 10:35:57 +0000
Subject: [PATCH 4/5] Add move-to-start/end and better subflow menu options
---
.../editor-client/locales/en-US/editor.json | 6 +-
.../@node-red/editor-client/src/js/nodes.js | 2 +-
.../editor-client/src/js/ui/subflow.js | 83 ++++++-----
.../editor-client/src/js/ui/workspaces.js | 137 ++++++++++++++----
4 files changed, 162 insertions(+), 66 deletions(-)
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 f226cb79e..44d370aac 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
@@ -68,7 +68,11 @@
"enabled": "Enabled",
"disabled": "Disabled",
"info": "Description",
- "selectNodes": "Click nodes to select"
+ "selectNodes": "Click nodes to select",
+ "enableFlow": "Enable flow",
+ "disableFlow": "Disable flow",
+ "moveToStart": "Move flow to start",
+ "moveToEnd": "Move flow to end"
},
"menu": {
"label": {
diff --git a/packages/node_modules/@node-red/editor-client/src/js/nodes.js b/packages/node_modules/@node-red/editor-client/src/js/nodes.js
index 9da5aad05..6dd500581 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/nodes.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/nodes.js
@@ -2834,7 +2834,7 @@ RED.nodes = (function() {
},
addWorkspace: addWorkspace,
removeWorkspace: removeWorkspace,
- getWorkspaceOrder: function() { return workspacesOrder },
+ getWorkspaceOrder: function() { return [...workspacesOrder] },
setWorkspaceOrder: function(order) { workspacesOrder = order; },
workspace: getWorkspace,
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js b/packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js
index ca4f651ab..e979adf65 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js
@@ -431,44 +431,7 @@ RED.subflow = (function() {
$("#red-ui-subflow-delete").on("click", function(event) {
event.preventDefault();
- var subflow = RED.nodes.subflow(RED.workspaces.active());
- if (subflow.instances.length > 0) {
- var msg = $('')
- $('
').text(RED._("subflow.subflowInstances",{count: subflow.instances.length})).appendTo(msg);
- $('
').text(RED._("subflow.confirmDelete")).appendTo(msg);
- var confirmDeleteNotification = RED.notify(msg, {
- modal: true,
- fixed: true,
- buttons: [
- {
- text: RED._('common.label.cancel'),
- click: function() {
- confirmDeleteNotification.close();
- }
- },
- {
- text: RED._('workspace.confirmDelete'),
- class: "primary",
- click: function() {
- confirmDeleteNotification.close();
- completeDelete();
- }
- }
- ]
- });
-
- return;
- } else {
- completeDelete();
- }
- function completeDelete() {
- var startDirty = RED.nodes.dirty();
- var historyEvent = removeSubflow(RED.workspaces.active());
- historyEvent.t = 'delete';
- historyEvent.dirty = startDirty;
- RED.history.push(historyEvent);
- }
-
+ RED.subflow.delete(RED.workspaces.active())
});
refreshToolbar(activeSubflow);
@@ -481,7 +444,48 @@ RED.subflow = (function() {
$("#red-ui-workspace-toolbar").hide().empty();
$("#red-ui-workspace-chart").css({"margin-top": "0"});
}
+ function deleteSubflow(id) {
+ const subflow = RED.nodes.subflow(id || RED.workspaces.active());
+ if (!subflow) {
+ return
+ }
+ if (subflow.instances.length > 0) {
+ const msg = $('
')
+ $('
').text(RED._("subflow.subflowInstances",{count: subflow.instances.length})).appendTo(msg);
+ $('
').text(RED._("subflow.confirmDelete")).appendTo(msg);
+ const confirmDeleteNotification = RED.notify(msg, {
+ modal: true,
+ fixed: true,
+ buttons: [
+ {
+ text: RED._('common.label.cancel'),
+ click: function() {
+ confirmDeleteNotification.close();
+ }
+ },
+ {
+ text: RED._('workspace.confirmDelete'),
+ class: "primary",
+ click: function() {
+ confirmDeleteNotification.close();
+ completeDelete();
+ }
+ }
+ ]
+ });
+ return;
+ } else {
+ completeDelete();
+ }
+ function completeDelete() {
+ const startDirty = RED.nodes.dirty();
+ const historyEvent = removeSubflow(subflow.id);
+ historyEvent.t = 'delete';
+ historyEvent.dirty = startDirty;
+ RED.history.push(historyEvent);
+ }
+ }
function removeSubflow(id, keepInstanceNodes) {
// TODO: A lot of this logic is common with RED.nodes.removeWorkspace
var removedNodes = [];
@@ -1323,7 +1327,10 @@ RED.subflow = (function() {
init: init,
createSubflow: createSubflow,
convertToSubflow: convertToSubflow,
+ // removeSubflow: Internal function to remove subflow
removeSubflow: removeSubflow,
+ // delete: Prompt user for confirmation
+ delete: deleteSubflow,
refresh: refresh,
removeInput: removeSubflowInput,
removeOutput: removeSubflowOutput,
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 5df1ca69c..d274ba519 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
@@ -141,6 +141,8 @@ RED.workspaces = (function() {
})
}
const hiddenflowCount = hiddenFlows.size;
+ let activeWorkspace = tab || RED.nodes.workspace(RED.workspaces.active()) || RED.nodes.subflow(RED.workspaces.active())
+ let isFlowDisabled = activeWorkspace ? activeWorkspace.disabled : false
var menuItems = []
if (isMenuButton) {
@@ -172,27 +174,69 @@ RED.workspaces = (function() {
onselect: function() {
RED.actions.invoke("core:add-flow-to-right", tab)
}
+ },
+ null
+ )
+ if (activeWorkspace && activeWorkspace.type === 'tab') {
+ menuItems.push(
+ isFlowDisabled ? {
+ label: RED._("workspace.enableFlow"),
+ shortcut: RED.keyboard.getShortcut("core:enable-flow"),
+ onselect: function() {
+ RED.actions.invoke("core:enable-flow", tab?tab.id:undefined)
+ }
+ } : {
+ label: RED._("workspace.disableFlow"),
+ shortcut: RED.keyboard.getShortcut("core:disable-flow"),
+ onselect: function() {
+ RED.actions.invoke("core:disable-flow", tab?tab.id:undefined)
+ }
+ }
+ )
+ }
+ const currentTabs = workspace_tabs.listTabs()
+ const activeIndex = currentTabs.findIndex(id => id === activeWorkspace.id)
+ menuItems.push(
+ {
+ label: RED._("workspace.moveToStart"),
+ shortcut: RED.keyboard.getShortcut("core:move-flow-to-start"),
+ onselect: function() {
+ RED.actions.invoke("core:move-flow-to-start", tab?tab.id:undefined)
+ },
+ disabled: activeIndex === 0
+ },
+ {
+ label: RED._("workspace.moveToEnd"),
+ shortcut: RED.keyboard.getShortcut("core:move-flow-to-end"),
+ onselect: function() {
+ RED.actions.invoke("core:move-flow-to-end", tab?tab.id:undefined)
+ },
+ disabled: activeIndex === currentTabs.length - 1
+ }
+ )
+ }
+ menuItems.push(null)
+ if (isMenuButton || !!tab) {
+ menuItems.push(
+ {
+ id:"red-ui-tabs-menu-option-add-hide-flows",
+ label: RED._("workspace.hideFlow"),
+ shortcut: RED.keyboard.getShortcut("core:hide-flow"),
+ onselect: function() {
+ RED.actions.invoke("core:hide-flow", tab)
+ }
+ },
+ {
+ id:"red-ui-tabs-menu-option-add-hide-other-flows",
+ label: RED._("workspace.hideOtherFlows"),
+ shortcut: RED.keyboard.getShortcut("core:hide-other-flows"),
+ onselect: function() {
+ RED.actions.invoke("core:hide-other-flows", tab)
+ }
}
)
}
menuItems.push(
- null,
- {
- id:"red-ui-tabs-menu-option-add-hide-flows",
- label: RED._("workspace.hideFlow"),
- shortcut: RED.keyboard.getShortcut("core:hide-flow"),
- onselect: function() {
- RED.actions.invoke("core:hide-flow", tab)
- }
- },
- {
- id:"red-ui-tabs-menu-option-add-hide-other-flows",
- label: RED._("workspace.hideOtherFlows"),
- shortcut: RED.keyboard.getShortcut("core:hide-other-flows"),
- onselect: function() {
- RED.actions.invoke("core:hide-other-flows", tab)
- }
- },
{
id:"red-ui-tabs-menu-option-add-hide-all-flows",
label: RED._("workspace.hideAllFlows"),
@@ -216,9 +260,12 @@ RED.workspaces = (function() {
null,
{
label: RED._("common.label.delete"),
- disabled: tab.type !== 'tab',
onselect: function() {
- RED.workspaces.delete(tab)
+ if (tab.type === 'tab') {
+ RED.workspaces.delete(tab)
+ } else if (tab.type === 'subflow') {
+ RED.subflow.delete(tab.id)
+ }
}
},
{
@@ -302,13 +349,19 @@ RED.workspaces = (function() {
RED.history.push({
t:'reorder',
workspaces: {
- from:oldOrder,
- to:newOrder
+ from: oldOrder,
+ to: newOrder
},
dirty:RED.nodes.dirty()
});
- RED.nodes.dirty(true);
- setWorkspaceOrder(newOrder);
+ // Only mark flows dirty if flow-order has changed (excluding subflows)
+ const filteredOldOrder = oldOrder.filter(id => !!RED.nodes.workspace(id))
+ const filteredNewOrder = newOrder.filter(id => !!RED.nodes.workspace(id))
+
+ if (JSON.stringify(filteredOldOrder) !== JSON.stringify(filteredNewOrder)) {
+ RED.nodes.dirty(true);
+ setWorkspaceOrder(newOrder);
+ }
},
onselect: function(selectedTabs) {
RED.view.select(false)
@@ -412,6 +465,8 @@ RED.workspaces = (function() {
RED.actions.add("core:remove-flow",removeWorkspace);
RED.actions.add("core:enable-flow",enableWorkspace);
RED.actions.add("core:disable-flow",disableWorkspace);
+ RED.actions.add("core:move-flow-to-start", function(id) { moveWorkspace(id, 'start') });
+ RED.actions.add("core:move-flow-to-end", function(id) { moveWorkspace(id, 'end') });
RED.actions.add("core:hide-flow", function(workspace) {
let selection
@@ -597,16 +652,46 @@ RED.workspaces = (function() {
}
}
+ function moveWorkspace(id, direction) {
+ const workspace = RED.nodes.workspace(id||activeWorkspace) || RED.nodes.subflow(id||activeWorkspace);
+ if (!workspace) {
+ return;
+ }
+ const currentOrder = workspace_tabs.listTabs()
+ const oldOrder = [...currentOrder]
+ const currentIndex = currentOrder.findIndex(id => id === workspace.id)
+ currentOrder.splice(currentIndex, 1)
+ if (direction === 'start') {
+ currentOrder.unshift(workspace.id)
+ } else if (direction === 'end') {
+ currentOrder.push(workspace.id)
+ }
+ const newOrder = setWorkspaceOrder(currentOrder)
+ if (JSON.stringify(newOrder) !== JSON.stringify(oldOrder)) {
+ RED.history.push({
+ t:'reorder',
+ workspaces: {
+ from:oldOrder,
+ to:newOrder
+ },
+ dirty:RED.nodes.dirty()
+ });
+ const filteredOldOrder = oldOrder.filter(id => !!RED.nodes.workspace(id))
+ const filteredNewOrder = newOrder.filter(id => !!RED.nodes.workspace(id))
+ if (JSON.stringify(filteredOldOrder) !== JSON.stringify(filteredNewOrder)) {
+ RED.nodes.dirty(true);
+ }
+ }
+ }
function setWorkspaceOrder(order) {
- var newOrder = order.filter(function(id) {
- return RED.nodes.workspace(id) !== undefined;
- })
+ var newOrder = order.filter(id => !!RED.nodes.workspace(id))
var currentOrder = RED.nodes.getWorkspaceOrder();
if (JSON.stringify(newOrder) !== JSON.stringify(currentOrder)) {
RED.nodes.setWorkspaceOrder(newOrder);
RED.events.emit("flows:reorder",newOrder);
}
workspace_tabs.order(order);
+ return newOrder
}
function flashTab(tabId) {
From b3f761776d79dbb730714486a799ce30be9780a4 Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Sat, 3 Dec 2022 22:43:03 +0000
Subject: [PATCH 5/5] Update dependencies
---
package.json | 36 +++++++++----------
.../@node-red/editor-api/package.json | 6 ++--
.../node_modules/@node-red/nodes/package.json | 12 +++----
.../@node-red/registry/package.json | 6 ++--
.../@node-red/runtime/package.json | 4 +--
.../node_modules/@node-red/util/package.json | 4 +--
packages/node_modules/node-red/package.json | 6 ++--
7 files changed, 37 insertions(+), 37 deletions(-)
diff --git a/package.json b/package.json
index b596e10b6..ad65edd90 100644
--- a/package.json
+++ b/package.json
@@ -26,13 +26,13 @@
}
],
"dependencies": {
- "acorn": "8.7.1",
+ "acorn": "8.8.1",
"acorn-walk": "8.2.0",
- "ajv": "8.11.0",
- "async-mutex": "0.3.2",
+ "ajv": "8.11.2",
+ "async-mutex": "0.4.0",
"basic-auth": "2.0.1",
"bcryptjs": "2.4.3",
- "body-parser": "1.20.0",
+ "body-parser": "1.20.1",
"cheerio": "1.0.0-rc.10",
"clone": "2.1.2",
"content-type": "1.0.4",
@@ -40,16 +40,16 @@
"cookie-parser": "1.4.6",
"cors": "2.8.5",
"cronosjs": "1.7.1",
- "denque": "2.0.1",
- "express": "4.18.1",
+ "denque": "2.1.0",
+ "express": "4.18.2",
"express-session": "1.17.3",
"form-data": "4.0.0",
"fs-extra": "10.1.0",
"got": "11.8.5",
"hash-sum": "2.0.0",
- "hpagent": "1.0.0",
+ "hpagent": "1.2.0",
"https-proxy-agent": "5.0.1",
- "i18next": "21.8.14",
+ "i18next": "21.10.0",
"iconv-lite": "0.6.3",
"is-utf8": "0.2.1",
"js-yaml": "4.1.0",
@@ -60,7 +60,7 @@
"memorystore": "1.6.7",
"mime": "3.0.0",
"moment": "2.29.4",
- "moment-timezone": "0.5.34",
+ "moment-timezone": "0.5.39",
"mqtt": "4.3.7",
"multer": "1.4.5-lts.1",
"mustache": "4.2.0",
@@ -73,19 +73,19 @@
"passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2",
"raw-body": "2.5.1",
- "semver": "7.3.7",
- "tar": "6.1.11",
- "tough-cookie": "4.0.0",
- "uglify-js": "3.16.2",
+ "semver": "7.3.8",
+ "tar": "6.1.12",
+ "tough-cookie": "4.1.2",
+ "uglify-js": "3.17.4",
"uuid": "8.3.2",
"ws": "7.5.6",
"xml2js": "0.4.23"
},
"optionalDependencies": {
- "bcrypt": "5.0.1"
+ "bcrypt": "5.1.0"
},
"devDependencies": {
- "dompurify": "2.3.9",
+ "dompurify": "2.4.1",
"grunt": "1.5.3",
"grunt-chmod": "~1.1.1",
"grunt-cli": "~1.4.3",
@@ -108,13 +108,13 @@
"i18next-http-backend": "1.4.1",
"jquery-i18next": "1.2.1",
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
- "marked": "4.0.18",
+ "marked": "4.2.3",
"minami": "1.2.3",
"mocha": "9.2.2",
"node-red-node-test-helper": "^0.3.0",
- "nodemon": "2.0.19",
+ "nodemon": "2.0.20",
"proxy": "^1.0.2",
- "sass": "1.53.0",
+ "sass": "1.56.1",
"should": "13.2.3",
"sinon": "11.1.2",
"stoppable": "^1.1.0",
diff --git a/packages/node_modules/@node-red/editor-api/package.json b/packages/node_modules/@node-red/editor-api/package.json
index dd7020e75..01fcb0ec8 100644
--- a/packages/node_modules/@node-red/editor-api/package.json
+++ b/packages/node_modules/@node-red/editor-api/package.json
@@ -19,11 +19,11 @@
"@node-red/util": "3.1.0-beta.0",
"@node-red/editor-client": "3.1.0-beta.0",
"bcryptjs": "2.4.3",
- "body-parser": "1.20.0",
+ "body-parser": "1.20.1",
"clone": "2.1.2",
"cors": "2.8.5",
"express-session": "1.17.3",
- "express": "4.18.1",
+ "express": "4.18.2",
"memorystore": "1.6.7",
"mime": "3.0.0",
"multer": "1.4.5-lts.1",
@@ -35,6 +35,6 @@
"ws": "7.5.6"
},
"optionalDependencies": {
- "bcrypt": "5.0.1"
+ "bcrypt": "5.1.0"
}
}
diff --git a/packages/node_modules/@node-red/nodes/package.json b/packages/node_modules/@node-red/nodes/package.json
index 9db16efc0..c4b7023dd 100644
--- a/packages/node_modules/@node-red/nodes/package.json
+++ b/packages/node_modules/@node-red/nodes/package.json
@@ -15,22 +15,22 @@
}
],
"dependencies": {
- "acorn": "8.7.1",
+ "acorn": "8.8.1",
"acorn-walk": "8.2.0",
- "ajv": "8.11.0",
- "body-parser": "1.20.0",
+ "ajv": "8.11.2",
+ "body-parser": "1.20.1",
"cheerio": "1.0.0-rc.10",
"content-type": "1.0.4",
"cookie-parser": "1.4.6",
"cookie": "0.5.0",
"cors": "2.8.5",
"cronosjs": "1.7.1",
- "denque": "2.0.1",
+ "denque": "2.1.0",
"form-data": "4.0.0",
"fs-extra": "10.1.0",
"got": "11.8.5",
"hash-sum": "2.0.0",
- "hpagent": "1.0.0",
+ "hpagent": "1.2.0",
"https-proxy-agent": "5.0.1",
"is-utf8": "0.2.1",
"js-yaml": "4.1.0",
@@ -41,7 +41,7 @@
"node-watch": "0.7.3",
"on-headers": "1.0.2",
"raw-body": "2.5.1",
- "tough-cookie": "4.0.0",
+ "tough-cookie": "4.1.2",
"uuid": "8.3.2",
"ws": "7.5.6",
"xml2js": "0.4.23",
diff --git a/packages/node_modules/@node-red/registry/package.json b/packages/node_modules/@node-red/registry/package.json
index 088bba36a..8dbe03d5b 100644
--- a/packages/node_modules/@node-red/registry/package.json
+++ b/packages/node_modules/@node-red/registry/package.json
@@ -19,8 +19,8 @@
"@node-red/util": "3.1.0-beta.0",
"clone": "2.1.2",
"fs-extra": "10.1.0",
- "semver": "7.3.7",
- "tar": "6.1.11",
- "uglify-js": "3.16.2"
+ "semver": "7.3.8",
+ "tar": "6.1.12",
+ "uglify-js": "3.17.4"
}
}
diff --git a/packages/node_modules/@node-red/runtime/package.json b/packages/node_modules/@node-red/runtime/package.json
index 14171f1d6..f3c58ee71 100644
--- a/packages/node_modules/@node-red/runtime/package.json
+++ b/packages/node_modules/@node-red/runtime/package.json
@@ -18,9 +18,9 @@
"dependencies": {
"@node-red/registry": "3.1.0-beta.0",
"@node-red/util": "3.1.0-beta.0",
- "async-mutex": "0.3.2",
+ "async-mutex": "0.4.0",
"clone": "2.1.2",
- "express": "4.18.1",
+ "express": "4.18.2",
"fs-extra": "10.1.0",
"json-stringify-safe": "5.0.1"
}
diff --git a/packages/node_modules/@node-red/util/package.json b/packages/node_modules/@node-red/util/package.json
index aa82273f6..a02b99711 100644
--- a/packages/node_modules/@node-red/util/package.json
+++ b/packages/node_modules/@node-red/util/package.json
@@ -16,11 +16,11 @@
],
"dependencies": {
"fs-extra": "10.1.0",
- "i18next": "21.8.14",
+ "i18next": "21.10.0",
"json-stringify-safe": "5.0.1",
"jsonata": "1.8.6",
"lodash.clonedeep": "^4.5.0",
"moment": "2.29.4",
- "moment-timezone": "0.5.34"
+ "moment-timezone": "0.5.39"
}
}
diff --git a/packages/node_modules/node-red/package.json b/packages/node_modules/node-red/package.json
index b4c4e53f0..e87a14c97 100644
--- a/packages/node_modules/node-red/package.json
+++ b/packages/node_modules/node-red/package.json
@@ -37,14 +37,14 @@
"@node-red/nodes": "3.1.0-beta.0",
"basic-auth": "2.0.1",
"bcryptjs": "2.4.3",
- "express": "4.18.1",
+ "express": "4.18.2",
"fs-extra": "10.1.0",
"node-red-admin": "^3.0.0",
"nopt": "5.0.0",
- "semver": "7.3.7"
+ "semver": "7.3.8"
},
"optionalDependencies": {
- "bcrypt": "5.0.1"
+ "bcrypt": "5.1.0"
},
"engines": {
"node": ">=14"