1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Add move-to-start/end and better subflow menu options

This commit is contained in:
Nick O'Leary 2022-11-01 10:35:57 +00:00
parent d8e01584f3
commit a351cd9d9f
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
4 changed files with 162 additions and 66 deletions

View File

@ -68,7 +68,11 @@
"enabled": "Enabled", "enabled": "Enabled",
"disabled": "Disabled", "disabled": "Disabled",
"info": "Description", "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": { "menu": {
"label": { "label": {

View File

@ -2834,7 +2834,7 @@ RED.nodes = (function() {
}, },
addWorkspace: addWorkspace, addWorkspace: addWorkspace,
removeWorkspace: removeWorkspace, removeWorkspace: removeWorkspace,
getWorkspaceOrder: function() { return workspacesOrder }, getWorkspaceOrder: function() { return [...workspacesOrder] },
setWorkspaceOrder: function(order) { workspacesOrder = order; }, setWorkspaceOrder: function(order) { workspacesOrder = order; },
workspace: getWorkspace, workspace: getWorkspace,

View File

@ -431,12 +431,29 @@ RED.subflow = (function() {
$("#red-ui-subflow-delete").on("click", function(event) { $("#red-ui-subflow-delete").on("click", function(event) {
event.preventDefault(); event.preventDefault();
var subflow = RED.nodes.subflow(RED.workspaces.active()); RED.subflow.delete(RED.workspaces.active())
});
refreshToolbar(activeSubflow);
$("#red-ui-workspace-chart").css({"margin-top": "40px"});
$("#red-ui-workspace-toolbar").show();
}
function hideWorkspaceToolbar() {
$("#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) { if (subflow.instances.length > 0) {
var msg = $('<div>') const msg = $('<div>')
$('<p>').text(RED._("subflow.subflowInstances",{count: subflow.instances.length})).appendTo(msg); $('<p>').text(RED._("subflow.subflowInstances",{count: subflow.instances.length})).appendTo(msg);
$('<p>').text(RED._("subflow.confirmDelete")).appendTo(msg); $('<p>').text(RED._("subflow.confirmDelete")).appendTo(msg);
var confirmDeleteNotification = RED.notify(msg, { const confirmDeleteNotification = RED.notify(msg, {
modal: true, modal: true,
fixed: true, fixed: true,
buttons: [ buttons: [
@ -462,26 +479,13 @@ RED.subflow = (function() {
completeDelete(); completeDelete();
} }
function completeDelete() { function completeDelete() {
var startDirty = RED.nodes.dirty(); const startDirty = RED.nodes.dirty();
var historyEvent = removeSubflow(RED.workspaces.active()); const historyEvent = removeSubflow(subflow.id);
historyEvent.t = 'delete'; historyEvent.t = 'delete';
historyEvent.dirty = startDirty; historyEvent.dirty = startDirty;
RED.history.push(historyEvent); RED.history.push(historyEvent);
} }
});
refreshToolbar(activeSubflow);
$("#red-ui-workspace-chart").css({"margin-top": "40px"});
$("#red-ui-workspace-toolbar").show();
} }
function hideWorkspaceToolbar() {
$("#red-ui-workspace-toolbar").hide().empty();
$("#red-ui-workspace-chart").css({"margin-top": "0"});
}
function removeSubflow(id, keepInstanceNodes) { function removeSubflow(id, keepInstanceNodes) {
// TODO: A lot of this logic is common with RED.nodes.removeWorkspace // TODO: A lot of this logic is common with RED.nodes.removeWorkspace
var removedNodes = []; var removedNodes = [];
@ -1323,7 +1327,10 @@ RED.subflow = (function() {
init: init, init: init,
createSubflow: createSubflow, createSubflow: createSubflow,
convertToSubflow: convertToSubflow, convertToSubflow: convertToSubflow,
// removeSubflow: Internal function to remove subflow
removeSubflow: removeSubflow, removeSubflow: removeSubflow,
// delete: Prompt user for confirmation
delete: deleteSubflow,
refresh: refresh, refresh: refresh,
removeInput: removeSubflowInput, removeInput: removeSubflowInput,
removeOutput: removeSubflowOutput, removeOutput: removeSubflowOutput,

View File

@ -141,6 +141,8 @@ RED.workspaces = (function() {
}) })
} }
const hiddenflowCount = hiddenFlows.size; 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 = [] var menuItems = []
if (isMenuButton) { if (isMenuButton) {
@ -172,11 +174,50 @@ RED.workspaces = (function() {
onselect: function() { onselect: function() {
RED.actions.invoke("core:add-flow-to-right", tab) 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( menuItems.push(
null,
{ {
id:"red-ui-tabs-menu-option-add-hide-flows", id:"red-ui-tabs-menu-option-add-hide-flows",
label: RED._("workspace.hideFlow"), label: RED._("workspace.hideFlow"),
@ -192,7 +233,10 @@ RED.workspaces = (function() {
onselect: function() { onselect: function() {
RED.actions.invoke("core:hide-other-flows", tab) RED.actions.invoke("core:hide-other-flows", tab)
} }
}, }
)
}
menuItems.push(
{ {
id:"red-ui-tabs-menu-option-add-hide-all-flows", id:"red-ui-tabs-menu-option-add-hide-all-flows",
label: RED._("workspace.hideAllFlows"), label: RED._("workspace.hideAllFlows"),
@ -216,9 +260,12 @@ RED.workspaces = (function() {
null, null,
{ {
label: RED._("common.label.delete"), label: RED._("common.label.delete"),
disabled: tab.type !== 'tab',
onselect: function() { onselect: function() {
if (tab.type === 'tab') {
RED.workspaces.delete(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({ RED.history.push({
t:'reorder', t:'reorder',
workspaces: { workspaces: {
from:oldOrder, from: oldOrder,
to:newOrder to: newOrder
}, },
dirty:RED.nodes.dirty() dirty:RED.nodes.dirty()
}); });
// 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); RED.nodes.dirty(true);
setWorkspaceOrder(newOrder); setWorkspaceOrder(newOrder);
}
}, },
onselect: function(selectedTabs) { onselect: function(selectedTabs) {
RED.view.select(false) RED.view.select(false)
@ -412,6 +465,8 @@ RED.workspaces = (function() {
RED.actions.add("core:remove-flow",removeWorkspace); RED.actions.add("core:remove-flow",removeWorkspace);
RED.actions.add("core:enable-flow",enableWorkspace); RED.actions.add("core:enable-flow",enableWorkspace);
RED.actions.add("core:disable-flow",disableWorkspace); 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) { RED.actions.add("core:hide-flow", function(workspace) {
let selection 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) { function setWorkspaceOrder(order) {
var newOrder = order.filter(function(id) { var newOrder = order.filter(id => !!RED.nodes.workspace(id))
return RED.nodes.workspace(id) !== undefined;
})
var currentOrder = RED.nodes.getWorkspaceOrder(); var currentOrder = RED.nodes.getWorkspaceOrder();
if (JSON.stringify(newOrder) !== JSON.stringify(currentOrder)) { if (JSON.stringify(newOrder) !== JSON.stringify(currentOrder)) {
RED.nodes.setWorkspaceOrder(newOrder); RED.nodes.setWorkspaceOrder(newOrder);
RED.events.emit("flows:reorder",newOrder); RED.events.emit("flows:reorder",newOrder);
} }
workspace_tabs.order(order); workspace_tabs.order(order);
return newOrder
} }
function flashTab(tabId) { function flashTab(tabId) {