Add tooltip input validation msg

This commit is contained in:
GogoVega 2023-12-12 17:17:33 +01:00
parent 918943816f
commit ba08cf0417
No known key found for this signature in database
GPG Key ID: E1E048B63AC5AC2B
2 changed files with 133 additions and 96 deletions

View File

@ -167,14 +167,16 @@
]
var allOptions = {
msg: { value: "msg", label: "msg.", validate: RED.utils.validatePropertyExpression, autoComplete: autoComplete(msgCompletions) },
flow: {value:"flow",label:"flow.",hasValue:true,
flow: {
value: "flow", label: "flow.", hasValue: true,
options: [],
validate: RED.utils.validatePropertyExpression,
parse: contextParse,
export: contextExport,
valueLabel: contextLabel
},
global: {value:"global",label:"global.",hasValue:true,
global: {
value: "global", label: "global.", hasValue: true,
options: [],
validate: RED.utils.validatePropertyExpression,
parse: contextParse,
@ -182,15 +184,17 @@
valueLabel: contextLabel
},
str: { value: "str", label: "string", icon: "red/images/typedInput/az.svg" },
num: {value:"num",label:"number",icon:"red/images/typedInput/09.svg",validate: function(v) {
return (true === RED.utils.validateTypedProperty(v, "num"));
num: { value: "num", label: "number", icon: "red/images/typedInput/09.svg", validate: function (v, o) {
return RED.utils.validateTypedProperty(v, "num", o);
} },
bool: { value: "bool", label: "boolean", icon: "red/images/typedInput/bool.svg", options: ["true", "false"] },
json: {
value: "json",
label: "JSON",
icon: "red/images/typedInput/json.svg",
validate: function(v) { try{JSON.parse(v);return true;}catch(e){return false;}},
validate: function (v, o) {
return RED.utils.validateTypedProperty(v, "json", o);
},
expand: function () {
var that = this;
var value = this.value();
@ -219,7 +223,9 @@
value: "jsonata",
label: "expression",
icon: "red/images/typedInput/expr.svg",
validate: function(v) { try{jsonata(v);return true;}catch(e){return false;}},
validate: function (v, o) {
return RED.utils.validateTypedProperty(v, "jsonata", o);
},
expand: function () {
var that = this;
RED.editor.editExpression({
@ -1234,25 +1240,41 @@
}
},
validate: function() {
var result;
var value = this.value();
var type = this.type();
let valid = true;
const value = this.value();
const type = this.type();
if (this.typeMap[type] && this.typeMap[type].validate) {
var val = this.typeMap[type].validate;
if (typeof val === 'function') {
result = val(value);
const validate = this.typeMap[type].validate;
if (typeof validate === 'function') {
valid = validate(value, {});
} else {
result = val.test(value);
// Regex
valid = validate.test(value);
if (!valid) {
valid = RED._("validator.errors.invalid-regexp");
}
}
}
if ((typeof valid === "string") || !valid) {
this.uiSelect.addClass("input-error");
if (typeof valid === "string") {
let tooltip = this.element.data("tooltip");
if (tooltip) {
tooltip.setContent(valid);
} else {
tooltip = RED.popover.tooltip(this.elementDiv, valid);
this.element.data("tooltip", tooltip);
}
}
} else {
result = true;
this.uiSelect.removeClass("input-error");
const tooltip = this.element.data("tooltip");
if (tooltip) {
this.element.data("tooltip", null);
tooltip.delete();
}
if (result) {
this.uiSelect.removeClass('input-error');
} else {
this.uiSelect.addClass('input-error');
}
return result;
return !!valid;
},
show: function() {
this.uiSelect.show();

View File

@ -888,11 +888,25 @@ RED.utils = (function() {
return parts;
}
function validatePropertyExpression(str) {
/**
* Validate a property expression
* @param {*} str - the property value
* @returns {boolean|string} whether the node proprty is valid. `true`: valid `false|String`: invalid
*/
function validatePropertyExpression(str, opt) {
try {
var parts = normalisePropertyExpression(str);
const parts = normalisePropertyExpression(str);
return true;
} catch(err) {
// If the validator has opt, it is a 3.x validator that
// can return a String to mean 'invalid' and provide a reason
if (opt) {
if (opt.label) {
return opt.label + ': ' + err.message;
}
return err.message;
}
// Otherwise, a 2.x returns a false value
return false;
}
}
@ -906,23 +920,24 @@ RED.utils = (function() {
* @returns true if valid, String if invalid
*/
function validateTypedProperty(propertyValue, propertyType, opt) {
let error
let error;
if (propertyType === 'json') {
try {
JSON.parse(propertyValue);
} catch(err) {
error = RED._("validator.errors.invalid-json", {
error: err.message
})
});
}
} else if (propertyType === 'msg' || propertyType === 'flow' || propertyType === 'global' ) {
if (!RED.utils.validatePropertyExpression(propertyValue)) {
error = RED._("validator.errors.invalid-prop")
// To avoid double label
const valid = RED.utils.validatePropertyExpression(propertyValue, opt ? {} : undefined);
if (valid !== true) {
error = opt ? valid : RED._("validator.errors.invalid-prop");
}
} else if (propertyType === 'num') {
if (!/^NaN$|^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$|^[+-]?(0b|0B)[01]+$|^[+-]?(0o|0O)[0-7]+$|^[+-]?(0x|0X)[0-9a-fA-F]+$/.test(propertyValue)) {
error = RED._("validator.errors.invalid-num")
error = RED._("validator.errors.invalid-num");
}
} else if (propertyType === 'jsonata') {
try {
@ -930,16 +945,16 @@ RED.utils = (function() {
} catch(err) {
error = RED._("validator.errors.invalid-expr", {
error: err.message
})
});
}
}
if (error) {
if (opt && opt.label) {
return opt.label+': '+error
return opt.label + ': ' + error;
}
return error
return error;
}
return true
return true;
}
function getMessageProperty(msg,expr) {