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 2023-02-02 10:40:33 +00:00
commit 68bb38b8d7
No known key found for this signature in database
GPG Key ID: 4F2157149161A6C9
135 changed files with 1055 additions and 357 deletions

View File

@ -5,6 +5,9 @@ on:
release: release:
types: [published] types: [published]
permissions:
contents: read
jobs: jobs:
generate: generate:
name: 'Update node-red-docker image' name: 'Update node-red-docker image'

View File

@ -6,8 +6,14 @@ on:
pull_request: pull_request:
branches: [ master, dev ] branches: [ master, dev ]
permissions:
contents: read
jobs: jobs:
build: build:
permissions:
checks: write # for coverallsapp/github-action to create new checks
contents: read # for actions/checkout to fetch code
runs-on: ubuntu-latest runs-on: ubuntu-latest
strategy: strategy:
matrix: matrix:

View File

@ -1,3 +1,37 @@
#### 3.0.2: Maintenance Release
Editor
- Fix workspace chart bottom property (#3812) @bonanitech
- Update german translation (#3802) @Dennis14e
- Support color reset to the default in subflow and group (#3801) @kazuhitoyokoi
- Allow generateNodeNames to handle names containing regex control chars (#3817) @knolleary
- Hide scrollbars until they're needed (#3808) @bonanitech
- Include junctions/groups when exporting subflows plus related fixes (#3816) @knolleary
- remove console.log (#3820) @Steve-Mcl
Runtime
- Register subflow module instance node with parent flow (#3818) @knolleary
Nodes
- HTTP Request: Allow HTTP Headers not in spec (#3776) @hardillb
#### 3.0.1: Maintenance Release
Editor
- Allow codeEditor theme to be set even if `codeEditor` is not set in settings.js (#3794) @Steve-Mcl
- Sys info (diagnostics report) amendments (#3793) @Steve-Mcl
- Allow `mode` and `title` to be omitted in `options` argument for `createEditor` (#3791) @Steve-Mcl
- Fix focus issues (#3789) @Steve-Mcl
- Ensure all typedInput buttons have button type set (#3788) @knolleary
- Do not flag hasUsers=false nodes as unused in search (#3787) @knolleary
- Properly position quick-add dialog in all cases (#3786) @knolleary
- Ensure quick-add dialog does not obscure ghost node when shifted (#3785) @knolleary
- Remove use of Object.hasOwn (#3784) @knolleary
#### 3.0.0: Milestone Release #### 3.0.0: Milestone Release
Editor Editor

View File

@ -327,9 +327,8 @@ module.exports = {
themeContext.header.url = themePlugin.header.url || themeContext.header.url themeContext.header.url = themePlugin.header.url || themeContext.header.url
} }
} }
if(theme.codeEditor) { theme.codeEditor = theme.codeEditor || {}
theme.codeEditor.options = Object.assign({}, themePlugin.monacoOptions, theme.codeEditor.options); theme.codeEditor.options = Object.assign({}, themePlugin.monacoOptions, theme.codeEditor.options);
}
} }
activeThemeInitialised = true; activeThemeInitialised = true;
} }

77
packages/node_modules/@node-red/editor-client/locales/de/editor.json vendored Executable file → Normal file
View File

@ -105,7 +105,7 @@
"search": "Flows durchsuchen", "search": "Flows durchsuchen",
"searchInput": "Flows durchsuchen", "searchInput": "Flows durchsuchen",
"subflows": "Subflow", "subflows": "Subflow",
"createSubflow": "Subflow", "createSubflow": "Hinzufügen",
"selectionToSubflow": "Auswahl in Subflow umwandeln", "selectionToSubflow": "Auswahl in Subflow umwandeln",
"flows": "Flow", "flows": "Flow",
"add": "Hinzufügen", "add": "Hinzufügen",
@ -152,7 +152,8 @@
"zoom-in": "Vergrößern", "zoom-in": "Vergrößern",
"search-flows": "Flows durchsuchen", "search-flows": "Flows durchsuchen",
"search-prev": "Vorherige", "search-prev": "Vorherige",
"search-next": "Nächste" "search-next": "Nächste",
"search-counter": "\"__term__\" __result__ von __count__"
}, },
"user": { "user": {
"loggedInAs": "Angemeldet als __name__", "loggedInAs": "Angemeldet als __name__",
@ -168,7 +169,11 @@
} }
}, },
"notification": { "notification": {
"warning": "<strong>Warnung:</strong> __message__", "state": {
"flowsStopped": "Flows gestoppt",
"flowsStarted": "Flows gestartet"
},
"warning": "<strong>Warnung</strong>: __message__",
"warnings": { "warnings": {
"undeployedChanges": "Node hat nicht übernommene (deploy) Änderungen", "undeployedChanges": "Node hat nicht übernommene (deploy) Änderungen",
"nodeActionDisabled": "Node-Aktionen deaktiviert", "nodeActionDisabled": "Node-Aktionen deaktiviert",
@ -177,15 +182,15 @@
"missing-modules": "<p>Flows angehalten aufgrund fehlender Module</p>", "missing-modules": "<p>Flows angehalten aufgrund fehlender Module</p>",
"safe-mode": "<p>Flows sind im abgesicherten Modus gestoppt.</p><p>Flows können bearbeitet und übernommen (deploy) werden, um sie neu zu starten.</p>", "safe-mode": "<p>Flows sind im abgesicherten Modus gestoppt.</p><p>Flows können bearbeitet und übernommen (deploy) werden, um sie neu zu starten.</p>",
"restartRequired": "Node-RED muss neu gestartet werden, damit die Module nach Upgrade aktiviert werden", "restartRequired": "Node-RED muss neu gestartet werden, damit die Module nach Upgrade aktiviert werden",
"credentials_load_failed": "<p>Flows gestoppt, da die Berechtigungen nicht entschlüsselt werden konnten.</p><p>Die Datei mit dem Flow-Berechtigungen ist verschlüsselt, aber der Schlüssel des Projekts fehlt oder ist ungültig.</p>", "credentials_load_failed": "<p>Flows gestoppt, da die Credentials nicht entschlüsselt werden konnten.</p><p>Die Datei mit den Flow-Credentials ist verschlüsselt, aber der Schlüssel des Projekts fehlt oder ist ungültig.</p>",
"credentials_load_failed_reset": "<p>Die Berechtigungen konnten nicht entschlüsselt werden.</p><p>Die Datei mit den Flow-Berechtigungen ist verschlüsselt, aber der Schlüssel des Projekts fehlt oder ist ungültig.</p><p>Die Datei mit den Flow-Berechtigungen wird bei der nächsten Übernahme (deploy) zurückgesetzt. Alle vorhandenen Flow-Berechtigungen werden gelöscht.</p>", "credentials_load_failed_reset": "<p>Die Credentials konnten nicht entschlüsselt werden.</p><p>Die Datei mit den Flow-Credentials ist verschlüsselt, aber der Schlüssel des Projekts fehlt oder ist ungültig.</p><p>Die Datei mit den Flow-Credentials wird bei der nächsten Übernahme (deploy) zurückgesetzt. Alle vorhandenen Flow-Credentials werden gelöscht.</p>",
"missing_flow_file": "<p>Die Flow-Datei des Projekts wurde nicht gefunden.</p><p>Das Projekt ist nicht mit einer Flow-Datei konfiguriert.</p>", "missing_flow_file": "<p>Die Flow-Datei des Projekts wurde nicht gefunden.</p><p>Das Projekt ist nicht mit einer Flow-Datei konfiguriert.</p>",
"missing_package_file": "<p>Die Paket-Datei des Projekts wurde nicht gefunden.</p><p>In dem Projekt fehlt die 'package.json'-Datei.</p>", "missing_package_file": "<p>Die Paket-Datei des Projekts wurde nicht gefunden.</p><p>In dem Projekt fehlt die 'package.json'-Datei.</p>",
"project_empty": "<p>Das Projekt ist leer.</p><p>Soll ein Standardsatz an Projektdateien erstellen werden?<br/>Andernfalls müssen die Dateien manuell außerhalb des Editors dem Projekt hinzugefügt werden.</p>", "project_empty": "<p>Das Projekt ist leer.</p><p>Soll ein Standardsatz an Projektdateien erstellen werden?<br/>Andernfalls müssen die Dateien manuell außerhalb des Editors dem Projekt hinzugefügt werden.</p>",
"project_not_found": "<p>Das Projekt '__project__' wurde nicht gefunden.</p>", "project_not_found": "<p>Das Projekt '__project__' wurde nicht gefunden.</p>",
"git_merge_conflict": "<p>Der automatische Merge der Änderungen ist fehlgeschlagen.</p><p>Die Merge-Konflikte müssen behoben und die Ergebnisse ins Repository übertragen werden (commit).</p>" "git_merge_conflict": "<p>Der automatische Merge der Änderungen ist fehlgeschlagen.</p><p>Die Merge-Konflikte müssen behoben und die Ergebnisse ins Repository übertragen werden (commit).</p>"
}, },
"error": "<strong>Fehler:</strong> __message__", "error": "<strong>Fehler</strong>: __message__",
"errors": { "errors": {
"lostConnection": "Verbindung zum Server verloren. Verbindung wird erneut hergestellt ...", "lostConnection": "Verbindung zum Server verloren. Verbindung wird erneut hergestellt ...",
"lostConnectionReconnect": "Verbindung zum Server verloren. Wiederherstellung der Verbindung in __time__s.", "lostConnectionReconnect": "Verbindung zum Server verloren. Wiederherstellung der Verbindung in __time__s.",
@ -203,7 +208,7 @@
"pull": "Projekt '__project__' erneut geladen", "pull": "Projekt '__project__' erneut geladen",
"revert": "Änderungen im Projekt '__project__' rückgängig gemacht", "revert": "Änderungen im Projekt '__project__' rückgängig gemacht",
"merge-complete": "Git-Merge abgeschlossen", "merge-complete": "Git-Merge abgeschlossen",
"setupCredentials": "Berechtigungen einrichten", "setupCredentials": "Credentials einrichten",
"setupProjectFiles": "Projektdateien einrichten", "setupProjectFiles": "Projektdateien einrichten",
"no": "Nein, Danke", "no": "Nein, Danke",
"createDefault": "Standardprojektdateien erstellen", "createDefault": "Standardprojektdateien erstellen",
@ -211,7 +216,7 @@
}, },
"label": { "label": {
"manage-project-dep": "Projektabhängigkeiten verwalten", "manage-project-dep": "Projektabhängigkeiten verwalten",
"setup-cred": "Berechtigungen einrichten", "setup-cred": "Credentials einrichten",
"setup-project": "Projektdateien einrichten", "setup-project": "Projektdateien einrichten",
"create-default-package": "Standardpaketdatei erstellen", "create-default-package": "Standardpaketdatei erstellen",
"no-thanks": "Nein, Danke", "no-thanks": "Nein, Danke",
@ -295,6 +300,10 @@
"modifiedFlowsDesc": "Übernimmt nur Flows, die geänderte Nodes enthalten", "modifiedFlowsDesc": "Übernimmt nur Flows, die geänderte Nodes enthalten",
"modifiedNodes": "Geänderte Nodes", "modifiedNodes": "Geänderte Nodes",
"modifiedNodesDesc": "Übernimmt nur Nodes, die sich geändert haben", "modifiedNodesDesc": "Übernimmt nur Nodes, die sich geändert haben",
"startFlows": "Start",
"startFlowsDesc": "Flows starten",
"stopFlows": "Stop",
"stopFlowsDesc": "Flows stoppen",
"restartFlows": "Flows neustarten", "restartFlows": "Flows neustarten",
"restartFlowsDesc": "Startet die aktuell übernommenen Flows (ohne vorheriges Deploy)", "restartFlowsDesc": "Startet die aktuell übernommenen Flows (ohne vorheriges Deploy)",
"successfulDeploy": "Erfolgreich übernommen (deploy)", "successfulDeploy": "Erfolgreich übernommen (deploy)",
@ -376,7 +385,7 @@
"confirmDelete": "Sind Sie sicher mit dem Löschen dieses Subflows?", "confirmDelete": "Sind Sie sicher mit dem Löschen dieses Subflows?",
"info": "Beschreibung", "info": "Beschreibung",
"category": "Kategorie", "category": "Kategorie",
"module": "Module", "module": "Modul",
"license": "Lizenz", "license": "Lizenz",
"licenseNone": "Keine", "licenseNone": "Keine",
"licenseOther": "Andere", "licenseOther": "Andere",
@ -434,7 +443,7 @@
"icon": "Icon", "icon": "Icon",
"inputType": "Eingangstyp", "inputType": "Eingangstyp",
"selectType": "Wähle Typen ...", "selectType": "Wähle Typen ...",
"loadCredentials": "Lade Node-Berechtigungen", "loadCredentials": "Lade Node-Credentials",
"inputs": { "inputs": {
"input": "Eingang", "input": "Eingang",
"select": "Auswahl", "select": "Auswahl",
@ -450,7 +459,7 @@
"json": "JSON", "json": "JSON",
"bin": "buffer", "bin": "buffer",
"env": "Umgebungsvariable", "env": "Umgebungsvariable",
"cred": "Berechtigung" "cred": "Credentials"
}, },
"menu": { "menu": {
"input": "Eingang", "input": "Eingang",
@ -470,7 +479,7 @@
"errors": { "errors": {
"scopeChange": "Wenn Sie den Geltungsbereich (scope) ändern, wird er für Nodes in anderen Flows nicht verfügbar sein", "scopeChange": "Wenn Sie den Geltungsbereich (scope) ändern, wird er für Nodes in anderen Flows nicht verfügbar sein",
"invalidProperties": "Ungültige Eigenschaften:", "invalidProperties": "Ungültige Eigenschaften:",
"credentialLoadFailed": "Laden der Node-Berechtigungen fehlgeschlagen" "credentialLoadFailed": "Laden der Node-Credentials fehlgeschlagen"
} }
}, },
"keyboard": { "keyboard": {
@ -683,7 +692,8 @@
"showHelp": "Hilfe zeigen", "showHelp": "Hilfe zeigen",
"showInOutline": "Zeige im Editor", "showInOutline": "Zeige im Editor",
"showTopics": "Zeige Hilfethemen", "showTopics": "Zeige Hilfethemen",
"noHelp": "Kein Hilfethema ausgewählt" "noHelp": "Kein Hilfethema ausgewählt",
"changeLog": "Änderungsprotokoll"
}, },
"config": { "config": {
"name": "Konfigurations-Node", "name": "Konfigurations-Node",
@ -737,7 +747,7 @@
"addToProject": "Zu Projekt hinzufügen", "addToProject": "Zu Projekt hinzufügen",
"files": "Dateien", "files": "Dateien",
"flow": "Flow", "flow": "Flow",
"credentials": "Berechtigungen", "credentials": "Credentials",
"package": "Paket", "package": "Paket",
"packageCreate": "Datei wird erstellt beim Speichern der Änderungen", "packageCreate": "Datei wird erstellt beim Speichern der Änderungen",
"fileNotExist": "Datei existiert nicht", "fileNotExist": "Datei existiert nicht",
@ -750,7 +760,7 @@
"changeTheEncryptionKey": "Schlüssel ändern", "changeTheEncryptionKey": "Schlüssel ändern",
"currentKey": "Aktueller Schlüssel", "currentKey": "Aktueller Schlüssel",
"newKey": "Neuer Schlüssel", "newKey": "Neuer Schlüssel",
"credentialsAlert": "Dadurch werden alle vorhandenen Berechtigungen gelöscht", "credentialsAlert": "Dadurch werden alle vorhandenen Credentials gelöscht",
"versionControl": "Versionsverwaltung (Git)", "versionControl": "Versionsverwaltung (Git)",
"branches": "Branches", "branches": "Branches",
"noBranches": "Keine Branches", "noBranches": "Keine Branches",
@ -886,7 +896,7 @@
"date": "timestamp", "date": "timestamp",
"jsonata": "JSONata", "jsonata": "JSONata",
"env": "Umgebungsvariable", "env": "Umgebungsvariable",
"cred": "Berechtigung" "cred": "Credentials"
} }
}, },
"editableList": { "editableList": {
@ -1026,7 +1036,7 @@
"passphrase": "Passphrase", "passphrase": "Passphrase",
"ssh-key-desc": "Bevor Sie ein Repository über SSH lokal klonen können, müssen Sie einen SSH-Schlüssel hinzufügen, um auf diesen zugreifen zu können", "ssh-key-desc": "Bevor Sie ein Repository über SSH lokal klonen können, müssen Sie einen SSH-Schlüssel hinzufügen, um auf diesen zugreifen zu können",
"ssh-key-add": "SSH-Schlüssel hinzufügen", "ssh-key-add": "SSH-Schlüssel hinzufügen",
"credential-key": "Schlüssel für Berechtigungen", "credential-key": "Schlüssel für Credentials",
"cant-get-ssh-key": "Fehler! Der ausgewählte SSH-Schlüsselpfad kann nicht abgerufen werden", "cant-get-ssh-key": "Fehler! Der ausgewählte SSH-Schlüsselpfad kann nicht abgerufen werden",
"already-exists2": "bereits vorhanden", "already-exists2": "bereits vorhanden",
"git-error": "Git-Fehler", "git-error": "Git-Fehler",
@ -1038,27 +1048,27 @@
"create": "Erstellen Sie Ihre Projektdateien", "create": "Erstellen Sie Ihre Projektdateien",
"desc0": "Ein Projekt enthält Ihre Flow-Dateien, eine README-Datei und die 'package.json'-Datei.", "desc0": "Ein Projekt enthält Ihre Flow-Dateien, eine README-Datei und die 'package.json'-Datei.",
"desc1": "Es kann alle anderen Dateien enthalten, die im Git-Repository verwaltet werden sollen.", "desc1": "Es kann alle anderen Dateien enthalten, die im Git-Repository verwaltet werden sollen.",
"desc2": "Ihre vorhandenen Flow- und Berechtigungs-Dateien werden in das Projekt kopiert.", "desc2": "Ihre vorhandenen Flow- und Credential-Dateien werden in das Projekt kopiert.",
"flow-file": "Flow-Datei", "flow-file": "Flow-Datei",
"credentials-file": "Datei mit Berechtigungen" "credentials-file": "Datei mit Credentials"
}, },
"encryption-config": { "encryption-config": {
"setup": "Einrichtung der Verschlüsselung Ihrer Datei mit den Berechtigungen", "setup": "Einrichtung der Verschlüsselung Ihrer Datei mit den Credentials",
"desc0": "Die Datei mit den Flow-Berechtigungen kann verschlüsselt werden, um ihren Inhalt zu schützen.", "desc0": "Die Datei mit den Flow-Credentials kann verschlüsselt werden, um ihren Inhalt zu schützen.",
"desc1": "Wenn Sie diese Berechtigungen in einem öffentlichen Repository speichern möchten, müssen Sie sie mit einen geheimen Schlüsselausdruck verschlüsseln.", "desc1": "Wenn Sie diese Credentials in einem öffentlichen Repository speichern möchten, müssen Sie sie mit einen geheimen Schlüsselausdruck verschlüsseln.",
"desc2": "Die Datei mit den Flow-Berechtigungen ist derzeit nicht verschlüsselt.", "desc2": "Die Datei mit den Flow-Credentials ist derzeit nicht verschlüsselt.",
"desc3": "D.h. ihr Inhalt (z.B. Passwörter und Zugriffs-Tokens) kann von jedem mit Zugriff auf die Datei gelesen werden.", "desc3": "D.h. ihr Inhalt (z.B. Passwörter und Zugriffs-Tokens) kann von jedem mit Zugriff auf die Datei gelesen werden.",
"desc4": "Wenn Sie diese Berechtigungen in einen öffentlichen Repository speichern möchten, müssen Sie diese verschlüsseln, indem Sie einen geheimen Schlüsselausdruck eingeben.", "desc4": "Wenn Sie diese Credentials in einen öffentlichen Repository speichern möchten, müssen Sie diese verschlüsseln, indem Sie einen geheimen Schlüsselausdruck eingeben.",
"desc5": "Ihre Datei mit den Flow-Berechtigungen wird derzeit mit dem Eintrag 'credentialSecret' Ihrer Einstellungsdatei als Schlüssel verschlüsselt.", "desc5": "Ihre Datei mit den Flow-Credentials wird derzeit mit dem Eintrag 'credentialSecret' Ihrer Einstellungsdatei als Schlüssel verschlüsselt.",
"desc6": "Die Datei mit den Flow-Berechtigungen wird derzeit mit einem vom System generierten Schlüssel verschlüsselt. Sie sollten einen neuen geheimen Schlüssel für dieses Projekt vorgeben.", "desc6": "Die Datei mit den Flow-Credentials wird derzeit mit einem vom System generierten Schlüssel verschlüsselt. Sie sollten einen neuen geheimen Schlüssel für dieses Projekt vorgeben.",
"desc7": "Der Schlüssel wird separat von den Projektdateien gespeichert. Sie müssen den Schlüssel angeben, damit dieses Projekt auch in einem anderen Node-RED-System verwendet werden kann.", "desc7": "Der Schlüssel wird separat von den Projektdateien gespeichert. Sie müssen den Schlüssel angeben, damit dieses Projekt auch in einem anderen Node-RED-System verwendet werden kann.",
"credentials": "Berechtigung", "credentials": "Credentials",
"enable": "Verschlüsselung aktivieren", "enable": "Verschlüsselung aktivieren",
"disable": "Verschlüsselung deaktivieren", "disable": "Verschlüsselung deaktivieren",
"disabled": "deaktiviert", "disabled": "deaktiviert",
"copy": "Vorhandenen Schlüssel ersetzen", "copy": "Vorhandenen Schlüssel ersetzen",
"use-custom": "Eigenen Schlüssel verwenden", "use-custom": "Eigenen Schlüssel verwenden",
"desc8": "Die Datei mit den Berechtigungen wird nicht verschlüsselt, und ihr Inhalt kann leicht gelesen werden", "desc8": "Die Datei mit den Credentials wird nicht verschlüsselt und ihr Inhalt kann leicht gelesen werden",
"create-project-files": "Projektdateien erstellen", "create-project-files": "Projektdateien erstellen",
"create-project": "Projekt erstellen", "create-project": "Projekt erstellen",
"already-exists": "bereits vorhanden", "already-exists": "bereits vorhanden",
@ -1083,12 +1093,12 @@
"desc": "Beschreibung", "desc": "Beschreibung",
"opt": "Optional", "opt": "Optional",
"flow-file": "Flow-Datei", "flow-file": "Flow-Datei",
"credentials": "Berechtigungen", "credentials": "Credentials",
"enable-encryption": "Verschlüsselung aktivieren", "enable-encryption": "Verschlüsselung aktivieren",
"disable-encryption": "Verschlüsselung deaktivieren", "disable-encryption": "Verschlüsselung deaktivieren",
"encryption-key": "Schlüssel", "encryption-key": "Schlüssel",
"desc0": "Eine Floskel, mit der Sie Ihre Berechtigungen schützen", "desc0": "Eine Ausdruck, mit der Sie Ihre Credentials schützen",
"desc1": "Die Datei mit den Berechtigungen wird nicht verschlüsselt, und ihr Inhalt kann leicht gelesen werden", "desc1": "Die Datei mit den Credentials wird nicht verschlüsselt und ihr Inhalt kann leicht gelesen werden",
"git-url": "Git-Repository-URL", "git-url": "Git-Repository-URL",
"protocols": "https://, ssh:// oder file://", "protocols": "https://, ssh:// oder file://",
"auth-failed": "Authentifizierung fehlgeschlagen", "auth-failed": "Authentifizierung fehlgeschlagen",
@ -1098,7 +1108,7 @@
"passphrase": "Passphrase", "passphrase": "Passphrase",
"desc2": "Bevor Sie ein Repository über SSH klonen können, müssen Sie einen SSH-Schlüssel hinzufügen, um auf diesen zu zugreifen", "desc2": "Bevor Sie ein Repository über SSH klonen können, müssen Sie einen SSH-Schlüssel hinzufügen, um auf diesen zu zugreifen",
"add-ssh-key": "Einen SSH-Schlüssel hinzufügen", "add-ssh-key": "Einen SSH-Schlüssel hinzufügen",
"credentials-encryption-key": "Schlüssel für Berechtigungen", "credentials-encryption-key": "Schlüssel für Credentials",
"already-exists-2": "bereits vorhanden", "already-exists-2": "bereits vorhanden",
"git-error": "Git-Fehler", "git-error": "Git-Fehler",
"con-failed": "Verbindung fehlgeschlagen", "con-failed": "Verbindung fehlgeschlagen",
@ -1156,7 +1166,8 @@
"tourGuide": { "tourGuide": {
"takeATour": "Tour starten", "takeATour": "Tour starten",
"start": "Start", "start": "Start",
"next": "Nächste" "next": "Nächste",
"welcomeTours": "Welcome Tours"
}, },
"diagnostics": { "diagnostics": {
"title": "System-Informationen" "title": "System-Informationen"

View File

View File

View File

@ -944,6 +944,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

View File

View File

@ -943,8 +943,11 @@
"errors": { "errors": {
"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コンテキスト関数をテストできません",
"eval": "表現評価エラー:\n __message__" "env-unsupported": "$env関数はテストできません",
"moment-unsupported": "$moment関数はテストできません",
"clone-unsupported": "$clone関数はテストできません",
"eval": "式評価エラー:\n __message__"
} }
}, },
"monaco": { "monaco": {

View File

View File

View File

View File

View File

View File

View File

@ -868,14 +868,7 @@ RED.nodes = (function() {
var node; var node;
if (allNodes.hasTab(id)) { if (allNodes.hasTab(id)) {
removedNodes = allNodes.getNodes(id).filter(n => { removedNodes = allNodes.getNodes(id).slice()
if (n.type === 'junction') {
removedJunctions.push(n)
return false
} else {
return true
}
})
} }
for (i in configNodes) { for (i in configNodes) {
if (configNodes.hasOwnProperty(i)) { if (configNodes.hasOwnProperty(i)) {
@ -885,6 +878,7 @@ RED.nodes = (function() {
} }
} }
} }
removedJunctions = RED.nodes.junctions(id)
for (i=0;i<removedNodes.length;i++) { for (i=0;i<removedNodes.length;i++) {
var result = removeNode(removedNodes[i].id); var result = removeNode(removedNodes[i].id);
@ -1331,7 +1325,6 @@ RED.nodes = (function() {
} else { } else {
nodeSet = [sf]; nodeSet = [sf];
} }
console.log(nodeSet);
return createExportableNodeSet(nodeSet); return createExportableNodeSet(nodeSet);
} }
/** /**
@ -1367,6 +1360,10 @@ RED.nodes = (function() {
exportedConfigNodes[n.id] = true; exportedConfigNodes[n.id] = true;
} }
}); });
subflowSet = subflowSet.concat(RED.nodes.junctions(subflowId))
subflowSet = subflowSet.concat(RED.nodes.groups(subflowId))
var exportableSubflow = createExportableNodeSet(subflowSet, exportedIds, exportedSubflows, exportedConfigNodes); var exportableSubflow = createExportableNodeSet(subflowSet, exportedIds, exportedSubflows, exportedConfigNodes);
nns = exportableSubflow.concat(nns); nns = exportableSubflow.concat(nns);
} }
@ -1968,7 +1965,7 @@ RED.nodes = (function() {
} }
} }
} else { } else {
const keepNodesCurrentZ = reimport && n.z && RED.workspaces.contains(n.z) const keepNodesCurrentZ = reimport && n.z && (RED.workspaces.contains(n.z) || RED.nodes.subflow(n.z))
if (!keepNodesCurrentZ && n.z && !workspace_map[n.z] && !subflow_map[n.z]) { if (!keepNodesCurrentZ && n.z && !workspace_map[n.z] && !subflow_map[n.z]) {
n.z = activeWorkspace; n.z = activeWorkspace;
} }
@ -2070,7 +2067,7 @@ RED.nodes = (function() {
node.id = getID(); node.id = getID();
} else { } else {
node.id = n.id; node.id = n.id;
const keepNodesCurrentZ = reimport && node.z && RED.workspaces.contains(node.z) const keepNodesCurrentZ = reimport && node.z && (RED.workspaces.contains(node.z) || RED.nodes.subflow(node.z))
if (!keepNodesCurrentZ && (node.z == null || (!workspace_map[node.z] && !subflow_map[node.z]))) { if (!keepNodesCurrentZ && (node.z == null || (!workspace_map[node.z] && !subflow_map[node.z]))) {
if (createMissingWorkspace) { if (createMissingWorkspace) {
if (missingWorkspace === null) { if (missingWorkspace === null) {
@ -2743,6 +2740,7 @@ RED.nodes = (function() {
} }
}); });
const nodeGroupMap = {}
var replaceNodeIds = Object.keys(replaceNodes); var replaceNodeIds = Object.keys(replaceNodes);
if (replaceNodeIds.length > 0) { if (replaceNodeIds.length > 0) {
var reimportList = []; var reimportList = [];
@ -2753,6 +2751,12 @@ RED.nodes = (function() {
} else { } else {
allNodes.removeNode(n); allNodes.removeNode(n);
} }
if (n.g) {
// reimporting a node *without* including its group object
// will cause the g property to be cleared. Cache it
// here so we can restore it
nodeGroupMap[n.id] = n.g
}
reimportList.push(convertNode(n)); reimportList.push(convertNode(n));
RED.events.emit('nodes:remove',n); RED.events.emit('nodes:remove',n);
}); });
@ -2774,6 +2778,18 @@ RED.nodes = (function() {
var newNodeMap = {}; var newNodeMap = {};
result.nodes.forEach(function(n) { result.nodes.forEach(function(n) {
newNodeMap[n.id] = n; newNodeMap[n.id] = n;
if (nodeGroupMap[n.id]) {
// This node is in a group - need to substitute the
// node reference inside the group
n.g = nodeGroupMap[n.id]
const group = RED.nodes.group(n.g)
if (group) {
var index = group.nodes.findIndex(gn => gn.id === n.id)
if (index > -1) {
group.nodes[index] = n
}
}
}
}); });
RED.nodes.eachLink(function(l) { RED.nodes.eachLink(function(l) {
if (newNodeMap.hasOwnProperty(l.source.id)) { if (newNodeMap.hasOwnProperty(l.source.id)) {

View File

@ -348,6 +348,8 @@ var RED = (function() {
loader.end() loader.end()
RED.notify($("<p>").text(message)); RED.notify($("<p>").text(message));
RED.sidebar.info.refresh() RED.sidebar.info.refresh()
RED.menu.setDisabled('menu-item-projects-open',false);
RED.menu.setDisabled('menu-item-projects-settings',false);
}); });
}); });
return; return;
@ -794,7 +796,7 @@ var RED = (function() {
$('<div id="red-ui-header-shade" class="hide"></div>').appendTo(header); $('<div id="red-ui-header-shade" class="hide"></div>').appendTo(header);
$('<div id="red-ui-main-container" class="red-ui-sidebar-closed hide">'+ $('<div id="red-ui-main-container" class="red-ui-sidebar-closed hide">'+
'<div id="red-ui-workspace"></div>'+ '<div id="red-ui-workspace"></div>'+
'<div id="red-ui-editor-stack"></div>'+ '<div id="red-ui-editor-stack" tabindex="-1"></div>'+
'<div id="red-ui-palette"></div>'+ '<div id="red-ui-palette"></div>'+
'<div id="red-ui-sidebar"></div>'+ '<div id="red-ui-sidebar"></div>'+
'<div id="red-ui-sidebar-separator"></div>'+ '<div id="red-ui-sidebar-separator"></div>'+

View File

@ -160,7 +160,7 @@
this.element.css("maxHeight",null); this.element.css("maxHeight",null);
} }
if (this.options.height !== 'auto') { if (this.options.height !== 'auto') {
this.uiContainer.css("overflow-y","scroll"); this.uiContainer.css("overflow-y","auto");
if (!isNaN(this.options.height)) { if (!isNaN(this.options.height)) {
this.uiHeight = this.options.height; this.uiHeight = this.options.height;
} }

View File

@ -146,7 +146,7 @@
{ value: "reset", source: ["delay","trigger","join","rbe"] }, { value: "reset", source: ["delay","trigger","join","rbe"] },
{ value: "responseCookies", source: ["http request"] }, { value: "responseCookies", source: ["http request"] },
{ value: "responseTopic", source: ["mqtt"] }, { value: "responseTopic", source: ["mqtt"] },
{ value: "responseURL", source: ["http request"] }, { value: "responseUrl", source: ["http request"] },
{ value: "restartTimeout", source: ["join"] }, { value: "restartTimeout", source: ["join"] },
{ value: "retain", source: ["mqtt"] }, { value: "retain", source: ["mqtt"] },
{ value: "schema", source: ["json"] }, { value: "schema", source: ["json"] },
@ -501,7 +501,7 @@
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 type="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);
this.selectLabel = $('<span class="red-ui-typedInput-type-label"></span>').appendTo(this.selectTrigger); this.selectLabel = $('<span class="red-ui-typedInput-type-label"></span>').appendTo(this.selectTrigger);
@ -570,7 +570,7 @@
}) })
// explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline' // explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline'
this.optionSelectTrigger = $('<button tabindex="0" class="red-ui-typedInput-option-trigger" style="display:inline-block"><span class="red-ui-typedInput-option-caret"><i class="red-ui-typedInput-icon fa fa-caret-down"></i></span></button>').appendTo(this.uiSelect); this.optionSelectTrigger = $('<button type="button" tabindex="0" class="red-ui-typedInput-option-trigger" style="display:inline-block"><span class="red-ui-typedInput-option-caret"><i class="red-ui-typedInput-icon fa fa-caret-down"></i></span></button>').appendTo(this.uiSelect);
this.optionSelectLabel = $('<span class="red-ui-typedInput-option-label"></span>').prependTo(this.optionSelectTrigger); this.optionSelectLabel = $('<span class="red-ui-typedInput-option-label"></span>').prependTo(this.optionSelectTrigger);
// RED.popover.tooltip(this.optionSelectLabel,function() { // RED.popover.tooltip(this.optionSelectLabel,function() {
// return that.optionValue; // return that.optionValue;
@ -591,7 +591,7 @@
that.uiSelect.addClass('red-ui-typedInput-focus'); that.uiSelect.addClass('red-ui-typedInput-focus');
}); });
this.optionExpandButton = $('<button tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"></button>').appendTo(this.uiSelect); this.optionExpandButton = $('<button type="button" tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"></button>').appendTo(this.uiSelect);
this.optionExpandButtonIcon = $('<i class="red-ui-typedInput-icon fa fa-ellipsis-h"></i>').appendTo(this.optionExpandButton); this.optionExpandButtonIcon = $('<i class="red-ui-typedInput-icon fa fa-ellipsis-h"></i>').appendTo(this.optionExpandButton);
this.type(this.typeField.val() || this.options.default||this.typeList[0].value); this.type(this.typeField.val() || this.options.default||this.typeList[0].value);

View File

@ -238,6 +238,7 @@ RED.editor = (function() {
var valid = validateNodeProperty(node, defaults, property,value); var valid = validateNodeProperty(node, defaults, property,value);
if (((typeof valid) === "string") || !valid) { if (((typeof valid) === "string") || !valid) {
input.addClass("input-error"); input.addClass("input-error");
input.next(".red-ui-typedInput-container").addClass("input-error");
if ((typeof valid) === "string") { if ((typeof valid) === "string") {
var tooltip = input.data("tooltip"); var tooltip = input.data("tooltip");
if (tooltip) { if (tooltip) {
@ -250,6 +251,7 @@ RED.editor = (function() {
} }
} else { } else {
input.removeClass("input-error"); input.removeClass("input-error");
input.next(".red-ui-typedInput-container").removeClass("input-error");
var tooltip = input.data("tooltip"); var tooltip = input.data("tooltip");
if (tooltip) { if (tooltip) {
input.data("tooltip", null); input.data("tooltip", null);
@ -1105,6 +1107,10 @@ RED.editor = (function() {
if (editing_node) { if (editing_node) {
RED.sidebar.info.refresh(editing_node); RED.sidebar.info.refresh(editing_node);
RED.sidebar.help.show(editing_node.type, false); RED.sidebar.help.show(editing_node.type, false);
//ensure focused element is NOT body (for keyboard scope to operate correctly)
if (document.activeElement.tagName === 'BODY') {
$('#red-ui-editor-stack').trigger('focus')
}
} }
} }
} }

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 = {};
@ -764,7 +764,7 @@ RED.editor.codeEditor.monaco = (function() {
if(!options.stateId && options.stateId !== false) { if(!options.stateId && options.stateId !== false) {
options.stateId = RED.editor.generateViewStateId("monaco", options, (options.mode || options.title).split("/").pop()); options.stateId = RED.editor.generateViewStateId("monaco", options, (options.mode || options.title || "").split("/").pop());
} }
var el = options.element || $("#"+options.id)[0]; var el = options.element || $("#"+options.id)[0];
var toolbarRow = $("<div>").appendTo(el); var toolbarRow = $("<div>").appendTo(el);

View File

@ -76,6 +76,9 @@ RED.editor.colorPicker = RED.colorPicker = (function() {
var focusTarget = colorInput; var focusTarget = colorInput;
colorInput.on("change", function (e) { colorInput.on("change", function (e) {
var color = colorInput.val(); var color = colorInput.val();
if (options.defaultValue && !color.match(/^([a-z]+|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3})$/)) {
color = options.defaultValue;
}
colorHiddenInput.val(color).trigger('change'); colorHiddenInput.val(color).trigger('change');
refreshDisplay(color); refreshDisplay(color);
}); });

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

@ -235,6 +235,7 @@
RED.editor.colorPicker.create({ RED.editor.colorPicker.create({
id: "red-ui-editor-node-color", id: "red-ui-editor-node-color",
value: color, value: color,
defaultValue: "#DDAA99",
palette: recommendedColors, palette: recommendedColors,
sortPalette: function (a, b) {return a.l - b.l;} sortPalette: function (a, b) {return a.l - b.l;}
}).appendTo(colorRow); }).appendTo(colorRow);

View File

@ -101,6 +101,7 @@ RED.group = (function() {
RED.editor.colorPicker.create({ RED.editor.colorPicker.create({
id:"node-input-style-stroke", id:"node-input-style-stroke",
value: style.stroke || defaultGroupStyle.stroke || "#a4a4a4", value: style.stroke || defaultGroupStyle.stroke || "#a4a4a4",
defaultValue: "#a4a4a4",
palette: colorPalette, palette: colorPalette,
cellPerRow: colorCount, cellPerRow: colorCount,
cellWidth: 16, cellWidth: 16,
@ -112,6 +113,7 @@ RED.group = (function() {
RED.editor.colorPicker.create({ RED.editor.colorPicker.create({
id:"node-input-style-fill", id:"node-input-style-fill",
value: style.fill || defaultGroupStyle.fill ||"none", value: style.fill || defaultGroupStyle.fill ||"none",
defaultValue: "none",
palette: colorPalette, palette: colorPalette,
cellPerRow: colorCount, cellPerRow: colorCount,
cellWidth: 16, cellWidth: 16,
@ -129,6 +131,7 @@ RED.group = (function() {
RED.editor.colorPicker.create({ RED.editor.colorPicker.create({
id:"node-input-style-color", id:"node-input-style-color",
value: style.color || defaultGroupStyle.color ||"#a4a4a4", value: style.color || defaultGroupStyle.color ||"#a4a4a4",
defaultValue: "#a4a4a4",
palette: colorPalette, palette: colorPalette,
cellPerRow: colorCount, cellPerRow: colorCount,
cellWidth: 16, cellWidth: 16,

0
packages/node_modules/@node-red/editor-client/src/js/ui/library.js vendored Executable file → Normal file
View File

16
packages/node_modules/@node-red/editor-client/src/js/ui/palette.js vendored Executable file → Normal file
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);
@ -422,6 +432,7 @@ RED.palette = (function() {
categoryNode.find(".red-ui-palette-content").slideToggle(); categoryNode.find(".red-ui-palette-content").slideToggle();
categoryNode.find("i").toggleClass("expanded"); categoryNode.find("i").toggleClass("expanded");
} }
categoryNode.hide();
} }
} }
@ -500,6 +511,7 @@ RED.palette = (function() {
currentCategoryNode.find(".red-ui-palette-content").slideToggle(); currentCategoryNode.find(".red-ui-palette-content").slideToggle();
currentCategoryNode.find("i").toggleClass("expanded"); currentCategoryNode.find("i").toggleClass("expanded");
} }
currentCategoryNode.hide();
} }
} }

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++;
}
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);
} }
var flags = {}; 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,8 +199,8 @@ 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) (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

@ -510,6 +510,13 @@ RED.subflow = (function() {
RED.nodes.groups(id).forEach(function(n) { RED.nodes.groups(id).forEach(function(n) {
removedGroups.push(n); removedGroups.push(n);
}) })
var removedJunctions = RED.nodes.junctions(id)
for (var i=0;i<removedJunctions.length;i++) {
var removedEntities = RED.nodes.removeJunction(removedJunctions[i])
removedLinks = removedLinks.concat(removedEntities.links)
}
var removedConfigNodes = []; var removedConfigNodes = [];
for (var i=0;i<removedNodes.length;i++) { for (var i=0;i<removedNodes.length;i++) {
var removedEntities = RED.nodes.remove(removedNodes[i].id); var removedEntities = RED.nodes.remove(removedNodes[i].id);
@ -540,6 +547,7 @@ RED.subflow = (function() {
nodes:removedNodes, nodes:removedNodes,
links:removedLinks, links:removedLinks,
groups: removedGroups, groups: removedGroups,
junctions: removedJunctions,
subflows: [activeSubflow] subflows: [activeSubflow]
} }
} }
@ -936,7 +944,6 @@ RED.subflow = (function() {
function buildEnvUIRow(row, tenv, ui, node) { function buildEnvUIRow(row, tenv, ui, node) {
console.log(tenv, ui)
ui.label = ui.label||{}; ui.label = ui.label||{};
if ((tenv.type === "cred" || (tenv.parent && tenv.parent.type === "cred")) && !ui.type) { if ((tenv.type === "cred" || (tenv.parent && tenv.parent.type === "cred")) && !ui.type) {
ui.type = "cred"; ui.type = "cred";

View File

@ -50,7 +50,7 @@ RED.sidebar.help = (function() {
tocPanel = $("<div>", {class: "red-ui-sidebar-help-toc"}).appendTo(stackContainer); tocPanel = $("<div>", {class: "red-ui-sidebar-help-toc"}).appendTo(stackContainer);
var helpPanel = $("<div>").css({ var helpPanel = $("<div>").css({
"overflow-y": "scroll" "overflow-y": "auto"
}).appendTo(stackContainer); }).appendTo(stackContainer);
panels = RED.panels.create({ panels = RED.panels.create({

View File

@ -108,7 +108,7 @@ RED.sidebar.info = (function() {
propertiesPanelContent = $("<div>").css({ propertiesPanelContent = $("<div>").css({
"flex":"1 1 auto", "flex":"1 1 auto",
"overflow-y":"scroll", "overflow-y":"auto",
}).appendTo(propertiesPanel); }).appendTo(propertiesPanel);

View File

@ -269,8 +269,8 @@ RED.typeSearch = (function() {
moveCallback = opts.move; moveCallback = opts.move;
RED.events.emit("type-search:open"); RED.events.emit("type-search:open");
//shade.show(); //shade.show();
if ($("#red-ui-main-container").height() - opts.y - 150 < 0) { if ($("#red-ui-main-container").height() - opts.y - 195 < 0) {
opts.y = opts.y - 235; opts.y = opts.y - 275;
} }
dialog.css({left:opts.x+"px",top:opts.y+"px"}).show(); dialog.css({left:opts.x+"px",top:opts.y+"px"}).show();
searchResultsDiv.slideDown(300); searchResultsDiv.slideDown(300);

View File

@ -1015,7 +1015,7 @@ RED.view.tools = (function() {
const nodeDef = n._def || RED.nodes.getType(n.type) const nodeDef = n._def || RED.nodes.getType(n.type)
if (nodeDef && nodeDef.defaults && nodeDef.defaults.name) { if (nodeDef && nodeDef.defaults && nodeDef.defaults.name) {
const paletteLabel = RED.utils.getPaletteLabel(n.type, nodeDef) const paletteLabel = RED.utils.getPaletteLabel(n.type, nodeDef)
const defaultNodeNameRE = new RegExp('^'+paletteLabel+' (\\d+)$') const defaultNodeNameRE = new RegExp('^'+paletteLabel.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')+' (\\d+)$')
if (!typeIndex.hasOwnProperty(n.type)) { if (!typeIndex.hasOwnProperty(n.type)) {
const existingNodes = RED.nodes.filterNodes({type: n.type}) const existingNodes = RED.nodes.filterNodes({type: n.type})
let maxNameNumber = 0; let maxNameNumber = 0;

12
packages/node_modules/@node-red/editor-client/src/js/ui/view.js vendored Executable file → Normal file
View File

@ -1072,12 +1072,15 @@ RED.view = (function() {
RED.view.redraw(); RED.view.redraw();
} }
// `point` is the place in the workspace the mouse has clicked.
// This takes into account scrolling and scaling of the workspace.
var ox = point[0]; var ox = point[0];
var oy = point[1]; var oy = point[1];
// Need to map that to browser location to position the pop-up
const offset = $("#red-ui-workspace-chart").offset() const offset = $("#red-ui-workspace-chart").offset()
var clientX = ox + offset.left - $("#red-ui-workspace-chart").scrollLeft() var clientX = (ox * scaleFactor) + offset.left - $("#red-ui-workspace-chart").scrollLeft()
var clientY = oy + offset.top - $("#red-ui-workspace-chart").scrollTop() var clientY = (oy * scaleFactor) + offset.top - $("#red-ui-workspace-chart").scrollTop()
if (RED.settings.get("editor").view['view-snap-grid']) { if (RED.settings.get("editor").view['view-snap-grid']) {
// eventLayer.append("circle").attr("cx",point[0]).attr("cy",point[1]).attr("r","2").attr('fill','red') // eventLayer.append("circle").attr("cx",point[0]).attr("cy",point[1]).attr("r","2").attr('fill','red')
@ -3367,6 +3370,9 @@ RED.view = (function() {
} }
if (dblClickPrimed && mousedown_node == d && clickElapsed > 0 && clickElapsed < dblClickInterval) { if (dblClickPrimed && mousedown_node == d && clickElapsed > 0 && clickElapsed < dblClickInterval) {
mouse_mode = RED.state.DEFAULT; mouse_mode = RED.state.DEFAULT;
// Avoid dbl click causing text selection.
d3.event.preventDefault()
document.getSelection().removeAllRanges()
if (d.type != "subflow") { if (d.type != "subflow") {
if (/^subflow:/.test(d.type) && (d3.event.ctrlKey || d3.event.metaKey)) { if (/^subflow:/.test(d.type) && (d3.event.ctrlKey || d3.event.metaKey)) {
RED.workspaces.show(d.type.substring(8)); RED.workspaces.show(d.type.substring(8));
@ -4907,7 +4913,7 @@ RED.view = (function() {
if (d._def.button) { if (d._def.button) {
var buttonEnabled = isButtonEnabled(d); var buttonEnabled = isButtonEnabled(d);
this.__buttonGroup__.classList.toggle("red-ui-flow-node-button-disabled", !buttonEnabled); this.__buttonGroup__.classList.toggle("red-ui-flow-node-button-disabled", !buttonEnabled);
if (RED.runtime && Object.hasOwn(RED.runtime,'started')) { if (RED.runtime && RED.runtime.started !== undefined) {
this.__buttonGroup__.classList.toggle("red-ui-flow-node-button-stopped", !RED.runtime.started); this.__buttonGroup__.classList.toggle("red-ui-flow-node-button-stopped", !RED.runtime.started);
} }

View File

@ -30,7 +30,7 @@
bottom: 0px; bottom: 0px;
left:0px; left:0px;
right: 0px; right: 0px;
overflow-y: scroll; overflow-y: auto;
} }
.red-ui-debug-filter-box { .red-ui-debug-filter-box {
position:absolute; position:absolute;

View File

@ -368,7 +368,7 @@ button.red-ui-button-small
border:1px solid var(--red-ui-secondary-border-color); border:1px solid var(--red-ui-secondary-border-color);
border-radius:5px; border-radius:5px;
height: calc(100% - 21px); height: calc(100% - 21px);
overflow-y: scroll; overflow-y: auto;
background: var(--red-ui-secondary-background); background: var(--red-ui-secondary-background);
} }
@ -562,7 +562,7 @@ div.red-ui-button-small.red-ui-color-picker-opacity-slider-handle {
.red-ui-icon-list { .red-ui-icon-list {
width: 308px; width: 308px;
height: 200px; height: 200px;
overflow-y: scroll; overflow-y: auto;
line-height: 0px; line-height: 0px;
position: relative; position: relative;
&.red-ui-icon-list-dark { &.red-ui-icon-list-dark {

View File

@ -32,7 +32,8 @@
color: var(--red-ui-primary-text-color); color: var(--red-ui-primary-text-color);
border: 1px solid var(--red-ui-notification-border-default); border: 1px solid var(--red-ui-notification-border-default);
border-left-width: 16px; border-left-width: 16px;
overflow: hidden; overflow: scroll;
max-height: 80vh;
.ui-dialog-buttonset { .ui-dialog-buttonset {
margin-top: 20px; margin-top: 20px;
margin-bottom: 10px; margin-bottom: 10px;

View File

@ -26,7 +26,7 @@
} }
} }
#red-ui-project-settings-tab-settings { #red-ui-project-settings-tab-settings {
overflow-y: scroll; overflow-y: auto;
} }
.red-ui-sidebar-vc-shade { .red-ui-sidebar-vc-shade {
background: var(--red-ui-primary-background); background: var(--red-ui-primary-background);
@ -183,7 +183,7 @@
} }
.red-ui-projects-dialog-project-list-inner-container { .red-ui-projects-dialog-project-list-inner-container {
flex-grow: 1 ; flex-grow: 1 ;
overflow-y: scroll; overflow-y: auto;
position:relative; position:relative;
.red-ui-editableList-border { .red-ui-editableList-border {
border: none; border: none;

View File

@ -41,6 +41,7 @@
height: 50px; height: 50px;
background: var(--red-ui-secondary-background); background: var(--red-ui-secondary-background);
border: 2px solid var(--red-ui-primary-border-color); border: 2px solid var(--red-ui-primary-border-color);
color: var(--red-ui-primary-text-color);
text-align: center; text-align: center;
line-height:50px; line-height:50px;
@ -51,7 +52,7 @@
.red-ui-editor-radial-menu-opt-disabled { .red-ui-editor-radial-menu-opt-disabled {
border-color: var(--red-ui-tertiary-border-color); border-color: var(--red-ui-tertiary-border-color);
color: var(--red-ui-tertiary-border-color); color: var(--red-ui-secondary-text-color-disabled);
} }
.red-ui-editor-radial-menu-opt-active { .red-ui-editor-radial-menu-opt-active {
background: var(--red-ui-secondary-background-hover); background: var(--red-ui-secondary-background-hover);

View File

@ -20,7 +20,7 @@
bottom: 0; bottom: 0;
left: 0; left: 0;
right: 0; right: 0;
overflow-y: scroll; overflow-y: auto;
.red-ui-palette-category { .red-ui-palette-category {
&:not(.expanded) button { &:not(.expanded) button {

View File

@ -67,7 +67,7 @@
left: 0; left: 0;
bottom: 0; bottom: 0;
padding: 8px 20px 20px; padding: 8px 20px 20px;
overflow-y: scroll; overflow-y: auto;
} }
.red-ui-settings-row { .red-ui-settings-row {
padding: 5px 10px 2px; padding: 5px 10px 2px;

View File

@ -29,7 +29,7 @@
#red-ui-workspace-chart { #red-ui-workspace-chart {
overflow: auto; overflow: auto;
position: absolute; position: absolute;
bottom:25px; bottom:26px;
top: 35px; top: 35px;
left:0px; left:0px;
right:0px; right:0px;

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

@ -95,45 +95,64 @@ module.exports = function(RED) {
} }
this.on("input", function(msg, send, done) { this.on("input", function(msg, send, done) {
var errors = []; const errors = [];
var props = this.props; let props = this.props;
if (msg.__user_inject_props__ && Array.isArray(msg.__user_inject_props__)) { if (msg.__user_inject_props__ && Array.isArray(msg.__user_inject_props__)) {
props = msg.__user_inject_props__; props = msg.__user_inject_props__;
} }
delete msg.__user_inject_props__; delete msg.__user_inject_props__;
props.forEach(p => { props = [...props]
var property = p.p; function evaluateProperty(doneEvaluating) {
var value = p.v ? p.v : ''; if (props.length === 0) {
var valueType = p.vt ? p.vt : 'str'; doneEvaluating()
return
}
const p = props.shift()
const property = p.p;
const value = p.v ? p.v : '';
const valueType = p.vt ? p.vt : 'str';
if (!property) return; if (property) {
if (valueType === "jsonata") {
if (valueType === "jsonata") { if (p.v) {
if (p.v) { try {
try { var exp = RED.util.prepareJSONataExpression(p.v, node);
var exp = RED.util.prepareJSONataExpression(p.v, node); var val = RED.util.evaluateJSONataExpression(exp, msg);
var val = RED.util.evaluateJSONataExpression(exp, msg); RED.util.setMessageProperty(msg, property, val, true);
RED.util.setMessageProperty(msg, property, val, true); }
catch (err) {
errors.push(err.message);
}
} }
catch (err) { evaluateProperty(doneEvaluating)
errors.push(err.message); } else {
try {
RED.util.evaluateNodeProperty(value, valueType, node, msg, (err, newValue) => {
if (err) {
errors.push(err.toString())
} else {
RED.util.setMessageProperty(msg,property,newValue,true);
}
evaluateProperty(doneEvaluating)
})
} catch (err) {
errors.push(err.toString());
evaluateProperty(doneEvaluating)
} }
} }
return; } else {
evaluateProperty(doneEvaluating)
} }
try {
RED.util.setMessageProperty(msg,property,RED.util.evaluateNodeProperty(value, valueType, this, msg),true);
} catch (err) {
errors.push(err.toString());
}
});
if (errors.length) {
done(errors.join('; '));
} else {
send(msg);
done();
} }
evaluateProperty(() => {
if (errors.length) {
done(errors.join('; '));
} else {
send(msg);
done();
}
})
}); });
} }

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

@ -4,7 +4,7 @@
<label style="width: auto" for="node-input-scope" data-i18n="catch.label.source"></label> <label style="width: auto" for="node-input-scope" data-i18n="catch.label.source"></label>
<select id="node-input-scope-select"> <select id="node-input-scope-select">
<option value="all" data-i18n="catch.scope.all"></option> <option value="all" data-i18n="catch.scope.all"></option>
<option value="target" data-i18n="catch.scope.selected"></options> <option value="target" data-i18n="catch.scope.selected"></option>
</select> </select>
</div> </div>
<div class="form-row node-input-uncaught-row"> <div class="form-row node-input-uncaught-row">
@ -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

@ -4,11 +4,11 @@
<label style="width: auto" for="node-input-scope" data-i18n="status.label.source"></label> <label style="width: auto" for="node-input-scope" data-i18n="status.label.source"></label>
<select id="node-input-scope-select"> <select id="node-input-scope-select">
<option value="all" data-i18n="status.scope.all"></option> <option value="all" data-i18n="status.scope.all"></option>
<option value="target" data-i18n="status.scope.selected"></options> <option value="target" data-i18n="status.scope.selected"></option>
</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

@ -17,6 +17,8 @@
display: flex; display: flex;
background: var(--red-ui-tertiary-background); background: var(--red-ui-tertiary-background);
padding-right: 75px; padding-right: 75px;
border-top-left-radius: 3px;
border-top-right-radius: 3px;
} }
#node-input-libs-container-row .red-ui-editableList-header > div { #node-input-libs-container-row .red-ui-editableList-header > div {
flex-grow: 1; flex-grow: 1;
@ -91,21 +93,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 +296,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");
@ -451,11 +453,13 @@
tabs.activateTab("func-tab-body"); tabs.activateTab("func-tab-body");
$( "#node-input-outputs" ).spinner({ $( "#node-input-outputs" ).spinner({
min:0, min: 0,
max: 500,
change: function(event, ui) { change: function(event, ui) {
var value = this.value; var value = parseInt(this.value);
if (!value.match(/^\d+$/)) { value = 1; } value = isNaN(value) ? 1 : value;
else if (value < this.min) { value = this.min; } value = Math.max(value, parseInt($(this).attr("aria-valuemin")));
value = Math.min(value, parseInt($(this).attr("aria-valuemax")));
if (value !== this.value) { $(this).spinner("value", value); } if (value !== this.value) { $(this).spinner("value", value); }
} }
}); });

View File

@ -318,7 +318,7 @@ module.exports = function(RED) {
} }
var r = node.rules[currentRule]; var r = node.rules[currentRule];
if (r.t === "move") { if (r.t === "move") {
if ((r.tot !== r.pt) || (r.p.indexOf(r.to) !== -1)) { if ((r.tot !== r.pt) || (r.p.indexOf(r.to) !== -1) && (r.p !== r.to)) {
applyRule(msg,{t:"set", p:r.to, pt:r.tot, to:r.p, tot:r.pt},(err,msg) => { applyRule(msg,{t:"set", p:r.to, pt:r.tot, to:r.p, tot:r.pt},(err,msg) => {
applyRule(msg,{t:"delete", p:r.p, pt:r.pt}, (err,msg) => { applyRule(msg,{t:"delete", p:r.p, pt:r.pt}, (err,msg) => {
completeApplyingRules(msg,currentRule,done); completeApplyingRules(msg,currentRule,done);

View File

@ -21,12 +21,13 @@
<option value="javascript">JavaScript</option> <option value="javascript">JavaScript</option>
<option value="css">CSS</option> <option value="css">CSS</option>
<option value="markdown">Markdown</option> <option value="markdown">Markdown</option>
<option value="php">PHP</option>
<option value="python">Python</option> <option value="python">Python</option>
<option value="sql">SQL</option> <option value="sql">SQL</option>
<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

@ -101,6 +101,7 @@
hostField.val(data.host); hostField.val(data.host);
} }
}, },
sortable: true,
removable: true removable: true
}); });
if (this.noproxy) { if (this.noproxy) {

View File

@ -421,7 +421,11 @@
<script type="text/javascript"> <script type="text/javascript">
(function() { (function() {
var typedInputNoneOpt = { value: 'none', label: '', hasValue: false }; var typedInputNoneOpt = {
value: 'none',
label: RED._("node-red:mqtt.label.none"),
hasValue: false
};
var makeTypedInputOpt = function(value){ var makeTypedInputOpt = function(value){
return { return {
value: value, value: value,
@ -436,7 +440,11 @@
makeTypedInputOpt("text/csv"), makeTypedInputOpt("text/csv"),
makeTypedInputOpt("text/html"), makeTypedInputOpt("text/html"),
makeTypedInputOpt("text/plain"), makeTypedInputOpt("text/plain"),
{value:"other", label:""} {
value: "other",
label: RED._("node-red:mqtt.label.other"),
icon: "red/images/typedInput/az.svg"
}
]; ];
function getDefaultContentType(value) { function getDefaultContentType(value) {
@ -499,17 +507,17 @@
cleansession: {value: true}, cleansession: {value: true},
birthTopic: {value:"", validate:validateMQTTPublishTopic}, birthTopic: {value:"", validate:validateMQTTPublishTopic},
birthQos: {value:"0"}, birthQos: {value:"0"},
birthRetain: {value:false}, birthRetain: {value:"false"},
birthPayload: {value:""}, birthPayload: {value:""},
birthMsg: { value: {}}, birthMsg: { value: {}},
closeTopic: {value:"", validate:validateMQTTPublishTopic}, closeTopic: {value:"", validate:validateMQTTPublishTopic},
closeQos: {value:"0"}, closeQos: {value:"0"},
closeRetain: {value:false}, closeRetain: {value:"false"},
closePayload: {value:""}, closePayload: {value:""},
closeMsg: { value: {}}, closeMsg: { value: {}},
willTopic: {value:"", validate:validateMQTTPublishTopic}, willTopic: {value:"", validate:validateMQTTPublishTopic},
willQos: {value:"0"}, willQos: {value:"0"},
willRetain: {value:false}, willRetain: {value:"false"},
willPayload: {value:""}, willPayload: {value:""},
willMsg: { value: {}}, willMsg: { value: {}},
userProps: { value: ""}, userProps: { value: ""},

View File

@ -366,6 +366,16 @@ module.exports = function(RED) {
} }
} }
function updateStatus(node, allNodes) {
let setStatus = setStatusDisconnected
if(node.connecting) {
setStatus = setStatusConnecting
} else if(node.connected) {
setStatus = setStatusConnected
}
setStatus(node, allNodes)
}
function setStatusDisconnected(node, allNodes) { function setStatusDisconnected(node, allNodes) {
if(allNodes) { if(allNodes) {
for (var id in node.users) { for (var id in node.users) {
@ -459,7 +469,6 @@ module.exports = function(RED) {
if(!opts || typeof opts !== "object") { if(!opts || typeof opts !== "object") {
return; //nothing to change, simply return return; //nothing to change, simply return
} }
const originalBrokerURL = node.brokerurl;
//apply property changes (only if the property exists in the opts object) //apply property changes (only if the property exists in the opts object)
setIfHasProperty(opts, node, "url", init); setIfHasProperty(opts, node, "url", init);
@ -468,13 +477,11 @@ module.exports = function(RED) {
setIfHasProperty(opts, node, "clientid", init); setIfHasProperty(opts, node, "clientid", init);
setIfHasProperty(opts, node, "autoConnect", init); setIfHasProperty(opts, node, "autoConnect", init);
setIfHasProperty(opts, node, "usetls", init); setIfHasProperty(opts, node, "usetls", init);
setIfHasProperty(opts, node, "usews", init);
setIfHasProperty(opts, node, "verifyservercert", init); setIfHasProperty(opts, node, "verifyservercert", init);
setIfHasProperty(opts, node, "compatmode", init); setIfHasProperty(opts, node, "compatmode", init);
setIfHasProperty(opts, node, "protocolVersion", init); setIfHasProperty(opts, node, "protocolVersion", init);
setIfHasProperty(opts, node, "keepalive", init); setIfHasProperty(opts, node, "keepalive", init);
setIfHasProperty(opts, node, "cleansession", init); setIfHasProperty(opts, node, "cleansession", init);
setIfHasProperty(opts, node, "sessionExpiry", init);
setIfHasProperty(opts, node, "topicAliasMaximum", init); setIfHasProperty(opts, node, "topicAliasMaximum", init);
setIfHasProperty(opts, node, "maximumPacketSize", init); setIfHasProperty(opts, node, "maximumPacketSize", init);
setIfHasProperty(opts, node, "receiveMaximum", init); setIfHasProperty(opts, node, "receiveMaximum", init);
@ -484,6 +491,11 @@ module.exports = function(RED) {
} else if (hasProperty(opts, "userProps")) { } else if (hasProperty(opts, "userProps")) {
node.userProperties = opts.userProps; node.userProperties = opts.userProps;
} }
if (hasProperty(opts, "sessionExpiry")) {
node.sessionExpiryInterval = opts.sessionExpiry;
} else if (hasProperty(opts, "sessionExpiryInterval")) {
node.sessionExpiryInterval = opts.sessionExpiryInterval
}
function createLWT(topic, payload, qos, retain, v5opts, v5SubPropName) { function createLWT(topic, payload, qos, retain, v5opts, v5SubPropName) {
let message = undefined; let message = undefined;
@ -567,9 +579,6 @@ module.exports = function(RED) {
if (typeof node.usetls === 'undefined') { if (typeof node.usetls === 'undefined') {
node.usetls = false; node.usetls = false;
} }
if (typeof node.usews === 'undefined') {
node.usews = false;
}
if (typeof node.verifyservercert === 'undefined') { if (typeof node.verifyservercert === 'undefined') {
node.verifyservercert = false; node.verifyservercert = false;
} }
@ -698,16 +707,21 @@ module.exports = function(RED) {
if (Object.keys(node.users).length === 1) { if (Object.keys(node.users).length === 1) {
if(node.autoConnect) { if(node.autoConnect) {
node.connect(); node.connect();
//update nodes status
setTimeout(function() {
updateStatus(node, true)
}, 1)
} }
} }
}; };
node.deregister = function(mqttNode,done) { node.deregister = function(mqttNode, done, autoDisconnect) {
delete node.users[mqttNode.id]; delete node.users[mqttNode.id];
if (!node.closing && node.connected && Object.keys(node.users).length === 0) { if (autoDisconnect && !node.closing && node.connected && Object.keys(node.users).length === 0) {
node.disconnect(); node.disconnect(done);
} else {
done();
} }
done();
}; };
node.canConnect = function() { node.canConnect = function() {
return !node.connected && !node.connecting; return !node.connected && !node.connecting;
@ -782,7 +796,9 @@ module.exports = function(RED) {
// Send any birth message // Send any birth message
if (node.birthMessage) { if (node.birthMessage) {
node.publish(node.birthMessage); setTimeout(() => {
node.publish(node.birthMessage);
}, 1);
} }
}); });
node._clientOn("reconnect", function() { node._clientOn("reconnect", function() {
@ -991,14 +1007,21 @@ 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 if(err) {
node.error(err, msg)
}
})
} else { } else {
const error = new Error(RED._("mqtt.errors.invalid-topic")); const error = new Error(RED._("mqtt.errors.invalid-topic"))
error.warn = true; error.warn = true
done(error); if (done) {
done(error)
} else {
node.warn(error, msg)
}
} }
} }
}; };
@ -1212,7 +1235,7 @@ module.exports = function(RED) {
} else { } else {
node.brokerConn.unsubscribe(node.topic,node.id, removed); node.brokerConn.unsubscribe(node.topic,node.id, removed);
} }
node.brokerConn.deregister(node, done); node.brokerConn.deregister(node, done, removed);
node.brokerConn = null; node.brokerConn = null;
} else { } else {
done(); done();
@ -1275,9 +1298,9 @@ module.exports = function(RED) {
node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"}); node.status({fill:"green",shape:"dot",text:"node-red:common.status.connected"});
} }
node.brokerConn.register(node); node.brokerConn.register(node);
node.on('close', function(done) { node.on('close', function(removed, done) {
if (node.brokerConn) { if (node.brokerConn) {
node.brokerConn.deregister(node,done); node.brokerConn.deregister(node, done, removed)
node.brokerConn = null; node.brokerConn = null;
} else { } else {
done(); done();

View File

@ -227,6 +227,7 @@
} }
}); });
}, },
sortable: true,
removable: true removable: true
}); });

View File

@ -200,6 +200,15 @@ module.exports = function(RED) {
this.callback = function(req,res) { this.callback = function(req,res) {
var msgid = RED.util.generateId(); var msgid = RED.util.generateId();
res._msgid = msgid; res._msgid = msgid;
// Since Node 15, req.headers are lazily computed and the property
// marked as non-enumerable.
// That means it doesn't show up in the Debug sidebar.
// This redefines the property causing it to be evaluated *and*
// marked as enumerable again.
Object.defineProperty(req, 'headers', {
value: req.headers,
enumerable: true
})
if (node.method.match(/^(post|delete|put|options|patch)$/)) { if (node.method.match(/^(post|delete|put|options|patch)$/)) {
node.send({_msgid:msgid,req:req,res:createResponseWrapper(node,res),payload:req.body}); node.send({_msgid:msgid,req:req,res:createResponseWrapper(node,res),payload:req.body});
} else if (node.method == "get") { } else if (node.method == "get") {
@ -282,7 +291,7 @@ module.exports = function(RED) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);
var node = this; var node = this;
this.headers = n.headers||{}; this.headers = n.headers||{};
this.statusCode = n.statusCode; this.statusCode = parseInt(n.statusCode);
this.on("input",function(msg,_send,done) { this.on("input",function(msg,_send,done) {
if (msg.res) { if (msg.res) {
var headers = RED.util.cloneMessage(node.headers); var headers = RED.util.cloneMessage(node.headers);
@ -323,7 +332,7 @@ module.exports = function(RED) {
} }
} }
} }
var statusCode = node.statusCode || msg.statusCode || 200; var statusCode = node.statusCode || parseInt(msg.statusCode) || 200;
if (typeof msg.payload == "object" && !Buffer.isBuffer(msg.payload)) { if (typeof msg.payload == "object" && !Buffer.isBuffer(msg.payload)) {
msg.res._res.status(statusCode).jsonp(msg.payload); msg.res._res.status(statusCode).jsonp(msg.payload);
} else { } else {

View File

@ -91,6 +91,11 @@
<label for="node-input-senderr" style="width: auto" data-i18n="httpin.senderr"></label> <label for="node-input-senderr" style="width: auto" data-i18n="httpin.senderr"></label>
</div> </div>
<div class="form-row">
<input type="checkbox" id="node-input-insecureHTTPParser" style="display: inline-block; width: auto; vertical-align: top;">
<label for="node-input-insecureHTTPParser", style="width: auto;" data-i18n="httpin.insecureHTTPParser"></label>
</div>
<div class="form-row"> <div class="form-row">
<label for="node-input-ret"><i class="fa fa-arrow-left"></i> <span data-i18n="httpin.label.return"></span></label> <label for="node-input-ret"><i class="fa fa-arrow-left"></i> <span data-i18n="httpin.label.return"></span></label>
@ -227,6 +232,7 @@
persist: {value:false}, persist: {value:false},
proxy: {type:"http proxy",required: false, proxy: {type:"http proxy",required: false,
label:RED._("node-red:httpin.proxy-config") }, label:RED._("node-red:httpin.proxy-config") },
insecureHTTPParser: {value: false},
authType: {value: ""}, authType: {value: ""},
senderr: {value: false}, senderr: {value: false},
headers: { value: [] } headers: { value: [] }
@ -338,6 +344,12 @@
} else { } else {
$("#node-input-useProxy").prop("checked", false); $("#node-input-useProxy").prop("checked", false);
} }
if (node.insecureHTTPParser) {
$("node-intput-insecureHTTPParser").prop("checked", true)
} else {
$("node-intput-insecureHTTPParser").prop("checked", false)
}
updateProxyOptions(); updateProxyOptions();
$("#node-input-useProxy").on("click", function() { $("#node-input-useProxy").on("click", function() {
updateProxyOptions(); updateProxyOptions();
@ -405,6 +417,7 @@
}); });
}, },
sortable: true,
removable: true removable: true
}); });
if (node.headers) { if (node.headers) {

View File

@ -86,6 +86,7 @@ in your Node-RED user directory (${RED.settings.userDir}).
if (n.paytoqs === true || n.paytoqs === "query") { paytoqs = true; } if (n.paytoqs === true || n.paytoqs === "query") { paytoqs = true; }
else if (n.paytoqs === "body") { paytobody = true; } else if (n.paytoqs === "body") { paytobody = true; }
node.insecureHTTPParser = n.insecureHTTPParser
var prox, noprox; var prox, noprox;
if (process.env.http_proxy) { prox = process.env.http_proxy; } if (process.env.http_proxy) { prox = process.env.http_proxy; }
@ -244,6 +245,10 @@ in your Node-RED user directory (${RED.settings.userDir}).
delete options.headers[h]; delete options.headers[h];
} }
}) })
if (node.insecureHTTPParser) {
options.insecureHTTPParser = true
}
} }
], ],
beforeRedirect: [ beforeRedirect: [
@ -430,6 +435,10 @@ in your Node-RED user directory (${RED.settings.userDir}).
formData.append(opt, val); formData.append(opt, val);
} else if (typeof val === 'object' && val.hasOwnProperty('value')) { } else if (typeof val === 'object' && val.hasOwnProperty('value')) {
formData.append(opt,val.value,val.options || {}); formData.append(opt,val.value,val.options || {});
} else if (Array.isArray(val)) {
for (var i=0; i<val.length; i++) {
formData.append(opt, val[i])
}
} else { } else {
formData.append(opt,JSON.stringify(val)); formData.append(opt,JSON.stringify(val));
} }

View File

@ -110,7 +110,12 @@ module.exports = function(RED) {
if (msg.payload[s].hasOwnProperty(p)) { if (msg.payload[s].hasOwnProperty(p)) {
/* istanbul ignore else */ /* istanbul ignore else */
if (typeof msg.payload[s][p] !== "object") { if (typeof msg.payload[s][p] !== "object") {
var q = "" + msg.payload[s][p]; // Fix to honour include null values flag
//if (typeof msg.payload[s][p] !== "object" || (node.include_null_values === true && msg.payload[s][p] === null)) {
var q = "";
if (msg.payload[s][p] !== undefined) {
q += msg.payload[s][p];
}
if (q.indexOf(node.quo) !== -1) { // add double quotes if any quotes if (q.indexOf(node.quo) !== -1) { // add double quotes if any quotes
q = q.replace(/"/g, '""'); q = q.replace(/"/g, '""');
ou += node.quo + q + node.quo + node.sep; ou += node.quo + q + node.quo + node.sep;
@ -130,9 +135,15 @@ module.exports = function(RED) {
ou += node.sep; ou += node.sep;
} }
else { else {
var p = RED.util.ensureString(RED.util.getMessageProperty(msg,"payload["+s+"]['"+template[t]+"']")); var tt = template[t];
if (template[t].indexOf('"') >=0 ) { tt = "'"+tt+"'"; }
else { tt = '"'+tt+'"'; }
var p = RED.util.getMessageProperty(msg,'payload["'+s+'"]['+tt+']');
/* istanbul ignore else */ /* istanbul ignore else */
if (p === "undefined") { p = ""; } if (p === undefined) { p = ""; }
// fix to honour include null values flag
//if (p === null && node.include_null_values !== true) { p = "";}
p = RED.util.ensureString(p);
if (p.indexOf(node.quo) !== -1) { // add double quotes if any quotes if (p.indexOf(node.quo) !== -1) { // add double quotes if any quotes
p = p.replace(/"/g, '""'); p = p.replace(/"/g, '""');
ou += node.quo + p + node.quo + node.sep; ou += node.quo + p + node.quo + node.sep;

View File

@ -251,7 +251,9 @@ module.exports = function(RED) {
} }
else { else {
node.buffer = buff.slice(p,buff.length); node.buffer = buff.slice(p,buff.length);
node.pendingDones.push(done); if (node.buffer.length > 0) {
node.pendingDones.push(done);
}
} }
if (node.buffer.length == 0) { if (node.buffer.length == 0) {
done(); done();

0
packages/node_modules/@node-red/nodes/core/storage/10-file.html vendored Executable file → Normal file
View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

0
packages/node_modules/@node-red/nodes/locales/de/messages.json vendored Executable file → Normal file
View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

View File

@ -18,5 +18,5 @@
<p>A node you can use to add comments to your flows.</p> <p>A node you can use to add comments to your flows.</p>
<h3>Details</h3> <h3>Details</h3>
<p>The edit panel will accept Markdown syntax. The text will be rendered into <p>The edit panel will accept Markdown syntax. The text will be rendered into
this information side panel.</p> the information side panel.</p>
</script> </script>

Some files were not shown because too many files have changed in this diff Show More