From fb499be9795f667d2c0810dbd657d61dae6ed4a2 Mon Sep 17 00:00:00 2001
From: Nick O'Leary
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 |
---|---|---|
').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 b95df6d8832909b91d5e34fba69113aeb65ff23f Mon Sep 17 00:00:00 2001
From: Hiroyasu Nishiyama