mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Merge branch 'master' into master
This commit is contained in:
commit
328390c2a9
@ -1038,23 +1038,34 @@ RED.nodes = (function() {
|
|||||||
return {nodes:removedNodes,links:removedLinks, groups: removedGroups, junctions: removedJunctions};
|
return {nodes:removedNodes,links:removedLinks, groups: removedGroups, junctions: removedJunctions};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Add a Subflow to the Workspace
|
||||||
|
*
|
||||||
|
* @param {object} sf The Subflow to add.
|
||||||
|
* @param {boolean|undefined} createNewIds Whether to update the name.
|
||||||
|
*/
|
||||||
function addSubflow(sf, createNewIds) {
|
function addSubflow(sf, createNewIds) {
|
||||||
if (createNewIds) {
|
if (createNewIds) {
|
||||||
var subflowNames = Object.keys(subflows).map(function(sfid) {
|
// Update the Subflow name to highlight that this is a copy
|
||||||
return subflows[sfid].name;
|
const subflowNames = Object.keys(subflows).map(function (sfid) {
|
||||||
});
|
return subflows[sfid].name || "";
|
||||||
|
})
|
||||||
|
subflowNames.sort()
|
||||||
|
|
||||||
subflowNames.sort();
|
let copyNumber = 1;
|
||||||
var copyNumber = 1;
|
let subflowName = sf.name;
|
||||||
var subflowName = sf.name;
|
|
||||||
subflowNames.forEach(function(name) {
|
subflowNames.forEach(function(name) {
|
||||||
if (subflowName == name) {
|
if (subflowName == name) {
|
||||||
|
subflowName = sf.name + " (" + copyNumber + ")";
|
||||||
copyNumber++;
|
copyNumber++;
|
||||||
subflowName = sf.name+" ("+copyNumber+")";
|
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
|
||||||
sf.name = subflowName;
|
sf.name = subflowName;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
sf.instances = [];
|
||||||
|
|
||||||
subflows[sf.id] = sf;
|
subflows[sf.id] = sf;
|
||||||
allNodes.addTab(sf.id);
|
allNodes.addTab(sf.id);
|
||||||
linkTabMap[sf.id] = [];
|
linkTabMap[sf.id] = [];
|
||||||
@ -1107,7 +1118,7 @@ RED.nodes = (function() {
|
|||||||
module: "node-red"
|
module: "node-red"
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
sf.instances = [];
|
|
||||||
sf._def = RED.nodes.getType("subflow:"+sf.id);
|
sf._def = RED.nodes.getType("subflow:"+sf.id);
|
||||||
RED.events.emit("subflows:add",sf);
|
RED.events.emit("subflows:add",sf);
|
||||||
}
|
}
|
||||||
@ -1749,7 +1760,8 @@ RED.nodes = (function() {
|
|||||||
// Remove the old subflow definition - but leave the instances in place
|
// Remove the old subflow definition - but leave the instances in place
|
||||||
var removalResult = RED.subflow.removeSubflow(n.id, true);
|
var removalResult = RED.subflow.removeSubflow(n.id, true);
|
||||||
// Create the list of nodes for the new subflow def
|
// Create the list of nodes for the new subflow def
|
||||||
var subflowNodes = [n].concat(zMap[n.id]);
|
// Need to sort the list in order to remove missing nodes
|
||||||
|
var subflowNodes = [n].concat(zMap[n.id]).filter((s) => !!s);
|
||||||
// Import the new subflow - no clashes should occur as we've removed
|
// Import the new subflow - no clashes should occur as we've removed
|
||||||
// the old version
|
// the old version
|
||||||
var result = importNodes(subflowNodes);
|
var result = importNodes(subflowNodes);
|
||||||
@ -2029,6 +2041,8 @@ RED.nodes = (function() {
|
|||||||
if (matchingSubflow) {
|
if (matchingSubflow) {
|
||||||
subflow_denylist[n.id] = matchingSubflow;
|
subflow_denylist[n.id] = matchingSubflow;
|
||||||
} else {
|
} else {
|
||||||
|
const oldId = n.id;
|
||||||
|
|
||||||
subflow_map[n.id] = n;
|
subflow_map[n.id] = n;
|
||||||
if (createNewIds || options.importMap[n.id] === "copy") {
|
if (createNewIds || options.importMap[n.id] === "copy") {
|
||||||
nid = getID();
|
nid = getID();
|
||||||
@ -2056,7 +2070,7 @@ RED.nodes = (function() {
|
|||||||
n.status.id = getID();
|
n.status.id = getID();
|
||||||
}
|
}
|
||||||
new_subflows.push(n);
|
new_subflows.push(n);
|
||||||
addSubflow(n,createNewIds || options.importMap[n.id] === "copy");
|
addSubflow(n,createNewIds || options.importMap[oldId] === "copy");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2176,7 +2190,7 @@ RED.nodes = (function() {
|
|||||||
x:parseFloat(n.x || 0),
|
x:parseFloat(n.x || 0),
|
||||||
y:parseFloat(n.y || 0),
|
y:parseFloat(n.y || 0),
|
||||||
z:n.z,
|
z:n.z,
|
||||||
type:0,
|
type: n.type,
|
||||||
info: n.info,
|
info: n.info,
|
||||||
changed:false,
|
changed:false,
|
||||||
_config:{}
|
_config:{}
|
||||||
@ -2237,7 +2251,6 @@ RED.nodes = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
node.type = n.type;
|
|
||||||
node._def = def;
|
node._def = def;
|
||||||
if (node.type === "group") {
|
if (node.type === "group") {
|
||||||
node._def = RED.group.def;
|
node._def = RED.group.def;
|
||||||
@ -2267,6 +2280,15 @@ RED.nodes = (function() {
|
|||||||
outputs: n.outputs|| (n.wires && n.wires.length) || 0,
|
outputs: n.outputs|| (n.wires && n.wires.length) || 0,
|
||||||
set: registry.getNodeSet("node-red/unknown")
|
set: registry.getNodeSet("node-red/unknown")
|
||||||
}
|
}
|
||||||
|
var orig = {};
|
||||||
|
for (var p in n) {
|
||||||
|
if (n.hasOwnProperty(p) && p!="x" && p!="y" && p!="z" && p!="id" && p!="wires") {
|
||||||
|
orig[p] = n[p];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
node._orig = orig;
|
||||||
|
node.name = n.type;
|
||||||
|
node.type = "unknown";
|
||||||
} else {
|
} else {
|
||||||
if (subflow_denylist[parentId] || createNewIds || options.importMap[n.id] === "copy") {
|
if (subflow_denylist[parentId] || createNewIds || options.importMap[n.id] === "copy") {
|
||||||
parentId = subflow.id;
|
parentId = subflow.id;
|
||||||
@ -2464,9 +2486,11 @@ RED.nodes = (function() {
|
|||||||
n = new_subflows[i];
|
n = new_subflows[i];
|
||||||
n.in.forEach(function(input) {
|
n.in.forEach(function(input) {
|
||||||
input.wires.forEach(function(wire) {
|
input.wires.forEach(function(wire) {
|
||||||
var link = {source:input, sourcePort:0, target:node_map[wire.id]};
|
if (node_map.hasOwnProperty(wire.id)) {
|
||||||
addLink(link);
|
var link = {source:input, sourcePort:0, target:node_map[wire.id]};
|
||||||
new_links.push(link);
|
addLink(link);
|
||||||
|
new_links.push(link);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
delete input.wires;
|
delete input.wires;
|
||||||
});
|
});
|
||||||
@ -2475,11 +2499,13 @@ RED.nodes = (function() {
|
|||||||
var link;
|
var link;
|
||||||
if (subflow_map[wire.id] && subflow_map[wire.id].id == n.id) {
|
if (subflow_map[wire.id] && subflow_map[wire.id].id == n.id) {
|
||||||
link = {source:n.in[wire.port], sourcePort:wire.port,target:output};
|
link = {source:n.in[wire.port], sourcePort:wire.port,target:output};
|
||||||
} else {
|
} else if (node_map.hasOwnProperty(wire.id) || subflow_map.hasOwnProperty(wire.id)) {
|
||||||
link = {source:node_map[wire.id]||subflow_map[wire.id], sourcePort:wire.port,target:output};
|
link = {source:node_map[wire.id]||subflow_map[wire.id], sourcePort:wire.port,target:output};
|
||||||
}
|
}
|
||||||
addLink(link);
|
if (link) {
|
||||||
new_links.push(link);
|
addLink(link);
|
||||||
|
new_links.push(link);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
delete output.wires;
|
delete output.wires;
|
||||||
});
|
});
|
||||||
@ -2488,11 +2514,13 @@ RED.nodes = (function() {
|
|||||||
var link;
|
var link;
|
||||||
if (subflow_map[wire.id] && subflow_map[wire.id].id == n.id) {
|
if (subflow_map[wire.id] && subflow_map[wire.id].id == n.id) {
|
||||||
link = {source:n.in[wire.port], sourcePort:wire.port,target:n.status};
|
link = {source:n.in[wire.port], sourcePort:wire.port,target:n.status};
|
||||||
} else {
|
} else if (node_map.hasOwnProperty(wire.id) || subflow_map.hasOwnProperty(wire.id)) {
|
||||||
link = {source:node_map[wire.id]||subflow_map[wire.id], sourcePort:wire.port,target:n.status};
|
link = {source:node_map[wire.id]||subflow_map[wire.id], sourcePort:wire.port,target:n.status};
|
||||||
}
|
}
|
||||||
addLink(link);
|
if (link) {
|
||||||
new_links.push(link);
|
addLink(link);
|
||||||
|
new_links.push(link);
|
||||||
|
}
|
||||||
});
|
});
|
||||||
delete n.status.wires;
|
delete n.status.wires;
|
||||||
}
|
}
|
||||||
|
@ -288,7 +288,7 @@ RED.view = (function() {
|
|||||||
}
|
}
|
||||||
selectedLinks.clearUnselected()
|
selectedLinks.clearUnselected()
|
||||||
},
|
},
|
||||||
length: () => groups.length,
|
length: () => groups.size,
|
||||||
forEach: (func) => { groups.forEach(func) },
|
forEach: (func) => { groups.forEach(func) },
|
||||||
toArray: () => [...groups],
|
toArray: () => [...groups],
|
||||||
clear: function () {
|
clear: function () {
|
||||||
@ -2689,22 +2689,21 @@ RED.view = (function() {
|
|||||||
addToRemovedLinks(reconnectResult.removedLinks)
|
addToRemovedLinks(reconnectResult.removedLinks)
|
||||||
}
|
}
|
||||||
|
|
||||||
var startDirty = RED.nodes.dirty();
|
const startDirty = RED.nodes.dirty();
|
||||||
var startChanged = false;
|
let movingSelectedGroups = [];
|
||||||
var selectedGroups = [];
|
|
||||||
if (movingSet.length() > 0) {
|
if (movingSet.length() > 0) {
|
||||||
|
|
||||||
for (var i=0;i<movingSet.length();i++) {
|
for (var i=0;i<movingSet.length();i++) {
|
||||||
node = movingSet.get(i).n;
|
node = movingSet.get(i).n;
|
||||||
if (node.type === "group") {
|
if (node.type === "group") {
|
||||||
selectedGroups.push(node);
|
movingSelectedGroups.push(node);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
// Make sure we have identified all groups about to be deleted
|
// Make sure we have identified all groups about to be deleted
|
||||||
for (i=0;i<selectedGroups.length;i++) {
|
for (i=0;i<movingSelectedGroups.length;i++) {
|
||||||
selectedGroups[i].nodes.forEach(function(n) {
|
movingSelectedGroups[i].nodes.forEach(function(n) {
|
||||||
if (n.type === "group" && selectedGroups.indexOf(n) === -1) {
|
if (n.type === "group" && movingSelectedGroups.indexOf(n) === -1) {
|
||||||
selectedGroups.push(n);
|
movingSelectedGroups.push(n);
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
@ -2721,7 +2720,7 @@ RED.view = (function() {
|
|||||||
addToRemovedLinks(removedEntities.links);
|
addToRemovedLinks(removedEntities.links);
|
||||||
if (node.g) {
|
if (node.g) {
|
||||||
var group = RED.nodes.group(node.g);
|
var group = RED.nodes.group(node.g);
|
||||||
if (selectedGroups.indexOf(group) === -1) {
|
if (movingSelectedGroups.indexOf(group) === -1) {
|
||||||
// Don't use RED.group.removeFromGroup as that emits
|
// Don't use RED.group.removeFromGroup as that emits
|
||||||
// a change event on the node - but we're deleting it
|
// a change event on the node - but we're deleting it
|
||||||
var index = group.nodes.indexOf(node);
|
var index = group.nodes.indexOf(node);
|
||||||
@ -2735,7 +2734,7 @@ RED.view = (function() {
|
|||||||
removedLinks = removedLinks.concat(result.links);
|
removedLinks = removedLinks.concat(result.links);
|
||||||
if (node.g) {
|
if (node.g) {
|
||||||
var group = RED.nodes.group(node.g);
|
var group = RED.nodes.group(node.g);
|
||||||
if (selectedGroups.indexOf(group) === -1) {
|
if (movingSelectedGroups.indexOf(group) === -1) {
|
||||||
// Don't use RED.group.removeFromGroup as that emits
|
// Don't use RED.group.removeFromGroup as that emits
|
||||||
// a change event on the node - but we're deleting it
|
// a change event on the node - but we're deleting it
|
||||||
var index = group.nodes.indexOf(node);
|
var index = group.nodes.indexOf(node);
|
||||||
@ -2757,8 +2756,8 @@ RED.view = (function() {
|
|||||||
|
|
||||||
// Groups must be removed in the right order - from inner-most
|
// Groups must be removed in the right order - from inner-most
|
||||||
// to outermost.
|
// to outermost.
|
||||||
for (i = selectedGroups.length-1; i>=0; i--) {
|
for (i = movingSelectedGroups.length-1; i>=0; i--) {
|
||||||
var g = selectedGroups[i];
|
var g = movingSelectedGroups[i];
|
||||||
removedGroups.push(g);
|
removedGroups.push(g);
|
||||||
RED.nodes.removeGroup(g);
|
RED.nodes.removeGroup(g);
|
||||||
}
|
}
|
||||||
|
@ -253,7 +253,13 @@ module.exports = function(RED) {
|
|||||||
if (node.allowrate && m.hasOwnProperty("rate") && !isNaN(parseFloat(m.rate))) {
|
if (node.allowrate && m.hasOwnProperty("rate") && !isNaN(parseFloat(m.rate))) {
|
||||||
node.rate = m.rate;
|
node.rate = m.rate;
|
||||||
}
|
}
|
||||||
send(m);
|
if (msg.hasOwnProperty("reset")) {
|
||||||
|
if (msg.hasOwnProperty("flush")) {
|
||||||
|
node.buffer.push({msg: m, send: send, done: done});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else { send(m); }
|
||||||
|
|
||||||
node.reportDepth();
|
node.reportDepth();
|
||||||
node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
|
node.intervalID = setInterval(sendMsgFromBuffer, node.rate);
|
||||||
done();
|
done();
|
||||||
@ -303,7 +309,8 @@ module.exports = function(RED) {
|
|||||||
node.droppedMsgs++;
|
node.droppedMsgs++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
}
|
||||||
|
else {
|
||||||
if (node.allowrate && msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate))) {
|
if (node.allowrate && msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate))) {
|
||||||
node.rate = msg.rate;
|
node.rate = msg.rate;
|
||||||
}
|
}
|
||||||
|
@ -113,6 +113,10 @@ async function evaluateEnvProperties(flow, env, credentials) {
|
|||||||
resolve()
|
resolve()
|
||||||
});
|
});
|
||||||
}))
|
}))
|
||||||
|
} else if (type === "conf-type" && /^\${[^}]+}$/.test(value)) {
|
||||||
|
// Get the config node from the parent subflow
|
||||||
|
const name = value.substring(2, value.length - 1);
|
||||||
|
value = flow.getSetting(name);
|
||||||
} else {
|
} else {
|
||||||
try {
|
try {
|
||||||
value = redUtil.evaluateNodeProperty(value, type, {_flow: flow}, null, null);
|
value = redUtil.evaluateNodeProperty(value, type, {_flow: flow}, null, null);
|
||||||
|
@ -1009,6 +1009,29 @@ describe('delay Node', function() {
|
|||||||
});
|
});
|
||||||
});
|
});
|
||||||
|
|
||||||
|
it('sending a msg with reset to empty queue doesnt send anything', function(done) {
|
||||||
|
this.timeout(2000);
|
||||||
|
var flow = [{"id":"delayNode1","type":"delay","name":"delayNode","pauseType":"rate","timeout":1,"timeoutUnits":"seconds","rate":2,"rateUnits":"second","randomFirst":"1","randomLast":"5","randomUnits":"seconds","drop":false,"wires":[["helperNode1"]]},
|
||||||
|
{id:"helperNode1", type:"helper", wires:[]}];
|
||||||
|
helper.load(delayNode, flow, function() {
|
||||||
|
var delayNode1 = helper.getNode("delayNode1");
|
||||||
|
var helperNode1 = helper.getNode("helperNode1");
|
||||||
|
var t = Date.now();
|
||||||
|
var c = 0;
|
||||||
|
helperNode1.on("input", function(msg) {
|
||||||
|
console.log("Shold not get here")
|
||||||
|
done(e);
|
||||||
|
});
|
||||||
|
|
||||||
|
setTimeout( function() {
|
||||||
|
if (c === 0) { done(); }
|
||||||
|
}, 250);
|
||||||
|
|
||||||
|
// send test messages
|
||||||
|
delayNode1.receive({payload:1,topic:"foo",reset:true}); // send something with blank topic
|
||||||
|
});
|
||||||
|
});
|
||||||
|
|
||||||
/* Messaging API support */
|
/* Messaging API support */
|
||||||
function mapiDoneTestHelper(done, pauseType, drop, msgAndTimings) {
|
function mapiDoneTestHelper(done, pauseType, drop, msgAndTimings) {
|
||||||
const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js");
|
const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js");
|
||||||
|
Loading…
x
Reference in New Issue
Block a user