From 39602ff5f26c115c0dbed432eb583fc8ef6d0333 Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Tue, 3 May 2022 13:58:02 +0100
Subject: [PATCH 001/195] Update changelog
---
CHANGELOG.md | 6 ++++++
1 file changed, 6 insertions(+)
diff --git a/CHANGELOG.md b/CHANGELOG.md
index 44dffa5be..6333fdb53 100644
--- a/CHANGELOG.md
+++ b/CHANGELOG.md
@@ -1,5 +1,11 @@
#### 3.0.0-beta.1: Beta Release
+**Migration from 2.x**
+
+ - Node-RED now requires Node.js 14.x or later.
+ - New installs of Node-RED will default to the monaco editor.
+
+
Editor
- Add Junctions (#3462) @knolleary
From f04d954882734c8cf9f068113b2f39e2e696ca30 Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Tue, 3 May 2022 14:25:27 +0100
Subject: [PATCH 002/195] Drop node 12 from test runs
---
.github/workflows/release.yml | 2 +-
.github/workflows/tests.yml | 2 +-
2 files changed, 2 insertions(+), 2 deletions(-)
diff --git a/.github/workflows/release.yml b/.github/workflows/release.yml
index e86c2afe3..8f3c8a6ce 100644
--- a/.github/workflows/release.yml
+++ b/.github/workflows/release.yml
@@ -26,7 +26,7 @@ jobs:
path: 'node-red.github.io'
- uses: actions/setup-node@v1
with:
- node-version: '12'
+ node-version: '16'
- run: node ./node-red/.github/scripts/update-node-red-docker.js
- name: Create Docker Pull Request
uses: peter-evans/create-pull-request@v2
diff --git a/.github/workflows/tests.yml b/.github/workflows/tests.yml
index dde581a01..0db909da6 100644
--- a/.github/workflows/tests.yml
+++ b/.github/workflows/tests.yml
@@ -11,7 +11,7 @@ jobs:
runs-on: ubuntu-latest
strategy:
matrix:
- node-version: [12, 14, 16]
+ node-version: [14, 16]
steps:
- uses: actions/checkout@v2
- name: Use Node.js ${{ matrix.node-version }}
From 38410397285a787f666689f908ab47ae3a503384 Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Tue, 3 May 2022 14:29:25 +0100
Subject: [PATCH 003/195] Update gen publish script for 3.x
---
scripts/generate-publish-script.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/scripts/generate-publish-script.js b/scripts/generate-publish-script.js
index 0c64cb832..82d98ea3c 100644
--- a/scripts/generate-publish-script.js
+++ b/scripts/generate-publish-script.js
@@ -4,7 +4,7 @@ const path = require("path");
const fs = require("fs-extra");
const should = require("should");
-const LATEST = "2";
+const LATEST = "3";
function generateScript() {
return new Promise((resolve, reject) => {
From 58085e39d153e57f0c075eaf81faeedb16d0bd25 Mon Sep 17 00:00:00 2001
From: Kazuhito Yokoi
Date: Wed, 4 May 2022 11:39:34 +0900
Subject: [PATCH 004/195] Add Japanese translations for welcome tour in
3.0-beta.1
---
.../editor-client/src/tours/welcome.js | 45 +++++++++++++------
1 file changed, 31 insertions(+), 14 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 e3f332da1..219aaec7b 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
@@ -5,17 +5,17 @@ export default {
titleIcon: "fa fa-map-o",
title: {
"en-US": "Welcome to Node-RED 3.0 Beta 1!",
- "ja": "Node-RED 3.0 Beta 1へようこそ!"
+ "ja": "Node-RED 3.0 ベータ1へようこそ!"
},
description: {
"en-US": "This is the first Beta release of Node-RED 3.0. It contains just about everything we have planned for the final release.
Let's take a moment to discover the new features in this release.
",
- "ja": "本リリースの新機能を見つけてみましょう。"
+ "ja": "これはNode-RED 3.0の最初のベータリリースです。これには、最終リリースで計画しているほぼ全ての機能が含まれています。
本リリースの新機能を見つけてみましょう。
"
}
},
{
title: {
"en-US": "Wire Junctions",
- // "ja": ""
+ "ja": "分岐点をワイヤーに追加"
},
image: 'images/junction-slice.gif',
description: {
@@ -23,26 +23,28 @@ export default {
add junction nodes that give you more control.
Junctions can be added to wires by holding the Shift key, then click and drag with
the right-hand mouse button across the wires.
`,
- // "ja": ""
+ "ja": `フローのワイヤーの経路をより制御しやすくするために、分岐点ノードを追加できるようになりました。
+ シフトキーを押しながら、マウスの右ボタンをクリックし、ワイヤーを横切るようにドラッグすることで、分岐点を追加できます。
`
},
},
{
title: {
"en-US": "Wire Junctions",
- // "ja": ""
+ "ja": "分岐点をワイヤーに追加"
},
image: 'images/junction-quick-add.png',
description: {
"en-US": `Junctions can also be added using the quick-add dialog.
The dialog is opened by holding the Ctrl (or Cmd) key when
clicking in the workspace.
`,
- // "ja": ""
+ "ja": `クイック追加ダイアログを用いて、分岐点を追加することもできます。
+ 本ダイアログを開くには、Ctrl(またはCmd)キーを押しながら、ワークスペース上でクリックします。
`
},
},
{
title: {
"en-US": "Debug Path Tooltip",
- // "ja": ""
+ "ja": "デバッグパスのツールチップ"
},
image: 'images/debug-path-tooltip.png',
description: {
@@ -53,20 +55,22 @@ export default {
the message.
Clicking on any item in the list will reveal it in
the workspace.
`,
- // "ja": ""
+ "ja": `デバックサイドバー内のノード名の上にマウスカーソルを乗せると、新たにツールチップが表示され、ノードの場所が分かるようになっています。
+ これは、サブフローを用いる時に役立つ機能であり、メッセージがどのノードから出力されたかを正確に特定することが遥かに簡単になります。
+ 本リスト内の要素をクリックすると、ワークスペース内にその要素が表示されます。
`
},
},
{
title: {
"en-US": "Continuous Search",
- // "ja": ""
+ "ja": "連続した検索"
},
image: 'images/continuous-search.png',
description: {
"en-US": `When searching for things in the editor, a new toolbar in
the workspace provides options to quickly jump between
the search results.
`,
- // "ja": ""
+ "ja": `ワークスペース内の新しいツールバーにあるオプションによって、エディタ内を検索する際に、検索結果の間を素早く移動できます。
`
},
},
{
@@ -81,13 +85,17 @@ export default {
Split Wire With Link Nodes
Actions can be accessed from the Action List in the main menu.
`,
- // "ja": ``
+ "ja": `ワイヤーを、接続されたLinkノードのペアに置き換える動作が新たに追加されました:
+
+ 本アクションは、メインメニュー内の動作一覧から呼び出せます。
`,
},
},
{
title: {
"en-US": "Default node names",
- // "ja": ""
+ "ja": "標準ノードの名前"
},
// image: "images/",
description: {
@@ -100,7 +108,12 @@ export default {
Generate Node Names
Actions can be accessed from the Action List in the main menu.
`,
- // "ja": ``
+ "ja": `一部のノードは、ワークスペース上に新インスタンスとして追加した際に、一意の名前を付けるよう変更されました。この変更は、Debug
、Function
、Link
ノードに適用されています。
+ 選択したノードに対して、標準の名前を生成する動作も新たに追加されました:
+ 本アクションは、メインメニュー内の動作一覧から呼び出せます。
+ `
}
},
{
@@ -115,7 +128,11 @@ export default {
The Link Call node can use a message property to dynamically target the link it should call
The HTTP Request node can be preconfigured with HTTP headers
`,
- // "ja": ``
+ "ja": `
+ Debugノードは、受信したメッセージの数をカウントするよう設定できるようになりました。
+ Link Callノードは、メッセージのプロパティによって、呼び出し対象のlinkを動的に指定できるようになりました。
+ HTTP Requestノードは、HTTPヘッダを事前設定できるようになりました。
+ `
}
}
]
From 7955a17a17e05a643dc4013b9c224e5070f20ac8 Mon Sep 17 00:00:00 2001
From: Mauricio Bonani
Date: Wed, 4 May 2022 06:37:52 -0400
Subject: [PATCH 005/195] Fix typedInput label not visible
---
.../editor-client/src/js/ui/common/typedInput.js | 5 +----
.../editor-client/src/sass/ui/common/typedInput.scss | 10 ++++++++++
2 files changed, 11 insertions(+), 4 deletions(-)
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js
index aa05ad695..549479d85 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js
@@ -1026,10 +1026,7 @@
$(opt.icon).prependTo(this.selectLabel);
}
else if (opt.icon.indexOf("/") !== -1) {
- image = new Image();
- image.name = opt.icon;
- image.src = mapDeprecatedIcon(opt.icon);
- $(' ',{src:mapDeprecatedIcon(opt.icon),style:"margin-right: 4px;height: 18px;"}).prependTo(this.selectLabel);
+ $('',{class:"red-ui-typedInput-icon", style:"mask-image: url("+opt.icon+"); -webkit-mask-image: url("+opt.icon+"); margin-right: 4px;height: 18px;width:13px"}).prependTo(this.selectLabel);
}
else {
$('',{class:"red-ui-typedInput-icon "+opt.icon,style:"min-width: 13px; margin-right: 4px;"}).prependTo(this.selectLabel);
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/ui/common/typedInput.scss b/packages/node_modules/@node-red/editor-client/src/sass/ui/common/typedInput.scss
index da53e1e2d..76345e980 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/ui/common/typedInput.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/ui/common/typedInput.scss
@@ -153,6 +153,16 @@ button.red-ui-typedInput-option-trigger
img {
max-width: none;
}
+ .red-ui-typedInput-icon:not(.fa) {
+ display: inline-block;
+ -webkit-mask-size: cover;
+ mask-size: cover;
+ -webkit-mask-position: center;
+ mask-position: center;
+ -webkit-mask-repeat: no-repeat;
+ mask-repeat: no-repeat;
+ background-color: $primary-text-color;
+ }
}
&:not(.disabled):hover {
From bd19c203e122d8de82932f85b1ff2a1fb426c307 Mon Sep 17 00:00:00 2001
From: Steve-Mcl
Date: Wed, 4 May 2022 15:08:52 +0100
Subject: [PATCH 006/195] Prevent error when `uses` search term is used fixes
#3578
---
.../node_modules/@node-red/editor-client/src/js/ui/search.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/search.js b/packages/node_modules/@node-red/editor-client/src/js/ui/search.js
index e477fbc22..ec50c532e 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/search.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/search.js
@@ -144,7 +144,7 @@ RED.search = (function() {
var key = keys[i];
var kpos = keys[i].indexOf(val);
if (kpos > -1) {
- var ids = Object.keys(index[key]);
+ var ids = Object.keys(index[key]||{});
for (j=0;j
Date: Wed, 4 May 2022 15:10:02 +0100
Subject: [PATCH 007/195] declare undeclared loop var
---
.../node_modules/@node-red/editor-client/src/js/ui/search.js | 2 +-
1 file changed, 1 insertion(+), 1 deletion(-)
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/search.js b/packages/node_modules/@node-red/editor-client/src/js/ui/search.js
index ec50c532e..6b73a1c41 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/search.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/search.js
@@ -255,7 +255,7 @@ RED.search = (function() {
}
currentResults = search(value);
if (currentResults.length > 0) {
- for (i=0;i 25) {
From bf8bfa582a4aa2a7ac4d1351b9867a7c4ce9a9eb Mon Sep 17 00:00:00 2001
From: Steve-Mcl
Date: Wed, 4 May 2022 15:16:35 +0100
Subject: [PATCH 008/195] fix error initialising flow tab editor fixes #3577
---
.../editor-client/src/js/ui/editors/panes/flowProperties.js | 1 -
1 file changed, 1 deletion(-)
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/flowProperties.js b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/flowProperties.js
index 826814bab..2db4d0c85 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/flowProperties.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/editors/panes/flowProperties.js
@@ -19,7 +19,6 @@
this.tabflowEditor = RED.editor.createEditor({
id: 'node-input-info',
mode: 'ace/mode/markdown',
- stateId: options.stateId,
value: ""
});
From 50ae29a08cab052669269cfc634c8f79ddabb703 Mon Sep 17 00:00:00 2001
From: Kazuhito Yokoi
Date: Wed, 4 May 2022 23:29:40 +0900
Subject: [PATCH 009/195] Add Japanese translations for v3.0-beta.1
---
.../editor-client/locales/ja/editor.json | 41 +++++----
.../@node-red/nodes/locales/ja/messages.json | 89 ++++++++++---------
.../@node-red/runtime/locales/ja/runtime.json | 4 +-
3 files changed, 71 insertions(+), 63 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 d4a638137..9713e2bab 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
@@ -302,9 +302,9 @@
"successfulRestart": "フローの再起動が成功しました",
"deployFailed": "デプロイが失敗しました: __message__",
"unusedConfigNodes": "使われていない設定ノードがあります。",
- "unusedConfigNodesButton":"未使用の構成ノードを検索",
- "unknownNodesButton":"不明なノードを検索する",
- "invalidNodesButton":"無効なノードを検索する",
+ "unusedConfigNodesButton": "未使用の構成ノードを検索",
+ "unknownNodesButton": "不明なノードを検索する",
+ "invalidNodesButton": "無効なノードを検索する",
"errors": {
"noResponse": "サーバの応答がありません"
},
@@ -1159,6 +1159,9 @@
"start": "開始",
"next": "次へ"
},
+ "diagnostics": {
+ "title": "システム情報"
+ },
"languages": {
"de": "ドイツ語",
"en-US": "英語",
@@ -1168,6 +1171,22 @@
"zh-CN": "中国語(簡体)",
"zh-TW": "中国語(繁体)"
},
+ "validator": {
+ "errors": {
+ "invalid-json": "JSONデータが不正: __error__",
+ "invalid-json-prop": "__prop__: JSONデータが不正: __error__",
+ "invalid-prop": "プロパティ式が不正",
+ "invalid-prop-prop": "__prop__: プロパティ式が不正",
+ "invalid-num": "数値が不正",
+ "invalid-num-prop": "__prop__: 数値が不正",
+ "invalid-regexp": "入力パターンが不正",
+ "invalid-regex-prop": "__prop__: 入力パターンが不正",
+ "missing-required-prop": "__prop__: プロパティが未設定",
+ "invalid-config": "__prop__: 設定ノードが不正",
+ "missing-config": "__prop__: 設定ノードが存在しません",
+ "validation-error": "__prop__: チェックエラー: __node__, __id__: __error__"
+ }
+ },
"action-list": {
"toggle-show-tips": "ヒント表示切替",
"show-about": "Node-REDの説明を表示",
@@ -1305,21 +1324,5 @@
"zoom-reset": "ズームリセット",
"toggle-navigator": "ナビゲータ表示切替",
"show-system-info": "システムインフォメーション"
- },
- "validator": {
- "errors": {
- "invalid-json": "JSONデータが不正: __error__",
- "invalid-json-prop": "__prop__: JSONデータが不正: __error__",
- "invalid-prop": "プロパティ式が不正",
- "invalid-prop-prop": "__prop__: プロパティ式が不正",
- "invalid-num": "数値が不正",
- "invalid-num-prop": "__prop__: 数値が不正",
- "invalid-regexp": "入力パターンが不正",
- "invalid-regex-prop": "__prop__: 入力パターンが不正",
- "missing-required-prop": "__prop__: プロパティが未設定",
- "invalid-config": "__prop__: 設定ノードが不正",
- "missing-config": "__prop__: 設定ノードが存在しません",
- "validation-error": "__prop__: チェックエラー: __node__, __id__: __error__"
- }
}
}
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 79d13a01c..a88dc3c55 100644
--- a/packages/node_modules/@node-red/nodes/locales/ja/messages.json
+++ b/packages/node_modules/@node-red/nodes/locales/ja/messages.json
@@ -86,10 +86,10 @@
"failed": "inject処理が失敗しました。詳細はログを確認してください。",
"toolong": "時間間隔が大き過ぎます",
"invalid-expr": "JSONata式が不正: __error__",
- "invalid-jsonata": "__prop__: プロパティ式が不正: __error__",
- "invalid-prop": "__prop__: プロパティ式が不正: __error__",
- "invalid-json": "__prop__: JSONデータが不正: __error__",
- "invalid-repeat": "繰り返し数が不正"
+ "invalid-jsonata": "__prop__: プロパティ式が不正: __error__",
+ "invalid-prop": "__prop__: プロパティ式が不正: __error__",
+ "invalid-json": "__prop__: JSONデータが不正: __error__",
+ "invalid-repeat": "繰り返し数が不正"
}
},
"catch": {
@@ -129,6 +129,7 @@
"msgprop": "メッセージプロパティ",
"msgobj": "msgオブジェクト全体",
"autostatus": "デバッグ出力と同じ",
+ "messageCount": "メッセージ数をカウント",
"to": "出力先",
"debtab": "デバッグタブ",
"tabcon": "デバッグタブとコンソール",
@@ -206,8 +207,8 @@
},
"error": {
"missing-file": "証明書と秘密鍵のファイルが設定されていません",
- "invalid-cert": "証明書が指定されていません",
- "invalid-key": "秘密鍵が指定されていません"
+ "invalid-cert": "証明書が指定されていません",
+ "invalid-key": "秘密鍵が指定されていません"
}
},
"exec": {
@@ -263,8 +264,8 @@
"moduleNameReserved": "予約された変数名です: __name__",
"inputListener": "コード内で'input'イベントのリスナを設定できません",
"non-message-returned": "Functionノードが __type__ 型のメッセージ送信を試みました",
- "invalid-js": "JavaScriptコードのエラー",
- "missing-module": "モジュール __module__ が存在しません"
+ "invalid-js": "JavaScriptコードのエラー",
+ "missing-module": "モジュール __module__ が存在しません"
}
},
"template": {
@@ -318,9 +319,9 @@
"limit": "limit",
"limitTopic": "limit topic",
"random": "random",
- "rate": "流量",
- "random-first": "ランダム最小値",
- "random-last": "ランダム最大値",
+ "rate": "流量",
+ "random-first": "ランダム最小値",
+ "random-last": "ランダム最大値",
"units": {
"second": {
"plural": "秒",
@@ -342,11 +343,11 @@
},
"errors": {
"too-many": "delayノード内で保持しているメッセージが多すぎます",
- "invalid-timeout": "遅延時間が不正",
- "invalid-rate": "流量値が不正",
- "invalid-rate-unit": "流量単位時間が不正",
- "invalid-random-first": "ランダム最小値が不正",
- "invalid-random-last": "ランダム最大値が不正"
+ "invalid-timeout": "遅延時間が不正",
+ "invalid-rate": "流量値が不正",
+ "invalid-rate-unit": "流量単位時間が不正",
+ "invalid-random-first": "ランダム最小値が不正",
+ "invalid-random-last": "ランダム最大値が不正"
}
},
"trigger": {
@@ -384,8 +385,8 @@
"resetMessage": "msg.resetを設定",
"resetPayload": "msg.payloadが次の値",
"resetprompt": "任意",
- "duration": "時間間隔",
- "topic": "トピック"
+ "duration": "時間間隔",
+ "topic": "トピック"
}
},
"comment": {
@@ -443,7 +444,8 @@
"action": "動作",
"staticTopic": "1つのトピックを購読",
"dynamicTopic": "動的な購読",
- "auto-connect": "自動接続"
+ "auto-connect": "自動接続",
+ "auto-mode-depreciated": "本オプションは非推奨になりました。新しい自動判定モードを使用してください。"
},
"sections-label": {
"birth-message": "接続時の送信メッセージ(Birthメッセージ)",
@@ -490,7 +492,7 @@
"invalid-action-action": "指定された動作が不正です",
"invalid-action-alreadyconnected": "接続する前にブローカから切断してください",
"invalid-action-badsubscription": "msg.topicが存在しないか不正です",
- "invalid-client-id": "クライアントIDが未指定"
+ "invalid-client-id": "クライアントIDが未指定"
}
},
"httpin": {
@@ -581,8 +583,8 @@
"send-error": "送信中にエラーが発生しました: ",
"missing-conf": "サーバ設定が不足しています",
"duplicate-path": "同じパスに対して2つのWebSocketリスナは指定できません: __path__",
- "missing-server": "サーバが設定されていません",
- "missing-client": "クライアントが設定されていません"
+ "missing-server": "サーバが設定されていません",
+ "missing-client": "クライアントが設定されていません"
}
},
"watch": {
@@ -611,7 +613,8 @@
"ms": "ミリ秒",
"chars": "文字",
"close": "終了",
- "optional": "(任意)"
+ "optional": "(任意)",
+ "reattach": "区切り文字を再追加"
},
"type": {
"listen": "待ち受け",
@@ -652,8 +655,8 @@
"connect-timeout": "接続がタイムアウトしました",
"connect-fail": "接続に失敗しました",
"bad-string": "文字列への変換に失敗しました",
- "invalid-host": "ホスト名が不正",
- "invalid-port": "ポートが不正"
+ "invalid-host": "ホスト名が不正",
+ "invalid-port": "ポートが不正"
}
},
"udp": {
@@ -668,7 +671,7 @@
"toport": "ポート",
"address": "アドレス",
"decode-base64": "Base64形式のペイロードを復号",
- "port": "ポート"
+ "port": "ポート"
},
"placeholder": {
"interface": "(任意) 使用するローカルインターフェイスもしくはアドレス",
@@ -716,7 +719,7 @@
"port-invalid": "udp: ポート番号が不正です",
"alreadyused": "udp: 既に__port__番ポートが使用されています",
"ifnotfound": "udp: インターフェイス __iface__ がありません",
- "invalid-group": "マルチキャストグループが不正"
+ "invalid-group": "マルチキャストグループが不正"
}
},
"switch": {
@@ -781,8 +784,8 @@
"invalid-json": "対象の値のJSONプロパティが不正",
"invalid-expr": "JSONata式が不正: __error__",
"no-override": "オブジェクト型でないプロパティを設定できません: __property__",
- "invalid-prop": "プロパティ式が不正: __property__",
- "invalid-json-data": "JSONデータが不正: __error__"
+ "invalid-prop": "プロパティ式が不正: __property__",
+ "invalid-json-data": "JSONデータが不正: __error__"
}
},
"range": {
@@ -794,10 +797,10 @@
"from": "最小値",
"to": "最大値",
"roundresult": "小数値を四捨五入し整数値へ変換",
- "minin": "入力最小値",
- "maxin": "入力最大値",
- "minout": "出力最小値",
- "maxout": "出力最大値"
+ "minin": "入力最小値",
+ "maxin": "入力最大値",
+ "minout": "出力最小値",
+ "maxout": "出力最大値"
},
"placeholder": {
"min": "例) 0",
@@ -1022,8 +1025,8 @@
"complete": "msg.complete
プロパティが設定されたメッセージ受信後",
"tip": "このモードでは、本ノードが split ノードと組となるか、 msg.parts
プロパティが設定されたメッセージを受け取ることが前提となります。",
"too-many": "joinノード内部で保持しているメッセージが多すぎます",
- "message-prop": "メッセージプロパティ",
- "merge": {
+ "message-prop": "メッセージプロパティ",
+ "merge": {
"topics-label": "対象トピック",
"topics": "トピック",
"topic": "トピック",
@@ -1081,11 +1084,11 @@
"too-many": "batchノード内で保持しているメッセージが多すぎます",
"unexpected": "想定外のモード",
"no-parts": "メッセージにpartsプロパティがありません",
- "error": {
- "invalid-count": "メッセージ数が不正",
- "invalid-overlap": "オーバラップが不正",
- "invalid-interval": "時間間隔が不正"
- }
+ "error": {
+ "invalid-count": "メッセージ数が不正",
+ "invalid-overlap": "オーバラップが不正",
+ "invalid-interval": "時間間隔が不正"
+ }
},
"rbe": {
"rbe": "filter",
@@ -1095,9 +1098,9 @@
"start": "初期値",
"name": "名前",
"septopics": "個別に動作を適用",
- "gap": "変化量",
- "property": "プロパティ",
- "topic": "トピック"
+ "gap": "変化量",
+ "property": "プロパティ",
+ "topic": "トピック"
},
"placeholder": {
"bandgap": "例:10、5%",
diff --git a/packages/node_modules/@node-red/runtime/locales/ja/runtime.json b/packages/node_modules/@node-red/runtime/locales/ja/runtime.json
index fdf8b2249..df5f9fa08 100644
--- a/packages/node_modules/@node-red/runtime/locales/ja/runtime.json
+++ b/packages/node_modules/@node-red/runtime/locales/ja/runtime.json
@@ -100,7 +100,9 @@
"error": "クレデンシャルの読み込みエラー: __message__",
"error-saving": "クレデンシャルの保存エラー: __message__",
"not-registered": "クレデンシャル '__type__' は登録されていません",
- "system-key-warning": "\n\n---------------------------------------------------------------------\nフローのクレデンシャルファイルはシステム生成キーで暗号化されています。\n\nシステム生成キーを何らかの理由で失った場合、クレデンシャルファイルを\n復元することはできません。その場合、ファイルを削除してクレデンシャルを\n再入力しなければなりません。\n\n設定ファイル内で 'credentialSecret' オプションを使って独自キーを設定\nします。変更を次にデプロイする際、Node-REDは選択したキーを用いてクレ\nデンシャルを再暗号化します。 \n\n---------------------------------------------------------------------\n"
+ "system-key-warning": "\n\n---------------------------------------------------------------------\nフローのクレデンシャルファイルはシステム生成キーで暗号化されています。\n\nシステム生成キーを何らかの理由で失った場合、クレデンシャルファイルを\n復元することはできません。その場合、ファイルを削除してクレデンシャルを\n再入力しなければなりません。\n\n設定ファイル内で 'credentialSecret' オプションを使って独自キーを設定\nします。変更を次にデプロイする際、Node-REDは選択したキーを用いてクレ\nデンシャルを再暗号化します。 \n\n---------------------------------------------------------------------\n",
+ "unencrypted": "暗号化されていないクレデンシャルを使用",
+ "encryptedNotFound": "暗号化されたクレデンシャルが存在しません"
},
"flows": {
"safe-mode": "セーフモードでフローを停止しました。開始するためにはデプロイしてください",
From 84a3884ffc735b4db51a3920efc52031c18548e6 Mon Sep 17 00:00:00 2001
From: Kazuhito Yokoi
Date: Wed, 4 May 2022 23:54:23 +0900
Subject: [PATCH 010/195] Fix i18n in typedInput of header area
---
.../@node-red/nodes/core/network/21-httprequest.html | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/packages/node_modules/@node-red/nodes/core/network/21-httprequest.html b/packages/node_modules/@node-red/nodes/core/network/21-httprequest.html
index 3e18f4fe7..6dc8af72a 100644
--- a/packages/node_modules/@node-red/nodes/core/network/21-httprequest.html
+++ b/packages/node_modules/@node-red/nodes/core/network/21-httprequest.html
@@ -127,12 +127,14 @@
{ value: "Cache-Control", label: "Cache-Control", hasValue: false },
{ value: "User-Agent", label: "User-Agent", hasValue: false },
{ value: "Location", label: "Location", hasValue: false },
- { value: "other", label: "other", hasValue: true, icon: "red/images/typedInput/az.png" },
+ { value: "other", label: RED._("node-red:httpin.label.other"),
+ hasValue: true, icon: "red/images/typedInput/az.png" },
{ value: "msg", label: "msg.", hasValue: true },
]
const headerOptions = {};
const defaultOptions = [
- { value: "other", label: "other", hasValue: true, icon: "red/images/typedInput/az.png" },
+ { value: "other", label: RED._("node-red:httpin.label.other"),
+ hasValue: true, icon: "red/images/typedInput/az.png" },
{ value: "msg", label: "msg.", hasValue: true },
];
headerOptions["accept"] = [
From 5fb811eb4c33e72824cdfdc8d793b285b83d37a6 Mon Sep 17 00:00:00 2001
From: Kazuhito Yokoi
Date: Thu, 5 May 2022 01:20:41 +0900
Subject: [PATCH 011/195] Change icon path from png to svg in typedInput
---
.../@node-red/nodes/core/network/21-httprequest.html | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/packages/node_modules/@node-red/nodes/core/network/21-httprequest.html b/packages/node_modules/@node-red/nodes/core/network/21-httprequest.html
index 6dc8af72a..8b1320496 100644
--- a/packages/node_modules/@node-red/nodes/core/network/21-httprequest.html
+++ b/packages/node_modules/@node-red/nodes/core/network/21-httprequest.html
@@ -128,13 +128,13 @@
{ value: "User-Agent", label: "User-Agent", hasValue: false },
{ value: "Location", label: "Location", hasValue: false },
{ value: "other", label: RED._("node-red:httpin.label.other"),
- hasValue: true, icon: "red/images/typedInput/az.png" },
+ hasValue: true, icon: "red/images/typedInput/az.svg" },
{ value: "msg", label: "msg.", hasValue: true },
]
const headerOptions = {};
const defaultOptions = [
{ value: "other", label: RED._("node-red:httpin.label.other"),
- hasValue: true, icon: "red/images/typedInput/az.png" },
+ hasValue: true, icon: "red/images/typedInput/az.svg" },
{ value: "msg", label: "msg.", hasValue: true },
];
headerOptions["accept"] = [
From bc5eafce666055ea6a7a7fe9608bdbf16d28a07b Mon Sep 17 00:00:00 2001
From: Kazuhito Yokoi
Date: Thu, 5 May 2022 01:28:42 +0900
Subject: [PATCH 012/195] Update translations in file and http request nodes
---
.../nodes/locales/ja/network/21-httprequest.html | 2 +-
.../nodes/locales/ja/storage/10-file.html | 14 ++++++++------
2 files changed, 9 insertions(+), 7 deletions(-)
diff --git a/packages/node_modules/@node-red/nodes/locales/ja/network/21-httprequest.html b/packages/node_modules/@node-red/nodes/locales/ja/network/21-httprequest.html
index d592c1d6e..1835b88f6 100644
--- a/packages/node_modules/@node-red/nodes/locales/ja/network/21-httprequest.html
+++ b/packages/node_modules/@node-red/nodes/locales/ja/network/21-httprequest.html
@@ -24,7 +24,7 @@
method 文字列
ノードの設定で指定していない場合、このプロパティでリクエストに用いるHTTPメソッドを設定します。GET
, PUT
, POST
, PATCH
, DELETE
のいずれかを指定してください。
headers オブジェクト
- リクエストのHTTPヘッダを指定します。
+ リクエストのHTTPヘッダを指定します。注釈: msg.headers
のヘッダは、ノード設定のヘッダで上書きされます。
cookies オブジェクト
設定すると、リクエストと共にクッキーを送ることができます。
payload
diff --git a/packages/node_modules/@node-red/nodes/locales/ja/storage/10-file.html b/packages/node_modules/@node-red/nodes/locales/ja/storage/10-file.html
index 3e67368d3..69765304c 100644
--- a/packages/node_modules/@node-red/nodes/locales/ja/storage/10-file.html
+++ b/packages/node_modules/@node-red/nodes/locales/ja/storage/10-file.html
@@ -15,11 +15,12 @@
-->
\ No newline at end of file
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/loose1.js b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose1.js
new file mode 100644
index 000000000..624cfe6d8
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose1.js
@@ -0,0 +1,4 @@
+
+ (function() {
+ console.log("hello from loose1.js")
+ })()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2.svg b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2.svg
new file mode 100644
index 000000000..04bebc370
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2.svg
@@ -0,0 +1 @@
+
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2b.svg b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2b.svg
new file mode 100644
index 000000000..250348861
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/icons/loose2b.svg
@@ -0,0 +1 @@
+
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.html b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.html
new file mode 100644
index 000000000..e23e2880a
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.js b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.js
new file mode 100644
index 000000000..e1cde2a82
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/loose2/loose2.js
@@ -0,0 +1,4 @@
+
+ (function() {
+ console.log("hello from loose2.js")
+ })()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/icons/test.svg b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/icons/test.svg
new file mode 100644
index 000000000..04bebc370
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/icons/test.svg
@@ -0,0 +1 @@
+
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/main.js b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/main.js
new file mode 100644
index 000000000..e2e0781d1
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/main.js
@@ -0,0 +1,4 @@
+
+ (function() {
+ console.log("hello from regular module main.js")
+ })()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/package.json
new file mode 100644
index 000000000..26d4151fb
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/node-red-node-testnode/package.json
@@ -0,0 +1,19 @@
+{
+ "name": "node-red-node-testnode",
+ "version": "1.0.0",
+ "description": "A node-red node that does nothing other than exist",
+ "main": "main.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "node-red"
+ ],
+ "node-red": {
+ "nodes": {
+ "testnode": "index.js"
+ }
+ },
+ "author": "@testyMcTersterson",
+ "license": "MIT"
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/icons/test.svg b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/icons/test.svg
new file mode 100644
index 000000000..04bebc370
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/icons/test.svg
@@ -0,0 +1 @@
+
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/main.js b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/main.js
new file mode 100644
index 000000000..e2e0781d1
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/main.js
@@ -0,0 +1,4 @@
+
+ (function() {
+ console.log("hello from regular module main.js")
+ })()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/package.json
new file mode 100644
index 000000000..23cfd7e86
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir1/regular_module/package.json
@@ -0,0 +1,14 @@
+{
+ "name": "regular_node",
+ "version": "1.0.0",
+ "description": "A regular node that does nothing other than exist",
+ "main": "main.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "test"
+ ],
+ "author": "@testyMcTersterson",
+ "license": "MIT"
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.html b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.html
new file mode 100644
index 000000000..0e45b3007
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.js b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.js
new file mode 100644
index 000000000..1fe9d89a3
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/index.js
@@ -0,0 +1,4 @@
+
+ (function() {
+ console.log("hello from @test/testnode index.js")
+ })()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/package.json
new file mode 100644
index 000000000..a32462631
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/@test/testnode/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "@test/testnode",
+ "version": "1.0.0",
+ "description": "A test node that does nothing other than exist",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "node-red",
+ "test"
+ ],
+ "node-red": {
+ "nodes": {
+ "testnode": "index.js"
+ }
+ },
+ "author": "@testyMcTersterson",
+ "license": "MIT"
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.html b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.html
new file mode 100644
index 000000000..5d9f2b0ec
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.js b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.js
new file mode 100644
index 000000000..0f0eba392
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/index.js
@@ -0,0 +1,4 @@
+
+ (function() {
+ console.log("hello from testnode2 index.js")
+ })()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/package.json
new file mode 100644
index 000000000..f9e8aecbe
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/testnode2/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "testnode2",
+ "version": "1.0.0",
+ "description": "A test node that does nothing other than exist",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "node-red",
+ "test"
+ ],
+ "node-red": {
+ "nodes": {
+ "testnode2": "index.js"
+ }
+ },
+ "author": "@testyMcTersterson",
+ "license": "MIT"
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/clientside.js b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/clientside.js
new file mode 100644
index 000000000..fb2e22289
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/clientside.js
@@ -0,0 +1,3 @@
+(function() {
+ console.log("Hi from test plugin client side")
+})()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/plugin.js b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/plugin.js
new file mode 100644
index 000000000..3202aeb8b
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/plugin.js
@@ -0,0 +1,14 @@
+module.exports = function (RED) {
+ RED.plugins.registerPlugin('test-theme', {
+ type: 'node-red-theme',
+ scripts: [
+ 'files/clientside.js'
+ ],
+ css: [
+ 'files/theme.css',
+ ],
+ monacoOptions: {
+ theme: "vs"
+ }
+ })
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/theme.css b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/theme.css
new file mode 100644
index 000000000..872c93e10
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/files/theme.css
@@ -0,0 +1 @@
+:root{--red-ui-primary-background: #f2f3fb;}
\ No newline at end of file
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/package.json
new file mode 100644
index 000000000..b8608c175
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir2/theme-plugin2/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "test-theme2",
+ "version": "0.0.1",
+ "description": "test theme for Node-RED",
+
+ "keywords": [
+ "node-red",
+ "plugin",
+ "theme"
+ ],
+ "author": {
+ "name": "testy-McTesterson"
+ },
+ "license": "MIT",
+ "node-red": {
+ "version": ">=2.2.0",
+ "plugins": {
+ "test-theme2": "files/plugin.js"
+ }
+ },
+ "engines": {
+ "node": ">=12.x"
+ }
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.html b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.html
new file mode 100644
index 000000000..0e45b3007
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.js b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.js
new file mode 100644
index 000000000..1fe9d89a3
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/index.js
@@ -0,0 +1,4 @@
+
+ (function() {
+ console.log("hello from @test/testnode index.js")
+ })()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/package.json
new file mode 100644
index 000000000..a32462631
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/testnode/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "@test/testnode",
+ "version": "1.0.0",
+ "description": "A test node that does nothing other than exist",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "node-red",
+ "test"
+ ],
+ "node-red": {
+ "nodes": {
+ "testnode": "index.js"
+ }
+ },
+ "author": "@testyMcTersterson",
+ "license": "MIT"
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/clientside.js b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/clientside.js
new file mode 100644
index 000000000..fb2e22289
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/clientside.js
@@ -0,0 +1,3 @@
+(function() {
+ console.log("Hi from test plugin client side")
+})()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/plugin.js b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/plugin.js
new file mode 100644
index 000000000..3202aeb8b
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/plugin.js
@@ -0,0 +1,14 @@
+module.exports = function (RED) {
+ RED.plugins.registerPlugin('test-theme', {
+ type: 'node-red-theme',
+ scripts: [
+ 'files/clientside.js'
+ ],
+ css: [
+ 'files/theme.css',
+ ],
+ monacoOptions: {
+ theme: "vs"
+ }
+ })
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/theme.css b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/theme.css
new file mode 100644
index 000000000..872c93e10
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/files/theme.css
@@ -0,0 +1 @@
+:root{--red-ui-primary-background: #f2f3fb;}
\ No newline at end of file
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/package.json
new file mode 100644
index 000000000..56b1bfb6d
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/@test/theme-plugin3/package.json
@@ -0,0 +1,24 @@
+{
+ "name": "@test/test-theme3",
+ "version": "0.0.1",
+ "description": "test theme for Node-RED",
+
+ "keywords": [
+ "node-red",
+ "plugin",
+ "theme"
+ ],
+ "author": {
+ "name": "testy-McTesterson"
+ },
+ "license": "MIT",
+ "node-red": {
+ "version": ">=2.2.0",
+ "plugins": {
+ "test-theme3": "files/plugin.js"
+ }
+ },
+ "engines": {
+ "node": ">=12.x"
+ }
+}
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.html b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.html
new file mode 100644
index 000000000..a4034f340
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.html
@@ -0,0 +1,5 @@
+
\ No newline at end of file
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.js b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.js
new file mode 100644
index 000000000..855768ad8
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/index.js
@@ -0,0 +1,4 @@
+
+ (function() {
+ console.log("hello from testnode3 index.js")
+ })()
diff --git a/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/package.json b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/package.json
new file mode 100644
index 000000000..41e9bb8f8
--- /dev/null
+++ b/test/unit/@node-red/registry/lib/resources/nodesDir3/node_modules/testnode3/package.json
@@ -0,0 +1,20 @@
+{
+ "name": "testnode3",
+ "version": "1.0.0",
+ "description": "A test node that does nothing other than exist",
+ "main": "index.js",
+ "scripts": {
+ "test": "echo \"Error: no test specified\" && exit 1"
+ },
+ "keywords": [
+ "node-red",
+ "test"
+ ],
+ "node-red": {
+ "nodes": {
+ "testnode3": "index.js"
+ }
+ },
+ "author": "@testyMcTersterson",
+ "license": "MIT"
+}
From 62a2a4a9f5b90b660d790eaf626ac20d16e91db4 Mon Sep 17 00:00:00 2001
From: Steve-Mcl
Date: Thu, 16 Jun 2022 11:38:19 +0100
Subject: [PATCH 077/195] Further simplify file node filename entry UX (v3)
fixes #3668
---
.../@node-red/nodes/core/storage/10-file.html | 16 ++++++++--------
.../@node-red/nodes/locales/en-US/messages.json | 1 +
2 files changed, 9 insertions(+), 8 deletions(-)
diff --git a/packages/node_modules/@node-red/nodes/core/storage/10-file.html b/packages/node_modules/@node-red/nodes/core/storage/10-file.html
index b726b537d..6b19ebaa8 100755
--- a/packages/node_modules/@node-red/nodes/core/storage/10-file.html
+++ b/packages/node_modules/@node-red/nodes/core/storage/10-file.html
@@ -198,8 +198,8 @@
category: 'storage',
defaults: {
name: {value:""},
- filename: {value:"filename"},
- filenameType: {value:"msg"},
+ filename: {value:""},
+ filenameType: {value:"str"},
appendNewline: {value:true},
createDir: {value:false},
overwriteFile: {value:"false"},
@@ -236,8 +236,8 @@
label: node._("file.encoding.setbymsg")
}).text(label).appendTo(encSel);
$("#node-input-filename").typedInput({
- default: "msg",
- types: ["str", "msg", "jsonata", "env"],
+ default: "str",
+ types: [{label:RED._("node-red:file.label.path"), value:"str", icon:""}, "msg", "jsonata", "env"],
typeField: $("#node-input-filenameType")
});
if(typeof node.filenameType == 'undefined') {
@@ -297,8 +297,8 @@
category: 'storage',
defaults: {
name: {value:""},
- filename: {value:"filename"},
- filenameType: {value:"msg"},
+ filename: {value:""},
+ filenameType: {value:"str"},
format: {value:"utf8"},
chunk: {value:false},
sendError: {value: false},
@@ -341,8 +341,8 @@
label: label
}).text(label).appendTo(encSel);
$("#node-input-filename").typedInput({
- default: "msg",
- types: ["str", "msg", "jsonata", "env"],
+ default: "str",
+ types: [{label:RED._("node-red:file.label.path"), value:"str", icon:""}, "msg", "jsonata", "env"],
typeField: $("#node-input-filenameType")
});
if(typeof node.filenameType == 'undefined') {
diff --git a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
index 77d832abd..62d5f351f 100644
--- a/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
+++ b/packages/node_modules/@node-red/nodes/locales/en-US/messages.json
@@ -928,6 +928,7 @@
"write": "write file",
"read": "read file",
"filename": "Filename",
+ "path": "path",
"action": "Action",
"addnewline": "Add newline (\\n) to each payload?",
"createdir": "Create directory if it doesn't exist?",
From ea469470541de61bcb13dc8dc4a120a9c6905673 Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Thu, 16 Jun 2022 13:48:36 +0100
Subject: [PATCH 078/195] Add RED.actions.getLabel to retrieve action i18n
label
---
.../editor-client/src/js/ui/actions.js | 53 +++++++++++--------
1 file changed, 31 insertions(+), 22 deletions(-)
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/actions.js b/packages/node_modules/@node-red/editor-client/src/js/ui/actions.js
index 2273ae9ab..5bd9ea034 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/actions.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/actions.js
@@ -21,6 +21,34 @@ RED.actions = (function() {
function getAction(name) {
return actions[name].handler;
}
+ function getActionLabel(name) {
+ let def = actions[name]
+ if (!def) {
+ return ''
+ }
+ if (!def.label) {
+ var options = def.options;
+ var key = options ? options.label : undefined;
+ if (!key) {
+ key = "action-list." +name.replace(/^.*:/,"");
+ }
+ var label = RED._(key);
+ if (label === key) {
+ // no translation. convert `name` to description
+ label = name.replace(/(^.+:([a-z]))|(-([a-z]))/g, function() {
+ if (arguments[5] === 0) {
+ return arguments[2].toUpperCase();
+ } else {
+ return " "+arguments[4].toUpperCase();
+ }
+ });
+ }
+ def.label = label;
+ }
+ return def.label
+ }
+
+
function invokeAction() {
var args = Array.prototype.slice.call(arguments);
var name = args.shift();
@@ -31,7 +59,7 @@ RED.actions = (function() {
}
function listActions() {
var result = [];
- var missing = [];
+
Object.keys(actions).forEach(function(action) {
var def = actions[action];
var shortcut = RED.keyboard.getShortcut(action);
@@ -42,28 +70,8 @@ RED.actions = (function() {
isUser = !!RED.keyboard.getUserShortcut(action);
}
if (!def.label) {
- var name = action;
- var options = def.options;
- var key = options ? options.label : undefined;
- if (!key) {
- key = "action-list." +name.replace(/^.*:/,"");
- }
- var label = RED._(key);
- if (label === key) {
- // no translation. convert `name` to description
- label = name.replace(/(^.+:([a-z]))|(-([a-z]))/g, function() {
- if (arguments[5] === 0) {
- return arguments[2].toUpperCase();
- } else {
- return " "+arguments[4].toUpperCase();
- }
- });
- missing.push(key);
- }
- def.label = label;
+ def.label = getActionLabel(action)
}
- //console.log("; missing:", missing);
-
result.push({
id:action,
scope:shortcut?shortcut.scope:undefined,
@@ -79,6 +87,7 @@ RED.actions = (function() {
add: addAction,
remove: removeAction,
get: getAction,
+ getLabel: getActionLabel,
invoke: invokeAction,
list: listActions
}
From 6bea3dabbb4a999a4c3fb77926ec0b0b154664b6 Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Thu, 16 Jun 2022 13:49:25 +0100
Subject: [PATCH 079/195] Allow popover position to be set via absolute pos
rather than relative
---
.../@node-red/editor-client/src/js/ui/common/popover.js | 9 ++++++---
1 file changed, 6 insertions(+), 3 deletions(-)
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js
index f1728ed83..9ddd3d866 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/popover.js
@@ -610,10 +610,13 @@ RED.popover = (function() {
var target = options.target;
var align = options.align || "right";
var offset = options.offset || [0,0];
+ var xPos = options.x;
+ var yPos = options.y;
+ var isAbsolutePosition = (xPos !== undefined && yPos !== undefined)
- var pos = target.offset();
- var targetWidth = target.width();
- var targetHeight = target.outerHeight();
+ var pos = isAbsolutePosition?{left:xPos, top: yPos}:target.offset();
+ var targetWidth = isAbsolutePosition?0:target.width();
+ var targetHeight = isAbsolutePosition?0:target.outerHeight();
var panelHeight = panel.height();
var panelWidth = panel.width();
From cce4f6f7f764675d6c9eecd611fde310f657f054 Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Thu, 16 Jun 2022 13:50:05 +0100
Subject: [PATCH 080/195] Add onpre/postselect, direction opts to menu and make
id optional
---
.../editor-client/src/js/ui/common/menu.js | 51 +++++++++++++++----
1 file changed, 42 insertions(+), 9 deletions(-)
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/common/menu.js b/packages/node_modules/@node-red/editor-client/src/js/ui/common/menu.js
index 417189b33..6327f5268 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/common/menu.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/common/menu.js
@@ -16,6 +16,7 @@
RED.menu = (function() {
var menuItems = {};
+ let menuItemCount = 0
function createMenuItem(opt) {
var item;
@@ -59,15 +60,16 @@ RED.menu = (function() {
item = $('');
} else {
item = $(' ');
-
+ if (!opt.id) {
+ opt.id = 'red-ui-menu-item-'+(menuItemCount++)
+ }
if (opt.group) {
item.addClass("red-ui-menu-group-"+opt.group);
-
}
var linkContent = '';
if (opt.toggle) {
- linkContent += ' ';
- linkContent += ' ';
+ linkContent += ' ';
+ linkContent += ' ';
}
if (opt.icon !== undefined) {
@@ -77,12 +79,15 @@ RED.menu = (function() {
linkContent += ' ';
}
}
-
+ let label = opt.label
+ if (!opt.label && typeof opt.onselect === 'string') {
+ label = RED.actions.getLabel(opt.onselect)
+ }
if (opt.sublabel) {
- linkContent += ' ';
@@ -126,10 +131,21 @@ RED.menu = (function() {
});
}
if (opt.options) {
- item.addClass("red-ui-menu-dropdown-submenu pull-left");
+ item.addClass("red-ui-menu-dropdown-submenu"+(opt.direction!=='right'?" pull-left":""));
var submenu = $('').appendTo(item);
for (var i=0;i",{class:"red-ui-menu red-ui-menu-dropdown pull-right"});
-
+ if (options.direction) {
+ topMenu.addClass("red-ui-menu-dropdown-direction-"+options.direction)
+ }
if (options.id) {
topMenu.attr({id:options.id+"-submenu"});
var menuParent = $("#"+options.id);
@@ -175,6 +193,15 @@ RED.menu = (function() {
var lastAddedSeparator = false;
for (var i=0;i
Date: Thu, 16 Jun 2022 13:57:50 +0100
Subject: [PATCH 081/195] Allow typeSearch to list actions
A proof-of-concept which needs a bit more UI polish, but capturing the
current code for the future. We do not add actions to the list, so the code
is unused.
---
.../editor-client/src/js/ui/typeSearch.js | 33 +++++++++++++++----
.../editor-client/src/js/ui/utils.js | 2 ++
2 files changed, 28 insertions(+), 7 deletions(-)
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/typeSearch.js b/packages/node_modules/@node-red/editor-client/src/js/ui/typeSearch.js
index 0fc633071..fc5b8e99e 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/typeSearch.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/typeSearch.js
@@ -104,7 +104,9 @@ RED.typeSearch = (function() {
var index = Math.max(0,selected);
if (index < children.length) {
var n = $(children[index]).find(".red-ui-editableList-item-content").data('data');
- typesUsed[n.type] = Date.now();
+ if (!/^_action_:/.test(n.type)) {
+ typesUsed[n.type] = Date.now();
+ }
if (n.def.outputs === 0) {
confirm(n);
} else {
@@ -173,6 +175,8 @@ RED.typeSearch = (function() {
var nodeDiv = $('',{class:"red-ui-search-result-node"}).appendTo(div);
if (object.type === "junction") {
nodeDiv.addClass("red-ui-palette-icon-junction");
+ } else if (/^_action_:/.test(object.type)) {
+ nodeDiv.addClass("red-ui-palette-icon-junction")
} else {
var colour = RED.utils.getNodeColor(object.type,def);
nodeDiv.css('backgroundColor',colour);
@@ -182,11 +186,14 @@ RED.typeSearch = (function() {
var iconContainer = $('
',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
RED.utils.createIconElement(icon_url, iconContainer, false);
- if (object.type !== "junction" && def.inputs > 0) {
- $('
',{class:"red-ui-search-result-node-port"}).appendTo(nodeDiv);
- }
- if (object.type !== "junction" && def.outputs > 0) {
- $('
',{class:"red-ui-search-result-node-port red-ui-search-result-node-output"}).appendTo(nodeDiv);
+
+ if (!/^_action_:/.test(object.type) && object.type !== "junction") {
+ if (def.inputs > 0) {
+ $('
',{class:"red-ui-search-result-node-port"}).appendTo(nodeDiv);
+ }
+ if (def.outputs > 0) {
+ $('
',{class:"red-ui-search-result-node-port red-ui-search-result-node-output"}).appendTo(nodeDiv);
+ }
}
var contentDiv = $('
',{class:"red-ui-search-result-description"}).appendTo(div);
@@ -207,7 +214,9 @@ RED.typeSearch = (function() {
}
function confirm(def) {
hide();
- typesUsed[def.type] = Date.now();
+ if (!/^_action_:/.test(def.type)) {
+ typesUsed[def.type] = Date.now();
+ }
addCallback(def.type);
}
@@ -316,6 +325,7 @@ RED.typeSearch = (function() {
function applyFilter(filter,type,def) {
return !filter ||
(
+ (!filter.spliceMultiple) &&
(!filter.type || type === filter.type) &&
(!filter.input || type === 'junction' || def.inputs > 0) &&
(!filter.output || type === 'junction' || def.outputs > 0)
@@ -330,6 +340,13 @@ RED.typeSearch = (function() {
'inject','debug','function','change','switch','junction'
].filter(function(t) { return applyFilter(opts.filter,t,RED.nodes.getType(t)); });
+ // if (opts.filter && opts.filter.input && opts.filter.output && !opts.filter.type) {
+ // if (opts.filter.spliceMultiple) {
+ // common.push('_action_:core:split-wires-with-junctions')
+ // }
+ // common.push('_action_:core:split-wire-with-link-nodes')
+ // }
+
var recentlyUsed = Object.keys(typesUsed);
recentlyUsed.sort(function(a,b) {
return typesUsed[b]-typesUsed[a];
@@ -354,6 +371,8 @@ RED.typeSearch = (function() {
var itemDef = RED.nodes.getType(common[i]);
if (common[i] === 'junction') {
itemDef = { inputs:1, outputs: 1, label: 'junction', type: 'junction'}
+ } else if (/^_action_:/.test(common[i]) ) {
+ itemDef = { inputs:1, outputs: 1, label: common[i], type: common[i]}
}
if (itemDef) {
item = {
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
index c3ea0ddd1..2c4cdca6b 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/utils.js
@@ -1032,6 +1032,8 @@ RED.utils = (function() {
return "font-awesome/fa-circle-o"
} else if (def.category === 'config') {
return RED.settings.apiRootUrl+"icons/node-red/cog.svg"
+ } else if ((node && /^_action_:/.test(node.type)) || /^_action_:/.test(def.type)) {
+ return "font-awesome/fa-cogs"
} else if (node && node.type === 'tab') {
return "red-ui-icons/red-ui-icons-flow"
// return RED.settings.apiRootUrl+"images/subflow_tab.svg"
From 0eba4bdd61e196b446981b786d30edb5ccbd3665 Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Thu, 16 Jun 2022 13:59:14 +0100
Subject: [PATCH 082/195] Add right-click context menu to workspace
---
Gruntfile.js | 1 +
.../editor-client/src/js/ui/contextMenu.js | 175 +++++++++++
.../editor-client/src/js/ui/view-tools.js | 155 +++++++++-
.../@node-red/editor-client/src/js/ui/view.js | 272 ++++++++++--------
.../editor-client/src/sass/dropdownMenu.scss | 35 ++-
5 files changed, 505 insertions(+), 133 deletions(-)
create mode 100644 packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js
diff --git a/Gruntfile.js b/Gruntfile.js
index 979b38051..a168d7ce4 100644
--- a/Gruntfile.js
+++ b/Gruntfile.js
@@ -192,6 +192,7 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/ui/library.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/notifications.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/search.js",
+ "packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/actionList.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/typeSearch.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js",
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
new file mode 100644
index 000000000..1a0dee2bb
--- /dev/null
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/contextMenu.js
@@ -0,0 +1,175 @@
+RED.contextMenu = (function() {
+
+ let menu;
+ function createMenu() {
+ // menu = RED.popover.menu({
+ // options: [
+ // {
+ // label: 'delete selection',
+ // onselect: function() {
+ // RED.actions.invoke('core:delete-selection')
+ // RED.view.focus()
+ // }
+ // },
+ // { label: 'world' }
+ // ],
+ // width: 200,
+ // })
+
+
+
+
+ }
+
+ function disposeMenu() {
+ $(document).off("mousedown.red-ui-workspace-context-menu");
+ if (menu) {
+ menu.remove();
+ }
+ menu = null;
+ }
+ function show(options) {
+ if (menu) {
+ menu.remove()
+ }
+
+ const selection = RED.view.selection()
+ const hasSelection = (selection.nodes && selection.nodes.length > 0);
+ const hasMultipleSelection = hasSelection && selection.nodes.length > 1;
+ const hasLinks = selection.links && selection.links.length > 0;
+ const isSingleLink = !hasSelection && hasLinks && selection.links.length === 1
+ const isMultipleLinks = !hasSelection && hasLinks && selection.links.length > 1
+ const canDelete = hasSelection || hasLinks
+ const isGroup = hasSelection && selection.nodes.length === 1 && selection.nodes[0].type === 'group'
+
+ const canRemoveFromGroup = hasSelection && !!selection.nodes[0].g
+
+
+ const menuItems = [
+ { onselect: 'core:show-action-list', onpostselect: function() {} },
+ {
+ label: 'Insert',
+ options: [
+ {
+ label: 'Node',
+ onselect: function() {
+ RED.view.showQuickAddDialog({
+ position: [ options.x - offset.left, options.y - offset.top ],
+ touchTrigger: true,
+ splice: isSingleLink?selection.links[0]:undefined,
+ // spliceMultiple: isMultipleLinks
+ })
+ }
+ },
+ {
+ label: 'Junction',
+ onselect: 'core:split-wires-with-junctions',
+ disabled: hasSelection || !hasLinks
+ },
+ {
+ label: 'Link Nodes',
+ onselect: 'core:split-wire-with-link-nodes',
+ disabled: hasSelection || !hasLinks
+ }
+ ]
+
+
+
+ }
+ ]
+ // menuItems.push(
+ // {
+ // label: (isSingleLink || isMultipleLinks)?'Insert into wire...':'Add node...',
+ // onselect: function() {
+ // RED.view.showQuickAddDialog({
+ // position: [ options.x - offset.left, options.y - offset.top ],
+ // touchTrigger: true,
+ // splice: isSingleLink?selection.links[0]:undefined,
+ // spliceMultiple: isMultipleLinks
+ // })
+ // }
+ // },
+ // )
+ // if (hasLinks && !hasSelection) {
+ // menuItems.push({ onselect: 'core:split-wires-with-junctions', label: 'Insert junction'})
+ // }
+ menuItems.push(
+ null,
+ { onselect: 'core:undo', disabled: RED.history.list().length === 0 },
+ { onselect: 'core:redo', disabled: RED.history.listRedo().length === 0 },
+ null,
+ { onselect: 'core:cut-selection-to-internal-clipboard', label: RED._("keyboard.cutNode"), disabled: !hasSelection},
+ { onselect: 'core:copy-selection-to-internal-clipboard', label: RED._("keyboard.copyNode"), disabled: !hasSelection },
+ { onselect: 'core:paste-from-internal-clipboard', label: RED._("keyboard.pasteNode"), disabled: !RED.view.clipboard() },
+ { onselect: 'core:delete-selection', disabled: !canDelete },
+ { onselect: 'core:show-export-dialog', label: RED._("menu.label.export") },
+ { onselect: 'core:select-all-nodes' },
+ )
+
+ if (hasSelection) {
+ menuItems.push(
+ null,
+ isGroup
+ ? { onselect: 'core:ungroup-selection', disabled: !isGroup }
+ : { onselect: 'core:group-selection', disabled: !hasSelection }
+ )
+ if (canRemoveFromGroup) {
+ menuItems.push({ onselect: 'core:remove-selection-from-group', label: RED._("menu.label.groupRemoveSelection") })
+ }
+
+ }
+ const offset = $("#red-ui-workspace-chart").offset()
+ menu = RED.menu.init({
+ direction: 'right',
+ onpreselect: function() {
+ disposeMenu()
+ },
+ onpostselect: function() {
+ RED.view.focus()
+ },
+ options: menuItems
+ });
+
+ menu.attr("id","red-ui-workspace-context-menu");
+ menu.css({
+ position: "absolute"
+ })
+ menu.appendTo("body");
+
+ // TODO: prevent the menu from overflowing the window.
+
+ var top = options.y
+ var left = options.x
+
+ if (top+menu.height()-$(document).scrollTop() > $(window).height()) {
+ top -= (top+menu.height())-$(window).height() + 22;
+ }
+ if (left+menu.width()-$(document).scrollLeft() > $(window).width()) {
+ left -= (left+menu.width())-$(window).width() + 18;
+ }
+ menu.css({
+ top: top+"px",
+ left: left+"px"
+ })
+ $(".red-ui-menu.red-ui-menu-dropdown").hide();
+ $(document).on("mousedown.red-ui-workspace-context-menu", function(evt) {
+ if (menu && menu[0].contains(evt.target)) {
+ return
+ }
+ disposeMenu()
+ });
+ menu.show();
+
+ // menu.show({
+ // target: $('#red-ui-main-container'),
+ // x: options.x,
+ // y: options.y
+ // })
+
+
+ }
+
+ return {
+ show: show
+ }
+})()
diff --git a/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js b/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js
index 699e5f222..888fb4d7f 100644
--- a/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js
+++ b/packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js
@@ -336,17 +336,17 @@ RED.view.tools = (function() {
}
- function addNode() {
- var selection = RED.view.selection();
- if (selection.nodes && selection.nodes.length === 1 && selection.nodes[0].outputs > 0) {
- var selectedNode = selection.nodes[0];
- RED.view.showQuickAddDialog([
- selectedNode.x + selectedNode.w + 50,selectedNode.y
- ])
- } else {
- RED.view.showQuickAddDialog();
- }
- }
+ // function addNode() {
+ // var selection = RED.view.selection();
+ // if (selection.nodes && selection.nodes.length === 1 && selection.nodes[0].outputs > 0) {
+ // var selectedNode = selection.nodes[0];
+ // RED.view.showQuickAddDialog([
+ // selectedNode.x + selectedNode.w + 50,selectedNode.y
+ // ])
+ // } else {
+ // RED.view.showQuickAddDialog();
+ // }
+ // }
function gotoNearestNode(direction) {
@@ -815,6 +815,9 @@ RED.view.tools = (function() {
*/
function splitWiresWithLinkNodes(wires) {
let wiresToSplit = wires || RED.view.selection().links;
+ if (!wiresToSplit) {
+ return
+ }
if (!Array.isArray(wiresToSplit)) {
wiresToSplit = [wiresToSplit];
}
@@ -1047,6 +1050,135 @@ RED.view.tools = (function() {
}
}
+ function addJunctionsToWires(wires) {
+ let wiresToSplit = wires || RED.view.selection().links;
+ if (!wiresToSplit) {
+ return
+ }
+ if (!Array.isArray(wiresToSplit)) {
+ wiresToSplit = [wiresToSplit];
+ }
+ if (wiresToSplit.length === 0) {
+ return;
+ }
+
+ var removedLinks = new Set()
+ var addedLinks = []
+ var addedJunctions = []
+
+ var groupedLinks = {}
+ wiresToSplit.forEach(function(l) {
+ var sourceId = l.source.id+":"+l.sourcePort
+ groupedLinks[sourceId] = groupedLinks[sourceId] || []
+ groupedLinks[sourceId].push(l)
+
+ groupedLinks[l.target.id] = groupedLinks[l.target.id] || []
+ groupedLinks[l.target.id].push(l)
+ });
+ var linkGroups = Object.keys(groupedLinks)
+ linkGroups.sort(function(A,B) {
+ return groupedLinks[B].length - groupedLinks[A].length
+ })
+ linkGroups.forEach(function(gid) {
+ var links = groupedLinks[gid]
+ var junction = {
+ _def: {defaults:{}},
+ type: 'junction',
+ z: RED.workspaces.active(),
+ id: RED.nodes.id(),
+ x: 0,
+ y: 0,
+ w: 0, h: 0,
+ outputs: 1,
+ inputs: 1,
+ dirty: true
+ }
+ links = links.filter(function(l) { return !removedLinks.has(l) })
+ if (links.length === 0) {
+ return
+ }
+ let pointCount = 0
+ links.forEach(function(l) {
+ if (l._sliceLocation) {
+ junction.x += l._sliceLocation.x
+ junction.y += l._sliceLocation.y
+ delete l._sliceLocation
+ pointCount++
+ } else {
+ junction.x += l.source.x + l.source.w/2 + l.target.x - l.target.w/2
+ junction.y += l.source.y + l.target.y
+ pointCount += 2
+ }
+ })
+ junction.x = Math.round(junction.x/pointCount)
+ junction.y = Math.round(junction.y/pointCount)
+ if (RED.view.snapGrid) {
+ let gridSize = RED.view.gridSize()
+ junction.x = (gridSize*Math.round(junction.x/gridSize));
+ junction.y = (gridSize*Math.round(junction.y/gridSize));
+ }
+
+ var nodeGroups = new Set()
+
+ RED.nodes.addJunction(junction)
+ addedJunctions.push(junction)
+ let newLink
+ if (gid === links[0].source.id+":"+links[0].sourcePort) {
+ newLink = {
+ source: links[0].source,
+ sourcePort: links[0].sourcePort,
+ target: junction
+ }
+ } else {
+ newLink = {
+ source: junction,
+ sourcePort: 0,
+ target: links[0].target
+ }
+ }
+ addedLinks.push(newLink)
+ RED.nodes.addLink(newLink)
+ links.forEach(function(l) {
+ removedLinks.add(l)
+ RED.nodes.removeLink(l)
+ let newLink
+ if (gid === l.target.id) {
+ newLink = {
+ source: l.source,
+ sourcePort: l.sourcePort,
+ target: junction
+ }
+ } else {
+ newLink = {
+ source: junction,
+ sourcePort: 0,
+ target: l.target
+ }
+ }
+ addedLinks.push(newLink)
+ RED.nodes.addLink(newLink)
+ nodeGroups.add(l.source.g || "__NONE__")
+ nodeGroups.add(l.target.g || "__NONE__")
+ })
+ if (nodeGroups.size === 1) {
+ var group = nodeGroups.values().next().value
+ if (group !== "__NONE__") {
+ RED.group.addToGroup(RED.nodes.group(group), junction)
+ }
+ }
+ })
+ if (addedJunctions.length > 0) {
+ RED.history.push({
+ t: 'add',
+ links: addedLinks,
+ junctions: addedJunctions,
+ removedLinks: Array.from(removedLinks)
+ })
+ RED.nodes.dirty(true)
+ }
+ RED.view.redraw(true);
+ }
+
return {
init: function() {
RED.actions.add("core:show-selected-node-labels", function() { setSelectedNodeLabelState(true); })
@@ -1109,6 +1241,7 @@ RED.view.tools = (function() {
RED.actions.add("core:wire-node-to-multiple", function() { wireNodeToMultiple() })
RED.actions.add("core:split-wire-with-link-nodes", function () { splitWiresWithLinkNodes() });
+ RED.actions.add("core:split-wires-with-junctions", function () { addJunctionsToWires() });
RED.actions.add("core:generate-node-names", generateNodeNames )
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 5ac9525ff..9f28d7191 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
@@ -206,7 +206,15 @@ RED.view = (function() {
function init() {
chart = $("#red-ui-workspace-chart");
-
+ chart.on('contextmenu', function(evt) {
+ evt.preventDefault()
+ evt.stopPropagation()
+ RED.contextMenu.show({
+ x:evt.clientX-5,
+ y:evt.clientY-5
+ })
+ return false
+ })
outer = d3.select("#red-ui-workspace-chart")
.append("svg:svg")
.attr("width", space_width)
@@ -992,7 +1000,10 @@ RED.view = (function() {
scroll_position = [chart.scrollLeft(),chart.scrollTop()];
return;
}
- if (!mousedown_node && !mousedown_link && !mousedown_group) {
+ if (d3.event.button === 2) {
+ return
+ }
+ if (!mousedown_node && !mousedown_link && !mousedown_group && !d3.event.shiftKey) {
selectedLinks.clear();
updateSelection();
}
@@ -1046,6 +1057,7 @@ RED.view = (function() {
options = options || {};
var point = options.position || lastClickPosition;
var spliceLink = options.splice;
+ var spliceMultipleLinks = options.spliceMultiple
var targetGroup = options.group;
var touchTrigger = options.touchTrigger;
@@ -1058,6 +1070,10 @@ RED.view = (function() {
var ox = point[0];
var oy = point[1];
+ const offset = $("#red-ui-workspace-chart").offset()
+ var clientX = ox + offset.left
+ var clientY = oy + offset.top
+
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')
point[0] = Math.round(point[0] / gridSize) * gridSize;
@@ -1109,8 +1125,12 @@ RED.view = (function() {
}
hideDragLines();
}
- if (spliceLink) {
- filter = {input:true, output:true}
+ if (spliceLink || spliceMultipleLinks) {
+ filter = {
+ input:true,
+ output:true,
+ spliceMultiple: spliceMultipleLinks
+ }
}
var rebuildQuickAddLink = function() {
@@ -1135,8 +1155,8 @@ RED.view = (function() {
var lastAddedWidth;
RED.typeSearch.show({
- x:d3.event.clientX-mainPos.left-node_width/2 - (ox-point[0]),
- y:d3.event.clientY-mainPos.top+ node_height/2 + 5 - (oy-point[1]),
+ x:clientX-mainPos.left-node_width/2 - (ox-point[0]),
+ y:clientY-mainPos.top+ node_height/2 + 5 - (oy-point[1]),
disableFocus: touchTrigger,
filter: filter,
move: function(dx,dy) {
@@ -1164,7 +1184,7 @@ RED.view = (function() {
hideDragLines();
redraw();
},
- add: function(type,keepAdding) {
+ add: function(type, keepAdding) {
if (touchTrigger) {
keepAdding = false;
resetMouseVars();
@@ -1172,7 +1192,13 @@ RED.view = (function() {
var nn;
var historyEvent;
- if (type === 'junction') {
+ if (/^_action_:/.test(type)) {
+ const actionName = type.substring(9)
+ quickAddActive = false;
+ ghostNode.remove();
+ RED.actions.invoke(actionName)
+ return
+ } else if (type === 'junction') {
nn = {
_def: {defaults:{}},
type: 'junction',
@@ -1844,8 +1870,20 @@ RED.view = (function() {
}
}
})
-
-
+ activeLinks.forEach(function(link) {
+ if (!link.selected) {
+ var sourceY = link.source.y
+ var targetY = link.target.y
+ var sourceX = link.source.x+(link.source.w/2) + 10
+ var targetX = link.target.x-(link.target.w/2) - 10
+ if (
+ sourceX > x && sourceX < x2 && sourceY > y && sourceY < y2 &&
+ targetX > x && targetX < x2 && targetY > y && targetY < y2
+ ) {
+ selectedLinks.add(link);
+ }
+ }
+ })
// var selectionChanged = false;
// do {
@@ -1893,114 +1931,118 @@ RED.view = (function() {
slicePath = null;
RED.view.redraw(true);
} else if (mouse_mode == RED.state.SLICING_JUNCTION) {
- var removedLinks = new Set()
- var addedLinks = []
- var addedJunctions = []
-
- var groupedLinks = {}
- selectedLinks.forEach(function(l) {
- var sourceId = l.source.id+":"+l.sourcePort
- groupedLinks[sourceId] = groupedLinks[sourceId] || []
- groupedLinks[sourceId].push(l)
-
- groupedLinks[l.target.id] = groupedLinks[l.target.id] || []
- groupedLinks[l.target.id].push(l)
- });
- var linkGroups = Object.keys(groupedLinks)
- linkGroups.sort(function(A,B) {
- return groupedLinks[B].length - groupedLinks[A].length
- })
- linkGroups.forEach(function(gid) {
- var links = groupedLinks[gid]
- var junction = {
- _def: {defaults:{}},
- type: 'junction',
- z: RED.workspaces.active(),
- id: RED.nodes.id(),
- x: 0,
- y: 0,
- w: 0, h: 0,
- outputs: 1,
- inputs: 1,
- dirty: true
- }
- links = links.filter(function(l) { return !removedLinks.has(l) })
- if (links.length === 0) {
- return
- }
- links.forEach(function(l) {
- junction.x += l._sliceLocation.x
- junction.y += l._sliceLocation.y
- })
- junction.x = Math.round(junction.x/links.length)
- junction.y = Math.round(junction.y/links.length)
- if (snapGrid) {
- junction.x = (gridSize*Math.round(junction.x/gridSize));
- junction.y = (gridSize*Math.round(junction.y/gridSize));
- }
-
- var nodeGroups = new Set()
-
- RED.nodes.addJunction(junction)
- addedJunctions.push(junction)
- let newLink
- if (gid === links[0].source.id+":"+links[0].sourcePort) {
- newLink = {
- source: links[0].source,
- sourcePort: links[0].sourcePort,
- target: junction
- }
- } else {
- newLink = {
- source: junction,
- sourcePort: 0,
- target: links[0].target
- }
- }
- addedLinks.push(newLink)
- RED.nodes.addLink(newLink)
- links.forEach(function(l) {
- removedLinks.add(l)
- RED.nodes.removeLink(l)
- let newLink
- if (gid === l.target.id) {
- newLink = {
- source: l.source,
- sourcePort: l.sourcePort,
- target: junction
- }
- } else {
- newLink = {
- source: junction,
- sourcePort: 0,
- target: l.target
- }
- }
- addedLinks.push(newLink)
- RED.nodes.addLink(newLink)
- nodeGroups.add(l.source.g || "__NONE__")
- nodeGroups.add(l.target.g || "__NONE__")
- })
- if (nodeGroups.size === 1) {
- var group = nodeGroups.values().next().value
- if (group !== "__NONE__") {
- RED.group.addToGroup(RED.nodes.group(group), junction)
- }
- }
- })
+ RED.actions.invoke("core:split-wires-with-junctions")
slicePath.remove();
slicePath = null;
- if (addedJunctions.length > 0) {
- RED.history.push({
- t: 'add',
- links: addedLinks,
- junctions: addedJunctions,
- removedLinks: Array.from(removedLinks)
- })
- RED.nodes.dirty(true)
- }
- RED.view.redraw(true);
+ // var removedLinks = new Set()
+ // var addedLinks = []
+ // var addedJunctions = []
+ //
+ // var groupedLinks = {}
+ // selectedLinks.forEach(function(l) {
+ // var sourceId = l.source.id+":"+l.sourcePort
+ // groupedLinks[sourceId] = groupedLinks[sourceId] || []
+ // groupedLinks[sourceId].push(l)
+ //
+ // groupedLinks[l.target.id] = groupedLinks[l.target.id] || []
+ // groupedLinks[l.target.id].push(l)
+ // });
+ // var linkGroups = Object.keys(groupedLinks)
+ // linkGroups.sort(function(A,B) {
+ // return groupedLinks[B].length - groupedLinks[A].length
+ // })
+ // linkGroups.forEach(function(gid) {
+ // var links = groupedLinks[gid]
+ // var junction = {
+ // _def: {defaults:{}},
+ // type: 'junction',
+ // z: RED.workspaces.active(),
+ // id: RED.nodes.id(),
+ // x: 0,
+ // y: 0,
+ // w: 0, h: 0,
+ // outputs: 1,
+ // inputs: 1,
+ // dirty: true
+ // }
+ // links = links.filter(function(l) { return !removedLinks.has(l) })
+ // if (links.length === 0) {
+ // return
+ // }
+ // links.forEach(function(l) {
+ // junction.x += l._sliceLocation.x
+ // junction.y += l._sliceLocation.y
+ // })
+ // junction.x = Math.round(junction.x/links.length)
+ // junction.y = Math.round(junction.y/links.length)
+ // if (snapGrid) {
+ // junction.x = (gridSize*Math.round(junction.x/gridSize));
+ // junction.y = (gridSize*Math.round(junction.y/gridSize));
+ // }
+ //
+ // var nodeGroups = new Set()
+ //
+ // RED.nodes.addJunction(junction)
+ // addedJunctions.push(junction)
+ // let newLink
+ // if (gid === links[0].source.id+":"+links[0].sourcePort) {
+ // newLink = {
+ // source: links[0].source,
+ // sourcePort: links[0].sourcePort,
+ // target: junction
+ // }
+ // } else {
+ // newLink = {
+ // source: junction,
+ // sourcePort: 0,
+ // target: links[0].target
+ // }
+ // }
+ // addedLinks.push(newLink)
+ // RED.nodes.addLink(newLink)
+ // links.forEach(function(l) {
+ // removedLinks.add(l)
+ // RED.nodes.removeLink(l)
+ // let newLink
+ // if (gid === l.target.id) {
+ // newLink = {
+ // source: l.source,
+ // sourcePort: l.sourcePort,
+ // target: junction
+ // }
+ // } else {
+ // newLink = {
+ // source: junction,
+ // sourcePort: 0,
+ // target: l.target
+ // }
+ // }
+ // addedLinks.push(newLink)
+ // RED.nodes.addLink(newLink)
+ // nodeGroups.add(l.source.g || "__NONE__")
+ // nodeGroups.add(l.target.g || "__NONE__")
+ // })
+ // if (nodeGroups.size === 1) {
+ // var group = nodeGroups.values().next().value
+ // if (group !== "__NONE__") {
+ // RED.group.addToGroup(RED.nodes.group(group), junction)
+ // }
+ // }
+ // })
+ // slicePath.remove();
+ // slicePath = null;
+ //
+ // if (addedJunctions.length > 0) {
+ // RED.history.push({
+ // t: 'add',
+ // links: addedLinks,
+ // junctions: addedJunctions,
+ // removedLinks: Array.from(removedLinks)
+ // })
+ // RED.nodes.dirty(true)
+ // }
+ // RED.view.redraw(true);
}
if (mouse_mode == RED.state.MOVING_ACTIVE) {
if (movingSet.length() > 0) {
diff --git a/packages/node_modules/@node-red/editor-client/src/sass/dropdownMenu.scss b/packages/node_modules/@node-red/editor-client/src/sass/dropdownMenu.scss
index 98ab3bd3b..4104fd83e 100644
--- a/packages/node_modules/@node-red/editor-client/src/sass/dropdownMenu.scss
+++ b/packages/node_modules/@node-red/editor-client/src/sass/dropdownMenu.scss
@@ -46,7 +46,7 @@
& > li > a,
& > li > a:focus {
display: block;
- padding: 4px 12px 4px 32px;
+ padding: 4px 20px 4px 12px;
clear: both;
font-weight: normal;
line-height: 20px;
@@ -54,7 +54,10 @@
white-space: normal !important;
outline: none;
}
-
+ & > li.pull-left > a,
+ & > li.pull-left > a:focus {
+ padding: 4px 12px 4px 32px;
+ }
& > .active > a,
& > .active > a:hover,
& > .active > a:focus {
@@ -145,8 +148,8 @@
position: relative;
& > .red-ui-menu-dropdown {
top: 0;
- left: 100%;
- margin-top: -6px;
+ left: calc(100% - 5px);
+ margin-top: 0;
margin-left: -1px;
}
&.open > .red-ui-menu-dropdown,
@@ -175,10 +178,10 @@
}
}
-.red-ui-menu-dropdown-submenu>a:after {
+.red-ui-menu-dropdown-submenu.pull-left>a:after {
display: none;
}
-.red-ui-menu-dropdown-submenu>a:before {
+.red-ui-menu-dropdown-submenu.pull-left>a:before {
display: block;
float: left;
width: 0;
@@ -192,7 +195,25 @@
border-width: 5px 5px 5px 0;
content: " ";
}
-
+.red-ui-menu-dropdown-direction-right {
+ .red-ui-menu-dropdown-submenu>a:after {
+ display: none;
+ }
+ .red-ui-menu-dropdown-submenu>a:before {
+ display: block;
+ float: right;
+ width: 0;
+ height: 0;
+ margin-top: 5px;
+ margin-right: -15px;
+ /* Caret Arrow */
+ border-color: transparent;
+ border-left-color: $menuCaret;
+ border-style: solid;
+ border-width: 5px 0 5px 5px;
+ content: " ";
+ }
+}
.red-ui-menu-dropdown-submenu.disabled > a:before {
border-right-color: $menuCaret;
}
From ad32677263c3219161f0382973df9be550f52f13 Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Thu, 16 Jun 2022 14:37:48 +0100
Subject: [PATCH 083/195] Fix lint errors in contextMenu
---
.../@node-red/editor-client/src/js/ui/contextMenu.js | 6 +++---
1 file changed, 3 insertions(+), 3 deletions(-)
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 1a0dee2bb..379ed5433 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
@@ -103,14 +103,14 @@ RED.contextMenu = (function() {
{ onselect: 'core:paste-from-internal-clipboard', label: RED._("keyboard.pasteNode"), disabled: !RED.view.clipboard() },
{ onselect: 'core:delete-selection', disabled: !canDelete },
{ onselect: 'core:show-export-dialog', label: RED._("menu.label.export") },
- { onselect: 'core:select-all-nodes' },
+ { onselect: 'core:select-all-nodes' }
)
if (hasSelection) {
menuItems.push(
null,
- isGroup
- ? { onselect: 'core:ungroup-selection', disabled: !isGroup }
+ isGroup ?
+ { onselect: 'core:ungroup-selection', disabled: !isGroup }
: { onselect: 'core:group-selection', disabled: !hasSelection }
)
if (canRemoveFromGroup) {
From 1780cb9b91a3ac0d954cf2f5ddb821f82f5535a4 Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Thu, 16 Jun 2022 14:47:11 +0100
Subject: [PATCH 084/195] Update dependencies
---
package.json | 12 ++++++------
1 file changed, 6 insertions(+), 6 deletions(-)
diff --git a/package.json b/package.json
index d22cf89dd..87518820e 100644
--- a/package.json
+++ b/package.json
@@ -49,7 +49,7 @@
"hash-sum": "2.0.0",
"hpagent": "1.0.0",
"https-proxy-agent": "5.0.1",
- "i18next": "21.8.2",
+ "i18next": "21.8.10",
"iconv-lite": "0.6.3",
"is-utf8": "0.2.1",
"js-yaml": "4.1.0",
@@ -62,7 +62,7 @@
"moment": "2.29.3",
"moment-timezone": "0.5.34",
"mqtt": "4.3.7",
- "multer": "1.4.4",
+ "multer": "1.4.5-lts.1",
"mustache": "4.2.0",
"node-red-admin": "^3.0.0",
"node-watch": "0.7.3",
@@ -76,7 +76,7 @@
"semver": "7.3.7",
"tar": "6.1.11",
"tough-cookie": "4.0.0",
- "uglify-js": "3.15.5",
+ "uglify-js": "3.16.0",
"uuid": "8.3.2",
"ws": "7.5.6",
"xml2js": "0.4.23"
@@ -105,16 +105,16 @@
"grunt-sass": "~3.1.0",
"grunt-simple-mocha": "~0.4.1",
"grunt-simple-nyc": "^3.0.1",
- "i18next-http-backend": "1.4.0",
+ "i18next-http-backend": "1.4.1",
"jquery-i18next": "1.2.1",
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
- "marked": "4.0.15",
+ "marked": "4.0.17",
"minami": "1.2.3",
"mocha": "9.2.2",
"node-red-node-test-helper": "^0.2.7",
"nodemon": "2.0.16",
"proxy": "^1.0.2",
- "sass": "1.51.0",
+ "sass": "1.52.3",
"should": "13.2.3",
"sinon": "11.1.2",
"stoppable": "^1.1.0",
From 16644284296faf6aea7108533cf430bde41c42f2 Mon Sep 17 00:00:00 2001
From: Nick O'Leary
Date: Thu, 16 Jun 2022 15:37:07 +0100
Subject: [PATCH 085/195] Update tour for 3.0-beta.3
---
.../src/tours/images/context-menu.png | Bin 0 -> 67976 bytes
.../editor-client/src/tours/welcome.js | 35 ++++++++++++------
2 files changed, 24 insertions(+), 11 deletions(-)
create mode 100644 packages/node_modules/@node-red/editor-client/src/tours/images/context-menu.png
diff --git a/packages/node_modules/@node-red/editor-client/src/tours/images/context-menu.png b/packages/node_modules/@node-red/editor-client/src/tours/images/context-menu.png
new file mode 100644
index 0000000000000000000000000000000000000000..1acaab48b867480c8927079552f7e9431374573d
GIT binary patch
literal 67976
zcmeFZWmH^E*Cvbw3GN!)-Q6XPlRy$65F|Lk-6gm?1cwkHBm@uc?j9s~BaHgIISIaRfHZM&}Oh!^T0%%@~e;o#sfl@#SQ;ouPGfEOz&0&wLo
zo*zH(2Jfs1l7%Z9rPu-fu`$z8GFMZBV+B5=!Xd$v!99UC0bY{u0XN6!mJPh2IVkEn!@&_TKwt1m
zn)F9-a0pMWUg@~#sHuvY*xPa%o7%rO+M2l-Q+wFj*g1=ONYKJs
zhytIXm$_)EVNF~k3O-(KCWNI#|DgXSR?!bQ%w3aR|
z4x(IK?(XiK?tGl~P8M7|A|fJO+`L@8yc|Fa4rfn07h?|&J7>DboBVqpc{67dCo2aR
zD|?JQ8!jGBZm$2So0*5z|D_xB
zo5yajc|AT(9C|ZRO*3bE8&~M4UfWr@Nb-uqp7H;^{NF)}L+>T}!pg(UMn~St*38Zs
z=qf29%rDOMKYsH+_SF4vPhlSJ|Gnq`_RT*%#kruX^}ns&qiA4P0oh1C73cbooF$)*
zbsS2@4^c+Kfl$F6sPIS`=66&irnBDdWlhsuEFFUyrr
z?;?w8q_{njuZ>TgPikYb{?VJOilf0@<>9b}?pc|I+l6hquh|9po!@spi&2i#KMP_O
zqgmb-%NYV6X7)bl{j?_BB;wSc)84s9pSOG1_hMmz7+9X$vqA3X&owniTgG=+-i+Q=
z?-hQ@^3MO&_9N@YVpe5<2O{1^{N}f^Gy-0H01`blJes03!U)bdu6=01PvGN!uI4cz
zh=L{7CUyRM>HjtS?^^u-yF90F%Jk>8;A0pb<@YGGzz#GLT&k>mf&W8{76_*^rMgqj
z`2z^w-~0eSgrF1u)owo2tX&Xl%y~N4z@+a>KGb0EB0-q!tWke0nCiT;?ZwIr$#FQh
zWrws*oWF7y79qzy+$mQuf$GY?3c@cZ4QeKhouP$k&_5%{LER3&2v+%j4blGJ^8BkR
zf&a5o7|HPc;@2JmteL1b5wcc>YuT5$g4zX?8p+8125d`Tf&^!(@oQ#Y%q+-A<}9d>
z{ZY}X1KU+a!Hy9bm<0Plfc**-QEm@(iS=`I(*sl!4#~V7_o8aeFbDcoK3>0K^YKZ(
zQ>_zJa}n`ANrLnryxYqM!BBnmVu(j9r}Qk}u1NzdAvY#cQ5WtQn+z31i;Fy?u{Cbc
zoArH@#M =0K2h=@!%H_&AY_?2KO6k^+5hHBuwRE1t|r
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≧h`;Ao2cW=E&fS`~X;_=(6n8!UyaT&;l
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