add support of property validation message

This commit is contained in:
Hiroyasu Nishiyama
2022-02-14 10:40:49 +09:00
parent 5293563a6a
commit 9f98b4b082
32 changed files with 672 additions and 141 deletions

View File

@@ -1156,5 +1156,21 @@
"ru": "Russian",
"zh-CN": "Chinese(Simplified)",
"zh-TW": "Chinese(Traditional)"
},
"validator": {
"errors": {
"invalid-json": "Invalid JSON data: __error__",
"invalid-json-prop": "__prop__: invalid JSON data: __error__",
"invalid-prop": "Invalid property expression",
"invalid-prop-prop": "__prop__: invalid property expression",
"invalid-num": "Invalid number",
"invalid-num-prop": "__prop__: invalid number",
"invalid-regexp": "Invalid input pattern",
"invalid-regex-prop": "__prop__: invalid input pattern",
"missing-required-prop": "__prop__: property value missing",
"invalid-config": "__prop__: invalid configuration node",
"missing-config": "__prop__: missing configuration node",
"validation-error": "__prop__: validation error: __node__, __id__: __error__"
}
}
}

View File

@@ -1288,5 +1288,21 @@
"zoom-out": "ズームアウト",
"zoom-reset": "ズームリセット",
"toggle-navigator": "ナビゲータ表示切替"
},
"validator": {
"errors": {
"invalid-json": "JSONデータが不正: __error__",
"invalid-json-prop": "__prop__: JSONデータが不正: __error__",
"invalid-prop": "プロパティ式が不正",
"invalid-prop-prop": "__prop__: プロパティ式が不正",
"invalid-num": "数値が不正",
"invalid-num-prop": "__prop__: 数値が不正",
"invalid-regexp": "入力パターンが不正",
"invalid-regex-prop": "__prop__: 入力パターンが不正",
"missing-required-prop": "__prop__: プロパティが未設定",
"invalid-config": "__prop__: 設定ノードが不正",
"missing-config": "__prop__: 設定ノードが存在しません",
"validation-error": "__prop__: チェックエラー: __node__, __id__: __error__"
}
}
}

View File

@@ -349,7 +349,6 @@ RED.popover = (function() {
}
}
}
if (trigger === 'hover') {
target.on('mouseenter',function(e) {
clearTimeout(timer);
@@ -461,6 +460,10 @@ RED.popover = (function() {
popover.setAction = function(newAction) {
action = newAction;
}
popover.delete = function() {
target.off("mouseenter");
target.off("mouseleave");
};
return popover;
},

View File

@@ -110,7 +110,11 @@ RED.editor = (function() {
var result = [];
for (var prop in definition) {
if (definition.hasOwnProperty(prop)) {
if (!validateNodeProperty(node, definition, prop, properties[prop])) {
var valid = validateNodeProperty(node, definition, prop, properties[prop]);
if ((typeof valid) === "string") {
result.push(valid);
}
else if(!valid) {
result.push(prop);
}
}
@@ -136,22 +140,64 @@ RED.editor = (function() {
if (/^\$\{[a-zA-Z_][a-zA-Z0-9_]*\}$/.test(value)) {
return true;
}
var label = null;
if (("label" in definition[property]) &&
((typeof definition[property].label) == "string")) {
label = definition[property].label;
}
if ("required" in definition[property] && definition[property].required) {
valid = value !== "";
if (!valid && label) {
return RED._("validator.errors.missing-required-prop", {
prop: label
});
}
}
if (valid && "validate" in definition[property]) {
try {
valid = definition[property].validate.call(node,value);
var opt = {};
valid = definition[property].validate.call(node,value, opt);
if ((typeof valid) === "string") {
return valid;
}
} catch(err) {
console.log("Validation error:",node.type,node.id,"property: "+property,"value:",value,err);
return RED._("validator.errors.validation-error", {
prop: property,
node: node.type,
id: node.id,
error: err.message
});
}
}
if (valid && definition[property].type && RED.nodes.getType(definition[property].type) && !("validate" in definition[property])) {
if (!value || value == "_ADD_") {
valid = definition[property].hasOwnProperty("required") && !definition[property].required;
if (!valid && label) {
return RED._("validator.errors.missing-required-prop", {
prop: label
});
}
} else {
var configNode = RED.nodes.node(value);
valid = (configNode && (configNode.valid == null || configNode.valid));
if (configNode) {
if ((configNode.valid == null) || configNode.valid) {
return true;
}
if (label) {
return RED._("validator.errors.invalid-config", {
prop: label
});
}
}
else {
if (label) {
return RED._("validator.errors.missing-config", {
prop: label
});
}
}
return false;
}
}
return valid;
@@ -179,10 +225,26 @@ RED.editor = (function() {
if (defaults[property].hasOwnProperty("format") && defaults[property].format !== "" && input[0].nodeName === "DIV") {
value = input.text();
}
if (!validateNodeProperty(node, defaults, property,value)) {
var valid = validateNodeProperty(node, defaults, property,value);
if (((typeof valid) === "string") || !valid) {
input.addClass("input-error");
if ((typeof valid) === "string") {
var tooltip = input.data("tooltip");
if (tooltip) {
tooltip.setContent(valid);
}
else {
tooltip = RED.popover.tooltip(input, valid);
input.data("tooltip", tooltip);
}
}
} else {
input.removeClass("input-error");
var tooltip = input.data("tooltip");
if (tooltip) {
input.data("tooltip", null);
tooltip.delete();
}
}
}
}

View File

@@ -14,22 +14,72 @@
* limitations under the License.
**/
RED.validators = {
number: function(blankAllowed){return function(v) { return (blankAllowed&&(v===''||v===undefined)) || (v!=='' && !isNaN(v));}},
regex: function(re){return function(v) { return re.test(v);}},
typedInput: function(ptypeName,isConfig) { return function(v) {
var ptype = $("#node-"+(isConfig?"config-":"")+"input-"+ptypeName).val() || this[ptypeName];
if (ptype === 'json') {
try {
JSON.parse(v);
number: function(blankAllowed,mopt){
return function(v, opt) {
if ((blankAllowed&&(v===''||v===undefined)) || (v!=='' && !isNaN(v))) {
return true;
} catch(err) {
return false;
}
} else if (ptype === 'msg' || ptype === 'flow' || ptype === 'global' ) {
return RED.utils.validatePropertyExpression(v);
} else if (ptype === 'num') {
return /^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/.test(v);
}
return true;
}}
if (mopt && mopt.property) {
return opt ? RED._("validator.errors.invalid-num-prop", {
prop: mopt.property
}) : false;
}
return opt ? RED._("validator.errors.invalid-num") : false;
};
},
regex: function(re, mopt) {
return function(v, opt) {
if (re.test(v)) {
return true;
}
if (mopt && mopt.property) {
return opt ? RED._("validator.errors.invalid-regex-prop", {
prop: mopt.property
}) : false;
}
return opt ? RED._("validator.errors.invalid-regexp") : false;
};
},
typedInput: function(ptypeName,isConfig,mopt) {
return function(v, opt) {
var ptype = $("#node-"+(isConfig?"config-":"")+"input-"+ptypeName).val() || this[ptypeName];
if (ptype === 'json') {
try {
JSON.parse(v);
return true;
} catch(err) {
if (mopt && mopt.property) {
return opt ? RED._("validator.errors.invalid-json-prop", {
error: err.message,
prop: mopt.property,
}) : false;
}
return opt ? RED._("validator.errors.invalid-json", {
error: err.message
}) : false;
}
} else if (ptype === 'msg' || ptype === 'flow' || ptype === 'global' ) {
if (RED.utils.validatePropertyExpression(v)) {
return true;
}
if (mopt && mopt.property) {
return opt ? RED._("validator.errors.invalid-prop-prop", {
prop: mopt.property
}) : false;
}
return opt ? RED._("validator.errors.invalid-prop") : false;
} else if (ptype === 'num') {
if (/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/.test(v)) {
return true;
}
if (mopt && mopt.property) {
return opt ? RED._("validator.errors.invalid-num-prop", {
prop: mopt.property
}) : false;
}
return opt ? RED._("validator.errors.invalid-num") : false;
}
return true;
};
}
};