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: with:
node-version: '12' node-version: '12'
- run: node ./node-red/.github/scripts/update-node-red-docker.js - run: node ./node-red/.github/scripts/update-node-red-docker.js
with:
env:
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
- name: Create Docker Pull Request - name: Create Docker Pull Request
uses: peter-evans/create-pull-request@v2 uses: peter-evans/create-pull-request@v2
with: 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 ### 1.2.3: Maintenance Release
Editor Editor

View File

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

View File

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

View File

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

View File

@ -42,7 +42,8 @@
"loadNodeCatalogs": "Загрузка каталогов узлов", "loadNodeCatalogs": "Загрузка каталогов узлов",
"loadNodes": "Загрузка узлов __count__", "loadNodes": "Загрузка узлов __count__",
"loadFlows": "Загрузка потоков", "loadFlows": "Загрузка потоков",
"importFlows": "Добавление потоков в рабочую область" "importFlows": "Добавление потоков в рабочую область",
"importError": "<p>Ошибка добавления потоков</p><p>__message__</p>"
}, },
"workspace": { "workspace": {
"defaultName": "Поток __number__", "defaultName": "Поток __number__",
@ -214,6 +215,9 @@
"importUnrecognised": "Импортирован неопознанный тип:", "importUnrecognised": "Импортирован неопознанный тип:",
"importUnrecognised_plural_2": "Импортированы неопознанные типы:", "importUnrecognised_plural_2": "Импортированы неопознанные типы:",
"importUnrecognised_plural_5": "Импортированы неопознанные типы:", "importUnrecognised_plural_5": "Импортированы неопознанные типы:",
"importDuplicate": "Импортирован дубликат узла:",
"importDuplicate_plural_2": "Импортированы дубликаты узлов:",
"importDuplicate_plural_5": "Импортированы дубликаты узлов:",
"nodesExported": "Узлы экспортированы в буфер обмена", "nodesExported": "Узлы экспортированы в буфер обмена",
"nodesImported": "Импортированы:", "nodesImported": "Импортированы:",
"nodeCopied": "__count__ узел скопирован", "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) { 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 // representation or null
return null; return null;
} }
if (value.type === 'bigint') {
return value.data.toString();
}
if (value.type === 'undefined') { if (value.type === 'undefined') {
return undefined; return undefined;
} }

View File

@ -173,6 +173,7 @@
valueLabel: function(container,value) { valueLabel: function(container,value) {
var that = this; var that = this;
container.css("pointer-events","none"); container.css("pointer-events","none");
container.css("flex-grow",0);
this.elementDiv.hide(); this.elementDiv.hide();
var buttons = $('<div>').css({ var buttons = $('<div>').css({
position: "absolute", position: "absolute",
@ -184,22 +185,25 @@
width:"20px" width:"20px"
}).appendTo(buttons).on("click", function(evt) { }).appendTo(buttons).on("click", function(evt) {
evt.preventDefault(); evt.preventDefault();
var cursorPosition = that.input[0].selectionStart;
var currentType = that.input.attr("type"); var currentType = that.input.attr("type");
if (currentType === "text") { if (currentType === "text") {
that.input.attr("type","password"); that.input.attr("type","password");
eyeCon.removeClass("fa-eye-slash").addClass("fa-eye"); eyeCon.removeClass("fa-eye-slash").addClass("fa-eye");
setTimeout(function() { setTimeout(function() {
that.input.focus(); that.input.focus();
that.input[0].setSelectionRange(cursorPosition, cursorPosition);
},50); },50);
} else { } else {
that.input.attr("type","text"); that.input.attr("type","text");
eyeCon.removeClass("fa-eye").addClass("fa-eye-slash"); eyeCon.removeClass("fa-eye").addClass("fa-eye-slash");
setTimeout(function() { setTimeout(function() {
that.input.focus(); that.input.focus();
that.input[0].setSelectionRange(cursorPosition, cursorPosition);
},50); },50);
} }
}).hide(); }).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__") { 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({ 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.input.css('width','100%');
this.uiSelect.width(m[1]); this.uiSelect.width(m[1]);
this.uiWidth = null; this.uiWidth = null;
} else { } else if (this.uiWidth !== 0){
this.uiSelect.width(this.uiWidth); this.uiSelect.width(this.uiWidth);
} }
["Right","Left"].forEach(function(d) { ["Right","Left"].forEach(function(d) {
@ -304,7 +308,11 @@
this.element.attr('type','hidden'); 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.options.types = this.options.types||Object.keys(allOptions);
}
this.selectTrigger = $('<button class="red-ui-typedInput-type-select" tabindex="0"></button>').prependTo(this.uiSelect); 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); $('<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.elementDiv.hide();
this.valueLabelContainer.hide(); this.valueLabelContainer.hide();
} else if (opt.valueLabel) { } 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.show();
this.valueLabelContainer.empty(); this.valueLabelContainer.empty();
this.elementDiv.hide(); 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); 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); $('<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() { .on("change keyup paste",function() {
if (popover) { if (popover) {
popover.close(); popover.close();
@ -1046,7 +1046,7 @@ RED.projects.settings = (function() {
$('<label for=""></label>').text(RED._("sidebar.project.projectSettings.newKey")).appendTo(credentialSecretNewRow); $('<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); 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); $('<p>').text(RED._("projects.welcome.desc2")).appendTo(body);
var row = $('<div style="text-align: center"></div>').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 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-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 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) { createAsEmpty.on("click", function(e) {
e.preventDefault(); 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); 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); $('<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 ------------------- // 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); 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); $('<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 = $('<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); 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); 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._("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(); e.preventDefault();
dialog.dialog( "close" ); dialog.dialog( "close" );
RED.userSettings.show('gitconfig'); RED.userSettings.show('gitconfig');
@ -558,8 +559,8 @@ RED.projects = (function() {
// Secret - clone // 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); 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); $('<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; 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); $('<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); 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 = $('<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); emptyProjectCredentialInput.on("change keyup paste", validateForm);
row = $('<div class="form-row projects-encryption-disabled-row"></div>').hide().appendTo(credentialsRightBox); 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); 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 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-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 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-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 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-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-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 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) { 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');
@ -1298,6 +1300,7 @@ RED.projects = (function() {
$('<label class="red-ui-projects-edit-form-inline-label">'+RED._("projects.create.encryption-key")+'</label>').appendTo(row); $('<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); // row = $('<div class="projects-encryption-enabled-row"></div>').appendTo(credentialsRightBox);
emptyProjectCredentialInput = $('<input type="password"></input>').appendTo(row); emptyProjectCredentialInput = $('<input type="password"></input>').appendTo(row);
emptyProjectCredentialInput.typedInput({type:"cred"});
emptyProjectCredentialInput.on("change keyup paste", validateForm); emptyProjectCredentialInput.on("change keyup paste", validateForm);
$('<label class="red-ui-projects-edit-form-sublabel"><small>'+RED._("projects.create.desc0")+'</small></label>').appendTo(row); $('<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); 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); $('<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 ------------------- // 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); 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); $('<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 = $('<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); 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); 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._("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(); e.preventDefault();
$('#red-ui-projects-dialog-cancel').trigger("click"); $('#red-ui-projects-dialog-cancel').trigger("click");
RED.userSettings.show('gitconfig'); RED.userSettings.show('gitconfig');
@ -1403,8 +1408,8 @@ RED.projects = (function() {
// Secret - clone // 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); 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); $('<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") { switch(options.screen||"empty") {
case "empty": createAsEmpty.trigger("click"); break; case "empty": createAsEmpty.trigger("click"); break;
@ -1617,14 +1622,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._("common.label.cancel")+'</button>') $('<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 primary">'+RED._("common.label.delete")+'</button>') $('<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();
@ -1808,7 +1813,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-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) .appendTo(tools)
.on("click", function(e) { .on("click", function(e) {
e.stopPropagation(); e.stopPropagation();
@ -1962,7 +1967,8 @@ RED.projects = (function() {
var isSSH = false; var isSSH = false;
if (/^https?:\/\//.test(url)) { 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-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)) { } else if (/^(?:ssh|[\d\w\.\-_]+@[\w\.]+):(?:\/\/)?/.test(url)) {
isSSH = true; isSSH = true;
var row = $('<div class="form-row"></div>').appendTo(message); var row = $('<div class="form-row"></div>').appendTo(message);
@ -1980,7 +1986,7 @@ RED.projects = (function() {
}); });
row = $('<div class="form-row"></div>').appendTo(message); row = $('<div class="form-row"></div>').appendTo(message);
$('<label for="projects-user-auth-passphrase">'+RED._("projects.send-req.passphrase")+'</label>').appendTo(row); $('<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,{ 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+']'); 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') { } 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'); 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); result = $('<span class="red-ui-debug-msg-object-value red-ui-debug-msg-type-number"></span>').text(value.data);
} else { } else {
result = $('<span class="red-ui-debug-msg-object-value red-ui-debug-msg-type-meta">object</span>'); 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); $('<span class="red-ui-debug-msg-type-null">'+obj+'</span>').appendTo(entryObj);
} else if (obj.__enc__ && obj.type === 'undefined') { } else if (obj.__enc__ && obj.type === 'undefined') {
$('<span class="red-ui-debug-msg-type-null">undefined</span>').appendTo(entryObj); $('<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); 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')) { } 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); 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; font-size: 1.2em;
} }
} }
button.red-ui-button { button.red-ui-button.red-ui-projects-dialog-button {
width: calc(50% - 80px); width: calc(50% - 80px);
margin: 20px; margin: 20px;
height: auto; height: auto;

View File

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

View File

@ -21,8 +21,11 @@ module.exports = function(RED) {
this.tosidebar = n.tosidebar; this.tosidebar = n.tosidebar;
if (this.tosidebar === undefined) { this.tosidebar = true; } if (this.tosidebar === undefined) { this.tosidebar = true; }
this.active = (n.active === null || typeof n.active === "undefined") || n.active; this.active = (n.active === null || typeof n.active === "undefined") || n.active;
if (this.tostatus) { this.status({fill:"grey", shape:"ring"}); } if (this.tostatus) {
else { this.status({}); } this.status({fill:"grey", shape:"ring"});
this.oldState = "{}";
}
var hasStatExpression = (n.statusType === "jsonata"); var hasStatExpression = (n.statusType === "jsonata");
var statExpression = hasStatExpression ? n.statusVal : null; 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) { 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)) { if (msg.hasOwnProperty("status") && msg.status.hasOwnProperty("source") && msg.status.source.hasOwnProperty("id") && (msg.status.source.id === node.id)) {
done(); done();
@ -202,13 +209,8 @@ module.exports = function(RED) {
function setNodeState(node,state) { function setNodeState(node,state) {
if (state) { if (state) {
node.active = true; node.active = true;
if (node.tostatus) { node.status({fill:"grey", shape:"dot"}); }
} else { } else {
node.active = false; 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.topic = n.topic;
node.outstandingTimers = []; node.outstandingTimers = [];
node.outstandingIntervals = []; node.outstandingIntervals = [];
node.clearStatus = false;
var sandbox = { var sandbox = {
console:console, console:console,
util:util, util:util,
@ -163,6 +165,7 @@ module.exports = function(RED) {
node.on.apply(node, arguments); node.on.apply(node, arguments);
}, },
status: function() { status: function() {
node.clearStatus = true;
node.status.apply(node, arguments); node.status.apply(node, arguments);
} }
}, },
@ -389,7 +392,9 @@ module.exports = function(RED) {
while (node.outstandingIntervals.length > 0) { while (node.outstandingIntervals.length > 0) {
clearInterval(node.outstandingIntervals.pop()); clearInterval(node.outstandingIntervals.pop());
} }
if (node.clearStatus) {
node.status({}); node.status({});
}
}); });
promise.then(function (v) { promise.then(function (v) {

View File

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

View File

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

View File

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

View File

@ -38,6 +38,13 @@ function handleCommsEvent(event) {
publish(event.topic,event.data,event.retain); publish(event.topic,event.data,event.retain);
} }
function handleStatusEvent(event) { 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 = { var status = {
text: event.status.text, text: event.status.text,
fill: event.status.fill, fill: event.status.fill,
@ -45,6 +52,7 @@ function handleStatusEvent(event) {
}; };
publish("status/"+event.id,status,true); publish("status/"+event.id,status,true);
} }
}
function handleRuntimeEvent(event) { function handleRuntimeEvent(event) {
runtime.log.trace("runtime event: "+JSON.stringify(event)); runtime.log.trace("runtime event: "+JSON.stringify(event));
publish("notification/"+event.id,event.payload||{},event.retain); publish("notification/"+event.id,event.payload||{},event.retain);

View File

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

View File

@ -18,6 +18,7 @@ const clone = require("clone");
const Flow = require('./Flow').Flow; const Flow = require('./Flow').Flow;
const context = require('../nodes/context'); const context = require('../nodes/context');
const util = require("util"); const util = require("util");
const events = require("../events");
const redUtil = require("@node-red/util").util; const redUtil = require("@node-red/util").util;
const flowUtil = require("./util"); const flowUtil = require("./util");
@ -308,7 +309,26 @@ class Subflow extends Flow {
super.start(diff); 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 * Get environment variable of subflow
* @param {String} name name of env var * @param {String} name name of env var

View File

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

View File

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

View File

@ -211,6 +211,82 @@ describe("runtime-api/comms", function() {
}); });
}).catch(done); }).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) { it('retained messages get cleared',function(done) {
eventHandlers['comms']({ eventHandlers['comms']({
topic: "my-event", topic: "my-event",