Merge branch 'dev' into pr_2165

This commit is contained in:
Nick O'Leary
2019-07-10 09:30:48 +01:00
282 changed files with 4009 additions and 1538 deletions

View File

@@ -168,7 +168,7 @@
once: {value:false},
onceDelay: {value:0.1}
},
icon: "inject.png",
icon: "inject.svg",
inputs:0,
outputs:1,
outputLabels: function(index) {

View File

@@ -11,57 +11,18 @@
<input type="checkbox" id="node-input-uncaught" style="display: inline-block; width: auto; vertical-align: top; margin-left: 30px; margin-right: 5px;">
<label for="node-input-uncaught" style="width: auto" data-i18n="catch.label.uncaught"></label>
</div>
<div class="form-row node-input-target-row" style="display: none;">
<div id="node-input-catch-target-container-div" style="min-height: 100px;position: relative; box-sizing: border-box; border-radius: 2px; height: 180px; border: 1px solid #ccc;overflow:hidden; ">
<div style="box-sizing: border-box; line-height: 20px; font-size: 0.8em; border-bottom: 1px solid #ddd; height: 20px;">
<input type="checkbox" data-i18n="[title]catch.label.selectAll" id="node-input-target-node-checkbox-all" style="width: 30px; margin: 0 2px 1px 2px;">
<div style="display: inline-block;"><a id="node-input-target-sort-label" href="#" data-i18n="[title]catch.label.sortByLabel"><span data-i18n="catch.label.node"></span> <i class="node-input-catch-sort-label-a fa fa-caret-down"></i><i class="node-input-catch-sort-label-d fa fa-caret-up"></i></a></div>
<div style="position: absolute; right: 10px; width: 50px; display: inline-block; text-align: right;"><a id="node-input-target-sort-type" href="#" data-i18n="[title]catch.label.sortByType"><i class="node-input-catch-sort-sublabel-a fa fa-caret-down"></i><i class="node-input-catch-sort-sublabel-d fa fa-caret-up"></i> <span data-i18n="catch.label.type"></span></a></div>
</div>
<div style="background: #fbfbfb; box-sizing: border-box; position:absolute; top:20px;bottom:0;left:0px;right:0px; overflow-y: scroll; overflow-x: hidden;">
<ul id="node-input-catch-target-container" style=" list-style-type:none; margin: 0;"></ul>
</div>
</div>
<div class="form-row node-input-target-row">
<button id="node-input-catch-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
</div>
<div class="form-row node-input-target-row node-input-target-list-row" style="min-height: 100px">
<div id="node-input-catch-target-container-div"></div>
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
</div>
</script>
<style>
#node-input-catch-target-container {
position: relative;
}
#node-input-catch-target-container li {
padding: 2px 5px;
background: none;
font-size: 0.8em;
margin:0;
white-space: nowrap;
}
#node-input-catch-target-container li label {
margin-bottom: 0;
width: 100%;
}
#node-input-catch-target-container li label input {
vertical-align: top;
width:15px;
margin-right: 10px;
}
#node-input-catch-target-container li:hover,
#node-input-catch-target-container li:hover .node-input-target-node-sublabel {
background: #f0f0f0;
}
.node-input-target-node-sublabel {
position:absolute;
right: 0px;
padding-right: 10px;
padding-left: 10px;
font-size: 0.8em;
background: #fbfbfb;
}
</style>
<script type="text/javascript">
RED.nodes.registerType('catch',{
category: 'input',
@@ -73,7 +34,7 @@
},
inputs:0,
outputs:1,
icon: "alert.png",
icon: "alert.svg",
label: function() {
if (this.name) {
return this.name;
@@ -87,146 +48,108 @@
return this.name?"node_label_italic":"";
},
oneditprepare: function() {
var nodeList = $("#node-input-catch-target-container");
var node = this;
this.resize = function() {
var rows = $("#dialog-form>div:not(.node-input-target-row)");
var scope = node.scope || [];
this._resize = function() {
var rows = $("#dialog-form>div:not(.node-input-target-list-row)");
var height = $("#dialog-form").height();
for (var i=0;i<rows.length;i++) {
height -= $(rows[i]).outerHeight(true);
}
var editorRow = $("#dialog-form>div.node-input-target-row");
height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
$("#node-input-catch-target-container-div").css("height",height+"px");
var editorRow = $("#dialog-form>div.node-input-target-list-row");
editorRow.css("height",height+"px");
};
function createNodeList() {
var scope = node.scope || [];
nodeList.empty();
var dirList = $("#node-input-catch-target-container-div").css({width: "100%", height: "100%"})
.treeList({multi:true}).on("treelistitemmouseover", function(e, item) {
item.node.highlighted = true;
item.node.dirty = true;
RED.view.redraw();
}).on("treelistitemmouseout", function(e, item) {
item.node.highlighted = false;
item.node.dirty = true;
RED.view.redraw();
})
var candidateNodes = RED.nodes.filterNodes({z:node.z});
var allChecked = true;
var items = [];
var nodeItemMap = {};
var candidateNodes = RED.nodes.filterNodes({z:node.z});
var allChecked = true;
candidateNodes.forEach(function(n) {
if (n.id === node.id) {
return;
}
var isChecked = scope.indexOf(n.id) !== -1;
allChecked = allChecked && isChecked;
var container = $('<li/>',{class:"node-input-target-node"});
var row = $('<label/>',{for:"node-input-target-node-"+n.id}).appendTo(container);
$('<input>',{type:"checkbox",class:"node-input-target-node-checkbox",id:"node-input-target-node-"+n.id})
.data('node-id',n.id)
.prop('checked', isChecked)
.appendTo(row);
container.on('mouseover',function(e) {
n.highlighted = true;
n.dirty = true;
RED.view.redraw();
});
container.on('mouseout',function(e) {
n.highlighted = false;
n.dirty = true;
RED.view.redraw();
});
var labelSpan = $('<span>');
var nodeDef = RED.nodes.getType(n.type);
var label;
var sublabel;
if (nodeDef) {
var l = nodeDef.label;
label = (typeof l === "function" ? l.call(n) : l)||"";
sublabel = n.type;
if (sublabel.indexOf("subflow:") === 0) {
var subflowId = sublabel.substring(8);
var subflow = RED.nodes.subflow(subflowId);
sublabel = "subflow : "+subflow.name;
}
}
if (!nodeDef || !label) {
label = n.type;
}
$('<span>',{class:"node-input-target-node-label",style:"white-space:nowrap"}).text(label).appendTo(row);
if (sublabel) {
$('<span>',{class:"node-input-target-node-sublabel"}).text(sublabel).appendTo(row);
}
container.appendTo(nodeList);
});
$(".node-input-target-node-checkbox").on("change", function() {
if (!this.checked) {
$("#node-input-target-node-checkbox-all").prop('checked',false);
}
});
$("#node-input-target-node-checkbox-all").prop('checked',allChecked);
sortNodeList('label');
}
function sortNodeList(sortOn) {
var currentSort = nodeList.data('currentSort');
var currentSortOrder = nodeList.data('currentSortOrder');
if (!currentSort) {
currentSort = sortOn;
currentSortOrder = 'a';
} else {
if (currentSort === sortOn) {
currentSortOrder = (currentSortOrder === 'a'?'d':'a');
} else {
currentSortOrder = 'a';
}
currentSort = sortOn;
candidateNodes.forEach(function(n) {
if (n.id === node.id) {
return;
}
nodeList.data('currentSort',currentSort);
nodeList.data('currentSortOrder',currentSortOrder);
var isChecked = scope.indexOf(n.id) !== -1;
$("#node-input-catch-target-container-div .fa").hide();
$(".node-input-catch-sort-"+currentSort+"-"+currentSortOrder).show();
allChecked = allChecked && isChecked;
var nodeDef = RED.nodes.getType(n.type);
var label;
var sublabel;
if (nodeDef) {
var l = nodeDef.label;
label = (typeof l === "function" ? l.call(n) : l)||"";
sublabel = n.type;
if (sublabel.indexOf("subflow:") === 0) {
var subflowId = sublabel.substring(8);
var subflow = RED.nodes.subflow(subflowId);
sublabel = "subflow : "+subflow.name;
}
}
if (!nodeDef || !label) {
label = n.type;
}
nodeItemMap[n.id] = {
node: n,
label: label,
sublabel: sublabel,
selected: isChecked
};
items.push(nodeItemMap[n.id]);
});
dirList.treeList('data',items);
var items = nodeList.find("li").get();
items.sort(function(a,b) {
var labelA = $(a).find(".node-input-target-node-"+currentSort).text().toLowerCase();
var labelB = $(b).find(".node-input-target-node-"+currentSort).text().toLowerCase();
if (labelA < labelB) { return currentSortOrder==='a'?-1:1; }
if (labelA > labelB) { return currentSortOrder==='a'?1:-1; }
return 0;
});
$.each(items, function(i, li){
nodeList.append(li);
});
}
$("#node-input-target-sort-label").on("click", function(e) {
$("#node-input-catch-target-select").on("click", function(e) {
e.preventDefault();
sortNodeList('label');
});
$("#node-input-target-sort-type").on("click", function(e) {
e.preventDefault();
sortNodeList('sublabel');
});
$("#node-input-target-node-checkbox-all").on("change", function() {
$(".node-input-target-node-checkbox").prop('checked',this.checked);
});
var preselected = dirList.treeList('selected').map(function(n) {return n.node.id});
RED.tray.hide();
RED.view.selectNodes({
selected: preselected,
onselect: function(selection) {
RED.tray.show();
var newlySelected = {};
selection.forEach(function(n) {
newlySelected[n.id] = true;
if (nodeItemMap[n.id]) {
nodeItemMap[n.id].treeList.select(true);
}
})
preselected.forEach(function(id) {
if (!newlySelected[id]) {
nodeItemMap[id].treeList.select(false);
}
})
},
oncancel: function() {
RED.tray.show();
},
filter: function(n) {
return n.id !== node.id;
}
});
})
$("#node-input-scope-select").on("change", function(e) {
var scope = $(this).val();
if (scope === "target") {
createNodeList();
$(".node-input-target-row").show();
$(".node-input-uncaught-row").hide();
} else {
$(".node-input-target-row").hide();
$(".node-input-uncaught-row").show();
}
node.resize();
node._resize();
});
if (this.scope === null) {
$("#node-input-scope-select").val("all");
@@ -241,17 +164,11 @@
this.scope = null;
} else {
$("#node-input-uncaught").prop("checked",false);
var node = this;
node.scope = [];
$(".node-input-target-node-checkbox").each(function(n) {
if ($(this).prop("checked")) {
node.scope.push($(this).data('node-id'));
}
});
this.scope = $("#node-input-catch-target-container-div").treeList('selected').map(function(i) { return i.node.id})
}
},
oneditresize: function(size) {
this.resize();
this._resize();
}
});
</script>

View File

@@ -7,17 +7,11 @@
<option value="target" data-i18n="status.scope.selected"></options>
</select>
</div>
<div class="form-row node-input-target-row" style="display: none;">
<div id="node-input-status-target-container-div" style=" min-height: 100px;position: relative; box-sizing: border-box; border-radius: 2px; height: 180px; border: 1px solid #ccc;overflow:hidden; ">
<div style="box-sizing: border-box; line-height: 20px; font-size: 0.8em; border-bottom: 1px solid #ddd; height: 20px;">
<input type="checkbox" data-i18n="[title]status.label.selectAll" id="node-input-target-node-checkbox-all" style="width: 30px; margin: 0 2px 1px 2px;">
<div style="display: inline-block;"><a id="node-input-target-sort-label" href="#" data-i18n="[title]status.label.sortByLabel"><span data-i18n="status.label.node"></span> <i class="node-input-status-sort-label-a fa fa-caret-down"></i><i class="node-input-status-sort-label-d fa fa-caret-up"></i></a></div>
<div style="position: absolute; right: 10px; width: 50px; display: inline-block; text-align: right;"><a id="node-input-target-sort-type" href="#" data-i18n="[title]status.label.sortByType"><i class="node-input-status-sort-sublabel-a fa fa-caret-down"></i><i class="node-input-status-sort-sublabel-d fa fa-caret-up"></i> <span data-i18n="status.label.type"></span></a></div>
</div>
<div style="background: #fbfbfb; box-sizing: border-box; position:absolute; top:20px;bottom:0;left:0px;right:0px; overflow-y: scroll; overflow-x: hidden;">
<ul id="node-input-status-target-container" style=" list-style-type:none; margin: 0;"></ul>
</div>
</div>
<div class="form-row node-input-target-row">
<button id="node-input-status-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
</div>
<div class="form-row node-input-target-row node-input-target-list-row" style="min-height: 100px">
<div id="node-input-status-target-container-div"></div>
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
@@ -25,50 +19,17 @@
</div>
</script>
<style>
#node-input-status-target-container {
position: relative;
}
#node-input-status-target-container li {
padding: 2px 5px;
background: none;
font-size: 0.8em;
margin:0;
white-space: nowrap;
}
#node-input-status-target-container li label {
margin-bottom: 0;
width: 100%;
}
#node-input-status-target-container li label input {
vertical-align: top;
width:15px;
margin-right: 10px;
}
#node-input-status-target-container li:hover,
#node-input-status-target-container li:hover .node-input-target-node-sublabel {
background: #f0f0f0;
}
.node-input-target-node-sublabel {
position:absolute;
right: 0px;
padding-right: 10px;
padding-left: 10px;
font-size: 0.8em;
background: #fbfbfb;
}
</style>
<script type="text/javascript">
RED.nodes.registerType('status',{
category: 'input',
color:"#c0edc0",
color:"#d9f4fd",
defaults: {
name: {value:""},
scope: {value:null}
},
inputs:0,
outputs:1,
icon: "alert.png",
icon: "alert.svg",
label: function() {
return this.name||(this.scope?this._("status.statusNodes",{number:this.scope.length}):this._("status.status"));
},
@@ -76,142 +37,105 @@
return this.name?"node_label_italic":"";
},
oneditprepare: function() {
var nodeList = $("#node-input-status-target-container");
var node = this;
this.resize = function() {
var rows = $("#dialog-form>div:not(.node-input-target-row)");
var scope = node.scope || [];
this._resize = function() {
var rows = $("#dialog-form>div:not(.node-input-target-list-row)");
var height = $("#dialog-form").height();
for (var i=0;i<rows.length;i++) {
height -= $(rows[i]).outerHeight(true);
}
var editorRow = $("#dialog-form>div.node-input-target-row");
height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
$("#node-input-status-target-container-div").css("height",height+"px");
var editorRow = $("#dialog-form>div.node-input-target-list-row");
editorRow.css("height",height+"px");
};
function createNodeList() {
var scope = node.scope || [];
nodeList.empty();
var dirList = $("#node-input-status-target-container-div").css({width: "100%", height: "100%"})
.treeList({multi:true}).on("treelistitemmouseover", function(e, item) {
item.node.highlighted = true;
item.node.dirty = true;
RED.view.redraw();
}).on("treelistitemmouseout", function(e, item) {
item.node.highlighted = false;
item.node.dirty = true;
RED.view.redraw();
})
var candidateNodes = RED.nodes.filterNodes({z:node.z});
var allChecked = true;
var items = [];
var nodeItemMap = {};
var candidateNodes = RED.nodes.filterNodes({z:node.z});
var allChecked = true;
candidateNodes.forEach(function(n) {
if (n.id === node.id) {
return;
}
var isChecked = scope.indexOf(n.id) !== -1;
allChecked = allChecked && isChecked;
var container = $('<li/>',{class:"node-input-target-node"});
var row = $('<label/>',{for:"node-input-target-node-"+n.id}).appendTo(container);
$('<input>',{type:"checkbox",class:"node-input-target-node-checkbox",id:"node-input-target-node-"+n.id})
.data('node-id',n.id)
.prop('checked', isChecked)
.appendTo(row);
container.on('mouseover',function(e) {
n.highlighted = true;
n.dirty = true;
RED.view.redraw();
});
container.on('mouseout',function(e) {
n.highlighted = false;
n.dirty = true;
RED.view.redraw();
});
var labelSpan = $('<span>');
var nodeDef = RED.nodes.getType(n.type);
var label;
var sublabel;
if (nodeDef) {
var l = nodeDef.label;
label = (typeof l === "function" ? l.call(n) : l)||"";
sublabel = n.type;
if (sublabel.indexOf("subflow:") === 0) {
var subflowId = sublabel.substring(8);
var subflow = RED.nodes.subflow(subflowId);
sublabel = "subflow : "+subflow.name;
}
}
if (!nodeDef || !label) {
label = n.type;
}
$('<span>',{class:"node-input-target-node-label",style:"white-space:nowrap"}).text(label).appendTo(row);
if (sublabel) {
$('<span>',{class:"node-input-target-node-sublabel"}).text(sublabel).appendTo(row);
}
container.appendTo(nodeList);
});
$(".node-input-target-node-checkbox").on("change", function() {
if (!this.checked) {
$("#node-input-target-node-checkbox-all").prop('checked',false);
}
});
$("#node-input-target-node-checkbox-all").prop('checked',allChecked);
sortNodeList('label');
}
function sortNodeList(sortOn) {
var currentSort = nodeList.data('currentSort');
var currentSortOrder = nodeList.data('currentSortOrder');
if (!currentSort) {
currentSort = sortOn;
currentSortOrder = 'a';
} else {
if (currentSort === sortOn) {
currentSortOrder = (currentSortOrder === 'a'?'d':'a');
} else {
currentSortOrder = 'a';
}
currentSort = sortOn;
candidateNodes.forEach(function(n) {
if (n.id === node.id) {
return;
}
nodeList.data('currentSort',currentSort);
nodeList.data('currentSortOrder',currentSortOrder);
var isChecked = scope.indexOf(n.id) !== -1;
$("#node-input-status-target-container-div .fa").hide();
$(".node-input-status-sort-"+currentSort+"-"+currentSortOrder).show();
allChecked = allChecked && isChecked;
var nodeDef = RED.nodes.getType(n.type);
var label;
var sublabel;
if (nodeDef) {
var l = nodeDef.label;
label = (typeof l === "function" ? l.call(n) : l)||"";
sublabel = n.type;
if (sublabel.indexOf("subflow:") === 0) {
var subflowId = sublabel.substring(8);
var subflow = RED.nodes.subflow(subflowId);
sublabel = "subflow : "+subflow.name;
}
}
if (!nodeDef || !label) {
label = n.type;
}
nodeItemMap[n.id] = {
node: n,
label: label,
sublabel: sublabel,
selected: isChecked
};
items.push(nodeItemMap[n.id]);
});
dirList.treeList('data',items);
var items = nodeList.find("li").get();
items.sort(function(a,b) {
var labelA = $(a).find(".node-input-target-node-"+currentSort).text().toLowerCase();
var labelB = $(b).find(".node-input-target-node-"+currentSort).text().toLowerCase();
if (labelA < labelB) { return currentSortOrder==='a'?-1:1; }
if (labelA > labelB) { return currentSortOrder==='a'?1:-1; }
return 0;
});
$.each(items, function(i, li) {
nodeList.append(li);
});
}
$("#node-input-target-sort-label").on("click", function(e) {
$("#node-input-status-target-select").on("click", function(e) {
e.preventDefault();
sortNodeList('label');
});
$("#node-input-target-sort-type").on("click", function(e) {
e.preventDefault();
sortNodeList('sublabel');
});
$("#node-input-target-node-checkbox-all").on("change", function() {
$(".node-input-target-node-checkbox").prop('checked',this.checked);
});
var preselected = dirList.treeList('selected').map(function(n) {return n.node.id});
RED.tray.hide();
RED.view.selectNodes({
selected: preselected,
onselect: function(selection) {
RED.tray.show();
var newlySelected = {};
selection.forEach(function(n) {
newlySelected[n.id] = true;
if (nodeItemMap[n.id]) {
nodeItemMap[n.id].treeList.select(true);
}
})
preselected.forEach(function(id) {
if (!newlySelected[id]) {
nodeItemMap[id].treeList.select(false);
}
})
},
oncancel: function() {
RED.tray.show();
},
filter: function(n) {
return n.id !== node.id;
}
});
})
$("#node-input-scope-select").on("change", function(e) {
var scope = $(this).val();
if (scope === "target") {
createNodeList();
$(".node-input-target-row").show();
} else {
$(".node-input-target-row").hide();
}
node.resize();
node._resize();
});
if (this.scope === null) {
$("#node-input-scope-select").val("all");
@@ -225,17 +149,11 @@
if (scope === 'all') {
this.scope = null;
} else {
var node = this;
node.scope = [];
$(".node-input-target-node-checkbox").each(function(n) {
if ($(this).prop("checked")) {
node.scope.push($(this).data('node-id'));
}
});
this.scope = $("#node-input-status-target-container-div").treeList('selected').map(function(i) { return i.node.id})
}
},
oneditresize: function(size) {
this.resize();
this._resize();
}
});
</script>

View File

@@ -65,7 +65,7 @@
color:"#87a980",
inputs:1,
outputs:0,
icon: "debug.png",
icon: "debug.svg",
align: "right",
button: {
toggle: "active",
@@ -205,6 +205,7 @@
}
};
RED.events.on("project:change", this.clearMessageList);
RED.actions.add("core:clear-debug-messages", function() { RED.debug.clearMessageList(true) });
$("#red-ui-sidebar-debug-open").on("click", function(e) {
e.preventDefault();
@@ -246,7 +247,8 @@
RED.sidebar.removeTab("debug");
RED.events.off("workspace:change", this.refreshMessageList);
window.removeEventListener("message",this.handleWindowMessage);
RED.actions.remove("core:show-debug");
RED.actions.remove("core:show-debug-tab");
RED.actions.remove("core:clear-debug-messages");
delete RED._debug;
},

View File

@@ -170,7 +170,7 @@
},
inputs:0,
outputs:1,
icon: "link-out.png",
icon: "link-out.svg",
outputLabels: function(i) {
return this.name||this._("link.linkIn");
},
@@ -200,7 +200,7 @@
align:"right",
inputs:1,
outputs:0,
icon: "link-out.png",
icon: "link-out.svg",
inputLabels: function(i) {
return this.name||this._("link.linkOut");
},

View File

@@ -73,7 +73,7 @@
this._("exec.label.retcode")
][i];
},
icon: "arrow-in.png",
icon: "arrow-in.svg",
align: "right",
label: function() {
return this.name||this.command||(this.useSpawn=="true"?this._("exec.spawn"):this._("exec.exec"));

View File

@@ -27,11 +27,11 @@
name: {value:""},
func: {value:"\nreturn msg;"},
outputs: {value:1},
noerr: {value:0,required:true,validate:function(v) { return ((!v) || (v === 0)) ? true : false; }}
noerr: {value:0,required:true,validate:function(v) { return !v; }}
},
inputs:1,
outputs:1,
icon: "function.png",
icon: "function.svg",
label: function() {
return this.name||this._("function.function");
},
@@ -75,10 +75,13 @@
type:"function", // the type of object the library is for
editor:this.editor, // the field name the main text body goes to
mode:"ace/mode/nrjavascript",
fields:['name','outputs']
fields:['name','outputs'],
ext:"js"
});
this.editor.focus();
RED.popover.tooltip($("#node-function-expand-js"), RED._("node-red:common.label.expand"));
$("#node-function-expand-js").on("click", function(e) {
e.preventDefault();
var value = that.editor.getValue();

View File

@@ -9,14 +9,6 @@
<input type="text" id="node-input-field" placeholder="payload" style="width:250px;">
<input type="hidden" id="node-input-fieldType">
</div>
<div class="form-row">
<label for="node-input-syntax"><i class="fa fa-code"></i> <span data-i18n="template.label.syntax"></span></label>
<select id="node-input-syntax" style="width:180px;">
<option value="mustache" data-i18n="template.label.mustache"></option>
<option value="plain" data-i18n="template.label.plain"></option>
</select>
</div>
<div class="form-row" style="position: relative; margin-bottom: 0px;">
<label for="node-input-template"><i class="fa fa-file-code-o"></i> <span data-i18n="template.label.template"></span></label>
<input type="hidden" id="node-input-template" autofocus="autofocus">
@@ -32,11 +24,19 @@
<option value="yaml">YAML</option>
<option value="text" data-i18n="template.label.none"></option>
</select>
<button id="node-template-expand-editor" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button>
</div>
</div>
<div class="form-row node-text-editor-row">
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-template-editor" ></div>
</div>
<div class="form-row">
<label for="node-input-syntax"><i class="fa fa-code"></i> <span data-i18n="template.label.syntax"></span></label>
<select id="node-input-syntax" style="width:180px;">
<option value="mustache" data-i18n="template.label.mustache"></option>
<option value="plain" data-i18n="template.label.plain"></option>
</select>
</div>
<div class="form-row">
<label for="node-input-output"><i class="fa fa-long-arrow-right"></i> <span data-i18n="template.label.output"></span></label>
<select id="node-input-output" style="width:180px;">
@@ -63,7 +63,7 @@
},
inputs:1,
outputs:1,
icon: "template.png",
icon: "template.svg",
label: function() {
return this.name||this._("template.template");;
},
@@ -95,10 +95,11 @@
value: $("#node-input-template").val()
});
RED.library.create({
url:"functions", // where to get the data from
type:"function", // the type of object the library is for
url:"templates", // where to get the data from
type:"template", // the type of object the library is for
editor:that.editor, // the field name the main text body goes to
fields:['name','outputs']
fields:['name','format','output','syntax'],
ext: "txt"
});
this.editor.focus();
@@ -109,6 +110,24 @@
v: Date.now()
});
});
RED.popover.tooltip($("#node-template-expand-editor"), RED._("node-red:common.label.expand"));
$("#node-template-expand-editor").on("click", function(e) {
e.preventDefault();
var value = that.editor.getValue();
RED.editor.editText({
mode: $("#node-input-format").val(),
value: value,
width: "Infinity",
cursor: that.editor.getCursorPosition(),
complete: function(v,cursor) {
that.editor.setValue(v, -1);
that.editor.gotoLine(cursor.row+1,cursor.column,false);
setTimeout(function() {
that.editor.focus();
},300);
}
})
})
},
oneditsave: function() {
$("#node-input-template").val(this.editor.getValue());

View File

@@ -114,7 +114,7 @@
},
inputs:1,
outputs:1,
icon: "timer.png",
icon: "timer.svg",
label: function() {
if (this.name) {
return this.name;

View File

@@ -87,7 +87,7 @@
},
inputs:1,
outputs:1,
icon: "trigger.png",
icon: "trigger.svg",
label: function() {
if (this.duration > 0) {
return this.name|| this._("trigger.label.trigger")+" "+this.duration+this.units;

View File

@@ -20,7 +20,7 @@
},
inputs:0,
outputs:0,
icon: "comment.png",
icon: "comment.svg",
label: function() {
return this.name||this._("comment.comment");
},

View File

@@ -400,48 +400,47 @@ RED.debug = (function() {
}
function processDebugMessage(o) {
var msg = document.createElement("div");
var msg = $("<div/>");
var sourceNode = o._source;
msg.onmouseenter = function() {
$(msg).addClass('red-ui-debug-msg-hover');
msg.on("mouseenter", function() {
msg.addClass('red-ui-debug-msg-hover');
if (o._source) {
config.messageMouseEnter(o._source.id);
if (o._source._alias) {
config.messageMouseEnter(o._source._alias);
}
}
};
msg.onmouseleave = function() {
$(msg).removeClass('red-ui-debug-msg-hover');
});
msg.on("mouseleave", function() {
msg.removeClass('red-ui-debug-msg-hover');
if (o._source) {
config.messageMouseLeave(o._source.id);
if (o._source._alias) {
config.messageMouseLeave(o._source._alias);
}
}
};
});
var name = sanitize(((o.name?o.name:o.id)||"").toString());
var topic = sanitize((o.topic||"").toString());
var property = sanitize(o.property?o.property:'');
var payload = o.msg;
var format = sanitize((o.format||"").toString());
msg.className = 'red-ui-debug-msg'+(o.level?(' red-ui-debug-msg-level-'+o.level):'')+
msg.attr("class", 'red-ui-debug-msg'+(o.level?(' red-ui-debug-msg-level-'+o.level):'')+
(sourceNode?(
" red-ui-debug-msg-node-"+sourceNode.id.replace(/\./g,"_")+
(sourceNode.z?" red-ui-debug-msg-flow-"+sourceNode.z.replace(/\./g,"_"):"")
):"");
):""));
if (sourceNode) {
$(msg).data('source',sourceNode.id);
msg.data('source',sourceNode.id);
if (filterType === "filterCurrent" && activeWorkspace) {
if (sourceNode.z && sourceNode.z.replace(/\./g,"_") !== activeWorkspace) {
$(msg).addClass('hide');
msg.addClass('hide');
}
} else if (filterType === 'filterSelected'){
if (!!filteredNodes[sourceNode.id]) {
$(msg).addClass('hide');
msg.addClass('hide');
}
}
}
@@ -481,7 +480,7 @@ RED.debug = (function() {
errorLvl = 30;
errorLvlType = 'warn';
}
$(msg).addClass('red-ui-debug-msg-level-' + errorLvl);
msg.addClass('red-ui-debug-msg-level-' + errorLvl);
$('<span class="red-ui-debug-msg-topic">function : (' + errorLvlType + ')</span>').appendTo(metaRow);
} else {
var tools = $('<span class="red-ui-debug-msg-tools button-group"></span>').appendTo(metaRow);

View File

@@ -4,7 +4,7 @@
<link rel="stylesheet" href="../../vendor/font-awesome/css/font-awesome.min.css">
<title>Node-RED Debug Tools</title>
</head>
<body class="red-ui-debug-window">
<body class="red-ui-editor red-ui-debug-window">
</body>
<script src="../../vendor/vendor.js"></script>
<script src="../../red/red.min.js"></script>

View File

@@ -57,7 +57,7 @@
color:"#d8bfd8",
inputs:0,
outputs:1,
icon: "bridge.png",
icon: "bridge.svg",
label: function() {
return this.name||this.topic||"mqtt";
},
@@ -118,7 +118,7 @@
color:"#d8bfd8",
inputs:1,
outputs:0,
icon: "bridge.png",
icon: "bridge.svg",
align: "right",
label: function() {
return this.name||this.topic||"mqtt";

View File

@@ -77,7 +77,7 @@
},
inputs:0,
outputs:1,
icon: "white-globe.png",
icon: "white-globe.svg",
label: function() {
if (this.name) {
return this.name;
@@ -152,7 +152,7 @@
inputs:1,
outputs:0,
align: "right",
icon: "white-globe.png",
icon: "white-globe.svg",
label: function() {
return this.name||("http"+(this.statusCode?" ("+this.statusCode+")":""));
},

View File

@@ -23,6 +23,7 @@ module.exports = function(RED) {
var cors = require('cors');
var onHeaders = require('on-headers');
var typer = require('content-type');
var mediaTyper = require('media-typer');
var isUtf8 = require('is-utf8');
var hashSum = require("hash-sum");
@@ -36,18 +37,22 @@ module.exports = function(RED) {
var checkUTF = false;
if (req.headers['content-type']) {
var parsedType = typer.parse(req.headers['content-type'])
if (parsedType.type === "text") {
isText = true;
} else if (parsedType.subtype === "xml" || parsedType.suffix === "xml") {
isText = true;
} else if (parsedType.type !== "application") {
isText = false;
} else if (parsedType.subtype !== "octet-stream") {
checkUTF = true;
} else {
// applicatino/octet-stream
isText = false;
var contentType = typer.parse(req.headers['content-type'])
if (contentType.type) {
var parsedType = mediaTyper.parse(contentType.type);
if (parsedType.type === "text") {
isText = true;
} else if (parsedType.subtype === "xml" || parsedType.suffix === "xml") {
isText = true;
} else if (parsedType.type !== "application") {
isText = false;
} else if (parsedType.subtype !== "octet-stream") {
checkUTF = true;
} else {
// applicatino/octet-stream
isText = false;
}
}
}

View File

@@ -49,12 +49,13 @@
<label for="node-input-useAuth" style="width: 70%;"><span data-i18n="httpin.basicauth"></span></label>
<div style="margin-left: 20px" class="node-input-useAuth-row hide">
<div class="form-row">
<label for="node-input-authType"><i class="fa fa-user-secret "></i> <span data-i18n="httpin.label.authType"></span></label>
<select type="text" id="node-input-authType" style="width:70%;">
<label for="node-input-authType-select"><i class="fa fa-user-secret "></i> <span data-i18n="httpin.label.authType"></span></label>
<select type="text" id="node-input-authType-select" style="width:70%;">
<option value="basic" data-i18n="httpin.basic"></option>
<option value="digest" data-i18n="httpin.digest"></option>
<option value="bearer" data-i18n="httpin.bearer"></option>
</select>
<input type="hidden" id="node-input-authType">
</div>
<div class="form-row node-input-basic-row">
<label for="node-input-user"><i class="fa fa-user"></i> <span data-i18n="common.label.username"></span></label>
@@ -102,7 +103,7 @@
url:{value:"",validate:function(v) { return (v.trim().length === 0) || (v.indexOf("://") === -1) || (v.trim().indexOf("http") === 0)} },
tls: {type:"tls-config",required: false},
proxy: {type:"http proxy",required: false},
authType: {value: "basic"}
authType: {value: ""}
},
credentials: {
user: {type:"text"},
@@ -117,7 +118,7 @@
obj: this._("httpin.label.jsonObject")
}[this.ret]);
},
icon: "white-globe.png",
icon: "white-globe.svg",
label: function() {
return this.name||this._("httpin.httpreq");
},
@@ -130,7 +131,7 @@
$(".node-input-useAuth-row").show();
// Nodes (< version 0.20.x) with credentials but without authentication type, need type 'basic'
if (!$('#node-input-authType').val()) {
$('#node-input-authType').val('basic');
$("#node-input-authType-select").val('basic').trigger("change");
}
} else {
$(".node-input-useAuth-row").hide();
@@ -139,12 +140,14 @@
$('#node-input-password').val('');
}
});
$("#node-input-authType").on("change", function() {
if ($(this).val() == "basic" || $(this).val() == "digest") {
$("#node-input-authType-select").on("change", function() {
var val = $(this).val();
$("#node-input-authType").val(val);
if (val === "basic" || val === "digest") {
$(".node-input-basic-row").show();
$('#node-span-password').show();
$('#node-span-token').hide();
} else if ($(this).val() == "bearer") {
} else if (val === "bearer") {
$(".node-input-basic-row").hide();
$('#node-span-password').hide();
$('#node-span-token').show();
@@ -158,8 +161,9 @@
$(".node-input-paytoqs-row").hide();
}
});
if (this.credentials.user || this.credentials.has_password) {
if (this.authType) {
$('#node-input-useAuth').prop('checked', true);
$("#node-input-authType-select").val(this.authType);
} else {
$('#node-input-useAuth').prop('checked', false);
}

View File

@@ -94,10 +94,10 @@ module.exports = function(RED) {
opts.maxRedirects = 21;
opts.jar = request.jar();
opts.proxy = null;
if (msg.requestTimeout) {
if (msg.requestTimeout !== undefined) {
if (isNaN(msg.requestTimeout)) {
node.warn(RED._("httpin.errors.timeout-isnan"));
} else if (msg.requestTimeout < 0) {
} else if (msg.requestTimeout < 1) {
node.warn(RED._("httpin.errors.timeout-isnegative"));
} else {
opts.timeout = msg.requestTimeout;
@@ -203,8 +203,28 @@ module.exports = function(RED) {
var payload = null;
if (method !== 'GET' && method !== 'HEAD' && typeof msg.payload !== "undefined") {
if (opts.headers['content-type'] == 'multipart/form-data' && typeof payload === "object") {
opts.formData = msg.payload;
if (opts.headers['content-type'] == 'multipart/form-data' && typeof msg.payload === "object") {
opts.formData = {};
for (var opt in msg.payload) {
if (msg.payload.hasOwnProperty(opt)) {
var val = msg.payload[opt];
if (val !== undefined && val !== null) {
if (typeof val === 'string' || Buffer.isBuffer(val)) {
opts.formData[opt] = val;
} else if (typeof val === 'object' && val.hasOwnProperty('value')) {
// Treat as file to upload - ensure it has an options object
// as request complains if it doesn't
if (!val.hasOwnProperty('options')) {
val.options = {};
}
opts.formData[opt] = val;
} else {
opts.formData[opt] = JSON.stringify(val);
}
}
}
}
} else {
if (typeof msg.payload === "string" || Buffer.isBuffer(msg.payload)) {
payload = msg.payload;

View File

@@ -106,7 +106,7 @@
color:"rgb(215, 215, 160)",
inputs:0,
outputs:1,
icon: "white-globe.png",
icon: "white-globe.svg",
labelStyle: function() {
return this.name?"node_label_italic":"";
},
@@ -125,7 +125,7 @@
color:"rgb(215, 215, 160)",
inputs:1,
outputs:0,
icon: "white-globe.png",
icon: "white-globe.svg",
align: "right",
labelStyle: function() {
return this.name?"node_label_italic":"";

View File

@@ -178,6 +178,9 @@ module.exports = function(RED) {
if (this.wholemsg) {
try {
msg = JSON.parse(data);
if (typeof msg !== "object" && !Array.isArray(msg) && (msg !== null)) {
msg = { payload:msg };
}
}
catch(err) {
msg = { payload:data };
@@ -194,20 +197,23 @@ module.exports = function(RED) {
}
WebSocketListenerNode.prototype.broadcast = function(data) {
try {
if (this.isServer) {
for (let client in this._clients) {
if (this._clients.hasOwnProperty(client)) {
if (this.isServer) {
for (let client in this._clients) {
if (this._clients.hasOwnProperty(client)) {
try {
this._clients[client].send(data);
} catch(err) {
this.warn(RED._("websocket.errors.send-error")+" "+client+" "+err.toString())
}
}
}
else {
this.server.send(data);
}
}
catch(e) { // swallow any errors
this.warn("ws:"+i+" : "+e);
else {
try {
this.server.send(data);
} catch(err) {
this.warn(RED._("websocket.errors.send-error")+" "+err.toString())
}
}
}

View File

@@ -42,7 +42,7 @@
color:"BurlyWood",
inputs:0,
outputs:1,
icon: "watch.png",
icon: "watch.svg",
label: function() {
return this.name||this.files||this._("watch.watch");
},

View File

@@ -72,7 +72,7 @@
},
inputs:0,
outputs:1,
icon: "bridge-dash.png",
icon: "bridge-dash.svg",
label: function() {
return this.name || "tcp:"+(this.host?this.host+":":"")+this.port;
},
@@ -155,7 +155,7 @@
},
inputs:1,
outputs:0,
icon: "bridge-dash.png",
icon: "bridge-dash.svg",
align: "right",
label: function() {
return this.name || "tcp:"+(this.host?this.host+":":"")+this.port;
@@ -226,7 +226,7 @@
},
inputs:1,
outputs:1,
icon: "bridge-dash.png",
icon: "bridge-dash.svg",
label: function() {
return this.name || "tcp:"+(this.server?this.server+":":"")+this.port;
},

View File

@@ -70,7 +70,7 @@
},
inputs:0,
outputs:1,
icon: "bridge-dash.png",
icon: "bridge-dash.svg",
label: function() {
if (this.multicast=="false") {
return this.name||"udp "+this.port;
@@ -173,7 +173,7 @@
},
inputs:1,
outputs:0,
icon: "bridge-dash.png",
icon: "bridge-dash.svg",
align: "right",
label: function() {
return this.name||"udp "+(this.addr+":"+this.port);

View File

@@ -117,7 +117,7 @@
return label;
}
},
icon: "switch.png",
icon: "switch.svg",
label: function() {
return this.name||this._("switch.switch");
},
@@ -128,7 +128,7 @@
var node = this;
var previousValueType = {value:"prev",label:this._("inject.previous"),hasValue:false};
$("#node-input-property").typedInput({default:this.propertyType||'msg',types:['msg','flow','global','jsonata']});
$("#node-input-property").typedInput({default:this.propertyType||'msg',types:['msg','flow','global','jsonata','env']});
var outputCount = $("#node-input-outputs").val("{}");
var andLabel = this._("switch.and");

View File

@@ -28,7 +28,7 @@
},
inputs: 1,
outputs: 1,
icon: "swap.png",
icon: "swap.svg",
label: function() {
function prop2name(type, key) {
var result = RED.utils.parseContextKey(key);

View File

@@ -52,7 +52,7 @@
},
inputs: 1,
outputs: 1,
icon: "range.png",
icon: "range.svg",
label: function() {
if (this.minout !== "" && this.maxout !== "") { return this.name||this.minout + " - " + this.maxout; }
else { return this.name||this._("range.range"); }

View File

@@ -61,7 +61,7 @@
},
inputs:1,
outputs:1,
icon: "split.png",
icon: "split.svg",
label: function() {
return this.name||this._("split.split");
},
@@ -218,7 +218,7 @@
},
inputs:1,
outputs:1,
icon: "join.png",
icon: "join.svg",
label: function() {
return this.name||this._("join.join");
},

View File

@@ -572,6 +572,8 @@ module.exports = function(RED) {
}
}
if (msg.hasOwnProperty("reset")) { if (inflight[partId]) { delete inflight[partId] }; return; }
if ((payloadType === 'object') && (propertyKey === null || propertyKey === undefined || propertyKey === "")) {
if (node.mode === "auto") {
node.warn("Message missing 'msg.parts.key' property - cannot add to object");
@@ -590,7 +592,6 @@ module.exports = function(RED) {
return;
}
if (msg.hasOwnProperty("reset")) { if (inflight[partid]) { delete inflight[partId] } return; }
if (!inflight.hasOwnProperty(partId)) {
if (payloadType === 'object' || payloadType === 'merged') {
inflight[partId] = {
@@ -627,11 +628,13 @@ module.exports = function(RED) {
var group = inflight[partId];
if (payloadType === 'buffer') {
inflight[partId].bufferLen += property.length;
if (property !== undefined) {
inflight[partId].bufferLen += property.length;
}
}
if (payloadType === 'object') {
group.payload[propertyKey] = property;
group.currentCount = (group.currentCount || 0) + 1;
group.currentCount = Object.keys(group.payload).length;
} else if (payloadType === 'merged') {
if (Array.isArray(property) || typeof property !== 'object') {
if (!msg.hasOwnProperty("complete")) {

View File

@@ -75,7 +75,7 @@
},
inputs:1,
outputs:1,
icon: "sort.png",
icon: "sort.svg",
label: function() {
return this.name||this._("sort.sort");
},

View File

@@ -81,7 +81,7 @@
},
inputs:1,
outputs:1,
icon: "batch.png",
icon: "batch.svg",
label: function() {
return this.name||this._("batch.batch");;
},

View File

@@ -24,7 +24,7 @@
</div>
<hr align="middle"/>
<div class="form-row">
<label style="width:100%; border-bottom:1px solid #eee;"><span data-i18n="csv.label.c2o"></span></label>
<label style="width:100%;"><span data-i18n="csv.label.c2o"></span></label>
</div>
<div class="form-row" style="padding-left:20px;">
<label><i class="fa fa-sign-in"></i> <span data-i18n="csv.label.input"></span></label>
@@ -42,7 +42,7 @@
</select>
</div>
<div class="form-row" style="margin-top:20px">
<label style="width:100%; border-bottom:1px solid #eee;"><span data-i18n="csv.label.o2c"></span></label>
<label style="width:100%;"><span data-i18n="csv.label.o2c"></span></label>
</div>
<div class="form-row" style="padding-left:20px;">
<label><i class="fa fa-sign-in"></i> <span data-i18n="csv.label.output"></span></label>
@@ -78,7 +78,7 @@
},
inputs:1,
outputs:1,
icon: "parser-csv.png",
icon: "parser-csv.svg",
label: function() {
return this.name||"csv";
},

View File

@@ -49,7 +49,7 @@
},
inputs:1,
outputs:1,
icon: "parser-html.png",
icon: "parser-html.svg",
label: function() {
return this.name||this.tag||"html";
},

View File

@@ -18,7 +18,7 @@
</div>
<hr align="middle"/>
<div class="form-row node-json-to-json-options">
<label style="width:100%; border-bottom: 1px solid #eee;"><span data-i18n="json.label.o2j"></span></label>
<label style="width:100%;"><span data-i18n="json.label.o2j"></span></label>
</div>
<div class="form-row node-json-to-json-options" style="padding-left: 20px;">
<input style="width:20px; vertical-align:top; margin-right: 5px;" type="checkbox" id="node-input-pretty"><label style="width: auto;" for="node-input-pretty" data-i18n="json.label.pretty"></span>
@@ -37,7 +37,7 @@
},
inputs:1,
outputs:1,
icon: "parser-json.png",
icon: "parser-json.svg",
label: function() {
return this.name||"json";
},

View File

@@ -10,7 +10,7 @@
</div>
<hr align="middle"/>
<div class="form-row">
<label style="width:100%; border-bottom: 1px solid #eee;"><span data-i18n="xml.label.x2o"></span></label>
<label style="width:100%;"><span data-i18n="xml.label.x2o"></span></label>
</div>
<div class="form-row" style="padding-left: 20px;">
<label style="width:250px;" for="node-input-attr" data-i18n="xml.label.represent"></label> <input type="text" id="node-input-attr" style="text-align:center; width:40px" placeholder="$">
@@ -32,7 +32,7 @@
},
inputs:1,
outputs:1,
icon: "parser-xml.png",
icon: "parser-xml.svg",
label: function() {
return this.name||"xml";
},

View File

@@ -20,7 +20,7 @@
},
inputs:1,
outputs:1,
icon: "parser-yaml.png",
icon: "parser-yaml.svg",
label: function() {
return this.name||"yaml";
},

View File

@@ -205,7 +205,7 @@
color:"BurlyWood",
inputs:1,
outputs:1,
icon: "file-out.png",
icon: "file-out.svg",
label: function() {
if (this.overwriteFile === "delete") {
return this.name||this._("file.label.deletelabel",{file:this.filename});
@@ -273,7 +273,7 @@
outputLabels: function(i) {
return (this._((this.format === "utf8") ? "file.label.utf8String" : "file.label.binaryBuffer"));
},
icon: "file-in.png",
icon: "file-in.svg",
label: function() {
return this.name||this.filename||this._("file.label.filelabel");
},