mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Merge pull request #4747 from GogoVega/tooltip-input-validation
Add tooltip and message validation to `typedInput`
This commit is contained in:
commit
3952a23ba3
@ -367,7 +367,8 @@
|
||||
valueLabel: contextLabel,
|
||||
autoComplete: contextAutoComplete
|
||||
},
|
||||
global: {value:"global",label:"global.",hasValue:true,
|
||||
global: {
|
||||
value: "global", label: "global.", hasValue: true,
|
||||
options: [],
|
||||
validate: RED.utils.validatePropertyExpression,
|
||||
parse: contextParse,
|
||||
@ -376,15 +377,17 @@
|
||||
autoComplete: contextAutoComplete
|
||||
},
|
||||
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();
|
||||
@ -431,7 +434,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({
|
||||
@ -1538,26 +1543,48 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
validate: function() {
|
||||
var result;
|
||||
var value = this.value();
|
||||
var type = this.type();
|
||||
validate: function(options) {
|
||||
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.element.addClass("input-error");
|
||||
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.element.removeClass("input-error");
|
||||
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;
|
||||
if (options?.returnErrorMessage === true) {
|
||||
return valid;
|
||||
}
|
||||
// Must return a boolean for no 3.x validator
|
||||
return (typeof valid === "string") ? false : valid;
|
||||
},
|
||||
show: function() {
|
||||
this.uiSelect.show();
|
||||
|
@ -190,7 +190,10 @@ RED.editor = (function() {
|
||||
const input = $("#"+prefix+"-"+property);
|
||||
const isTypedInput = input.length > 0 && input.next(".red-ui-typedInput-container").length > 0;
|
||||
if (isTypedInput) {
|
||||
valid = input.typedInput("validate");
|
||||
valid = input.typedInput("validate", { returnErrorMessage: true });
|
||||
if (typeof valid === "string") {
|
||||
return label ? label + ": " + valid : valid;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -901,11 +901,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;
|
||||
}
|
||||
}
|
||||
@ -923,22 +937,24 @@ RED.utils = (function() {
|
||||
// Allow ${ENV_VAR} value
|
||||
return true
|
||||
}
|
||||
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 ? {} : null);
|
||||
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 {
|
||||
@ -946,16 +962,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) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user