Compare commits

..

95 Commits

Author SHA1 Message Date
Nick O'Leary
2350540a98 Introduce RED.utils.createSVGElement 2022-08-07 22:28:08 +01:00
Nick O'Leary
c021c4020e Add RED.utils.domSelection module 2022-08-07 22:27:29 +01:00
Nick O'Leary
11a6925ae4 Remove almost all d3 from palette.js 2022-08-05 23:08:09 +01:00
Nick O'Leary
24ff5262d9 Remove d3 from radialMenu 2022-08-05 23:07:39 +01:00
Nick O'Leary
c24d7fafa9 Remove d3 from keyboard.js 2022-08-05 21:19:45 +01:00
Nick O'Leary
30ea300f65 Merge pull request #3769 from node-red/310
Bump dev to 3.1.0-beta.0
2022-07-14 21:16:38 +01:00
Nick O'Leary
04f4d5274d Bump dev to 3.1.0-beta.0 2022-07-14 20:58:25 +01:00
Nick O'Leary
1f9695abd7 Merge pull request #3768 from node-red/master
Get `dev` branch up to date with `master`
2022-07-14 20:56:42 +01:00
Nick O'Leary
1b94cc3ac0 Merge pull request #3764 from node-red/300
Node-RED 3.0 release
2022-07-14 09:49:05 +01:00
Nick O'Leary
4698d5d2fc Update dependencies 2022-07-14 09:31:10 +01:00
Nick O'Leary
92bc9d81c5 Update changelog 2022-07-14 09:27:57 +01:00
Nick O'Leary
952cfaec14 Merge pull request #3766 from Steve-Mcl/fix-split-with
Fix "split with" on virtual links
2022-07-14 09:26:05 +01:00
Nick O'Leary
637c44aa59 Merge pull request #3767 from Steve-Mcl/use-theme-page-and-header-values
Use theme page and header values if settings.js values are not present
2022-07-14 09:20:44 +01:00
Steve-Mcl
6e5fc29dca show add junction when nodes are selected 2022-07-13 22:34:22 +01:00
Steve-Mcl
8bd02d0c36 update header url if set in theme and not settings 2022-07-13 20:36:27 +01:00
Steve-Mcl
c6cfbb8755 use page&theme settings in a theme plugin 2022-07-13 20:16:34 +01:00
Steve-Mcl
75d3444391 Ensure added junc(s) are selected
Feature parity with insert node, insert links etc
2022-07-13 12:43:58 +01:00
Steve-Mcl
c648e1e8d6 fix context menu insert junc/links enabled state 2022-07-13 12:42:55 +01:00
Steve-Mcl
e2f42fddb5 Ensire only wire links are split with junctions/links 2022-07-13 12:19:05 +01:00
Nick O'Leary
f93fe684c0 Update changelog 2022-07-12 21:26:16 +01:00
Nick O'Leary
ee378ea0c4 Update version to 3.0 2022-07-12 21:18:49 +01:00
Nick O'Leary
613d34e6e6 Update tourGuide for 3.0 2022-07-12 21:12:31 +01:00
Nick O'Leary
4c784af55d Update dependencies 2022-07-12 21:12:00 +01:00
Nick O'Leary
b28595c814 Merge pull request #3759 from kazuhitoyokoi/master-fixundo
Focus editor for undo after some actions in menu
2022-07-12 13:18:55 +01:00
Nick O'Leary
fca7beec01 Merge pull request #3763 from node-red/pr_3756
Ensure node icon shade has properly rounded corners
2022-07-12 13:18:22 +01:00
Stephen McLaughlin
f813f03a46 Merge pull request #3762 from node-red/sf-creds-fix
Fix storing subflow credential type when input has multiple types
2022-07-12 10:21:20 +01:00
Nick O'Leary
6ff2232df3 Ensure node icon shade has properly rounded corners 2022-07-12 09:27:45 +01:00
Nick O'Leary
e3b1f058cd Merge pull request #3752 from Steve-Mcl/fix-global-path-popover
Ensure global-config and flow-config have info in the hierarchy popover
2022-07-11 20:28:58 +01:00
Nick O'Leary
542e9cacc2 Merge pull request #3751 from Steve-Mcl/fix-linkcall-registry
Fix linkcall registry bugs
2022-07-11 20:27:08 +01:00
Nick O'Leary
0a0a7ca39b Fix storing subflow credential type when input has multiple types
Fixes #3749
2022-07-11 20:19:48 +01:00
Kazuhito Yokoi
cee287da99 Focus editor for undo after some actions in menu 2022-07-12 02:09:20 +09:00
Stephen McLaughlin
c8e4df94f9 Merge pull request #3754 from braincube-io/fix-change-context
Fix change node, not handling from field properly when using context
2022-07-11 17:26:30 +01:00
Kazuhito Yokoi
c86e4f52a0 Fix shade for node icon to be rounded rectangle 2022-07-12 00:10:51 +09:00
Steve-Mcl
44216310ca Ensure global/config and flow/config have info
fixes #3750
2022-07-11 13:09:49 +01:00
Steve-Mcl
5c69599e78 Apply linting suggestions to the registry enclosure 2022-07-11 10:28:31 +01:00
Steve-Mcl
e4098d3991 fix undecalred variable access 2022-07-11 10:28:17 +01:00
Steve-Mcl
55a94d659b fix const reassignment 2022-07-11 10:27:30 +01:00
Franck Mourre
7a048d5b32 Fix change node, not handling from field properly when using context 2022-07-11 10:51:31 +02:00
Nick O'Leary
e14dd06a94 Merge pull request #3748 from Steve-Mcl/fix-add-junc-undo
include dirty state in history event
2022-07-08 17:07:27 +01:00
Nick O'Leary
62332a2b56 Merge pull request #3746 from node-red/pr_3744
Fix display direction of context sub-menu
2022-07-08 17:07:03 +01:00
Steve-Mcl
639030924f include dirty state in history event 2022-07-08 14:09:54 +01:00
Nick O'Leary
241b47fe19 Merge branch 'master' into pr_3744 2022-07-08 13:08:26 +01:00
Nick O'Leary
69beecf334 Fix menu padding for pull-left submenus 2022-07-08 13:06:05 +01:00
Nick O'Leary
e308e02f9d Merge pull request #3745 from node-red-hitachi/fix-debug-path-menu
Fix clear pinned paths of debug sidebar menu
2022-07-08 08:53:24 +01:00
Nick O'Leary
87258e485a Merge pull request #3742 from Steve-Mcl/fix-tooltip-exception
prevent exception generating tooltip for deleted nodes
2022-07-08 08:23:56 +01:00
Nick O'Leary
0682c346ea Merge pull request #3741 from Steve-Mcl/fix-context-menu
Fix context menu issues ready for v3 beta.5
2022-07-08 08:23:02 +01:00
Hiroyasu Nishiyama
5ae566952b do not show clear pinned if not available 2022-07-08 13:10:21 +09:00
Hiroyasu Nishiyama
18f9ab0cda make left sub-menu caret fit within context menu 2022-07-07 20:23:27 +09:00
Hiroyasu Nishiyama
bd4a5ac844 fixed menu width and window width 2022-07-07 19:39:28 +09:00
Hiroyasu Nishiyama
257b1f89f3 fix display direction of context sub-menu 2022-07-07 16:49:13 +09:00
Steve-Mcl
962672564e prevent exception generating tooltip for deleted nodes 2022-07-06 15:17:58 +01:00
Steve-Mcl
7216c6d62a code linting and remove excessive new lines 2022-07-06 13:08:56 +01:00
Steve-Mcl
21d3261eec Allow editor events to close context menu 2022-07-06 13:05:57 +01:00
Steve-Mcl
03f758720c Allow escape key to close context menu 2022-07-06 13:05:18 +01:00
Steve-Mcl
eaa85ae8d5 Fix insert=>link nodes enable/disable state 2022-07-06 12:54:22 +01:00
Stephen McLaughlin
8cb212d897 Merge pull request #3729 from node-red/cut-vs-copy
Do not generate new node-ids when pasting a cut flow
2022-07-06 10:36:14 +01:00
Stephen McLaughlin
a38d3981df Merge pull request #3731 from node-red-hitachi/fix-node-move
Fix to prevent node from moving out of workspace
2022-07-06 10:35:54 +01:00
Stephen McLaughlin
af08c077d2 Merge pull request #3736 from bonanitech/disabled-config-node-background
Don't let themes change disabled config node background color
2022-07-06 10:34:20 +01:00
Stephen McLaughlin
84e2489585 Merge pull request #3737 from bonanitech/pr3692-leftovers
Move colors left behind in #3692 to CSS variables
2022-07-06 10:33:59 +01:00
Mauricio Bonani
744375bd5d Don't let themes change config node label colors 2022-07-05 07:33:31 -04:00
Hiroyasu Nishiyama
6c1f63bfbb introduce RED.view.dimensions for workspace dimensions 2022-07-05 09:02:21 +09:00
Mauricio Bonani
7d0267c924 Move colors left behind in #3692 to CSS variables 2022-07-04 18:38:45 -04:00
Mauricio Bonani
daa9cb65e5 Change disabled config node background color variable 2022-07-04 17:17:40 -04:00
Nick O'Leary
7072265225 Merge pull request #3734 from node-red-hitachi/fix-close-websocket
Fix close timeout of websocket node
2022-07-04 21:02:20 +01:00
Nick O'Leary
8daade0021 Merge pull request #3733 from node-red-hitachi/fix-debug-message-handling
fix handling of global debug message
2022-07-04 21:01:35 +01:00
Nick O'Leary
b4d30b462f Merge pull request #3730 from ralphwetzel/master
Fix label overflow @ config-node palette
2022-07-04 20:52:04 +01:00
Nick O'Leary
18acd67b4f Merge pull request #3728 from node-red/fix-credential-clear
Do not remove unknown credentials of Subflow Modules
2022-07-04 20:47:04 +01:00
Nick O'Leary
78ed53f4fb Ensure a second paste of cut nodes is treated as a copy-paste 2022-07-04 20:46:21 +01:00
Nick O'Leary
d95314c754 Update packages/node_modules/@node-red/runtime/lib/nodes/credentials.js 2022-07-04 20:21:25 +01:00
Hiroyasu Nishiyama
277cc19ec3 call done after close handler 2022-07-04 11:23:47 +09:00
Hiroyasu Nishiyama
67f4553213 fix handling of global debug message 2022-07-04 10:45:20 +09:00
Nick O'Leary
b2bb656d30 Merge pull request #3732 from node-red/fix-monaco-default
Fix defaulting to monaco if settings does not contain codeEditor
2022-07-03 20:55:16 +01:00
Nick O'Leary
ca20f41d0e Update theme tests to ensure monaco is loaded 2022-07-03 20:37:55 +01:00
Nick O'Leary
13e8aeae4e Fix defaulting to monaco if settings does not contain codeEditor 2022-07-03 20:22:19 +01:00
Hiroyasu Nishiyama
02308f9e2f prevennt node from moving out of workspace 2022-07-03 20:39:54 +09:00
ralphwetzel
0fdcbb4611 Fix label overflow @ config-node palette 2022-07-02 09:52:14 +02:00
Nick O'Leary
829ccc3466 Do not generate new node-ids when pasting a cut flow
Fixes #3629
2022-07-01 17:48:14 +01:00
Nick O'Leary
9ac83cf62e Do not remove unknown credentials of Subflow Modules
Fixes #3641
2022-07-01 17:34:16 +01:00
Nick O'Leary
f760354e82 Merge pull request #3700 from ralphwetzel/master
Disable keyboard shortcut mapping when showing Edit[..]Dialog
2022-07-01 12:23:49 +01:00
Nick O'Leary
e91e35d508 Merge pull request #3721 from node-red/update-changlog
Add missing entries from beta.4 changelog
2022-07-01 12:22:09 +01:00
Nick O'Leary
db7e196bf8 Merge pull request #3727 from node-red/rh-click-link-actions
Update add-junction menu to work in more cases
2022-07-01 12:22:00 +01:00
Nick O'Leary
f5fe4f99f1 Merge pull request #3723 from Steve-Mcl/fix-import
Ensure importMap is not null when using import UI
2022-07-01 12:21:37 +01:00
Nick O'Leary
e2bff36395 Merge pull request #3724 from kazuhitoyokoi/master-addjpn
Add Japanese translations for v3.0-beta.4
2022-07-01 10:40:26 +01:00
Nick O'Leary
0a5d7c2100 Update add-junction menu to work in more cases 2022-07-01 10:31:50 +01:00
ralphwetzel
4d42f8ec58 Global variable definition in for loop: Fixed 2022-06-30 22:08:58 +02:00
ralphwetzel
81e7b052da Merge branch 'master' of https://github.com/ralphwetzel/node-red 2022-06-30 21:55:25 +02:00
ralphwetzel
be44b7e2c7 Merge branch 'node-red:master' into master 2022-06-30 21:54:18 +02:00
ralphwetzel
d8a781632c Re-order shortcut keymap 2022-06-30 21:52:52 +02:00
ralphwetzel
3726d6fe3b Finetune keyboard shortcut management 2022-06-30 21:52:16 +02:00
ralphwetzel
6090a5b274 Revert disable/enable logic proposed before 2022-06-30 21:51:51 +02:00
Kazuhito Yokoi
d4fdf6be67 Add Japanese translations for v3.0-beta.4 2022-07-01 01:09:06 +09:00
Steve-Mcl
1b6cbe5c23 Ensure importMap is not null when using import UI
fixes #3722
2022-06-30 15:17:49 +01:00
Nick O'Leary
1d130a7857 Add missing entries from beta.4 changelog 2022-06-30 10:14:51 +01:00
ralphwetzel
d81523370e Merge branch 'node-red:master' into master 2022-06-22 19:58:49 +02:00
ralphwetzel
6939546f22 Disable keyboard shortcut mapping when showing Edit[..]Dialog 2022-06-22 19:58:02 +02:00
47 changed files with 853 additions and 1072 deletions

View File

@@ -1,7 +1,46 @@
#### 3.0.0: Milestone Release
Editor
- Use theme page and header values if settings.js values are not present (#3767) @Steve-Mcl
- Focus editor for undo after some actions in menu (#3759) @kazuhitoyokoi
- Ensure node icon shade has properly rounded corners (#3763) @knolleary
- Fix storing subflow credential type when input has multiple types (#3762) @knolleary
- Ensure global-config and flow-config have info in the hierarchy popover (#3752) @Steve-Mcl
- Include dirty state in history event (#3748) @Steve-Mcl
- Fix display direction of context sub-menu (#3746) @knolleary
- Fix clear pinned paths of debug sidebar menu (#3745) @HiroyasuNishiyama
- prevent exception generating tooltip for deleted nodes (#3742) @Steve-Mcl
- Fix context menu issues ready for v3 beta.5 (#3741) @Steve-Mcl
- Do not generate new node-ids when pasting a cut flow (#3729) @knolleary
- Fix to prevent node from moving out of workspace (#3731) @HiroyasuNishiyama
- Don't let themes change disabled config node background color (#3736) @bonanitech
- Move colors left behind in #3692 to CSS variables (#3737) @bonanitech
- Fix handling of global debug message (#3733) @HiroyasuNishiyama
- Fix label overflow @ config-node palette (#3730) @ralphwetzel
- Fix defaulting to monaco if settings does not contain codeEditor (#3732) @knolleary
- Disable keyboard shortcut mapping when showing Edit[..]Dialog (#3700) @ralphwetzel
- Update add-junction menu to work in more cases (#3727) @knolleary
- Ensure importMap is not null when using import UI (#3723) @Steve-Mcl
- Add Japanese translations for v3.0-beta.4 (#3724) @kazuhitoyokoi
- Fix "split with" on virtual links (#3766) @Steve-Mcl
Runtime
- Do not remove unknown credentials of Subflow Modules (#3728) @knolleary
- Add missing entries from beta.4 changelog (#3721) @knolleary
Nodes
- Change: Fix change node, not handling from field properly when using context (#3754) @Fadoli
- Link Call: Fix linkcall registry bugs (#3751) @Steve-Mcl
- WebSocket: Fix close timeout of websocket node (#3734) @HiroyasuNishiyama
#### 3.0.0-beta.4: Beta Release #### 3.0.0-beta.4: Beta Release
Editor Editor
- Move all colours to CSS variables (#3692) @bonanitech
- Fix clicking on node in workspace to hide context menu (#3696) @knolleary - Fix clicking on node in workspace to hide context menu (#3696) @knolleary
- Fix credential type input item of subflow template (#3703) @HiroyasuNishiyama - Fix credential type input item of subflow template (#3703) @HiroyasuNishiyama
- Add option flag `reimport` to `importNodes` (#3718) @Steve-Mcl - Add option flag `reimport` to `importNodes` (#3718) @Steve-Mcl
@@ -22,6 +61,7 @@ Editor
Runtime Runtime
- Allow flows to be stopped and started manually (#3719) @knolleary
- Import default export if node is a transpiled es module (#3669) @dschmidt - Import default export if node is a transpiled es module (#3669) @dschmidt
- Leave Monaco theme commented out by default (#3704) @bonanitech - Leave Monaco theme commented out by default (#3704) @bonanitech
@@ -183,528 +223,6 @@ Nodes
- Watch: Update Watch node to use node-watch module (#3559 #3569) @knolleary - Watch: Update Watch node to use node-watch module (#3559 #3569) @knolleary
- WebSocket: call done after ws disconnects (#3531) @Steve-Mcl - WebSocket: call done after ws disconnects (#3531) @Steve-Mcl
#### 2.2.2: Maintenance Release
Nodes
- Fix "close timed out" error when performing full deploy or modifying broker node. (#3451) @Steve-Mcl
#### 2.2.1: Maintenance Release
Editor
- Handle mixed-cased filter terms in keyboard shortcut dialog (#3444) @knolleary
- Prevent duplicate links being added between nodes (#3442) @knolleary
- Fix to hide tooltip after removing subflow tab (#3391) @HiroyasuNishiyama
- Fix node validation to be applied to config node (#3397) @HiroyasuNishiyama
- Fix: Dont add wires to undo buffer twice (#3437) @Steve-Mcl
Runtime
- Improve module location parsing (of stack info) when adding hook (#3447) @Steve-Mcl
- Fix substitution of NR_NODE_PATH (#3445) @HiroyasuNishiyama
- Remove console.log when ignoring disabled module (#3439) @knolleary
- Improve "Unexpected Node Error" logging (#3446) @Steve-Mcl
Nodes
- Debug: Fix no-prototype-builtins bug in debug node and utils (#3394) @Alkarex
- Delay: Fix Japanese message of delay node (#3434)
- Allow nbRateUnits to be undefined when validating (#3443) @knolleary
- Coding help for recently added node-red Predefined Environment Variables (#3440) @Steve-Mcl
#### 2.2.0: Milestone Release
Editor
- Add editorTheme.tours property to default settings file (#3375) @knolleary
- Remember Zoom level and Sidebar tab selection between sessions (#3361) @knolleary
- Fix timing issue when merging background changes fixes #3364 (#3373) @Steve-Mcl
- Use a nodes palette label in help tree (#3372) @Steve-Mcl
- Subflow: Add labels to OUTPUT nodes (#3352) @ralphwetzel
- Fix vertical align subflow port (#3370) @knolleary
- Make actions list i18n ready and Japanese translation (#3359) @HiroyasuNishiyama
- Update tour for 2.2.0 (#3378) @knolleary
- Include paletteLabel when building search index (#3380) @Steve-Mcl
- Fix opening/closing subflow template not to make subflow changed (#3382) @HiroyasuNishiyama
- Add Japanese translations for v2.2.0 (#3353, #3381) @kazuhitoyokoi
Runtime
- Add support for accessing node id & name as environment variable (#3356) @HiroyasuNishiyama
- Clear context contents when switching projects (#3243) @knolleary
Nodes
- MQTT: reject invalid topics (#3374) @Steve-Mcl
- Function: Expose node.path property (#3371) @knolleary
- Function: Update `node` declarations in func.d.ts (#3377) @Steve-Mcl
#### 2.2.0-beta.1: Beta Release
Editor
- Add search history to main search box (#3262) @knolleary
- Check availability of type of config node on deploy (#3304) @k-toumura
- Add wire-slice mode to delete wires with Ctrl-RHClick-Drag (#3340) @knolleary
- Wiring keyboard shortcuts (#3288) @knolleary
- Snap nodes on grid using either edge as reference (#3289) @knolleary
- Detach node action (#3338) @knolleary
- Highlight links when selecting nodes (#3323) @knolleary
- Allow multiple links to be selected by ctrl-click (#3294) @knolleary
Nodes
- JSON: Let JSON node attempt to parse buffer if it contains a valid string (#3296) @dceejay
- Remove use of verbose flag in core nodes - and use node.debug level instead (#3300) @dceejay
- TCP: Add TLS option to tcp client nodes (#3307) @dceejay
- WebSocket: Implemented support for Websocket Subprotocols in WS Client Node. (#3333) @tobiasoort
#### 2.1.6: Maintenance Release
Editor
- Revert copy-text change and apply alternative fix (#3363) @knolleary
- Update marked to latest (#3362) @knolleary
- fix to make start of property error tooltip messages aligned (#3358) @HiroyasuNishiyama
Nodes
- Inject: fix JSON propety validation of inject node (#3349) @HiroyasuNishiyama
- Delay: fix unit value validation of delay node (#3351) @HiroyasuNishiyama
#### 2.1.5: Maintenance Release
Runtime
- Handle reporting error location when stack is truncated (#3346) @knolleary
- Initialize passport when only adminAuth.tokens is set (#3343) @knolleary
- Add log logging (#3342) @knolleary
Editor
- Fix copy buttons on the debug window (another method) (#3331) @kazuhitoyokoi
- Add Japanese translations for hidden flow (#3302) @kazuhitoyokoi
- Improve jsonata legacy mode detection regex (#3345) @knolleary
- Fix generating flow name with incrementing number (#3347) @knolleary
- resume focus after import/export dialog close (#3337) @HiroyasuNishiyama
- Fix findPreviousVisibleTab action (#3321) @knolleary
- Fix storing hidden tab state when not hidden via action (#3312) @knolleary
- Avoid adding empty env properties to tabs/groups (#3311) @knolleary
- Fix hide icon in tour guide (#3301) @kazuhitoyokoi
Nodes
- File: Update file node examples according to node name change (#3335) @HiroyasuNishiyama
- Filter (RBE): Fix for filter node narrrowbandEq mode start condition failure (#3339) @dceejay
- Function: Prevent function scrollbar from obscuring expand button (#3348) @knolleary
- Function: load extralibs when expanding monaco. fixes #3319 (#3334) @Steve-Mcl
- Function: Update Function to use correct api to access env vars (#3310) @knolleary
- HTTP Request: Fix basic auth with empty username or password (#3325) @hardillb
- Inject: Fix incorrect clearing of blank payload property in Inject node (#3322) @knolleary
- Link Call: add link call example (#3336) @HiroyasuNishiyama
- WebSocket: Only setup ws client heartbeat once it is connected (#3344) @knolleary
- Update Japanese translations in node help (#3332) @kazuhitoyokoi
#### 2.1.4: Maintenance Release
Runtime
- fix env var access using $parent for groups (#3278) @HiroyasuNishiyama
- Add proper error handling for 404 errors when serving debug files (#3277) @knolleary
- Add Japanese translations for Node-RED v2.1.0-beta.1 (#3179) @kazuhitoyokoi
- Include full user object on login audit events (#3269) @knolleary
- Remove styling from de locale files (#3237) @knolleary
Editor
- Change tab hide button icon to an eye and add search option (#3282) @knolleary
- Fix i18n handling of namespaces with spaces in (#3281) @knolleary
- Trigger change event when autoComplete fills in input (#3280) @knolleary
- Apply CN i18n fix (#3279) @knolleary
- fix select menu label of config node to use paletteLabel (#3273) @HiroyasuNishiyama
- fix removed tab not to cause node conflict (#3275) @HiroyasuNishiyama
- Group diff fix (#3239) @knolleary
- Only toggle disabled workspace flag if on activeWorkspace (#3252) @knolleary
- Do not show status for disabled nodes (#3253) @knolleary
- Set dimension value for tour guide (#3265) @kazuhitoyokoi
- Avoid redundant initialisation of TypedInput type (#3263) @knolleary
- Don't let themes change flow port label color (#3270) @bonanitech
- Fix treeList gutter calculation to handle floating gutters (#3238) @knolleary
Nodes
- Debug: Handle RegExp types in Debug sidebar (#3251) @knolleary
- Delay: fix 2nd output when in rate limit per topic modes (#3261) @dceejay
- Link: fix to show link target when selected (#3267) @HiroyasuNishiyama
- Inject: Do not modify inject node props in oneditprepare (#3242) @knolleary
- HTTP Request: HTTP Basic Auth should always add : between username and password even if empty (#3236) @hardillb
#### 2.1.3: Maintenance Release
Runtime
- Update gen-publish script to update 'next' tag for main releases
- Add environment variable to enable/disable tours (#3221) @hardillb
- Fix loading non-default language files leaving runtime in wrong locale (#3225) @knolleary
Editor
- Refresh editor settings whenever a node is added or enabled (#3227) @knolleary
- Revert spinner css change that made it shrink in some cases (#3229) @knolleary
- Fix import notification message when importing config nodes (#3224) @knolleary
- Handle changing types of TypedInput repeatedly (#3223) @knolleary
#### 2.1.2: Maintenance Release
Runtime
- node-red-pi: Remove bash dependency (#3216) @a16bitsysop
Editor
- Improved regex for markdown renderer (#3213) @GerwinvBeek
- Fix TypedInput initialisation (#3220) @knolleary
Nodes
- MQTT: fix datatype in node config not used. fixes #3215 (#3219) @Steve-Mcl
#### 2.1.1: Maintenance Release
Editor
- Ensure tourGuide popover doesn't fall offscreen (#3212) @knolleary
- Fix issue with old inject nodes that migrated topic to 'string' type (#3210) @knolleary
- Add cache-busting query params to index.mst (#3211) @knolleary
- Fix TypedInput validation of type without options (#3207) @knolleary
#### 2.1.0: Milestone Release
Editor
- Position popover properly on a scrolled page
- Fixes from 2.1.0-beta.2 (#3202) @knolleary
Nodes
- Link Out: Fix saving link out node links (#3201) @knolleary
- Switch: Refix #3170 - copy switch rule type when adding new rule
- TCP Request: Add string option to TCP request node output (#3204) @dceejay
#### 2.1.0-beta.2: Beta Release
Editor
- Fix switching projects (#3199) @knolleary
- Use locale setting when installing/enabling node (#3198) @knolleary
- Do not show projects-wecome dialog until welcome tour completes (#3197) @knolleary
- Fix converting selection to subflow (#3196) @knolleary
- Avoid conflicts with native browser cmd-ctrl type shortcuts (#3195) @knolleary
- Ensure message tools stay attached to top-level entry in Debug/Context (#3186) @knolleary
- Ensure tab state updates properly when toggling enable state (#3175) @knolleary
- Improve handling of long labels in TreeList (#3176) @knolleary
- Shift-click tab scroll arrows to jump to start/end (#3177) @knolleary
Runtime
- Update package dependencies
- Update to latest node-red-admin
Nodes
- Dynamic MQTT connections (#3189)
- Link: Filter out Link Out Return nodes in Link In edit dialog Fixes #3187
- Link: Fix link call label (#3200) @knolleary
- Debug: Redesign debug filter options and make them persistant (#3183) @knolleary
- Inject: Widen Inject interval box for >1 digit (#3184) @knolleary
- Switch: Fix rule focus when switch 'otherwise' rule is used (#3185) @knolleary
#### 2.1.0-beta.1: Beta Release
Editor
- Add Tour Guide component (#3136) @knolleary
- Allow tabs to be hidden (#3120) @knolleary
- Add align actions to editor (#3110) @knolleary
- Add support of environment variable for tab & group (#3112) @HiroyasuNishiyama
- Add autoComplete widget and add to TypedInput for msg. props (#3171) @knolleary
- Render node documentation to node-red style guide when written in markdown. (#3169) @Steve-Mcl
- Allow colouring of tab icon svg (#3140) @harmonic7
- Restore tab selection after merging conflicts (#3151) @GerwinvBeek
- Fix serving of theme files on Windows (#3154) @knolleary
- Ensure config-node select inherits width properly from input (#3155) @knolleary
- Do better remembering TypedInput values whilst switching types (#3159) @knolleary
- Update monaco to 0.28.1 (#3153) @knolleary
- Improve themeing of tourGuide (#3161) @knolleary
- Allow a node to specify a filter for the config nodes it can pick from (#3160) @knolleary
- Allow RED.notify.update to modify any notification setting (#3163) @knolleary
- Fix typo in ko editor.json Fixes #3119
- Improve RED.actions api to ensure actions cannot be overridden
- Ensure treeList row has suitable min-height when no content Fixes #3109
- Refactor edit dialogs to use separate edit panes
- Ensure type select button is not focussable when TypedInput only has one type
- Place close tab link in front of fade
Runtime
- Improve error reporting with oauth login strategies (#3148) @knolleary
- Add allowUpdate feature to externalModules.palette (#3143) @knolleary
- Improve node install error reporting (#3158) @knolleary
- Improve unit test coverage (#3168) @knolleary
- Allow coreNodesDir to be set to false (#3149) @hardillb
- Update package dependencies
- uncaughtException debug improvements (#3146) @renatojuniorrs
Nodes
- Change: Add option to deep-clone properties in Change node (#3156) @knolleary
- Delay: Add push to front of rate limit queue. (#3069) @dceejay
- File: Add paletteLabel to file nodes to make read/write more obvious (#3157) @knolleary
- HTTP Request: Extend HTTP request node to log detailed timing information (#3116) @k-toumura
- HTTP Response: Fix sizing of HTTP Response header fields (#3164) @knolleary
- Join: Support for msg.restartTimeout (#3121) @magma1447
- Link Call: Add Link Call node (#3152) @knolleary
- Switch: Copy previous rule type when adding rule to switch node (#3170) @knolleary
- Delay node: add option to send intermediate messages on separate output (#3166) @knolleary
- Typo in http request set method translation (#3173) @mailsvb
#### 2.0.6: Maintenance Release
Editor
- Fix typo in ko editor.json Fixes #3119
- Change fade color when hovering an inactive tab (#3106) @bonanitech
- Ensure treeList row has suitable min-height when no content Fixes #3109
Runtime
- Update tar to latest (#3128) @aksswami
- Give passport verify callback the same arity as the original callback (#3117) @dschmidt
- Handle HTTPS Key and certificate as string or buffer (#3115) @bartbutenaers
#### 2.0.5: Maintenance Release
Editor
- Remove default ctrl-enter keybinding from monaco editor Fixes #3093
Runtime
- Update tar dependency
- Add support for maintenance streams in generate-publish-script
Nodes
- Fix regression in Join node when manual joining array with msg.parts present Fixes #3096
#### 2.0.4: Maintenance Release
Editor
- Fix tab fade CSS for when using themes (#3085) @bonanitech
- Handle just-copied-but-not-deployed node with credentials in editor Fixes #3090
Nodes
- Filter: Fix RBE node handling of default topi property Fixes #3087
- HTTP Request: Handle partially encoded url query strings in request node
- HTTP Request: Fix support for supplied CA certs (#3089) @hardillb
- HTTP Request: Ensure TLS Cert is used (#3092) @hardillb
- Inject: Fix inject now button unable to send empty props
- Inject: Inject now button success notification should use label with updated props
#### 2.0.3: Maintenance Release
Nodes
- HTML: Fix HTML parsing when body is included in the select tag Fixes #3079
- HTTP Request: Preserve case of user-provided http headers in request node Fixes #3081
- HTTP Request: Set decompress to false for HTTP Request to keep 1.x compatibility Fixes #3083
- HTTP Request: Add unit tests for HTTP Request encodeURI and error response
- HTTP Request: Do not throw HTTP errors in request node Fixes #3082
- HTTP Request: Ensure uri is properly encoded before passing to got module Fixes #3080
#### 2.0.2: Maintenance Release
Runtime
- Use file:// url with dynamic import
- Detect if agent-base has patched https.request and undo it Fixes #3072
Editor
- Fix tab fade css because Safari Fixes #3073
- Fix error closing library dialog with monaco
- Handle other error types in Manage Palette view
Nodes
- HTTP Request node - ignore invalid cookies rather than fail request Fixes #3075
- Fix msg.reset handling in Delay node Fixes #3074
#### 2.0.1: Maintenance Release
Nodes
- Function: Ensure default module export is exposed in Function node
#### 2.0.0: Milestone Release
**Migration from 1.x**
- Node-RED now requires Node.js 12.x or later.
- The following nodes have had significant dependency updates. Unless stated,
they should be fully backward compatible.
- RBE: Relabelled as 'filter' to make it more discoverable and made part of
the core palette, rather than as a separate module.
- Tail: This node has been removed from the default palette. You can reinstall it
from node-red-node-tail
- HTTP Request: Reimplemented with a different underlying module. We have
tried to maintain 100% functional compatibility, but it is possible
some edge cases remain.
- JSON: The schema validation option no longer supports JSON-Schema draft-04
- HTML: Its underlying module has had a major version update. Should be fully
backward compatible.
- `functionExternalModules` is now enabled by default for new installs.
If you have an existing settings file that contains this setting, you will
need to set it to `true` yourself.
The external modules will now get installed in your Node-RED user directory,
(`~/.node-red`) rather than in a subdirectory. This means all dependencies will
be listed in your top-level `package.json`. If you have existing external modules,
they will get reinstalled to the new location when you first run Node-RED 2.0.
Runtime
- Fix missing dependencies (#3052, #2057) @kazuhitoyokoi
- Ensure node.types is defined if node html file missing
- Fix reporting of type_already_registered error
- Move install location of external modules (#3064) @knolleary
Editor
- Update translations (#3063) @kazuhitoyokoi
- Add a slight fade to tab labels that overflow
- Show config node details when selected in outliner
- Fix layout of info outliner for subflow entries
Nodes
- Delay: let `msg.flush` specify how many messages to flush from node (#3059) @dceejay
- Function: external modules is now enabled by default (#3065) @knolleary
- Function: external modules now supports both ES6 and CJS modules (#3065) @knolleary
- WebSocket: add option for client node to send automatic pings (#3056) @knolleary
##### 2.0.0-beta.2: Beta Release
Runtime
- Add `node-red admin init` (via `node-red-admin@2.1.0`)
- Move to GH Actions rather than Travis for build (#3042) @knolleary
Editor
- Include hasUser=false config nodes when exporting whole flow (#3048)
- Emit nodes:change for any updated config node when node deleted/added
- Fix padding of compact notification Closes #3045
- Ensure any html in changelog is escaped before displaying
- Add support for Map/Set property types on Debug (#3040) @knolleary
- Add 'theme' to default settings file
- Add RED.view.annotations api (#3032) @knolleary
- Update monaco editor to V0.25.2 (#3031) @Steve-Mcl
- Lower tray zIndex when overlay tray being opened Fixes #3019
- Reduce z-Index of Function expand buttons to prevent overlap Part of #3019
- Ensure RED.clipboard.import displays the right library Fixes #3021
- Batch messages sent over comms to prevent flooding (#3025) @knolleary
- Allow RED.popover.panel to specify a closeButton to ignore click events on
- Use browser default language for initial page load
- Add css var for node font color
- Fix label padding of toggleButton
- Give sidebar open tab a bit more room for its label
- Various Monaco updates (#3015) @Steve-Mcl
- Log readOnly on startup (#3024) @sammachin
- Translation updates (#3020 #3022) @HiroyasuNishiyama @kazuhitoyokoi
Nodes
- HTTP Request: Fix proxy handling (#3044) @hardillb
- HTTP Request: Handle basic auth with @ in username (#3017) @hardillb
- Add Japanese translation for file-in node (#3037 #3039) @kazuhitoyokoi
- File In: Add option for file-in node to include all properties (default off) (#3035) @dceejay
- Exec: add windowsHide option to hide windows under Windows (#3026) @natcl
- Support loading external module sub path Fixes #3023
##### 2.0.0-beta.1: Beta Release
Runtime
- [MAJOR] Set minimum node version to 12.
- [MAJOR] Fix flowfile name to flows.json in settings (#2951) @dceejay
- [MAJOR] Update to latest i18n in editor and runtime (#2940) @knolleary
- [MAJOR] Deprecate usage of httpRoot (#2953) @knolleary
- Add pre/postInstall hooks to npm install handling (#2936) @knolleary
- Add engine-strict flag to npm install args (#2965) @nileio
- Restructure default settings.js to be more organised (#3012) @knolleary
- Ensure httpServerOptions gets applied to ALL the express apps
- Allow RED.settings.set to replace string property with object property
- Update debug tests to handle compact comms format
- Updates to encode/decode message when passed over debug comms link
- Remove all input event listeners on a node once it is closed
- Move hooks to util package
- Rework hooks structure to be a linkedlist
- Update dependencies (#2922) @knolleary
Editor
- [MAJOR] Change node id generation to give fixed length values without '.' (#2987) @knolleary
- [MAJOR] Add Monaco code editor (#2971) @Steve-Mcl
- Update to latest Monaco (#3007) @Steve-Mcl
- Update Node-RED Function typings in Monaco (#3008) @Steve-Mcl
- Add css named variables for certain key colours (#2994) @knolleary
- Improve contrast of export dialog JSON font color
- Switch editableList buttons from <a> to <button> elements
- Add option to RED.nodes.createCompleteNodeSet to include node dimensions
- Fix css of node help table of contents elements
- Improve red-ui-node-icon css and add red-ui-node-icon-small modifier class
- Add RED.hooks to editor
- Add viewAddPort viewRemovePort viewAddNode viewRemoveNode hooks to view
- Use paletteLabel if set in help sidebar
- Add missing args from JSONata $now signature
Nodes
- [MAJOR] Relabel RBE node as 'filter' and move into core. Also remove tail (#2944) @dceejay
- [MAJOR] HTTP Request: migrate to 'got' module (#2952) @knolleary
- [MAJOR] Move Inject node to CronosJS module (#2959) @knolleary
- [MAJOR] JSON: Update ajv to 8.2.0 - drop support for JSON-Schema draft-04 (#2969) @knolleary
- [MAJOR] HTML node: cheerio update to 1.x (#3011) @knolleary
- Join: change default manual mode to object (#2931) @knolleary
- File node: Add fileWorkingDirectory (#2932) @knolleary
- Delay node enhancements (#2294) @kazuhitoyokoi (#2949) @dceejay
- Add Japanese translations for delay node enhancements (#2958) @kazuhitoyokoi
- Inject node: reorder TypedInput options (#2961) @dceejay
- HTTP Request: update to work with proxies (#2983) @hardillb (#3009) @hardillb
- HTTP Request: fix msg.responseUrl (#2986) @hardillb
- TLS: Add ALPN support to TLS node (#2988) @hardillb
- Inject: add "Inject now" button to edit dialog (#2990) @Steve-Mcl
#### Older Releases #### Older Releases
Change logs for older releases are available on GitHub: https://github.com/node-red/node-red/releases Change logs for older releases are available on GitHub: https://github.com/node-red/node-red/releases

View File

@@ -152,6 +152,7 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/history.js", "packages/node_modules/@node-red/editor-client/src/js/history.js",
"packages/node_modules/@node-red/editor-client/src/js/validators.js", "packages/node_modules/@node-red/editor-client/src/js/validators.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/utils.js", "packages/node_modules/@node-red/editor-client/src/js/ui/utils.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/utils-domselection.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/editableList.js", "packages/node_modules/@node-red/editor-client/src/js/ui/common/editableList.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/treeList.js", "packages/node_modules/@node-red/editor-client/src/js/ui/common/treeList.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/common/checkboxSet.js", "packages/node_modules/@node-red/editor-client/src/js/ui/common/checkboxSet.js",

View File

@@ -1,6 +1,6 @@
{ {
"name": "node-red", "name": "node-red",
"version": "3.0.0-beta.4", "version": "3.1.0-beta.0",
"description": "Low-code programming for event-driven applications", "description": "Low-code programming for event-driven applications",
"homepage": "http://nodered.org", "homepage": "http://nodered.org",
"license": "Apache-2.0", "license": "Apache-2.0",
@@ -49,7 +49,7 @@
"hash-sum": "2.0.0", "hash-sum": "2.0.0",
"hpagent": "1.0.0", "hpagent": "1.0.0",
"https-proxy-agent": "5.0.1", "https-proxy-agent": "5.0.1",
"i18next": "21.8.10", "i18next": "21.8.14",
"iconv-lite": "0.6.3", "iconv-lite": "0.6.3",
"is-utf8": "0.2.1", "is-utf8": "0.2.1",
"js-yaml": "4.1.0", "js-yaml": "4.1.0",
@@ -59,7 +59,7 @@
"media-typer": "1.1.0", "media-typer": "1.1.0",
"memorystore": "1.6.7", "memorystore": "1.6.7",
"mime": "3.0.0", "mime": "3.0.0",
"moment": "2.29.3", "moment": "2.29.4",
"moment-timezone": "0.5.34", "moment-timezone": "0.5.34",
"mqtt": "4.3.7", "mqtt": "4.3.7",
"multer": "1.4.5-lts.1", "multer": "1.4.5-lts.1",
@@ -69,14 +69,14 @@
"nopt": "5.0.0", "nopt": "5.0.0",
"oauth2orize": "1.11.1", "oauth2orize": "1.11.1",
"on-headers": "1.0.2", "on-headers": "1.0.2",
"passport": "0.5.2", "passport": "0.6.0",
"passport-http-bearer": "1.0.1", "passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2", "passport-oauth2-client-password": "0.1.2",
"raw-body": "2.5.1", "raw-body": "2.5.1",
"semver": "7.3.7", "semver": "7.3.7",
"tar": "6.1.11", "tar": "6.1.11",
"tough-cookie": "4.0.0", "tough-cookie": "4.0.0",
"uglify-js": "3.16.0", "uglify-js": "3.16.2",
"uuid": "8.3.2", "uuid": "8.3.2",
"ws": "7.5.6", "ws": "7.5.6",
"xml2js": "0.4.23" "xml2js": "0.4.23"
@@ -85,7 +85,7 @@
"bcrypt": "5.0.1" "bcrypt": "5.0.1"
}, },
"devDependencies": { "devDependencies": {
"dompurify": "2.3.8", "dompurify": "2.3.9",
"grunt": "1.5.3", "grunt": "1.5.3",
"grunt-chmod": "~1.1.1", "grunt-chmod": "~1.1.1",
"grunt-cli": "~1.4.3", "grunt-cli": "~1.4.3",
@@ -95,7 +95,7 @@
"grunt-contrib-concat": "2.1.0", "grunt-contrib-concat": "2.1.0",
"grunt-contrib-copy": "1.0.0", "grunt-contrib-copy": "1.0.0",
"grunt-contrib-jshint": "3.2.0", "grunt-contrib-jshint": "3.2.0",
"grunt-contrib-uglify": "5.2.1", "grunt-contrib-uglify": "5.2.2",
"grunt-contrib-watch": "1.1.0", "grunt-contrib-watch": "1.1.0",
"grunt-jsdoc": "2.4.1", "grunt-jsdoc": "2.4.1",
"grunt-jsdoc-to-markdown": "6.0.0", "grunt-jsdoc-to-markdown": "6.0.0",
@@ -108,17 +108,17 @@
"i18next-http-backend": "1.4.1", "i18next-http-backend": "1.4.1",
"jquery-i18next": "1.2.1", "jquery-i18next": "1.2.1",
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template", "jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
"marked": "4.0.17", "marked": "4.0.18",
"minami": "1.2.3", "minami": "1.2.3",
"mocha": "9.2.2", "mocha": "9.2.2",
"node-red-node-test-helper": "^0.3.0", "node-red-node-test-helper": "^0.3.0",
"nodemon": "2.0.16", "nodemon": "2.0.19",
"proxy": "^1.0.2", "proxy": "^1.0.2",
"sass": "1.52.3", "sass": "1.53.0",
"should": "13.2.3", "should": "13.2.3",
"sinon": "11.1.2", "sinon": "11.1.2",
"stoppable": "^1.1.0", "stoppable": "^1.1.0",
"supertest": "6.2.3" "supertest": "6.2.4"
}, },
"engines": { "engines": {
"node": ">=14" "node": ">=14"

View File

@@ -101,7 +101,10 @@ module.exports = {
} }
themeSettings = null; themeSettings = null;
theme = settings.editorTheme || {}; theme = settings.editorTheme || {};
themeContext.asset.vendorMonaco = ((theme.codeEditor || {}).lib === "monaco") ? "vendor/monaco/monaco-bootstrap.js" : ""; themeContext.asset.vendorMonaco = "vendor/monaco/monaco-bootstrap.js"
if (theme.codeEditor && theme.codeEditor.lib === 'ace') {
themeContext.asset.vendorMonaco = ''
}
activeTheme = theme.theme; activeTheme = theme.theme;
}, },
@@ -263,6 +266,67 @@ module.exports = {
theme.page = theme.page || {_:{}} theme.page = theme.page || {_:{}}
theme.page._.scripts = scriptFiles.concat(theme.page._.scripts || []) theme.page._.scripts = scriptFiles.concat(theme.page._.scripts || [])
} }
// check and load page settings from theme
if (themePlugin.page) {
if (themePlugin.page.favicon && !theme.page.favicon) {
const result = serveFilesFromTheme(
[themePlugin.page.favicon],
themeApp,
"/",
themePlugin.path
)
if(result && result.length > 0) {
// update themeContext page favicon
themeContext.page.favicon = result[0]
theme.page = theme.page || {_:{}}
theme.page._.favicon = result[0]
}
}
if (themePlugin.page.tabicon && themePlugin.page.tabicon.icon && !theme.page.tabicon) {
const result = serveFilesFromTheme(
[themePlugin.page.tabicon.icon],
themeApp,
"/page/",
themePlugin.path
)
if(result && result.length > 0) {
// update themeContext page tabicon
themeContext.page.tabicon.icon = result[0]
themeContext.page.tabicon.colour = themeContext.page.tabicon.colour || themeContext.page.tabicon.colour
theme.page = theme.page || {_:{}}
theme.page._.tabicon = theme.page._.tabicon || {}
theme.page._.tabicon.icon = themeContext.page.tabicon.icon
theme.page._.tabicon.colour = themeContext.page.tabicon.colour
}
}
// if the plugin has a title AND the users settings.js does NOT
if (themePlugin.page.title && !theme.page.title) {
themeContext.page.title = themePlugin.page.title || themeContext.page.title
}
}
// check and load header settings from theme
if (themePlugin.header) {
if (themePlugin.header.image && !theme.header.image) {
const result = serveFilesFromTheme(
[themePlugin.header.image],
themeApp,
"/header/",
themePlugin.path
)
if(result && result.length > 0) {
// update themeContext header image
themeContext.header.image = result[0]
}
}
// if the plugin has a title AND the users settings.js does NOT have a title
if (themePlugin.header.title && !theme.header.title) {
themeContext.header.title = themePlugin.header.title || themeContext.header.title
}
// if the plugin has a header url AND the users settings.js does NOT
if (themePlugin.header.url && !theme.header.url) {
themeContext.header.url = themePlugin.header.url || themeContext.header.url
}
}
if(theme.codeEditor) { if(theme.codeEditor) {
theme.codeEditor.options = Object.assign({}, themePlugin.monacoOptions, theme.codeEditor.options); theme.codeEditor.options = Object.assign({}, themePlugin.monacoOptions, theme.codeEditor.options);
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@node-red/editor-api", "name": "@node-red/editor-api",
"version": "3.0.0-beta.4", "version": "3.1.0-beta.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {
@@ -16,8 +16,8 @@
} }
], ],
"dependencies": { "dependencies": {
"@node-red/util": "3.0.0-beta.4", "@node-red/util": "3.1.0-beta.0",
"@node-red/editor-client": "3.0.0-beta.4", "@node-red/editor-client": "3.1.0-beta.0",
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"body-parser": "1.20.0", "body-parser": "1.20.0",
"clone": "2.1.2", "clone": "2.1.2",
@@ -31,7 +31,7 @@
"oauth2orize": "1.11.1", "oauth2orize": "1.11.1",
"passport-http-bearer": "1.0.1", "passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2", "passport-oauth2-client-password": "0.1.2",
"passport": "0.5.2", "passport": "0.6.0",
"ws": "7.5.6" "ws": "7.5.6"
}, },
"optionalDependencies": { "optionalDependencies": {

View File

@@ -300,6 +300,10 @@
"modifiedFlowsDesc": "Only deploys flows that contain changed nodes", "modifiedFlowsDesc": "Only deploys flows that contain changed nodes",
"modifiedNodes": "Modified Nodes", "modifiedNodes": "Modified Nodes",
"modifiedNodesDesc": "Only deploys nodes that have changed", "modifiedNodesDesc": "Only deploys nodes that have changed",
"startFlows": "Start",
"startFlowsDesc": "Start Flows",
"stopFlows": "Stop",
"stopFlowsDesc": "Stop Flows",
"restartFlows": "Restart Flows", "restartFlows": "Restart Flows",
"restartFlowsDesc": "Restarts the current deployed flows", "restartFlowsDesc": "Restarts the current deployed flows",
"successfulDeploy": "Successfully deployed", "successfulDeploy": "Successfully deployed",

View File

@@ -169,6 +169,10 @@
} }
}, },
"notification": { "notification": {
"state": {
"flowsStopped": "フローを停止しました",
"flowsStarted": "フローを開始しました"
},
"warning": "<strong>警告</strong>: __message__", "warning": "<strong>警告</strong>: __message__",
"warnings": { "warnings": {
"undeployedChanges": "ノードの変更をデプロイしていません", "undeployedChanges": "ノードの変更をデプロイしていません",
@@ -296,6 +300,10 @@
"modifiedFlowsDesc": "変更したノードを含むフローのみデプロイ", "modifiedFlowsDesc": "変更したノードを含むフローのみデプロイ",
"modifiedNodes": "変更したノード", "modifiedNodes": "変更したノード",
"modifiedNodesDesc": "変更したノードのみデプロイ", "modifiedNodesDesc": "変更したノードのみデプロイ",
"startFlows": "開始",
"startFlowsDesc": "フローを開始",
"stopFlows": "停止",
"stopFlowsDesc": "フローを停止",
"restartFlows": "フローを再起動", "restartFlows": "フローを再起動",
"restartFlowsDesc": "デプロイされた現在のフローを再起動", "restartFlowsDesc": "デプロイされた現在のフローを再起動",
"successfulDeploy": "デプロイが成功しました", "successfulDeploy": "デプロイが成功しました",
@@ -685,7 +693,8 @@
"showHelp": "ヘルプを表示", "showHelp": "ヘルプを表示",
"showInOutline": "アウトラインに表示", "showInOutline": "アウトラインに表示",
"showTopics": "トピックを表示", "showTopics": "トピックを表示",
"noHelp": "ヘルプのトピックが未選択" "noHelp": "ヘルプのトピックが未選択",
"changeLog": "更新履歴"
}, },
"config": { "config": {
"name": "設定ノードを表示", "name": "設定ノードを表示",
@@ -845,7 +854,7 @@
"pushFailed": "リモートに新しいコミットがあるため、プッシュに失敗しました。プルしてマージしてから、再度プッシュしてください。", "pushFailed": "リモートに新しいコミットがあるため、プッシュに失敗しました。プルしてマージしてから、再度プッシュしてください。",
"push": "プッシュ", "push": "プッシュ",
"pull": "プル", "pull": "プル",
"unablePull": "<p>リモートの変更のプル失敗:ステージングされていないローカルの変更上書きされてしまいます。</p><p>変更をコミットしてから再度実行してください。</p>", "unablePull": "<p>リモートの変更のプル失敗:ステージングされていないローカルの変更上書きされてしまいます。</p><p>変更をコミットしてから再度実行してください。</p>",
"showUnstagedChanges": "ステージングされていない変更を表示", "showUnstagedChanges": "ステージングされていない変更を表示",
"connectionFailed": "リモートリポジトリに接続できません: ", "connectionFailed": "リモートリポジトリに接続できません: ",
"pullUnrelatedHistory": "<p>リモートに関連のないコミット履歴があります。</p><p>本当に変更をプルしてローカルリポジトリに反映しますか?</p>", "pullUnrelatedHistory": "<p>リモートに関連のないコミット履歴があります。</p><p>本当に変更をプルしてローカルリポジトリに反映しますか?</p>",
@@ -1159,7 +1168,8 @@
"takeATour": "ツアーを開始", "takeATour": "ツアーを開始",
"start": "開始", "start": "開始",
"next": "次へ", "next": "次へ",
"tours": "ツアー" "welcomeTours": "ウェルカムツアー",
"tours": "ツアー"
}, },
"diagnostics": { "diagnostics": {
"title": "システム情報" "title": "システム情報"
@@ -1336,6 +1346,8 @@
"new-project": "新しいプロジェクト", "new-project": "新しいプロジェクト",
"open-project": "プロジェクトを開く", "open-project": "プロジェクトを開く",
"show-project-settings": "プロジェクト設定を表示", "show-project-settings": "プロジェクト設定を表示",
"show-version-control-tab": "バージョンコントロールタブを表示" "show-version-control-tab": "バージョンコントロールタブを表示",
"start-flows": "フローを開始",
"stop-flows": "フローを停止"
} }
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "@node-red/editor-client", "name": "@node-red/editor-client",
"version": "3.0.0-beta.4", "version": "3.1.0-beta.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@@ -3,16 +3,12 @@
"alt-shift-p":"core:manage-palette", "alt-shift-p":"core:manage-palette",
"ctrl-f": "core:search", "ctrl-f": "core:search",
"ctrl-shift-f": "core:list-flows", "ctrl-shift-f": "core:list-flows",
"ctrl-+": "core:zoom-in",
"ctrl--": "core:zoom-out",
"ctrl-0": "core:zoom-reset",
"ctrl-enter": "core:confirm-edit-tray",
"ctrl-escape": "core:cancel-edit-tray",
"ctrl-d": "core:deploy-flows", "ctrl-d": "core:deploy-flows",
"ctrl-g i": "core:show-info-tab",
"ctrl-g h": "core:show-help-tab",
"ctrl-g d": "core:show-debug-tab",
"ctrl-g c": "core:show-config-tab", "ctrl-g c": "core:show-config-tab",
"ctrl-g d": "core:show-debug-tab",
"ctrl-g h": "core:show-help-tab",
"ctrl-g i": "core:show-info-tab",
"ctrl-g v": "core:show-version-control-tab",
"ctrl-g x": "core:show-context-tab", "ctrl-g x": "core:show-context-tab",
"ctrl-e": "core:show-export-dialog", "ctrl-e": "core:show-export-dialog",
"ctrl-i": "core:show-import-dialog", "ctrl-i": "core:show-import-dialog",
@@ -23,11 +19,8 @@
"ctrl-alt-r": "core:show-remote-diff", "ctrl-alt-r": "core:show-remote-diff",
"ctrl-alt-n": "core:new-project", "ctrl-alt-n": "core:new-project",
"ctrl-alt-o": "core:open-project", "ctrl-alt-o": "core:open-project",
"ctrl-g v": "core:show-version-control-tab",
"ctrl-shift-l": "core:show-event-log", "ctrl-shift-l": "core:show-event-log",
"ctrl-shift-p":"core:show-action-list", "ctrl-shift-p":"core:show-action-list"
"alt-w": "core:hide-flow",
"alt-shift-w": "core:show-last-hidden-flow"
}, },
"red-ui-sidebar-node-config": { "red-ui-sidebar-node-config": {
"backspace": "core:delete-config-selection", "backspace": "core:delete-config-selection",
@@ -93,7 +86,16 @@
"alt-a v": "core:distribute-selection-vertically", "alt-a v": "core:distribute-selection-vertically",
"shift-f": "core:search-previous", "shift-f": "core:search-previous",
"f": "core:search-next", "f": "core:search-next",
"alt-l l": "core:split-wire-with-link-nodes" "alt-l l": "core:split-wire-with-link-nodes",
"alt-w": "core:hide-flow",
"alt-shift-w": "core:show-last-hidden-flow",
"ctrl-+": "core:zoom-in",
"ctrl--": "core:zoom-out",
"ctrl-0": "core:zoom-reset"
},
"red-ui-editor-stack": {
"ctrl-enter": "core:confirm-edit-tray",
"ctrl-escape": "core:cancel-edit-tray"
} }
} }

View File

@@ -1664,6 +1664,7 @@ RED.nodes = (function() {
function importNodes(newNodesObj,options) { // createNewIds,createMissingWorkspace) { function importNodes(newNodesObj,options) { // createNewIds,createMissingWorkspace) {
const defOpts = { generateIds: false, addFlow: false, reimport: false, importMap: {} } const defOpts = { generateIds: false, addFlow: false, reimport: false, importMap: {} }
options = Object.assign({}, defOpts, options) options = Object.assign({}, defOpts, options)
options.importMap = options.importMap || {}
const createNewIds = options.generateIds; const createNewIds = options.generateIds;
const reimport = (!createNewIds && !!options.reimport) const reimport = (!createNewIds && !!options.reimport)
const createMissingWorkspace = options.addFlow; const createMissingWorkspace = options.addFlow;

View File

@@ -1,4 +1,4 @@
RED.contextMenu = (function() { RED.contextMenu = (function () {
let menu; let menu;
function createMenu() { function createMenu() {
@@ -15,10 +15,6 @@ RED.contextMenu = (function() {
// ], // ],
// width: 200, // width: 200,
// }) // })
} }
function disposeMenu() { function disposeMenu() {
@@ -34,42 +30,80 @@ RED.contextMenu = (function() {
} }
const selection = RED.view.selection() const selection = RED.view.selection()
const noSelection = !selection || Object.keys(selection).length === 0
const hasSelection = (selection.nodes && selection.nodes.length > 0); const hasSelection = (selection.nodes && selection.nodes.length > 0);
const hasMultipleSelection = hasSelection && selection.nodes.length > 1; const hasMultipleSelection = hasSelection && selection.nodes.length > 1;
const hasLinks = selection.links && selection.links.length > 0; const virtulLinks = (selection.links && selection.links.filter(e => !!e.link)) || [];
const isSingleLink = !hasSelection && hasLinks && selection.links.length === 1 const wireLinks = (selection.links && selection.links.filter(e => !e.link)) || [];
const isMultipleLinks = !hasSelection && hasLinks && selection.links.length > 1 const hasLinks = wireLinks.length > 0;
const isSingleLink = !hasSelection && hasLinks && wireLinks.length === 1
const isMultipleLinks = !hasSelection && hasLinks && wireLinks.length > 1
const canDelete = hasSelection || hasLinks const canDelete = hasSelection || hasLinks
const isGroup = hasSelection && selection.nodes.length === 1 && selection.nodes[0].type === 'group' const isGroup = hasSelection && selection.nodes.length === 1 && selection.nodes[0].type === 'group'
const canRemoveFromGroup = hasSelection && !!selection.nodes[0].g const canRemoveFromGroup = hasSelection && !!selection.nodes[0].g
const offset = $("#red-ui-workspace-chart").offset()
let addX = options.x - offset.left + $("#red-ui-workspace-chart").scrollLeft()
let addY = options.y - offset.top + $("#red-ui-workspace-chart").scrollTop()
if (RED.view.snapGrid) {
const gridSize = RED.view.gridSize()
addX = gridSize * Math.floor(addX / gridSize)
addY = gridSize * Math.floor(addY / gridSize)
}
const menuItems = [ const menuItems = [
{ onselect: 'core:show-action-list', onpostselect: function() {} }, { onselect: 'core:show-action-list', onpostselect: function () { } },
{ {
label: RED._("contextMenu.insert"), label: RED._("contextMenu.insert"),
options: [ options: [
{ {
label: RED._("contextMenu.node"), label: RED._("contextMenu.node"),
onselect: function() { onselect: function () {
RED.view.showQuickAddDialog({ RED.view.showQuickAddDialog({
position: [ options.x - offset.left, options.y - offset.top ], position: [addX, addY],
touchTrigger: true, touchTrigger: true,
splice: isSingleLink?selection.links[0]:undefined, splice: isSingleLink ? selection.links[0] : undefined,
// spliceMultiple: isMultipleLinks // spliceMultiple: isMultipleLinks
}) })
} }
}, },
{ (hasLinks) ? { // has least 1 wire selected
label: RED._("contextMenu.junction"), label: RED._("contextMenu.junction"),
onselect: 'core:split-wires-with-junctions', onselect: 'core:split-wires-with-junctions',
disabled: hasSelection || !hasLinks disabled: !hasLinks
} : {
label: RED._("contextMenu.junction"),
onselect: function () {
const nn = {
_def: { defaults: {} },
type: 'junction',
z: RED.workspaces.active(),
id: RED.nodes.id(),
x: addX,
y: addY,
w: 0, h: 0,
outputs: 1,
inputs: 1,
dirty: true
}
const historyEvent = {
dirty: RED.nodes.dirty(),
t: 'add',
junctions: [nn]
}
RED.nodes.addJunction(nn);
RED.history.push(historyEvent);
RED.nodes.dirty(true);
RED.view.select({nodes: [nn] });
RED.view.redraw(true)
}
}, },
{ {
label: RED._("contextMenu.linkNodes"), label: RED._("contextMenu.linkNodes"),
onselect: 'core:split-wire-with-link-nodes', onselect: 'core:split-wire-with-link-nodes',
disabled: hasSelection || !hasLinks disabled: !hasLinks
} }
] ]
@@ -77,28 +111,13 @@ RED.contextMenu = (function() {
} }
] ]
// 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( menuItems.push(
null, null,
{ onselect: 'core:undo', disabled: RED.history.list().length === 0 }, { onselect: 'core:undo', disabled: RED.history.list().length === 0 },
{ onselect: 'core:redo', disabled: RED.history.listRedo().length === 0 }, { onselect: 'core:redo', disabled: RED.history.listRedo().length === 0 },
null, null,
{ onselect: 'core:cut-selection-to-internal-clipboard', label: RED._("keyboard.cutNode"), disabled: !hasSelection}, { 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: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:paste-from-internal-clipboard', label: RED._("keyboard.pasteNode"), disabled: !RED.view.clipboard() },
{ onselect: 'core:delete-selection', disabled: !canDelete }, { onselect: 'core:delete-selection', disabled: !canDelete },
@@ -110,27 +129,34 @@ RED.contextMenu = (function() {
menuItems.push( menuItems.push(
null, null,
isGroup ? isGroup ?
{ onselect: 'core:ungroup-selection', disabled: !isGroup } { onselect: 'core:ungroup-selection', disabled: !isGroup }
: { onselect: 'core:group-selection', disabled: !hasSelection } : { onselect: 'core:group-selection', disabled: !hasSelection }
) )
if (canRemoveFromGroup) { if (canRemoveFromGroup) {
menuItems.push({ onselect: 'core:remove-selection-from-group', label: RED._("menu.label.groupRemoveSelection") }) menuItems.push({ onselect: 'core:remove-selection-from-group', label: RED._("menu.label.groupRemoveSelection") })
} }
} }
const offset = $("#red-ui-workspace-chart").offset()
var direction = "right";
var MENU_WIDTH = 500; // can not use menu width here
if ((options.x -$(document).scrollLeft()) >
($(window).width() -MENU_WIDTH)) {
direction = "left";
}
menu = RED.menu.init({ menu = RED.menu.init({
direction: 'right', direction: direction,
onpreselect: function() { onpreselect: function() {
disposeMenu() disposeMenu()
}, },
onpostselect: function() { onpostselect: function () {
RED.view.focus() RED.view.focus()
}, },
options: menuItems options: menuItems
}); });
menu.attr("id","red-ui-workspace-context-menu"); menu.attr("id", "red-ui-workspace-context-menu");
menu.css({ menu.css({
position: "absolute" position: "absolute"
}) })
@@ -141,34 +167,35 @@ RED.contextMenu = (function() {
var top = options.y var top = options.y
var left = options.x var left = options.x
if (top+menu.height()-$(document).scrollTop() > $(window).height()) { if (top + menu.height() - $(document).scrollTop() > $(window).height()) {
top -= (top+menu.height())-$(window).height() + 22; top -= (top + menu.height()) - $(window).height() + 22;
} }
if (left+menu.width()-$(document).scrollLeft() > $(window).width()) { if (left + menu.width() - $(document).scrollLeft() > $(window).width()) {
left -= (left+menu.width())-$(window).width() + 18; left -= (left + menu.width()) - $(window).width() + 18;
} }
menu.css({ menu.css({
top: top+"px", top: top + "px",
left: left+"px" left: left + "px"
}) })
$(".red-ui-menu.red-ui-menu-dropdown").hide(); $(".red-ui-menu.red-ui-menu-dropdown").hide();
$(document).on("mousedown.red-ui-workspace-context-menu", function(evt) { $(document).on("mousedown.red-ui-workspace-context-menu", function (evt) {
if (menu && menu[0].contains(evt.target)) { if (menu && menu[0].contains(evt.target)) {
return return
} }
disposeMenu() disposeMenu()
}); });
menu.show(); menu.show();
// set focus to first item so that pressing escape key closes the menu
// menu.show({ $("#red-ui-workspace-context-menu :first(ul) > a").trigger("focus")
// target: $('#red-ui-main-container'),
// x: options.x,
// y: options.y
// })
} }
// Allow escape key hook and other editor events to close context menu
RED.keyboard.add("red-ui-workspace-context-menu", "escape", function () { RED.contextMenu.hide() })
RED.events.on("editor:open", function () { RED.contextMenu.hide() });
RED.events.on("search:open", function () { RED.contextMenu.hide() });
RED.events.on("type-search:open", function () { RED.contextMenu.hide() });
RED.events.on("actionList:open", function () { RED.contextMenu.hide() });
RED.events.on("view:selection-changed", function () { RED.contextMenu.hide() });
return { return {
show: show, show: show,
hide: disposeMenu hide: disposeMenu

View File

@@ -70,8 +70,8 @@ RED.deploy = (function() {
null null
] ]
if (RED.settings.runtimeState && RED.settings.runtimeState.ui === true) { if (RED.settings.runtimeState && RED.settings.runtimeState.ui === true) {
mainMenuItems.push({id:"deploymenu-item-runtime-start", icon:"red/images/start.svg",label:"Start"/*RED._("deploy.startFlows")*/,sublabel:"Start Flows" /*RED._("deploy.startFlowsDesc")*/,onselect:"core:start-flows", visible:false}) mainMenuItems.push({id:"deploymenu-item-runtime-start", icon:"red/images/start.svg",label:RED._("deploy.startFlows"),sublabel:RED._("deploy.startFlowsDesc"),onselect:"core:start-flows", visible:false})
mainMenuItems.push({id:"deploymenu-item-runtime-stop", icon:"red/images/stop.svg",label:"Stop"/*RED._("deploy.startFlows")*/,sublabel:"Stop Flows" /*RED._("deploy.startFlowsDesc")*/,onselect:"core:stop-flows", visible:false}) mainMenuItems.push({id:"deploymenu-item-runtime-stop", icon:"red/images/stop.svg",label:RED._("deploy.stopFlows"),sublabel:RED._("deploy.stopFlowsDesc"),onselect:"core:stop-flows", visible:false})
} }
mainMenuItems.push({id:"deploymenu-item-reload", icon:"red/images/deploy-reload.svg",label:RED._("deploy.restartFlows"),sublabel:RED._("deploy.restartFlowsDesc"),onselect:"core:restart-flows"}) mainMenuItems.push({id:"deploymenu-item-reload", icon:"red/images/deploy-reload.svg",label:RED._("deploy.restartFlows"),sublabel:RED._("deploy.restartFlowsDesc"),onselect:"core:restart-flows"})
RED.menu.init({id:"red-ui-header-button-deploy-options", options: mainMenuItems }); RED.menu.init({id:"red-ui-header-button-deploy-options", options: mainMenuItems });

View File

@@ -308,6 +308,7 @@ RED.group = (function() {
RED.history.push(historyEvent); RED.history.push(historyEvent);
RED.view.select({nodes:[group]}); RED.view.select({nodes:[group]});
RED.nodes.dirty(true); RED.nodes.dirty(true);
RED.view.focus();
} }
} }
} }
@@ -330,6 +331,7 @@ RED.group = (function() {
RED.history.push(historyEvent); RED.history.push(historyEvent);
RED.view.select({nodes:newSelection}) RED.view.select({nodes:newSelection})
RED.nodes.dirty(true); RED.nodes.dirty(true);
RED.view.focus();
} }
} }
@@ -424,6 +426,7 @@ RED.group = (function() {
}); });
RED.history.push(historyEvent); RED.history.push(historyEvent);
RED.nodes.dirty(true); RED.nodes.dirty(true);
RED.view.focus();
} }
} }
@@ -451,6 +454,7 @@ RED.group = (function() {
} }
} }
RED.view.select({nodes:selection.nodes}) RED.view.select({nodes:selection.nodes})
RED.view.focus();
} }
} }
function createGroup(nodes) { function createGroup(nodes) {

View File

@@ -265,13 +265,18 @@ RED.keyboard = (function() {
if (partialState) { if (partialState) {
partialState = null; partialState = null;
return resolveKeyEvent(evt); return resolveKeyEvent(evt);
} else if (Object.keys(handler).length > 0) {
partialState = handler;
evt.preventDefault();
return null;
} else {
return null;
} }
if (Object.keys(handler).length > 0) {
// check if there's a potential combined handler initiated by this keyCode
for (let h in handler) {
if (matchHandlerToEvent(evt,handler[h]) > -1) {
partialState = handler;
evt.preventDefault();
break;
}
}
}
return null;
} else { } else {
var depth = Infinity; var depth = Infinity;
var matchedHandler; var matchedHandler;
@@ -293,21 +298,21 @@ RED.keyboard = (function() {
return resolveKeyEvent(evt); return resolveKeyEvent(evt);
} }
} }
d3.select(window).on("keydown",function() { document.addEventListener("keydown", function(event) {
if (!handlersActive) { if (!handlersActive) {
return; return;
} }
if (metaKeyCodes[d3.event.keyCode]) { if (metaKeyCodes[event.keyCode]) {
return; return;
} }
var handler = resolveKeyEvent(d3.event); var handler = resolveKeyEvent(event);
if (handler && handler.ondown) { if (handler && handler.ondown) {
if (typeof handler.ondown === "string") { if (typeof handler.ondown === "string") {
RED.actions.invoke(handler.ondown); RED.actions.invoke(handler.ondown);
} else { } else {
handler.ondown(); handler.ondown();
} }
d3.event.preventDefault(); event.preventDefault();
} }
}); });

View File

@@ -299,7 +299,7 @@ RED.palette = (function() {
RED.view.focus(); RED.view.focus();
}, },
stop: function() { stop: function() {
d3.select('.red-ui-flow-link-splice').classed('red-ui-flow-link-splice',false); document.querySelectorAll(".red-ui-flow-link-splice").forEach(n => { n.classList.remove("red-ui-flow-link-splice") })
if (hoverGroup) { if (hoverGroup) {
document.getElementById("group_select_"+hoverGroup.id).classList.remove("red-ui-flow-group-hovered"); document.getElementById("group_select_"+hoverGroup.id).classList.remove("red-ui-flow-group-hovered");
} }
@@ -358,26 +358,26 @@ RED.palette = (function() {
var mx = mouseX / RED.view.scale(); var mx = mouseX / RED.view.scale();
var my = mouseY / RED.view.scale(); var my = mouseY / RED.view.scale();
for (var i=0;i<nodes.length;i++) { for (var i=0;i<nodes.length;i++) {
var node = d3.select(nodes[i]); var node = nodes[i];
if (node.classed('red-ui-flow-link-background') && !node.classed('red-ui-flow-link-link')) { if (node.classList.contains('red-ui-flow-link-background') && !node.classList.contains('red-ui-flow-link-link')) {
var length = nodes[i].getTotalLength(); var length = node.getTotalLength();
for (var j=0;j<length;j+=10) { for (var j=0;j<length;j+=10) {
var p = nodes[i].getPointAtLength(j); var p = node.getPointAtLength(j);
var d2 = ((p.x-mx)*(p.x-mx))+((p.y-my)*(p.y-my)); var d2 = ((p.x-mx)*(p.x-mx))+((p.y-my)*(p.y-my));
if (d2 < 200 && d2 < bestDistance) { if (d2 < 200 && d2 < bestDistance) {
bestDistance = d2; bestDistance = d2;
bestLink = nodes[i]; bestLink = node;
} }
} }
} }
} }
if (activeSpliceLink && activeSpliceLink !== bestLink) { if (activeSpliceLink && activeSpliceLink !== bestLink) {
d3.select(activeSpliceLink.parentNode).classed('red-ui-flow-link-splice',false); activeSpliceLink.parentNode.classList.remove('red-ui-flow-link-splice');
} }
if (bestLink) { if (bestLink) {
d3.select(bestLink.parentNode).classed('red-ui-flow-link-splice',true) bestLink.parentNode.classList.add('red-ui-flow-link-splice');
} else { } else {
d3.select('.red-ui-flow-link-splice').classed('red-ui-flow-link-splice',false); document.querySelectorAll(".red-ui-flow-link-splice").forEach(n => { n.classList.remove("red-ui-flow-link-splice") })
} }
if (activeSpliceLink !== bestLink) { if (activeSpliceLink !== bestLink) {
if (bestLink) { if (bestLink) {

View File

@@ -877,6 +877,7 @@ RED.subflow = (function() {
RED.nodes.dirty(true); RED.nodes.dirty(true);
RED.view.updateActive(); RED.view.updateActive();
RED.view.select(null); RED.view.select(null);
RED.view.focus();
} }
@@ -931,6 +932,7 @@ RED.subflow = (function() {
function buildEnvUIRow(row, tenv, ui, node) { function buildEnvUIRow(row, tenv, ui, node) {
console.log(tenv, ui)
ui.label = ui.label||{}; ui.label = ui.label||{};
if ((tenv.type === "cred" || (tenv.parent && tenv.parent.type === "cred")) && !ui.type) { if ((tenv.type === "cred" || (tenv.parent && tenv.parent.type === "cred")) && !ui.type) {
ui.type = "cred"; ui.type = "cred";
@@ -991,6 +993,17 @@ RED.subflow = (function() {
default: inputType default: inputType
}) })
input.typedInput('value',val.value) input.typedInput('value',val.value)
if (inputType === 'cred') {
if (node.credentials) {
if (node.credentials[tenv.name]) {
input.typedInput('value', node.credentials[tenv.name]);
} else if (node.credentials['has_'+tenv.name]) {
input.typedInput('value', "__PWRD__")
} else {
input.typedInput('value', "");
}
}
}
} else { } else {
input.val(val.value) input.val(val.value)
} }

View File

@@ -27,26 +27,24 @@ RED.touch.radialMenu = (function() {
function createRadial(obj,pos,options) { function createRadial(obj,pos,options) {
isActive = true; isActive = true;
try { try {
touchMenu = d3.select("body").append("div").classed("red-ui-editor-radial-menu",true) touchMenu = $('<div>', {class: 'red-ui-editor-radial-menu'}).appendTo('body')
.on('touchstart',function() { .on('touchstart',function(evt) {
hide(); hide();
d3.event.preventDefault(); evt.preventDefault();
}); });
var menu = touchMenu.append("div") var menu = $('<div>').appendTo(touchMenu).css({
.style({
top: (pos[1]-80)+"px", top: (pos[1]-80)+"px",
left:(pos[0]-80)+"px", left:(pos[0]-80)+"px",
}); });
var menuOpts = []; var menuOpts = [];
var createMenuOpt = function(x,y,opt) { var createMenuOpt = function(x,y,opt) {
opt.el = menu.append("div").classed("red-ui-editor-radial-menu-opt",true) opt.el = $('<div>', {class: 'red-ui-editor-radial-menu-opt'}).appendTo(menu)
.style({ .css({
top: (y+80-25)+"px", top: (y+80-25)+"px",
left:(x+80-25)+"px" left:(x+80-25)+"px"
}) })
.classed("red-ui-editor-radial-menu-opt-disabled",!!opt.disabled) .toggleClass("red-ui-editor-radial-menu-opt-disabled",!!opt.disabled)
opt.el.html(opt.name); opt.el.html(opt.name);
@@ -54,16 +52,16 @@ RED.touch.radialMenu = (function() {
opt.y = y; opt.y = y;
menuOpts.push(opt); menuOpts.push(opt);
opt.el.on('touchstart',function() { opt.el.on('touchstart',function(evt) {
opt.el.classed("red-ui-editor-radial-menu-opt-active",true) opt.el.toggleClass("red-ui-editor-radial-menu-opt-active",true)
d3.event.preventDefault(); evt.preventDefault();
d3.event.stopPropagation(); evt.stopPropagation();
}); });
opt.el.on('touchend',function() { opt.el.on('touchend',function(evt) {
hide(); hide();
opt.onselect(); opt.onselect();
d3.event.preventDefault(); evt.preventDefault();
d3.event.stopPropagation(); evt.stopPropagation();
}); });
} }
@@ -88,8 +86,8 @@ RED.touch.radialMenu = (function() {
} }
obj.on('touchend.radial',function() { obj.on('touchend.radial',function() {
obj.on('touchend.radial',null); obj.off('touchend.radial');
obj.on('touchmenu.radial',null); obj.off('touchmenu.radial');
if (activeOption) { if (activeOption) {
try { try {
@@ -103,9 +101,9 @@ RED.touch.radialMenu = (function() {
} }
}); });
obj.on('touchmove.radial',function() { obj.on('touchmove.radial',function(evt) {
try { try {
var touch0 = d3.event.touches.item(0); var touch0 = evt.touches.item(0);
var p = [touch0.pageX - pos[0],touch0.pageY-pos[1]]; var p = [touch0.pageX - pos[0],touch0.pageY-pos[1]];
for (var i=0;i<menuOpts.length;i++) { for (var i=0;i<menuOpts.length;i++) {
var opt = menuOpts[i]; var opt = menuOpts[i];
@@ -119,7 +117,7 @@ RED.touch.radialMenu = (function() {
if (opt === activeOption) { if (opt === activeOption) {
activeOption = null; activeOption = null;
} }
opt.el.classed("selected",false); opt.el.toggleClass("selected",false);
} }
} }
} }

View File

@@ -437,17 +437,17 @@ RED.tourGuide = (function() {
return [ return [
{ {
id: "3_0", id: "3_0",
label: "3.0.0-beta.4", label: "3.0",
path: "./tours/welcome.js" path: "./tours/welcome.js"
}, },
{ {
id: "2_2", id: "2_2",
label: "2.2.0", label: "2.2",
path: "./tours/2.2/welcome.js" path: "./tours/2.2/welcome.js"
}, },
{ {
id: "2_1", id: "2_1",
label: "2.1.0", label: "2.1",
path: "./tours/2.1/welcome.js" path: "./tours/2.1/welcome.js"
} }
]; ];

View File

@@ -0,0 +1,61 @@
/**
* Modelled after `d3.selection` this provides a way to keep a mapping of
* DOM Nodes with a data collection.
*
* The goal here is not to reproduce d3 functionality as-is, but to provide an
* api that is specific to what we need to do
*
* const domSelection = RED.utils.domSelection(container, selector, createNode, eachNode)
*
* - container - a DOM Node that is the container of the DOM Nodes to track
* - selector - CSS selector to get the DOM nodes to track
* - createNode - function called when a DOM node must be created for a piece of data.
* `this` is the data item. Should return the DOM Node. It will
* get added to the container.
* - eachNode - function called for each DOM node/data item in the selection
*
* DomSelection.refresh(data) - called whenever the selection should be refreshed.
* Data is expected to be an array of objects that contain an 'id' property
*
*/
RED.utils.domSelection = (function() {
class DomSelection {
constructor(container, selector, createNode, eachNode) {
this.container = container
this.selector = selector
this.createNode = createNode
this.eachNode = eachNode
this.data = []
}
refresh(data) {
const domNodes = this.container.querySelectorAll(this.selector)
const domItems = new Map()
const dataLength = data.length
const domLength = domNodes.length
for (let i = 0; i < domLength; i++) {
const domNode = domNodes[i]
if (domNode.__data__) {
domItems.set(domNode.__data__.id, domNode)
}
}
for (let i = 0; i < dataLength; i++) {
const datum = data[i]
let domNode = domItems.get(datum.id)
if (!domNode) {
domNode = this.createNode.call(datum)
this.container.appendChild(domNode)
domNode.__data__ = datum
} else {
domItems.delete(datum.id)
}
this.eachNode.call(datum, domNode)
}
for (const remainingDomNodes of domItems) {
remainingDomNodes[1].remove()
}
}
}
return (container, selector, createNode, eachNode) => new DomSelection(container, selector, createNode, eachNode)
})()

View File

@@ -1397,6 +1397,17 @@ RED.utils = (function() {
return r; return r;
} }
function createSVGElement(tag, attrs = {}, parent) {
const element = document.createElementNS('http://www.w3.org/2000/svg', tag)
for (const k in attrs) {
element.setAttribute(k, attrs[k])
}
if (parent) {
parent.appendChild(element)
}
return element
}
return { return {
createObjectElement: createObjectElement, createObjectElement: createObjectElement,
getMessageProperty: getMessageProperty, getMessageProperty: getMessageProperty,
@@ -1420,6 +1431,7 @@ RED.utils = (function() {
getDarkerColor: getDarkerColor, getDarkerColor: getDarkerColor,
parseModuleList: parseModuleList, parseModuleList: parseModuleList,
checkModuleAllowed: checkModuleAllowed, checkModuleAllowed: checkModuleAllowed,
getBrowserInfo: getBrowserInfo getBrowserInfo: getBrowserInfo,
createSVGElement: createSVGElement
} }
})(); })();

View File

@@ -91,8 +91,7 @@ RED.view.annotations = (function() {
function addAnnotation(id,evt) { function addAnnotation(id,evt) {
var opts = annotations[id]; var opts = annotations[id];
evt.el.__annotations__ = evt.el.__annotations__ || []; evt.el.__annotations__ = evt.el.__annotations__ || [];
var annotationGroup = document.createElementNS("http://www.w3.org/2000/svg","g"); var annotationGroup = RED.utils.createSVGElement("g", { class: opts.class || '' })
annotationGroup.setAttribute("class",opts.class || "");
evt.el.__annotations__.push({ evt.el.__annotations__.push({
id:id, id:id,
element: annotationGroup element: annotationGroup

View File

@@ -15,133 +15,128 @@
**/ **/
RED.view.navigator = (function() { RED.view.navigator = (function() {
var nav_scale = 25;
var nav_width = 5000/nav_scale;
var nav_height = 5000/nav_scale;
var nav_scale = 25; var navContainer;
var nav_width = 5000/nav_scale; var navBox;
var nav_height = 5000/nav_scale; var navBorder;
var scrollPos;
var scaleFactor;
var chartSize;
var dimensions;
var isDragging;
var isShowing = false;
var navContainer; var domSelection
var navBox;
var navBorder;
var navVis;
var scrollPos;
var scaleFactor;
var chartSize;
var dimensions;
var isDragging;
var isShowing = false;
function refreshNodes() { function refreshNodes() {
if (!isShowing) { if (!isShowing) {
return; return;
} }
var navNode = navVis.selectAll(".red-ui-navigator-node").data(RED.view.getActiveNodes(),function(d){return d.id}); domSelection.refresh(RED.view.getActiveNodes())
navNode.exit().remove(); }
navNode.enter().insert("rect")
.attr('class','red-ui-navigator-node')
.attr("pointer-events", "none");
navNode.each(function(d) {
d3.select(this).attr("x",function(d) { return (d.x-d.w/2)/nav_scale })
.attr("y",function(d) { return (d.y-d.h/2)/nav_scale })
.attr("width",function(d) { return Math.max(9,d.w/nav_scale) })
.attr("height",function(d) { return Math.max(3,d.h/nav_scale) })
.attr("fill",function(d) { return RED.utils.getNodeColor(d.type,d._def);})
});
}
function onScroll() {
if (!isDragging) {
resizeNavBorder();
}
}
function resizeNavBorder() {
if (navBorder) {
scaleFactor = RED.view.scale();
chartSize = [ $("#red-ui-workspace-chart").width(), $("#red-ui-workspace-chart").height()];
scrollPos = [$("#red-ui-workspace-chart").scrollLeft(),$("#red-ui-workspace-chart").scrollTop()];
navBorder.attr('x',scrollPos[0]/nav_scale)
.attr('y',scrollPos[1]/nav_scale)
.attr('width',chartSize[0]/nav_scale/scaleFactor)
.attr('height',chartSize[1]/nav_scale/scaleFactor)
}
}
function toggle() {
if (!isShowing) {
isShowing = true;
$("#red-ui-view-navigate").addClass("selected");
resizeNavBorder();
refreshNodes();
$("#red-ui-workspace-chart").on("scroll",onScroll);
navContainer.fadeIn(200);
} else {
isShowing = false;
navContainer.fadeOut(100);
$("#red-ui-workspace-chart").off("scroll",onScroll);
$("#red-ui-view-navigate").removeClass("selected");
}
}
return { function onScroll() {
init: function() { if (!isDragging) {
resizeNavBorder();
}
}
function resizeNavBorder() {
if (navBorder) {
scaleFactor = RED.view.scale();
chartSize = [ $("#red-ui-workspace-chart").width(), $("#red-ui-workspace-chart").height()];
scrollPos = [$("#red-ui-workspace-chart").scrollLeft(),$("#red-ui-workspace-chart").scrollTop()];
$(window).on("resize", resizeNavBorder); navBorder.attr('x', scrollPos[0]/nav_scale)
RED.events.on("sidebar:resize",resizeNavBorder); navBorder.attr('y', scrollPos[1]/nav_scale)
RED.actions.add("core:toggle-navigator",toggle); navBorder.attr('width',chartSize[0]/nav_scale/scaleFactor)
var hideTimeout; navBorder.attr('height',chartSize[1]/nav_scale/scaleFactor)
}
}
function toggle() {
if (!isShowing) {
isShowing = true;
$("#red-ui-view-navigate").addClass("selected");
resizeNavBorder();
refreshNodes();
$("#red-ui-workspace-chart").on("scroll",onScroll);
navContainer.fadeIn(200);
} else {
isShowing = false;
navContainer.fadeOut(100);
$("#red-ui-workspace-chart").off("scroll",onScroll);
$("#red-ui-view-navigate").removeClass("selected");
}
}
navContainer = $('<div>').css({ return {
"position":"absolute", init: function() {
"bottom":$("#red-ui-workspace-footer").height(),
"right":0,
zIndex: 1
}).appendTo("#red-ui-workspace").hide();
navBox = d3.select(navContainer[0]) $(window).on("resize", resizeNavBorder);
.append("svg:svg") RED.events.on("sidebar:resize",resizeNavBorder);
.attr("width", nav_width) RED.actions.add("core:toggle-navigator",toggle);
.attr("height", nav_height)
.attr("pointer-events", "all")
.attr("id","red-ui-navigator-canvas")
navBox.append("rect").attr("x",0).attr("y",0).attr("width",nav_width).attr("height",nav_height).style({ navContainer = $('<div>').css({
fill:"none", "position":"absolute",
stroke:"none", "bottom":$("#red-ui-workspace-footer").height(),
pointerEvents:"all" "right":0,
}).on("mousedown", function() { zIndex: 1
// Update these in case they have changed }).appendTo("#red-ui-workspace").hide();
scaleFactor = RED.view.scale();
chartSize = [ $("#red-ui-workspace-chart").width(), $("#red-ui-workspace-chart").height()];
dimensions = [chartSize[0]/nav_scale/scaleFactor, chartSize[1]/nav_scale/scaleFactor];
var newX = Math.max(0,Math.min(d3.event.offsetX+dimensions[0]/2,nav_width)-dimensions[0]);
var newY = Math.max(0,Math.min(d3.event.offsetY+dimensions[1]/2,nav_height)-dimensions[1]);
navBorder.attr('x',newX).attr('y',newY);
isDragging = true;
$("#red-ui-workspace-chart").scrollLeft(newX*nav_scale*scaleFactor);
$("#red-ui-workspace-chart").scrollTop(newY*nav_scale*scaleFactor);
}).on("mousemove", function() {
if (!isDragging) { return }
if (d3.event.buttons === 0) {
isDragging = false;
return;
}
var newX = Math.max(0,Math.min(d3.event.offsetX+dimensions[0]/2,nav_width)-dimensions[0]);
var newY = Math.max(0,Math.min(d3.event.offsetY+dimensions[1]/2,nav_height)-dimensions[1]);
navBorder.attr('x',newX).attr('y',newY);
$("#red-ui-workspace-chart").scrollLeft(newX*nav_scale*scaleFactor);
$("#red-ui-workspace-chart").scrollTop(newY*nav_scale*scaleFactor);
}).on("mouseup", function() {
isDragging = false;
})
navBorder = navBox.append("rect").attr("class","red-ui-navigator-border") navBox = $(RED.utils.createSVGElement('svg', {id: "red-ui-navigator-canvas", width: nav_width, height: nav_height, 'pointer-events': 'all'})).appendTo(navContainer)
navVis = navBox.append("svg:g") const navBoxBody = $(RED.utils.createSVGElement("rect", { x: 0, y: 0, width: nav_width, height: nav_height, fill: 'none', stroke: 'none', 'pointer-events': 'all'}))
.css({'cursor': 'pointer'})
navBoxBody.on('mousedown',function(event) {
// Update these in case they have changed
scaleFactor = RED.view.scale();
chartSize = [ $("#red-ui-workspace-chart").width(), $("#red-ui-workspace-chart").height()];
dimensions = [chartSize[0]/nav_scale/scaleFactor, chartSize[1]/nav_scale/scaleFactor];
var newX = Math.max(0,Math.min(event.offsetX+dimensions[0]/2,nav_width)-dimensions[0]);
var newY = Math.max(0,Math.min(event.offsetY+dimensions[1]/2,nav_height)-dimensions[1]);
navBorder.attr('x',newX)
navBorder.attr('y',newY);
isDragging = true;
$("#red-ui-workspace-chart").scrollLeft(newX*nav_scale*scaleFactor);
$("#red-ui-workspace-chart").scrollTop(newY*nav_scale*scaleFactor);
}).on('mousemove', function(event) {
if (!isDragging) { return }
if (event.buttons === 0) {
isDragging = false;
return;
}
var newX = Math.max(0,Math.min(event.offsetX+dimensions[0]/2,nav_width)-dimensions[0]);
var newY = Math.max(0,Math.min(event.offsetY+dimensions[1]/2,nav_height)-dimensions[1]);
navBorder.attr('x',newX)
navBorder.attr('y',newY);
$("#red-ui-workspace-chart").scrollLeft(newX*nav_scale*scaleFactor);
$("#red-ui-workspace-chart").scrollTop(newY*nav_scale*scaleFactor);
}).on('mouseup', function() {
isDragging = false;
}).appendTo(navBox)
RED.statusBar.add({ navBorder = $(RED.utils.createSVGElement("rect", { "class": "red-ui-navigator-border" })).appendTo(navBox)
id: "view-navigator",
align: "right", const navVis = $(RED.utils.createSVGElement('g')).appendTo(navBox)
element: $('<button class="red-ui-footer-button-toggle single" id="red-ui-view-navigate"><i class="fa fa-map-o"></i></button>')
}) domSelection = RED.utils.domSelection(navVis[0], '.red-ui-navigator-node', function() {
return RED.utils.createSVGElement('rect', { class: 'red-ui-navigator-node', 'pointer-events': 'none' })
}, function(node) {
node.setAttribute('x', (this.x-this.w/2)/nav_scale)
node.setAttribute('y', (this.y-this.h/2)/nav_scale)
node.setAttribute('width', Math.max(9,this.w/nav_scale))
node.setAttribute('height', Math.max(3,this.h/nav_scale))
node.setAttribute('fill', RED.utils.getNodeColor(this.type,this._def))
})
RED.statusBar.add({
id: "view-navigator",
align: "right",
element: $('<button class="red-ui-footer-button-toggle single" id="red-ui-view-navigate"><i class="fa fa-map-o"></i></button>')
})
$("#red-ui-view-navigate").on("click", function(evt) { $("#red-ui-view-navigate").on("click", function(evt) {
evt.preventDefault(); evt.preventDefault();

View File

@@ -105,6 +105,9 @@ RED.view.tools = (function() {
$(document).one('keyup',endKeyboardMove); $(document).one('keyup',endKeyboardMove);
endMoveSet = true; endMoveSet = true;
} }
var dim = RED.view.dimensions();
var space_width = dim.width;
var space_height = dim.height;
var minX = 0; var minX = 0;
var minY = 0; var minY = 0;
var node; var node;
@@ -120,6 +123,12 @@ RED.view.tools = (function() {
node.n.dirty = true; node.n.dirty = true;
node.n.x += dx; node.n.x += dx;
node.n.y += dy; node.n.y += dy;
if ((node.n.x +node.n.w/2) >= space_width) {
node.n.x = space_width -node.n.w/2;
}
if ((node.n.y +node.n.h/2) >= space_height) {
node.n.y = space_height -node.n.h/2;
}
node.n.dirty = true; node.n.dirty = true;
if (node.n.type === "group") { if (node.n.type === "group") {
RED.group.markDirty(node.n); RED.group.markDirty(node.n);
@@ -814,7 +823,7 @@ RED.view.tools = (function() {
* @param {Object || Object[]} wires The wire(s) to split and replace with link-out, link-in nodes. * @param {Object || Object[]} wires The wire(s) to split and replace with link-out, link-in nodes.
*/ */
function splitWiresWithLinkNodes(wires) { function splitWiresWithLinkNodes(wires) {
let wiresToSplit = wires || RED.view.selection().links; let wiresToSplit = wires || (RED.view.selection().links && RED.view.selection().links.filter(e => !e.link));
if (!wiresToSplit) { if (!wiresToSplit) {
return return
} }
@@ -1052,7 +1061,7 @@ RED.view.tools = (function() {
} }
function addJunctionsToWires(wires) { function addJunctionsToWires(wires) {
let wiresToSplit = wires || RED.view.selection().links; let wiresToSplit = wires || (RED.view.selection().links && RED.view.selection().links.filter(e => !e.link));
if (!wiresToSplit) { if (!wiresToSplit) {
return return
} }
@@ -1080,6 +1089,7 @@ RED.view.tools = (function() {
linkGroups.sort(function(A,B) { linkGroups.sort(function(A,B) {
return groupedLinks[B].length - groupedLinks[A].length return groupedLinks[B].length - groupedLinks[A].length
}) })
const wasDirty = RED.nodes.dirty()
linkGroups.forEach(function(gid) { linkGroups.forEach(function(gid) {
var links = groupedLinks[gid] var links = groupedLinks[gid]
var junction = { var junction = {
@@ -1170,12 +1180,14 @@ RED.view.tools = (function() {
}) })
if (addedJunctions.length > 0) { if (addedJunctions.length > 0) {
RED.history.push({ RED.history.push({
dirty: wasDirty,
t: 'add', t: 'add',
links: addedLinks, links: addedLinks,
junctions: addedJunctions, junctions: addedJunctions,
removedLinks: Array.from(removedLinks) removedLinks: Array.from(removedLinks)
}) })
RED.nodes.dirty(true) RED.nodes.dirty(true)
RED.view.select({nodes: addedJunctions });
} }
RED.view.redraw(true); RED.view.redraw(true);
} }

View File

@@ -95,6 +95,7 @@ RED.view = (function() {
let flashingNodeId; let flashingNodeId;
var clipboard = ""; var clipboard = "";
let clipboardSource
// Note: these are the permitted status colour aliases. The actual RGB values // Note: these are the permitted status colour aliases. The actual RGB values
// are set in the CSS - flow.scss/colors.scss // are set in the CSS - flow.scss/colors.scss
@@ -293,25 +294,13 @@ RED.view = (function() {
] ]
startTouchDistance = Math.sqrt((a*a)+(b*b)); startTouchDistance = Math.sqrt((a*a)+(b*b));
} else { } else {
var obj = d3.select(document.body);
touch0 = d3.event.touches.item(0); touch0 = d3.event.touches.item(0);
var pos = [touch0.pageX,touch0.pageY]; var pos = [touch0.pageX,touch0.pageY];
startTouchCenter = [touch0.pageX,touch0.pageY]; startTouchCenter = [touch0.pageX,touch0.pageY];
startTouchDistance = 0; startTouchDistance = 0;
var point = d3.touches(this)[0];
touchStartTime = setTimeout(function() { touchStartTime = setTimeout(function() {
touchStartTime = null; touchStartTime = null;
showTouchMenu(obj,pos); showTouchMenu(document.body,pos);
//lasso = eventLayer.append("rect")
// .attr("ox",point[0])
// .attr("oy",point[1])
// .attr("rx",2)
// .attr("ry",2)
// .attr("x",point[0])
// .attr("y",point[1])
// .attr("width",0)
// .attr("height",0)
// .attr("class","nr-ui-view-lasso");
},touchLongPressTimeout); },touchLongPressTimeout);
} }
d3.event.preventDefault(); d3.event.preventDefault();
@@ -628,8 +617,10 @@ RED.view = (function() {
}); });
RED.actions.add("core:copy-selection-to-internal-clipboard",copySelection); RED.actions.add("core:copy-selection-to-internal-clipboard",copySelection);
RED.actions.add("core:cut-selection-to-internal-clipboard",function(){copySelection();deleteSelection();}); RED.actions.add("core:cut-selection-to-internal-clipboard",function(){copySelection(true);deleteSelection();});
RED.actions.add("core:paste-from-internal-clipboard",function(){importNodes(clipboard,{generateIds: true, generateDefaultNames: true});}); RED.actions.add("core:paste-from-internal-clipboard",function(){
importNodes(clipboard,{generateIds: clipboardSource === 'copy', generateDefaultNames: clipboardSource === 'copy'});
});
RED.actions.add("core:detach-selected-nodes", function() { detachSelectedNodes() }) RED.actions.add("core:detach-selected-nodes", function() { detachSelectedNodes() })
@@ -709,11 +700,11 @@ RED.view = (function() {
type: "badge", type: "badge",
class: "red-ui-flow-node-changed", class: "red-ui-flow-node-changed",
element: function() { element: function() {
var changeBadge = document.createElementNS("http://www.w3.org/2000/svg","circle"); return RED.utils.createSVGElement("circle", {
changeBadge.setAttribute("cx",5); cx: 5,
changeBadge.setAttribute("cy",5); cy: 5,
changeBadge.setAttribute("r",5); r: 5
return changeBadge; })
}, },
show: function(n) { return n.changed||n.moved } show: function(n) { return n.changed||n.moved }
}) })
@@ -722,9 +713,9 @@ RED.view = (function() {
type: "badge", type: "badge",
class: "red-ui-flow-node-error", class: "red-ui-flow-node-error",
element: function(d) { element: function(d) {
var errorBadge = document.createElementNS("http://www.w3.org/2000/svg","path"); return RED.utils.createSVGElement("path", {
errorBadge.setAttribute("d","M 0,9 l 10,0 -5,-8 z"); d: "M 0,9 l 10,0 -5,-8 z"
return errorBadge })
}, },
tooltip: function(d) { tooltip: function(d) {
if (d.validationErrors && d.validationErrors.length > 0) { if (d.validationErrors && d.validationErrors.length > 0) {
@@ -2149,6 +2140,9 @@ RED.view = (function() {
} }
} }
if (mouse_mode == RED.state.IMPORT_DRAGGING) { if (mouse_mode == RED.state.IMPORT_DRAGGING) {
if (clipboardSource === 'cut') {
clipboardSource = 'copy'
}
updateActiveNodes(); updateActiveNodes();
RED.nodes.dirty(true); RED.nodes.dirty(true);
} }
@@ -2703,7 +2697,7 @@ RED.view = (function() {
} }
} }
function copySelection() { function copySelection(isCut) {
if (mouse_mode === RED.state.SELECTING_NODE) { if (mouse_mode === RED.state.SELECTING_NODE) {
return; return;
} }
@@ -2767,6 +2761,7 @@ RED.view = (function() {
} }
} }
clipboard = JSON.stringify(nns); clipboard = JSON.stringify(nns);
clipboardSource = isCut ? 'cut' : 'copy'
RED.menu.setDisabled("menu-item-edit-paste", false); RED.menu.setDisabled("menu-item-edit-paste", false);
if (nodeCount > 0) { if (nodeCount > 0) {
RED.notify(RED._("clipboard.nodeCopied",{count:nodeCount}),{id:"clipboard"}); RED.notify(RED._("clipboard.nodeCopied",{count:nodeCount}),{id:"clipboard"});
@@ -3286,11 +3281,17 @@ RED.view = (function() {
if (active && ((portType === PORT_TYPE_INPUT && ((d._def && d._def.inputLabels)||d.inputLabels)) || (portType === PORT_TYPE_OUTPUT && ((d._def && d._def.outputLabels)||d.outputLabels)))) { if (active && ((portType === PORT_TYPE_INPUT && ((d._def && d._def.inputLabels)||d.inputLabels)) || (portType === PORT_TYPE_OUTPUT && ((d._def && d._def.outputLabels)||d.outputLabels)))) {
portLabelHoverTimeout = setTimeout(function() { portLabelHoverTimeout = setTimeout(function() {
const n = port && port.node()
const nId = n && n.__data__ && n.__data__.id
//check see if node has been deleted since timeout started
if(!n || !n.parentNode || !RED.nodes.node(n.__data__.id)) {
return; //node is gone!
}
var tooltip = getPortLabel(d,portType,portIndex); var tooltip = getPortLabel(d,portType,portIndex);
if (!tooltip) { if (!tooltip) {
return; return;
} }
var pos = getElementPosition(port.node()); var pos = getElementPosition(n);
portLabelHoverTimeout = null; portLabelHoverTimeout = null;
portLabelHover = showTooltip( portLabelHover = showTooltip(
(pos[0]+(portType===PORT_TYPE_INPUT?-2:12)), (pos[0]+(portType===PORT_TYPE_INPUT?-2:12)),
@@ -3477,6 +3478,9 @@ RED.view = (function() {
updateSelection(); updateSelection();
RED.nodes.dirty(true); RED.nodes.dirty(true);
redraw(); redraw();
if (clipboardSource === 'cut') {
clipboardSource = 'copy'
}
resetMouseVars(); resetMouseVars();
d3.event.stopPropagation(); d3.event.stopPropagation();
return; return;
@@ -3687,13 +3691,12 @@ RED.view = (function() {
} }
function nodeTouchStart(d) { function nodeTouchStart(d) {
if (RED.view.DEBUG) { console.warn("nodeTouchStart", mouse_mode,d); } if (RED.view.DEBUG) { console.warn("nodeTouchStart", mouse_mode,d); }
var obj = d3.select(this);
var touch0 = d3.event.touches.item(0); var touch0 = d3.event.touches.item(0);
var pos = [touch0.pageX,touch0.pageY]; var pos = [touch0.pageX,touch0.pageY];
startTouchCenter = [touch0.pageX,touch0.pageY]; startTouchCenter = [touch0.pageX,touch0.pageY];
startTouchDistance = 0; startTouchDistance = 0;
touchStartTime = setTimeout(function() { touchStartTime = setTimeout(function() {
showTouchMenu(obj,pos); showTouchMenu(this,pos);
},touchLongPressTimeout); },touchLongPressTimeout);
nodeMouseDown.call(this,d) nodeMouseDown.call(this,d)
d3.event.preventDefault(); d3.event.preventDefault();
@@ -3724,6 +3727,10 @@ RED.view = (function() {
if (d.hasOwnProperty('l')?!d.l : (d.type === "link in" || d.type === "link out")) { if (d.hasOwnProperty('l')?!d.l : (d.type === "link in" || d.type === "link out")) {
var parentNode = this.parentNode; var parentNode = this.parentNode;
portLabelHoverTimeout = setTimeout(function() { portLabelHoverTimeout = setTimeout(function() {
//check see if node has been deleted since timeout started
if(!parentNode || !parentNode.parentNode || !RED.nodes.node(parentNode.id)) {
return; //node is gone!
}
var tooltip; var tooltip;
if (d._def.label) { if (d._def.label) {
tooltip = d._def.label; tooltip = d._def.label;
@@ -3848,12 +3855,11 @@ RED.view = (function() {
focusView(); focusView();
d3.event.stopPropagation(); d3.event.stopPropagation();
var obj = d3.select(document.body);
var touch0 = d3.event.touches.item(0); var touch0 = d3.event.touches.item(0);
var pos = [touch0.pageX,touch0.pageY]; var pos = [touch0.pageX,touch0.pageY];
touchStartTime = setTimeout(function() { touchStartTime = setTimeout(function() {
touchStartTime = null; touchStartTime = null;
showTouchMenu(obj,pos); showTouchMenu(document.body,pos);
},touchLongPressTimeout); },touchLongPressTimeout);
d3.event.preventDefault(); d3.event.preventDefault();
} }
@@ -4086,7 +4092,7 @@ RED.view = (function() {
var mdn = mousedown_node; var mdn = mousedown_node;
var options = []; var options = [];
options.push({name:"delete",disabled:(movingSet.length()===0 && selectedLinks.length() === 0),onselect:function() {deleteSelection();}}); options.push({name:"delete",disabled:(movingSet.length()===0 && selectedLinks.length() === 0),onselect:function() {deleteSelection();}});
options.push({name:"cut",disabled:(movingSet.length()===0),onselect:function() {copySelection();deleteSelection();}}); options.push({name:"cut",disabled:(movingSet.length()===0),onselect:function() {copySelection(true);deleteSelection();}});
options.push({name:"copy",disabled:(movingSet.length()===0),onselect:function() {copySelection();}}); options.push({name:"copy",disabled:(movingSet.length()===0),onselect:function() {copySelection();}});
options.push({name:"paste",disabled:(clipboard.length===0),onselect:function() {importNodes(clipboard, {generateIds: true, touchImport: true});}}); options.push({name:"paste",disabled:(clipboard.length===0),onselect:function() {importNodes(clipboard, {generateIds: true, touchImport: true});}});
options.push({name:"edit",disabled:(movingSet.length() != 1),onselect:function() { RED.editor.edit(mdn);}}); options.push({name:"edit",disabled:(movingSet.length() != 1),onselect:function() { RED.editor.edit(mdn);}});
@@ -4227,13 +4233,14 @@ RED.view = (function() {
d.resize = true; d.resize = true;
d.dirty = true; d.dirty = true;
var mainRect = document.createElementNS("http://www.w3.org/2000/svg","rect"); var mainRect = RED.utils.createSVGElement("rect", {
class: "red-ui-flow-subflow-port",
rx: 8,
ry: 8,
width: 40,
height: 40,
})
mainRect.__data__ = d; mainRect.__data__ = d;
mainRect.setAttribute("class", "red-ui-flow-subflow-port");
mainRect.setAttribute("rx", 8);
mainRect.setAttribute("ry", 8);
mainRect.setAttribute("width", 40);
mainRect.setAttribute("height", 40);
node[0][0].__mainRect__ = mainRect; node[0][0].__mainRect__ = mainRect;
d3.select(mainRect) d3.select(mainRect)
.on("mouseup",nodeMouseUp) .on("mouseup",nodeMouseUp)
@@ -4242,50 +4249,50 @@ RED.view = (function() {
.on("touchend",nodeTouchEnd) .on("touchend",nodeTouchEnd)
nodeContents.appendChild(mainRect); nodeContents.appendChild(mainRect);
var output_groupEl = document.createElementNS("http://www.w3.org/2000/svg","g"); var output_groupEl = RED.utils.createSVGElement("g", { x: 0, y: 0 })
output_groupEl.setAttribute("x",0);
output_groupEl.setAttribute("y",0);
node[0][0].__outputLabelGroup__ = output_groupEl; node[0][0].__outputLabelGroup__ = output_groupEl;
var output_output = document.createElementNS("http://www.w3.org/2000/svg","text"); var output_output = RED.utils.createSVGElement("text", { class: "red-ui-flow-port-label" })
output_output.setAttribute("class","red-ui-flow-port-label");
output_output.style["font-size"] = "10px"; output_output.style["font-size"] = "10px";
output_output.textContent = "output"; output_output.textContent = "output";
output_groupEl.appendChild(output_output); output_groupEl.appendChild(output_output);
node[0][0].__outputOutput__ = output_output; node[0][0].__outputOutput__ = output_output;
var output_number = document.createElementNS("http://www.w3.org/2000/svg","text"); var output_number = RED.utils.createSVGElement("text", {
output_number.setAttribute("class","red-ui-flow-port-label red-ui-flow-port-index"); class: "red-ui-flow-port-label red-ui-flow-port-index",
output_number.setAttribute("x",0); x: 0,
output_number.setAttribute("y",0); y: 0
})
output_number.textContent = d.i+1; output_number.textContent = d.i+1;
output_groupEl.appendChild(output_number); output_groupEl.appendChild(output_number);
node[0][0].__outputNumber__ = output_number; node[0][0].__outputNumber__ = output_number;
var output_border = document.createElementNS("http://www.w3.org/2000/svg","path"); var output_border = RED.utils.createSVGElement("path", {
output_border.setAttribute("d","M 40 1 l 0 38") d: "M 40 1 l 0 38",
output_border.setAttribute("class", "red-ui-flow-node-icon-shade-border") class: "red-ui-flow-node-icon-shade-border"
})
output_groupEl.appendChild(output_border); output_groupEl.appendChild(output_border);
node[0][0].__outputBorder__ = output_border; node[0][0].__outputBorder__ = output_border;
nodeContents.appendChild(output_groupEl); nodeContents.appendChild(output_groupEl);
var text = document.createElementNS("http://www.w3.org/2000/svg","g"); var text = RED.utils.createSVGElement("g", {
text.setAttribute("class","red-ui-flow-port-label"); class: "red-ui-flow-port-label",
text.setAttribute("transform","translate(38,0)"); transform: "translate(38,0)",
text.setAttribute('style', 'fill : #888'); // hard coded here! style: 'fill : #888' // hard coded here!
})
node[0][0].__textGroup__ = text; node[0][0].__textGroup__ = text;
nodeContents.append(text); nodeContents.append(text);
var portEl = document.createElementNS("http://www.w3.org/2000/svg","g"); var portEl = RED.utils.createSVGElement("g", { transform: 'translate(-5,15)'})
portEl.setAttribute('transform','translate(-5,15)')
var port = document.createElementNS("http://www.w3.org/2000/svg","rect"); var port = RED.utils.createSVGElement("rect", {
port.setAttribute("class","red-ui-flow-port"); class: "red-ui-flow-port",
port.setAttribute("rx",3); rx: 3,
port.setAttribute("ry",3); ry: 3,
port.setAttribute("width",10); width: 10,
port.setAttribute("height",10); height: 10
})
portEl.appendChild(port); portEl.appendChild(port);
port.__data__ = d; port.__data__ = d;
@@ -4414,10 +4421,11 @@ RED.view = (function() {
} }
for (var i=0; i<sn; i++) { for (var i=0; i<sn; i++) {
if (i===textLines.length) { if (i===textLines.length) {
var line = document.createElementNS("http://www.w3.org/2000/svg","text"); var line = RED.utils.createSVGElement("text", {
line.setAttribute("class","red-ui-flow-node-label-text"); class: "red-ui-flow-node-label-text",
line.setAttribute("x",0); x: 0,
line.setAttribute("y",i*24); y: i*24
});
this.__textGroup__.appendChild(line); this.__textGroup__.appendChild(line);
} }
textLines[i].textContent = sa[i]; textLines[i].textContent = sa[i];
@@ -4487,32 +4495,35 @@ RED.view = (function() {
d.resize = true; d.resize = true;
if (d._def.button) { if (d._def.button) {
var buttonGroup = document.createElementNS("http://www.w3.org/2000/svg","g"); var buttonGroup = RED.utils.createSVGElement("g", {
class: "red-ui-flow-node-button",
transform: "translate("+((d._def.align == "right") ? 94 : -25)+",2)"
})
buttonGroup.__data__ = d; buttonGroup.__data__ = d;
buttonGroup.setAttribute("transform", "translate("+((d._def.align == "right") ? 94 : -25)+",2)");
buttonGroup.setAttribute("class","red-ui-flow-node-button");
node[0][0].__buttonGroup__ = buttonGroup; node[0][0].__buttonGroup__ = buttonGroup;
var bgBackground = document.createElementNS("http://www.w3.org/2000/svg","rect"); var bgBackground = RED.utils.createSVGElement("rect", {
class: "red-ui-flow-node-button-background",
rx: 5,
ry: 5,
width: 32,
height: node_height-4
})
bgBackground.__data__ = d; bgBackground.__data__ = d;
bgBackground.setAttribute("class","red-ui-flow-node-button-background");
bgBackground.setAttribute("rx",5);
bgBackground.setAttribute("ry",5);
bgBackground.setAttribute("width",32);
bgBackground.setAttribute("height",node_height-4);
buttonGroup.appendChild(bgBackground); buttonGroup.appendChild(bgBackground);
node[0][0].__buttonGroupBackground__ = bgBackground; node[0][0].__buttonGroupBackground__ = bgBackground;
var bgButton = document.createElementNS("http://www.w3.org/2000/svg","rect"); var bgButton = RED.utils.createSVGElement("rect", {
class: "red-ui-flow-node-button-button",
x: d._def.align == "right"? 11:5,
y: 4,
rx: 4,
ry: 4,
width: 16,
height: node_height-12,
fill: RED.utils.getNodeColor(d.type,d._def)
})
bgButton.__data__ = d; bgButton.__data__ = d;
bgButton.setAttribute("class","red-ui-flow-node-button-button");
bgButton.setAttribute("x", d._def.align == "right"? 11:5);
bgButton.setAttribute("y",4);
bgButton.setAttribute("rx",4);
bgButton.setAttribute("ry",4);
bgButton.setAttribute("width",16);
bgButton.setAttribute("height",node_height-12);
bgButton.setAttribute("fill", RED.utils.getNodeColor(d.type,d._def));
d3.select(bgButton) d3.select(bgButton)
.on("mousedown",function(d) {if (!lasso && isButtonEnabled(d)) {focusView();d3.select(this).attr("fill-opacity",0.2);d3.event.preventDefault(); d3.event.stopPropagation();}}) .on("mousedown",function(d) {if (!lasso && isButtonEnabled(d)) {focusView();d3.select(this).attr("fill-opacity",0.2);d3.event.preventDefault(); d3.event.stopPropagation();}})
.on("mouseup",function(d) {if (!lasso && isButtonEnabled(d)) { d3.select(this).attr("fill-opacity",0.4);d3.event.preventDefault();d3.event.stopPropagation();}}) .on("mouseup",function(d) {if (!lasso && isButtonEnabled(d)) { d3.select(this).attr("fill-opacity",0.4);d3.event.preventDefault();d3.event.stopPropagation();}})
@@ -4533,12 +4544,13 @@ RED.view = (function() {
} }
var mainRect = document.createElementNS("http://www.w3.org/2000/svg","rect"); var mainRect = RED.utils.createSVGElement("rect", {
class: "red-ui-flow-node "+(d.type == "unknown"?"red-ui-flow-node-unknown":""),
rx: 5,
ry: 5,
fill: RED.utils.getNodeColor(d.type,d._def)
})
mainRect.__data__ = d; mainRect.__data__ = d;
mainRect.setAttribute("class", "red-ui-flow-node "+(d.type == "unknown"?"red-ui-flow-node-unknown":""));
mainRect.setAttribute("rx", 5);
mainRect.setAttribute("ry", 5);
mainRect.setAttribute("fill", RED.utils.getNodeColor(d.type,d._def));
node[0][0].__mainRect__ = mainRect; node[0][0].__mainRect__ = mainRect;
d3.select(mainRect) d3.select(mainRect)
.on("mouseup",nodeMouseUp) .on("mouseup",nodeMouseUp)
@@ -4553,63 +4565,65 @@ RED.view = (function() {
if (d._def.icon) { if (d._def.icon) {
var icon_url = RED.utils.getNodeIcon(d._def,d); var icon_url = RED.utils.getNodeIcon(d._def,d);
var icon_groupEl = document.createElementNS("http://www.w3.org/2000/svg","g"); var icon_groupEl = RED.utils.createSVGElement("g", {
icon_groupEl.__data__ = d; class: "red-ui-flow-node-icon-group"+("right" == d._def.align?" red-ui-flow-node-icon-group-right":""),
icon_groupEl.setAttribute("class","red-ui-flow-node-icon-group"+("right" == d._def.align?" red-ui-flow-node-icon-group-right":"")); x: 0,
icon_groupEl.setAttribute("x",0); y: 0
icon_groupEl.setAttribute("y",0); })
icon_groupEl.style["pointer-events"] = "none"; icon_groupEl.style["pointer-events"] = "none";
icon_groupEl.__data__ = d;
node[0][0].__iconGroup__ = icon_groupEl; node[0][0].__iconGroup__ = icon_groupEl;
var icon_shade = document.createElementNS("http://www.w3.org/2000/svg","rect"); var icon_shade = RED.utils.createSVGElement("path", {
icon_shade.setAttribute("x",0); x: 0,
icon_shade.setAttribute("y",0); y: 0,
icon_shade.setAttribute("class","red-ui-flow-node-icon-shade") class: "red-ui-flow-node-icon-shade"
icon_shade.setAttribute("width",30); })
icon_shade.setAttribute("height",Math.min(50,d.h-4));
icon_groupEl.appendChild(icon_shade); icon_groupEl.appendChild(icon_shade);
node[0][0].__iconShade__ = icon_shade; node[0][0].__iconShade__ = icon_shade;
var icon_group = d3.select(icon_groupEl) var icon_group = d3.select(icon_groupEl)
createIconAttributes(icon_url, icon_group, d); createIconAttributes(icon_url, icon_group, d);
var icon_shade_border = document.createElementNS("http://www.w3.org/2000/svg","path"); var icon_shade_border = RED.utils.createSVGElement("path", {
icon_shade_border.setAttribute("d","right" != d._def.align ? "M 30 1 l 0 "+(d.h-2) : "M 0 1 l 0 "+(d.h-2) ) d: "right" != d._def.align ? "M 30 1 l 0 "+(d.h-2) : "M 0 1 l 0 "+(d.h-2),
icon_shade_border.setAttribute("class", "red-ui-flow-node-icon-shade-border") class: "red-ui-flow-node-icon-shade-border"
})
icon_groupEl.appendChild(icon_shade_border); icon_groupEl.appendChild(icon_shade_border);
node[0][0].__iconShadeBorder__ = icon_shade_border; node[0][0].__iconShadeBorder__ = icon_shade_border;
nodeContents.appendChild(icon_groupEl); nodeContents.appendChild(icon_groupEl);
} }
var text = document.createElementNS("http://www.w3.org/2000/svg","g"); var text = RED.utils.createSVGElement("g", {
text.setAttribute("class","red-ui-flow-node-label"+(hideLabel?" hide":"")+(d._def.align?" red-ui-flow-node-label-"+d._def.align:"")); class: "red-ui-flow-node-label"+(hideLabel?" hide":"")+(d._def.align?" red-ui-flow-node-label-"+d._def.align:""),
text.setAttribute("transform","translate(38,0)"); transform: "translate(38,0)"
// text.setAttribute("dy", ".3px"); // dy: ".3px",
// text.setAttribute("text-anchor",d._def.align !== "right" ? "start":"end"); // "text-anchor": d._def.align !== "right" ? "start":"end"
})
nodeContents.appendChild(text); nodeContents.appendChild(text);
node[0][0].__textGroup__ = text; node[0][0].__textGroup__ = text;
var statusEl = document.createElementNS("http://www.w3.org/2000/svg","g"); var statusEl = RED.utils.createSVGElement("g", { class: "red-ui-flow-node-status-group" })
// statusEl.__data__ = d;
statusEl.setAttribute("class","red-ui-flow-node-status-group");
statusEl.style.display = "none"; statusEl.style.display = "none";
node[0][0].__statusGroup__ = statusEl; node[0][0].__statusGroup__ = statusEl;
var statusRect = document.createElementNS("http://www.w3.org/2000/svg","rect"); var statusRect = RED.utils.createSVGElement("rect", {
statusRect.setAttribute("class","red-ui-flow-node-status"); class: "red-ui-flow-node-status",
statusRect.setAttribute("x",6); x: 6,
statusRect.setAttribute("y",1); y: 1,
statusRect.setAttribute("width",9); width: 9,
statusRect.setAttribute("height",9); height: 9,
statusRect.setAttribute("rx",2); rx: 2,
statusRect.setAttribute("ry",2); ry: 2,
statusRect.setAttribute("stroke-width","3"); "stroke-width": 3
})
statusEl.appendChild(statusRect); statusEl.appendChild(statusRect);
node[0][0].__statusShape__ = statusRect; node[0][0].__statusShape__ = statusRect;
var statusLabel = document.createElementNS("http://www.w3.org/2000/svg","text"); var statusLabel = RED.utils.createSVGElement("text", {
statusLabel.setAttribute("class","red-ui-flow-node-status-label"); class: "red-ui-flow-node-status-label",
statusLabel.setAttribute("x",20); x: 20,
statusLabel.setAttribute("y",10); y: 10
})
statusEl.appendChild(statusLabel); statusEl.appendChild(statusLabel);
node[0][0].__statusLabel__ = statusLabel; node[0][0].__statusLabel__ = statusLabel;
@@ -4694,10 +4708,11 @@ RED.view = (function() {
} }
for (var i=0; i<sn; i++) { for (var i=0; i<sn; i++) {
if (i===textLines.length) { if (i===textLines.length) {
var line = document.createElementNS("http://www.w3.org/2000/svg","text"); var line = RED.utils.createSVGElement("text", {
line.setAttribute("class","red-ui-flow-node-label-text"); class: "red-ui-flow-node-label-text",
line.setAttribute("x",0); x: 0,
line.setAttribute("y",i*24); y: i*24
})
this.__textGroup__.appendChild(line); this.__textGroup__.appendChild(line);
} }
textLines[i].textContent = sa[i]; textLines[i].textContent = sa[i];
@@ -4796,22 +4811,23 @@ RED.view = (function() {
for(var portIndex = 0; portIndex < numOutputs; portIndex++ ) { for(var portIndex = 0; portIndex < numOutputs; portIndex++ ) {
var portGroup; var portGroup;
if (portIndex === this.__outputs__.length) { if (portIndex === this.__outputs__.length) {
portGroup = document.createElementNS("http://www.w3.org/2000/svg","g"); portGroup = RED.utils.createSVGElement("g", { class: "red-ui-flow-port-output" })
portGroup.setAttribute("class","red-ui-flow-port-output");
var portPort; var portPort;
if (d.type === "link out") { if (d.type === "link out") {
portPort = document.createElementNS("http://www.w3.org/2000/svg","circle"); portPort = RED.utils.createSVGElement("circle", {
portPort.setAttribute("cx",11); cx: 11,
portPort.setAttribute("cy",5); cy: 5,
portPort.setAttribute("r",5); r: 5,
portPort.setAttribute("class","red-ui-flow-port red-ui-flow-link-port"); class: "red-ui-flow-port red-ui-flow-link-port"
})
} else { } else {
portPort = document.createElementNS("http://www.w3.org/2000/svg","rect"); portPort = RED.utils.createSVGElement("rect", {
portPort.setAttribute("rx",3); rx: 3,
portPort.setAttribute("ry",3); ry: 3,
portPort.setAttribute("width",10); width: 10,
portPort.setAttribute("height",10); height: 10,
portPort.setAttribute("class","red-ui-flow-port"); class: "red-ui-flow-port"
})
} }
portGroup.appendChild(portPort); portGroup.appendChild(portPort);
portGroup.__port__ = portPort; portGroup.__port__ = portPort;
@@ -4858,9 +4874,20 @@ RED.view = (function() {
} }
icon.attr("y",function(){return (d.h-d3.select(this).attr("height"))/2;}); icon.attr("y",function(){return (d.h-d3.select(this).attr("height"))/2;});
this.__iconShade__.setAttribute("height", d.h );
const iconShadeHeight = d.h
const iconShadeWidth = 30
this.__iconShade__.setAttribute("d", hideLabel ?
`M5 0 h${iconShadeWidth-10} a 5 5 0 0 1 5 5 v${iconShadeHeight-10} a 5 5 0 0 1 -5 5 h-${iconShadeWidth-10} a 5 5 0 0 1 -5 -5 v-${iconShadeHeight-10} a 5 5 0 0 1 5 -5` : (
"right" === d._def.align ?
`M 0 0 h${iconShadeWidth-5} a 5 5 0 0 1 5 5 v${iconShadeHeight-10} a 5 5 0 0 1 -5 5 h-${iconShadeWidth-5} v-${iconShadeHeight}` :
`M5 0 h${iconShadeWidth-5} v${iconShadeHeight} h-${iconShadeWidth-5} a 5 5 0 0 1 -5 -5 v-${iconShadeHeight-10} a 5 5 0 0 1 5 -5`
)
)
this.__iconShadeBorder__.style.display = hideLabel?'none':''
this.__iconShadeBorder__.setAttribute("d", this.__iconShadeBorder__.setAttribute("d",
"M " + (((!d._def.align && d.inputs !== 0 && d.outputs === 0) || "right" === d._def.align) ? 0 : 30) + " 1 l 0 " + (d.h - 2) "M " + (((!d._def.align && d.inputs !== 0 && d.outputs === 0) || "right" === d._def.align) ? 0.5 : 29.5) + " "+(d.selected?1:0.5)+" l 0 " + (d.h - (d.selected?2:1))
); );
faIcon.attr("y",(d.h+13)/2); faIcon.attr("y",(d.h+13)/2);
} }
@@ -4952,26 +4979,28 @@ RED.view = (function() {
var junction = d3.select(this); var junction = d3.select(this);
var contents = document.createDocumentFragment(); var contents = document.createDocumentFragment();
// d.added = true; // d.added = true;
var junctionBack = document.createElementNS("http://www.w3.org/2000/svg","rect"); var junctionBack = RED.utils.createSVGElement("rect", {
junctionBack.setAttribute("class","red-ui-flow-junction-background"); class: "red-ui-flow-junction-background",
junctionBack.setAttribute("x",-5); x: -5,
junctionBack.setAttribute("y",-5); y: -5,
junctionBack.setAttribute("width",10); width: 10,
junctionBack.setAttribute("height",10); height: 10,
junctionBack.setAttribute("rx",3); rx: 3,
junctionBack.setAttribute("ry",3); ry: 3
})
junctionBack.__data__ = d; junctionBack.__data__ = d;
this.__junctionBack__ = junctionBack; this.__junctionBack__ = junctionBack;
contents.appendChild(junctionBack); contents.appendChild(junctionBack);
var junctionInput = document.createElementNS("http://www.w3.org/2000/svg","rect"); var junctionInput = RED.utils.createSVGElement("rect", {
junctionInput.setAttribute("class","red-ui-flow-junction-port red-ui-flow-junction-port-input"); class: "red-ui-flow-junction-port red-ui-flow-junction-port-input",
junctionInput.setAttribute("x",-5); x: -5,
junctionInput.setAttribute("y",-5); y: -5,
junctionInput.setAttribute("width",10); width: 10,
junctionInput.setAttribute("height",10); height: 10,
junctionInput.setAttribute("rx",3); rx: 3,
junctionInput.setAttribute("ry",3); ry: 3
})
junctionInput.__data__ = d; junctionInput.__data__ = d;
junctionInput.__portType__ = PORT_TYPE_INPUT; junctionInput.__portType__ = PORT_TYPE_INPUT;
junctionInput.__portIndex__ = 0; junctionInput.__portIndex__ = 0;
@@ -4983,14 +5012,15 @@ RED.view = (function() {
this.__junctionInput__ = junctionInput; this.__junctionInput__ = junctionInput;
contents.appendChild(junctionInput); contents.appendChild(junctionInput);
var junctionOutput = document.createElementNS("http://www.w3.org/2000/svg","rect"); var junctionOutput = RED.utils.createSVGElement("rect", {
junctionOutput.setAttribute("class","red-ui-flow-junction-port red-ui-flow-junction-port-output"); class: "red-ui-flow-junction-port red-ui-flow-junction-port-output",
junctionOutput.setAttribute("x",-5); x: -5,
junctionOutput.setAttribute("y",-5); y: -5,
junctionOutput.setAttribute("width",10); width: 10,
junctionOutput.setAttribute("height",10); height: 10,
junctionOutput.setAttribute("rx",3); rx: 3,
junctionOutput.setAttribute("ry",3); ry: 3,
})
junctionOutput.__data__ = d; junctionOutput.__data__ = d;
junctionOutput.__portType__ = PORT_TYPE_OUTPUT; junctionOutput.__portType__ = PORT_TYPE_OUTPUT;
junctionOutput.__portIndex__ = 0; junctionOutput.__portIndex__ = 0;
@@ -5047,9 +5077,8 @@ RED.view = (function() {
var pathContents = document.createDocumentFragment(); var pathContents = document.createDocumentFragment();
d.added = true; d.added = true;
var pathBack = document.createElementNS("http://www.w3.org/2000/svg","path"); var pathBack = RED.utils.createSVGElement("path", { class: "red-ui-flow-link-background red-ui-flow-link-path"+(d.link?" red-ui-flow-link-link":"")})
pathBack.__data__ = d; pathBack.__data__ = d;
pathBack.setAttribute("class","red-ui-flow-link-background red-ui-flow-link-path"+(d.link?" red-ui-flow-link-link":""));
this.__pathBack__ = pathBack; this.__pathBack__ = pathBack;
pathContents.appendChild(pathBack); pathContents.appendChild(pathBack);
d3.select(pathBack) d3.select(pathBack)
@@ -5085,16 +5114,17 @@ RED.view = (function() {
} }
}) })
var pathOutline = document.createElementNS("http://www.w3.org/2000/svg","path"); var pathOutline = RED.utils.createSVGElement("path", {
class: "red-ui-flow-link-outline red-ui-flow-link-path"
})
pathOutline.__data__ = d; pathOutline.__data__ = d;
pathOutline.setAttribute("class","red-ui-flow-link-outline red-ui-flow-link-path");
this.__pathOutline__ = pathOutline; this.__pathOutline__ = pathOutline;
pathContents.appendChild(pathOutline); pathContents.appendChild(pathOutline);
var pathLine = document.createElementNS("http://www.w3.org/2000/svg","path"); var pathLine = RED.utils.createSVGElement("path", {
class: "red-ui-flow-link-line red-ui-flow-link-path"+(d.link?" red-ui-flow-link-link":(activeSubflow?" red-ui-flow-subflow-link":""))
})
pathLine.__data__ = d; pathLine.__data__ = d;
pathLine.setAttribute("class","red-ui-flow-link-line red-ui-flow-link-path"+
(d.link?" red-ui-flow-link-link":(activeSubflow?" red-ui-flow-subflow-link":"")));
this.__pathLine__ = pathLine; this.__pathLine__ = pathLine;
pathContents.appendChild(pathLine); pathContents.appendChild(pathLine);
@@ -6236,6 +6266,12 @@ RED.view = (function() {
showQuickAddDialog:showQuickAddDialog, showQuickAddDialog:showQuickAddDialog,
calculateNodeDimensions: calculateNodeDimensions, calculateNodeDimensions: calculateNodeDimensions,
getElementPosition:getElementPosition, getElementPosition:getElementPosition,
showTooltip:showTooltip showTooltip:showTooltip,
dimensions: function() {
return {
width: space_width,
height: space_height
};
}
}; };
})(); })();

View File

@@ -217,6 +217,7 @@ $node-icon-border-color: #000;
$node-icon-border-color-opacity: 0.1; $node-icon-border-color-opacity: 0.1;
$node-config-background: #f3f3f3; $node-config-background: #f3f3f3;
$node-config-icon-container-disabled: #aaa;
$node-link-port-background: #eee; $node-link-port-background: #eee;

View File

@@ -63,11 +63,14 @@
padding: 4px 12px 4px 12px; padding: 4px 12px 4px 12px;
} }
&.red-ui-menu-dropdown-submenus > li > a, &.red-ui-menu-dropdown-submenus.red-ui-menu-dropdown-direction-right > li > a,
&.red-ui-menu-dropdown-submenus > li > a:focus { &.red-ui-menu-dropdown-submenus.red-ui-menu-dropdown-direction-right > li > a:focus {
padding-right: 20px; padding-right: 20px;
} }
&.red-ui-menu-dropdown-submenus.red-ui-menu-dropdown-direction-left > li > a,
&.red-ui-menu-dropdown-submenus.red-ui-menu-dropdown-direction-left > li > a:focus {
padding-left: 20px;
}
& > .active > a, & > .active > a,
@@ -199,7 +202,7 @@
width: 0; width: 0;
height: 0; height: 0;
margin-top: 5px; margin-top: 5px;
margin-left: -30px; margin-left: -15px;
/* Caret Arrow */ /* Caret Arrow */
border-color: transparent; border-color: transparent;
border-right-color: var(--red-ui-menuCaret); border-right-color: var(--red-ui-menuCaret);
@@ -220,7 +223,7 @@
margin-right: -15px; margin-right: -15px;
/* Caret Arrow */ /* Caret Arrow */
border-color: transparent; border-color: transparent;
border-left-color: $menuCaret; border-left-color: var(--red-ui-menuCaret);
border-style: solid; border-style: solid;
border-width: 5px 0 5px 5px; border-width: 5px 0 5px 5px;
content: " "; content: " ";

View File

@@ -191,7 +191,7 @@
margin-top: 0; margin-top: 0;
li a { li a {
color: var(--red-ui-header-menu-color); color: var(--red-ui-header-menu-color);
padding: 3px 10px 3px 40px; padding: 3px 10px 3px 30px;
img { img {
max-width: 100%; max-width: 100%;
margin-right: 10px; margin-right: 10px;
@@ -243,6 +243,7 @@
} }
.red-ui-menu-dropdown-submenu>a:before { .red-ui-menu-dropdown-submenu>a:before {
border-right-color: var(--red-ui-headerMenuCaret); border-right-color: var(--red-ui-headerMenuCaret);
margin-left: -25px !important;
} }
/* Deploy menu customisations */ /* Deploy menu customisations */

View File

@@ -171,6 +171,7 @@
left:0; left:0;
width: 30px; width: 30px;
border-right: 1px solid var(--red-ui-node-icon-background-color); border-right: 1px solid var(--red-ui-node-icon-background-color);
border-radius: 4px 0px 0px 4px;
background-color: var(--red-ui-node-icon-background-color); background-color: var(--red-ui-node-icon-background-color);
} }
.red-ui-palette-icon-container-right { .red-ui-palette-icon-container-right {
@@ -178,6 +179,7 @@
right: 0; right: 0;
border-right: none; border-right: none;
border-left: 1px solid var(--red-ui-node-icon-background-color); border-left: 1px solid var(--red-ui-node-icon-background-color);
border-radius: 0px 4px 4px 0px;
} }
.red-ui-palette-icon { .red-ui-palette-icon {
display: inline-block; display: inline-block;

View File

@@ -711,7 +711,9 @@
transform: rotate(90deg); transform: rotate(90deg);
} }
} }
.red-ui-projects-dialog-file-list-entry-file-type-git { color: $tertiary-text-color } .red-ui-projects-dialog-file-list-entry-file-type-git {
color: var(--red-ui-tertiary-text-color);
}
.red-ui-projects-dialog-remote-list { .red-ui-projects-dialog-remote-list {
.red-ui-editableList-container { .red-ui-editableList-container {

View File

@@ -84,7 +84,7 @@
.red-ui-search-result-node-port { .red-ui-search-result-node-port {
position: absolute; position: absolute;
border-radius: 2px; border-radius: 2px;
border: 1px solid $node-border; border: 1px solid var(--red-ui-node-border);
width: 6px; width: 6px;
height: 7px; height: 7px;
top:4px; top:4px;

View File

@@ -54,6 +54,9 @@ ul.red-ui-sidebar-node-config-list {
white-space: nowrap; white-space: nowrap;
overflow: hidden; overflow: hidden;
text-overflow: ellipsis; text-overflow: ellipsis;
&:not(:last-child) {
width: calc(100% - 38px);
}
} }
.red-ui-palette-icon-container { .red-ui-palette-icon-container {
font-size: 12px; font-size: 12px;
@@ -98,15 +101,15 @@ ul.red-ui-sidebar-node-config-list li.red-ui-palette-node-config-type {
} }
.red-ui-palette-node-config-unused,.red-ui-palette-node-config-disabled { .red-ui-palette-node-config-unused,.red-ui-palette-node-config-disabled {
border-color: var(--red-ui-primary-border-color); border-color: var(--red-ui-primary-border-color);
background: var(--red-ui-secondary-background-inactive); background: var(--red-ui-node-config-background);
border-style: dashed; border-style: dashed;
color: var(--red-ui-tertiary-text-color); color: var(--red-ui-node-config-icon-container-disabled);
} }
.red-ui-palette-node-config-disabled { .red-ui-palette-node-config-disabled {
opacity: 0.6; opacity: 0.6;
font-style: italic; font-style: italic;
i { i {
color: var(--red-ui-secondary-text-color); color: var(--red-ui-node-port-label-color);
margin-right: 5px; margin-right: 5px;
} }
} }

View File

@@ -203,6 +203,7 @@
--red-ui-node-icon-border-color-opacity: #{$node-icon-border-color-opacity}; --red-ui-node-icon-border-color-opacity: #{$node-icon-border-color-opacity};
--red-ui-node-config-background: #{$node-config-background}; --red-ui-node-config-background: #{$node-config-background};
--red-ui-node-config-icon-container-disabled: #{$node-config-icon-container-disabled};
--red-ui-node-link-port-background: #{$node-link-port-background}; --red-ui-node-link-port-background: #{$node-link-port-background};

View File

@@ -1,15 +1,15 @@
export default { export default {
version: "3.0.0-beta.4", version: "3.0.0",
steps: [ steps: [
{ {
titleIcon: "fa fa-map-o", titleIcon: "fa fa-map-o",
title: { title: {
"en-US": "Welcome to Node-RED 3.0 Beta 4!", "en-US": "Welcome to Node-RED 3.0!",
"ja": "Node-RED 3.0 ベータ3へようこそ!" "ja": "Node-RED 3.0へようこそ!"
}, },
description: { description: {
"en-US": "<p>This is another final beta release of Node-RED 3.0.</p><p>Let's take a moment to discover the new features in this release.</p>", "en-US": "<p>Let's take a moment to discover the new features in this release.</p>",
"ja": "<p>これはNode-RED 3.0の最後のベータリリースです。</p><p>本リリースの新機能を見つけてみましょう。</p>" "ja": "<p>本リリースの新機能を見つけてみましょう。</p>"
} }
}, },
{ {

View File

@@ -245,44 +245,37 @@
// complete parentage of the node that generated this message. // complete parentage of the node that generated this message.
// flow-id/subflow-A-instance/subflow-B-instance // flow-id/subflow-A-instance/subflow-B-instance
// If it has one id, that is a top level flow // If it has one id, that is a top level flow or config node/global
// each subsequent id is the instance id of a subflow node // each subsequent id is the instance id of a subflow node
// //
pathParts = o.path.split("/"); pathParts = o.path.split("/");
if (pathParts.length === 1) { if (pathParts.length === 1) {
// The source node is on a flow - so can use its id to find // The source node is on a flow or is a global/config - so can use its id to find
sourceNode = RED.nodes.node(o.id); sourceNode = RED.nodes.node(o.id);
} else if (pathParts.length > 1) { } else if (pathParts.length > 1) {
// Highlight the subflow instance node. // Highlight the subflow instance node.
sourceNode = RED.nodes.node(pathParts[1]); sourceNode = RED.nodes.node(pathParts[1]);
} }
const getNodeLabel = (n) => n.name || (typeof n.label === "function" && n.label()) || (typeof n.label === "string" && n.label) || (n.type + ":" + n.id);
pathHierarchy = pathParts.map((id,index) => { pathHierarchy = pathParts.map((id,index) => {
if (index === 0) { if (index === 0) {
return { if (id === "global") {
id: id, return { id: sourceNode.id, label: getNodeLabel(sourceNode) }
label: RED.nodes.workspace(id).label }
} return { id: id, label: RED.nodes.workspace(id).label } //flow id + name
} else { } else {
var instanceNode = RED.nodes.node(id) const instanceNode = RED.nodes.node(id)
return { const pathLabel = (instanceNode.name || RED.nodes.subflow(instanceNode.type.substring(8)).name)
id: id, return { id: id, label: pathLabel }
label: (instanceNode.name || RED.nodes.subflow(instanceNode.type.substring(8)).name)
}
} }
}) })
if (pathParts.length === 1) { if (pathParts.length === 1 && pathParts[0] !== "global") {
pathHierarchy.push({ pathHierarchy.push({ id: o.id, label: getNodeLabel(sourceNode) })
id: o.id,
label: sourceNode.name || sourceNode.type+":"+sourceNode.id
})
} }
if (o._alias) { if (o._alias) {
let aliasNode = RED.nodes.node(o._alias) let aliasNode = RED.nodes.node(o._alias)
if (aliasNode) { if (aliasNode) {
pathHierarchy.push({ pathHierarchy.push({ id: o._alias, label: getNodeLabel(aliasNode) })
id: o._alias,
label: aliasNode.name || aliasNode.type+":"+aliasNode.id
})
} }
} }
} else { } else {

View File

@@ -29,23 +29,23 @@ module.exports = function(RED) {
"use strict"; "use strict";
const crypto = require("crypto"); const crypto = require("crypto");
const targetCache = (function () { const targetCache = (function () {
const registry = { id: {}, name: {} }; let registry = { id: {}, name: {} }
function getIndex(/** @type {[LinkTarget]}*/ targets, id) { function getIndex (/** @type {[LinkTarget]} */ targets, id) {
for (let index = 0; index < (targets || []).length; index++) { for (let index = 0; index < (targets || []).length; index++) {
const element = targets[index]; const element = targets[index]
if (element.id === id) { if (element.id === id) {
return index; return index
} }
} }
return -1; return -1
} }
/** /**
* Generate a target object from a node * Generate a target object from a node
* @param {LinkInNode} node * @param {LinkInNode} node
* @returns {LinkTarget} a link target object * @returns {LinkTarget} a link target object
*/ */
function generateTarget(node) { function generateTarget (node) {
const isSubFlow = node._flow.TYPE === "subflow"; const isSubFlow = node._flow.TYPE === 'subflow'
return { return {
id: node.id, id: node.id,
name: node.name || node.id, name: node.name || node.id,
@@ -58,72 +58,72 @@ module.exports = function(RED) {
/** /**
* Get a list of targets registerd to this name * Get a list of targets registerd to this name
* @param {string} name Name of the target * @param {string} name Name of the target
* @param {boolean} [excludeSubflows] set `true` to exclude * @param {boolean} [excludeSubflows] set `true` to exclude
* @returns {[LinkTarget]} Targets registerd to this name. * @returns {[LinkTarget]} Targets registerd to this name.
*/ */
getTargets(name, excludeSubflows) { getTargets (name, excludeSubflows) {
const targets = registry.name[name] || []; const targets = registry.name[name] || []
if (excludeSubflows) { if (excludeSubflows) {
return targets.filter(e => e.isSubFlow != true); return targets.filter(e => e.isSubFlow !== true)
} }
return targets; return targets
}, },
/** /**
* Get a single target by registered name. * Get a single target by registered name.
* To restrict to a single flow, include the `flowId` * To restrict to a single flow, include the `flowId`
* If there is no targets OR more than one target, null is returned * If there is no targets OR more than one target, null is returned
* @param {string} name Name of the node * @param {string} name Name of the node
* @param {string} [flowId] * @param {string} [flowId]
* @returns {LinkTarget} target * @returns {LinkTarget} target
*/ */
getTarget(name, flowId) { getTarget (name, flowId) {
/** @type {[LinkTarget]}*/ /** @type {[LinkTarget]} */
let possibleTargets = this.getTargets(name); let possibleTargets = this.getTargets(name)
/** @type {LinkTarget}*/ /** @type {LinkTarget} */
let target; let target
if (possibleTargets.length && flowId) { if (possibleTargets.length && flowId) {
possibleTargets = possibleTargets.filter(e => e.flowId == flowId); possibleTargets = possibleTargets.filter(e => e.flowId === flowId)
} }
if (possibleTargets.length === 1) { if (possibleTargets.length === 1) {
target = possibleTargets[0]; target = possibleTargets[0]
} }
return target; return target
}, },
/** /**
* Get a target by node ID * Get a target by node ID
* @param {string} nodeId ID of the node * @param {string} nodeId ID of the node
* @returns {LinkTarget} target * @returns {LinkTarget} target
*/ */
getTargetById(nodeId) { getTargetById (nodeId) {
return registry.id[nodeId]; return registry.id[nodeId]
}, },
register(/** @type {LinkInNode} */ node) { register (/** @type {LinkInNode} */ node) {
const target = generateTarget(node); const target = generateTarget(node)
const tByName = this.getTarget(target.name, target.flowId); const tByName = this.getTarget(target.name, target.flowId)
if (!tByName || tByName.id !== target.id) { if (!tByName || tByName.id !== target.id) {
registry.name[target.name] = registry.name[target.name] || []; registry.name[target.name] = registry.name[target.name] || []
registry.name[target.name].push(target) registry.name[target.name].push(target)
} }
registry.id[target.id] = target; registry.id[target.id] = target
return target; return target
}, },
remove(node) { remove (node) {
const target = generateTarget(node); const target = generateTarget(node)
const targs = this.getTargets(target.name); const targs = this.getTargets(target.name)
const idx = getIndex(targs, target.id); const idx = getIndex(targs, target.id)
if (idx > -1) { if (idx > -1) {
targs.splice(idx, 1); targs.splice(idx, 1)
} }
if (targs.length === 0) { if (targs.length === 0) {
delete registry.name[tn.name]; delete registry.name[target.name]
} }
delete registry.id[target.id]; delete registry.id[target.id]
}, },
clear() { clear () {
registry = { id: {}, name: {} }; registry = { id: {}, name: {} }
} }
} }
})(); })()
function LinkInNode(n) { function LinkInNode(n) {
RED.nodes.createNode(this,n); RED.nodes.createNode(this,n);

View File

@@ -459,30 +459,38 @@ RED.debug = (function() {
function showMessageMenu(button,dbgMessage,sourceId) { function showMessageMenu(button,dbgMessage,sourceId) {
activeMenuMessage = dbgMessage; activeMenuMessage = dbgMessage;
if (!menuOptionMenu) { if (!menuOptionMenu) {
menuOptionMenu = RED.menu.init({id:"red-ui-debug-msg-option-menu", var opts = [
options: [ {id:"red-ui-debug-msg-menu-item-collapse",label:RED._("node-red:debug.messageMenu.collapseAll"),onselect:function(){
{id:"red-ui-debug-msg-menu-item-collapse",label:RED._("node-red:debug.messageMenu.collapseAll"),onselect:function(){ activeMenuMessage.collapse();
activeMenuMessage.collapse(); }},
}}, ];
if (activeMenuMessage.clearPinned) {
opts.push(
{id:"red-ui-debug-msg-menu-item-clear-pins",label:RED._("node-red:debug.messageMenu.clearPinned"),onselect:function(){ {id:"red-ui-debug-msg-menu-item-clear-pins",label:RED._("node-red:debug.messageMenu.clearPinned"),onselect:function(){
activeMenuMessage.clearPinned(); activeMenuMessage.clearPinned();
}}, }},
null, );
{id:"red-ui-debug-msg-menu-item-filter", label:RED._("node-red:debug.messageMenu.filterNode"),onselect:function(){ }
var candidateNodes = RED.nodes.filterNodes({type:'debug'}); opts.push(
candidateNodes.forEach(function(n) { null,
filteredNodes[n.id] = true; {id:"red-ui-debug-msg-menu-item-filter", label:RED._("node-red:debug.messageMenu.filterNode"),onselect:function(){
}); var candidateNodes = RED.nodes.filterNodes({type:'debug'});
delete filteredNodes[sourceId]; candidateNodes.forEach(function(n) {
$("#red-ui-sidebar-debug-filterSelected").trigger("click"); filteredNodes[n.id] = true;
RED.settings.set('debug.filteredNodes',Object.keys(filteredNodes)) });
refreshMessageList(); delete filteredNodes[sourceId];
}}, $("#red-ui-sidebar-debug-filterSelected").trigger("click");
{id:"red-ui-debug-msg-menu-item-clear-filter",label:RED._("node-red:debug.messageMenu.clearFilter"),onselect:function(){ RED.settings.set('debug.filteredNodes',Object.keys(filteredNodes))
$("#red-ui-sidebar-debug-filterAll").trigger("click"); refreshMessageList();
refreshMessageList(); }},
}} {id:"red-ui-debug-msg-menu-item-clear-filter",label:RED._("node-red:debug.messageMenu.clearFilter"),onselect:function(){
] $("#red-ui-sidebar-debug-filterAll").trigger("click");
refreshMessageList();
}}
);
menuOptionMenu = RED.menu.init({id:"red-ui-debug-msg-option-menu",
options: opts
}); });
menuOptionMenu.css({ menuOptionMenu.css({
position: "absolute" position: "absolute"

View File

@@ -168,9 +168,9 @@ module.exports = function(RED) {
return getFromValueType(RED.util.getMessageProperty(msg,rule.from),done); return getFromValueType(RED.util.getMessageProperty(msg,rule.from),done);
} else if (rule.fromt === 'flow' || rule.fromt === 'global') { } else if (rule.fromt === 'flow' || rule.fromt === 'global') {
var contextKey = RED.util.parseContextStore(rule.from); var contextKey = RED.util.parseContextStore(rule.from);
if (/\[msg\./.test(context.key)) { if (/\[msg\./.test(contextKey.key)) {
// The key has a nest msg. reference to evaluate first // The key has a nest msg. reference to evaluate first
context.key = RED.util.normalisePropertyExpression(contextKey.key,msg,true); contextKey.key = RED.util.normalisePropertyExpression(contextKey.key,msg,true);
} }
node.context()[rule.fromt].get(contextKey.key, contextKey.store, (err,fromValue) => { node.context()[rule.fromt].get(contextKey.key, contextKey.store, (err,fromValue) => {
if (err) { if (err) {

View File

@@ -215,6 +215,7 @@ module.exports = function(RED) {
delete listenerNodes[node.fullPath]; delete listenerNodes[node.fullPath];
node.server.close(); node.server.close();
node._inputNodes = []; node._inputNodes = [];
done();
} }
else { else {
node.closing = true; node.closing = true;

View File

@@ -1,6 +1,6 @@
{ {
"name": "@node-red/nodes", "name": "@node-red/nodes",
"version": "3.0.0-beta.4", "version": "3.1.0-beta.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"repository": { "repository": {
"type": "git", "type": "git",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@node-red/registry", "name": "@node-red/registry",
"version": "3.0.0-beta.4", "version": "3.1.0-beta.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {
@@ -16,11 +16,11 @@
} }
], ],
"dependencies": { "dependencies": {
"@node-red/util": "3.0.0-beta.4", "@node-red/util": "3.1.0-beta.0",
"clone": "2.1.2", "clone": "2.1.2",
"fs-extra": "10.1.0", "fs-extra": "10.1.0",
"semver": "7.3.7", "semver": "7.3.7",
"tar": "6.1.11", "tar": "6.1.11",
"uglify-js": "3.16.0" "uglify-js": "3.16.2"
} }
} }

View File

@@ -390,7 +390,6 @@ class Subflow extends Flow {
} }
name = newName; name = newName;
} }
var parent = this.parent; var parent = this.parent;
if (parent) { if (parent) {

View File

@@ -373,11 +373,13 @@ var api = module.exports = {
} }
} }
for (cred in savedCredentials) { if (/^subflow(:|$)/.test(nodeType)) {
if (savedCredentials.hasOwnProperty(cred)) { for (cred in savedCredentials) {
if (!newCreds.hasOwnProperty(cred)) { if (savedCredentials.hasOwnProperty(cred)) {
delete savedCredentials[cred]; if (!newCreds.hasOwnProperty(cred)) {
dirty = true; delete savedCredentials[cred];
dirty = true;
}
} }
} }
} }

View File

@@ -122,6 +122,7 @@
"stopped-flows": "フローを停止しました", "stopped-flows": "フローを停止しました",
"stopped": "停止しました", "stopped": "停止しました",
"stopping-error": "ノードの停止に失敗しました: __message__", "stopping-error": "ノードの停止に失敗しました: __message__",
"updated-flows": "フローを更新しました",
"added-flow": "フローを追加します: __label__", "added-flow": "フローを追加します: __label__",
"updated-flow": "フローを更新しました: __label__", "updated-flow": "フローを更新しました: __label__",
"removed-flow": "フローを削除しました: __label__", "removed-flow": "フローを削除しました: __label__",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@node-red/runtime", "name": "@node-red/runtime",
"version": "3.0.0-beta.4", "version": "3.1.0-beta.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"main": "./lib/index.js", "main": "./lib/index.js",
"repository": { "repository": {
@@ -16,8 +16,8 @@
} }
], ],
"dependencies": { "dependencies": {
"@node-red/registry": "3.0.0-beta.4", "@node-red/registry": "3.1.0-beta.0",
"@node-red/util": "3.0.0-beta.4", "@node-red/util": "3.1.0-beta.0",
"async-mutex": "0.3.2", "async-mutex": "0.3.2",
"clone": "2.1.2", "clone": "2.1.2",
"express": "4.18.1", "express": "4.18.1",

View File

@@ -1,6 +1,6 @@
{ {
"name": "@node-red/util", "name": "@node-red/util",
"version": "3.0.0-beta.4", "version": "3.1.0-beta.0",
"license": "Apache-2.0", "license": "Apache-2.0",
"repository": { "repository": {
"type": "git", "type": "git",
@@ -16,11 +16,11 @@
], ],
"dependencies": { "dependencies": {
"fs-extra": "10.1.0", "fs-extra": "10.1.0",
"i18next": "21.8.10", "i18next": "21.8.14",
"json-stringify-safe": "5.0.1", "json-stringify-safe": "5.0.1",
"jsonata": "1.8.6", "jsonata": "1.8.6",
"lodash.clonedeep": "^4.5.0", "lodash.clonedeep": "^4.5.0",
"moment": "2.29.3", "moment": "2.29.4",
"moment-timezone": "0.5.34" "moment-timezone": "0.5.34"
} }
} }

View File

@@ -1,6 +1,6 @@
{ {
"name": "node-red", "name": "node-red",
"version": "3.0.0-beta.4", "version": "3.1.0-beta.0",
"description": "Low-code programming for event-driven applications", "description": "Low-code programming for event-driven applications",
"homepage": "http://nodered.org", "homepage": "http://nodered.org",
"license": "Apache-2.0", "license": "Apache-2.0",
@@ -31,10 +31,10 @@
"flow" "flow"
], ],
"dependencies": { "dependencies": {
"@node-red/editor-api": "3.0.0-beta.4", "@node-red/editor-api": "3.1.0-beta.0",
"@node-red/runtime": "3.0.0-beta.4", "@node-red/runtime": "3.1.0-beta.0",
"@node-red/util": "3.0.0-beta.4", "@node-red/util": "3.1.0-beta.0",
"@node-red/nodes": "3.0.0-beta.4", "@node-red/nodes": "3.1.0-beta.0",
"basic-auth": "2.0.1", "basic-auth": "2.0.1",
"bcryptjs": "2.4.3", "bcryptjs": "2.4.3",
"express": "4.18.1", "express": "4.18.1",

View File

@@ -51,7 +51,7 @@ describe("api/editor/theme", function () {
context.should.have.a.property("asset"); context.should.have.a.property("asset");
context.asset.should.have.a.property("red", "red/red.min.js"); context.asset.should.have.a.property("red", "red/red.min.js");
context.asset.should.have.a.property("main", "red/main.min.js"); context.asset.should.have.a.property("main", "red/main.min.js");
context.asset.should.have.a.property("vendorMonaco", ""); context.asset.should.have.a.property("vendorMonaco", "vendor/monaco/monaco-bootstrap.js");
should.not.exist(theme.settings()); should.not.exist(theme.settings());
}); });
@@ -69,16 +69,16 @@ describe("api/editor/theme", function () {
} }
}); });
it("Adds monaco bootstrap when enabled", async function () { it("Does not add monaco bootstrap when ace selected", async function () {
theme.init({ theme.init({
editorTheme: { editorTheme: {
codeEditor: { codeEditor: {
lib: 'monaco' lib: 'ace'
} }
} }
}); });
var context = await theme.context(); var context = await theme.context();
context.asset.should.have.a.property("vendorMonaco", "vendor/monaco/monaco-bootstrap.js"); context.asset.should.have.a.property("vendorMonaco", "");
}); });
it("picks up custom theme", async function () { it("picks up custom theme", async function () {