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

Merge branch 'master' into dev

This commit is contained in:
Nick O'Leary 2020-11-18 16:36:56 +00:00
commit c6129b44a1
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
25 changed files with 247 additions and 55 deletions

View File

@ -27,6 +27,9 @@ jobs:
with:
node-version: '12'
- run: node ./node-red/.github/scripts/update-node-red-docker.js
with:
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
- name: Create Docker Pull Request
uses: peter-evans/create-pull-request@v2
with:

View File

@ -1,3 +1,35 @@
### 1.2.5: Maintenance Release
Editor
- Fix import of config nodes with unknown z property
Runtime
- Set ACTIONS_ALLOW_UNSECURE_COMMANDS in GH Action
### 1.2.4: Maintenance Release
Editor
- Support bigint types in Debug sidebar
- Clear retained status of deleted nodes
- Prevent needless retention of node status messages
- Update projects dialogs to use TypedInput-cred input
- Restore cursor position in TypedInput cred-mode
- Ensure config nodes with invalid z are imported somewhere
- Ensure user keyboard shortcuts override defaults Fixes #2753
Runtime
- Disable projects when flowFile passed into grunt dev
- Add Russian Locale (#2761) (#2531) (@alexk111)
- Add Japanese translation for http-in node (#2758) (@kazuhitoyokoi)
Nodes
- CSV: Fix CSV node repeating array output
### 1.2.3: Maintenance Release
Editor

View File

@ -24,6 +24,7 @@ module.exports = function(grunt) {
var flowFile = grunt.option('flowFile');
if (flowFile) {
nodemonArgs.push(flowFile);
process.env.NODE_RED_ENABLE_PROJECTS=false;
}
var userDir = grunt.option('userDir');
if (userDir) {

View File

@ -55,8 +55,8 @@
"media-typer": "1.1.0",
"memorystore": "1.6.4",
"mime": "2.4.6",
"moment-timezone": "^0.5.31",
"mqtt": "4.2.4",
"moment-timezone": "0.5.32",
"mqtt": "4.2.5",
"multer": "1.4.2",
"mustache": "4.0.1",
"node-red-admin": "^0.2.6",
@ -73,7 +73,7 @@
"request": "2.88.0",
"semver": "6.3.0",
"tar": "6.0.5",
"uglify-js": "3.11.4",
"uglify-js": "3.11.6",
"when": "3.7.8",
"ws": "6.2.1",
"xml2js": "0.4.23"
@ -104,7 +104,7 @@
"grunt-simple-nyc": "^3.0.1",
"http-proxy": "1.18.1",
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
"marked": "1.2.2",
"marked": "1.2.4",
"minami": "1.2.3",
"mocha": "^5.2.0",
"node-red-node-test-helper": "^0.2.5",

View File

@ -33,8 +33,6 @@ var activeConnections = [];
var anonymousUser;
var retained = {};
var heartbeatTimer;
var lastSentTime;

View File

@ -42,7 +42,8 @@
"loadNodeCatalogs": "Загрузка каталогов узлов",
"loadNodes": "Загрузка узлов __count__",
"loadFlows": "Загрузка потоков",
"importFlows": "Добавление потоков в рабочую область"
"importFlows": "Добавление потоков в рабочую область",
"importError": "<p>Ошибка добавления потоков</p><p>__message__</p>"
},
"workspace": {
"defaultName": "Поток __number__",
@ -214,6 +215,9 @@
"importUnrecognised": "Импортирован неопознанный тип:",
"importUnrecognised_plural_2": "Импортированы неопознанные типы:",
"importUnrecognised_plural_5": "Импортированы неопознанные типы:",
"importDuplicate": "Импортирован дубликат узла:",
"importDuplicate_plural_2": "Импортированы дубликаты узлов:",
"importDuplicate_plural_5": "Импортированы дубликаты узлов:",
"nodesExported": "Узлы экспортированы в буфер обмена",
"nodesImported": "Импортированы:",
"nodeCopied": "__count__ узел скопирован",

View File

@ -1359,6 +1359,10 @@ RED.nodes = (function() {
}
}
}
} else {
if (n.z && !workspaces[n.z]) {
n.z = activeWorkspace;
}
}
if (!existingConfigNode || existingConfigNode._def.exclusive) { //} || !compareNodes(existingConfigNode,n,true) || existingConfigNode.z !== n.z) {

View File

@ -773,6 +773,9 @@ RED.clipboard = (function() {
// representation or null
return null;
}
if (value.type === 'bigint') {
return value.data.toString();
}
if (value.type === 'undefined') {
return undefined;
}

View File

@ -173,6 +173,7 @@
valueLabel: function(container,value) {
var that = this;
container.css("pointer-events","none");
container.css("flex-grow",0);
this.elementDiv.hide();
var buttons = $('<div>').css({
position: "absolute",
@ -184,22 +185,25 @@
width:"20px"
}).appendTo(buttons).on("click", function(evt) {
evt.preventDefault();
var cursorPosition = that.input[0].selectionStart;
var currentType = that.input.attr("type");
if (currentType === "text") {
that.input.attr("type","password");
eyeCon.removeClass("fa-eye-slash").addClass("fa-eye");
setTimeout(function() {
that.input.focus();
that.input[0].setSelectionRange(cursorPosition, cursorPosition);
},50);
} else {
that.input.attr("type","text");
eyeCon.removeClass("fa-eye").addClass("fa-eye-slash");
setTimeout(function() {
that.input.focus();
that.input[0].setSelectionRange(cursorPosition, cursorPosition);
},50);
}
}).hide();
var eyeCon = $('<i class="fa fa-eye"></i>').css("margin-left","-1px").appendTo(eyeButton);
var eyeCon = $('<i class="fa fa-eye"></i>').css("margin-left","-2px").appendTo(eyeButton);
if (value === "__PWRD__") {
var innerContainer = $('<div><i class="fa fa-asterisk"></i><i class="fa fa-asterisk"></i><i class="fa fa-asterisk"></i><i class="fa fa-asterisk"></i><i class="fa fa-asterisk"></i></div>').css({
@ -284,7 +288,7 @@
this.input.css('width','100%');
this.uiSelect.width(m[1]);
this.uiWidth = null;
} else {
} else if (this.uiWidth !== 0){
this.uiSelect.width(this.uiWidth);
}
["Right","Left"].forEach(function(d) {
@ -304,7 +308,11 @@
this.element.attr('type','hidden');
if (!this.options.types && this.options.type) {
this.options.types = [this.options.type]
} else {
this.options.types = this.options.types||Object.keys(allOptions);
}
this.selectTrigger = $('<button class="red-ui-typedInput-type-select" tabindex="0"></button>').prependTo(this.uiSelect);
$('<i class="red-ui-typedInput-icon fa fa-caret-down"></i>').toggle(this.options.types.length > 1).appendTo(this.selectTrigger);
@ -872,6 +880,9 @@
this.elementDiv.hide();
this.valueLabelContainer.hide();
} else if (opt.valueLabel) {
// Reset any CSS the custom label may have set
this.valueLabelContainer.css("pointer-events","");
this.valueLabelContainer.css("flex-grow",1);
this.valueLabelContainer.show();
this.valueLabelContainer.empty();
this.elementDiv.hide();

View File

@ -1033,7 +1033,7 @@ RED.projects.settings = (function() {
var credentialSecretExistingRow = $('<div class="red-ui-settings-row red-ui-settings-row-credentials"></div>').appendTo(credentialFormRows);
$('<label for=""></label>').text(RED._("sidebar.project.projectSettings.currentKey")).appendTo(credentialSecretExistingRow);
var credentialSecretExistingInput = $('<input type="password">').appendTo(credentialSecretExistingRow)
var credentialSecretExistingInput = $('<input type="text">').appendTo(credentialSecretExistingRow).typedInput({type:"cred"})
.on("change keyup paste",function() {
if (popover) {
popover.close();
@ -1046,7 +1046,7 @@ RED.projects.settings = (function() {
$('<label for=""></label>').text(RED._("sidebar.project.projectSettings.newKey")).appendTo(credentialSecretNewRow);
var credentialSecretNewInput = $('<input type="password">').appendTo(credentialSecretNewRow).on("change keyup paste",checkFiles);
var credentialSecretNewInput = $('<input type="text">').appendTo(credentialSecretNewRow).typedInput({type:"cred"}).on("change keyup paste",checkFiles);
var credentialResetWarning = $('<div class="form-tips form-warning" style="margin: 10px;"><i class="fa fa-warning"></i>' + RED._("sidebar.project.projectSettings.credentialsAlert") + '</div>').hide().appendTo(credentialFormRows);

View File

@ -81,8 +81,8 @@ RED.projects = (function() {
$('<p>').text(RED._("projects.welcome.desc2")).appendTo(body);
var row = $('<div style="text-align: center"></div>').appendTo(body);
var createAsEmpty = $('<button data-type="empty" class="red-ui-button red-ui-projects-dialog-screen-create-type"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-asterisk"></i><br/>'+RED._("projects.welcome.create")+'</button>').appendTo(row);
var createAsClone = $('<button data-type="clone" class="red-ui-button red-ui-projects-dialog-screen-create-type"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-git"></i><br/>'+RED._("projects.welcome.clone")+'</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"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-asterisk"></i><br/>'+RED._("projects.welcome.create")+'</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"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-git"></i><br/>'+RED._("projects.welcome.clone")+'</button>').appendTo(row);
createAsEmpty.on("click", function(e) {
e.preventDefault();
@ -511,7 +511,8 @@ RED.projects = (function() {
subrow = $('<div style="width: calc(50% - 10px); margin-left: 20px; display:inline-block;"></div>').appendTo(row);
$('<label for="red-ui-projects-dialog-screen-create-project-repo-pass">'+RED._("projects.clone-project.passwd")+'</label>').appendTo(subrow);
projectRepoPasswordInput = $('<input id="red-ui-projects-dialog-screen-create-project-repo-pass" type="password"></input>').appendTo(subrow);
projectRepoPasswordInput = $('<input style="width:100%" id="red-ui-projects-dialog-screen-create-project-repo-pass" type="password"></input>').appendTo(subrow);
projectRepoPasswordInput.typedInput({type:"cred"});
// -----------------------------------------------------
// Repo credentials - key/passphrase -------------------
@ -539,12 +540,12 @@ RED.projects = (function() {
subrow = $('<div style="width: calc(50% - 10px); margin-left: 20px; display:inline-block;"></div>').appendTo(row);
$('<label for="red-ui-projects-dialog-screen-create-project-repo-passphrase">'+RED._("projects.clone-project.passphrase")+'</label>').appendTo(subrow);
projectRepoPassphrase = $('<input id="red-ui-projects-dialog-screen-create-project-repo-passphrase" type="password"></input>').appendTo(subrow);
projectRepoPassphrase.typedInput({type:"cred"});
subrow = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-sshkey"></div>').appendTo(cloneAuthRows);
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);
subrow = $('<div style="text-align: center">').appendTo(sshwarningRow);
$('<button class="red-ui-button">'+RED._("projects.clone-project.ssh-key-add")+'</button>').appendTo(subrow).on("click", function(e) {
$('<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();
dialog.dialog( "close" );
RED.userSettings.show('gitconfig');
@ -558,8 +559,8 @@ RED.projects = (function() {
// Secret - clone
row = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-clone"></div>').appendTo(body);
$('<label>'+RED._("projects.clone-project.credential-key")+'</label>').appendTo(row);
projectSecretInput = $('<input type="password"></input>').appendTo(row);
projectSecretInput = $('<input style="width: 100%" type="password"></input>').appendTo(row);
projectSecretInput.typedInput({type:"cred"});
return container;
@ -894,6 +895,7 @@ RED.projects = (function() {
$('<label class="red-ui-projects-edit-form-inline-label" style="margin-left: 5px"><input type="radio" style="vertical-align: middle; margin-top:0; margin-right: 10px;" value="custom" name="projects-encryption-key"> <span style="vertical-align: middle;">'+RED._("projects.encryption-config.use-custom")+'</span></label>').appendTo(row);
row = $('<div class="projects-encryption-enabled-row"></div>').appendTo(credentialsRightBox);
emptyProjectCredentialInput = $('<input disabled type="password" style="margin-left: 25px; width: calc(100% - 30px);"></input>').appendTo(row);
emptyProjectCredentialInput.typedInput({type:"cred"});
emptyProjectCredentialInput.on("change keyup paste", validateForm);
row = $('<div class="form-row projects-encryption-disabled-row"></div>').hide().appendTo(credentialsRightBox);
@ -1169,11 +1171,11 @@ RED.projects = (function() {
row = $('<div class="form-row button-group"></div>').appendTo(container);
var openProject = $('<button data-type="open" class="red-ui-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-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-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-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-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 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 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 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 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 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) {
evt.preventDefault();
container.find(".red-ui-projects-dialog-screen-create-type").removeClass('selected');
@ -1298,6 +1300,7 @@ RED.projects = (function() {
$('<label class="red-ui-projects-edit-form-inline-label">'+RED._("projects.create.encryption-key")+'</label>').appendTo(row);
// row = $('<div class="projects-encryption-enabled-row"></div>').appendTo(credentialsRightBox);
emptyProjectCredentialInput = $('<input type="password"></input>').appendTo(row);
emptyProjectCredentialInput.typedInput({type:"cred"});
emptyProjectCredentialInput.on("change keyup paste", validateForm);
$('<label class="red-ui-projects-edit-form-sublabel"><small>'+RED._("projects.create.desc0")+'</small></label>').appendTo(row);
@ -1356,7 +1359,8 @@ RED.projects = (function() {
subrow = $('<div style="width: calc(50% - 10px); margin-left: 20px; display:inline-block;"></div>').appendTo(row);
$('<label for="red-ui-projects-dialog-screen-create-project-repo-pass">'+RED._("projects.create.password")+'</label>').appendTo(subrow);
projectRepoPasswordInput = $('<input id="red-ui-projects-dialog-screen-create-project-repo-pass" type="password"></input>').appendTo(subrow);
projectRepoPasswordInput = $('<input style="width:100%" id="red-ui-projects-dialog-screen-create-project-repo-pass" type="password"></input>').appendTo(subrow);
projectRepoPasswordInput.typedInput({type:"cred"});
// -----------------------------------------------------
// Repo credentials - key/passphrase -------------------
@ -1384,12 +1388,13 @@ RED.projects = (function() {
subrow = $('<div style="width: calc(50% - 10px); margin-left: 20px; display:inline-block;"></div>').appendTo(row);
$('<label for="red-ui-projects-dialog-screen-create-project-repo-passphrase">'+RED._("projects.create.passphrase")+'</label>').appendTo(subrow);
projectRepoPassphrase = $('<input id="red-ui-projects-dialog-screen-create-project-repo-passphrase" type="password"></input>').appendTo(subrow);
projectRepoPassphrase.typedInput({type:"cred"});
subrow = $('<div class="form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-sshkey"></div>').appendTo(cloneAuthRows);
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);
subrow = $('<div style="text-align: center">').appendTo(sshwarningRow);
$('<button class="red-ui-button">'+RED._("projects.create.add-ssh-key")+'</button>').appendTo(subrow).on("click", function(e) {
$('<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();
$('#red-ui-projects-dialog-cancel').trigger("click");
RED.userSettings.show('gitconfig');
@ -1403,8 +1408,8 @@ RED.projects = (function() {
// Secret - clone
row = $('<div class="hide form-row red-ui-projects-dialog-screen-create-row red-ui-projects-dialog-screen-create-row-clone"></div>').appendTo(container);
$('<label>'+RED._("projects.create.credentials-encryption-key")+'</label>').appendTo(row);
projectSecretInput = $('<input type="password"></input>').appendTo(row);
projectSecretInput = $('<input style="width:100%" type="password"></input>').appendTo(row);
projectSecretInput.typedInput({type:"cred"});
switch(options.screen||"empty") {
case "empty": createAsEmpty.trigger("click"); break;
@ -1617,14 +1622,14 @@ RED.projects = (function() {
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);
$('<span>').text(RED._("projects.delete.confirm")).appendTo(cover);
$('<button class="red-ui-button">'+RED._("common.label.cancel")+'</button>')
$('<button class="red-ui-button red-ui-projects-dialog-button">'+RED._("common.label.cancel")+'</button>')
.appendTo(cover)
.on("click", function(e) {
e.stopPropagation();
cover.remove();
done(true);
});
$('<button class="red-ui-button primary">'+RED._("common.label.delete")+'</button>')
$('<button class="red-ui-button red-ui-projects-dialog-button primary">'+RED._("common.label.delete")+'</button>')
.appendTo(cover)
.on("click", function(e) {
e.stopPropagation();
@ -1808,7 +1813,7 @@ RED.projects = (function() {
header.addClass("selectable");
var tools = $('<div class="red-ui-projects-dialog-project-list-entry-tools"></div>').appendTo(header);
$('<button class="red-ui-button red-ui-button-small" style="float: right;"><i class="fa fa-trash"></i></button>')
$('<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)
.on("click", function(e) {
e.stopPropagation();
@ -1962,7 +1967,8 @@ RED.projects = (function() {
var isSSH = false;
if (/^https?:\/\//.test(url)) {
$('<div class="form-row"><label for="projects-user-auth-username">'+RED._("projects.send-req.username")+'</label><input id="projects-user-auth-username" type="text"></input></div>'+
'<div class="form-row"><label for=projects-user-auth-password">'+RED._("projects.send-req.password")+'</label><input id="projects-user-auth-password" type="password"></input></div>').appendTo(message);
'<div class="form-row"><label for="projects-user-auth-password">'+RED._("projects.send-req.password")+'</label><input id="projects-user-auth-password" type="password"></input></div>').appendTo(message);
message.find("#projects-user-auth-password").typedInput({type:"cred"})
} else if (/^(?:ssh|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?/.test(url)) {
isSSH = true;
var row = $('<div class="form-row"></div>').appendTo(message);
@ -1980,7 +1986,7 @@ RED.projects = (function() {
});
row = $('<div class="form-row"></div>').appendTo(message);
$('<label for="projects-user-auth-passphrase">'+RED._("projects.send-req.passphrase")+'</label>').appendTo(row);
$('<input id="projects-user-auth-passphrase" type="password"></input>').appendTo(row);
$('<input id="projects-user-auth-passphrase" type="password"></input>').appendTo(row).typedInput({type:"cred"});
}
var notification = RED.notify(message,{

View File

@ -60,7 +60,7 @@ RED.utils = (function() {
result = $('<span class="red-ui-debug-msg-object-value red-ui-debug-msg-type-meta"></span>').text('array['+value.length+']');
} else if (value.hasOwnProperty('type') && value.type === 'function') {
result = $('<span class="red-ui-debug-msg-object-value red-ui-debug-msg-type-meta"></span>').text('function');
} else if (value.hasOwnProperty('type') && value.type === 'number') {
} else if (value.hasOwnProperty('type') && (value.type === 'number' || value.type === 'bigint')) {
result = $('<span class="red-ui-debug-msg-object-value red-ui-debug-msg-type-number"></span>').text(value.data);
} else {
result = $('<span class="red-ui-debug-msg-object-value red-ui-debug-msg-type-meta">object</span>');
@ -352,7 +352,7 @@ RED.utils = (function() {
$('<span class="red-ui-debug-msg-type-null">'+obj+'</span>').appendTo(entryObj);
} else if (obj.__enc__ && obj.type === 'undefined') {
$('<span class="red-ui-debug-msg-type-null">undefined</span>').appendTo(entryObj);
} else if (obj.__enc__ && obj.type === 'number') {
} else if (obj.__enc__ && (obj.type === 'number' || obj.type === 'bigint')) {
e = $('<span class="red-ui-debug-msg-type-number red-ui-debug-msg-object-header"></span>').text(obj.data).appendTo(entryObj);
} else if (typeHint === "function" || (obj.__enc__ && obj.type === 'function')) {
e = $('<span class="red-ui-debug-msg-type-meta red-ui-debug-msg-object-header"></span>').text("function").appendTo(entryObj);

View File

@ -90,7 +90,7 @@
font-size: 1.2em;
}
}
button.red-ui-button {
button.red-ui-button.red-ui-projects-dialog-button {
width: calc(50% - 80px);
margin: 20px;
height: auto;

View File

@ -18,6 +18,7 @@
border: 1px solid $form-input-border-color;
border-radius: 4px;
height: 34px;
line-height: 14px;
display: inline-flex;
padding: 0;
margin: 0;

View File

@ -21,8 +21,11 @@ module.exports = function(RED) {
this.tosidebar = n.tosidebar;
if (this.tosidebar === undefined) { this.tosidebar = true; }
this.active = (n.active === null || typeof n.active === "undefined") || n.active;
if (this.tostatus) { this.status({fill:"grey", shape:"ring"}); }
else { this.status({}); }
if (this.tostatus) {
this.status({fill:"grey", shape:"ring"});
this.oldState = "{}";
}
var hasStatExpression = (n.statusType === "jsonata");
var statExpression = hasStatExpression ? n.statusVal : null;
@ -97,7 +100,11 @@ module.exports = function(RED) {
}
}
}
this.on("close", function() {
if (this.oldState) {
this.status({});
}
})
this.on("input", function(msg, send, done) {
if (msg.hasOwnProperty("status") && msg.status.hasOwnProperty("source") && msg.status.source.hasOwnProperty("id") && (msg.status.source.id === node.id)) {
done();
@ -202,13 +209,8 @@ module.exports = function(RED) {
function setNodeState(node,state) {
if (state) {
node.active = true;
if (node.tostatus) { node.status({fill:"grey", shape:"dot"}); }
} else {
node.active = false;
if (node.tostatus && node.hasOwnProperty("oldStatus")) {
node.oldStatus.shape = "dot";
node.status(node.oldStatus);
}
}
}

View File

@ -127,6 +127,8 @@ module.exports = function(RED) {
node.topic = n.topic;
node.outstandingTimers = [];
node.outstandingIntervals = [];
node.clearStatus = false;
var sandbox = {
console:console,
util:util,
@ -163,6 +165,7 @@ module.exports = function(RED) {
node.on.apply(node, arguments);
},
status: function() {
node.clearStatus = true;
node.status.apply(node, arguments);
}
},
@ -389,7 +392,9 @@ module.exports = function(RED) {
while (node.outstandingIntervals.length > 0) {
clearInterval(node.outstandingIntervals.pop());
}
if (node.clearStatus) {
node.status({});
}
});
promise.then(function (v) {

View File

@ -46,7 +46,7 @@
При преобразовании в CSV шаблон столбцов используется для определения того, какие свойства извлекать из объекта и в каком порядке.
</p>
<p>
Если шаблон пуст, то узел может использовать простой список свойств, разделенных запятыми, предоставленных в <code>msg.columns</code>, чтобы определить, что извлечь. Если этого нет, то все свойства объекта выводятся в том порядке, в котором они были найдены.
Если шаблон пуст, то узел может использовать простой список свойств, разделенных запятыми, предоставленных в <code>msg.columns</code>, чтобы определить, что извлечь. Если этого нет, то все свойства объекта выводятся в том порядке, в котором они были найдены в первой строке.
</p>
<p>
Если входные данные являются массивом, то шаблон столбцов используется только для необязательного генерирования строки с заголовками столбцов.

View File

@ -31,7 +31,7 @@
"is-utf8": "0.2.1",
"js-yaml": "3.14.0",
"media-typer": "1.1.0",
"mqtt": "4.2.4",
"mqtt": "4.2.5",
"multer": "1.4.2",
"mustache": "4.0.1",
"on-headers": "1.0.2",

View File

@ -19,7 +19,7 @@
"@node-red/util": "1.3.0-beta.1",
"semver": "6.3.0",
"tar": "6.0.5",
"uglify-js": "3.11.4",
"uglify-js": "3.11.6",
"when": "3.7.8"
}
}

View File

@ -38,12 +38,20 @@ function handleCommsEvent(event) {
publish(event.topic,event.data,event.retain);
}
function handleStatusEvent(event) {
if (!event.status) {
delete retained["status/"+event.id]
} else if (!event.status.text && !event.status.fill && !event.status.shape) {
if (retained["status/"+event.id]) {
publish("status/"+event.id,{},false);
}
} else {
var status = {
text: event.status.text,
fill: event.status.fill,
shape: event.status.shape
};
publish("status/"+event.id,status,true);
}
}
function handleRuntimeEvent(event) {
runtime.log.trace("runtime event: "+JSON.stringify(event));

View File

@ -319,6 +319,11 @@ class Flow {
node.error(err);
}
}
if (removedMap[stopList[i]]) {
events.emit("node-status",{
id: node.id
});
}
}
}
return Promise.all(promises);

View File

@ -18,6 +18,7 @@ const clone = require("clone");
const Flow = require('./Flow').Flow;
const context = require('../nodes/context');
const util = require("util");
const events = require("../events");
const redUtil = require("@node-red/util").util;
const flowUtil = require("./util");
@ -308,7 +309,26 @@ class Subflow extends Flow {
super.start(diff);
}
/**
* Stop this subflow.
* The `stopList` argument helps define what needs to be stopped in the case
* of a modified-nodes/flows type deploy.
* @param {[type]} stopList [description]
* @param {[type]} removedList [description]
* @return {[type]} [description]
*/
stop(stopList, removedList) {
const nodes = Object.keys(this.activeNodes);
return super.stop(stopList, removedList).then(res => {
nodes.forEach(id => {
events.emit("node-status",{
id: id
});
})
return res;
})
}
/**
* Get environment variable of subflow
* @param {String} name name of env var

View File

@ -774,6 +774,12 @@ function encodeObject(msg,opts) {
data: value.toString()
}
}
} else if (typeof value === 'bigint') {
value = {
__enc__: true,
type: 'bigint',
data: value.toString()
}
} else if (value && value.constructor) {
if (value.type === "Buffer") {
value.__enc__ = true;
@ -808,6 +814,13 @@ function encodeObject(msg,opts) {
} else if (msgType === "number") {
msg.format = "number";
msg.msg = msg.msg.toString();
} else if (msgType === "bigint") {
msg.format = "bigint";
msg.msg = {
__enc__: true,
type: 'bigint',
data: msg.msg.toString()
};
} else if (msg.msg === null || msgType === "undefined") {
msg.format = (msg.msg === null)?"null":"undefined";
msg.msg = "(undefined)";

View File

@ -20,7 +20,7 @@
"json-stringify-safe": "5.0.1",
"jsonata": "1.8.4",
"lodash.clonedeep": "^4.5.0",
"moment-timezone": "^0.5.31",
"moment-timezone": "0.5.32",
"when": "3.7.8"
}
}

View File

@ -211,6 +211,82 @@ describe("runtime-api/comms", function() {
});
}).catch(done);
})
it('retains non-blank status message',function(done){
eventHandlers['node-status']({
id: "node1234",
status: {text:"hello"}
})
messages.should.have.length(0);
comms.addConnection({client: clientConnection}).then(function() {
return comms.subscribe({client: clientConnection, topic: "status/#"}).then(function() {
messages.should.have.length(1);
messages[0].should.have.property("topic","status/node1234");
messages[0].should.have.property("data",{text:"hello", fill: undefined, shape: undefined});
done();
});
}).catch(done);
})
it('does not retain blank status message',function(done){
eventHandlers['node-status']({
id: "node1234",
status: {}
})
messages.should.have.length(0);
comms.addConnection({client: clientConnection}).then(function() {
return comms.subscribe({client: clientConnection, topic: "status/#"}).then(function() {
messages.should.have.length(0);
done();
});
}).catch(done);
})
it('does not send blank status if first status',function(done){
messages.should.have.length(0);
comms.addConnection({client: clientConnection}).then(function() {
return comms.subscribe({client: clientConnection, topic: "status/#"}).then(function() {
eventHandlers['node-status']({
id: "node5678",
status: {}
})
messages.should.have.length(0);
done()
})
}).catch(done);
});
it('sends blank status if replacing retained',function(done){
eventHandlers['node-status']({
id: "node5678",
status: {text:"hello"}
})
messages.should.have.length(0);
comms.addConnection({client: clientConnection}).then(function() {
return comms.subscribe({client: clientConnection, topic: "status/#"}).then(function() {
messages.should.have.length(1);
eventHandlers['node-status']({
id: "node5678",
status: {}
})
messages.should.have.length(2);
done()
})
}).catch(done);
});
it('does not retain initial status blank message',function(done){
eventHandlers['node-status']({
id: "my-event",
status: {}
})
messages.should.have.length(0);
comms.addConnection({client: clientConnection}).then(function() {
return comms.subscribe({client: clientConnection, topic: "my-event"}).then(function() {
messages.should.have.length(1);
messages[0].should.have.property("topic","my-event");
messages[0].should.have.property("data","my-payload");
done();
});
}).catch(done);
})
it('retained messages get cleared',function(done) {
eventHandlers['comms']({
topic: "my-event",