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:
		| @@ -1038,23 +1038,34 @@ RED.nodes = (function() { | ||||
|         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) { | ||||
|         if (createNewIds) { | ||||
|             var subflowNames = Object.keys(subflows).map(function(sfid) { | ||||
|                 return subflows[sfid].name; | ||||
|             }); | ||||
|             // Update the Subflow name to highlight that this is a copy | ||||
|             const subflowNames = Object.keys(subflows).map(function (sfid) { | ||||
|                 return subflows[sfid].name || ""; | ||||
|             }) | ||||
|             subflowNames.sort() | ||||
|  | ||||
|             subflowNames.sort(); | ||||
|             var copyNumber = 1; | ||||
|             var subflowName = sf.name; | ||||
|             let copyNumber = 1; | ||||
|             let subflowName = sf.name; | ||||
|             subflowNames.forEach(function(name) { | ||||
|                 if (subflowName == name) { | ||||
|                     subflowName = sf.name + " (" + copyNumber + ")"; | ||||
|                     copyNumber++; | ||||
|                     subflowName = sf.name+" ("+copyNumber+")"; | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             sf.name = subflowName; | ||||
|         } | ||||
|  | ||||
|         sf.instances = []; | ||||
|  | ||||
|         subflows[sf.id] = sf; | ||||
|         allNodes.addTab(sf.id); | ||||
|         linkTabMap[sf.id] = []; | ||||
| @@ -1107,7 +1118,7 @@ RED.nodes = (function() { | ||||
|                 module: "node-red" | ||||
|             } | ||||
|         }); | ||||
|         sf.instances = []; | ||||
|  | ||||
|         sf._def = RED.nodes.getType("subflow:"+sf.id); | ||||
|         RED.events.emit("subflows:add",sf); | ||||
|     } | ||||
| @@ -1749,7 +1760,8 @@ RED.nodes = (function() { | ||||
|             // Remove the old subflow definition - but leave the instances in place | ||||
|             var removalResult = RED.subflow.removeSubflow(n.id, true); | ||||
|             // 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 | ||||
|             // the old version | ||||
|             var result = importNodes(subflowNodes); | ||||
| @@ -2029,6 +2041,8 @@ RED.nodes = (function() { | ||||
|                 if (matchingSubflow) { | ||||
|                     subflow_denylist[n.id] = matchingSubflow; | ||||
|                 } else { | ||||
|                     const oldId = n.id; | ||||
|  | ||||
|                     subflow_map[n.id] = n; | ||||
|                     if (createNewIds || options.importMap[n.id] === "copy") { | ||||
|                         nid = getID(); | ||||
| @@ -2056,7 +2070,7 @@ RED.nodes = (function() { | ||||
|                         n.status.id = getID(); | ||||
|                     } | ||||
|                     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), | ||||
|                         y:parseFloat(n.y || 0), | ||||
|                         z:n.z, | ||||
|                         type:0, | ||||
|                         type: n.type, | ||||
|                         info: n.info, | ||||
|                         changed:false, | ||||
|                         _config:{} | ||||
| @@ -2237,7 +2251,6 @@ RED.nodes = (function() { | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                     node.type = n.type; | ||||
|                     node._def = def; | ||||
|                     if (node.type === "group") { | ||||
|                         node._def = RED.group.def; | ||||
| @@ -2267,6 +2280,15 @@ RED.nodes = (function() { | ||||
|                                 outputs: n.outputs|| (n.wires && n.wires.length) || 0, | ||||
|                                 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 { | ||||
|                             if (subflow_denylist[parentId] || createNewIds || options.importMap[n.id] === "copy") { | ||||
|                                 parentId = subflow.id; | ||||
| @@ -2464,9 +2486,11 @@ RED.nodes = (function() { | ||||
|             n = new_subflows[i]; | ||||
|             n.in.forEach(function(input) { | ||||
|                 input.wires.forEach(function(wire) { | ||||
|                     var link = {source:input, sourcePort:0, target:node_map[wire.id]}; | ||||
|                     addLink(link); | ||||
|                     new_links.push(link); | ||||
|                     if (node_map.hasOwnProperty(wire.id)) { | ||||
|                         var link = {source:input, sourcePort:0, target:node_map[wire.id]}; | ||||
|                         addLink(link); | ||||
|                         new_links.push(link); | ||||
|                     } | ||||
|                 }); | ||||
|                 delete input.wires; | ||||
|             }); | ||||
| @@ -2475,11 +2499,13 @@ RED.nodes = (function() { | ||||
|                     var link; | ||||
|                     if (subflow_map[wire.id] && subflow_map[wire.id].id == n.id) { | ||||
|                         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}; | ||||
|                     } | ||||
|                     addLink(link); | ||||
|                     new_links.push(link); | ||||
|                     if (link) { | ||||
|                         addLink(link); | ||||
|                         new_links.push(link); | ||||
|                     } | ||||
|                 }); | ||||
|                 delete output.wires; | ||||
|             }); | ||||
| @@ -2488,11 +2514,13 @@ RED.nodes = (function() { | ||||
|                     var link; | ||||
|                     if (subflow_map[wire.id] && subflow_map[wire.id].id == n.id) { | ||||
|                         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}; | ||||
|                     } | ||||
|                     addLink(link); | ||||
|                     new_links.push(link); | ||||
|                     if (link) { | ||||
|                         addLink(link); | ||||
|                         new_links.push(link); | ||||
|                     } | ||||
|                 }); | ||||
|                 delete n.status.wires; | ||||
|             } | ||||
|   | ||||
| @@ -288,7 +288,7 @@ RED.view = (function() { | ||||
|                 } | ||||
|                 selectedLinks.clearUnselected() | ||||
|             }, | ||||
|             length: () => groups.length, | ||||
|             length: () => groups.size, | ||||
|             forEach: (func) => { groups.forEach(func) }, | ||||
|             toArray: () => [...groups], | ||||
|             clear: function () { | ||||
| @@ -2689,22 +2689,21 @@ RED.view = (function() { | ||||
|                 addToRemovedLinks(reconnectResult.removedLinks) | ||||
|             } | ||||
|  | ||||
|             var startDirty = RED.nodes.dirty(); | ||||
|             var startChanged = false; | ||||
|             var selectedGroups = []; | ||||
|             const startDirty = RED.nodes.dirty(); | ||||
|             let movingSelectedGroups = []; | ||||
|             if (movingSet.length() > 0) { | ||||
|  | ||||
|                 for (var i=0;i<movingSet.length();i++) { | ||||
|                     node = movingSet.get(i).n; | ||||
|                     if (node.type === "group") { | ||||
|                         selectedGroups.push(node); | ||||
|                         movingSelectedGroups.push(node); | ||||
|                     } | ||||
|                 } | ||||
|                 // Make sure we have identified all groups about to be deleted | ||||
|                 for (i=0;i<selectedGroups.length;i++) { | ||||
|                     selectedGroups[i].nodes.forEach(function(n) { | ||||
|                         if (n.type === "group" && selectedGroups.indexOf(n) === -1) { | ||||
|                             selectedGroups.push(n); | ||||
|                 for (i=0;i<movingSelectedGroups.length;i++) { | ||||
|                     movingSelectedGroups[i].nodes.forEach(function(n) { | ||||
|                         if (n.type === "group" && movingSelectedGroups.indexOf(n) === -1) { | ||||
|                             movingSelectedGroups.push(n); | ||||
|                         } | ||||
|                     }) | ||||
|                 } | ||||
| @@ -2721,7 +2720,7 @@ RED.view = (function() { | ||||
|                         addToRemovedLinks(removedEntities.links); | ||||
|                         if (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 | ||||
|                                 // a change event on the node - but we're deleting it | ||||
|                                 var index = group.nodes.indexOf(node); | ||||
| @@ -2735,7 +2734,7 @@ RED.view = (function() { | ||||
|                         removedLinks = removedLinks.concat(result.links); | ||||
|                         if (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 | ||||
|                                 // a change event on the node - but we're deleting it | ||||
|                                 var index = group.nodes.indexOf(node); | ||||
| @@ -2757,8 +2756,8 @@ RED.view = (function() { | ||||
|  | ||||
|                 // Groups must be removed in the right order - from inner-most | ||||
|                 // to outermost. | ||||
|                 for (i = selectedGroups.length-1; i>=0; i--) { | ||||
|                     var g = selectedGroups[i]; | ||||
|                 for (i = movingSelectedGroups.length-1; i>=0; i--) { | ||||
|                     var g = movingSelectedGroups[i]; | ||||
|                     removedGroups.push(g); | ||||
|                     RED.nodes.removeGroup(g); | ||||
|                 } | ||||
|   | ||||
| @@ -253,7 +253,13 @@ module.exports = function(RED) { | ||||
|                             if (node.allowrate && m.hasOwnProperty("rate") && !isNaN(parseFloat(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.intervalID = setInterval(sendMsgFromBuffer, node.rate); | ||||
|                             done(); | ||||
| @@ -303,7 +309,8 @@ module.exports = function(RED) { | ||||
|                                 node.droppedMsgs++; | ||||
|                             } | ||||
|                         } | ||||
|                     } else { | ||||
|                     } | ||||
|                     else { | ||||
|                         if (node.allowrate && msg.hasOwnProperty("rate") && !isNaN(parseFloat(msg.rate))) { | ||||
|                             node.rate = msg.rate; | ||||
|                         } | ||||
|   | ||||
| @@ -113,6 +113,10 @@ async function evaluateEnvProperties(flow, env, credentials) { | ||||
|                     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 { | ||||
|             try { | ||||
|                 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 */ | ||||
|     function mapiDoneTestHelper(done, pauseType, drop, msgAndTimings) { | ||||
|         const completeNode = require("nr-test-utils").require("@node-red/nodes/core/common/24-complete.js"); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user