", {class:"red-ui-info-outline"}).css({'height': '400px'});
+ var toolbar = $("
", {class:"red-ui-info-outline-toolbar"}).appendTo(container);
+
+ var searchInput = $('
').appendTo(toolbar).searchBox({
+ delay: 100,
+ change: function() {
+ var val = $(this).val().trim().toLowerCase();
+ if (val) {
+ var c = treeList.treeList('filter',function(item) {
+ if (item.depth === 0) {
+ return true;
+ }
+ if (item.id && objects[item.id]) {
+ var l = ((objects[item.id].type||"")+" "+(objects[item.id].name||"")+" "+(objects[item.id].id||"")+" "+(objects[item.id].label||"")).toLowerCase();
+ var isMatch = l.indexOf(val) > -1;
+ if (isMatch) {
+ return true;
+ }
+ }
+ return false;
+ })
+ } else {
+ treeList.treeList('filter',null);
+
+ }
+ }
+ });
+
+ treeList = $("
").css({width: "100%"}).appendTo(container).treeList({
+ data:getFlowData()
+ })
+ // treeList.on('treelistselect', function(e,item) {
+ // console.log(item)
+ // RED.view.reveal(item.id);
+ // })
+ // treeList.treeList('data',[ ... ] )
+ treeList.on('treelistconfirm', function(e,item) {
+ var node = RED.nodes.node(item.id);
+ if (node) {
+ if (node._def.category === "config") {
+ RED.editor.editConfig("", node.type, node.id);
+ } else {
+ RED.editor.edit(node);
+ }
+ }
+ })
+
+ RED.events.on("projects:load", onProjectLoad)
+
+ RED.events.on("flows:add", onFlowAdd)
+ RED.events.on("flows:remove", onObjectRemove)
+ RED.events.on("flows:change", onFlowChange)
+ RED.events.on("flows:reorder", onFlowsReorder)
+
+ RED.events.on("subflows:add", onSubflowAdd)
+ RED.events.on("subflows:remove", onObjectRemove)
+ RED.events.on("subflows:change", onSubflowChange)
+
+ RED.events.on("nodes:add",onNodeAdd);
+ RED.events.on("nodes:remove",onObjectRemove);
+ RED.events.on("nodes:change",onNodeChange);
+
+ RED.events.on("groups:add",onNodeAdd);
+ RED.events.on("groups:remove",onObjectRemove);
+ RED.events.on("groups:change",onNodeChange);
+
+ RED.events.on("view:selection-changed", onSelectionChanged);
+
+
+ // ["links","nodes","flows","subflows","groups"].forEach(function(t) {
+ // ["add","remove","change"].forEach(function(v) {
+ // RED.events.on(t+":"+v, function(n) { console.log(t+":"+v,n)})
+ // })
+ // })
+ // RED.events.on("workspace:clear", function() { console.log("workspace:clear")})
+
+ return container;
+ }
+ function onFlowAdd(ws) {
+ objects[ws.id] = {
+ id: ws.id,
+ element: getFlowLabel(ws),
+ children:[getEmptyItem(ws.id)],
+ deferBuild: true,
+ icon: "red-ui-icons red-ui-icons-flow"
+ }
+ flowList.treeList.addChild(objects[ws.id])
+ objects[ws.id].element.toggleClass("red-ui-info-outline-item-disabled", !!ws.disabled)
+ objects[ws.id].treeList.container.toggleClass("red-ui-info-outline-item-disabled", !!ws.disabled)
+
+
+ }
+ function onFlowChange(n) {
+ var existingObject = objects[n.id];
+ existingObject.element.find(".red-ui-info-outline-item-label").text(n.label || n.id);
+ existingObject.element.toggleClass("red-ui-info-outline-item-disabled", !!n.disabled)
+ existingObject.treeList.container.toggleClass("red-ui-info-outline-item-disabled", !!n.disabled)
+ }
+ function onFlowsReorder(order) {
+ var indexMap = {};
+ order.forEach(function(id,index) {
+ indexMap[id] = index;
+ })
+
+ flowList.treeList.sortChildren(function(A,B) {
+ if (A.id === "__global__") { return -1 }
+ if (B.id === "__global__") { return 1 }
+ return indexMap[A.id] - indexMap[B.id]
+ })
+ }
+ function onSubflowAdd(sf) {
+ objects[sf.id] = {
+ id: sf.id,
+ element: getSubflowLabel(sf),
+ children:[getEmptyItem(sf.id)],
+ deferBuild: true
+ }
+ subflowList.treeList.addChild(objects[sf.id])
+ }
+ function onSubflowChange(n) {
+ var existingObject = objects[n.id];
+
+ existingObject.treeList.replaceElement(getSubflowLabel(n));
+ // existingObject.element.find(".red-ui-info-outline-item-label").text(n.name || n.id);
+
+ }
+
+ function onNodeChange(n) {
+ var existingObject = objects[n.id];
+ var parent = n.g||n.z;
+
+ var nodeLabelText = getNodeLabelText(n);
+ if (nodeLabelText) {
+ existingObject.element.find(".red-ui-info-outline-item-label").text(nodeLabelText);
+ } else {
+ existingObject.element.find(".red-ui-info-outline-item-label").html(" ");
+ }
+
+ if (parent !== existingObject.parent.id) {
+ existingObject.treeList.remove();
+ if (!parent) {
+ globalConfigNodes.treeList.addChild(existingObject);
+ } else {
+ objects[parent].treeList.addChild(existingObject)
+ }
+ }
+ existingObject.element.toggleClass("red-ui-info-outline-item-disabled", !!n.d)
+ }
+ function onObjectRemove(n) {
+ var existingObject = objects[n.id];
+ existingObject.treeList.remove();
+ delete objects[n.d]
+ var parent = existingObject.parent;
+ if (parent.children.length === 0) {
+ parent.treeList.addChild(getEmptyItem(parent.id));
+ }
+ }
+
+ function onNodeAdd(n) {
+ objects[n.id] = {
+ id: n.id,
+ element: getNodeLabel(n)
+ }
+ if (n.type === "group") {
+ objects[n.id].children = [];
+ objects[n.id].deferBuild = true;
+ }
+ var parent = n.g||n.z;
+ if (parent) {
+ if (objects[parent]) {
+ if (empties[parent]) {
+ empties[parent].treeList.remove();
+ delete empties[parent];
+ }
+ objects[parent].treeList.addChild(objects[n.id])
+ } else {
+ // The parent hasn't been added yet
+ console.log("missing",parent)
+ }
+ } else {
+ // No parent - add to Global flow list
+ globalConfigNodes.treeList.addChild(objects[n.id])
+ }
+ objects[n.id].element.toggleClass("red-ui-info-outline-item-disabled", !!n.d)
+ }
+
+ function onSelectionChanged(selection) {
+ // treeList.treeList('clearSelection');
+ // console.log(selection);
+ if (selection.nodes) {
+ selection.nodes.forEach(function(n) {
+ // console.log("..",n.id);
+ treeList.treeList('show',n.id);
+ if (objects[n.id].treeList) {
+ objects[n.id].treeList.select(true);
+ }
+
+ });
+ }
+ }
+
+ return {
+ build: build
+ }
+})();
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 39683e41e..c6e9aec52 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
@@ -18,6 +18,7 @@ RED.sidebar.info = (function() {
var content;
var sections;
var propertiesSection;
+ var outlinerSection;
var infoSection;
var helpSection;
var tipBox;
@@ -39,6 +40,13 @@ RED.sidebar.info = (function() {
container: stackContainer
}).hide();
+ outlinerSection = sections.add({
+ title: RED._("sidebar.info.outline"),
+ collapsible: true
+ })
+ outlinerSection.expand();
+ RED.sidebar.info.outliner.build().appendTo(outlinerSection.content);
+
propertiesSection = sections.add({
title: RED._("sidebar.info.info"),
collapsible: true
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
index a9c1c9500..7e3d72b89 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
@@ -859,7 +859,9 @@ RED.utils = (function() {
}
function getNodeIcon(def,node) {
- if (def.category === 'config') {
+ if (node && node.type === 'group') {
+ return "font-awesome/fa-object-group"
+ } else if (def.category === 'config') {
return RED.settings.apiRootUrl+"icons/node-red/cog.svg"
} else if (node && node.type === 'tab') {
return RED.settings.apiRootUrl+"icons/node-red/subflow.svg"
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/search.scss b/packages/node_modules/@node-red/editor-client/src/sass/search.scss
index 0ec8b6525..273793896 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/search.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/search.scss
@@ -87,6 +87,8 @@
}
.red-ui-palette-icon {
width: 15px;
+ position:relative;
+ left: -1px;
}
.red-ui-search-result-description {
margin-left:28px;
@@ -153,7 +155,7 @@
width: 30px;
float:left;
height: 25px;
- border-radius: 5px;
+ border-radius: 3px;
border: 1px solid $node-border;
background-position: 5% 50%;
background-repeat: no-repeat;
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 bc72f7532..1605c9c76 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
@@ -279,3 +279,173 @@ div.red-ui-info-table {
border-radius: 4px;
padding: 2px 4px 2px;
}
+
+.red-ui-help-search {
+ border-bottom: 1px solid $secondary-border-color;
+}
+
+
+.red-ui-info-outline {
+ display: flex;
+ flex-direction: column;
+
+ .red-ui-treeList {
+ flex-grow: 1;
+ }
+
+ .red-ui-treeList-container,.red-ui-editableList-border {
+ border: none;
+ border-radius: 0;
+ }
+ .red-ui-treeList-label {
+ font-size: 13px;
+ padding: 2px 0;
+ overflow: hidden;
+ }
+ .red-ui-info-outline-item {
+ display: inline-block;
+ padding: 0;
+ font-size: 13px;
+ border: none;
+ .red-ui-palette-icon-fa {
+ position: relative;
+ top: 1px;
+ left: 0px;
+ }
+ &:hover {
+ background: inherit
+ }
+
+ &.red-ui-info-outline-item-flow {
+ .red-ui-search-result-description {
+ margin-left: 4px;
+ }
+ }
+ &.red-ui-info-outline-item-group .red-ui-search-result-node {
+ background: none;
+ border-color: transparent;
+ .red-ui-palette-icon-container {
+ background: none;
+ }
+ .red-ui-palette-icon-fa {
+ color: $secondary-text-color;
+ font-size: 18px;
+ }
+ }
+ &.red-ui-info-outline-item-empty {
+ font-style: italic;
+ color: $form-placeholder-color;
+ }
+ }
+
+ .red-ui-search-result-node {
+ width: 24px;
+ height: 20px;
+ margin-top: 1px;
+ }
+
+ .red-ui-palette-icon-container {
+ width: 24px;
+ }
+ .red-ui-palette-icon {
+ width: 20px;
+ }
+ .red-ui-search-result-description {
+ margin-left: 32px;
+ line-height: 22px;
+ white-space: nowrap;
+ }
+ .red-ui-search-result-node-label {
+ color: $secondary-text-color;
+ }
+}
+.red-ui-info-outline-item-control-spacer {
+ display: inline-block;
+ width: 23px;
+}
+
+.red-ui-info-outline-item-controls {
+ position: absolute;
+ top:0;
+ bottom: 0;
+ right: 0px;
+ padding: 2px 0 0 1px;
+ text-align: right;
+ background: $list-item-background;
+
+ .red-ui-treeList-label:hover & {
+ background: $list-item-background-hover;
+ }
+ .red-ui-treeList-label.selected & {
+ background: $list-item-background-selected;
+ }
+
+
+ &.red-ui-info-outline-item-hover-controls button {
+ min-width: 23px;
+ }
+
+ .red-ui-treeList-label:not(:hover) &.red-ui-info-outline-item-hover-controls {
+ button {
+ border: none;
+ background: none;
+ }
+ }
+ .red-ui-info-outline-item-control-reveal,
+ .red-ui-info-outline-item-control-action {
+ display: none;
+ }
+ .red-ui-treeList-label:hover & {
+ .red-ui-info-outline-item-control-reveal,
+ .red-ui-info-outline-item-control-action {
+ display: inline-block;
+ }
+ }
+
+ .fa-ban {
+ display: none;
+ }
+ .red-ui-info-outline-item.red-ui-info-outline-item-disabled & {
+ .fa-ban {
+ display: inline-block;
+ }
+ .fa-circle-thin {
+ display: none;
+ }
+ }
+ button {
+ margin-right: 3px
+ }
+}
+.red-ui-info-outline-item-disabled {
+ .red-ui-search-result-node {
+ opacity: 0.4;
+ }
+ .red-ui-info-outline-item-label {
+ font-style: italic;
+ color: $secondary-text-color-disabled;
+ }
+ .red-ui-icons-flow {
+ opacity: 0.4;
+ }
+}
+.red-ui-icons {
+ display: inline-block;
+ width: 18px;
+ &:before {
+ white-space: pre;
+ content: ' '
+ }
+
+}
+
+.red-ui-icons-flow {
+ background-image: url('images/subflow_tab.svg');
+ background-repeat: no-repeat;
+ background-size: contain;
+ filter: brightness(2.5);
+}
+
+.red-ui-info-outline-toolbar {
+ border-bottom: 1px solid $secondary-border-color;
+}