Merge branch 'master' into dev

This commit is contained in:
Nick O'Leary
2023-12-04 15:58:45 +00:00
89 changed files with 903 additions and 670 deletions

View File

@@ -320,7 +320,7 @@
}
// but replace with repeat one if set to repeat
if ((this.repeat && this.repeat != 0) || this.crontab) {
suffix = " ↻";
suffix = "\t↻";
}
if (this.name) {
return this.name+suffix;

View File

@@ -109,9 +109,8 @@ module.exports = function(RED) {
}
const p = props.shift()
const property = p.p;
const value = p.v ? p.v : '';
const valueType = p.vt ? p.vt : 'str';
const value = p.v !== undefined ? p.v : '';
const valueType = p.vt !== undefined ? p.vt : 'str';
if (property) {
if (valueType === "jsonata") {
if (p.v) {

View File

@@ -86,7 +86,7 @@
},
label: function() {
var suffix = "";
if (this.console === true || this.console === "true") { suffix = " ⇲"; }
if (this.console === true || this.console === "true") { suffix = "\t⇲"; }
if (this.targetType === "jsonata") {
return (this.name || "JSONata") + suffix;
}
@@ -195,6 +195,119 @@
node.dirty = true;
});
RED.view.redraw();
},
requestDebugNodeList: function(filteredNodes) {
var workspaceOrder = RED.nodes.getWorkspaceOrder();
var workspaceOrderMap = {};
workspaceOrder.forEach(function(ws,i) {
workspaceOrderMap[ws] = i;
});
var candidateNodes = [];
var candidateSFs = [];
var subflows = {};
RED.nodes.eachNode(function (n) {
var nt = n.type;
if (nt === "debug") {
if (n.z in workspaceOrderMap) {
candidateNodes.push(n);
}
else {
var sf = RED.nodes.subflow(n.z);
if (sf) {
subflows[sf.id] = {
debug: true,
subflows: {}
};
}
}
}
else if(nt.substring(0, 8) === "subflow:") {
if (n.z in workspaceOrderMap) {
candidateSFs.push(n);
}
else {
var psf = RED.nodes.subflow(n.z);
if (psf) {
var sid = nt.substring(8);
var item = subflows[psf.id];
if (!item) {
item = {
debug: undefined,
subflows: {}
};
subflows[psf.id] = item;
}
item.subflows[sid] = true;
}
}
}
});
candidateSFs.forEach(function (sf) {
var sid = sf.type.substring(8);
if (containsDebug(sid, subflows)) {
candidateNodes.push(sf);
}
});
candidateNodes.sort(function(A,B) {
var wsA = workspaceOrderMap[A.z];
var wsB = workspaceOrderMap[B.z];
if (wsA !== wsB) {
return wsA-wsB;
}
var labelA = RED.utils.getNodeLabel(A,A.id);
var labelB = RED.utils.getNodeLabel(B,B.id);
return labelA.localeCompare(labelB);
});
var currentWs = null;
var data = [];
var currentFlow;
var currentSelectedCount = 0;
candidateNodes.forEach(function(node) {
if (currentWs !== node.z) {
if (currentFlow && currentFlow.checkbox) {
currentFlow.selected = currentSelectedCount === currentFlow.children.length
}
currentSelectedCount = 0;
currentWs = node.z;
var parent = RED.nodes.workspace(currentWs) || RED.nodes.subflow(currentWs);
currentFlow = {
label: RED.utils.getNodeLabel(parent, currentWs),
}
if (!parent.disabled) {
currentFlow.children = [];
currentFlow.checkbox = true;
} else {
currentFlow.class = "disabled"
}
data.push(currentFlow);
}
if (currentFlow.children) {
if (!filteredNodes[node.id]) {
currentSelectedCount++;
}
currentFlow.children.push({
label: RED.utils.getNodeLabel(node,node.id),
node: {
id: node.id
},
checkbox: true,
selected: !filteredNodes[node.id]
});
}
});
if (currentFlow && currentFlow.checkbox) {
currentFlow.selected = currentSelectedCount === currentFlow.children.length
}
if (subWindow) {
try {
subWindow.postMessage({event:"refreshDebugNodeList", nodes:data},"*");
} catch(err) {
console.log(err);
}
}
RED.debug.refreshDebugNodeList(data)
}
};
@@ -396,6 +509,26 @@
}
}
function containsDebug(sid, map) {
var item = map[sid];
if (item) {
if (item.debug === undefined) {
var sfs = Object.keys(item.subflows);
var contain = false;
for (var i = 0; i < sfs.length; i++) {
var sf = sfs[i];
if (containsDebug(sf, map)) {
contain = true;
break;
}
}
item.debug = contain;
}
return item.debug;
}
return false;
}
$("#red-ui-sidebar-debug-open").on("click", function(e) {
e.preventDefault();
subWindow = window.open(document.location.toString().replace(/[?#].*$/,"")+"debug/view/view.html"+document.location.search,"nodeREDDebugView","menubar=no,location=no,toolbar=no,chrome,height=500,width=600");
@@ -427,6 +560,8 @@
options.messageSourceClick(msg.id,msg._alias,msg.path);
} else if (msg.event === "clear") {
options.clear();
} else if (msg.event === "requestDebugNodeList") {
options.requestDebugNodeList(msg.filteredNodes)
}
};
window.addEventListener('message',this.handleWindowMessage);

View File

@@ -275,7 +275,7 @@
value: [],
type: "link in[]",
validate: function (v, opt) {
if ((this.linkType === "static" && v.length > 0)
if (((this.linkType || "static") === "static" && v.length > 0)
|| this.linkType === "dynamic") {
return true;
}

View File

@@ -167,19 +167,13 @@ RED.debug = (function() {
var menu = RED.popover.menu({
options: options,
onselect: function(item) {
if (item.value !== filterType) {
filterType = item.value;
$('#red-ui-sidebar-debug-filter span').text(RED._('node-red:debug.sidebar.'+filterType));
refreshMessageList();
RED.settings.set("debug.filter",filterType)
}
setFilterType(item.value)
if (filterType === 'filterSelected') {
refreshDebugNodeList();
config.requestDebugNodeList(filteredNodes);
filterDialog.slideDown(200);
filterDialogShown = true;
debugNodeTreeList.focus();
}
}
});
menu.show({
@@ -254,131 +248,7 @@ RED.debug = (function() {
}
function containsDebug(sid, map) {
var item = map[sid];
if (item) {
if (item.debug === undefined) {
var sfs = Object.keys(item.subflows);
var contain = false;
for (var i = 0; i < sfs.length; i++) {
var sf = sfs[i];
if (containsDebug(sf, map)) {
contain = true;
break;
}
}
item.debug = contain;
}
return item.debug;
}
return false;
}
function refreshDebugNodeList() {
var workspaceOrder = RED.nodes.getWorkspaceOrder();
var workspaceOrderMap = {};
workspaceOrder.forEach(function(ws,i) {
workspaceOrderMap[ws] = i;
});
var candidateNodes = [];
var candidateSFs = [];
var subflows = {};
RED.nodes.eachNode(function (n) {
var nt = n.type;
if (nt === "debug") {
if (n.z in workspaceOrderMap) {
candidateNodes.push(n);
}
else {
var sf = RED.nodes.subflow(n.z);
if (sf) {
subflows[sf.id] = {
debug: true,
subflows: {}
};
}
}
}
else if(nt.substring(0, 8) === "subflow:") {
if (n.z in workspaceOrderMap) {
candidateSFs.push(n);
}
else {
var psf = RED.nodes.subflow(n.z);
if (psf) {
var sid = nt.substring(8);
var item = subflows[psf.id];
if (!item) {
item = {
debug: undefined,
subflows: {}
};
subflows[psf.id] = item;
}
item.subflows[sid] = true;
}
}
}
});
candidateSFs.forEach(function (sf) {
var sid = sf.type.substring(8);
if (containsDebug(sid, subflows)) {
candidateNodes.push(sf);
}
});
candidateNodes.sort(function(A,B) {
var wsA = workspaceOrderMap[A.z];
var wsB = workspaceOrderMap[B.z];
if (wsA !== wsB) {
return wsA-wsB;
}
var labelA = RED.utils.getNodeLabel(A,A.id);
var labelB = RED.utils.getNodeLabel(B,B.id);
return labelA.localeCompare(labelB);
});
var currentWs = null;
var data = [];
var currentFlow;
var currentSelectedCount = 0;
candidateNodes.forEach(function(node) {
if (currentWs !== node.z) {
if (currentFlow && currentFlow.checkbox) {
currentFlow.selected = currentSelectedCount === currentFlow.children.length
}
currentSelectedCount = 0;
currentWs = node.z;
var parent = RED.nodes.workspace(currentWs) || RED.nodes.subflow(currentWs);
currentFlow = {
label: RED.utils.getNodeLabel(parent, currentWs),
}
if (!parent.disabled) {
currentFlow.children = [];
currentFlow.checkbox = true;
} else {
currentFlow.class = "disabled"
}
data.push(currentFlow);
}
if (currentFlow.children) {
if (!filteredNodes[node.id]) {
currentSelectedCount++;
}
currentFlow.children.push({
label: RED.utils.getNodeLabel(node,node.id),
node: node,
checkbox: true,
selected: !filteredNodes[node.id]
});
}
});
if (currentFlow && currentFlow.checkbox) {
currentFlow.selected = currentSelectedCount === currentFlow.children.length
}
function refreshDebugNodeList(data) {
debugNodeTreeList.treeList("data", data);
}
@@ -401,7 +271,7 @@ RED.debug = (function() {
},200);
}
function _refreshMessageList(_activeWorkspace) {
if (_activeWorkspace) {
if (typeof _activeWorkspace === 'string') {
activeWorkspace = _activeWorkspace.replace(/\./g,"_");
}
if (filterType === "filterAll") {
@@ -479,12 +349,12 @@ RED.debug = (function() {
filteredNodes[n.id] = true;
});
delete filteredNodes[sourceId];
$("#red-ui-sidebar-debug-filterSelected").trigger("click");
RED.settings.set('debug.filteredNodes',Object.keys(filteredNodes))
setFilterType('filterSelected')
refreshMessageList();
}},
{id:"red-ui-debug-msg-menu-item-clear-filter",label:RED._("node-red:debug.messageMenu.clearFilter"),onselect:function(){
$("#red-ui-sidebar-debug-filterAll").trigger("click");
clearFilterSettings()
refreshMessageList();
}}
);
@@ -713,9 +583,17 @@ RED.debug = (function() {
if (!!clearFilter) {
clearFilterSettings();
}
refreshDebugNodeList();
config.requestDebugNodeList(filteredNodes);
}
function setFilterType(type) {
if (type !== filterType) {
filterType = type;
$('#red-ui-sidebar-debug-filter span').text(RED._('node-red:debug.sidebar.'+filterType));
refreshMessageList();
RED.settings.set("debug.filter",filterType)
}
}
function clearFilterSettings() {
filteredNodes = {};
filterType = 'filterAll';
@@ -728,6 +606,7 @@ RED.debug = (function() {
init: init,
refreshMessageList:refreshMessageList,
handleDebugMessage: handleDebugMessage,
clearMessageList: clearMessageList
clearMessageList: clearMessageList,
refreshDebugNodeList: refreshDebugNodeList
}
})();

View File

@@ -12,6 +12,9 @@ $(function() {
},
clear: function() {
window.opener.postMessage({event:"clear"},'*');
},
requestDebugNodeList: function(filteredNodes) {
window.opener.postMessage({event: 'requestDebugNodeList', filteredNodes},'*')
}
}
@@ -26,6 +29,8 @@ $(function() {
RED.debug.refreshMessageList(evt.data.activeWorkspace);
} else if (evt.data.event === "projectChange") {
RED.debug.clearMessageList(true);
} else if (evt.data.event === "refreshDebugNodeList") {
RED.debug.refreshDebugNodeList(evt.data.nodes)
}
},false);
} catch(err) {

View File

@@ -103,7 +103,6 @@
} else if (type === "istype") {
r.v = rule.find(".node-input-rule-type-value").typedInput('type');
r.vt = rule.find(".node-input-rule-type-value").typedInput('type');
r.vt = (r.vt === "number") ? "num" : "str";
} else if (type === "jsonata_exp") {
r.v = rule.find(".node-input-rule-exp-value").typedInput('value');
r.vt = rule.find(".node-input-rule-exp-value").typedInput('type');
@@ -168,7 +167,33 @@
label:RED._("node-red:common.label.payload"),
validate: RED.validators.typedInput("propertyType", false)},
propertyType: { value:"msg" },
rules: {value:[{t:"eq", v:"", vt:"str"}]},
rules: {
value:[{t:"eq", v:"", vt:"str"}],
validate: function (rules, opt) {
let msg;
const errors = []
if (!rules || rules.length === 0) { return true }
for (var i=0;i<rules.length;i++) {
const opt = { label: RED._('node-red:switch.label.rule')+' '+(i+1) }
const r = rules[i];
if (r.hasOwnProperty('v')) {
if ((msg = RED.utils.validateTypedProperty(r.v,r.vt,opt)) !== true) {
errors.push(msg)
}
}
if (r.hasOwnProperty('v2')) {
if ((msg = RED.utils.validateTypedProperty(r.v2,r.v2t,opt)) !== true) {
errors.push(msg)
}
}
}
if (errors.length) {
console.log(errors)
return errors
}
return true;
}
},
checkall: {value:"true", required:true},
repair: {value:false},
outputs: {value:1}
@@ -218,7 +243,11 @@
if (i > 0) {
var lastRule = $("#node-input-rule-container").editableList('getItemAt',i-1);
var exportedRule = exportRule(lastRule.element);
opt.r.vt = exportedRule.vt;
if (exportedRule.t === "istype") {
opt.r.vt = (exportedRule.vt === "number") ? "num" : "str";
} else {
opt.r.vt = exportedRule.vt;
}
opt.r.v = "";
// We could copy the value over as well and preselect it (see the 'activeElement' code below)
// But not sure that feels right. Is copying over the last value 'expected' behaviour?

View File

@@ -19,71 +19,42 @@
<script type="text/javascript">
(function() {
function isInvalidProperty(v,vt) {
if (/msg|flow|global/.test(vt)) {
if (!RED.utils.validatePropertyExpression(v)) {
return RED._("node-red:change.errors.invalid-prop", {
property: v
});
}
} else if (vt === "jsonata") {
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 RED._("node-red:change.errors.invalid-json-data", {
error: e.message
});
}
}
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, 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 (msg = isInvalidProperty(r.p,r.pt)) {
return msg;
rules:{
value:[{t:"set",p:"payload",pt:"msg",to:"",tot:"str"}],
validate: function(rules, opt) {
let msg;
const errors = []
if (!rules || rules.length === 0) { return true }
for (var i=0;i<rules.length;i++) {
const opt = { label: RED._('node-red:change.label.rule')+' '+(i+1) }
const r = rules[i];
if (r.t === 'set' || r.t === 'change' || r.t === 'delete' || r.t === 'move') {
if ((msg = RED.utils.validateTypedProperty(r.p,r.pt,opt)) !== true) {
errors.push(msg)
}
}
if (msg = isInvalidProperty(r.to,r.tot)) {
return msg;
if (r.t === 'set' || r.t === 'change' || r.t === 'move') {
if ((msg = RED.utils.validateTypedProperty(r.to,r.tot,opt)) !== true) {
errors.push(msg)
}
}
} else if (r.t === 'change') {
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 (msg = isInvalidProperty(r.p,r.pt)) {
return msg;
}
if (msg = isInvalidProperty(r.to,r.tot)) {
return msg;
if (r.t === 'change') {
if ((msg = RED.utils.validateTypedProperty(r.from,r.fromt,opt)) !== true) {
errors.push(msg)
}
}
}
if (errors.length) {
return errors
}
return true;
}
return true;
}},
},
// legacy
action: {value:""},
property: {value:""},

View File

@@ -57,7 +57,12 @@
action: {value:"scale"},
round: {value:false},
property: {value:"payload",required:true,
label:RED._("node-red:common.label.property")},
label:RED._("node-red:common.label.property"),
validate: RED.validators.typedInput({ type: 'msg' })
},
// RED.validators.typedInput("propertyType", false)},
name: {value:""}
},
inputs: 1,

View File

@@ -153,7 +153,7 @@
}
var editorRow = $("#dialog-form>div.node-text-editor-row");
height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
$(".node-text-editor").css("height",height+"px");
$("#dialog-form .node-text-editor").css("height",height+"px");
this.editor.resize();
}
});

View File

@@ -284,7 +284,7 @@ module.exports = function(RED) {
done();
}
}
else {
else if (!msg.hasOwnProperty("reset")) {
if (maxKeptMsgsCount(node) > 0) {
if (node.intervalID === -1) {
node.send(msg);

View File

@@ -56,7 +56,7 @@
color:"darksalmon",
defaults: {
command: {value:""},
addpay: {value:""},
addpay: {value:"", validate: RED.validators.typedInput({ type: 'msg', allowBlank: true })},
append: {value:""},
useSpawn: {value:"false"},
timer: {value:""},

View File

@@ -56,9 +56,11 @@
inout: {value:"out"},
septopics: {value:true},
property: {value:"payload", required:true,
label:RED._("node-red:rbe.label.property")},
label:RED._("node-red:rbe.label.property"),
validate: RED.validators.typedInput({ type: 'msg' })},
topi: {value:"topic", required:true,
label:RED._("node-red:rbe.label.topic")}
label:RED._("node-red:rbe.label.topic"),
validate: RED.validators.typedInput({ type: 'msg' })}
},
inputs:1,
outputs:1,

View File

@@ -104,6 +104,7 @@ module.exports = function(RED) {
* @returns `true` if it is a valid topic
*/
function isValidPublishTopic(topic) {
if (topic.length === 0) return false;
return !/[\+#\b\f\n\r\t\v\0]/.test(topic);
}
@@ -219,8 +220,8 @@ module.exports = function(RED) {
*/
function subscriptionHandler(node, datatype ,topic, payload, packet) {
const msg = {topic:topic, payload:null, qos:packet.qos, retain:packet.retain};
const v5 = (node && node.brokerConn)
? node.brokerConn.v5()
const v5 = (node && node.brokerConn)
? node.brokerConn.v5()
: Object.prototype.hasOwnProperty.call(packet, "properties");
if(v5 && packet.properties) {
setStrProp(packet.properties, msg, "responseTopic");
@@ -451,7 +452,7 @@ module.exports = function(RED) {
/**
* Perform the disconnect action
* @param {MQTTInNode|MQTTOutNode} node
* @param {MQTTInNode|MQTTOutNode} node
* @param {Function} done
*/
function handleDisconnectAction(node, done) {
@@ -611,7 +612,7 @@ module.exports = function(RED) {
node.brokerurl = node.url;
} else {
// if the broker is ws:// or wss:// or tcp://
if (node.broker.indexOf("://") > -1) {
if ((typeof node.broker === 'string') && node.broker.indexOf("://") > -1) {
node.brokerurl = node.broker;
// Only for ws or wss, check if proxy env var for additional configuration
if (node.brokerurl.indexOf("wss://") > -1 || node.brokerurl.indexOf("ws://") > -1) {
@@ -865,7 +866,7 @@ module.exports = function(RED) {
* Call end and wait for the client to end (or timeout)
* @param {mqtt.MqttClient} client The broker client
* @param {number} ms The time to wait for the client to end
* @returns
* @returns
*/
let waitEnd = (client, ms) => {
return new Promise( (resolve, reject) => {
@@ -905,7 +906,7 @@ module.exports = function(RED) {
node.subid = 1;
//typedef for subscription object:
/**
/**
* @typedef {Object} Subscription
* @property {String} topic - topic to subscribe to
* @property {Object} [options] - options object
@@ -933,7 +934,7 @@ module.exports = function(RED) {
const ref = _ref || 0;
let options
let qos = 1 // default to QoS 1 (AWS and several other brokers don't support QoS 2)
// if options is an object, then clone it
if (typeof _options == "object") {
options = RED.util.cloneMessage(_options || {})
@@ -947,7 +948,7 @@ module.exports = function(RED) {
if (typeof qos === "number" && qos >= 0 && qos <= 2) {
options.qos = qos;
}
subscription.topic = _topic;
subscription.qos = qos;
subscription.options = RED.util.cloneMessage(options);
@@ -957,16 +958,16 @@ module.exports = function(RED) {
}
/**
* If topic is a subscription object, then use that, otherwise look up the topic in
* If topic is a subscription object, then use that, otherwise look up the topic in
* the subscriptions object. If the topic is not found, then create a new subscription
* object and add it to the subscriptions object.
* @param {Subscription|String} topic
* @param {*} options
* @param {*} callback
* @param {*} ref
* @param {Subscription|String} topic
* @param {*} options
* @param {*} callback
* @param {*} ref
*/
node.subscribe = function (topic, options, callback, ref) {
/** @type {Subscription} */
/** @type {Subscription} */
let subscription
let doCompare = false
let changesFound = false
@@ -1004,7 +1005,7 @@ module.exports = function(RED) {
_brokerConn.unsubscribe(sub.topic, sub.ref, true)
}
})
// if subscription is found (or sent in as a parameter), then check for changes.
// if there are any changes requested, tidy up the old subscription
if (subscription) {
@@ -1091,7 +1092,7 @@ module.exports = function(RED) {
delete sub[ref]
}
}
// if instructed to remove the actual MQTT client subscription
// if instructed to remove the actual MQTT client subscription
if (unsub) {
// if there are no more subscriptions for the topic, then remove the topic
if (Object.keys(sub).length === 0) {

View File

@@ -452,10 +452,6 @@ in your Node-RED user directory (${RED.settings.userDir}).
formData.append(opt, val);
} else if (typeof val === 'object' && val.hasOwnProperty('value')) {
formData.append(opt,val.value,val.options || {});
} else if (Array.isArray(val)) {
for (var i=0; i<val.length; i++) {
formData.append(opt, val[i])
}
} else {
formData.append(opt,JSON.stringify(val));
}

View File

@@ -63,7 +63,7 @@ module.exports = function(RED) {
if (!(notemplate && (msg.hasOwnProperty("parts") && msg.parts.hasOwnProperty("index") && msg.parts.index > 0))) {
template = clean(node.template);
}
var ou = "";
const ou = [];
if (!Array.isArray(msg.payload)) { msg.payload = [ msg.payload ]; }
if (node.hdrout !== "none" && node.hdrSent === false) {
if ((template.length === 1) && (template[0] === '')) {
@@ -74,7 +74,7 @@ module.exports = function(RED) {
template = Object.keys(msg.payload[0]);
}
}
ou += template.map(v => v.indexOf(node.sep)!==-1 ? '"'+v+'"' : v).join(node.sep) + node.ret;
ou.push(template.map(v => v.indexOf(node.sep)!==-1 ? '"'+v+'"' : v).join(node.sep));
if (node.hdrout === "once") { node.hdrSent = true; }
}
for (var s = 0; s < msg.payload.length; s++) {
@@ -93,7 +93,7 @@ module.exports = function(RED) {
msg.payload[s][t] = node.quo + msg.payload[s][t].toString() + node.quo;
}
}
ou += msg.payload[s].join(node.sep) + node.ret;
ou.push(msg.payload[s].join(node.sep));
}
else {
if ((template.length === 1) && (template[0] === '') && (msg.hasOwnProperty("columns"))) {
@@ -105,6 +105,7 @@ module.exports = function(RED) {
node.warn(RED._("csv.errors.obj_csv"));
tmpwarn = false;
}
const row = [];
for (var p in msg.payload[0]) {
/* istanbul ignore else */
if (msg.payload[s].hasOwnProperty(p)) {
@@ -118,21 +119,22 @@ module.exports = function(RED) {
}
if (q.indexOf(node.quo) !== -1) { // add double quotes if any quotes
q = q.replace(/"/g, '""');
ou += node.quo + q + node.quo + node.sep;
row.push(node.quo + q + node.quo);
}
else if (q.indexOf(node.sep) !== -1 || p.indexOf("\n") !== -1) { // add quotes if any "commas" or "\n"
ou += node.quo + q + node.quo + node.sep;
row.push(node.quo + q + node.quo);
}
else { ou += q + node.sep; } // otherwise just add
else { row.push(q); } // otherwise just add
}
}
}
ou = ou.slice(0,-1) + node.ret;
ou.push(row.join(node.sep)); // add separator
}
else {
const row = [];
for (var t=0; t < template.length; t++) {
if (template[t] === '') {
ou += node.sep;
row.push('');
}
else {
var tt = template[t];
@@ -146,19 +148,20 @@ module.exports = function(RED) {
p = RED.util.ensureString(p);
if (p.indexOf(node.quo) !== -1) { // add double quotes if any quotes
p = p.replace(/"/g, '""');
ou += node.quo + p + node.quo + node.sep;
row.push(node.quo + p + node.quo);
}
else if (p.indexOf(node.sep) !== -1 || p.indexOf("\n") !== -1) { // add quotes if any "commas" or "\n"
ou += node.quo + p + node.quo + node.sep;
row.push(node.quo + p + node.quo);
}
else { ou += p + node.sep; } // otherwise just add
else { row.push(p); } // otherwise just add
}
}
ou = ou.slice(0,-1) + node.ret; // remove final "comma" and add "newline"
ou.push(row.join(node.sep)); // add separator
}
}
}
msg.payload = ou;
// join lines, don't forget to add the last new line
msg.payload = ou.join(node.ret) + node.ret;
msg.columns = template.map(v => v.indexOf(',')!==-1 ? '"'+v+'"' : v).join(',');
if (msg.payload !== '') { send(msg); }
done();

View File

@@ -41,8 +41,8 @@
color:"#DEBD5C",
defaults: {
name: {value:""},
property: {value:"payload"},
outproperty: {value:"payload"},
property: {value:"payload", validate: RED.validators.typedInput({ type: 'msg' }) },
outproperty: {value:"payload", validate: RED.validators.typedInput({ type: 'msg' }) },
tag: {value:""},
ret: {value:"html"},
as: {value:"single"}

View File

@@ -32,6 +32,7 @@
defaults: {
name: {value:""},
property: {value:"payload",required:true,
validate: RED.validators.typedInput({ type: 'msg' }),
label:RED._("node-red:json.label.property")},
action: {value:""},
pretty: {value:false}

View File

@@ -27,7 +27,8 @@
defaults: {
name: {value:""},
property: {value:"payload",required:true,
label:RED._("node-red:common.label.property")},
label:RED._("node-red:common.label.property"),
validate: RED.validators.typedInput({ type: 'msg' })},
attr: {value:""},
chr: {value:""}
},

View File

@@ -16,6 +16,7 @@
color:"#DEBD5C",
defaults: {
property: {value:"payload",required:true,
validate: RED.validators.typedInput({ type: 'msg' }),
label:RED._("node-red:common.label.property")},
name: {value:""}
},

View File

@@ -57,7 +57,7 @@
arraySplt: {value:1},
arraySpltType: {value:"len"},
stream: {value:false},
addname: {value:""}
addname: {value:"", validate: RED.validators.typedInput({ type: 'msg', allowBlank: true })}
},
inputs:1,
outputs:1,
@@ -208,7 +208,22 @@
validate:RED.validators.typedInput("propertyType", false)
},
propertyType: { value:"msg"},
key: {value:"topic"},
key: {value:"topic", validate: (function () {
const typeValidator = RED.validators.typedInput({ type: 'msg' })
return function(v, opt) {
const joinMode = $("#node-input-mode").val() || this.mode
if (joinMode !== 'custom') {
return true
}
const buildType = $("#node-input-build").val() || this.build
if (buildType !== 'object') {
return true
} else {
return typeValidator(v, opt)
}
}
})()
},
joiner: { value:"\\n"},
joinerType: { value:"str"},
accumulate: { value:"false" },

View File

@@ -198,7 +198,7 @@
category: 'storage',
defaults: {
name: {value:""},
filename: {value:""},
filename: {value:"", validate: RED.validators.typedInput({ typeField: 'filenameType' })},
filenameType: {value:"str"},
appendNewline: {value:true},
createDir: {value:false},
@@ -297,7 +297,7 @@
category: 'storage',
defaults: {
name: {value:""},
filename: {value:""},
filename: {value:"", validate: RED.validators.typedInput({ typeField: 'filenameType' }) },
filenameType: {value:"str"},
format: {value:"utf8"},
chunk: {value:false},

Binary file not shown.

Before

Width:  |  Height:  |  Size: 603 B

View File

@@ -0,0 +1 @@
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#fff"><path d="m9.7884 22.379c-5.2427-0.41732-9.6475 5.7885-7.4975 10.585 2.0949 5.2041 9.9782 6.6154 13.727 2.4477 3.633-3.5613 5.0332-9.0411 9.4821-11.853 4.5205-3.0872 11.797-0.172 12.68 5.3144 0.86 5.2537-4.8017 10.364-9.9231 8.8205-3.7873-0.85449-6.5051-4.0905-8.0487-7.4975-1.9019-3.2526-4.3882-6.7257-8.2693-7.6077-0.6891-0.15656-1.4003-0.21831-2.1059-0.21721z" stroke-width="3.3"/><path d="m6.7012 29.821h6.6154" stroke-width="1.4"/><path d="m26.988 29.821h5.5128m-2.8115-2.7564v5.5128" stroke-width="1.8"/></g></svg>

After

Width:  |  Height:  |  Size: 635 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.3 KiB

View File

@@ -0,0 +1 @@
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="m8.3474 17.75 22.298 22.444-10.747 13.013v-46.497l10.747 12.428-22.298 21.859" fill="none" stroke="#fff" stroke-width="4"/></svg>

After

Width:  |  Height:  |  Size: 225 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1.6 KiB

View File

@@ -0,0 +1 @@
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="m2.7078 12.986c0 7.7994-0.36386 21.569 0 32.545s35.118 9.8751 34.848 0c-0.26959-9.8751 0-24.82 0-32.545 0-7.7243-34.848-7.7995-34.848 0z" fill="none" stroke="#fff"/><g fill="#fff"><path d="m3.8741 13.406v8.955c0.021834 3.5781 19.543 5.0789 25.575 3.2543 0 0 0.02229-2.6683 0.02998-2.6673l5.5325 0.7238c0.64508 0.0844 1.1345-0.74597 1.134-1.3284v-8.573l-0.99896 0.93349-15.217-2.2765c4.5883 2.1798 9.808 4.1312 9.808 4.1312-9.3667 3.1562-25.846-0.31965-25.864-3.1525z"/><path d="m3.886 26.607v8.1052c3.2188 6.1087 29.901 5.8574 32.272 0v-8.1052c-3.3598 4.6685-29.204 5.1534-32.272 0z"/><path d="m4.0032 39.082v7.1522c2.556 7.4622 28.918 7.6072 32.272 0v-7.1522c-3.2345 4.9471-29.087 5.359-32.272 0z"/></g></svg>

After

Width:  |  Height:  |  Size: 806 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 414 B

View File

@@ -0,0 +1 @@
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="m23.515 13.831c-4.7594-5.8789-2.6084-5.7751-7.3474 0-8.0368 10.477-8.3322 24.431 2.5476 32.935 0.13181 2.0418 0.46056 4.9803 0.46056 4.9803h1.315s0.32875-2.9219 0.46017-4.9803c2.8458-2.2339 16.799-14.619 2.5641-32.935z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 335 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 671 B

View File

@@ -0,0 +1 @@
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#fff" stroke-width="3"><path d="m6 30c6 5 24 4 29-0.07"/><path d="m21 33 0.1-19c0.02-4 4-3 4-6s-4-2-4-5"/><path d="m6 22c0-11 29-10 29 0v21c0 18-29 19-29 0s4e-7 -11 0-21z"/></g></svg>

After

Width:  |  Height:  |  Size: 293 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 252 B

View File

@@ -0,0 +1 @@
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="m29 12s0.1 30 0.05 31-3 5-7 5-19 0.04-19 0.04c6-4 9-5 17-5 0 0 4-0.1 4-2 0-2 8e-3 -29 8e-3 -29z" fill="#fff"/><path d="m12 47s-0.1-30-0.05-31 3-5 7-5 19-0.04 19-0.04c-6 4-9 5-17 5 0 0-4 0.1-4 2 0 2-8e-3 29-8e-3 29z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 331 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 736 B

View File

@@ -0,0 +1 @@
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><g fill="none" stroke="#fff" stroke-width="3"><path class="cls-4" d="m17.639 30.221c-1.7087-0.88225-12.465-5.6284-14.414-6.636-1.9492-1.0075-1.9868-1.7073-0.075164-2.5188 1.9117-0.81145 12.643-5.3861 14.91-6.2738 2.2675-0.8877 3.0517-0.91493 4.9785-0.14704 1.9267 0.76789 12.026 5.1329 13.923 5.8898 1.8966 0.75699 1.9843 1.386 0.02631 2.4861-1.958 1.1001-12.1 5.6611-14.285 6.8729s-3.355 1.2091-5.0636 0.32685z"/><path class="cls-4" d="m32.23 25.251c2.8239 1.2039 4.155 1.764 4.7307 1.9938 1.8966 0.75699 1.9843 1.386 0.0263 2.4861s-12.1 5.6611-14.285 6.8729c-2.1848 1.2117-3.3548 1.209-5.0634 0.32676-1.7087-0.88225-12.465-5.6284-14.414-6.636-1.9492-1.0075-1.9868-1.7073-0.075164-2.5188 10.883-4.6196-9.1087 3.8612 4.9598-2.1076"/><path class="cls-4" d="m32.23 31.961c2.8239 1.2039 4.155 1.764 4.7307 1.9938 1.8966 0.75699 1.9843 1.386 0.0263 2.4861s-12.1 5.6611-14.285 6.8729c-2.1848 1.2117-3.3548 1.209-5.0634 0.32676-1.7087-0.88225-12.465-5.6284-14.414-6.636-1.9492-1.0075-1.9868-1.7073-0.075164-2.5188 10.883-4.6196-9.1087 3.8612 4.9598-2.1076"/></g></svg>

After

Width:  |  Height:  |  Size: 1.1 KiB

View File

@@ -36,5 +36,5 @@
<p><b>Remarque</b> : Les options <i>"Intervalle entre les heures"</i> et <i>"à une heure précise"</i> utilisent le système cron standard.
Cela signifie que pour la première option, vous pouvez envoyer un message à intervalle régulier entre les heures voulues.
Si vous voulez envoyer un message toutes les minutes à partir de maintenant, utiliser l'option <i>"intervalle"</i>.</p>
<p><b>Remarque</b> : Pour inclure une nouvelle ligne dans une chaîne, vous devez utiliser un noeud de fonction pour créer la charge utile.</p>
<p><b>Remarque</b> : Pour inclure une nouvelle ligne dans une chaîne, vous devez utiliser soit un noeud de fonction soit le noeud template pour créer la charge utile.</p>
</script>

View File

@@ -11,11 +11,11 @@
"expand": "Développer"
},
"status": {
"connected": "connecté",
"not-connected": "pas connecté",
"disconnected": "déconnecté",
"connecting": "connexion",
"error": "erreur",
"connected": "Connecté",
"not-connected": "Pas connecté",
"disconnected": "Déconnecté",
"connecting": "Connexion",
"error": "Erreur",
"ok": "OK"
},
"notification": {
@@ -32,7 +32,7 @@
},
"inject": {
"inject": "Injecter",
"injectNow": "injecter maintenant",
"injectNow": "Injecter maintenant",
"repeat": "répéter = __repeat__",
"crontab": "crontab = __crontab__",
"stopped": "arrêté",
@@ -98,7 +98,7 @@
"catchUncaught": "catch : non capturé",
"label": {
"source": "Détecter les erreurs de",
"selectAll": "tout sélectionner",
"selectAll": "Tout sélectionner",
"uncaught": "Ignorer les erreurs gérées par les autres noeuds Catch"
},
"scope": {
@@ -112,7 +112,7 @@
"statusNodes": "statut : __number__",
"label": {
"source": "Signaler l'état de",
"sortByType": "trier par type"
"sortByType": "Trier par type"
},
"scope": {
"all": "tous les noeuds",
@@ -148,23 +148,23 @@
"deactivated": "Désactivé avec succès : __label__"
},
"sidebar": {
"label": "débogage",
"label": "Débogage",
"name": "Messages de débogage",
"filterAll": "tous les noeuds",
"filterSelected": "noeuds sélectionnés",
"filterCurrent": "flux actuel",
"filterAll": "Tous les noeuds",
"filterSelected": "Noeuds sélectionnés",
"filterCurrent": "Flux actuel",
"debugNodes": "noeuds de débogage",
"clearLog": "Effacer les messages",
"clearFilteredLog": "Effacer les messages filtrés",
"clearLog": "Tous les messages",
"clearFilteredLog": "Les messages filtrés",
"filterLog": "Filtrer les messages",
"openWindow": "Ouvrir dans une nouvelle fenêtre",
"copyPath": "Copier le chemin",
"copyPayload": "Copier la valeur",
"pinPath": "Épingler le chemin",
"selectAll": "tout sélectionner",
"selectNone": "ne rien sélectionner",
"all": "tout",
"filtered": "filtré"
"selectAll": "Tout sélectionner",
"selectNone": "Ne rien sélectionner",
"all": "Tout",
"filtered": "Filtrés"
},
"messageMenu": {
"collapseAll": "Réduire tous les chemins",
@@ -177,11 +177,11 @@
"linkIn": "Lien entrant",
"linkOut": "Lien sortant",
"linkCall": "Appel de lien",
"linkOutReturn": "retour de lien",
"linkOutReturn": "Retour de lien",
"outMode": "Mode",
"sendToAll": "Envoyer à tous les noeuds de liaison connectés",
"returnToCaller": "Retour au noeud de liaison appelant",
"timeout": "temps mort",
"timeout": "Temps mort",
"linkCallType": "Type de liaison",
"staticLinkCall": "Lien fixe",
"dynamicLinkCall": "Lien dynamique (msg.target)",
@@ -225,7 +225,7 @@
"command": "Commande",
"append": "Joindre",
"timeout": "Temps mort",
"timeoutplace": "facultatif",
"timeoutplace": "Facultatif",
"return": "Sortie",
"seconds": "secondes",
"stdout": "stdout",
@@ -234,7 +234,7 @@
"winHide": "Masquer la console"
},
"placeholder": {
"extraparams": "paramètres d'entrée supplémentaires"
"extraparams": "Paramètres d'entrée supplémentaires"
},
"opt": {
"exec": "lorsque la commande est terminée - mode exec",
@@ -319,7 +319,7 @@
"queuemsg": "Mettre en file d'attente les messages intermédiaires",
"dropmsg": "Supprimer les messages intermédiaires",
"sendmsg": "Envoyer les messages intermédiaires sur la 2ème sortie",
"allowrate": "autoriser msg.rate (en ms) à remplacer le débit",
"allowrate": "Autoriser msg.rate (en ms) à remplacer le débit",
"label": {
"delay": "retard",
"variable": "variable",
@@ -349,7 +349,7 @@
}
},
"errors": {
"too-many": "trop de messages en attente dans le noeud 'Delay'",
"too-many": "Trop de messages en attente dans le noeud 'Delay'",
"invalid-timeout": "Valeur de délai invalide",
"invalid-rate": "Valeur de taux invalide",
"invalid-rate-unit": "Valeur de débit invalide",
@@ -359,8 +359,8 @@
},
"trigger": {
"send": "Envoyer",
"then": "puis",
"then-send": "puis envoyer",
"then": "Puis",
"then-send": "Puis envoyer",
"output": {
"string": "la chaîne",
"number": "le nombre",
@@ -381,9 +381,9 @@
"m": "Minutes",
"h": "Heures"
},
"extend": " prolonger le délai si un nouveau message arrive",
"override": "remplacer le délai avec msg.delay",
"second": " envoyer un deuxième message à une sortie séparée",
"extend": " Prolonger le délai si un nouveau message arrive",
"override": "Remplacer le délai avec msg.delay",
"second": " Envoyer un deuxième message à une sortie séparée",
"label": {
"trigger": "déclencher",
"trigger-block": "déclencher et bloquer",
@@ -408,7 +408,7 @@
"mqtt": {
"label": {
"broker": "Serveur",
"example": "par exemple. localhost",
"example": "expl. localhost",
"output": "Sortie",
"qos": "QoS",
"retain": "Conserver",
@@ -438,7 +438,7 @@
"sessionExpiry": "Expiration de la session (secondes)",
"topicAlias": "Alias",
"payloadFormatIndicator": "Formater",
"payloadFormatIndicatorFalse": "octets non spécifiés (par défaut)",
"payloadFormatIndicatorFalse": "Octets non spécifiés (par défaut)",
"payloadFormatIndicatorTrue": "Charge utile encodée en UTF-8",
"protocolVersion": "Protocole",
"protocolVersion3": "MQTT V3.1 (hérité)",
@@ -493,8 +493,8 @@
"false": "faux",
"tip": "Conseil : laisser le sujet, le qos ou le contenu vide si vous souhaitez les définir via les propriétés du msg.",
"errors": {
"not-defined": "sujet non défini",
"missing-config": "configuration du courtier manquante",
"not-defined": "Sujet non défini",
"missing-config": "Configuration du courtier manquante",
"invalid-topic": "Sujet invalide spécifié",
"nonclean-missingclientid": "Aucun ID client défini, utilisation d'une session propre",
"invalid-json-string": "Chaîne JSON invalide",
@@ -514,7 +514,7 @@
"upload": "Accepter les téléchargements de fichiers ?",
"status": "Code d'état",
"headers": "En-têtes",
"other": "autre",
"other": "Autre",
"paytoqs": {
"ignore": "Ignorer",
"query": "Joindre aux paramètres de chaîne de requête",
@@ -625,7 +625,7 @@
"chars": "caractères",
"close": "Fermer",
"optional": "(facultatif)",
"reattach": "rattacher le délimiteur"
"reattach": "Rattacher le délimiteur"
},
"type": {
"listen": "Écoute sur",
@@ -633,8 +633,8 @@
"reply": "Répondre sur TCP"
},
"output": {
"stream": "flux de",
"single": "unique",
"stream": "Flux de",
"single": "Unique",
"buffer": "Tampon",
"string": "Chaîne",
"base64": "Chaîne en Base64"
@@ -657,15 +657,15 @@
"connections_plural": "__count__ connexions"
},
"errors": {
"connection-lost": "connexion perdue avec __host__:__port__",
"timeout": "délai d'expiration du port __port__ du socket fermé",
"cannot-listen": "impossible d'écouter sur le port __port__, erreur : __error__",
"error": "erreur : __error__",
"socket-error": "erreur de courtier depuis __host__:__port__",
"connection-lost": "Connexion perdue avec __host__:__port__",
"timeout": "Délai d'expiration du port __port__ du socket fermé",
"cannot-listen": "Impossible d'écouter sur le port __port__, erreur : __error__",
"error": "Erreur : __error__",
"socket-error": "Erreur de courtier depuis __host__:__port__",
"no-host": "Hôte et/ou port non défini",
"connect-timeout": "délai de connexion",
"connect-fail": "la connexion a échoué",
"bad-string": "échec de la conversion en chaîne",
"connect-timeout": "Délai de connexion",
"connect-fail": "La connexion a échoué",
"bad-string": "Échec de la conversion en chaîne",
"invalid-host": "Hôte invalide",
"invalid-port": "Port invalide"
}
@@ -722,7 +722,7 @@
},
"errors": {
"access-error": "Erreur d'accès UDP, vous aurez peut-être besoin d'un accès root pour les ports inférieurs à 1024",
"error": "erreur : __erreur__",
"error": "Erreur : __erreur__",
"bad-mcaddress": "Mauvaise adresse de multidiffusion",
"interface": "Doit être l'adresse IP de l'interface requise",
"ip-notset": "udp : adresse IP non définie",
@@ -730,7 +730,7 @@
"port-invalid": "udp : numéro de port non valide",
"alreadyused": "udp : port __port__ déjà utilisé",
"ifnotfound": "udp : interface __iface__ introuvable",
"invalid-group": "groupe de multidiffusion invalide"
"invalid-group": "Groupe de multidiffusion invalide"
}
},
"switch": {
@@ -738,15 +738,15 @@
"label": {
"property": "Propriété",
"rule": "règle",
"repair": "recréer des séquences du messages",
"value-rules": "règles de valeur",
"sequence-rules": "règles de séquence"
"repair": "Recréer des séquences du messages",
"value-rules": "Règles de valeur",
"sequence-rules": "Règles de séquence"
},
"previous": "valeur précédente",
"and": "et",
"checkall": "vérifier toutes les règles",
"stopfirst": "arrêter après la première concordance",
"ignorecase": "ignorer la casse",
"checkall": "Vérifier toutes les règles",
"stopfirst": "Arrêter après la première concordance",
"ignorecase": "Ignorer la casse",
"rules": {
"btwn": "est entre",
"cont": "contient",
@@ -767,7 +767,7 @@
},
"errors": {
"invalid-expr": "Expression JSONata non valide : __error__",
"too-many": "trop de messages en attente dans le noeud de commutation"
"too-many": "Trop de messages en attente dans le noeud de commutation"
}
},
"change": {
@@ -840,13 +840,13 @@
"entrée": "Entrée",
"skip-s": "Passer en premier",
"skip-e": "lignes",
"firstrow": "la première ligne contient les noms des colonnes",
"firstrow": "La première ligne contient les noms des colonnes",
"output": "Sortie",
"includerow": "inclure la ligne du nom de la colonne",
"includerow": "Inclure la ligne du nom de la colonne",
"newline": "Nouvelle ligne",
"usestrings": "analyser les valeurs numériques",
"include_empty_strings": "inclure les chaînes vides",
"include_null_values": "inclure les valeurs nulles"
"usestrings": "Analyser les valeurs numériques",
"include_empty_strings": "Inclure les chaînes vides",
"include_null_values": "Inclure les valeurs nulles"
},
"placeholder": {
"columns": "noms de colonnes séparés par des virgules"
@@ -936,8 +936,8 @@
},
"file": {
"label": {
"write": "écrire le fichier",
"read": "lire le fichier",
"write": "Écrire le fichier",
"read": "Lire le fichier",
"filename": "Nom du fichier",
"path": "chemin",
"action": "Action",
@@ -972,8 +972,8 @@
"appendedfile": "ajouté au fichier : __file__"
},
"encoding": {
"none": "par défaut",
"setbymsg": "défini par msg.encoding",
"none": "Par défaut",
"setbymsg": "Défini par msg.encoding",
"native": "Natif",
"unicode": "Unicode",
"japanese": "Japonais",
@@ -990,10 +990,10 @@
"errors": {
"nofilename": "Aucun nom de fichier spécifié",
"invaliddelete": "Attention : suppression non valide. Veuiller utiliser une option de suppression spécifique dans la boîte de dialogue de configuration.",
"deletefail": "échec de la suppression du fichier : __error__",
"writefail": "échec de l'écriture dans le fichier : __error__",
"appendfail": "échec de l'ajout au fichier : __error__",
"createfail": "échec de la création du fichier : __error__"
"deletefail": "Échec de la suppression du fichier : __error__",
"writefail": "Échec de l'écriture dans le fichier : __error__",
"appendfail": "Échec de l'ajout au fichier : __error__",
"createfail": "Échec de la création du fichier : __error__"
},
"tip": "Astuce : Le nom du fichier doit être un chemin absolu, sinon il sera relatif au répertoire de travail du processus Node-RED."
},
@@ -1018,9 +1018,9 @@
"reduce": "réduire la séquence",
"custom": "manuel"
},
"combine": "Combine each",
"combine": "Combiner chaque",
"completeMessage": "message complet",
"create": "créer",
"create": "Créer",
"type": {
"string": "une Chaîne",
"array": "un Tableau",
@@ -1028,13 +1028,13 @@
"object": "un Objet clé/valeur",
"merged": "un Objet fusionné"
},
"using": "en utilisant la valeur de",
"key": "comme la clé",
"using": "En utilisant la valeur du",
"key": "comme clé",
"joinedUsing": "joint en utilisant",
"send": "Envoyer le message :",
"afterCount": "Après un certain nombre de parties du message",
"count": "compter",
"subsequent": "et tous les messages suivants.",
"afterCount": "Après un nombre de parties du message",
"count": "nombre",
"subsequent": "Et tous les messages suivants.",
"afterTimeout": "Après un délai d'attente après le premier message",
"seconds": "secondes",
"complete": "Après un message avec la propriété <code>msg.complete</code> définie",
@@ -1068,10 +1068,10 @@
"order": "Sens",
"ascending": "croissant",
"descending": "descendant",
"as-number": "comme nombre",
"as-number": "Comme nombre",
"invalid-exp": "Expression JSONata invalide dans le noeud sort: __message__",
"too-many": "Trop de messages en attente dans le noeud sort",
"clear": "effacer le message en attente dans le noeud sort"
"clear": "Effacer le message en attente dans le noeud sort"
},
"batch": {
"batch": "Regrouper",
@@ -1084,21 +1084,21 @@
"count": {
"label": "Nombre de messages",
"overlap": "Chevauchement",
"count": "compter",
"count": "nombre",
"invalid": "Comptage et chevauchement invalides"
},
"interval": {
"label": "Intervalle",
"seconds": "secondes",
"empty": "envoyer un message vide lorsqu'aucun message n'arrive"
"empty": "Envoyer un message vide lorsqu'aucun message n'arrive"
},
"concat": {
"topics-label": "Sujets",
"topic": "sujet"
},
"too-many": "trop de messages en attente dans le noeud batch",
"unexpected": "mode inattendu",
"no-parts": "aucune propriété de pièces dans le message",
"too-many": "Trop de messages en attente dans le noeud batch",
"unexpected": "Mode inattendu",
"no-parts": "Aucune propriété de pièces dans le message",
"error": {
"invalid-count": "Compte invalide",
"invalid-overlap": "Recouvrement invalide",
@@ -1132,7 +1132,7 @@
"out": "par rapport à la dernière valeur de sortie valide"
},
"warn": {
"nonumber": "aucun numéro trouvé dans la charge utile"
"nonumber": "Aucun numéro trouvé dans la charge utile"
}
},
"global-config": {