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

Add context menu to tab bar

This commit is contained in:
Nick O'Leary 2022-10-25 23:44:59 +01:00
parent 7da3773f7f
commit fb499be979
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
7 changed files with 300 additions and 224 deletions

View File

@ -57,11 +57,11 @@
"addFlowToRight": "Add flow to the right", "addFlowToRight": "Add flow to the right",
"hideFlow": "Hide flow", "hideFlow": "Hide flow",
"hideOtherFlows": "Hide other flows", "hideOtherFlows": "Hide other flows",
"showAllFlows": "Show all flows", "showAllFlows": "Show all flows (__count__ hidden)",
"hideAllFlows": "Hide all flows", "hideAllFlows": "Hide all flows",
"hiddenFlows": "List __count__ hidden flow", "hiddenFlows": "List __count__ hidden flow",
"hiddenFlows_plural": "List __count__ hidden flows", "hiddenFlows_plural": "List __count__ hidden flows",
"showLastHiddenFlow": "Show last hidden flow", "showLastHiddenFlow": "Reopen hidden flow",
"listFlows": "List flows", "listFlows": "List flows",
"listSubflows": "List subflows", "listSubflows": "List subflows",
"status": "Status", "status": "Status",

View File

@ -423,11 +423,10 @@ RED.clipboard = (function() {
} }
} }
function showImportNodes(mode) { function showImportNodes(library = 'clipboard') {
if (disabled) { if (disabled) {
return; return;
} }
mode = mode || "clipboard";
dialogContainer.empty(); dialogContainer.empty();
dialogContainer.append($(importNodesDialog)); dialogContainer.append($(importNodesDialog));
@ -533,8 +532,8 @@ RED.clipboard = (function() {
$("#red-ui-clipboard-dialog-import-file-upload").trigger("click"); $("#red-ui-clipboard-dialog-import-file-upload").trigger("click");
}) })
tabs.activateTab("red-ui-clipboard-dialog-import-tab-"+mode); tabs.activateTab("red-ui-clipboard-dialog-import-tab-"+library);
if (mode === 'clipboard') { if (library === 'clipboard') {
setTimeout(function() { setTimeout(function() {
$("#red-ui-clipboard-dialog-import-text").trigger("focus"); $("#red-ui-clipboard-dialog-import-text").trigger("focus");
},100) },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) { if (disabled) {
return; return;
} }
mode = mode || "clipboard";
dialogContainer.empty(); dialogContainer.empty();
dialogContainer.append($(exportNodesDialog)); 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") { if (format === "red-ui-clipboard-dialog-export-fmt-full") {
$("#red-ui-clipboard-dialog-export-fmt-full").trigger("click"); $("#red-ui-clipboard-dialog-export-fmt-full").trigger("click");
} else { } else {
$("#red-ui-clipboard-dialog-export-fmt-mini").trigger("click"); $("#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 dialogHeight = 400;
var winHeight = $(window).height(); var winHeight = $(window).height();

View File

@ -94,8 +94,8 @@ RED.menu = (function() {
var link = $(linkContent).appendTo(item); var link = $(linkContent).appendTo(item);
opt.link = link; opt.link = link;
if (typeof opt.onselect === 'string') { if (typeof opt.onselect === 'string' || opt.shortcut) {
var shortcut = RED.keyboard.getShortcut(opt.onselect); var shortcut = opt.shortcut || RED.keyboard.getShortcut(opt.onselect);
if (shortcut && shortcut.key) { if (shortcut && shortcut.key) {
opt.shortcutSpan = $('<span class="red-ui-popover-key">'+RED.keyboard.formatKey(shortcut.key, true)+'</span>').appendTo(link.find(".red-ui-menu-label")); opt.shortcutSpan = $('<span class="red-ui-popover-key">'+RED.keyboard.formatKey(shortcut.key, true)+'</span>').appendTo(link.find(".red-ui-menu-label"));
} }

View File

@ -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 scrollLeft;
var scrollRight; var scrollRight;
@ -809,17 +831,17 @@ RED.tabs = (function() {
}); });
RED.popover.tooltip(closeLink,RED._("workspace.hideFlow")); RED.popover.tooltip(closeLink,RED._("workspace.hideFlow"));
} }
if (tab.hideable) { // if (tab.hideable) {
li.addClass("red-ui-tabs-closeable") // li.addClass("red-ui-tabs-closeable")
var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close red-ui-tab-hide"}).appendTo(li); // var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close red-ui-tab-hide"}).appendTo(li);
closeLink.append('<i class="fa fa-eye" />'); // closeLink.append('<i class="fa fa-eye" />');
closeLink.append('<i class="fa fa-eye-slash" />'); // closeLink.append('<i class="fa fa-eye-slash" />');
closeLink.on("click",function(event) { // closeLink.on("click",function(event) {
event.preventDefault(); // event.preventDefault();
hideTab(tab.id); // hideTab(tab.id);
}); // });
RED.popover.tooltip(closeLink,RED._("workspace.hideFlow")); // RED.popover.tooltip(closeLink,RED._("workspace.hideFlow"));
} // }
var badges = $('<span class="red-ui-tabs-badges"></span>').appendTo(li); var badges = $('<span class="red-ui-tabs-badges"></span>').appendTo(li);
if (options.onselect) { if (options.onselect) {
@ -938,6 +960,9 @@ RED.tabs = (function() {
activeIndex: function() { activeIndex: function() {
return ul.find("li.active").index() return ul.find("li.active").index()
}, },
getTabIndex: function (id) {
return ul.find("a[href='#"+id+"']").parent().index()
},
contains: function(id) { contains: function(id) {
return ul.find("a[href='#"+id+"']").length > 0; return ul.find("a[href='#"+id+"']").length > 0;
}, },

View File

@ -1,21 +1,6 @@
RED.contextMenu = (function () { RED.contextMenu = (function () {
let menu; 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() { function disposeMenu() {
$(document).off("mousedown.red-ui-workspace-context-menu"); $(document).off("mousedown.red-ui-workspace-context-menu");
@ -28,7 +13,10 @@ RED.contextMenu = (function () {
if (menu) { if (menu) {
menu.remove() menu.remove()
} }
let menuItems = []
if (options.options) {
menuItems = options.options
} else if (options.type === 'workspace') {
const selection = RED.view.selection() const selection = RED.view.selection()
const noSelection = !selection || Object.keys(selection).length === 0 const noSelection = !selection || Object.keys(selection).length === 0
const hasSelection = (selection.nodes && selection.nodes.length > 0); const hasSelection = (selection.nodes && selection.nodes.length > 0);
@ -53,7 +41,7 @@ RED.contextMenu = (function () {
addY = gridSize * Math.floor(addY / gridSize) addY = gridSize * Math.floor(addY / gridSize)
} }
const menuItems = [ menuItems.push(
{ onselect: 'core:show-action-list', onpostselect: function () { } }, { onselect: 'core:show-action-list', onpostselect: function () { } },
{ {
label: RED._("contextMenu.insert"), label: RED._("contextMenu.insert"),
@ -110,7 +98,7 @@ RED.contextMenu = (function () {
} }
] )
menuItems.push( menuItems.push(
null, null,
@ -137,6 +125,7 @@ RED.contextMenu = (function () {
} }
} }
}
var direction = "right"; var direction = "right";
var MENU_WIDTH = 500; // can not use menu width here var MENU_WIDTH = 500; // can not use menu width here

View File

@ -211,6 +211,7 @@ RED.view = (function() {
evt.preventDefault() evt.preventDefault()
evt.stopPropagation() evt.stopPropagation()
RED.contextMenu.show({ RED.contextMenu.show({
type: 'workspace',
x:evt.clientX-5, x:evt.clientX-5,
y:evt.clientY-5 y:evt.clientY-5
}) })

View File

@ -126,6 +126,113 @@ RED.workspaces = (function() {
var workspace_tabs; var workspace_tabs;
var workspaceTabCount = 0; 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() { function createWorkspaceTabs() {
workspace_tabs = RED.tabs.create({ workspace_tabs = RED.tabs.create({
id: "red-ui-workspace-tabs", id: "red-ui-workspace-tabs",
@ -214,12 +321,12 @@ RED.workspaces = (function() {
}, },
onhide: function(tab) { onhide: function(tab) {
hideStack.push(tab.id); hideStack.push(tab.id);
if (tab.type === "tab") {
var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}"); var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}");
hiddenTabs[tab.id] = true; hiddenTabs[tab.id] = true;
RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs)); RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs));
RED.events.emit("workspace:hide",{workspace: tab.id}) RED.events.emit("workspace:hide",{workspace: tab.id})
}
}, },
onshow: function(tab) { onshow: function(tab) {
removeFromHideStack(tab.id); removeFromHideStack(tab.id);
@ -234,77 +341,8 @@ RED.workspaces = (function() {
scrollable: true, scrollable: true,
addButton: "core:add-flow", addButton: "core:add-flow",
addButtonCaption: RED._("workspace.addFlow"), addButtonCaption: RED._("workspace.addFlow"),
menu: function() { menu: function() { return getMenuItems(true) },
var menuItems = [ contextmenu: function(tab) { return getMenuItems(false, tab) }
{
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;
}
}); });
workspaceTabCount = 0; workspaceTabCount = 0;
} }
@ -355,17 +393,30 @@ RED.workspaces = (function() {
}); });
RED.actions.add("core:add-flow",function(opts) { addWorkspace(undefined,undefined,opts?opts.index:undefined)}); 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:edit-flow",editWorkspace);
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:hide-flow", function() { RED.actions.add("core:hide-flow", function(workspace) {
var selection = workspace_tabs.selection(); let selection
if (workspace) {
selection = [workspace]
} else {
selection = workspace_tabs.selection();
if (selection.length === 0) { if (selection.length === 0) {
selection = [{id:activeWorkspace}] selection = [{id:activeWorkspace}]
} }
}
var hiddenTabs = []; var hiddenTabs = [];
selection.forEach(function(ws) { selection.forEach(function(ws) {
RED.workspaces.hide(ws.id); RED.workspaces.hide(ws.id);
@ -378,11 +429,16 @@ RED.workspaces = (function() {
workspace_tabs.clearSelection(); workspace_tabs.clearSelection();
}) })
RED.actions.add("core:hide-other-flows", function() { RED.actions.add("core:hide-other-flows", function(workspace) {
var selection = workspace_tabs.selection(); let selection
if (workspace) {
selection = [workspace]
} else {
selection = workspace_tabs.selection();
if (selection.length === 0) { if (selection.length === 0) {
selection = [{id:activeWorkspace}] selection = [{id:activeWorkspace}]
} }
}
var selected = new Set(selection.map(function(ws) { return ws.id })) var selected = new Set(selection.map(function(ws) { return ws.id }))
var currentTabs = workspace_tabs.listTabs(); var currentTabs = workspace_tabs.listTabs();