Config node tray

This commit is contained in:
Nick O'Leary 2016-02-27 23:13:19 +00:00
parent 41b10fd5e4
commit 6354b68bae
6 changed files with 309 additions and 196 deletions

View File

@ -596,7 +596,8 @@ RED.editor = (function() {
},0); },0);
} }
}, },
open: function(trayBody) { open: function(tray) {
var trayBody = tray.find('.editor-tray-body');
RED.keyboard.disable(); RED.keyboard.disable();
var dialogForm = $('<form id="dialog-form" class="form-horizontal"></form>').appendTo(trayBody); var dialogForm = $('<form id="dialog-form" class="form-horizontal"></form>').appendTo(trayBody);
dialogForm.html($("script[data-template-name='"+type+"']").html()); dialogForm.html($("script[data-template-name='"+type+"']").html());
@ -656,7 +657,6 @@ RED.editor = (function() {
RED.sidebar.info.refresh(editing_node); RED.sidebar.info.refresh(editing_node);
} }
RED.workspaces.refresh(); RED.workspaces.refresh();
RED.tray.close();
} }
} }
/*).parent().on('keydown', function(evt) { /*).parent().on('keydown', function(evt) {
@ -669,11 +669,15 @@ RED.editor = (function() {
*/ */
RED.tray.show(trayOptions); RED.tray.show(trayOptions);
} }
/**
* name - name of the property that holds this config node
* type - type of config node
* id - id of config node to edit. _ADD_ for a new one
*/
function showEditConfigNodeDialog(name,type,id) { function showEditConfigNodeDialog(name,type,id) {
var adding = (id == "_ADD_"); var adding = (id == "_ADD_");
var node_def = RED.nodes.getType(type); var node_def = RED.nodes.getType(type);
editing_config_node = RED.nodes.node(id); var editing_config_node = RED.nodes.node(id);
var ns; var ns;
if (node_def.set.module === "node-red") { if (node_def.set.module === "node-red") {
@ -681,12 +685,10 @@ RED.editor = (function() {
} else { } else {
ns = node_def.set.id; ns = node_def.set.id;
} }
var activeWorkspace = RED.nodes.workspace(RED.workspaces.active()); var activeWorkspace = RED.nodes.workspace(RED.workspaces.active());
if (!activeWorkspace) { if (!activeWorkspace) {
activeWorkspace = RED.nodes.subflow(RED.workspaces.active()); activeWorkspace = RED.nodes.subflow(RED.workspaces.active());
} }
if (editing_config_node == null) { if (editing_config_node == null) {
editing_config_node = { editing_config_node = {
id: (1+Math.random()*4294967295).toString(16), id: (1+Math.random()*4294967295).toString(16),
@ -702,149 +704,251 @@ RED.editor = (function() {
} }
editing_config_node["_"] = node_def._; editing_config_node["_"] = node_def._;
} }
editStack.push({node:editing_config_node});
$("#node-config-dialog-edit-form").html($("script[data-template-name='"+type+"']").html()); RED.view.state(RED.state.EDITING);
var trayOptions = {
$("#dialog-config-form").find('[data-i18n]').each(function() { title: (adding?RED._("editor.addNewConfig", {type:type}):RED._("editor.editConfig", {type:type})),
var current = $(this).attr("data-i18n"); resize: function() {
if (current.indexOf(":") === -1) { var editing_node = editStack[editStack.length-1];
var prefix = ""; if (editing_node && editing_node.node._def.oneditresize) {
if (current.indexOf("[")===0) { setTimeout(function() {
var parts = current.split("]"); var form = $("#node-config-dialog-edit-form");
prefix = parts[0]+"]"; editing_node.node._def.oneditresize.call(editing_node.node,{width:form.width(),height:form.height()});
current = parts[1]; },0);
} }
$(this).attr("data-i18n",prefix+ns+":"+current); },
open: function(tray) {
var trayHeader = tray.find(".editor-tray-header");
var trayBody = tray.find(".editor-tray-body");
var trayFooter = tray.find(".editor-tray-footer");
trayFooter.prepend('<div id="node-config-dialog-user-count"><i class="fa fa-info-circle"></i> <span></span></div>');
trayHeader.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>');
if (RED.view.state() != RED.state.EDITING) {
RED.keyboard.disable();
}
var dialogForm = $('<form id="node-config-dialog-edit-form" class="form-horizontal"></form>').appendTo(trayBody);
dialogForm.html($("script[data-template-name='"+type+"']").html());
dialogForm.find('[data-i18n]').each(function() {
var current = $(this).attr("data-i18n");
if (current.indexOf(":") === -1) {
var prefix = "";
if (current.indexOf("[")===0) {
var parts = current.split("]");
prefix = parts[0]+"]";
current = parts[1];
}
$(this).attr("data-i18n",prefix+ns+":"+current);
}
});
$('<input type="text" style="display: none;" />').prependTo(dialogForm);
prepareEditDialog(editing_config_node,node_def,"node-config-input");
if (editing_config_node._def.exclusive) {
$("#node-config-dialog-scope").hide();
} else {
$("#node-config-dialog-scope").show();
}
$("#node-config-dialog-scope-warning").hide();
var nodeUserFlows = {};
editing_config_node.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=""'+(!editing_config_node.z?" selected":"")+' data-i18n="sidebar.config.global"></option>');
tabSelect.append('<option disabled data-i18n="sidebar.config.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==editing_config_node.z?" selected":"")+'>'+workspaceLabel+'</option>');
});
tabSelect.append('<option disabled data-i18n="sidebar.config.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==editing_config_node.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.i18n();
dialogForm.i18n();
$("#node-config-dialog-user-count").find("span").html(RED._("editor.nodesUse", {count:editing_config_node.users.length})).parent().show();
},
close: function() {
if (RED.view.state() != RED.state.EDITING) {
RED.keyboard.enable();
}
RED.workspaces.refresh();
} }
}); }
trayOptions.buttons = [
{
prepareEditDialog(editing_config_node,node_def,"node-config-input"); id: "node-config-dialog-ok",
text: adding?RED._("editor.configAdd"):RED._("editor.configUpdate"),
var buttons = $( "#node-config-dialog" ).dialog("option","buttons"); click: function() {
if (adding) { var configProperty = name;
if (buttons.length == 3) { var configId = editing_config_node.id;
buttons = buttons.splice(1); var configType = type;
} var configAdding = adding;
buttons[0].text = "Add"; var configTypeDef = RED.nodes.getType(configType);
$("#node-config-dialog-user-count").find("span").html("").parent().hide(); var d;
} else { var input;
if (buttons.length == 2) { var scope = $("#node-config-dialog-scope").val();
buttons.unshift({ for (d in configTypeDef.defaults) {
class: 'leftButton', if (configTypeDef.defaults.hasOwnProperty(d)) {
text: RED._("editor.configDelete"), input = $("#node-config-input-"+d);
click: function() { if (input.attr('type') === "checkbox") {
var configProperty = $(this).dialog('option','node-property'); editing_config_node[d] = input.prop('checked');
var configId = $(this).dialog('option','node-id'); } else {
var configType = $(this).dialog('option','node-type'); editing_config_node[d] = input.val();
var configTypeDef = RED.nodes.getType(configType);
if (configTypeDef.ondelete) {
configTypeDef.ondelete.call(editing_config_node);
} }
if (configTypeDef.oneditdelete) { }
configTypeDef.oneditdelete.call(editing_config_node); }
} editing_config_node.label = configTypeDef.label;
var historyEvent = { editing_config_node.z = scope;
t:'delete',
nodes:[editing_config_node], if (scope) {
changes: {}, editing_config_node.users = editing_config_node.users.filter(function(n) {
dirty: RED.nodes.dirty() var keep = true;
} for (var d in n._def.defaults) {
RED.nodes.remove(configId); if (n._def.defaults.hasOwnProperty(d)) {
for (var i=0;i<editing_config_node.users.length;i++) { if (n._def.defaults[d].type === editing_config_node.type &&
var user = editing_config_node.users[i]; n[d] === editing_config_node.id &&
historyEvent.changes[user.id] = { n.z !== scope) {
changed: user.changed, keep = false;
valid: user.valid n[d] = null;
}; n.dirty = true;
for (var d in user._def.defaults) { n.changed = true;
if (user._def.defaults.hasOwnProperty(d) && user[d] == configId) { validateNode(n);
historyEvent.changes[user.id][d] = configId
user[d] = "";
user.changed = true;
user.dirty = true;
} }
} }
validateNode(user);
} }
updateConfigNodeSelect(configProperty,configType,""); return keep;
RED.nodes.dirty(true); });
$( this ).dialog( "close" ); }
RED.view.redraw();
RED.history.push(historyEvent); if (configAdding) {
RED.nodes.add(editing_config_node);
}
if (configTypeDef.oneditsave) {
configTypeDef.oneditsave.call(editing_config_node);
}
if (configTypeDef.credentials) {
updateNodeCredentials(editing_config_node,configTypeDef.credentials,"node-config-input");
}
validateNode(editing_config_node);
for (var i=0;i<editing_config_node.users.length;i++) {
var user = editing_config_node.users[i];
validateNode(user);
}
updateConfigNodeSelect(configProperty,configType,editing_config_node.id);
RED.nodes.dirty(true);
RED.view.redraw(true);
RED.tray.close();
}
},
{
id: "node-config-dialog-cancel",
text: RED._("common.label.cancel"),
click: function() {
var configType = type;
var configId = editing_config_node.id;
var configAdding = adding;
var configTypeDef = RED.nodes.getType(configType);
if (configTypeDef.oneditcancel) {
// TODO: what to pass as this to call
if (configTypeDef.oneditcancel) {
var cn = RED.nodes.node(configId);
if (cn) {
configTypeDef.oneditcancel.call(cn,false);
} else {
configTypeDef.oneditcancel.call({id:configId},true);
}
} }
}); }
RED.tray.close();
}
} }
buttons[1].text = "Update"; ];
$("#node-config-dialog-user-count").find("span").html(RED._("editor.nodesUse", {count:editing_config_node.users.length})).parent().show();
}
if (editing_config_node._def.exclusive) { if (!adding) {
$("#node-config-dialog-scope").hide(); trayOptions.buttons.unshift({
} else { class: 'leftButton',
$("#node-config-dialog-scope").show(); text: RED._("editor.configDelete"),
} click: function() {
$("#node-config-dialog-scope-warning").hide(); var configProperty = name;
var configId = editing_config_node.id;
var configType = type;
var configTypeDef = RED.nodes.getType(configType);
if (configTypeDef.ondelete) {
var nodeUserFlows = {}; configTypeDef.ondelete.call(editing_config_node);
editing_config_node.users.forEach(function(n) { }
nodeUserFlows[n.z] = true; if (configTypeDef.oneditdelete) {
}); configTypeDef.oneditdelete.call(editing_config_node);
var flowCount = Object.keys(nodeUserFlows).length; }
var historyEvent = {
var tabSelect = $("#node-config-dialog-scope").empty(); t:'delete',
tabSelect.off("change"); nodes:[editing_config_node],
tabSelect.append('<option value=""'+(!editing_config_node.z?" selected":"")+' data-i18n="sidebar.config.global"></option>'); changes: {},
tabSelect.append('<option disabled data-i18n="sidebar.config.flows"></option>'); dirty: RED.nodes.dirty()
RED.nodes.eachWorkspace(function(ws) { }
var workspaceLabel = ws.label; RED.nodes.remove(configId);
if (nodeUserFlows[ws.id]) { for (var i=0;i<editing_config_node.users.length;i++) {
workspaceLabel = "* "+workspaceLabel; var user = editing_config_node.users[i];
} historyEvent.changes[user.id] = {
tabSelect.append('<option value="'+ws.id+'"'+(ws.id==editing_config_node.z?" selected":"")+'>'+workspaceLabel+'</option>'); changed: user.changed,
}); valid: user.valid
tabSelect.append('<option disabled data-i18n="sidebar.config.subflows"></option>'); };
RED.nodes.eachSubflow(function(ws) { for (var d in user._def.defaults) {
var workspaceLabel = ws.name; if (user._def.defaults.hasOwnProperty(d) && user[d] == configId) {
if (nodeUserFlows[ws.id]) { historyEvent.changes[user.id][d] = configId
workspaceLabel = "* "+workspaceLabel; user[d] = "";
} user.changed = true;
tabSelect.append('<option value="'+ws.id+'"'+(ws.id==editing_config_node.z?" selected":"")+'>'+workspaceLabel+'</option>'); user.dirty = true;
}); }
if (flowCount > 0) { }
tabSelect.on('change',function() { validateNode(user);
var newScope = $(this).val(); }
if (newScope === '') { updateConfigNodeSelect(configProperty,configType,"");
// global scope - everyone can use it RED.nodes.dirty(true);
$("#node-config-dialog-scope-warning").hide(); RED.view.redraw();
} else if (!nodeUserFlows[newScope] || flowCount > 1) { RED.history.push(historyEvent);
// a user will loose access to it RED.tray.close();
$("#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>'); RED.tray.show(trayOptions);
tabSelect.i18n();
$( "#node-config-dialog" ).dialog("option","buttons",buttons);
$("#node-config-dialog").i18n();
$( "#node-config-dialog" )
.dialog("option","node-adding",adding)
.dialog("option","node-property",name)
.dialog("option","node-id",editing_config_node.id)
.dialog("option","node-type",type)
.dialog("option","title",(adding?RED._("editor.addNewConfig", {type:type}):RED._("editor.editConfig", {type:type})))
.dialog( "open" );
} }
function updateConfigNodeSelect(name,type,value) { function updateConfigNodeSelect(name,type,value) {
var button = $("#node-input-edit-"+name); var button = $("#node-input-edit-"+name);
if (button.length) { if (button.length) {

View File

@ -20,6 +20,62 @@ RED.tray = (function() {
function resize() { function resize() {
} }
function showTray(options) {
var el = $('<div class="editor-tray"></div>');
var header = $('<div class="editor-tray-header">'+(options.title||"")+'</div>').appendTo(el);
var body = $('<div class="editor-tray-body"></div>').appendTo(el);
var footer = $('<div class="editor-tray-footer"></div>').appendTo(el);
if (options.buttons) {
for (var i=0;i<options.buttons.length;i++) {
var button = options.buttons[i];
var b = $('<button>').appendTo(footer);
if (button.id) {
b.attr('id',button.id);
}
if (button.text) {
b.text(button.text);
}
if (button.click) {
b.click(button.click);
}
if (button.class) {
b.addClass(button.class);
}
}
}
el.appendTo("#editor-stack");
var tray = {
tray: el,
header: header,
body: body,
footer: footer,
options: options
};
if (options.open) {
options.open(el);
}
$("#editor-shade").show();
el.css({
right: -(el.width()+10)+"px",
transition: "right 0.2s ease"
});
$("#workspace").scrollLeft(0);
stack.push(tray);
setTimeout(function() {
var trayHeight = el.height()-header.outerHeight()-footer.outerHeight();
body.height(trayHeight-40);
if (options.resize) {
options.resize();
}
el.css({right:0});
},0);
}
return { return {
init: function() { init: function() {
$( window ).resize(function() { $( window ).resize(function() {
@ -43,61 +99,12 @@ RED.tray = (function() {
}); });
setTimeout(function() { setTimeout(function() {
oldTray.tray.detach(); oldTray.tray.detach();
},400) showTray(options);
} },200)
var el = $('<div class="editor-tray"></div>'); } else {
var header = $('<div class="editor-tray-header">'+(options.title||"")+'</div>').appendTo(el); showTray(options);
var body = $('<div class="editor-tray-body"></div>').appendTo(el);
var footer = $('<div class="editor-tray-footer"></div>').appendTo(el);
//'<form id="dialog-form" class="form-horizontal"></form>'+
// '<button type="button" id="node-dialog-ok">Ok</button>'+
// '<button type="button" id="node-dialog-cancel">Cancel</button>'+
if (options.buttons) {
for (var i=0;i<options.buttons.length;i++) {
var button = options.buttons[i];
var b = $('<button>').appendTo(footer);
if (button.id) {
b.attr('id',button.id);
}
if (button.text) {
b.text(button.text);
}
if (button.click) {
b.click(button.click);
}
}
}
el.appendTo("#editor-stack");
var tray = {
tray: el,
header: header,
body: body,
footer: footer,
options: options
};
if (options.open) {
options.open(body);
} }
$("#editor-shade").show();
el.css({
right: -(el.width()+10)+"px",
transition: "right 0.3s ease"
});
$("#workspace").scrollLeft(0);
stack.push(tray);
setTimeout(function() {
var trayHeight = el.height()-header.outerHeight()-footer.outerHeight();
body.height(trayHeight-40);
if (options.resize) {
options.resize();
}
el.css({right:0});
},0);
}, },
close: function close() { close: function close() {
if (stack.length > 0) { if (stack.length > 0) {
@ -117,7 +124,7 @@ RED.tray = (function() {
oldTray.tray.css({right:0}); oldTray.tray.css({right:0});
},0); },0);
} }
},400) },200)
if (stack.length === 0) { if (stack.length === 0) {
$("#editor-shade").hide(); $("#editor-shade").hide();
} }

View File

@ -23,10 +23,6 @@
border-color: rgb(214, 97, 95) !important; border-color: rgb(214, 97, 95) !important;
} }
.ui-dialog .ui-dialog-buttonpane button.leftButton {
margin-right: 40px;
}
.form-row { .form-row {
clear: both; clear: both;
color: $form-text-color; color: $form-text-color;

View File

@ -22,7 +22,7 @@
width: 315px; width: 315px;
background: #fff; background: #fff;
box-sizing: border-box; box-sizing: border-box;
z-index: 100; z-index: 10;
@include component-border; @include component-border;
} }
@ -47,7 +47,7 @@
right: 315px; right: 315px;
bottom:10px; bottom:10px;
width: 7px; width: 7px;
z-index: 101; z-index: 11;
background: $background-color url(images/grip.png) no-repeat 50% 50%; background: $background-color url(images/grip.png) no-repeat 50% 50%;
cursor: col-resize; cursor: col-resize;
} }

View File

@ -97,9 +97,14 @@
button { button {
@include workspace-button; @include workspace-button;
padding: 0.4em 1em; padding: 0.4em 1em;
} margin-right: 8px;
&.leftButton {
margin-right: 40px;
}
}
} }
#editor-shade { #editor-shade {
position: absolute; position: absolute;
top:0; top:0;

View File

@ -121,8 +121,9 @@
} }
}, },
"editor": { "editor": {
"configEdit": "edit", "configEdit": "Edit",
"configAdd": "add", "configAdd": "Add",
"configUpdate": "Update",
"configDelete": "Delete", "configDelete": "Delete",
"nodesUse": "__count__ node uses this config", "nodesUse": "__count__ node uses this config",
"nodesUse_plural": "__count__ nodes use this config", "nodesUse_plural": "__count__ nodes use this config",