mirror of
https://github.com/node-red/node-red.git
synced 2023-10-10 13:36:53 +02:00
Clean up subflow editor
- new appearance of subflow tabs - input/output buttons now counters - allow multiple input wires to the same node when converting to subflow - ensure edit history is propagated properly to instance nodes
This commit is contained in:
parent
d1a5395727
commit
fdbf079896
@ -15,7 +15,7 @@
|
|||||||
**/
|
**/
|
||||||
RED.history = (function() {
|
RED.history = (function() {
|
||||||
var undo_history = [];
|
var undo_history = [];
|
||||||
|
|
||||||
return {
|
return {
|
||||||
//TODO: this function is a placeholder until there is a 'save' event that can be listened to
|
//TODO: this function is a placeholder until there is a 'save' event that can be listened to
|
||||||
markAllDirty: function() {
|
markAllDirty: function() {
|
||||||
@ -62,6 +62,23 @@ RED.history = (function() {
|
|||||||
RED.workspaces.remove(ev.subflows[i]);
|
RED.workspaces.remove(ev.subflows[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ev.subflow) {
|
||||||
|
if (ev.subflow.instances) {
|
||||||
|
ev.subflow.instances.forEach(function(n) {
|
||||||
|
var node = RED.nodes.node(n.id);
|
||||||
|
if (node) {
|
||||||
|
node.changed = n.changed;
|
||||||
|
node.dirty = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
if (ev.subflow.hasOwnProperty('changed')) {
|
||||||
|
var subflow = RED.nodes.subflow(ev.subflow.id);
|
||||||
|
if (subflow) {
|
||||||
|
subflow.changed = ev.subflow.changed;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
} else if (ev.t == "delete") {
|
} else if (ev.t == "delete") {
|
||||||
if (ev.workspaces) {
|
if (ev.workspaces) {
|
||||||
for (i=0;i<ev.workspaces.length;i++) {
|
for (i=0;i<ev.workspaces.length;i++) {
|
||||||
@ -69,8 +86,8 @@ RED.history = (function() {
|
|||||||
RED.workspaces.add(ev.workspaces[i]);
|
RED.workspaces.add(ev.workspaces[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (ev.subflow) {
|
if (ev.subflow && ev.subflow.subflow) {
|
||||||
RED.nodes.addSubflow(ev.subflow);
|
RED.nodes.addSubflow(ev.subflow.subflow);
|
||||||
}
|
}
|
||||||
var subflow;
|
var subflow;
|
||||||
if (ev.subflowInputs && ev.subflowInputs.length > 0) {
|
if (ev.subflowInputs && ev.subflowInputs.length > 0) {
|
||||||
@ -97,9 +114,17 @@ RED.history = (function() {
|
|||||||
});
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ev.subflow && ev.subflow.hasOwnProperty('instances')) {
|
||||||
|
ev.subflow.instances.forEach(function(n) {
|
||||||
|
var node = RED.nodes.node(n.id);
|
||||||
|
if (node) {
|
||||||
|
node.changed = n.changed;
|
||||||
|
node.dirty = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
if (subflow) {
|
if (subflow) {
|
||||||
RED.nodes.filterNodes({type:"subflow:"+subflow.id}).forEach(function(n) {
|
RED.nodes.filterNodes({type:"subflow:"+subflow.id}).forEach(function(n) {
|
||||||
n.changed = true;
|
|
||||||
n.inputs = subflow.in.length;
|
n.inputs = subflow.in.length;
|
||||||
n.outputs = subflow.out.length;
|
n.outputs = subflow.out.length;
|
||||||
while (n.outputs > n.ports.length) {
|
while (n.outputs > n.ports.length) {
|
||||||
@ -148,13 +173,21 @@ RED.history = (function() {
|
|||||||
ev.node.out = ev.node.out.concat(ev.subflow.outputs);
|
ev.node.out = ev.node.out.concat(ev.subflow.outputs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (ev.subflow.hasOwnProperty('instances')) {
|
||||||
|
ev.subflow.instances.forEach(function(n) {
|
||||||
|
var node = RED.nodes.node(n.id);
|
||||||
|
if (node) {
|
||||||
|
node.changed = n.changed;
|
||||||
|
node.dirty = true;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
RED.nodes.filterNodes({type:"subflow:"+ev.node.id}).forEach(function(n) {
|
RED.nodes.filterNodes({type:"subflow:"+ev.node.id}).forEach(function(n) {
|
||||||
n.changed = ev.changed;
|
|
||||||
n.inputs = ev.node.in.length;
|
n.inputs = ev.node.in.length;
|
||||||
n.outputs = ev.node.out.length;
|
n.outputs = ev.node.out.length;
|
||||||
RED.editor.updateNodeProperties(n);
|
RED.editor.updateNodeProperties(n);
|
||||||
});
|
});
|
||||||
|
|
||||||
RED.palette.refresh();
|
RED.palette.refresh();
|
||||||
} else {
|
} else {
|
||||||
RED.editor.updateNodeProperties(ev.node);
|
RED.editor.updateNodeProperties(ev.node);
|
||||||
@ -182,10 +215,10 @@ RED.history = (function() {
|
|||||||
RED.nodes.removeLink(ev.links[i]);
|
RED.nodes.removeLink(ev.links[i]);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
RED.nodes.removeSubflow(ev.subflow);
|
RED.nodes.removeSubflow(ev.subflow.subflow);
|
||||||
RED.workspaces.remove(ev.subflow);
|
RED.workspaces.remove(ev.subflow.subflow);
|
||||||
|
|
||||||
if (ev.removedLinks) {
|
if (ev.removedLinks) {
|
||||||
for (i=0;i<ev.removedLinks.length;i++) {
|
for (i=0;i<ev.removedLinks.length;i++) {
|
||||||
RED.nodes.addLink(ev.removedLinks[i]);
|
RED.nodes.addLink(ev.removedLinks[i]);
|
||||||
@ -199,7 +232,6 @@ RED.history = (function() {
|
|||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
|
|
||||||
RED.nodes.dirty(ev.dirty);
|
RED.nodes.dirty(ev.dirty);
|
||||||
RED.view.redraw(true);
|
RED.view.redraw(true);
|
||||||
RED.palette.refresh();
|
RED.palette.refresh();
|
||||||
|
@ -33,7 +33,6 @@ RED.editor = (function() {
|
|||||||
var subflow;
|
var subflow;
|
||||||
var isValid;
|
var isValid;
|
||||||
var hasChanged;
|
var hasChanged;
|
||||||
|
|
||||||
if (node.type.indexOf("subflow:")===0) {
|
if (node.type.indexOf("subflow:")===0) {
|
||||||
subflow = RED.nodes.subflow(node.type.substring(8));
|
subflow = RED.nodes.subflow(node.type.substring(8));
|
||||||
isValid = subflow.valid;
|
isValid = subflow.valid;
|
||||||
@ -43,7 +42,7 @@ RED.editor = (function() {
|
|||||||
hasChanged = subflow.changed;
|
hasChanged = subflow.changed;
|
||||||
}
|
}
|
||||||
node.valid = isValid;
|
node.valid = isValid;
|
||||||
node.changed = hasChanged;
|
node.changed = node.changed || hasChanged;
|
||||||
} else if (node._def) {
|
} else if (node._def) {
|
||||||
node.valid = validateNodeProperties(node, node._def.defaults, node);
|
node.valid = validateNodeProperties(node, node._def.defaults, node);
|
||||||
if (node._def._creds) {
|
if (node._def._creds) {
|
||||||
@ -65,7 +64,7 @@ RED.editor = (function() {
|
|||||||
var modifiedTabs = {};
|
var modifiedTabs = {};
|
||||||
for (i=0;i<subflowInstances.length;i++) {
|
for (i=0;i<subflowInstances.length;i++) {
|
||||||
subflowInstances[i].valid = node.valid;
|
subflowInstances[i].valid = node.valid;
|
||||||
subflowInstances[i].changed = node.changed;
|
subflowInstances[i].changed = subflowInstances[i].changed || node.changed;
|
||||||
subflowInstances[i].dirty = true;
|
subflowInstances[i].dirty = true;
|
||||||
modifiedTabs[subflowInstances[i].z] = true;
|
modifiedTabs[subflowInstances[i].z] = true;
|
||||||
}
|
}
|
||||||
@ -270,7 +269,36 @@ RED.editor = (function() {
|
|||||||
var wasChanged = editing_node.changed;
|
var wasChanged = editing_node.changed;
|
||||||
editing_node.changed = true;
|
editing_node.changed = true;
|
||||||
RED.nodes.dirty(true);
|
RED.nodes.dirty(true);
|
||||||
RED.history.push({t:'edit',node:editing_node,changes:changes,links:removedLinks,dirty:wasDirty,changed:wasChanged});
|
|
||||||
|
var activeSubflow = RED.nodes.subflow(RED.workspaces.active());
|
||||||
|
if (activeSubflow) {
|
||||||
|
var subflowInstances = [];
|
||||||
|
RED.nodes.eachNode(function(n) {
|
||||||
|
if (n.type == "subflow:"+RED.workspaces.active()) {
|
||||||
|
subflowInstances.push({
|
||||||
|
id:n.id,
|
||||||
|
changed:n.changed
|
||||||
|
});
|
||||||
|
n.changed = true;
|
||||||
|
n.dirty = true;
|
||||||
|
updateNodeProperties(n);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
var historyEvent = {
|
||||||
|
t:'edit',
|
||||||
|
node:editing_node,
|
||||||
|
changes:changes,
|
||||||
|
links:removedLinks,
|
||||||
|
dirty:wasDirty,
|
||||||
|
changed:wasChanged
|
||||||
|
};
|
||||||
|
if (subflowInstances) {
|
||||||
|
historyEvent.subflow = {
|
||||||
|
instances:subflowInstances
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RED.history.push(historyEvent);
|
||||||
}
|
}
|
||||||
editing_node.dirty = true;
|
editing_node.dirty = true;
|
||||||
validateNode(editing_node);
|
validateNode(editing_node);
|
||||||
@ -900,15 +928,21 @@ 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(RED._("subflow.tabLabel",{name:newName}));
|
$("#menu-item-workspace-menu-"+editing_node.id.replace(".","-")).text(newName);
|
||||||
}
|
}
|
||||||
|
|
||||||
RED.palette.refresh();
|
RED.palette.refresh();
|
||||||
|
|
||||||
if (changed) {
|
if (changed) {
|
||||||
|
var subflowInstances = [];
|
||||||
RED.nodes.eachNode(function(n) {
|
RED.nodes.eachNode(function(n) {
|
||||||
if (n.type == "subflow:"+editing_node.id) {
|
if (n.type == "subflow:"+editing_node.id) {
|
||||||
|
subflowInstances.push({
|
||||||
|
id:n.id,
|
||||||
|
changed:n.changed
|
||||||
|
})
|
||||||
n.changed = true;
|
n.changed = true;
|
||||||
|
n.dirty = true;
|
||||||
updateNodeProperties(n);
|
updateNodeProperties(n);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -920,7 +954,10 @@ RED.editor = (function() {
|
|||||||
node:editing_node,
|
node:editing_node,
|
||||||
changes:changes,
|
changes:changes,
|
||||||
dirty:wasDirty,
|
dirty:wasDirty,
|
||||||
changed:wasChanged
|
changed:wasChanged,
|
||||||
|
subflow: {
|
||||||
|
instances:subflowInstances
|
||||||
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
RED.history.push(historyEvent);
|
RED.history.push(historyEvent);
|
||||||
|
@ -21,8 +21,11 @@ RED.subflow = (function() {
|
|||||||
return RED.nodes.subflow(RED.workspaces.active());
|
return RED.nodes.subflow(RED.workspaces.active());
|
||||||
}
|
}
|
||||||
|
|
||||||
function findAvailableSubflowIOPosition(subflow) {
|
function findAvailableSubflowIOPosition(subflow,isInput) {
|
||||||
var pos = {x:70,y:70};
|
var pos = {x:50,y:30};
|
||||||
|
if (!isInput) {
|
||||||
|
pos.x += 110;
|
||||||
|
}
|
||||||
for (var i=0;i<subflow.out.length+subflow.in.length;i++) {
|
for (var i=0;i<subflow.out.length+subflow.in.length;i++) {
|
||||||
var port;
|
var port;
|
||||||
if (i < subflow.out.length) {
|
if (i < subflow.out.length) {
|
||||||
@ -40,7 +43,10 @@ RED.subflow = (function() {
|
|||||||
|
|
||||||
function addSubflowInput() {
|
function addSubflowInput() {
|
||||||
var subflow = RED.nodes.subflow(RED.workspaces.active());
|
var subflow = RED.nodes.subflow(RED.workspaces.active());
|
||||||
var position = findAvailableSubflowIOPosition(subflow);
|
if (subflow.in.length === 1) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var position = findAvailableSubflowIOPosition(subflow,true);
|
||||||
var newInput = {
|
var newInput = {
|
||||||
type:"subflow",
|
type:"subflow",
|
||||||
direction:"in",
|
direction:"in",
|
||||||
@ -56,31 +62,50 @@ RED.subflow = (function() {
|
|||||||
var wasDirty = RED.nodes.dirty();
|
var wasDirty = RED.nodes.dirty();
|
||||||
var wasChanged = subflow.changed;
|
var wasChanged = subflow.changed;
|
||||||
subflow.changed = true;
|
subflow.changed = true;
|
||||||
|
var result = refresh(true);
|
||||||
RED.nodes.eachNode(function(n) {
|
|
||||||
if (n.type == "subflow:"+subflow.id) {
|
|
||||||
n.changed = true;
|
|
||||||
n.inputs = subflow.in.length;
|
|
||||||
RED.editor.updateNodeProperties(n);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var historyEvent = {
|
var historyEvent = {
|
||||||
t:'edit',
|
t:'edit',
|
||||||
node:subflow,
|
node:subflow,
|
||||||
dirty:wasDirty,
|
dirty:wasDirty,
|
||||||
changed:wasChanged,
|
changed:wasChanged,
|
||||||
subflow: {
|
subflow: {
|
||||||
inputCount: oldInCount
|
inputCount: oldInCount,
|
||||||
|
instances: result.instances
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
RED.history.push(historyEvent);
|
RED.history.push(historyEvent);
|
||||||
$("#workspace-subflow-add-input").toggleClass("disabled",true);
|
|
||||||
RED.view.select();
|
RED.view.select();
|
||||||
|
RED.nodes.dirty(true);
|
||||||
|
RED.view.redraw();
|
||||||
|
$("#workspace-subflow-input-add").addClass("active");
|
||||||
|
$("#workspace-subflow-input-remove").removeClass("active");
|
||||||
|
}
|
||||||
|
|
||||||
|
function removeSubflowInput() {
|
||||||
|
var activeSubflow = RED.nodes.subflow(RED.workspaces.active());
|
||||||
|
if (activeSubflow.in.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
var removedInput = activeSubflow.in[0];
|
||||||
|
var removedInputLinks = [];
|
||||||
|
RED.nodes.eachLink(function(l) {
|
||||||
|
if (l.source.type == "subflow" && l.source.z == activeSubflow.id && l.source.i == removedInput.i) {
|
||||||
|
removedInputLinks.push(l);
|
||||||
|
} else if (l.target.type == "subflow:"+activeSubflow.id) {
|
||||||
|
removedInputLinks.push(l);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
removedInputLinks.forEach(function(l) { RED.nodes.removeLink(l)});
|
||||||
|
activeSubflow.in = [];
|
||||||
|
$("#workspace-subflow-input-add").removeClass("active");
|
||||||
|
$("#workspace-subflow-input-remove").addClass("active");
|
||||||
|
activeSubflow.changed = true;
|
||||||
|
return {subflowInputs: [ removedInput ], links:removedInputLinks};
|
||||||
}
|
}
|
||||||
|
|
||||||
function addSubflowOutput(id) {
|
function addSubflowOutput(id) {
|
||||||
var subflow = RED.nodes.subflow(RED.workspaces.active());
|
var subflow = RED.nodes.subflow(RED.workspaces.active());
|
||||||
var position = findAvailableSubflowIOPosition(subflow);
|
var position = findAvailableSubflowIOPosition(subflow,false);
|
||||||
|
|
||||||
var newOutput = {
|
var newOutput = {
|
||||||
type:"subflow",
|
type:"subflow",
|
||||||
@ -98,45 +123,186 @@ RED.subflow = (function() {
|
|||||||
var wasChanged = subflow.changed;
|
var wasChanged = subflow.changed;
|
||||||
subflow.changed = true;
|
subflow.changed = true;
|
||||||
|
|
||||||
RED.nodes.eachNode(function(n) {
|
var result = refresh(true);
|
||||||
if (n.type == "subflow:"+subflow.id) {
|
|
||||||
n.changed = true;
|
|
||||||
n.outputs = subflow.out.length;
|
|
||||||
RED.editor.updateNodeProperties(n);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
var historyEvent = {
|
var historyEvent = {
|
||||||
t:'edit',
|
t:'edit',
|
||||||
node:subflow,
|
node:subflow,
|
||||||
dirty:wasDirty,
|
dirty:wasDirty,
|
||||||
changed:wasChanged,
|
changed:wasChanged,
|
||||||
subflow: {
|
subflow: {
|
||||||
outputCount: oldOutCount
|
outputCount: oldOutCount,
|
||||||
|
instances: result.instances
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
RED.history.push(historyEvent);
|
RED.history.push(historyEvent);
|
||||||
RED.view.select();
|
RED.view.select();
|
||||||
|
RED.nodes.dirty(true);
|
||||||
|
RED.view.redraw();
|
||||||
|
$("#workspace-subflow-output .spinner-value").html(subflow.out.length);
|
||||||
}
|
}
|
||||||
|
|
||||||
function init() {
|
function removeSubflowOutput(removedSubflowOutputs) {
|
||||||
|
var activeSubflow = RED.nodes.subflow(RED.workspaces.active());
|
||||||
|
if (activeSubflow.out.length === 0) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
|
if (typeof removedSubflowOutputs === "undefined") {
|
||||||
|
removedSubflowOutputs = [activeSubflow.out[activeSubflow.out.length-1]];
|
||||||
|
}
|
||||||
|
var removedLinks = [];
|
||||||
|
removedSubflowOutputs.sort(function(a,b) { return b.i-a.i});
|
||||||
|
for (i=0;i<removedSubflowOutputs.length;i++) {
|
||||||
|
var output = removedSubflowOutputs[i];
|
||||||
|
activeSubflow.out.splice(output.i,1);
|
||||||
|
var subflowRemovedLinks = [];
|
||||||
|
var subflowMovedLinks = [];
|
||||||
|
RED.nodes.eachLink(function(l) {
|
||||||
|
if (l.target.type == "subflow" && l.target.z == activeSubflow.id && l.target.i == output.i) {
|
||||||
|
subflowRemovedLinks.push(l);
|
||||||
|
}
|
||||||
|
if (l.source.type == "subflow:"+activeSubflow.id) {
|
||||||
|
if (l.sourcePort == output.i) {
|
||||||
|
subflowRemovedLinks.push(l);
|
||||||
|
} else if (l.sourcePort > output.i) {
|
||||||
|
subflowMovedLinks.push(l);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
});
|
||||||
|
subflowRemovedLinks.forEach(function(l) { RED.nodes.removeLink(l)});
|
||||||
|
subflowMovedLinks.forEach(function(l) { l.sourcePort--; });
|
||||||
|
|
||||||
|
removedLinks = removedLinks.concat(subflowRemovedLinks);
|
||||||
|
for (var j=output.i;j<activeSubflow.out.length;j++) {
|
||||||
|
activeSubflow.out[j].i--;
|
||||||
|
activeSubflow.out[j].dirty = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
activeSubflow.changed = true;
|
||||||
|
|
||||||
|
return {subflowOutputs: removedSubflowOutputs, links: removedLinks}
|
||||||
|
}
|
||||||
|
|
||||||
|
function refresh(markChange) {
|
||||||
|
var activeSubflow = RED.nodes.subflow(RED.workspaces.active());
|
||||||
|
refreshToolbar(activeSubflow);
|
||||||
|
var subflowInstances = [];
|
||||||
|
if (activeSubflow) {
|
||||||
|
RED.nodes.filterNodes({type:"subflow:"+activeSubflow.id}).forEach(function(n) {
|
||||||
|
subflowInstances.push({
|
||||||
|
id: n.id,
|
||||||
|
changed: n.changed
|
||||||
|
});
|
||||||
|
if (markChange) {
|
||||||
|
n.changed = true;
|
||||||
|
}
|
||||||
|
n.inputs = activeSubflow.in.length;
|
||||||
|
n.outputs = activeSubflow.out.length;
|
||||||
|
while (n.outputs < n.ports.length) {
|
||||||
|
n.ports.pop();
|
||||||
|
}
|
||||||
|
n.resize = true;
|
||||||
|
n.dirty = true;
|
||||||
|
RED.editor.updateNodeProperties(n);
|
||||||
|
});
|
||||||
|
RED.editor.validateNode(activeSubflow);
|
||||||
|
return {
|
||||||
|
instances: subflowInstances
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function refreshToolbar(activeSubflow) {
|
||||||
|
if (activeSubflow) {
|
||||||
|
$("#workspace-subflow-input-add").toggleClass("active", activeSubflow.in.length !== 0);
|
||||||
|
$("#workspace-subflow-input-remove").toggleClass("active",activeSubflow.in.length === 0);
|
||||||
|
|
||||||
|
$("#workspace-subflow-output .spinner-value").html(activeSubflow.out.length);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function showWorkspaceToolbar(activeSubflow) {
|
||||||
|
var toolbar = $("#workspace-toolbar");
|
||||||
|
toolbar.empty();
|
||||||
|
|
||||||
|
$('<a class="button" id="workspace-subflow-edit" href="#" data-i18n="[append]subflow.editSubflowName"><i class="fa fa-pencil"></i></a>').appendTo(toolbar);
|
||||||
|
$('<span style="margin-left: 5px;" data-i18n="subflow.input"></span> '+
|
||||||
|
'<div style="display: inline-block;" class="button-group">'+
|
||||||
|
'<a id="workspace-subflow-input-remove" class="button active" href="#">0</a>'+
|
||||||
|
'<a id="workspace-subflow-input-add" class="button" href="#">1</a>'+
|
||||||
|
'</div>').appendTo(toolbar);
|
||||||
|
|
||||||
|
$('<span style="margin-left: 5px;" data-i18n="subflow.output"></span> <div id="workspace-subflow-output" style="display: inline-block;" class="button-group spinner-group">'+
|
||||||
|
'<a id="workspace-subflow-output-remove" class="button" href="#"><i class="fa fa-minus"></i></a>'+
|
||||||
|
'<div class="spinner-value">3</div>'+
|
||||||
|
'<a id="workspace-subflow-output-add" class="button" href="#"><i class="fa fa-plus"></i></a>'+
|
||||||
|
'</div>').appendTo(toolbar);
|
||||||
|
|
||||||
|
// $('<a class="button disabled" id="workspace-subflow-add-input" href="#" data-i18n="[append]subflow.input"><i class="fa fa-plus"></i> </a>').appendTo(toolbar);
|
||||||
|
// $('<a class="button" id="workspace-subflow-add-output" href="#" data-i18n="[append]subflow.output"><i class="fa fa-plus"></i> </a>').appendTo(toolbar);
|
||||||
|
$('<a class="button" id="workspace-subflow-delete" href="#" data-i18n="[append]subflow.deleteSubflow"><i class="fa fa-trash"></i> </a>').appendTo(toolbar);
|
||||||
|
toolbar.i18n();
|
||||||
|
|
||||||
|
|
||||||
|
$("#workspace-subflow-output-remove").click(function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var wasDirty = RED.nodes.dirty();
|
||||||
|
var wasChanged = activeSubflow.changed;
|
||||||
|
var result = removeSubflowOutput();
|
||||||
|
if (result) {
|
||||||
|
var inst = refresh(true);
|
||||||
|
RED.history.push({
|
||||||
|
t:'delete',
|
||||||
|
links:result.links,
|
||||||
|
subflowOutputs: result.subflowOutputs,
|
||||||
|
changed: wasChanged,
|
||||||
|
dirty:wasDirty,
|
||||||
|
subflow: {
|
||||||
|
instances: inst.instances
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
RED.view.select();
|
||||||
|
RED.nodes.dirty(true);
|
||||||
|
RED.view.redraw(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
$("#workspace-subflow-output-add").click(function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
addSubflowOutput();
|
||||||
|
});
|
||||||
|
|
||||||
|
$("#workspace-subflow-input-add").click(function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
addSubflowInput();
|
||||||
|
});
|
||||||
|
$("#workspace-subflow-input-remove").click(function(event) {
|
||||||
|
event.preventDefault();
|
||||||
|
var wasDirty = RED.nodes.dirty();
|
||||||
|
var wasChanged = activeSubflow.changed;
|
||||||
|
activeSubflow.changed = true;
|
||||||
|
var result = removeSubflowInput();
|
||||||
|
if (result) {
|
||||||
|
var inst = refresh(true);
|
||||||
|
RED.history.push({
|
||||||
|
t:'delete',
|
||||||
|
links:result.links,
|
||||||
|
changed: wasChanged,
|
||||||
|
subflowInputs: result.subflowInputs,
|
||||||
|
dirty:wasDirty,
|
||||||
|
subflow: {
|
||||||
|
instances: inst.instances
|
||||||
|
}
|
||||||
|
});
|
||||||
|
RED.view.select();
|
||||||
|
RED.nodes.dirty(true);
|
||||||
|
RED.view.redraw(true);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
$("#workspace-subflow-edit").click(function(event) {
|
$("#workspace-subflow-edit").click(function(event) {
|
||||||
RED.editor.editSubflow(RED.nodes.subflow(RED.workspaces.active()));
|
RED.editor.editSubflow(RED.nodes.subflow(RED.workspaces.active()));
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
});
|
});
|
||||||
$("#workspace-subflow-add-input").click(function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
if ($(this).hasClass("disabled")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
addSubflowInput();
|
|
||||||
});
|
|
||||||
$("#workspace-subflow-add-output").click(function(event) {
|
|
||||||
event.preventDefault();
|
|
||||||
if ($(this).hasClass("disabled")) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
addSubflowOutput();
|
|
||||||
});
|
|
||||||
|
|
||||||
$("#workspace-subflow-delete").click(function(event) {
|
$("#workspace-subflow-delete").click(function(event) {
|
||||||
event.preventDefault();
|
event.preventDefault();
|
||||||
@ -170,7 +336,9 @@ RED.subflow = (function() {
|
|||||||
t:'delete',
|
t:'delete',
|
||||||
nodes:removedNodes,
|
nodes:removedNodes,
|
||||||
links:removedLinks,
|
links:removedLinks,
|
||||||
subflow: activeSubflow,
|
subflow: {
|
||||||
|
subflow: activeSubflow
|
||||||
|
},
|
||||||
dirty:startDirty
|
dirty:startDirty
|
||||||
});
|
});
|
||||||
|
|
||||||
@ -179,6 +347,26 @@ RED.subflow = (function() {
|
|||||||
RED.view.redraw();
|
RED.view.redraw();
|
||||||
});
|
});
|
||||||
|
|
||||||
|
refreshToolbar(activeSubflow);
|
||||||
|
|
||||||
|
$("#chart").css({"margin-top": "40px"});
|
||||||
|
$("#workspace-toolbar").show();
|
||||||
|
}
|
||||||
|
function hideWorkspaceToolbar() {
|
||||||
|
$("#workspace-toolbar").hide().empty();
|
||||||
|
$("#chart").css({"margin-top": "0"});
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
function init() {
|
||||||
|
RED.events.on("workspace:change",function(event) {
|
||||||
|
var activeSubflow = RED.nodes.subflow(event.workspace);
|
||||||
|
if (activeSubflow) {
|
||||||
|
showWorkspaceToolbar(activeSubflow);
|
||||||
|
} else {
|
||||||
|
hideWorkspaceToolbar();
|
||||||
|
}
|
||||||
|
});
|
||||||
RED.events.on("view:selection-changed",function(selection) {
|
RED.events.on("view:selection-changed",function(selection) {
|
||||||
if (!selection.nodes) {
|
if (!selection.nodes) {
|
||||||
RED.menu.setDisabled("menu-item-subflow-convert",true);
|
RED.menu.setDisabled("menu-item-subflow-convert",true);
|
||||||
@ -211,7 +399,9 @@ RED.subflow = (function() {
|
|||||||
RED.nodes.addSubflow(subflow);
|
RED.nodes.addSubflow(subflow);
|
||||||
RED.history.push({
|
RED.history.push({
|
||||||
t:'createSubflow',
|
t:'createSubflow',
|
||||||
subflow: subflow,
|
subflow: {
|
||||||
|
subflow:subflow
|
||||||
|
},
|
||||||
dirty:RED.nodes.dirty()
|
dirty:RED.nodes.dirty()
|
||||||
});
|
});
|
||||||
RED.workspaces.show(subflowId);
|
RED.workspaces.show(subflowId);
|
||||||
@ -230,6 +420,8 @@ RED.subflow = (function() {
|
|||||||
|
|
||||||
var candidateInputs = [];
|
var candidateInputs = [];
|
||||||
var candidateOutputs = [];
|
var candidateOutputs = [];
|
||||||
|
var candidateInputNodes = {};
|
||||||
|
|
||||||
|
|
||||||
var boundingBox = [selection.nodes[0].x,
|
var boundingBox = [selection.nodes[0].x,
|
||||||
selection.nodes[0].y,
|
selection.nodes[0].y,
|
||||||
@ -262,6 +454,7 @@ RED.subflow = (function() {
|
|||||||
if (!nodes[link.source.id] && nodes[link.target.id]) {
|
if (!nodes[link.source.id] && nodes[link.target.id]) {
|
||||||
// An inbound link
|
// An inbound link
|
||||||
candidateInputs.push(link);
|
candidateInputs.push(link);
|
||||||
|
candidateInputNodes[link.target.id] = link.target;
|
||||||
removedLinks.push(link);
|
removedLinks.push(link);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@ -279,15 +472,10 @@ RED.subflow = (function() {
|
|||||||
});
|
});
|
||||||
candidateOutputs.sort(function(a,b) { return a.source.y-b.source.y});
|
candidateOutputs.sort(function(a,b) { return a.source.y-b.source.y});
|
||||||
|
|
||||||
if (candidateInputs.length > 1) {
|
if (Object.keys(candidateInputNodes).length > 1) {
|
||||||
RED.notify(RED._("subflow.errors.multipleInputsToSelection"),"error");
|
RED.notify(RED._("subflow.errors.multipleInputsToSelection"),"error");
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
//if (candidateInputs.length == 0) {
|
|
||||||
// RED.notify("<strong>Cannot create subflow</strong>: no input to selection","error");
|
|
||||||
// return;
|
|
||||||
//}
|
|
||||||
|
|
||||||
|
|
||||||
var lastIndex = 0;
|
var lastIndex = 0;
|
||||||
RED.nodes.eachSubflow(function(sf) {
|
RED.nodes.eachSubflow(function(sf) {
|
||||||
@ -304,15 +492,15 @@ RED.subflow = (function() {
|
|||||||
type:"subflow",
|
type:"subflow",
|
||||||
id:subflowId,
|
id:subflowId,
|
||||||
name:name,
|
name:name,
|
||||||
in: candidateInputs.map(function(v,i) { var index = i; return {
|
in: Object.keys(candidateInputNodes).map(function(v,i) { var index = i; return {
|
||||||
type:"subflow",
|
type:"subflow",
|
||||||
direction:"in",
|
direction:"in",
|
||||||
x:v.target.x-(v.target.w/2)-80,
|
x:candidateInputNodes[v].x-(candidateInputNodes[v].w/2)-80,
|
||||||
y:v.target.y,
|
y:candidateInputNodes[v].y,
|
||||||
z:subflowId,
|
z:subflowId,
|
||||||
i:index,
|
i:index,
|
||||||
id:RED.nodes.id(),
|
id:RED.nodes.id(),
|
||||||
wires:[{id:v.target.id}]
|
wires:[{id:candidateInputNodes[v].id}]
|
||||||
}}),
|
}}),
|
||||||
out: candidateOutputs.map(function(v,i) { var index = i; return {
|
out: candidateOutputs.map(function(v,i) { var index = i; return {
|
||||||
type:"subflow",
|
type:"subflow",
|
||||||
@ -325,6 +513,7 @@ RED.subflow = (function() {
|
|||||||
wires:[{id:v.source.id,port:v.sourcePort}]
|
wires:[{id:v.source.id,port:v.sourcePort}]
|
||||||
}})
|
}})
|
||||||
};
|
};
|
||||||
|
|
||||||
RED.nodes.addSubflow(subflow);
|
RED.nodes.addSubflow(subflow);
|
||||||
|
|
||||||
var subflowInstance = {
|
var subflowInstance = {
|
||||||
@ -383,7 +572,9 @@ RED.subflow = (function() {
|
|||||||
t:'createSubflow',
|
t:'createSubflow',
|
||||||
nodes:[subflowInstance.id],
|
nodes:[subflowInstance.id],
|
||||||
links:new_links,
|
links:new_links,
|
||||||
subflow: subflow,
|
subflow: {
|
||||||
|
subflow: subflow
|
||||||
|
},
|
||||||
|
|
||||||
activeWorkspace: RED.workspaces.active(),
|
activeWorkspace: RED.workspaces.active(),
|
||||||
removedLinks: removedLinks,
|
removedLinks: removedLinks,
|
||||||
@ -401,6 +592,9 @@ RED.subflow = (function() {
|
|||||||
return {
|
return {
|
||||||
init: init,
|
init: init,
|
||||||
createSubflow: createSubflow,
|
createSubflow: createSubflow,
|
||||||
convertToSubflow: convertToSubflow
|
convertToSubflow: convertToSubflow,
|
||||||
|
refresh: refresh,
|
||||||
|
removeInput: removeSubflowInput,
|
||||||
|
removeOutput: removeSubflowOutput
|
||||||
}
|
}
|
||||||
})();
|
})();
|
||||||
|
@ -80,12 +80,15 @@ RED.tabs = (function() {
|
|||||||
tabs.css({width:currentTabWidth+"%"});
|
tabs.css({width:currentTabWidth+"%"});
|
||||||
if (tabWidth < 50) {
|
if (tabWidth < 50) {
|
||||||
ul.find(".red-ui-tab-close").hide();
|
ul.find(".red-ui-tab-close").hide();
|
||||||
|
ul.find(".red-ui-tab-icon").hide();
|
||||||
} else {
|
} else {
|
||||||
ul.find(".red-ui-tab-close").show();
|
ul.find(".red-ui-tab-close").show();
|
||||||
|
ul.find(".red-ui-tab-icon").show();
|
||||||
}
|
}
|
||||||
if (currentActiveTabWidth !== 0) {
|
if (currentActiveTabWidth !== 0) {
|
||||||
ul.find("li.red-ui-tab.active").css({"width":options.minimumActiveTabWidth});
|
ul.find("li.red-ui-tab.active").css({"width":options.minimumActiveTabWidth});
|
||||||
ul.find("li.red-ui-tab.active .red-ui-tab-close").show();
|
ul.find("li.red-ui-tab.active .red-ui-tab-close").show();
|
||||||
|
ul.find("li.red-ui-tab.active .red-ui-tab-icon").show();
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
@ -116,13 +119,16 @@ RED.tabs = (function() {
|
|||||||
tabs[tab.id] = tab;
|
tabs[tab.id] = tab;
|
||||||
var li = $("<li/>",{class:"red-ui-tab"}).appendTo(ul);
|
var li = $("<li/>",{class:"red-ui-tab"}).appendTo(ul);
|
||||||
var link = $("<a/>",{href:"#"+tab.id, class:"red-ui-tab-label"}).appendTo(li);
|
var link = $("<a/>",{href:"#"+tab.id, class:"red-ui-tab-label"}).appendTo(li);
|
||||||
link.html(tab.label);
|
if (tab.icon) {
|
||||||
|
$('<img src="'+tab.icon+'" class="red-ui-tab-icon"/>').appendTo(link);
|
||||||
|
}
|
||||||
|
$('<span/>').text(tab.label).appendTo(link);
|
||||||
|
|
||||||
link.on("click",onTabClick);
|
link.on("click",onTabClick);
|
||||||
link.on("dblclick",onTabDblClick);
|
link.on("dblclick",onTabDblClick);
|
||||||
if (tab.closeable) {
|
if (tab.closeable) {
|
||||||
var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close"}).appendTo(li);
|
var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close"}).appendTo(li);
|
||||||
closeLink.html('<i class="fa fa-times" />');
|
closeLink.append('<i class="fa fa-times" />');
|
||||||
|
|
||||||
closeLink.on("click",function(event) {
|
closeLink.on("click",function(event) {
|
||||||
removeTab(tab.id);
|
removeTab(tab.id);
|
||||||
@ -150,7 +156,7 @@ RED.tabs = (function() {
|
|||||||
tabs[id].label = label;
|
tabs[id].label = label;
|
||||||
var tab = ul.find("a[href='#"+id+"']");
|
var tab = ul.find("a[href='#"+id+"']");
|
||||||
tab.attr("title",label);
|
tab.attr("title",label);
|
||||||
tab.text(label);
|
tab.find("span").text(label);
|
||||||
updateTabWidths();
|
updateTabWidths();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -255,9 +255,6 @@ RED.view = (function() {
|
|||||||
var scrollStartTop = chart.scrollTop();
|
var scrollStartTop = chart.scrollTop();
|
||||||
|
|
||||||
activeSubflow = RED.nodes.subflow(event.workspace);
|
activeSubflow = RED.nodes.subflow(event.workspace);
|
||||||
if (activeSubflow) {
|
|
||||||
$("#workspace-subflow-add-input").toggleClass("disabled",activeSubflow.in.length > 0);
|
|
||||||
}
|
|
||||||
|
|
||||||
RED.menu.setDisabled("menu-item-workspace-edit", activeSubflow);
|
RED.menu.setDisabled("menu-item-workspace-edit", activeSubflow);
|
||||||
RED.menu.setDisabled("menu-item-workspace-delete",RED.workspaces.count() == 1 || activeSubflow);
|
RED.menu.setDisabled("menu-item-workspace-delete",RED.workspaces.count() == 1 || activeSubflow);
|
||||||
@ -351,7 +348,23 @@ RED.view = (function() {
|
|||||||
|
|
||||||
nn.changed = true;
|
nn.changed = true;
|
||||||
nn.h = Math.max(node_height,(nn.outputs||0) * 15);
|
nn.h = Math.max(node_height,(nn.outputs||0) * 15);
|
||||||
RED.history.push({t:'add',nodes:[nn.id],dirty:RED.nodes.dirty()});
|
var historyEvent = {
|
||||||
|
t:'add',
|
||||||
|
nodes:[nn.id],
|
||||||
|
dirty:RED.nodes.dirty()
|
||||||
|
}
|
||||||
|
if (activeSubflow) {
|
||||||
|
var subflowRefresh = RED.subflow.refresh(true);
|
||||||
|
if (subflowRefresh) {
|
||||||
|
historyEvent.subflow = {
|
||||||
|
id:activeSubflow.id,
|
||||||
|
changed: activeSubflow.changed,
|
||||||
|
instances: subflowRefresh.instances
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.history.push(historyEvent);
|
||||||
RED.nodes.add(nn);
|
RED.nodes.add(nn);
|
||||||
RED.editor.validateNode(nn);
|
RED.editor.validateNode(nn);
|
||||||
RED.nodes.dirty(true);
|
RED.nodes.dirty(true);
|
||||||
@ -745,8 +758,10 @@ RED.view = (function() {
|
|||||||
var removedLinks = [];
|
var removedLinks = [];
|
||||||
var removedSubflowOutputs = [];
|
var removedSubflowOutputs = [];
|
||||||
var removedSubflowInputs = [];
|
var removedSubflowInputs = [];
|
||||||
|
var subflowInstances = [];
|
||||||
|
|
||||||
var startDirty = RED.nodes.dirty();
|
var startDirty = RED.nodes.dirty();
|
||||||
|
var startChanged = false;
|
||||||
if (moving_set.length > 0) {
|
if (moving_set.length > 0) {
|
||||||
for (var i=0;i<moving_set.length;i++) {
|
for (var i=0;i<moving_set.length;i++) {
|
||||||
var node = moving_set[i].n;
|
var node = moving_set[i].n;
|
||||||
@ -769,65 +784,22 @@ RED.view = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (removedSubflowOutputs.length > 0) {
|
if (removedSubflowOutputs.length > 0) {
|
||||||
removedSubflowOutputs.sort(function(a,b) { return b.i-a.i});
|
var result = RED.subflow.removeOutput(removedSubflowOutputs);
|
||||||
for (i=0;i<removedSubflowOutputs.length;i++) {
|
if (result) {
|
||||||
var output = removedSubflowOutputs[i];
|
removedLinks = removedLinks.concat(result.links);
|
||||||
activeSubflow.out.splice(output.i,1);
|
|
||||||
var subflowRemovedLinks = [];
|
|
||||||
var subflowMovedLinks = [];
|
|
||||||
RED.nodes.eachLink(function(l) {
|
|
||||||
if (l.target.type == "subflow" && l.target.z == activeSubflow.id && l.target.i == output.i) {
|
|
||||||
subflowRemovedLinks.push(l);
|
|
||||||
}
|
|
||||||
if (l.source.type == "subflow:"+activeSubflow.id) {
|
|
||||||
if (l.sourcePort == output.i) {
|
|
||||||
subflowRemovedLinks.push(l);
|
|
||||||
} else if (l.sourcePort > output.i) {
|
|
||||||
subflowMovedLinks.push(l);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
});
|
|
||||||
subflowRemovedLinks.forEach(function(l) { RED.nodes.removeLink(l)});
|
|
||||||
subflowMovedLinks.forEach(function(l) { l.sourcePort--; });
|
|
||||||
|
|
||||||
removedLinks = removedLinks.concat(subflowRemovedLinks);
|
|
||||||
for (var j=output.i;j<activeSubflow.out.length;j++) {
|
|
||||||
activeSubflow.out[j].i--;
|
|
||||||
activeSubflow.out[j].dirty = true;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Assume 0/1 inputs
|
// Assume 0/1 inputs
|
||||||
if (removedSubflowInputs.length == 1) {
|
if (removedSubflowInputs.length == 1) {
|
||||||
var input = removedSubflowInputs[0];
|
var result = RED.subflow.removeInput();
|
||||||
var subflowRemovedInputLinks = [];
|
if (result) {
|
||||||
RED.nodes.eachLink(function(l) {
|
removedLinks = removedLinks.concat(result.links);
|
||||||
if (l.source.type == "subflow" && l.source.z == activeSubflow.id && l.source.i == input.i) {
|
}
|
||||||
subflowRemovedInputLinks.push(l);
|
|
||||||
} else if (l.target.type == "subflow:"+activeSubflow.id) {
|
|
||||||
subflowRemovedInputLinks.push(l);
|
|
||||||
}
|
|
||||||
});
|
|
||||||
subflowRemovedInputLinks.forEach(function(l) { RED.nodes.removeLink(l)});
|
|
||||||
removedLinks = removedLinks.concat(subflowRemovedInputLinks);
|
|
||||||
activeSubflow.in = [];
|
|
||||||
$("#workspace-subflow-add-input").toggleClass("disabled",false);
|
|
||||||
}
|
}
|
||||||
|
var instances = RED.subflow.refresh(true);
|
||||||
if (activeSubflow) {
|
if (instances) {
|
||||||
RED.nodes.filterNodes({type:"subflow:"+activeSubflow.id}).forEach(function(n) {
|
subflowInstances = instances.instances;
|
||||||
n.changed = true;
|
|
||||||
n.inputs = activeSubflow.in.length;
|
|
||||||
n.outputs = activeSubflow.out.length;
|
|
||||||
while (n.outputs < n.ports.length) {
|
|
||||||
n.ports.pop();
|
|
||||||
}
|
|
||||||
n.resize = true;
|
|
||||||
n.dirty = true;
|
|
||||||
});
|
|
||||||
RED.editor.validateNode(activeSubflow);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
moving_set = [];
|
moving_set = [];
|
||||||
if (removedNodes.length > 0 || removedSubflowOutputs.length > 0 || removedSubflowInputs.length > 0) {
|
if (removedNodes.length > 0 || removedSubflowOutputs.length > 0 || removedSubflowInputs.length > 0) {
|
||||||
RED.nodes.dirty(true);
|
RED.nodes.dirty(true);
|
||||||
@ -838,7 +810,18 @@ RED.view = (function() {
|
|||||||
removedLinks.push(selected_link);
|
removedLinks.push(selected_link);
|
||||||
RED.nodes.dirty(true);
|
RED.nodes.dirty(true);
|
||||||
}
|
}
|
||||||
RED.history.push({t:'delete',nodes:removedNodes,links:removedLinks,subflowOutputs:removedSubflowOutputs,subflowInputs:removedSubflowInputs,dirty:startDirty});
|
var historyEvent = {
|
||||||
|
t:'delete',
|
||||||
|
nodes:removedNodes,
|
||||||
|
links:removedLinks,
|
||||||
|
subflowOutputs:removedSubflowOutputs,
|
||||||
|
subflowInputs:removedSubflowInputs,
|
||||||
|
subflow: {
|
||||||
|
instances: subflowInstances
|
||||||
|
},
|
||||||
|
dirty:startDirty
|
||||||
|
};
|
||||||
|
RED.history.push(historyEvent);
|
||||||
|
|
||||||
selected_link = null;
|
selected_link = null;
|
||||||
updateActiveNodes();
|
updateActiveNodes();
|
||||||
@ -945,7 +928,22 @@ RED.view = (function() {
|
|||||||
if (!existingLink) {
|
if (!existingLink) {
|
||||||
var link = {source: src, sourcePort:src_port, target: dst};
|
var link = {source: src, sourcePort:src_port, target: dst};
|
||||||
RED.nodes.addLink(link);
|
RED.nodes.addLink(link);
|
||||||
RED.history.push({t:'add',links:[link],dirty:RED.nodes.dirty()});
|
var historyEvent = {
|
||||||
|
t:'add',
|
||||||
|
links:[link],
|
||||||
|
dirty:RED.nodes.dirty()
|
||||||
|
};
|
||||||
|
if (activeSubflow) {
|
||||||
|
var subflowRefresh = RED.subflow.refresh(true);
|
||||||
|
if (subflowRefresh) {
|
||||||
|
historyEvent.subflow = {
|
||||||
|
id:activeSubflow.id,
|
||||||
|
changed: activeSubflow.changed,
|
||||||
|
instances: subflowRefresh.instances
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RED.history.push(historyEvent);
|
||||||
updateActiveNodes();
|
updateActiveNodes();
|
||||||
RED.nodes.dirty(true);
|
RED.nodes.dirty(true);
|
||||||
} else {
|
} else {
|
||||||
@ -1695,6 +1693,10 @@ RED.view = (function() {
|
|||||||
*/
|
*/
|
||||||
function importNodes(newNodesStr,touchImport) {
|
function importNodes(newNodesStr,touchImport) {
|
||||||
try {
|
try {
|
||||||
|
var activeSubflowChanged;
|
||||||
|
if (activeSubflow) {
|
||||||
|
activeSubflowChanged = activeSubflow.changed;
|
||||||
|
}
|
||||||
var result = RED.nodes.import(newNodesStr,true);
|
var result = RED.nodes.import(newNodesStr,true);
|
||||||
if (result) {
|
if (result) {
|
||||||
var new_nodes = result[0];
|
var new_nodes = result[0];
|
||||||
@ -1752,14 +1754,25 @@ RED.view = (function() {
|
|||||||
moving_set = new_ms;
|
moving_set = new_ms;
|
||||||
}
|
}
|
||||||
|
|
||||||
RED.history.push({
|
var historyEvent = {
|
||||||
t:'add',
|
t:'add',
|
||||||
nodes:new_node_ids,
|
nodes:new_node_ids,
|
||||||
links:new_links,
|
links:new_links,
|
||||||
workspaces:new_workspaces,
|
workspaces:new_workspaces,
|
||||||
subflows:new_subflows,
|
subflows:new_subflows,
|
||||||
dirty:RED.nodes.dirty()
|
dirty:RED.nodes.dirty()
|
||||||
});
|
};
|
||||||
|
if (activeSubflow) {
|
||||||
|
var subflowRefresh = RED.subflow.refresh(true);
|
||||||
|
if (subflowRefresh) {
|
||||||
|
historyEvent.subflow = {
|
||||||
|
id:activeSubflow.id,
|
||||||
|
changed: activeSubflowChanged,
|
||||||
|
instances: subflowRefresh.instances
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
RED.history.push(historyEvent);
|
||||||
|
|
||||||
updateActiveNodes();
|
updateActiveNodes();
|
||||||
redraw();
|
redraw();
|
||||||
|
@ -84,13 +84,6 @@ RED.workspaces = (function() {
|
|||||||
workspace_tabs = RED.tabs.create({
|
workspace_tabs = RED.tabs.create({
|
||||||
id: "workspace-tabs",
|
id: "workspace-tabs",
|
||||||
onchange: function(tab) {
|
onchange: function(tab) {
|
||||||
if (tab.type == "subflow") {
|
|
||||||
$("#chart").css({"margin-top": "40px"});
|
|
||||||
$("#workspace-toolbar").show();
|
|
||||||
} else {
|
|
||||||
$("#workspace-toolbar").hide();
|
|
||||||
$("#chart").css({"margin-top": "0"});
|
|
||||||
}
|
|
||||||
var event = {
|
var event = {
|
||||||
old: activeWorkspace
|
old: activeWorkspace
|
||||||
}
|
}
|
||||||
@ -242,7 +235,7 @@ RED.workspaces = (function() {
|
|||||||
if (!workspace_tabs.contains(id)) {
|
if (!workspace_tabs.contains(id)) {
|
||||||
var sf = RED.nodes.subflow(id);
|
var sf = RED.nodes.subflow(id);
|
||||||
if (sf) {
|
if (sf) {
|
||||||
addWorkspace({type:"subflow",id:id,label:RED._("subflow.tabLabel",{name:sf.name}), closeable: true});
|
addWorkspace({type:"subflow",id:id,icon:"red/images/subflow_tab.png",label:sf.name, closeable: true});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
workspace_tabs.activateTab(id);
|
workspace_tabs.activateTab(id);
|
||||||
@ -250,7 +243,7 @@ RED.workspaces = (function() {
|
|||||||
refresh: function() {
|
refresh: function() {
|
||||||
RED.nodes.eachSubflow(function(sf) {
|
RED.nodes.eachSubflow(function(sf) {
|
||||||
if (workspace_tabs.contains(sf.id)) {
|
if (workspace_tabs.contains(sf.id)) {
|
||||||
workspace_tabs.renameTab(sf.id,RED._("subflow.tabLabel",{name:sf.name}));
|
workspace_tabs.renameTab(sf.id,sf.name);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
},
|
},
|
||||||
|
@ -47,7 +47,7 @@ span.logo {
|
|||||||
font-size: 30px;
|
font-size: 30px;
|
||||||
line-height: 30px;
|
line-height: 30px;
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
|
|
||||||
span {
|
span {
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
font-size: 16px !important;
|
font-size: 16px !important;
|
||||||
@ -55,14 +55,14 @@ span.logo {
|
|||||||
img {
|
img {
|
||||||
height: 18px;
|
height: 18px;
|
||||||
}
|
}
|
||||||
|
|
||||||
a {
|
a {
|
||||||
color: inherit;
|
color: inherit;
|
||||||
&:hover {
|
&:hover {
|
||||||
text-decoration: none;
|
text-decoration: none;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
.header-toolbar {
|
.header-toolbar {
|
||||||
@ -70,13 +70,13 @@ span.logo {
|
|||||||
margin: 0;
|
margin: 0;
|
||||||
list-style: none;
|
list-style: none;
|
||||||
float: right;
|
float: right;
|
||||||
|
|
||||||
> li {
|
> li {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
padding: 0;
|
padding: 0;
|
||||||
margin: 0;
|
margin: 0;
|
||||||
position: relative;
|
position: relative;
|
||||||
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -97,19 +97,19 @@ span.logo {
|
|||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
border-left: 2px solid #000;
|
border-left: 2px solid #000;
|
||||||
border-right: 2px solid #000;
|
border-right: 2px solid #000;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
border-color: $headerMenuItemHover;
|
border-color: $headerMenuItemHover;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
.button-group {
|
#header .button-group {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
margin: auto 15px;
|
margin: auto 15px;
|
||||||
vertical-align: middle;
|
vertical-align: middle;
|
||||||
clear: both;
|
clear: both;
|
||||||
}
|
}
|
||||||
.button-group > a {
|
#header .button-group > a {
|
||||||
display: inline-block;
|
display: inline-block;
|
||||||
float: left;
|
float: left;
|
||||||
line-height: 22px;
|
line-height: 22px;
|
||||||
@ -122,11 +122,11 @@ span.logo {
|
|||||||
.deploy-button {
|
.deploy-button {
|
||||||
background: $deployButton;
|
background: $deployButton;
|
||||||
color: #eee !important;
|
color: #eee !important;
|
||||||
|
|
||||||
&:hover {
|
&:hover {
|
||||||
background: $deployButtonHover;
|
background: $deployButtonHover;
|
||||||
}
|
}
|
||||||
|
|
||||||
&:active {
|
&:active {
|
||||||
background: $deployButtonActive;
|
background: $deployButtonActive;
|
||||||
color: #ccc !important;
|
color: #ccc !important;
|
||||||
@ -134,18 +134,18 @@ span.logo {
|
|||||||
}
|
}
|
||||||
|
|
||||||
#btn-deploy {
|
#btn-deploy {
|
||||||
|
|
||||||
padding: 4px 12px;
|
padding: 4px 12px;
|
||||||
|
|
||||||
&.disabled {
|
&.disabled {
|
||||||
cursor: default;
|
cursor: default;
|
||||||
background: $deployDisabledButton;
|
background: $deployDisabledButton;
|
||||||
color: #999 !important;
|
color: #999 !important;
|
||||||
|
|
||||||
img {
|
img {
|
||||||
opacity: 0.3;
|
opacity: 0.3;
|
||||||
}
|
}
|
||||||
|
|
||||||
&+ #btn-deploy-options {
|
&+ #btn-deploy-options {
|
||||||
background: $deployDisabledButton;
|
background: $deployDisabledButton;
|
||||||
color: #ddd;
|
color: #ddd;
|
||||||
@ -157,7 +157,7 @@ span.logo {
|
|||||||
background: $deployDisabledButton;
|
background: $deployDisabledButton;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
img {
|
img {
|
||||||
margin-right: 8px;
|
margin-right: 8px;
|
||||||
}
|
}
|
||||||
@ -264,4 +264,3 @@ span.logo {
|
|||||||
font-size: 16px;
|
font-size: 16px;
|
||||||
color: #fff;
|
color: #fff;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -21,13 +21,10 @@ ul.red-ui-tabs {
|
|||||||
display: block;
|
display: block;
|
||||||
height: 35px;
|
height: 35px;
|
||||||
box-sizing:border-box;
|
box-sizing:border-box;
|
||||||
|
white-space: nowrap;
|
||||||
border-bottom: 1px solid $primary-border-color;
|
border-bottom: 1px solid $primary-border-color;
|
||||||
background: #fff;
|
background: #fff;
|
||||||
-webkit-user-select: none;
|
@include disable-selection;
|
||||||
-khtml-user-select: none;
|
|
||||||
-moz-user-select: none;
|
|
||||||
-ms-user-select: none;
|
|
||||||
user-select: none;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
ul.red-ui-tabs li {
|
ul.red-ui-tabs li {
|
||||||
@ -110,3 +107,16 @@ ul.red-ui-tabs li.active {
|
|||||||
ul.red-ui-tabs li.active a {
|
ul.red-ui-tabs li.active a {
|
||||||
color: #333;
|
color: #333;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
ul.red-ui-tabs li img {
|
||||||
|
margin-left: -8px;
|
||||||
|
margin-right: 3px;
|
||||||
|
margin-top: -2px;
|
||||||
|
opacity: 0.1;
|
||||||
|
width: 20px;
|
||||||
|
height: 20px;
|
||||||
|
vertical-align: middle;
|
||||||
|
}
|
||||||
|
ul.red-ui-tabs li.active img {
|
||||||
|
opacity: 0.2;
|
||||||
|
}
|
||||||
|
@ -17,6 +17,9 @@
|
|||||||
|
|
||||||
#workspace-toolbar {
|
#workspace-toolbar {
|
||||||
display: none;
|
display: none;
|
||||||
|
color: $workspace-button-color;
|
||||||
|
font-size: 12px;
|
||||||
|
line-height: 18px;
|
||||||
position: absolute;
|
position: absolute;
|
||||||
top: 35px;
|
top: 35px;
|
||||||
left:0;
|
left:0;
|
||||||
@ -26,12 +29,46 @@
|
|||||||
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;
|
||||||
|
|
||||||
|
.button {
|
||||||
|
@include workspace-button;
|
||||||
|
margin-right: 10px;
|
||||||
|
padding: 2px 8px;
|
||||||
|
}
|
||||||
|
|
||||||
|
.button-group {
|
||||||
|
@include disable-selection;
|
||||||
|
|
||||||
|
.button:first-child {
|
||||||
|
margin-right: 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
&:not(.spinner-group) {
|
||||||
|
.button:not(:first-child) {
|
||||||
|
border-left: none;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
.button.active {
|
||||||
|
background: $workspace-button-background-active;
|
||||||
|
cursor: default;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
.spinner-value {
|
||||||
|
width: 25px;
|
||||||
|
color: $workspace-button-color;
|
||||||
|
padding: 0 5px;
|
||||||
|
display: inline-block;
|
||||||
|
text-align: center;
|
||||||
|
border-top: 1px solid $secondary-border-color;
|
||||||
|
border-bottom: 1px solid $secondary-border-color;
|
||||||
|
margin: 0;
|
||||||
|
height: 24px;
|
||||||
|
font-size: 12px;
|
||||||
|
background: #f9f9f9;
|
||||||
|
line-height: 22px;
|
||||||
|
box-sizing: border-box;
|
||||||
|
}
|
||||||
|
|
||||||
#workspace-toolbar .button {
|
|
||||||
@include workspace-button;
|
|
||||||
line-height: 18px;
|
|
||||||
font-size: 12px;
|
|
||||||
margin-right: 5px;
|
|
||||||
padding: 2px 8px;
|
|
||||||
}
|
}
|
||||||
|
@ -58,12 +58,7 @@
|
|||||||
<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-toolbar">
|
<div id="workspace-toolbar"></div>
|
||||||
<a class="button" id="workspace-subflow-edit" href="#" data-i18n="[append]subflow.editSubflowName"><i class="fa fa-pencil"></i> </a>
|
|
||||||
<a class="button disabled" id="workspace-subflow-add-input" href="#" data-i18n="[append]subflow.input"><i class="fa fa-plus"></i> </a>
|
|
||||||
<a class="button" id="workspace-subflow-add-output" href="#" data-i18n="[append]subflow.output"><i class="fa fa-plus"></i> </a>
|
|
||||||
<a class="button" id="workspace-subflow-delete" href="#" data-i18n="[append]subflow.deleteSubflow"><i class="fa fa-trash"></i> </a>
|
|
||||||
</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>
|
||||||
<a class="workspace-footer-button" id="btn-zoom-zero" href="#"><i class="fa fa-circle-o"></i></a>
|
<a class="workspace-footer-button" id="btn-zoom-zero" href="#"><i class="fa fa-circle-o"></i></a>
|
||||||
|
@ -94,14 +94,13 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"subflow": {
|
"subflow": {
|
||||||
"tabLabel": "Subflow: __name__",
|
|
||||||
"editSubflow": "Edit flow __name__",
|
"editSubflow": "Edit flow __name__",
|
||||||
"edit": "Edit flow",
|
"edit": "Edit flow",
|
||||||
"subflowInstances": "There is __count__ instance of this subflow",
|
"subflowInstances": "There is __count__ instance of this subflow",
|
||||||
"subflowInstances_plural": "There are __count__ instances of this subflow",
|
"subflowInstances_plural": "There are __count__ instances of this subflow",
|
||||||
"editSubflowName": "edit name",
|
"editSubflowName": "edit name",
|
||||||
"input": "input",
|
"input": "inputs:",
|
||||||
"output": "output",
|
"output": "outputs:",
|
||||||
"deleteSubflow": "delete subflow",
|
"deleteSubflow": "delete subflow",
|
||||||
"errors": {
|
"errors": {
|
||||||
"noNodesSelected": "<strong>Cannot create subflow</strong>: no nodes selected",
|
"noNodesSelected": "<strong>Cannot create subflow</strong>: no nodes selected",
|
||||||
|
Loading…
Reference in New Issue
Block a user