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 63ea0efe9..2a1e16f1d 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 @@ -53,8 +53,15 @@ "confirmDelete": "Confirm delete", "delete": "Are you sure you want to delete '__label__'?", "dropFlowHere": "Drop the flow here", - "addFlow": "Add Flow", - "listFlows": "List Flows", + "addFlow": "Add flow", + "addFlowToRight": "Add flow to the right", + "hideFlow": "Hide flow", + "hideOtherFlows": "Hide other flows", + "showAllFlows": "Show all flows", + "hideAllFlows": "Hide all flows", + "showLastHiddenFlow": "Show last hidden flow", + "listFlows": "List flows", + "listSubflows": "List subflows", "status": "Status", "enabled": "Enabled", "disabled":"Disabled", diff --git a/packages/node_modules/@node-red/editor-client/src/js/keymap.json b/packages/node_modules/@node-red/editor-client/src/js/keymap.json index c50508389..766f6bd9f 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/keymap.json +++ b/packages/node_modules/@node-red/editor-client/src/js/keymap.json @@ -25,7 +25,9 @@ "ctrl-alt-o": "core:open-project", "ctrl-g v": "core:show-version-control-tab", "ctrl-shift-l": "core:show-event-log", - "ctrl-shift-p":"core:show-action-list" + "ctrl-shift-p":"core:show-action-list", + "alt-w": "core:hide-flow", + "alt-shift-w": "core:show-last-hidden-flow" }, "red-ui-sidebar-node-config": { "backspace": "core:delete-config-selection", diff --git a/packages/node_modules/@node-red/editor-client/src/js/settings.js b/packages/node_modules/@node-red/editor-client/src/js/settings.js index 39f372974..467c5b569 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/settings.js +++ b/packages/node_modules/@node-red/editor-client/src/js/settings.js @@ -220,6 +220,16 @@ RED.settings = (function () { return defaultValue; } } + function getLocal(key) { + return localStorage.getItem(key) + } + function setLocal(key, value) { + localStorage.setItem(key, value); + } + function removeLocal(key) { + localStorage.removeItem(key) + } + return { init: init, @@ -228,6 +238,9 @@ RED.settings = (function () { set: set, get: get, remove: remove, - theme: theme + theme: theme, + setLocal: setLocal, + getLocal: getLocal, + removeLocal: removeLocal } })(); 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 485b43d98..b38017c60 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 @@ -498,6 +498,13 @@ RED.clipboard = (function() { $("#red-ui-clipboard-dialog-import-text").on("keyup", validateImport); $("#red-ui-clipboard-dialog-import-text").on('paste',function() { setTimeout(validateImport,10)}); + if (RED.workspaces.active() === 0) { + $("#red-ui-clipboard-dialog-import-opt-current").addClass('disabled').removeClass("selected"); + $("#red-ui-clipboard-dialog-import-opt-new").addClass("selected"); + } else { + $("#red-ui-clipboard-dialog-import-opt-current").removeClass('disabled').addClass("selected"); + $("#red-ui-clipboard-dialog-import-opt-new").removeClass("selected"); + } $("#red-ui-clipboard-dialog-import-opt > a").on("click", function(evt) { evt.preventDefault(); if ($(this).hasClass('disabled') || $(this).hasClass('selected')) { @@ -611,9 +618,6 @@ RED.clipboard = (function() { activeLibraries[tabId] = browser; }) - - - $("#red-ui-clipboard-dialog-tab-library-name").on("keyup", validateExportFilename); $("#red-ui-clipboard-dialog-tab-library-name").on('paste',function() { setTimeout(validateExportFilename,10)}); $("#red-ui-clipboard-dialog-export").button("enable"); @@ -636,7 +640,6 @@ RED.clipboard = (function() { label: RED._("editor.types.json") }); - var previewList = $("#red-ui-clipboard-dialog-export-tab-clipboard-preview-list").css({position:"absolute",top:0,right:0,bottom:0,left:0}).treeList({ data: [] }) @@ -738,16 +741,22 @@ RED.clipboard = (function() { $("#red-ui-clipboard-dialog-export").hide(); $("#red-ui-clipboard-dialog-import-conflict").hide(); - var selection = RED.workspaces.selection(); - if (selection.length > 0) { - $("#red-ui-clipboard-dialog-export-rng-selected").trigger("click"); + if (RED.workspaces.active() === 0) { + $("#red-ui-clipboard-dialog-export-rng-selected").addClass('disabled').removeClass('selected'); + $("#red-ui-clipboard-dialog-export-rng-flow").addClass('disabled').removeClass('selected'); + $("#red-ui-clipboard-dialog-export-rng-full").trigger("click"); } else { - selection = RED.view.selection(); - if (selection.nodes) { + var selection = RED.workspaces.selection(); + if (selection.length > 0) { $("#red-ui-clipboard-dialog-export-rng-selected").trigger("click"); } else { - $("#red-ui-clipboard-dialog-export-rng-selected").addClass('disabled').removeClass('selected'); - $("#red-ui-clipboard-dialog-export-rng-flow").trigger("click"); + selection = RED.view.selection(); + if (selection.nodes) { + $("#red-ui-clipboard-dialog-export-rng-selected").trigger("click"); + } else { + $("#red-ui-clipboard-dialog-export-rng-selected").addClass('disabled').removeClass('selected'); + $("#red-ui-clipboard-dialog-export-rng-flow").trigger("click"); + } } } if (format === "red-ui-clipboard-dialog-export-fmt-full") { 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 e8c678333..f1239edef 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 @@ -82,7 +82,7 @@ RED.menu = (function() { linkContent += ''+opt.label+''+ ''+opt.sublabel+'' } else { - linkContent += ''+opt.label+'' + linkContent += ''+opt.label+'' } linkContent += ''; @@ -92,7 +92,7 @@ RED.menu = (function() { if (typeof opt.onselect === 'string') { var shortcut = RED.keyboard.getShortcut(opt.onselect); if (shortcut && shortcut.key) { - opt.shortcutSpan = $(''+RED.keyboard.formatKey(shortcut.key, true)+'').appendTo(link); + 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 41c6e704c..9bc52d5fc 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 @@ -38,6 +38,7 @@ RED.tabs = (function() { if (options.vertical) { wrapper.addClass("red-ui-tabs-vertical"); } + if (options.addButton) { wrapper.addClass("red-ui-tabs-add"); var addButton = $('
').appendTo(wrapper); @@ -75,6 +76,8 @@ RED.tabs = (function() { }); } if (options.searchButton) { + // This is soft-deprecated as we don't use this in the core anymore + // We no use the `menu` option to provide a drop-down list of actions wrapper.addClass("red-ui-tabs-search"); var searchButton = $('').appendTo(wrapper); searchButton.find('a').on("click", function(evt) { @@ -94,6 +97,48 @@ RED.tabs = (function() { } } + if (options.menu) { + wrapper.addClass("red-ui-tabs-menu"); + var menuButton = $('
').appendTo(wrapper); + var menuButtonLink = menuButton.find('a') + var menuOpen = false; + menuButtonLink.on("click", function(evt) { + evt.stopPropagation(); + evt.preventDefault(); + if (menuOpen) { + menu.remove(); + menuOpen = false; + return; + } + menuOpen = true; + var menuOptions = []; + if (typeof options.searchButton === 'function') { + menuOptions = options.menu() + } else if (Array.isArray(options.menu)) { + menuOptions = options.menu; + } + var menu = RED.menu.init({options: menuOptions}); + menu.css({ + position: "absolute" + }) + menu.appendTo("body"); + var elementPos = menuButton.offset(); + menu.css({ + top: (elementPos.top+menuButton.height()-2)+"px", + left: (elementPos.left - menu.width() + menuButton.width())+"px" + }) + $(".red-ui-menu.red-ui-menu-dropdown").hide(); + $(document).on("click.red-ui-tabmenu", function(evt) { + $(document).off("click.red-ui-tabmenu"); + menuOpen = false; + menu.remove(); + }); + menu.show(); + }) + } + + + var scrollLeft; var scrollRight; @@ -337,6 +382,12 @@ RED.tabs = (function() { if (link.length === 0) { return; } + if (link.parent().hasClass("hide-tab")) { + link.parent().removeClass("hide-tab").removeClass("hide"); + if (options.onshow) { + options.onshow(tabs[link.attr('href').slice(1)]) + } + } if (!link.parent().hasClass("active")) { ul.children().removeClass("active"); ul.children().css({"transition": "width 100ms"}); @@ -362,13 +413,13 @@ RED.tabs = (function() { } } function activatePreviousTab() { - var previous = ul.find("li.active").prev(); + var previous = findPreviousVisibleTab(); if (previous.length > 0) { activateTab(previous.find("a")); } } function activateNextTab() { - var next = ul.find("li.active").next(); + var next = findNextVisibleTab(); if (next.length > 0) { activateTab(next.find("a")); } @@ -378,7 +429,9 @@ RED.tabs = (function() { if (options.vertical) { return; } - var tabs = ul.find("li.red-ui-tab"); + var allTabs = ul.find("li.red-ui-tab"); + var tabs = allTabs.filter(":not(.hide-tab)"); + var hiddenTabs = allTabs.filter(".hide-tab"); var width = wrapper.width(); var tabCount = tabs.length; var tabWidth; @@ -446,6 +499,7 @@ RED.tabs = (function() { // } tabs.css({width:currentTabWidth}); + hiddenTabs.css({width:"0px"}); if (tabWidth < 50) { // ul.find(".red-ui-tab-close").hide(); ul.find(".red-ui-tab-icon").hide(); @@ -486,24 +540,101 @@ RED.tabs = (function() { } var li = ul.find("a[href='#"+id+"']").parent(); if (li.hasClass("active")) { - var tab = li.prev(); + var tab = findPreviousVisibleTab(li); if (tab.length === 0) { - tab = li.next(); + tab = findNextVisibleTab(li); + } + if (tab.length > 0) { + activateTab(tab.find("a")); + } else { + if (options.onchange) { + options.onchange(null); + } } - activateTab(tab.find("a")); } - li.remove(); - if (tabs[id].pinned) { - pinnedTabsCount--; + + li.one("transitionend", function(evt) { + li.remove(); + if (tabs[id].pinned) { + pinnedTabsCount--; + } + if (options.onremove) { + options.onremove(tabs[id]); + } + delete tabs[id]; + updateTabWidths(); + if (collapsibleMenu) { + collapsibleMenu.remove(); + collapsibleMenu = null; + } + }) + li.addClass("hide-tab"); + li.width(0); + } + + function findPreviousVisibleTab(li) { + if (!li) { + li = ul.find("li.active").parent(); } - if (options.onremove) { - options.onremove(tabs[id]); + var previous = li.prev(); + while(previous.length > 0 && previous.hasClass("hide-tab")) { + previous = previous.prev(); } - delete tabs[id]; - updateTabWidths(); - if (collapsibleMenu) { - collapsibleMenu.remove(); - collapsibleMenu = null; + return previous; + } + function findNextVisibleTab(li) { + if (!li) { + li = ul.find("li.active").parent(); + } + var next = ul.find("li.active").next(); + while(next.length > 0 && next.hasClass("hide-tab")) { + next = next.next(); + } + return next; + } + function showTab(id) { + if (tabs[id]) { + var li = ul.find("a[href='#"+id+"']").parent(); + if (li.hasClass("hide-tab")) { + li.removeClass("hide-tab").removeClass("hide"); + if (ul.find("li.red-ui-tab:not(.hide-tab)").length === 1) { + activateTab(li.find("a")) + } + updateTabWidths(); + if (options.onshow) { + options.onshow(tabs[id]) + } + } + } + } + function hideTab(id) { + if (tabs[id]) { + var li = ul.find("a[href='#"+id+"']").parent(); + if (!li.hasClass("hide-tab")) { + if (li.hasClass("active")) { + var tab = findPreviousVisibleTab(li); + if (tab.length === 0) { + tab = findNextVisibleTab(li); + } + if (tab.length > 0) { + activateTab(tab.find("a")); + } else { + if (options.onchange) { + options.onchange(null); + } + } + } + li.removeClass("active"); + li.one("transitionend", function(evt) { + li.addClass("hide"); + updateTabWidths(); + if (options.onhide) { + options.onhide(tabs[id]) + } + }) + li.addClass("hide-tab"); + li.css({width:0}) + } } } @@ -663,7 +794,6 @@ RED.tabs = (function() { link.on("click", function(evt) { evt.preventDefault(); }) link.on("dblclick", function(evt) { evt.stopPropagation(); evt.preventDefault(); }) - $('').appendTo(li); if (tab.closeable) { @@ -675,6 +805,15 @@ RED.tabs = (function() { removeTab(tab.id); }); } + if (tab.hideable) { + li.addClass("red-ui-tabs-closeable") + var closeLink = $("",{href:"#",class:"red-ui-tab-close"}).appendTo(li); + closeLink.append(''); + closeLink.on("click",function(event) { + event.preventDefault(); + hideTab(tab.id); + }); + } var badges = $('').appendTo(li); if (options.onselect) { @@ -682,11 +821,11 @@ RED.tabs = (function() { $('').appendTo(badges); } + link.attr("title",tab.label); if (options.onadd) { options.onadd(tab); } - link.attr("title",tab.label); if (ul.find("li.red-ui-tab").length == 1) { activateTab(link); } @@ -787,7 +926,7 @@ RED.tabs = (function() { previousTab: activatePreviousTab, resize: updateTabWidths, count: function() { - return ul.find("li.red-ui-tab").length; + return ul.find("li.red-ui-tab:not(.hide)").length; }, activeIndex: function() { return ul.find("li.active").index() @@ -795,6 +934,9 @@ RED.tabs = (function() { contains: function(id) { return ul.find("a[href='#"+id+"']").length > 0; }, + showTab: showTab, + hideTab: hideTab, + renameTab: function(id,label) { tabs[id].label = label; var tab = ul.find("a[href='#"+id+"']"); @@ -802,7 +944,20 @@ RED.tabs = (function() { tab.find("span.red-ui-text-bidi-aware").text(label).attr('dir', RED.text.bidi.resolveBaseTextDir(label)); updateTabWidths(); }, + listTabs: function() { + return $.makeArray(ul.children().map(function() { return $(this).data('tabId');})); + }, selection: getSelection, + clearSelection: function() { + if (options.onselect) { + var selection = ul.find("li.red-ui-tab.selected"); + if (selection.length > 0) { + selection.removeClass("selected"); + selectionChanged(); + } + } + + }, order: function(order) { preferredOrder = order; var existingTabOrder = $.makeArray(ul.children().map(function() { return $(this).data('tabId');})); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/treeList.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/treeList.js index 6619ad76e..19d65c591 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/treeList.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/treeList.js @@ -532,8 +532,8 @@ }).appendTo(label) } - var labelPaddingWidth = (item.gutter?item.gutter.width()+2:0)+(depth*20); - // var labelPaddingWidth = (item.gutter ? item.gutter[0].offsetWidth + 2 : 0) + (depth * 20) + // var labelPaddingWidth = (item.gutter?item.gutter.width()+2:0)+(depth*20); + var labelPaddingWidth = (item.gutter ? item.gutter[0].offsetWidth + 2 : 0) + (depth * 20) item.treeList.labelPadding = $('').css({ display: "inline-block", width: labelPaddingWidth+'px' diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-config.js b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-config.js index c16be54e2..492600f91 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-config.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-config.js @@ -229,7 +229,7 @@ RED.sidebar.config = (function() { var globalConfigNodes = []; var configList = {}; RED.nodes.eachConfig(function(cn) { - if (cn.z) {//} == RED.workspaces.active()) { + if (cn.z) { configList[cn.z.replace(/\./g,"-")] = configList[cn.z.replace(/\./g,"-")]||[]; configList[cn.z.replace(/\./g,"-")].push(cn); } else if (!cn.z) { diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info-outliner.js b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info-outliner.js index f77b5f010..52606cd88 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info-outliner.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info-outliner.js @@ -122,11 +122,20 @@ RED.sidebar.info.outliner = (function() { }) RED.popover.tooltip(triggerButton,RED._("sidebar.info.triggerAction")); } - // $('').appendTo(controls).on("click",function(evt) { - // evt.preventDefault(); - // evt.stopPropagation(); - // RED.view.reveal(n.id); - // }) + + if (n.type === "tab") { + var toggleVisibleButton = $('').appendTo(controls).on("click",function(evt) { + evt.preventDefault(); + evt.stopPropagation(); + var isHidden = !div.hasClass("red-ui-info-outline-item-hidden"); + div.toggleClass("red-ui-info-outline-item-hidden",isHidden); + if (isHidden) { + RED.workspaces.hide(n.id); + } else { + RED.workspaces.show(n.id, null, true); + } + }); + } if (n.type !== 'subflow') { var toggleButton = $('').appendTo(controls).on("click",function(evt) { evt.preventDefault(); @@ -317,13 +326,27 @@ RED.sidebar.info.outliner = (function() { RED.events.on("groups:remove",onObjectRemove); RED.events.on("groups:change",onNodeChange); - RED.events.on("workspace:clear", onWorkspaceClear) + RED.events.on("workspace:show", onWorkspaceShow); + RED.events.on("workspace:hide", onWorkspaceHide); + RED.events.on("workspace:clear", onWorkspaceClear); return container; } function onWorkspaceClear() { treeList.treeList('data',getFlowData()); } + function onWorkspaceShow(event) { + var existingObject = objects[event.workspace]; + if (existingObject) { + existingObject.element.removeClass("red-ui-info-outline-item-hidden") + } + } + function onWorkspaceHide(event) { + var existingObject = objects[event.workspace]; + if (existingObject) { + existingObject.element.addClass("red-ui-info-outline-item-hidden") + } + } function onFlowAdd(ws) { objects[ws.id] = { id: ws.id, 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 15b705448..017172a23 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 @@ -180,6 +180,10 @@ RED.sidebar.info = (function() { if (node === null) { RED.sidebar.info.outliner.select(null); + propertiesPanelHeaderIcon.empty(); + propertiesPanelHeaderLabel.text(""); + propertiesPanelHeaderReveal.hide(); + propertiesPanelHeaderHelp.hide(); return; } else if (Array.isArray(node)) { // Multiple things selected 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 d154fe865..8ccbf6fe4 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 @@ -345,8 +345,8 @@ RED.view = (function() { activeSubflow = RED.nodes.subflow(event.workspace); - RED.menu.setDisabled("menu-item-workspace-edit", activeSubflow); - RED.menu.setDisabled("menu-item-workspace-delete",RED.workspaces.count() == 1 || activeSubflow); + RED.menu.setDisabled("menu-item-workspace-edit", activeSubflow || event.workspace === 0); + RED.menu.setDisabled("menu-item-workspace-delete",event.workspace === 0 || RED.workspaces.count() == 1 || activeSubflow); if (workspaceScrollPositions[event.workspace]) { chart.scrollLeft(workspaceScrollPositions[event.workspace].left); @@ -675,27 +675,33 @@ RED.view = (function() { function updateActiveNodes() { var activeWorkspace = RED.workspaces.active(); + if (activeWorkspace !== 0) { + activeNodes = RED.nodes.filterNodes({z:activeWorkspace}); + activeNodes.forEach(function(n,i) { + n._index = i; + }) + activeLinks = RED.nodes.filterLinks({ + source:{z:activeWorkspace}, + target:{z:activeWorkspace} + }); - activeNodes = RED.nodes.filterNodes({z:activeWorkspace}); - activeNodes.forEach(function(n,i) { - n._index = i; - }) - activeLinks = RED.nodes.filterLinks({ - source:{z:activeWorkspace}, - target:{z:activeWorkspace} - }); + activeGroups = RED.nodes.groups(activeWorkspace)||[]; + activeGroups.forEach(function(g, i) { + g._index = i; + if (g.g) { + g._root = g.g; + g._depth = 1; + } else { + g._root = g.id; + g._depth = 0; + } + }); + } else { + activeNodes = []; + activeLinks = []; + activeGroups = []; + } - activeGroups = RED.nodes.groups(activeWorkspace)||[]; - activeGroups.forEach(function(g,i) { - g._index = i; - if (g.g) { - g._root = g.g; - g._depth = 1; - } else { - g._root = g.id; - g._depth = 0; - } - }); var changed = false; do { changed = false; @@ -1966,93 +1972,94 @@ RED.view = (function() { function updateSelection() { var selection = {}; var activeWorkspace = RED.workspaces.active(); - var workspaceSelection = RED.workspaces.selection(); - if (workspaceSelection.length === 0) { - selection = getSelection(); - activeLinks = RED.nodes.filterLinks({ - source:{z:activeWorkspace}, - target:{z:activeWorkspace} - }); - var tabOrder = RED.nodes.getWorkspaceOrder(); - var currentLinks = activeLinks; - var addedLinkLinks = {}; - activeFlowLinks = []; - var activeLinkNodeIds = Object.keys(activeLinkNodes); - activeLinkNodeIds.forEach(function(n) { - activeLinkNodes[n].dirty = true; - }) - activeLinkNodes = {}; - for (var i=0;i 0) { - activeFlowLinks.push({ - refresh: Math.floor(Math.random()*10000), - node: linkNode, - links: offFlowLinks//offFlows.map(function(i) { return {id:i,links:offFlowLinks[i]};}) }); + var offFlows = Object.keys(offFlowLinks); + // offFlows.sort(function(A,B) { + // return tabOrder.indexOf(A) - tabOrder.indexOf(B); + // }); + if (offFlows.length > 0) { + activeFlowLinks.push({ + refresh: Math.floor(Math.random()*10000), + node: linkNode, + links: offFlowLinks//offFlows.map(function(i) { return {id:i,links:offFlowLinks[i]};}) + }); + } } } + if (activeFlowLinks.length === 0 && selected_link !== null && selected_link.link) { + activeLinks.push(selected_link); + activeLinkNodes[selected_link.source.id] = selected_link.source; + selected_link.source.dirty = true; + activeLinkNodes[selected_link.target.id] = selected_link.target; + selected_link.target.dirty = true; + } + } else { + selection.flows = workspaceSelection; } - if (activeFlowLinks.length === 0 && selected_link !== null && selected_link.link) { - activeLinks.push(selected_link); - activeLinkNodes[selected_link.source.id] = selected_link.source; - selected_link.source.dirty = true; - activeLinkNodes[selected_link.target.id] = selected_link.target; - selected_link.target.dirty = true; - } - } else { - selection.flows = workspaceSelection; } var selectionJSON = activeWorkspace+":"+JSON.stringify(selection,function(key,value) { if (key === 'nodes' || key === 'flows') { 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 cce64e6ff..a6288a7f3 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 @@ -21,24 +21,46 @@ RED.workspaces = (function() { var workspaceIndex = 0; var viewStack = []; + var hideStack = []; var viewStackPos = 0; - function isSameObj(env0, env1) { - return (JSON.stringify(env0) === JSON.stringify(env1)); - } - function addToViewStack(id) { if (viewStackPos !== viewStack.length) { viewStack.splice(viewStackPos); } viewStack.push(id); viewStackPos = viewStack.length; - // console.warn("addToViewStack",id,viewStack); + } + + function removeFromHideStack(id) { + hideStack = hideStack.filter(function(v) { + if (v === id) { + return false; + } else if (Array.isArray(v)) { + var i = v.indexOf(id); + if (i > -1) { + v.splice(i,1); + } + if (v.length === 0) { + return false; + } + return true + } + return true; + }) } function addWorkspace(ws,skipHistoryEntry,targetIndex) { if (ws) { + if (!ws.closeable) { + ws.hideable = true; + } workspace_tabs.addTab(ws,targetIndex); + + var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}"); + if (hiddenTabs[ws.id]) { + workspace_tabs.hideTab(ws.id); + } workspace_tabs.resize(); } else { var tabId = RED.nodes.id(); @@ -46,7 +68,15 @@ RED.workspaces = (function() { workspaceIndex += 1; } while ($("#red-ui-workspace-tabs a[title='"+RED._('workspace.defaultName',{number:workspaceIndex})+"']").size() !== 0); - ws = {type:"tab",id:tabId,disabled: false,info:"",label:RED._('workspace.defaultName',{number:workspaceIndex}),env:[]}; + ws = { + type: "tab", + id: tabId, + disabled: false, + info: "", + label: RED._('workspace.defaultName',{number:workspaceIndex}), + env: [], + hideable: true + }; RED.nodes.addWorkspace(ws,targetIndex); workspace_tabs.addTab(ws,targetIndex); workspace_tabs.activateTab(tabId); @@ -97,11 +127,18 @@ RED.workspaces = (function() { var event = { old: activeWorkspace } - activeWorkspace = tab.id; + if (tab) { + $("#red-ui-workspace-chart").show(); + activeWorkspace = tab.id; + window.location.hash = 'flow/'+tab.id; + $("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!tab.disabled); + } else { + $("#red-ui-workspace-chart").hide(); + activeWorkspace = 0; + window.location.hash = ''; + } event.workspace = activeWorkspace; RED.events.emit("workspace:change",event); - window.location.hash = 'flow/'+tab.id; - $("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!tab.disabled); RED.sidebar.config.refresh(); RED.view.focus(); }, @@ -126,7 +163,7 @@ RED.workspaces = (function() { if (tab.disabled) { $("#red-ui-tab-"+(tab.id.replace(".","-"))).addClass('red-ui-workspace-disabled'); } - RED.menu.setDisabled("menu-item-workspace-delete",workspaceTabCount <= 1); + RED.menu.setDisabled("menu-item-workspace-delete",activeWorkspace === 0 || workspaceTabCount <= 1); if (workspaceTabCount === 1) { showWorkspace(); } @@ -134,8 +171,10 @@ RED.workspaces = (function() { onremove: function(tab) { if (tab.type === "tab") { workspaceTabCount--; + } else { + hideStack.push(tab.id); } - RED.menu.setDisabled("menu-item-workspace-delete",workspaceTabCount <= 1); + RED.menu.setDisabled("menu-item-workspace-delete",activeWorkspace === 0 || workspaceTabCount <= 1); if (workspaceTabCount === 0) { hideWorkspace(); } @@ -167,12 +206,67 @@ RED.workspaces = (function() { $(".red-ui-sidebar-shade").show(); } }, + onhide: function(tab) { + hideStack.push(tab.id); + RED.events.emit("workspace:hide",{workspace: tab.id}) + }, + onshow: function(tab) { + removeFromHideStack(tab.id); + RED.events.emit("workspace:show",{workspace: tab.id}) + }, minimumActiveTabWidth: 150, scrollable: true, addButton: "core:add-flow", addButtonCaption: RED._("workspace.addFlow"), - searchButton: "core:list-flows", - searchButtonCaption: RED._("workspace.listFlows") + menu: [ + { + 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" + } + ] }); workspaceTabCount = 0; } @@ -223,15 +317,102 @@ 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: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}] + } + var hiddenTabs = []; + selection.forEach(function(ws) { + RED.workspaces.hide(ws.id); + hideStack.pop(); + hiddenTabs.push(ws.id); + }) + if (hiddenTabs.length > 0) { + hideStack.push(hiddenTabs); + } + workspace_tabs.clearSelection(); + }) + + RED.actions.add("core:hide-other-flows", function() { + var selection = workspace_tabs.selection(); + if (selection.length === 0) { + selection = [{id:activeWorkspace}] + } + var selected = new Set(selection.map(function(ws) { return ws.id })) + + var currentTabs = workspace_tabs.listTabs(); + var hiddenTabs = []; + currentTabs.forEach(function(id) { + if (!selected.has(id)) { + RED.workspaces.hide(id); + hideStack.pop(); + hiddenTabs.push(id); + } + }) + if (hiddenTabs.length > 0) { + hideStack.push(hiddenTabs); + } + }) + + RED.actions.add("core:hide-all-flows", function() { + var currentTabs = workspace_tabs.listTabs(); + currentTabs.forEach(function(id) { + RED.workspaces.hide(id); + hideStack.pop(); + }) + if (currentTabs.length > 0) { + hideStack.push(currentTabs); + } + workspace_tabs.clearSelection(); + }) + RED.actions.add("core:show-all-flows", function() { + var currentTabs = workspace_tabs.listTabs(); + currentTabs.forEach(function(id) { + RED.workspaces.show(id, null, true) + }) + }) + // RED.actions.add("core:toggle-flows", function() { + // var currentTabs = workspace_tabs.listTabs(); + // var visibleCount = workspace_tabs.count(); + // currentTabs.forEach(function(id) { + // if (visibleCount === 0) { + // RED.workspaces.show(id) + // } else { + // RED.workspaces.hide(id) + // } + // }) + // }) + RED.actions.add("core:show-last-hidden-flow", function() { + var id = hideStack.pop(); + if (id) { + if (typeof id === 'string') { + RED.workspaces.show(id); + } else { + var last = id.pop(); + id.forEach(function(i) { + RED.workspaces.show(i, null, true); + }) + setTimeout(function() { + RED.workspaces.show(last); + },150) + + } + } + }) + RED.actions.add("core:list-flows",function() { RED.actions.invoke("core:search","type:tab "); }) - + RED.actions.add("core:list-subflows",function() { + RED.actions.invoke("core:search","type:subflow "); + }) RED.actions.add("core:go-to-previous-location", function() { if (viewStackPos > 0) { if (viewStackPos === viewStack.length) { @@ -247,8 +428,6 @@ RED.workspaces = (function() { RED.workspaces.show(viewStack[++viewStackPos],true); } }) - - hideWorkspace(); } @@ -346,7 +525,18 @@ RED.workspaces = (function() { selection: function() { return workspace_tabs.selection(); }, - show: function(id,skipStack) { + hide: function(id) { + if (!id) { + id = activeWorkspace; + } + if (workspace_tabs.contains(id)) { + workspace_tabs.hideTab(id); + var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}"); + hiddenTabs[id] = true; + RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs)); + } + }, + show: function(id,skipStack,unhideOnly) { if (!workspace_tabs.contains(id)) { var sf = RED.nodes.subflow(id); if (sf) { @@ -355,14 +545,22 @@ RED.workspaces = (function() { null, workspace_tabs.activeIndex()+1 ); + removeFromHideStack(id); } else { return; } } - if (!skipStack && activeWorkspace !== id) { - addToViewStack(activeWorkspace) + if (unhideOnly) { + workspace_tabs.showTab(id); + } else { + if (!skipStack && activeWorkspace !== id) { + addToViewStack(activeWorkspace) + } + workspace_tabs.activateTab(id); } - workspace_tabs.activateTab(id); + var hiddenTabs = JSON.parse(RED.settings.getLocal("hiddenTabs")||"{}"); + delete hiddenTabs[id]; + RED.settings.setLocal("hiddenTabs",JSON.stringify(hiddenTabs)); }, refresh: function() { RED.nodes.eachWorkspace(function(ws) { diff --git a/packages/node_modules/@node-red/editor-client/src/sass/dropdownMenu.scss b/packages/node_modules/@node-red/editor-client/src/sass/dropdownMenu.scss index ca19afc73..4c7f51109 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/dropdownMenu.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/dropdownMenu.scss @@ -19,7 +19,7 @@ font-size: $primary-font-size; position: absolute; top: 100%; - width: 200px; + width: 230px; left: 0; z-index: 1000; display: none; @@ -46,7 +46,7 @@ & > li > a, & > li > a:focus { display: block; - padding: 4px 0 4px 32px; + padding: 4px 12px 4px 32px; clear: both; font-weight: normal; line-height: 20px; @@ -106,11 +106,17 @@ display: none; } } + .red-ui-menu-label { + display: flex; + & > :first-child { + flex-grow: 1 + } + } .red-ui-popover-key { border: none; padding: 0; font-size: 13px; - float: right; + // float: right; color: $menuColor; border-color: $menuColor; } diff --git a/packages/node_modules/@node-red/editor-client/src/sass/header.scss b/packages/node_modules/@node-red/editor-client/src/sass/header.scss index 02528a446..e638506b4 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/header.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/header.scss @@ -214,7 +214,6 @@ } span.red-ui-menu-label { font-size: 14px; - display: inline-block; text-indent: 0px; } span.red-ui-menu-sublabel { diff --git a/packages/node_modules/@node-red/editor-client/src/sass/tab-info.scss b/packages/node_modules/@node-red/editor-client/src/sass/tab-info.scss index d4d86cd89..2b8f17d4b 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/tab-info.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/tab-info.scss @@ -435,6 +435,12 @@ div.red-ui-info-table { border: none; background: none; } + .fa-circle-thin { + display: none; + } + .fa-eye { + display: none; + } } .red-ui-info-outline-item-control-reveal, .red-ui-info-outline-item-control-action { @@ -446,7 +452,17 @@ div.red-ui-info-table { display: inline-block; } } - + .fa-eye-slash { + display: none; + } + .red-ui-info-outline-item.red-ui-info-outline-item-hidden & { + .fa-eye-slash { + display: inline-block; + } + .fa-eye { + display: none; + } + } .fa-ban { display: none; } diff --git a/packages/node_modules/@node-red/editor-client/src/sass/tabs.scss b/packages/node_modules/@node-red/editor-client/src/sass/tabs.scss index 0b038932a..e83996a5e 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/tabs.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/tabs.scss @@ -21,6 +21,9 @@ height: 35px; box-sizing: border-box; + .hide-tab { + transition: width 0.1s ease-in; + } .red-ui-tabs-scroll-container { height: 60px; overflow-x: scroll; @@ -142,13 +145,18 @@ padding-right: 21px; } &.red-ui-tabs-add { - padding-right: 35px; + padding-right: 29px; } &.red-ui-tabs-add.red-ui-tabs-scrollable { - padding-right: 59px; + padding-right: 53px; } + &.red-ui-tabs-add.red-ui-tabs-menu.red-ui-tabs-scrollable, &.red-ui-tabs-add.red-ui-tabs-search.red-ui-tabs-scrollable { - padding-right: 95px; + padding-right: 83px; + } + + &.red-ui-tabs-add.red-ui-tabs-search.red-ui-tabs-menu.red-ui-tabs-scrollable { + padding-right: 113px; } &.red-ui-tabs-collapsible { @@ -232,13 +240,14 @@ a { @include workspace-button; - line-height: 32px; - height: 32px; - width: 32px; + line-height: 30px; + height: 28px; + width: 28px; + margin-left: 2px; + margin-right: 2px; margin-top: 3px; - margin-right:3px; - margin-left:3px; - border: 1px solid $primary-border-color; + margin-bottom: 3px; + border: none; z-index: 2; } } @@ -280,6 +289,8 @@ border-left: none; border-right: none; border-top: none; + border-bottom: 1px solid $primary-border-color; + line-height: 34px; } } .red-ui-tab-scroll-left { @@ -296,15 +307,30 @@ } .red-ui-tabs.red-ui-tabs-add .red-ui-tab-scroll-right { - right: 38px; + right: 32px; } +.red-ui-tabs.red-ui-tabs-add.red-ui-tabs-menu .red-ui-tab-scroll-right, .red-ui-tabs.red-ui-tabs-add.red-ui-tabs-search .red-ui-tab-scroll-right { - right: 76px; + right: 64px; } +.red-ui-tabs.red-ui-tabs-add.red-ui-tabs-menu .red-ui-tabs-add, .red-ui-tabs.red-ui-tabs-add.red-ui-tabs-search .red-ui-tabs-add { - right: 38px; + right: 32px; } + +.red-ui-tabs.red-ui-tabs-add.red-ui-tabs-search.red-ui-tabs-menu { + .red-ui-tab-scroll-right { + right: 96px; + } + .red-ui-tabs-add { + right: 64px; + } + .red-ui-tabs-search { + right: 32px; + } +} + .red-ui-tabs-fade { position: absolute; bottom: 0;