mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Merge pull request #2050 from node-red/subflow-props
Display parent subflow properties in subflow instance edit dialog
This commit is contained in:
commit
431266069e
@ -277,6 +277,10 @@
|
|||||||
"deleteSubflow": "delete subflow",
|
"deleteSubflow": "delete subflow",
|
||||||
"info": "Description",
|
"info": "Description",
|
||||||
"category": "Category",
|
"category": "Category",
|
||||||
|
"env": {
|
||||||
|
"restore": "Restore to subflow default",
|
||||||
|
"remove": "Remove environment variable"
|
||||||
|
},
|
||||||
"errors": {
|
"errors": {
|
||||||
"noNodesSelected": "<strong>Cannot create subflow</strong>: no nodes selected",
|
"noNodesSelected": "<strong>Cannot create subflow</strong>: no nodes selected",
|
||||||
"multipleInputsToSelection": "<strong>Cannot create subflow</strong>: multiple inputs to selection"
|
"multipleInputsToSelection": "<strong>Cannot create subflow</strong>: multiple inputs to selection"
|
||||||
|
@ -550,54 +550,129 @@ RED.editor = (function() {
|
|||||||
.editableList({
|
.editableList({
|
||||||
addItem: function(container, i, opt) {
|
addItem: function(container, i, opt) {
|
||||||
var row = $('<div/>').appendTo(container);
|
var row = $('<div/>').appendTo(container);
|
||||||
var nameField = $('<input/>', {
|
if (opt.parent) {
|
||||||
class: "node-input-env-name",
|
$('<div/>', {
|
||||||
type: "text",
|
class:"uneditable-input",
|
||||||
style: "margin-left: 5px; width: calc(40% - 5px)",
|
style: "margin-left: 5px; width: calc(40% - 8px)",
|
||||||
placeholder: RED._("common.label.name")
|
}).appendTo(row).text(opt.name);
|
||||||
}).appendTo(row);
|
} else {
|
||||||
|
$('<input/>', {
|
||||||
|
class: "node-input-env-name",
|
||||||
|
type: "text",
|
||||||
|
style: "margin-left: 5px; width: calc(40% - 8px)",
|
||||||
|
placeholder: RED._("common.label.name")
|
||||||
|
}).appendTo(row).val(opt.name);
|
||||||
|
}
|
||||||
var valueField = $('<input/>',{
|
var valueField = $('<input/>',{
|
||||||
class: "node-input-env-value",
|
class: "node-input-env-value",
|
||||||
type: "text",
|
type: "text",
|
||||||
style: "margin-left: 5px; width: calc(60% - 5px)"
|
style: "margin-left: 5px; width: calc(60% - 8px)"
|
||||||
}).appendTo(row)
|
}).appendTo(row)
|
||||||
|
|
||||||
valueField.typedInput({default:'str',
|
valueField.typedInput({default:'str',
|
||||||
types:['str','num','bool','json','bin','re','date']
|
types:['str','num','bool','json','bin','env']
|
||||||
});
|
});
|
||||||
if (opt) {
|
|
||||||
nameField.val(opt.name);
|
valueField.typedInput('type', opt.parent?(opt.type||opt.parent.type):opt.type);
|
||||||
valueField.typedInput('type', opt.type);
|
valueField.typedInput('value', opt.parent?(opt.value||opt.parent.value):opt.value);
|
||||||
valueField.typedInput('value', opt.value);
|
|
||||||
|
var actionButton = $('<a/>',{href:"#",class:"red-ui-editableList-item-remove editor-button editor-button-small"}).appendTo(container);
|
||||||
|
$('<i/>',{class:"fa "+(opt.parent?"fa-reply":"fa-remove")}).appendTo(actionButton);
|
||||||
|
container.parent().addClass("red-ui-editableList-item-removable");
|
||||||
|
if (opt.parent) {
|
||||||
|
if (opt.value && (opt.value !== opt.parent.value || opt.type !== opt.parent.type)) {
|
||||||
|
actionButton.show();
|
||||||
|
} else {
|
||||||
|
actionButton.hide();
|
||||||
|
}
|
||||||
|
var restoreTip = RED.popover.tooltip(actionButton,RED._("subflow.env.restore"));
|
||||||
|
valueField.change(function(evt) {
|
||||||
|
var newType = valueField.typedInput('type');
|
||||||
|
var newValue = valueField.typedInput('value');
|
||||||
|
if (newType === opt.parent.type && newValue === opt.parent.value) {
|
||||||
|
actionButton.hide();
|
||||||
|
} else {
|
||||||
|
actionButton.show();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
actionButton.click(function(evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
restoreTip.close();
|
||||||
|
valueField.typedInput('type', opt.parent.type);
|
||||||
|
valueField.typedInput('value', opt.parent.value);
|
||||||
|
})
|
||||||
|
} else {
|
||||||
|
var removeTip = RED.popover.tooltip(actionButton,RED._("subflow.env.remove"));
|
||||||
|
actionButton.click(function(evt) {
|
||||||
|
evt.preventDefault();
|
||||||
|
removeTip.close();
|
||||||
|
container.parent().addClass("red-ui-editableList-item-deleting")
|
||||||
|
container.fadeOut(300, function() {
|
||||||
|
env_container.editableList('removeItem',opt);
|
||||||
|
});
|
||||||
|
});
|
||||||
}
|
}
|
||||||
},
|
},
|
||||||
sortable: true,
|
sortable: false,
|
||||||
removable: true
|
removable: false
|
||||||
});
|
});
|
||||||
var envs = node.env;
|
var parentEnv = {};
|
||||||
if (envs) {
|
var envList = [];
|
||||||
for (var i = 0; i < envs.length; i++) {
|
if (/^subflow:/.test(node.type)) {
|
||||||
var env = envs[i];
|
var subflowDef = RED.nodes.subflow(node.type.substring(8));
|
||||||
env_container.editableList('addItem', env);
|
if (subflowDef.env) {
|
||||||
|
subflowDef.env.forEach(function(env) {
|
||||||
|
var item = {
|
||||||
|
name:env.name,
|
||||||
|
parent: {
|
||||||
|
type: env.type,
|
||||||
|
value: env.value
|
||||||
|
}
|
||||||
|
}
|
||||||
|
envList.push(item);
|
||||||
|
parentEnv[env.name] = item;
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (node.env) {
|
||||||
|
for (var i = 0; i < node.env.length; i++) {
|
||||||
|
var env = node.env[i];
|
||||||
|
if (parentEnv.hasOwnProperty(env.name)) {
|
||||||
|
parentEnv[env.name].type = env.type;
|
||||||
|
parentEnv[env.name].value = env.value;
|
||||||
|
} else {
|
||||||
|
envList.push({
|
||||||
|
name: env.name,
|
||||||
|
type: env.type,
|
||||||
|
value: env.value
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
envList.forEach(function(env) {
|
||||||
|
env_container.editableList('addItem', env);
|
||||||
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
function convEnv(editable_list) {
|
function exportEnvList(list) {
|
||||||
if (editable_list) {
|
if (list) {
|
||||||
var env = [];
|
var env = [];
|
||||||
editable_list.each(function(i) {
|
list.each(function(i) {
|
||||||
var entry = $(this);
|
var entry = $(this);
|
||||||
var nf = entry.find(".node-input-env-name");
|
var item = entry.data('data');
|
||||||
var vf = entry.find(".node-input-env-value");
|
var name = item.parent?item.name:entry.find(".node-input-env-name").val();
|
||||||
var name = nf.val();
|
var valueInput = entry.find(".node-input-env-value");
|
||||||
var value = vf.typedInput("value");
|
var value = valueInput.typedInput("value");
|
||||||
var type = vf.typedInput("type");
|
var type = valueInput.typedInput("type");
|
||||||
var item = {
|
if (!item.parent || (item.parent.value !== value || item.parent.type !== type)) {
|
||||||
name: name,
|
var item = {
|
||||||
type: type,
|
name: name,
|
||||||
value: value
|
type: type,
|
||||||
};
|
value: value
|
||||||
env.push(item);
|
};
|
||||||
|
env.push(item);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
return env;
|
return env;
|
||||||
}
|
}
|
||||||
@ -1343,7 +1418,7 @@ RED.editor = (function() {
|
|||||||
|
|
||||||
if (type === "subflow") {
|
if (type === "subflow") {
|
||||||
var old_env = editing_node.env;
|
var old_env = editing_node.env;
|
||||||
var new_env = convEnv($("#node-input-env-container").editableList("items"));
|
var new_env = exportEnvList($("#node-input-env-container").editableList("items"));
|
||||||
if (!isSameEnv(old_env, new_env)) {
|
if (!isSameEnv(old_env, new_env)) {
|
||||||
editing_node.env = new_env;
|
editing_node.env = new_env;
|
||||||
changes.env = editing_node.env;
|
changes.env = editing_node.env;
|
||||||
@ -2070,7 +2145,7 @@ RED.editor = (function() {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var old_env = editing_node.env;
|
var old_env = editing_node.env;
|
||||||
var new_env = convEnv($("#node-input-env-container").editableList("items"));
|
var new_env = exportEnvList($("#node-input-env-container").editableList("items"));
|
||||||
if (!isSameEnv(old_env, new_env)) {
|
if (!isSameEnv(old_env, new_env)) {
|
||||||
editing_node.env = new_env;
|
editing_node.env = new_env;
|
||||||
changes.env = editing_node.env;
|
changes.env = editing_node.env;
|
||||||
|
@ -265,7 +265,7 @@ class Subflow extends Flow {
|
|||||||
if (env && env.hasOwnProperty(name)) {
|
if (env && env.hasOwnProperty(name)) {
|
||||||
var val = env[name];
|
var val = env[name];
|
||||||
try {
|
try {
|
||||||
var ret = redUtil.evaluateNodeProperty(val.value, val.type, null, null, null);
|
var ret = redUtil.evaluateNodeProperty(val.value, val.type, this.node, null, null);
|
||||||
return ret;
|
return ret;
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
|
@ -166,7 +166,7 @@ describe('subflow', function() {
|
|||||||
n1.receive({payload:"foo"});
|
n1.receive({payload:"foo"});
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
it('should access env var of subflow instance', function(done) {
|
it('should access env var of subflow instance', function(done) {
|
||||||
var flow = [
|
var flow = [
|
||||||
{id:"t0", type:"tab", label:"", disabled:false, info:""},
|
{id:"t0", type:"tab", label:"", disabled:false, info:""},
|
||||||
@ -256,13 +256,11 @@ describe('subflow', function() {
|
|||||||
{id:"t0", type:"tab", label:"", disabled:false, info:""},
|
{id:"t0", type:"tab", label:"", disabled:false, info:""},
|
||||||
{id:"n1", x:10, y:10, z:"t0", type:"subflow:s1",
|
{id:"n1", x:10, y:10, z:"t0", type:"subflow:s1",
|
||||||
env: [
|
env: [
|
||||||
{name: "KS", type: "str", value: "STR"},
|
|
||||||
{name: "KN", type: "num", value: "100"},
|
{name: "KN", type: "num", value: "100"},
|
||||||
{name: "KB", type: "bool", value: "true"},
|
{name: "KB", type: "bool", value: "true"},
|
||||||
{name: "KJ", type: "json", value: "[1,2,3]"},
|
{name: "KJ", type: "json", value: "[1,2,3]"},
|
||||||
{name: "Kb", type: "bin", value: "[65,65]"},
|
{name: "Kb", type: "bin", value: "[65,65]"},
|
||||||
{name: "KR", type: "re", value: "[A-Z]"},
|
{name: "Ke", type: "env", value: "KS"}
|
||||||
{name: "KD", type: "date", value: ""}
|
|
||||||
],
|
],
|
||||||
wires:[["n2"]]},
|
wires:[["n2"]]},
|
||||||
{id:"n2", x:10, y:10, z:"t0", type:"helper", wires:[]},
|
{id:"n2", x:10, y:10, z:"t0", type:"helper", wires:[]},
|
||||||
@ -275,10 +273,13 @@ describe('subflow', function() {
|
|||||||
out:[{
|
out:[{
|
||||||
x:10, y:10,
|
x:10, y:10,
|
||||||
wires:[ {id:"s1-n1", port:0} ]
|
wires:[ {id:"s1-n1", port:0} ]
|
||||||
}]
|
}],
|
||||||
|
env: [
|
||||||
|
{name: "KS", type: "str", value: "STR"}
|
||||||
|
]
|
||||||
},
|
},
|
||||||
{id:"s1-n1", x:10, y:10, z:"s1", type:"function",
|
{id:"s1-n1", x:10, y:10, z:"s1", type:"function",
|
||||||
func:"msg.VS = env.get('KS'); msg.VN = env.get('KN'); msg.VB = env.get('KB'); msg.VJ = env.get('KJ'); msg.Vb = env.get('Kb'); msg.VR = env.get('KR'); msg.VD = env.get('KD'); return msg;",
|
func:"msg.VE = env.get('Ke'); msg.VS = env.get('KS'); msg.VN = env.get('KN'); msg.VB = env.get('KB'); msg.VJ = env.get('KJ'); msg.Vb = env.get('Kb'); return msg;",
|
||||||
wires:[]}
|
wires:[]}
|
||||||
];
|
];
|
||||||
helper.load(functionNode, flow, function() {
|
helper.load(functionNode, flow, function() {
|
||||||
@ -292,14 +293,10 @@ describe('subflow', function() {
|
|||||||
msg.should.have.property("VJ", [1,2,3]);
|
msg.should.have.property("VJ", [1,2,3]);
|
||||||
msg.should.have.property("Vb");
|
msg.should.have.property("Vb");
|
||||||
should.ok(msg.Vb instanceof Buffer);
|
should.ok(msg.Vb instanceof Buffer);
|
||||||
msg.should.have.property("VR");
|
msg.should.have.property("VE","STR");
|
||||||
should.ok(msg.VR instanceof RegExp);
|
|
||||||
msg.should.have.property("VD");
|
|
||||||
should.ok((typeof msg.VD) === "number");
|
|
||||||
done();
|
done();
|
||||||
}
|
}
|
||||||
catch (e) {
|
catch (e) {
|
||||||
console.log(e);
|
|
||||||
done(e);
|
done(e);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
Loading…
Reference in New Issue
Block a user