mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Merge branch 'gg-changes' into fix-conf-type-env
This commit is contained in:
commit
5f92bc83fd
@ -574,6 +574,24 @@ RED.history = (function() {
|
|||||||
RED.editor.updateNodeProperties(ev.node,outputMap);
|
RED.editor.updateNodeProperties(ev.node,outputMap);
|
||||||
RED.editor.validateNode(ev.node);
|
RED.editor.validateNode(ev.node);
|
||||||
}
|
}
|
||||||
|
// If it's a Config Node, validate user nodes too.
|
||||||
|
// NOTE: The Config Node must be validated before validating users.
|
||||||
|
if (ev.node.users) {
|
||||||
|
const validatedNodes = new Set();
|
||||||
|
const userStack = ev.node.users.slice();
|
||||||
|
|
||||||
|
validatedNodes.add(ev.node.id);
|
||||||
|
while (userStack.length) {
|
||||||
|
const node = userStack.pop();
|
||||||
|
if (!validatedNodes.has(node.id)) {
|
||||||
|
validatedNodes.add(node.id);
|
||||||
|
if (node.users) {
|
||||||
|
userStack.push(...node.users);
|
||||||
|
}
|
||||||
|
RED.editor.validateNode(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
if (ev.links) {
|
if (ev.links) {
|
||||||
inverseEv.createdLinks = [];
|
inverseEv.createdLinks = [];
|
||||||
for (i=0;i<ev.links.length;i++) {
|
for (i=0;i<ev.links.length;i++) {
|
||||||
|
@ -73,7 +73,13 @@ RED.nodes = (function() {
|
|||||||
|
|
||||||
var exports = {
|
var exports = {
|
||||||
setModulePendingUpdated: function(module,version) {
|
setModulePendingUpdated: function(module,version) {
|
||||||
moduleList[module].pending_version = version;
|
if (!!RED.plugins.getModule(module)) {
|
||||||
|
// The module updated is a plugin
|
||||||
|
RED.plugins.getModule(module).pending_version = version;
|
||||||
|
} else {
|
||||||
|
moduleList[module].pending_version = version;
|
||||||
|
}
|
||||||
|
|
||||||
RED.events.emit("registry:module-updated",{module:module,version:version});
|
RED.events.emit("registry:module-updated",{module:module,version:version});
|
||||||
},
|
},
|
||||||
getModule: function(module) {
|
getModule: function(module) {
|
||||||
@ -706,7 +712,7 @@ RED.nodes = (function() {
|
|||||||
} else {
|
} else {
|
||||||
if (n.wires && (n.wires.length > n.outputs)) { n.outputs = n.wires.length; }
|
if (n.wires && (n.wires.length > n.outputs)) { n.outputs = n.wires.length; }
|
||||||
n.dirty = true;
|
n.dirty = true;
|
||||||
updateConfigNodeUsers(newNode);
|
updateConfigNodeUsers(newNode, { action: "add" });
|
||||||
if (n._def.category == "subflows" && typeof n.i === "undefined") {
|
if (n._def.category == "subflows" && typeof n.i === "undefined") {
|
||||||
var nextId = 0;
|
var nextId = 0;
|
||||||
RED.nodes.eachNode(function(node) {
|
RED.nodes.eachNode(function(node) {
|
||||||
@ -779,6 +785,7 @@ RED.nodes = (function() {
|
|||||||
delete nodeLinks[id];
|
delete nodeLinks[id];
|
||||||
removedLinks = links.filter(function(l) { return (l.source === node) || (l.target === node); });
|
removedLinks = links.filter(function(l) { return (l.source === node) || (l.target === node); });
|
||||||
removedLinks.forEach(removeLink);
|
removedLinks.forEach(removeLink);
|
||||||
|
updateConfigNodeUsers(node, { action: "remove" });
|
||||||
var updatedConfigNode = false;
|
var updatedConfigNode = false;
|
||||||
for (var d in node._def.defaults) {
|
for (var d in node._def.defaults) {
|
||||||
if (node._def.defaults.hasOwnProperty(d)) {
|
if (node._def.defaults.hasOwnProperty(d)) {
|
||||||
@ -792,10 +799,6 @@ RED.nodes = (function() {
|
|||||||
if (configNode._def.exclusive) {
|
if (configNode._def.exclusive) {
|
||||||
removeNode(node[d]);
|
removeNode(node[d]);
|
||||||
removedNodes.push(configNode);
|
removedNodes.push(configNode);
|
||||||
} else {
|
|
||||||
var users = configNode.users;
|
|
||||||
users.splice(users.indexOf(node),1);
|
|
||||||
RED.events.emit('nodes:change',configNode)
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1046,23 +1049,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] = [];
|
||||||
@ -1115,7 +1129,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);
|
||||||
}
|
}
|
||||||
@ -1757,7 +1771,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);
|
||||||
@ -1794,9 +1809,20 @@ RED.nodes = (function() {
|
|||||||
// Replace config nodes
|
// Replace config nodes
|
||||||
//
|
//
|
||||||
configNodeIds.forEach(function(id) {
|
configNodeIds.forEach(function(id) {
|
||||||
removedNodes = removedNodes.concat(convertNode(getNode(id)));
|
const configNode = getNode(id);
|
||||||
|
const currentUserCount = configNode.users;
|
||||||
|
|
||||||
|
// Add a snapshot of the Config Node
|
||||||
|
removedNodes = removedNodes.concat(convertNode(configNode));
|
||||||
|
|
||||||
|
// Remove the Config Node instance
|
||||||
removeNode(id);
|
removeNode(id);
|
||||||
importNodes([newConfigNodes[id]])
|
|
||||||
|
// Import the new one
|
||||||
|
importNodes([newConfigNodes[id]]);
|
||||||
|
|
||||||
|
// Re-attributes the user count
|
||||||
|
getNode(id).users = currentUserCount;
|
||||||
});
|
});
|
||||||
|
|
||||||
return {
|
return {
|
||||||
@ -2037,6 +2063,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();
|
||||||
@ -2064,7 +2092,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");
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -2184,7 +2212,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:{}
|
||||||
@ -2245,7 +2273,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;
|
||||||
@ -2275,6 +2302,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;
|
||||||
@ -2335,29 +2371,31 @@ RED.nodes = (function() {
|
|||||||
node.type = "unknown";
|
node.type = "unknown";
|
||||||
}
|
}
|
||||||
if (node._def.category != "config") {
|
if (node._def.category != "config") {
|
||||||
if (n.hasOwnProperty('inputs')) {
|
if (n.hasOwnProperty('inputs') && def.defaults.hasOwnProperty("inputs")) {
|
||||||
node.inputs = n.inputs;
|
node.inputs = parseInt(n.inputs, 10);
|
||||||
node._config.inputs = JSON.stringify(n.inputs);
|
node._config.inputs = JSON.stringify(n.inputs);
|
||||||
} else {
|
} else {
|
||||||
node.inputs = node._def.inputs;
|
node.inputs = node._def.inputs;
|
||||||
}
|
}
|
||||||
if (n.hasOwnProperty('outputs')) {
|
if (n.hasOwnProperty('outputs') && def.defaults.hasOwnProperty("outputs")) {
|
||||||
node.outputs = n.outputs;
|
node.outputs = parseInt(n.outputs, 10);
|
||||||
node._config.outputs = JSON.stringify(n.outputs);
|
node._config.outputs = JSON.stringify(n.outputs);
|
||||||
} else {
|
} else {
|
||||||
node.outputs = node._def.outputs;
|
node.outputs = node._def.outputs;
|
||||||
}
|
}
|
||||||
if (node.hasOwnProperty('wires') && node.wires.length > node.outputs) {
|
|
||||||
if (!node._def.defaults.hasOwnProperty("outputs") || !isNaN(parseInt(n.outputs))) {
|
// The node declares outputs in its defaults, but has not got a valid value
|
||||||
// If 'wires' is longer than outputs, clip wires
|
// Defer to the length of the wires array
|
||||||
console.log("Warning: node.wires longer than node.outputs - trimming wires:",node.id," wires:",node.wires.length," outputs:",node.outputs);
|
if (node.hasOwnProperty('wires')) {
|
||||||
node.wires = node.wires.slice(0,node.outputs);
|
if (isNaN(node.outputs)) {
|
||||||
} else {
|
|
||||||
// The node declares outputs in its defaults, but has not got a valid value
|
|
||||||
// Defer to the length of the wires array
|
|
||||||
node.outputs = node.wires.length;
|
node.outputs = node.wires.length;
|
||||||
|
} else if (node.wires.length > node.outputs) {
|
||||||
|
// If 'wires' is longer than outputs, clip wires
|
||||||
|
console.log("Warning: node.wires longer than node.outputs - trimming wires:", node.id, " wires:", node.wires.length, " outputs:", node.outputs);
|
||||||
|
node.wires = node.wires.slice(0, node.outputs);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
for (d in node._def.defaults) {
|
for (d in node._def.defaults) {
|
||||||
if (node._def.defaults.hasOwnProperty(d) && d !== 'inputs' && d !== 'outputs') {
|
if (node._def.defaults.hasOwnProperty(d) && d !== 'inputs' && d !== 'outputs') {
|
||||||
node[d] = n[d];
|
node[d] = n[d];
|
||||||
@ -2454,11 +2492,6 @@ RED.nodes = (function() {
|
|||||||
nodeList = nodeList.map(function(id) {
|
nodeList = nodeList.map(function(id) {
|
||||||
var node = node_map[id];
|
var node = node_map[id];
|
||||||
if (node) {
|
if (node) {
|
||||||
if (node._def.category === 'config') {
|
|
||||||
if (node.users.indexOf(n) === -1) {
|
|
||||||
node.users.push(n);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return node.id;
|
return node.id;
|
||||||
}
|
}
|
||||||
return id;
|
return id;
|
||||||
@ -2472,9 +2505,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;
|
||||||
});
|
});
|
||||||
@ -2483,11 +2518,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;
|
||||||
});
|
});
|
||||||
@ -2496,11 +2533,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;
|
||||||
}
|
}
|
||||||
@ -2679,19 +2718,44 @@ RED.nodes = (function() {
|
|||||||
return result;
|
return result;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Update any config nodes referenced by the provided node to ensure their 'users' list is correct
|
/**
|
||||||
function updateConfigNodeUsers(n) {
|
* Update any config nodes referenced by the provided node to ensure
|
||||||
for (var d in n._def.defaults) {
|
* their 'users' list is correct.
|
||||||
if (n._def.defaults.hasOwnProperty(d)) {
|
*
|
||||||
var property = n._def.defaults[d];
|
* Options:
|
||||||
|
* - `action` - Add or remove the node from the Config Node users list. Default `add`.
|
||||||
|
* - `emitEvent` - Emit the `nodes:changes` event. Default true.
|
||||||
|
*
|
||||||
|
* @param {object} node The node in which to check if it contains references
|
||||||
|
* @param {{ action?: "add" | "remove"; emitEvent?: boolean; }} options Options to apply.
|
||||||
|
*/
|
||||||
|
function updateConfigNodeUsers(node, options = {}) {
|
||||||
|
const defaultOptions = { action: "add", emitEvent: true };
|
||||||
|
options = Object.assign({}, defaultOptions, options);
|
||||||
|
|
||||||
|
for (var d in node._def.defaults) {
|
||||||
|
if (node._def.defaults.hasOwnProperty(d)) {
|
||||||
|
var property = node._def.defaults[d];
|
||||||
if (property.type) {
|
if (property.type) {
|
||||||
var type = registry.getNodeType(property.type);
|
var type = registry.getNodeType(property.type);
|
||||||
if (type && type.category == "config") {
|
if (type && type.category == "config") {
|
||||||
var configNode = configNodes[n[d]];
|
var configNode = configNodes[node[d]];
|
||||||
if (configNode) {
|
if (configNode) {
|
||||||
if (configNode.users.indexOf(n) === -1) {
|
if (options.action === "add") {
|
||||||
configNode.users.push(n);
|
if (configNode.users.indexOf(node) === -1) {
|
||||||
RED.events.emit('nodes:change',configNode)
|
configNode.users.push(node);
|
||||||
|
if (options.emitEvent) {
|
||||||
|
RED.events.emit('nodes:change', configNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else if (options.action === "remove") {
|
||||||
|
if (configNode.users.indexOf(node) !== -1) {
|
||||||
|
const users = configNode.users;
|
||||||
|
users.splice(users.indexOf(node), 1);
|
||||||
|
if (options.emitEvent) {
|
||||||
|
RED.events.emit('nodes:change', configNode);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -808,6 +808,17 @@ RED.editor = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const oldCreds = {};
|
||||||
|
if (editing_node._def.credentials) {
|
||||||
|
for (const prop in editing_node._def.credentials) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(editing_node._def.credentials, prop)) {
|
||||||
|
if (prop in editing_node.credentials) {
|
||||||
|
oldCreds[prop] = editing_node.credentials[prop];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
try {
|
try {
|
||||||
const rc = editing_node._def.oneditsave.call(editing_node);
|
const rc = editing_node._def.oneditsave.call(editing_node);
|
||||||
if (rc === true) {
|
if (rc === true) {
|
||||||
@ -839,6 +850,21 @@ RED.editor = (function() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (editing_node._def.credentials) {
|
||||||
|
for (const prop in editing_node._def.credentials) {
|
||||||
|
if (Object.prototype.hasOwnProperty.call(editing_node._def.credentials, prop)) {
|
||||||
|
if (oldCreds[prop] !== editing_node.credentials[prop]) {
|
||||||
|
if (editing_node.credentials[prop] === '__PWRD__') {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
editState.changes.credentials = editState.changes.credentials || {};
|
||||||
|
editState.changes.credentials[prop] = oldCreds[prop];
|
||||||
|
editState.changed = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -1481,134 +1507,181 @@ RED.editor = (function() {
|
|||||||
},
|
},
|
||||||
{
|
{
|
||||||
id: "node-config-dialog-ok",
|
id: "node-config-dialog-ok",
|
||||||
text: adding?RED._("editor.configAdd"):RED._("editor.configUpdate"),
|
text: adding ? RED._("editor.configAdd") : RED._("editor.configUpdate"),
|
||||||
class: "primary",
|
class: "primary",
|
||||||
click: function() {
|
click: function() {
|
||||||
var editState = {
|
// TODO: Already defined
|
||||||
|
const configProperty = name;
|
||||||
|
const configType = type;
|
||||||
|
const configTypeDef = RED.nodes.getType(configType);
|
||||||
|
|
||||||
|
const wasChanged = editing_config_node.changed;
|
||||||
|
const editState = {
|
||||||
changes: {},
|
changes: {},
|
||||||
changed: false,
|
changed: false,
|
||||||
outputMap: null
|
outputMap: null
|
||||||
};
|
};
|
||||||
var configProperty = name;
|
|
||||||
var configId = editing_config_node.id;
|
|
||||||
var configType = type;
|
|
||||||
var configAdding = adding;
|
|
||||||
var configTypeDef = RED.nodes.getType(configType);
|
|
||||||
var d;
|
|
||||||
var input;
|
|
||||||
|
|
||||||
if (configTypeDef.oneditsave) {
|
// Call `oneditsave` and search for changes
|
||||||
try {
|
handleEditSave(editing_config_node, editState);
|
||||||
configTypeDef.oneditsave.call(editing_config_node);
|
|
||||||
} catch(err) {
|
|
||||||
console.warn("oneditsave",editing_config_node.id,editing_config_node.type,err.toString());
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
for (d in configTypeDef.defaults) {
|
// Search for changes in the edit box (panes)
|
||||||
if (configTypeDef.defaults.hasOwnProperty(d)) {
|
activeEditPanes.forEach(function (pane) {
|
||||||
var newValue;
|
|
||||||
input = $("#node-config-input-"+d);
|
|
||||||
if (input.attr('type') === "checkbox") {
|
|
||||||
newValue = input.prop('checked');
|
|
||||||
} else if ("format" in configTypeDef.defaults[d] && configTypeDef.defaults[d].format !== "" && input[0].nodeName === "DIV") {
|
|
||||||
newValue = input.text();
|
|
||||||
} else {
|
|
||||||
newValue = input.val();
|
|
||||||
}
|
|
||||||
if (newValue != null && newValue !== editing_config_node[d]) {
|
|
||||||
if (editing_config_node._def.defaults[d].type) {
|
|
||||||
if (newValue == "_ADD_") {
|
|
||||||
newValue = "";
|
|
||||||
}
|
|
||||||
// Change to a related config node
|
|
||||||
var configNode = RED.nodes.node(editing_config_node[d]);
|
|
||||||
if (configNode) {
|
|
||||||
var users = configNode.users;
|
|
||||||
users.splice(users.indexOf(editing_config_node),1);
|
|
||||||
RED.events.emit("nodes:change",configNode);
|
|
||||||
}
|
|
||||||
configNode = RED.nodes.node(newValue);
|
|
||||||
if (configNode) {
|
|
||||||
configNode.users.push(editing_config_node);
|
|
||||||
RED.events.emit("nodes:change",configNode);
|
|
||||||
}
|
|
||||||
}
|
|
||||||
editing_config_node[d] = newValue;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
activeEditPanes.forEach(function(pane) {
|
|
||||||
if (pane.apply) {
|
if (pane.apply) {
|
||||||
pane.apply.call(pane, editState);
|
pane.apply.call(pane, editState);
|
||||||
}
|
}
|
||||||
})
|
});
|
||||||
|
|
||||||
editing_config_node.label = configTypeDef.label;
|
// TODO: Why?
|
||||||
|
editing_config_node.label = configTypeDef.label
|
||||||
var scope = $("#red-ui-editor-config-scope").val();
|
|
||||||
editing_config_node.z = scope;
|
|
||||||
|
|
||||||
|
// Check if disabled has changed
|
||||||
if ($("#node-config-input-node-disabled").prop('checked')) {
|
if ($("#node-config-input-node-disabled").prop('checked')) {
|
||||||
if (editing_config_node.d !== true) {
|
if (editing_config_node.d !== true) {
|
||||||
|
editState.changes.d = editing_config_node.d;
|
||||||
|
editState.changed = true;
|
||||||
editing_config_node.d = true;
|
editing_config_node.d = true;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if (editing_config_node.d === true) {
|
if (editing_config_node.d === true) {
|
||||||
|
editState.changes.d = editing_config_node.d;
|
||||||
|
editState.changed = true;
|
||||||
delete editing_config_node.d;
|
delete editing_config_node.d;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NOTE: must be undefined if no scope used
|
||||||
|
const scope = $("#red-ui-editor-config-scope").val() || undefined;
|
||||||
|
|
||||||
|
// Check if the scope has changed
|
||||||
|
if (editing_config_node.z !== scope) {
|
||||||
|
editState.changes.z = editing_config_node.z;
|
||||||
|
editState.changed = true;
|
||||||
|
editing_config_node.z = scope;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Search for nodes that use this config node that are no longer
|
||||||
|
// in scope, so must be removed
|
||||||
|
const historyEvents = [];
|
||||||
if (scope) {
|
if (scope) {
|
||||||
// Search for nodes that use this one that are no longer
|
const newUsers = editing_config_node.users.filter(function (node) {
|
||||||
// in scope, so must be removed
|
let keepNode = false;
|
||||||
editing_config_node.users = editing_config_node.users.filter(function(n) {
|
let nodeModified = null;
|
||||||
var keep = true;
|
|
||||||
for (var d in n._def.defaults) {
|
for (const d in node._def.defaults) {
|
||||||
if (n._def.defaults.hasOwnProperty(d)) {
|
if (node._def.defaults.hasOwnProperty(d)) {
|
||||||
if (n._def.defaults[d].type === editing_config_node.type &&
|
if (node._def.defaults[d].type === editing_config_node.type) {
|
||||||
n[d] === editing_config_node.id &&
|
if (node[d] === editing_config_node.id) {
|
||||||
n.z !== scope) {
|
if (node.z === editing_config_node.z) {
|
||||||
keep = false;
|
// The node is kept only if at least one property uses
|
||||||
// Remove the reference to this node
|
// this config node in the correct scope.
|
||||||
// and revalidate
|
keepNode = true;
|
||||||
n[d] = null;
|
} else {
|
||||||
n.dirty = true;
|
if (!nodeModified) {
|
||||||
n.changed = true;
|
nodeModified = {
|
||||||
validateNode(n);
|
t: "edit",
|
||||||
|
node: node,
|
||||||
|
changes: { [d]: node[d] },
|
||||||
|
changed: node.changed,
|
||||||
|
dirty: node.dirty
|
||||||
|
};
|
||||||
|
} else {
|
||||||
|
nodeModified.changes[d] = node[d];
|
||||||
|
}
|
||||||
|
|
||||||
|
// Remove the reference to the config node
|
||||||
|
node[d] = "";
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return keep;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
if (configAdding) {
|
// Add the node modified to the history
|
||||||
RED.nodes.add(editing_config_node);
|
if (nodeModified) {
|
||||||
}
|
historyEvents.push(nodeModified);
|
||||||
|
|
||||||
validateNode(editing_config_node);
|
|
||||||
var validatedNodes = {};
|
|
||||||
validatedNodes[editing_config_node.id] = true;
|
|
||||||
|
|
||||||
var userStack = editing_config_node.users.slice();
|
|
||||||
while(userStack.length > 0) {
|
|
||||||
var user = userStack.pop();
|
|
||||||
if (!validatedNodes[user.id]) {
|
|
||||||
validatedNodes[user.id] = true;
|
|
||||||
if (user.users) {
|
|
||||||
userStack = userStack.concat(user.users);
|
|
||||||
}
|
}
|
||||||
validateNode(user);
|
|
||||||
|
// Mark as changed and revalidate this node
|
||||||
|
if (!keepNode) {
|
||||||
|
node.changed = true;
|
||||||
|
node.dirty = true;
|
||||||
|
validateNode(node);
|
||||||
|
RED.events.emit("nodes:change", node);
|
||||||
|
}
|
||||||
|
|
||||||
|
return keepNode;
|
||||||
|
});
|
||||||
|
|
||||||
|
// Check if users are changed
|
||||||
|
if (editing_config_node.users.length !== newUsers.length) {
|
||||||
|
editState.changes.users = editing_config_node.users;
|
||||||
|
editState.changed = true;
|
||||||
|
editing_config_node.users = newUsers;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
RED.nodes.dirty(true);
|
|
||||||
RED.view.redraw(true);
|
if (editState.changed) {
|
||||||
if (!configAdding) {
|
// Set the congig node as changed
|
||||||
RED.events.emit("editor:save",editing_config_node);
|
editing_config_node.changed = true;
|
||||||
RED.events.emit("nodes:change",editing_config_node);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// Now, validate the config node
|
||||||
|
validateNode(editing_config_node);
|
||||||
|
|
||||||
|
// And validate nodes using this config node too
|
||||||
|
const validatedNodes = new Set();
|
||||||
|
const userStack = editing_config_node.users.slice();
|
||||||
|
|
||||||
|
validatedNodes.add(editing_config_node.id);
|
||||||
|
while (userStack.length) {
|
||||||
|
const node = userStack.pop();
|
||||||
|
if (!validatedNodes.has(node.id)) {
|
||||||
|
validatedNodes.add(node.id);
|
||||||
|
if (node.users) {
|
||||||
|
userStack.push(...node.users);
|
||||||
|
}
|
||||||
|
validateNode(node);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
let historyEvent = {
|
||||||
|
t: "edit",
|
||||||
|
node: editing_config_node,
|
||||||
|
changes: editState.changes,
|
||||||
|
changed: wasChanged,
|
||||||
|
dirty: RED.nodes.dirty()
|
||||||
|
};
|
||||||
|
|
||||||
|
if (historyEvents.length) {
|
||||||
|
// Need a multi events
|
||||||
|
historyEvent = {
|
||||||
|
t: "multi",
|
||||||
|
events: [historyEvent].concat(historyEvents),
|
||||||
|
dirty: historyEvent.dirty
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!adding) {
|
||||||
|
// This event is triggered when the edit box is saved,
|
||||||
|
// regardless of whether there are any modifications.
|
||||||
|
RED.events.emit("editor:save", editing_config_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
if (editState.changed) {
|
||||||
|
if (adding) {
|
||||||
|
RED.history.push({ t: "add", nodes: [editing_config_node.id], dirty: RED.nodes.dirty() });
|
||||||
|
// Add the new config node and trigger the `nodes:add` event
|
||||||
|
RED.nodes.add(editing_config_node);
|
||||||
|
} else {
|
||||||
|
RED.history.push(historyEvent);
|
||||||
|
RED.events.emit("nodes:change", editing_config_node);
|
||||||
|
}
|
||||||
|
|
||||||
|
RED.nodes.dirty(true);
|
||||||
|
RED.view.redraw(true);
|
||||||
|
}
|
||||||
|
|
||||||
RED.tray.close(function() {
|
RED.tray.close(function() {
|
||||||
var filter = null;
|
var filter = null;
|
||||||
// when editing a config via subflow edit panel, the `configProperty` will not
|
// when editing a config via subflow edit panel, the `configProperty` will not
|
||||||
|
@ -132,9 +132,16 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
if (node._def.credentials) {
|
if (node._def.credentials) {
|
||||||
var credDefinition = node._def.credentials;
|
const credDefinition = node._def.credentials;
|
||||||
var credsChanged = updateNodeCredentials(node,credDefinition,this.inputClass);
|
const credChanges = updateNodeCredentials(node, credDefinition, this.inputClass);
|
||||||
editState.changed = editState.changed || credsChanged;
|
|
||||||
|
if (Object.keys(credChanges).length) {
|
||||||
|
editState.changed = true;
|
||||||
|
editState.changes.credentials = {
|
||||||
|
...(editState.changes.credentials || {}),
|
||||||
|
...credChanges
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -162,10 +169,11 @@
|
|||||||
* @param node - the node containing the credentials
|
* @param node - the node containing the credentials
|
||||||
* @param credDefinition - definition of the credentials
|
* @param credDefinition - definition of the credentials
|
||||||
* @param prefix - prefix of the input fields
|
* @param prefix - prefix of the input fields
|
||||||
* @return {boolean} whether anything has changed
|
* @return {object} an object containing the modified properties
|
||||||
*/
|
*/
|
||||||
function updateNodeCredentials(node, credDefinition, prefix) {
|
function updateNodeCredentials(node, credDefinition, prefix) {
|
||||||
var changed = false;
|
const changes = {};
|
||||||
|
|
||||||
if (!node.credentials) {
|
if (!node.credentials) {
|
||||||
node.credentials = {_:{}};
|
node.credentials = {_:{}};
|
||||||
} else if (!node.credentials._) {
|
} else if (!node.credentials._) {
|
||||||
@ -178,22 +186,32 @@
|
|||||||
if (input.length > 0) {
|
if (input.length > 0) {
|
||||||
var value = input.val();
|
var value = input.val();
|
||||||
if (credDefinition[cred].type == 'password') {
|
if (credDefinition[cred].type == 'password') {
|
||||||
node.credentials['has_' + cred] = (value !== "");
|
if (value === '__PWRD__') {
|
||||||
if (value == '__PWRD__') {
|
// A cred value exists - no changes
|
||||||
continue;
|
} else if (value === '' && node.credentials['has_' + cred] === false) {
|
||||||
|
// Empty cred value exists - no changes
|
||||||
|
} else if (value === node.credentials[cred]) {
|
||||||
|
// A cred value exists locally in the editor - no changes
|
||||||
|
// Like the user sets a value, saves the config,
|
||||||
|
// reopens the config and save the config again
|
||||||
|
} else {
|
||||||
|
changes[cred] = node.credentials[cred];
|
||||||
|
node.credentials[cred] = value;
|
||||||
}
|
}
|
||||||
changed = true;
|
|
||||||
|
|
||||||
}
|
node.credentials['has_' + cred] = (value !== '');
|
||||||
node.credentials[cred] = value;
|
} else {
|
||||||
if (value != node.credentials._[cred]) {
|
// Since these creds are loaded by the editor,
|
||||||
changed = true;
|
// values can be directly compared
|
||||||
|
if (value !== node.credentials[cred]) {
|
||||||
|
changes[cred] = node.credentials[cred];
|
||||||
|
node.credentials[cred] = value;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return changed;
|
|
||||||
|
return changes;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
})();
|
})();
|
||||||
|
@ -512,6 +512,7 @@ RED.subflow = (function() {
|
|||||||
removedNodes.push(n);
|
removedNodes.push(n);
|
||||||
}
|
}
|
||||||
if (n.z == id) {
|
if (n.z == id) {
|
||||||
|
RED.nodes.updateConfigNodeUsers(n, { action: "remove" });
|
||||||
removedNodes.push(n);
|
removedNodes.push(n);
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -382,7 +382,7 @@ RED.typeSearch = (function() {
|
|||||||
var items = [];
|
var items = [];
|
||||||
RED.nodes.registry.getNodeTypes().forEach(function(t) {
|
RED.nodes.registry.getNodeTypes().forEach(function(t) {
|
||||||
var def = RED.nodes.getType(t);
|
var def = RED.nodes.getType(t);
|
||||||
if (def.category !== 'config' && t !== 'unknown' && t !== 'tab') {
|
if (def.set?.enabled !== false && def.category !== 'config' && t !== 'unknown' && t !== 'tab') {
|
||||||
items.push({type:t,def: def, label:getTypeLabel(t,def)});
|
items.push({type:t,def: def, label:getTypeLabel(t,def)});
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
|
@ -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