mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	| @@ -448,12 +448,18 @@ RED.nodes = (function() { | ||||
|                         doZFilter = true; | ||||
|                     } | ||||
|                 } | ||||
|                 var objectLookup = false; | ||||
|                 if (searchSet === null) { | ||||
|                     searchSet = nodes; | ||||
|                     searchSet = Object.keys(nodes); | ||||
|                     objectLookup = true; | ||||
|                 } | ||||
|  | ||||
|  | ||||
|                 for (var n=0;n<searchSet.length;n++) { | ||||
|                     var node = searchSet[n]; | ||||
|                     if (objectLookup) { | ||||
|                         node = nodes[node]; | ||||
|                     } | ||||
|                     if (filter.hasOwnProperty("type") && node.type !== filter.type) { | ||||
|                         continue; | ||||
|                     } | ||||
| @@ -1118,8 +1124,8 @@ RED.nodes = (function() { | ||||
|                 } | ||||
|             } | ||||
|             if ((!n._def.defaults || !n._def.defaults.hasOwnProperty("l")) && n.hasOwnProperty('l')) { | ||||
|                 var isLink = /^link (in|out)$/.test(node.type); | ||||
|                 if (isLink == n.l) { | ||||
|                 var showLabel = n._def.hasOwnProperty("showLabel")?n._def.showLabel:true; | ||||
|                 if (showLabel != n.l) { | ||||
|                     node.l = n.l; | ||||
|                 } | ||||
|             } | ||||
|   | ||||
| @@ -41,6 +41,7 @@ | ||||
|  *         sublabel: 'Local', // a sub-label for the item | ||||
|  *         icon: 'fa fa-rocket', // (optional) icon for the item | ||||
|  *         checkbox: true/false, // (optional) if present, display checkbox accordingly | ||||
|  *         radio: 'group-name',  // (optional) if present, display radio box - using group-name to set radio group | ||||
|  *         selected: true/false, // (optional) whether the item is selected or not | ||||
|  *         children: [] | function(done,item) // (optional) an array of child items, or a function | ||||
|  *                                       // that will call the `done` callback with an array | ||||
| @@ -640,6 +641,41 @@ | ||||
|                     } | ||||
|                 } | ||||
|                 selectWrapper.appendTo(label) | ||||
|             } else if (item.radio) { | ||||
|                 var selectWrapper = $('<span class="red-ui-treeList-icon"></span>'); | ||||
|                 var cb = $('<input class="red-ui-treeList-radio" type="radio">').prop('name', item.radio).prop('checked',item.selected).appendTo(selectWrapper); | ||||
|                 cb.on('click', function(e) { | ||||
|                     e.stopPropagation(); | ||||
|                 }); | ||||
|                 cb.on('change', function(e) { | ||||
|                     item.selected = this.checked; | ||||
|                     that._selected.forEach(function(selectedItem) { | ||||
|                         if (selectedItem.radio === item.radio) { | ||||
|                             selectedItem.treeList.label.removeClass("selected"); | ||||
|                             selectedItem.selected = false; | ||||
|                             that._selected.delete(selectedItem); | ||||
|                         } | ||||
|                     }) | ||||
|                     if (item.selected) { | ||||
|                         that._selected.add(item); | ||||
|                     } else { | ||||
|                         that._selected.delete(item); | ||||
|                     } | ||||
|                     label.toggleClass("selected",this.checked); | ||||
|                     that._trigger("select",e,item); | ||||
|                 }) | ||||
|                 if (!item.children) { | ||||
|                     label.on("click", function(e) { | ||||
|                         e.stopPropagation(); | ||||
|                         cb.trigger("click"); | ||||
|                     }) | ||||
|                 } | ||||
|                 item.treeList.select = function(v) { | ||||
|                     if (v !== item.selected) { | ||||
|                         cb.trigger("click"); | ||||
|                     } | ||||
|                 } | ||||
|                 selectWrapper.appendTo(label) | ||||
|             } else { | ||||
|                 label.on("click", function(e) { | ||||
|                     if (!that.options.multi) { | ||||
|   | ||||
| @@ -151,7 +151,7 @@ RED.editor = (function() { | ||||
|                 valid = definition[property].hasOwnProperty("required") && !definition[property].required; | ||||
|             } else { | ||||
|                 var configNode = RED.nodes.node(value); | ||||
|                 valid = (configNode !== null && (configNode.valid == null || configNode.valid)); | ||||
|                 valid = (configNode && (configNode.valid == null || configNode.valid)); | ||||
|             } | ||||
|         } | ||||
|         return valid; | ||||
|   | ||||
| @@ -93,17 +93,20 @@ | ||||
|  | ||||
|  | ||||
|                 } | ||||
|                 var showLabel = node._def.hasOwnProperty("showLabel")?node._def.showLabel:true; | ||||
|  | ||||
|                 if (!$("#node-input-show-label").prop('checked')) { | ||||
|                     // Not checked - hide label | ||||
|                     if (!/^link (in|out)$/.test(node.type)) { | ||||
|                         // Not a link node - default state is true | ||||
|  | ||||
|                     if (showLabel) { | ||||
|                         // Default to show label | ||||
|                         if (node.l !== false) { | ||||
|                             editState.changes.l = node.l | ||||
|                             editState.changed = true; | ||||
|                         } | ||||
|                         node.l = false; | ||||
|                     } else { | ||||
|                         // A link node - default state is false | ||||
|                         // Node has showLabel:false (eg link nodes) | ||||
|                         if (node.hasOwnProperty('l') && node.l) { | ||||
|                             editState.changes.l = node.l | ||||
|                             editState.changed = true; | ||||
| @@ -112,8 +115,8 @@ | ||||
|                     } | ||||
|                 } else { | ||||
|                     // Checked - show label | ||||
|                     if (!/^link (in|out)$/.test(node.type)) { | ||||
|                         // Not a link node - default state is true | ||||
|                     if (showLabel) { | ||||
|                         // Default to show label | ||||
|                         if (node.hasOwnProperty('l') && !node.l) { | ||||
|                             editState.changes.l = node.l | ||||
|                             editState.changed = true; | ||||
| @@ -204,8 +207,8 @@ | ||||
|         }) | ||||
|  | ||||
|         if (!node.hasOwnProperty("l")) { | ||||
|             // Show label if type not link | ||||
|             node.l = !/^link (in|out)$/.test(node._def.type); | ||||
|             // Show label unless def.showLabel set to false | ||||
|             node.l =  node._def.hasOwnProperty("showLabel")?node._def.showLabel:true; | ||||
|         } | ||||
|         $("#node-input-show-label").prop("checked",node.l).trigger("change"); | ||||
|  | ||||
|   | ||||
| @@ -159,15 +159,15 @@ RED.view.tools = (function() { | ||||
|         nodes.forEach(function(n) { | ||||
|             var modified = false; | ||||
|             var oldValue = n.l === undefined?true:n.l; | ||||
|             var isLink = /^link (in|out)$/.test(n._def.type); | ||||
|             var showLabel = n._def.hasOwnProperty("showLabel")?n._def.showLabel:true; | ||||
|  | ||||
|             if (labelShown) { | ||||
|                 if (n.l === false || (isLink && !n.hasOwnProperty('l'))) { | ||||
|                 if (n.l === false || (!showLabel && !n.hasOwnProperty('l'))) { | ||||
|                     n.l = true; | ||||
|                     modified = true; | ||||
|                 } | ||||
|             } else { | ||||
|                 if ((!isLink && (!n.hasOwnProperty('l') || n.l === true)) || (isLink && n.l === true) ) { | ||||
|                 if ((showLabel && (!n.hasOwnProperty('l') || n.l === true)) || (!showLabel && n.l === true) ) { | ||||
|                     n.l = false; | ||||
|                     modified = true; | ||||
|                 } | ||||
|   | ||||
| @@ -413,7 +413,7 @@ RED.view = (function() { | ||||
|                 var nn = result.node; | ||||
|  | ||||
|                 var showLabel = RED.utils.getMessageProperty(RED.settings.get('editor'),"view.view-node-show-label"); | ||||
|                 if (showLabel !== undefined && !/^link (in|out)$/.test(nn._def.type) && !nn._def.defaults.hasOwnProperty("l")) { | ||||
|                 if (showLabel !== undefined &&  (nn._def.hasOwnProperty("showLabel")?nn._def.showLabel:true) && !nn._def.defaults.hasOwnProperty("l")) { | ||||
|                     nn.l = showLabel; | ||||
|                 } | ||||
|  | ||||
| @@ -1088,7 +1088,7 @@ RED.view = (function() { | ||||
|                 nn.x = point[0]; | ||||
|                 nn.y = point[1]; | ||||
|                 var showLabel = RED.utils.getMessageProperty(RED.settings.get('editor'),"view.view-node-show-label"); | ||||
|                 if (showLabel !== undefined && !/^link (in|out)$/.test(nn._def.type) && !nn._def.defaults.hasOwnProperty("l")) { | ||||
|                 if (showLabel !== undefined && (nn._def.hasOwnProperty("showLabel")?nn._def.showLabel:true) && !nn._def.defaults.hasOwnProperty("l")) { | ||||
|                     nn.l = showLabel; | ||||
|                 } | ||||
|                 if (quickAddLink) { | ||||
| @@ -1991,7 +1991,7 @@ RED.view = (function() { | ||||
|                 activeLinkNodes = {}; | ||||
|                 for (var i=0;i<movingSet.length();i++) { | ||||
|                     var msn = movingSet.get(i); | ||||
|                     if ((msn.n.type === "link out" || msn.n.type === "link in") && | ||||
|                     if (((msn.n.type === "link out" && msn.n.mode !== 'return') || msn.n.type === "link in") && | ||||
|                         (msn.n.z === activeWorkspace)) { | ||||
|                         var linkNode = msn.n; | ||||
|                         activeLinkNodes[linkNode.id] = linkNode; | ||||
| @@ -4140,7 +4140,7 @@ RED.view = (function() { | ||||
|                         } | ||||
|                         var numOutputs = d.outputs; | ||||
|                         if (isLink && d.type === "link out") { | ||||
|                             if (showAllLinkPorts===PORT_TYPE_OUTPUT || activeLinkNodes[d.id]) { | ||||
|                             if (d.mode !== "return" && (showAllLinkPorts===PORT_TYPE_OUTPUT || activeLinkNodes[d.id])) { | ||||
|                                 numOutputs = 1; | ||||
|                             } else { | ||||
|                                 numOutputs = 0; | ||||
|   | ||||
| @@ -95,7 +95,8 @@ | ||||
|         color: $list-item-color; | ||||
|     } | ||||
|  | ||||
|     input.red-ui-treeList-checkbox { | ||||
|     input.red-ui-treeList-checkbox, | ||||
|     input.red-ui-treeList-radio { | ||||
|         margin: 0; | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -12,6 +12,26 @@ | ||||
|         <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> | ||||
|     <div class="form-row"> | ||||
|         <label for="node-input-mode"><span data-i18n="link.outMode"></span></label> | ||||
|         <select id="node-input-mode" style="width: 70%"> | ||||
|             <option value="link" selected data-i18n="link.sendToAll"></option> | ||||
|             <option value="return" data-i18n="link.returnToCaller"></option> | ||||
|         </select> | ||||
|     </div> | ||||
|     <div class="node-input-link-rows" style="position:relative; height: 30px; text-align: right;"><div style="display:inline-block"><input type="text" id="node-input-link-target-filter"></div></div> | ||||
|     <div class="form-row node-input-link-row node-input-link-rows"></div> | ||||
| </script> | ||||
|  | ||||
| <script type="text/html" data-template-name="link call"> | ||||
|     <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> | ||||
|     <div class="form-row"> | ||||
|         <label for="node-input-timeout"><span data-i18n="exec.label.timeout"></span></label> | ||||
|         <input type="text" id="node-input-timeout" placeholder="30" style="width: 70px; margin-right: 5px;"><span data-i18n="inject.seconds"></span> | ||||
|     </div> | ||||
|     <div style="position:relative; height: 30px; text-align: right;"><div style="display:inline-block"><input type="text" id="node-input-link-target-filter"></div></div> | ||||
|     <div class="form-row node-input-link-row"></div> | ||||
| </script> | ||||
| @@ -48,7 +68,6 @@ | ||||
|                 } | ||||
|             }); | ||||
|         var candidateNodes = RED.nodes.filterNodes({type:targetType}); | ||||
|  | ||||
|         var search = $("#node-input-link-target-filter").searchBox({ | ||||
|             style: "compact", | ||||
|             delay: 300, | ||||
| @@ -104,7 +123,8 @@ | ||||
|                     node: n, | ||||
|                     label: n.name||n.id, | ||||
|                     selected: isChecked, | ||||
|                     checkbox: true | ||||
|                     checkbox: node.type !== "link call", | ||||
|                     radio: node.type === "link call" | ||||
|                 }) | ||||
|             } | ||||
|         }); | ||||
| @@ -129,15 +149,22 @@ | ||||
|     function onEditSave(node) { | ||||
|         var flows = treeList.treeList('data'); | ||||
|         node.links = []; | ||||
|         flows.forEach(function(f) { | ||||
|             f.children.forEach(function(n) { | ||||
|                 if (n.selected) { | ||||
|                     node.links.push(n.id); | ||||
|                 } | ||||
|         if (node.type !== "link out" || $("node-input-mode").val() === 'link') { | ||||
|             flows.forEach(function(f) { | ||||
|                 f.children.forEach(function(n) { | ||||
|                     if (n.selected) { | ||||
|                         node.links.push(n.id); | ||||
|                     } | ||||
|                 }) | ||||
|             }) | ||||
|         }) | ||||
|         } | ||||
|         node.oldLinks.sort(); | ||||
|         node.links.sort(); | ||||
|  | ||||
|         if (node.type === "link call") { | ||||
|             return | ||||
|         } | ||||
|  | ||||
|         var nodeMap = {}; | ||||
|         var length = Math.max(node.oldLinks.length,node.links.length); | ||||
|         for (var i=0;i<length;i++) { | ||||
| @@ -195,6 +222,7 @@ | ||||
|         outputLabels: function(i) { | ||||
|             return this.name||this._("link.linkIn"); | ||||
|         }, | ||||
|         showLabel: false, | ||||
|         label: function() { | ||||
|             return this.name||this._("link.linkIn"); | ||||
|         }, | ||||
| @@ -211,25 +239,32 @@ | ||||
|         oneditresize: resizeNodeList | ||||
|     }); | ||||
|  | ||||
|     RED.nodes.registerType('link out',{ | ||||
|     RED.nodes.registerType('link call',{ | ||||
|         category: 'common', | ||||
|         color:"#ddd",//"#87D8CF", | ||||
|         defaults: { | ||||
|             name: {value:""}, | ||||
|             links: { value: [], type:"link in[]"} | ||||
|             links: { value: [], type:"link in[]"}, | ||||
|             timeout: { value: "30", validate:RED.validators.number(true) } | ||||
|         }, | ||||
|         align:"right", | ||||
|         inputs:1, | ||||
|         outputs:0, | ||||
|         icon: "link-out.svg", | ||||
|         inputs: 1, | ||||
|         outputs: 1, | ||||
|         icon: "link-call.svg", | ||||
|         inputLabels: function(i) { | ||||
|             return this.name||this._("link.linkOut"); | ||||
|             return this.name||this._("link.linkCall"); | ||||
|         }, | ||||
|         label: function() { | ||||
|             return this.name||this._("link.linkOut"); | ||||
|             if (this.name) { | ||||
|                 return this.name; | ||||
|             } | ||||
|             if (this.links.length > 0) { | ||||
|                 var targetNode = RED.nodes.node(this.links[0]); | ||||
|                 return targetNode && (targetNode.name || targetNode.id); | ||||
|             } | ||||
|             return this._("link.linkCall"); | ||||
|         }, | ||||
|         labelStyle: function() { | ||||
|             return this.name?"node_label_italic":""; | ||||
|             return (this.name || this.links.length > 0)?"node_label_italic":""; | ||||
|         }, | ||||
|         oneditprepare: function() { | ||||
|             onEditPrepare(this,"link in"); | ||||
| @@ -237,8 +272,56 @@ | ||||
|         oneditsave: function() { | ||||
|             onEditSave(this); | ||||
|         }, | ||||
|         oneditresize: resizeNodeList | ||||
|     }); | ||||
|  | ||||
|  | ||||
|     RED.nodes.registerType('link out',{ | ||||
|         category: 'common', | ||||
|         color:"#ddd",//"#87D8CF", | ||||
|         defaults: { | ||||
|             name: {value:""}, | ||||
|             mode: { value: "link" },// link || return | ||||
|             links: { value: [], type:"link in[]"} | ||||
|         }, | ||||
|         align:"right", | ||||
|         inputs:1, | ||||
|         outputs:0, | ||||
|         icon: function() { | ||||
|             if (this.mode === "return") { | ||||
|                 return "link-return.svg"; | ||||
|             } else { | ||||
|                 return "link-out.svg"; | ||||
|             } | ||||
|         }, | ||||
|         inputLabels: function(i) { | ||||
|             return this.name||(this.mode === "return" ?this._("link.linkOutReturn"):this._("link.linkOut")); | ||||
|         }, | ||||
|         showLabel: false, | ||||
|         label: function() { | ||||
|             return this.name||(this.mode === "return" ?this._("link.linkOutReturn"):this._("link.linkOut")); | ||||
|         }, | ||||
|         labelStyle: function() { | ||||
|             return this.name?"node_label_italic":""; | ||||
|         }, | ||||
|         oneditprepare: function() { | ||||
|             onEditPrepare(this,"link in"); | ||||
|             $("#node-input-mode").on("change", function() { | ||||
|                 $(".node-input-link-rows").toggle(this.value === "link") | ||||
|             }) | ||||
|             if (!this.mode) { | ||||
|                 $("#node-input-mode").val('link').trigger("change"); | ||||
|             } | ||||
|  | ||||
|         }, | ||||
|         oneditsave: function() { | ||||
|             onEditSave(this); | ||||
|         }, | ||||
|         onadd: onAdd, | ||||
|         oneditresize: resizeNodeList | ||||
|     }); | ||||
|  | ||||
|  | ||||
|  | ||||
| })(); | ||||
| </script> | ||||
|   | ||||
| @@ -17,6 +17,8 @@ | ||||
| module.exports = function(RED) { | ||||
|     "use strict"; | ||||
|  | ||||
|     const crypto = require("crypto"); | ||||
|  | ||||
|     function LinkInNode(n) { | ||||
|         RED.nodes.createNode(this,n); | ||||
|         var node = this; | ||||
| @@ -40,13 +42,91 @@ module.exports = function(RED) { | ||||
|     function LinkOutNode(n) { | ||||
|         RED.nodes.createNode(this,n); | ||||
|         var node = this; | ||||
|         var mode = n.mode || "link"; | ||||
|  | ||||
|         var event = "node:"+n.id; | ||||
|         this.on("input", function(msg, send, done) { | ||||
|             msg._event = event; | ||||
|             RED.events.emit(event,msg) | ||||
|             send(msg); | ||||
|             done(); | ||||
|  | ||||
|             if (mode === "return") { | ||||
|                 if (Array.isArray(msg._linkSource) && msg._linkSource.length > 0) { | ||||
|                     var messageEvent = msg._linkSource.pop(); | ||||
|                     var returnNode = RED.nodes.getNode(messageEvent.node); | ||||
|                     if (returnNode && returnNode.returnLinkMessage) { | ||||
|                         returnNode.returnLinkMessage(messageEvent.id, msg); | ||||
|                     } else { | ||||
|                         node.warn(RED._("link.error.missingReturn")) | ||||
|                     } | ||||
|                 } else { | ||||
|                     node.warn(RED._("link.error.missingReturn")) | ||||
|                 } | ||||
|                 done(); | ||||
|             } else if (mode === "link") { | ||||
|                 send(msg); | ||||
|                 done(); | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|     RED.nodes.registerType("link out",LinkOutNode); | ||||
|  | ||||
|  | ||||
|     function LinkCallNode(n) { | ||||
|         RED.nodes.createNode(this,n); | ||||
|         const node = this; | ||||
|         const target = n.links[0]; | ||||
|         const messageEvents = {}; | ||||
|         let timeout = parseFloat(n.timeout || "30")*1000; | ||||
|         if (isNaN(timeout)) { | ||||
|             timeout = 30000; | ||||
|         } | ||||
|  | ||||
|         this.on("input", function(msg, send, done) { | ||||
|             msg._linkSource = msg._linkSource || []; | ||||
|             const messageEvent = { | ||||
|                 id: crypto.randomBytes(14).toString('hex'), | ||||
|                 node: node.id, | ||||
|             } | ||||
|             messageEvents[messageEvent.id] = { | ||||
|                 msg: RED.util.cloneMessage(msg), | ||||
|                 send, | ||||
|                 done, | ||||
|                 ts: setTimeout(function() { | ||||
|                     timeoutMessage(messageEvent.id) | ||||
|                 }, timeout ) | ||||
|             }; | ||||
|             msg._linkSource.push(messageEvent); | ||||
|             var targetNode = RED.nodes.getNode(target); | ||||
|             if (targetNode) { | ||||
|                 targetNode.receive(msg); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         this.returnLinkMessage = function(eventId, msg) { | ||||
|             if (Array.isArray(msg._linkSource) && msg._linkSource.length === 0) { | ||||
|                 delete msg._linkSource; | ||||
|             } | ||||
|             const messageEvent = messageEvents[eventId]; | ||||
|             if (messageEvent) { | ||||
|                 clearTimeout(messageEvent.ts); | ||||
|                 delete messageEvents[eventId]; | ||||
|                 messageEvent.send(msg); | ||||
|                 messageEvent.done(); | ||||
|             } else { | ||||
|                 node.send(msg); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         function timeoutMessage(eventId) { | ||||
|             const messageEvent = messageEvents[eventId]; | ||||
|             if (messageEvent) { | ||||
|                 delete messageEvents[eventId]; | ||||
|                 node.error("timeout",messageEvent.msg); | ||||
|             } | ||||
|         } | ||||
|  | ||||
|     } | ||||
|     RED.nodes.registerType("link call",LinkCallNode); | ||||
|  | ||||
|  | ||||
| } | ||||
|   | ||||
							
								
								
									
										5
									
								
								packages/node_modules/@node-red/nodes/icons/link-call.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								packages/node_modules/@node-red/nodes/icons/link-call.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||||
| <svg width="10.583mm" height="15.875mm" version="1.1" viewBox="0 0 10.583 15.875" xmlns="http://www.w3.org/2000/svg"> | ||||
|  <path d="m8.2021 2.3812-4.8922 0.53612 1.604 0.92604-1.0395 1.8004c0.73719-0.37402 1.6437-0.38227 2.4095 0.059892 0.76511 0.44174 1.2118 1.2301 1.2577 2.055l1.0384-1.7986 1.604 0.92604zm-2.3813 4.1244c-0.77016-0.44465-1.7402-0.18474-2.1848 0.58542-0.44465 0.77016-0.185 1.7406 0.58516 2.1853 0.77016 0.44465 1.7422 0.18533 2.1869-0.58483 0.44465-0.77016 0.18295-1.7412-0.58721-2.1858zm-3.3193 1.5159-1.8211 3.1542 3.6662 2.1167 1.82-3.1524c-0.73731 0.37266-1.6431 0.37961-2.4082-0.062129-0.76585-0.44216-1.2122-1.2309-1.2569-2.0563z" fill="#fff"/> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 771 B | 
							
								
								
									
										5
									
								
								packages/node_modules/@node-red/nodes/icons/link-return.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						
									
										5
									
								
								packages/node_modules/@node-red/nodes/icons/link-return.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							| @@ -0,0 +1,5 @@ | ||||
| <?xml version="1.0" encoding="UTF-8"?> | ||||
| <!-- Created with Inkscape (http://www.inkscape.org/) --> | ||||
| <svg width="10.583mm" height="15.875mm" version="1.1" viewBox="0 0 10.583 15.875" xmlns="http://www.w3.org/2000/svg"> | ||||
|  <path d="m2.6623 13.292 4.8922-0.53612-1.604-0.92604 1.0395-1.8004c-0.73719 0.37402-1.6437 0.38227-2.4095-0.059892-0.76511-0.44174-1.2118-1.2301-1.2577-2.055l-1.0384 1.7986-1.604-0.92604zm2.3813-4.1244c0.77016 0.44465 1.7402 0.18474 2.1848-0.58542 0.44465-0.77016 0.185-1.7406-0.58516-2.1853-0.77016-0.44465-1.7422-0.18533-2.1869 0.58483-0.44465 0.77016-0.18295 1.7412 0.58721 2.1858zm3.3193-1.5159 1.8211-3.1542-3.6662-2.1167-1.82 3.1524c0.73731-0.37266 1.6431-0.37961 2.4082 0.062129 0.76585 0.44216 1.2122 1.2309 1.2569 2.0563z" fill="#fff"/> | ||||
| </svg> | ||||
| After Width: | Height: | Size: 769 B | 
| @@ -28,10 +28,23 @@ | ||||
| <script type="text/html" data-help-name="link out"> | ||||
|     <p>Create virtual wires between flows.</p> | ||||
|     <h3>Details</h3> | ||||
|     <p>The node can be connected to any <code>link in</code> node that exists on any tab. | ||||
|        Once connected, they behave as if they were wired together.</p> | ||||
|     <p>The wires between link nodes are only displayed when a link node is selected. | ||||
|        If there are any wires to other tabs, a virtual node is show that can be clicked | ||||
|        on to jump to the appropriate tab.</p> | ||||
|     <p>This node can be configured to either send messages to all <code>link in</code> | ||||
|         nodes it is connected to, or to send a response back to the <code>link call</code> | ||||
|         node that triggered the flow.</p> | ||||
|     <p>When in 'send to all' mode, the wires between link nodes are only displayed when | ||||
|        the node is selected. If there are any wires to other tabs, a virtual node | ||||
|        is shown that can be clicked on to jump to the appropriate tab.</p> | ||||
|     <p><b>Note: </b>Links cannot be created going into, or out of, a subflow.</p> | ||||
| </script> | ||||
|  | ||||
| <script type="text/html" data-help-name="link call"> | ||||
|     <p>Calls a flow that starts with a <code>link in</code> node and passes on the response.</p> | ||||
|     <h3>Details</h3> | ||||
|     <p>This node can be connected to a <code>link in</code> node that exists on any tab. | ||||
|        The flow connected to that node must end with a <code>link out</code> node configured | ||||
|        in 'return' mode.</p> | ||||
|     <p>When this node receives a message, it is passed to the connected <code>link in</code> node. | ||||
|        It then waits for a response which it then sends on.</o> | ||||
|     <p>If no response is received within the configured timeout, default 30 seconds, the node | ||||
|        will log an error that can be caught using the <code>catch</code> node.</p> | ||||
| </script> | ||||
|   | ||||
| @@ -159,7 +159,15 @@ | ||||
|     }, | ||||
|     "link": { | ||||
|         "linkIn": "link in", | ||||
|         "linkOut": "link out" | ||||
|         "linkOut": "link out", | ||||
|         "linkCall": "link call", | ||||
|         "linkOutReturn": "link return", | ||||
|         "outMode": "Mode", | ||||
|         "sendToAll": "Send to all connected link nodes", | ||||
|         "returnToCaller": "Return to calling link node", | ||||
|         "error": { | ||||
|             "missingReturn": "Missing return node information" | ||||
|         } | ||||
|     }, | ||||
|     "tls": { | ||||
|         "tls": "TLS configuration", | ||||
|   | ||||
| @@ -119,4 +119,69 @@ describe('link Node', function() { | ||||
|         }); | ||||
|     }); | ||||
|  | ||||
|     describe("link-call node", function() { | ||||
|         it('should call link-in node and get response', function(done) { | ||||
|             var flow = [{id:"link-in-1", type:"link in", wires: [[ "func"]]}, | ||||
|                         {id:"func", type:"helper", wires: [["link-out-1"]]}, | ||||
|                         {id:"link-out-1", type:"link out", mode: "return"}, | ||||
|                         {id:"link-call", type:"link call", links:["link-in-1"], wires:[["n4"]]}, | ||||
|                         {id:"n4", type:"helper"} ]; | ||||
|             helper.load(linkNode, flow, function() { | ||||
|                 var func = helper.getNode("func"); | ||||
|                 func.on("input", function(msg, send, done) { | ||||
|                     msg.payload = "123"; | ||||
|                     send(msg); | ||||
|                     done(); | ||||
|                 }) | ||||
|                 var n1 = helper.getNode("link-call"); | ||||
|                 var n4 = helper.getNode("n4"); | ||||
|                 n4.on("input", function(msg) { | ||||
|                     try { | ||||
|                         msg.should.have.property('payload', '123'); | ||||
|                         done(); | ||||
|                     } catch(err) { | ||||
|                         done(err); | ||||
|                     } | ||||
|                 }); | ||||
|                 n1.receive({payload:"hello"}); | ||||
|             }); | ||||
|         }) | ||||
|     }); | ||||
|  | ||||
|     it('should allow nested link-call flows', function(done) { | ||||
|         var flow = [/** Multiply by 2 link flow **/ | ||||
|                     {id:"li1", type:"link in", wires: [[ "m2"]]}, | ||||
|                     {id:"m2", type:"helper", wires: [["lo1"]]}, | ||||
|                     {id:"lo1", type:"link out", mode: "return"}, | ||||
|                     /** Multiply by 3 link flow **/ | ||||
|                     {id:"li2", type:"link in", wires: [[ "m3"]]}, | ||||
|                     {id:"m3", type:"helper", wires: [["lo2"]]}, | ||||
|                     {id:"lo2", type:"link out", mode: "return"}, | ||||
|                     /** Multiply by 6 link flow **/ | ||||
|                     {id:"li3", type:"link in", wires: [[ "link-call-1"]]}, | ||||
|                     {id:"link-call-1", type:"link call", links:["m2"], wires:[["link-call-2"]]}, | ||||
|                     {id:"link-call-2", type:"link call", links:["m3"], wires:[["lo3"]]}, | ||||
|                     {id:"lo3", type:"link out", mode: "return"}, | ||||
|                     /** Test Flow Entry **/ | ||||
|                     {id:"link-call", type:"link call", links:["li3"], wires:[["n4"]]}, | ||||
|                     {id:"n4", type:"helper"} ]; | ||||
|         helper.load(linkNode, flow, function() { | ||||
|             var m2 = helper.getNode("m2"); | ||||
|             m2.on("input", function(msg, send, done) { msg.payload *= 2 ; send(msg); done(); }) | ||||
|             var m3 = helper.getNode("m3"); | ||||
|             m3.on("input", function(msg, send, done) { msg.payload *= 3 ; send(msg); done(); }) | ||||
|  | ||||
|             var n1 = helper.getNode("link-call"); | ||||
|             var n4 = helper.getNode("n4"); | ||||
|             n4.on("input", function(msg) { | ||||
|                 try { | ||||
|                     msg.should.have.property('payload', 24); | ||||
|                     done(); | ||||
|                 } catch(err) { | ||||
|                     done(err); | ||||
|                 } | ||||
|             }); | ||||
|             n1.receive({payload:4}); | ||||
|         }); | ||||
|     }) | ||||
| }); | ||||
|   | ||||
		Reference in New Issue
	
	Block a user