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 dbb14c6df..656f2764f 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
@@ -40,7 +40,8 @@
* label: 'Local', // label for the item
* sublabel: 'Local', // a sub-label for the item
* icon: 'fa fa-rocket', // (optional) icon for the item
- * selected: true/false, // (optional) if present, display checkbox accordingly
+ * checkbox: true/false, // (optional) if present, display checkbox accordingly
+ * selected: true/false, // (optional) whether the item is selected or not
* children: [] | function(done,item) // (optional) an array of child items, or a function
* // that will call the `done` callback with an array
* // of child items
@@ -163,6 +164,7 @@
});
this._data = [];
this._items = {};
+ this._selected = new Set();
this._topList = $('
').css({
position:'absolute',
top: 0,
@@ -318,6 +320,7 @@
item.parent.children.splice(index,1)
that._trigger("sort",null,item.parent);
}
+ delete item.treeList;
delete(that._items[item.id]);
}
item.treeList.insertChildAt = function(newItem,position,select) {
@@ -564,7 +567,7 @@
item.treeList.makeParent();
}
- if (item.hasOwnProperty('selected')) {
+ if (item.checkbox) {
var selectWrapper = $(' ').appendTo(label);
var cb = $(' ').prop('checked',item.selected).appendTo(selectWrapper);
label.toggleClass("selected",item.selected);
@@ -573,6 +576,11 @@
});
cb.on('change', function(e) {
item.selected = this.checked;
+ if (item.selected) {
+ that._selected.add(item);
+ } else {
+ that._selected.delete(item);
+ }
label.toggleClass("selected",this.checked);
that._trigger("select",e,item);
})
@@ -590,9 +598,11 @@
} else {
label.on("click", function(e) {
if (!that.options.multi) {
- that._topList.find(".selected").removeClass("selected");
+ that.clearSelection();
}
label.addClass("selected");
+ that._selected.add(item);
+
that._trigger("select",e,item)
})
label.on("dblclick", function(e) {
@@ -602,14 +612,21 @@
})
item.treeList.select = function(v) {
if (!that.options.multi) {
- that._topList.find(".selected").removeClass("selected");
+ that.clearSelection();
}
label.toggleClass("selected",v);
if (v) {
+ that._selected.add(item);
that._trigger("select",null,item)
+ } else {
+ that._selected.delete(item);
}
that.reveal(item);
}
+ if (item.selected) {
+ that._selected.add(item);
+ }
+ label.toggleClass("selected",!!item.selected);
}
if (item.icon) {
if (typeof item.icon === "string") {
@@ -663,7 +680,7 @@
return this._data;
}
},
- show: function(item) {
+ show: function(item, done) {
if (typeof item === "string") {
item = this._items[item]
}
@@ -684,6 +701,7 @@
if (stack.length === 0) {
setTimeout(function() {
that.reveal(item);
+ if (done) { done(); }
},isOpening?200:0);
} else {
item.treeList.expand(handleStack)
@@ -710,36 +728,53 @@
this._topList.parent().scrollTop(scrollTop+((itemOffset+2.5*itemHeight)-treeHeight));
}
},
- select: function(item, triggerEvent) {
+ select: function(item, triggerEvent, deselectExisting) {
+ var that = this;
+ if (!this.options.multi && deselectExisting !== false) {
+ this.clearSelection();
+ }
+ if (Array.isArray(item)) {
+ item.forEach(function(i) {
+ that.select(i,triggerEvent,false);
+ })
+ return;
+ }
if (typeof item === "string") {
item = this._items[item]
}
- if (!this.options.multi) {
- this._topList.find(".selected").removeClass("selected");
- }
if (!item) {
return;
}
- this.show(item.id);
- item.treeList.label.addClass("selected");
+ // this.show(item.id);
+ item.selected = true;
+ this._selected.add(item);
+
+ if (item.treeList.label) {
+ item.treeList.label.addClass("selected");
+ }
if (triggerEvent !== false) {
this._trigger("select",null,item)
}
},
clearSelection: function() {
- this._topList.find(".selected").removeClass("selected");
+ this._selected.forEach(function(item) {
+ item.selected = false;
+ if (item.treeList.label) {
+ item.treeList.label.removeClass("selected")
+ }
+ });
+ this._selected.clear();
},
selected: function() {
- var s = this._topList.find(".selected");
+ var selected = [];
+ this._selected.forEach(function(item) {
+ selected.push(item);
+ })
if (this.options.multi) {
- var res = [];
- s.each(function() {
- res.push($(this).parent().data('data'));
- })
- return res;
+ return selected;
}
- if (s.length) {
- return s.parent().data('data');
+ if (selected.length) {
+ return selected[0]
} else {
// TODO: This may be a bug.. it causes the call to return itself
// not undefined.
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js
index 09c9720ae..a0bf74cb4 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editor.js
@@ -1092,6 +1092,7 @@ RED.editor = (function() {
var defaultIcon;
var nodeInfoEditor;
var finishedBuilding = false;
+ var skipInfoRefreshOnClose = false;
editStack.push(node);
RED.view.state(RED.state.EDITING);
@@ -1532,9 +1533,6 @@ RED.editor = (function() {
collapsible: true,
menu: false
});
- if (editing_node) {
- RED.sidebar.info.refresh(editing_node);
- }
var ns;
if (node._def.set.module === "node-red") {
ns = "node-red";
@@ -1614,7 +1612,7 @@ RED.editor = (function() {
if (RED.view.state() != RED.state.IMPORT_DRAGGING) {
RED.view.state(RED.state.DEFAULT);
}
- if (editing_node) {
+ if (editing_node && !skipInfoRefreshOnClose) {
RED.sidebar.info.refresh(editing_node);
}
RED.workspaces.refresh();
@@ -1642,6 +1640,7 @@ RED.editor = (function() {
text: RED._("subflow.edit"),
click: function() {
RED.workspaces.show(id);
+ skipInfoRefreshOnClose = true;
$("#node-dialog-ok").trigger("click");
}
});
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/group.js b/packages/node_modules/@node-red/editor-client/src/js/ui/group.js
index c0c6e889a..49f2a8702 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/group.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/group.js
@@ -504,7 +504,9 @@ RED.group = (function() {
}
}
}
-
+ if (g) {
+ RED.events.emit("groups:change",group)
+ }
markDirty(group);
}
function removeFromGroup(group, nodes, reparent) {
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-help.js b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-help.js
index c75dba284..4c469425b 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-help.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-help.js
@@ -59,7 +59,7 @@ RED.sidebar.help = (function() {
panels = RED.panels.create({
container: stackContainer
})
- panels.ratio(0.5);
+ panels.ratio(0.3);
helpSearch = $(' ').appendTo(toolbar).searchBox({
delay: 100,
@@ -255,6 +255,7 @@ RED.sidebar.help = (function() {
if (ratio > 0.7) {
panels.ratio(0.7)
}
+ treeList.treeList("show","node-type:"+nodeType)
treeList.treeList("select","node-type:"+nodeType, false);
}
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 5a6e11ce3..2e8a6939e 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
@@ -61,7 +61,7 @@ RED.sidebar.info.outliner = (function() {
}
function getNodeLabelText(n) {
- var label = n.name || n.id;
+ var label = n.name || n.type+": "+n.id;
if (n._def.label) {
try {
label = (typeof n._def.label === "function" ? n._def.label.call(n) : n._def.label)||"";
@@ -131,11 +131,11 @@ RED.sidebar.info.outliner = (function() {
RED.view.clickNodeButton(n);
})
}
- $(' ').appendTo(controls).on("click",function(evt) {
- evt.preventDefault();
- evt.stopPropagation();
- RED.view.reveal(n.id);
- })
+ // $(' ').appendTo(controls).on("click",function(evt) {
+ // evt.preventDefault();
+ // evt.stopPropagation();
+ // RED.view.reveal(n.id);
+ // })
if (n.type !== 'group' && n.type !== 'subflow') {
$(' ').appendTo(controls).on("click",function(evt) {
evt.preventDefault();
@@ -226,11 +226,16 @@ RED.sidebar.info.outliner = (function() {
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('treelistselect', function(e,item) {
+ var node = RED.nodes.node(item.id) || RED.nodes.group(item.id);
+ if (node) {
+ if (node.type === 'group' || node._def.category !== "config") {
+ RED.view.select({nodes:[node]})
+ } else {
+ RED.view.select({nodes:[]})
+ }
+ }
+ })
treeList.on('treelistconfirm', function(e,item) {
var node = RED.nodes.node(item.id);
if (node) {
@@ -276,7 +281,8 @@ RED.sidebar.info.outliner = (function() {
element: getFlowLabel(ws),
children:[getEmptyItem(ws.id)],
deferBuild: true,
- icon: "red-ui-icons red-ui-icons-flow"
+ icon: "red-ui-icons red-ui-icons-flow",
+ gutter: getGutter(ws)
}
flowList.treeList.addChild(objects[ws.id])
objects[ws.id].element.toggleClass("red-ui-info-outline-item-disabled", !!ws.disabled)
@@ -307,7 +313,8 @@ RED.sidebar.info.outliner = (function() {
id: sf.id,
element: getNodeLabel(sf),
children:[getEmptyItem(sf.id)],
- deferBuild: true
+ deferBuild: true,
+ gutter: getGutter(sf)
}
subflowList.treeList.addChild(objects[sf.id])
}
@@ -353,11 +360,20 @@ RED.sidebar.info.outliner = (function() {
parent.treeList.addChild(getEmptyItem(parent.id));
}
}
-
+ function getGutter(n) {
+ var span = $("",{class:"red-ui-info-outline-gutter"});
+ $(' ').appendTo(span).on("click",function(evt) {
+ evt.preventDefault();
+ evt.stopPropagation();
+ RED.view.reveal(n.id);
+ })
+ return span;
+ }
function onNodeAdd(n) {
objects[n.id] = {
id: n.id,
- element: getNodeLabel(n)
+ element: getNodeLabel(n),
+ gutter: getGutter(n)
}
if (n.type === "group") {
objects[n.id].children = [];
@@ -383,7 +399,7 @@ RED.sidebar.info.outliner = (function() {
}
function onSelectionChanged(selection) {
- treeList.treeList('clearSelection');
+ // treeList.treeList('clearSelection');
}
return {
@@ -391,8 +407,20 @@ RED.sidebar.info.outliner = (function() {
search: function(val) {
searchInput.searchBox('value',val)
},
+ select: function(node) {
+ if (node) {
+ if (Array.isArray(node)) {
+ treeList.treeList('select', node.map(function(n) { return objects[n.id] }), false)
+ } else {
+ treeList.treeList('select', objects[node.id], false)
+
+ }
+ } else {
+ treeList.treeList('clearSelection')
+ }
+ },
reveal: function(node) {
- treeList.treeList('select', objects[node.id])
+ treeList.treeList('show', objects[node.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 4d1af6e4b..16cf49efb 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
@@ -70,12 +70,12 @@ RED.sidebar.info = (function() {
propertiesPanelHeaderHelp = $(' ').css({
position: 'absolute',
top: '12px',
- right: '38px'
+ right: '32px'
}).on("click", function(evt) {
evt.preventDefault();
evt.stopPropagation();
if (selectedObject) {
- RED.sidebar.help.show(selectedObject.type)
+ RED.sidebar.help.show(selectedObject.type);
}
}).appendTo(propertiesPanelHeader);
RED.popover.tooltip(propertiesPanelHeaderHelp,RED._("sidebar.help.showHelp"));
@@ -90,6 +90,7 @@ RED.sidebar.info = (function() {
evt.stopPropagation();
if (selectedObject) {
RED.sidebar.info.outliner.reveal(selectedObject);
+ RED.view.reveal(selectedObject.id);
}
}).appendTo(propertiesPanelHeader);
RED.popover.tooltip(propertiesPanelHeaderReveal,RED._("sidebar.help.showInOutline"));
@@ -176,10 +177,12 @@ RED.sidebar.info = (function() {
var subflowUserCount;
if (node === null) {
+ RED.sidebar.info.outliner.select(null);
return;
} else if (Array.isArray(node)) {
// Multiple things selected
// - hide help and info sections
+ RED.sidebar.info.outliner.select(node);
propertiesPanelHeaderIcon.empty();
RED.utils.createNodeIcon({type:"_selection_"}).appendTo(propertiesPanelHeaderIcon);
@@ -226,6 +229,8 @@ RED.sidebar.info = (function() {
} else {
// A single 'thing' selected.
+ RED.sidebar.info.outliner.select(node);
+
// Check to see if this is a subflow or subflow instance
var subflowRegex = /^subflow(:(.+))?$/.exec(node.type);
if (subflowRegex) {
@@ -246,17 +251,30 @@ RED.sidebar.info = (function() {
propertiesPanelHeaderIcon.empty();
RED.utils.createNodeIcon(node).appendTo(propertiesPanelHeaderIcon);
- propertiesPanelHeaderLabel.text(RED.utils.getNodeLabel(node, node.type+" "+node.id));
+ propertiesPanelHeaderLabel.text(RED.utils.getNodeLabel(node, node.type+": "+node.id));
propertiesPanelHeaderReveal.show();
selectedObject = node;
+ propRow = $(' ').appendTo(tableBody);
+ var objectType = "node";
+ if (node.type === "subflow" || subflowRegex) {
+ objectType = "subflow";
+ } else if (node.type === "tab") {
+ objectType = "flow";
+ }else if (node.type === "group") {
+ objectType = "group";
+ }
+ $(propRow.children()[0]).text(RED._("sidebar.info."+objectType))
+ RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]);
+
if (node.type === "tab" || node.type === "subflow") {
// If nothing is selected, but we're on a flow or subflow tab.
propertiesPanelHeaderHelp.hide();
+
} else if (node.type === "group") {
propertiesPanelHeaderHelp.hide();
- propRow = $(''+RED._("sidebar.info.group")+' ').appendTo(tableBody);
+ propRow = $(' ').appendTo(tableBody);
var typeCounts = {
nodes:0,
@@ -280,16 +298,7 @@ RED.sidebar.info = (function() {
} else {
- propertiesPanelHeaderHelp.show ();
-
- propRow = $(' ').appendTo(tableBody);
-
- if (!subflowRegex) {
- $(propRow.children()[0]).text(RED._("sidebar.info.node"))
- } else {
- $(propRow.children()[0]).text(RED._("sidebar.info.subflow"))
- }
- RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]);
+ propertiesPanelHeaderHelp.show();
if (!subflowRegex) {
propRow = $(''+RED._("sidebar.info.type")+' ').appendTo(tableBody);
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 84bb1dac5..acfc8eca7 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
@@ -4665,45 +4665,51 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); }
},
getGroupAtPoint: getGroupAt,
getActiveGroup: function() { return activeGroup },
- reveal: function(id) {
+ reveal: function(id,triggerHighlight) {
if (RED.nodes.workspace(id) || RED.nodes.subflow(id)) {
RED.workspaces.show(id);
} else {
var node = RED.nodes.node(id) || RED.nodes.group(id);
if (node) {
if (node.z && (node.type === "group" || node._def.category !== 'config')) {
- node.highlighted = true;
node.dirty = true;
RED.workspaces.show(node.z);
var screenSize = [chart.width()/scaleFactor,chart.height()/scaleFactor];
var scrollPos = [chart.scrollLeft()/scaleFactor,chart.scrollTop()/scaleFactor];
-
- if (node.x < scrollPos[0] || node.y < scrollPos[1] || node.x > screenSize[0]+scrollPos[0] || node.y > screenSize[1]+scrollPos[1]) {
- var deltaX = '-='+(((scrollPos[0] - node.x) + screenSize[0]/2)*scaleFactor);
- var deltaY = '-='+(((scrollPos[1] - node.y) + screenSize[1]/2)*scaleFactor);
+ var cx = node.x;
+ var cy = node.y;
+ if (node.type === "group") {
+ cx += node.w/2;
+ cy += node.h/2;
+ }
+ if (cx < scrollPos[0] || cy < scrollPos[1] || cx > screenSize[0]+scrollPos[0] || cy > screenSize[1]+scrollPos[1]) {
+ var deltaX = '-='+(((scrollPos[0] - cx) + screenSize[0]/2)*scaleFactor);
+ var deltaY = '-='+(((scrollPos[1] - cy) + screenSize[1]/2)*scaleFactor);
chart.animate({
scrollLeft: deltaX,
scrollTop: deltaY
},200);
}
-
- if (!node._flashing) {
- node._flashing = true;
- var flash = 22;
- var flashFunc = function() {
- flash--;
- node.dirty = true;
- if (flash >= 0) {
- node.highlighted = !node.highlighted;
- setTimeout(flashFunc,100);
- } else {
- node.highlighted = false;
- delete node._flashing;
+ if (triggerHighlight !== false) {
+ node.highlighted = true;
+ if (!node._flashing) {
+ node._flashing = true;
+ var flash = 22;
+ var flashFunc = function() {
+ flash--;
+ node.dirty = true;
+ if (flash >= 0) {
+ node.highlighted = !node.highlighted;
+ setTimeout(flashFunc,100);
+ } else {
+ node.highlighted = false;
+ delete node._flashing;
+ }
+ RED.view.redraw();
}
- RED.view.redraw();
+ flashFunc();
}
- flashFunc();
}
} else if (node._def.category === 'config') {
RED.sidebar.config.show(id);
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 8bb0fde68..f50a40050 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
@@ -387,7 +387,7 @@ RED.workspaces = (function() {
RED.nodes.dirty(true);
RED.sidebar.config.refresh();
var selection = RED.view.selection();
- if (!selection.nodes && !selection.links) {
+ if (!selection.nodes && !selection.links && workspace.id === activeWorkspace) {
RED.sidebar.info.refresh(workspace);
}
if (changes.hasOwnProperty('disabled')) {
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 2bd436b1c..38754d475 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
@@ -391,7 +391,15 @@ div.red-ui-info-table {
display: inline-block;
width: 23px;
}
-
+.red-ui-info-outline-gutter {
+ display:none;
+ position: absolute;
+ top: 2px;
+ left: 2px;
+ .red-ui-treeList-label:hover & {
+ display: inline;
+ }
+}
.red-ui-info-outline-item-controls {
position: absolute;
top:0;