RED.sidebar.info.outliner = (function() { var treeList; var searchInput; var projectInfo; var flowList; var subflowList; var globalConfigNodes; var objects = {}; var objectBacklog = {}; 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) { var newFlowData = getFlowData(); getProjectLabel(activeProject).appendTo(projectInfo); 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
').appendTo(container) //
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); // ["links","nodes","flows","subflows","groups"].forEach(function(t) { // ["add","remove","change"].forEach(function(v) { // RED.events.on(t+":"+v, function(n) { console.log(t+":"+v,n)}) // }) // }) // RED.events.on("workspace:clear", function() { console.log("workspace:clear")}) return container; } function onFlowAdd(ws) { objects[ws.id] = { id: ws.id, element: getFlowLabel(ws), children:[getEmptyItem(ws.id)], deferBuild: true, icon: "red-ui-icons red-ui-icons-flow" } flowList.treeList.addChild(objects[ws.id]) objects[ws.id].element.toggleClass("red-ui-info-outline-item-disabled", !!ws.disabled) objects[ws.id].treeList.container.toggleClass("red-ui-info-outline-item-disabled", !!ws.disabled) } function onFlowChange(n) { var existingObject = objects[n.id]; existingObject.element.find(".red-ui-info-outline-item-label").text(n.label || n.id); existingObject.element.toggleClass("red-ui-info-outline-item-disabled", !!n.disabled) existingObject.treeList.container.toggleClass("red-ui-info-outline-item-disabled", !!n.disabled) } function onFlowsReorder(order) { var indexMap = {}; order.forEach(function(id,index) { indexMap[id] = index; }) flowList.treeList.sortChildren(function(A,B) { if (A.id === "__global__") { return -1 } if (B.id === "__global__") { return 1 } return indexMap[A.id] - indexMap[B.id] }) } function onSubflowAdd(sf) { objects[sf.id] = { id: sf.id, element: 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'); // // console.log(selection); // if (selection.nodes) { // selection.nodes.forEach(function(n) { // // console.log("..",n.id); // treeList.treeList('show',n.id); // if (objects[n.id].treeList) { // objects[n.id].treeList.select(true); // } // // }); // } } return { build: build, search: function(val) { searchInput.searchBox('value',val) }, reveal: function(node) { treeList.treeList('select', objects[node.id]) } } })();