mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Compare commits
	
		
			21 Commits
		
	
	
		
			310-tour
			...
			fix-link-t
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | 24178beafc | ||
|  | 6044871438 | ||
|  | e612bb6a38 | ||
|  | 81ea67d6da | ||
|  | 06e35baeaa | ||
|  | c9d72d7a1d | ||
|  | 62e9572070 | ||
|  | fea68c8acc | ||
|  | 929f0e90ac | ||
|  | 81331e68d2 | ||
|  | 4fda59a585 | ||
|  | ede3ac4282 | ||
|  | 16f8b78b39 | ||
|  | 892d21fb77 | ||
|  | adfc5b3e98 | ||
|  | f3d7016ab2 | ||
|  | 95a7980ada | ||
|  | 281e9d1357 | ||
|  | 742f05f59d | ||
|  | 79db4f8aa1 | ||
|  | f4d7b71984 | 
							
								
								
									
										4
									
								
								.github/workflows/tests.yml
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										4
									
								
								.github/workflows/tests.yml
									
									
									
									
										vendored
									
									
								
							| @@ -19,9 +19,9 @@ jobs: | ||||
|       matrix: | ||||
|         node-version: [14, 16] | ||||
|     steps: | ||||
|     - uses: actions/checkout@v2 | ||||
|     - uses: actions/checkout@v3 | ||||
|     - name: Use Node.js ${{ matrix.node-version }} | ||||
|       uses: actions/setup-node@v2 | ||||
|       uses: actions/setup-node@v3 | ||||
|       with: | ||||
|         node-version: ${{ matrix.node-version }} | ||||
|     - name: Install Dependencies | ||||
|   | ||||
| @@ -683,6 +683,8 @@ | ||||
|             "empty": "empty", | ||||
|             "globalConfig": "Global Configuration Nodes", | ||||
|             "triggerAction": "Trigger action", | ||||
|             "showFlow": "Show", | ||||
|             "hideFlow": "Hide", | ||||
|             "find": "Find in workspace" | ||||
|         }, | ||||
|         "help": { | ||||
|   | ||||
| @@ -683,6 +683,8 @@ | ||||
|             "empty": "空", | ||||
|             "globalConfig": "グローバル設定ノード", | ||||
|             "triggerAction": "アクションを実行", | ||||
|             "showFlow": "表示", | ||||
|             "hideFlow": "非表示", | ||||
|             "find": "ワークスペース内を検索" | ||||
|         }, | ||||
|         "help": { | ||||
|   | ||||
| @@ -135,6 +135,10 @@ RED.sidebar.info.outliner = (function() { | ||||
|                     RED.workspaces.show(n.id, null, true); | ||||
|                 } | ||||
|             }); | ||||
|             RED.popover.tooltip(toggleVisibleButton, function () { | ||||
|                 var isHidden = !div.hasClass("red-ui-info-outline-item-hidden"); | ||||
|                 return RED._("sidebar.info." + (isHidden ? "hideFlow" : "showFlow")); | ||||
|             }); | ||||
|         } | ||||
|         if (n.type !== 'subflow') { | ||||
|             var toggleButton = $('<button type="button" class="red-ui-info-outline-item-control-disable red-ui-button red-ui-button-small"><i class="fa fa-circle-thin"></i><i class="fa fa-ban"></i></button>').appendTo(controls).on("click",function(evt) { | ||||
| @@ -613,6 +617,9 @@ RED.sidebar.info.outliner = (function() { | ||||
|                 objects[n.id].children = missingParents[n.id]; | ||||
|                 delete missingParents[n.id] | ||||
|             } | ||||
|             if (objects[n.id].children.length === 0) { | ||||
|                 objects[n.id].children.push(getEmptyItem(n.id)); | ||||
|             } | ||||
|         } | ||||
|         var parent = n.g||n.z||"__global__"; | ||||
|  | ||||
|   | ||||
| @@ -586,11 +586,28 @@ RED.view = (function() { | ||||
|  | ||||
|                 var group = $(ui.helper).data("group"); | ||||
|                 if (group) { | ||||
|                     var oldX = group.x;  | ||||
|                     var oldY = group.y;  | ||||
|                     RED.group.addToGroup(group, nn); | ||||
|                     var moveEvent = null; | ||||
|                     if ((group.x !== oldX) || | ||||
|                         (group.y !== oldY)) { | ||||
|                         moveEvent = { | ||||
|                             t: "move", | ||||
|                             nodes: [{n: group, | ||||
|                                      ox: oldX, oy: oldY, | ||||
|                                      dx: group.x -oldX, | ||||
|                                      dy: group.y -oldY}], | ||||
|                             dirty: true | ||||
|                         }; | ||||
|                     } | ||||
|                     historyEvent = { | ||||
|                         t: 'multi', | ||||
|                         events: [historyEvent], | ||||
|  | ||||
|                     }; | ||||
|                     if (moveEvent) { | ||||
|                         historyEvent.events.push(moveEvent) | ||||
|                     } | ||||
|                     historyEvent.events.push({ | ||||
|                         t: "addToGroup", | ||||
| @@ -1350,19 +1367,35 @@ RED.view = (function() { | ||||
|                 RED.editor.validateNode(nn); | ||||
|  | ||||
|                 if (targetGroup) { | ||||
|                     var oldX = targetGroup.x;  | ||||
|                     var oldY = targetGroup.y;  | ||||
|                     RED.group.addToGroup(targetGroup, nn); | ||||
|                     var moveEvent = null; | ||||
|                     if ((targetGroup.x !== oldX) || | ||||
|                         (targetGroup.y !== oldY)) { | ||||
|                         moveEvent = { | ||||
|                             t: "move", | ||||
|                             nodes: [{n: targetGroup, | ||||
|                                      ox: oldX, oy: oldY, | ||||
|                                      dx: targetGroup.x -oldX, | ||||
|                                      dy: targetGroup.y -oldY}], | ||||
|                             dirty: true | ||||
|                         }; | ||||
|                     } | ||||
|                     if (historyEvent.t !== "multi") { | ||||
|                         historyEvent = { | ||||
|                             t:'multi', | ||||
|                             events: [historyEvent] | ||||
|                         } | ||||
|                         }; | ||||
|                     } | ||||
|                     historyEvent.events.push({ | ||||
|                         t: "addToGroup", | ||||
|                         group: targetGroup, | ||||
|                         nodes: nn | ||||
|                     }) | ||||
|  | ||||
|                     }); | ||||
|                     if (moveEvent) { | ||||
|                         historyEvent.events.push(moveEvent); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 if (spliceLink) { | ||||
| @@ -1698,6 +1731,7 @@ RED.view = (function() { | ||||
|  | ||||
|             // Check link splice or group-add | ||||
|             if (movingSet.length() === 1 && movingSet.get(0).n.type !== "group") { | ||||
|             //}{//NIS | ||||
|                 node = movingSet.get(0); | ||||
|                 if (spliceActive) { | ||||
|                     if (!spliceTimer) { | ||||
| @@ -2057,11 +2091,25 @@ RED.view = (function() { | ||||
|         if (mouse_mode == RED.state.MOVING_ACTIVE) { | ||||
|             if (movingSet.length() > 0) { | ||||
|                 var addedToGroup = null; | ||||
|                 var moveEvent = null; | ||||
|                 if (activeHoverGroup) { | ||||
|                     var oldX = activeHoverGroup.x;  | ||||
|                     var oldY = activeHoverGroup.y;  | ||||
|                     for (var j=0;j<movingSet.length();j++) { | ||||
|                         var n = movingSet.get(j); | ||||
|                         RED.group.addToGroup(activeHoverGroup,n.n); | ||||
|                     } | ||||
|                     if ((activeHoverGroup.x !== oldX) || | ||||
|                         (activeHoverGroup.y !== oldY)) { | ||||
|                         moveEvent = { | ||||
|                             t: "move", | ||||
|                             nodes: [{n: activeHoverGroup, | ||||
|                                      ox: oldX, oy: oldY, | ||||
|                                      dx: activeHoverGroup.x -oldX, | ||||
|                                      dy: activeHoverGroup.y -oldY}], | ||||
|                             dirty: true | ||||
|                         }; | ||||
|                     } | ||||
|                     addedToGroup = activeHoverGroup; | ||||
|  | ||||
|                     activeHoverGroup.hovered = false; | ||||
| @@ -2107,6 +2155,12 @@ RED.view = (function() { | ||||
|                         historyEvent.addToGroup = addedToGroup; | ||||
|                     } | ||||
|                     RED.nodes.dirty(true); | ||||
|                     if (moveEvent) { | ||||
|                         historyEvent = { | ||||
|                             t: "multi", | ||||
|                             events: [moveEvent, historyEvent] | ||||
|                         }; | ||||
|                     } | ||||
|                     RED.history.push(historyEvent); | ||||
|                 } | ||||
|             } | ||||
| @@ -3466,11 +3520,25 @@ RED.view = (function() { | ||||
|                 updateActiveNodes(); | ||||
|             } | ||||
|  | ||||
|             var moveEvent = null; | ||||
|             if (activeHoverGroup) { | ||||
|                 var oldX = activeHoverGroup.x;  | ||||
|                 var oldY = activeHoverGroup.y;  | ||||
|                 for (var j=0;j<movingSet.length();j++) { | ||||
|                     var n = movingSet.get(j); | ||||
|                     RED.group.addToGroup(activeHoverGroup,n.n); | ||||
|                 } | ||||
|                 if ((activeHoverGroup.x !== oldX) || | ||||
|                     (activeHoverGroup.y !== oldY)) { | ||||
|                     moveEvent = { | ||||
|                         t: "move", | ||||
|                         nodes: [{n: activeHoverGroup, | ||||
|                                  ox: oldX, oy: oldY, | ||||
|                                  dx: activeHoverGroup.x -oldX, | ||||
|                                  dy: activeHoverGroup.y -oldY}], | ||||
|                         dirty: true | ||||
|                     }; | ||||
|                 } | ||||
|                 historyEvent.addedToGroup = activeHoverGroup; | ||||
|  | ||||
|                 activeHoverGroup.hovered = false; | ||||
| @@ -3479,7 +3547,6 @@ RED.view = (function() { | ||||
|                 activeGroup.selected = true; | ||||
|                 activeHoverGroup = null; | ||||
|             } | ||||
|  | ||||
|             if (mouse_mode == RED.state.DETACHED_DRAGGING) { | ||||
|                 var ns = []; | ||||
|                 for (var j=0;j<movingSet.length();j++) { | ||||
| @@ -3490,7 +3557,15 @@ RED.view = (function() { | ||||
|                         n.n.moved = true; | ||||
|                     } | ||||
|                 } | ||||
|                 RED.history.replace({t:"multi",events:[historyEvent,{t:"move",nodes:ns}],dirty: historyEvent.dirty}) | ||||
|                 var event = {t:"multi",events:[historyEvent,{t:"move",nodes:ns}],dirty: historyEvent.dirty}; | ||||
|                 if (moveEvent) { | ||||
|                     event.events.push(moveEvent); | ||||
|                 } | ||||
|                 RED.history.replace(event) | ||||
|             } | ||||
|             else if(moveEvent) { | ||||
|                 var event = {t:"multi", events:[historyEvent, moveEvent], dirty: true}; | ||||
|                 RED.history.replace(event); | ||||
|             } | ||||
|  | ||||
|             updateSelection(); | ||||
|   | ||||
| @@ -32,7 +32,7 @@ | ||||
|     color: var(--red-ui-primary-text-color); | ||||
|     border: 1px solid var(--red-ui-notification-border-default); | ||||
|     border-left-width: 16px; | ||||
|     overflow: scroll; | ||||
|     overflow: auto; | ||||
|     max-height: 80vh; | ||||
|     .ui-dialog-buttonset { | ||||
|         margin-top: 20px; | ||||
|   | ||||
| @@ -18,7 +18,16 @@ | ||||
|         color:"#c0edc0", | ||||
|         defaults: { | ||||
|             name: {value:""}, | ||||
|             scope: {value:[], type:"*[]"}, | ||||
|             scope: { | ||||
|                 value: [], | ||||
|                 type: "*[]", | ||||
|                 validate: function (v, opt) { | ||||
|                     if (v.length > 0) { | ||||
|                         return true; | ||||
|                     } | ||||
|                     return RED._("node-red:complete.errors.scopeUndefined"); | ||||
|                 } | ||||
|             }, | ||||
|             uncaught: {value:false} | ||||
|         }, | ||||
|         inputs:0, | ||||
|   | ||||
| @@ -1,4 +1,3 @@ | ||||
|  | ||||
| <script type="text/html" data-template-name="link in"> | ||||
|     <div class="form-row"> | ||||
|         <label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label> | ||||
| @@ -272,7 +271,17 @@ | ||||
|         color:"#ddd",//"#87D8CF", | ||||
|         defaults: { | ||||
|             name: { value: "" }, | ||||
|             links: { value: [], type:"link in[]" }, | ||||
|             links: { | ||||
|                 value: [], | ||||
|                 type: "link in[]", | ||||
|                 validate: function (v, opt) { | ||||
|                     if ((this.linkType === "static" && v.length > 0) | ||||
|                       || this.linkType === "dynamic") { | ||||
|                         return true; | ||||
|                     } | ||||
|                     return RED._("node-red:link.errors.linkUndefined"); | ||||
|                 } | ||||
|             }, | ||||
|             linkType: { value:"static" }, | ||||
|             timeout: { | ||||
|                 value: "30", | ||||
|   | ||||
| @@ -164,10 +164,10 @@ module.exports = function(RED) { | ||||
|                     if (returnNode && returnNode.returnLinkMessage) { | ||||
|                         returnNode.returnLinkMessage(messageEvent.id, msg); | ||||
|                     } else { | ||||
|                         node.warn(RED._("link.error.missingReturn")) | ||||
|                         node.warn(RED._("link.errors.missingReturn")); | ||||
|                     } | ||||
|                 } else { | ||||
|                     node.warn(RED._("link.error.missingReturn")) | ||||
|                     node.warn(RED._("link.errors.missingReturn")); | ||||
|                 } | ||||
|                 done(); | ||||
|             } else if (mode === "link") { | ||||
|   | ||||
| @@ -117,7 +117,9 @@ module.exports = function(RED) { | ||||
|                 } | ||||
|                 if (typeof data === "boolean") { data = data.toString(); } | ||||
|                 if (typeof data === "number") { data = data.toString(); } | ||||
|                 if ((node.appendNewline) && (!Buffer.isBuffer(data))) { data += os.EOL; } | ||||
|                 var aflg = true; | ||||
|                 if (msg.hasOwnProperty("parts") && msg.parts.type === "string" && (msg.parts.count === msg.parts.index + 1)) { aflg = false; } | ||||
|                 if ((node.appendNewline) && (!Buffer.isBuffer(data)) && aflg) { data += os.EOL; } | ||||
|                 var buf; | ||||
|                 if (node.encoding === "setbymsg") { | ||||
|                     buf = encode(data, msg.encoding || "none"); | ||||
| @@ -314,7 +316,6 @@ module.exports = function(RED) { | ||||
|             }); | ||||
|             filename = filename || ""; | ||||
|             var fullFilename = filename; | ||||
|             var filePath = ""; | ||||
|             if (filename && RED.settings.fileWorkingDirectory && !path.isAbsolute(filename)) { | ||||
|                 fullFilename = path.resolve(path.join(RED.settings.fileWorkingDirectory,filename)); | ||||
|             } | ||||
|   | ||||
| @@ -119,7 +119,10 @@ | ||||
|         } | ||||
|     }, | ||||
|     "complete": { | ||||
|         "completeNodes": "complete: __number__" | ||||
|         "completeNodes": "complete: __number__", | ||||
|         "errors": { | ||||
|             "scopeUndefined": "scope undefined" | ||||
|         } | ||||
|     }, | ||||
|     "debug": { | ||||
|         "output": "Output", | ||||
| @@ -181,8 +184,9 @@ | ||||
|         "staticLinkCall": "Fixed target", | ||||
|         "dynamicLinkCall": "Dynamic target (msg.target)", | ||||
|         "dynamicLinkLabel": "Dynamic", | ||||
|         "error": { | ||||
|             "missingReturn": "Missing return node information" | ||||
|         "errors": { | ||||
|             "missingReturn": "Missing return node information", | ||||
|             "linkUndefined": "link undefined" | ||||
|         } | ||||
|     }, | ||||
|     "tls": { | ||||
|   | ||||
| @@ -119,7 +119,10 @@ | ||||
|         } | ||||
|     }, | ||||
|     "complete": { | ||||
|         "completeNodes": "complete: __number__" | ||||
|         "completeNodes": "complete: __number__", | ||||
|         "errors": { | ||||
|             "scopeUndefined": "スコープが未定義" | ||||
|         } | ||||
|     }, | ||||
|     "debug": { | ||||
|         "output": "対象", | ||||
| @@ -181,8 +184,9 @@ | ||||
|         "staticLinkCall": "対象を固定で指定", | ||||
|         "dynamicLinkCall": "対象を動的に指定 (msg.target)", | ||||
|         "dynamicLinkLabel": "動的", | ||||
|         "error": { | ||||
|             "missingReturn": "返却するノードの情報が存在しません" | ||||
|         "errors": { | ||||
|             "missingReturn": "返却するノードの情報が存在しません", | ||||
|             "linkUndefined": "リンクが未定義" | ||||
|         } | ||||
|     }, | ||||
|     "tls": { | ||||
|   | ||||
| @@ -818,6 +818,16 @@ function handlePreRoute(flow, sendEvent, reportError) { | ||||
|     }) | ||||
| } | ||||
|  | ||||
| function deliverMessageToDestination(sendEvent) { | ||||
|     if (sendEvent?.destination?.node) { | ||||
|         try { | ||||
|             sendEvent.destination.node.receive(sendEvent.msg); | ||||
|         } catch(err) { | ||||
|             Log.error(`Error delivering message to node:${sendEvent.destination.node._path} [${sendEvent.destination.node.type}]`) | ||||
|             Log.error(err.stack) | ||||
|         } | ||||
|     } | ||||
| } | ||||
| function handlePreDeliver(flow,sendEvent, reportError) { | ||||
|     // preDeliver - the local router has identified the node it is going to send to. At this point, the message has been cloned if needed. | ||||
|     hooks.trigger("preDeliver",sendEvent,(err) => { | ||||
| @@ -827,15 +837,10 @@ function handlePreDeliver(flow,sendEvent, reportError) { | ||||
|         } else if (err !== false) { | ||||
|             if (asyncMessageDelivery) { | ||||
|                 setImmediate(function() { | ||||
|                     if (sendEvent.destination.node) { | ||||
|                         sendEvent.destination.node.receive(sendEvent.msg); | ||||
|                     } | ||||
|                     deliverMessageToDestination(sendEvent) | ||||
|                 }) | ||||
|             } else { | ||||
|                 if (sendEvent.destination.node) { | ||||
|                     sendEvent.destination.node.receive(sendEvent.msg); | ||||
|  | ||||
|                 } | ||||
|                 deliverMessageToDestination(sendEvent) | ||||
|             } | ||||
|             // postDeliver - the message has been dispatched to be delivered asynchronously (unless the sync delivery flag is set, in which case it would be continue as synchronous delivery) | ||||
|             hooks.trigger("postDeliver", sendEvent, function(err) { | ||||
|   | ||||
							
								
								
									
										2
									
								
								packages/node_modules/node-red/red.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								packages/node_modules/node-red/red.js
									
									
									
									
										vendored
									
									
								
							| @@ -458,7 +458,7 @@ httpsPromise.then(function(startupHttps) { | ||||
|     RED.start().then(function() { | ||||
|         if (settings.httpAdminRoot !== false || settings.httpNodeRoot !== false || settings.httpStatic) { | ||||
|             server.on('error', function(err) { | ||||
|                 if (err.errno === "EADDRINUSE") { | ||||
|                 if (err.code === "EADDRINUSE") { | ||||
|                     RED.log.error(RED.log._("server.unable-to-listen", {listenpath:getListenPath()})); | ||||
|                     RED.log.error(RED.log._("server.port-in-use")); | ||||
|                 } else { | ||||
|   | ||||
							
								
								
									
										2
									
								
								packages/node_modules/node-red/settings.js
									
									
									
									
										vendored
									
									
								
							
							
						
						
									
										2
									
								
								packages/node_modules/node-red/settings.js
									
									
									
									
										vendored
									
									
								
							| @@ -416,7 +416,7 @@ module.exports = { | ||||
|                  */ | ||||
|                 // theme: "vs", | ||||
|                 /** other overrides can be set e.g. fontSize, fontFamily, fontLigatures etc. | ||||
|                  * for the full list, see https://microsoft.github.io/monaco-editor/api/interfaces/monaco.editor.IStandaloneEditorConstructionOptions.html | ||||
|                  * for the full list, see https://microsoft.github.io/monaco-editor/docs.html#interfaces/editor.IStandaloneEditorConstructionOptions.html | ||||
|                  */ | ||||
|                 //fontSize: 14, | ||||
|                 //fontFamily: "Cascadia Code, Fira Code, Consolas, 'Courier New', monospace", | ||||
|   | ||||
| @@ -194,6 +194,55 @@ describe('file Nodes', function() { | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('should append to a file and add newline, except last line of multipart input', function(done) { | ||||
|             var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":true, "overwriteFile":false, wires: [["helperNode1"]]}, | ||||
|                         {id:"helperNode1", type:"helper"}]; | ||||
|             try { | ||||
|                 fs.unlinkSync(fileToTest); | ||||
|             } catch(err) { | ||||
|             } | ||||
|             helper.load(fileNode, flow, function() { | ||||
|                 var n1 = helper.getNode("fileNode1"); | ||||
|                 var n2 = helper.getNode("helperNode1"); | ||||
|                 var count = 0; | ||||
|                 //var data = ["Line1", "Line2"]; | ||||
|  | ||||
|                 n2.on("input", function (msg) { | ||||
|                     try { | ||||
|                         msg.should.have.property("payload"); | ||||
|                         //data.should.containDeep([msg.payload]); | ||||
|                         if (count === 3) { | ||||
|                             var f = fs.readFileSync(fileToTest).toString(); | ||||
|                             if (os.type() !== "Windows_NT") { | ||||
|                                 f.should.have.length(23); | ||||
|                                 f.should.equal("Line1\nLine2\nLine3\nLine4"); | ||||
|                             } | ||||
|                             else { | ||||
|                                 f.should.have.length(23); | ||||
|                                 f.should.equal("Line1\r\nLine2\r\nLine3\r\nLine4"); | ||||
|                             } | ||||
|                             done(); | ||||
|                         } | ||||
|                         count++; | ||||
|                     } | ||||
|                     catch (e) { | ||||
|                         done(e); | ||||
|                     } | ||||
|                 }); | ||||
|  | ||||
|                 n1.receive({payload:"Line1",parts:{index:0,type:"string"}});    // string | ||||
|                 setTimeout(function() { | ||||
|                     n1.receive({payload:"Line2",parts:{index:1,type:"string"}});    // string | ||||
|                 },30); | ||||
|                 setTimeout(function() { | ||||
|                     n1.receive({payload:"Line3",parts:{index:2,type:"string"}});    // string | ||||
|                 },60); | ||||
|                 setTimeout(function() { | ||||
|                     n1.receive({payload:"Line4",parts:{index:3,type:"string",count:4}});    // string | ||||
|                 },90); | ||||
|             }); | ||||
|         }); | ||||
|  | ||||
|         it('should append to a file after it has been deleted ', function(done) { | ||||
|             var flow = [{id:"fileNode1", type:"file", name: "fileNode", "filename":fileToTest, "appendNewline":false, "overwriteFile":false, wires: [["helperNode1"]]}, | ||||
|                         {id:"helperNode1", type:"helper"}]; | ||||
|   | ||||
		Reference in New Issue
	
	Block a user