mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Update Join node runtime to match UI changes
This commit is contained in:
@@ -44,7 +44,7 @@
|
||||
color:"#E2D96E",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
splt: {value:""}
|
||||
splt: {value:"\\n"}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:1,
|
||||
@@ -61,12 +61,12 @@
|
||||
|
||||
<script type="text/x-red" data-template-name="join">
|
||||
<div class="form-row">
|
||||
<label for="node-input-out"><i class="fa fa-long-arrow-right"></i> Output</label>
|
||||
<select id="node-input-out" style="width:70%; margin-right:5px;">
|
||||
<label for="node-input-build"><i class="fa fa-long-arrow-right"></i> Output</label>
|
||||
<select id="node-input-build" style="width:70%; margin-right:5px;">
|
||||
<option value="auto">automatic</option>
|
||||
<option value="str">a String of joined properties</option>
|
||||
<option value="arr">an Array of properties</option>
|
||||
<option value="obj">an Object of key/property pairs</option>
|
||||
<option value="string">a String of joined properties</option>
|
||||
<option value="array">an Array of properties</option>
|
||||
<option value="object">an Object of key/property pairs</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row node-row-key">
|
||||
@@ -78,22 +78,24 @@
|
||||
<input type="text" id="node-input-property">
|
||||
<input type="hidden" id="node-input-propertyType">
|
||||
</div>
|
||||
<div class="form-row node-row-join">
|
||||
<label for="node-input-join" style="padding-right: 10px; box-sizing: border-box; text-align: right;">joined using</label>
|
||||
<input type="text" id="node-input-join" style="width: 40px">
|
||||
<div class="form-row node-row-joiner">
|
||||
<label for="node-input-joiner" style="padding-right: 10px; box-sizing: border-box; text-align: right;">joined using</label>
|
||||
<input type="text" id="node-input-joiner" style="width: 40px">
|
||||
</div>
|
||||
|
||||
<div class="form-row node-row-trigger">
|
||||
<label style="width: auto;">Send the message:</label>
|
||||
<div style="height: 40px;">
|
||||
<label style="margin-left: 40px; width: auto;"><input type="checkbox" style="width: auto;margin-bottom: 5px;"> after a fixed number of messages: <input type="text" style="width: 75px;"></label>
|
||||
</div>
|
||||
<div style="height: 40px;">
|
||||
<label style="margin-left: 40px; width: auto;"><input type="checkbox" style="width: auto;margin-bottom: 5px;"> after a timeout following the first message: <input placeholder="seconds" type="text" style="width: 75px;"></label>
|
||||
</div>
|
||||
<div style="height: 40px; padding-top: 6px;" class="node-row-accumulate">
|
||||
<label style="margin-left: 40px; width: auto;"><input type="checkbox" style="width: auto;margin-bottom: 5px;"> whenever a property is updated</label>
|
||||
</div>
|
||||
<ul>
|
||||
<li style="height: 40px;">
|
||||
<label style="width: 280px;" for="node-input-count">After a fixed number of messages:</label> <input id="node-input-count" placeholder="count" type="text" style="width: 75px;">
|
||||
</li>
|
||||
<li style="height: 40px;">
|
||||
<label style="width: 280px;" for="node-input-timeout">After a timeout following the first message:</label> <input id="node-input-timeout" placeholder="seconds" type="text" style="width: 75px;">
|
||||
</li>
|
||||
<li style="height: 40px; padding-top: 6px;" class="node-row-accumulate">
|
||||
<label style="width: auto;"><input type="checkbox" id="node-input-accumulate" style="width: auto;margin-bottom: 5px;margin-right: 5px;"> whenever a property is updated</label>
|
||||
</li>
|
||||
</ul>
|
||||
</div>
|
||||
|
||||
<div class="form-tips form-tips-auto hide">This mode assumes this node is either
|
||||
@@ -122,13 +124,14 @@
|
||||
color:"#E2D96E",
|
||||
defaults: {
|
||||
name: {value:""},
|
||||
out: { value:"auto"},
|
||||
build: { value:"auto"},
|
||||
property: { value: "payload"},
|
||||
propertyType: { value:"msg"},
|
||||
key: {value:"topic"},
|
||||
joiner: { value:"\\n"},
|
||||
timeout: {value:""},
|
||||
timerr: {value:"send"},
|
||||
count: {value:""},
|
||||
joiner: {value:""},
|
||||
build: {value:"array"}
|
||||
accumulate: {value: false}
|
||||
},
|
||||
inputs:1,
|
||||
outputs:1,
|
||||
@@ -140,14 +143,19 @@
|
||||
return this.name?"node_label_italic":"";
|
||||
},
|
||||
oneditprepare: function() {
|
||||
$("#node-input-out").change(function(e) {
|
||||
$("#node-input-build").change(function(e) {
|
||||
var val = $(this).val();
|
||||
$(".node-row-key").toggle(val==='obj');
|
||||
$(".node-row-property").toggle(val!=='auto');
|
||||
$(".node-row-join").toggle(val==='str');
|
||||
$(".node-row-joiner").toggle(val==='str');
|
||||
$(".node-row-trigger").toggle(val!=='auto');
|
||||
$(".node-row-accumulate").toggle(val==='obj');
|
||||
$(".form-tips-auto").toggle(val==='auto');
|
||||
if (val === 'str') {
|
||||
$("#node-input-property").typedInput('types',['msg']);
|
||||
} else if (val !== 'auto') {
|
||||
$("#node-input-property").typedInput('types',['msg', {value:"full",label:"complete message",hasValue:false}]);
|
||||
}
|
||||
})
|
||||
|
||||
$("#node-input-property").typedInput({
|
||||
@@ -158,7 +166,7 @@
|
||||
types:['msg']
|
||||
})
|
||||
|
||||
$("#node-input-out").change();
|
||||
$("#node-input-build").change();
|
||||
}
|
||||
});
|
||||
</script>
|
||||
|
@@ -68,6 +68,9 @@ module.exports = function(RED) {
|
||||
|
||||
function JoinNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
this.property = n.property||"payload";
|
||||
this.propertyType = n.propertyType||"msg";
|
||||
this.key = n.key||"topic";
|
||||
this.timer = Number(n.timeout || 0);
|
||||
this.timerr = n.timerr || "send";
|
||||
this.count = Number(n.count || 0);
|
||||
@@ -78,10 +81,6 @@ module.exports = function(RED) {
|
||||
var misc = (this.build === "array") ? [] : {};
|
||||
var tout;
|
||||
|
||||
function isObject (item) {
|
||||
return (typeof item === "object" && !Array.isArray(item)&& ! Buffer.isBuffer(item) && item !== null);
|
||||
}
|
||||
|
||||
// if array came from a string then reassemble it and send it
|
||||
var sendIt = function(m) {
|
||||
if (inflight[m.parts.id].ch !== undefined) { // if it was a string - rejoin it using the split char
|
||||
@@ -116,80 +115,93 @@ module.exports = function(RED) {
|
||||
m.payload = misc.join(node.joiner.replace(/\\n/,"\n").replace(/\\r/,"\r").replace(/\\t/,"\t").replace(/\\e/,"\e").replace(/\\f/,"\c").replace(/\\0/,"\0"));
|
||||
}
|
||||
if (node.build === "array") { misc = []; }
|
||||
if (node.build === "object") { misc = {}; }
|
||||
else if (node.build === "object") { misc = {}; }
|
||||
node.send(m);
|
||||
}
|
||||
|
||||
this.on("input", function(msg) {
|
||||
if (msg.hasOwnProperty("payload")) {
|
||||
if (msg.hasOwnProperty("parts")) { // only act if it has parts
|
||||
var count = node.count || msg.parts.count || 1;
|
||||
if (msg.parts.hasOwnProperty("index")) { // it's a numbered part (from a split node)
|
||||
if (!inflight[msg.parts.id]) { // New message - create new empty array of correct size
|
||||
if (msg.parts.type === "object") {
|
||||
inflight[msg.parts.id] = {i:0, a:{}, c:msg.parts.count, ch:msg.parts.ch, t:msg.parts.type};
|
||||
} else { // it's an array or string
|
||||
inflight[msg.parts.id] = {i:0, a:new Array(msg.parts.count), ch:msg.parts.ch, t:msg.parts.type};
|
||||
}
|
||||
if (node.timer !== 0) { // If there is a timer to set start it now
|
||||
inflight[msg.parts.id].timeout = setTimeout(function() {
|
||||
if (node.timerr === "send") { sendIt(msg); }
|
||||
if (node.timerr === "error") { node.error("Incomplete",msg); }
|
||||
delete inflight[msg.parts.id];
|
||||
}, node.timer);
|
||||
}
|
||||
}
|
||||
var property;
|
||||
if (node.propertyType == "full") {
|
||||
property = msg;
|
||||
} else {
|
||||
try {
|
||||
property = RED.util.getMessageProperty(msg,node.property);
|
||||
} catch(err) {
|
||||
node.warn("Message property "+node.property+" not found");
|
||||
return;
|
||||
}
|
||||
}
|
||||
if (msg.hasOwnProperty("parts")) {
|
||||
// only act if it has parts
|
||||
var count = node.count || msg.parts.count || 1;
|
||||
if (msg.parts.hasOwnProperty("index")) {
|
||||
// it's a numbered part (from a split node)
|
||||
if (!inflight[msg.parts.id]) {
|
||||
// New message - create new empty array of correct size
|
||||
if (msg.parts.type === "object") {
|
||||
inflight[msg.parts.id].a[msg.parts.key] = msg.payload; // Add to the tracking array
|
||||
inflight[msg.parts.id].i = Object.keys(inflight[msg.parts.id].a).length;
|
||||
} else { // it's an array or string
|
||||
inflight[msg.parts.id].a[msg.parts.index] = msg.payload; // Add to the tracking array
|
||||
inflight[msg.parts.id].i += 1; // Increment the count
|
||||
inflight[msg.parts.id] = {i:0, a:{}, c:msg.parts.count, ch:msg.parts.ch, t:msg.parts.type};
|
||||
} else {
|
||||
// it's an array or string
|
||||
inflight[msg.parts.id] = {i:0, a:new Array(msg.parts.count), ch:msg.parts.ch, t:msg.parts.type};
|
||||
}
|
||||
if (inflight[msg.parts.id].i >= count) { sendIt(msg); } // All arrived - send
|
||||
} // otherwise ignore it
|
||||
if (msg.hasOwnProperty("complete")) { // if set then send right away anyway...
|
||||
delete(msg.complete);
|
||||
if (node.timer !== 0) { // If there is a timer to set start it now
|
||||
inflight[msg.parts.id].timeout = setTimeout(function() {
|
||||
if (node.timerr === "send") { sendIt(msg); }
|
||||
else if (node.timerr === "error") { node.error("Incomplete",msg); }
|
||||
delete inflight[msg.parts.id];
|
||||
}, node.timer);
|
||||
}
|
||||
}
|
||||
if (msg.parts.type === "object") {
|
||||
// Add to the tracking array
|
||||
inflight[msg.parts.id].a[msg.parts.key] = property;
|
||||
inflight[msg.parts.id].i = Object.keys(inflight[msg.parts.id].a).length;
|
||||
} else {
|
||||
// it's an array or string
|
||||
// Add to the tracking array
|
||||
inflight[msg.parts.id].a[msg.parts.index] = property;
|
||||
// Increment the count
|
||||
inflight[msg.parts.id].i += 1;
|
||||
}
|
||||
if (inflight[msg.parts.id].i >= count) {
|
||||
// All arrived - send
|
||||
sendIt(msg);
|
||||
}
|
||||
} // otherwise ignore it
|
||||
if (msg.hasOwnProperty("complete")) { // if set then send right away anyway...
|
||||
delete(msg.complete);
|
||||
sendIt(msg);
|
||||
}
|
||||
|
||||
} else {
|
||||
// The case for any messages arriving without parts - ie random messages you want to join.
|
||||
else {
|
||||
var l;
|
||||
if (node.build === "array") { // simple case of build the array
|
||||
misc.push(msg.payload); // Add the payload to an array
|
||||
l = misc.length;
|
||||
} else { // OK so let's build an object
|
||||
if ((msg.key === undefined) && ((msg.topic === undefined) || (msg.topic === ''))) {
|
||||
if (isObject(msg.payload)) { // if it's already an object (and no topic or key) just append it
|
||||
misc = Object.assign(misc,msg.payload);
|
||||
l = Object.keys(misc).length;
|
||||
}
|
||||
else { // if no topic or key and not an object then warn and drop it.
|
||||
node.warn("key or topic not defined");
|
||||
return;
|
||||
}
|
||||
}
|
||||
else { // if it's got a msg.key or msg.topic then use key||topic as the property name
|
||||
misc[ msg.key || msg.topic ] = msg.payload;
|
||||
//if (msg.topic) { msg.topic = (msg.topic.split('/')).slice(0,-1).join('/'); }
|
||||
l = Object.keys(misc).length;
|
||||
}
|
||||
}
|
||||
if (l >= node.count) { sendMisc(msg); } // if it's long enough send it
|
||||
else if (msg.hasOwnProperty("complete")) { // if set then send right away anyway...
|
||||
delete(msg.complete);
|
||||
sendMisc(msg);
|
||||
}
|
||||
else if ((node.timer !== 0) && !tout) { // if not start the timer if there is one.
|
||||
tout = setTimeout(function() {
|
||||
if (node.timerr === "send") { sendMisc(msg); }
|
||||
if (node.timerr === "error") { node.error("Timeout",msg); }
|
||||
if (node.build === "array") { misc = []; }
|
||||
if (node.build === "object") { misc = {}; }
|
||||
}, node.timer);
|
||||
var l;
|
||||
if (node.build === "array" || node.build === "string") {
|
||||
// simple case of build the array
|
||||
// Add the payload to an array
|
||||
misc.push(property);
|
||||
l = misc.length;
|
||||
} else {
|
||||
// OK so let's build an object
|
||||
if (msg.hasOwnProperty(node.key) && msg[node.key] !== "") {
|
||||
misc[msg[node.key]] = property;
|
||||
}
|
||||
l = Object.keys(misc).length;
|
||||
}
|
||||
if (l >= node.count) {
|
||||
// if it's long enough send it
|
||||
sendMisc(msg);
|
||||
} else if (msg.hasOwnProperty("complete")) {
|
||||
// if set then send right away anyway...
|
||||
delete(msg.complete);
|
||||
sendMisc(msg);
|
||||
} else if ((node.timer !== 0) && !tout) {
|
||||
// if not start the timer if there is one.
|
||||
tout = setTimeout(function() {
|
||||
if (node.timerr === "send") { sendMisc(msg); }
|
||||
else if (node.timerr === "error") { node.error("Timeout",msg); }
|
||||
if (node.build === "array") { misc = []; }
|
||||
else if (node.build === "object") { misc = {}; }
|
||||
}, node.timer);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
Reference in New Issue
Block a user