diff --git a/Gruntfile.js b/Gruntfile.js index b6474182a..c7867bd35 100644 --- a/Gruntfile.js +++ b/Gruntfile.js @@ -165,6 +165,8 @@ module.exports = function(grunt) { "packages/node_modules/@node-red/editor-client/src/js/ui/sidebar.js", "packages/node_modules/@node-red/editor-client/src/js/ui/palette.js", "packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js", + "packages/node_modules/@node-red/editor-client/src/js/ui/tab-info-outliner.js", + "packages/node_modules/@node-red/editor-client/src/js/ui/tab-help.js", "packages/node_modules/@node-red/editor-client/src/js/ui/tab-config.js", "packages/node_modules/@node-red/editor-client/src/js/ui/tab-context.js", "packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js", 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 84e37edcb..06712b4de 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 @@ -585,7 +585,18 @@ "nodeHelp": "Node Help", "none":"None", "arrayItems": "__count__ items", - "showTips":"You can open the tips from the settings panel" + "showTips":"You can open the tips from the settings panel", + "outline": "Outline", + "globalConfig": "Global Configuration Nodes" + }, + "help": { + "name": "Help", + "label": "help", + "search": "Search help", + "nodeHelp": "Node Help", + "showHelp": "Show help", + "showTopics": "Show topics", + "noHelp": "No help topic selected" }, "config": { "name": "Configuration nodes", diff --git a/packages/node_modules/@node-red/editor-client/src/js/nodes.js b/packages/node_modules/@node-red/editor-client/src/js/nodes.js index e6b4bccca..1eac45494 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/nodes.js +++ b/packages/node_modules/@node-red/editor-client/src/js/nodes.js @@ -348,6 +348,9 @@ RED.nodes = (function() { workspacesOrder.splice(targetIndex,0,ws.id); } RED.events.emit('flows:add',ws); + if (targetIndex !== undefined) { + RED.events.emit('flows:reorder',workspacesOrder) + } } function getWorkspace(id) { return workspaces[id]; @@ -1521,7 +1524,6 @@ RED.nodes = (function() { groupsByZ = {}; var subflowIds = Object.keys(subflows); - subflows = {}; subflowIds.forEach(function(id) { RED.subflow.removeSubflow(id) }); diff --git a/packages/node_modules/@node-red/editor-client/src/js/red.js b/packages/node_modules/@node-red/editor-client/src/js/red.js index fd2adf05f..330b2f9a5 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/red.js +++ b/packages/node_modules/@node-red/editor-client/src/js/red.js @@ -124,9 +124,9 @@ var RED = (function() { $("#red-ui-palette > .red-ui-palette-spinner").hide(); $(".red-ui-palette-scroll").removeClass("hide"); $("#red-ui-palette-search").removeClass("hide"); - loadFlows(function() { - if (RED.settings.theme("projects.enabled",false)) { - RED.projects.refresh(function(activeProject) { + if (RED.settings.theme("projects.enabled",false)) { + RED.projects.refresh(function(activeProject) { + loadFlows(function() { RED.sidebar.info.refresh() if (!activeProject) { // Projects enabled but no active project @@ -140,12 +140,14 @@ var RED = (function() { } completeLoad(); }); - } else { + }); + } else { + loadFlows(function() { // Projects disabled by the user RED.sidebar.info.refresh() completeLoad(); - } - }); + }); + } } else { var config = configs.shift(); appendNodeConfig(config,stepConfig); @@ -431,8 +433,7 @@ var RED = (function() { ''+ ''; - RED.sidebar.info.set(aboutHeader+RED.utils.renderMarkdown(data)); - RED.sidebar.info.show(); + RED.sidebar.help.set(aboutHeader+RED.utils.renderMarkdown(data)); }); } diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/colorPicker.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/colorPicker.js index 0c7944c84..3739cd970 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/colorPicker.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/colorPicker.js @@ -1,26 +1,5 @@ RED.colorPicker = (function() { - function getDarkerColor(c) { - var r,g,b; - if (/^#[a-f0-9]{6}$/i.test(c)) { - r = parseInt(c.substring(1, 3), 16); - g = parseInt(c.substring(3, 5), 16); - b = parseInt(c.substring(5, 7), 16); - } else if (/^#[a-f0-9]{3}$/i.test(c)) { - r = parseInt(c.substring(1, 2)+c.substring(1, 2), 16); - g = parseInt(c.substring(2, 3)+c.substring(2, 3), 16); - b = parseInt(c.substring(3, 4)+c.substring(3, 4), 16); - } else { - return c; - } - var l = 0.3 * r/255 + 0.59 * g/255 + 0.11 * b/255 ; - r = Math.max(0,r-50); - g = Math.max(0,g-50); - b = Math.max(0,b-50); - var s = ((r<<16) + (g<<8) + b).toString(16); - return '#'+'000000'.slice(0, 6-s.length)+s; - } - function create(options) { var color = options.value; var id = options.id; @@ -57,7 +36,7 @@ RED.colorPicker = (function() { "background-color": color, "opacity": opacity }); - var border = getDarkerColor(color); + var border = RED.utils.getDarkerColor(color); if (border[0] === '#') { border += Math.round(255*Math.floor(opacity*100)/100).toString(16); } else { @@ -132,7 +111,7 @@ RED.colorPicker = (function() { height: height+"px", margin: margin+"px", backgroundColor: col, - "border-color": getDarkerColor(col) + "border-color": RED.utils.getDarkerColor(col) }).appendTo(row); button.on("click", function (e) { e.preventDefault(); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/editableList.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/editableList.js index 06ccc97d9..3df2f9a51 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/editableList.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/editableList.js @@ -183,7 +183,7 @@ if (this.options.resizeItem) { var that = this; this.element.children().each(function(i) { - that.options.resizeItem($(this).find(".red-ui-editableList-item-content"),i); + that.options.resizeItem($(this).children(".red-ui-editableList-item-content"),i); }); } }, @@ -223,7 +223,7 @@ var items = this.element.children(); var that = this; items.sort(function(A,B) { - return that.activeSort($(A).find(".red-ui-editableList-item-content").data('data'),$(B).find(".red-ui-editableList-item-content").data('data')); + return that.activeSort($(A).children(".red-ui-editableList-item-content").data('data'),$(B).children(".red-ui-editableList-item-content").data('data')); }); $.each(items,function(idx,li) { that.element.append(li); @@ -305,7 +305,7 @@ } if (this.options.addItem) { var index = that.element.children().length-1; - setTimeout(function() { + // setTimeout(function() { that.options.addItem(row,index,data); if (that.activeFilter) { try { @@ -321,7 +321,7 @@ that.uiContainer.scrollTop(that.element.height()); },0); } - },0); + // },0); } }, addItem: function(data) { @@ -334,7 +334,7 @@ }, removeItem: function(data) { var items = this.element.children().filter(function(f) { - return data === $(this).find(".red-ui-editableList-item-content").data('data'); + return data === $(this).children(".red-ui-editableList-item-content").data('data'); }); items.remove(); if (this.options.removeItem) { @@ -342,7 +342,7 @@ } }, items: function() { - return this.element.children().map(function(i) { return $(this).find(".red-ui-editableList-item-content"); }); + return this.element.children().map(function(i) { return $(this).children(".red-ui-editableList-item-content"); }); }, empty: function() { this.element.empty(); @@ -365,14 +365,14 @@ }, show: function(item) { var items = this.element.children().filter(function(f) { - return item === $(this).find(".red-ui-editableList-item-content").data('data'); + return item === $(this).children(".red-ui-editableList-item-content").data('data'); }); if (items.length > 0) { this.uiContainer.scrollTop(this.uiContainer.scrollTop()+items.position().top) } }, getItem: function(li) { - var el = li.find(".red-ui-editableList-item-content"); + var el = li.children(".red-ui-editableList-item-content"); if (el.length) { return el.data('data'); } else { diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/panels.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/panels.js index 5a82f9d35..285c7c9bb 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/panels.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/panels.js @@ -29,6 +29,10 @@ RED.panels = (function() { if (!vertical) { container.addClass("red-ui-panels-horizontal"); } + + $(children[0]).addClass("red-ui-panel"); + $(children[1]).addClass("red-ui-panel"); + var separator = $('
').insertAfter(children[0]); var startPosition; var panelSizes = []; @@ -52,11 +56,11 @@ RED.panels = (function() { var newSizes = [panelSizes[0]+delta,panelSizes[1]-delta]; if (vertical) { $(children[0]).height(newSizes[0]); - $(children[1]).height(newSizes[1]); + // $(children[1]).height(newSizes[1]); ui.position.top -= delta; } else { $(children[0]).width(newSizes[0]); - $(children[1]).width(newSizes[1]); + // $(children[1]).width(newSizes[1]); ui.position.left -= delta; } if (options.resize) { @@ -71,6 +75,9 @@ RED.panels = (function() { var panel = { ratio: function(ratio) { + if (ratio === undefined) { + return panelRatio; + } panelRatio = ratio; modifiedSizes = true; if (ratio === 0 || ratio === 1) { @@ -99,10 +106,10 @@ RED.panels = (function() { panelSizes = [topPanelSize,bottomPanelSize]; if (vertical) { $(children[0]).outerHeight(panelSizes[0]); - $(children[1]).outerHeight(panelSizes[1]); + // $(children[1]).outerHeight(panelSizes[1]); } else { $(children[0]).outerWidth(panelSizes[0]); - $(children[1]).outerWidth(panelSizes[1]); + // $(children[1]).outerWidth(panelSizes[1]); } } if (options.resize) { diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js index fca2f26f1..6f8724a8a 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js @@ -136,6 +136,23 @@ RED.popover = (function() { closePopup(true); }); } + if (trigger === 'hover' && options.interactive) { + div.on('mouseenter', function(e) { + clearTimeout(timer); + active = true; + }) + div.on('mouseleave', function(e) { + if (timer) { + clearTimeout(timer); + } + if (active) { + timer = setTimeout(function() { + active = false; + closePopup(); + },delay.hide); + } + }) + } if (instant) { div.show(); } else { @@ -163,8 +180,10 @@ RED.popover = (function() { if (trigger === 'hover') { target.on('mouseenter',function(e) { clearTimeout(timer); - active = true; - timer = setTimeout(openPopup,delay.show); + if (!active) { + active = true; + timer = setTimeout(openPopup,delay.show); + } }); target.on('mouseleave disabled', function(e) { if (timer) { @@ -278,6 +297,7 @@ RED.popover = (function() { var closeCallback = options.onclose; var target = options.target; var align = options.align || "left"; + var offset = options.offset || [0,0]; var pos = target.offset(); var targetWidth = target.width(); @@ -285,7 +305,7 @@ RED.popover = (function() { var panelHeight = panel.height(); var panelWidth = panel.width(); - var top = (targetHeight+pos.top); + var top = (targetHeight+pos.top) + offset[1]; if (top+panelHeight > $(window).height()) { top -= (top+panelHeight)-$(window).height() + 5; } @@ -296,12 +316,12 @@ RED.popover = (function() { if (align === "left") { panel.css({ top: top+"px", - left: (pos.left)+"px", + left: (pos.left+offset[0])+"px", }); } else if(align === "right") { panel.css({ top: top+"px", - left: (pos.left-panelWidth)+"px", + left: (pos.left-panelWidth+offset[0])+"px", }); } panel.slideDown(100); 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 ed04733c9..dbb14c6df 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 @@ -27,7 +27,8 @@ * * methods: * - data(items) - clears existing items and replaces with new data - * + * - clearSelection - clears the selected items + * - filter(filterFunc) - filters the tree using the provided function * events: * - treelistselect : function(event, item) {} * - treelistconfirm : function(event,item) {} @@ -59,9 +60,9 @@ * properties and functions: * * item.parent - set to the parent item + * item.depth - the depth in the tree (0 == root) * item.treeList.container * item.treeList.label - the label element for the item - * item.treeList.depth - the depth in the tree (0 == root) * item.treeList.parentList - the editableList instance this item is in * item.treeList.remove() - removes the item from the tree * item.treeList.makeLeaf(detachChildElements) - turns an element with children into a leaf node, @@ -78,8 +79,8 @@ * Optionally selects the item after adding. * item.treeList.expand(done) - expands the parent item to show children. Optional 'done' callback. * item.treeList.collapse() - collapse the parent item to hide children. - * - * + * item.treeList.sortChildren(sortFunction) - does a one-time sort of the children using sortFunction + * item.treeList.replaceElement(element) - replace the custom element for the item * * */ @@ -100,6 +101,8 @@ var target; switch(evt.keyCode) { case 13: // ENTER + evt.preventDefault(); + evt.stopPropagation(); if (selected.children) { if (selected.treeList.container.hasClass("expanded")) { selected.treeList.collapse() @@ -112,6 +115,8 @@ break; case 37: // LEFT + evt.preventDefault(); + evt.stopPropagation(); if (selected.children&& selected.treeList.container.hasClass("expanded")) { selected.treeList.collapse() } else if (selected.parent) { @@ -119,6 +124,8 @@ } break; case 38: // UP + evt.preventDefault(); + evt.stopPropagation(); target = that._getPreviousSibling(selected); if (target) { target = that._getLastDescendant(target); @@ -128,6 +135,8 @@ } break; case 39: // RIGHT + evt.preventDefault(); + evt.stopPropagation(); if (selected.children) { if (!selected.treeList.container.hasClass("expanded")) { selected.treeList.expand() @@ -135,6 +144,8 @@ } break case 40: //DOWN + evt.preventDefault(); + evt.stopPropagation(); if (selected.children && Array.isArray(selected.children) && selected.children.length > 0 && selected.treeList.container.hasClass("expanded")) { target = selected.children[0]; } else { @@ -151,7 +162,7 @@ } }); this._data = []; - + this._items = {}; this._topList = $('
    ').css({ position:'absolute', top: 0, @@ -244,7 +255,8 @@ that._trigger("changeparent",null,evt); }); that._trigger("sort",null,parent); - } + }, + filter: parent.treeList.childFilter }); if (!!that.options.sortable) { subtree.addClass('red-ui-treeList-sortable'); @@ -289,21 +301,178 @@ } return reparentedEvent; }, - _addSubtree: function(parentList, container, item, depth) { + _initItem: function(item,depth) { + if (item.treeList) { + return; + } var that = this; + this._items[item.id] = item; item.treeList = {}; - item.treeList.depth = depth; - item.treeList.container = container; - - item.treeList.parentList = parentList; + item.depth = depth; item.treeList.remove = function() { - parentList.editableList('removeItem',item); + if (item.treeList.parentList) { + item.treeList.parentList.editableList('removeItem',item); + } if (item.parent) { var index = item.parent.children.indexOf(item); item.parent.children.splice(index,1) that._trigger("sort",null,item.parent); } + delete(that._items[item.id]); } + item.treeList.insertChildAt = function(newItem,position,select) { + newItem.parent = item; + item.children.splice(position,0,newItem); + var processChildren = function(parent,i) { + that._initItem(i,parent.depth+1) + i.parent = parent; + if (i.children && typeof i.children !== 'function') { + i.children.forEach(function(item) { + processChildren(i, item, parent.depth+2) + }); + } + } + processChildren(item,newItem); + + if (!item.deferBuild) { + item.treeList.childList.editableList('insertItemAt',newItem,position) + if (select) { + setTimeout(function() { + that.select(newItem) + },100); + } + that._trigger("sort",null,item); + } + } + item.treeList.addChild = function(newItem,select) { + item.treeList.insertChildAt(newItem,item.children.length,select); + } + item.treeList.expand = function(done) { + if (!item.children) { + if (done) { done(false) } + return; + } + if (!item.treeList.container) { + item.expanded = true; + if (done) { done(false) } + return; + } + var container = item.treeList.container; + if (container.hasClass("expanded")) { + if (done) { done(false) } + return; + } + + if (!container.hasClass("built") && (item.deferBuild || typeof item.children === 'function')) { + container.addClass('built'); + var childrenAdded = false; + var spinner; + var startTime = 0; + var completeBuild = function(children) { + childrenAdded = true; + item.treeList.childList = that._addChildren(container,item,children,depth).hide(); + var delta = Date.now() - startTime; + if (delta < 400) { + setTimeout(function() { + item.treeList.childList.slideDown('fast'); + if (spinner) { + spinner.remove(); + } + },400-delta); + } else { + item.treeList.childList.slideDown('fast'); + if (spinner) { + spinner.remove(); + } + } + item.expanded = true; + if (done) { done(true) } + that._trigger("childrenloaded",null,item) + } + if (typeof item.children === 'function') { + item.children(completeBuild,item); + } else { + delete item.deferBuild; + completeBuild(item.children); + } + if (!childrenAdded) { + startTime = Date.now(); + spinner = $('
    ').css({ + "background-position": (35+depth*20)+'px 50%' + }).appendTo(container); + } + + } else { + if (that._loadingData) { + item.treeList.childList.show(); + } else { + item.treeList.childList.slideDown('fast'); + } + item.expanded = true; + if (done) { done(!that._loadingData) } + } + container.addClass("expanded"); + } + item.treeList.collapse = function() { + if (!item.children) { + return; + } + item.expanded = false; + if (item.treeList.container) { + item.treeList.childList.slideUp('fast'); + item.treeList.container.removeClass("expanded"); + } + } + item.treeList.sortChildren = function(sortFunc) { + if (!item.children) { + return; + } + item.children.sort(sortFunc); + if (item.treeList.childList) { + // Do a one-off sort of the list, which means calling sort twice: + // 1. first with the desired sort function + item.treeList.childList.editableList('sort',sortFunc); + // 2. and then with null to remove it + item.treeList.childList.editableList('sort',null); + } + } + item.treeList.replaceElement = function (element) { + if (item.element) { + if (item.treeList.container) { + $(item.element).remove(); + $(element).appendTo(item.treeList.label); + var labelPaddingWidth = (item.gutter?item.gutter.width()+2:0)+(item.depth*20); + $(element).css({ + width: "calc(100% - "+(labelPaddingWidth+20+(item.icon?20:0))+"px)" + }) + } + item.element = element; + } + } + + if (item.children && typeof item.children !== "function") { + item.children.forEach(function(i) { + that._initItem(i,depth+1); + }) + } + }, + _addSubtree: function(parentList, container, item, depth) { + var that = this; + this._initItem(item,depth); + // item.treeList = {}; + // item.treeList.depth = depth; + item.treeList.container = container; + + item.treeList.parentList = parentList; + // item.treeList.remove = function() { + // parentList.editableList('removeItem',item); + // if (item.parent) { + // var index = item.parent.children.indexOf(item); + // item.parent.children.splice(index,1) + // that._trigger("sort",null,item.parent); + // } + // delete(that._items[item.id]); + // } var label = $("
    ",{class:"red-ui-treeList-label"}).appendTo(container); item.treeList.label = label; @@ -357,6 +526,7 @@ treeListIcon.off("click.red-ui-treeList-expand"); delete item.children; container.removeClass("expanded"); + delete item.expanded; } item.treeList.makeParent = function(children) { if (treeListIcon.children().length) { @@ -388,86 +558,6 @@ item.treeList.childList = that._addChildren(container,item,item.children,depth).hide(); } } - item.treeList.insertChildAt = function(newItem,position,select) { - newItem.parent = item; - item.children.splice(position,0,newItem); - - if (!item.deferBuild) { - item.treeList.childList.editableList('insertItemAt',newItem,position) - if (select) { - setTimeout(function() { - that.select(newItem) - },100); - } - that._trigger("sort",null,item); - } - } - item.treeList.addChild = function(newItem,select) { - item.treeList.insertChildAt(newItem,item.children.length,select); - } - item.treeList.expand = function(done) { - if (!item.children) { - return; - } - if (container.hasClass("expanded")) { - if (done) { done() } - return; - } - if (!container.hasClass("built") && (item.deferBuild || typeof item.children === 'function')) { - container.addClass('built'); - var childrenAdded = false; - var spinner; - var startTime = 0; - var completeBuild = function(children) { - childrenAdded = true; - item.treeList.childList = that._addChildren(container,item,children,depth).hide(); - var delta = Date.now() - startTime; - if (delta < 400) { - setTimeout(function() { - item.treeList.childList.slideDown('fast'); - if (spinner) { - spinner.remove(); - } - },400-delta); - } else { - item.treeList.childList.slideDown('fast'); - if (spinner) { - spinner.remove(); - } - } - if (done) { done() } - that._trigger("childrenloaded",null,item) - } - if (typeof item.children === 'function') { - item.children(completeBuild,item); - } else { - delete item.deferBuild; - completeBuild(item.children); - } - if (!childrenAdded) { - startTime = Date.now(); - spinner = $('
    ').css({ - "background-position": (35+depth*20)+'px 50%' - }).appendTo(container); - } - - } else { - if (that._loadingData) { - item.treeList.childList.show(); - } else { - item.treeList.childList.slideDown('fast'); - } - if (done) { done() } - } - container.addClass("expanded"); - } - item.treeList.collapse = function() { - if (!item.children) { - return; - } - item.treeList.childList.slideUp('fast'); - container.removeClass("expanded"); - } var treeListIcon = $('').appendTo(label); if (item.children) { @@ -499,7 +589,9 @@ } } else { label.on("click", function(e) { - that._topList.find(".selected").removeClass("selected"); + if (!that.options.multi) { + that._topList.find(".selected").removeClass("selected"); + } label.addClass("selected"); that._trigger("select",e,item) }) @@ -508,9 +600,23 @@ that._trigger("confirm",e,item); } }) + item.treeList.select = function(v) { + if (!that.options.multi) { + that._topList.find(".selected").removeClass("selected"); + } + label.toggleClass("selected",v); + if (v) { + that._trigger("select",null,item) + } + that.reveal(item); + } } if (item.icon) { - $('').appendTo(label); + if (typeof item.icon === "string") { + $('').appendTo(label); + } else { + $('').appendTo(label).append(item.icon); + } } if (item.hasOwnProperty('label') || item.hasOwnProperty('sublabel')) { if (item.hasOwnProperty('label')) { @@ -542,6 +648,7 @@ var that = this; if (items !== undefined) { this._data = items; + this._items = {}; this._topList.editableList('empty'); this._loadingData = true; for (var i=0; i treeHeight) { + this._topList.parent().scrollTop(scrollTop+((itemOffset+2.5*itemHeight)-treeHeight)); + } + }, + select: function(item, triggerEvent) { + 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._trigger("select",null,item) - + if (triggerEvent !== false) { + this._trigger("select",null,item) + } + }, + clearSelection: function() { + this._topList.find(".selected").removeClass("selected"); }, selected: function() { var s = this._topList.find(".selected"); @@ -581,8 +741,46 @@ if (s.length) { return s.parent().data('data'); } else { + // TODO: This may be a bug.. it causes the call to return itself + // not undefined. return undefined; } + }, + filter: function(filterFunc,expandResults) { + var filter = function(item) { + var matchCount = 0; + if (filterFunc && filterFunc(item)) { + matchCount++; + } + var childCount = 0; + if (item.children && typeof item.children !== "function") { + if (item.treeList.childList) { + childCount = item.treeList.childList.editableList('filter', filter); + } else { + item.treeList.childFilter = filter; + if (filterFunc) { + item.children.forEach(function(i) { + if (filter(i)) { + childCount++; + } + }) + + } + } + matchCount += childCount; + if (childCount > 0) { + item.treeList.expand(); + } + } + if (!filterFunc) { + return true + } + return matchCount > 0 + } + return this._topList.editableList('filter', filter); + }, + get: function(id) { + return this._items[id] || null; } }); 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 e36e5c969..7baf72575 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 @@ -790,6 +790,11 @@ RED.editor = (function() { nodeDiv.css({ 'backgroundColor': backgroundColor }); + var borderColor = RED.utils.getDarkerColor(backgroundColor); + if (borderColor !== backgroundColor) { + nodeDiv.css('border-color',borderColor) + } + } var iconContainer = $('
    ',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv); RED.utils.createIconElement(icon_url, iconContainer, true); @@ -932,7 +937,12 @@ RED.editor = (function() { $("#red-ui-editor-node-color").on('change', function(ev) { // Horribly out of scope... - nodeDiv.css('backgroundColor',$(this).val()); + var colour = $(this).val(); + nodeDiv.css('backgroundColor',colour); + var borderColor = RED.utils.getDarkerColor(colour); + if (borderColor !== colour) { + nodeDiv.css('border-color',borderColor) + } }) } @@ -948,6 +958,11 @@ RED.editor = (function() { var colour = RED.utils.getNodeColor(node.type, node._def); var icon_url = RED.utils.getNodeIcon(node._def,node); nodeDiv.css('backgroundColor',colour); + var borderColor = RED.utils.getDarkerColor(colour); + if (borderColor !== colour) { + nodeDiv.css('border-color',borderColor) + } + var iconContainer = $('
    ',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv); RED.utils.createIconElement(icon_url, iconContainer, true); @@ -1071,7 +1086,7 @@ RED.editor = (function() { return nodeInfoEditor; } - function showEditDialog(node) { + function showEditDialog(node, defaultTab) { var editing_node = node; var isDefaultIcon; var defaultIcon; @@ -1589,6 +1604,9 @@ RED.editor = (function() { prepareEditDialog(node,node._def,"node-input", function() { trayBody.i18n(); finishedBuilding = true; + if (defaultTab) { + editorTabs.activateTab(defaultTab); + } done(); }); }, diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/buffer.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/buffer.js index ec5b78c99..a1e244290 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/buffer.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/buffer.js @@ -15,7 +15,7 @@ **/ (function() { - var template = ''; + var template = ''; function stringToUTF8Array(str) { var data = []; @@ -187,8 +187,7 @@ $(".red-ui-editor-type-buffer-type").on("click", function(e) { e.preventDefault(); - RED.sidebar.info.set(RED._("bufferEditor.modeDesc")); - RED.sidebar.info.show(); + RED.sidebar.help.set(RED._("bufferEditor.modeDesc")); }) diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js index 9a9765c35..64dec3a62 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/expression.js @@ -237,8 +237,7 @@ var changeTimer; $(".red-ui-editor-type-expression-legacy").on("click", function(e) { e.preventDefault(); - RED.sidebar.info.set(RED._("expressionEditor.compatModeDesc")); - RED.sidebar.info.show(); + RED.sidebar.help.set(RED._("expressionEditor.compatModeDesc")); }) var testExpression = function() { var value = testDataEditor.getValue(); @@ -318,9 +317,9 @@ var p2 = $("#red-ui-editor-type-expression-panel-info > .form-row > div:first-child"); p2Height -= p2.outerHeight(true) + 20; $(".red-ui-editor-type-expression-tab-content").height(p2Height); - $("#red-ui-editor-type-expression-test-data").css("height",(p2Height-5)+"px"); + $("#red-ui-editor-type-expression-test-data").css("height",(p2Height-25)+"px"); testDataEditor.resize(); - $("#red-ui-editor-type-expression-test-result").css("height",(p2Height-5)+"px"); + $("#red-ui-editor-type-expression-test-result").css("height",(p2Height-25)+"px"); testResultEditor.resize(); } }); 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 388dcecdd..c0c6e889a 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 @@ -427,15 +427,16 @@ RED.group = (function() { h: 0, _def: RED.group.def } + + group.z = nodes[0].z; + RED.nodes.addGroup(group); + try { addToGroup(group,nodes); } catch(err) { RED.notify(err,"error"); return; } - group.z = nodes[0].z; - - RED.nodes.addGroup(group); return group; } function addToGroup(group,nodes) { diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/palette.js b/packages/node_modules/@node-red/editor-client/src/js/ui/palette.js index 345f7e7f3..170ff149a 100755 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/palette.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/palette.js @@ -165,6 +165,7 @@ RED.palette = (function() { metaData = typeInfo.set.module+" : "; } metaData += type; + $('').appendTo(popOverContent) $('

    ',{style:"font-size: 0.8em"}).text(metaData).appendTo(popOverContent); } } catch(err) { @@ -255,6 +256,7 @@ RED.palette = (function() { var popover = RED.popover.create({ target:d, trigger: "hover", + interactive: true, width: "300px", content: "hi", delay: { show: 750, hide: 50 } @@ -270,19 +272,19 @@ RED.palette = (function() { // html: true, // container:'body' // }); - d.on("click", function() { - RED.view.focus(); - var helpText; - if (nt.indexOf("subflow:") === 0) { - helpText = RED.utils.renderMarkdown(RED.nodes.subflow(nt.substring(8)).info||"")||(''+RED._("sidebar.info.none")+''); - } else { - helpText = $("script[data-help-name='"+d.attr("data-palette-type")+"']").html()||(''+RED._("sidebar.info.none")+''); - } - // Don't look too closely. RED.sidebar.info.set will set the 'Description' - // section of the sidebar. Pass in the title of the Help section so it looks - // right. - RED.sidebar.info.set(helpText,RED._("sidebar.info.nodeHelp")); - }); + // d.on("click", function() { + // RED.view.focus(); + // var helpText; + // if (nt.indexOf("subflow:") === 0) { + // helpText = RED.utils.renderMarkdown(RED.nodes.subflow(nt.substring(8)).info||"")||(''+RED._("sidebar.info.none")+''); + // } else { + // helpText = $("script[data-help-name='"+d.attr("data-palette-type")+"']").html()||(''+RED._("sidebar.info.none")+''); + // } + // // Don't look too closely. RED.sidebar.info.set will set the 'Description' + // // section of the sidebar. Pass in the title of the Help section so it looks + // // right. + // RED.sidebar.type.show(helpText,RED._("sidebar.info.nodeHelp")); + // }); var chart = $("#red-ui-workspace-chart"); var chartSVG = $("#red-ui-workspace-chart>svg").get(0); var activeSpliceLink; diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/projects/projects.js b/packages/node_modules/@node-red/editor-client/src/js/ui/projects/projects.js index 2fc561b9f..024a569e5 100755 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/projects/projects.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/projects/projects.js @@ -2314,6 +2314,7 @@ RED.projects = (function() { if (data.active) { $.getJSON("projects/"+data.active, function(project) { activeProject = project; + RED.events.emit("projects:load",activeProject); RED.sidebar.versionControl.refresh(true); if (done) { done(activeProject); diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/search.js b/packages/node_modules/@node-red/editor-client/src/js/ui/search.js index 9bb4cefb0..7be689c4a 100644 --- a/packages/node_modules/@node-red/editor-client/src/js/ui/search.js +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/search.js @@ -23,8 +23,7 @@ RED.search = (function() { var visible = false; var index = {}; - var keys = []; - var results = []; + var currentResults = []; var previousActiveElement; @@ -66,23 +65,9 @@ RED.search = (function() { } } - function indexWorkspace() { - index = {}; - RED.nodes.eachWorkspace(indexNode); - RED.nodes.eachSubflow(indexNode); - RED.nodes.eachConfig(indexNode); - RED.nodes.eachNode(indexNode); - keys = Object.keys(index); - keys.sort(); - keys.forEach(function(key) { - index[key] = Object.keys(index[key]).map(function(id) { - return index[key][id]; - }) - }) - } - function search(val) { - searchResults.editableList('empty'); + var results = []; + var keys = Object.keys(index); var typeFilter; var m = /(?:^| )type:([^ ]+)/.exec(val); if (m) { @@ -92,8 +77,7 @@ RED.search = (function() { val = val.trim(); - selected = -1; - results = []; + if (val.length > 0 || typeFilter) { val = val.toLowerCase(); var i; @@ -104,10 +88,14 @@ RED.search = (function() { var key = keys[i]; var kpos = keys[i].indexOf(val); if (kpos > -1) { - for (j=0;j 0) { - for (i=0;i 25) { - searchResults.editableList('addItem', { - more: { - results: results, - start: 25 - } - }) - } - } else { - searchResults.editableList('addItem',{}); - } } + return results; } function ensureSelectedIsVisible() { @@ -161,13 +135,37 @@ RED.search = (function() { searchInput = $('').appendTo(searchDiv).searchBox({ delay: 200, change: function() { - search($(this).val()); + searchResults.editableList('empty'); + selected = -1; + currentResults = search($(this).val()); + if (currentResults.length > 0) { + for (i=0;i 25) { + searchResults.editableList('addItem', { + more: { + results: currentResults, + start: 25 + } + }) + } + } else { + searchResults.editableList('addItem',{}); + } + + } }); + var copySearchContainer = $('').appendTo(searchDiv).on('click', function(evt) { + evt.preventDefault(); + RED.sidebar.info.outliner.search(searchInput.val()) + hide(); + }); searchInput.on('keydown',function(evt) { var children; - if (results.length > 0) { + if (currentResults.length > 0) { if (evt.keyCode === 40) { // Down children = searchResults.children(); @@ -199,21 +197,21 @@ RED.search = (function() { var object = $(children[selected]).find(".red-ui-editableList-item-content").data('data'); if (object) { searchResults.editableList('removeItem',object); - for (i=object.more.start;i object.more.start+25) { + if (currentResults.length > object.more.start+25) { searchResults.editableList('addItem', { more: { - results: results, + results: currentResults, start: object.more.start+25 } }) } } } else { - if (results.length > 0) { - reveal(results[Math.max(0,selected)].node); + if (currentResults.length > 0) { + reveal(currentResults[Math.max(0,selected)].node); } } } @@ -234,13 +232,13 @@ RED.search = (function() { div.on("click", function(evt) { evt.preventDefault(); searchResults.editableList('removeItem',object); - for (i=object.more.start;i object.more.start+25) { + if (currentResults.length > object.more.start+25) { searchResults.editableList('addItem', { more: { - results: results, + results: currentResults, start: object.more.start+25 } }) @@ -253,17 +251,7 @@ RED.search = (function() { var def = node._def; div = $('',{href:'#',class:"red-ui-search-result"}).appendTo(container); - var nodeDiv = $('

    ',{class:"red-ui-search-result-node"}).appendTo(div); - var colour = RED.utils.getNodeColor(node.type,def); - var icon_url = RED.utils.getNodeIcon(def,node); - if (node.type === 'tab') { - colour = "#C0DEED"; - } - nodeDiv.css('backgroundColor',colour); - - var iconContainer = $('
    ',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv); - RED.utils.createIconElement(icon_url, iconContainer, true); - + RED.utils.createNodeIcon(node).appendTo(div); var contentDiv = $('
    ',{class:"red-ui-search-result-node-description"}).appendTo(div); if (node.z) { var workspace = RED.nodes.workspace(node.z); @@ -308,7 +296,7 @@ RED.search = (function() { $("#red-ui-palette-shade").show(); $("#red-ui-sidebar-shade").show(); $("#red-ui-sidebar-separator").hide(); - indexWorkspace(); + if (dialog === null) { createDialog(); } @@ -342,6 +330,28 @@ RED.search = (function() { } } + function clearIndex() { + index = {}; + } + + function addItemToIndex(item) { + indexNode(item); + } + function removeItemFromIndex(item) { + var keys = Object.keys(index); + for (var i=0,l=keys.length;i", {class:"red-ui-sidebar-header red-ui-info-toolbar"}).appendTo(content); + $('').appendTo(toolbar) + var showTOCButton = toolbar.find('#red-ui-sidebar-help-show-toc') + RED.popover.tooltip(showTOCButton,RED._("sidebar.help.showTopics")); + showTOCButton.on("click",function(e) { + e.preventDefault(); + if ($(this).hasClass('selected')) { + hideTOC(); + } else { + showTOC(); + } + }); + + var stackContainer = $("
    ",{class:"red-ui-sidebar-help-stack"}).appendTo(content); + + tocPanel = $("
    ", {class: "red-ui-sidebar-help-toc"}).appendTo(stackContainer); + var helpPanel = $("
    ").css({ + "overflow-y": "scroll" + }).appendTo(stackContainer); + + panels = RED.panels.create({ + container: stackContainer + }) + panels.ratio(0.5); + + helpSearch = $('').appendTo(toolbar).searchBox({ + delay: 100, + change: function() { + var val = $(this).val().toLowerCase(); + if (val) { + showTOC(); + var c = treeList.treeList('filter',function(item) { + if (item.depth === 0) { + return true; + } + return (item.nodeType && item.nodeType.indexOf(val) > -1) || + (item.subflowLabel && item.subflowLabel.indexOf(val) > -1) + },true) + } else { + treeList.treeList('filter',null); + var selected = treeList.treeList('selected'); + if (selected.id) { + treeList.treeList('show',selected.id); + } + + } + } + }) + + helpSection = $("
    ",{class:"red-ui-help"}).css({ + "padding":"6px", + }).appendTo(helpPanel) + + $(''+RED._("sidebar.help.noHelp")+'').appendTo(helpSection); + + treeList = $("
    ").css({width: "100%"}).appendTo(tocPanel).treeList({data: []}) + treeList.on('treelistselect', function(e,item) { + if (item.nodeType) { + showHelp(item.nodeType); + } + }) + + RED.sidebar.addTab({ + id: "help", + label: RED._("sidebar.help.label"), + name: RED._("sidebar.help.name"), + iconClass: "fa fa-book", + action:"core:show-help-tab", + content: content, + pinned: true, + enableOnEdit: true, + onchange: function() { + resizeStack() + } + }); + + $(window).on("resize", resizeStack); + $(window).on("focus", resizeStack); + + RED.events.on('registry:node-type-added', queueRefresh); + RED.events.on('registry:node-type-removed', queueRefresh); + RED.events.on('subflows:change', refreshSubflow); + + RED.actions.add("core:show-help-tab",show); + + } + + var refreshTimer; + function queueRefresh() { + if (!refreshTimer) { + refreshTimer = setTimeout(function() { + refreshTimer = null; + refreshHelpIndex(); + },500); + } + } + + function refreshSubflow(sf) { + var item = treeList.treeList('get',"node-type:subflow:"+sf.id); + item.subflowLabel = sf._def.label().toLowerCase(); + item.treeList.replaceElement(getNodeLabel({_def:sf._def,type:sf._def.label()})); + } + + function hideTOC() { + var tocButton = $('#red-ui-sidebar-help-show-toc') + if (tocButton.hasClass('selected')) { + tocButton.removeClass('selected'); + panelRatio = panels.ratio(); + tocPanel.css({"transition":"height 0.2s"}) + panels.ratio(0) + setTimeout(function() { + tocPanel.css({"transition":""}) + },250); + } + } + function showTOC() { + var tocButton = $('#red-ui-sidebar-help-show-toc') + if (!tocButton.hasClass('selected')) { + tocButton.addClass('selected'); + tocPanel.css({"transition":"height 0.2s"}) + panels.ratio(Math.max(0.3,Math.min(panelRatio,0.7))); + setTimeout(function() { + tocPanel.css({"transition":""}) + var selected = treeList.treeList('selected'); + if (selected.id) { + treeList.treeList('show',selected); + } + },250); + } + } + + function refreshHelpIndex() { + helpTopics = []; + var modules = RED.nodes.registry.getModuleList(); + var moduleNames = Object.keys(modules); + moduleNames.sort(); + + var helpData = [{ + label: RED._("sidebar.help.nodeHelp"), + children: [], + expanded: true + }] + + var subflows = RED.nodes.registry.getNodeTypes().filter(function(t) {return /subflow/.test(t)}); + if (subflows.length > 0) { + helpData[0].children.push({ + label: RED._("menu.label.subflows"), + children: [] + }) + subflows.forEach(function(nodeType) { + var sf = RED.nodes.getType(nodeType); + helpData[0].children[0].children.push({ + id:"node-type:"+nodeType, + nodeType: nodeType, + subflowLabel: sf.label().toLowerCase(), + element: getNodeLabel({_def:sf,type:sf.label()}) + }) + }) + } + + + moduleNames.forEach(function(moduleName) { + var module = modules[moduleName]; + var nodeTypes = []; + + var setNames = Object.keys(module.sets); + setNames.forEach(function(setName) { + module.sets[setName].types.forEach(function(nodeType) { + if ($("script[data-help-name='"+nodeType+"']").length) { + nodeTypes.push({ + id: "node-type:"+nodeType, + nodeType: nodeType, + element:getNodeLabel({_def:RED.nodes.getType(nodeType),type:nodeType}) + }) + } + }) + }) + if (nodeTypes.length > 0) { + nodeTypes.sort(function(A,B) { + return A.nodeType.localeCompare(B.nodeType) + }) + helpData[0].children.push({ + id: moduleName, + icon: "fa fa-cube", + label: moduleName, + children: nodeTypes + }) + } + }); + treeList.treeList("data",helpData); + } + + function getNodeLabel(n) { + var div = $('
    ',{class:"red-ui-info-outline-item"}); + RED.utils.createNodeIcon(n).appendTo(div); + var contentDiv = $('
    ',{class:"red-ui-search-result-description"}).appendTo(div); + $('
    ',{class:"red-ui-search-result-node-label red-ui-info-outline-item-label"}).text(n.name||n.type).appendTo(contentDiv); + return div; + } + + function showHelp(nodeType) { + helpSection.empty(); + var helpText; + var title; + var m = /^subflow(:(.+))?$/.exec(nodeType); + if (m && m[2]) { + var subflowNode = RED.nodes.subflow(m[2]); + helpText = (RED.utils.renderMarkdown(subflowNode.info||"")||(''+RED._("sidebar.info.none")+'')); + title = subflowNode.name || nodeType; + } else { + helpText = $("script[data-help-name='"+nodeType+"']").html()||(''+RED._("sidebar.info.none")+''); + title = nodeType; + } + setInfoText(title, helpText, helpSection); + + var ratio = panels.ratio(); + if (ratio > 0.7) { + panels.ratio(0.7) + } + treeList.treeList("select","node-type:"+nodeType, false); + + } + + function show(type) { + RED.sidebar.show("help"); + if (type) { + hideTOC(); + showHelp(type); + } + } + + // TODO: DRY - projects.js + function addTargetToExternalLinks(el) { + $(el).find("a").each(function(el) { + var href = $(this).attr('href'); + if (/^https?:/.test(href)) { + $(this).attr('target','_blank'); + } + }); + return el; + } + + function setInfoText(title, infoText,target) { + if (title) { + $("

    ",{class:"red-ui-help-title"}).text(title).appendTo(target); + } + var info = addTargetToExternalLinks($('
    '+infoText+'
    ')).appendTo(target); + info.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "" ); + var foldingHeader = "H3"; + info.find(foldingHeader).wrapInner('') + .find("a").prepend('').on("click", function(e) { + e.preventDefault(); + var isExpanded = $(this).hasClass('expanded'); + var el = $(this).parent().next(); + while(el.length === 1 && el[0].nodeName !== foldingHeader) { + el.toggle(!isExpanded); + el = el.next(); + } + $(this).toggleClass('expanded',!isExpanded); + }) + target.parent().scrollTop(0); + } + + function set(html,title) { + $(helpSection).empty(); + setInfoText(title,html,helpSection); + hideTOC(); + show(); + } + + function refreshSelection(selection) { + if (selection === undefined) { + selection = RED.view.selection(); + } + if (selection.nodes) { + if (selection.nodes.length == 1) { + var node = selection.nodes[0]; + if (node.type === "subflow" && node.direction) { + // ignore subflow virtual ports + } else if (node.type !== 'group'){ + showHelp(node.type); + } + } else { + refresh(selection.nodes); + } + } + } + RED.events.on("view:selection-changed",refreshSelection); + + return { + init: init, + show: show, + set: set + } +})(); 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 new file mode 100644 index 000000000..ec06808e7 --- /dev/null +++ b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-info-outliner.js @@ -0,0 +1,405 @@ +RED.sidebar.info.outliner = (function() { + + var treeList; + var searchInput; + var projectInfo; + var projectInfoLabel; + var flowList; + var subflowList; + var globalConfigNodes; + + var objects = {}; + + function getFlowData() { + var flowData = [ + { + label: RED._("menu.label.flows"), + expanded: true, + children: [] + }, + { + label: RED._("menu.label.subflows"), + children: [] + }, + { + id: "__global__", + label: RED._("sidebar.info.globalConfig"), + children: [] + } + ] + flowList = flowData[0]; + subflowList = flowData[1]; + globalConfigNodes = flowData[2]; + + return flowData; + } + + function getProjectLabel(p) { + var div = $('
    ',{class:"red-ui-info-outline-item red-ui-info-outline-item-flow"}); + div.css("width", "calc(100% - 40px)"); + var contentDiv = $('
    ',{class:"red-ui-search-result-description red-ui-info-outline-item-label"}).appendTo(div); + contentDiv.text(p.name); + var controls = $('
    ',{class:"red-ui-info-outline-item-controls"}).appendTo(div); + var editProjectButton = $('') + .appendTo(controls) + .on("click", function(evt) { + evt.preventDefault(); + RED.projects.editProject(); + }); + RED.popover.tooltip(editProjectButton,RED._('sidebar.project.showProjectSettings')); + return div; + } + + var empties = {}; + function getEmptyItem(id) { + var item = { + empty: true, + element: $('
    ').text("empty") + } + empties[id] = item; + return item; + } + + function getNodeLabelText(n) { + var label = n.name || n.id; + if (n._def.label) { + try { + label = (typeof n._def.label === "function" ? n._def.label.call(n) : n._def.label)||""; + } catch(err) { + console.log("Definition error: "+type+".label",err); + } + } + return label; + } + + function getNodeLabel(n) { + var div = $('
    ',{class:"red-ui-info-outline-item"}); + RED.utils.createNodeIcon(n).appendTo(div); + var contentDiv = $('
    ',{class:"red-ui-search-result-description"}).appendTo(div); + var labelText = getNodeLabelText(n); + var label = $('
    ',{class:"red-ui-search-result-node-label red-ui-info-outline-item-label"}).appendTo(contentDiv); + if (labelText) { + label.text(labelText) + } else { + label.html(" ") + } + + addControls(n, div); + + return div; + } + + function getFlowLabel(n) { + var div = $('
    ',{class:"red-ui-info-outline-item red-ui-info-outline-item-flow"}); + var contentDiv = $('
    ',{class:"red-ui-search-result-description red-ui-info-outline-item-label"}).appendTo(div); + contentDiv.text(typeof n === "string"? n : n.label); + addControls(n, div); + return div; + } + + function getSubflowLabel(n) { + + var div = $('
    ',{class:"red-ui-info-outline-item"}); + RED.utils.createNodeIcon(n).appendTo(div); + var contentDiv = $('
    ',{class:"red-ui-search-result-description"}).appendTo(div); + var labelText = getNodeLabelText(n); + var label = $('
    ',{class:"red-ui-search-result-node-label red-ui-info-outline-item-label"}).appendTo(contentDiv); + if (labelText) { + label.text(labelText) + } else { + label.html(" ") + } + + addControls(n, div); + + return div; + + + // var div = $('
    ',{class:"red-ui-info-outline-item red-ui-info-outline-item-flow"}); + // var contentDiv = $('
    ',{class:"red-ui-search-result-description red-ui-info-outline-item-label"}).appendTo(div); + // contentDiv.text(n.name || n.id); + // addControls(n, div); + // return div; + } + + function addControls(n,div) { + if (n.type === 'group') { + return; + } + var controls = $('
    ',{class:"red-ui-info-outline-item-controls red-ui-info-outline-item-hover-controls"}).appendTo(div); + if (n._def.button) { + $('').appendTo(controls).on("click",function(evt) { + evt.preventDefault(); + evt.stopPropagation(); + RED.view.clickNodeButton(n); + }) + } + + + if (n.type !== 'group') { + $('').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(); + evt.stopPropagation(); + if (n.type === 'tab') { + if (n.disabled) { + RED.workspaces.enable(n.id) + } else { + RED.workspaces.disable(n.id) + } + } else { + // TODO: this ought to be a utility function in RED.nodes + var historyEvent = { + t: "edit", + node: n, + changed: n.changed, + changes: { + d: n.d + }, + dirty:RED.nodes.dirty() + } + if (n.d) { + delete n.d; + } else { + n.d = true; + } + n.dirty = true; + n.changed = true; + RED.events.emit("nodes:change",n); + RED.nodes.dirty(true) + RED.view.redraw(); + } + }); + } else { + $('
    ').appendTo(controls) + } + controls.find("button").on("dblclick", function(evt) { + evt.preventDefault(); + evt.stopPropagation(); + }) + } + + function onProjectLoad(activeProject) { + objects = {}; + var newFlowData = getFlowData(); + projectInfoLabel.empty(); + getProjectLabel(activeProject).appendTo(projectInfoLabel); + projectInfo.show(); + treeList.treeList('data',newFlowData); + } + + function build() { + var container = $("
    ", {class:"red-ui-info-outline"}).css({'height': '100%'}); + var toolbar = $("
    ", {class:"red-ui-sidebar-header red-ui-info-toolbar"}).appendTo(container); + + searchInput = $('').appendTo(toolbar).searchBox({ + delay: 300, + change: function() { + var val = $(this).val(); + var searchResults = RED.search.search(val); + if (val) { + var resultMap = {}; + for (var i=0,l=searchResults.length;i
    ').hide().appendTo(container) + projectInfoLabel = $('').appendTo(projectInfo); + + //
    Space Monkey
    ').appendTo(container) + + 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); + + RED.events.on("workspace:clear", onWorkspaceClear) + + return container; + } + function onWorkspaceClear() { + treeList.treeList('data',getFlowData()); + } + 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: getNodeLabel(sf), + children:[getEmptyItem(sf.id)], + deferBuild: true + } + subflowList.treeList.addChild(objects[sf.id]) + } + function onSubflowChange(sf) { + var existingObject = objects[sf.id]; + existingObject.treeList.replaceElement(getNodeLabel(sf)); + // existingObject.element.find(".red-ui-info-outline-item-label").text(n.name || n.id); + RED.nodes.eachNode(function(n) { + if (n.type == "subflow:"+sf.id) { + var sfInstance = objects[n.id]; + sfInstance.treeList.replaceElement(getNodeLabel(n)); + } + }); + } + + 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'); + } + + return { + build: build, + search: function(val) { + searchInput.searchBox('value',val) + }, + reveal: function(node) { + treeList.treeList('select', 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 39683e41e..5d548103e 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 @@ -16,16 +16,32 @@ RED.sidebar.info = (function() { var content; - var sections; - var propertiesSection; + var panels; var infoSection; - var helpSection; + + var propertiesPanelContent; + var propertiesPanelHeader; + var propertiesPanelHeaderIcon; + var propertiesPanelHeaderLabel; + var propertiesPanelHeaderReveal; + var propertiesPanelHeaderHelp; + + var selectedObject; + + var tipContainer; var tipBox; + // TODO: remove this var expandedSections = { "property": false }; + function resizeStack() { + if (panels) { + var h = $(content).parent().height() - tipContainer.outerHeight(); + panels.resize(h) + } + } function init() { content = document.createElement("div"); @@ -35,31 +51,78 @@ RED.sidebar.info = (function() { var stackContainer = $("
    ",{class:"red-ui-sidebar-info-stack"}).appendTo(content); - sections = RED.stack.create({ - container: stackContainer - }).hide(); + var outlinerPanel = $("
    ").css({ + "overflow": "hidden", + "height": "calc(70%)" + }).appendTo(stackContainer); + var propertiesPanel = $("
    ").css({ + "overflow":"hidden", + "height":"100%", + "display": "flex", + "flex-direction": "column" + }).appendTo(stackContainer); + propertiesPanelHeader = $("
    ", {class:"red-ui-palette-header red-ui-info-header"}).css({ + "flex":"0 0 auto" + }).appendTo(propertiesPanel); - propertiesSection = sections.add({ - title: RED._("sidebar.info.info"), - collapsible: true + propertiesPanelHeaderIcon = $("").appendTo(propertiesPanelHeader); + propertiesPanelHeaderLabel = $("").appendTo(propertiesPanelHeader); + propertiesPanelHeaderHelp = $('').css({ + position: 'absolute', + top: '12px', + right: '38px' + }).on("click", function(evt) { + evt.preventDefault(); + evt.stopPropagation(); + if (selectedObject) { + RED.sidebar.help.show(selectedObject.type) + } + }).appendTo(propertiesPanelHeader); + RED.popover.tooltip(propertiesPanelHeaderHelp,RED._("sidebar.help.showHelp")); + + + propertiesPanelHeaderReveal = $('').css({ + position: 'absolute', + top: '12px', + right: '8px' + }).on("click", function(evt) { + evt.preventDefault(); + evt.stopPropagation(); + if (selectedObject) { + RED.sidebar.info.outliner.reveal(selectedObject); + } + }).appendTo(propertiesPanelHeader); + RED.popover.tooltip(propertiesPanelHeaderReveal,"Show in outline"); + + + propertiesPanelContent = $("
    ").css({ + "flex":"1 1 auto", + "overflow-y":"scroll", + }).appendTo(propertiesPanel); + + + panels = RED.panels.create({container: stackContainer}) + panels.ratio(0.6); + RED.sidebar.info.outliner.build().appendTo(outlinerPanel); + + + RED.sidebar.addTab({ + id: "info", + label: RED._("sidebar.info.label"), + name: RED._("sidebar.info.name"), + iconClass: "fa fa-info", + action:"core:show-info-tab", + content: content, + pinned: true, + enableOnEdit: true }); - propertiesSection.expand(); - infoSection = sections.add({ - title: RED._("sidebar.info.desc"), - collapsible: true - }); - infoSection.expand(); - infoSection.content.css("padding","6px"); + $(window).on("resize", resizeStack); + $(window).on("focus", resizeStack); - helpSection = sections.add({ - title: RED._("sidebar.info.nodeHelp"), - collapsible: true - }); - helpSection.expand(); - helpSection.content.css("padding","6px"); - var tipContainer = $('
    ').appendTo(content); + // Tip Box + tipContainer = $('
    ').appendTo(content); tipBox = $('
    ').appendTo(tipContainer); var tipButtons = $('
    ').appendTo(tipContainer); @@ -75,17 +138,6 @@ RED.sidebar.info = (function() { RED.actions.invoke("core:toggle-show-tips"); RED.notify(RED._("sidebar.info.showTips")); }); - - RED.sidebar.addTab({ - id: "info", - label: RED._("sidebar.info.label"), - name: RED._("sidebar.info.name"), - iconClass: "fa fa-info", - action:"core:show-info-tab", - content: content, - pinned: true, - enableOnEdit: true - }); if (tips.enabled()) { tips.start(); } else { @@ -113,42 +165,29 @@ RED.sidebar.info = (function() { refreshSelection(); return; } - sections.show(); - $(propertiesSection.content).empty(); - $(infoSection.content).empty(); - $(helpSection.content).empty(); - infoSection.title.text(RED._("sidebar.info.desc")); + $(propertiesPanelContent).empty(); var propRow; - var table = $('
    ').appendTo(propertiesSection.content); + var table = $('
    ').appendTo(propertiesPanelContent); var tableBody = $('').appendTo(table); var subflowNode; var subflowUserCount; - var activeProject = RED.projects.getActiveProject(); - if (activeProject) { - propRow = $(''+ RED._("sidebar.project.name") + '').appendTo(tableBody); - $(propRow.children()[1]).text(activeProject.name||""); - $('').appendTo(tableBody); - var editProjectButton = $('') - .appendTo(propRow.children()[1]) - .on("click", function(evt) { - evt.preventDefault(); - RED.projects.editProject(); - }); - RED.popover.tooltip(editProjectButton,RED._('sidebar.project.showProjectSettings')); - } - propertiesSection.container.show(); - infoSection.container.show(); - helpSection.container.show(); if (node === null) { return; } else if (Array.isArray(node)) { // Multiple things selected // - hide help and info sections + propertiesPanelHeaderIcon.empty(); + RED.utils.createNodeIcon({type:"_selection_"}).appendTo(propertiesPanelHeaderIcon); + propertiesPanelHeaderLabel.text("Selection"); + propertiesPanelHeaderReveal.hide(); + propertiesPanelHeaderHelp.hide(); + selectedObject = null; + var types = { nodes:0, flows:0, @@ -167,8 +206,7 @@ RED.sidebar.info = (function() { types.nodes++; } }); - helpSection.container.hide(); - infoSection.container.hide(); + // infoSection.container.hide(); // - show the count of selected nodes propRow = $(''+RED._("sidebar.info.selection")+"").appendTo(tableBody); @@ -189,10 +227,10 @@ RED.sidebar.info = (function() { // A single 'thing' selected. // Check to see if this is a subflow or subflow instance - var m = /^subflow(:(.+))?$/.exec(node.type); - if (m) { - if (m[2]) { - subflowNode = RED.nodes.subflow(m[2]); + var subflowRegex = /^subflow(:(.+))?$/.exec(node.type); + if (subflowRegex) { + if (subflowRegex[2]) { + subflowNode = RED.nodes.subflow(subflowRegex[2]); } else { subflowNode = node; } @@ -205,25 +243,21 @@ RED.sidebar.info = (function() { } }); } + + propertiesPanelHeaderIcon.empty(); + RED.utils.createNodeIcon(node).appendTo(propertiesPanelHeaderIcon); + propertiesPanelHeaderLabel.text(RED.utils.getNodeLabel(node, node.type+" "+node.id)); + propertiesPanelHeaderReveal.show(); + selectedObject = node; + if (node.type === "tab" || node.type === "subflow") { // If nothing is selected, but we're on a flow or subflow tab. - propRow = $(''+RED._("sidebar.info."+(node.type==='tab'?'flow':'subflow'))+'').appendTo(tableBody); - RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]); - propRow = $(''+RED._("sidebar.info.tabName")+"").appendTo(tableBody); - $(propRow.children()[1]).text(node.label||node.name||""); - if (node.type === "tab") { - propRow = $(''+RED._("sidebar.info.status")+'').appendTo(tableBody); - $(propRow.children()[1]).text((!!!node.disabled)?RED._("sidebar.info.enabled"):RED._("sidebar.info.disabled")) - } + propertiesPanelHeaderHelp.hide(); } else if (node.type === "group") { - // An actual node is selected in the editor - build up its properties table - propRow = $(''+RED._("sidebar.info.group")+"").appendTo(tableBody); - RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]); - if (node.name) { - propRow = $(''+RED._("common.label.name")+'').appendTo(tableBody); - $('').text(node.name).appendTo(propRow.children()[1]); - } - propRow = $(' ').appendTo(tableBody); + propertiesPanelHeaderHelp.hide(); + + propRow = $(''+RED._("sidebar.info.group")+'').appendTo(tableBody); + var typeCounts = { nodes:0, groups: 0 @@ -246,22 +280,30 @@ RED.sidebar.info = (function() { } else { - // An actual node is selected in the editor - build up its properties table - propRow = $(''+RED._("sidebar.info.node")+"").appendTo(tableBody); - RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]); - if (node.type !== "subflow" && node.type !== "unknown" && node.name) { - propRow = $(''+RED._("common.label.name")+'').appendTo(tableBody); - $('').text(node.name).appendTo(propRow.children()[1]); + propertiesPanelHeaderHelp.show (); + + propRow = $('').appendTo(tableBody); + + if (!subflowRegex) { + $(propRow.children()[0]).text(RED._("sidebar.info.node")) + } else { + $(propRow.children()[0]).text(RED._("sidebar.info.subflow")) } - if (!m) { - propRow = $(''+RED._("sidebar.info.type")+"").appendTo(tableBody); + RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]); + + if (!subflowRegex) { + propRow = $(''+RED._("sidebar.info.type")+'').appendTo(tableBody); $(propRow.children()[1]).text((node.type === "unknown")?node._orig.type:node.type); if (node.type === "unknown") { $('').prependTo($(propRow.children()[1])) } } + var count = 0; - if (!m && node.type != "subflow" && node.type != "group") { + if (!subflowRegex && node.type != "subflow" && node.type != "group") { + + var blankRow = $('').appendTo(tableBody); + var defaults; if (node.type === 'unknown') { defaults = {}; @@ -276,7 +318,6 @@ RED.sidebar.info = (function() { $(propRow.children()[1]).text(RED.nodes.getType(node.type).set.module); count++; } - $('').appendTo(tableBody); if (defaults) { for (var n in defaults) { @@ -284,7 +325,8 @@ RED.sidebar.info = (function() { var val = node[n]; var type = typeof val; count++; - propRow = $(''+n+"").appendTo(tableBody); + propRow = $('').appendTo(tableBody); + $(propRow.children()[0]).text(n); if (defaults[n].type) { var configNode = RED.nodes.node(val); if (!configNode) { @@ -314,37 +356,35 @@ RED.sidebar.info = (function() { } } if (count > 0) { - $(''+RED._("sidebar.info.showMore")+''+RED._("sidebar.info.showLess")+' ').appendTo(tableBody); + $(''+RED._("sidebar.info.showMore")+''+RED._("sidebar.info.showLess")+' ').appendTo(blankRow.children()[0]); } } if (node.type !== 'tab') { - if (m) { + if (subflowRegex) { $(''+RED._("sidebar.info.subflow")+'').appendTo(tableBody); $(''+RED._("common.label.name")+''+RED.utils.sanitize(subflowNode.name)+'').appendTo(tableBody); } } } - if (m) { + if (subflowRegex) { propRow = $(''+RED._("subflow.category")+'').appendTo(tableBody); var category = subflowNode.category||"subflows"; $(propRow.children()[1]).text(RED._("palette.label."+category,{defaultValue:category})) $(''+RED._("sidebar.info.instances")+""+subflowUserCount+'').appendTo(tableBody); } - var helpText = ""; - if (node.type === "tab" || node.type === "subflow") { - $(helpSection.container).hide(); - } else { - $(helpSection.container).show(); - if (subflowNode && node.type !== "subflow") { - // Selected a subflow instance node. - // - The subflow template info goes into help - helpText = (RED.utils.renderMarkdown(subflowNode.info||"")||(''+RED._("sidebar.info.none")+'')); - } else { - helpText = $("script[data-help-name='"+node.type+"']").html()||(''+RED._("sidebar.info.none")+''); - } - setInfoText(helpText, helpSection.content); - } + // var helpText = ""; + // if (node.type === "tab" || node.type === "subflow") { + // } else { + // if (subflowNode && node.type !== "subflow") { + // // Selected a subflow instance node. + // // - The subflow template info goes into help + // helpText = (RED.utils.renderMarkdown(subflowNode.info||"")||(''+RED._("sidebar.info.none")+'')); + // } else { + // helpText = $("script[data-help-name='"+node.type+"']").html()||(''+RED._("sidebar.info.none")+''); + // } + // setInfoText(helpText, helpSection.content); + // } var infoText = ""; @@ -356,7 +396,26 @@ RED.sidebar.info = (function() { if (node.info) { infoText = infoText + RED.utils.renderMarkdown(node.info || "") } - setInfoText(infoText, infoSection.content); + var infoSectionContainer = $("
    ").css("padding","0 6px 6px").appendTo(propertiesPanelContent) + + // var editInfo = $('').appendTo(infoSectionContainer).on("click", function(evt) { + // //.text(RED._("sidebar.info.editDescription")) + // evt.preventDefault(); + // evt.stopPropagation(); + // if (node.type === 'tab') { + // + // } else if (node.type === 'subflow') { + // + // } else if (node.type === 'group') { + // + // } else if (node._def.category !== 'config') { + // RED.editor.edit(node,"editor-tab-description"); + // } else { + // + // } + // }) + + setInfoText(infoText, infoSectionContainer); $(".red-ui-sidebar-info-stack").scrollTop(0); $(".node-info-property-header").on("click", function(e) { @@ -372,7 +431,7 @@ RED.sidebar.info = (function() { // propRow = $('Actions').appendTo(tableBody); // var actionBar = $(propRow.children()[1]); // - // // var actionBar = $('
    ',{style:"background: #fefefe; padding: 3px;"}).appendTo(propertiesSection.content); + // // var actionBar = $('
    ',{style:"background: #fefefe; padding: 3px;"}).appendTo(propertiesPanel); // $('').appendTo(actionBar); // $('').appendTo(actionBar); // $('').appendTo(actionBar); @@ -447,6 +506,7 @@ RED.sidebar.info = (function() { } function startTips() { $(".red-ui-sidebar-info").addClass('show-tips'); + resizeStack(); if (enabled) { if (!startTimeout && !refreshTimeout) { if (tipCount === -1) { @@ -460,6 +520,7 @@ RED.sidebar.info = (function() { } function stopTips() { $(".red-ui-sidebar-info").removeClass('show-tips'); + resizeStack(); clearInterval(refreshTimeout); clearTimeout(startTimeout); refreshTimeout = null; @@ -484,15 +545,8 @@ RED.sidebar.info = (function() { } function set(html,title) { - // tips.stop(); - // sections.show(); - refresh(null); - propertiesSection.container.hide(); - helpSection.container.hide(); - infoSection.container.show(); - infoSection.title.text(title||RED._("sidebar.info.desc")); - setInfoText(html,infoSection.content); - $(".red-ui-sidebar-info-stack").scrollTop(0); + console.warn("Deprecated use of RED.sidebar.info.set - use RED.sidebar.help.set instead") + RED.sidebar.help.set(html,title); } function refreshSelection(selection) { 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..e8306bd0f 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 @@ -806,9 +806,9 @@ RED.utils = (function() { function separateIconPath(icon) { var result = {module: "", file: ""}; if (icon) { - var index = icon.indexOf('icons/'); - if (index !== -1) { - icon = icon.substring(index+6); + var index = icon.indexOf(RED.settings.apiRootUrl+'icons/'); + if (index === 0) { + icon = icon.substring((RED.settings.apiRootUrl+'icons/').length); } index = icon.indexOf('/'); if (index !== -1) { @@ -859,10 +859,15 @@ RED.utils = (function() { } function getNodeIcon(def,node) { - if (def.category === 'config') { + if (node && node.type === '_selection_') { + return "font-awesome/fa-object-ungroup"; + } else 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" + return "red-ui-icons/red-ui-icons-flow" + // return RED.settings.apiRootUrl+"images/subflow_tab.svg" } else if (node && node.type === 'unknown') { return RED.settings.apiRootUrl+"icons/node-red/alert.svg" } else if (node && node.icon) { @@ -921,6 +926,8 @@ RED.utils = (function() { var l; if (node.type === 'tab') { l = node.label || defaultLabel + } else if (node.type === 'group') { + l = node.name || defaultLabel } else { l = node._def.label; try { @@ -1054,11 +1061,63 @@ RED.utils = (function() { } // If the specified name is not defined in font-awesome, show arrow-in icon. iconUrl = RED.settings.apiRootUrl+"icons/node-red/arrow-in.svg" + } else if (iconPath.module === "red-ui-icons") { + var redIconElement = $('').appendTo(iconContainer); + redIconElement.addClass("red-ui-palette-icon red-ui-icons " + iconPath.file); + return; } var imageIconElement = $('
    ',{class:"red-ui-palette-icon"}).appendTo(iconContainer); imageIconElement.css("backgroundImage", "url("+iconUrl+")"); } + function createNodeIcon(node) { + var def = node._def; + var nodeDiv = $('
    ',{class:"red-ui-search-result-node"}) + if (node.type === "_selection_") { + nodeDiv.addClass("red-ui-palette-icon-selection"); + } else if (node.type === "group") { + nodeDiv.addClass("red-ui-palette-icon-group"); + } else if (node.type === 'tab') { + nodeDiv.addClass("red-ui-palette-icon-flow"); + } else { + var colour = RED.utils.getNodeColor(node.type,def); + // if (node.type === 'tab') { + // colour = "#C0DEED"; + // } + nodeDiv.css('backgroundColor',colour); + var borderColor = getDarkerColor(colour); + if (borderColor !== colour) { + nodeDiv.css('border-color',borderColor) + } + } + + var icon_url = RED.utils.getNodeIcon(def,node); + var iconContainer = $('
    ',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv); + RED.utils.createIconElement(icon_url, iconContainer, true); + return nodeDiv; + } + + function getDarkerColor(c) { + var r,g,b; + if (/^#[a-f0-9]{6}$/i.test(c)) { + r = parseInt(c.substring(1, 3), 16); + g = parseInt(c.substring(3, 5), 16); + b = parseInt(c.substring(5, 7), 16); + } else if (/^#[a-f0-9]{3}$/i.test(c)) { + r = parseInt(c.substring(1, 2)+c.substring(1, 2), 16); + g = parseInt(c.substring(2, 3)+c.substring(2, 3), 16); + b = parseInt(c.substring(3, 4)+c.substring(3, 4), 16); + } else { + return c; + } + var l = 0.3 * r/255 + 0.59 * g/255 + 0.11 * b/255 ; + r = Math.max(0,r-50); + g = Math.max(0,g-50); + b = Math.max(0,b-50); + var s = ((r<<16) + (g<<8) + b).toString(16); + return '#'+'000000'.slice(0, 6-s.length)+s; + } + return { createObjectElement: buildMessageElement, getMessageProperty: getMessageProperty, @@ -1076,6 +1135,8 @@ RED.utils = (function() { parseContextKey: parseContextKey, createIconElement: createIconElement, sanitize: sanitize, - renderMarkdown: renderMarkdown + renderMarkdown: renderMarkdown, + createNodeIcon: createNodeIcon, + getDarkerColor: getDarkerColor } })(); 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 35bcbb4e6..d15ef09d4 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 @@ -3060,7 +3060,9 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); } function nodeButtonClicked(d) { if (mouse_mode === RED.state.SELECTING_NODE) { - d3.event.stopPropagation(); + if (d3.event) { + d3.event.stopPropagation(); + } return; } var activeWorkspace = RED.workspaces.active(); @@ -3087,7 +3089,9 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); } RED.notify(RED._("notification.warning", {message:RED._("notification.warnings.nodeActionDisabled")}),"warning"); } } - d3.event.preventDefault(); + if (d3.event) { + d3.event.preventDefault(); + } } function showTouchMenu(obj,pos) { @@ -4660,42 +4664,44 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); } RED.workspaces.show(id); } else { var node = RED.nodes.node(id); - if (node._def.category !== 'config' && node.z) { - node.highlighted = true; - node.dirty = true; - RED.workspaces.show(node.z); + if (node) { + if (node._def.category !== 'config' && node.z) { + 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]; + 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); - 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; - } - RED.view.redraw(); + 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); + chart.animate({ + scrollLeft: deltaX, + scrollTop: deltaY + },200); } - flashFunc(); + + 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(); + } + flashFunc(); + } + } else if (node._def.category === 'config') { + RED.sidebar.config.show(id); } - } else if (node._def.category === 'config') { - RED.sidebar.config.show(id); } } }, @@ -4776,6 +4782,11 @@ if (DEBUG_EVENTS) { console.warn("nodeMouseDown", mouse_mode,d); } scroll: function(x,y) { chart.scrollLeft(chart.scrollLeft()+x); chart.scrollTop(chart.scrollTop()+y) + }, + clickNodeButton: function(n) { + if (n._def.button) { + nodeButtonClicked(n); + } } }; })(); 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 7a5f7a86c..8bb0fde68 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 @@ -372,7 +372,9 @@ RED.workspaces = (function() { var changes = { disabled: workspace.disabled }; workspace.disabled = disabled; $("#red-ui-tab-"+(workspace.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!workspace.disabled); - $("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!workspace.disabled); + if (id === activeWorkspace) { + $("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!workspace.disabled); + } var historyEvent = { t: "edit", changes:changes, diff --git a/packages/node_modules/@node-red/editor-client/src/sass/colors.scss b/packages/node_modules/@node-red/editor-client/src/sass/colors.scss index d95f8516f..96be7b5ab 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/colors.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/colors.scss @@ -23,7 +23,7 @@ $primary-background: #f3f3f3;//#0ff; $secondary-background: #fff;//#ff0; $secondary-background-selected: #efefef;//#e9e900; $secondary-background-inactive: #f0f0f0;//#f0f000; -$secondary-background-hover: #ddd;//#dd0; +$secondary-background-hover: #e6e6e6;//#dd0; $secondary-background-disabled: #f9f9f9;//#fafa0; $tertiary-background: #f7f7f7;//#f0f; @@ -94,7 +94,7 @@ $list-item-secondary-color: $secondary-text-color; $list-item-background: $secondary-background; $list-item-background-disabled: $secondary-background-inactive; $list-item-background-hover: $secondary-background-hover; -$list-item-background-selected: $secondary-background-selected; +$list-item-background-selected: #ffebc7; // #fff1e5; $list-item-border-selected: $secondary-text-color-selected; $tab-text-color-active: $header-text-color; diff --git a/packages/node_modules/@node-red/editor-client/src/sass/editor.scss b/packages/node_modules/@node-red/editor-client/src/sass/editor.scss index 4614d83fa..d8ef3e89c 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/editor.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/editor.scss @@ -304,9 +304,6 @@ button.red-ui-button-small &:first-child { padding: 20px 20px 0; } - &:last-child { - padding-bottom: 20px; - } } } .red-ui-editor-type-expression-tab-content { diff --git a/packages/node_modules/@node-red/editor-client/src/sass/palette.scss b/packages/node_modules/@node-red/editor-client/src/sass/palette.scss index ea4b06c52..922a31e33 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/palette.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/palette.scss @@ -186,6 +186,21 @@ background-size: contain; background-repeat: no-repeat; } +.red-ui-search-result-node { + &.red-ui-palette-icon-flow, + &.red-ui-palette-icon-group, + &.red-ui-palette-icon-selection { + 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-palette-icon-fa { color: white; position: absolute; diff --git a/packages/node_modules/@node-red/editor-client/src/sass/panels.scss b/packages/node_modules/@node-red/editor-client/src/sass/panels.scss index 9f99db5d4..455aab891 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/panels.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/panels.scss @@ -22,9 +22,19 @@ // border: 1px solid red; box-sizing: border-box; } + display: flex; + flex-direction: column; + + >.red-ui-panel:first-child { + flex: 0 0 auto; + } + >.red-ui-panel:last-child { + flex: 1 1 auto; + } } .red-ui-panels-separator { + flex: 0 0 auto; border-top: 1px solid $secondary-border-color; border-bottom: 1px solid $secondary-border-color; height: 7px; @@ -37,10 +47,13 @@ .red-ui-panel { overflow: auto; height: calc(50% - 4px); + position: relative; } .red-ui-panels.red-ui-panels-horizontal { height: 100%; + flex-direction: row; + &>.red-ui-panel { vertical-align: top; display: inline-block; diff --git a/packages/node_modules/@node-red/editor-client/src/sass/popover.scss b/packages/node_modules/@node-red/editor-client/src/sass/popover.scss index 95097a30e..872f32024 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/popover.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/popover.scss @@ -150,6 +150,16 @@ .red-ui-popover a.red-ui-button, .red-ui-popover button.red-ui-button { + &:not(.primary) { + border-color: $popover-button-border-color; + background: $popover-background; + color: $popover-color !important; + } + &:not(.primary):not(.disabled):not(.ui-button-disabled):hover { + border-color: $popover-button-border-color-hover; + } + + &.primary { border-color: $popover-button-border-color; } 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..27ebb1a04 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 @@ -24,6 +24,13 @@ top: 0px; border: 1px solid $primary-border-color; box-shadow: 0 0 10px $shadow; + background: $secondary-background; + + .red-ui-searchBox-container { + display: inline-block; + margin-right: 6px; + width: calc(100% - 30px); + } } .red-ui-type-search { @@ -87,6 +94,8 @@ } .red-ui-palette-icon { width: 15px; + position:relative; + left: -1px; } .red-ui-search-result-description { margin-left:28px; @@ -153,7 +162,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/style.scss b/packages/node_modules/@node-red/editor-client/src/sass/style.scss index 088e5c1b8..ca572ea46 100644 --- a/packages/node_modules/@node-red/editor-client/src/sass/style.scss +++ b/packages/node_modules/@node-red/editor-client/src/sass/style.scss @@ -42,6 +42,7 @@ @import "tab-config"; @import "tab-context"; @import "tab-info"; +@import "tab-help"; @import "popover"; @import "flow"; @import "palette-editor"; diff --git a/packages/node_modules/@node-red/editor-client/src/sass/tab-help.scss b/packages/node_modules/@node-red/editor-client/src/sass/tab-help.scss new file mode 100644 index 000000000..fe4f9fb84 --- /dev/null +++ b/packages/node_modules/@node-red/editor-client/src/sass/tab-help.scss @@ -0,0 +1,27 @@ +.red-ui-sidebar-help-stack { + // height: calc(100% - 39px); +} +.red-ui-help-search { + border-bottom: 1px solid $secondary-border-color; +} + +.red-ui-sidebar-help-toc { + .red-ui-treeList-label { + font-size: 13px; + padding: 2px 0; + overflow: hidden; + white-space: nowrap; + } + +} +#red-ui-sidebar-help-show-toc { + i.fa-angle-right { + transition: all 0.2s ease-in-out; + } + &.selected { + i.fa-angle-right { + transform: rotate(90deg); + } + } + +} 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..2bd436b1c 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 @@ -14,9 +14,25 @@ * limitations under the License. **/ +.red-ui-sidebar-info { + height: 100%; +} .red-ui-sidebar-info hr { margin: 10px 0; } +.red-ui-info-header { + padding-left: 9px; + line-height: 21px; + cursor: default; + > * { + vertical-align: middle + } + > span { + display: inline-block; + margin-left: 5px; + } + border-bottom: 1px solid $secondary-border-color; +} table.red-ui-info-table { font-size: 14px; margin: 0 0 10px; @@ -125,6 +141,9 @@ div.red-ui-info-table { font-size: 1.296em; line-height: 1.3em; margin: 8px auto; + &.red-ui-help-title { + border-bottom: 1px solid $tertiary-border-color; + } } h2 { font-weight: 500; @@ -214,12 +233,13 @@ div.red-ui-info-table { } .red-ui-sidebar-info-stack { - position: absolute; - top: 0; - bottom: 0; - left: 0; - right: 0; - overflow-y: scroll; + height: 100%; + // position: absolute; + // top: 0; + // bottom: 0; + // left: 0; + // right: 0; + // overflow-y: scroll; } .red-ui-help-tips { display: none; @@ -227,20 +247,23 @@ div.red-ui-info-table { left:0; right:0; bottom: 0; - height: 150px; + height: 0; + transition: height 0.2s, padding 0.2s; box-sizing: border-box; border-top: 1px solid $secondary-border-color; background-color: $secondary-background; - padding: 20px; + padding: 0; box-shadow: 0 5px 20px 0px $shadow; overflow-y: auto; } .red-ui-sidebar-info.show-tips { .red-ui-sidebar-info-stack { - bottom: 150px; + height: calc(100% - 150px); } .red-ui-help-tips { display: block; + height: 150px; + padding: 20px; } } @@ -279,3 +302,210 @@ div.red-ui-info-table { border-radius: 4px; padding: 2px 4px 2px; } + +.red-ui-info-outline,.red-ui-sidebar-help-toc { + display: flex; + flex-direction: column; + + .red-ui-treeList { + flex-grow: 1; + position: relative; + } + .red-ui-treeList-container { + position: absolute; + top: 0; + bottom: 0; + } + + .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-project { + border-bottom: 1px solid $secondary-border-color; + } + + .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 3px 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-toolbar { + min-height: 39px; + height: 39px; + box-sizing: border-box; + text-align: left; + // padding-left: 9px; + // box-sizing: border-box; + // background: $palette-header-background; + // border-bottom: 1px solid $secondary-border-color; + + .red-ui-searchBox-container { + position: absolute; + top: 6px; + right: 8px; + width: calc(100% - 150px); + max-width: 250px; + background: $palette-header-background; + input.red-ui-searchBox-input { + border: 1px solid $secondary-border-color; + border-radius: 3px; + font-size: 12px; + height: 26px; + } + input:focus.red-ui-searchBox-input { + border: 1px solid $secondary-border-color; + } + i.fa-search, i.fa-times { + top: 7px; + } + } + +}