mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Merge remote-tracking branch 'upstream/dev' into dev
This commit is contained in:
		| @@ -1033,7 +1033,7 @@ RED.view = (function() { | |||||||
|         }) |         }) | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     function generateLinkPath(origX,origY, destX, destY, sc) { |     function generateLinkPath(origX,origY, destX, destY, sc, hasStatus = false) { | ||||||
|         var dy = destY-origY; |         var dy = destY-origY; | ||||||
|         var dx = destX-origX; |         var dx = destX-origX; | ||||||
|         var delta = Math.sqrt(dy*dy+dx*dx); |         var delta = Math.sqrt(dy*dy+dx*dx); | ||||||
| @@ -1050,62 +1050,110 @@ RED.view = (function() { | |||||||
|         } else { |         } else { | ||||||
|             scale = 0.4-0.2*(Math.max(0,(node_width-Math.min(Math.abs(dx),Math.abs(dy)))/node_width)); |             scale = 0.4-0.2*(Math.max(0,(node_width-Math.min(Math.abs(dx),Math.abs(dy)))/node_width)); | ||||||
|         } |         } | ||||||
|  |         function genCP(cp) { | ||||||
|  |             return ` M ${cp[0]-5} ${cp[1]} h 10 M ${cp[0]} ${cp[1]-5} v 10 ` | ||||||
|  |         } | ||||||
|         if (dx*sc > 0) { |         if (dx*sc > 0) { | ||||||
|             return "M "+origX+" "+origY+ |             let cp = [ | ||||||
|                 " C "+(origX+sc*(node_width*scale))+" "+(origY+scaleY*node_height)+" "+ |                 [(origX+sc*(node_width*scale)), (origY+scaleY*node_height)], | ||||||
|                 (destX-sc*(scale)*node_width)+" "+(destY-scaleY*node_height)+" "+ |                 [(destX-sc*(scale)*node_width), (destY-scaleY*node_height)] | ||||||
|                 destX+" "+destY |             ] | ||||||
|  |             return `M ${origX} ${origY} C ${cp[0][0]} ${cp[0][1]} ${cp[1][0]} ${cp[1][1]} ${destX} ${destY}` | ||||||
|  |                 //    + ` ${genCP(cp[0])} ${genCP(cp[1])}` | ||||||
|         } else { |         } else { | ||||||
|  |             let topX, topY, bottomX, bottomY | ||||||
|  |             let cp | ||||||
|  |             let midX = Math.floor(destX-dx/2); | ||||||
|  |             let midY = Math.floor(destY-dy/2);           | ||||||
|  |             if (Math.abs(dy) < 10) { | ||||||
|  |                 bottomY = Math.max(origY, destY) + (hasStatus?35:25) | ||||||
|  |                 let startCurveHeight = bottomY - origY | ||||||
|  |                 let endCurveHeight = bottomY - destY | ||||||
|  |                 cp = [ | ||||||
|  |                     [ origX + sc*15 , origY ], | ||||||
|  |                     [ origX + sc*25 , origY + 5 ], | ||||||
|  |                     [ origX + sc*25 , origY + startCurveHeight/2 ], | ||||||
|  |  | ||||||
|             var midX = Math.floor(destX-dx/2); |                     [ origX + sc*25 , origY + startCurveHeight - 5 ], | ||||||
|             var midY = Math.floor(destY-dy/2); |                     [ origX + sc*15 , origY + startCurveHeight ], | ||||||
|             // |                     [ origX , origY + startCurveHeight ], | ||||||
|             if (dy === 0) { |  | ||||||
|                 midY = destY + node_height; |                     [ destX - sc*15, origY + startCurveHeight ], | ||||||
|             } |                     [ destX - sc*25, origY + startCurveHeight - 5 ], | ||||||
|             var cp_height = node_height/2; |                     [ destX - sc*25, destY + endCurveHeight/2 ], | ||||||
|             var y1 = (destY + midY)/2 |  | ||||||
|             var topX =origX + sc*node_width*scale; |                     [ destX - sc*25, destY + 5 ], | ||||||
|             var topY = dy>0?Math.min(y1 - dy/2 , origY+cp_height):Math.max(y1 - dy/2 , origY-cp_height); |                     [ destX - sc*15, destY ], | ||||||
|             var bottomX = destX - sc*node_width*scale; |                     [ destX, destY ], | ||||||
|             var bottomY = dy>0?Math.max(y1, destY-cp_height):Math.min(y1, destY+cp_height); |                 ] | ||||||
|             var x1 = (origX+topX)/2; |  | ||||||
|             var scy = dy>0?1:-1; |                 return "M "+origX+" "+origY+ | ||||||
|             var cp = [ |                     " C "+ | ||||||
|                 // Orig -> Top |                     cp[0][0]+" "+cp[0][1]+" "+ | ||||||
|                 [x1,origY], |                     cp[1][0]+" "+cp[1][1]+" "+ | ||||||
|                 [topX,dy>0?Math.max(origY, topY-cp_height):Math.min(origY, topY+cp_height)], |                     cp[2][0]+" "+cp[2][1]+" "+ | ||||||
|                 // Top -> Mid |                     " C " + | ||||||
|                 // [Mirror previous cp] |                     cp[3][0]+" "+cp[3][1]+" "+ | ||||||
|                 [x1,dy>0?Math.min(midY, topY+cp_height):Math.max(midY, topY-cp_height)], |  | ||||||
|                 // Mid -> Bottom |  | ||||||
|                 // [Mirror previous cp] |  | ||||||
|                 [bottomX,dy>0?Math.max(midY, bottomY-cp_height):Math.min(midY, bottomY+cp_height)], |  | ||||||
|                 // Bottom -> Dest |  | ||||||
|                 // [Mirror previous cp] |  | ||||||
|                 [(destX+bottomX)/2,destY] |  | ||||||
|             ]; |  | ||||||
|             if (cp[2][1] === topY+scy*cp_height) { |  | ||||||
|                 if (Math.abs(dy) < cp_height*10) { |  | ||||||
|                     cp[1][1] = topY-scy*cp_height/2; |  | ||||||
|                     cp[3][1] = bottomY-scy*cp_height/2; |  | ||||||
|                 } |  | ||||||
|                 cp[2][0] = topX; |  | ||||||
|             } |  | ||||||
|             return "M "+origX+" "+origY+ |  | ||||||
|                 " C "+ |  | ||||||
|                    cp[0][0]+" "+cp[0][1]+" "+ |  | ||||||
|                    cp[1][0]+" "+cp[1][1]+" "+ |  | ||||||
|                    topX+" "+topY+ |  | ||||||
|                 " S "+ |  | ||||||
|                    cp[2][0]+" "+cp[2][1]+" "+ |  | ||||||
|                    midX+" "+midY+ |  | ||||||
|                " S "+ |  | ||||||
|                   cp[3][0]+" "+cp[3][1]+" "+ |  | ||||||
|                   bottomX+" "+bottomY+ |  | ||||||
|                 " S "+ |  | ||||||
|                     cp[4][0]+" "+cp[4][1]+" "+ |                     cp[4][0]+" "+cp[4][1]+" "+ | ||||||
|                     destX+" "+destY |                     cp[5][0]+" "+cp[5][1]+" "+ | ||||||
|  |                     " h "+dx+ | ||||||
|  |                     " C "+ | ||||||
|  |                     cp[6][0]+" "+cp[6][1]+" "+ | ||||||
|  |                     cp[7][0]+" "+cp[7][1]+" "+ | ||||||
|  |                     cp[8][0]+" "+cp[8][1]+" "+ | ||||||
|  |                     " C " + | ||||||
|  |                     cp[9][0]+" "+cp[9][1]+" "+ | ||||||
|  |                     cp[10][0]+" "+cp[10][1]+" "+ | ||||||
|  |                     cp[11][0]+" "+cp[11][1]+" " | ||||||
|  |                     // +genCP(cp[0])+genCP(cp[1])+genCP(cp[2])+genCP(cp[3])+genCP(cp[4]) | ||||||
|  |                     // +genCP(cp[5])+genCP(cp[6])+genCP(cp[7])+genCP(cp[8])+genCP(cp[9])+genCP(cp[10]) | ||||||
|  |             } else { | ||||||
|  |                 var cp_height = node_height/2; | ||||||
|  |                 var y1 = (destY + midY)/2 | ||||||
|  |                 topX = origX + sc*node_width*scale; | ||||||
|  |                 topY = dy>0?Math.min(y1 - dy/2 , origY+cp_height):Math.max(y1 - dy/2 , origY-cp_height); | ||||||
|  |                 bottomX = destX - sc*node_width*scale; | ||||||
|  |                 bottomY = dy>0?Math.max(y1, destY-cp_height):Math.min(y1, destY+cp_height); | ||||||
|  |                 var x1 = (origX+topX)/2; | ||||||
|  |                 var scy = dy>0?1:-1; | ||||||
|  |                 cp = [ | ||||||
|  |                     // Orig -> Top | ||||||
|  |                     [x1,origY], | ||||||
|  |                     [topX,dy>0?Math.max(origY, topY-cp_height):Math.min(origY, topY+cp_height)], | ||||||
|  |                     // Top -> Mid | ||||||
|  |                     // [Mirror previous cp] | ||||||
|  |                     [x1,dy>0?Math.min(midY, topY+cp_height):Math.max(midY, topY-cp_height)], | ||||||
|  |                     // Mid -> Bottom | ||||||
|  |                     // [Mirror previous cp] | ||||||
|  |                     [bottomX,dy>0?Math.max(midY, bottomY-cp_height):Math.min(midY, bottomY+cp_height)], | ||||||
|  |                     // Bottom -> Dest | ||||||
|  |                     // [Mirror previous cp] | ||||||
|  |                     [(destX+bottomX)/2,destY] | ||||||
|  |                 ]; | ||||||
|  |                 if (cp[2][1] === topY+scy*cp_height) { | ||||||
|  |                     if (Math.abs(dy) < cp_height*10) { | ||||||
|  |                         cp[1][1] = topY-scy*cp_height/2; | ||||||
|  |                         cp[3][1] = bottomY-scy*cp_height/2; | ||||||
|  |                     } | ||||||
|  |                     cp[2][0] = topX; | ||||||
|  |                 } | ||||||
|  |                 return "M "+origX+" "+origY+ | ||||||
|  |                     " C "+ | ||||||
|  |                     cp[0][0]+" "+cp[0][1]+" "+ | ||||||
|  |                     cp[1][0]+" "+cp[1][1]+" "+ | ||||||
|  |                     topX+" "+topY+ | ||||||
|  |                     " S "+ | ||||||
|  |                     cp[2][0]+" "+cp[2][1]+" "+ | ||||||
|  |                     midX+" "+midY+ | ||||||
|  |                 " S "+ | ||||||
|  |                     cp[3][0]+" "+cp[3][1]+" "+ | ||||||
|  |                     bottomX+" "+bottomY+ | ||||||
|  |                     " S "+ | ||||||
|  |                         cp[4][0]+" "+cp[4][1]+" "+ | ||||||
|  |                         destX+" "+destY | ||||||
|  |  | ||||||
|  |                 // +genCP(cp[0])+genCP(cp[1])+genCP(cp[2])+genCP(cp[3])+genCP(cp[4]) | ||||||
|  |             } | ||||||
|         } |         } | ||||||
|     } |     } | ||||||
|  |  | ||||||
| @@ -1722,7 +1770,7 @@ RED.view = (function() { | |||||||
|                 var portY = -((numOutputs-1)/2)*13 +13*sourcePort; |                 var portY = -((numOutputs-1)/2)*13 +13*sourcePort; | ||||||
|  |  | ||||||
|                 var sc = (drag_line.portType === PORT_TYPE_OUTPUT)?1:-1; |                 var sc = (drag_line.portType === PORT_TYPE_OUTPUT)?1:-1; | ||||||
|                 drag_line.el.attr("d",generateLinkPath(drag_line.node.x+sc*drag_line.node.w/2,drag_line.node.y+portY,mousePos[0],mousePos[1],sc)); |                 drag_line.el.attr("d",generateLinkPath(drag_line.node.x+sc*drag_line.node.w/2,drag_line.node.y+portY,mousePos[0],mousePos[1],sc, !!drag_line.node.status)); | ||||||
|             } |             } | ||||||
|             d3.event.preventDefault(); |             d3.event.preventDefault(); | ||||||
|         } else if (mouse_mode == RED.state.MOVING) { |         } else if (mouse_mode == RED.state.MOVING) { | ||||||
| @@ -4112,21 +4160,27 @@ RED.view = (function() { | |||||||
|                 nodeEl.__statusGroup__.style.display = "none"; |                 nodeEl.__statusGroup__.style.display = "none"; | ||||||
|             } else { |             } else { | ||||||
|                 nodeEl.__statusGroup__.style.display = "inline"; |                 nodeEl.__statusGroup__.style.display = "inline"; | ||||||
|  |                 let backgroundWidth = 12 | ||||||
|                 var fill = status_colours[d.status.fill]; // Only allow our colours for now |                 var fill = status_colours[d.status.fill]; // Only allow our colours for now | ||||||
|                 if (d.status.shape == null && fill == null) { |                 if (d.status.shape == null && fill == null) { | ||||||
|  |                     backgroundWidth = 0 | ||||||
|                     nodeEl.__statusShape__.style.display = "none"; |                     nodeEl.__statusShape__.style.display = "none"; | ||||||
|  |                     nodeEl.__statusBackground__.setAttribute("x", 17) | ||||||
|                     nodeEl.__statusGroup__.setAttribute("transform","translate(-14,"+(d.h+3)+")"); |                     nodeEl.__statusGroup__.setAttribute("transform","translate(-14,"+(d.h+3)+")"); | ||||||
|                 } else { |                 } else { | ||||||
|                     nodeEl.__statusGroup__.setAttribute("transform","translate(3,"+(d.h+3)+")"); |                     nodeEl.__statusGroup__.setAttribute("transform","translate(3,"+(d.h+3)+")"); | ||||||
|                     var statusClass = "red-ui-flow-node-status-"+(d.status.shape||"dot")+"-"+d.status.fill; |                     var statusClass = "red-ui-flow-node-status-"+(d.status.shape||"dot")+"-"+d.status.fill; | ||||||
|                     nodeEl.__statusShape__.style.display = "inline"; |                     nodeEl.__statusShape__.style.display = "inline"; | ||||||
|                     nodeEl.__statusShape__.setAttribute("class","red-ui-flow-node-status "+statusClass); |                     nodeEl.__statusShape__.setAttribute("class","red-ui-flow-node-status "+statusClass); | ||||||
|  |                     nodeEl.__statusBackground__.setAttribute("x", 3) | ||||||
|                 } |                 } | ||||||
|                 if (d.status.hasOwnProperty('text')) { |                 if (d.status.hasOwnProperty('text')) { | ||||||
|                     nodeEl.__statusLabel__.textContent = d.status.text; |                     nodeEl.__statusLabel__.textContent = d.status.text; | ||||||
|                 } else { |                 } else { | ||||||
|                     nodeEl.__statusLabel__.textContent = ""; |                     nodeEl.__statusLabel__.textContent = ""; | ||||||
|                 } |                 } | ||||||
|  |                 const textSize = nodeEl.__statusLabel__.getBBox() | ||||||
|  |                 nodeEl.__statusBackground__.setAttribute('width', backgroundWidth + textSize.width + 6) | ||||||
|             } |             } | ||||||
|             delete d.dirtyStatus; |             delete d.dirtyStatus; | ||||||
|         } |         } | ||||||
| @@ -4532,17 +4586,30 @@ RED.view = (function() { | |||||||
|                 statusEl.style.display = "none"; |                 statusEl.style.display = "none"; | ||||||
|                 node[0][0].__statusGroup__ = statusEl; |                 node[0][0].__statusGroup__ = statusEl; | ||||||
|  |  | ||||||
|                 var statusRect = document.createElementNS("http://www.w3.org/2000/svg","rect"); |                 var statusBackground = document.createElementNS("http://www.w3.org/2000/svg","rect"); | ||||||
|                 statusRect.setAttribute("class","red-ui-flow-node-status"); |                 statusBackground.setAttribute("class","red-ui-flow-node-status-background"); | ||||||
|                 statusRect.setAttribute("x",6); |                 statusBackground.setAttribute("x",3); | ||||||
|                 statusRect.setAttribute("y",1); |                 statusBackground.setAttribute("y",-1); | ||||||
|                 statusRect.setAttribute("width",9); |                 statusBackground.setAttribute("width",200); | ||||||
|                 statusRect.setAttribute("height",9); |                 statusBackground.setAttribute("height",13); | ||||||
|                 statusRect.setAttribute("rx",2); |                 statusBackground.setAttribute("rx",1); | ||||||
|                 statusRect.setAttribute("ry",2); |                 statusBackground.setAttribute("ry",1); | ||||||
|                 statusRect.setAttribute("stroke-width","3"); |                  | ||||||
|                 statusEl.appendChild(statusRect); |                 statusEl.appendChild(statusBackground); | ||||||
|                 node[0][0].__statusShape__ = statusRect; |                 node[0][0].__statusBackground__ = statusBackground; | ||||||
|  |  | ||||||
|  |  | ||||||
|  |                 var statusIcon = document.createElementNS("http://www.w3.org/2000/svg","rect"); | ||||||
|  |                 statusIcon.setAttribute("class","red-ui-flow-node-status"); | ||||||
|  |                 statusIcon.setAttribute("x",6); | ||||||
|  |                 statusIcon.setAttribute("y",1); | ||||||
|  |                 statusIcon.setAttribute("width",9); | ||||||
|  |                 statusIcon.setAttribute("height",9); | ||||||
|  |                 statusIcon.setAttribute("rx",2); | ||||||
|  |                 statusIcon.setAttribute("ry",2); | ||||||
|  |                 statusIcon.setAttribute("stroke-width","3"); | ||||||
|  |                 statusEl.appendChild(statusIcon); | ||||||
|  |                 node[0][0].__statusShape__ = statusIcon; | ||||||
|  |  | ||||||
|                 var statusLabel = document.createElementNS("http://www.w3.org/2000/svg","text"); |                 var statusLabel = document.createElementNS("http://www.w3.org/2000/svg","text"); | ||||||
|                 statusLabel.setAttribute("class","red-ui-flow-node-status-label"); |                 statusLabel.setAttribute("class","red-ui-flow-node-status-label"); | ||||||
| @@ -5067,7 +5134,7 @@ RED.view = (function() { | |||||||
|                     //     " C "+(d.x1+scale*node_width)+" "+(d.y1+scaleY*node_height)+" "+ |                     //     " C "+(d.x1+scale*node_width)+" "+(d.y1+scaleY*node_height)+" "+ | ||||||
|                     //     (d.x2-scale*node_width)+" "+(d.y2-scaleY*node_height)+" "+ |                     //     (d.x2-scale*node_width)+" "+(d.y2-scaleY*node_height)+" "+ | ||||||
|                     //     d.x2+" "+d.y2; |                     //     d.x2+" "+d.y2; | ||||||
|                     var path = generateLinkPath(d.x1,d.y1,d.x2,d.y2,1); |                     var path = generateLinkPath(d.x1,d.y1,d.x2,d.y2,1, !!(d.source.status || d.target.status)); | ||||||
|                     if (/NaN/.test(path)) { |                     if (/NaN/.test(path)) { | ||||||
|                         path = "" |                         path = "" | ||||||
|                     } |                     } | ||||||
|   | |||||||
| @@ -304,7 +304,11 @@ g.red-ui-flow-node-selected { | |||||||
|         stroke: var(--red-ui-node-status-colors-#{"" + $current-color}); |         stroke: var(--red-ui-node-status-colors-#{"" + $current-color}); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  | .red-ui-flow-node-status-background { | ||||||
|  |     stroke: none; | ||||||
|  |     fill: var(--red-ui-view-background); | ||||||
|  |     fill-opacity: 0.9; | ||||||
|  | } | ||||||
| .red-ui-flow-node-status-label { | .red-ui-flow-node-status-label { | ||||||
|     @include disable-selection; |     @include disable-selection; | ||||||
|     stroke-width: 0; |     stroke-width: 0; | ||||||
|   | |||||||
| @@ -650,10 +650,9 @@ class Flow { | |||||||
|             // Delegate status to any nodes using this config node |             // Delegate status to any nodes using this config node | ||||||
|             for (let userNode in node.users) { |             for (let userNode in node.users) { | ||||||
|                 if (node.users.hasOwnProperty(userNode)) { |                 if (node.users.hasOwnProperty(userNode)) { | ||||||
|                     node.users[userNode]._flow.handleStatus(node,statusMessage,node.users[userNode],true); |                     handled = node.users[userNode]._flow.handleStatus(node,statusMessage,node.users[userNode],true) || handled; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             handled = true; |  | ||||||
|         } else { |         } else { | ||||||
|             const candidateNodes = []; |             const candidateNodes = []; | ||||||
|             this.statusNodes.forEach(targetStatusNode => { |             this.statusNodes.forEach(targetStatusNode => { | ||||||
| @@ -737,10 +736,9 @@ class Flow { | |||||||
|             // Delegate status to any nodes using this config node |             // Delegate status to any nodes using this config node | ||||||
|             for (let userNode in node.users) { |             for (let userNode in node.users) { | ||||||
|                 if (node.users.hasOwnProperty(userNode)) { |                 if (node.users.hasOwnProperty(userNode)) { | ||||||
|                     node.users[userNode]._flow.handleError(node,logMessage,msg,node.users[userNode]); |                     handled = node.users[userNode]._flow.handleError(node,logMessage,msg,node.users[userNode]) || handled; | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|             handled = true; |  | ||||||
|         } else { |         } else { | ||||||
|             const candidateNodes = []; |             const candidateNodes = []; | ||||||
|             this.catchNodes.forEach(targetCatchNode => { |             this.catchNodes.forEach(targetCatchNode => { | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user