mirror of https://github.com/node-red/node-red.git
Merge pull request #4654 from node-red/fix-subflow-recursion-check
Prevent subflow being added to itselfpull/4655/head
commit
7ac7f9b4c8
|
@ -646,120 +646,128 @@ RED.view = (function() {
|
||||||
}
|
}
|
||||||
d3.event = event;
|
d3.event = event;
|
||||||
var selected_tool = $(ui.draggable[0]).attr("data-palette-type");
|
var selected_tool = $(ui.draggable[0]).attr("data-palette-type");
|
||||||
var result = createNode(selected_tool);
|
|
||||||
if (!result) {
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
var historyEvent = result.historyEvent;
|
|
||||||
var nn = RED.nodes.add(result.node);
|
|
||||||
|
|
||||||
var showLabel = RED.utils.getMessageProperty(RED.settings.get('editor'),"view.view-node-show-label");
|
|
||||||
if (showLabel !== undefined && (nn._def.hasOwnProperty("showLabel")?nn._def.showLabel:true) && !nn._def.defaults.hasOwnProperty("l")) {
|
|
||||||
nn.l = showLabel;
|
|
||||||
}
|
|
||||||
|
|
||||||
var helperOffset = d3.touches(ui.helper.get(0))[0]||d3.mouse(ui.helper.get(0));
|
|
||||||
var helperWidth = ui.helper.width();
|
|
||||||
var helperHeight = ui.helper.height();
|
|
||||||
var mousePos = d3.touches(this)[0]||d3.mouse(this);
|
|
||||||
|
|
||||||
try {
|
try {
|
||||||
var isLink = (nn.type === "link in" || nn.type === "link out")
|
var result = createNode(selected_tool);
|
||||||
var hideLabel = nn.hasOwnProperty('l')?!nn.l : isLink;
|
if (!result) {
|
||||||
|
return;
|
||||||
var label = RED.utils.getNodeLabel(nn, nn.type);
|
|
||||||
var labelParts = getLabelParts(label, "red-ui-flow-node-label");
|
|
||||||
if (hideLabel) {
|
|
||||||
nn.w = node_height;
|
|
||||||
nn.h = Math.max(node_height,(nn.outputs || 0) * 15);
|
|
||||||
} else {
|
|
||||||
nn.w = Math.max(node_width,20*(Math.ceil((labelParts.width+50+(nn._def.inputs>0?7:0))/20)) );
|
|
||||||
nn.h = Math.max(6+24*labelParts.lines.length,(nn.outputs || 0) * 15, 30);
|
|
||||||
}
|
}
|
||||||
} catch(err) {
|
var historyEvent = result.historyEvent;
|
||||||
}
|
var nn = RED.nodes.add(result.node);
|
||||||
|
|
||||||
mousePos[1] += this.scrollTop + ((helperHeight/2)-helperOffset[1]);
|
var showLabel = RED.utils.getMessageProperty(RED.settings.get('editor'),"view.view-node-show-label");
|
||||||
mousePos[0] += this.scrollLeft + ((helperWidth/2)-helperOffset[0]);
|
if (showLabel !== undefined && (nn._def.hasOwnProperty("showLabel")?nn._def.showLabel:true) && !nn._def.defaults.hasOwnProperty("l")) {
|
||||||
mousePos[1] /= scaleFactor;
|
nn.l = showLabel;
|
||||||
mousePos[0] /= scaleFactor;
|
}
|
||||||
|
|
||||||
nn.x = mousePos[0];
|
var helperOffset = d3.touches(ui.helper.get(0))[0]||d3.mouse(ui.helper.get(0));
|
||||||
nn.y = mousePos[1];
|
var helperWidth = ui.helper.width();
|
||||||
|
var helperHeight = ui.helper.height();
|
||||||
|
var mousePos = d3.touches(this)[0]||d3.mouse(this);
|
||||||
|
|
||||||
var minX = nn.w/2 -5;
|
try {
|
||||||
if (nn.x < minX) {
|
var isLink = (nn.type === "link in" || nn.type === "link out")
|
||||||
nn.x = minX;
|
var hideLabel = nn.hasOwnProperty('l')?!nn.l : isLink;
|
||||||
}
|
|
||||||
var minY = nn.h/2 -5;
|
|
||||||
if (nn.y < minY) {
|
|
||||||
nn.y = minY;
|
|
||||||
}
|
|
||||||
var maxX = space_width -nn.w/2 +5;
|
|
||||||
if (nn.x > maxX) {
|
|
||||||
nn.x = maxX;
|
|
||||||
}
|
|
||||||
var maxY = space_height -nn.h +5;
|
|
||||||
if (nn.y > maxY) {
|
|
||||||
nn.y = maxY;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (snapGrid) {
|
var label = RED.utils.getNodeLabel(nn, nn.type);
|
||||||
var gridOffset = RED.view.tools.calculateGridSnapOffsets(nn);
|
var labelParts = getLabelParts(label, "red-ui-flow-node-label");
|
||||||
nn.x -= gridOffset.x;
|
if (hideLabel) {
|
||||||
nn.y -= gridOffset.y;
|
nn.w = node_height;
|
||||||
}
|
nn.h = Math.max(node_height,(nn.outputs || 0) * 15);
|
||||||
|
} else {
|
||||||
|
nn.w = Math.max(node_width,20*(Math.ceil((labelParts.width+50+(nn._def.inputs>0?7:0))/20)) );
|
||||||
|
nn.h = Math.max(6+24*labelParts.lines.length,(nn.outputs || 0) * 15, 30);
|
||||||
|
}
|
||||||
|
} catch(err) {
|
||||||
|
}
|
||||||
|
|
||||||
var linkToSplice = $(ui.helper).data("splice");
|
mousePos[1] += this.scrollTop + ((helperHeight/2)-helperOffset[1]);
|
||||||
if (linkToSplice) {
|
mousePos[0] += this.scrollLeft + ((helperWidth/2)-helperOffset[0]);
|
||||||
spliceLink(linkToSplice, nn, historyEvent)
|
mousePos[1] /= scaleFactor;
|
||||||
}
|
mousePos[0] /= scaleFactor;
|
||||||
|
|
||||||
|
nn.x = mousePos[0];
|
||||||
|
nn.y = mousePos[1];
|
||||||
|
|
||||||
|
var minX = nn.w/2 -5;
|
||||||
|
if (nn.x < minX) {
|
||||||
|
nn.x = minX;
|
||||||
|
}
|
||||||
|
var minY = nn.h/2 -5;
|
||||||
|
if (nn.y < minY) {
|
||||||
|
nn.y = minY;
|
||||||
|
}
|
||||||
|
var maxX = space_width -nn.w/2 +5;
|
||||||
|
if (nn.x > maxX) {
|
||||||
|
nn.x = maxX;
|
||||||
|
}
|
||||||
|
var maxY = space_height -nn.h +5;
|
||||||
|
if (nn.y > maxY) {
|
||||||
|
nn.y = maxY;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (snapGrid) {
|
||||||
|
var gridOffset = RED.view.tools.calculateGridSnapOffsets(nn);
|
||||||
|
nn.x -= gridOffset.x;
|
||||||
|
nn.y -= gridOffset.y;
|
||||||
|
}
|
||||||
|
|
||||||
|
var linkToSplice = $(ui.helper).data("splice");
|
||||||
|
if (linkToSplice) {
|
||||||
|
spliceLink(linkToSplice, nn, historyEvent)
|
||||||
|
}
|
||||||
|
|
||||||
|
var group = $(ui.helper).data("group");
|
||||||
|
if (group) {
|
||||||
|
var oldX = group.x;
|
||||||
|
var oldY = group.y;
|
||||||
|
RED.group.addToGroup(group, nn);
|
||||||
|
var moveEvent = null;
|
||||||
|
if ((group.x !== oldX) ||
|
||||||
|
(group.y !== oldY)) {
|
||||||
|
moveEvent = {
|
||||||
|
t: "move",
|
||||||
|
nodes: [{n: group,
|
||||||
|
ox: oldX, oy: oldY,
|
||||||
|
dx: group.x -oldX,
|
||||||
|
dy: group.y -oldY}],
|
||||||
|
dirty: true
|
||||||
|
};
|
||||||
|
}
|
||||||
|
historyEvent = {
|
||||||
|
t: 'multi',
|
||||||
|
events: [historyEvent],
|
||||||
|
|
||||||
var group = $(ui.helper).data("group");
|
|
||||||
if (group) {
|
|
||||||
var oldX = group.x;
|
|
||||||
var oldY = group.y;
|
|
||||||
RED.group.addToGroup(group, nn);
|
|
||||||
var moveEvent = null;
|
|
||||||
if ((group.x !== oldX) ||
|
|
||||||
(group.y !== oldY)) {
|
|
||||||
moveEvent = {
|
|
||||||
t: "move",
|
|
||||||
nodes: [{n: group,
|
|
||||||
ox: oldX, oy: oldY,
|
|
||||||
dx: group.x -oldX,
|
|
||||||
dy: group.y -oldY}],
|
|
||||||
dirty: true
|
|
||||||
};
|
};
|
||||||
|
if (moveEvent) {
|
||||||
|
historyEvent.events.push(moveEvent)
|
||||||
|
}
|
||||||
|
historyEvent.events.push({
|
||||||
|
t: "addToGroup",
|
||||||
|
group: group,
|
||||||
|
nodes: nn
|
||||||
|
})
|
||||||
}
|
}
|
||||||
historyEvent = {
|
|
||||||
t: 'multi',
|
|
||||||
events: [historyEvent],
|
|
||||||
|
|
||||||
};
|
RED.history.push(historyEvent);
|
||||||
if (moveEvent) {
|
RED.editor.validateNode(nn);
|
||||||
historyEvent.events.push(moveEvent)
|
RED.nodes.dirty(true);
|
||||||
|
// auto select dropped node - so info shows (if visible)
|
||||||
|
clearSelection();
|
||||||
|
nn.selected = true;
|
||||||
|
movingSet.add(nn);
|
||||||
|
updateActiveNodes();
|
||||||
|
updateSelection();
|
||||||
|
redraw();
|
||||||
|
|
||||||
|
if (nn._def.autoedit) {
|
||||||
|
RED.editor.edit(nn);
|
||||||
|
}
|
||||||
|
} catch (error) {
|
||||||
|
if (error.code != "NODE_RED") {
|
||||||
|
RED.notify(RED._("notification.error",{message:error.toString()}),"error");
|
||||||
|
} else {
|
||||||
|
RED.notify(RED._("notification.error",{message:error.message}),"error");
|
||||||
}
|
}
|
||||||
historyEvent.events.push({
|
|
||||||
t: "addToGroup",
|
|
||||||
group: group,
|
|
||||||
nodes: nn
|
|
||||||
})
|
|
||||||
}
|
|
||||||
|
|
||||||
RED.history.push(historyEvent);
|
|
||||||
RED.editor.validateNode(nn);
|
|
||||||
RED.nodes.dirty(true);
|
|
||||||
// auto select dropped node - so info shows (if visible)
|
|
||||||
clearSelection();
|
|
||||||
nn.selected = true;
|
|
||||||
movingSet.add(nn);
|
|
||||||
updateActiveNodes();
|
|
||||||
updateSelection();
|
|
||||||
redraw();
|
|
||||||
|
|
||||||
if (nn._def.autoedit) {
|
|
||||||
RED.editor.edit(nn);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -6063,14 +6071,19 @@ RED.view = (function() {
|
||||||
function createNode(type, x, y, z) {
|
function createNode(type, x, y, z) {
|
||||||
const wasDirty = RED.nodes.dirty()
|
const wasDirty = RED.nodes.dirty()
|
||||||
var m = /^subflow:(.+)$/.exec(type);
|
var m = /^subflow:(.+)$/.exec(type);
|
||||||
var activeSubflow = z ? RED.nodes.subflow(z) : null;
|
var activeSubflow = (z || RED.workspaces.active()) ? RED.nodes.subflow(z || RED.workspaces.active()) : null;
|
||||||
|
|
||||||
if (activeSubflow && m) {
|
if (activeSubflow && m) {
|
||||||
var subflowId = m[1];
|
var subflowId = m[1];
|
||||||
|
let err
|
||||||
if (subflowId === activeSubflow.id) {
|
if (subflowId === activeSubflow.id) {
|
||||||
throw new Error(RED._("notification.error", { message: RED._("notification.errors.cannotAddSubflowToItself") }))
|
err = new Error(RED._("notification.errors.cannotAddSubflowToItself"))
|
||||||
|
} else if (RED.nodes.subflowContains(m[1], activeSubflow.id)) {
|
||||||
|
err = new Error(RED._("notification.errors.cannotAddCircularReference"))
|
||||||
}
|
}
|
||||||
if (RED.nodes.subflowContains(m[1], activeSubflow.id)) {
|
if (err) {
|
||||||
throw new Error(RED._("notification.error", { message: RED._("notification.errors.cannotAddCircularReference") }))
|
err.code = 'NODE_RED'
|
||||||
|
throw err
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue