From 326f346936e79e5da8a36fdb3a47e11aaff15a35 Mon Sep 17 00:00:00 2001
From: Dominik Schmidt
Date: Tue, 14 Jun 2022 22:54:00 +0200
Subject: [PATCH 01/30] Import default export if node is a transpiled es module
---
packages/node_modules/@node-red/registry/lib/loader.js | 1 +
1 file changed, 1 insertion(+)
diff --git a/packages/node_modules/@node-red/registry/lib/loader.js b/packages/node_modules/@node-red/registry/lib/loader.js
index fc508aa57..61f28ab86 100644
--- a/packages/node_modules/@node-red/registry/lib/loader.js
+++ b/packages/node_modules/@node-red/registry/lib/loader.js
@@ -359,6 +359,7 @@ function loadNodeSet(node) {
try {
var loadPromise = null;
var r = require(node.file);
+ r = r.__esModule ? r.default : r
if (typeof r === "function") {
var red = registryUtil.createNodeApi(node);
From 6c0d6c5425125d8dd89469eb7d6d4fc5f8e31479 Mon Sep 17 00:00:00 2001
From: Dave Conway-Jones
Date: Wed, 15 Jun 2022 10:16:12 +0100
Subject: [PATCH 02/30] Join-reduce keep existing msg properties
see https://discourse.nodered.org/t/no-response-object-after-split-join/63919
---
.../node_modules/@node-red/nodes/core/sequence/17-split.js | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/packages/node_modules/@node-red/nodes/core/sequence/17-split.js b/packages/node_modules/@node-red/nodes/core/sequence/17-split.js
index e158f344c..325cf85b5 100644
--- a/packages/node_modules/@node-red/nodes/core/sequence/17-split.js
+++ b/packages/node_modules/@node-red/nodes/core/sequence/17-split.js
@@ -314,11 +314,13 @@ module.exports = function(RED) {
if (err) {
return done(err);
}
- msgInfo.send({payload: result});
+ msgInfo.msg.payload = result;
+ msgInfo.send(msgInfo.msg);
done();
});
} else {
- msgInfo.send({payload: result});
+ msgInfo.msg.payload = result;
+ msgInfo.send(msgInfo.msg);
done();
}
} else {
From 0000f2a34d274d0785d6d7c6a8021ff38d8000fa Mon Sep 17 00:00:00 2001
From: Kazuhito Yokoi
Date: Sat, 18 Jun 2022 00:51:05 +0900
Subject: [PATCH 03/30] Support i18n in context menu
---
.../@node-red/editor-client/locales/en-US/editor.json | 6 ++++++
.../@node-red/editor-client/locales/ja/editor.json | 6 ++++++
.../@node-red/editor-client/src/js/ui/contextMenu.js | 8 ++++----
3 files changed, 16 insertions(+), 4 deletions(-)
diff --git a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json
index 01107d49d..e3028272b 100755
--- a/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json
+++ b/packages/node_modules/@node-red/editor-client/locales/en-US/editor.json
@@ -1187,5 +1187,11 @@
"missing-config": "__prop__: missing configuration node",
"validation-error": "__prop__: validation error: __node__, __id__: __error__"
}
+ },
+ "contextMenu": {
+ "insert": "Insert",
+ "node": "Node",
+ "junction": "Junction",
+ "linkNodes": "Link Nodes"
}
}
diff --git a/packages/node_modules/@node-red/editor-client/locales/ja/editor.json b/packages/node_modules/@node-red/editor-client/locales/ja/editor.json
index 4c918b615..a78fb7d24 100644
--- a/packages/node_modules/@node-red/editor-client/locales/ja/editor.json
+++ b/packages/node_modules/@node-red/editor-client/locales/ja/editor.json
@@ -1188,6 +1188,12 @@
"validation-error": "__prop__: チェックエラー: __node__, __id__: __error__"
}
},
+ "contextMenu": {
+ "insert": "挿入",
+ "node": "ノード",
+ "junction": "分岐点",
+ "linkNodes": "Linkノード"
+ },
"action-list": {
"toggle-show-tips": "ヒント表示切替",
"show-about": "Node-REDの説明を表示",
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js b/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js
index 379ed5433..9920789f5 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js
@@ -48,10 +48,10 @@ RED.contextMenu = (function() {
const menuItems = [
{ onselect: 'core:show-action-list', onpostselect: function() {} },
{
- label: 'Insert',
+ label: RED._("contextMenu.insert"),
options: [
{
- label: 'Node',
+ label: RED._("contextMenu.node"),
onselect: function() {
RED.view.showQuickAddDialog({
position: [ options.x - offset.left, options.y - offset.top ],
@@ -62,12 +62,12 @@ RED.contextMenu = (function() {
}
},
{
- label: 'Junction',
+ label: RED._("contextMenu.junction"),
onselect: 'core:split-wires-with-junctions',
disabled: hasSelection || !hasLinks
},
{
- label: 'Link Nodes',
+ label: RED._("contextMenu.linkNodes"),
onselect: 'core:split-wire-with-link-nodes',
disabled: hasSelection || !hasLinks
}
From 418b3ee7d68f280e30340032b28df97106a8d87e Mon Sep 17 00:00:00 2001
From: Kazuhito Yokoi
Date: Sat, 18 Jun 2022 00:56:34 +0900
Subject: [PATCH 04/30] Fix Japanese translations to be same as others
---
.../@node-red/editor-client/locales/ja/editor.json | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/node_modules/@node-red/editor-client/locales/ja/editor.json b/packages/node_modules/@node-red/editor-client/locales/ja/editor.json
index a78fb7d24..70cb0aa22 100644
--- a/packages/node_modules/@node-red/editor-client/locales/ja/editor.json
+++ b/packages/node_modules/@node-red/editor-client/locales/ja/editor.json
@@ -1308,7 +1308,7 @@
"search": "検索",
"search-previous": "前を検索",
"search-next": "次を検索",
- "show-action-list": "アクション一覧を表示",
+ "show-action-list": "動作一覧を表示",
"confirm-edit-tray": "編集を完了",
"cancel-edit-tray": "編集をキャンセル",
"show-remote-diff": "リモートとの変更差分を表示",
@@ -1330,6 +1330,6 @@
"zoom-out": "ズームアウト",
"zoom-reset": "ズームリセット",
"toggle-navigator": "ナビゲータ表示切替",
- "show-system-info": "システムインフォメーション"
+ "show-system-info": "システム情報"
}
}
From 3ad95bec3ca553ddd35e48e95aaf171e504d7a97 Mon Sep 17 00:00:00 2001
From: Kazuhito Yokoi
Date: Sat, 18 Jun 2022 00:57:30 +0900
Subject: [PATCH 05/30] Add Japanese translation for file nodes
---
packages/node_modules/@node-red/nodes/locales/ja/messages.json | 1 +
1 file changed, 1 insertion(+)
diff --git a/packages/node_modules/@node-red/nodes/locales/ja/messages.json b/packages/node_modules/@node-red/nodes/locales/ja/messages.json
index c508a3e76..6e16daa6f 100644
--- a/packages/node_modules/@node-red/nodes/locales/ja/messages.json
+++ b/packages/node_modules/@node-red/nodes/locales/ja/messages.json
@@ -928,6 +928,7 @@
"write": "write file",
"read": "read file",
"filename": "ファイル名",
+ "path": "パス",
"action": "動作",
"addnewline": "メッセージの入力のたびに改行を追加",
"createdir": "ディレクトリが存在しない場合は作成",
From 01d9affe61efbf35fdeb304985dfc5061d24299e Mon Sep 17 00:00:00 2001
From: cow0w
Date: Fri, 17 Jun 2022 22:18:14 +0300
Subject: [PATCH 06/30] Add support for evalulating {{env.}} within a
template node
---
.../nodes/core/function/80-template.js | 24 +++++++++++++++++++
test/nodes/core/function/80-template_spec.js | 22 +++++++++++++++++
2 files changed, 46 insertions(+)
diff --git a/packages/node_modules/@node-red/nodes/core/function/80-template.js b/packages/node_modules/@node-red/nodes/core/function/80-template.js
index d4c27cfd0..69954aba2 100644
--- a/packages/node_modules/@node-red/nodes/core/function/80-template.js
+++ b/packages/node_modules/@node-red/nodes/core/function/80-template.js
@@ -44,6 +44,14 @@ module.exports = function(RED) {
return undefined;
}
+ function parseEnv(key) {
+ var match = /^env\.(.+)/.exec(key);
+ if (match) {
+ return match[1];
+ }
+ return undefined;
+ }
+
/**
* Custom Mustache Context capable to collect message property and node
* flow and global context
@@ -74,6 +82,11 @@ module.exports = function(RED) {
return value;
}
+ // try env
+ if (parseEnv(name)) {
+ return this.cachedContextTokens[name];
+ }
+
// try flow/global context:
var context = parseContext(name);
if (context) {
@@ -156,6 +169,17 @@ module.exports = function(RED) {
var tokens = extractTokens(mustache.parse(template));
var resolvedTokens = {};
tokens.forEach(function(name) {
+ var env_name = parseEnv(name);
+ if (env_name) {
+ var promise = new Promise((resolve, reject) => {
+ var val = RED.util.evaluateNodeProperty(env_name, 'env', node)
+ resolvedTokens[name] = val;
+ resolve();
+ });
+ promises.push(promise);
+ return;
+ }
+
var context = parseContext(name);
if (context) {
var type = context.type;
diff --git a/test/nodes/core/function/80-template_spec.js b/test/nodes/core/function/80-template_spec.js
index e944824b3..b4f530d05 100644
--- a/test/nodes/core/function/80-template_spec.js
+++ b/test/nodes/core/function/80-template_spec.js
@@ -144,6 +144,28 @@ describe('template node', function() {
});
});
+ describe('env var', function() {
+ before(function() {
+ process.env.TEST = 'xyzzy';
+ })
+ after(function() {
+ delete process.env.TEST;
+ })
+
+ it('should modify payload from env variable', function(done) {
+ var flow = [{id:"n1",z:"t1", type:"template", field:"payload", template:"payload={{env.TEST}}",wires:[["n2"]]},{id:"n2",z:"t1",type:"helper"}];
+ helper.load(templateNode, flow, function() {
+ var n1 = helper.getNode("n1");
+ var n2 = helper.getNode("n2");
+ n2.on("input", function(msg) {
+ msg.should.have.property('payload', 'payload=xyzzy');
+ done();
+ });
+ n1.receive({payload:"foo",topic: "bar"});
+ });
+ });
+ });
+
it('should modify payload from flow context', function(done) {
var flow = [{id:"n1",z:"t1", type:"template", field:"payload", template:"payload={{flow.value}}",wires:[["n2"]]},{id:"n2",z:"t1",type:"helper"}];
helper.load(templateNode, flow, function() {
From 75c9353cbddbbeb7203ddc5ebb24dc3fb8b0b0ea Mon Sep 17 00:00:00 2001
From: Kazuhito Yokoi
Date: Sun, 19 Jun 2022 01:23:28 +0900
Subject: [PATCH 07/30] Fix keys to insert junction
---
.../node_modules/@node-red/editor-client/src/tours/welcome.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/node_modules/@node-red/editor-client/src/tours/welcome.js b/packages/node_modules/@node-red/editor-client/src/tours/welcome.js
index 4b6f5f66d..1289e6bee 100644
--- a/packages/node_modules/@node-red/editor-client/src/tours/welcome.js
+++ b/packages/node_modules/@node-red/editor-client/src/tours/welcome.js
@@ -34,7 +34,7 @@ export default {
"en-US": `To make it easier to route wires around your flows,
it is now possible to add junction nodes that give
you more control.
- Junctions can be added to wires by holding the Alt key
+
Junctions can be added to wires by holding both the Alt key and the Shift key
then click and drag the mouse across the wires.
`,
// "ja": `フローのワイヤーの経路をより制御しやすくするために、分岐点ノードを追加できるようになりました。
// シフトキーを押しながら、マウスの右ボタンをクリックし、ワイヤーを横切るようにドラッグすることで、分岐点を追加できます。
`
From 13885493acbc09d0578894717fff65daaf6e3a61 Mon Sep 17 00:00:00 2001
From: Kazuhito Yokoi
Date: Sun, 19 Jun 2022 01:26:48 +0900
Subject: [PATCH 08/30] Update Japanese translations in welcome tour
---
.../@node-red/editor-client/src/tours/welcome.js | 13 ++++++++-----
1 file changed, 8 insertions(+), 5 deletions(-)
diff --git a/packages/node_modules/@node-red/editor-client/src/tours/welcome.js b/packages/node_modules/@node-red/editor-client/src/tours/welcome.js
index 1289e6bee..98d83c7e5 100644
--- a/packages/node_modules/@node-red/editor-client/src/tours/welcome.js
+++ b/packages/node_modules/@node-red/editor-client/src/tours/welcome.js
@@ -9,19 +9,22 @@ export default {
},
description: {
"en-US": "This is the final beta release of Node-RED 3.0.
Let's take a moment to discover the new features in this release.
",
- // "ja": "これはNode-RED 3.0の最初のベータリリースです。これには、最終リリースで計画しているほぼ全ての機能が含まれています。
本リリースの新機能を見つけてみましょう。
"
+ "ja": "これはNode-RED 3.0の最後のベータリリースです。
本リリースの新機能を見つけてみましょう。
"
}
},
{
title: {
- "en-US": "Context Menu"
+ "en-US": "Context Menu",
+ "ja": "コンテキストメニュー"
},
image: 'images/context-menu.png',
description: {
"en-US": `The editor now has its own context menu when you
right-click in the workspace.
This makes many of the built-in actions much easier
- to access.
`
+ to access.
`,
+ "ja": `ワークスペースで右クリックすると、エディタに独自のコンテキストメニューが表示されるようになりました。
+ これによって多くの組み込み動作を、より簡単に利用できます。
`
}
},
{
@@ -36,8 +39,8 @@ export default {
you more control.
Junctions can be added to wires by holding both the Alt key and the Shift key
then click and drag the mouse across the wires.
`,
- // "ja": `フローのワイヤーの経路をより制御しやすくするために、分岐点ノードを追加できるようになりました。
- // シフトキーを押しながら、マウスの右ボタンをクリックし、ワイヤーを横切るようにドラッグすることで、分岐点を追加できます。
`
+ "ja": `フローのワイヤーの経路をより制御しやすくするために、分岐点ノードを追加できるようになりました。
+ Altキーとシフトキーを押しながらマウスをクリックし、ワイヤーを横切るようにドラッグすることで、分岐点を追加できます。
`
},
},
{
From 643541eebdc4394937c0038e5582ff21586a9589 Mon Sep 17 00:00:00 2001
From: Kazuhito Yokoi
Date: Sun, 19 Jun 2022 01:37:55 +0900
Subject: [PATCH 09/30] Remove unnecessary spaces
---
.../@node-red/nodes/locales/ja/function/10-function.html | 2 +-
.../@node-red/nodes/locales/ja/network/10-mqtt.html | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/node_modules/@node-red/nodes/locales/ja/function/10-function.html b/packages/node_modules/@node-red/nodes/locales/ja/function/10-function.html
index a18e5e8a8..960b755f6 100644
--- a/packages/node_modules/@node-red/nodes/locales/ja/function/10-function.html
+++ b/packages/node_modules/@node-red/nodes/locales/ja/function/10-function.html
@@ -28,7 +28,7 @@
返却/sendの対象は次のとおりです:
- 単一メッセージオブジェクト - 最初の出力に接続されたノードに渡されます
- - メッセージオブジェクトの配列 - 対応する出力に接続されたノードに渡されます
+ - メッセージオブジェクトの配列 - 対応する出力に接続されたノードに渡されます
注: 初期化処理の実行はノードの初期化中に行われます。そのため、初期化処理タブにsendを記述した場合に後続ノードでメッセージを受け取れないことがあります。
配列要素が配列の場合には、複数のメッセージを対応する出力に送出します。
diff --git a/packages/node_modules/@node-red/nodes/locales/ja/network/10-mqtt.html b/packages/node_modules/@node-red/nodes/locales/ja/network/10-mqtt.html
index 1b43ea097..435829e1e 100644
--- a/packages/node_modules/@node-red/nodes/locales/ja/network/10-mqtt.html
+++ b/packages/node_modules/@node-red/nodes/locales/ja/network/10-mqtt.html
@@ -89,7 +89,7 @@
userProperties オブジェクト
MQTTv5: メッセージのユーザプロパティ
messageExpiryInterval 数値
- MQTTv5: 秒単位のメッセージの有効期限
+ MQTTv5: 秒単位のメッセージの有効期限
topicAlias 数値
MQTTv5: 使用するMQTTトピックエイリアス
From 5e592427e940bd095440bb2ea0bf65636fe30194 Mon Sep 17 00:00:00 2001
From: Kazuhito Yokoi
Date: Sun, 19 Jun 2022 01:56:59 +0900
Subject: [PATCH 10/30] Add Japanese translation in action list for junction
---
.../@node-red/editor-client/locales/ja/editor.json | 3 ++-
1 file changed, 2 insertions(+), 1 deletion(-)
diff --git a/packages/node_modules/@node-red/editor-client/locales/ja/editor.json b/packages/node_modules/@node-red/editor-client/locales/ja/editor.json
index 70cb0aa22..ac09a1e87 100644
--- a/packages/node_modules/@node-red/editor-client/locales/ja/editor.json
+++ b/packages/node_modules/@node-red/editor-client/locales/ja/editor.json
@@ -1330,6 +1330,7 @@
"zoom-out": "ズームアウト",
"zoom-reset": "ズームリセット",
"toggle-navigator": "ナビゲータ表示切替",
- "show-system-info": "システム情報"
+ "show-system-info": "システム情報",
+ "split-wires-with-junctions": "分岐点によりワイヤーを分割"
}
}
From 6c2297c3659ddbd5cc784ba07e97680d4816eaea Mon Sep 17 00:00:00 2001
From: Dennis Neufeld
Date: Sat, 18 Jun 2022 19:41:46 +0200
Subject: [PATCH 11/30] Update german translation
---
.../editor-client/locales/de/editor.json | 191 ++++++++++++------
1 file changed, 131 insertions(+), 60 deletions(-)
diff --git a/packages/node_modules/@node-red/editor-client/locales/de/editor.json b/packages/node_modules/@node-red/editor-client/locales/de/editor.json
index 11d8e5d96..dd931a812 100755
--- a/packages/node_modules/@node-red/editor-client/locales/de/editor.json
+++ b/packages/node_modules/@node-red/editor-client/locales/de/editor.json
@@ -44,7 +44,8 @@
"loadNodes": "Lade Nodes __count__",
"loadFlows": "Lade Flows",
"importFlows": "Füge Flows dem Arbeitsbereich hinzu",
- "importError": "Fehler beim Laden von Flows.
__message__
"
+ "importError": "Fehler beim Laden von Flows.
__message__
",
+ "loadingProject": "Lade Projekt"
},
"workspace": {
"defaultName": "Flow __number__",
@@ -53,7 +54,16 @@
"delete": "Sind Sie sicher, dass '__label__' gelöscht werden soll?",
"dropFlowHere": "Hier kann der Flow eingefügt werden",
"addFlow": "Flow hinzufügen",
+ "addFlowToRight": "Flow zum Arbeitsbereich rechts hinzufügen",
+ "hideFlow": "Flow ausblenden",
+ "hideOtherFlows": "Andere Flows ausblenden",
+ "showAllFlows": "Alle Flows anzeigen",
+ "hideAllFlows": "Alle Flows ausblenden",
+ "hiddenFlows": "Liste __count__ ausgeblendeten Flow auf",
+ "hiddenFlows_plural": "Liste __count__ ausgeblendete Flows auf",
+ "showLastHiddenFlow": "Letzten ausgeblendeten Flow anzeigen",
"listFlows": "Flows auflisten",
+ "listSubflows": "Subflows auflisten",
"status": "Status",
"enabled": "Aktiviert",
"disabled": "Deaktiviert",
@@ -65,6 +75,8 @@
"view": {
"view": "Ansicht",
"grid": "Raster",
+ "storeZoom": "Zoomstufe beim Laden wiederherstellen",
+ "storePosition": "Scrollposition beim Laden wiederherstellen",
"showGrid": "Raster anzeigen",
"snapGrid": "Am Raster ausrichten",
"gridSize": "Rastergröße",
@@ -82,8 +94,9 @@
"palette": {
"show": "Palette anzeigen"
},
+ "edit": "Bearbeiten",
"settings": "Einstellungen",
- "userSettings": "Einstellungen",
+ "userSettings": "Benutzereinstellungen",
"nodes": "Nodes",
"displayStatus": "Node-Status anzeigen",
"displayConfig": "Konfigurations-Nodes",
@@ -92,7 +105,7 @@
"search": "Flows durchsuchen",
"searchInput": "Flows durchsuchen",
"subflows": "Subflow",
- "createSubflow": "Erstellen",
+ "createSubflow": "Subflow erstellen",
"selectionToSubflow": "Auswahl in Subflow umwandeln",
"flows": "Flow",
"add": "Hinzufügen",
@@ -104,24 +117,42 @@
"editPalette": "Palette verwalten",
"other": "Sonstige",
"showTips": "Tipps anzeigen",
+ "showWelcomeTours": "Geführte Touren für neue Versionen anzeigen",
"help": "Node-RED-Website",
- "projects": "Projekt",
+ "projects": "Projekte",
"projects-new": "Neu",
"projects-open": "Öffnen",
- "projects-settings": "Einstellungen",
+ "projects-settings": "Projekteinstellungen",
"showNodeLabelDefault": "Zeige Namen von neu hinzugefügten Nodes",
- "groups": "Gruppe",
+ "codeEditor": "Code-Editor",
+ "groups": "Gruppen",
"groupSelection": "Auswahl gruppieren",
"ungroupSelection": "Gruppe auflösen",
"groupMergeSelection": "Auswahl der Gruppe hinzufügen",
- "groupRemoveSelection": "Auswahl aus der Gruppe entfernen"
+ "groupRemoveSelection": "Auswahl aus der Gruppe entfernen",
+ "arrange": "Anordnen",
+ "alignLeft": "Links ausrichten",
+ "alignCenter": "Zentrieren",
+ "alignRight": "Rechts ausrichten",
+ "alignTop": "Oben ausrichten",
+ "alignMiddle": "Mittig ausrichten",
+ "alignBottom": "Unten ausrichten",
+ "distributeHorizontally": "Horizontal verteilen",
+ "distributeVertically": "Vertikal verteilen",
+ "moveToBack": "Nach hinten verschieben",
+ "moveToFront": "Nach vorne verschieben",
+ "moveBackwards": "Rückwärts verschieben",
+ "moveForwards": "Vorwärts verschieben"
}
},
"actions": {
"toggle-navigator": "Navigator ein-/ausblenden",
"zoom-out": "Verkleinern",
"zoom-reset": "Vergrößerung rücksetzen",
- "zoom-in": "Vergrößern"
+ "zoom-in": "Vergrößern",
+ "search-flows": "Flows durchsuchen",
+ "search-prev": "Vorherige",
+ "search-next": "Nächste"
},
"user": {
"loggedInAs": "Angemeldet als __name__",
@@ -131,7 +162,7 @@
"loginFailed": "Anmeldung fehlgeschlagen",
"notAuthorized": "Nicht berechtigt",
"errors": {
- "settings": "Sie müssen angemeldet sein, um auf die Einstellungen zuzugreifen zu können",
+ "settings": "Sie müssen angemeldet sein, um auf die Einstellungen zugreifen zu können",
"deploy": "Sie müssen angemeldet sein, um Änderungen übernehmen (deploy) zu können",
"notAuthorized": "Sie müssen angemeldet sein, um diese Aktion ausführen zu können"
}
@@ -141,7 +172,7 @@
"warnings": {
"undeployedChanges": "Node hat nicht übernommene (deploy) Änderungen",
"nodeActionDisabled": "Node-Aktionen deaktiviert",
- "nodeActionDisabledSubflow": "Node-Aktionen deaktiviert im Subflow",
+ "nodeActionDisabledSubflow": "Node-Aktionen innerhalb des Subflows deaktiviert",
"missing-types": "Flows gestoppt aufgrund fehlender Node-Typen
",
"missing-modules": "Flows angehalten aufgrund fehlender Module
",
"safe-mode": "Flows sind im abgesicherten Modus gestoppt.
Flows können bearbeitet und übernommen (deploy) werden, um sie neu zu starten.
",
@@ -157,21 +188,21 @@
"error": "Fehler: __message__",
"errors": {
"lostConnection": "Verbindung zum Server verloren. Verbindung wird erneut hergestellt ...",
- "lostConnectionReconnect": "Verbindung zum Server verloren. Verbindung wird in __time__ s versucht wieder herzustellen.",
- "lostConnectionTry": "Jetzt testen",
+ "lostConnectionReconnect": "Verbindung zum Server verloren. Wiederherstellung der Verbindung in __time__s.",
+ "lostConnectionTry": "Jetzt versuchen",
"cannotAddSubflowToItself": "Subflow kann nicht zu sich selbst hinzugefügt werden",
"cannotAddCircularReference": "Subflow kann nicht hinzugefügt werden, da ein zirkulärer Bezug erkannt wurde",
- "unsupportedVersion": "Nicht unterstützte Version von Node.js erkannt.
Es muss ein Upgrade auf das neueste LTS-Release von Node.js durchgeführt werden.
",
+ "unsupportedVersion": "Nicht unterstützte Version von Node.js erkannt.
Es sollte ein Upgrade auf das neueste LTS-Release von Node.js durchgeführt werden.
",
"failedToAppendNode": "Fehler beim Laden von '__module__'.
__error__
"
},
"project": {
- "change-branch": "Wechsel in den Branch '__project__'",
- "merge-abort": "Merge abgebrochen",
+ "change-branch": "Wechsel in den lokalen Branch '__project__'",
+ "merge-abort": "Git-Merge abgebrochen",
"loaded": "Projekt '__project__' geladen",
"updated": "Projekt '__project__' aktualisiert",
"pull": "Projekt '__project__' erneut geladen",
"revert": "Änderungen im Projekt '__project__' rückgängig gemacht",
- "merge-complete": "Merge abgeschlossen",
+ "merge-complete": "Git-Merge abgeschlossen",
"setupCredentials": "Berechtigungen einrichten",
"setupProjectFiles": "Projektdateien einrichten",
"no": "Nein, Danke",
@@ -186,7 +217,7 @@
"no-thanks": "Nein, Danke",
"create-default-project": "Standardprojektdateien erstellen",
"show-merge-conflicts": "Merge-Konflikte anzeigen",
- "unknownNodesButton": "Finden Sie unbekannte nodes"
+ "unknownNodesButton": "Nach unbekannten Nodes suchen"
}
},
"clipboard": {
@@ -204,17 +235,17 @@
"subflow_plural": "__count__ Subflows",
"replacedNodes": "__count__ Node ersetzt",
"replacedNodes_plural": "__count__ Nodes ersetzt",
- "pasteNodes": "Flow-JSON hier einfügen oder",
+ "pasteNodes": "Flow-JSON einfügen oder",
"selectFile": "Datei für Import auswählen",
- "importNodes": "Import",
- "exportNodes": "Export",
+ "importNodes": "Importiere Nodes",
+ "exportNodes": "Exportiere Nodes",
"download": "Download",
- "importUnrecognised": "Importierter Typ nicht erkannt:",
- "importUnrecognised_plural": "Importierte Typen nicht erkannt:",
- "importDuplicate": "Importiertes doppeltes Node:",
- "importDuplicate_plural": "Importierte doppelte Nodes:",
- "nodesExported": "Nodes in der Zwischenablage abgelegt",
- "nodesImported": "Eingefügt:",
+ "importUnrecognised": "Nicht erkannter Typ importiert:",
+ "importUnrecognised_plural": "Nicht erkannte Typen importiert:",
+ "importDuplicate": "Doppelte Node importiert:",
+ "importDuplicate_plural": "Doppelte Nodes importiert:",
+ "nodesExported": "Nodes in die Zwischenablage exportiert",
+ "nodesImported": "Importiert:",
"nodeCopied": "__count__ Node kopiert",
"nodeCopied_plural": "__count__ Nodes kopiert",
"groupCopied": "__count__ Gruppe kopiert",
@@ -230,11 +261,11 @@
"all": "Alle Flows",
"compact": "Kompakt",
"formatted": "Formatiert",
- "copy": "In Zwischenablage exportieren",
+ "copy": "In Zwischenablage kopieren",
"export": "In Bibliothek exportieren",
"exportAs": "Exportiere als",
"overwrite": "Ersetzen",
- "exists": "'__file__' existiert bereits.
Soll sie ersetzt werden?
"
+ "exists": "\"__file__\" existiert bereits.
Soll sie ersetzt werden?
"
},
"import": {
"import": "Importiere in",
@@ -270,9 +301,9 @@
"successfulRestart": "Flows erfolgreich neugestartet",
"deployFailed": "Übernahme (deploy) fehlgeschlagen: __message__",
"unusedConfigNodes": "Einige Konfigurations-Nodes werden nicht verwendet.",
- "unusedConfigNodesButton":"Finden Sie ungenutzte konfig nodes",
- "unknownNodesButton":"Finden Sie unbekannte nodes",
- "invalidNodesButton":"Finden Sie ungültige nodes",
+ "unusedConfigNodesButton": "Suche nach unbenutzten Konfigurations-Nodes",
+ "unknownNodesButton": "Suche nach unbekannten Nodes",
+ "invalidNodesButton": "Suche nach ungültigen Nodes",
"errors": {
"noResponse": "Keine Antwort vom Server"
},
@@ -355,10 +386,10 @@
"keys": "Schlüsselwörter",
"keysPlaceholder": "Komma-getrennte Schlüsselwörter",
"author": "Author",
- "authorPlaceholder": "Dein Name ",
+ "authorPlaceholder": "Ihr Name ",
"desc": "Beschreibung",
"env": {
- "restore": "Stelle auf Subflow-Standard zurück",
+ "restore": "Subflow-Standard wiederherstellen",
"remove": "Entferne Umgebungsvariable"
},
"errors": {
@@ -367,9 +398,9 @@
}
},
"group": {
- "editGroup": "Editiere Gruppe: __name__",
+ "editGroup": "Bearbeite Gruppe: __name__",
"errors": {
- "cannotCreateDiffGroups": "Kann keine Gruppe erzeugen mit Nodes von verschiedenen Gruppen",
+ "cannotCreateDiffGroups": "Kann keine Gruppe mit Nodes von anderen Gruppen erstellen",
"cannotAddSubflowPorts": "Kann keine Subflow-Anschlüsse zu einer Gruppe hinzufügen"
}
},
@@ -383,7 +414,7 @@
"addNewConfig": "Neuen Konfigurations-Node '__type__' hinzufügen",
"editNode": "Node '__type__' bearbeiten",
"editConfig": "Konfigurations-Node '__type__' bearbeiten",
- "addNewType": "Neuen Typ '__type__' hinzufügen",
+ "addNewType": "Neuen Typ '__type__' hinzufügen ...",
"nodeProperties": "Node-Eigenschaften",
"label": "Name",
"color": "Farbe",
@@ -406,7 +437,7 @@
"loadCredentials": "Lade Node-Berechtigungen",
"inputs": {
"input": "Eingang",
- "select": "Wähle",
+ "select": "Auswahl",
"checkbox": "Checkbox",
"spinner": "Spinner",
"none": "Kein",
@@ -449,23 +480,27 @@
"shortcut": "Tastenkürzel",
"scope": "Geltungsbereich",
"unassigned": "Nicht zugeordnet",
- "global": "global",
+ "global": "Global",
"workspace": "Arbeitsbereich",
- "selectAll": "Alle Nodes auswählen",
+ "selectAll": "Alles auswählen",
+ "selectNone": "Alles abwählen",
"selectAllConnected": "Alle verbundenen Nodes auswählen",
"addRemoveNode": "Node aus Auswahl hinzufügen/entfernen",
"editSelected": "Ausgewählten Node bearbeiten",
"deleteSelected": "Ausgewählte Nodes oder Links löschen",
- "importNode": "Node importieren",
- "exportNode": "Node exportieren",
+ "importNode": "Nodes importieren",
+ "exportNode": "Nodes exportieren",
"nudgeNode": "Ausgewählte Nodes verschieben (1px)",
"moveNode": "Ausgewählte Nodes verschieben (20px)",
"toggleSidebar": "Seitenleiste ein-/ausblenden",
"togglePalette": "Palette ein-/ausblenden",
"copyNode": "Ausgewählte Nodes kopieren",
"cutNode": "Ausgewählte Nodes ausschneiden",
- "pasteNode": "Node einfügen",
+ "pasteNode": "Nodes einfügen",
+ "copyGroupStyle": "Gruppenstil kopieren",
+ "pasteGroupStyle": "Gruppenstil einfügen",
"undoChange": "Letzte Änderung rückgängig machen",
+ "redoChange": "Letzte Änderung wiederholen",
"searchBox": "Suchfeld öffnen",
"managePalette": "Palette verwalten",
"actionList": "Aktionsliste"
@@ -491,7 +526,7 @@
"palette": {
"noInfo": "Keine Informationen verfügbar",
"filter": "Nodes filtern",
- "search": "Modules durchsuchen",
+ "search": "Module durchsuchen",
"addCategory": "Neu hinzufügen ...",
"label": {
"subflows": "Subflows",
@@ -508,8 +543,8 @@
"advanced": "Fortgeschritten"
},
"actions": {
- "collapse-all": "Kategorien einklappen",
- "expand-all": "Kategorien ausklappen"
+ "collapse-all": "Alle Kategorien einklappen",
+ "expand-all": "Alle Kategorien ausklappen"
},
"event": {
"nodeAdded": "Node zur Palette hinzugefügt:",
@@ -520,7 +555,8 @@
"nodeEnabled_plural": "Nodes aktiviert:",
"nodeDisabled": "Node deaktiviert:",
"nodeDisabled_plural": "Nodes deaktiviert:",
- "nodeUpgraded": "Upgrade von Node-Modul __module__ auf Version __version__ durchgeführt"
+ "nodeUpgraded": "Upgrade von Node-Modul __module__ auf Version __version__ durchgeführt",
+ "unknownNodeRegistered": "Fehler beim Laden des Nodes: "
},
"editor": {
"title": "Palette verwalten",
@@ -636,7 +672,7 @@
"outline": "Entwurf",
"empty": "leer",
"globalConfig": "Globale Konfigurations-Nodes",
- "triggerAction": "Auslösen",
+ "triggerAction": "Aktion auslösen",
"find": "Suche im Arbeitsbereich"
},
"help": {
@@ -739,7 +775,7 @@
"userName": "Benutzername",
"email": "E-Mail",
"workflow": "Arbeitsablauf",
- "workfowTip": "Wähle deinen bevorzugten Git-Arbeitsablauf",
+ "workfowTip": "Wählen Sie Ihren bevorzugten Git-Arbeitsablauf (Workflow)",
"workflowManual": "Manuell",
"workflowManualTip": "Alle Änderungen müssen manuell übertragen werden (commit) über die Seitenleiste 'Projekthistorie'",
"workflowAuto": "Automatisch",
@@ -858,6 +894,8 @@
"addTitle": "Element hinzufügen"
},
"search": {
+ "history": "Suchhistorie",
+ "clear": "Leeren",
"empty": "Keine Übereinstimmungen gefunden",
"addNode": "Node hinzufügen ...",
"options": {
@@ -865,7 +903,10 @@
"unusedConfigNodes": "Unbenutzte Konfigurations-Nodes",
"invalidNodes": "Ungültige Nodes",
"uknownNodes": "Unbekannte Nodes",
- "unusedSubflows": "Unbenutzte Subflows"
+ "unusedSubflows": "Unbenutzte Subflows",
+ "hiddenFlows": "Versteckte Flows",
+ "modifiedNodes": "Geänderte Nodes",
+ "thisFlow": "Aktueller Flow"
}
},
"expressionEditor": {
@@ -887,6 +928,9 @@
"eval": "Fehler beim Auswerten des Ausdrucks\n__message__"
}
},
+ "monaco": {
+ "setTheme": "Thema auswählen"
+ },
"jsEditor": {
"title": "JavaScript-Editor"
},
@@ -896,8 +940,10 @@
"jsonEditor": {
"title": "JSON-Editor",
"format": "JSON formatieren",
- "rawMode": "JSON-Editor",
+ "rawMode": "Bearbeite JSON",
"uiMode": "Visueller Editor",
+ "rawMode-readonly": "JSON",
+ "uiMode-readonly": "Visuell",
"insertAbove": "Oberhalb einfügen",
"insertBelow": "Unterhalb einfügen",
"addItem": "Element hinzufügen",
@@ -968,7 +1014,7 @@
"clone": "Projekt klonen",
"desc0": "Wenn Sie bereits über ein Git-Repository verfügen, das ein Projekt enthält, können Sie es klonen, um damit zu arbeiten.",
"already-exists": "Das Projekt ist bereits vorhanden",
- "must-contain": "Darf nur A-Z 0-9 _ enthalten",
+ "must-contain": "Darf nur A-Z 0-9 _ - enthalten",
"project-name": "Projektname",
"no-info-in-url": "Geben Sie Benutzername & Passwort nicht innerhalb der URL vor",
"git-url": "Git-Repository-URL",
@@ -1026,7 +1072,7 @@
"desc2": "Im Tab 'Commit-Historie' in der Seitenleiste werden alle Dateien angezeigt, die sich in Ihrem Projekt geändert haben, und um sie ins lokale Repository zu übertragen (commit). Es zeigt Ihnen eine vollständige Historie Ihrer Commits an und ermöglicht es Ihnen, Ihre Commits in ein (remote) Server-Repository zu schieben (push)."
},
"create": {
- "projects": "Projekt",
+ "projects": "Projekte",
"already-exists": "Das Projekt ist bereits vorhanden",
"must-contain": "Darf nur A-Z 0-9 _ enthalten",
"no-info-in-url": "Geben Sie Benutzername & Passwort nicht innerhalb der URL vor",
@@ -1059,7 +1105,8 @@
"not-git": "Kein Git-Repository",
"no-resource": "Repository nicht gefunden",
"cant-get-ssh-key-path": "Fehler! Der ausgewählte SSH-Schlüsselpfad kann nicht abgerufen werden.",
- "unexpected_error": "unerwarteter_Fehler"
+ "unexpected_error": "unerwarteter_Fehler",
+ "clearContext": "Kontextdaten löscshen beim Projektwechsel"
},
"delete": {
"confirm": "Sind Sie sicher, dass dieses Projekt gelöscht werden soll?"
@@ -1106,13 +1153,37 @@
"preview": "Vorschau",
"defaultValue": "Standardwert"
},
+ "tourGuide": {
+ "takeATour": "Tour starten",
+ "start": "Start",
+ "next": "Nächste"
+ },
+ "diagnostics": {
+ "title": "System-Informationen"
+ },
"languages": {
- "de": "German",
- "en-US": "English",
- "ja": "Japanese",
- "ko": "Korean",
- "ru": "Russian",
- "zh-CN": "Chinese(Simplified)",
- "zh-TW": "Chinese(Traditional)"
+ "de": "Deutsch",
+ "en-US": "Englisch",
+ "ja": "Japanisch",
+ "ko": "Koreanisch",
+ "ru": "Russisch",
+ "zh-CN": "Chinesisch (Vereinfacht)",
+ "zh-TW": "Chinesisch (Traditionell)"
+ },
+ "validator": {
+ "errors": {
+ "invalid-json": "Ungültige JSON-Daten: __error__",
+ "invalid-json-prop": "__prop__: ungültige JSON-Daten: __error__",
+ "invalid-prop": "Ungültiger Eigenschaftsausdruck",
+ "invalid-prop-prop": "__prop__: ungültiger Eigenschaftsausdruck",
+ "invalid-num": "Ungültige Nummer",
+ "invalid-num-prop": "__prop__: ungültige Nummer",
+ "invalid-regexp": "Ungültiges Eingabemuster",
+ "invalid-regex-prop": "__prop__: ungültiges Eingabemuster",
+ "missing-required-prop": "__prop__: Eigenschaftswert fehlt",
+ "invalid-config": "__prop__: ungültige Konfigurations-Node",
+ "missing-config": "__prop__: Konfigurations-Node fehlt",
+ "validation-error": "__prop__: Validierungsfehler: __node__, __id__: __error__"
+ }
}
}
From ad0a08ea0e7dde0684e97545a0fd52c33c7a6316 Mon Sep 17 00:00:00 2001
From: Kazuhito Yokoi
Date: Mon, 20 Jun 2022 00:44:20 +0900
Subject: [PATCH 12/30] Add Japanese translations in action list for project
feature
---
.../@node-red/editor-client/locales/ja/editor.json | 6 +++++-
1 file changed, 5 insertions(+), 1 deletion(-)
diff --git a/packages/node_modules/@node-red/editor-client/locales/ja/editor.json b/packages/node_modules/@node-red/editor-client/locales/ja/editor.json
index ac09a1e87..2849070bf 100644
--- a/packages/node_modules/@node-red/editor-client/locales/ja/editor.json
+++ b/packages/node_modules/@node-red/editor-client/locales/ja/editor.json
@@ -1331,6 +1331,10 @@
"zoom-reset": "ズームリセット",
"toggle-navigator": "ナビゲータ表示切替",
"show-system-info": "システム情報",
- "split-wires-with-junctions": "分岐点によりワイヤーを分割"
+ "split-wires-with-junctions": "分岐点によりワイヤーを分割",
+ "new-project": "新しいプロジェクト",
+ "open-project": "プロジェクトを開く",
+ "show-project-settings": "プロジェクト設定を表示",
+ "show-version-control-tab": "バージョンコントロールタブを表示"
}
}
From 3fbbfce17cd9ef011b3dcd37a9376f08821963a9 Mon Sep 17 00:00:00 2001
From: Dennis Neufeld
Date: Mon, 20 Jun 2022 13:28:10 +0200
Subject: [PATCH 13/30] Fix typo in german translation
---
.../node_modules/@node-red/editor-client/locales/de/editor.json | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/node_modules/@node-red/editor-client/locales/de/editor.json b/packages/node_modules/@node-red/editor-client/locales/de/editor.json
index dd931a812..ba3007f51 100755
--- a/packages/node_modules/@node-red/editor-client/locales/de/editor.json
+++ b/packages/node_modules/@node-red/editor-client/locales/de/editor.json
@@ -1106,7 +1106,7 @@
"no-resource": "Repository nicht gefunden",
"cant-get-ssh-key-path": "Fehler! Der ausgewählte SSH-Schlüsselpfad kann nicht abgerufen werden.",
"unexpected_error": "unerwarteter_Fehler",
- "clearContext": "Kontextdaten löscshen beim Projektwechsel"
+ "clearContext": "Kontextdaten löschen beim Projektwechsel"
},
"delete": {
"confirm": "Sind Sie sicher, dass dieses Projekt gelöscht werden soll?"
From 9729c89f5dc30181765aef276a6daf151f687482 Mon Sep 17 00:00:00 2001
From: Steve-Mcl
Date: Mon, 20 Jun 2022 18:25:41 +0100
Subject: [PATCH 14/30] ensure link-call cache is updated when link-in is
modified fixes #3694 depends on node-red-node-test-helper@0.3.0
---
package.json | 2 +-
.../@node-red/nodes/core/common/60-link.js | 17 +++-----
test/nodes/core/common/60-link_spec.js | 43 +++++++++++++++++++
3 files changed, 51 insertions(+), 11 deletions(-)
diff --git a/package.json b/package.json
index 1343af50c..715d09a5b 100644
--- a/package.json
+++ b/package.json
@@ -111,7 +111,7 @@
"marked": "4.0.17",
"minami": "1.2.3",
"mocha": "9.2.2",
- "node-red-node-test-helper": "^0.2.7",
+ "node-red-node-test-helper": "^0.3.0",
"nodemon": "2.0.16",
"proxy": "^1.0.2",
"sass": "1.52.3",
diff --git a/packages/node_modules/@node-red/nodes/core/common/60-link.js b/packages/node_modules/@node-red/nodes/core/common/60-link.js
index 24572f8b1..08bad7a62 100644
--- a/packages/node_modules/@node-red/nodes/core/common/60-link.js
+++ b/packages/node_modules/@node-red/nodes/core/common/60-link.js
@@ -109,16 +109,13 @@ module.exports = function(RED) {
},
remove(node) {
const target = generateTarget(node);
- const tn = this.getTarget(target.name, target.flowId);
- if (tn) {
- const targs = this.getTargets(tn.name);
- const idx = getIndex(targs, tn.id);
- if (idx > -1) {
- targs.splice(idx, 1);
- }
- if (targs.length === 0) {
- delete registry.name[tn.name];
- }
+ const targs = this.getTargets(target.name);
+ const idx = getIndex(targs, target.id);
+ if (idx > -1) {
+ targs.splice(idx, 1);
+ }
+ if (targs.length === 0) {
+ delete registry.name[tn.name];
}
delete registry.id[target.id];
},
diff --git a/test/nodes/core/common/60-link_spec.js b/test/nodes/core/common/60-link_spec.js
index 63733455c..be7ffc39f 100644
--- a/test/nodes/core/common/60-link_spec.js
+++ b/test/nodes/core/common/60-link_spec.js
@@ -17,6 +17,7 @@
var should = require("should");
var linkNode = require("nr-test-utils").require("@node-red/nodes/core/common/60-link.js");
var helper = require("node-red-node-test-helper");
+var clone = require("clone");
describe('link Node', function() {
@@ -319,6 +320,48 @@ describe('link Node', function() {
linkCall.receive({ payload: "hello", target: "double payload" });
});
})
+ it('should not raise error after deploying a name change to a duplicate link-in node', async function () {
+ this.timeout(400);
+ const flow = [
+ { id: "tab-flow-1", type: "tab", label: "Flow 1" },
+ { id: "link-in-1", z: "tab-flow-1", type: "link in", name: "duplicate", wires: [["link-out-1"]] },
+ { id: "link-in-2", z: "tab-flow-1", type: "link in", name: "duplicate", wires: [["link-out-1"]] }, //duplicate name
+ { id: "link-out-1", z: "tab-flow-1", type: "link out", mode: "return" },
+ { id: "link-call", z: "tab-flow-1", type: "link call", linkType: "dynamic", links: [], wires: [["n4"]] },
+ { id: "n4", z: "tab-flow-1", type: "helper" }
+ ];
+
+ await helper.load(linkNode, flow)
+
+ const linkIn2before = helper.getNode("link-in-2");
+ linkIn2before.should.have.property("name", "duplicate") // check link-in-2 has been deployed with the duplicate name
+
+ //modify the flow and deploy change
+ const newConfig = clone(flow);
+ newConfig[2].name = "add" // change nodes name
+ await helper.setFlows(newConfig, "nodes") // deploy "nodes" only
+
+ const helperNode = helper.getNode("n4");
+ const linkCall2 = helper.getNode("link-call");
+ const linkIn2after = helper.getNode("link-in-2");
+ linkIn2after.should.have.property("name", "add") // check link-in-2 no longer has a duplicate name
+
+ //poke { payload: "hello", target: "add" } into the link-call node and
+ //ensure that a message arrives via the link-in node named "add"
+ await new Promise((resolve, reject) => {
+ helperNode.on("input", function (msg) {
+ try {
+ msg.should.have.property("target", "add");
+ msg.should.not.have.property("error");
+ resolve()
+ } catch (err) {
+ reject(err);
+ }
+ });
+ linkCall2.receive({ payload: "hello", target: "add" });
+ });
+
+ })
it('should allow nested link-call flows', function(done) {
this.timeout(500);
var flow = [/** Multiply by 2 link flow **/
From 202102ebf7374e6697d9c807457f9bc0c31099cd Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Mon, 20 Jun 2022 20:51:31 +0100
Subject: [PATCH 15/30] Fix clicking on node in workspace to hide context menu
---
.../editor-client/src/js/ui/contextMenu.js | 3 ++-
.../@node-red/editor-client/src/js/ui/view.js | 14 ++++++++++++++
2 files changed, 16 insertions(+), 1 deletion(-)
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js b/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js
index 9920789f5..0b388aff3 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js
@@ -170,6 +170,7 @@ RED.contextMenu = (function() {
}
return {
- show: show
+ show: show,
+ hide: disposeMenu
}
})()
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
index 522b86cbc..b55244d0f 100755
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view.js
@@ -988,6 +988,7 @@ RED.view = (function() {
if (RED.view.DEBUG) {
console.warn("canvasMouseDown", { mouse_mode, point: d3.mouse(this), event: d3.event });
}
+ RED.contextMenu.hide();
if (mouse_mode === RED.state.SELECTING_NODE) {
d3.event.stopPropagation();
return;
@@ -1779,6 +1780,9 @@ RED.view = (function() {
}
var i;
var historyEvent;
+ if (d3.event.button === 2) {
+ return
+ }
if (mouse_mode === RED.state.PANNING) {
resetMouseVars();
return
@@ -2903,6 +2907,7 @@ RED.view = (function() {
function portMouseDown(d,portType,portIndex, evt) {
if (RED.view.DEBUG) { console.warn("portMouseDown", mouse_mode,d,portType,portIndex); }
+ RED.contextMenu.hide();
evt = evt || d3.event;
if (evt === 1) {
return;
@@ -3411,6 +3416,7 @@ RED.view = (function() {
function nodeMouseDown(d) {
if (RED.view.DEBUG) { console.warn("nodeMouseDown", mouse_mode,d); }
focusView();
+ RED.contextMenu.hide();
if (d3.event.button === 1) {
return;
}
@@ -3793,6 +3799,7 @@ RED.view = (function() {
if (RED.view.DEBUG) {
console.warn("linkMouseDown", { mouse_mode, point: d3.mouse(this), event: d3.event });
}
+ RED.contextMenu.hide();
if (mouse_mode === RED.state.SELECTING_NODE) {
d3.event.stopPropagation();
return;
@@ -3852,6 +3859,9 @@ RED.view = (function() {
}
function groupMouseUp(g) {
+ if (RED.view.DEBUG) {
+ console.warn("groupMouseUp", { mouse_mode, event: d3.event });
+ }
if (dblClickPrimed && mousedown_group == g && clickElapsed > 0 && clickElapsed < dblClickInterval) {
mouse_mode = RED.state.DEFAULT;
RED.editor.editGroup(g);
@@ -3867,6 +3877,10 @@ RED.view = (function() {
// return
// }
+ if (RED.view.DEBUG) {
+ console.warn("groupMouseDown", { mouse_mode, point: mouse, event: d3.event });
+ }
+ RED.contextMenu.hide();
focusView();
if (d3.event.button === 1) {
return;
From 10835968fb3f714d971ea78bc48be41378bc7f9f Mon Sep 17 00:00:00 2001
From: Hiroyasu Nishiyama
Date: Tue, 21 Jun 2022 21:47:57 +0900
Subject: [PATCH 16/30] add access to previous tours
---
.../editor-client/src/js/ui/tab-help.js | 23 +-
.../editor-client/src/js/ui/tour/tourGuide.js | 26 ++
.../editor-client/src/tours/2.1/welcome.js | 229 ++++++++++++++++++
.../src/tours/2.2/images/delete-repair.gif | Bin 0 -> 29584 bytes
.../src/tours/2.2/images/detach-repair.gif | Bin 0 -> 71182 bytes
.../src/tours/2.2/images/slice.gif | Bin 0 -> 83214 bytes
.../src/tours/2.2/images/subflow-labels.png | Bin 0 -> 30101 bytes
.../editor-client/src/tours/2.2/welcome.js | 156 ++++++++++++
8 files changed, 430 insertions(+), 4 deletions(-)
create mode 100644 packages/node_modules/@node-red/editor-client/src/tours/2.1/welcome.js
create mode 100644 packages/node_modules/@node-red/editor-client/src/tours/2.2/images/delete-repair.gif
create mode 100644 packages/node_modules/@node-red/editor-client/src/tours/2.2/images/detach-repair.gif
create mode 100644 packages/node_modules/@node-red/editor-client/src/tours/2.2/images/slice.gif
create mode 100644 packages/node_modules/@node-red/editor-client/src/tours/2.2/images/subflow-labels.png
create mode 100644 packages/node_modules/@node-red/editor-client/src/tours/2.2/welcome.js
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-help.js b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-help.js
index 154b64364..c6b33dbc7 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/tab-help.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/tab-help.js
@@ -97,7 +97,10 @@ RED.sidebar.help = (function() {
var pendingContentLoad;
treeList.on('treelistselect', function(e,item) {
pendingContentLoad = item;
- if (item.nodeType) {
+ if (item.tour) {
+ RED.tourGuide.run(item.tour);
+ }
+ else if (item.nodeType) {
showNodeTypeHelp(item.nodeType);
} else if (item.content) {
helpSection.empty();
@@ -198,15 +201,27 @@ RED.sidebar.help = (function() {
label: RED._("sidebar.help.nodeHelp"),
children: [],
expanded: true
- }
+ };
+ var tours = RED.tourGuide.list().map(function (item) {
+ return {
+ icon: "fa fa-repeat",
+ label: item.label,
+ tour: item.path,
+ };
+ });
var helpData = [
{
id: 'changelog',
label: "Node-RED v"+RED.settings.version,
content: getChangelog
},
- nodeHelp
- ]
+ nodeHelp,
+ {
+ id: "tours",
+ label: "Tours",
+ children: tours
+ },
+ ];
var subflows = RED.nodes.registry.getNodeTypes().filter(function(t) {return /subflow/.test(t)});
if (subflows.length > 0) {
nodeHelp.children.push({
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/tour/tourGuide.js b/packages/node_modules/@node-red/editor-client/src/js/ui/tour/tourGuide.js
index 31612cfeb..49b960402 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/tour/tourGuide.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/tour/tourGuide.js
@@ -433,9 +433,35 @@ RED.tourGuide = (function() {
})
}
+ function listTour() {
+ return [
+ {
+ id: "2_3",
+ label: "3.0.0-beta.3 (latest)",
+ path: "./tours/welcome.js"
+ },
+ {
+ id: "2_2",
+ label: "2.2.0",
+ path: "./tours/2.2/welcome.js"
+ },
+ {
+ id: "2_1",
+ label: "2.1.0",
+ path: "./tours/2.1/welcome.js"
+ },
+ {
+ id: "first_flow",
+ label: "First flow",
+ path: "./tours/first-flow.js"
+ },
+ ];
+ }
+
return {
load: loadTour,
run: run,
+ list: listTour,
reset: function() {
RED.settings.set("editor.tours.welcome",'');
}
diff --git a/packages/node_modules/@node-red/editor-client/src/tours/2.1/welcome.js b/packages/node_modules/@node-red/editor-client/src/tours/2.1/welcome.js
new file mode 100644
index 000000000..8a4565bab
--- /dev/null
+++ b/packages/node_modules/@node-red/editor-client/src/tours/2.1/welcome.js
@@ -0,0 +1,229 @@
+export default {
+ version: "2.1.0",
+ steps: [
+ {
+ titleIcon: "fa fa-map-o",
+ title: {
+ "en-US": "Welcome to Node-RED 2.1!",
+ "ja": "Node-RED 2.1へようこそ!"
+ },
+ description: {
+ "en-US": "Let's take a moment to discover the new features in this release.",
+ "ja": "本リリースの新機能を見つけてみましょう。"
+ }
+ },
+ {
+ title: {
+ "en-US": "A new Tour Guide",
+ "ja": "新しいツアーガイド"
+ },
+ description: {
+ "en-US": "First, as you've already found, we now have this tour of new features. We'll only show the tour the first time you open the editor for each new version of Node-RED.
" +
+ "You can choose not to see this tour in the future by disabling it under the View tab of User Settings.
",
+ "ja": "最初に、既に見つけている様に、新機能の本ツアーがあります。本ツアーは、新バージョンのNode-REDフローエディタを初めて開いた時のみ表示されます。
" +
+ "ユーザ設定の表示タブの中で、この機能を無効化することで、本ツアーを表示しないようにすることもできます。
"
+ }
+ },
+ {
+ title: {
+ "en-US": "New Edit menu",
+ "ja": "新しい編集メニュー"
+ },
+ prepare() {
+ $("#red-ui-header-button-sidemenu").trigger("click");
+ $("#menu-item-edit-menu").parent().addClass("open");
+ },
+ complete() {
+ $("#menu-item-edit-menu").parent().removeClass("open");
+ },
+ element: "#menu-item-edit-menu-submenu",
+ interactive: false,
+ direction: "left",
+ description: {
+ "en-US": "The main menu has been updated with a new 'Edit' section. This includes all of the familar options, like cut/paste and undo/redo.
" +
+ "The menu now displays keyboard shortcuts for the options.
",
+ "ja": "メインメニューに「編集」セクションが追加されました。本セクションには、切り取り/貼り付けや、変更操作を戻す/やり直しの様な使い慣れたオプションが含まれています。
" +
+ "本メニューには、オプションのためのキーボードショートカットも表示されるようになりました。
"
+ }
+ },
+ {
+ title: {
+ "en-US": "Arranging nodes",
+ "ja": "ノードの配置"
+ },
+ prepare() {
+ $("#red-ui-header-button-sidemenu").trigger("click");
+ $("#menu-item-arrange-menu").parent().addClass("open");
+ },
+ complete() {
+ $("#menu-item-arrange-menu").parent().removeClass("open");
+ },
+ element: "#menu-item-arrange-menu-submenu",
+ interactive: false,
+ direction: "left",
+ description: {
+ "en-US": "The new 'Arrange' section of the menu provides new options to help arrange your nodes. You can align them to a common edge, spread them out evenly or change their order.
",
+ "ja": "メニューの新しい「配置」セクションには、ノードの配置を助ける新しいオプションが提供されています。ノードの端を揃えたり、均等に配置したり、表示順序を変更したりできます。
"
+ }
+ },
+ {
+ title: {
+ "en-US": "Hiding tabs",
+ "ja": "タブの非表示"
+ },
+ element: "#red-ui-workspace-tabs > li.active",
+ description: {
+ "en-US": 'Tabs can now be hidden by clicking their icon.
The Info Sidebar will still list all of your tabs, and tell you which ones are currently hidden.',
+ "ja": '
アイコンをクリックすることで、タブを非表示にできます。
情報サイドバーには、全てのタブが一覧表示されており、現在非表示になっているタブを確認できます。'
+ },
+ interactive: false,
+ prepare() {
+ $("#red-ui-workspace-tabs > li.active .red-ui-tab-close").css("display","block");
+ },
+ complete() {
+ $("#red-ui-workspace-tabs > li.active .red-ui-tab-close").css("display","");
+ }
+ },
+ {
+ title: {
+ "en-US": "Tab menu",
+ "ja": "タブメニュー"
+ },
+ element: "#red-ui-workspace-tabs-menu",
+ description: {
+ "en-US": "
The new tab menu also provides lots of new options for your tabs.
",
+ "ja": "新しいタブメニューには、タブに関する沢山の新しいオプションが提供されています。
"
+ },
+ interactive: false,
+ direction: "left",
+ prepare() {
+ $("#red-ui-workspace > .red-ui-tabs > .red-ui-tabs-menu a").trigger("click");
+ },
+ complete() {
+ $(document).trigger("click");
+ }
+ },
+ {
+ title: {
+ "en-US": "Flow and Group level environment variables",
+ "ja": "フローとグループの環境変数"
+ },
+ element: "#red-ui-workspace-tabs > li.active",
+ interactive: false,
+ description: {
+ "en-US": "Flows and Groups can now have their own environment variables that can be referenced by nodes inside them.
",
+ "ja": "フローとグループには、内部のノードから参照できる環境変数を設定できるようになりました。
"
+ }
+ },
+ {
+ prepare(done) {
+ RED.editor.editFlow(RED.nodes.workspace(RED.workspaces.active()),"editor-tab-envProperties");
+ setTimeout(done,700);
+ },
+ element: "#red-ui-tab-editor-tab-envProperties-link-button",
+ description: {
+ "en-US": "Their edit dialogs have a new Environment Variables section.
",
+ "ja": "編集ダイアログに環境変数セクションが追加されました。
"
+ }
+ },
+ {
+ element: ".node-input-env-container-row",
+ direction: "left",
+ description: {
+ "en-US": 'The environment variables are listed in this table and new ones can be added by clicking the button.
',
+ "ja": 'この表に環境変数が一覧表示されており、ボタンをクリックすることで新しい変数を追加できます。
'
+ },
+ complete(done) {
+ $("#node-dialog-cancel").trigger("click");
+ setTimeout(done,500);
+ }
+ },
+ {
+ title: {
+ "en-US": "Link Call node added",
+ "ja": "Link Callノードを追加"
+ },
+ prepare(done) {
+ this.paletteWasClosed = $("#red-ui-main-container").hasClass("red-ui-palette-closed");
+ RED.actions.invoke("core:toggle-palette",true)
+ $('[data-palette-type="link call"]')[0].scrollIntoView({block:"center"})
+ setTimeout(done,100);
+ },
+ element: '[data-palette-type="link call"]',
+ direction: "right",
+ description: {
+ "en-US": "The Link Call
node lets you call another flow that begins with a Link In
node and get the result back when the message reaches a Link Out
node.
",
+ "ja": "Link Call
ノードを用いることで、Link In
ノードから始まるフローを呼び出し、Link Out
ノードに到達した時に、結果を取得できます。
"
+ }
+ },
+ {
+ title: {
+ "en-US": "MQTT nodes support dynamic connections",
+ "ja": "MQTTノードが動的接続をサポート"
+ },
+ prepare(done) {
+ $('[data-palette-type="mqtt out"]')[0].scrollIntoView({block:"center"})
+ setTimeout(done,100);
+ },
+ element: '[data-palette-type="mqtt out"]',
+ direction: "right",
+ description: {
+ "en-US": 'The MQTT
nodes now support creating their connections and subscriptions dynamically.
',
+ "ja": 'MQTT
ノードは、動的な接続や購読ができるようになりました。
'
+ },
+ },
+ {
+ title: {
+ "en-US": "File nodes renamed",
+ "ja": "ファイルノードの名前変更"
+ },
+ prepare(done) {
+ $('[data-palette-type="file"]')[0].scrollIntoView({block:"center"});
+ setTimeout(done,100);
+ },
+ complete() {
+ if (this.paletteWasClosed) {
+ RED.actions.invoke("core:toggle-palette",false)
+ }
+ },
+ element: '[data-palette-type="file"]',
+ direction: "right",
+ description: {
+ "en-US": "The file nodes have been renamed to make it clearer which node does what.
",
+ "ja": "fileノードの名前が変更され、どのノードが何を行うかが明確になりました。
"
+ }
+ },
+ {
+ title: {
+ "en-US": "Deep copy option on Change node",
+ "ja": "Changeノードのディープコピーオプション"
+ },
+ prepare(done) {
+ var def = RED.nodes.getType('change');
+ RED.editor.edit({id:"test",type:"change",rules:[{t:"set",p:"payload",pt:"msg", tot:"msg",to:"anotherProperty"}],_def:def, _:def._});
+ setTimeout(done,700);
+ },
+ complete(done) {
+ $("#node-dialog-cancel").trigger("click");
+ setTimeout(done,500);
+ },
+ element: function() {
+ return $(".node-input-rule-property-deepCopy").next();
+ },
+ description: {
+ "en-US": "The Set rule has a new option to create a deep copy of the value. This ensures a complete copy is made, rather than using a reference.
",
+ "ja": "値を代入に、値のディープコピーを作成するオプションが追加されました。これによって参照ではなく、完全なコピーが作成されます。
"
+ }
+ },
+ {
+ title: {
+ "en-US": "And that's not all...",
+ "ja": "これが全てではありません..."
+ },
+ description: {
+ "en-US": "There are many more smaller changes, including:
- Auto-complete suggestions in the
msg
TypedInput. - Support for
msg.resetTimeout
in the Join
node. - Pushing messages to the front of the queue in the
Delay
node's rate limiting mode. - An optional second output on the
Delay
node for rate limited messages.
",
+ "ja": "以下の様な小さな変更が沢山あります:
msg
TypedInputの自動補完提案Join
ノードでmsg.resetTimeout
のサポートDelay
ノードの流量制御モードにおいて先頭メッセージをキューに追加Delay
ノードで流量制限されたメッセージ向けの任意の2つ目の出力
"
+ }
+ }
+ ]
+}
diff --git a/packages/node_modules/@node-red/editor-client/src/tours/2.2/images/delete-repair.gif b/packages/node_modules/@node-red/editor-client/src/tours/2.2/images/delete-repair.gif
new file mode 100644
index 0000000000000000000000000000000000000000..c668dfdee52b73e9ae2f21e3d9969986d4b526a5
GIT binary patch
literal 29584
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
JgF8Bf{{x*;*Yp4Y
literal 0
HcmV?d00001
diff --git a/packages/node_modules/@node-red/editor-client/src/tours/2.2/images/detach-repair.gif b/packages/node_modules/@node-red/editor-client/src/tours/2.2/images/detach-repair.gif
new file mode 100644
index 0000000000000000000000000000000000000000..14fe1a423b89eb8203701c9000472bcdaf4adbd1
GIT binary patch
literal 71182
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