mirror of
				https://github.com/node-red/node-red.git
				synced 2025-03-01 10:36:34 +00:00 
			
		
		
		
	Add tooltip on node error icon for validation errs
This commit is contained in:
		| @@ -321,7 +321,8 @@ | |||||||
|         "show": "Show", |         "show": "Show", | ||||||
|         "hide": "Hide", |         "hide": "Hide", | ||||||
|         "errors": { |         "errors": { | ||||||
|             "scopeChange": "Changing the scope will make it unavailable to nodes in other flows that use it" |             "scopeChange": "Changing the scope will make it unavailable to nodes in other flows that use it", | ||||||
|  |             "invalidProperties": "Invalid properties:" | ||||||
|         } |         } | ||||||
|     }, |     }, | ||||||
|     "keyboard": { |     "keyboard": { | ||||||
|   | |||||||
| @@ -45,6 +45,7 @@ RED.editor = (function() { | |||||||
|         node.valid = true; |         node.valid = true; | ||||||
|         var subflow; |         var subflow; | ||||||
|         var isValid; |         var isValid; | ||||||
|  |         var validationErrors; | ||||||
|         var hasChanged; |         var hasChanged; | ||||||
|         if (node.type.indexOf("subflow:")===0) { |         if (node.type.indexOf("subflow:")===0) { | ||||||
|             subflow = RED.nodes.subflow(node.type.substring(8)); |             subflow = RED.nodes.subflow(node.type.substring(8)); | ||||||
| @@ -54,13 +55,17 @@ RED.editor = (function() { | |||||||
|                 isValid = validateNode(subflow); |                 isValid = validateNode(subflow); | ||||||
|                 hasChanged = subflow.changed; |                 hasChanged = subflow.changed; | ||||||
|             } |             } | ||||||
|             node.valid = isValid && validateNodeProperties(node, node._def.defaults, node); |             validationErrors = validateNodeProperties(node, node._def.defaults, node); | ||||||
|  |             node.valid = isValid && validationErrors.length === 0; | ||||||
|             node.changed = node.changed || hasChanged; |             node.changed = node.changed || hasChanged; | ||||||
|  |             node.validationErrors = validationErrors; | ||||||
|         } else if (node._def) { |         } else if (node._def) { | ||||||
|             node.valid = validateNodeProperties(node, node._def.defaults, node); |             validationErrors = validateNodeProperties(node, node._def.defaults, node); | ||||||
|             if (node._def._creds) { |             if (node._def._creds) { | ||||||
|                 node.valid = node.valid && validateNodeProperties(node, node._def.credentials, node._def._creds); |                 validationErrors = validationErrors.concat(validateNodeProperties(node, node._def.credentials, node._def._creds)) | ||||||
|             } |             } | ||||||
|  |             node.valid = (validationErrors.length === 0); | ||||||
|  |             node.validationErrors = validationErrors; | ||||||
|         } else if (node.type == "subflow") { |         } else if (node.type == "subflow") { | ||||||
|             var subflowNodes = RED.nodes.filterNodes({z:node.id}); |             var subflowNodes = RED.nodes.filterNodes({z:node.id}); | ||||||
|             for (var i=0;i<subflowNodes.length;i++) { |             for (var i=0;i<subflowNodes.length;i++) { | ||||||
| @@ -103,18 +108,18 @@ RED.editor = (function() { | |||||||
|      * @param node - the node being validated |      * @param node - the node being validated | ||||||
|      * @param definition - the node property definitions (either def.defaults or def.creds) |      * @param definition - the node property definitions (either def.defaults or def.creds) | ||||||
|      * @param properties - the node property values to validate |      * @param properties - the node property values to validate | ||||||
|      * @returns {boolean} whether the node's properties are valid |      * @returns {array} an array of invalid properties | ||||||
|      */ |      */ | ||||||
|     function validateNodeProperties(node, definition, properties) { |     function validateNodeProperties(node, definition, properties) { | ||||||
|         var isValid = true; |         var result = []; | ||||||
|         for (var prop in definition) { |         for (var prop in definition) { | ||||||
|             if (definition.hasOwnProperty(prop)) { |             if (definition.hasOwnProperty(prop)) { | ||||||
|                 if (!validateNodeProperty(node, definition, prop, properties[prop])) { |                 if (!validateNodeProperty(node, definition, prop, properties[prop])) { | ||||||
|                     isValid = false; |                     result.push(prop); | ||||||
|                 } |                 } | ||||||
|             } |             } | ||||||
|         } |         } | ||||||
|         return isValid; |         return result; | ||||||
|     } |     } | ||||||
|  |  | ||||||
|     /** |     /** | ||||||
| @@ -127,9 +132,11 @@ RED.editor = (function() { | |||||||
|      */ |      */ | ||||||
|     function validateNodeProperty(node,definition,property,value) { |     function validateNodeProperty(node,definition,property,value) { | ||||||
|         var valid = true; |         var valid = true; | ||||||
|  |         // Check for $(env-var) and consider it valid | ||||||
|         if (/^\$\([a-zA-Z_][a-zA-Z0-9_]*\)$/.test(value)) { |         if (/^\$\([a-zA-Z_][a-zA-Z0-9_]*\)$/.test(value)) { | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|  |         // Check for ${env-var} and consider it valid | ||||||
|         if (/^\$\{[a-zA-Z_][a-zA-Z0-9_]*\}$/.test(value)) { |         if (/^\$\{[a-zA-Z_][a-zA-Z0-9_]*\}$/.test(value)) { | ||||||
|             return true; |             return true; | ||||||
|         } |         } | ||||||
|   | |||||||
| @@ -2053,18 +2053,18 @@ RED.view = (function() { | |||||||
|             .attr("class","red-ui-flow-port-tooltip"); |             .attr("class","red-ui-flow-port-tooltip"); | ||||||
|  |  | ||||||
|         var lines = content.split("\n"); |         var lines = content.split("\n"); | ||||||
|         var labelWidth = 0; |         var labelWidth = 6; | ||||||
|         var labelHeight = 4; |         var labelHeight = 12; | ||||||
|         var labelHeights = []; |         var labelHeights = []; | ||||||
|         var lineHeight = 0; |         var lineHeight = 0; | ||||||
|         lines.forEach(function(l,i) { |         lines.forEach(function(l,i) { | ||||||
|             var labelDimensions = calculateTextDimensions(l||" ", "red-ui-flow-port-tooltip-label", 8,0); |             var labelDimensions = calculateTextDimensions(l||" ", "red-ui-flow-port-tooltip-label", 8,0); | ||||||
|             labelWidth = Math.max(labelWidth,labelDimensions[0]); |             labelWidth = Math.max(labelWidth,labelDimensions[0] + 6); | ||||||
|             labelHeights.push(0.8*labelDimensions[1]); |             labelHeights.push(labelDimensions[1]); | ||||||
|             if (i === 0) { |             if (i === 0) { | ||||||
|                 lineHeight = 0.8*labelDimensions[1]; |                 lineHeight = labelDimensions[1]; | ||||||
|             } |             } | ||||||
|             labelHeight += 0.8*labelDimensions[1]; |             labelHeight += labelDimensions[1]; | ||||||
|         }); |         }); | ||||||
|         var labelWidth1 = (labelWidth/2)-5-2; |         var labelWidth1 = (labelWidth/2)-5-2; | ||||||
|         var labelWidth2 = labelWidth - 4; |         var labelWidth2 = labelWidth - 4; | ||||||
| @@ -2073,20 +2073,20 @@ RED.view = (function() { | |||||||
|         var labelHeight2 = labelHeight - 4; |         var labelHeight2 = labelHeight - 4; | ||||||
|         var path; |         var path; | ||||||
|         var lx; |         var lx; | ||||||
|         var ly = -labelHeight/2+1; |         var ly = -labelHeight/2+3; | ||||||
|         var anchor; |         var anchor; | ||||||
|         if (direction === "left") { |         if (direction === "left") { | ||||||
|             path = "M0 0 l -5 -5 v -"+(labelHeight1)+" q 0 -2 -2 -2 h -"+labelWidth+" q -2 0 -2 2 v "+(labelHeight2)+" q 0 2 2 2 h "+labelWidth+" q 2 0 2 -2 v -"+(labelHeight1)+" l 5 -5"; |             path = "M0 0 l -5 -5 v -"+(labelHeight1)+" q 0 -2 -2 -2 h -"+labelWidth+" q -2 0 -2 2 v "+(labelHeight2)+" q 0 2 2 2 h "+labelWidth+" q 2 0 2 -2 v -"+(labelHeight1)+" l 5 -5"; | ||||||
|             lx = -10; |             lx = -14; | ||||||
|             anchor = "end"; |             anchor = "end"; | ||||||
|         } else if (direction === "right") { |         } else if (direction === "right") { | ||||||
|             path = "M0 0 l 5 -5 v -"+(labelHeight1)+" q 0 -2 2 -2 h "+labelWidth+" q 2 0 2 2 v "+(labelHeight2)+" q 0 2 -2 2 h -"+labelWidth+" q -2 0 -2 -2 v -"+(labelHeight1)+" l -5 -5" |             path = "M0 0 l 5 -5 v -"+(labelHeight1)+" q 0 -2 2 -2 h "+labelWidth+" q 2 0 2 2 v "+(labelHeight2)+" q 0 2 -2 2 h -"+labelWidth+" q -2 0 -2 -2 v -"+(labelHeight1)+" l -5 -5" | ||||||
|             lx = 10; |             lx = 14; | ||||||
|             anchor = "start"; |             anchor = "start"; | ||||||
|         } else if (direction === "top") { |         } else if (direction === "top") { | ||||||
|             path = "M0 0 l 5 -5 h "+(labelWidth1)+" q 2 0 2 -2 v -"+labelHeight+" q 0 -2 -2 -2 h -"+(labelWidth2)+" q -2 0 -2 2 v "+labelHeight+" q 0 2 2 2 h "+(labelWidth1)+" l 5 5" |             path = "M0 0 l 5 -5 h "+(labelWidth1)+" q 2 0 2 -2 v -"+labelHeight+" q 0 -2 -2 -2 h -"+(labelWidth2)+" q -2 0 -2 2 v "+labelHeight+" q 0 2 2 2 h "+(labelWidth1)+" l 5 5" | ||||||
|             lx = -labelWidth/2 + 4; |             lx = -labelWidth/2 + 6; | ||||||
|             ly = -labelHeight-lineHeight+5; |             ly = -labelHeight-lineHeight+10; | ||||||
|             anchor = "start"; |             anchor = "start"; | ||||||
|         } |         } | ||||||
|         tooltip.append("path").attr("d",path); |         tooltip.append("path").attr("d",path); | ||||||
| @@ -2781,25 +2781,27 @@ RED.view = (function() { | |||||||
|  |  | ||||||
|                     node.append("g").attr("class","red-ui-flow-node-changed hide").attr("transform","translate(20, -2)").append("circle").attr("r",5); |                     node.append("g").attr("class","red-ui-flow-node-changed hide").attr("transform","translate(20, -2)").append("circle").attr("r",5); | ||||||
|                     var nodeErrorButton = node.append("g").attr("class","red-ui-flow-node-error hide").attr("transform","translate(0, -2)").append("path").attr("d","M -5,4 l 10,0 -5,-8 z"); |                     var nodeErrorButton = node.append("g").attr("class","red-ui-flow-node-error hide").attr("transform","translate(0, -2)").append("path").attr("d","M -5,4 l 10,0 -5,-8 z"); | ||||||
|                     // nodeErrorButton.on("mouseenter", function() { |                     nodeErrorButton.on("mouseenter", function() { | ||||||
|                     //     clearTimeout(portLabelHoverTimeout); |                         if (d.validationErrors && d.validationErrors.length > 0) { | ||||||
|                     //     portLabelHoverTimeout = setTimeout(function() { |                             clearTimeout(portLabelHoverTimeout); | ||||||
|                     //         var pos = getElementPosition(nodeErrorButton.node()); |                             portLabelHoverTimeout = setTimeout(function() { | ||||||
|                     //         portLabelHoverTimeout = null; |                                 var pos = getElementPosition(nodeErrorButton.node()); | ||||||
|                     //         portLabelHover = showTooltip( |                                 portLabelHoverTimeout = null; | ||||||
|                     //             (pos[0]), |                                 portLabelHover = showTooltip( | ||||||
|                     //             (pos[1]), |                                     (pos[0]), | ||||||
|                     //             tooltip, |                                     (pos[1]), | ||||||
|                     //             "top" |                                     RED._("editor.errors.invalidProperties")+"\n  - "+d.validationErrors.join("\n    - "), | ||||||
|                     //         ); |                                     "top" | ||||||
|                     //     },500); |                                 ); | ||||||
|                     // }).on("mouseleave", function() { |                             },500); | ||||||
|                     //     clearTimeout(portLabelHoverTimeout); |                         } | ||||||
|                     //     if (portLabelHover) { |                     }).on("mouseleave", function() { | ||||||
|                     //         portLabelHover.remove(); |                         clearTimeout(portLabelHoverTimeout); | ||||||
|                     //         portLabelHover = null; |                         if (portLabelHover) { | ||||||
|                     //     } |                             portLabelHover.remove(); | ||||||
|                     // }); |                             portLabelHover = null; | ||||||
|  |                         } | ||||||
|  |                     }); | ||||||
|             }); |             }); | ||||||
|  |  | ||||||
|             node.each(function(d,i) { |             node.each(function(d,i) { | ||||||
|   | |||||||
| @@ -256,5 +256,6 @@ g.red-ui-flow-link-unknown path.red-ui-flow-link-line { | |||||||
|     font-size: 12px; |     font-size: 12px; | ||||||
|     pointer-events: none; |     pointer-events: none; | ||||||
|     -webkit-touch-callout: none; |     -webkit-touch-callout: none; | ||||||
|  |     white-space: pre; | ||||||
|     @include disable-selection; |     @include disable-selection; | ||||||
| } | } | ||||||
|   | |||||||
		Reference in New Issue
	
	Block a user