mirror of
https://github.com/node-red/node-red.git
synced 2025-03-01 10:36:34 +00:00
Compare commits
122 Commits
pr_3744
...
fix-change
Author | SHA1 | Date | |
---|---|---|---|
|
3e4c45ac6a | ||
|
f060309002 | ||
|
fc3d86e6ff | ||
|
d657817211 | ||
|
954649007c | ||
|
b0d9903fe2 | ||
|
6375f3c445 | ||
|
2328f418be | ||
|
22b6564847 | ||
|
25c8bfefe2 | ||
|
30f4524821 | ||
|
9e4c3a7200 | ||
|
5b7e84c1b0 | ||
|
e6097e4968 | ||
|
0f2829097b | ||
|
e2a9f940e2 | ||
|
3eb2b2ac5d | ||
|
ce7b0a3b5e | ||
|
7bd7c99dd4 | ||
|
b0d12c4125 | ||
|
745607b5bc | ||
|
cc5a770b16 | ||
|
fbde0091de | ||
|
a533943a40 | ||
|
e11f17672c | ||
|
c038c99f9d | ||
|
5f159c1fbd | ||
|
cd8ca8981b | ||
|
a5d7f7acce | ||
|
a032c2e326 | ||
|
9d770ed436 | ||
|
ae753940f3 | ||
|
d0d22c333c | ||
|
266ba17ebb | ||
|
0d0d5bafb0 | ||
|
58b951e134 | ||
|
30956b5441 | ||
|
9540cfe749 | ||
|
31b17faa2a | ||
|
5c6b8e9e50 | ||
|
5a36e8fb11 | ||
|
7d4c857a43 | ||
|
598bcf675f | ||
|
5365786386 | ||
|
c9b0a7c2dd | ||
|
371d8042d6 | ||
|
be343cb21e | ||
|
e9eabd6881 | ||
|
abccdc7f21 | ||
|
4ae914f729 | ||
|
86ac955b79 | ||
|
9734691cac | ||
|
d94f3a477d | ||
|
d53cd209f7 | ||
|
65cacb39d2 | ||
|
b008a6a2aa | ||
|
5c29feec63 | ||
|
d8e350d603 | ||
|
14a3366850 | ||
|
5ea0c6fca1 | ||
|
f454c29b8c | ||
|
fe5132be1d | ||
|
b50ba3e0e4 | ||
|
4fb40f9077 | ||
|
dc7fef6395 | ||
|
da65bf7292 | ||
|
17d9c2577e | ||
|
bc7852c1cc | ||
|
51d8792f62 | ||
|
bfdbeb0964 | ||
|
ede82ad0d5 | ||
|
f50dcb9e40 | ||
|
676c5e5df5 | ||
|
d52be76c8a | ||
|
c6a517c88c | ||
|
96eb8719b8 | ||
|
bcd31610f6 | ||
|
a4d66622a5 | ||
|
af4f07cb26 | ||
|
f7120b32f5 | ||
|
273404e24d | ||
|
1b53b5b927 | ||
|
7c5413e568 | ||
|
39b2fe45a5 | ||
|
8d3c5d09f6 | ||
|
5944fdb5dc | ||
|
e120bad779 | ||
|
d546a4a15b | ||
|
660a2e0ed6 | ||
|
1b94cc3ac0 | ||
|
4698d5d2fc | ||
|
92bc9d81c5 | ||
|
952cfaec14 | ||
|
637c44aa59 | ||
|
6e5fc29dca | ||
|
8bd02d0c36 | ||
|
c6cfbb8755 | ||
|
75d3444391 | ||
|
c648e1e8d6 | ||
|
e2f42fddb5 | ||
|
f93fe684c0 | ||
|
ee378ea0c4 | ||
|
613d34e6e6 | ||
|
4c784af55d | ||
|
b28595c814 | ||
|
fca7beec01 | ||
|
f813f03a46 | ||
|
6ff2232df3 | ||
|
e3b1f058cd | ||
|
542e9cacc2 | ||
|
0a0a7ca39b | ||
|
cee287da99 | ||
|
c8e4df94f9 | ||
|
c86e4f52a0 | ||
|
44216310ca | ||
|
5c69599e78 | ||
|
e4098d3991 | ||
|
55a94d659b | ||
|
7a048d5b32 | ||
|
e14dd06a94 | ||
|
62332a2b56 | ||
|
639030924f |
594
CHANGELOG.md
594
CHANGELOG.md
@@ -1,3 +1,75 @@
|
||||
#### 3.0.2: Maintenance Release
|
||||
|
||||
Editor
|
||||
|
||||
- Fix workspace chart bottom property (#3812) @bonanitech
|
||||
- Update german translation (#3802) @Dennis14e
|
||||
- Support color reset to the default in subflow and group (#3801) @kazuhitoyokoi
|
||||
- Allow generateNodeNames to handle names containing regex control chars (#3817) @knolleary
|
||||
- Hide scrollbars until they're needed (#3808) @bonanitech
|
||||
- Include junctions/groups when exporting subflows plus related fixes (#3816) @knolleary
|
||||
- remove console.log (#3820) @Steve-Mcl
|
||||
|
||||
Runtime
|
||||
|
||||
- Register subflow module instance node with parent flow (#3818) @knolleary
|
||||
|
||||
Nodes
|
||||
|
||||
- HTTP Request: Allow HTTP Headers not in spec (#3776) @hardillb
|
||||
|
||||
#### 3.0.1: Maintenance Release
|
||||
|
||||
Editor
|
||||
|
||||
- Allow codeEditor theme to be set even if `codeEditor` is not set in settings.js (#3794) @Steve-Mcl
|
||||
- Sys info (diagnostics report) amendments (#3793) @Steve-Mcl
|
||||
- Allow `mode` and `title` to be omitted in `options` argument for `createEditor` (#3791) @Steve-Mcl
|
||||
- Fix focus issues (#3789) @Steve-Mcl
|
||||
- Ensure all typedInput buttons have button type set (#3788) @knolleary
|
||||
- Do not flag hasUsers=false nodes as unused in search (#3787) @knolleary
|
||||
- Properly position quick-add dialog in all cases (#3786) @knolleary
|
||||
- Ensure quick-add dialog does not obscure ghost node when shifted (#3785) @knolleary
|
||||
- Remove use of Object.hasOwn (#3784) @knolleary
|
||||
|
||||
#### 3.0.0: Milestone Release
|
||||
|
||||
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
|
||||
|
||||
Editor
|
||||
@@ -185,528 +257,6 @@ Nodes
|
||||
- Watch: Update Watch node to use node-watch module (#3559 #3569) @knolleary
|
||||
- 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
|
||||
|
||||
Change logs for older releases are available on GitHub: https://github.com/node-red/node-red/releases
|
||||
|
24
package.json
24
package.json
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "3.0.0-beta.4",
|
||||
"version": "3.0.2",
|
||||
"description": "Low-code programming for event-driven applications",
|
||||
"homepage": "http://nodered.org",
|
||||
"license": "Apache-2.0",
|
||||
@@ -40,7 +40,7 @@
|
||||
"cookie-parser": "1.4.6",
|
||||
"cors": "2.8.5",
|
||||
"cronosjs": "1.7.1",
|
||||
"denque": "2.0.1",
|
||||
"denque": "2.1.0",
|
||||
"express": "4.18.1",
|
||||
"express-session": "1.17.3",
|
||||
"form-data": "4.0.0",
|
||||
@@ -49,7 +49,7 @@
|
||||
"hash-sum": "2.0.0",
|
||||
"hpagent": "1.0.0",
|
||||
"https-proxy-agent": "5.0.1",
|
||||
"i18next": "21.8.10",
|
||||
"i18next": "21.8.16",
|
||||
"iconv-lite": "0.6.3",
|
||||
"is-utf8": "0.2.1",
|
||||
"js-yaml": "4.1.0",
|
||||
@@ -59,7 +59,7 @@
|
||||
"media-typer": "1.1.0",
|
||||
"memorystore": "1.6.7",
|
||||
"mime": "3.0.0",
|
||||
"moment": "2.29.3",
|
||||
"moment": "2.29.4",
|
||||
"moment-timezone": "0.5.34",
|
||||
"mqtt": "4.3.7",
|
||||
"multer": "1.4.5-lts.1",
|
||||
@@ -69,14 +69,14 @@
|
||||
"nopt": "5.0.0",
|
||||
"oauth2orize": "1.11.1",
|
||||
"on-headers": "1.0.2",
|
||||
"passport": "0.5.2",
|
||||
"passport": "0.6.0",
|
||||
"passport-http-bearer": "1.0.1",
|
||||
"passport-oauth2-client-password": "0.1.2",
|
||||
"raw-body": "2.5.1",
|
||||
"semver": "7.3.7",
|
||||
"tar": "6.1.11",
|
||||
"tough-cookie": "4.0.0",
|
||||
"uglify-js": "3.16.0",
|
||||
"uglify-js": "3.16.3",
|
||||
"uuid": "8.3.2",
|
||||
"ws": "7.5.6",
|
||||
"xml2js": "0.4.23"
|
||||
@@ -85,7 +85,7 @@
|
||||
"bcrypt": "5.0.1"
|
||||
},
|
||||
"devDependencies": {
|
||||
"dompurify": "2.3.8",
|
||||
"dompurify": "2.3.10",
|
||||
"grunt": "1.5.3",
|
||||
"grunt-chmod": "~1.1.1",
|
||||
"grunt-cli": "~1.4.3",
|
||||
@@ -95,7 +95,7 @@
|
||||
"grunt-contrib-concat": "2.1.0",
|
||||
"grunt-contrib-copy": "1.0.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-jsdoc": "2.4.1",
|
||||
"grunt-jsdoc-to-markdown": "6.0.0",
|
||||
@@ -108,17 +108,17 @@
|
||||
"i18next-http-backend": "1.4.1",
|
||||
"jquery-i18next": "1.2.1",
|
||||
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
|
||||
"marked": "4.0.17",
|
||||
"marked": "4.0.18",
|
||||
"minami": "1.2.3",
|
||||
"mocha": "9.2.2",
|
||||
"node-red-node-test-helper": "^0.3.0",
|
||||
"nodemon": "2.0.16",
|
||||
"nodemon": "2.0.19",
|
||||
"proxy": "^1.0.2",
|
||||
"sass": "1.52.3",
|
||||
"sass": "1.54.2",
|
||||
"should": "13.2.3",
|
||||
"sinon": "11.1.2",
|
||||
"stoppable": "^1.1.0",
|
||||
"supertest": "6.2.3"
|
||||
"supertest": "6.2.4"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=14"
|
||||
|
@@ -266,9 +266,69 @@ module.exports = {
|
||||
theme.page = theme.page || {_:{}}
|
||||
theme.page._.scripts = scriptFiles.concat(theme.page._.scripts || [])
|
||||
}
|
||||
if(theme.codeEditor) {
|
||||
theme.codeEditor.options = Object.assign({}, themePlugin.monacoOptions, theme.codeEditor.options);
|
||||
// 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
|
||||
}
|
||||
}
|
||||
theme.codeEditor = theme.codeEditor || {}
|
||||
theme.codeEditor.options = Object.assign({}, themePlugin.monacoOptions, theme.codeEditor.options);
|
||||
}
|
||||
activeThemeInitialised = true;
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/editor-api",
|
||||
"version": "3.0.0-beta.4",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,8 +16,8 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/util": "3.0.0-beta.4",
|
||||
"@node-red/editor-client": "3.0.0-beta.4",
|
||||
"@node-red/util": "3.0.2",
|
||||
"@node-red/editor-client": "3.0.2",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.20.0",
|
||||
"clone": "2.1.2",
|
||||
@@ -31,7 +31,7 @@
|
||||
"oauth2orize": "1.11.1",
|
||||
"passport-http-bearer": "1.0.1",
|
||||
"passport-oauth2-client-password": "0.1.2",
|
||||
"passport": "0.5.2",
|
||||
"passport": "0.6.0",
|
||||
"ws": "7.5.6"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
@@ -105,7 +105,7 @@
|
||||
"search": "Flows durchsuchen",
|
||||
"searchInput": "Flows durchsuchen",
|
||||
"subflows": "Subflow",
|
||||
"createSubflow": "Subflow",
|
||||
"createSubflow": "Hinzufügen",
|
||||
"selectionToSubflow": "Auswahl in Subflow umwandeln",
|
||||
"flows": "Flow",
|
||||
"add": "Hinzufügen",
|
||||
@@ -152,7 +152,8 @@
|
||||
"zoom-in": "Vergrößern",
|
||||
"search-flows": "Flows durchsuchen",
|
||||
"search-prev": "Vorherige",
|
||||
"search-next": "Nächste"
|
||||
"search-next": "Nächste",
|
||||
"search-counter": "\"__term__\" __result__ von __count__"
|
||||
},
|
||||
"user": {
|
||||
"loggedInAs": "Angemeldet als __name__",
|
||||
@@ -168,7 +169,11 @@
|
||||
}
|
||||
},
|
||||
"notification": {
|
||||
"warning": "<strong>Warnung:</strong> __message__",
|
||||
"state": {
|
||||
"flowsStopped": "Flows gestoppt",
|
||||
"flowsStarted": "Flows gestartet"
|
||||
},
|
||||
"warning": "<strong>Warnung</strong>: __message__",
|
||||
"warnings": {
|
||||
"undeployedChanges": "Node hat nicht übernommene (deploy) Änderungen",
|
||||
"nodeActionDisabled": "Node-Aktionen deaktiviert",
|
||||
@@ -177,15 +182,15 @@
|
||||
"missing-modules": "<p>Flows angehalten aufgrund fehlender Module</p>",
|
||||
"safe-mode": "<p>Flows sind im abgesicherten Modus gestoppt.</p><p>Flows können bearbeitet und übernommen (deploy) werden, um sie neu zu starten.</p>",
|
||||
"restartRequired": "Node-RED muss neu gestartet werden, damit die Module nach Upgrade aktiviert werden",
|
||||
"credentials_load_failed": "<p>Flows gestoppt, da die Berechtigungen nicht entschlüsselt werden konnten.</p><p>Die Datei mit dem Flow-Berechtigungen ist verschlüsselt, aber der Schlüssel des Projekts fehlt oder ist ungültig.</p>",
|
||||
"credentials_load_failed_reset": "<p>Die Berechtigungen konnten nicht entschlüsselt werden.</p><p>Die Datei mit den Flow-Berechtigungen ist verschlüsselt, aber der Schlüssel des Projekts fehlt oder ist ungültig.</p><p>Die Datei mit den Flow-Berechtigungen wird bei der nächsten Übernahme (deploy) zurückgesetzt. Alle vorhandenen Flow-Berechtigungen werden gelöscht.</p>",
|
||||
"credentials_load_failed": "<p>Flows gestoppt, da die Credentials nicht entschlüsselt werden konnten.</p><p>Die Datei mit den Flow-Credentials ist verschlüsselt, aber der Schlüssel des Projekts fehlt oder ist ungültig.</p>",
|
||||
"credentials_load_failed_reset": "<p>Die Credentials konnten nicht entschlüsselt werden.</p><p>Die Datei mit den Flow-Credentials ist verschlüsselt, aber der Schlüssel des Projekts fehlt oder ist ungültig.</p><p>Die Datei mit den Flow-Credentials wird bei der nächsten Übernahme (deploy) zurückgesetzt. Alle vorhandenen Flow-Credentials werden gelöscht.</p>",
|
||||
"missing_flow_file": "<p>Die Flow-Datei des Projekts wurde nicht gefunden.</p><p>Das Projekt ist nicht mit einer Flow-Datei konfiguriert.</p>",
|
||||
"missing_package_file": "<p>Die Paket-Datei des Projekts wurde nicht gefunden.</p><p>In dem Projekt fehlt die 'package.json'-Datei.</p>",
|
||||
"project_empty": "<p>Das Projekt ist leer.</p><p>Soll ein Standardsatz an Projektdateien erstellen werden?<br/>Andernfalls müssen die Dateien manuell außerhalb des Editors dem Projekt hinzugefügt werden.</p>",
|
||||
"project_not_found": "<p>Das Projekt '__project__' wurde nicht gefunden.</p>",
|
||||
"git_merge_conflict": "<p>Der automatische Merge der Änderungen ist fehlgeschlagen.</p><p>Die Merge-Konflikte müssen behoben und die Ergebnisse ins Repository übertragen werden (commit).</p>"
|
||||
},
|
||||
"error": "<strong>Fehler:</strong> __message__",
|
||||
"error": "<strong>Fehler</strong>: __message__",
|
||||
"errors": {
|
||||
"lostConnection": "Verbindung zum Server verloren. Verbindung wird erneut hergestellt ...",
|
||||
"lostConnectionReconnect": "Verbindung zum Server verloren. Wiederherstellung der Verbindung in __time__s.",
|
||||
@@ -203,7 +208,7 @@
|
||||
"pull": "Projekt '__project__' erneut geladen",
|
||||
"revert": "Änderungen im Projekt '__project__' rückgängig gemacht",
|
||||
"merge-complete": "Git-Merge abgeschlossen",
|
||||
"setupCredentials": "Berechtigungen einrichten",
|
||||
"setupCredentials": "Credentials einrichten",
|
||||
"setupProjectFiles": "Projektdateien einrichten",
|
||||
"no": "Nein, Danke",
|
||||
"createDefault": "Standardprojektdateien erstellen",
|
||||
@@ -211,7 +216,7 @@
|
||||
},
|
||||
"label": {
|
||||
"manage-project-dep": "Projektabhängigkeiten verwalten",
|
||||
"setup-cred": "Berechtigungen einrichten",
|
||||
"setup-cred": "Credentials einrichten",
|
||||
"setup-project": "Projektdateien einrichten",
|
||||
"create-default-package": "Standardpaketdatei erstellen",
|
||||
"no-thanks": "Nein, Danke",
|
||||
@@ -295,6 +300,10 @@
|
||||
"modifiedFlowsDesc": "Übernimmt nur Flows, die geänderte Nodes enthalten",
|
||||
"modifiedNodes": "Geänderte Nodes",
|
||||
"modifiedNodesDesc": "Übernimmt nur Nodes, die sich geändert haben",
|
||||
"startFlows": "Start",
|
||||
"startFlowsDesc": "Flows starten",
|
||||
"stopFlows": "Stop",
|
||||
"stopFlowsDesc": "Flows stoppen",
|
||||
"restartFlows": "Flows neustarten",
|
||||
"restartFlowsDesc": "Startet die aktuell übernommenen Flows (ohne vorheriges Deploy)",
|
||||
"successfulDeploy": "Erfolgreich übernommen (deploy)",
|
||||
@@ -376,7 +385,7 @@
|
||||
"confirmDelete": "Sind Sie sicher mit dem Löschen dieses Subflows?",
|
||||
"info": "Beschreibung",
|
||||
"category": "Kategorie",
|
||||
"module": "Module",
|
||||
"module": "Modul",
|
||||
"license": "Lizenz",
|
||||
"licenseNone": "Keine",
|
||||
"licenseOther": "Andere",
|
||||
@@ -434,7 +443,7 @@
|
||||
"icon": "Icon",
|
||||
"inputType": "Eingangstyp",
|
||||
"selectType": "Wähle Typen ...",
|
||||
"loadCredentials": "Lade Node-Berechtigungen",
|
||||
"loadCredentials": "Lade Node-Credentials",
|
||||
"inputs": {
|
||||
"input": "Eingang",
|
||||
"select": "Auswahl",
|
||||
@@ -450,7 +459,7 @@
|
||||
"json": "JSON",
|
||||
"bin": "buffer",
|
||||
"env": "Umgebungsvariable",
|
||||
"cred": "Berechtigung"
|
||||
"cred": "Credentials"
|
||||
},
|
||||
"menu": {
|
||||
"input": "Eingang",
|
||||
@@ -470,7 +479,7 @@
|
||||
"errors": {
|
||||
"scopeChange": "Wenn Sie den Geltungsbereich (scope) ändern, wird er für Nodes in anderen Flows nicht verfügbar sein",
|
||||
"invalidProperties": "Ungültige Eigenschaften:",
|
||||
"credentialLoadFailed": "Laden der Node-Berechtigungen fehlgeschlagen"
|
||||
"credentialLoadFailed": "Laden der Node-Credentials fehlgeschlagen"
|
||||
}
|
||||
},
|
||||
"keyboard": {
|
||||
@@ -683,7 +692,8 @@
|
||||
"showHelp": "Hilfe zeigen",
|
||||
"showInOutline": "Zeige im Editor",
|
||||
"showTopics": "Zeige Hilfethemen",
|
||||
"noHelp": "Kein Hilfethema ausgewählt"
|
||||
"noHelp": "Kein Hilfethema ausgewählt",
|
||||
"changeLog": "Änderungsprotokoll"
|
||||
},
|
||||
"config": {
|
||||
"name": "Konfigurations-Node",
|
||||
@@ -737,7 +747,7 @@
|
||||
"addToProject": "Zu Projekt hinzufügen",
|
||||
"files": "Dateien",
|
||||
"flow": "Flow",
|
||||
"credentials": "Berechtigungen",
|
||||
"credentials": "Credentials",
|
||||
"package": "Paket",
|
||||
"packageCreate": "Datei wird erstellt beim Speichern der Änderungen",
|
||||
"fileNotExist": "Datei existiert nicht",
|
||||
@@ -750,7 +760,7 @@
|
||||
"changeTheEncryptionKey": "Schlüssel ändern",
|
||||
"currentKey": "Aktueller Schlüssel",
|
||||
"newKey": "Neuer Schlüssel",
|
||||
"credentialsAlert": "Dadurch werden alle vorhandenen Berechtigungen gelöscht",
|
||||
"credentialsAlert": "Dadurch werden alle vorhandenen Credentials gelöscht",
|
||||
"versionControl": "Versionsverwaltung (Git)",
|
||||
"branches": "Branches",
|
||||
"noBranches": "Keine Branches",
|
||||
@@ -886,7 +896,7 @@
|
||||
"date": "timestamp",
|
||||
"jsonata": "JSONata",
|
||||
"env": "Umgebungsvariable",
|
||||
"cred": "Berechtigung"
|
||||
"cred": "Credentials"
|
||||
}
|
||||
},
|
||||
"editableList": {
|
||||
@@ -1026,7 +1036,7 @@
|
||||
"passphrase": "Passphrase",
|
||||
"ssh-key-desc": "Bevor Sie ein Repository über SSH lokal klonen können, müssen Sie einen SSH-Schlüssel hinzufügen, um auf diesen zugreifen zu können",
|
||||
"ssh-key-add": "SSH-Schlüssel hinzufügen",
|
||||
"credential-key": "Schlüssel für Berechtigungen",
|
||||
"credential-key": "Schlüssel für Credentials",
|
||||
"cant-get-ssh-key": "Fehler! Der ausgewählte SSH-Schlüsselpfad kann nicht abgerufen werden",
|
||||
"already-exists2": "bereits vorhanden",
|
||||
"git-error": "Git-Fehler",
|
||||
@@ -1038,27 +1048,27 @@
|
||||
"create": "Erstellen Sie Ihre Projektdateien",
|
||||
"desc0": "Ein Projekt enthält Ihre Flow-Dateien, eine README-Datei und die 'package.json'-Datei.",
|
||||
"desc1": "Es kann alle anderen Dateien enthalten, die im Git-Repository verwaltet werden sollen.",
|
||||
"desc2": "Ihre vorhandenen Flow- und Berechtigungs-Dateien werden in das Projekt kopiert.",
|
||||
"desc2": "Ihre vorhandenen Flow- und Credential-Dateien werden in das Projekt kopiert.",
|
||||
"flow-file": "Flow-Datei",
|
||||
"credentials-file": "Datei mit Berechtigungen"
|
||||
"credentials-file": "Datei mit Credentials"
|
||||
},
|
||||
"encryption-config": {
|
||||
"setup": "Einrichtung der Verschlüsselung Ihrer Datei mit den Berechtigungen",
|
||||
"desc0": "Die Datei mit den Flow-Berechtigungen kann verschlüsselt werden, um ihren Inhalt zu schützen.",
|
||||
"desc1": "Wenn Sie diese Berechtigungen in einem öffentlichen Repository speichern möchten, müssen Sie sie mit einen geheimen Schlüsselausdruck verschlüsseln.",
|
||||
"desc2": "Die Datei mit den Flow-Berechtigungen ist derzeit nicht verschlüsselt.",
|
||||
"setup": "Einrichtung der Verschlüsselung Ihrer Datei mit den Credentials",
|
||||
"desc0": "Die Datei mit den Flow-Credentials kann verschlüsselt werden, um ihren Inhalt zu schützen.",
|
||||
"desc1": "Wenn Sie diese Credentials in einem öffentlichen Repository speichern möchten, müssen Sie sie mit einen geheimen Schlüsselausdruck verschlüsseln.",
|
||||
"desc2": "Die Datei mit den Flow-Credentials ist derzeit nicht verschlüsselt.",
|
||||
"desc3": "D.h. ihr Inhalt (z.B. Passwörter und Zugriffs-Tokens) kann von jedem mit Zugriff auf die Datei gelesen werden.",
|
||||
"desc4": "Wenn Sie diese Berechtigungen in einen öffentlichen Repository speichern möchten, müssen Sie diese verschlüsseln, indem Sie einen geheimen Schlüsselausdruck eingeben.",
|
||||
"desc5": "Ihre Datei mit den Flow-Berechtigungen wird derzeit mit dem Eintrag 'credentialSecret' Ihrer Einstellungsdatei als Schlüssel verschlüsselt.",
|
||||
"desc6": "Die Datei mit den Flow-Berechtigungen wird derzeit mit einem vom System generierten Schlüssel verschlüsselt. Sie sollten einen neuen geheimen Schlüssel für dieses Projekt vorgeben.",
|
||||
"desc4": "Wenn Sie diese Credentials in einen öffentlichen Repository speichern möchten, müssen Sie diese verschlüsseln, indem Sie einen geheimen Schlüsselausdruck eingeben.",
|
||||
"desc5": "Ihre Datei mit den Flow-Credentials wird derzeit mit dem Eintrag 'credentialSecret' Ihrer Einstellungsdatei als Schlüssel verschlüsselt.",
|
||||
"desc6": "Die Datei mit den Flow-Credentials wird derzeit mit einem vom System generierten Schlüssel verschlüsselt. Sie sollten einen neuen geheimen Schlüssel für dieses Projekt vorgeben.",
|
||||
"desc7": "Der Schlüssel wird separat von den Projektdateien gespeichert. Sie müssen den Schlüssel angeben, damit dieses Projekt auch in einem anderen Node-RED-System verwendet werden kann.",
|
||||
"credentials": "Berechtigung",
|
||||
"credentials": "Credentials",
|
||||
"enable": "Verschlüsselung aktivieren",
|
||||
"disable": "Verschlüsselung deaktivieren",
|
||||
"disabled": "deaktiviert",
|
||||
"copy": "Vorhandenen Schlüssel ersetzen",
|
||||
"use-custom": "Eigenen Schlüssel verwenden",
|
||||
"desc8": "Die Datei mit den Berechtigungen wird nicht verschlüsselt, und ihr Inhalt kann leicht gelesen werden",
|
||||
"desc8": "Die Datei mit den Credentials wird nicht verschlüsselt und ihr Inhalt kann leicht gelesen werden",
|
||||
"create-project-files": "Projektdateien erstellen",
|
||||
"create-project": "Projekt erstellen",
|
||||
"already-exists": "bereits vorhanden",
|
||||
@@ -1083,12 +1093,12 @@
|
||||
"desc": "Beschreibung",
|
||||
"opt": "Optional",
|
||||
"flow-file": "Flow-Datei",
|
||||
"credentials": "Berechtigungen",
|
||||
"credentials": "Credentials",
|
||||
"enable-encryption": "Verschlüsselung aktivieren",
|
||||
"disable-encryption": "Verschlüsselung deaktivieren",
|
||||
"encryption-key": "Schlüssel",
|
||||
"desc0": "Eine Floskel, mit der Sie Ihre Berechtigungen schützen",
|
||||
"desc1": "Die Datei mit den Berechtigungen wird nicht verschlüsselt, und ihr Inhalt kann leicht gelesen werden",
|
||||
"desc0": "Eine Ausdruck, mit der Sie Ihre Credentials schützen",
|
||||
"desc1": "Die Datei mit den Credentials wird nicht verschlüsselt und ihr Inhalt kann leicht gelesen werden",
|
||||
"git-url": "Git-Repository-URL",
|
||||
"protocols": "https://, ssh:// oder file://",
|
||||
"auth-failed": "Authentifizierung fehlgeschlagen",
|
||||
@@ -1098,7 +1108,7 @@
|
||||
"passphrase": "Passphrase",
|
||||
"desc2": "Bevor Sie ein Repository über SSH klonen können, müssen Sie einen SSH-Schlüssel hinzufügen, um auf diesen zu zugreifen",
|
||||
"add-ssh-key": "Einen SSH-Schlüssel hinzufügen",
|
||||
"credentials-encryption-key": "Schlüssel für Berechtigungen",
|
||||
"credentials-encryption-key": "Schlüssel für Credentials",
|
||||
"already-exists-2": "bereits vorhanden",
|
||||
"git-error": "Git-Fehler",
|
||||
"con-failed": "Verbindung fehlgeschlagen",
|
||||
@@ -1156,7 +1166,8 @@
|
||||
"tourGuide": {
|
||||
"takeATour": "Tour starten",
|
||||
"start": "Start",
|
||||
"next": "Nächste"
|
||||
"next": "Nächste",
|
||||
"welcomeTours": "Welcome Tours"
|
||||
},
|
||||
"diagnostics": {
|
||||
"title": "System-Informationen"
|
||||
|
@@ -936,6 +936,9 @@
|
||||
"invalid-expr": "Invalid JSONata expression:\n __message__",
|
||||
"invalid-msg": "Invalid example JSON message:\n __message__",
|
||||
"context-unsupported": "Cannot test context functions\n $flowContext or $globalContext",
|
||||
"env-unsupported": "Cannot test $env function",
|
||||
"moment-unsupported": "Cannot test $moment function",
|
||||
"clone-unsupported": "Cannot test $clone function",
|
||||
"eval": "Error evaluating expression:\n __message__"
|
||||
}
|
||||
},
|
||||
|
@@ -935,8 +935,11 @@
|
||||
"errors": {
|
||||
"invalid-expr": "不正なJSONata式:\n __message__",
|
||||
"invalid-msg": "不正なJSONメッセージ例:\n __message__",
|
||||
"context-unsupported": "$flowContext や $globalContextの\nコンテキスト機能をテストできません",
|
||||
"eval": "表現評価エラー:\n __message__"
|
||||
"context-unsupported": "$flowContext や $globalContextの\nコンテキスト関数をテストできません",
|
||||
"env-unsupported": "$env関数はテストできません",
|
||||
"moment-unsupported": "$moment関数はテストできません",
|
||||
"clone-unsupported": "$clone関数はテストできません",
|
||||
"eval": "式評価エラー:\n __message__"
|
||||
}
|
||||
},
|
||||
"monaco": {
|
||||
@@ -1168,8 +1171,7 @@
|
||||
"takeATour": "ツアーを開始",
|
||||
"start": "開始",
|
||||
"next": "次へ",
|
||||
"welcomeTours": "ウェルカムツアー",
|
||||
"tours": "ツアー"
|
||||
"welcomeTours": "ウェルカムツアー"
|
||||
},
|
||||
"diagnostics": {
|
||||
"title": "システム情報"
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/editor-client",
|
||||
"version": "3.0.0-beta.4",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
@@ -868,14 +868,7 @@ RED.nodes = (function() {
|
||||
var node;
|
||||
|
||||
if (allNodes.hasTab(id)) {
|
||||
removedNodes = allNodes.getNodes(id).filter(n => {
|
||||
if (n.type === 'junction') {
|
||||
removedJunctions.push(n)
|
||||
return false
|
||||
} else {
|
||||
return true
|
||||
}
|
||||
})
|
||||
removedNodes = allNodes.getNodes(id).slice()
|
||||
}
|
||||
for (i in configNodes) {
|
||||
if (configNodes.hasOwnProperty(i)) {
|
||||
@@ -885,6 +878,7 @@ RED.nodes = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
removedJunctions = RED.nodes.junctions(id)
|
||||
|
||||
for (i=0;i<removedNodes.length;i++) {
|
||||
var result = removeNode(removedNodes[i].id);
|
||||
@@ -1331,7 +1325,6 @@ RED.nodes = (function() {
|
||||
} else {
|
||||
nodeSet = [sf];
|
||||
}
|
||||
console.log(nodeSet);
|
||||
return createExportableNodeSet(nodeSet);
|
||||
}
|
||||
/**
|
||||
@@ -1367,6 +1360,10 @@ RED.nodes = (function() {
|
||||
exportedConfigNodes[n.id] = true;
|
||||
}
|
||||
});
|
||||
|
||||
subflowSet = subflowSet.concat(RED.nodes.junctions(subflowId))
|
||||
subflowSet = subflowSet.concat(RED.nodes.groups(subflowId))
|
||||
|
||||
var exportableSubflow = createExportableNodeSet(subflowSet, exportedIds, exportedSubflows, exportedConfigNodes);
|
||||
nns = exportableSubflow.concat(nns);
|
||||
}
|
||||
|
@@ -766,7 +766,7 @@ var RED = (function() {
|
||||
$('<div id="red-ui-header-shade" class="hide"></div>').appendTo(header);
|
||||
$('<div id="red-ui-main-container" class="red-ui-sidebar-closed hide">'+
|
||||
'<div id="red-ui-workspace"></div>'+
|
||||
'<div id="red-ui-editor-stack"></div>'+
|
||||
'<div id="red-ui-editor-stack" tabindex="-1"></div>'+
|
||||
'<div id="red-ui-palette"></div>'+
|
||||
'<div id="red-ui-sidebar"></div>'+
|
||||
'<div id="red-ui-sidebar-separator"></div>'+
|
||||
|
@@ -160,7 +160,7 @@
|
||||
this.element.css("maxHeight",null);
|
||||
}
|
||||
if (this.options.height !== 'auto') {
|
||||
this.uiContainer.css("overflow-y","scroll");
|
||||
this.uiContainer.css("overflow-y","auto");
|
||||
if (!isNaN(this.options.height)) {
|
||||
this.uiHeight = this.options.height;
|
||||
}
|
||||
|
@@ -90,10 +90,10 @@
|
||||
optEl.append(generateSpans(srcMatch));
|
||||
optEl.appendTo(element);
|
||||
}
|
||||
matches.push({
|
||||
value: optVal,
|
||||
label: element,
|
||||
i: (valMatch.found ? valMatch.index : srcMatch.index)
|
||||
matches.push({
|
||||
value: optVal,
|
||||
label: element,
|
||||
i: (valMatch.found ? valMatch.index : srcMatch.index)
|
||||
});
|
||||
}
|
||||
})
|
||||
@@ -501,7 +501,7 @@
|
||||
this.options.types = this.options.types||Object.keys(allOptions);
|
||||
}
|
||||
|
||||
this.selectTrigger = $('<button class="red-ui-typedInput-type-select" tabindex="0"></button>').prependTo(this.uiSelect);
|
||||
this.selectTrigger = $('<button type="button" class="red-ui-typedInput-type-select" tabindex="0"></button>').prependTo(this.uiSelect);
|
||||
$('<i class="red-ui-typedInput-icon fa fa-caret-down"></i>').toggle(this.options.types.length > 1).appendTo(this.selectTrigger);
|
||||
|
||||
this.selectLabel = $('<span class="red-ui-typedInput-type-label"></span>').appendTo(this.selectTrigger);
|
||||
@@ -570,7 +570,7 @@
|
||||
})
|
||||
|
||||
// explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline'
|
||||
this.optionSelectTrigger = $('<button tabindex="0" class="red-ui-typedInput-option-trigger" style="display:inline-block"><span class="red-ui-typedInput-option-caret"><i class="red-ui-typedInput-icon fa fa-caret-down"></i></span></button>').appendTo(this.uiSelect);
|
||||
this.optionSelectTrigger = $('<button type="button" tabindex="0" class="red-ui-typedInput-option-trigger" style="display:inline-block"><span class="red-ui-typedInput-option-caret"><i class="red-ui-typedInput-icon fa fa-caret-down"></i></span></button>').appendTo(this.uiSelect);
|
||||
this.optionSelectLabel = $('<span class="red-ui-typedInput-option-label"></span>').prependTo(this.optionSelectTrigger);
|
||||
// RED.popover.tooltip(this.optionSelectLabel,function() {
|
||||
// return that.optionValue;
|
||||
@@ -591,7 +591,7 @@
|
||||
that.uiSelect.addClass('red-ui-typedInput-focus');
|
||||
});
|
||||
|
||||
this.optionExpandButton = $('<button tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"></button>').appendTo(this.uiSelect);
|
||||
this.optionExpandButton = $('<button type="button" tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"></button>').appendTo(this.uiSelect);
|
||||
this.optionExpandButtonIcon = $('<i class="red-ui-typedInput-icon fa fa-ellipsis-h"></i>').appendTo(this.optionExpandButton);
|
||||
|
||||
this.type(this.typeField.val() || this.options.default||this.typeList[0].value);
|
||||
|
@@ -30,25 +30,24 @@ RED.contextMenu = (function () {
|
||||
}
|
||||
|
||||
const selection = RED.view.selection()
|
||||
const noSelection = !selection || Object.keys(selection).length === 0
|
||||
const hasSelection = (selection.nodes && selection.nodes.length > 0);
|
||||
const hasMultipleSelection = hasSelection && selection.nodes.length > 1;
|
||||
const hasLinks = selection.links && selection.links.length > 0;
|
||||
const isSingleLink = !hasSelection && hasLinks && selection.links.length === 1
|
||||
const isMultipleLinks = !hasSelection && hasLinks && selection.links.length > 1
|
||||
const virtulLinks = (selection.links && selection.links.filter(e => !!e.link)) || [];
|
||||
const wireLinks = (selection.links && selection.links.filter(e => !e.link)) || [];
|
||||
const hasLinks = wireLinks.length > 0;
|
||||
const isSingleLink = !hasSelection && hasLinks && wireLinks.length === 1
|
||||
const isMultipleLinks = !hasSelection && hasLinks && wireLinks.length > 1
|
||||
const canDelete = hasSelection || hasLinks
|
||||
const isGroup = hasSelection && selection.nodes.length === 1 && selection.nodes[0].type === 'group'
|
||||
|
||||
const canRemoveFromGroup = hasSelection && !!selection.nodes[0].g
|
||||
const 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)
|
||||
}
|
||||
// addX/addY must be the position in the workspace accounting for both scroll and scale
|
||||
// The +5 is because we display the contextMenu -5,-5 to actual click position
|
||||
let addX = (options.x + 5 - offset.left + $("#red-ui-workspace-chart").scrollLeft()) / RED.view.scale()
|
||||
let addY = (options.y + 5 - offset.top + $("#red-ui-workspace-chart").scrollTop()) / RED.view.scale()
|
||||
|
||||
const menuItems = [
|
||||
{ onselect: 'core:show-action-list', onpostselect: function () { } },
|
||||
@@ -64,9 +63,13 @@ RED.contextMenu = (function () {
|
||||
splice: isSingleLink ? selection.links[0] : undefined,
|
||||
// spliceMultiple: isMultipleLinks
|
||||
})
|
||||
},
|
||||
onpostselect: function() {
|
||||
// ensure quick add dialog search input has focus
|
||||
$('#red-ui-type-search-input').trigger('focus')
|
||||
}
|
||||
},
|
||||
(hasSelection || hasLinks) ? {
|
||||
(hasLinks) ? { // has least 1 wire selected
|
||||
label: RED._("contextMenu.junction"),
|
||||
onselect: 'core:split-wires-with-junctions',
|
||||
disabled: !hasLinks
|
||||
@@ -93,6 +96,7 @@ RED.contextMenu = (function () {
|
||||
RED.nodes.addJunction(nn);
|
||||
RED.history.push(historyEvent);
|
||||
RED.nodes.dirty(true);
|
||||
RED.view.select({nodes: [nn] });
|
||||
RED.view.redraw(true)
|
||||
}
|
||||
},
|
||||
@@ -140,7 +144,7 @@ RED.contextMenu = (function () {
|
||||
($(window).width() -MENU_WIDTH)) {
|
||||
direction = "left";
|
||||
}
|
||||
|
||||
|
||||
menu = RED.menu.init({
|
||||
direction: direction,
|
||||
onpreselect: function() {
|
||||
|
@@ -1105,6 +1105,10 @@ RED.editor = (function() {
|
||||
if (editing_node) {
|
||||
RED.sidebar.info.refresh(editing_node);
|
||||
RED.sidebar.help.show(editing_node.type, false);
|
||||
//ensure focused element is NOT body (for keyboard scope to operate correctly)
|
||||
if (document.activeElement.tagName === 'BODY') {
|
||||
$('#red-ui-editor-stack').trigger('focus')
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -100,7 +100,7 @@ RED.editor.codeEditor.monaco = (function() {
|
||||
"node-red-util": {package: "node-red", module: "util", path: "node-red/util.d.ts" },
|
||||
"node-red-func": {package: "node-red", module: "func", path: "node-red/func.d.ts" },
|
||||
}
|
||||
const defaultServerSideTypes = [ knownModules["node-red-util"], knownModules["node-red-func"], knownModules["globals"], knownModules["console"], knownModules["buffer"] ];
|
||||
const defaultServerSideTypes = [ knownModules["node-red-util"], knownModules["node-red-func"], knownModules["globals"], knownModules["console"], knownModules["buffer"] , knownModules["util"] ];
|
||||
|
||||
const modulesCache = {};
|
||||
|
||||
@@ -764,7 +764,7 @@ RED.editor.codeEditor.monaco = (function() {
|
||||
|
||||
|
||||
if(!options.stateId && options.stateId !== false) {
|
||||
options.stateId = RED.editor.generateViewStateId("monaco", options, (options.mode || options.title).split("/").pop());
|
||||
options.stateId = RED.editor.generateViewStateId("monaco", options, (options.mode || options.title || "").split("/").pop());
|
||||
}
|
||||
var el = options.element || $("#"+options.id)[0];
|
||||
var toolbarRow = $("<div>").appendTo(el);
|
||||
|
@@ -76,6 +76,9 @@ RED.editor.colorPicker = RED.colorPicker = (function() {
|
||||
var focusTarget = colorInput;
|
||||
colorInput.on("change", function (e) {
|
||||
var color = colorInput.val();
|
||||
if (options.defaultValue && !color.match(/^([a-z]+|#[0-9a-fA-F]{6}|#[0-9a-fA-F]{3})$/)) {
|
||||
color = options.defaultValue;
|
||||
}
|
||||
colorHiddenInput.val(color).trigger('change');
|
||||
refreshDisplay(color);
|
||||
});
|
||||
|
@@ -255,6 +255,9 @@
|
||||
var currentExpression = expressionEditor.getValue();
|
||||
var expr;
|
||||
var usesContext = false;
|
||||
var usesEnv = false;
|
||||
var usesMoment = false;
|
||||
var usesClone = false;
|
||||
var legacyMode = /(^|[^a-zA-Z0-9_'".])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression);
|
||||
$(".red-ui-editor-type-expression-legacy").toggle(legacyMode);
|
||||
try {
|
||||
@@ -267,6 +270,18 @@
|
||||
usesContext = true;
|
||||
return null;
|
||||
});
|
||||
expr.assign("env", function(name) {
|
||||
usesEnv = true;
|
||||
return null;
|
||||
});
|
||||
expr.assign("moment", function(name) {
|
||||
usesMoment = true;
|
||||
return null;
|
||||
});
|
||||
expr.assign("clone", function(name) {
|
||||
usesClone = true;
|
||||
return null;
|
||||
});
|
||||
} catch(err) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.invalid-expr",{message:err.message}),-1);
|
||||
return;
|
||||
@@ -284,6 +299,18 @@
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.context-unsupported"),-1);
|
||||
return;
|
||||
}
|
||||
if (usesEnv) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.env-unsupported"),-1);
|
||||
return;
|
||||
}
|
||||
if (usesMoment) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.moment-unsupported"),-1);
|
||||
return;
|
||||
}
|
||||
if (usesClone) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.clone-unsupported"),-1);
|
||||
return;
|
||||
}
|
||||
|
||||
var formattedResult;
|
||||
if (result !== undefined) {
|
||||
|
@@ -235,6 +235,7 @@
|
||||
RED.editor.colorPicker.create({
|
||||
id: "red-ui-editor-node-color",
|
||||
value: color,
|
||||
defaultValue: "#DDAA99",
|
||||
palette: recommendedColors,
|
||||
sortPalette: function (a, b) {return a.l - b.l;}
|
||||
}).appendTo(colorRow);
|
||||
|
@@ -101,6 +101,7 @@ RED.group = (function() {
|
||||
RED.editor.colorPicker.create({
|
||||
id:"node-input-style-stroke",
|
||||
value: style.stroke || defaultGroupStyle.stroke || "#a4a4a4",
|
||||
defaultValue: "#a4a4a4",
|
||||
palette: colorPalette,
|
||||
cellPerRow: colorCount,
|
||||
cellWidth: 16,
|
||||
@@ -112,6 +113,7 @@ RED.group = (function() {
|
||||
RED.editor.colorPicker.create({
|
||||
id:"node-input-style-fill",
|
||||
value: style.fill || defaultGroupStyle.fill ||"none",
|
||||
defaultValue: "none",
|
||||
palette: colorPalette,
|
||||
cellPerRow: colorCount,
|
||||
cellWidth: 16,
|
||||
@@ -129,6 +131,7 @@ RED.group = (function() {
|
||||
RED.editor.colorPicker.create({
|
||||
id:"node-input-style-color",
|
||||
value: style.color || defaultGroupStyle.color ||"#a4a4a4",
|
||||
defaultValue: "#a4a4a4",
|
||||
palette: colorPalette,
|
||||
cellPerRow: colorCount,
|
||||
cellWidth: 16,
|
||||
@@ -308,6 +311,7 @@ RED.group = (function() {
|
||||
RED.history.push(historyEvent);
|
||||
RED.view.select({nodes:[group]});
|
||||
RED.nodes.dirty(true);
|
||||
RED.view.focus();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -330,6 +334,7 @@ RED.group = (function() {
|
||||
RED.history.push(historyEvent);
|
||||
RED.view.select({nodes:newSelection})
|
||||
RED.nodes.dirty(true);
|
||||
RED.view.focus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -424,6 +429,7 @@ RED.group = (function() {
|
||||
});
|
||||
RED.history.push(historyEvent);
|
||||
RED.nodes.dirty(true);
|
||||
RED.view.focus();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -451,6 +457,7 @@ RED.group = (function() {
|
||||
}
|
||||
}
|
||||
RED.view.select({nodes:selection.nodes})
|
||||
RED.view.focus();
|
||||
}
|
||||
}
|
||||
function createGroup(nodes) {
|
||||
|
@@ -175,9 +175,19 @@ RED.palette = (function() {
|
||||
$('<button type="button" onclick="RED.workspaces.show(\''+type.substring(8).replace(/'/g,"\\'")+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-pencil"></i></button>').appendTo(popOverContent)
|
||||
}
|
||||
|
||||
var safeType = type.replace(/'/g,"\\'");
|
||||
const safeType = type.replace(/'/g,"\\'");
|
||||
const wrapStr = function (str) {
|
||||
if(str.indexOf(' ') >= 0) {
|
||||
return '"' + str + '"'
|
||||
}
|
||||
return str
|
||||
}
|
||||
|
||||
$('<button type="button" onclick="RED.search.show(\'type:'+safeType+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-search"></i></button>').appendTo(popOverContent)
|
||||
$('<button type="button"; return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-search"></i></button>')
|
||||
.appendTo(popOverContent)
|
||||
.on('click', function() {
|
||||
RED.search.show('type:' + wrapStr(safeType))
|
||||
})
|
||||
$('<button type="button" onclick="RED.sidebar.help.show(\''+safeType+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-book"></i></button>').appendTo(popOverContent)
|
||||
|
||||
$('<p>',{style:"font-size: 0.8em"}).text(metaData).appendTo(popOverContent);
|
||||
|
@@ -545,7 +545,7 @@ RED.projects = (function() {
|
||||
var sshwarningRow = $('<div class="red-ui-projects-dialog-screen-create-row-auth-error-no-keys"></div>').hide().appendTo(subrow);
|
||||
$('<div class="form-row"><i class="fa fa-warning"></i> '+RED._("projects.clone-project.ssh-key-desc")+'</div>').appendTo(sshwarningRow);
|
||||
subrow = $('<div style="text-align: center">').appendTo(sshwarningRow);
|
||||
$('<button class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.clone-project.ssh-key-add")+'</button>').appendTo(subrow).on("click", function(e) {
|
||||
$('<button type="button" class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.clone-project.ssh-key-add")+'</button>').appendTo(subrow).on("click", function(e) {
|
||||
e.preventDefault();
|
||||
dialog.dialog( "close" );
|
||||
RED.userSettings.show('gitconfig');
|
||||
@@ -1171,11 +1171,11 @@ RED.projects = (function() {
|
||||
|
||||
row = $('<div class="form-row button-group"></div>').appendTo(container);
|
||||
|
||||
var openProject = $('<button data-type="open" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-folder-open"></i><br/>'+RED._("projects.create.open")+'</button>').appendTo(row);
|
||||
var createAsEmpty = $('<button data-type="empty" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-asterisk"></i><br/>'+RED._("projects.create.create")+'</button>').appendTo(row);
|
||||
// var createAsCopy = $('<button data-type="copy" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i class="fa fa-long-arrow-right fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Copy existing</button>').appendTo(row);
|
||||
var createAsClone = $('<button data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-git"></i><br/>'+RED._("projects.create.clone")+'</button>').appendTo(row);
|
||||
// var createAsClone = $('<button data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-git fa-2x"></i><i class="fa fa-arrows-h fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Clone Repository</button>').appendTo(row);
|
||||
var openProject = $('<button type="button" data-type="open" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-folder-open"></i><br/>'+RED._("projects.create.open")+'</button>').appendTo(row);
|
||||
var createAsEmpty = $('<button type="button" data-type="empty" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-asterisk"></i><br/>'+RED._("projects.create.create")+'</button>').appendTo(row);
|
||||
// var createAsCopy = $('<button type="button" data-type="copy" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i class="fa fa-long-arrow-right fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Copy existing</button>').appendTo(row);
|
||||
var createAsClone = $('<button type="button" data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-archive fa-2x"></i><i style="position: absolute;" class="fa fa-git"></i><br/>'+RED._("projects.create.clone")+'</button>').appendTo(row);
|
||||
// var createAsClone = $('<button type="button" data-type="clone" class="red-ui-button red-ui-projects-dialog-button red-ui-projects-dialog-screen-create-type toggle"><i class="fa fa-git fa-2x"></i><i class="fa fa-arrows-h fa-2x"></i><i class="fa fa-archive fa-2x"></i><br/>Clone Repository</button>').appendTo(row);
|
||||
row.find(".red-ui-projects-dialog-screen-create-type").on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
container.find(".red-ui-projects-dialog-screen-create-type").removeClass('selected');
|
||||
@@ -1271,7 +1271,7 @@ RED.projects = (function() {
|
||||
var credentialsLeftBox = $('<div class="red-ui-projects-dialog-credentials-box-left">').appendTo(credentialsBox);
|
||||
|
||||
var credentialsEnabledBox = $('<div class="form-row red-ui-projects-dialog-credentials-box-enabled"></div>').appendTo(credentialsLeftBox);
|
||||
$('<label class="red-ui-projects-edit-form-inline-label"><input type="radio" name="projects-encryption-type" value="enabled"> <i class="fa fa-lock"></i> <span>'+RED._("projects.encryption-config.enable")+'</span></label>').appendTo(credentialsEnabledBox);
|
||||
$('<label class="red-ui-projects-edit-form-inline-label"><input type="radio" name="projects-encryption-type" value="enabled" checked> <i class="fa fa-lock"></i> <span>'+RED._("projects.encryption-config.enable")+'</span></label>').appendTo(credentialsEnabledBox);
|
||||
var credentialsDisabledBox = $('<div class="form-row red-ui-projects-dialog-credentials-box-disabled disabled"></div>').appendTo(credentialsLeftBox);
|
||||
$('<label class="red-ui-projects-edit-form-inline-label"><input type="radio" name="projects-encryption-type" value="disabled"> <i class="fa fa-unlock"></i> <span>'+RED._("projects.encryption-config.disable")+'</span></label>').appendTo(credentialsDisabledBox);
|
||||
|
||||
@@ -1397,7 +1397,7 @@ RED.projects = (function() {
|
||||
var sshwarningRow = $('<div class="red-ui-projects-dialog-screen-create-row-auth-error-no-keys"></div>').hide().appendTo(subrow);
|
||||
$('<div class="form-row"><i class="fa fa-warning"></i> '+RED._("projects.create.desc2")+'</div>').appendTo(sshwarningRow);
|
||||
subrow = $('<div style="text-align: center">').appendTo(sshwarningRow);
|
||||
$('<button class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.create.add-ssh-key")+'</button>').appendTo(subrow).on("click", function(e) {
|
||||
$('<button type="button" class="red-ui-button red-ui-projects-dialog-button">'+RED._("projects.create.add-ssh-key")+'</button>').appendTo(subrow).on("click", function(e) {
|
||||
e.preventDefault();
|
||||
$('#red-ui-projects-dialog-cancel').trigger("click");
|
||||
RED.userSettings.show('gitconfig');
|
||||
@@ -1631,14 +1631,14 @@ RED.projects = (function() {
|
||||
function deleteProject(row,name,done) {
|
||||
var cover = $('<div class="red-ui-projects-dialog-project-list-entry-delete-confirm"></div>').on("click", function(evt) { evt.stopPropagation(); }).appendTo(row);
|
||||
$('<span>').text(RED._("projects.delete.confirm")).appendTo(cover);
|
||||
$('<button class="red-ui-button red-ui-projects-dialog-button">'+RED._("common.label.cancel")+'</button>')
|
||||
$('<button type="button" class="red-ui-button red-ui-projects-dialog-button">'+RED._("common.label.cancel")+'</button>')
|
||||
.appendTo(cover)
|
||||
.on("click", function(e) {
|
||||
e.stopPropagation();
|
||||
cover.remove();
|
||||
done(true);
|
||||
});
|
||||
$('<button class="red-ui-button red-ui-projects-dialog-button primary">'+RED._("common.label.delete")+'</button>')
|
||||
$('<button type="button" class="red-ui-button red-ui-projects-dialog-button primary">'+RED._("common.label.delete")+'</button>')
|
||||
.appendTo(cover)
|
||||
.on("click", function(e) {
|
||||
e.stopPropagation();
|
||||
@@ -1822,7 +1822,7 @@ RED.projects = (function() {
|
||||
header.addClass("selectable");
|
||||
|
||||
var tools = $('<div class="red-ui-projects-dialog-project-list-entry-tools"></div>').appendTo(header);
|
||||
$('<button class="red-ui-button red-ui-projects-dialog-button red-ui-button-small" style="float: right;"><i class="fa fa-trash"></i></button>')
|
||||
$('<button type="button" class="red-ui-button red-ui-projects-dialog-button red-ui-button-small" style="float: right;"><i class="fa fa-trash"></i></button>')
|
||||
.appendTo(tools)
|
||||
.on("click", function(e) {
|
||||
e.stopPropagation();
|
||||
|
@@ -106,38 +106,51 @@ RED.search = (function() {
|
||||
return val;
|
||||
}
|
||||
|
||||
function search(val) {
|
||||
var results = [];
|
||||
var typeFilter;
|
||||
var m = /(?:^| )type:([^ ]+)/.exec(val);
|
||||
if (m) {
|
||||
val = val.replace(/(?:^| )type:[^ ]+/,"");
|
||||
typeFilter = m[1];
|
||||
function extractType(val, flags) {
|
||||
// extracts: type:XYZ & type:"X Y Z"
|
||||
const regEx = /(?:type):\s*(?:"([^"]+)"|([^" ]+))/;
|
||||
let m
|
||||
while ((m = regEx.exec(val)) !== null) {
|
||||
// avoid infinite loops with zero-width matches
|
||||
if (m.index === regEx.lastIndex) {
|
||||
regEx.lastIndex++;
|
||||
}
|
||||
val = val.replace(m[0]," ").trim()
|
||||
const flag = m[2] || m[1] // quoted entries in capture group 1, unquoted in capture group 2
|
||||
flags.type = flags.type || [];
|
||||
flags.type.push(flag);
|
||||
}
|
||||
var flags = {};
|
||||
return val;
|
||||
}
|
||||
|
||||
function search(val) {
|
||||
const results = [];
|
||||
const flags = {};
|
||||
val = extractFlag(val,"invalid",flags);
|
||||
val = extractFlag(val,"unused",flags);
|
||||
val = extractFlag(val,"config",flags);
|
||||
val = extractFlag(val,"subflow",flags);
|
||||
val = extractFlag(val,"hidden",flags);
|
||||
val = extractFlag(val,"modified",flags);
|
||||
val = extractValue(val,"flow",flags);// flow:active or flow:<flow-id>
|
||||
val = extractValue(val,"flow",flags);// flow:current or flow:<flow-id>
|
||||
val = extractValue(val,"uses",flags);// uses:<node-id>
|
||||
val = extractType(val,flags);// type:<node-type>
|
||||
val = val.trim();
|
||||
var hasFlags = Object.keys(flags).length > 0;
|
||||
const hasFlags = Object.keys(flags).length > 0;
|
||||
const hasTypeFilter = flags.type && flags.type.length > 0
|
||||
if (flags.flow && flags.flow.indexOf("current") >= 0) {
|
||||
let idx = flags.flow.indexOf("current");
|
||||
flags.flow[idx] = RED.workspaces.active();//convert active to flow ID
|
||||
flags.flow[idx] = RED.workspaces.active();//convert 'current' to active flow ID
|
||||
}
|
||||
if (flags.flow && flags.flow.length) {
|
||||
flags.flow = [ ...new Set(flags.flow) ]; //deduplicate
|
||||
}
|
||||
if (val.length > 0 || typeFilter || hasFlags) {
|
||||
if (val.length > 0 || hasFlags) {
|
||||
val = val.toLowerCase();
|
||||
var i;
|
||||
var j;
|
||||
var list = [];
|
||||
var nodes = {};
|
||||
let i;
|
||||
let j;
|
||||
let list = [];
|
||||
const nodes = {};
|
||||
let keys = [];
|
||||
if (flags.uses) {
|
||||
keys = flags.uses;
|
||||
@@ -145,10 +158,10 @@ RED.search = (function() {
|
||||
keys = Object.keys(index);
|
||||
}
|
||||
for (i=0;i<keys.length;i++) {
|
||||
var key = keys[i];
|
||||
var kpos = keys[i].indexOf(val);
|
||||
if (kpos > -1) {
|
||||
var ids = Object.keys(index[key]||{});
|
||||
const key = keys[i];
|
||||
const kpos = val ? keys[i].indexOf(val) : -1;
|
||||
if (kpos > -1 || (val === "" && hasFlags)) {
|
||||
const ids = Object.keys(index[key]||{});
|
||||
for (j=0;j<ids.length;j++) {
|
||||
var node = index[key][ids[j]];
|
||||
var isConfigNode = node.node._def.category === "config" && node.node.type !== 'group';
|
||||
@@ -156,7 +169,7 @@ RED.search = (function() {
|
||||
continue;
|
||||
}
|
||||
if (flags.hasOwnProperty("invalid")) {
|
||||
var nodeIsValid = !node.node.hasOwnProperty("valid") || node.node.valid;
|
||||
const nodeIsValid = !node.node.hasOwnProperty("valid") || node.node.valid;
|
||||
if (flags.invalid === nodeIsValid) {
|
||||
continue;
|
||||
}
|
||||
@@ -186,8 +199,8 @@ RED.search = (function() {
|
||||
}
|
||||
}
|
||||
if (flags.hasOwnProperty("unused")) {
|
||||
var isUnused = (node.node.type === 'subflow' && node.node.instances.length === 0) ||
|
||||
(isConfigNode && node.node.users.length === 0)
|
||||
const isUnused = (node.node.type === 'subflow' && node.node.instances.length === 0) ||
|
||||
(isConfigNode && node.node.users.length === 0 && node.node._def.hasUsers !== false)
|
||||
if (flags.unused !== isUnused) {
|
||||
continue;
|
||||
}
|
||||
@@ -197,12 +210,16 @@ RED.search = (function() {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (!typeFilter || node.node.type === typeFilter) {
|
||||
nodes[node.node.id] = nodes[node.node.id] = {
|
||||
let typeIndex = -1
|
||||
if(hasTypeFilter) {
|
||||
typeIndex = flags.type.indexOf(node.node.type)
|
||||
}
|
||||
if (!hasTypeFilter || typeIndex > -1) {
|
||||
nodes[node.node.id] = nodes[node.node.id] || {
|
||||
node: node.node,
|
||||
label: node.label
|
||||
};
|
||||
nodes[node.node.id].index = Math.min(nodes[node.node.id].index||Infinity,kpos);
|
||||
nodes[node.node.id].index = Math.min(nodes[node.node.id].index || Infinity, typeIndex > -1 ? typeIndex : kpos);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -538,7 +555,7 @@ RED.search = (function() {
|
||||
$(previousActiveElement).trigger("focus");
|
||||
}
|
||||
previousActiveElement = null;
|
||||
}
|
||||
}
|
||||
if(!keepSearchToolbar) {
|
||||
clearActiveSearch();
|
||||
}
|
||||
@@ -630,7 +647,7 @@ RED.search = (function() {
|
||||
$("#red-ui-sidebar-shade").on('mousedown',hide);
|
||||
|
||||
$("#red-ui-view-searchtools-close").on("click", function close() {
|
||||
clearActiveSearch();
|
||||
clearActiveSearch();
|
||||
updateSearchToolbar();
|
||||
});
|
||||
$("#red-ui-view-searchtools-close").trigger("click");
|
||||
|
@@ -506,6 +506,13 @@ RED.subflow = (function() {
|
||||
RED.nodes.groups(id).forEach(function(n) {
|
||||
removedGroups.push(n);
|
||||
})
|
||||
|
||||
var removedJunctions = RED.nodes.junctions(id)
|
||||
for (var i=0;i<removedJunctions.length;i++) {
|
||||
var removedEntities = RED.nodes.removeJunction(removedJunctions[i])
|
||||
removedLinks = removedLinks.concat(removedEntities.links)
|
||||
}
|
||||
|
||||
var removedConfigNodes = [];
|
||||
for (var i=0;i<removedNodes.length;i++) {
|
||||
var removedEntities = RED.nodes.remove(removedNodes[i].id);
|
||||
@@ -536,6 +543,7 @@ RED.subflow = (function() {
|
||||
nodes:removedNodes,
|
||||
links:removedLinks,
|
||||
groups: removedGroups,
|
||||
junctions: removedJunctions,
|
||||
subflows: [activeSubflow]
|
||||
}
|
||||
}
|
||||
@@ -877,6 +885,7 @@ RED.subflow = (function() {
|
||||
RED.nodes.dirty(true);
|
||||
RED.view.updateActive();
|
||||
RED.view.select(null);
|
||||
RED.view.focus();
|
||||
}
|
||||
|
||||
|
||||
@@ -991,6 +1000,17 @@ RED.subflow = (function() {
|
||||
default: inputType
|
||||
})
|
||||
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 {
|
||||
input.val(val.value)
|
||||
}
|
||||
|
@@ -50,7 +50,7 @@ RED.sidebar.help = (function() {
|
||||
|
||||
tocPanel = $("<div>", {class: "red-ui-sidebar-help-toc"}).appendTo(stackContainer);
|
||||
var helpPanel = $("<div>").css({
|
||||
"overflow-y": "scroll"
|
||||
"overflow-y": "auto"
|
||||
}).appendTo(stackContainer);
|
||||
|
||||
panels = RED.panels.create({
|
||||
|
@@ -98,7 +98,7 @@ RED.sidebar.info = (function() {
|
||||
|
||||
propertiesPanelContent = $("<div>").css({
|
||||
"flex":"1 1 auto",
|
||||
"overflow-y":"scroll",
|
||||
"overflow-y":"auto",
|
||||
}).appendTo(propertiesPanel);
|
||||
|
||||
|
||||
|
@@ -437,17 +437,17 @@ RED.tourGuide = (function() {
|
||||
return [
|
||||
{
|
||||
id: "3_0",
|
||||
label: "3.0.0-beta.4",
|
||||
label: "3.0",
|
||||
path: "./tours/welcome.js"
|
||||
},
|
||||
{
|
||||
id: "2_2",
|
||||
label: "2.2.0",
|
||||
label: "2.2",
|
||||
path: "./tours/2.2/welcome.js"
|
||||
},
|
||||
{
|
||||
id: "2_1",
|
||||
label: "2.1.0",
|
||||
label: "2.1",
|
||||
path: "./tours/2.1/welcome.js"
|
||||
}
|
||||
];
|
||||
|
@@ -269,8 +269,8 @@ RED.typeSearch = (function() {
|
||||
moveCallback = opts.move;
|
||||
RED.events.emit("type-search:open");
|
||||
//shade.show();
|
||||
if ($("#red-ui-main-container").height() - opts.y - 150 < 0) {
|
||||
opts.y = opts.y - 235;
|
||||
if ($("#red-ui-main-container").height() - opts.y - 195 < 0) {
|
||||
opts.y = opts.y - 275;
|
||||
}
|
||||
dialog.css({left:opts.x+"px",top:opts.y+"px"}).show();
|
||||
searchResultsDiv.slideDown(300);
|
||||
|
@@ -823,7 +823,7 @@ RED.view.tools = (function() {
|
||||
* @param {Object || Object[]} wires The wire(s) to split and replace with link-out, link-in nodes.
|
||||
*/
|
||||
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) {
|
||||
return
|
||||
}
|
||||
@@ -1015,7 +1015,7 @@ RED.view.tools = (function() {
|
||||
const nodeDef = n._def || RED.nodes.getType(n.type)
|
||||
if (nodeDef && nodeDef.defaults && nodeDef.defaults.name) {
|
||||
const paletteLabel = RED.utils.getPaletteLabel(n.type, nodeDef)
|
||||
const defaultNodeNameRE = new RegExp('^'+paletteLabel+' (\\d+)$')
|
||||
const defaultNodeNameRE = new RegExp('^'+paletteLabel.replace(/[.*+?^${}()|[\]\\]/g, '\\$&')+' (\\d+)$')
|
||||
if (!typeIndex.hasOwnProperty(n.type)) {
|
||||
const existingNodes = RED.nodes.filterNodes({type: n.type})
|
||||
let maxNameNumber = 0;
|
||||
@@ -1061,7 +1061,7 @@ RED.view.tools = (function() {
|
||||
}
|
||||
|
||||
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) {
|
||||
return
|
||||
}
|
||||
@@ -1089,6 +1089,7 @@ RED.view.tools = (function() {
|
||||
linkGroups.sort(function(A,B) {
|
||||
return groupedLinks[B].length - groupedLinks[A].length
|
||||
})
|
||||
const wasDirty = RED.nodes.dirty()
|
||||
linkGroups.forEach(function(gid) {
|
||||
var links = groupedLinks[gid]
|
||||
var junction = {
|
||||
@@ -1179,12 +1180,14 @@ RED.view.tools = (function() {
|
||||
})
|
||||
if (addedJunctions.length > 0) {
|
||||
RED.history.push({
|
||||
dirty: wasDirty,
|
||||
t: 'add',
|
||||
links: addedLinks,
|
||||
junctions: addedJunctions,
|
||||
removedLinks: Array.from(removedLinks)
|
||||
})
|
||||
RED.nodes.dirty(true)
|
||||
RED.view.select({nodes: addedJunctions });
|
||||
}
|
||||
RED.view.redraw(true);
|
||||
}
|
||||
|
@@ -1071,12 +1071,15 @@ RED.view = (function() {
|
||||
RED.view.redraw();
|
||||
}
|
||||
|
||||
// `point` is the place in the workspace the mouse has clicked.
|
||||
// This takes into account scrolling and scaling of the workspace.
|
||||
var ox = point[0];
|
||||
var oy = point[1];
|
||||
|
||||
// Need to map that to browser location to position the pop-up
|
||||
const offset = $("#red-ui-workspace-chart").offset()
|
||||
var clientX = ox + offset.left - $("#red-ui-workspace-chart").scrollLeft()
|
||||
var clientY = oy + offset.top - $("#red-ui-workspace-chart").scrollTop()
|
||||
var clientX = (ox * scaleFactor) + offset.left - $("#red-ui-workspace-chart").scrollLeft()
|
||||
var clientY = (oy * scaleFactor) + offset.top - $("#red-ui-workspace-chart").scrollTop()
|
||||
|
||||
if (RED.settings.get("editor").view['view-snap-grid']) {
|
||||
// eventLayer.append("circle").attr("cx",point[0]).attr("cy",point[1]).attr("r","2").attr('fill','red')
|
||||
@@ -4580,12 +4583,10 @@ RED.view = (function() {
|
||||
icon_groupEl.setAttribute("y",0);
|
||||
icon_groupEl.style["pointer-events"] = "none";
|
||||
node[0][0].__iconGroup__ = icon_groupEl;
|
||||
var icon_shade = document.createElementNS("http://www.w3.org/2000/svg","rect");
|
||||
var icon_shade = document.createElementNS("http://www.w3.org/2000/svg","path");
|
||||
icon_shade.setAttribute("x",0);
|
||||
icon_shade.setAttribute("y",0);
|
||||
icon_shade.setAttribute("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);
|
||||
node[0][0].__iconShade__ = icon_shade;
|
||||
|
||||
@@ -4878,9 +4879,20 @@ RED.view = (function() {
|
||||
}
|
||||
|
||||
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",
|
||||
"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);
|
||||
}
|
||||
@@ -4897,7 +4909,7 @@ RED.view = (function() {
|
||||
if (d._def.button) {
|
||||
var buttonEnabled = isButtonEnabled(d);
|
||||
this.__buttonGroup__.classList.toggle("red-ui-flow-node-button-disabled", !buttonEnabled);
|
||||
if (RED.runtime && Object.hasOwn(RED.runtime,'started')) {
|
||||
if (RED.runtime && RED.runtime.started !== undefined) {
|
||||
this.__buttonGroup__.classList.toggle("red-ui-flow-node-button-stopped", !RED.runtime.started);
|
||||
}
|
||||
|
||||
|
@@ -30,7 +30,7 @@
|
||||
bottom: 0px;
|
||||
left:0px;
|
||||
right: 0px;
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.red-ui-debug-filter-box {
|
||||
position:absolute;
|
||||
|
@@ -368,7 +368,7 @@ button.red-ui-button-small
|
||||
border:1px solid var(--red-ui-secondary-border-color);
|
||||
border-radius:5px;
|
||||
height: calc(100% - 21px);
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
background: var(--red-ui-secondary-background);
|
||||
}
|
||||
|
||||
@@ -562,7 +562,7 @@ div.red-ui-button-small.red-ui-color-picker-opacity-slider-handle {
|
||||
.red-ui-icon-list {
|
||||
width: 308px;
|
||||
height: 200px;
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
line-height: 0px;
|
||||
position: relative;
|
||||
&.red-ui-icon-list-dark {
|
||||
|
@@ -171,6 +171,7 @@
|
||||
left:0;
|
||||
width: 30px;
|
||||
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);
|
||||
}
|
||||
.red-ui-palette-icon-container-right {
|
||||
@@ -178,6 +179,7 @@
|
||||
right: 0;
|
||||
border-right: none;
|
||||
border-left: 1px solid var(--red-ui-node-icon-background-color);
|
||||
border-radius: 0px 4px 4px 0px;
|
||||
}
|
||||
.red-ui-palette-icon {
|
||||
display: inline-block;
|
||||
|
@@ -26,7 +26,7 @@
|
||||
}
|
||||
}
|
||||
#red-ui-project-settings-tab-settings {
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.red-ui-sidebar-vc-shade {
|
||||
background: var(--red-ui-primary-background);
|
||||
@@ -183,7 +183,7 @@
|
||||
}
|
||||
.red-ui-projects-dialog-project-list-inner-container {
|
||||
flex-grow: 1 ;
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
position:relative;
|
||||
.red-ui-editableList-border {
|
||||
border: none;
|
||||
|
@@ -20,7 +20,7 @@
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
right: 0;
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
|
||||
.red-ui-palette-category {
|
||||
&:not(.expanded) button {
|
||||
|
@@ -67,7 +67,7 @@
|
||||
left: 0;
|
||||
bottom: 0;
|
||||
padding: 8px 20px 20px;
|
||||
overflow-y: scroll;
|
||||
overflow-y: auto;
|
||||
}
|
||||
.red-ui-settings-row {
|
||||
padding: 5px 10px 2px;
|
||||
|
@@ -29,7 +29,7 @@
|
||||
#red-ui-workspace-chart {
|
||||
overflow: auto;
|
||||
position: absolute;
|
||||
bottom:25px;
|
||||
bottom:26px;
|
||||
top: 35px;
|
||||
left:0px;
|
||||
right:0px;
|
||||
|
@@ -1,15 +1,15 @@
|
||||
export default {
|
||||
version: "3.0.0-beta.4",
|
||||
version: "3.0.0",
|
||||
steps: [
|
||||
{
|
||||
titleIcon: "fa fa-map-o",
|
||||
title: {
|
||||
"en-US": "Welcome to Node-RED 3.0 Beta 4!",
|
||||
"ja": "Node-RED 3.0 ベータ4へようこそ!"
|
||||
"en-US": "Welcome to Node-RED 3.0!",
|
||||
"ja": "Node-RED 3.0へようこそ!"
|
||||
},
|
||||
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>",
|
||||
"ja": "<p>これはNode-RED 3.0のもう一つの最後のベータリリースです。</p><p>本リリースの新機能を見つけてみましょう。</p>"
|
||||
"en-US": "<p>Let's take a moment to discover the new features in this release.</p>",
|
||||
"ja": "<p>本リリースの新機能を見つけてみましょう。</p>"
|
||||
}
|
||||
},
|
||||
{
|
||||
|
@@ -14,6 +14,9 @@ declare var msg: NodeMessage;
|
||||
/** @type {string} the id of the incoming `msg` (alias of msg._msgid) */
|
||||
declare const __msgid__:string;
|
||||
|
||||
declare const util:typeof import('util')
|
||||
declare const promisify:typeof import('util').promisify
|
||||
|
||||
/**
|
||||
* @typedef NodeStatus
|
||||
* @type {object}
|
||||
|
@@ -160,6 +160,7 @@
|
||||
'$base64encode':{ args:[ ]},
|
||||
'$boolean':{ args:[ 'arg' ]},
|
||||
'$ceil':{ args:[ 'number' ]},
|
||||
'$clone': { args:[ 'arg' ]},
|
||||
'$contains':{ args:[ 'str', 'pattern' ]},
|
||||
'$count':{ args:[ 'array' ]},
|
||||
'$decodeUrl':{ args:[ 'str' ]},
|
||||
|
@@ -245,47 +245,37 @@
|
||||
// complete parentage of the node that generated this message.
|
||||
// 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
|
||||
//
|
||||
pathParts = o.path.split("/");
|
||||
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);
|
||||
if (pathParts[0] === "global") {
|
||||
pathParts = [];
|
||||
}
|
||||
} else if (pathParts.length > 1) {
|
||||
// Highlight the subflow instance node.
|
||||
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) => {
|
||||
if (index === 0) {
|
||||
return {
|
||||
id: id,
|
||||
label: RED.nodes.workspace(id).label
|
||||
}
|
||||
if (id === "global") {
|
||||
return { id: sourceNode.id, label: getNodeLabel(sourceNode) }
|
||||
}
|
||||
return { id: id, label: RED.nodes.workspace(id).label } //flow id + name
|
||||
} else {
|
||||
var instanceNode = RED.nodes.node(id)
|
||||
return {
|
||||
id: id,
|
||||
label: (instanceNode.name || RED.nodes.subflow(instanceNode.type.substring(8)).name)
|
||||
}
|
||||
const instanceNode = RED.nodes.node(id)
|
||||
const pathLabel = (instanceNode.name || RED.nodes.subflow(instanceNode.type.substring(8)).name)
|
||||
return { id: id, label: pathLabel }
|
||||
}
|
||||
})
|
||||
if (pathParts.length === 1) {
|
||||
pathHierarchy.push({
|
||||
id: o.id,
|
||||
label: sourceNode.name || sourceNode.type+":"+sourceNode.id
|
||||
})
|
||||
if (pathParts.length === 1 && pathParts[0] !== "global") {
|
||||
pathHierarchy.push({ id: o.id, label: getNodeLabel(sourceNode) })
|
||||
}
|
||||
if (o._alias) {
|
||||
let aliasNode = RED.nodes.node(o._alias)
|
||||
if (aliasNode) {
|
||||
pathHierarchy.push({
|
||||
id: o._alias,
|
||||
label: aliasNode.name || aliasNode.type+":"+aliasNode.id
|
||||
})
|
||||
pathHierarchy.push({ id: o._alias, label: getNodeLabel(aliasNode) })
|
||||
}
|
||||
}
|
||||
} else {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
<script type="text/html" data-template-name="complete">
|
||||
<div class="form-row node-input-target-row">
|
||||
<button id="node-input-complete-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
<button type="button" id="node-input-complete-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
</div>
|
||||
<div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px">
|
||||
<div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-complete-target-filter"></div>
|
||||
|
@@ -12,7 +12,7 @@
|
||||
<label for="node-input-uncaught" style="width: auto" data-i18n="catch.label.uncaught"></label>
|
||||
</div>
|
||||
<div class="form-row node-input-target-row">
|
||||
<button id="node-input-catch-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
<button type="button" id="node-input-catch-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
</div>
|
||||
<div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px">
|
||||
<div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-catch-target-filter"></div>
|
||||
|
@@ -8,7 +8,7 @@
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-row node-input-target-row">
|
||||
<button id="node-input-status-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
<button type="button" id="node-input-status-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
|
||||
</div>
|
||||
<div class="form-row node-input-target-row node-input-target-list-row" style="position: relative; min-height: 100px">
|
||||
<div style="position: absolute; top: -30px; right: 0;"><input type="text" id="node-input-status-target-filter"></div>
|
||||
|
@@ -29,23 +29,23 @@ module.exports = function(RED) {
|
||||
"use strict";
|
||||
const crypto = require("crypto");
|
||||
const targetCache = (function () {
|
||||
const registry = { id: {}, name: {} };
|
||||
function getIndex(/** @type {[LinkTarget]}*/ targets, id) {
|
||||
let registry = { id: {}, name: {} }
|
||||
function getIndex (/** @type {[LinkTarget]} */ targets, id) {
|
||||
for (let index = 0; index < (targets || []).length; index++) {
|
||||
const element = targets[index];
|
||||
const element = targets[index]
|
||||
if (element.id === id) {
|
||||
return index;
|
||||
return index
|
||||
}
|
||||
}
|
||||
return -1;
|
||||
return -1
|
||||
}
|
||||
/**
|
||||
* Generate a target object from a node
|
||||
* @param {LinkInNode} node
|
||||
* @param {LinkInNode} node
|
||||
* @returns {LinkTarget} a link target object
|
||||
*/
|
||||
function generateTarget(node) {
|
||||
const isSubFlow = node._flow.TYPE === "subflow";
|
||||
function generateTarget (node) {
|
||||
const isSubFlow = node._flow.TYPE === 'subflow'
|
||||
return {
|
||||
id: node.id,
|
||||
name: node.name || node.id,
|
||||
@@ -58,72 +58,72 @@ module.exports = function(RED) {
|
||||
/**
|
||||
* Get a list of targets registerd to this name
|
||||
* @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.
|
||||
*/
|
||||
getTargets(name, excludeSubflows) {
|
||||
const targets = registry.name[name] || [];
|
||||
getTargets (name, excludeSubflows) {
|
||||
const targets = registry.name[name] || []
|
||||
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.
|
||||
* To restrict to a single flow, include the `flowId`
|
||||
* If there is no targets OR more than one target, null is returned
|
||||
* @param {string} name Name of the node
|
||||
* @param {string} [flowId]
|
||||
* @param {string} [flowId]
|
||||
* @returns {LinkTarget} target
|
||||
*/
|
||||
getTarget(name, flowId) {
|
||||
/** @type {[LinkTarget]}*/
|
||||
let possibleTargets = this.getTargets(name);
|
||||
/** @type {LinkTarget}*/
|
||||
let target;
|
||||
getTarget (name, flowId) {
|
||||
/** @type {[LinkTarget]} */
|
||||
let possibleTargets = this.getTargets(name)
|
||||
/** @type {LinkTarget} */
|
||||
let target
|
||||
if (possibleTargets.length && flowId) {
|
||||
possibleTargets = possibleTargets.filter(e => e.flowId == flowId);
|
||||
possibleTargets = possibleTargets.filter(e => e.flowId === flowId)
|
||||
}
|
||||
if (possibleTargets.length === 1) {
|
||||
target = possibleTargets[0];
|
||||
target = possibleTargets[0]
|
||||
}
|
||||
return target;
|
||||
return target
|
||||
},
|
||||
/**
|
||||
* Get a target by node ID
|
||||
* @param {string} nodeId ID of the node
|
||||
* @returns {LinkTarget} target
|
||||
*/
|
||||
getTargetById(nodeId) {
|
||||
return registry.id[nodeId];
|
||||
getTargetById (nodeId) {
|
||||
return registry.id[nodeId]
|
||||
},
|
||||
register(/** @type {LinkInNode} */ node) {
|
||||
const target = generateTarget(node);
|
||||
const tByName = this.getTarget(target.name, target.flowId);
|
||||
register (/** @type {LinkInNode} */ node) {
|
||||
const target = generateTarget(node)
|
||||
const tByName = this.getTarget(target.name, target.flowId)
|
||||
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.id[target.id] = target;
|
||||
return target;
|
||||
registry.id[target.id] = target
|
||||
return target
|
||||
},
|
||||
remove(node) {
|
||||
const target = generateTarget(node);
|
||||
const targs = this.getTargets(target.name);
|
||||
const idx = getIndex(targs, target.id);
|
||||
remove (node) {
|
||||
const target = generateTarget(node)
|
||||
const targs = this.getTargets(target.name)
|
||||
const idx = getIndex(targs, target.id)
|
||||
if (idx > -1) {
|
||||
targs.splice(idx, 1);
|
||||
targs.splice(idx, 1)
|
||||
}
|
||||
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() {
|
||||
registry = { id: {}, name: {} };
|
||||
clear () {
|
||||
registry = { id: {}, name: {} }
|
||||
}
|
||||
}
|
||||
})();
|
||||
})()
|
||||
|
||||
function LinkInNode(n) {
|
||||
RED.nodes.createNode(this,n);
|
||||
|
@@ -91,21 +91,21 @@
|
||||
<div id="func-tab-init" style="display:none">
|
||||
<div class="form-row node-text-editor-row" style="position:relative">
|
||||
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-init-editor" ></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-init-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button type="button" id="node-init-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="func-tab-body" style="display:none">
|
||||
<div class="form-row node-text-editor-row" style="position:relative">
|
||||
<div style="height: 220px; min-height:150px;" class="node-text-editor" id="node-input-func-editor" ></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-function-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button type="button" id="node-function-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div id="func-tab-finalize" style="display:none">
|
||||
<div class="form-row node-text-editor-row" style="position:relative">
|
||||
<div style="height: 250px; min-height:150px;" class="node-text-editor" id="node-input-finalize-editor" ></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button id="node-finalize-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
<div style="position: absolute; right:0; bottom: calc(100% - 20px); z-Index: 10;"><button type="button" id="node-finalize-expand-js" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button></div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -294,7 +294,7 @@
|
||||
if (val === "_custom_") {
|
||||
val = $(this).val();
|
||||
}
|
||||
var varName = val.trim().replace(/^@/,"").replace(/@.*$/,"").replace(/[-_/].?/g, function(v) { return v[1]?v[1].toUpperCase():"" });
|
||||
var varName = val.trim().replace(/^@/,"").replace(/@.*$/,"").replace(/[-_/\.].?/g, function(v) { return v[1]?v[1].toUpperCase():"" });
|
||||
fvar.val(varName);
|
||||
fvar.trigger("change");
|
||||
|
||||
|
@@ -168,9 +168,9 @@ module.exports = function(RED) {
|
||||
return getFromValueType(RED.util.getMessageProperty(msg,rule.from),done);
|
||||
} else if (rule.fromt === 'flow' || rule.fromt === 'global') {
|
||||
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
|
||||
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) => {
|
||||
if (err) {
|
||||
@@ -318,7 +318,7 @@ module.exports = function(RED) {
|
||||
}
|
||||
var r = node.rules[currentRule];
|
||||
if (r.t === "move") {
|
||||
if ((r.tot !== r.pt) || (r.p.indexOf(r.to) !== -1)) {
|
||||
if ((r.tot !== r.pt) || (r.p.indexOf(r.to) !== -1) && (r.p !== r.to)) {
|
||||
applyRule(msg,{t:"set", p:r.to, pt:r.tot, to:r.p, tot:r.pt},(err,msg) => {
|
||||
applyRule(msg,{t:"delete", p:r.p, pt:r.pt}, (err,msg) => {
|
||||
completeApplyingRules(msg,currentRule,done);
|
||||
|
@@ -26,7 +26,7 @@
|
||||
<option value="yaml">YAML</option>
|
||||
<option value="text" data-i18n="template.label.none"></option>
|
||||
</select>
|
||||
<button id="node-template-expand-editor" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button>
|
||||
<button type="button" id="node-template-expand-editor" class="red-ui-button red-ui-button-small"><i class="fa fa-expand"></i></button>
|
||||
</div>
|
||||
</div>
|
||||
<div class="form-row node-text-editor-row">
|
||||
|
@@ -25,7 +25,7 @@
|
||||
<label class="red-ui-button" for="node-config-input-certfile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label>
|
||||
<input class="hide" type="file" id="node-config-input-certfile">
|
||||
<span id="tls-config-certname" style="width: calc(100% - 280px); overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span>
|
||||
<button class="red-ui-button red-ui-button-small" id="tls-config-button-cert-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
<button type="button" class="red-ui-button red-ui-button-small" id="tls-config-button-cert-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
</span>
|
||||
<input type="hidden" id="node-config-input-certname">
|
||||
<input type="hidden" id="node-config-input-certdata">
|
||||
@@ -37,7 +37,7 @@
|
||||
<label class="red-ui-button" for="node-config-input-keyfile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label>
|
||||
<input class="hide" type="file" id="node-config-input-keyfile">
|
||||
<span id="tls-config-keyname" style="width: calc(100% - 280px); overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span>
|
||||
<button class="red-ui-button red-ui-button-small" id="tls-config-button-key-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
<button type="button" class="red-ui-button red-ui-button-small" id="tls-config-button-key-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
</span>
|
||||
<input type="hidden" id="node-config-input-keyname">
|
||||
<input type="hidden" id="node-config-input-keydata">
|
||||
@@ -53,7 +53,7 @@
|
||||
<label class="red-ui-button" for="node-config-input-cafile"><i class="fa fa-upload"></i> <span data-i18n="tls.label.upload"></span></label>
|
||||
<input class="hide" type="file" title=" " id="node-config-input-cafile">
|
||||
<span id="tls-config-caname" style="width: calc(100% - 280px); overflow: hidden; line-height:34px; height:34px; text-overflow: ellipsis; white-space: nowrap; display: inline-block; vertical-align: middle;"> </span>
|
||||
<button class="red-ui-button red-ui-button-small" id="tls-config-button-ca-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
<button type="button" class="red-ui-button red-ui-button-small" id="tls-config-button-ca-clear" style="margin-left: 10px"><i class="fa fa-times"></i></button>
|
||||
</span>
|
||||
<input type="hidden" id="node-config-input-caname">
|
||||
<input type="hidden" id="node-config-input-cadata">
|
||||
|
@@ -101,6 +101,7 @@
|
||||
hostField.val(data.host);
|
||||
}
|
||||
},
|
||||
sortable: true,
|
||||
removable: true
|
||||
});
|
||||
if (this.noproxy) {
|
||||
|
@@ -474,7 +474,6 @@ module.exports = function(RED) {
|
||||
setIfHasProperty(opts, node, "protocolVersion", init);
|
||||
setIfHasProperty(opts, node, "keepalive", init);
|
||||
setIfHasProperty(opts, node, "cleansession", init);
|
||||
setIfHasProperty(opts, node, "sessionExpiry", init);
|
||||
setIfHasProperty(opts, node, "topicAliasMaximum", init);
|
||||
setIfHasProperty(opts, node, "maximumPacketSize", init);
|
||||
setIfHasProperty(opts, node, "receiveMaximum", init);
|
||||
@@ -484,6 +483,11 @@ module.exports = function(RED) {
|
||||
} else if (hasProperty(opts, "userProps")) {
|
||||
node.userProperties = opts.userProps;
|
||||
}
|
||||
if (hasProperty(opts, "sessionExpiry")) {
|
||||
node.sessionExpiryInterval = opts.sessionExpiry;
|
||||
} else if (hasProperty(opts, "sessionExpiryInterval")) {
|
||||
node.sessionExpiryInterval = opts.sessionExpiryInterval
|
||||
}
|
||||
|
||||
function createLWT(topic, payload, qos, retain, v5opts, v5SubPropName) {
|
||||
let message = undefined;
|
||||
@@ -782,7 +786,9 @@ module.exports = function(RED) {
|
||||
|
||||
// Send any birth message
|
||||
if (node.birthMessage) {
|
||||
node.publish(node.birthMessage);
|
||||
setTimeout(() => {
|
||||
node.publish(node.birthMessage);
|
||||
}, 1);
|
||||
}
|
||||
});
|
||||
node._clientOn("reconnect", function() {
|
||||
@@ -991,14 +997,21 @@ module.exports = function(RED) {
|
||||
}
|
||||
|
||||
if (topicOK) {
|
||||
node.client.publish(msg.topic, msg.payload, options, function(err) {
|
||||
done && done(err);
|
||||
return
|
||||
});
|
||||
node.client.publish(msg.topic, msg.payload, options, function (err) {
|
||||
if (done) {
|
||||
done(err)
|
||||
} else {
|
||||
node.error(err, msg)
|
||||
}
|
||||
})
|
||||
} else {
|
||||
const error = new Error(RED._("mqtt.errors.invalid-topic"));
|
||||
error.warn = true;
|
||||
done(error);
|
||||
const error = new Error(RED._("mqtt.errors.invalid-topic"))
|
||||
error.warn = true
|
||||
if (done) {
|
||||
done(error)
|
||||
} else {
|
||||
node.warn(error, msg)
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
|
@@ -227,6 +227,7 @@
|
||||
}
|
||||
});
|
||||
},
|
||||
sortable: true,
|
||||
removable: true
|
||||
});
|
||||
|
||||
|
@@ -91,6 +91,11 @@
|
||||
<label for="node-input-senderr" style="width: auto" data-i18n="httpin.senderr"></label>
|
||||
</div>
|
||||
|
||||
<div class="form-row">
|
||||
<input type="checkbox" id="node-input-insecureHTTPParser" style="display: inline-block; width: auto; vertical-align: top;">
|
||||
<label for="node-input-insecureHTTPParser", style="width: auto;" data-i18n="httpin.insecureHTTPParser"></label>
|
||||
</div>
|
||||
|
||||
|
||||
<div class="form-row">
|
||||
<label for="node-input-ret"><i class="fa fa-arrow-left"></i> <span data-i18n="httpin.label.return"></span></label>
|
||||
@@ -227,6 +232,7 @@
|
||||
persist: {value:false},
|
||||
proxy: {type:"http proxy",required: false,
|
||||
label:RED._("node-red:httpin.proxy-config") },
|
||||
insecureHTTPParser: {value: false},
|
||||
authType: {value: ""},
|
||||
senderr: {value: false},
|
||||
headers: { value: [] }
|
||||
@@ -338,6 +344,12 @@
|
||||
} else {
|
||||
$("#node-input-useProxy").prop("checked", false);
|
||||
}
|
||||
|
||||
if (node.insecureHTTPParser) {
|
||||
$("node-intput-insecureHTTPParser").prop("checked", true)
|
||||
} else {
|
||||
$("node-intput-insecureHTTPParser").prop("checked", false)
|
||||
}
|
||||
updateProxyOptions();
|
||||
$("#node-input-useProxy").on("click", function() {
|
||||
updateProxyOptions();
|
||||
@@ -405,6 +417,7 @@
|
||||
});
|
||||
|
||||
},
|
||||
sortable: true,
|
||||
removable: true
|
||||
});
|
||||
if (node.headers) {
|
||||
|
@@ -86,6 +86,7 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
||||
if (n.paytoqs === true || n.paytoqs === "query") { paytoqs = true; }
|
||||
else if (n.paytoqs === "body") { paytobody = true; }
|
||||
|
||||
node.insecureHTTPParser = n.insecureHTTPParser
|
||||
|
||||
var prox, noprox;
|
||||
if (process.env.http_proxy) { prox = process.env.http_proxy; }
|
||||
@@ -244,6 +245,10 @@ in your Node-RED user directory (${RED.settings.userDir}).
|
||||
delete options.headers[h];
|
||||
}
|
||||
})
|
||||
|
||||
if (node.insecureHTTPParser) {
|
||||
options.insecureHTTPParser = true
|
||||
}
|
||||
}
|
||||
],
|
||||
beforeRedirect: [
|
||||
|
@@ -52,4 +52,7 @@
|
||||
used to mark the templated sections. For example, to use <code>[[ ]]</code>
|
||||
instead, add the following line to the top of the template:</p>
|
||||
<pre>{{=[[ ]]=}}</pre>
|
||||
<h4>Using environment variables</h4>
|
||||
<p>The template node can access environment variables using the syntax:</p>
|
||||
<pre>My favourite colour is {{env.COLOUR}}.</pre>
|
||||
</script>
|
||||
|
@@ -554,7 +554,8 @@
|
||||
},
|
||||
"status": {
|
||||
"requesting": "requesting"
|
||||
}
|
||||
},
|
||||
"insecureHTTPParser": "Disable strict HTTP parsing"
|
||||
},
|
||||
"websocket": {
|
||||
"label": {
|
||||
|
@@ -48,4 +48,7 @@
|
||||
<p><b>注: </b>デフォルトでは、<i>mustache</i>形式は置換対象のHTML要素をエスケープします。これを抑止するには<code>{{{三重}}}</code>括弧形式を使います。</p>
|
||||
<p>もし、コンテンツの中で<code>{{ }}</code>を出力する必要がある場合は、テンプレートで使われる記号文字を変えることもできます。例えば、<code>[[ ]]</code>を代わりに用いるには、テンプレートの先頭に以下の行を追加します。</p>
|
||||
<pre>{{=[[ ]]=}}</pre>
|
||||
<h4>環境変数の利用</h4>
|
||||
<p>templateノードでは、次の構文を用いると環境変数にアクセスできます:</p>
|
||||
<pre>私の好きな色は{{env.COLOUR}}です。</pre>
|
||||
</script>
|
||||
|
@@ -554,7 +554,8 @@
|
||||
},
|
||||
"status": {
|
||||
"requesting": "要求中"
|
||||
}
|
||||
},
|
||||
"insecureHTTPParser": "厳密なHTTPパース処理を無効化"
|
||||
},
|
||||
"websocket": {
|
||||
"label": {
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/nodes",
|
||||
"version": "3.0.0-beta.4",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -25,7 +25,7 @@
|
||||
"cookie": "0.5.0",
|
||||
"cors": "2.8.5",
|
||||
"cronosjs": "1.7.1",
|
||||
"denque": "2.0.1",
|
||||
"denque": "2.1.0",
|
||||
"form-data": "4.0.0",
|
||||
"fs-extra": "10.1.0",
|
||||
"got": "11.8.5",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/registry",
|
||||
"version": "3.0.0-beta.4",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,11 +16,11 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/util": "3.0.0-beta.4",
|
||||
"@node-red/util": "3.0.2",
|
||||
"clone": "2.1.2",
|
||||
"fs-extra": "10.1.0",
|
||||
"semver": "7.3.7",
|
||||
"tar": "6.1.11",
|
||||
"uglify-js": "3.16.0"
|
||||
"uglify-js": "3.16.3"
|
||||
}
|
||||
}
|
||||
|
@@ -100,9 +100,13 @@ function buildDiagnosticReport(scope, callback) {
|
||||
version: os.version(),
|
||||
},
|
||||
runtime: {
|
||||
isStarted: runtime.isStarted(),
|
||||
modules: modules,
|
||||
version: runtime.settings.version,
|
||||
isStarted: runtime.isStarted(),
|
||||
flows: {
|
||||
state: runtime.flows && runtime.flows.state(),
|
||||
started: runtime.flows && runtime.flows.started,
|
||||
},
|
||||
modules: modules,
|
||||
settings: {
|
||||
available: runtime.settings.available(),
|
||||
apiMaxLength: runtime.settings.apiMaxLength || "UNSET",
|
||||
@@ -114,6 +118,11 @@ function buildDiagnosticReport(scope, callback) {
|
||||
flowFile: runtime.settings.flowFile || "UNSET",
|
||||
mqttReconnectTime: runtime.settings.mqttReconnectTime || "UNSET",
|
||||
serialReconnectTime: runtime.settings.serialReconnectTime || "UNSET",
|
||||
socketReconnectTime: runtime.settings.socketReconnectTime || "UNSET",
|
||||
socketTimeout: runtime.settings.socketTimeout || "UNSET",
|
||||
tcpMsgQueueSize: runtime.settings.tcpMsgQueueSize || "UNSET",
|
||||
inboundWebSocketTimeout: runtime.settings.inboundWebSocketTimeout || "UNSET",
|
||||
runtimeState: runtime.settings.runtimeState || "UNSET",
|
||||
|
||||
adminAuth: runtime.settings.adminAuth ? "SET" : "UNSET",
|
||||
|
||||
@@ -131,6 +140,7 @@ function buildDiagnosticReport(scope, callback) {
|
||||
uiHost: runtime.settings.uiHost ? "SET" : "UNSET",
|
||||
uiPort: runtime.settings.uiPort ? "SET" : "UNSET",
|
||||
userDir: runtime.settings.userDir ? "SET" : "UNSET",
|
||||
nodesDir: runtime.settings.nodesDir && runtime.settings.nodesDir.length ? "SET" : "UNSET",
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@@ -134,10 +134,12 @@ function createNode(flow,config) {
|
||||
subflowInstanceConfig,
|
||||
instanceConfig
|
||||
);
|
||||
// Register this subflow as an instance node of the parent flow.
|
||||
// This allows nodes inside the subflow to get ahold of each other
|
||||
// such as a node accessing its config node
|
||||
flow.subflowInstanceNodes[config.id] = subflow
|
||||
subflow.start();
|
||||
return subflow.node;
|
||||
|
||||
Log.error(Log._("nodes.flow.unknown-type", {type:type}));
|
||||
}
|
||||
} catch(err) {
|
||||
Log.error(err);
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"runtime": {
|
||||
"welcome": "Willkommen bei Node-RED!",
|
||||
"welcome": "Willkommen bei Node-RED",
|
||||
"version": "__component__ Version: __version__",
|
||||
"unsupported_version": "Nicht unterstützte Version von __component__. Erforderlich: __requires__, jedoch gefunden: __version__",
|
||||
"paths": {
|
||||
@@ -8,7 +8,6 @@
|
||||
"httpStatic": "HTTP-Statisch: __path__"
|
||||
}
|
||||
},
|
||||
|
||||
"server": {
|
||||
"loading": "Paletten-Nodes werden geladen",
|
||||
"palette-editor": {
|
||||
@@ -34,17 +33,19 @@
|
||||
"install-failed-not-found": "Das Modul $t(server.install.install-failed-long) wurde nicht gefunden",
|
||||
"install-failed-name": "$t(server.install.install-failed-long). Ungültiger Modulname: __name__",
|
||||
"install-failed-url": "$t(server.install.install-failed-long). Ungültige URL: __url__",
|
||||
"post-install-error": "Fehler bei der Ausführung des 'postInstall'-Hooks:",
|
||||
"upgrading": "Upgrade von Modul __name__ auf Version __version__ gestartet",
|
||||
"upgraded": "Upgrade von Modul __name__ war erfolgreich. Neustart von Node-RED für die Verwendung der neuen Version erforderlich.",
|
||||
"upgrade-failed-not-found": "Upgrade fehlgeschlagen. $t(server.install.install-failed-long). Version nicht gefunden.",
|
||||
"uninstalling": "Das Modul __name__ wird deinstalliert",
|
||||
"uninstall-failed": "Deinstallation fehlgeschlagen",
|
||||
"uninstall-failed-long": "Die Deinstallation des Moduls __name__ ist fehlgeschlagen:",
|
||||
"uninstalled": "Das Modul __name__ ist deinstalliert"
|
||||
"uninstalled": "Das Modul __name__ ist deinstalliert",
|
||||
"old-ext-mod-dir-warning": "\n\n---------------------------------------------------------------------\nNode-RED 1.3 Verzeichnis externer Module erkannt:\n __oldDir__\nDieses Verzeichnis wird nicht mehr verwendet. Die externen Module werden\nin Ihrem Node-RED-Benutzerverzeichnis neu installiert:\n __newDir__\nLöschen Sie das alte externalModules-Verzeichnis, um diese Meldung abzustellen.\n---------------------------------------------------------------------\n"
|
||||
},
|
||||
"deprecatedOption": "Die Verwendung von __old__ ist abgekündigt. Stattdessen __new__ verwenden.",
|
||||
"unable-to-listen": "Überwachen (listen) von __listenpath__ nicht möglich",
|
||||
"port-in-use": "FEHLER: Port wird verwendet",
|
||||
"port-in-use": "Fehler: Port wird verwendet",
|
||||
"uncaught-exception": "Nicht abgefangene Ausnahmebedingung:",
|
||||
"admin-ui-disabled": "Administrator-Benutzeroberfläche deaktiv",
|
||||
"now-running": "Server wird jetzt auf __listenpath__ ausgeführt",
|
||||
@@ -55,11 +56,10 @@
|
||||
"refresh-interval": "Erneuerung der https-Einstellungen erfolgt alle __interval__ Stunden",
|
||||
"settings-refreshed": "https-Einstellungen wurden erneuert",
|
||||
"refresh-failed": "Erneuerung der https-Einstellungen fehlgeschlagen: __message__",
|
||||
"nodejs-version": "httpsRefreshInterval erfordert Node.js 11 or later",
|
||||
"nodejs-version": "httpsRefreshInterval erfordert Node.js 11 oder höher",
|
||||
"function-required": "httpsRefreshInterval erfordert die https-Eigenschaft in Form einer Funktion"
|
||||
}
|
||||
},
|
||||
|
||||
"api": {
|
||||
"flows": {
|
||||
"error-save": "Fehler beim Speichern der Flows: __message__",
|
||||
@@ -77,17 +77,16 @@
|
||||
"error-enable": "Der Node konnte nicht aktiviert werden:"
|
||||
}
|
||||
},
|
||||
|
||||
"comms": {
|
||||
"error": "Kommunikationskanal-Fehler: __message__",
|
||||
"error-server": "Kommunikationsserver-Fehler: __message__",
|
||||
"error-send": "Kommunikationsende-Fehler: __message__"
|
||||
},
|
||||
|
||||
"settings": {
|
||||
"user-not-available": "Einstellungen konnten nicht gespeichert werden: __message__",
|
||||
"not-available": "Einstellungen nicht verfügbar",
|
||||
"property-read-only": "Die Eigenschaft '__prop__ 'ist schreibgeschützt"
|
||||
"property-read-only": "Die Eigenschaft '__prop__' ist schreibgeschützt",
|
||||
"readonly-mode": "Laufzeitumgebung im Nur-Lese-Modus. Änderungen werden nicht gespeichert."
|
||||
},
|
||||
"library": {
|
||||
"unknownLibrary": "Unbekannte Bibliothek (Library): __library__",
|
||||
@@ -98,10 +97,12 @@
|
||||
},
|
||||
"nodes": {
|
||||
"credentials": {
|
||||
"error": "Fehler beim Laden der Berechtigungen: __message__",
|
||||
"error-saving": "Fehler beim Speichern der Berechtigungen: __message__",
|
||||
"not-registered": "Der Berechtigung-Typ '__type__' ist nicht registriert",
|
||||
"system-key-warning": "\n---------------------------------------------------------------------\nDie Datei mit den Flow-Berechtigungen wird mit einem vom System\ngenerierten Schlüssel verschlüsselt.\nWenn der vom System generierte Schlüssel aus irgendeinem Grund\nverloren geht, kann die Datei mit den Berechtigungen nicht\nwiederhergestellt werden. Sie muss dann gelöscht und die\nBerechtigungen müssen erneut eingestellt werden.\nEs sollte ein eigener Schlüssel mit Hilfe der Option\n'credentialSecret' in der Einstellungsdatei vorgegeben werden.\nNode-RED wird dann die Datei mit den Flow-Berechtigungen\nbei der nächsten Übernahme (deploy) einer Änderung erneut\nverschlüsseln.\n---------------------------------------------------------------------"
|
||||
"error": "Fehler beim Laden der Credentials: __message__",
|
||||
"error-saving": "Fehler beim Speichern der Credentials: __message__",
|
||||
"not-registered": "Der Credentials-Typ '__type__' ist nicht registriert",
|
||||
"system-key-warning": "\n---------------------------------------------------------------------\nDie Datei mit den Flow-Credentials wird mit einem vom System\ngenerierten Schlüssel verschlüsselt.\nWenn der vom System generierte Schlüssel aus irgendeinem Grund\nverloren geht, kann die Datei mit den Credentials nicht\nwiederhergestellt werden. Sie muss dann gelöscht und die\nCredentials müssen erneut eingestellt werden.\nEs sollte ein eigener Schlüssel mit Hilfe der Option\n'credentialSecret' in der Einstellungsdatei vorgegeben werden.\nNode-RED wird dann die Datei mit den Flow-Credentials\nbei der nächsten Übernahme (deploy) einer Änderung erneut\nverschlüsseln.\n---------------------------------------------------------------------",
|
||||
"unencrypted": "Verwende unverschlüsselte Credentials",
|
||||
"encryptedNotFound": "Verschlüsselte Credentials nicht gefunden"
|
||||
},
|
||||
"flows": {
|
||||
"safe-mode": "Die Flows sind gestoppt im abgesicherten Modus. Übernahme (deploy) zum Starten.",
|
||||
@@ -121,6 +122,7 @@
|
||||
"stopped-flows": "Flows sind gestoppt",
|
||||
"stopped": "gestoppt",
|
||||
"stopping-error": "Fehler beim Stoppen des Nodes: __message__",
|
||||
"updated-flows": "Flows aktualisiert",
|
||||
"added-flow": "Flow wird hinzugefügt: __label__",
|
||||
"updated-flow": "Aktualisierter Flow: __label__",
|
||||
"removed-flow": "Entfernter Flow: __label__",
|
||||
@@ -145,7 +147,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"storage": {
|
||||
"index": {
|
||||
"forbidden-flow-name": "Unzulässiger Flow-Name"
|
||||
@@ -159,6 +160,7 @@
|
||||
"restore": "Die '__type__'-Dateisicherung wird wiederhergestellt: __path__",
|
||||
"restore-fail": "Die Wiederherstellung der '__type__'-Dateisicherung ist fehlgeschlagen: __message__",
|
||||
"fsync-fail": "Die Übertragung der Datei __path__ auf das Laufwerk ist fehlgeschlagen: __message__",
|
||||
"warn_name": "Name der Flows-Datei nicht festgelegt. Name wird unter Verwendung des Hostnamens generiert.",
|
||||
"projects": {
|
||||
"changing-project": "Aktives Projekt wird festgelegt: __project__",
|
||||
"active-project": "Aktives Projekt: __project__",
|
||||
@@ -174,7 +176,6 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
"context": {
|
||||
"log-store-init": "Kontextspeicher: __name__ [__info__]",
|
||||
"error-loading-module": "Fehler beim Laden des Kontextspeichers: __message__",
|
||||
@@ -189,5 +190,4 @@
|
||||
"error-write": "Fehler beim Schreiben des Kontextes: __message__"
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/runtime",
|
||||
"version": "3.0.0-beta.4",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,8 +16,8 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/registry": "3.0.0-beta.4",
|
||||
"@node-red/util": "3.0.0-beta.4",
|
||||
"@node-red/registry": "3.0.2",
|
||||
"@node-red/util": "3.0.2",
|
||||
"async-mutex": "0.3.2",
|
||||
"clone": "2.1.2",
|
||||
"express": "4.18.1",
|
||||
|
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/util",
|
||||
"version": "3.0.0-beta.4",
|
||||
"version": "3.0.2",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
@@ -16,11 +16,11 @@
|
||||
],
|
||||
"dependencies": {
|
||||
"fs-extra": "10.1.0",
|
||||
"i18next": "21.8.10",
|
||||
"i18next": "21.8.16",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"jsonata": "1.8.6",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"moment": "2.29.3",
|
||||
"moment": "2.29.4",
|
||||
"moment-timezone": "0.5.34"
|
||||
}
|
||||
}
|
||||
|
10
packages/node_modules/node-red/package.json
vendored
10
packages/node_modules/node-red/package.json
vendored
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "3.0.0-beta.4",
|
||||
"version": "3.0.2",
|
||||
"description": "Low-code programming for event-driven applications",
|
||||
"homepage": "http://nodered.org",
|
||||
"license": "Apache-2.0",
|
||||
@@ -31,10 +31,10 @@
|
||||
"flow"
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/editor-api": "3.0.0-beta.4",
|
||||
"@node-red/runtime": "3.0.0-beta.4",
|
||||
"@node-red/util": "3.0.0-beta.4",
|
||||
"@node-red/nodes": "3.0.0-beta.4",
|
||||
"@node-red/editor-api": "3.0.2",
|
||||
"@node-red/runtime": "3.0.2",
|
||||
"@node-red/util": "3.0.2",
|
||||
"@node-red/nodes": "3.0.2",
|
||||
"basic-auth": "2.0.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"express": "4.18.1",
|
||||
|
@@ -1717,6 +1717,24 @@ describe('change Node', function() {
|
||||
changeNode1.receive({topic:{foo:{bar:1}}, payload:"String"});
|
||||
});
|
||||
});
|
||||
it('moves the value of a message property object to itself', function(done) {
|
||||
var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"move","p":"payload","pt":"msg","to":"payload","tot":"msg"}],"name":"changeNode","wires":[["helperNode1"]]},
|
||||
{id:"helperNode1", type:"helper", wires:[]}];
|
||||
helper.load(changeNode, flow, function() {
|
||||
var changeNode1 = helper.getNode("changeNode1");
|
||||
var helperNode1 = helper.getNode("helperNode1");
|
||||
helperNode1.on("input", function(msg) {
|
||||
try {
|
||||
msg.should.have.property('payload');
|
||||
msg.payload.should.equal("bar");
|
||||
done();
|
||||
} catch(err) {
|
||||
done(err);
|
||||
}
|
||||
});
|
||||
changeNode1.receive({payload:"bar"});
|
||||
});
|
||||
});
|
||||
it('moves the value of a message property object to a sub-property', function(done) {
|
||||
var flow = [{"id":"changeNode1","type":"change","rules":[{"t":"move","p":"payload","pt":"msg","to":"payload.foo","tot":"msg"}],"name":"changeNode","wires":[["helperNode1"]]},
|
||||
{id:"helperNode1", type:"helper", wires:[]}];
|
||||
|
@@ -31,6 +31,8 @@ var multer = require("multer");
|
||||
var RED = require("nr-test-utils").require("node-red/lib/red");
|
||||
var fs = require('fs-extra');
|
||||
var auth = require('basic-auth');
|
||||
const { version } = require("os");
|
||||
const net = require('net')
|
||||
|
||||
describe('HTTP Request Node', function() {
|
||||
var testApp;
|
||||
@@ -2265,4 +2267,71 @@ describe('HTTP Request Node', function() {
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
describe('should parse broken headers', function() {
|
||||
|
||||
const versions = process.versions.node.split('.')
|
||||
|
||||
if (( versions[0] == 14 && versions[1] >= 20 ) ||
|
||||
( versions[0] == 16 && versions[1] >= 16 ) ||
|
||||
( versions[0] == 18 && versions[1] >= 5 ) ||
|
||||
( versions[0] > 18)) {
|
||||
// only test if on new enough NodeJS version
|
||||
|
||||
let port = testPort++
|
||||
|
||||
let server;
|
||||
|
||||
before(function() {
|
||||
server = net.createServer(function (socket) {
|
||||
socket.write("HTTP/1.0 200\nContent-Type: text/plain\n\nHelloWorld")
|
||||
socket.end()
|
||||
})
|
||||
|
||||
server.listen(port,'127.0.0.1', function(err) {
|
||||
})
|
||||
});
|
||||
|
||||
after(function() {
|
||||
server.close()
|
||||
});
|
||||
|
||||
it('should accept broken headers', function (done) {
|
||||
var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:`http://localhost:${port}/`, insecureHTTPParser: true},
|
||||
{id:"n2", type:"helper"}];
|
||||
helper.load(httpRequestNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on('input', function(msg) {
|
||||
try {
|
||||
msg.payload.should.equal('HelloWorld')
|
||||
done()
|
||||
} catch (err) {
|
||||
done(err)
|
||||
}
|
||||
})
|
||||
n1.receive({payload: 'foo'})
|
||||
});
|
||||
});
|
||||
|
||||
it('should reject broken headers', function (done) {
|
||||
var flow = [{id:'n1',type:'http request',wires:[['n2']],method:'GET',ret:'obj',url:`http://localhost:${port}/`},
|
||||
{id:"n2", type:"helper"}];
|
||||
helper.load(httpRequestNode, flow, function() {
|
||||
var n1 = helper.getNode("n1");
|
||||
var n2 = helper.getNode("n2");
|
||||
n2.on('input', function(msg) {
|
||||
try{
|
||||
msg.payload.should.equal(`RequestError: Parse Error: Missing expected CR after header value : http://localhost:${port}/`)
|
||||
done()
|
||||
} catch (err) {
|
||||
done(err)
|
||||
}
|
||||
})
|
||||
n1.receive({payload: 'foo'})
|
||||
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
});
|
||||
|
@@ -27,7 +27,7 @@ describe('MQTT Nodes', function () {
|
||||
} catch (error) { }
|
||||
});
|
||||
|
||||
it('should be loaded and have default values', function (done) {
|
||||
it('should be loaded and have default values (MQTT V4)', function (done) {
|
||||
this.timeout = 2000;
|
||||
const { flow, nodes } = buildBasicMQTTSendRecvFlow({ id: "mqtt.broker", name: "mqtt_broker", autoConnect: false }, { id: "mqtt.in", topic: "in_topic" }, { id: "mqtt.out", topic: "out_topic" });
|
||||
helper.load(mqttNodes, flow, function () {
|
||||
@@ -61,6 +61,52 @@ describe('MQTT Nodes', function () {
|
||||
mqttBroker.options.clientId.should.containEql('nodered_');
|
||||
mqttBroker.options.should.have.property('keepalive').type("number");
|
||||
mqttBroker.options.should.have.property('reconnectPeriod').type("number");
|
||||
//as this is not a v5 connection, ensure v5 properties are not present
|
||||
mqttBroker.options.should.not.have.property('protocolVersion', 5);
|
||||
mqttBroker.options.should.not.have.property('properties');
|
||||
done();
|
||||
} catch (error) {
|
||||
done(error)
|
||||
}
|
||||
});
|
||||
});
|
||||
it('should be loaded and have default values (MQTT V5)', function (done) {
|
||||
this.timeout = 2000;
|
||||
const { flow, nodes } = buildBasicMQTTSendRecvFlow({ id: "mqtt.broker", name: "mqtt_broker", autoConnect: false, cleansession: false, clientid: 'clientid', keepalive: 35, sessionExpiry: '6000', protocolVersion: '5', userProps: {"prop": "val"}}, { id: "mqtt.in", topic: "in_topic" }, { id: "mqtt.out", topic: "out_topic" });
|
||||
helper.load(mqttNodes, flow, function () {
|
||||
try {
|
||||
const mqttIn = helper.getNode("mqtt.in");
|
||||
const mqttOut = helper.getNode("mqtt.out");
|
||||
const mqttBroker = helper.getNode("mqtt.broker");
|
||||
|
||||
should(mqttIn).be.type("object", "mqtt in node should be an object")
|
||||
mqttIn.should.have.property('broker', nodes.mqtt_broker.id); //should be the id of the broker node
|
||||
mqttIn.should.have.property('datatype', 'utf8'); //default: 'utf8'
|
||||
mqttIn.should.have.property('isDynamic', false); //default: false
|
||||
mqttIn.should.have.property('inputs', 0); //default: 0
|
||||
mqttIn.should.have.property('qos', 2); //default: 2
|
||||
mqttIn.should.have.property('topic', "in_topic");
|
||||
mqttIn.should.have.property('wires', [["helper.node"]]);
|
||||
|
||||
should(mqttOut).be.type("object", "mqtt out node should be an object")
|
||||
mqttOut.should.have.property('broker', nodes.mqtt_broker.id); //should be the id of the broker node
|
||||
mqttOut.should.have.property('topic', "out_topic");
|
||||
|
||||
should(mqttBroker).be.type("object", "mqtt broker node should be an object")
|
||||
mqttBroker.should.have.property('broker', BROKER_HOST);
|
||||
mqttBroker.should.have.property('port', BROKER_PORT);
|
||||
mqttBroker.should.have.property('brokerurl');
|
||||
// mqttBroker.should.have.property('autoUnsubscribe', true);//default: true
|
||||
mqttBroker.should.have.property('autoConnect', false);//Set "autoConnect:false" in brokerOptions
|
||||
mqttBroker.should.have.property('options');
|
||||
mqttBroker.options.should.have.property('clean', false);
|
||||
mqttBroker.options.should.have.property('clientId', 'clientid');
|
||||
mqttBroker.options.should.have.property('keepalive').type("number", 35);
|
||||
mqttBroker.options.should.have.property('reconnectPeriod').type("number");
|
||||
//as this IS a v5 connection, ensure v5 properties are not present
|
||||
mqttBroker.options.should.have.property('protocolVersion', 5);
|
||||
mqttBroker.options.should.have.property('properties');
|
||||
mqttBroker.options.properties.should.have.property('sessionExpiryInterval');
|
||||
done();
|
||||
} catch (error) {
|
||||
done(error)
|
||||
@@ -173,7 +219,7 @@ describe('MQTT Nodes', function () {
|
||||
topic: nextTopic(),
|
||||
payload: '{prop:"value3", "num":3}', // send invalid JSON ...
|
||||
}
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
const hooks = { done: null, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
hooks.afterLoad = (helperNode, mqttBroker, mqttIn, mqttOut) => {
|
||||
helperNode.on("input", function (msg) {
|
||||
try {
|
||||
@@ -299,7 +345,7 @@ describe('MQTT Nodes', function () {
|
||||
topic: nextTopic(),
|
||||
payload: '{prop:"value3", "num":3}', contentType: "application/json", // send invalid JSON ...
|
||||
}
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
const hooks = { done: null, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
hooks.afterLoad = (helperNode, mqttBroker, mqttIn, mqttOut) => {
|
||||
helperNode.on("input", function (msg) {
|
||||
try {
|
||||
@@ -385,7 +431,7 @@ describe('MQTT Nodes', function () {
|
||||
if (skipTests) { return this.skip() }
|
||||
this.timeout = 2000;
|
||||
const options = {}
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
const hooks = { beforeLoad: null, afterLoad: null, afterConnect: null }
|
||||
hooks.beforeLoad = (flow) => { //add a status node pointed at MQTT Out node (to watch for connection status change)
|
||||
flow.push({ "id": "status.node", "type": "status", "name": "status_node", "scope": ["mqtt.out"], "wires": [["helper.node"]] });//add status node to watch mqtt_out
|
||||
}
|
||||
@@ -416,18 +462,31 @@ describe('MQTT Nodes', function () {
|
||||
this.timeout = 2000;
|
||||
const baseTopic = nextTopic();
|
||||
const brokerOptions = {
|
||||
autoConnect: false,
|
||||
protocolVersion: 4,
|
||||
birthTopic: baseTopic + "/birth",
|
||||
birthPayload: "broker connected",
|
||||
birthPayload: "broker birth",
|
||||
birthQos: 2,
|
||||
}
|
||||
const options = {};
|
||||
const hooks = { done: done, beforeLoad: null, afterLoad: null, afterConnect: null };
|
||||
options.expectMsg = {
|
||||
const expectMsg = {
|
||||
topic: brokerOptions.birthTopic,
|
||||
payload: brokerOptions.birthPayload,
|
||||
qos: brokerOptions.birthQos
|
||||
};
|
||||
const options = { };
|
||||
const hooks = { };
|
||||
hooks.afterLoad = (helperNode, mqttBroker, mqttIn, mqttOut) => {
|
||||
helperNode.on("input", function (msg) {
|
||||
try {
|
||||
compareMsgToExpected(msg, expectMsg);
|
||||
done();
|
||||
} catch (error) {
|
||||
done(error)
|
||||
}
|
||||
})
|
||||
mqttIn.receive({ "action": "connect" }); //now request connect action
|
||||
return true; //handled
|
||||
}
|
||||
testSendRecv(brokerOptions, { topic: brokerOptions.birthTopic }, {}, options, hooks);
|
||||
});
|
||||
itConditional('should publish close message', function (done) {
|
||||
@@ -666,6 +725,7 @@ function buildMQTTBrokerNode(id, name, brokerHost, brokerPort, options) {
|
||||
node.cleansession = String(options.cleansession) == "false" ? false : true;
|
||||
node.autoUnsubscribe = String(options.autoUnsubscribe) == "false" ? false : true;
|
||||
node.autoConnect = String(options.autoConnect) == "false" ? false : true;
|
||||
node.sessionExpiry = options.sessionExpiry ? options.sessionExpiry : undefined;
|
||||
|
||||
if (options.birthTopic) {
|
||||
node.birthTopic = options.birthTopic;
|
||||
@@ -760,8 +820,8 @@ function waitBrokerConnect(broker, timeLimit) {
|
||||
let waitConnected = (broker, timeLimit) => {
|
||||
const brokers = Array.isArray(broker) ? broker : [broker];
|
||||
timeLimit = timeLimit || 1000;
|
||||
let timer, resolved = false;
|
||||
return new Promise( (resolve, reject) => {
|
||||
let timer, resolved = false;
|
||||
timer = wait();
|
||||
function wait() {
|
||||
if (brokers.every(e => e.connected == true)) {
|
||||
|
@@ -61,7 +61,7 @@ describe("api/index", function() {
|
||||
should.not.exist(api.httpAdmin);
|
||||
done();
|
||||
});
|
||||
describe('initalises admin api without adminAuth', function(done) {
|
||||
describe('initalises admin api without adminAuth', function() {
|
||||
before(function() {
|
||||
beforeEach();
|
||||
api.init({},{},{},{});
|
||||
@@ -78,7 +78,7 @@ describe("api/index", function() {
|
||||
})
|
||||
});
|
||||
|
||||
describe('initalises admin api without editor', function(done) {
|
||||
describe('initalises admin api without editor', function() {
|
||||
before(function() {
|
||||
beforeEach();
|
||||
api.init({ disableEditor: true },{},{},{});
|
||||
@@ -95,7 +95,7 @@ describe("api/index", function() {
|
||||
})
|
||||
});
|
||||
|
||||
describe('initialises api with admin middleware', function(done) {
|
||||
describe('initialises api with admin middleware', function() {
|
||||
it('ignores non-function values',function(done) {
|
||||
api.init({ httpAdminRoot: true, httpAdminMiddleware: undefined },{},{},{});
|
||||
const middlewareFound = api.httpAdmin._router.stack.filter((layer) => layer.name === 'testMiddleware')
|
||||
@@ -112,7 +112,7 @@ describe("api/index", function() {
|
||||
});
|
||||
});
|
||||
|
||||
describe('initialises api with authentication enabled', function(done) {
|
||||
describe('initialises api with authentication enabled', function() {
|
||||
|
||||
it('enables an oauth/openID based authentication mechanism',function(done) {
|
||||
const stub = sinon.stub(apiAuth, 'genericStrategy').callsFake(function(){});
|
||||
@@ -135,7 +135,7 @@ describe("api/index", function() {
|
||||
|
||||
});
|
||||
|
||||
describe('initialises api with custom cors config', function (done) {
|
||||
describe('initialises api with custom cors config', function () {
|
||||
const httpAdminCors = {
|
||||
origin: "*",
|
||||
methods: "GET,PUT,POST,DELETE"
|
||||
@@ -156,7 +156,7 @@ describe("api/index", function() {
|
||||
})
|
||||
});
|
||||
|
||||
describe('editor start', function (done) {
|
||||
describe('editor start', function () {
|
||||
|
||||
it('cannot be started when editor is disabled', function (done) {
|
||||
const stub = sinon.stub(apiEditor, 'start').callsFake(function () {
|
||||
|
@@ -33,6 +33,11 @@ describe("runtime-api/diagnostics", function() {
|
||||
flowFile: "flows.json",
|
||||
mqttReconnectTime: 321,
|
||||
serialReconnectTime: 432,
|
||||
socketReconnectTime: 2222,
|
||||
socketTimeout: 3333,
|
||||
tcpMsgQueueSize: 4444,
|
||||
inboundWebSocketTimeout: 5555,
|
||||
runtimeState: {enabled: true, ui: false},
|
||||
adminAuth: {},//should be sanitised to "SET"
|
||||
httpAdminRoot: "/admin/root/",
|
||||
httpAdminCors: {},//should be sanitised to "SET"
|
||||
@@ -45,6 +50,7 @@ describe("runtime-api/diagnostics", function() {
|
||||
uiHost: "something.secret.com",//should be sanitised to "SET"
|
||||
uiPort: 1337,//should be sanitised to "SET"
|
||||
userDir: "/var/super/secret/",//should be sanitised to "SET",
|
||||
nodesDir: "/var/super/secret/",//should be sanitised to "SET",
|
||||
contextStorage: {
|
||||
default : { module: "memory" },
|
||||
file: { module: "localfilesystem" },
|
||||
@@ -73,8 +79,9 @@ describe("runtime-api/diagnostics", function() {
|
||||
|
||||
//result.runtime.xxxxx
|
||||
const runtimeCount = Object.keys(result.runtime).length;
|
||||
runtimeCount.should.eql(4);//ensure no more than 4 keys are present in runtime
|
||||
runtimeCount.should.eql(5);//ensure 5 keys are present in runtime
|
||||
result.runtime.should.have.property('isStarted',true)
|
||||
result.runtime.should.have.property('flows')
|
||||
result.runtime.should.have.property('modules').type("object");
|
||||
result.runtime.should.have.property('settings').type("object");
|
||||
result.runtime.should.have.property('version','7.7.7');
|
||||
@@ -87,7 +94,7 @@ describe("runtime-api/diagnostics", function() {
|
||||
|
||||
//result.runtime.settings.xxxxx
|
||||
const settingsCount = Object.keys(result.runtime.settings).length;
|
||||
settingsCount.should.eql(21);//ensure no more than the 21 settings listed below are present in the settings object
|
||||
settingsCount.should.eql(27);//ensure no more than the 21 settings listed below are present in the settings object
|
||||
result.runtime.settings.should.have.property('available',true);
|
||||
result.runtime.settings.should.have.property('apiMaxLength', "UNSET");//deliberately disabled to ensure UNSET is returned
|
||||
result.runtime.settings.should.have.property('debugMaxLength', 1111);
|
||||
@@ -96,6 +103,11 @@ describe("runtime-api/diagnostics", function() {
|
||||
result.runtime.settings.should.have.property('flowFile', "flows.json");
|
||||
result.runtime.settings.should.have.property('mqttReconnectTime', 321);
|
||||
result.runtime.settings.should.have.property('serialReconnectTime', 432);
|
||||
result.runtime.settings.should.have.property('socketReconnectTime', 2222);
|
||||
result.runtime.settings.should.have.property('socketTimeout', 3333);
|
||||
result.runtime.settings.should.have.property('tcpMsgQueueSize', 4444);
|
||||
result.runtime.settings.should.have.property('inboundWebSocketTimeout', 5555);
|
||||
result.runtime.settings.should.have.property('runtimeState', {enabled: true, ui: false});
|
||||
result.runtime.settings.should.have.property("adminAuth", "SET"); //should be sanitised to "SET"
|
||||
result.runtime.settings.should.have.property("httpAdminCors", "SET"); //should be sanitised to "SET"
|
||||
result.runtime.settings.should.have.property('httpAdminRoot', "/admin/root/");
|
||||
@@ -109,6 +121,7 @@ describe("runtime-api/diagnostics", function() {
|
||||
result.runtime.settings.should.have.property("uiPort", "SET"); //should be sanitised to "SET"
|
||||
result.runtime.settings.should.have.property("userDir", "SET"); //should be sanitised to "SET"
|
||||
result.runtime.settings.should.have.property('contextStorage').type("object");
|
||||
result.runtime.settings.should.have.property('nodesDir', "SET")
|
||||
|
||||
//result.runtime.settings.contextStorage.xxxxx
|
||||
const contextCount = Object.keys(result.runtime.settings.contextStorage).length;
|
||||
|
Reference in New Issue
Block a user