Add node done API

This commit is contained in:
Nick O'Leary
2019-07-08 23:23:33 +01:00
parent f0a51bafbe
commit 3b5ea0f15f
17 changed files with 1039 additions and 498 deletions

View File

@@ -0,0 +1,136 @@
<script type="text/x-red" data-template-name="complete">
<div class="form-row node-input-target-row">
<button id="node-input-complete-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
</div>
<div class="form-row node-input-target-row node-input-target-list-row" style="min-height: 100px">
<div id="node-input-complete-target-container-div"></div>
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
</div>
</script>
<script type="text/javascript">
RED.nodes.registerType('complete',{
category: 'input',
color:"#c0edc0",
defaults: {
name: {value:""},
scope: {value:[]},
uncaught: {value:false}
},
inputs:0,
outputs:1,
icon: "alert.svg",
label: function() {
if (this.name) {
return this.name;
}
return this._("complete.completeNodes",{number:this.scope.length});
},
labelStyle: function() {
return this.name?"node_label_italic":"";
},
oneditprepare: function() {
var node = this;
var scope = node.scope || [];
this._resize = function() {
var rows = $("#dialog-form>div:not(.node-input-target-list-row)");
var height = $("#dialog-form").height();
for (var i=0;i<rows.length;i++) {
height -= $(rows[i]).outerHeight(true);
}
var editorRow = $("#dialog-form>div.node-input-target-list-row");
editorRow.css("height",height+"px");
};
var dirList = $("#node-input-complete-target-container-div").css({width: "100%", height: "100%"})
.treeList({multi:true}).on("treelistitemmouseover", function(e, item) {
item.node.highlighted = true;
item.node.dirty = true;
RED.view.redraw();
}).on("treelistitemmouseout", function(e, item) {
item.node.highlighted = false;
item.node.dirty = true;
RED.view.redraw();
})
var candidateNodes = RED.nodes.filterNodes({z:node.z});
var allChecked = true;
var items = [];
var nodeItemMap = {};
candidateNodes.forEach(function(n) {
if (n.id === node.id) {
return;
}
var isChecked = scope.indexOf(n.id) !== -1;
allChecked = allChecked && isChecked;
var nodeDef = RED.nodes.getType(n.type);
var label;
var sublabel;
if (nodeDef) {
var l = nodeDef.label;
label = (typeof l === "function" ? l.call(n) : l)||"";
sublabel = n.type;
if (sublabel.indexOf("subflow:") === 0) {
var subflowId = sublabel.substring(8);
var subflow = RED.nodes.subflow(subflowId);
sublabel = "subflow : "+subflow.name;
}
}
if (!nodeDef || !label) {
label = n.type;
}
nodeItemMap[n.id] = {
node: n,
label: label,
sublabel: sublabel,
selected: isChecked
};
items.push(nodeItemMap[n.id]);
});
dirList.treeList('data',items);
$("#node-input-complete-target-select").on("click", function(e) {
e.preventDefault();
var preselected = dirList.treeList('selected').map(function(n) {return n.node.id});
RED.tray.hide();
RED.view.selectNodes({
selected: preselected,
onselect: function(selection) {
RED.tray.show();
var newlySelected = {};
selection.forEach(function(n) {
newlySelected[n.id] = true;
if (nodeItemMap[n.id]) {
nodeItemMap[n.id].treeList.select(true);
}
})
preselected.forEach(function(id) {
if (!newlySelected[id]) {
nodeItemMap[id].treeList.select(false);
}
})
},
oncancel: function() {
RED.tray.show();
},
filter: function(n) {
return n.id !== node.id;
}
});
})
},
oneditsave: function() {
this.scope = $("#node-input-complete-target-container-div").treeList('selected').map(function(i) { return i.node.id})
},
oneditresize: function(size) {
this._resize();
}
});
</script>

View File

@@ -0,0 +1,30 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
module.exports = function(RED) {
"use strict";
function CompleteNode(n) {
RED.nodes.createNode(this,n);
var node = this;
this.scope = n.scope;
this.on("input",function(msg) {
this.send(msg);
});
}
RED.nodes.registerType("complete",CompleteNode);
}

View File

@@ -81,7 +81,7 @@ module.exports = function(RED) {
}
}
this.on("input", function(msg) {
this.on("input", function(msg, done) {
if (this.complete === "true") {
// debug complete msg object
if (this.console === "true") {
@@ -90,13 +90,14 @@ module.exports = function(RED) {
if (this.active && this.tosidebar) {
sendDebug({id:node.id, name:node.name, topic:msg.topic, msg:msg, _path:msg._path});
}
done();
} else {
prepareValue(msg,function(err,msg) {
prepareValue(msg,function(err,debugMsg) {
if (err) {
node.error(err);
return;
}
var output = msg.msg;
var output = debugMsg.msg;
if (node.console === "true") {
if (typeof output === "string") {
node.log((output.indexOf("\n") !== -1 ? "\n" : "") + output);
@@ -114,9 +115,10 @@ module.exports = function(RED) {
}
if (node.active) {
if (node.tosidebar == true) {
sendDebug(msg);
sendDebug(debugMsg);
}
}
done();
});
}
})

View File

@@ -328,13 +328,14 @@ module.exports = function(RED) {
}
if (valid) {
this.on('input', function(msg) {
this.on('input', function(msg, done) {
applyRules(msg, 0, (err,msg) => {
if (err) {
node.error(err,msg);
} else if (msg) {
node.send(msg);
}
done();
})
});
}

View File

@@ -0,0 +1,29 @@
<!--
Copyright JS Foundation and other contributors, http://js.foundation
Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at
http://www.apache.org/licenses/LICENSE-2.0
Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
-->
<script type="text/x-red" data-help-name="complete">
<p>Trigger a flow when another node completes its handling of a message.</p>
<h3>Details</h3>
<p>If a node tells the runtime when it has finished handling a message,
this node can be used to trigger a second flow.</p>
<p>For example, this can be used alongside a node with no output port,
such as the Email sending node, to continue the flow.</p>
<p>This node must be configured to handle the event for selected nodes in the
flow. Unlike the Catch node, it does not provide a 'handle all' mode automatically
applies to all nodes in the flow.</p>
<p>Not all nodes will trigger this event - it will depend on whether they
have been implemented to support this feature as introduced in Node-RED 1.0.</p>
</script>

View File

@@ -112,6 +112,9 @@
"selected": "selected nodes"
}
},
"complete": {
"completeNodes": "complete: __number__"
},
"debug": {
"output": "Output",
"none": "None",