1
0
mirror of https://github.com/node-red/node-red.git synced 2023-10-10 13:36:53 +02:00

merge master

This commit is contained in:
Hiroyasu Nishiyama 2022-09-13 10:52:48 +09:00
commit 954649007c
18 changed files with 135 additions and 66 deletions

View File

@ -936,6 +936,9 @@
"invalid-expr": "Invalid JSONata expression:\n __message__", "invalid-expr": "Invalid JSONata expression:\n __message__",
"invalid-msg": "Invalid example JSON message:\n __message__", "invalid-msg": "Invalid example JSON message:\n __message__",
"context-unsupported": "Cannot test context functions\n $flowContext or $globalContext", "context-unsupported": "Cannot test context functions\n $flowContext or $globalContext",
"env-unsupported": "Cannot test $env function",
"moment-unsupported": "Cannot test $moment function",
"clone-unsupported": "Cannot test $clone function",
"eval": "Error evaluating expression:\n __message__" "eval": "Error evaluating expression:\n __message__"
} }
}, },

View File

@ -936,6 +936,9 @@
"invalid-expr": "不正なJSONata式:\n __message__", "invalid-expr": "不正なJSONata式:\n __message__",
"invalid-msg": "不正なJSONメッセージ例:\n __message__", "invalid-msg": "不正なJSONメッセージ例:\n __message__",
"context-unsupported": "$flowContext や $globalContextの\nコンテキスト関数をテストできません", "context-unsupported": "$flowContext や $globalContextの\nコンテキスト関数をテストできません",
"env-unsupported": "$env関数はテストできません",
"moment-unsupported": "$moment関数はテストできません",
"clone-unsupported": "$clone関数はテストできません",
"eval": "式評価エラー:\n __message__" "eval": "式評価エラー:\n __message__"
} }
}, },

View File

@ -100,7 +100,7 @@ RED.editor.codeEditor.monaco = (function() {
"node-red-util": {package: "node-red", module: "util", path: "node-red/util.d.ts" }, "node-red-util": {package: "node-red", module: "util", path: "node-red/util.d.ts" },
"node-red-func": {package: "node-red", module: "func", path: "node-red/func.d.ts" }, "node-red-func": {package: "node-red", module: "func", path: "node-red/func.d.ts" },
} }
const defaultServerSideTypes = [ knownModules["node-red-util"], knownModules["node-red-func"], knownModules["globals"], knownModules["console"], knownModules["buffer"] ]; const defaultServerSideTypes = [ knownModules["node-red-util"], knownModules["node-red-func"], knownModules["globals"], knownModules["console"], knownModules["buffer"] , knownModules["util"] ];
const modulesCache = {}; const modulesCache = {};

View File

@ -255,6 +255,9 @@
var currentExpression = expressionEditor.getValue(); var currentExpression = expressionEditor.getValue();
var expr; var expr;
var usesContext = false; var usesContext = false;
var usesEnv = false;
var usesMoment = false;
var usesClone = false;
var legacyMode = /(^|[^a-zA-Z0-9_'".])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression); var legacyMode = /(^|[^a-zA-Z0-9_'".])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression);
$(".red-ui-editor-type-expression-legacy").toggle(legacyMode); $(".red-ui-editor-type-expression-legacy").toggle(legacyMode);
try { try {
@ -267,6 +270,18 @@
usesContext = true; usesContext = true;
return null; return null;
}); });
expr.assign("env", function(name) {
usesEnv = true;
return null;
});
expr.assign("moment", function(name) {
usesMoment = true;
return null;
});
expr.assign("clone", function(name) {
usesClone = true;
return null;
});
} catch(err) { } catch(err) {
testResultEditor.setValue(RED._("expressionEditor.errors.invalid-expr",{message:err.message}),-1); testResultEditor.setValue(RED._("expressionEditor.errors.invalid-expr",{message:err.message}),-1);
return; return;
@ -284,6 +299,18 @@
testResultEditor.setValue(RED._("expressionEditor.errors.context-unsupported"),-1); testResultEditor.setValue(RED._("expressionEditor.errors.context-unsupported"),-1);
return; return;
} }
if (usesEnv) {
testResultEditor.setValue(RED._("expressionEditor.errors.env-unsupported"),-1);
return;
}
if (usesMoment) {
testResultEditor.setValue(RED._("expressionEditor.errors.moment-unsupported"),-1);
return;
}
if (usesClone) {
testResultEditor.setValue(RED._("expressionEditor.errors.clone-unsupported"),-1);
return;
}
var formattedResult; var formattedResult;
if (result !== undefined) { if (result !== undefined) {

View File

@ -175,9 +175,19 @@ RED.palette = (function() {
$('<button type="button" onclick="RED.workspaces.show(\''+type.substring(8).replace(/'/g,"\\'")+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-pencil"></i></button>').appendTo(popOverContent) $('<button type="button" onclick="RED.workspaces.show(\''+type.substring(8).replace(/'/g,"\\'")+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-pencil"></i></button>').appendTo(popOverContent)
} }
var safeType = type.replace(/'/g,"\\'"); const safeType = type.replace(/'/g,"\\'");
const wrapStr = function (str) {
if(str.indexOf(' ') >= 0) {
return '"' + str + '"'
}
return str
}
$('<button type="button" onclick="RED.search.show(\'type:'+safeType+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-search"></i></button>').appendTo(popOverContent) $('<button type="button"; return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-search"></i></button>')
.appendTo(popOverContent)
.on('click', function() {
RED.search.show('type:' + wrapStr(safeType))
})
$('<button type="button" onclick="RED.sidebar.help.show(\''+safeType+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-book"></i></button>').appendTo(popOverContent) $('<button type="button" onclick="RED.sidebar.help.show(\''+safeType+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-book"></i></button>').appendTo(popOverContent)
$('<p>',{style:"font-size: 0.8em"}).text(metaData).appendTo(popOverContent); $('<p>',{style:"font-size: 0.8em"}).text(metaData).appendTo(popOverContent);

View File

@ -545,7 +545,7 @@ RED.projects = (function() {
var sshwarningRow = $('<div class="red-ui-projects-dialog-screen-create-row-auth-error-no-keys"></div>').hide().appendTo(subrow); var sshwarningRow = $('<div class="red-ui-projects-dialog-screen-create-row-auth-error-no-keys"></div>').hide().appendTo(subrow);
$('<div class="form-row"><i class="fa fa-warning"></i> '+RED._("projects.clone-project.ssh-key-desc")+'</div>').appendTo(sshwarningRow); $('<div class="form-row"><i class="fa fa-warning"></i> '+RED._("projects.clone-project.ssh-key-desc")+'</div>').appendTo(sshwarningRow);
subrow = $('<div style="text-align: center">').appendTo(sshwarningRow); subrow = $('<div style="text-align: center">').appendTo(sshwarningRow);
$('<button class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.clone-project.ssh-key-add")+'</button>').appendTo(subrow).on("click", function(e) { $('<button type="button" class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.clone-project.ssh-key-add")+'</button>').appendTo(subrow).on("click", function(e) {
e.preventDefault(); e.preventDefault();
dialog.dialog( "close" ); dialog.dialog( "close" );
RED.userSettings.show('gitconfig'); RED.userSettings.show('gitconfig');
@ -1171,11 +1171,11 @@ RED.projects = (function() {
row = $('<div class="form-row button-group"></div>').appendTo(container); row = $('<div class="form-row button-group"></div>').appendTo(container);
var openProject = $('<button data-type="open" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-folder-open"></i><br/>'+RED._("projects.create.open")+'</button>').appendTo(row); var openProject = $('<button type="button" data-type="open" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-folder-open"></i><br/>'+RED._("projects.create.open")+'</button>').appendTo(row);
var createAsEmpty = $('<button data-type="empty" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-asterisk"></i><br/>'+RED._("projects.create.create")+'</button>').appendTo(row); var createAsEmpty = $('<button type="button" data-type="empty" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-asterisk"></i><br/>'+RED._("projects.create.create")+'</button>').appendTo(row);
// var createAsCopy = $('<button data-type="copy" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i class="fa fa-long-arrow-right fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Copy existing</button>').appendTo(row); // var createAsCopy = $('<button type="button" data-type="copy" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i class="fa fa-long-arrow-right fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Copy existing</button>').appendTo(row);
var createAsClone = $('<button data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-git"></i><br/>'+RED._("projects.create.clone")+'</button>').appendTo(row); var createAsClone = $('<button type="button" data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-git"></i><br/>'+RED._("projects.create.clone")+'</button>').appendTo(row);
// var createAsClone = $('<button data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-git fa-2x"></i><i class="fa fa-arrows-h fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Clone Repository</button>').appendTo(row); // var createAsClone = $('<button type="button" data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-git fa-2x"></i><i class="fa fa-arrows-h fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Clone Repository</button>').appendTo(row);
row.find(".red-ui-projects-dialog-screen-create-type").on("click", function(evt) { row.find(".red-ui-projects-dialog-screen-create-type").on("click", function(evt) {
evt.preventDefault(); evt.preventDefault();
container.find(".red-ui-projects-dialog-screen-create-type").removeClass('selected'); container.find(".red-ui-projects-dialog-screen-create-type").removeClass('selected');
@ -1271,7 +1271,7 @@ RED.projects = (function() {
var credentialsLeftBox = $('<div class="red-ui-projects-dialog-credentials-box-left">').appendTo(credentialsBox); var credentialsLeftBox = $('<div class="red-ui-projects-dialog-credentials-box-left">').appendTo(credentialsBox);
var credentialsEnabledBox = $('<div class="form-row red-ui-projects-dialog-credentials-box-enabled"></div>').appendTo(credentialsLeftBox); var credentialsEnabledBox = $('<div class="form-row red-ui-projects-dialog-credentials-box-enabled"></div>').appendTo(credentialsLeftBox);
$('<label class="red-ui-projects-edit-form-inline-label"><input type="radio" name="projects-encryption-type" value="enabled"> <i class="fa fa-lock"></i> <span>'+RED._("projects.encryption-config.enable")+'</span></label>').appendTo(credentialsEnabledBox); $('<label class="red-ui-projects-edit-form-inline-label"><input type="radio" name="projects-encryption-type" value="enabled" checked> <i class="fa fa-lock"></i> <span>'+RED._("projects.encryption-config.enable")+'</span></label>').appendTo(credentialsEnabledBox);
var credentialsDisabledBox = $('<div class="form-row red-ui-projects-dialog-credentials-box-disabled disabled"></div>').appendTo(credentialsLeftBox); var credentialsDisabledBox = $('<div class="form-row red-ui-projects-dialog-credentials-box-disabled disabled"></div>').appendTo(credentialsLeftBox);
$('<label class="red-ui-projects-edit-form-inline-label"><input type="radio" name="projects-encryption-type" value="disabled"> <i class="fa fa-unlock"></i> <span>'+RED._("projects.encryption-config.disable")+'</span></label>').appendTo(credentialsDisabledBox); $('<label class="red-ui-projects-edit-form-inline-label"><input type="radio" name="projects-encryption-type" value="disabled"> <i class="fa fa-unlock"></i> <span>'+RED._("projects.encryption-config.disable")+'</span></label>').appendTo(credentialsDisabledBox);
@ -1397,7 +1397,7 @@ RED.projects = (function() {
var sshwarningRow = $('<div class="red-ui-projects-dialog-screen-create-row-auth-error-no-keys"></div>').hide().appendTo(subrow); var sshwarningRow = $('<div class="red-ui-projects-dialog-screen-create-row-auth-error-no-keys"></div>').hide().appendTo(subrow);
$('<div class="form-row"><i class="fa fa-warning"></i> '+RED._("projects.create.desc2")+'</div>').appendTo(sshwarningRow); $('<div class="form-row"><i class="fa fa-warning"></i> '+RED._("projects.create.desc2")+'</div>').appendTo(sshwarningRow);
subrow = $('<div style="text-align: center">').appendTo(sshwarningRow); subrow = $('<div style="text-align: center">').appendTo(sshwarningRow);
$('<button class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.create.add-ssh-key")+'</button>').appendTo(subrow).on("click", function(e) { $('<button type="button" class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.create.add-ssh-key")+'</button>').appendTo(subrow).on("click", function(e) {
e.preventDefault(); e.preventDefault();
$('#red-ui-projects-dialog-cancel').trigger("click"); $('#red-ui-projects-dialog-cancel').trigger("click");
RED.userSettings.show('gitconfig'); RED.userSettings.show('gitconfig');
@ -1631,14 +1631,14 @@ RED.projects = (function() {
function deleteProject(row,name,done) { function deleteProject(row,name,done) {
var cover = $('<div class="red-ui-projects-dialog-project-list-entry-delete-confirm"></div>').on("click", function(evt) { evt.stopPropagation(); }).appendTo(row); var cover = $('<div class="red-ui-projects-dialog-project-list-entry-delete-confirm"></div>').on("click", function(evt) { evt.stopPropagation(); }).appendTo(row);
$('<span>').text(RED._("projects.delete.confirm")).appendTo(cover); $('<span>').text(RED._("projects.delete.confirm")).appendTo(cover);
$('<button class="red-ui-button red-ui-projects-dialog-button">'+RED._("common.label.cancel")+'</button>') $('<button type="button" class="red-ui-button red-ui-projects-dialog-button">'+RED._("common.label.cancel")+'</button>')
.appendTo(cover) .appendTo(cover)
.on("click", function(e) { .on("click", function(e) {
e.stopPropagation(); e.stopPropagation();
cover.remove(); cover.remove();
done(true); done(true);
}); });
$('<button class="red-ui-button red-ui-projects-dialog-button primary">'+RED._("common.label.delete")+'</button>') $('<button type="button" class="red-ui-button red-ui-projects-dialog-button primary">'+RED._("common.label.delete")+'</button>')
.appendTo(cover) .appendTo(cover)
.on("click", function(e) { .on("click", function(e) {
e.stopPropagation(); e.stopPropagation();
@ -1822,7 +1822,7 @@ RED.projects = (function() {
header.addClass("selectable"); header.addClass("selectable");
var tools = $('<div class="red-ui-projects-dialog-project-list-entry-tools"></div>').appendTo(header); var tools = $('<div class="red-ui-projects-dialog-project-list-entry-tools"></div>').appendTo(header);
$('<button class="red-ui-button red-ui-projects-dialog-button red-ui-button-small" style="float: right;"><i class="fa fa-trash"></i></button>') $('<button type="button" class="red-ui-button red-ui-projects-dialog-button red-ui-button-small" style="float: right;"><i class="fa fa-trash"></i></button>')
.appendTo(tools) .appendTo(tools)
.on("click", function(e) { .on("click", function(e) {
e.stopPropagation(); e.stopPropagation();

View File

@ -106,38 +106,51 @@ RED.search = (function() {
return val; return val;
} }
function search(val) { function extractType(val, flags) {
var results = []; // extracts: type:XYZ & type:"X Y Z"
var typeFilter; const regEx = /(?:type):\s*(?:"([^"]+)"|([^" ]+))/;
var m = /(?:^| )type:([^ ]+)/.exec(val); let m
if (m) { while ((m = regEx.exec(val)) !== null) {
val = val.replace(/(?:^| )type:[^ ]+/,""); // avoid infinite loops with zero-width matches
typeFilter = m[1]; if (m.index === regEx.lastIndex) {
regEx.lastIndex++;
} }
var flags = {}; val = val.replace(m[0]," ").trim()
const flag = m[2] || m[1] // quoted entries in capture group 1, unquoted in capture group 2
flags.type = flags.type || [];
flags.type.push(flag);
}
return val;
}
function search(val) {
const results = [];
const flags = {};
val = extractFlag(val,"invalid",flags); val = extractFlag(val,"invalid",flags);
val = extractFlag(val,"unused",flags); val = extractFlag(val,"unused",flags);
val = extractFlag(val,"config",flags); val = extractFlag(val,"config",flags);
val = extractFlag(val,"subflow",flags); val = extractFlag(val,"subflow",flags);
val = extractFlag(val,"hidden",flags); val = extractFlag(val,"hidden",flags);
val = extractFlag(val,"modified",flags); val = extractFlag(val,"modified",flags);
val = extractValue(val,"flow",flags);// flow:active or flow:<flow-id> val = extractValue(val,"flow",flags);// flow:current or flow:<flow-id>
val = extractValue(val,"uses",flags);// uses:<node-id> val = extractValue(val,"uses",flags);// uses:<node-id>
val = extractType(val,flags);// type:<node-type>
val = val.trim(); val = val.trim();
var hasFlags = Object.keys(flags).length > 0; const hasFlags = Object.keys(flags).length > 0;
const hasTypeFilter = flags.type && flags.type.length > 0
if (flags.flow && flags.flow.indexOf("current") >= 0) { if (flags.flow && flags.flow.indexOf("current") >= 0) {
let idx = flags.flow.indexOf("current"); let idx = flags.flow.indexOf("current");
flags.flow[idx] = RED.workspaces.active();//convert active to flow ID flags.flow[idx] = RED.workspaces.active();//convert 'current' to active flow ID
} }
if (flags.flow && flags.flow.length) { if (flags.flow && flags.flow.length) {
flags.flow = [ ...new Set(flags.flow) ]; //deduplicate flags.flow = [ ...new Set(flags.flow) ]; //deduplicate
} }
if (val.length > 0 || typeFilter || hasFlags) { if (val.length > 0 || hasFlags) {
val = val.toLowerCase(); val = val.toLowerCase();
var i; let i;
var j; let j;
var list = []; let list = [];
var nodes = {}; const nodes = {};
let keys = []; let keys = [];
if (flags.uses) { if (flags.uses) {
keys = flags.uses; keys = flags.uses;
@ -145,10 +158,10 @@ RED.search = (function() {
keys = Object.keys(index); keys = Object.keys(index);
} }
for (i=0;i<keys.length;i++) { for (i=0;i<keys.length;i++) {
var key = keys[i]; const key = keys[i];
var kpos = keys[i].indexOf(val); const kpos = val ? keys[i].indexOf(val) : -1;
if (kpos > -1) { if (kpos > -1 || (val === "" && hasFlags)) {
var ids = Object.keys(index[key]||{}); const ids = Object.keys(index[key]||{});
for (j=0;j<ids.length;j++) { for (j=0;j<ids.length;j++) {
var node = index[key][ids[j]]; var node = index[key][ids[j]];
var isConfigNode = node.node._def.category === "config" && node.node.type !== 'group'; var isConfigNode = node.node._def.category === "config" && node.node.type !== 'group';
@ -156,7 +169,7 @@ RED.search = (function() {
continue; continue;
} }
if (flags.hasOwnProperty("invalid")) { if (flags.hasOwnProperty("invalid")) {
var nodeIsValid = !node.node.hasOwnProperty("valid") || node.node.valid; const nodeIsValid = !node.node.hasOwnProperty("valid") || node.node.valid;
if (flags.invalid === nodeIsValid) { if (flags.invalid === nodeIsValid) {
continue; continue;
} }
@ -186,7 +199,7 @@ RED.search = (function() {
} }
} }
if (flags.hasOwnProperty("unused")) { if (flags.hasOwnProperty("unused")) {
var isUnused = (node.node.type === 'subflow' && node.node.instances.length === 0) || const isUnused = (node.node.type === 'subflow' && node.node.instances.length === 0) ||
(isConfigNode && node.node.users.length === 0 && node.node._def.hasUsers !== false) (isConfigNode && node.node.users.length === 0 && node.node._def.hasUsers !== false)
if (flags.unused !== isUnused) { if (flags.unused !== isUnused) {
continue; continue;
@ -197,12 +210,16 @@ RED.search = (function() {
continue; continue;
} }
} }
if (!typeFilter || node.node.type === typeFilter) { let typeIndex = -1
nodes[node.node.id] = nodes[node.node.id] = { if(hasTypeFilter) {
typeIndex = flags.type.indexOf(node.node.type)
}
if (!hasTypeFilter || typeIndex > -1) {
nodes[node.node.id] = nodes[node.node.id] || {
node: node.node, node: node.node,
label: node.label label: node.label
}; };
nodes[node.node.id].index = Math.min(nodes[node.node.id].index||Infinity,kpos); nodes[node.node.id].index = Math.min(nodes[node.node.id].index || Infinity, typeIndex > -1 ? typeIndex : kpos);
} }
} }
} }

View File

@ -14,6 +14,9 @@ declare var msg: NodeMessage;
/** @type {string} the id of the incoming `msg` (alias of msg._msgid) */ /** @type {string} the id of the incoming `msg` (alias of msg._msgid) */
declare const __msgid__:string; declare const __msgid__:string;
declare const util:typeof import('util')
declare const promisify:typeof import('util').promisify
/** /**
* @typedef NodeStatus * @typedef NodeStatus
* @type {object} * @type {object}

View File

@ -160,6 +160,7 @@
'$base64encode':{ args:[ ]}, '$base64encode':{ args:[ ]},
'$boolean':{ args:[ 'arg' ]}, '$boolean':{ args:[ 'arg' ]},
'$ceil':{ args:[ 'number' ]}, '$ceil':{ args:[ 'number' ]},
'$clone': { args:[ 'arg' ]},
'$contains':{ args:[ 'str', 'pattern' ]}, '$contains':{ args:[ 'str', 'pattern' ]},
'$count':{ args:[ 'array' ]}, '$count':{ args:[ 'array' ]},
'$decodeUrl':{ args:[ 'str' ]}, '$decodeUrl':{ args:[ 'str' ]},

View File

@ -1,6 +1,6 @@
<script type="text/html" data-template-name="complete"> <script type="text/html" data-template-name="complete">
<div class="form-row node-input-target-row"> <div class="form-row node-input-target-row">
<button id="node-input-complete-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button> <button type="button" id="node-input-complete-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
</div> </div>
<div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px"> <div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px">
<div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-complete-target-filter"></div> <div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-complete-target-filter"></div>

View File

@ -12,7 +12,7 @@
<label for="node-input-uncaught" style="width: auto" data-i18n="catch.label.uncaught"></label> <label for="node-input-uncaught" style="width: auto" data-i18n="catch.label.uncaught"></label>
</div> </div>
<div class="form-row node-input-target-row"> <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> <button type="button" id="node-input-catch-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
</div> </div>
<div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px"> <div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px">
<div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-catch-target-filter"></div> <div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-catch-target-filter"></div>

View File

@ -8,7 +8,7 @@
</select> </select>
</div> </div>
<div class="form-row node-input-target-row"> <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> <button type="button" id="node-input-status-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
</div> </div>
<div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px"> <div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px">
<div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-status-target-filter"></div> <div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-status-target-filter"></div>

View File

@ -91,21 +91,21 @@
<div id="func-tab-init" style="display:none"> <div id="func-tab-init" style="display:none">
<div class="form-row node-text-editor-row" style="position:relative"> <div class="form-row node-text-editor-row" style="position:relative">
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-init-editor" ></div> <div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-init-editor" ></div>
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-init-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div> <div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button type="button" id="node-init-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
</div> </div>
</div> </div>
<div id="func-tab-body" style="display:none"> <div id="func-tab-body" style="display:none">
<div class="form-row node-text-editor-row" style="position:relative"> <div class="form-row node-text-editor-row" style="position:relative">
<div style="height: 220px; min-height:150px;" class="node-text-editor" id="node-input-func-editor" ></div> <div style="height: 220px; min-height:150px;" class="node-text-editor" id="node-input-func-editor" ></div>
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-function-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div> <div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button type="button" id="node-function-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
</div> </div>
</div> </div>
<div id="func-tab-finalize" style="display:none"> <div id="func-tab-finalize" style="display:none">
<div class="form-row node-text-editor-row" style="position:relative"> <div class="form-row node-text-editor-row" style="position:relative">
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-finalize-editor" ></div> <div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-finalize-editor" ></div>
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-finalize-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div> <div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button type="button" id="node-finalize-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
</div> </div>
</div> </div>
@ -294,7 +294,7 @@
if (val === "_custom_") { if (val === "_custom_") {
val = $(this).val(); val = $(this).val();
} }
var varName = val.trim().replace(/^@/,"").replace(/@.*$/,"").replace(/[-_/].?/g, function(v) { return v[1]?v[1].toUpperCase():"" }); var varName = val.trim().replace(/^@/,"").replace(/@.*$/,"").replace(/[-_/\.].?/g, function(v) { return v[1]?v[1].toUpperCase():"" });
fvar.val(varName); fvar.val(varName);
fvar.trigger("change"); fvar.trigger("change");

View File

@ -26,7 +26,7 @@
<option value="yaml">YAML</option> <option value="yaml">YAML</option>
<option value="text" data-i18n="template.label.none"></option> <option value="text" data-i18n="template.label.none"></option>
</select> </select>
<button id="node-template-expand-editor" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button> <button type="button" id="node-template-expand-editor" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button>
</div> </div>
</div> </div>
<div class="form-row node-text-editor-row"> <div class="form-row node-text-editor-row">

View File

@ -25,7 +25,7 @@
<label class="red-ui-button" for="node-config-input-certfile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label> <label class="red-ui-button" for="node-config-input-certfile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label>
<input class="hide" type="file" id="node-config-input-certfile"> <input class="hide" type="file" id="node-config-input-certfile">
<span id="tls-config-certname" style="width: calc(100% - 280px); overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span> <span id="tls-config-certname" style="width: calc(100% - 280px); overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span>
<button class="red-ui-button red-ui-button-small" id="tls-config-button-cert-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button> <button type="button" class="red-ui-button red-ui-button-small" id="tls-config-button-cert-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
</span> </span>
<input type="hidden" id="node-config-input-certname"> <input type="hidden" id="node-config-input-certname">
<input type="hidden" id="node-config-input-certdata"> <input type="hidden" id="node-config-input-certdata">
@ -37,7 +37,7 @@
<label class="red-ui-button" for="node-config-input-keyfile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label> <label class="red-ui-button" for="node-config-input-keyfile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label>
<input class="hide" type="file" id="node-config-input-keyfile"> <input class="hide" type="file" id="node-config-input-keyfile">
<span id="tls-config-keyname" style="width: calc(100% - 280px); overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span> <span id="tls-config-keyname" style="width: calc(100% - 280px); overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span>
<button class="red-ui-button red-ui-button-small" id="tls-config-button-key-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button> <button type="button" class="red-ui-button red-ui-button-small" id="tls-config-button-key-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
</span> </span>
<input type="hidden" id="node-config-input-keyname"> <input type="hidden" id="node-config-input-keyname">
<input type="hidden" id="node-config-input-keydata"> <input type="hidden" id="node-config-input-keydata">
@ -53,7 +53,7 @@
<label class="red-ui-button" for="node-config-input-cafile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label> <label class="red-ui-button" for="node-config-input-cafile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label>
<input class="hide" type="file" title=" " id="node-config-input-cafile"> <input class="hide" type="file" title=" " id="node-config-input-cafile">
<span id="tls-config-caname" style="width: calc(100% - 280px); overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span> <span id="tls-config-caname" style="width: calc(100% - 280px); overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span>
<button class="red-ui-button red-ui-button-small" id="tls-config-button-ca-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button> <button type="button" class="red-ui-button red-ui-button-small" id="tls-config-button-ca-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
</span> </span>
<input type="hidden" id="node-config-input-caname"> <input type="hidden" id="node-config-input-caname">
<input type="hidden" id="node-config-input-cadata"> <input type="hidden" id="node-config-input-cadata">

View File

@ -998,13 +998,20 @@ module.exports = function(RED) {
if (topicOK) { if (topicOK) {
node.client.publish(msg.topic, msg.payload, options, function (err) { node.client.publish(msg.topic, msg.payload, options, function (err) {
done && done(err); if (done) {
return done(err)
});
} else { } else {
const error = new Error(RED._("mqtt.errors.invalid-topic")); node.error(err, msg)
error.warn = true; }
done(error); })
} else {
const error = new Error(RED._("mqtt.errors.invalid-topic"))
error.warn = true
if (done) {
done(error)
} else {
node.warn(error, msg)
}
} }
} }
}; };

View File

@ -2268,7 +2268,7 @@ describe('HTTP Request Node', function() {
}); });
}); });
describe('should parse broken headers', function(done) { describe('should parse broken headers', function() {
const versions = process.versions.node.split('.') const versions = process.versions.node.split('.')
@ -2332,8 +2332,6 @@ describe('HTTP Request Node', function() {
}); });
}); });
} else {
done()
} }
}); });
}); });

View File

@ -61,7 +61,7 @@ describe("api/index", function() {
should.not.exist(api.httpAdmin); should.not.exist(api.httpAdmin);
done(); done();
}); });
describe('initalises admin api without adminAuth', function(done) { describe('initalises admin api without adminAuth', function() {
before(function() { before(function() {
beforeEach(); beforeEach();
api.init({},{},{},{}); api.init({},{},{},{});
@ -78,7 +78,7 @@ describe("api/index", function() {
}) })
}); });
describe('initalises admin api without editor', function(done) { describe('initalises admin api without editor', function() {
before(function() { before(function() {
beforeEach(); beforeEach();
api.init({ disableEditor: true },{},{},{}); api.init({ disableEditor: true },{},{},{});
@ -95,7 +95,7 @@ describe("api/index", function() {
}) })
}); });
describe('initialises api with admin middleware', function(done) { describe('initialises api with admin middleware', function() {
it('ignores non-function values',function(done) { it('ignores non-function values',function(done) {
api.init({ httpAdminRoot: true, httpAdminMiddleware: undefined },{},{},{}); api.init({ httpAdminRoot: true, httpAdminMiddleware: undefined },{},{},{});
const middlewareFound = api.httpAdmin._router.stack.filter((layer) => layer.name === 'testMiddleware') const middlewareFound = api.httpAdmin._router.stack.filter((layer) => layer.name === 'testMiddleware')
@ -112,7 +112,7 @@ describe("api/index", function() {
}); });
}); });
describe('initialises api with authentication enabled', function(done) { describe('initialises api with authentication enabled', function() {
it('enables an oauth/openID based authentication mechanism',function(done) { it('enables an oauth/openID based authentication mechanism',function(done) {
const stub = sinon.stub(apiAuth, 'genericStrategy').callsFake(function(){}); const stub = sinon.stub(apiAuth, 'genericStrategy').callsFake(function(){});
@ -135,7 +135,7 @@ describe("api/index", function() {
}); });
describe('initialises api with custom cors config', function (done) { describe('initialises api with custom cors config', function () {
const httpAdminCors = { const httpAdminCors = {
origin: "*", origin: "*",
methods: "GET,PUT,POST,DELETE" methods: "GET,PUT,POST,DELETE"
@ -156,7 +156,7 @@ describe("api/index", function() {
}) })
}); });
describe('editor start', function (done) { describe('editor start', function () {
it('cannot be started when editor is disabled', function (done) { it('cannot be started when editor is disabled', function (done) {
const stub = sinon.stub(apiEditor, 'start').callsFake(function () { const stub = sinon.stub(apiEditor, 'start').callsFake(function () {