1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

Allow config nodes to be scoped to an individual Flow

This commit is contained in:
Nick O'Leary 2015-09-23 22:49:48 +01:00
parent da64c018ac
commit d96b6e77c0
22 changed files with 447 additions and 160 deletions

View File

@ -118,7 +118,6 @@ module.exports = function(grunt) {
"editor/js/ui/sidebar.js", "editor/js/ui/sidebar.js",
"editor/js/ui/palette.js", "editor/js/ui/palette.js",
"editor/js/ui/tab-info.js", "editor/js/ui/tab-info.js",
"editor/js/ui/tab-config.js",
"editor/js/ui/editor.js", "editor/js/ui/editor.js",
"editor/js/ui/clipboard.js", "editor/js/ui/clipboard.js",
"editor/js/ui/library.js", "editor/js/ui/library.js",

View File

@ -189,7 +189,7 @@ RED.history = (function() {
}); });
if (ev.node.type === 'subflow') { if (ev.node.type === 'subflow') {
$("#menu-item-workspace-menu-"+ev.node.id.replace(".","-")).text(ev.node.name); $("#menu-item-flow-menu-"+ev.node.id.replace(".","-")).text(ev.node.name);
} }
RED.palette.refresh(); RED.palette.refresh();

View File

@ -152,6 +152,9 @@ var RED = (function() {
statusEnabled = state; statusEnabled = state;
RED.view.status(statusEnabled); RED.view.status(statusEnabled);
} }
function toggleConfigNodes(state) {
RED.workspaces.toggleConfigNodes(state);
}
function loadEditor() { function loadEditor() {
RED.menu.init({id:"btn-sidemenu", RED.menu.init({id:"btn-sidemenu",
@ -161,6 +164,7 @@ var RED = (function() {
null null
]}, ]},
{id:"menu-item-status",label:RED._("menu.label.displayStatus"),toggle:true,onselect:toggleStatus, selected: true}, {id:"menu-item-status",label:RED._("menu.label.displayStatus"),toggle:true,onselect:toggleStatus, selected: true},
{id:"menu-item-config-nodes",label:RED._("menu.label.displayConfig"),toggle:true,onselect:toggleConfigNodes, selected: false},
null, null,
{id:"menu-item-import",label:RED._("menu.label.import"),options:[ {id:"menu-item-import",label:RED._("menu.label.import"),options:[
{id:"menu-item-import-clipboard",label:RED._("menu.label.clipboard"),onselect:RED.clipboard.import}, {id:"menu-item-import-clipboard",label:RED._("menu.label.clipboard"),onselect:RED.clipboard.import},
@ -171,18 +175,18 @@ var RED = (function() {
{id:"menu-item-export-library",label:RED._("menu.label.library"),disabled:true,onselect:RED.library.export} {id:"menu-item-export-library",label:RED._("menu.label.library"),disabled:true,onselect:RED.library.export}
]}, ]},
null, null,
{id:"menu-item-flow",label:RED._("menu.label.flows"),options:[
{id:"menu-item-flow-add",label:RED._("menu.label.add"),onselect:RED.workspaces.add},
{id:"menu-item-flow-edit",label:RED._("menu.label.rename"),onselect:RED.workspaces.edit},
{id:"menu-item-flow-delete",label:RED._("menu.label.delete"),onselect:RED.workspaces.remove},
null
]},
null,
{id:"menu-item-subflow",label:RED._("menu.label.subflows"), options: [ {id:"menu-item-subflow",label:RED._("menu.label.subflows"), options: [
{id:"menu-item-subflow-create",label:RED._("menu.label.createSubflow"),onselect:RED.subflow.createSubflow}, {id:"menu-item-subflow-create",label:RED._("menu.label.createSubflow"),onselect:RED.subflow.createSubflow},
{id:"menu-item-subflow-convert",label:RED._("menu.label.selectionToSubflow"),disabled:true,onselect:RED.subflow.convertToSubflow}, {id:"menu-item-subflow-convert",label:RED._("menu.label.selectionToSubflow"),disabled:true,onselect:RED.subflow.convertToSubflow},
]}, ]},
null, null,
{id:"menu-item-workspace",label:RED._("menu.label.workspaces"),options:[
{id:"menu-item-workspace-add",label:RED._("menu.label.add"),onselect:RED.workspaces.add},
{id:"menu-item-workspace-edit",label:RED._("menu.label.rename"),onselect:RED.workspaces.edit},
{id:"menu-item-workspace-delete",label:RED._("menu.label.delete"),onselect:RED.workspaces.remove},
null
]},
null,
{id:"menu-item-keyboard-shortcuts",label:RED._("menu.label.keyboardShortcuts"),onselect:RED.keyboard.showHelp}, {id:"menu-item-keyboard-shortcuts",label:RED._("menu.label.keyboardShortcuts"),onselect:RED.keyboard.showHelp},
{id:"menu-item-help", {id:"menu-item-help",
label: RED.settings.theme("menu.menu-item-help.label","Node-RED Website"), label: RED.settings.theme("menu.menu-item-help.label","Node-RED Website"),

View File

@ -156,7 +156,6 @@ RED.nodes = (function() {
} }
if (n._def.category == "config") { if (n._def.category == "config") {
configNodes[n.id] = n; configNodes[n.id] = n;
RED.sidebar.config.refresh();
} else { } else {
n.dirty = true; n.dirty = true;
var updatedConfigNode = false; var updatedConfigNode = false;
@ -176,7 +175,7 @@ RED.nodes = (function() {
} }
} }
if (updatedConfigNode) { if (updatedConfigNode) {
RED.sidebar.config.refresh(); // TODO: refresh config tab?
} }
if (n._def.category == "subflows" && typeof n.i === "undefined") { if (n._def.category == "subflows" && typeof n.i === "undefined") {
var nextId = 0; var nextId = 0;
@ -215,7 +214,7 @@ RED.nodes = (function() {
if (id in configNodes) { if (id in configNodes) {
node = configNodes[id]; node = configNodes[id];
delete configNodes[id]; delete configNodes[id];
RED.sidebar.config.refresh(); RED.workspaces.refresh();
} else { } else {
node = getNode(id); node = getNode(id);
if (node) { if (node) {
@ -245,11 +244,11 @@ RED.nodes = (function() {
} }
} }
if (updatedConfigNode) { if (updatedConfigNode) {
RED.sidebar.config.refresh(); RED.workspaces.refresh();
} }
} }
} }
if (node._def.onremove) { if (node && node._def.onremove) {
node._def.onremove.call(n); node._def.onremove.call(n);
} }
return {links:removedLinks,nodes:removedNodes}; return {links:removedLinks,nodes:removedNodes};
@ -273,16 +272,26 @@ RED.nodes = (function() {
var removedNodes = []; var removedNodes = [];
var removedLinks = []; var removedLinks = [];
var n; var n;
var node;
for (n=0;n<nodes.length;n++) { for (n=0;n<nodes.length;n++) {
var node = nodes[n]; node = nodes[n];
if (node.z == id) { if (node.z == id) {
removedNodes.push(node); removedNodes.push(node);
} }
} }
for (n=0;n<removedNodes.length;n++) { for(n in configNodes) {
var rmlinks = removeNode(removedNodes[n].id); if (configNodes.hasOwnProperty(n)) {
removedLinks = removedLinks.concat(rmlinks); node = configNodes[n];
if (node.z == id) {
removedNodes.push(node);
} }
}
}
for (n=0;n<removedNodes.length;n++) {
var result = removeNode(removedNodes[n].id);
removedLinks = removedLinks.concat(result.links);
}
console.log(removedLinks);
return {nodes:removedNodes,links:removedLinks}; return {nodes:removedNodes,links:removedLinks};
} }
@ -382,6 +391,7 @@ RED.nodes = (function() {
var node = {}; var node = {};
node.id = n.id; node.id = n.id;
node.type = n.type; node.type = n.type;
node.z = n.z;
if (node.type == "unknown") { if (node.type == "unknown") {
for (var p in n._orig) { for (var p in n._orig) {
if (n._orig.hasOwnProperty(p)) { if (n._orig.hasOwnProperty(p)) {
@ -417,7 +427,6 @@ RED.nodes = (function() {
if (n._def.category != "config") { if (n._def.category != "config") {
node.x = n.x; node.x = n.x;
node.y = n.y; node.y = n.y;
node.z = n.z;
node.wires = []; node.wires = [];
for(var i=0;i<n.outputs;i++) { for(var i=0;i<n.outputs;i++) {
node.wires.push([]); node.wires.push([]);
@ -690,7 +699,7 @@ RED.nodes = (function() {
if (def && def.category == "config") { if (def && def.category == "config") {
var existingConfigNode = RED.nodes.node(n.id); var existingConfigNode = RED.nodes.node(n.id);
if (!existingConfigNode || !compareNodes(existingConfigNode,n) || existingConfigNode._def.exclusive) { if (!existingConfigNode || !compareNodes(existingConfigNode,n) || existingConfigNode._def.exclusive) {
var configNode = {id:n.id,type:n.type,users:[]}; var configNode = {id:n.id, z:n.z, type:n.type, users:[]};
for (var d in def.defaults) { for (var d in def.defaults) {
if (def.defaults.hasOwnProperty(d)) { if (def.defaults.hasOwnProperty(d)) {
configNode[d] = n[d]; configNode[d] = n[d];
@ -846,6 +855,7 @@ RED.nodes = (function() {
}); });
} }
RED.workspaces.refresh();
return [new_nodes,new_links,new_workspaces,new_subflows]; return [new_nodes,new_links,new_workspaces,new_subflows];
} }
@ -947,6 +957,13 @@ RED.nodes = (function() {
} }
} }
}, },
eachWorkspace: function(cb) {
for (var id in workspaces) {
if (workspaces.hasOwnProperty(id)) {
cb(workspaces[id]);
}
}
},
node: getNode, node: getNode,

View File

@ -103,7 +103,7 @@ RED.deploy = (function() {
], ],
create: function() { create: function() {
$("#node-dialog-confirm-deploy").parent().find("div.ui-dialog-buttonpane") $("#node-dialog-confirm-deploy").parent().find("div.ui-dialog-buttonpane")
.append('<div style="height:0; vertical-align: middle; display:inline-block;">'+ .prepend('<div style="height:0; vertical-align: middle; display:inline-block; margin-top: 13px; float:left;">'+
'<input style="vertical-align:top;" type="checkbox" id="node-dialog-confirm-deploy-hide">'+ '<input style="vertical-align:top;" type="checkbox" id="node-dialog-confirm-deploy-hide">'+
'<label style="display:inline;" for="node-dialog-confirm-deploy-hide"> do not warn about this again</label>'+ '<label style="display:inline;" for="node-dialog-confirm-deploy-hide"> do not warn about this again</label>'+
'<input type="hidden" id="node-dialog-confirm-deploy-type">'+ '<input type="hidden" id="node-dialog-confirm-deploy-type">'+

View File

@ -391,7 +391,7 @@ RED.editor = (function() {
if (editing_node) { if (editing_node) {
RED.sidebar.info.refresh(editing_node); RED.sidebar.info.refresh(editing_node);
} }
RED.sidebar.config.refresh(); RED.workspaces.refresh();
var buttons = $( this ).dialog("option","buttons"); var buttons = $( this ).dialog("option","buttons");
if (buttons.length == 3) { if (buttons.length == 3) {
@ -671,12 +671,18 @@ RED.editor = (function() {
ns = node_def.set.id; ns = node_def.set.id;
} }
var activeWorkspace = RED.nodes.workspace(RED.workspaces.active());
if (!activeWorkspace) {
activeWorkspace = RED.nodes.subflow(RED.workspaces.active());
}
if (configNode == null) { if (configNode == null) {
configNode = { configNode = {
id: (1+Math.random()*4294967295).toString(16), id: (1+Math.random()*4294967295).toString(16),
_def: node_def, _def: node_def,
type: type type: type,
z: activeWorkspace.id,
users: []
} }
for (var d in node_def.defaults) { for (var d in node_def.defaults) {
if (node_def.defaults[d].value) { if (node_def.defaults[d].value) {
@ -710,7 +716,7 @@ RED.editor = (function() {
buttons = buttons.splice(1); buttons = buttons.splice(1);
} }
buttons[0].text = "Add"; buttons[0].text = "Add";
$("#node-config-dialog-user-count").html("").hide(); $("#node-config-dialog-user-count").find("span").html("").parent().hide();
} else { } else {
if (buttons.length == 2) { if (buttons.length == 2) {
buttons.unshift({ buttons.unshift({
@ -747,8 +753,60 @@ RED.editor = (function() {
}); });
} }
buttons[1].text = "Update"; buttons[1].text = "Update";
$("#node-config-dialog-user-count").html(RED._("editor.nodesUse", {count:configNode.users.length})).show(); $("#node-config-dialog-user-count").find("span").html(RED._("editor.nodesUse", {count:configNode.users.length})).parent().show();
} }
if (configNode._def.exclusive) {
$("#node-config-dialog-scope").hide();
} else {
$("#node-config-dialog-scope").show();
}
$("#node-config-dialog-scope-warning").hide();
var nodeUserFlows = {};
configNode.users.forEach(function(n) {
nodeUserFlows[n.z] = true;
});
var flowCount = Object.keys(nodeUserFlows).length;
var tabSelect = $("#node-config-dialog-scope").empty();
tabSelect.off("change");
tabSelect.append('<option value=""'+(!configNode.z?" selected":"")+' data-i18n="workspace.config.global"></option>');
tabSelect.append('<option disabled>flows</option>');
RED.nodes.eachWorkspace(function(ws) {
var workspaceLabel = ws.label;
if (nodeUserFlows[ws.id]) {
workspaceLabel = "* "+workspaceLabel;
}
tabSelect.append('<option value="'+ws.id+'"'+(ws.id==configNode.z?" selected":"")+'>'+workspaceLabel+'</option>');
});
tabSelect.append('<option disabled>subflows</option>');
RED.nodes.eachSubflow(function(ws) {
var workspaceLabel = ws.name;
if (nodeUserFlows[ws.id]) {
workspaceLabel = "* "+workspaceLabel;
}
tabSelect.append('<option value="'+ws.id+'"'+(ws.id==configNode.z?" selected":"")+'>'+workspaceLabel+'</option>');
});
if (flowCount > 0) {
tabSelect.on('change',function() {
var newScope = $(this).val();
if (newScope === '') {
// global scope - everyone can use it
$("#node-config-dialog-scope-warning").hide();
} else if (!nodeUserFlows[newScope] || flowCount > 1) {
// a user will loose access to it
$("#node-config-dialog-scope-warning").show();
} else {
$("#node-config-dialog-scope-warning").hide();
}
});
}
//tabSelect.append('<option value="'+activeWorkspace.id+'"'+(activeWorkspace.id==configNode.z?" selected":"")+'>'+workspaceLabel+'</option>');
tabSelect.i18n();
$( "#node-config-dialog" ).dialog("option","buttons",buttons); $( "#node-config-dialog" ).dialog("option","buttons",buttons);
$("#node-config-dialog").i18n(); $("#node-config-dialog").i18n();
@ -776,17 +834,39 @@ RED.editor = (function() {
var select = $("#node-input-"+name); var select = $("#node-input-"+name);
var node_def = RED.nodes.getType(type); var node_def = RED.nodes.getType(type);
select.children().remove(); select.children().remove();
var activeWorkspace = RED.nodes.workspace(RED.workspaces.active());
if (!activeWorkspace) {
activeWorkspace = RED.nodes.subflow(RED.workspaces.active());
}
var configNodes = [];
RED.nodes.eachConfig(function(config) { RED.nodes.eachConfig(function(config) {
if (config.type == type) { if (config.type == type && (!config.z || config.z === activeWorkspace.id)) {
var label = ""; var label = "";
if (typeof node_def.label == "function") { if (typeof node_def.label == "function") {
label = node_def.label.call(config); label = node_def.label.call(config);
} else { } else {
label = node_def.label; label = node_def.label;
} }
select.append('<option value="'+config.id+'"'+(value==config.id?" selected":"")+'>'+label+'</option>'); configNodes.push({id:config.id,label:label});
} }
}); });
configNodes.sort(function(A,B) {
if (A.label < B.label) {
return -1;
} else if (A.label > B.label) {
return 1;
}
return 0;
});
configNodes.forEach(function(cn) {
select.append('<option value="'+cn.id+'"'+(value==cn.id?" selected":"")+'>'+cn.label+'</option>');
});
select.append('<option value="_ADD_"'+(value===""?" selected":"")+'>'+RED._("editor.addNewType", {type:type})+'</option>'); select.append('<option value="_ADD_"'+(value===""?" selected":"")+'>'+RED._("editor.addNewType", {type:type})+'</option>');
window.setTimeout(function() { select.change();},50); window.setTimeout(function() { select.change();},50);
} }
@ -813,7 +893,7 @@ RED.editor = (function() {
var configNode; var configNode;
var d; var d;
var input; var input;
var scope = $("#node-config-dialog-scope").val();
if (configAdding) { if (configAdding) {
configNode = {type:configType,id:configId,users:[]}; configNode = {type:configType,id:configId,users:[]};
for (d in configTypeDef.defaults) { for (d in configTypeDef.defaults) {
@ -828,6 +908,7 @@ RED.editor = (function() {
} }
configNode.label = configTypeDef.label; configNode.label = configTypeDef.label;
configNode._def = configTypeDef; configNode._def = configTypeDef;
configNode.z = scope;
RED.nodes.add(configNode); RED.nodes.add(configNode);
updateConfigNodeSelect(configProperty,configType,configNode.id); updateConfigNodeSelect(configProperty,configType,configNode.id);
} else { } else {
@ -842,6 +923,26 @@ RED.editor = (function() {
} }
} }
} }
if (scope) {
configNode.users = configNode.users.filter(function(n) {
var keep = true;
for (var d in n._def.defaults) {
if (n._def.defaults.hasOwnProperty(d)) {
if (n._def.defaults[d].type === configNode.type &&
n[d] === configNode.id &&
n.z !== scope) {
keep = false;
n[d] = null;
n.dirty = true;
n.changed = true;
validateNode(n);
}
}
}
return keep;
});
}
configNode.z = scope;
updateConfigNodeSelect(configProperty,configType,configId); updateConfigNodeSelect(configProperty,configType,configId);
} }
if (configTypeDef.credentials) { if (configTypeDef.credentials) {
@ -857,6 +958,7 @@ RED.editor = (function() {
} }
RED.nodes.dirty(true); RED.nodes.dirty(true);
RED.view.redraw(true);
$(this).dialog("close"); $(this).dialog("close");
} }
@ -903,7 +1005,16 @@ RED.editor = (function() {
if (RED.view.state() != RED.state.EDITING) { if (RED.view.state() != RED.state.EDITING) {
RED.keyboard.enable(); RED.keyboard.enable();
} }
RED.sidebar.config.refresh(); RED.workspaces.refresh();
},
create: function() {
$("#node-config-dialog").parent().find("div.ui-dialog-buttonpane")
.prepend('<div id="node-config-dialog-user-count"><i class="fa fa-info-circle"></i> <span></span></div>');
$("#node-config-dialog").parent().find('.ui-dialog-titlebar').append('<span id="node-config-dialog-scope-container"><span id="node-config-dialog-scope-warning" data-i18n="[title]editor.errors.scopeChange"><i class="fa fa-warning"></i></span><select id="node-config-dialog-scope"></select></span>');
$("#node-config-dialog").parent().draggable({
cancel: '.ui-dialog-content, .ui-dialog-titlebar-close, #node-config-dialog-scope-container'
});
} }
}); });
} }
@ -933,7 +1044,7 @@ RED.editor = (function() {
changes['name'] = editing_node.name; changes['name'] = editing_node.name;
editing_node.name = newName; editing_node.name = newName;
changed = true; changed = true;
$("#menu-item-workspace-menu-"+editing_node.id.replace(".","-")).text(newName); $("#menu-item-flow-menu-"+editing_node.id.replace(".","-")).text(newName);
} }
RED.palette.refresh(); RED.palette.refresh();
@ -996,6 +1107,7 @@ RED.editor = (function() {
RED.view.state(RED.state.DEFAULT); RED.view.state(RED.state.DEFAULT);
} }
RED.sidebar.info.refresh(editing_node); RED.sidebar.info.refresh(editing_node);
RED.workspaces.refresh();
editing_node = null; editing_node = null;
} }
}); });

View File

@ -61,7 +61,7 @@ RED.palette = (function() {
} }
function setLabel(type, el,label) { function setLabel(type, el,label) {
var nodeWidth = 80; var nodeWidth = 82;
var nodeHeight = 25; var nodeHeight = 25;
var lineHeight = 20; var lineHeight = 20;
var portHeight = 10; var portHeight = 10;

View File

@ -188,7 +188,6 @@ RED.sidebar = (function() {
RED.keyboard.add(/* SPACE */ 32,{ctrl:true},function(){RED.menu.setSelected("menu-item-sidebar",!RED.menu.isSelected("menu-item-sidebar"));d3.event.preventDefault();}); RED.keyboard.add(/* SPACE */ 32,{ctrl:true},function(){RED.menu.setSelected("menu-item-sidebar",!RED.menu.isSelected("menu-item-sidebar"));d3.event.preventDefault();});
showSidebar(); showSidebar();
RED.sidebar.info.init(); RED.sidebar.info.init();
RED.sidebar.config.init();
// hide info bar at start if screen rather narrow... // hide info bar at start if screen rather narrow...
if ($(window).width() < 600) { toggleSidebar(); } if ($(window).width() < 600) { toggleSidebar(); }
} }

View File

@ -1,92 +0,0 @@
/**
* Copyright 2013 IBM Corp.
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
RED.sidebar.config = (function() {
var content = document.createElement("div");
content.style.paddingTop = "4px";
content.style.paddingLeft = "4px";
content.style.paddingRight = "4px";
var list = $("<ul>",{class:"tab-config-list"}).appendTo(content);
function init() {
RED.sidebar.addTab({
id: "config",
label: RED._("sidebar.config.label"),
name: RED._("sidebar.config.name"),
content: content,
closeable: true,
visible: false,
onchange: function() { refresh(); }
});
}
function show() {
refresh();
RED.sidebar.show("config");
}
function refresh() {
list.empty();
RED.nodes.eachConfig(function(node) {
var li = list.find("#tab-config-list-type-"+node.type);
if (li.length === 0) {
li = $("<li>",{id:"tab-config-list-type-"+node.type}).appendTo(list);
$('<div class="tab-config-list-type">'+node.type+'</div>').appendTo(li);
}
var label = "";
if (typeof node._def.label == "function") {
label = node._def.label.call(node);
} else {
label = node._def.label;
}
label = label || "&nbsp;";
var entry = $('<div class="tab-config-list-entry"></div>').appendTo(li);
entry.on('dblclick',function(e) {
RED.editor.editConfig("", node.type, node.id);
});
var userArray = node.users.map(function(n) { return n.id });
entry.on('mouseover',function(e) {
RED.nodes.eachNode(function(node) {
if( userArray.indexOf(node.id) != -1) {
node.highlighted = true;
node.dirty = true;
}
});
RED.view.redraw();
});
entry.on('mouseout',function(e) {
RED.nodes.eachNode(function(node) {
if(node.highlighted) {
node.highlighted = false;
node.dirty = true;
}
});
RED.view.redraw();
});
$('<div class="tab-config-list-label">'+label+'</div>').appendTo(entry);
$('<div class="tab-config-list-users">'+node.users.length+'</div>').appendTo(entry);
});
}
return {
init:init,
show:show,
refresh:refresh
}
})();

View File

@ -256,8 +256,8 @@ RED.view = (function() {
activeSubflow = RED.nodes.subflow(event.workspace); activeSubflow = RED.nodes.subflow(event.workspace);
RED.menu.setDisabled("menu-item-workspace-edit", activeSubflow); RED.menu.setDisabled("menu-item-flow-edit", activeSubflow);
RED.menu.setDisabled("menu-item-workspace-delete",RED.workspaces.count() == 1 || activeSubflow); RED.menu.setDisabled("menu-item-flow-delete",RED.workspaces.count() == 1 || activeSubflow);
if (workspaceScrollPositions[event.workspace]) { if (workspaceScrollPositions[event.workspace]) {
chart.scrollLeft(workspaceScrollPositions[event.workspace].left); chart.scrollLeft(workspaceScrollPositions[event.workspace].left);
@ -407,8 +407,8 @@ RED.view = (function() {
lasso = vis.append('rect') lasso = vis.append('rect')
.attr("ox",point[0]) .attr("ox",point[0])
.attr("oy",point[1]) .attr("oy",point[1])
.attr("rx",2) .attr("rx",1)
.attr("ry",2) .attr("ry",1)
.attr("x",point[0]) .attr("x",point[0])
.attr("y",point[1]) .attr("y",point[1])
.attr("width",0) .attr("width",0)
@ -1370,14 +1370,7 @@ RED.view = (function() {
var statusLabel = status.append("svg:text") var statusLabel = status.append("svg:text")
.attr("class","node_status_label") .attr("class","node_status_label")
.attr('x',20).attr('y',9) .attr('x',20).attr('y',9);
.style({
'stroke-width': 0,
'fill': '#888',
'font-size':'9pt',
'stroke':'#000',
'text-anchor':'start'
});
//node.append("circle").attr({"class":"centerDot","cx":0,"cy":0,"r":5}); //node.append("circle").attr({"class":"centerDot","cx":0,"cy":0,"r":5});
@ -1802,7 +1795,6 @@ RED.view = (function() {
if (updateActive) { if (updateActive) {
updateActiveNodes(); updateActiveNodes();
} }
RED.workspaces.refresh();
redraw(); redraw();
}, },
focus: focusView, focus: focusView,

View File

@ -90,6 +90,7 @@ RED.workspaces = (function() {
activeWorkspace = tab.id; activeWorkspace = tab.id;
event.workspace = activeWorkspace; event.workspace = activeWorkspace;
RED.events.emit("workspace:change",event); RED.events.emit("workspace:change",event);
refreshConfigNodeList();
}, },
ondblclick: function(tab) { ondblclick: function(tab) {
if (tab.type != "subflow") { if (tab.type != "subflow") {
@ -99,18 +100,18 @@ RED.workspaces = (function() {
} }
}, },
onadd: function(tab) { onadd: function(tab) {
RED.menu.addItem("menu-item-workspace",{ RED.menu.addItem("menu-item-flow",{
id:"menu-item-workspace-menu-"+tab.id.replace(".","-"), id:"menu-item-flow-menu-"+tab.id.replace(".","-"),
label:tab.label, label:tab.label,
onselect:function() { onselect:function() {
workspace_tabs.activateTab(tab.id); workspace_tabs.activateTab(tab.id);
} }
}); });
RED.menu.setDisabled("menu-item-workspace-delete",workspace_tabs.count() == 1); RED.menu.setDisabled("menu-item-flow-delete",workspace_tabs.count() == 1);
}, },
onremove: function(tab) { onremove: function(tab) {
RED.menu.setDisabled("menu-item-workspace-delete",workspace_tabs.count() == 1); RED.menu.setDisabled("menu-item-flow-delete",workspace_tabs.count() == 1);
RED.menu.removeItem("menu-item-workspace-menu-"+tab.id.replace(".","-")); RED.menu.removeItem("menu-item-flow-menu-"+tab.id.replace(".","-"));
}, },
minimumActiveTabWidth: 150 minimumActiveTabWidth: 150
}); });
@ -140,7 +141,7 @@ RED.workspaces = (function() {
if (workspace.label != label) { if (workspace.label != label) {
workspace_tabs.renameTab(workspace.id,label); workspace_tabs.renameTab(workspace.id,label);
RED.nodes.dirty(true); RED.nodes.dirty(true);
$("#menu-item-workspace-menu-"+workspace.id.replace(".","-")).text(label); $("#menu-item-flow-menu-"+workspace.id.replace(".","-")).text(label);
// TODO: update entry in menu // TODO: update entry in menu
} }
$( this ).dialog( "close" ); $( this ).dialog( "close" );
@ -196,7 +197,19 @@ RED.workspaces = (function() {
$('#btn-workspace-add-tab').on("click",function(e) {addWorkspace(); e.preventDefault()}); $('#btn-workspace-add-tab').on("click",function(e) {addWorkspace(); e.preventDefault()});
RED.events.on("sidebar:resize",workspace_tabs.resize); RED.events.on("sidebar:resize",workspace_tabs.resize);
RED.menu.setAction('menu-item-workspace-delete',function() { $(".workspace-config-node-tray-header").on('click', function(e) {
var icon = $(this).find("i");
if (icon.hasClass("expanded")) {
icon.removeClass("expanded");
$(this).next().slideUp();
} else {
icon.addClass("expanded");
$(this).next().slideDown();
}
});
RED.menu.setAction('menu-item-flow-delete',function() {
deleteWorkspace(RED.nodes.workspace(activeWorkspace)); deleteWorkspace(RED.nodes.workspace(activeWorkspace));
}); });
@ -214,6 +227,84 @@ RED.workspaces = (function() {
} }
} }
} }
function createConfigNodeList(nodes,list) {
nodes.sort(function(A,B) {
if (A.type < B.type) { return -1;}
if (A.type > B.type) { return 1;}
return 0;
});
list.empty();
if (nodes.length === 0) {
$('<li class="config_node_none">none</li>').appendTo(list);
} else {
var currentType = "";
nodes.forEach(function(node) {
var label = "";
if (typeof node._def.label == "function") {
label = node._def.label.call(node);
} else {
label = node._def.label;
}
label = label || node.id;
if (node.type != currentType) {
$('<li class="config_node_type">'+node.type+'</li>').appendTo(list);
currentType = node.type;
}
var entry = $('<li class="palette_node config_node"></li>').appendTo(list);
$('<div class="palette_label"></div>').text(label).appendTo(entry);
var iconContainer = $('<div/>',{class:"palette_icon_container palette_icon_container_right"}).text(node.users.length).appendTo(entry);
if (node.users.length === 0) {
entry.addClass("config_node_unused");
}
entry.on('click',function(e) {
RED.sidebar.info.refresh(node);
});
entry.on('dblclick',function(e) {
RED.editor.editConfig("", node.type, node.id);
});
var userArray = node.users.map(function(n) { return n.id });
entry.on('mouseover',function(e) {
RED.nodes.eachNode(function(node) {
if( userArray.indexOf(node.id) != -1) {
node.highlighted = true;
node.dirty = true;
}
});
RED.view.redraw();
});
entry.on('mouseout',function(e) {
RED.nodes.eachNode(function(node) {
if(node.highlighted) {
node.highlighted = false;
node.dirty = true;
}
});
RED.view.redraw();
});
});
}
}
function refreshConfigNodeList() {
var localConfigNodes = [];
var globalConfigNodes = [];
RED.nodes.eachConfig(function(cn) {
if (cn.z == activeWorkspace) {
localConfigNodes.push(cn);
} else if (!cn.z) {
globalConfigNodes.push(cn);
}
});
createConfigNodeList(localConfigNodes,$("#workspace-config-node-tray-locals"));
createConfigNodeList(globalConfigNodes,$("#workspace-config-node-tray-globals"));
}
return { return {
init: init, init: init,
add: addWorkspace, add: addWorkspace,
@ -246,9 +337,14 @@ RED.workspaces = (function() {
workspace_tabs.renameTab(sf.id,sf.name); workspace_tabs.renameTab(sf.id,sf.name);
} }
}); });
refreshConfigNodeList();
}, },
resize: function() { resize: function() {
workspace_tabs.resize(); workspace_tabs.resize();
},
toggleConfigNodes: function(state) {
refreshConfigNodeList();
$("#workspace").toggleClass("config-open",state);
} }
} }
})(); })();

View File

@ -23,8 +23,8 @@
border-color: rgb(214, 97, 95) !important; border-color: rgb(214, 97, 95) !important;
} }
.leftButton { .ui-dialog .ui-dialog-buttonpane button.leftButton {
margin-right: 200px !important; margin-right: 40px;
} }
.form-row { .form-row {
@ -42,7 +42,6 @@
.form-tips { .form-tips {
background: #ffe; background: #ffe;
font-size: 12px;
padding: 8px; padding: 8px;
border-radius: 2px; border-radius: 2px;
border: 1px solid $secondary-border-color; border: 1px solid $secondary-border-color;
@ -67,7 +66,7 @@
.editor-button { .editor-button {
@include workspace-button; @include workspace-button;
height: 34px; height: 34px;
line-height: 30px; line-height: 32px;
font-size: 13px; font-size: 13px;
border-radius: 4px; border-radius: 4px;
padding: 0 10px; padding: 0 10px;
@ -79,3 +78,29 @@
border-radius: 2px; border-radius: 2px;
padding: 0 5px; padding: 0 5px;
} }
#node-config-dialog-scope-container {
cursor: auto;
float: right;
font-size: 12px !important;
}
#node-config-dialog-scope-warning {
display: inline-block;
margin-right: 5px;
color: #AD1625;
vertical-align: middle;
}
#node-config-dialog-scope {
margin: 1px 0 0 0;
padding: 0;
height: 22px;
width: 110px;
}
#node-config-dialog-user-count {
vertical-align: middle;
display:inline-block;
margin-top: 10px;
margin-right: 20px;
float:left;
font-size: 12px;
}

View File

@ -19,7 +19,7 @@
} }
.lasso { .lasso {
stroke-width: 2px; stroke-width: 1px;
stroke: #ff7f0e; stroke: #ff7f0e;
fill: rgba(20,125,255,0.1); fill: rgba(20,125,255,0.1);
stroke-dasharray: 10 5; stroke-dasharray: 10 5;
@ -165,6 +165,15 @@
.node_hovered { .node_hovered {
} }
.node_status_label {
@include disable-selection;
stroke-width: 0;
fill: #888;
font-size:9pt;
stroke:#000;
text-anchor:start;
}
.port_hovered { .port_hovered {
stroke: $port-selected-color; stroke: $port-selected-color;
fill: $port-selected-color; fill: $port-selected-color;

View File

@ -14,6 +14,15 @@
* limitations under the License. * limitations under the License.
**/ **/
.ui-widget {
font-size: 14px !important;
font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif !important;
}
.ui-widget input, .ui-widget select, .ui-widget textarea, .ui-widget button {
font-size: 14px !important;
font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif !important;
}
/* jQuery Theme overrides */ /* jQuery Theme overrides */
.ui-tabs .ui-tabs-panel { .ui-tabs .ui-tabs-panel {
padding: 0px; padding: 0px;
@ -34,6 +43,9 @@
.ui-dialog .ui-dialog-content { .ui-dialog .ui-dialog-content {
padding: 25px 25px 10px 25px; padding: 25px 25px 10px 25px;
} }
.ui-dialog .ui-dialog-title {
width: auto;
}
.ui-dialog .ui-dialog-titlebar { .ui-dialog .ui-dialog-titlebar {
padding: 10px; padding: 10px;
background: #f3f3f3; background: #f3f3f3;
@ -50,3 +62,14 @@
.ui-dialog-no-close .ui-dialog-titlebar-close { .ui-dialog-no-close .ui-dialog-titlebar-close {
display: none; display: none;
} }
.ui-dialog-buttonset {
text-align: right;
}
.ui-dialog .ui-dialog-buttonpane .ui-dialog-buttonset {
float: none;
}
.ui-dialog .ui-dialog-buttonpane {
padding: .3em 1em .5em 1em;
}

View File

@ -50,10 +50,12 @@
} }
&:not(.disabled):focus { &:not(.disabled):focus {
color: $workspace-button-color-focus; color: $workspace-button-color-focus;
text-decoration: none;
} }
&:not(.disabled):active { &:not(.disabled):active {
color: $workspace-button-color-active; color: $workspace-button-color-active;
background: $workspace-button-background-active; background: $workspace-button-background-active;
text-decoration: none;
} }
} }
@mixin component-footer { @mixin component-footer {
@ -75,6 +77,10 @@
line-height: 17px; line-height: 17px;
width: 18px; width: 18px;
height: 18px; height: 18px;
&.text-button {
width: auto;
padding: 0 5px;
}
} }
@mixin component-shadow { @mixin component-shadow {

View File

@ -200,7 +200,7 @@
left: auto; left: auto;
right: 0; right: 0;
border-right: none; border-right: none;
border-left: 2px solid rgba(0,0,0,0.1); border-left: 1px solid rgba(0,0,0,0.1);
} }
.palette_icon { .palette_icon {
display: inline-block; display: inline-block;

View File

@ -47,7 +47,8 @@
body { body {
font: 14px "Helvetica" !important; font-size: 14px;
font-family: 'Helvetica Neue', Arial, Helvetica, sans-serif;
padding-top: 100px; padding-top: 100px;
background: #f3f3f3; background: #f3f3f3;
} }

View File

@ -46,6 +46,7 @@ ul.red-ui-tabs li {
ul.red-ui-tabs li a.red-ui-tab-label { ul.red-ui-tabs li a.red-ui-tab-label {
display: block; display: block;
font-size: 14px;
padding-left: 12px; padding-left: 12px;
width: 100%; width: 100%;
height: 100%; height: 100%;

View File

@ -24,8 +24,22 @@
left:0px; left:0px;
right:0px; right:0px;
box-sizing:border-box; box-sizing:border-box;
transition: right 0.2s ease;
} }
#workspace.config-open {
#chart {
right: 190px;
}
#workspace-config-node-tray {
right: 0px;
}
#workspace-toolbar {
right: 190px;
}
}
#chart svg:focus { #chart svg:focus {
outline: none; outline: none;
} }
@ -73,3 +87,64 @@
#workspace-footer { #workspace-footer {
@include component-footer; @include component-footer;
} }
#workspace-config-node-tray {
@include disable-selection;
position: absolute;
top: 35px;
bottom:25px;
right:-190px;
width: 190px;
border-left: 1px solid $secondary-border-color;
box-sizing:border-box;
background: #f3f3f3;
transition: right 0.2s ease;
overflow-y: auto;
}
.config-node-list {
margin: 0;
list-style-type: none;
}
.config_node {
width: 160px;
height: 30px;
background: #f3f3f3;
color: #666;
cursor: pointer;
.palette_label {
margin-left: 8px;
line-height: 24px;
text-align: left;
white-space: nowrap;
overflow: hidden;
text-overflow: ellipsis;
}
.palette_icon_container {
font-size: 12px;
line-height: 30px;
background-color: #e8e8e8;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
}
.config_node_type {
color: #999;
text-align: right;
padding-right: 3px;
&:not(:first-child) {
margin-top: 20px;
}
}
.config_node_none {
color: #ddd;
text-align:right;
padding-right: 3px;
}
.config_node_unused {
border-color: #aaa;
background: #f9f9f9;
border-style: dashed;
color: #aaa;
}

View File

@ -23,13 +23,15 @@
position: absolute; position: absolute;
top: 35px; top: 35px;
left:0; left:0;
width: 100%; right: 0;
padding: 7px; padding: 7px;
height: 40px; height: 40px;
box-sizing: border-box; box-sizing: border-box;
background: #fff; background: #fff;
border-bottom: 1px solid $secondary-border-color; border-bottom: 1px solid $secondary-border-color;
white-space: nowrap; white-space: nowrap;
transition: right 0.2s ease;
overflow: hidden;
.button { .button {
@include workspace-button; @include workspace-button;

View File

@ -58,6 +58,16 @@
<ul id="workspace-tabs"></ul> <ul id="workspace-tabs"></ul>
<div id="workspace-add-tab"><a id="btn-workspace-add-tab" href="#"><i class="fa fa-plus"></i></a></div> <div id="workspace-add-tab"><a id="btn-workspace-add-tab" href="#"><i class="fa fa-plus"></i></a></div>
<div id="chart"></div> <div id="chart"></div>
<div id="workspace-config-node-tray">
<div class="palette-category">
<div class="workspace-config-node-tray-header palette-header"><i class="fa fa-angle-down expanded"></i><span data-i18n="workspace.config.local"></span></div>
<ul id="workspace-config-node-tray-locals" class="palette-content config-node-list"></ul>
</div>
<div class="palette-category">
<div class="workspace-config-node-tray-header palette-header"><i class="fa fa-angle-down expanded"></i><span data-i18n="workspace.config.global"></span></div>
<ul id="workspace-config-node-tray-globals" class="palette-content config-node-list"></ul>
</div>
</div>
<div id="workspace-toolbar"></div> <div id="workspace-toolbar"></div>
<div id="workspace-footer"> <div id="workspace-footer">
<a class="workspace-footer-button" id="btn-zoom-out" href="#"><i class="fa fa-minus"></i></a> <a class="workspace-footer-button" id="btn-zoom-out" href="#"><i class="fa fa-minus"></i></a>
@ -79,7 +89,7 @@
<div id="dropTarget"><div data-i18n="[append]workspace.dropFlowHere"><br/><i class="fa fa-download"></i></div></div> <div id="dropTarget"><div data-i18n="[append]workspace.dropFlowHere"><br/><i class="fa fa-download"></i></div></div>
<div id="dialog" class="hide"><form id="dialog-form" class="form-horizontal"></form></div> <div id="dialog" class="hide"><form id="dialog-form" class="form-horizontal"></form></div>
<div id="node-config-dialog" class="hide"><form id="dialog-config-form" class="form-horizontal"><div id="node-config-dialog-edit-form"></div><div class="form-tips" id="node-config-dialog-user-count"></div></form></div> <div id="node-config-dialog" class="hide"><form id="dialog-config-form" class="form-horizontal"><div id="node-config-dialog-edit-form"></div><!--<div id="node-config-dialog-toolbar" class="form-row"><label><span>Node scope</span></label><select id="node-config-dialog-scope"></select></div>--></form></div>
<div id="subflow-dialog" class="hide"> <div id="subflow-dialog" class="hide">
<form class="form-horizontal"> <form class="form-horizontal">
<div class="form-row"> <div class="form-row">

View File

@ -9,11 +9,15 @@
} }
}, },
"workspace": { "workspace": {
"defaultName": "Sheet __number__", "defaultName": "Flow __number__",
"renameSheet": "Rename sheet", "renameSheet": "Rename flow",
"confirmDelete": "Confirm delete", "confirmDelete": "Confirm delete",
"delete": "Are you sure you want to delete '__label__'?", "delete": "Are you sure you want to delete '__label__'?",
"dropFlowHere": "Drop the flow here" "dropFlowHere": "Drop the flow here",
"config": {
"local": "on this flow",
"global": "on all flows"
}
}, },
"menu": { "menu": {
"label": { "label": {
@ -22,6 +26,7 @@
"show": "Toggle Sidebar" "show": "Toggle Sidebar"
}, },
"displayStatus": "Display Node Status", "displayStatus": "Display Node Status",
"displayConfig": "Configuration Nodes",
"import": "Import", "import": "Import",
"export": "Export", "export": "Export",
"clipboard": "Clipboard", "clipboard": "Clipboard",
@ -29,7 +34,7 @@
"subflows": "Subflows", "subflows": "Subflows",
"createSubflow": "Create Subflow", "createSubflow": "Create Subflow",
"selectionToSubflow": "Selection to Subflow", "selectionToSubflow": "Selection to Subflow",
"workspaces": "Workspaces", "flows": "Flows",
"add": "Add", "add": "Add",
"rename": "Rename", "rename": "Rename",
"delete": "Delete", "delete": "Delete",
@ -115,7 +120,10 @@
"nodesUse_plural": "__count__ nodes use this config", "nodesUse_plural": "__count__ nodes use this config",
"addNewConfig": "Add new __type__ config node", "addNewConfig": "Add new __type__ config node",
"editConfig": "Edit __type__ config node", "editConfig": "Edit __type__ config node",
"addNewType": "Add new __type__..." "addNewType": "Add new __type__...",
"errors": {
"scopeChange": "Changing the scope will make it unavailable to nodes in other flows that use it"
}
}, },
"keyboard": { "keyboard": {
"selectAll": "Select all nodes", "selectAll": "Select all nodes",