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

@@ -225,28 +225,45 @@
color:"#a6bbcf",
defaults: {
name: {value:""},
props:{value:[{p:"payload"},{p:"topic",vt:"str"}], validate:function(v) {
props:{value:[{p:"payload"},{p:"topic",vt:"str"}], validate:function(v, opt) {
if (!v || v.length === 0) { return true }
for (var i=0;i<v.length;i++) {
if (/msg|flow|global/.test(v[i].vt)) {
if (!RED.utils.validatePropertyExpression(v[i].v)) {
return false;
return RED._("node-red:inject.errors.invalid-prop", { prop: v[i].p, error: v[i].v });
}
} else if (v[i].vt === "jsonata") {
try{jsonata(v[i].v);}catch(e){return false;}
try{ jsonata(v[i].v); }
catch(e){
return RED._("node-red:inject.errors.invalid-jsonata", { prop: v[i].p, error: e.message });
}
} else if (v[i].vt === "json") {
try{JSON.parse(v[i].v);}catch(e){return false;}
try{ JSON.parse(v[i].v); }
catch(e){
return RED._("node-red:inject.errors.invalid-json", { prop: v[i].p, error: e.message });
}
}
}
return true;
}
},
repeat: {value:"", validate:function(v) { return ((v === "") || (RED.validators.number(v) && (v >= 0) && (v <= 2147483))) }},
repeat: {
value:"", validate: function(v, opt) {
if ((v === "") ||
(RED.validators.number(v) &&
(v >= 0) && (v <= 2147483))) {
return true;
}
return RED._("node-red:inject.errors.invalid-repeat");
}
},
crontab: {value:""},
once: {value:false},
onceDelay: {value:0.1},
topic: {value:""},
payload: {value:"", validate: RED.validators.typedInput("payloadType")},
payload: {value:"", validate: RED.validators.typedInput("payloadType", false, {
property: "payload"
}) },
payloadType: {value:"date"},
},
icon: "inject.svg",

View File

@@ -259,7 +259,11 @@
defaults: {
name: {value:""},
links: { value: [], type:"link in[]"},
timeout: { value: "30", validate:RED.validators.number(true) }
timeout: { value: "30",
validate:RED.validators.number(true, {
property: RED._("node-red:link.timeout")
})
}
},
inputs: 1,
outputs: 1,

View File

@@ -358,24 +358,38 @@
name: {value:""},
func: {value:"\nreturn msg;"},
outputs: {value:1},
noerr: {value:0,required:true,validate:function(v) { return !v; }},
noerr: {value:0,required:true,
validate: function(v, opt) {
if (!v) {
return true;
}
return RED._("node-red:function.error.invalid-js");
}},
initialize: {value:""},
finalize: {value:""},
libs: {value: [], validate: function(v) {
libs: {value: [], validate: function(v, opt) {
if (!v) { return true; }
for (var i=0,l=v.length;i<l;i++) {
var m = v[i];
if (!RED.utils.checkModuleAllowed(m.module,null,installAllowList,installDenyList)) {
return false
return RED._("node-red:function.error.moduleNotAllowed", {
module: m.module
});
}
if (m.var === "" || / /.test(m.var)) {
return false;
return RED._("node-red:function.error.moduleNameError", {
name: m.var
});
}
if (missingModules.indexOf(m.module) > -1) {
return false;
return RED._("node-red:function.error.missing-module", {
module: m.module
});
}
if (invalidModuleVNames.indexOf(m.var) !== -1){
return false;
return RED._("node-red:function.error.moduleNameError", {
name: m.var
});
}
}
return true;

View File

@@ -163,7 +163,11 @@
category: 'function',
defaults: {
name: {value:""},
property: {value:"payload", required:true, validate: RED.validators.typedInput("propertyType")},
property: {value:"payload", required:true,
label:RED._("node-red:common.label.payload"),
validate: RED.validators.typedInput("propertyType", false, {
property: RED._("node-red:common.label.payload")
})},
propertyType: { value:"msg" },
rules: {value:[{t:"eq", v:"", vt:"str"}]},
checkall: {value:"true", required:true},

View File

@@ -19,38 +19,66 @@
<script type="text/javascript">
(function() {
function validateProperty(v,vt) {
function isInvalidProperty(v,vt) {
if (/msg|flow|global/.test(vt)) {
if (!RED.utils.validatePropertyExpression(v)) {
return false;
return RED._("node-red:change.errors.invalid-prop", {
property: v
});
}
} else if (vt === "jsonata") {
try{jsonata(v);}catch(e){return false;}
try{ jsonata(v); } catch(e) {
return RED._("node-red:change.errors.invalid-expr", {
error: e.message
});
}
} else if (vt === "json") {
try{JSON.parse(v);}catch(e){return false;}
try{ JSON.parse(v); } catch(e) {
return RED._("node-red:change.errors.invalid-json-data", {
error: e.message
});
}
}
return true;
return false;
}
RED.nodes.registerType('change', {
color: "#E2D96E",
category: 'function',
defaults: {
name: {value:""},
rules:{value:[{t:"set",p:"payload",pt:"msg",to:"",tot:"str"}],validate: function(rules) {
rules:{value:[{t:"set",p:"payload",pt:"msg",to:"",tot:"str"}],validate: function(rules, opt) {
var msg;
if (!rules || rules.length === 0) { return true }
for (var i=0;i<rules.length;i++) {
var r = rules[i];
if (r.t === 'set') {
if (!validateProperty(r.p,r.pt) || !validateProperty(r.to,r.tot)) {
return false;
if (msg = isInvalidProperty(r.p,r.pt)) {
return msg;
}
if (msg = isInvalidProperty(r.to,r.tot)) {
return msg;
}
} else if (r.t === 'change') {
if (!validateProperty(r.p,r.pt) || !validateProperty(r.from,r.fromt) || !validateProperty(r.to,r.tot)) {
return false;
if (msg = isInvalidProperty(r.p,r.pt)) {
return msg;
}
if(msg = isInvalidProperty(r.from,r.fromt)) {
return msg;
}
if(msg = isInvalidProperty(r.to,r.tot)) {
return msg;
}
} else if (r.t === 'delete') {
if (msg = isInvalidProperty(r.p,r.pt)) {
return msg;
}
} else if (r.t === 'move') {
if (!validateProperty(r.p,r.pt)) {
return false;
if (msg = isInvalidProperty(r.p,r.pt)) {
return msg;
}
if (msg = isInvalidProperty(r.to,r.tot)) {
return msg;
}
}
}

View File

@@ -41,13 +41,30 @@
color: "#E2D96E",
category: 'function',
defaults: {
minin: {value:"",required:true,validate:RED.validators.number()},
maxin: {value:"",required:true,validate:RED.validators.number()},
minout: {value:"",required:true,validate:RED.validators.number()},
maxout: {value:"",required:true,validate:RED.validators.number()},
minin: {value:"", required: true,
label:RED._("node-red:range.label.minin"),
validate:RED.validators.number(false, {
property: RED._("node-red:range.label.minin")
})},
maxin: {value:"", required: true,
label:RED._("node-red:range.label.maxin"),
validate:RED.validators.number(false, {
property: RED._("node-red:range.label.maxin")
})},
minout: {value:"", required:true,
label:RED._("node-red:range.label.minout"),
validate:RED.validators.number(false, {
property: RED._("node-red:range.label.minout")
})},
maxout: {value:"", required:true,
label:RED._("node-red:range.label.maxout"),
validate:RED.validators.number(false, {
property: RED._("node-red:range.label.maxout")
})},
action: {value:"scale"},
round: {value:false},
property: {value:"payload",required:true},
property: {value:"payload",required:true,
label:RED._("node-red:common.label.property")},
name: {value:""}
},
inputs: 1,

View File

@@ -56,7 +56,10 @@
category: 'function',
defaults: {
name: {value:""},
field: {value:"payload", validate:RED.validators.typedInput("fieldType")},
field: {value:"payload",
validate:RED.validators.typedInput("fieldType", false, {
property: "payload"
})},
fieldType: {value:"msg"},
format: {value:"handlebars"},
syntax: {value:"mustache"},

View File

@@ -111,14 +111,52 @@
defaults: {
name: {value:""},
pauseType: {value:"delay", required:true},
timeout: {value:"5", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
timeout: {
value:"5", required:true,
label:RED._("node-red:delay.label.delay"),
validate:function(v,opt) {
if (RED.validators.number(v) && (v >= 0)) {
return true;
}
return RED._("node-red:delay.errors.invalid-timeout");
}},
timeoutUnits: {value:"seconds"},
rate: {value:"1", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
nbRateUnits: {value:"1", required:false,
validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
rate: {
value:"1", required:true,
label:RED._("node-red:delay.label.rate"),
validate:function(v,opt) {
if (RED.validators.number(v) && (v >= 0)) {
return true;
}
return RED._("node-red:delay.errors.invalid-rate");
}},
nbRateUnits: {
value:"1", required:false,
validate:function(v,opt) {
if (RED.validators.number(v) && (v >= 0)) {
return true;
}
return RED._("node-red:delay.errors.invalid-rate-unit");
}},
rateUnits: {value: "second"},
randomFirst: {value:"1", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
randomLast: {value:"5", required:true, validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
randomFirst: {
value:"1", required:true,
label:RED._("node-red:delay.label.random-first"),
validate:function(v,opt) {
if (RED.validators.number(v) && (v >= 0)) {
return true;
}
return RED._("node-red:delay.errors.invalid-random-first");
}},
randomLast: {
value:"5", required:true,
label:RED._("node-red:delay.label.random-last"),
validate:function(v,opt) {
if (RED.validators.number(v) && (v >= 0)) {
return true;
}
return RED._("node-red:delay.errors.invalid-random-last");
}},
randomUnits: {value: "seconds"},
drop: {value:false},
allowrate: {value:false},

View File

@@ -87,17 +87,29 @@
color:"#E6E0F8",
defaults: {
name: {value:""},
op1: {value:"1", validate: RED.validators.typedInput("op1type")},
op2: {value:"0", validate: RED.validators.typedInput("op2type")},
op1: {value:"1",
validate: RED.validators.typedInput("op1type", false, {
property: RED._("node-red:trigger.send")
})},
op2: {value:"0",
validate: RED.validators.typedInput("op2type", false, {
property: RED._("node-red:trigger.then-send")
})},
op1type: {value:"val"},
op2type: {value:"val"},
duration: {value:"250",required:true,validate:RED.validators.number()},
duration: {
value:"250", required:true,
label:RED._("node-red:trigger.label.duration"),
validate:RED.validators.number(false, {
property: RED._("node-red:trigger.label.duration")
})},
extend: {value:"false"},
overrideDelay: {value:"false"},
units: {value:"ms"},
reset: {value:""},
bytopic: {value:"all"},
topic: {value:"topic",required:true},
topic: {value:"topic", required:true,
label:RED._("node-red:trigger.label.topic")},
outputs: {value:1}
},
inputs:1,

View File

@@ -49,12 +49,17 @@
defaults: {
name: {value:""},
func: {value:"rbe"},
gap: {value:"",validate:RED.validators.regex(/^(\d*[.]*\d*|)(%|)$/)},
gap: {value:"",
validate:RED.validators.regex(/^(\d*[.]*\d*|)(%|)$/, {
property: RED._("node-red:rbe.label.gap")
})},
start: {value:""},
inout: {value:"out"},
septopics: {value:true},
property: {value:"payload",required:true},
topi: {value:"topic",required:true}
property: {value:"payload", required:true,
label:RED._("node-red:rbe.label.property")},
topi: {value:"topic", required:true,
label:RED._("node-red:rbe.label.topic")}
},
inputs:1,
outputs:1,

View File

@@ -83,19 +83,25 @@
category: 'config',
defaults: {
name: {value:""},
cert: {value:"", validate: function(v) {
cert: {value:"", validate: function(v,opt) {
var currentKey = $("#node-config-input-key").val();
if (currentKey === undefined) {
currentKey = this.key;
}
return currentKey === '' || v != '';
if (currentKey === '' || v != '') {
return true;
}
return RED._("node-red:tls.error.invalid-cert");
}},
key: {value:"", validate: function(v) {
key: {value:"", validate: function(v,opt) {
var currentCert = $("#node-config-input-cert").val();
if (currentCert === undefined) {
currentCert = this.cert;
}
return currentCert === '' || v != '';
if (currentCert === '' || v != '') {
return true;
}
return RED._("node-red:tls.error.invalid-key");
}},
ca: {value:""},
certname: {value:""},

View File

@@ -50,7 +50,16 @@
category: 'config',
defaults: {
name: {value:''},
url: {value:'',validate:function(v) { return (v && (v.indexOf('://') !== -1) && (v.trim().indexOf('http') === 0)); }},
url: {
value:'',
validate:function(v, opt) {
if ((v && (v.indexOf('://') !== -1) &&
(v.trim().indexOf('http') === 0))) {
return true;
}
return RED._("node-red:httpin.errors.invalid-url");
}
},
noproxy: {value:[]}
},
credentials: {

View File

@@ -448,22 +448,36 @@
defaults: {
name: {value:""},
broker: {value:"",required:true},
port: {value:1883,required:false,validate:RED.validators.number(true)},
tls: {type:"tls-config",required: false},
clientid: {value:"", validate: function(v) {
port: {
value:1883,required:false,
validate:RED.validators.number(true, {
property: RED._("node-red:mqtt.label.port")
})},
tls: {type:"tls-config",required: false,
label:RED._("node-red:mqtt.label.use-tls") },
clientid: {value:"", validate: function(v, opt) {
var ok = false;
if ($("#node-config-input-clientid").length) {
// Currently editing the node
return $("#node-config-input-cleansession").is(":checked") || (v||"").length > 0;
ok = $("#node-config-input-cleansession").is(":checked") || (v||"").length > 0;
} else {
return (this.cleansession===undefined || this.cleansession) || (v||"").length > 0;
ok = (this.cleansession===undefined || this.cleansession) || (v||"").length > 0;
}
if (ok) {
return ok;
}
return RED._("node-red:mqtt.errors.invalid-client-id");
}},
autoConnect: {value: true},
usetls: {value: false},
verifyservercert: { value: false},
compatmode: { value: false},
protocolVersion: { value: 4},
keepalive: {value:60,validate:RED.validators.number()},
keepalive: {
value:60,
validate:RED.validators.number(false, {
property: RED._("node-red:mqtt.label.keepalive")
})},
cleansession: {value: true},
birthTopic: {value:""},
birthQos: {value:"0"},
@@ -740,18 +754,22 @@
name: {value:""},
topic: {
value:"",
validate: function(v) {
validate: function(v, opt) {
var isDynamic = this.inputs === 1;
var topicTypeSelect = $("#node-input-topicType");
if (topicTypeSelect.length) {
isDynamic = topicTypeSelect.val()==='dynamic'
}
return isDynamic || ((!!v) && RED.validators.regex(/^(#$|(\+|[^+#]*)(\/(\+|[^+#]*))*(\/(\+|#|[^+#]*))?$)/)(v));
if (isDynamic || ((!!v) && RED.validators.regex(/^(#$|(\+|[^+#]*)(\/(\+|[^+#]*))*(\/(\+|#|[^+#]*))?$)/)(v))) {
return true;
}
return RED._("node-red:mqtt.errors.invalid-topic");
}
},
qos: {value: "2"},
datatype: {value:"auto",required:true},
broker: {type:"mqtt-broker", required:true},
broker: {type:"mqtt-broker", required:true,
label:RED._("node-red:mqtt.label.broker")},
// subscriptionIdentifier: {value:0},
nl: {value:false},
rap: {value:true},
@@ -829,7 +847,8 @@
userProps: {value:''},
correl: {value:''},
expiry: {value:''},
broker: {type:"mqtt-broker", required:true}
broker: {type:"mqtt-broker", required:true,
label:RED._("node-red:mqtt.label.broker") }
},
color:"#d8bfd8",
inputs:1,

View File

@@ -70,7 +70,8 @@
color:"rgb(231, 231, 174)",
defaults: {
name: {value:""},
url: {value:"",required:true},
url: {value:"", required:true,
label:RED._("node-red:httpin.label.url")},
method: {value:"get",required:true},
upload: {value:false},
swaggerDoc: {type:"swagger-doc", required:false}
@@ -146,7 +147,11 @@
color:"rgb(231, 231, 174)",
defaults: {
name: {value:""},
statusCode: {value:"",validate: RED.validators.number(true)},
statusCode: {
value:"",
validate: RED.validators.number(true,{
property: RED._("node-red:httpin.label.status")
})},
headers: {value:{}}
},
inputs:1,

View File

@@ -116,10 +116,22 @@
method:{value:"GET"},
ret: {value:"txt"},
paytoqs: {value: false},
url:{value:"",validate:function(v) { return (v.trim().length === 0) || (v.indexOf("://") === -1) || (v.trim().indexOf("http") === 0)} },
tls: {type:"tls-config",required: false},
url:{
value:"",
validate: function(v, opt) {
if ((v.trim().length === 0) ||
(v.indexOf("://") === -1) ||
(v.trim().indexOf("http") === 0)) {
return true;
}
return RED._("node-red:httpin.errors.invalid-url");
}
},
tls: {type:"tls-config",required: false,
label:RED._("node-red:httpin.tls-config") },
persist: {value:false},
proxy: {type:"http proxy",required: false},
proxy: {type:"http proxy",required: false,
label:RED._("node-red:httpin.proxy-config") },
authType: {value: ""},
senderr: {value: false}
},

View File

@@ -83,13 +83,19 @@
return true;
}
else {
return RED.nodes.node(this.server) != null;
if (RED.nodes.node(this.server) != null) {
return true;
}
return RED._("node-red:websocket.errors.missing-server");
}
}
function ws_validateclient() {
if ($("#node-input-mode").val() === 'client' || (this.client && !this.server)) {
return RED.nodes.node(this.client) != null;
if (RED.nodes.node(this.client) != null) {
return true;
}
return RED._("node-red:websocket.errors.missing-client");
}
else {
return true;
@@ -138,7 +144,10 @@
RED.nodes.registerType('websocket-listener',{
category: 'config',
defaults: {
path: {value:"",required:true,validate:RED.validators.regex(/^((?!\/debug\/ws).)*$/)},
path: {value:"",required:true,
validate:RED.validators.regex(/^((?!\/debug\/ws).)*$/, {
property:RED._("node-red:websocket.label.path")
})},
wholemsg: {value:"false"}
},
inputs:0,
@@ -174,10 +183,18 @@
RED.nodes.registerType('websocket-client',{
category: 'config',
defaults: {
path: {value:"",required:true,validate:RED.validators.regex(/^((?!\/debug\/ws).)*$/)},
path: {
value:"",required:true,
validate:RED.validators.regex(/^((?!\/debug\/ws).)*$/, {
property:RED._("node-red:websocket.label.path")
})},
tls: {type:"tls-config",required: false},
wholemsg: {value:"false"},
hb: {value: "", validate: RED.validators.number(/*blank allowed*/true) },
hb: {
value: "",
validate: RED.validators.number(/*blank allowed*/true, {
property:RED._("node-red:websocket.sendheartbeat")
}) },
subprotocol: {value:"",required: false}
},
inputs:0,

View File

@@ -70,14 +70,28 @@
defaults: {
name: {value:""},
server: {value:"server", required:true},
host: {value:"", validate:function(v) { return (this.server == "server")||v.length > 0;} },
port: {value:"", required:true, validate:RED.validators.number()},
host: {
value:"",
validate:function(v, opt) {
if ((this.server == "server")||v.length > 0) {
return true;
}
return RED._("node-red:tcpin.errors.invalid-host");
}
},
port: {
value:"", required:true,
label:RED._("node-red:tcpin.label.port"),
validate:RED.validators.number(false, {
property: RED._("node-red:tcpin.label.port")
})},
datamode:{value:"stream"},
datatype:{value:"buffer"},
newline:{value:""},
topic: {value:""},
base64: {/*deprecated*/ value:false, required:true},
tls: {type:"tls-config", value:'', required:false}
tls: {type:"tls-config", value:'', required:false,
label:RED._("node-red:httpin.tls-config") }
},
inputs:0,
outputs:1,
@@ -186,12 +200,29 @@
color: "Silver",
defaults: {
name: {value:""},
host: {value:"",validate:function(v) { return (this.beserver != "client")||v.length > 0;} },
port: {value:"",validate:function(v) { return (this.beserver == "reply")||RED.validators.number()(v); } },
host: {
value:"",
validate:function(v, opt) {
if ((this.beserver != "client")||v.length > 0) {
return true;
}
return RED._("node-red:tcpin.errors.invalid-host");
}
},
port: {
value:"",
validate:function(v) {
if ((this.beserver == "reply")||RED.validators.number()(v)) {
return true;
}
return RED._("node-red:tcpin.errors.invalid-port");
}
},
beserver: {value:"client", required:true},
base64: {value:false, required:true},
end: {value:false, required:true},
tls: {type:"tls-config", value:'', required:false}
tls: {type:"tls-config", value:'', required:false,
label:RED._("node-red:httpin.tls-config") }
},
inputs:1,
outputs:0,
@@ -301,12 +332,18 @@
defaults: {
name: {value:""},
server: {value:""},
port: {value:"", validate:RED.validators.regex(/^(\d*|)$/)},
port: {
value:"",
validate:RED.validators.regex(/^(\d*|)$/, {
property: RED._("node-red:tcpin.label.port")
})
},
out: {value:"time", required:true},
ret: {value:"buffer"},
splitc: {value:"0", required:true},
newline: {value:""},
tls: {type:"tls-config", value:'', required:false}
tls: {type:"tls-config", value:'', required:false,
label:RED._("node-red:httpin.tls-config") }
},
inputs:1,
outputs:1,

View File

@@ -62,10 +62,24 @@
defaults: {
name: {value:""},
iface: {value:""},
port: {value:"",required:true,validate:RED.validators.number()},
port: {
value:"", required:true,
label:RED._("node-red:udp.label.port"),
validate:RED.validators.number(false, {
property: RED._("node-red:udp.label.port")
})
},
ipv: {value:"udp4"},
multicast: {value:"false"},
group: {value:"",validate:function(v) { return (this.multicast !== "true")||v.length > 0;} },
group: {
value:"",
validate:function(v,opt) {
if ((this.multicast !== "true")||v.length > 0) {
return true;
}
return RED._("node-red:udp.errors.invalid-group");
}
},
datatype: {value:"buffer",required:true}
},
inputs:0,

View File

@@ -75,7 +75,12 @@
color:"#DEBD5C",
defaults: {
name: {value:""},
sep: {value:',',required:true,validate:RED.validators.regex(/^.{1,2}$/)},
sep: {
value:',', required:true,
label:RED._("node-red:csv.label.separator"),
validate:RED.validators.regex(/^.{1,2}$/, {
property: RED._("node-red:csv.label.separator")
})},
//quo: {value:'"',required:true},
hdrin: {value:""},
hdrout: {value:"none"},

View File

@@ -31,7 +31,8 @@
color:"#DEBD5C",
defaults: {
name: {value:""},
property: {value:"payload",required:true},
property: {value:"payload",required:true,
label:RED._("node-red:json.label.property")},
action: {value:""},
pretty: {value:false}
},

View File

@@ -26,7 +26,8 @@
color:"#DEBD5C",
defaults: {
name: {value:""},
property: {value:"payload",required:true},
property: {value:"payload",required:true,
label:RED._("node-red:common.label.property")},
attr: {value:""},
chr: {value:""}
},

View File

@@ -15,7 +15,8 @@
category: 'parser',
color:"#DEBD5C",
defaults: {
property: {value:"payload",required:true},
property: {value:"payload",required:true,
label:RED._("node-red:common.label.property")},
name: {value:""}
},
inputs:1,

View File

@@ -202,7 +202,12 @@
name: {value:""},
mode: {value:"auto"},
build: { value:"object"},
property: { value:"payload", validate:RED.validators.typedInput("propertyType")},
property: {
value:"payload",
validate:RED.validators.typedInput("propertyType", false, {
property: RED._("node-red:join.message-prop")
})
},
propertyType: { value:"msg"},
key: {value:"topic"},
joiner: { value:"\\n"},

View File

@@ -73,9 +73,33 @@
defaults: {
name: {value:""},
mode: {value:"count"},
count: {value:10,validate:function(v) { return RED.validators.number(v) && (v >= 1); }},
overlap: {value:0,validate:function(v) { return RED.validators.number(v) && (v >= 0); }},
interval: {value:10,validate:function(v) { return RED.validators.number(v) && (v >= 1); }},
count: {
value:10,
validate:function(v, opt) {
if (RED.validators.number(v) && (v >= 1)) {
return true;
}
return RED._("node-red:batch.error.invalid-count");
}
},
overlap: {
value:0,
validate:function(v, opt) {
if (RED.validators.number(v) && (v >= 0)) {
return true;
}
return RED._("node-red:batch.error.invalid-overlap");
}
},
interval: {
value:10,
validate:function(v, opt) {
if (RED.validators.number(v) && (v >= 1)) {
return true;
}
return RED._("node-red:batch.error.invalid-interval");
}
},
allowEmptySequence: {value:false},
topics: {value:[{topic:""}]}
},

View File

@@ -36,7 +36,8 @@
category: 'storage',
defaults: {
name: {value:""},
files: {value:"",required:true},
files: {value:"",required:true,
label:RED._("node-red:watch.label.files")},
recursive: {value:""}
},
color:"BurlyWood",