Compare commits

...

480 Commits

Author SHA1 Message Date
Dave Conway-Jones
d5d9ac5c76 let setMessageProperty return success flag
so calling node can warn if operation tries to overwrite primitive type
2020-01-26 18:20:25 +00:00
Nick O'Leary
9d4238e5cc Re-enable jshint on editor and fixup issues 2020-01-22 11:53:41 +00:00
Nick O'Leary
ee6f6ae391 Fixup debug tests 2020-01-17 20:57:13 +00:00
Nick O'Leary
95a51aafdc Add path property to debug messages
Fixes #2358

This property can be used to identify the full path to the node that
logged a given message. If the node is inside a subflow (and maybe
nested many levels deep), this path can be used to help find the
node, rather than just the top-level subflow instance node.

A side-effect of this change is the Debug sidebar is now able to
show the message tools for a message coming from a deeply nested
subflow
2020-01-17 16:56:30 +00:00
Nick O'Leary
5e7cd79ed9 Merge pull request #2392 from kazuhitoyokoi/master-fixjsoneditor
Add icons and support i18n in typedInput of JSON editor
2020-01-17 10:38:23 +00:00
Nick O'Leary
aba6173e23 Merge pull request #2411 from kazuhitoyokoi/master-fixeditor
Fix IME bug in text editor
2020-01-17 10:36:43 +00:00
Nick O'Leary
e2c3b35391 Merge pull request #2408 from onozuka/remove-runtime-deploy-event
UI-test: fix memory leak. runtime-deploy event in deploy()
2020-01-17 10:21:34 +00:00
Nick O'Leary
448de23f59 Merge pull request #2426 from kazuhitoyokoi/master-fixuitest
Improvements of UI testing
2020-01-17 10:18:05 +00:00
Kazuhito Yokoi
44a07c74fd Click tab instead of workspace 2020-01-15 10:42:59 +09:00
Kazuhito Yokoi
0f8af4ba1c Use boolean value as flag instead of string value 2020-01-14 20:36:10 +09:00
Kazuhito Yokoi
214d788029 Use enter key to open node property instead of double click 2020-01-14 19:24:50 +09:00
Kazuhito Yokoi
530bf22bd5 Use palette search when selecting nodes 2020-01-14 18:02:27 +09:00
Kazuhito Yokoi
ccc98370eb Use ephemeral port number for MQTT broker 2020-01-14 17:44:56 +09:00
Kazuhito Yokoi
7640bc029c Add handling to remove unused file and directories in UI testing 2020-01-14 17:24:16 +09:00
Kazuhito Yokoi
3f72eb51a0 Fix shortcut key handling 2020-01-14 17:18:46 +09:00
Kazuhito Yokoi
8801ace247 Remain .payload in debug node property 2020-01-14 16:56:39 +09:00
Kazuhito Yokoi
faf46e4447 Improve node files for UI testing 2020-01-14 16:37:43 +09:00
Kazuhito Yokoi
63978e226b Move node files for UI testing to v1.0 directory structures 2020-01-14 15:42:56 +09:00
Nick O'Leary
b96164d4f5 Fix false change detection when no config node selected 2020-01-10 14:52:20 +00:00
Kazuhito Yokoi
944070dfb1 Move CSS definition to ace.scss 2020-01-09 13:06:39 +09:00
Kazuhito Yokoi
f0584df1d0 Revert "Fix IME bug in text editor"
This reverts commit 9cbd0fceea.
2020-01-09 12:53:39 +09:00
Nick O'Leary
ba209c2bdd Merge pull request #2417 from node-red-hitachi/fix-error-on-install
Remove undefined loadFlowLibrary call
2020-01-08 14:43:19 +00:00
Nick O'Leary
c6e2f28b97 Merge pull request #2419 from boisei0/fix-2418-regex-routes
Fixes the routes described in #2418
2020-01-08 14:43:00 +00:00
Arlena Derksen
2436bb0128 Fixes the routes described in #2418 regarding too broad matching of regex URLs. 2020-01-03 21:27:35 +01:00
Dave Conway-Jones
9c4640e010 Make min-height for change, switch, batch and mqtt consistent
to allow fit to smaller screens before scrolling
(to fix comment from forum)
2020-01-01 21:32:56 +00:00
Hiroyasu Nishiyama
1ee43113b1 remove undefined loadFlowLibrary call 2019-12-31 20:22:13 +09:00
Dave Conway-Jones
902f477ee3 Bump included nodes versions to mathc latest
rbe, tail (and sentiment).
To close #2415
2019-12-30 15:46:08 +00:00
Dave Conway-Jones
9c1d46ff92 Make node highlighting a bit more obvious for busy flows 2019-12-26 16:53:13 +00:00
Kazuhito Yokoi
9cbd0fceea Fix IME bug in text editor 2019-12-17 21:00:50 +09:00
Yukio Onozuka
b22a4f94ab when call event. remove runtime event. 2019-12-13 07:52:34 +09:00
Nick O'Leary
a4c351fd4f Merge pull request #2397 from kazuhitoyokoi/master-fixuitest
Fix test cases for UI
2019-12-03 10:33:05 +00:00
Kazuhito Yokoi
a364d4950d Fix test cases for UI 2019-12-02 12:43:13 +09:00
Kazuhito Yokoi
7805974736 Add icons and support i18n in typedInput of JSON editor 2019-11-25 16:40:42 +09:00
Nick O'Leary
c1dae95f71 Merge pull request #2390 from node-red-hitachi/fix-mqtt-jp
Update Japanese info text of mqtt out node
2019-11-22 22:29:35 +00:00
Hiroyasu Nishiyama
e7c2ff3bd2 fix typos in Japanese info text of mqtt out 2019-11-22 13:01:50 +09:00
Hiroyasu Nishiyama
25459b52a1 udate Japanese info text of mqtt 2019-11-22 12:47:36 +09:00
Nick O'Leary
b81be8f358 Update for 1.0.3 again 2019-11-21 17:28:28 +00:00
Nick O'Leary
aa6c0b9d6e Add clarification that MQTT Out requires payload to send msg
Fixes #2370
2019-11-21 16:56:01 +00:00
Nick O'Leary
64580237d5 Remove rogue debug 2019-11-21 11:08:15 +00:00
Nick O'Leary
b93165592e Merge pull request #2372 from btsimonh/proxy-support
noproxy support in mqtt, Proxy & noproxy support in websocket
2019-11-21 10:45:23 +00:00
Nick O'Leary
83c1e44925 Merge pull request #2371 from btsimonh/projects-flowsFile-absolute
flows file absolute path plus non-existent folder creation.
2019-11-21 10:44:20 +00:00
Nick O'Leary
3088115aba Avoid unnecessary i18n catalog load if base lng provided 2019-11-21 10:42:40 +00:00
Nick O'Leary
fc93e502b8 Merge pull request #2376 from tt92/master
I18n - language fallback behaviour
2019-11-21 10:38:21 +00:00
Nick O'Leary
e90e6eaac3 Merge pull request #2388 from node-red/subflow-status-i18n
let subflow add node-red context to status so i18n works
2019-11-21 09:59:40 +00:00
Dave Conway-Jones
2f4dcba54d let subflow add node-red context to status
For all those nodes thaht don't specify it.
So that subflow status then works ok
2019-11-20 06:12:33 -05:00
tot92
683c6a748e switched loading order 2019-11-18 20:45:48 +01:00
Simon Hailes
175a871ee0 repalce for-in with 'normal' for loop in mqtt and http 2019-11-18 17:14:38 +00:00
btsimonh
b4e2061e85 Update packages/node_modules/@node-red/nodes/core/network/21-httprequest.js
Co-Authored-By: Nick O'Leary <nick.oleary@gmail.com>
2019-11-18 17:03:59 +00:00
Nick O'Leary
2aef99c440 Merge pull request #2362 from node-red-hitachi/i18n-json-editor
Update support of i18n of visual JSON editor
2019-11-18 11:32:19 +00:00
Nick O'Leary
6c125e125f Merge pull request #2383 from kazuhitoyokoi/master-fixpermission
Revert permission of script file
2019-11-18 11:29:43 +00:00
Nick O'Leary
88cbc32abc Fix inverse of 'replace' editor event 2019-11-14 19:13:23 +00:00
Kazuhito Yokoi
8f45e8f84a Revert permission of script file 2019-11-14 12:38:54 +09:00
Hiroyasu Nishiyama
21635aadfe use type name from common.type 2019-11-13 22:50:44 +09:00
Hiroyasu Nishiyama
d5234888b3 Merge branch 'master' into i18n-json-editor 2019-11-13 22:42:53 +09:00
Nick O'Leary
1f5ff0c6d3 Merge pull request #2366 from btsimonh/fix-encodeObjecterror
Catches bad objects being encoded, returning instead the error.
2019-11-13 09:33:20 +00:00
Nick O'Leary
2a2541df59 Merge pull request #2361 from kazuhitoyokoi/master-fixtypedInput
Support i18n for typedInput in join and switch nodes
2019-11-13 09:29:08 +00:00
Nick O'Leary
cd629c1699 Merge pull request #2373 from kazuhitoyokoi/master-fixuitest
Fix UI testing on the latest Google Chrome
2019-11-13 09:25:59 +00:00
tot92
4d6828ec14 typo 2019-11-09 22:09:02 +01:00
tot92
dae1d6057e fixed i18n language fallback behaviour 2019-11-09 22:07:06 +01:00
Kazuhito Yokoi
6726c42cc8 Remove @wdio/cli module 2019-11-05 21:59:37 +09:00
Kazuhito Yokoi
4f6023e44c Support UI testing on the latest Google Chrome 2019-11-05 11:40:20 +09:00
Kazuhito Yokoi
9e16d7f433 Move messages to editor.json 2019-11-05 11:29:43 +09:00
Simon Hailes
aa86cfc55f Add fix for HttpsProxyAgent using an incorrect default port for http: 2019-11-03 11:08:24 +00:00
Simon Hailes
6931cb9895 Added test for both UNC path and flow in non-existent subfolder. 2019-11-03 10:42:50 +00:00
Simon Hailes
d32d04bd4e websocket - add proxy support. 2019-11-03 09:55:11 +00:00
Simon Hailes
0b3e9bf5e2 mqtt & httprequest: change proxy comparison from null to falsy.
mqtt - add no_proxy support.
2019-11-03 09:54:23 +00:00
Simon Hailes
a4af7b8e21 localfilesystem - ensure folder is present before write (e.g. flows file not in user folder) 2019-11-03 09:10:32 +00:00
Simon Hailes
72deee5d74 Detect windows UNC '\\' as well as 'X:' as an absolute flow path - use the path.isAbsolute function instead of rolling our own. 2019-11-03 08:24:47 +00:00
Simon Hailes
5e9e523d4c add one line of coverage in log tests. 2019-11-02 13:21:58 +00:00
Simon Hailes
c54509df3d additional test to cover last line in encodeObject 2019-11-02 13:03:37 +00:00
Simon Hailes
63cc9adeaa small update to log - if toString() causes exception, then note and use util.inspect instead - prevents log from causing processes to abort through exception.
Add tests.
2019-11-02 12:38:40 +00:00
Simon Hailes
74d760a46d add util.inspect data to 'type not printable'. Add test to cover these lines (no existing test). 2019-11-02 12:37:07 +00:00
Simon Hailes
d46531def8 add unit tests for encode Object changes. 2019-11-02 11:27:08 +00:00
Simon Hailes
eb09ec6834 add utils.inspect result and be more explicit about the error. 2019-11-02 10:39:22 +00:00
Nick O'Leary
9bd9c6a400 Merge pull request #2364 from kazuhitoyokoi/master-addtooltip
Add tooltip to the expand button in markdown editor
2019-11-01 23:36:31 +00:00
Nick O'Leary
7321e206c5 Merge pull request #2363 from kazuhitoyokoi/master-fixtabselectkey
Support ctrl key to select tabs for Windows
2019-11-01 23:35:18 +00:00
Nick O'Leary
2c7917f0ca Merge pull request #2355 from node-red-hitachi/fix-typedInput-line-break
Prohibit line break in type menu of typedInput
2019-11-01 23:27:36 +00:00
Nick O'Leary
d94b20a908 Merge pull request #2356 from node-red-hitachi/fix-jsonata-help-display
Make JSONata help initially shown
2019-11-01 23:27:01 +00:00
Nick O'Leary
b1b1fe21dd Merge pull request #2357 from kazuhitoyokoi/addplaceholder
Add placeholders to name fields
2019-11-01 23:26:40 +00:00
Nick O'Leary
1db3af7c8e Merge pull request #2354 from node-red-hitachi/update-jsonata-message-jp
Update Japanese JSONata message catalogue
2019-11-01 23:25:46 +00:00
piyonakajima
397fe31f97 Update 17-split.html (#2365) 2019-11-01 13:04:43 +00:00
Simon Hailes
bc283aa025 Catches bad objects being encoded, returning instead the error.
Symptom- Observed that global context would not display in front end, the call returning 400.
Traced to an object in global which cause encodeObject to except.
This push catches that, and now global will display, but the object in question display as an error.
2019-11-01 11:38:26 +00:00
Kazuhito Yokoi
9dbdf0947b Add tooltip to expand button in markdown editor 2019-10-31 17:21:26 +09:00
Kazuhito Yokoi
7c21bf4555 Add icons for typedInput 2019-10-31 16:03:27 +09:00
Kazuhito Yokoi
361dc194ee Support ctrl key to select tabs for Windows 2019-10-31 14:46:29 +09:00
Hiroyasu Nishiyama
8c1aa83d12 update support of i18n of JSON editor 2019-10-31 12:26:04 +09:00
Kazuhito Yokoi
d2755a8049 Support i18n for typedInput in split and switch nodes 2019-10-30 19:58:29 +09:00
Kazuhito Yokoi
1b78bd1684 Add placeholder to topic field 2019-10-30 19:39:38 +09:00
Kazuhito Yokoi
5f67f1f078 Add placeholders to name fields 2019-10-29 20:45:57 +09:00
Hiroyasu Nishiyama
07061928df make JSONata help initially shown 2019-10-29 10:24:15 +09:00
Hiroyasu Nishiyama
18ff2df65c prohibit line break in type menu of typedInput 2019-10-28 23:49:14 +09:00
Hiroyasu Nishiyama
7b1411d171 update Japanese JSONata message catalogue 2019-10-28 22:45:53 +09:00
Nick O'Leary
3a1d0f3695 Merge pull request #2330 from kazuhitoyokoi/master-fixcopyhandling4subflow
Fix handling to avoid invalid nested subflow
2019-10-28 09:58:32 +00:00
Nick O'Leary
2cd5e1d3c5 Bump for 1.0.3 2019-10-27 21:22:20 +00:00
Nick O'Leary
000765fb77 Increase timeouts in Subflow tests to minimise false positives 2019-10-25 21:15:59 +01:00
Dave Conway-Jones
0ff324b0db delay node- remove commented out code 2019-10-25 17:03:16 +01:00
Dave Conway-Jones
a96d5096fe Fix delay to not pass through .reset and .flush props consistently
to close #2349
(it used to not pass them through but did on initial message... now it doesn't)
2019-10-25 16:48:35 +01:00
Dave Conway-Jones
e8ef476a6d update grunt-sass and add node-sass for node12 support
and update Gruntfile.js to use them
2019-10-25 15:23:51 +01:00
juggledad
22b9df62d1 Using the ‘a msg per line’ the last line does not get msg.topic passed (#2352)
When using the file-in node and ‘a msg per line’ the last line does not get msg.topic passed. 

In the  
   .on(‘end’, function() { 
code (starting at line 334) the msg is created but no msg.topic is set. Adding 
   topic:msg.topic, 
after line 343 (var m = { payload: spare,) fixes the issue.
2019-10-25 14:51:50 +01:00
Nick O'Leary
6026da867b Fix timings of Delay node tests 2019-10-25 11:48:12 +01:00
Nick O'Leary
4d58902ba7 Merge pull request #2340 from pdong/chore/update-to-jsonata-1.7
Update JSONata to 1.7.0
2019-10-25 10:25:22 +01:00
Nick O'Leary
4dc1343445 Merge pull request #2350 from kazuhitoyokoi/master-addtranslation4httprequest
Add translation for http request node
2019-10-25 10:22:41 +01:00
Nick O'Leary
080487cb33 Bump https-proxy-agent version 2019-10-25 10:22:05 +01:00
Nick O'Leary
0febcf4f9e Merge pull request #2339 from bartbutenaers/master
Check auth type on opening
2019-10-23 21:38:54 +01:00
Nick O'Leary
cd23f711ed Merge pull request #2332 from TJKoury/patch-2
Remove msg
2019-10-23 21:37:58 +01:00
Nick O'Leary
f9b147af42 Merge pull request #2334 from kazuhitoyokoi/master-fixsubflowlang2
Fix language handling in subflow node
2019-10-23 21:36:57 +01:00
Nick O'Leary
775f1110d3 Merge pull request #2337 from piyonakajima/language_of_tooltip
fix tooltip language in subflow
2019-10-23 21:33:32 +01:00
Nick O'Leary
57649a9b81 Merge pull request #2345 from 1ft-seabass/fix-tcpin
Removed unused variable "remoteDetails"
2019-10-23 21:32:29 +01:00
Nick O'Leary
72a268b70a Merge pull request #2344 from 1ft-seabass/fix-70-csv
Fixed the code format of 70-CSV.js from Tab to Space. try again.
2019-10-23 21:31:30 +01:00
Nick O'Leary
f86a171dff Merge pull request #2346 from 1ft-seabass/fix-jsdoc-description
Fixed jsdoc descriptions
2019-10-23 21:31:02 +01:00
tseigo
e022b782a9 Fixed jsdoc descriptions 2019-10-22 00:35:35 +09:00
tseigo
bd67731bb7 Removed unused variable "remoteDetails" 2019-10-22 00:28:57 +09:00
tseigo
25de4e4782 Fixed the code format of 70-CSV.js from Tab to Space. try again. 2019-10-22 00:24:10 +09:00
Phi Dong
c590247afa Update node-red/util JSONata to 1.7.0 2019-10-19 14:33:13 -07:00
Phi Dong
5d36539271 Update JSONata to 1.7.0 2019-10-19 12:37:54 -07:00
bartbutenaers
0d673486a3 Check auth type on opening 2019-10-19 14:16:03 +02:00
Nick O'Leary
29f1651a18 Use default language if lng param not set in i18n req 2019-10-18 16:09:14 +01:00
NAKAJIMA,Tomohiro
dd20a3e685 Fix the language of the tooltip 2019-10-18 23:50:54 +09:00
Kazuhito Yokoi
75a5b1354c Add translation for http request node 2019-10-17 21:56:22 +09:00
Kazuhito Yokoi
dae9ac8173 Fix language handling in subflow node 2019-10-17 21:24:55 +09:00
Dave Conway-Jones
78b735276b fix httprequest timeout units info
to close #2333
2019-10-17 13:24:51 +01:00
Kazuhito Yokoi
e10dd54e2b Revert "Merge pull request #2328 from kazuhitoyokoi/master-fixsubflowlang"
This reverts commit 873bdc6733, reversing
changes made to 8a40b075b5.
2019-10-17 21:05:06 +09:00
TJKoury
cb8deab1f9 Update packages/node_modules/@node-red/runtime/lib/nodes/Node.js
Co-Authored-By: Nick O'Leary <nick.oleary@gmail.com>
2019-10-17 07:42:11 -04:00
TJKoury
e5c27d0236 Remove msg
`msg` not defined in scope.
2019-10-16 20:00:11 -04:00
Kazuhito Yokoi
faf6fa9450 Fix copy and paste handling in subflow 2019-10-16 20:59:01 +09:00
Nick O'Leary
873bdc6733 Merge pull request #2328 from kazuhitoyokoi/master-fixsubflowlang
Fix language handling in subflow node
2019-10-16 11:12:48 +01:00
Nick O'Leary
8a40b075b5 Merge pull request #2326 from bonanitech/patch-1
Fix palette editor search visualization
2019-10-16 11:12:03 +01:00
Kazuhito Yokoi
56c41374bf Fix language handling in subflow node 2019-10-15 16:50:16 +09:00
Mauricio Bonani
a08c2c6437 Fix palette editor search visualization 2019-10-14 15:13:59 -04:00
Nick O'Leary
e94634544c Add script to generate npm publish script 2019-10-14 15:50:48 +01:00
Nick O'Leary
07fe5b247b Bump for 1.0.2 2019-10-14 13:17:48 +01:00
Nick O'Leary
c1c694035d Allow node.status() to be passed number/bool types
Adds to the existing support for string types. Also
adds unit tests for all three cases
2019-10-14 13:06:59 +01:00
Nick O'Leary
147d2a02be Ensure node status is refreshed whenever node is edited
Fixes an issue where, if the number of node outputs was changes
the node would resize, but the status text would not reposition
until a new status message arrived.

This change marks status as dirty whenever the node has been
edited, forcing it to be redrawn.
2019-10-14 13:05:45 +01:00
Nick O'Leary
6f91786f4d Fixup Change node use of node.done 2019-10-11 11:08:25 +01:00
Nick O'Leary
f62a933d1c Ensure z property included in full message debug payload
Fixes #2315 #2316
2019-10-11 11:07:48 +01:00
1ft-seabass
451835fbeb Fixed editor.json (#2321) 2019-10-11 08:55:23 +01:00
Nick O'Leary
547e7a1b21 Allow node emitted events to have multiple arguments
This is fixing a regression introduced in 1.0 where a custom
`Node.emit` function was added that could only handle a single
argument.
2019-10-10 16:35:12 +01:00
Nick O'Leary
053e3ba923 Merge pull request #2313 from kazuhitoyokoi/master-fixvisualeditor
Fix menu in visual JSON editor
2019-10-10 14:31:19 +01:00
Nick O'Leary
bf65dcd49b Merge pull request #2314 from ThierryLeGal/addItem-insert-divider
Insert divider in menu by calling RED.menu.addItem('id', null);
2019-10-10 14:29:14 +01:00
Nick O'Leary
a1d186112a Merge pull request #2323 from boisei0/jsdoc-red-util
Fixed docstrings to have them match the function signature
2019-10-10 14:26:52 +01:00
Arlena Derksen
ca7a298509 Fixed docstrings to have them match the function signature (name of parameters). 2019-10-10 14:57:19 +02:00
Kazuhito Yokoi
ff4d58f648 Fix invalid JSON data in template node (#2322) 2019-10-10 10:34:10 +01:00
kitazaki
a1e10e99fa Update 10-file.html (#2320) 2019-10-09 14:51:38 +01:00
Ryoichi Obara
16bda530f6 Remove unnecessary comma. (#2312) 2019-10-09 08:41:33 +01:00
Ryoichi Obara
bf9e04d9db Unify translations of "boolean". (#2318) 2019-10-09 08:40:36 +01:00
Ryoichi Obara
8df86a75b1 Interval of inject node should be 596 hours or less. (#2319) 2019-10-09 08:39:08 +01:00
Thierry Le Gal
5056203023 Insert divider in menu by calling RED.menu.addItem('id', null); 2019-10-07 14:47:20 +02:00
Kazuhito Yokoi
a0026e66ce Fix element to collapse items in visual JSON editor 2019-10-07 16:13:04 +09:00
Nick O'Leary
f75dd2209d Bump for 1.0.1 2019-10-04 11:13:46 +01:00
Nick O'Leary
e35f6d9e35 Allow TLS config node to provide just CA cert
Fixes #2297
2019-10-04 11:02:00 +01:00
Nick O'Leary
3cb00ce4e0 Merge pull request #2308 from kazuhitoyokoi/master-fixgridsetting
Fix grid setting in flow editor
2019-10-04 10:53:01 +01:00
Nick O'Leary
8e18cf5986 Merge pull request #2306 from kazuhitoyokoi/master-fixtooltips
i18n support in tooltips
2019-10-04 10:50:27 +01:00
Nick O'Leary
81f80600f5 Merge pull request #2307 from kazuhitoyokoi/master-fixinjectnode
Fix width on inject node property
2019-10-04 10:49:48 +01:00
Kazuhito Yokoi
895156675f Fix grid setting 2019-10-04 18:15:32 +09:00
Kazuhito Yokoi
1c424e2e0a Fix width on inject node property 2019-10-04 15:33:31 +09:00
Kazuhito Yokoi
0124bb17e8 i18n support in tooltips 2019-10-04 12:22:09 +09:00
Hiroyasu Nishiyama
2c89b2d262 update Japanese info text of range node (#2302) 2019-10-03 20:32:56 +01:00
Nick O'Leary
c7bbe2f1fe Add env vars to enable safe mode and projects (#2301)
* Add NODE_RED_ENABLE_SAFE_MODE and NODE_RED_ENABLE_PROJECTS

* Allow env-vars to be set to false to disable features
2019-10-03 20:31:16 +01:00
Nick O'Leary
88609a8829 Merge pull request #2303 from pdong/bug/node-color-change-when-not-on-a-flow
Fix issue where subflow color did not update when not on a flow
2019-10-03 15:59:35 +01:00
Nick O'Leary
329beb166c Merge pull request #2305 from kazuhitoyokoi/master-fixlargeicon4subflowtab
Fix large icon on subflow tab in IE
2019-10-03 15:54:34 +01:00
Nick O'Leary
e36f3d937c Merge branch 'pr_2304' 2019-10-03 15:53:58 +01:00
Nick O'Leary
1395092ca6 Add viewbox to default icon 2019-10-03 15:53:26 +01:00
Nick O'Leary
c09004dbc8 Fix error when setting typedInput to boolean true/false 2019-10-03 15:04:49 +01:00
Kazuhito Yokoi
7efe4a2776 Fix large icon on subflow tab in IE 2019-10-02 18:22:43 +09:00
Dave Conway-Jones
b763e0b0cb Let switch node between rule work both ways round
and add test
2019-10-02 09:52:26 +01:00
Kazuhito Yokoi
ddd0d1bef3 Fix invisible icons in IE 2019-10-02 17:39:38 +09:00
Phi Dong
dbca2178c0 Fix issue where subflow color did not update when not on a flow 2019-10-01 22:46:01 -07:00
Dave Conway-Jones
af742ea536 Add example to range node info and make use of target consistent 2019-10-01 20:57:20 +01:00
Nick O'Leary
14c1a86b9b Merge pull request #2299 from kazuhitoyokoi/master-fixtypedinput4ie
Fix large icons in typed input for IE
2019-10-01 12:43:23 +01:00
Nick O'Leary
ee3dc8c4cd Join node must clone group message before sending 2019-10-01 12:41:20 +01:00
Kazuhito Yokoi
1ed148aaf5 Fix large icons in typed input for IE 2019-10-01 20:02:34 +09:00
Nick O'Leary
3327adb1ae Update readme 2019-09-30 13:38:46 +01:00
Nick O'Leary
4d5f771f9f Bump for 1.0 2019-09-30 11:02:22 +01:00
Nick O'Leary
aa69d663ed Put <meta> inside <head> to keep IE11 happy 2019-09-30 10:59:20 +01:00
Nick O'Leary
29d1894f9a Fix wrap of header logo in IE11 2019-09-30 10:59:04 +01:00
Nick O'Leary
e5738d608c Add fallback for Object.values call in IE11 2019-09-30 10:58:03 +01:00
Nick O'Leary
9775d3a33d Ensure status is refreshed when switching tabs 2019-09-30 09:56:51 +01:00
Nick O'Leary
ad4cf8d631 Merge branch 'dev' of github.com:node-red/node-red into dev 2019-09-30 09:56:01 +01:00
Dave Conway-Jones
a27e8777aa Let function node spinner go to 0 2019-09-30 09:54:05 +01:00
Nick O'Leary
d23edcc0b5 Merge branch 'dev' of github.com:node-red/node-red into dev 2019-09-29 16:47:44 +01:00
Nick O'Leary
52373e5bef Add click-on-tooltip to close
For the rare occasions a tooltip gets orphaned on the page
2019-09-29 16:47:18 +01:00
Dave Conway-Jones
bb70e796a1 Change MQtt node default 3.1 compatibility mode to false 2019-09-27 14:22:37 +01:00
Nick O'Leary
3365d26b40 Merge pull request #2291 from kazuhitoyokoi/dev-fixmenuhiding
Fix menu hiding function for flow editor
2019-09-26 20:45:59 +01:00
Nick O'Leary
d3c111b533 Merge pull request #2293 from kazuhitoyokoi/dev-fixi18n4project
Update i18n for project feature
2019-09-26 20:32:15 +01:00
Nick O'Leary
ec876eb102 Merge pull request #2295 from kazuhitoyokoi/dev-fixnodedraggablehandling
Fix draggable handling in palette
2019-09-26 20:31:41 +01:00
Kazuhito Yokoi
dddfb1ec08 Fix node draggable handling 2019-09-26 11:43:24 +09:00
Nick O'Leary
6fc9c03d70 Ensure complete node scope property is remapped on import 2019-09-24 21:04:33 +01:00
Kazuhito Yokoi
199ff071e8 Update i18n for project feature 2019-09-24 19:46:51 +09:00
Kazuhito Yokoi
7e4a06044a Fix menu hiding function for flow editor 2019-09-24 17:22:36 +09:00
Nick O'Leary
d047b75cb7 Show clear debug shortcut in tooltip 2019-09-23 10:28:26 +01:00
Nick O'Leary
6fb6b13037 Normalise default subflow color references 2019-09-23 10:28:26 +01:00
Dave Conway-Jones
460c5a1ae3 fix file-in port labels for all 4 options 2019-09-20 21:57:19 +01:00
Nick O'Leary
9955bcc339 Hide header text of very small screens to deploy is visible 2019-09-20 13:08:50 +01:00
Nick O'Leary
0a3ab996eb Merge pull request #2290 from node-red-hitachi/fix-node-name-breaking
allow word breaking of node name with long word
2019-09-20 13:08:34 +01:00
Nick O'Leary
46f912a6f9 Merge pull request #2283 from kazuhitoyokoi/dev-fixmarkdowneditor
Fix Markdown editor
2019-09-20 13:00:04 +01:00
Nick O'Leary
01e0f24752 Merge pull request #2289 from kazuhitoyokoi/dev-fixinfo4completenode
Fix typo in complete node
2019-09-20 12:59:38 +01:00
Nick O'Leary
7178c63e10 Fix tab access on touch screens 2019-09-20 12:58:21 +01:00
Nick O'Leary
30c402eb83 Update radialMenu to use standard theme colours 2019-09-20 12:58:21 +01:00
Nick O'Leary
2601cc898c Fix undefined reference loading on mobile 2019-09-20 12:58:21 +01:00
Dave Conway-Jones
d2a8823808 add extra comment re mustache escapes to tempalte info 2019-09-20 11:20:40 +01:00
Dave Conway-Jones
6b61fa9f6f remove legacy error option from file in mode
(for 1.0)
2019-09-20 11:18:19 +01:00
Hiroyasu Nishiyama
247052df5f allow word breaking of node name with long word 2019-09-19 22:50:35 +09:00
Kazuhito Yokoi
8eb28555bc Enable wrap mode in Markdown editor 2019-09-17 20:26:59 +09:00
Kazuhito Yokoi
73132475dc Fix typo in complete node 2019-09-17 18:10:47 +09:00
Kazuhito Yokoi
42c6487ff3 Show print margin on ace editor 2019-09-17 14:47:00 +09:00
Nick O'Leary
8d2ca25fd6 Update changelog 2019-09-16 15:33:05 +01:00
Nick O'Leary
5c5919a7eb Merge branch 'master' into dev 2019-09-16 15:27:34 +01:00
Nick O'Leary
34cdbfc852 Bump for 1.0.0-beta.4 2019-09-16 15:27:06 +01:00
Nick O'Leary
1bc50194aa Merge pull request #2282 from node-red-hitachi/update-jp-message
update Japanese message catalogue
2019-09-16 15:23:38 +01:00
Nick O'Leary
4a75236e74 Merge pull request #2286 from node-red-hitachi/fix-subflow-UI-select
Fix subflow UI for select
2019-09-16 15:23:15 +01:00
Nick O'Leary
64b2f881c4 Merge pull request #2285 from node-red-hitachi/fix-subflow-ui-label-padding
Remove padding for label for SUBFLOW UI row without icon
2019-09-16 15:21:05 +01:00
Nick O'Leary
4709ddea5d Merge pull request #2284 from node-red-hitachi/allow-subflow-label-row-wo-name
Allow subflow label row without environment variable name
2019-09-16 15:18:44 +01:00
Hiroyasu Nishiyama
6ef49152f3 remove useless variable definition 2019-09-15 23:55:27 +09:00
Hiroyasu Nishiyama
1c44b0bc98 Fix subflow UI for select 2019-09-15 23:44:01 +09:00
Hiroyasu Nishiyama
11bce8c17c remove padding before label text for SUBFLOW UI row 2019-09-13 23:11:23 +09:00
Hiroyasu Nishiyama
b42fff1055 Allow SUBFLOW UI label row without variable name 2019-09-13 22:49:48 +09:00
Kazuhito Yokoi
1b2e442513 Remove print margin from library editor 2019-09-13 14:43:13 +09:00
Kazuhito Yokoi
a4d48077ba Remove print margin from ace editor 2019-09-13 14:42:45 +09:00
Kazuhito Yokoi
901e2527d8 Maximize the size of markdown editor 2019-09-13 14:41:10 +09:00
Nick O'Leary
f0839571d0 Clone the first message passed to node.send in Function
Also introduces an optional second arg to node.send in the Function
node that can disable that cloning
2019-09-12 22:09:35 +01:00
Dave Conway-Jones
89d0d6ec93 remove old rc option from exec node for 1.0
(not removing functionality so old flows will keep working - just removing option to select it)
2019-09-12 17:01:11 +01:00
Hiroyasu Nishiyama
922ab1d17b update Japanese message catalogue 2019-09-11 22:46:01 +09:00
Dave Conway-Jones
7c7be378bc Add python and SQL to template language options
as we already include in the ACE modes
2019-09-10 17:17:21 +01:00
Nick O'Leary
ec01f8f54b Move context sidebar auto-refresh option to individual sections 2019-09-10 17:10:22 +01:00
Nick O'Leary
5a094b44c4 Remove 'uglify' from Grunt watch task
The grunt watch task is used by the grunt dev task that watches for
changes and auto rebuilds the editor js.

When running in dev mode, the editor will load the unminified version
of red.js. This means there is no point in running the uglify task to
generate the minified version. The uglify task tasks a few seconds and
if you do a couple rapid saves, the second will often not get built as
the previous uglify task was still running.

Removing it from the dev task shouldn't have any side effects. It still
forms part of the `grunt build` and `grunt release` tasks where it is
needed.
2019-09-10 17:04:53 +01:00
Nick O'Leary
3c657a6645 Fix Switch node display of jsonata_exp type 2019-09-10 14:31:34 +01:00
Nick O'Leary
3129d44ff1 Realign subflow output port labels 2019-09-10 14:31:17 +01:00
Nick O'Leary
00306f82c5 Remove sentiment from core nodes 2019-09-10 14:31:08 +01:00
Nick O'Leary
7def676a17 Create SECURITY.md 2019-09-10 12:56:32 +01:00
Nick O'Leary
6c48735854 Move flow-status button to footer for consistency 2019-09-10 11:49:59 +01:00
Nick O'Leary
a0b1831cdb Fix node hover effect to prevent jumping position 2019-09-10 11:39:07 +01:00
Nick O'Leary
db9fb8480a Filter quickadd properly when splicing a wire 2019-09-10 11:38:35 +01:00
Nick O'Leary
c138e2ffb4 Mark workspace dirty when deleting link node link
Fixes #2274
2019-09-10 11:12:38 +01:00
Nick O'Leary
473c45794e Merge pull request #2281 from node-red-hitachi/fix-comple-node-info-text
update info text of complete node & add JP text
2019-09-10 09:55:46 +01:00
Nick O'Leary
a12aa81d73 Add red-ui-button class to strategy login button 2019-09-10 09:54:15 +01:00
Nick O'Leary
0033e279f1 Merge pull request #2277 from hobbyquaker/patch-1
Add css class to login submit button
2019-09-10 09:48:26 +01:00
Nick O'Leary
a25e98d0cb Fix padding of subflow locale select
Closes #2276
2019-09-10 09:45:04 +01:00
Nick O'Leary
bc65480f27 Merge pull request #2273 from node-red-hitachi/update-jp-message
Update JP message catalogue
2019-09-10 09:32:27 +01:00
Hiroyasu Nishiyama
8582cda124 update info text of complete node & add JP text 2019-09-09 21:44:23 +09:00
Nick O'Leary
d963dfdbb6 Merge branch 'master' into dev 2019-09-06 10:49:27 +01:00
Nick O'Leary
f7e9c109f6 Bump for 0.20.8 2019-09-06 10:28:52 +01:00
Nick O'Leary
30c3004f27 Sanitize tab name in edit dialog 2019-09-06 10:25:30 +01:00
Sebastian Raff
4f049fd94b add class red-ui-button to cancel button 2019-08-28 17:55:59 +02:00
Sebastian Raff
f98d1c95cc Add css class to login submit button (#2275) 2019-08-27 19:32:59 +02:00
Hiroyasu Nishiyama
a2b5c0247b update JP message catalogue 2019-08-26 23:08:25 +09:00
Nick O'Leary
28bda9fa41 Bump for 1.0.0-beta.3 2019-08-22 11:09:55 +01:00
Nick O'Leary
18aeeab041 Bump dependencies 2019-08-22 10:40:33 +01:00
Nick O'Leary
c7427a5f7c Add nls messages for new palette categories 2019-08-21 17:30:02 +01:00
Nick O'Leary
03aa6c7d3a Apply user specified palette cateogies and remaining core ones 2019-08-21 17:27:06 +01:00
Nick O'Leary
10077ae750 Use a more atomic process for writing context files
Fixes #2271
2019-08-21 16:54:26 +01:00
Nick O'Leary
74eec25285 Merge pull request #2213 from node-red/node-categories
Change core node categories
2019-08-21 16:04:44 +01:00
Nick O'Leary
b6055479a1 Move Complete node to the new common category 2019-08-21 14:41:51 +01:00
Nick O'Leary
69b781419f Move io to network 2019-08-21 14:23:24 +01:00
Nick O'Leary
da6db24f9e Reorganise nodes into new categories 2019-08-21 14:23:23 +01:00
Nick O'Leary
2b66723d42 Another pass of categorisation 2019-08-21 14:22:30 +01:00
Nick O'Leary
00a3e25714 Change core node categories 2019-08-21 14:21:34 +01:00
Nick O'Leary
8ccbd2d8f9 Merge branch 'dev' into pr_2258 2019-08-21 12:52:58 +01:00
Nick O'Leary
8307f26099 Fix up dynamic generation of switch ui 2019-08-21 12:39:51 +01:00
Nick O'Leary
c686f7eefc Set default http request persist option to false 2019-08-21 11:45:21 +01:00
Nick O'Leary
311c7b1158 Merge pull request #2261 from eeyepee/master
Add HTTP Persistent (session reuse) capability
2019-08-21 11:44:35 +01:00
Nick O'Leary
a17325f028 Update Function catch tests to handle async receive 2019-08-21 11:39:34 +01:00
Nick O'Leary
b734097d16 Merge pull request #2227 from node-red/node-done
Adds Done callback to Input event handler
2019-08-21 11:15:00 +01:00
Nick O'Leary
afaf077aca Pass httpServer to runtime even when httpAdmin disabled
Fixes #2272
2019-08-21 11:12:50 +01:00
Dave Conway-Jones
bf14af6a1f Function node - handle things thrown that aren't proper Error types
and add tests
to close #2269
2019-08-19 10:42:14 +01:00
Nick O'Leary
e72faef839 Check both node props and defn props when deciding to splice 2019-08-16 14:59:15 +01:00
Nick O'Leary
b274bafe8e Allow a node to change if it has an input port
Closes #2268
2019-08-15 13:29:08 +01:00
Nick O'Leary
7bed967755 Add node.done to exec node 2019-08-15 10:40:40 +01:00
Nick O'Leary
944b81b71c Update UDP nodes for node.done 2019-08-15 10:20:54 +01:00
Nick O'Leary
cd529d53ae Update TCP nodes to node.done 2019-08-15 10:19:03 +01:00
Nam Giang
0d680a58f3 removed expensive try/catch 2019-08-14 15:11:03 -07:00
Nam Giang
b30d519523 Merge branch 'master' of github.com:namgk/node-red 2019-08-14 15:02:51 -07:00
Nick O'Leary
83932e1725 Fix Flow test for updated node.done api 2019-08-14 22:55:46 +01:00
Nick O'Leary
4ce0e39760 Add nodeDone to File nodes 2019-08-14 22:28:10 +01:00
Nick O'Leary
84232f25f0 Add node done to mqtt, http req and ws output nodes 2019-08-14 15:54:06 +01:00
Nick O'Leary
2daedf8fd5 Sanitize subflow env var names properly when building ui form 2019-08-14 11:43:04 +01:00
Nick O'Leary
fe084a4478 Allow search results to show more than 25 results 2019-08-14 11:37:46 +01:00
Nick O'Leary
5bf9646a76 Merge pull request #2266 from node-red-hitachi/fix-subflow-i18n
Fix i18n of new subflow feature
2019-08-14 09:52:42 +01:00
Nick O'Leary
2b1f28e6c2 Merge pull request #2265 from node-red-hitachi/fix-ko-message-catalogue
remove unused entries in KO message catalogue
2019-08-14 09:52:05 +01:00
Nick O'Leary
5b8bd6e64f Merge pull request #2264 from node-red-hitachi/fix-de-message-catalogue
remove unused entries in DE message catalogue
2019-08-14 09:51:51 +01:00
Nick O'Leary
426fd499ce Fix ctrl-click on wire whilst already in quick-join 2019-08-14 09:50:34 +01:00
Nick O'Leary
17d3a5840d Revert "Add initial core:layout-flow action"
This reverts commit be49e1d383.
2019-08-13 20:41:13 +01:00
Nick O'Leary
be49e1d383 Add initial core:layout-flow action 2019-08-13 20:38:25 +01:00
Hiroyasu Nishiyama
daa98e8925 fix i18n of new subflow feature 2019-08-13 21:17:31 +09:00
Nick O'Leary
58784b7568 Use ctrl-click on wire to splice node in place 2019-08-13 10:31:21 +01:00
Hiroyasu Nishiyama
419a183167 remove unused entries in KO message catalogue 2019-08-13 15:05:14 +09:00
Hiroyasu Nishiyama
675b4bde14 remove unused entries in DE message catalogue 2019-08-13 14:51:59 +09:00
Nick O'Leary
ee6ee99577 Make icon and color pickers more consistent 2019-08-12 22:07:55 +01:00
Ibrahim Al-Mahfooz
3bc1f69e75 Update 21-httprequest.js 2019-08-12 22:52:00 +03:00
Ibrahim Al-Mahfooz
5b9df6d5f2 Update 21-httprequest.html 2019-08-12 22:50:37 +03:00
Ibrahim Al-Mahfooz
9f062ec1b8 Update messages.json 2019-08-12 22:49:41 +03:00
Ibrahim Al-Mahfooz
b52a47bd03 Update messages.json
Change persistent to persist
2019-08-12 22:06:49 +03:00
Ibrahim Al-Mahfooz
5e20134f4f Update 21-httprequest.html
Change persistent to persist
2019-08-12 22:05:50 +03:00
Ibrahim Al-Mahfooz
89d267d6a2 Update packages/node_modules/@node-red/nodes/locales/en-US/messages.json
Co-Authored-By: Nick O'Leary <nick.oleary@gmail.com>
2019-08-12 20:29:09 +03:00
Nick O'Leary
607bc42f59 Merge branch 'dev' into pr_2225 2019-08-12 15:05:12 +01:00
Nick O'Leary
880757fb5d Rework Subflow Instance property UI (#2236)
* Add support of Subflow UI definition

* new UI definition for env var

* fix label

* fixed value obtaining

* fixed label width

* fix checkbox

* fix subflow info

* remove old subflow ui tests

* add tests

* merge ui new changes

* fix initial open button

* fix environment variable edit tab

* WIP: cp-1

* Rework subflow ui property

* Restrict SF value type according to input selection

* Move subflow property UI code to subflow.js

* Update subflow ui type select appearance

* Present subflow instance properties as table rather than generated UI

* Move subflow instance properties to separate tab

* Fix subflow property ui element layout issues
2019-08-12 15:01:54 +01:00
Nick O'Leary
c8acc6a12e Fix redo of subflow create 2019-08-12 14:51:01 +01:00
Nick O'Leary
7d4c2442da Merge branch 'dev' into pr_2221 2019-08-12 14:44:30 +01:00
Nick O'Leary
e5255b0c7c Ensure 2nd arg to node.error is an object
Fixes #2228
2019-08-12 14:36:26 +01:00
Nick O'Leary
ac3ef9b6fc Merge pull request #2263 from node-red-hitachi/fix-subflow-category-change
fix subflow category change on palette
2019-08-12 10:58:56 +01:00
Hiroyasu Nishiyama
7b5a41c3ff fix subflow category change on palette 2019-08-12 13:49:34 +09:00
Ibrahim Al-Mahfooz
d5b0d2a886 Update 21-httprequest.html
Adding the HTTP Persistent web configuration
2019-08-09 21:26:14 +03:00
Ibrahim Al-Mahfooz
4d60447242 Update 21-httprequest.js
Adding HTTP persistent definition and function
2019-08-09 21:23:28 +03:00
Ibrahim Al-Mahfooz
78bee3dc59 Update messages.json
Added the HTTP Persistent item
2019-08-09 21:20:45 +03:00
Nick O'Leary
e2db958510 Fix up admin nodes test for audit log changes 2019-08-09 17:27:32 +01:00
Nick O'Leary
16440072fb Add audit log to project spec tests 2019-08-09 17:09:03 +01:00
Nick O'Leary
be2dd6dc32 Add req back to audit log events and extend to Projects api 2019-08-09 16:56:11 +01:00
Nick O'Leary
189bde7c9c Merge pull request #2259 from kazuhitoyokoi/master-fixtabsmenu
Remove tab menu from node property UI for subflow and configuration nodes
2019-08-09 10:26:08 +01:00
Nick O'Leary
6a4760e291 Mark workspace dirty when shift-click-drag detaches wires
Fixes #2260
2019-08-09 10:24:52 +01:00
Kazuhito Yokoi
c082bb97e0 Remove tab menu from node property UI for subflow and config nodes 2019-08-07 12:29:20 +09:00
Nam Giang
c8e14f91e7 optimization for switch node 2019-08-06 17:41:35 -07:00
Nick O'Leary
6032d096ec Merge branch 'master' into dev 2019-08-06 17:13:00 +01:00
Nick O'Leary
defa9a2270 Fix ssh-keygen error handling 2019-08-06 17:12:40 +01:00
Nick O'Leary
77a913f858 Add Node 12 to full build matrix on Travis
Having removed the ui test dependencies out of package.json
we can remove the 'allow failures' flag from the node 12 build.

Given how close Node 12 is to being LTS, we really need to pay
proper attention to it.
2019-08-06 16:34:43 +01:00
Nick O'Leary
6e3fa974ba Remove all ui test dependencies from package.json
Given chromedriver was already an extra dependency that needed to
be manually installed, I have now moved all of the webdriver.io
dependencies out as well.

A new script has been added to install all of the ui test dependencies.

The Grunt file has been updated on how it checks for the missing
deps.
2019-08-06 16:32:46 +01:00
Nick O'Leary
7926055b97 Merge branch 'master' into dev 2019-08-06 16:10:33 +01:00
Nick O'Leary
ffd10e656e Merge pull request #2251 from kazuhitoyokoi/master-fixsplitnode
Fix escape character handling for separator in split node
2019-08-06 16:00:58 +01:00
Nick O'Leary
59c1828078 Merge pull request #2253 from kazuhitoyokoi/master-removetooltip
Fix duplicated tooltips
2019-08-06 16:00:40 +01:00
Nick O'Leary
6164271fe8 Merge pull request #2250 from kazuhitoyokoi/master-updatetranslation4delaynode
Add Japanese translation into delay node
2019-08-06 16:00:01 +01:00
Nick O'Leary
26ba35933d Merge pull request #2257 from kazuhitoyokoi/dev-updatejapanesetranslation
Update Japanese message catalog
2019-08-06 15:59:46 +01:00
Nick O'Leary
87359937c9 Merge pull request #2256 from kazuhitoyokoi/master-fixerrorhandlingtostartserver
Use appropriate version of Node.js
2019-08-06 15:59:34 +01:00
Nick O'Leary
9b938f6515 Fix default value handling on context array access
Fixes #2252
2019-08-06 15:55:25 +01:00
Nick O'Leary
6c3913785d Add error event handler to ssh-keygen child_process
Fixes #2255
2019-08-06 15:21:57 +01:00
Nick O'Leary
542cf3147d Support displaying falsey node status values
Fixes #2246
2019-08-06 15:12:13 +01:00
Nick O'Leary
fb9828badc Update Function node to add node.done 2019-08-06 14:27:56 +01:00
Kazuhito Yokoi
2505ac3f98 Update Japanese message catalog 2019-08-06 19:57:39 +09:00
Kazuhito Yokoi
fde8548166 Remove handling for unused error code 2019-08-06 19:30:05 +09:00
Kazuhito Yokoi
fe91295704 Replace node.js with Node.js 2019-08-06 19:27:46 +09:00
Kazuhito Yokoi
15b99c5749 Use appropriate the version of Node.js 2019-08-06 19:24:45 +09:00
Kazuhito Yokoi
9d66ca4a49 Fix duplicated tooltip 2019-08-05 19:03:30 +09:00
Kunihiko Toumura
b749a27f86 Eliminate snake_case and use camelCase, and change assignment of keyboard shortcut 2019-08-05 10:20:46 +09:00
Nick O'Leary
083212cffe Merge pull request #2248 from kazuhitoyokoi/master-removeunusedvariables
Remove unused variable
2019-08-02 09:42:22 +01:00
Kunihiko Toumura
c4e8756210 merge upstream changes 2019-08-02 15:15:30 +09:00
Kazuhito Yokoi
3a6448f727 Fix splitters in split node 2019-08-02 13:56:37 +09:00
Kazuhito Yokoi
fe18df25ba Add Japanese translation to delay node 2019-08-01 20:50:35 +09:00
Hiroyasu Nishiyama
db65460ec0 fix SUBFLOW palette node update & SUBFLOW default color 2019-07-31 22:59:29 +09:00
Kazuhito Yokoi
0ad3eceb82 Remove unused variables 2019-07-31 16:06:30 +09:00
Nick O'Leary
a376d6e361 Merge pull request #2226 from node-red/add-has_key-to-switch
Add "has key" rule to  switch node + tests
2019-07-30 23:06:44 +01:00
Nick O'Leary
45c7f3f3ca Update packages/node_modules/@node-red/nodes/core/logic/10-switch.html 2019-07-30 23:06:18 +01:00
Nick O'Leary
238de59a2a Merge pull request #2232 from node-red-hitachi/fix-delete-tab
fix reference error on deleting tab
2019-07-30 23:04:01 +01:00
Nick O'Leary
96255e51d2 Merge pull request #2245 from node-red-hitachi/fix-conv-subflow
Fix error on converting selection to subflow
2019-07-30 23:03:30 +01:00
Nick O'Leary
18c3223105 Merge pull request #2247 from kazuhitoyokoi/master-fixvariablename
Fix wrong variable name
2019-07-30 23:01:59 +01:00
Kazuhito Yokoi
b9e97792f3 Fix wrong variable name 2019-07-30 19:52:28 +09:00
Hiroyasu Nishiyama
cbce9b8637 fix undo handling & typo 2019-07-30 11:07:55 +09:00
Ben Hardill
5ab90b85da Limit the regex for the /nodes/ api end points
fixes #2240

It looks like the regex for the /nodes/... endpoints over matches.

I've added `^` to the start to anchor the matches to the start of the
URL.
2019-07-29 11:42:29 +01:00
Nick O'Leary
f3e1e8a2c7 Merge pull request #2244 from kazuhitoyokoi/master-fixwiring4subflownode
Fix inserting new subflow node to existing wire
2019-07-29 10:57:45 +01:00
Nick O'Leary
e41b292e54 Merge pull request #2238 from teastman/master
Handle undefined node._def in edit stack title.
2019-07-29 10:44:54 +01:00
Hiroyasu Nishiyama
86928bbb2d fix converting selection to subflow 2019-07-26 23:06:56 +09:00
Kazuhito Yokoi
2f5ec8b5bf Fix inserting new subflow node to existing wire between nodes 2019-07-26 17:51:49 +09:00
Tyler Eastman
14ac6446de Handle undefined node._def in edit stack title. 2019-07-22 14:25:52 -07:00
Hiroyasu Nishiyama
260a9723a4 use custom color picker instead of color input type 2019-07-21 22:55:25 +09:00
Kunihiko Toumura
4e7b000dcd Merge remote-tracking branch 'upstream/dev' into dev-redo 2019-07-17 09:13:01 +09:00
Kunihiko Toumura
2254e4c57e minor fix (add semicolon) 2019-07-17 09:12:47 +09:00
Hiroyasu Nishiyama
25a27733b9 fix reference error on deleting tab 2019-07-15 11:23:27 +09:00
Nick O'Leary
6ab520984c Merge branch 'dev' into pr_2229 2019-07-12 13:37:13 +01:00
Nick O'Leary
04d7106956 Remove unwanted icons 2019-07-12 13:37:01 +01:00
Hiroyasu Nishiyama
db5589f2aa rearrange contents of subflow template settings tab 2019-07-11 19:37:47 +09:00
Hiroyasu Nishiyama
d06dbbb4bd changed to color change reflect immediately on OK 2019-07-11 08:22:31 +09:00
Dave Conway-Jones
b7a62bd9e7 Update packages/node_modules/@node-red/nodes/core/logic/10-switch.html
Co-Authored-By: Nick O'Leary <nick.oleary@gmail.com>
2019-07-10 10:01:17 +01:00
Dave Conway-Jones
93ad9a3aa6 Update packages/node_modules/@node-red/nodes/core/logic/10-switch.js
Co-Authored-By: Nick O'Leary <nick.oleary@gmail.com>
2019-07-10 10:01:09 +01:00
Nick O'Leary
f1855174f0 Merge branch 'dev' into pr_2165 2019-07-10 09:30:48 +01:00
Dave Conway-Jones
a2dedba0ef change internal type to hask 2019-07-09 21:04:53 +01:00
Nick O'Leary
5a65f445f0 Bump test helper version 2019-07-09 11:44:33 +01:00
Nick O'Leary
f52289b2c3 Add send to input handler signature 2019-07-09 11:40:55 +01:00
Nick O'Leary
3b5ea0f15f Add node done API 2019-07-08 23:23:33 +01:00
Dave Conway-Jones
238bcb8698 Add "has key" rule to switch node + tests 2019-07-08 15:54:31 +01:00
Hiroyasu Nishiyama
3ee8bcad8c add support for specifying subflow template color 2019-07-08 23:52:08 +09:00
Nick O'Leary
f0a51bafbe Use node/tab map to make filterNodes more efficient 2019-07-08 10:55:26 +01:00
Nick O'Leary
944f3bd329 Merge branch 'master' into dev 2019-07-07 21:48:13 +01:00
Nick O'Leary
8bb7b2e88b Ensure session expiry timeout doesn't exceed limit 2019-07-06 16:34:48 +01:00
Nick O'Leary
aab0b0b4bf Bump for 0.20.7 2019-07-05 11:12:26 +01:00
Nick O'Leary
083d6c5125 Merge pull request #2224 from natcl/patch-4
Update jsonata to 1.6.5 which should fix #2183
2019-07-05 09:29:13 +01:00
Nathanaël Lécaudé
c2167a2c5f Add jsonata bump in util 2019-07-04 18:08:44 -04:00
Nathanaël Lécaudé
1a695e0451 Update jsonata to 1.6.5 which should fix #2183 2019-07-04 17:50:55 -04:00
Kunihiko Toumura
8847f325ed Merge remote-tracking branch 'upstream/dev' into dev-redo 2019-07-04 08:31:45 +01:00
Kunihiko Toumura
94c9da468e fix initialization bug 2019-07-04 08:26:39 +01:00
Nick O'Leary
24b38407e4 Merge branch 'master' into dev 2019-07-01 12:43:16 +01:00
Nick O'Leary
f49d1ae860 Ensure the subflow stop promise is waiting for before restarting 2019-07-01 12:42:11 +01:00
Nick O'Leary
8b3b541a56 Improve typedInput label width calculation
If the label contains an img, the width calculation needs
to wait for the img to be loaded. This fix is a bit hacky
as it doesn't actually tie into the onload event, but should
be good enough
2019-07-01 11:17:36 +01:00
Nick O'Leary
a974e84ad1 Merge pull request #2222 from node-red/no-empty-examples
Ignore empty examples directories (don't add to import menu)
2019-06-29 21:32:07 +01:00
Dave Conway-Jones
c4f4115bcb better handle example file at any depth 2019-06-29 01:16:02 +01:00
Nick O'Leary
3c5adbee31 Merge pull request #2220 from natcl/patch-3
Add default shortcut (ctrl-d) for deploy
2019-06-28 23:35:28 +01:00
Nick O'Leary
55645e3730 Properly escape node types in palette
We were only escaping the first instance of any invalid dom char
and not all of the
2019-06-28 22:39:27 +01:00
Dave Conway-Jones
d918bb568c Ignore empty examples directories (don't add to import menu) 2019-06-23 12:09:43 +01:00
Kunihiko Toumura
b1bff62bf7 Merge remote-tracking branch 'upstream/dev' into dev-redo 2019-06-23 16:19:15 +09:00
Nick O'Leary
d11d389ae4 Smarter filtering in action list dialog 2019-06-22 20:37:54 +01:00
Nick O'Leary
a73c159160 Ensure an item in action list is always selected 2019-06-22 20:25:57 +01:00
Kunihiko Toumura
7adf102d8d Initial implementation of redo (un-undo) 2019-06-22 16:05:50 +09:00
Nathanaël Lécaudé
e4d3ff623a change shortcut for ctrl-d 2019-06-21 19:04:25 -04:00
Nathanaël Lécaudé
2433d59f00 Add default shortcut (ctrl-s) for deploy
This adds a shortcut for deploy (ctrl-s).
2019-06-21 17:40:24 -04:00
Nick O'Leary
8c68e76c3e Merge pull request #2217 from node-red/svg-icons
Update all node icons and editor images to SVG
2019-06-21 22:08:34 +01:00
Nick O'Leary
0b204de5a9 Fix up tests for svg changes 2019-06-21 22:01:24 +01:00
Nick O'Leary
93c811ab70 Update typedInput icons to svg
Map any request for one of our pngs to its svg replacement
2019-06-21 21:45:14 +01:00
Nick O'Leary
3ff861099a Move deploy icons to svg 2019-06-21 16:08:43 +01:00
Nick O'Leary
f22762539f Handle png/svg fallback for def.icon values. Remove old pngs 2019-06-21 15:41:17 +01:00
Nick O'Leary
677442a3c0 Merge branch 'master' into dev 2019-06-21 14:01:34 +01:00
Nick O'Leary
b73f12cdba Bump for 0.20.6 2019-06-21 13:25:39 +01:00
Nick O'Leary
28fbb61e81 Bump dependencies 2019-06-21 13:25:09 +01:00
Nick O'Leary
c1104d1cd6 Revealing node position needs to account for zoom level
Fixes #2172
2019-06-21 12:53:09 +01:00
Dave Conway-Jones
e346702292 stop join tripping up if last message of buffer is blank. 2019-06-21 12:49:21 +01:00
Nick O'Leary
90887779ea Improve handling of file upload in request node
formData can only be Strings or Buffers - anything else will cause
errors. To help matters, we now look for invalid types and json-encode
them where needed.
2019-06-21 12:48:13 +01:00
Nick O'Leary
a941b1437c Handle subflow internal node wired to a non-existant node
Fixes #2202
2019-06-21 12:47:37 +01:00
Nick O'Leary
04bdcbd490 Do not save subflow env vars with blank names 2019-06-21 12:46:53 +01:00
Nick O'Leary
87a815fd6f Don't allow a link node virtual wire to connect to normal port 2019-06-21 12:45:50 +01:00
Nick O'Leary
d623848c87 Update all node icons to SVG
When listing icons provided by a module, if there is a png and svg
with the same name, only the svg will be listed.

If a node asks for a png icon which is not known, but there is a
corresponding svg, that will be used instead.
2019-06-21 12:36:20 +01:00
Nick O'Leary
46abd0cc42 Clear HTTP Request node authType when auth disabled
Fixes #2215
2019-06-20 22:33:38 +01:00
Nick O'Leary
e315325d91 Fix parsing of content-type header
Fixes #2216

This was broken when we switched from media-typer to content-type
modules for parsing the content-type header.

The content-type header can handle the field with parameters, but
does not do the type/sub-type parsing that media-typer does.

Our code relied on that extra bit of parsing to correctly
identify if the content should be parsed to String or kept as
a buffer.

The fix restores the use of media-typer, but using the result
of the content-type module to make sure it valid
2019-06-20 21:15:20 +01:00
Dave Conway-Jones
f3fc083330 Fix join node reset issue with merging objects
and add tests
to close #2188
2019-06-20 19:47:53 +01:00
Dave Conway-Jones
92cb57eb7b Fix join node reset issue with merging objects
and add tests
to close #2188
2019-06-20 18:14:46 +01:00
Nick O'Leary
d645fbff2f Merge branch 'master' into dev 2019-06-19 10:11:51 +01:00
Nick O'Leary
8486f4d43a Copy data-i18n attribute on TypedInput
Fixes #2211
2019-06-19 10:10:17 +01:00
Nick O'Leary
60b1a05894 Fix styling of Debug pop-out window 2019-06-18 11:40:13 +01:00
Nick O'Leary
f955d63707 Merge branch 'disable-node' into dev 2019-06-18 11:33:20 +01:00
Nick O'Leary
f106019938 Add runtime test for disabled nodes 2019-06-18 11:02:31 +01:00
Nick O'Leary
2473249c8b Allow config nodes to be disabled, tidy css and add actions 2019-06-17 22:46:34 +01:00
Nick O'Leary
d13dc4fba3 Don't allow a link node virtual wire to connect to normal port 2019-06-17 15:37:45 +01:00
Nick O'Leary
41a0af032c Enable individual flow nodes to be disabled 2019-06-14 22:12:47 +01:00
Nick O'Leary
70cf7b0c5a Do not save subflow env vars with blank names 2019-06-14 11:18:07 +01:00
Nick O'Leary
14f6788ab9 Set autocomplete to disabled in form input elements 2019-06-14 11:17:49 +01:00
Nick O'Leary
bb67049d90 Ensure focus returns to the right element after dialogs shown 2019-06-14 10:57:12 +01:00
Nick O'Leary
ae2162beaf Handle subflow internal node wired to a non-existant node
Fixes #2202
2019-06-13 14:23:46 +01:00
Nick O'Leary
19f2c5e07f Merge branch 'master' into dev 2019-06-13 09:37:36 +01:00
Nick O'Leary
8abc5b3889 Add actions to change deploy type 2019-06-12 10:06:58 +01:00
Nick O'Leary
4d37c28bc7 Merge pull request #2197 from node-red/commandPrompt
Add Command prompt dialog
2019-06-11 22:47:30 +01:00
Nick O'Leary
cc0933eee4 Rename commandPrompt to actionList 2019-06-11 22:43:28 +01:00
Nick O'Leary
2de9a804a0 Tidy up nls of command prompt and selection handling 2019-06-11 22:43:28 +01:00
Nick O'Leary
ffeb2e91f4 Add command prompt dialog 2019-06-11 22:43:28 +01:00
Nick O'Leary
8cf5ec9e5a Update UI tests for new editor css 2019-06-11 17:12:31 +01:00
Nick O'Leary
ea0526f29a Add insertItemAt doc to editableList 2019-06-11 17:12:31 +01:00
Nick O'Leary
cfcb3a69e5 Merge pull request #2198 from node-red-hitachi/allow-env-in-switch-node
Allow environment variable as target of switch node
2019-06-11 15:13:46 +01:00
Nick O'Leary
e3e0378857 Add visual json editor 2019-06-11 14:44:44 +01:00
Nick O'Leary
ccc3809daa Make 'anything else' template more explicit 2019-06-09 17:32:14 +01:00
Nick O'Leary
c97786e12c Improve handling of file upload in request node
formData can only be Strings or Buffers - anything else will cause
errors. To help matters, we now look for invalid types and json-encode
them where needed.
2019-06-08 20:42:14 +01:00
Nick O'Leary
400071879f Add enable/disable-flow actions 2019-06-07 15:14:21 +01:00
Nick O'Leary
4cd6e20c91 Fix undo of flow disable state change 2019-06-07 15:13:49 +01:00
Nick O'Leary
460e3ad395 Fix select-all action in main view 2019-06-07 14:35:22 +01:00
Nick O'Leary
6f08bd6fc5 Fix delete-all action on config node sidebar 2019-06-07 14:35:10 +01:00
Nick O'Leary
eed3a749db Fix undefined error on typedInput due to valueLabel used before being added 2019-06-07 14:34:35 +01:00
Hiroyasu Nishiyama
6587d12fbd update info text 2019-06-07 21:39:12 +09:00
Hiroyasu Nishiyama
f8dd68ecc4 Add support for env var propety in switch node 2019-06-07 21:35:36 +09:00
Nick O'Leary
f0aef2b853 Add show-library dialog actions 2019-06-07 11:35:04 +01:00
Nick O'Leary
7d27df1b97 Add shift-cursor handling for moving quick-add dialog 2019-06-06 17:17:44 +01:00
Nick O'Leary
457ec86c25 Do not allow tab focus on clipboard hidden element 2019-06-06 17:17:05 +01:00
Nick O'Leary
a24c66958f Fix display of node help when clicking in palette
Fixes #2194
2019-06-06 14:38:21 +01:00
Nick O'Leary
617628b886 Ensure node help is loaded in the right language
Fixes #2195
2019-06-06 14:16:19 +01:00
Nick O'Leary
6b7e623d33 Remove some hardcoded css colors 2019-06-06 11:34:20 +01:00
Nick O'Leary
5ca85b7e83 Merge branch 'pr_2187' into dev 2019-06-04 22:58:18 +01:00
Nick O'Leary
5965bf3332 Merge pull request #2190 from node-red-hitachi/fix-typedinput-appearance
Fix typedinput width calculation
2019-06-04 20:56:30 +01:00
Nick O'Leary
baf2dd293b Merge pull request #2189 from bonanitech/patch-1
Update build-custom-theme.js
2019-06-04 16:50:36 +01:00
Dave Conway-Jones
2cc19e7e32 stop join tripping up if last message of buffer is blank. 2019-06-01 23:49:27 +01:00
Dave Conway-Jones
53ab6f8569 Add popovers to context sidebar mini buttons 2019-06-01 13:21:21 +01:00
Hiroyasu Nishiyama
cf8faac7ef fix width calculation of typedInput 2019-05-31 22:20:54 +09:00
Mauricio Bonani
86947a384d Update build-custom-theme.js 2019-05-31 08:33:22 -04:00
Dave Conway-Jones
22855279bd ensure input box has focus on repeated quick add 2019-05-30 14:33:11 +01:00
Paul Williams
e56fdecdc6 Add new shortcut to clear debug message list
Clearing the debug message list is globally scoped by default to
`ctrl+alt+l`. Mnemonic: similar to clearing a terminal shell using
ctrl+l.
2019-05-30 09:36:44 +00:00
Dave Conway-Jones
dc75a5812f Handle webscoket item being parseable but not an object better
and add test
2019-05-29 12:49:35 +01:00
Dave Conway-Jones
33e20c9969 Only add copypath popover if button exists. 2019-05-28 21:43:21 +01:00
Nick O'Leary
109204897f Fix clipboard export download button 2019-05-28 16:10:21 +01:00
Nick O'Leary
3b3a2d62f8 Merge pull request #2175 from node-red-hitachi/update-language-selector
update editor language selection UI for i18n
2019-05-28 13:26:38 +01:00
Nick O'Leary
b1b4b3fb63 Ensure tooltip popover doesn't replace normal popover 2019-05-28 13:25:03 +01:00
Nick O'Leary
d583c68de5 Fix error handling in Websocket broadcast function
Fixes #2182
2019-05-28 11:51:34 +01:00
Nick O'Leary
d360f30af6 Ensure library list has an item selected when opened 2019-05-28 11:23:03 +01:00
Nick O'Leary
ed033565a4 Handle empty list of example flows
Fixes #2171
2019-05-28 11:21:53 +01:00
Nick O'Leary
2d6acfae1b Restore tray component css for compatibility. Mark as deprecated 2019-05-28 09:50:29 +01:00
Hiroyasu Nishiyama
10da894124 fix function name & string compare function 2019-05-28 08:55:00 +09:00
Nick O'Leary
6dda8f21e4 Merge pull request #2176 from node-red-hitachi/update-editor-message-jp
Update Japanese message catalogue for editor
2019-05-27 22:18:18 +01:00
Nick O'Leary
1a9d759002 Merge pull request #2177 from node-red-hitachi/i18n-library-ui
Update I18n support for library ui
2019-05-27 22:18:00 +01:00
Nick O'Leary
df24e13eb5 Merge pull request #2178 from node-red-hitachi/update-nodes-message-jp
update Japanese message for nodes
2019-05-27 22:17:19 +01:00
Nick O'Leary
2ab19937af Fix pinned debug item css 2019-05-27 21:23:41 +01:00
Nick O'Leary
390b86cd8e Revert treeList children function signature change 2019-05-27 21:11:50 +01:00
Nick O'Leary
423aba5bab Ensure ndoe status icon is shown when value set 2019-05-27 21:07:27 +01:00
Dave Conway-Jones
dc0b9231cd Add popover tooltips to debug sidebar,function and template
path, value, pin buttons in debug
expand buttons in function and template.
2019-05-27 15:48:06 +01:00
Hiroyasu Nishiyama
3b177bedf8 update Japanese message for nodes 2019-05-27 14:25:03 +09:00
Hiroyasu Nishiyama
12ce719213 make new library folder interface i18n ready 2019-05-27 13:34:47 +09:00
Hiroyasu Nishiyama
320433b1bf update Japanese message catalogue 2019-05-27 13:13:25 +09:00
Hiroyasu Nishiyama
7f35e2280e update editor language selection UI for i18n 2019-05-27 11:28:36 +09:00
Nick O'Leary
c514d988df Revealing node position needs to account for zoom level
Fixes #2172
2019-05-25 22:11:05 +01:00
Nick O'Leary
749a080397 Fix typedInput option selection
Fixes #2174
2019-05-25 21:19:31 +01:00
Nick O'Leary
b105a12505 Fix palette node id handling so search works
Fixes #2173
2019-05-24 22:13:21 +01:00
Dave Conway-Jones
85a438a40f remove pi, twitter, email and feedparser from packages
remove tests from core
2019-05-17 14:14:17 +01:00
Dave Conway-Jones
877260a243 Remove pi gpi, twitter, email and feedparser nodes from core 2019-05-17 14:08:51 +01:00
512 changed files with 9277 additions and 5248 deletions

View File

@@ -28,7 +28,7 @@ To help us understand the issue, please fill-in as much of the following informa
### Please tell us about your environment:
- [ ] Node-RED version:
- [ ] node.js version:
- [ ] Node.js version:
- [ ] npm version:
- [ ] Platform/OS:
- [ ] Browser:

View File

@@ -33,7 +33,7 @@ To help us understand the issue, please fill-in as much of the following informa
### Please tell us about your environment:
- [ ] Node-RED version:
- [ ] node.js version:
- [ ] Node.js version:
- [ ] npm version:
- [ ] Platform/OS:
- [ ] Browser:

View File

@@ -7,8 +7,11 @@ assignees: ''
---
Please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack).
Please DO NOT raise an issue.
You could also consider asking a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/node-red) and tag it `node-red`.
We DO NOT use the issue tracker for general support or feature requests. Only bug reports should be raised here using the 'Bug report' template.
For general support, please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack). You could also consider asking a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/node-red) and tag it `node-red`.
That way the whole Node-RED user community can help, rather than rely on the core development team.
For feature requests, please use the Node-RED Forum](https://discourse.nodered.org). Many ideas have already been discussed there and you should search that for your request before starting a new discussion.

View File

@@ -9,5 +9,3 @@ matrix:
before_script:
- npm install -g istanbul coveralls
- node_js: "8"
allow_failures:
- node_js: "12"

View File

@@ -1,3 +1,223 @@
#### 1.0.3: Maintenance Release
Runtime
- Increase timeouts in Subflow tests to minimise false positives
- Update grunt-sass and add node-sass for node12 support
- Fix timings of Delay node tests
- #2340 Update JSONata to 1.7.0
- Bump https-proxy-agent version
- #2332 Fix error handling of nodes with multiple input handlers
- Add script to generate npm publish script
- #2371 Ensure folder is present before write (e.g. flows file not in user folder)
- #2371 Handle windows UNC '\\' paths
- #2366 Handle logging of non-JSON encodable objects
Editor
- #2328 Fix language handling in subflow node
- Use default language if lng param not set in i18n req
- #2326 Fix palette editor search visualization
- #2375 Subflow status not showing i18n version of contained core nodes status
- Fix inverse of 'replace' editor event
- #2376 Fallback to base language files if present
- #2373 Support UI testing on the latest Google Chrome
- #2364 Add tooltip to expand button in markdown editor
- #2363 Support ctrl key to select tabs for Windows
- #2356 Make JSONata help initially shown in expression editor
- #2355 Prohibit line break in type menu of typedInput
Nodes
- Delay: Fix delay to not pass through .reset and .flush props consistently
- #2352 File: Using the a msg per line the last line does not get msg.topic passed
- #2339 HTTP Request: Check auth type on opening
- HTTP Request: add units info
- #2372 MQTT/WS: Improved proxy support for MQTT and WebSocket nodes
- #2370 MQTT: Add clarification that MQTT Out requires payload to send msg
#### 1.0.2: Maintenance Release
Runtime
- Allow node.status() to be passed number/bool types
- Allow node emitted events to have multiple arguments
- #2323 Fixed docstrings to have them match the function signature (name of parameters).
- #2318 NLS: Unify translations of "boolean"
Editor
- Ensure node status is refreshed whenever node is edited
- #2315 #2316 Ensure z property included in full message debug payload
- #2321 Fixed editor.json (JA nls)
- #2313 Fix element to collapse items in visual JSON editor
- #2314 Insert divider in menu by calling RED.menu.addItem('id', null);
Nodes
- Change: Fixup use of node.done
- #2322 Template: Fix invalid JSON data in template node docs
- #2320 File: Fixed a typo in 10-file.html (JA nls)
- #2312 Template: Remove unnecessary comma in help text
- #2319 Inject: Interval of inject node should be 596 hours or less.
#### 1.0.1: Maintenance Release
Runtime
- #2301 Add env vars to enable safe mode and projects
- `NODE_RED_ENABLE_SAFE_MODE`
- `NODE_RED_ENABLE_PROJECTS`
Editor
- #2308 Fix grid setting
- #2306 i18n support in tooltips
- Fix error when setting typedInput to boolean true/false
- #2299 Fix SVG icons in IE11
- #2303 Fix issue where subflow color did not update when not on a flow
Nodes
- #2297 TLS: Allow TLS config node to provide just CA cert
- #2307 Inject: Fix width on inject node property
- #2305 Switch: Let switch node between rule work both ways round
- Range: Add example to range node info and make use of target consistent
- Join: node must clone group message before sending
#### 1.0.0: Milestone Release
Editor
- Add click-on-tooltip to close
- Fix node draggable handling
- Ensure complete node scope property is remapped on import
- Update i18n for project feature
- Fix menu hiding function for flow editor
- Normalise default subflow color references
- Hide header text of very small screens to deploy is visible
- Fix tab access on touch screens
- Update radialMenu to use standard theme colours
- Fix undefined reference loading on mobile
- Allow word breaking of node name with long word
- Enable wrap mode in Markdown editor
- Maximize the size of markdown editor
Nodes
- remove legacy error option from file in mode
- Change MQTT node default 3.1 compatibility mode to false
- Show clear debug shortcut in tooltip
- Fix file-in port labels for all 4 options
- Add extra comment re Mustache escapes to Template info
- Fix typo in complete node
- Allow Function node output input to go to 0
#### 1.0.0-beta.4: Beta Release
Runtime
- Clone the first message passed to node.send in Function node
Editor
- Move flow-status button to footer for consistency
- Fix node hover effect to prevent jumping position
- Filter quick-add properly when splicing a wire
- Mark workspace dirty when deleting link node link Fixes #2274
- Add red-ui-button class to strategy login button
- Fix padding of subflow locale select Closes #2276
- Update info text of complete node & add JP text
- Add class red-ui-button to cancel button
- Add css class to login submit button (#2275)
- Realign subflow output port labels
- Move context sidebar auto-refresh option to individual sections
- Update Japanese message catalogue
- Fix subflow UI for select
- remove padding before label text for SUBFLOW UI row
- Allow SUBFLOW UI label row without variable name
Nodes
- Remove old rc option from exec node for 1.0
- Add python and SQL to template language options
- Fix Switch node display of jsonata_exp type
- Remove sentiment from core nodes
#### 1.0.0-beta.3: Beta Release
Runtime
- [FEATURE] Add Node Done API - make message passing async
- Ensure the subflow stop promise is waiting for before restarting
- Limit the regex for the /nodes/ api end points
- Add error event handler to ssh-keygen child_process Fixes #2255
- Fix default value handling on context array access Fixes #2252
- Remove all ui test dependencies from package.json
- Add req back to audit log events and extend to Projects api
- Ensure 2nd arg to node.error is an object Fixes #2228
- Use a more atomic process for writing context files Fixes #2271
Editor
- [FEATURE] Change core node categories
- [FEATURE] Subflow Instance property UI (#2236)
- [FEATURE] Add visual JSON editor
- [FEATURE] Add Action List dialog
- [FEATURE] Add new shortcut to clear debug message list - ctrl-alt-l
- [FEATURE] Add show-library dialog actions
- [FEATURE] Add shift-cursor handling for moving quick-add dialog
- [FEATURE] Add enable/disable-flow actions
- [FEATURE] Add actions to change deploy type
- [FEATURE] Allow config nodes to be disabled, tidy css and add actions
- [FEATURE] Add default shortcut (ctrl-d) for deploy
- [FEATURE] Initial implementation of redo (un-undo) - ctrl-y
- [FEATURE] add support for specifying subflow template color
- [FEATURE] Use ctrl-click on wire to splice node in place
- [FEATURE] Allow search results to show more than 25 results
- [FEATURE] Allow a node to change if it has an input port Closes #2268
- Revealing node position needs to account for zoom level Fixes #2172
- Fix typedInput option selection Fixes #2174
- Fix palette node id handling so search works Fixes #2173
- Add popover tooltips to debug sidebar,function and template
- Add popovers to context sidebar mini buttons
- Ensure node status icon is shown when value set
- Revert treeList children function signature change
- Restore tray component css for compatibility. Mark as deprecated
- fix function name & string compare function
- Handle empty list of example flows Fixes #2171
- Ensure library list has an item selected when opened
- Ensure tooltip popover doesn't replace normal popover
- Fix clipboard export download button
- Ensure input box has focus on repeated quick add
- Fix width calculation of typedInput
- Remove some hardcoded css colors
- Fix display of node help when clicking in palette Fixes #2194
- Ensure node help is loaded in the right language Fixes #2195
- Do not allow tab focus on clipboard hidden element
- Fix undefined error on typedInput due to valueLabel used before being added
- Fix undo of flow disable state change
- Fix select-all action in main view
- Fix delete-all action on config node sidebar
- Update UI tests for new editor css
- Add insertItemAt doc to editableList
- Ensure focus returns to the right element after dialogs shown
- Set autocomplete to disabled in form input elements
- Update all node icons to SVG
- Handle png/svg fallback for def.icon values. Remove old pngs
- Ignore empty examples directories (don't add to import menu)
- better handle example file at any depth - #2222
- Properly escape node types in palette
- Ensure session expiry timeout doesn't exceed limit
- Use node/tab map to make filterNodes more efficient
- Rearrange contents of subflow template settings tab
- Handle undefined node.\_def in edit stack title.
- fix converting selection to subflow
- Fix inserting new subflow node to existing wire between nodes
- Support displaying falsey node status values Fixes #2246
- Remove tab menu from node property UI for subflow and config nodes
- Mark workspace dirty when shift-click-drag detaches wires Fixes #2260
- Fix subflow category change on palette
Nodes
- Remove pi gpi, twitter, email and feedparser nodes from core
- Fix error handling in Websocket broadcast function Fixes #2182
- Handle websocket item being parseable but not an object better
- stop join tripping up if last message of buffer is blank.
- Add support for env var propety in switch node
- Improve handling of file upload in request node
- Add "has key" rule to switch node + tests
- Optimise generation of switch node edit dialog
- Add keep-alive option to HTTP Request - #2261
#### 1.0.0-beta.2: Beta Release
Runtime
@@ -46,8 +266,29 @@ Nodes
- Add expand editor button to Template node
- Update catch/status nodes to use selectNodes api and treeList
#### 0.20.8: Maintenance Release
- Sanitize tab name in edit dialog
- Pass httpServer to runtime even when httpAdmin disabled Fixes #2272
#### 0.20.7: Maintenance Release
- Update jsonata to 1.6.5 which should fix #2183
- Ensure the subflow stop promise is waiting for before restarting
- Properly escape node types in palette
#### 0.20.6: Maintenance Release
- Revealing node position needs to account for zoom level Fixes #2172
- stop join tripping up if last message of buffer is blank.
- Improve handling of file upload in request node
- Handle subflow internal node wired to a non-existant node Fixes #2202
- Do not save subflow env vars with blank names
- Don't allow a link node virtual wire to connect to normal port
- Clear HTTP Request node authType when auth disabled Fixes #2215
- Fix parsing of content-type header Fixes #2216
- Fix join node reset issue with merging objects
- Copy data-i18n attribute on TypedInput Fixes #2211
#### 0.20.5: Maintenance Release
@@ -709,7 +950,7 @@ Nodes
- Initial support of sequence rules for SWITCH node (#1545)
- initial support of SORT node (#1500)
- Inject node - let once delay be editable (#1541)
- Introduce `nodeMaxMessageBufferLength` setting for msg sequence nodes
- Introduce `nodeMessageBufferMaxLength` setting for msg sequence nodes
- Let CSV correct parts if we remove header row.
- let default apply if msg.delay not set in override mode. (#1397)
- let trigger node be reset by boolean message (#1554)

View File

@@ -26,7 +26,7 @@ relevant nodes, press Ctrl-E and copy the flow data from the Export dialog.
At a minimum, please include:
- Version of Node-RED - either release number if you downloaded a zip, or the first few lines of `git log` if you are cloning the repository directly.
- Version of node.js - what does `node -v` say?
- Version of Node.js - what does `node -v` say?
## Feature requests

View File

@@ -16,6 +16,7 @@
var path = require("path");
var fs = require("fs-extra");
var sass = require("node-sass");
module.exports = function(grunt) {
@@ -27,7 +28,7 @@ module.exports = function(grunt) {
var nonHeadless = grunt.option('non-headless');
if (nonHeadless) {
process.env.NODE_RED_NON_HEADLESS = 'true';
process.env.NODE_RED_NON_HEADLESS = true;
}
grunt.initConfig({
pkg: grunt.file.readJSON('package.json'),
@@ -79,20 +80,20 @@ module.exports = function(grunt) {
//"loopfunc": true, // allow functions to be defined in loops
//"sub": true // don't warn that foo['bar'] should be written as foo.bar
},
all: [
'Gruntfile.js',
'red.js',
'packages/**/*.js'
],
core: {
files: {
src: [
'Gruntfile.js',
'red.js',
'packages/**/*.js',
]
}
},
// all: [
// 'Gruntfile.js',
// 'red.js',
// 'packages/**/*.js'
// ],
// core: {
// files: {
// src: [
// 'Gruntfile.js',
// 'red.js',
// 'packages/**/*.js',
// ]
// }
// },
nodes: {
files: {
src: [ 'nodes/core/*/*.js' ]
@@ -100,7 +101,7 @@ module.exports = function(grunt) {
},
editor: {
files: {
src: [ 'editor/js/**/*.js' ]
src: [ 'packages/node_modules/@node-red/editor-client/src/js/**/*.js' ]
}
},
tests: {
@@ -169,6 +170,7 @@ module.exports = function(grunt) {
"packages/node_modules/@node-red/editor-client/src/js/ui/library.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/notifications.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/search.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/actionList.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/typeSearch.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js",
"packages/node_modules/@node-red/editor-client/src/js/ui/userSettings.js",
@@ -219,6 +221,7 @@ module.exports = function(grunt) {
sass: {
build: {
options: {
implementation: sass,
outputStyle: 'compressed'
},
files: [{
@@ -275,7 +278,7 @@ module.exports = function(grunt) {
files: [
'packages/node_modules/@node-red/editor-client/src/js/**/*.js'
],
tasks: ['copy:build','concat','uglify','attachCopyright:js']
tasks: ['copy:build','concat',/*'uglify',*/ 'attachCopyright:js']
},
sass: {
files: [
@@ -495,7 +498,9 @@ module.exports = function(grunt) {
grunt.loadNpmTasks('grunt-chmod');
grunt.loadNpmTasks('grunt-jsonlint');
grunt.loadNpmTasks('grunt-mocha-istanbul');
grunt.loadNpmTasks('grunt-webdriver');
if (fs.existsSync(path.join("node_modules", "grunt-webdriver"))) {
grunt.loadNpmTasks('grunt-webdriver');
}
grunt.loadNpmTasks('grunt-jsdoc');
grunt.loadNpmTasks('grunt-jsdoc-to-markdown');
grunt.loadNpmTasks('grunt-npm-command');
@@ -554,12 +559,25 @@ module.exports = function(grunt) {
});
grunt.registerTask('verifyUiTestDependencies', function() {
if (!fs.existsSync(path.join("node_modules", "chromedriver"))) {
grunt.fail.fatal('You need to run "npm install chromedriver@2" before running UI test.');
if (!fs.existsSync(path.join("node_modules", "grunt-webdriver"))) {
grunt.fail.fatal('You need to install the UI test dependencies first.\nUse the script in "scripts/install-ui-test-dependencies.sh"');
return false;
}
});
grunt.registerTask('generatePublishScript',
'Generates a script to publish build output to npm',
function () {
const done = this.async();
const generatePublishScript = require("./scripts/generate-publish-script.js");
generatePublishScript().then(function(output) {
grunt.log.writeln(output);
const filePath = path.join(grunt.config.get('paths.dist'),"modules","publish.sh");
grunt.file.write(filePath,output);
done();
});
});
grunt.registerTask('setDevEnv',
'Sets NODE_ENV=development so non-minified assets are used',
function () {
@@ -578,9 +596,15 @@ module.exports = function(grunt) {
'Runs code style check on editor code',
['jshint:editor']);
grunt.registerTask('test-ui',
'Builds editor content then runs unit tests on editor ui',
['verifyUiTestDependencies','build','jshint:editor','webdriver:all']);
if (!fs.existsSync(path.join("node_modules", "grunt-webdriver"))) {
grunt.registerTask('test-ui',
'Builds editor content then runs unit tests on editor ui',
['verifyUiTestDependencies']);
} else {
grunt.registerTask('test-ui',
'Builds editor content then runs unit tests on editor ui',
['verifyUiTestDependencies','build','jshint:editor','webdriver:all']);
}
grunt.registerTask('test-nodes',
'Runs unit tests on core nodes',
@@ -596,7 +620,7 @@ module.exports = function(grunt) {
grunt.registerTask('release',
'Create distribution zip file',
['build','verifyPackageDependencies','clean:release','mkdir:release','chmod:release','compress:release','pack-modules']);
['build','verifyPackageDependencies','clean:release','mkdir:release','chmod:release','compress:release','pack-modules','generatePublishScript']);
grunt.registerTask('pack-modules',
'Create module pack files for release',

View File

@@ -5,9 +5,9 @@ http://nodered.org
[![Build Status](https://travis-ci.org/node-red/node-red.svg?branch=master)](https://travis-ci.org/node-red/node-red)
[![Coverage Status](https://coveralls.io/repos/node-red/node-red/badge.svg?branch=master)](https://coveralls.io/r/node-red/node-red?branch=master)
A visual tool for wiring the Internet of Things.
Low-code programming for event-driven applications.
![Node-RED: A visual tool for wiring the Internet of Things](http://nodered.org/images/node-red-screenshot.png)
![Node-RED: Low-code programming for event-driven applications](http://nodered.org/images/node-red-screenshot.png)
## Quick Start
@@ -56,7 +56,7 @@ This project adheres to the [Contributor Covenant 1.4](http://contributor-covena
## Authors
Node-RED is a project of the [JS Foundation](http://js.foundation).
Node-RED is a project of the [OpenJS Foundation](https://openjsf.org).
It was created by [IBM Emerging Technology](https://www.ibm.com/blogs/emerging-technology/).
@@ -67,4 +67,4 @@ It was created by [IBM Emerging Technology](https://www.ibm.com/blogs/emerging-t
## Copyright and license
Copyright JS Foundation and other contributors, http://js.foundation under [the Apache 2.0 license](LICENSE).
Copyright JS Foundation and other contributors, https://openjsf.org under [the Apache 2.0 license](LICENSE).

13
SECURITY.md Normal file
View File

@@ -0,0 +1,13 @@
# Security Policy
## Supported Versions
| Version | Supported |
| ------- | ------------------ |
| 1.0.0 | :white_check_mark: |
| 0.20.x | :white_check_mark: |
## Reporting a Vulnerability
Please report any potential security issues to `team@nodered.org`. This will notify the core project team who will respond accordingly.

View File

@@ -1,7 +1,7 @@
{
"name": "node-red",
"version": "1.0.0-beta.2",
"description": "A visual tool for wiring the Internet of Things",
"version": "1.0.3",
"description": "Low-code programming for event-driven applications",
"homepage": "http://nodered.org",
"license": "Apache-2.0",
"repository": {
@@ -24,7 +24,7 @@
}
],
"dependencies": {
"ajv": "6.10.0",
"ajv": "6.10.2",
"basic-auth": "2.0.1",
"bcryptjs": "2.4.3",
"body-parser": "1.19.0",
@@ -34,85 +34,79 @@
"cookie": "0.4.0",
"cookie-parser": "1.4.4",
"cors": "2.8.5",
"cron": "1.7.1",
"cron": "1.7.2",
"denque": "1.4.1",
"express": "4.17.0",
"express-session": "1.16.1",
"fs-extra": "8.0.1",
"express": "4.17.1",
"express-session": "1.17.0",
"fs-extra": "8.1.0",
"fs.notify": "0.0.4",
"hash-sum": "1.0.2",
"https-proxy-agent": "2.2.1",
"hash-sum": "2.0.0",
"https-proxy-agent": "2.2.4",
"i18next": "15.1.2",
"iconv-lite": "0.4.24",
"iconv-lite": "0.5.0",
"is-utf8": "0.2.1",
"js-yaml": "3.13.1",
"json-stringify-safe": "5.0.1",
"jsonata": "1.6.4",
"jsonata": "1.7.0",
"media-typer": "1.1.0",
"memorystore": "1.6.1",
"mime": "2.4.3",
"mime": "2.4.4",
"mqtt": "2.18.8",
"multer": "1.4.1",
"mustache": "3.0.1",
"node-red-node-email": "^1.4.0",
"node-red-node-feedparser": "^0.1.14",
"node-red-node-rbe": "^0.2.4",
"node-red-node-sentiment": "^0.1.3",
"node-red-node-tail": "^0.0.2",
"node-red-node-twitter": "^1.1.4",
"multer": "1.4.2",
"mustache": "3.0.2",
"node-red-node-rbe": "^0.2.6",
"node-red-node-sentiment": "^0.1.6",
"node-red-node-tail": "^0.1.0",
"nopt": "4.0.1",
"oauth2orize": "1.11.0",
"on-headers": "1.0.2",
"passport": "0.4.0",
"passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2",
"raw-body": "2.4.0",
"raw-body": "2.4.1",
"request": "2.88.0",
"semver": "6.0.0",
"uglify-js": "3.5.15",
"semver": "6.3.0",
"uglify-js": "3.6.9",
"when": "3.7.8",
"ws": "6.2.1",
"xml2js": "0.4.19"
"xml2js": "0.4.22"
},
"optionalDependencies": {
"bcrypt": "3.0.6"
},
"devDependencies": {
"grunt": "~1.0.3",
"grunt": "~1.0.4",
"grunt-chmod": "~1.1.1",
"grunt-cli": "~1.3.2",
"grunt-concurrent": "~2.3.1",
"grunt-contrib-clean": "~1.1.0",
"grunt-contrib-compress": "~1.4.0",
"grunt-contrib-clean": "~2.0.0",
"grunt-contrib-compress": "~1.5.0",
"grunt-contrib-concat": "~1.0.1",
"grunt-contrib-copy": "~1.0.0",
"grunt-contrib-jshint": "~1.1.0",
"grunt-contrib-uglify": "~3.4.0",
"grunt-contrib-jshint": "~2.1.0",
"grunt-contrib-uglify": "~4.0.1",
"grunt-contrib-watch": "~1.1.0",
"grunt-jsdoc": "^2.2.1",
"grunt-jsdoc-to-markdown": "^4.0.0",
"grunt-jsonlint": "~1.1.0",
"grunt-jsonlint": "~2.0.0",
"grunt-mkdir": "~1.0.0",
"grunt-mocha-istanbul": "5.0.2",
"grunt-nodemon": "~0.4.2",
"grunt-npm-command": "~0.1.2",
"grunt-sass": "~2.0.0",
"grunt-sass": "~3.1.0",
"grunt-simple-mocha": "~0.4.1",
"grunt-webdriver": "^2.0.3",
"http-proxy": "^1.16.2",
"http-proxy": "1.18.0",
"istanbul": "0.4.5",
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
"minami": "1.2.3",
"mocha": "^5.2.0",
"mosca": "^2.8.3",
"node-red-node-test-helper": "^0.2.3",
"node-sass": "^4.13.0",
"should": "^8.4.0",
"sinon": "1.17.7",
"stoppable": "^1.1.0",
"supertest": "3.4.2",
"wdio-chromedriver-service": "^0.1.5",
"wdio-mocha-framework": "^0.6.4",
"wdio-spec-reporter": "^0.1.5",
"webdriverio": "^4.14.1",
"node-red-node-test-helper": "^0.2.2",
"jsdoc-nr-template": "node-red/jsdoc-nr-template"
"supertest": "3.4.2"
},
"engines": {
"node": ">=8"

View File

@@ -30,7 +30,8 @@ module.exports = {
scope: req.params.scope,
id: req.params.id,
key: req.params[0],
store: req.query['store']
store: req.query['store'],
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.context.getValue(opts).then(function(result) {
res.json(result);
@@ -45,7 +46,8 @@ module.exports = {
scope: req.params.scope,
id: req.params.id,
key: req.params[0],
store: req.query['store']
store: req.query['store'],
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.context.delete(opts).then(function(result) {
res.status(204).end();

View File

@@ -24,7 +24,8 @@ module.exports = {
get: function(req,res) {
var opts = {
user: req.user,
id: req.params.id
id: req.params.id,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.flows.getFlow(opts).then(function(result) {
return res.json(result);
@@ -35,7 +36,8 @@ module.exports = {
post: function(req,res) {
var opts = {
user: req.user,
flow: req.body
flow: req.body,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.flows.addFlow(opts).then(function(id) {
return res.json({id:id});
@@ -47,7 +49,8 @@ module.exports = {
var opts = {
user: req.user,
id: req.params.id,
flow: req.body
flow: req.body,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.flows.updateFlow(opts).then(function(id) {
return res.json({id:id});
@@ -58,7 +61,8 @@ module.exports = {
delete: function(req,res) {
var opts = {
user: req.user,
id: req.params.id
id: req.params.id,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.flows.deleteFlow(opts).then(function() {
res.status(204).end();

View File

@@ -27,7 +27,8 @@ module.exports = {
return res.status(400).json({code:"invalid_api_version", message:"Invalid API Version requested"});
}
var opts = {
user: req.user
user: req.user,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.flows.getFlows(opts).then(function(result) {
if (version === "v1") {
@@ -46,7 +47,8 @@ module.exports = {
}
var opts = {
user: req.user,
deploymentType: req.get("Node-RED-Deployment-Type")||"full"
deploymentType: req.get("Node-RED-Deployment-Type")||"full",
req: apiUtils.getRequestLogObject(req)
}
if (opts.deploymentType !== 'reload') {

View File

@@ -48,13 +48,13 @@ module.exports = {
// Nodes
adminApp.get("/nodes",needsPermission("nodes.read"),nodes.getAll,apiUtil.errorHandler);
adminApp.post("/nodes",needsPermission("nodes.write"),nodes.post,apiUtil.errorHandler);
adminApp.get(/\/nodes\/messages/,needsPermission("nodes.read"),nodes.getModuleCatalogs,apiUtil.errorHandler);
adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+\/[^\/]+)\/messages/,needsPermission("nodes.read"),nodes.getModuleCatalog,apiUtil.errorHandler);
adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.read"),nodes.getModule,apiUtil.errorHandler);
adminApp.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.putModule,apiUtil.errorHandler);
adminApp.delete(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.delete,apiUtil.errorHandler);
adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.read"),nodes.getSet,apiUtil.errorHandler);
adminApp.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.write"),nodes.putSet,apiUtil.errorHandler);
adminApp.get(/^\/nodes\/messages/,needsPermission("nodes.read"),nodes.getModuleCatalogs,apiUtil.errorHandler);
adminApp.get(/^\/nodes\/((@[^\/]+\/)?[^\/]+\/[^\/]+)\/messages/,needsPermission("nodes.read"),nodes.getModuleCatalog,apiUtil.errorHandler);
adminApp.get(/^\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.read"),nodes.getModule,apiUtil.errorHandler);
adminApp.put(/^\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.putModule,apiUtil.errorHandler);
adminApp.delete(/^\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.delete,apiUtil.errorHandler);
adminApp.get(/^\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.read"),nodes.getSet,apiUtil.errorHandler);
adminApp.put(/^\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.write"),nodes.putSet,apiUtil.errorHandler);
// Context
adminApp.get("/context/:scope(global)",needsPermission("context.read"),context.get,apiUtil.errorHandler);

View File

@@ -24,7 +24,8 @@ module.exports = {
},
getAll: function(req,res) {
var opts = {
user: req.user
user: req.user,
req: apiUtils.getRequestLogObject(req)
}
if (req.get("accept") == "application/json") {
runtimeAPI.nodes.getNodeList(opts).then(function(list) {
@@ -42,7 +43,8 @@ module.exports = {
var opts = {
user: req.user,
module: req.body.module,
version: req.body.version
version: req.body.version,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.nodes.addModule(opts).then(function(info) {
res.json(info);
@@ -54,7 +56,8 @@ module.exports = {
delete: function(req,res) {
var opts = {
user: req.user,
module: req.params[0]
module: req.params[0],
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.nodes.removeModule(opts).then(function() {
res.status(204).end();
@@ -66,7 +69,8 @@ module.exports = {
getSet: function(req,res) {
var opts = {
user: req.user,
id: req.params[0] + "/" + req.params[2]
id: req.params[0] + "/" + req.params[2],
req: apiUtils.getRequestLogObject(req)
}
if (req.get("accept") === "application/json") {
runtimeAPI.nodes.getNodeInfo(opts).then(function(result) {
@@ -87,7 +91,8 @@ module.exports = {
getModule: function(req,res) {
var opts = {
user: req.user,
module: req.params[0]
module: req.params[0],
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.nodes.getModuleInfo(opts).then(function(result) {
res.send(result);
@@ -106,7 +111,8 @@ module.exports = {
var opts = {
user: req.user,
id: req.params[0] + "/" + req.params[2],
enabled: body.enabled
enabled: body.enabled,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.nodes.setNodeSetState(opts).then(function(result) {
res.send(result);
@@ -125,7 +131,8 @@ module.exports = {
var opts = {
user: req.user,
module: req.params[0],
enabled: body.enabled
enabled: body.enabled,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.nodes.setModuleState(opts).then(function(result) {
res.send(result);
@@ -139,7 +146,8 @@ module.exports = {
var opts = {
user: req.user,
module: req.params[0],
lang: req.query.lng
lang: req.query.lng,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.nodes.getModuleCatalog(opts).then(function(result) {
res.json(result);
@@ -152,7 +160,8 @@ module.exports = {
getModuleCatalogs: function(req,res) {
var opts = {
user: req.user,
lang: req.query.lng
lang: req.query.lng,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.nodes.getModuleCatalogs(opts).then(function(result) {
res.json(result);
@@ -164,7 +173,8 @@ module.exports = {
getIcons: function(req,res) {
var opts = {
user: req.user
user: req.user,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.nodes.getIconList(opts).then(function(list) {
res.json(list);

View File

@@ -56,7 +56,7 @@ function expireSessions() {
}
if (nextExpiry < Number.MAX_SAFE_INTEGER) {
// Allow 5 seconds grace
expiryTimeout = setTimeout(expireSessions,(nextExpiry - Date.now()) + 5000)
expiryTimeout = setTimeout(expireSessions,Math.min(2147483647,(nextExpiry - Date.now()) + 5000))
}
if (modified) {
return storage.saveSessions(sessions);
@@ -129,7 +129,7 @@ module.exports = {
sessions[accessToken] = session;
if (!expiryTimeout) {
expiryTimeout = setTimeout(expireSessions,(accessTokenExpiresAt - Date.now()) + 5000)
expiryTimeout = setTimeout(expireSessions,Math.min(2147483647,(accessTokenExpiresAt - Date.now()) + 5000))
}
return storage.saveSessions(sessions).then(function() {

View File

@@ -88,13 +88,13 @@ module.exports = {
// Locales
var locales = require("./locales");
locales.init(runtimeAPI);
editorApp.get(/locales\/(.+)\/?$/,locales.get,apiUtil.errorHandler);
editorApp.get(/^\/locales\/(.+)\/?$/,locales.get,apiUtil.errorHandler);
// Library
var library = require("./library");
library.init(runtimeAPI);
editorApp.get(/library\/([^\/]+)\/([^\/]+)(?:$|\/(.*))/,needsPermission("library.read"),library.getEntry);
editorApp.post(/library\/([^\/]+)\/([^\/]+)\/(.*)/,needsPermission("library.write"),library.saveEntry);
editorApp.get(/^\/library\/([^\/]+)\/([^\/]+)(?:$|\/(.*))/,needsPermission("library.read"),library.getEntry);
editorApp.post(/^\/library\/([^\/]+)\/([^\/]+)\/(.*)/,needsPermission("library.write"),library.saveEntry);
// Credentials

View File

@@ -15,7 +15,7 @@
**/
var fs = require('fs');
var path = require('path');
//var apiUtil = require('../util');
// var apiUtil = require('../util');
var i18n = require("@node-red/util").i18n; // TODO: separate module
@@ -41,7 +41,7 @@ module.exports = {
var namespace = req.params[0];
var lngs = req.query.lng;
namespace = namespace.replace(/\.json$/,"");
var lang = req.query.lng; //apiUtil.determineLangFromHeaders(req.acceptsLanguages() || []);
var lang = req.query.lng || i18n.defaultLang; //apiUtil.determineLangFromHeaders(req.acceptsLanguages() || []);
var prevLang = i18n.i.language;
// Trigger a load from disk of the language if it is not the default
i18n.i.changeLanguage(lang, function(){

View File

@@ -22,7 +22,8 @@ var needsPermission = require("../auth").needsPermission;
function listProjects(req,res) {
var opts = {
user: req.user
user: req.user,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.listProjects(opts).then(function(result) {
res.json(result);
@@ -33,7 +34,8 @@ function listProjects(req,res) {
function getProject(req,res) {
var opts = {
user: req.user,
id: req.params.id
id: req.params.id,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.getProject(opts).then(function(data) {
if (data) {
@@ -49,7 +51,8 @@ function getProjectStatus(req,res) {
var opts = {
user: req.user,
id: req.params.id,
remote: req.query.remote
remote: req.query.remote,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.getStatus(opts).then(function(data){
if (data) {
@@ -64,7 +67,8 @@ function getProjectStatus(req,res) {
function getProjectRemotes(req,res) {
var opts = {
user: req.user,
id: req.params.id
id: req.params.id,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.getRemotes(opts).then(function(data) {
res.json(data);
@@ -98,7 +102,8 @@ module.exports = {
app.post("/", needsPermission("projects.write"), function(req,res) {
var opts = {
user: req.user,
project: req.body
project: req.body,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.createProject(opts).then(function(result) {
res.json(result);
@@ -112,7 +117,8 @@ module.exports = {
var opts = {
user: req.user,
id: req.params.id,
project: req.body
project: req.body,
req: apiUtils.getRequestLogObject(req)
}
if (req.body.active) {
@@ -150,7 +156,8 @@ module.exports = {
app.delete("/:id", needsPermission("projects.write"), function(req,res) {
var opts = {
user: req.user,
id: req.params.id
id: req.params.id,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.deleteProject(opts).then(function() {
res.status(204).end();
@@ -168,7 +175,8 @@ module.exports = {
app.get("/:id/files", needsPermission("projects.read"), function(req,res) {
var opts = {
user: req.user,
id: req.params.id
id: req.params.id,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.getFiles(opts).then(function(data) {
res.json(data);
@@ -185,7 +193,8 @@ module.exports = {
user: req.user,
id: req.params.id,
path: req.params[0],
tree: req.params.treeish
tree: req.params.treeish,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.getFile(opts).then(function(data) {
res.json({content:data});
@@ -199,7 +208,8 @@ module.exports = {
var opts = {
user: req.user,
id: req.params.id,
path: req.params[0]
path: req.params[0],
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.revertFile(opts).then(function() {
@@ -214,7 +224,8 @@ module.exports = {
var opts = {
user: req.user,
id: req.params.id,
path: req.params[0]
path: req.params[0],
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.stageFile(opts).then(function() {
getProjectStatus(req,res);
@@ -228,7 +239,8 @@ module.exports = {
var opts = {
user: req.user,
id: req.params.id,
path: req.body.files
path: req.body.files,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.stageFile(opts).then(function() {
getProjectStatus(req,res);
@@ -242,7 +254,8 @@ module.exports = {
var opts = {
user: req.user,
id: req.params.id,
message: req.body.message
message: req.body.message,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.commit(opts).then(function() {
getProjectStatus(req,res);
@@ -256,7 +269,8 @@ module.exports = {
var opts = {
user: req.user,
id: req.params.id,
path: req.params[0]
path: req.params[0],
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.unstageFile(opts).then(function() {
getProjectStatus(req,res);
@@ -269,7 +283,8 @@ module.exports = {
app.delete("/:id/stage", needsPermission("projects.write"), function(req, res) {
var opts = {
user: req.user,
id: req.params.id
id: req.params.id,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.unstageFile(opts).then(function() {
getProjectStatus(req,res);
@@ -284,7 +299,8 @@ module.exports = {
user: req.user,
id: req.params.id,
path: req.params[0],
type: req.params.type
type: req.params.type,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.getFileDiff(opts).then(function(data) {
res.json({
@@ -301,7 +317,8 @@ module.exports = {
user: req.user,
id: req.params.id,
limit: req.query.limit || 20,
before: req.query.before
before: req.query.before,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.getCommits(opts).then(function(data) {
res.json(data);
@@ -315,7 +332,8 @@ module.exports = {
var opts = {
user: req.user,
id: req.params.id,
sha: req.params.sha
sha: req.params.sha,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.getCommit(opts).then(function(data) {
res.json({commit:data});
@@ -330,7 +348,8 @@ module.exports = {
user: req.user,
id: req.params.id,
remote: req.params[0],
track: req.query.u
track: req.query.u,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.push(opts).then(function(data) {
res.status(204).end();
@@ -346,7 +365,8 @@ module.exports = {
id: req.params.id,
remote: req.params[0],
track: req.query.setUpstream,
allowUnrelatedHistories: req.query.allowUnrelatedHistories
allowUnrelatedHistories: req.query.allowUnrelatedHistories,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.pull(opts).then(function(data) {
res.status(204).end();
@@ -359,7 +379,8 @@ module.exports = {
app.delete("/:id/merge", needsPermission("projects.write"), function(req, res) {
var opts = {
user: req.user,
id: req.params.id
id: req.params.id,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.abortMerge(opts).then(function() {
res.status(204).end();
@@ -374,7 +395,8 @@ module.exports = {
user: req.user,
id: req.params.id,
path: req.params[0],
resolution: req.body.resolutions
resolution: req.body.resolutions,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.resolveMerge(opts).then(function() {
res.status(204).end();
@@ -388,7 +410,8 @@ module.exports = {
var opts = {
user: req.user,
id: req.params.id,
remote: false
remote: false,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.getBranches(opts).then(function(data) {
res.json(data);
@@ -403,7 +426,8 @@ module.exports = {
user: req.user,
id: req.params.id,
branch: req.params.branchName,
force: !!req.query.force
force: !!req.query.force,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.deleteBranch(opts).then(function(data) {
res.status(204).end();
@@ -417,7 +441,8 @@ module.exports = {
var opts = {
user: req.user,
id: req.params.id,
remote: true
remote: true,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.getBranches(opts).then(function(data) {
res.json(data);
@@ -431,7 +456,8 @@ module.exports = {
var opts = {
user: req.user,
id: req.params.id,
branch: req.params[0]
branch: req.params[0],
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.getBranchStatus(opts).then(function(data) {
res.json(data);
@@ -446,7 +472,8 @@ module.exports = {
user: req.user,
id: req.params.id,
branch: req.body.name,
create: req.body.create
create: req.body.create,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.setBranch(opts).then(function(data) {
res.json(data);
@@ -463,7 +490,8 @@ module.exports = {
var opts = {
user: req.user,
id: req.params.id,
remote: req.body
remote: req.body,
req: apiUtils.getRequestLogObject(req)
}
if (/^https?:\/\/[^/]+@/i.test(req.body.url)) {
res.status(400).json({error:"unexpected_error", message:"Git http url must not include username/password"});
@@ -481,7 +509,8 @@ module.exports = {
var opts = {
user: req.user,
id: req.params.id,
remote: req.params.remoteName
remote: req.params.remoteName,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.removeRemote(opts).then(function(data) {
getProjectRemotes(req,res);
@@ -497,7 +526,8 @@ module.exports = {
var opts = {
user: req.user,
id: req.params.id,
remote: remote
remote: remote,
req: apiUtils.getRequestLogObject(req)
}
runtimeAPI.projects.updateRemote(opts).then(function() {
res.status(204).end();

View File

@@ -28,7 +28,7 @@ var defaultContext = {
},
header: {
title: "Node-RED",
image: "red/images/node-red.png"
image: "red/images/node-red.svg"
},
asset: {
red: (process.env.NODE_ENV == "development")? "red/red.js":"red/red.min.js",

View File

@@ -25,7 +25,7 @@ var theme = require("./theme");
var runtimeAPI;
var editorClientDir = path.dirname(require.resolve("@node-red/editor-client"));
var defaultNodeIcon = path.join(editorClientDir,"public","red","images","icons","arrow-in.png");
var defaultNodeIcon = path.join(editorClientDir,"public","red","images","icons","arrow-in.svg");
var editorTemplatePath = path.join(editorClientDir,"templates","index.mst");
var editorTemplate;

View File

@@ -42,7 +42,7 @@ var editor;
/**
* Initialise the module.
* @param {Object} settings The runtime settings
* @param {HTTPServer} server An instance of HTTP Server
* @param {HTTPServer} _server An instance of HTTP Server
* @param {Storage} storage An instance of Node-RED Storage
* @param {Runtime} runtimeAPI An instance of Node-RED Runtime
* @memberof @node-red/editor-api

View File

@@ -47,5 +47,12 @@ module.exports = {
code: err.code||"unexpected_error",
message: err.message||err.toString()
});
},
getRequestLogObject: function(req) {
return {
user: req.user,
path: req.path,
ip: (req.headers && req.headers['x-forwarded-for']) || (req.connection && req.connection.remoteAddress) || undefined
}
}
}

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/editor-api",
"version": "1.0.0-beta.2",
"version": "1.0.3",
"license": "Apache-2.0",
"main": "./lib/index.js",
"repository": {
@@ -16,17 +16,17 @@
}
],
"dependencies": {
"@node-red/util": "1.0.0-beta.2",
"@node-red/editor-client": "1.0.0-beta.2",
"@node-red/util": "1.0.3",
"@node-red/editor-client": "1.0.3",
"bcryptjs": "2.4.3",
"body-parser": "1.19.0",
"clone": "2.1.2",
"cors": "2.8.5",
"express-session": "1.16.1",
"express": "4.17.0",
"express-session": "1.17.0",
"express": "4.17.1",
"memorystore": "1.6.1",
"mime": "2.4.3",
"mustache": "3.0.1",
"mime": "2.4.4",
"mustache": "3.0.2",
"oauth2orize": "1.11.0",
"passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2",
@@ -35,6 +35,6 @@
"ws": "6.2.1"
},
"optionalDependencies": {
"bcrypt": "3.0.5"
"bcrypt": "3.0.6"
}
}

View File

@@ -26,8 +26,7 @@
"status" : "Status",
"enabled" : "Aktiviert",
"disabled" : "Inaktiviert",
"info" : "Beschreibung",
"tip" : "Beschreibung akzeptiert Markdown und wird auf der Registerkarte Info angezeigt."
"info" : "Beschreibung"
},
"menu" : {
"label" : {
@@ -237,7 +236,6 @@
"deleteSubflow" : "Subflow löschen",
"info" : "Beschreibung",
"category" : "Kategorie",
"format" : "Markdown-Format",
"errors" : {
"noNodesSelected" : "<strong> Subflow kann nicht erstellt werden </strong>: Es wurden keine Nodes ausgewählt.",
"multipleInputsToSelection" : "<strong> Subflow kann nicht erstellt werden </strong>: Mehrere Eingaben zur Auswahl"
@@ -446,8 +444,8 @@
"none" : "keine",
"subflows" : "Subflows",
"flows" : "Flows",
"filterUnused" : "Nicht verwendet",
"filterAll" : "alle",
"filterUnused" : "Nicht verwendet",
"filtered" : "__count__ verdeckt"
},
"context" : {

View File

@@ -15,6 +15,17 @@
"next": "Next",
"clone": "Clone project",
"cont": "Continue"
},
"type": {
"string": "string",
"number": "number",
"boolean": "boolean",
"array": "array",
"buffer": "buffer",
"object": "object",
"jsonString": "JSON string",
"undefined": "undefined",
"null": "null"
}
},
"workspace": {
@@ -310,10 +321,12 @@
"addNewType": "Add new __type__...",
"nodeProperties": "node properties",
"label": "Label",
"color": "Color",
"portLabels": "Port labels",
"labelInputs": "Inputs",
"labelOutputs": "Outputs",
"settingIcon": "Icon",
"default": "default",
"noDefaultLabel": "none",
"defaultLabel": "use default label",
"searchIcons": "Search icons",
@@ -321,6 +334,40 @@
"description": "Description",
"show": "Show",
"hide": "Hide",
"locale": "Select UI Language",
"icon": "Icon",
"inputType": "Input type",
"inputs" : {
"input": "input",
"select": "select",
"checkbox": "checkbox",
"spinner": "spinner",
"none": "none",
"hidden": "hide property"
},
"types": {
"str": "string",
"num": "number",
"bool": "bool",
"json": "JSON",
"bin": "buffer",
"env": "env variable"
},
"menu": {
"input": "input",
"select": "select",
"checkbox": "checkbox",
"spinner": "spinner",
"hidden": "label only"
},
"select": {
"label": "Label",
"value": "Value"
},
"spinner": {
"min": "Minimum",
"max": "Maximum"
},
"errors": {
"scopeChange": "Changing the scope will make it unavailable to nodes in other flows that use it",
"invalidProperties": "Invalid properties:"
@@ -351,7 +398,8 @@
"pasteNode": "Paste nodes",
"undoChange": "Undo the last change performed",
"searchBox": "Open search box",
"managePalette": "Manage palette"
"managePalette": "Manage palette",
"actionList":"Action list"
},
"library": {
"library": "Library",
@@ -365,6 +413,7 @@
"savedNodes": "Saved nodes",
"savedType": "Saved __type__",
"saveFailed": "Save failed: __message__",
"newFolder": "New folder",
"types": {
"local": "Local",
"examples": "Examples"
@@ -377,9 +426,13 @@
"addCategory": "Add new...",
"label": {
"subflows": "subflows",
"network": "network",
"common": "common",
"input": "input",
"output": "output",
"function": "function",
"sequence": "sequence",
"parser": "parser",
"social": "social",
"storage": "storage",
"analysis": "analysis",
@@ -516,8 +569,10 @@
"none": "none",
"subflows": "subflows",
"flows": "flows",
"filterUnused":"unused",
"filterAll":"all",
"filterAll": "all",
"showAllConfigNodes": "Show all config nodes",
"filterUnused": "unused",
"showAllUnusedConfigNodes": "Show all unused config nodes",
"filtered": "__count__ hidden"
},
"context": {
@@ -530,7 +585,9 @@
"flow": "Flow",
"global": "Global",
"deleteConfirm": "Are you sure you want to delete this item?",
"autoRefresh": "Auto-refresh"
"autoRefresh": "Refresh on selection change",
"refrsh": "Refresh",
"delete": "Delete"
},
"palette": {
"name": "Palette management",
@@ -545,6 +602,7 @@
"noSummaryAvailable": "No summary available",
"editDescription": "Edit project description",
"editDependencies": "Edit project dependencies",
"noDescriptionAvailable": "No description available",
"editReadme": "Edit README.md",
"showProjectSettings": "Show project settings",
"projectSettings": {
@@ -736,10 +794,23 @@
},
"jsonEditor": {
"title": "JSON editor",
"format": "format JSON"
"format": "format JSON",
"rawMode": "Edit JSON",
"uiMode": "Visual editor",
"insertAbove": "Insert above",
"insertBelow": "Insert below",
"addItem": "Add item",
"copyPath": "Copy path to item",
"expandItems": "Expand items",
"collapseItems": "Collapse items",
"duplicate": "Duplicate",
"error": {
"invalidJSON": "Invalid JSON: "
}
},
"markdownEditor": {
"title": "Markdown editor",
"expand": "Expand",
"format": "Formatted with markdown",
"heading1": "Heading 1",
"heading2": "Heading 2",
@@ -926,8 +997,17 @@
},
"editor-tab": {
"properties": "Properties",
"envProperties": "Environment Variables",
"description": "Description",
"appearance": "Appearance",
"env": "Environment Variables"
"preview": "UI Preview",
"defaultValue": "Default value"
},
"languages" : {
"de": "German",
"en-US": "English",
"ja": "Japanese",
"ko": "Korean",
"zh-CN": "Chinese(Simplified)"
}
}

View File

@@ -1,7 +1,7 @@
{
"$string": {
"args": "arg",
"desc": "Casts the *arg* parameter to a string using the following casting rules:\n\n - Strings are unchanged\n - Functions are converted to an empty string\n - Numeric infinity and NaN throw an error because they cannot be represented as a JSON number\n - All other values are converted to a JSON string using the `JSON.stringify` function"
"args": "arg[, prettify]",
"desc": "Casts the `arg` parameter to a string using the following casting rules:\n\n - Strings are unchanged\n - Functions are converted to an empty string\n - Numeric infinity and NaN throw an error because they cannot be represented as a JSON number\n - All other values are converted to a JSON string using the `JSON.stringify` function. If `prettify` is true, then \"prettified\" JSON is produced. i.e One line per field and lines will be indented based on the field depth."
},
"$length": {
"args": "str",
@@ -185,7 +185,7 @@
},
"$reduce": {
"args":"array, function [, init]",
"desc":"Returns an aggregated value derived from applying the `function` parameter successively to each value in `array` in combination with the result of the previous application of the function.\n\nThe function must accept two arguments, and behaves like an infix operator between each value within the `array`.\n\nThe optional `init` parameter is used as the initial value in the aggregation."
"desc":"Returns an aggregated value derived from applying the `function` parameter successively to each value in `array` in combination with the result of the previous application of the function.\n\nThe function must accept two arguments, and behaves like an infix operator between each value within the `array`. The signature of `function` must be of the form: `myfunc($accumulator, $value[, $index[, $array]])`\n\nThe optional `init` parameter is used as the initial value in the aggregation."
},
"$flowContext": {
"args": "string[, string]",
@@ -230,6 +230,37 @@
"$parseInteger": {
"args": "string, picture",
"desc": "Parses the contents of the `string` parameter to an integer (as a JSON number) using the format specified by the `picture` string. The `picture` string parameter has the same format as `$formatInteger`."
},
"$error": {
"args": "[str]",
"desc": "Throws an error with a message. The optional `str` will replace the default message of `$error() function evaluated`"
},
"$assert": {
"args": "arg, str",
"desc": "If `arg` is true the function returns undefined. If `arg` is false an exception is thrown with `str` as the message of the exception."
},
"$single": {
"args": "array, function",
"desc": "Returns the one and only value in the `array` parameter that satisfies the `function` predicate (i.e. the `function` returns Boolean `true` when passed the value). Throws an exception if the number of matching values is not exactly one.\n\nThe function should be supplied in the following signature: `function(value [, index [, array]])` where value is each input of the array, index is the position of that value and the whole array is passed as the third argument"
},
"$encodeUrl": {
"args": "str",
"desc": "Encodes a Uniform Resource Locator (URL) component by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character.\n\nExample: `$encodeUrlComponent(\"?x=test\")` => `\"%3Fx%3Dtest\"`"
},
"$encodeUrlComponent": {
"args": "str",
"desc": "Encodes a Uniform Resource Locator (URL) by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character. \n\nExample: `$encodeUrl(\"https://mozilla.org/?x=шеллы\")` => `\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\"`"
},
"$decodeUrl": {
"args": "str",
"desc": "Decodes a Uniform Resource Locator (URL) component previously created by encodeUrlComponent. \n\nExample: `$decodeUrlComponent(\"%3Fx%3Dtest\")` => `\"?x=test\"`"
},
"$decodeUrlComponent": {
"args": "str",
"desc": "Decodes a Uniform Resource Locator (URL) previously created by encodeUrl. \n\nExample: `$decodeUrl(\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\")` => `\"https://mozilla.org/?x=шеллы\"`"
},
"$distinct": {
"args": "array",
"desc": "Returns an array with duplicate values removed from `array`"
}
}

View File

@@ -15,6 +15,17 @@
"next": "進む",
"clone": "プロジェクトをクローン",
"cont": "続ける"
},
"type": {
"string": "文字列",
"number": "数値",
"boolean": "真偽値",
"array": "配列",
"buffer": "バッファ",
"object": "オブジェクト",
"jsonString": "JSON文字列",
"undefined": "undefined",
"null": "null"
}
},
"workspace": {
@@ -28,7 +39,8 @@
"status": "状態",
"enabled": "有効",
"disabled": "無効",
"info": "詳細"
"info": "詳細",
"selectNodes": "ノードをクリックして選択"
},
"menu": {
"label": {
@@ -42,7 +54,9 @@
"defaultDir": "標準",
"ltr": "左から右",
"rtl": "右から左",
"auto": "文脈"
"auto": "文脈",
"language": "表示言語",
"browserDefault": "ブラウザのデフォルト"
},
"sidebar": {
"show": "サイドバーを表示"
@@ -77,7 +91,7 @@
"projects-new": "新規",
"projects-open": "開く",
"projects-settings": "設定",
"showNodeLabelDefault": "追加したノードのラベルを表示する"
"showNodeLabelDefault": "追加したノードのラベルを表示"
}
},
"actions": {
@@ -179,7 +193,11 @@
"all": "全てのタブ",
"compact": "インデントのないJSONフォーマット",
"formatted": "インデント付きのJSONフォーマット",
"copy": "書き出し"
"copy": "書き出し",
"export": "ライブラリに書き出し",
"exportAs": "書き出し先",
"overwrite": "更新",
"exists": "<p><b>\"__file__\"</b>は既に存在します。</p><p>更新しますか?</p>"
},
"import": {
"import": "読み込み先",
@@ -303,10 +321,12 @@
"addNewType": "新規に __type__ を追加...",
"nodeProperties": "プロパティ",
"label": "ラベル",
"color": "色",
"portLabels": "ポートラベル",
"labelInputs": "入力",
"labelOutputs": "出力",
"settingIcon": "アイコン",
"default": "デフォルト",
"noDefaultLabel": "なし",
"defaultLabel": "既定のラベルを使用",
"searchIcons": "アイコンを検索",
@@ -314,8 +334,43 @@
"description": "詳細",
"show": "表示",
"hide": "非表示",
"locale": "UI言語の選択",
"icon": "記号",
"inputType": "入力形式",
"inputs": {
"input": "入力",
"select": "メニュー",
"checkbox": "チェックボックス",
"spinner": "スピナー",
"none": "無し",
"hidden": "非表示"
},
"types": {
"str": "文字列",
"num": "数値",
"bool": "真偽",
"json": "JSON",
"bin": "バッファ",
"env": "環境変数"
},
"menu": {
"input": "入力",
"select": "選択",
"checkbox": "チェックボックス",
"spinner": "数値",
"hidden": "ラベルのみ"
},
"select": {
"label": "ラベル",
"value": "値"
},
"spinner": {
"min": "最小値",
"max": "最大値"
},
"errors": {
"scopeChange": "スコープの変更は、他のフローで使われているノードを無効にします"
"scopeChange": "スコープの変更は、他のフローで使われているノードを無効にします",
"invalidProperties": "プロパティが不正です:"
}
},
"keyboard": {
@@ -343,7 +398,8 @@
"pasteNode": "ノードを貼り付け",
"undoChange": "変更操作を戻す",
"searchBox": "ノードを検索",
"managePalette": "パレットの管理"
"managePalette": "パレットの管理",
"actionList": "動作一覧"
},
"library": {
"library": "ライブラリ",
@@ -351,12 +407,15 @@
"saveToLibrary": "ライブラリへ保存",
"typeLibrary": "__type__ ライブラリ",
"unnamedType": "名前なし __type__",
"exportedToLibrary": "ライブラリにノードを書き出しました",
"dialogSaveOverwrite": "__libraryName__ という __libraryType__ は既に存在しています 上書きしますか?",
"invalidFilename": "不正なファイル名",
"savedNodes": "フローを保存しました",
"savedType": "__type__ を保存しました",
"saveFailed": "保存に失敗しました: __message__",
"newFolder": "新規フォルダ",
"types": {
"local": "ローカル",
"examples": "サンプル"
}
},
@@ -367,9 +426,13 @@
"addCategory": "新規追加...",
"label": {
"subflows": "サブフロー",
"network": "ネットワーク",
"common": "共通",
"input": "入力",
"output": "出力",
"function": "機能",
"sequence": "シーケンス",
"parser": "パーサ",
"social": "ソーシャル",
"storage": "ストレージ",
"analysis": "分析",
@@ -506,8 +569,10 @@
"none": "なし",
"subflows": "サブフロー",
"flows": "フロー",
"filterUnused": "未使用",
"filterAll": "全て",
"showAllConfigNodes": "全設定ノードを表示",
"filterUnused": "未使用",
"showAllUnusedConfigNodes": "未使用の全設定ノードを表示",
"filtered": "__count__ 個が無効"
},
"context": {
@@ -516,10 +581,13 @@
"none": "選択されていません",
"refresh": "読み込みのため更新してください",
"empty": "データが存在しません",
"node": "Node",
"flow": "Flow",
"global": "Global",
"deleteConfirm": "データを削除しても良いですか?"
"node": "ノード",
"flow": "フロー",
"global": "グローバル",
"deleteConfirm": "データを削除しても良いですか?",
"autoRefresh": "選択対象が変化した場合更新",
"refrsh": "更新",
"delete": "削除"
},
"palette": {
"name": "パレットの管理",
@@ -531,9 +599,10 @@
"description": "詳細",
"dependencies": "依存関係",
"settings": "設定",
"noSummaryAvailable": "サマリが存在しません",
"noSummaryAvailable": "要約が存在しません",
"editDescription": "プロジェクトの詳細を編集",
"editDependencies": "プロジェクトの依存関係を編集",
"noDescriptionAvailable": "詳細が存在しません",
"editReadme": "README.mdを編集",
"showProjectSettings": "プロジェクト設定を表示",
"projectSettings": {
@@ -719,12 +788,28 @@
"jsEditor": {
"title": "JavaScriptエディタ"
},
"textEditor": {
"title": "テキストエディタ"
},
"jsonEditor": {
"title": "JSONエディタ",
"format": "JSONフォーマット"
"format": "JSONフォーマット",
"rawMode": "JSONを編集",
"uiMode": "ビジュアルエディタ",
"insertAbove": "上に挿入",
"insertBelow": "下に挿入",
"addItem": "要素を追加",
"copyPath": "要素のパスをコピー",
"expandItems": "要素を展開",
"collapseItems": "要素を折り畳む",
"duplicate": "複製",
"error": {
"invalidJSON": "不正なJSON: "
}
},
"markdownEditor": {
"title": "マークダウンエディタ",
"expand": "拡大",
"format": "マークダウン形式で記述",
"heading1": "見出しレベル1",
"heading2": "見出しレベル2",
@@ -885,7 +970,7 @@
"confirm": "<p>デプロイされていない変更は失われます。</p><p>続けますか?</p>"
},
"send-req": {
"auth-req": "リポジトリ対する認証が必要です",
"auth-req": "リポジトリ対する認証が必要です",
"username": "ユーザ名",
"password": "パスワード",
"passphrase": "パスフレーズ",
@@ -911,8 +996,17 @@
},
"editor-tab": {
"properties": "プロパティ",
"envProperties": "環境変数",
"description": "説明",
"appearance": "外観",
"env": "環境変数"
"preview": "UIプレビュー",
"defaultValue": "デフォルト値"
},
"languages": {
"de": "ドイツ語",
"en-US": "英語",
"ja": "日本語",
"ko": "韓国語",
"zh-CN": "中国語(簡体)"
}
}

View File

@@ -1,7 +1,7 @@
{
"$string": {
"args": "arg",
"desc": "以下の型変換ルールを用いて、引数 *arg* を文字列へ型変換します。:\n\n - 文字列は変換しません。\n - 関数は空の文字列に変換します。\n - JSONの数値として表現できないため、無限大やNaNはエラーになります。\n - 他の値は `JSON.stringify` 関数を用いて、JSONの文字列へ変換します。"
"args": "arg[, prettify]",
"desc": "以下の型変換ルールを用いて、引数 *arg* を文字列へ型変換します。:\n\n - 文字列は変換しません。\n - 関数は空の文字列に変換します。\n - JSONの数値として表現できないため、無限大やNaNはエラーになります。\n - 他の値は `JSON.stringify` 関数を用いて、JSONの文字列へ変換します。`prettify`が真の場合、JSONを整形出力します。フィールドを1行毎に出力。フィールドのネスト深さによってインデントを行います。"
},
"$length": {
"args": "str",
@@ -185,7 +185,7 @@
},
"$reduce": {
"args": "array, function [, init]",
"desc": "配列の各要素値に関数 `function` を連続的に適用して得られる集約値を返します。 `function` の適用の際には、直前の `function` の適用結果と要素値が引数として与えられます。\n\n関数 `function` は引数を2つ取り、配列の各要素の間に配置する中置演算子のように作用しなくてはなりません。\n\n任意の引数 `init` には、集約時の初期値を設定します。"
"desc": "配列の各要素値に関数 `function` を連続的に適用して得られる集約値を返します。 `function` の適用の際には、直前の `function` の適用結果と要素値が引数として与えられます。\n\n関数 `function` は引数を2つ取り、配列の各要素の間に配置する中置演算子のように作用しなくてはなりません。関数`function`のシグネチャは`myfunc($accumulator, $value[, $index[, $array]])`という形式でなければなりません。\n\n任意の引数 `init` には、集約時の初期値を設定します。"
},
"$flowContext": {
"args": "string",
@@ -230,5 +230,37 @@
"$parseInteger": {
"args": "string, picture",
"desc": "`picture`文字列の指定に従って、`string`パラメータを整数(JSON数値)に変換します。`picture`文字列は`$formatInteger`と同じ形式です。"
},
"$error": {
"args": "[str]",
"desc": "メッセージを指定して例外を送出します。メッセージ`str`を省略した場合は`$error() function evaluated`をメッセージとします。"
},
"$assert": {
"args": "arg, str",
"desc": "`arg`が真の場合、undefinedを返します。偽の場合、`str`をメッセージとする例外を送出します。"
},
"$single": {
"args": "array, function",
"desc": "`array`の要素のうち、条件判定関数`function`を満たす(`function`に与えた場合に真偽値`true`を返す)要素が1つのみである場合、それを返します。マッチする要素が1つのみでない場合、例外を送出します。\n\n指定する関数は`function(value [, index [, array]])`というシグネチャでなければなりません。ここで、`value`は`array`の要素値、`index`は要素の添字、第三引数には配列全体を渡します。"
},
"$encodeUrl": {
"args": "str",
"desc": "Uniform Resource Locator (URL)を構成する文字を1、、3、もしくは、4文字エスケープシーケンスのUTF-8文字エンコーディングで置換します。\n\n例: `$encodeUrlComponent(\"?x=test\")` => `\"%3Fx%3Dtest\"`"
},
"$encodeUrlComponent": {
"args": "str",
"desc": "Uniform Resource Locator (URL)要素を構成する文字を1、、もしくは、4文字エスケープシーケンスのUTF-8文字エンコーディングで置換します。\n\n例: `$encodeUrl(\"https://mozilla.org/?x=шеллы\")` => `\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\"`"
},
"$decodeUrl": {
"args": "str",
"desc": "encodeUrlComponentで置換したUniform Resource Locator (URL)をデコードします。\n\n例: `$decodeUrlComponent(\"%3Fx%3Dtest\")` => `\"?x=test\"`"
},
"$decodeUrlComponent": {
"args": "str",
"desc": "encodeUrlで置換したUniform Resource Locator (URL)要素をデコードします。 \n\n例: `$decodeUrl(\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\")` => `\"https://mozilla.org/?x=шеллы\"`"
},
"$distinct": {
"args": "array",
"desc": "配列`array`から重複要素を削除した配列を返します。"
}
}

View File

@@ -273,7 +273,6 @@
"deleteSubflow": "서브 플로우 삭제",
"info": "상세내역",
"category": "카테고리",
"format": "Markdown 형식",
"errors": {
"noNodesSelected": "<strong>서브 플로우를 생성할 수 없습니다</strong> : 노드가 선택되지 않았습니다",
"multipleInputsToSelection": "<strong>서브 플로우를 생성할 수 없습니다</strong> : 복수의 입력이 선택되었습니다"
@@ -495,8 +494,8 @@
"none": "없음",
"subflows": "보조 플로우",
"flows": "플로우",
"filterUnused": "미사용",
"filterAll": "전체",
"filterUnused": "미사용",
"filtered": "__count__ 개 숨김"
},
"context": {

View File

@@ -385,8 +385,8 @@
"none": "无",
"subflows": "子流程",
"flows": "流程",
"filterUnused": "未使用",
"filterAll": "所有",
"filterUnused": "未使用",
"filtered": "__count__ 个隐藏"
},
"palette": {

View File

@@ -1,6 +1,6 @@
{
"name": "@node-red/editor-client",
"version": "1.0.0-beta.2",
"version": "1.0.3",
"license": "Apache-2.0",
"repository": {
"type": "git",

Binary file not shown.

Before

Width:  |  Height:  |  Size: 291 B

View File

@@ -0,0 +1 @@
<svg width="27" height="18" xmlns="http://www.w3.org/2000/svg"><g color="#000"><path fill="#fff" d="M0 5.002h10v5H0zM17 .002h10v5H17z"/><path d="M17 13.002h10v5H17z"/></g><path d="M9.5 7.502h2l4-5h2" fill="none" stroke="#fff" stroke-width="1.5"/></svg>

After

Width:  |  Height:  |  Size: 252 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 B

View File

@@ -0,0 +1 @@
<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg"><path color="#000" fill="#8c101c" d="M0 .002h32v32H0z"/><g color="#000"><path fill="#fff" d="M2 13.002h10v5H2zM19 8.002h10v5H19z"/><path d="M19 21.002h10v5H19z"/></g><path d="M11.5 15.502h2l4-5h2" fill="none" stroke="#fff" stroke-width="1.5"/></svg>

After

Width:  |  Height:  |  Size: 312 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 289 B

View File

@@ -0,0 +1 @@
<svg width="27" height="18" xmlns="http://www.w3.org/2000/svg"><g fill="#fff" color="#000"><path d="M0 5h10v5H0zM17 0h10v5H17zM17 13h10v5H17z"/></g><path d="M9.5 7.5h2l4-5h2" fill="none" stroke="#fff" stroke-width="1.5"/></svg>

After

Width:  |  Height:  |  Size: 227 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 368 B

View File

@@ -0,0 +1 @@
<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg"><path color="#000" fill="#8c101c" d="M0 0h32v32H0z"/><g fill="#fff" color="#000"><path d="M2 13h10v5H2zM19 8h10v5H19zM19 21h10v5H19z"/></g><path d="M11.5 15.5h2l4-5h2" fill="none" stroke="#fff" stroke-width="1.5"/></svg>

After

Width:  |  Height:  |  Size: 283 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 290 B

View File

@@ -0,0 +1 @@
<svg width="27" height="18" xmlns="http://www.w3.org/2000/svg"><path color="#000" d="M0 5.002h10v5H0zM17 13.002h10v5H17z"/><path d="M9.5 7.502h2l4-5h2" fill="none" stroke="#000" stroke-width="1.5"/><path color="#000" fill="#fff" d="M17 .002h10v5H17z"/></svg>

After

Width:  |  Height:  |  Size: 258 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 392 B

View File

@@ -0,0 +1 @@
<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg"><path color="#000" fill="#8c101c" d="M0 .002h32v32H0z"/><path color="#000" d="M2 13.002h10v5H2zM19 21.002h10v5H19z"/><path d="M11.5 15.502h2l4-5h2" fill="none" stroke="#000" stroke-width="1.5"/><path color="#000" fill="#fff" d="M19 8.002h10v5H19z"/></svg>

After

Width:  |  Height:  |  Size: 318 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1015 B

View File

@@ -0,0 +1 @@
<svg width="32" height="32" xmlns="http://www.w3.org/2000/svg"><g color="#000"><path fill="#8c101c" d="M0 .006h32v32H0z"/><path d="M11.81 25.429a10.02 10.02 0 0 0 4.19.914c5.562 0 10.107-4.545 10.107-10.106S21.562 6.131 16 6.131 5.895 10.676 5.895 16.237h3.368c0-3.74 2.997-6.737 6.738-6.737s6.737 2.996 6.737 6.737-2.996 6.738-6.737 6.738a6.775 6.775 0 0 1-2.533-.486l1.43-3.48-6.947 1.317 2.13 8.485z" fill="#fff" style="isolation:auto;mix-blend-mode:normal;text-decoration-color:#000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/></g></svg>

After

Width:  |  Height:  |  Size: 606 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 393 B

View File

@@ -0,0 +1 @@
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="M18 5v12H7v26h11v12l14-25z" fill="#fff"/></svg>

After

Width:  |  Height:  |  Size: 143 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 386 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 1019 B

View File

@@ -0,0 +1 @@
<svg width="46.994" height="18.006" xmlns="http://www.w3.org/2000/svg"><g stroke="#d6d6d6"><g fill="#9e3131" stroke-linejoin="round" stroke-width="3.847" transform="matrix(.25848 0 0 .2614 -63.87 -108.483)"><rect x="249.04" y="435.92" width="50.294" height="22.953" ry="6.608"/><rect x="345.63" y="416.93" width="50.294" height="22.953" ry="6.608"/><rect x="376.71" y="459.01" width="50.294" height="22.953" ry="6.608"/></g><path d="M301.04 447.43c24.406.184 7.107-18.84 42.708-19.03M374.82 470.48c-46.966.538-28.989-22.664-73.619-22.944" fill="none" stroke-width="5.771" transform="matrix(.25848 0 0 .2614 -63.87 -108.483)"/></g></svg>

After

Width:  |  Height:  |  Size: 636 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 600 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 410 B

View File

@@ -0,0 +1 @@
<svg width="40" height="40" viewBox="0, 0, 40, 40" xmlns="http://www.w3.org/2000/svg"><path d="M25 16h7c.58 0 1-.42 1-1v-2c0-.58-.42-1-1-1h-7c-.58 0-1 .42-1 1v2c0 .58.42 1 1 1zM8 28h7c.58 0 1-.42 1-1v-2c0-.58-.42-1-1-1H8c-.58 0-1 .42-1 1v2c0 .58.42 1 1 1zm-.416 11C5.624 39 4 37.375 4 35.416V4.582C4 2.622 5.625 1 7.584 1h24.832C34.376 1 36 2.623 36 4.582v30.834C36 37.376 34.375 39 32.416 39zM32 27H19c0 2.19-1.81 4-4 4H7v4.416c0 .35.235.584.584.584h24.832c.35 0 .584-.235.584-.584v-8.417zm1-2v-6h-8c-2.19 0-4-1.81-4-4h-1c-4.333-.002-8.667.004-13 0v6h8c2.19 0 4 1.81 4 4h13zm0-16V4.582c0-.35-.235-.582-.584-.582H7.584C7.234 4 7 4.233 7 4.582v8.417c4.333.002 8.667.001 13 .001h1c0-2.19 1.81-4 4-4z" color="#000" fill="#333"/></svg>

After

Width:  |  Height:  |  Size: 732 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 638 B

View File

@@ -0,0 +1 @@
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M14.16 27.38l1.555-.144c.132.731.383 1.261.755 1.591.371.33.848.494 1.429.494.497 0 .931-.114 1.303-.341.377-.228.686-.53.926-.908.24-.383.44-.899.602-1.546a8.122 8.122 0 0 0 .233-2.3 3.732 3.732 0 0 1-1.33 1.258 3.605 3.605 0 0 1-1.815.476c-1.09 0-2.013-.395-2.768-1.186s-1.133-1.834-1.133-3.128c0-1.336.393-2.411 1.178-3.226.79-.815 1.78-1.223 2.966-1.223.856 0 1.638.231 2.345.692.713.462 1.253 1.12 1.618 1.978.372.85.557 2.085.557 3.702 0 1.684-.182 3.026-.548 4.027-.365.994-.91 1.752-1.636 2.274-.719.52-1.563.781-2.534.781-1.03 0-1.872-.284-2.525-.853-.654-.576-1.046-1.381-1.178-2.418zm6.624-5.815c0-.928-.249-1.666-.746-2.21-.492-.546-1.085-.819-1.78-.819-.719 0-1.345.294-1.878.881s-.8 1.348-.8 2.283c0 .839.252 1.522.755 2.05.51.52 1.135.781 1.878.781.75 0 1.363-.26 1.843-.782.485-.527.728-1.255.728-2.184zM4.858 10.466c0-1.558.158-2.81.476-3.757.324-.952.8-1.686 1.429-2.201.635-.516 1.432-.773 2.39-.773.708 0 1.328.143 1.861.431.533.282.974.692 1.321 1.231.348.534.62 1.187.818 1.96.198.767.297 1.803.297 3.11 0 1.545-.16 2.794-.477 3.747-.317.947-.794 1.68-1.429 2.202-.629.515-1.426.773-2.39.773-1.27 0-2.268-.456-2.993-1.366-.869-1.097-1.303-2.882-1.303-5.357zm1.662 0c0 2.163.252 3.604.755 4.323.51.713 1.136 1.07 1.879 1.07.743 0 1.366-.36 1.87-1.079.508-.719.763-2.157.763-4.314 0-2.169-.255-3.61-.764-4.323-.503-.713-1.132-1.07-1.887-1.07-.743 0-1.336.315-1.78.944-.557.803-.836 2.286-.836 4.45z" fill="#444"/></svg>

After

Width:  |  Height:  |  Size: 1.5 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 546 B

View File

@@ -0,0 +1 @@
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M13.27 29.15l6.733-8.143h-6.235V19.3h8.8v1.559l-6.69 8.09h6.892v1.707h-9.5zm4.909-10.125zM6.577 12.58q0 .827.604 1.304.605.478 1.432.478 1.007 0 1.95-.467 1.59-.774 1.59-2.534V9.824q-.349.222-.9.37-.552.15-1.082.213l-1.155.148q-1.04.138-1.56.435-.88.498-.88 1.59zM11.2 8.721q.657-.085.88-.551.127-.255.127-.732 0-.975-.7-1.41-.689-.445-1.983-.445-1.495 0-2.12.805-.35.446-.456 1.326H5.167q.053-2.1 1.357-2.916 1.315-.827 3.043-.827 2.004 0 3.255.763 1.24.764 1.24 2.375v6.542q0 .297.117.477.127.18.52.18.127 0 .286-.01.159-.021.34-.053v1.41q-.446.127-.68.16-.233.031-.636.031-.986 0-1.43-.7-.234-.37-.33-1.05-.583.764-1.675 1.326t-2.407.562q-1.58 0-2.587-.954-.996-.965-.996-2.407 0-1.58.986-2.45.986-.869 2.587-1.07zm-1.58-4.75z" fill="#444"/></svg>

After

Width:  |  Height:  |  Size: 846 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 638 B

View File

@@ -0,0 +1 @@
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M18.8 33.9c3.328 0 4.776-2.603 4.776-7.066s-1.448-7.066-4.776-7.066-4.776 2.603-4.776 7.066S15.473 33.9 18.8 33.9zm0-1.429c-2.192 0-3.073-1.781-3.073-4.522v-2.23c0-2.741.88-4.523 3.073-4.523s3.073 1.782 3.073 4.522v2.231c0 2.74-.88 4.522-3.073 4.522zm-6.306 1.194v-1.429H8.892V20.002H6.328l-3.621 3.386.959 1.038 3.445-3.21h.137v11.02H3.333v1.429zm11.2-17.7v-1.429h-3.602V2.302h-2.564l-3.621 3.386.959 1.038 3.445-3.21h.137v11.02h-3.915v1.429zM7.5 16.2c3.327 0 4.776-2.603 4.776-7.066S10.828 2.068 7.5 2.068 2.725 4.67 2.725 9.134 4.173 16.2 7.5 16.2zm0-1.429c-2.193 0-3.074-1.781-3.074-4.522V8.02c0-2.741.881-4.523 3.074-4.523s3.073 1.782 3.073 4.522v2.231c0 2.74-.881 4.522-3.073 4.522z" fill="#444"/></svg>

After

Width:  |  Height:  |  Size: 805 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 646 B

View File

@@ -0,0 +1 @@
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M9.96 21.98a5 5 0 1 1 6.11-7.917zm3.035-13.973c-5.512 0-10 4.488-10 10s4.488 9.998 10 9.998 10-4.486 10-9.998-4.488-10-10-10zm0 1.816c4.53 0 8.182 3.655 8.182 8.184s-3.652 8.182-8.182 8.182-8.181-3.653-8.181-8.182 3.652-8.184 8.181-8.184z" color="#000" fill="#444"/></svg>

After

Width:  |  Height:  |  Size: 368 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 809 B

View File

@@ -0,0 +1 @@
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M14.33 27.19q2.916-.136 4.024-2.131.58-1.024.58-2.37 0-2.132-1.569-3.24-.904-.648-3.035-1.228zM8.55 10.736q0 1.688 1.108 2.643 1.125.955 3.018 1.33V6.695q-2.234.085-3.189 1.364-.937 1.279-.937 2.677zm-3.07.205q0-2.592 1.893-4.672 1.91-2.08 5.337-2.115V1.887h1.62V4.12q3.393.239 5.2 2.012 1.825 1.757 1.91 4.655h-2.984q-.119-1.296-.699-2.233-1.074-1.723-3.427-1.808v8.287q3.956 1.108 5.371 2.08 2.302 1.603 2.302 4.74 0 4.536-2.95 6.446-1.637 1.057-4.723 1.398v3.308h-1.62v-3.308q-4.962-.324-6.735-3.513-.972-1.722-.972-4.655h3.018q.136 2.336.733 3.41 1.057 1.927 3.922 2.166v-9.293q-3.683-.699-5.44-2.336Q5.48 13.84 5.48 10.941z" fill="#444"/></svg>

After

Width:  |  Height:  |  Size: 745 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 563 B

View File

@@ -0,0 +1 @@
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-337.103 -913.25) scale(1.2585)" fill="#444" stroke-width=".795"><circle cx="284.36" cy="733.68" r="1.5" color="#000" style="isolation:auto;mix-blend-mode:normal"/><circle cx="284.33" cy="740.74" r="1.5" color="#000" style="isolation:auto;mix-blend-mode:normal"/><path d="M276.18 727.78l4.396-1.565v18.515c-.711 2.606-2.922 4.394-5.812 5.812l-4.135 1.974-.559-1.192 3.353-1.639c1.459-.724 2.689-1.87 2.869-4.955z" fill-rule="evenodd"/></g></svg>

After

Width:  |  Height:  |  Size: 556 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 588 B

View File

@@ -0,0 +1 @@
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M15 5.225v-1.92h2.24q.608 0 1.216.288.608.256 1.12.8.48.512.8 1.312.32.768.32 1.792v5.824q0 .832.224 1.536t.608 1.216q.352.48.832.768.48.256.992.256v2.176q-.512 0-.992.256t-.832.736q-.384.48-.608 1.184t-.224 1.568v5.792q0 1.024-.32 1.792-.32.8-.8 1.312-.512.544-1.12.8-.608.288-1.216.288H15v-1.92h1.6q.48 0 .768-.256.288-.224.48-.64.16-.384.224-.896.064-.48.064-.96v-5.824q0-1.216.352-2.016.32-.8.768-1.28.448-.512.928-.736.448-.224.736-.256v-.096q-.288-.064-.736-.32-.48-.256-.928-.768t-.768-1.28q-.352-.8-.352-1.92V7.977q0-.512-.064-.992-.064-.512-.224-.896-.192-.384-.48-.608-.288-.256-.768-.256zm-3.648 0v-1.92h-2.24q-.608 0-1.216.288-.608.256-1.12.8-.48.512-.8 1.312-.32.768-.32 1.792v5.824q0 .832-.224 1.536t-.608 1.216q-.352.48-.832.768-.48.256-.992.256v2.176q.512 0 .992.256t.832.736q.384.48.608 1.184t.224 1.568v5.792q0 1.024.32 1.792.32.8.8 1.312.512.544 1.12.8.608.288 1.216.288h2.24v-1.92h-1.6q-.48 0-.768-.256-.288-.224-.48-.64-.16-.384-.224-.896-.064-.48-.064-.96v-5.824q0-1.216-.352-2.016-.32-.8-.768-1.28-.448-.512-.928-.736-.448-.224-.736-.256v-.096q.288-.064.736-.32.48-.256.928-.768t.768-1.28q.352-.8.352-1.92V7.977q0-.512.064-.992.064-.512.224-.896.192-.384.48-.608.288-.256.768-.256z" fill="#444"/></svg>

After

Width:  |  Height:  |  Size: 1.3 KiB

Binary file not shown.

Before

Width:  |  Height:  |  Size: 502 B

View File

@@ -0,0 +1 @@
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M2 19h5v5H2zm16.099-3.304v-5.659h-2.654v5.66l-5.309-2.004-.901 2.404L14.543 18l-3.255 4.557 2.254 1.553 3.255-4.808 3.455 4.808 2.054-1.553L19 18l5.46-1.903-1.002-2.404z" color="#000" fill="#444444"/></svg>

After

Width:  |  Height:  |  Size: 302 B

Binary file not shown.

Before

Width:  |  Height:  |  Size: 944 B

View File

@@ -0,0 +1 @@
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M11 5v5.77a7.542 7.542 0 0 0-5.234 5.25L1 16c-1.432 1.397-1.232 2.722 0 4l4.75-.078a7.542 7.542 0 0 0 5.22 5.297L11 31c1.316 1.303 2.649 1.363 4 0l.009-5.775A7.542 7.542 0 0 0 20.228 20H25c1.261-1.294 1.404-2.623 0-4l-4.774-.01a7.542 7.542 0 0 0-5.23-5.22L15 5c-1.3-1.273-2.63-1.393-4 0zm2 7.499c3.05 0 5.5 2.45 5.5 5.5s-2.45 5.5-5.5 5.5-5.5-2.45-5.5-5.5 2.45-5.5 5.5-5.5z" color="#000" fill="#444"/></svg>

After

Width:  |  Height:  |  Size: 502 B

View File

@@ -14,7 +14,8 @@
* limitations under the License.
**/
RED.history = (function() {
var undo_history = [];
var undoHistory = [];
var redoHistory = [];
function undoEvent(ev) {
var i;
@@ -22,52 +23,81 @@ RED.history = (function() {
var node;
var subflow;
var modifiedTabs = {};
var inverseEv;
if (ev) {
if (ev.t == 'multi') {
inverseEv = {
t: 'multi',
events: []
};
len = ev.events.length;
for (i=len-1;i>=0;i--) {
undoEvent(ev.events[i]);
var r = undoEvent(ev.events[i]);
inverseEv.events.push(r);
}
} else if (ev.t == 'replace') {
inverseEv = {
t: 'replace',
config: RED.nodes.createCompleteNodeSet(),
changed: {},
rev: RED.nodes.version()
};
RED.nodes.clear();
var imported = RED.nodes.import(ev.config);
imported[0].forEach(function(n) {
if (ev.changed[n.id]) {
n.changed = true;
inverseEv.changed[n.id] = true;
}
})
RED.nodes.version(ev.rev);
} else if (ev.t == 'add') {
inverseEv = {
t: "delete",
};
if (ev.nodes) {
inverseEv.nodes = [];
for (i=0;i<ev.nodes.length;i++) {
node = RED.nodes.node(ev.nodes[i]);
if (node.z) {
modifiedTabs[node.z] = true;
}
inverseEv.nodes.push(node);
RED.nodes.remove(ev.nodes[i]);
}
}
if (ev.links) {
inverseEv.links = [];
for (i=0;i<ev.links.length;i++) {
inverseEv.links.push(ev.links[i]);
RED.nodes.removeLink(ev.links[i]);
}
}
if (ev.workspaces) {
inverseEv.workspaces = [];
for (i=0;i<ev.workspaces.length;i++) {
var workspaceOrder = RED.nodes.getWorkspaceOrder();
ev.workspaces[i]._index = workspaceOrder.indexOf(ev.workspaces[i].id);
inverseEv.workspaces.push(ev.workspaces[i]);
RED.nodes.removeWorkspace(ev.workspaces[i].id);
RED.workspaces.remove(ev.workspaces[i]);
}
}
if (ev.subflows) {
inverseEv.subflows = [];
for (i=0;i<ev.subflows.length;i++) {
inverseEv.subflows.push(ev.subflows[i]);
RED.nodes.removeSubflow(ev.subflows[i]);
RED.workspaces.remove(ev.subflows[i]);
}
}
if (ev.subflow) {
inverseEv.subflow = {};
if (ev.subflow.instances) {
inverseEv.subflow.instances = [];
ev.subflow.instances.forEach(function(n) {
inverseEv.subflow.instances.push(n);
var node = RED.nodes.node(n.id);
if (node) {
node.changed = n.changed;
@@ -83,21 +113,30 @@ RED.history = (function() {
}
}
if (ev.removedLinks) {
inverseEv.createdLinks = [];
for (i=0;i<ev.removedLinks.length;i++) {
inverseEv.createdLinks.push(ev.removedLinks[i]);
RED.nodes.addLink(ev.removedLinks[i]);
}
}
} else if (ev.t == "delete") {
inverseEv = {
t: "add"
};
if (ev.workspaces) {
inverseEv.workspaces = [];
for (i=0;i<ev.workspaces.length;i++) {
inverseEv.workspaces.push(ev.workspaces[i]);
RED.nodes.addWorkspace(ev.workspaces[i],ev.workspaces[i]._index);
RED.workspaces.add(ev.workspaces[i],undefined,ev.workspaces[i]._index);
delete ev.workspaces[i]._index;
}
}
if (ev.subflows) {
inverseEv.subflows = [];
for (i=0;i<ev.subflows.length;i++) {
inverseEv.subflows.push(ev.subflows[i]);
RED.nodes.addSubflow(ev.subflows[i]);
}
}
@@ -126,8 +165,11 @@ RED.history = (function() {
}
}
if (ev.subflow) {
inverseEv.subflow = {};
if (ev.subflow.hasOwnProperty('instances')) {
inverseEv.subflow.instances = [];
ev.subflow.instances.forEach(function(n) {
inverseEv.subflow.instances.push(n);
var node = RED.nodes.node(n.id);
if (node) {
node.changed = n.changed;
@@ -152,14 +194,25 @@ RED.history = (function() {
});
}
if (ev.nodes) {
inverseEv.nodes = [];
for (i=0;i<ev.nodes.length;i++) {
RED.nodes.add(ev.nodes[i]);
modifiedTabs[ev.nodes[i].z] = true;
inverseEv.nodes.push(ev.nodes[i].id);
}
}
if (ev.links) {
inverseEv.links = [];
for (i=0;i<ev.links.length;i++) {
RED.nodes.addLink(ev.links[i]);
inverseEv.links.push(ev.links[i]);
}
}
if (ev.createdLinks) {
inverseEv.removedLinks = [];
for (i=0;i<ev.createdLinks.length;i++) {
inverseEv.removedLinks.push(ev.createdLinks[i]);
RED.nodes.removeLink(ev.createdLinks[i]);
}
}
if (ev.changes) {
@@ -179,8 +232,14 @@ RED.history = (function() {
}
} else if (ev.t == "move") {
inverseEv = {
t: 'move',
nodes: []
};
for (i=0;i<ev.nodes.length;i++) {
var n = ev.nodes[i];
var rn = {n: n.n, ox: n.n.x, oy: n.n.y, dirty: true, moved: n.moved};
inverseEv.nodes.push(rn);
n.n.x = n.ox;
n.n.y = n.oy;
n.n.dirty = true;
@@ -188,18 +247,28 @@ RED.history = (function() {
}
// A move could have caused a link splice
if (ev.links) {
inverseEv.removedLinks = [];
for (i=0;i<ev.links.length;i++) {
inverseEv.removedLinks.push(ev.links[i]);
RED.nodes.removeLink(ev.links[i]);
}
}
if (ev.removedLinks) {
inverseEv.links = [];
for (i=0;i<ev.removedLinks.length;i++) {
inverseEv.links.push(ev.removedLinks[i]);
RED.nodes.addLink(ev.removedLinks[i]);
}
}
} else if (ev.t == "edit") {
inverseEv = {
t: "edit",
changes: {}
};
inverseEv.node = ev.node;
for (i in ev.changes) {
if (ev.changes.hasOwnProperty(i)) {
inverseEv.changes[i] = ev.node[i];
if (ev.node._def.defaults && ev.node._def.defaults[i] && ev.node._def.defaults[i].type) {
// This is a config node property
var currentConfigNode = RED.nodes.node(ev.node[i]);
@@ -214,23 +283,34 @@ RED.history = (function() {
ev.node[i] = ev.changes[i];
}
}
if (ev.node.type === 'tab' && ev.changes.hasOwnProperty('disabled')) {
$("#red-ui-tab-"+(ev.node.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!ev.node.disabled);
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!ev.node.disabled);
}
if (ev.subflow) {
inverseEv.subflow = {};
if (ev.subflow.hasOwnProperty('inputCount')) {
inverseEv.subflow.inputCount = ev.node.in.length;
if (ev.node.in.length > ev.subflow.inputCount) {
inverseEv.subflow.inputs = ev.node.in.slice(ev.subflow.inputCount);
ev.node.in.splice(ev.subflow.inputCount);
} else if (ev.subflow.inputs.length > 0) {
ev.node.in = ev.node.in.concat(ev.subflow.inputs);
}
}
if (ev.subflow.hasOwnProperty('outputCount')) {
inverseEv.subflow.outputCount = ev.node.out.length;
if (ev.node.out.length > ev.subflow.outputCount) {
inverseEv.subflow.outputs = ev.node.out.slice(ev.subflow.outputCount);
ev.node.out.splice(ev.subflow.outputCount);
} else if (ev.subflow.outputs.length > 0) {
ev.node.out = ev.node.out.concat(ev.subflow.outputs);
}
}
if (ev.subflow.hasOwnProperty('instances')) {
inverseEv.subflow.instances = [];
ev.subflow.instances.forEach(function(n) {
inverseEv.subflow.instances.push(n);
var node = RED.nodes.node(n.id);
if (node) {
node.changed = n.changed;
@@ -254,9 +334,11 @@ RED.history = (function() {
var outputMap;
if (ev.outputMap) {
outputMap = {};
inverseEv.outputMap = {};
for (var port in ev.outputMap) {
if (ev.outputMap.hasOwnProperty(port) && ev.outputMap[port] !== "-1") {
outputMap[ev.outputMap[port]] = port;
inverseEv.outputMap[ev.outputMap[port]] = port;
}
}
}
@@ -264,39 +346,107 @@ RED.history = (function() {
RED.editor.validateNode(ev.node);
}
if (ev.links) {
inverseEv.createdLinks = [];
for (i=0;i<ev.links.length;i++) {
RED.nodes.addLink(ev.links[i]);
inverseEv.createdLinks.push(ev.links[i]);
}
}
if (ev.createdLinks) {
inverseEv.links = [];
for (i=0;i<ev.createdLinks.length;i++) {
RED.nodes.removeLink(ev.createdLinks[i]);
inverseEv.links.push(ev.createdLinks[i]);
}
}
ev.node.dirty = true;
ev.node.changed = ev.changed;
} else if (ev.t == "createSubflow") {
inverseEv = {
t: "deleteSubflow",
activeWorkspace: ev.activeWorkspace,
dirty: RED.nodes.dirty()
};
if (ev.nodes) {
inverseEv.movedNodes = [];
var z = ev.activeWorkspace;
RED.nodes.filterNodes({z:ev.subflow.subflow.id}).forEach(function(n) {
n.x += ev.subflow.offsetX;
n.y += ev.subflow.offsetY;
n.z = ev.activeWorkspace;
n.dirty = true;
inverseEv.movedNodes.push(n.id);
RED.nodes.moveNodeToTab(n, z);
});
inverseEv.subflows = [];
for (i=0;i<ev.nodes.length;i++) {
inverseEv.subflows.push(RED.nodes.node(ev.nodes[i]));
RED.nodes.remove(ev.nodes[i]);
}
}
if (ev.links) {
inverseEv.links = [];
for (i=0;i<ev.links.length;i++) {
inverseEv.links.push(ev.links[i]);
RED.nodes.removeLink(ev.links[i]);
}
}
inverseEv.subflow = ev.subflow;
RED.nodes.removeSubflow(ev.subflow.subflow);
RED.workspaces.remove(ev.subflow.subflow);
if (ev.removedLinks) {
inverseEv.createdLinks = [];
for (i=0;i<ev.removedLinks.length;i++) {
inverseEv.createdLinks.push(ev.removedLinks[i]);
RED.nodes.addLink(ev.removedLinks[i]);
}
}
} else if (ev.t == "deleteSubflow") {
inverseEv = {
t: "createSubflow",
activeWorkspace: ev.activeWorkspace,
dirty: RED.nodes.dirty(),
};
if (ev.subflow) {
RED.nodes.addSubflow(ev.subflow.subflow);
inverseEv.subflow = ev.subflow;
}
if (ev.subflows) {
inverseEv.nodes = [];
for (i=0;i<ev.subflows.length;i++) {
RED.nodes.add(ev.subflows[i]);
inverseEv.nodes.push(ev.subflows[i].id);
}
}
if (ev.movedNodes) {
ev.movedNodes.forEach(function(nid) {
nn = RED.nodes.node(nid);
nn.x -= ev.subflow.offsetX;
nn.y -= ev.subflow.offsetY;
nn.dirty = true;
RED.nodes.moveNodeToTab(nn, ev.subflow.subflow.id);
});
}
if (ev.links) {
inverseEv.links = [];
for (i=0;i<ev.links.length;i++) {
inverseEv.links.push(ev.links[i]);
RED.nodes.addLink(ev.links[i]);
}
}
if (ev.createdLinks) {
inverseEv.removedLinks = [];
for (i=0;i<ev.createdLinks.length;i++) {
inverseEv.removedLinks.push(ev.createdLinks[i]);
RED.nodes.removeLink(ev.createdLinks[i]);
}
}
} else if (ev.t == "reorder") {
inverseEv = {
t: 'reorder',
order: RED.nodes.getWorkspaceOrder()
};
if (ev.order) {
RED.workspaces.order(ev.order);
}
@@ -316,6 +466,8 @@ RED.history = (function() {
RED.workspaces.refresh();
RED.sidebar.config.refresh();
RED.subflow.refresh();
return inverseEv;
}
}
@@ -323,28 +475,42 @@ RED.history = (function() {
return {
//TODO: this function is a placeholder until there is a 'save' event that can be listened to
markAllDirty: function() {
for (var i=0;i<undo_history.length;i++) {
undo_history[i].dirty = true;
for (var i=0;i<undoHistory.length;i++) {
undoHistory[i].dirty = true;
}
},
list: function() {
return undo_history
return undoHistory;
},
depth: function() {
return undo_history.length;
return undoHistory.length;
},
push: function(ev) {
undo_history.push(ev);
undoHistory.push(ev);
redoHistory = [];
},
pop: function() {
var ev = undo_history.pop();
undoEvent(ev);
var ev = undoHistory.pop();
var rev = undoEvent(ev);
if (rev) {
redoHistory.push(rev);
}
},
peek: function() {
return undo_history[undo_history.length-1];
return undoHistory[undoHistory.length-1];
},
clear: function() {
undo_history = [];
undoHistory = [];
redoHistory = [];
},
redo: function() {
var ev = redoHistory.pop();
if (ev) {
var uev = undoEvent(ev);
if (uev) {
undoHistory.push(uev);
}
}
}
}

View File

@@ -50,8 +50,21 @@ RED.i18n = (function() {
}
},
lang: function() {
// Gets the active message catalog language. This is based on what
// locale the editor is using and what languages are available.
//
var preferredLangs = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
var knownLangs = RED.settings.theme("languages")||["en-US"];
for (var i=0;i<preferredLangs.length;i++) {
if (knownLangs.indexOf(preferredLangs[i]) > -1) {
return preferredLangs[i]
}
}
return 'end-US'
},
loadNodeCatalog: function(namespace,done) {
var languageList = i18n.functions.toLanguages(i18n.detectLanguage());
var languageList = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
var toLoad = languageList.length;
languageList.forEach(function(lang) {
$.ajax({
@@ -73,7 +86,7 @@ RED.i18n = (function() {
},
loadNodeCatalogs: function(done) {
var languageList = i18n.functions.toLanguages(i18n.detectLanguage());
var languageList = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
var toLoad = languageList.length;
languageList.forEach(function(lang) {

View File

@@ -1,6 +1,6 @@
{
"*": {
"ctrl-shift-p":"core:manage-palette",
"alt-shift-p":"core:manage-palette",
"ctrl-f": "core:search",
"ctrl-shift-f": "core:list-flows",
"ctrl-=": "core:zoom-in",
@@ -8,6 +8,7 @@
"ctrl-0": "core:zoom-reset",
"ctrl-enter": "core:confirm-edit-tray",
"ctrl-escape": "core:cancel-edit-tray",
"ctrl-d": "core:deploy-flows",
"ctrl-g i": "core:show-info-tab",
"ctrl-g d": "core:show-debug-tab",
"ctrl-g c": "core:show-config-tab",
@@ -17,17 +18,20 @@
"ctrl-space": "core:toggle-sidebar",
"ctrl-p": "core:toggle-palette",
"ctrl-,": "core:show-user-settings",
"ctrl-alt-l": "core:clear-debug-messages",
"ctrl-alt-r": "core:show-remote-diff",
"ctrl-alt-n": "core:new-project",
"ctrl-alt-o": "core:open-project",
"ctrl-g v": "core:show-version-control-tab",
"ctrl-shift-l": "core:show-event-log"
"ctrl-shift-l": "core:show-event-log",
"ctrl-shift-p":"core:show-action-list"
},
"red-ui-sidebar-node-config": {
"backspace": "core:delete-config-selection",
"delete": "core:delete-config-selection",
"ctrl-a": "core:select-all-config-nodes",
"ctrl-z": "core:undo"
"ctrl-z": "core:undo",
"ctrl-y": "core:redo"
},
"red-ui-workspace": {
"backspace": "core:delete-selection",
@@ -37,6 +41,7 @@
"ctrl-x": "core:cut-selection-to-internal-clipboard",
"ctrl-v": "core:paste-from-internal-clipboard",
"ctrl-z": "core:undo",
"ctrl-y": "core:redo",
"ctrl-a": "core:select-all-nodes",
"shift-?": "core:show-help",
"up": "core:move-selection-up",

View File

@@ -17,6 +17,8 @@ RED.nodes = (function() {
var node_defs = {};
var nodes = [];
var nodeTabMap = {};
var configNodes = {};
var links = [];
var defaultWorkspace;
@@ -213,6 +215,11 @@ RED.nodes = (function() {
n.i = nextId+1;
}
nodes.push(n);
if (nodeTabMap[n.z]) {
nodeTabMap[n.z][n.id] = n;
} else {
console.warn("Node added to unknown tab/subflow:",n);
}
}
RED.events.emit('nodes:add',n);
}
@@ -246,6 +253,9 @@ RED.nodes = (function() {
node = getNode(id);
if (node) {
nodes.splice(nodes.indexOf(node),1);
if (nodeTabMap[node.z]) {
delete nodeTabMap[node.z][node.id];
}
removedLinks = links.filter(function(l) { return (l.source === node) || (l.target === node); });
removedLinks.forEach(function(l) {links.splice(links.indexOf(l), 1); });
var updatedConfigNode = false;
@@ -291,6 +301,17 @@ RED.nodes = (function() {
return {links:removedLinks,nodes:removedNodes};
}
function moveNodeToTab(node, z) {
if (nodeTabMap[node.z]) {
delete nodeTabMap[node.z][node.id];
}
if (!nodeTabMap[z]) {
nodeTabMap[z] = {};
}
nodeTabMap[z][node.id] = node;
node.z = z;
}
function removeLink(l) {
var index = links.indexOf(l);
if (index != -1) {
@@ -300,6 +321,8 @@ RED.nodes = (function() {
function addWorkspace(ws,targetIndex) {
workspaces[ws.id] = ws;
nodeTabMap[ws.id] = {};
ws._def = RED.nodes.getType('tab');
if (targetIndex === undefined) {
workspacesOrder.push(ws.id);
@@ -312,6 +335,7 @@ RED.nodes = (function() {
}
function removeWorkspace(id) {
delete workspaces[id];
delete nodeTabMap[id];
workspacesOrder.splice(workspacesOrder.indexOf(id),1);
var removedNodes = [];
@@ -357,30 +381,32 @@ RED.nodes = (function() {
sf.name = subflowName;
}
subflows[sf.id] = sf;
nodeTabMap[sf.id] = {};
RED.nodes.registerType("subflow:"+sf.id, {
defaults:{
name:{value:""},
env:{value:[]}
},
icon: function() { return sf.icon||"subflow.png" },
icon: function() { return sf.icon||"subflow.svg" },
category: sf.category || "subflows",
inputs: sf.in.length,
outputs: sf.out.length,
color: "#da9",
color: sf.color || "#DDAA99",
label: function() { return this.name||RED.nodes.subflow(sf.id).name },
labelStyle: function() { return this.name?"red-ui-flow-node-label-italic":""; },
paletteLabel: function() { return RED.nodes.subflow(sf.id).name },
inputLabels: function(i) { return sf.inputLabels?sf.inputLabels[i]:null },
outputLabels: function(i) { return sf.outputLabels?sf.outputLabels[i]:null },
oneditresize: function(size) {
var rows = $("#dialog-form>div:not(.node-input-env-container-row)");
// var rows = $(".dialog-form>div:not(.node-input-env-container-row)");
var height = size.height;
for (var i=0; i<rows.size(); i++) {
height -= $(rows[i]).outerHeight(true);
}
var editorRow = $("#dialog-form>div.node-input-env-container-row");
height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
$("#node-input-env-container").editableList('height',height-80);
// for (var i=0; i<rows.size(); i++) {
// height -= $(rows[i]).outerHeight(true);
// }
// var editorRow = $("#dialog-form>div.node-input-env-container-row");
// height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
$("ol.red-ui-editor-subflow-env-list").editableList('height',height);
},
set:{
module: "node-red"
@@ -393,6 +419,7 @@ RED.nodes = (function() {
}
function removeSubflow(sf) {
delete subflows[sf.id];
delete nodeTabMap[sf.id];
registry.removeNodeType("subflow:"+sf.id);
}
@@ -463,7 +490,9 @@ RED.nodes = (function() {
node.id = n.id;
node.type = n.type;
node.z = n.z;
if (n.d === true) {
node.d = true;
}
if (node.type == "unknown") {
for (var p in n._orig) {
if (n._orig.hasOwnProperty(p)) {
@@ -549,6 +578,7 @@ RED.nodes = (function() {
node.in = [];
node.out = [];
node.env = n.env;
node.color = n.color;
n.in.forEach(function(p) {
var nIn = {x:p.x,y:p.y,wires:[]};
@@ -581,7 +611,7 @@ RED.nodes = (function() {
node.outputLabels = n.outputLabels.slice();
}
if (n.icon) {
if (n.icon !== "node-red/subflow.png") {
if (n.icon !== "node-red/subflow.svg") {
node.icon = n.icon;
}
}
@@ -815,7 +845,7 @@ RED.nodes = (function() {
var m = /^subflow:(.+)$/.exec(newNodes[i].type);
if (m) {
var subflowId = m[1];
var parent = getSubflow(newNodes[i].z || activeWorkspace);
var parent = getSubflow(activeWorkspace);
if (parent) {
var err;
if (subflowId === parent.id) {
@@ -967,6 +997,9 @@ RED.nodes = (function() {
users:[],
_config:{}
};
if (n.hasOwnProperty('d')) {
configNode.d = n.d;
}
for (d in def.defaults) {
if (def.defaults.hasOwnProperty(d)) {
configNode[d] = n[d];
@@ -1016,6 +1049,9 @@ RED.nodes = (function() {
if (n.hasOwnProperty('l')) {
node.l = n.l;
}
if (n.hasOwnProperty('d')) {
node.d = n.d;
}
if (createNewIds) {
if (subflow_blacklist[n.z]) {
continue;
@@ -1158,6 +1194,7 @@ RED.nodes = (function() {
var nodeTypeArrayReferences = {
"catch":"scope",
"status":"scope",
"complete": "scope",
"link in":"links",
"link out":"links"
}
@@ -1258,13 +1295,22 @@ RED.nodes = (function() {
// TODO: supports filter.z|type
function filterNodes(filter) {
var result = [];
var searchSet = nodes;
var doZFilter = false;
if (filter.hasOwnProperty("z")) {
if (Object.hasOwnProperty("values") && nodeTabMap.hasOwnProperty(filter.z) ) {
searchSet = Object.values(nodeTabMap[filter.z]);
} else {
doZFilter = true;
}
}
for (var n=0;n<nodes.length;n++) {
var node = nodes[n];
if (filter.hasOwnProperty("z") && node.z !== filter.z) {
for (var n=0;n<searchSet.length;n++) {
var node = searchSet[n];
if (filter.hasOwnProperty("type") && node.type !== filter.type) {
continue;
}
if (filter.hasOwnProperty("type") && node.type !== filter.type) {
if (doZFilter && node.z !== filter.z) {
continue;
}
result.push(node);
@@ -1331,6 +1377,7 @@ RED.nodes = (function() {
function clear() {
nodes = [];
links = [];
nodeTabMap = {};
configNodes = {};
workspacesOrder = [];
var subflowIds = Object.keys(subflows);
@@ -1440,6 +1487,8 @@ RED.nodes = (function() {
remove: removeNode,
clear: clear,
moveNodeToTab: moveNodeToTab,
addLink: addLink,
removeLink: removeLink,

View File

@@ -107,9 +107,12 @@ var RED = (function() {
}
function loadNodes() {
var lang = localStorage.getItem("editor-language")||i18n.detectLanguage();
$.ajax({
headers: {
"Accept":"text/html"
"Accept":"text/html",
"Accept-Language": lang
},
cache: false,
url: 'nodes',
@@ -415,8 +418,6 @@ var RED = (function() {
RED.notify(RED._("palette.event.nodeUpgraded", {module:msg.module,version:msg.version}),"success");
RED.nodes.registry.setModulePendingUpdated(msg.module,msg.version);
}
// Refresh flow library to ensure any examples are updated
RED.library.loadFlowLibrary();
});
RED.comms.subscribe("event-log/#", function(topic,payload) {
var id = topic.substring(9);
@@ -448,11 +449,16 @@ var RED = (function() {
{id:"menu-item-palette",label:RED._("menu.label.palette.show"),toggle:true,onselect:"core:toggle-palette", selected: true},
{id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true},
{id:"menu-item-event-log",label:RED._("eventLog.title"),onselect:"core:show-event-log"},
{id:"menu-item-action-list",label:RED._("keyboard.actionList"),onselect:"core:show-action-list"},
null
]});
menuOptions.push(null);
menuOptions.push({id:"menu-item-import",label:RED._("menu.label.import"),onselect:"core:show-import-dialog"});
menuOptions.push({id:"menu-item-export",label:RED._("menu.label.export"),onselect:"core:show-export-dialog"});
if (RED.settings.theme("menu.menu-item-import-library", true)) {
menuOptions.push({id: "menu-item-import", label: RED._("menu.label.import"), onselect: "core:show-import-dialog"});
}
if (RED.settings.theme("menu.menu-item-export-library", true)) {
menuOptions.push({id: "menu-item-export", label: RED._("menu.label.export"), onselect: "core:show-export-dialog"});
}
menuOptions.push(null);
menuOptions.push({id:"menu-item-search",label:RED._("menu.label.search"),onselect:"core:search"});
menuOptions.push(null);
@@ -475,7 +481,9 @@ var RED = (function() {
menuOptions.push({id:"menu-item-user-settings",label:RED._("menu.label.settings"),onselect:"core:show-user-settings"});
menuOptions.push(null);
menuOptions.push({id:"menu-item-keyboard-shortcuts",label:RED._("menu.label.keyboardShortcuts"),onselect:"core:show-help"});
if (RED.settings.theme("menu.menu-item-keyboard-shortcuts", true)) {
menuOptions.push({id: "menu-item-keyboard-shortcuts", label: RED._("menu.label.keyboardShortcuts"), onselect: "core:show-help"});
}
menuOptions.push({id:"menu-item-help",
label: RED.settings.theme("menu.menu-item-help.label",RED._("menu.label.help")),
href: RED.settings.theme("menu.menu-item-help.url","http://nodered.org/docs")
@@ -518,6 +526,7 @@ var RED = (function() {
RED.subflow.init();
RED.clipboard.init();
RED.search.init();
RED.actionList.init();
RED.editor.init();
RED.diff.init();

View File

@@ -56,8 +56,9 @@ RED.settings = (function () {
if (key === "auth-tokens") {
return JSON.parse(localStorage.getItem(key));
} else {
var v;
try {
var v = RED.utils.getMessageProperty(userSettings,key);
v = RED.utils.getMessageProperty(userSettings,key);
if (v === undefined) {
v = defaultIfUndefined;
}

View File

@@ -0,0 +1,230 @@
/**
* Copyright JS Foundation and other contributors, http://js.foundation
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
**/
RED.actionList = (function() {
var disabled = false;
var dialog = null;
var searchInput;
var searchResults;
var selected = -1;
var visible = false;
var filterTerm = "";
var filterTerms = [];
var previousActiveElement;
function ensureSelectedIsVisible() {
var selectedEntry = searchResults.find("li.selected");
if (selectedEntry.length === 1) {
var scrollWindow = searchResults.parent();
var scrollHeight = scrollWindow.height();
var scrollOffset = scrollWindow.scrollTop();
var y = selectedEntry.position().top;
var h = selectedEntry.height();
if (y+h > scrollHeight) {
scrollWindow.animate({scrollTop: '-='+(scrollHeight-(y+h)-10)},50);
} else if (y<0) {
scrollWindow.animate({scrollTop: '+='+(y-10)},50);
}
}
}
function createDialog() {
dialog = $("<div>",{id:"red-ui-actionList",class:"red-ui-search"}).appendTo("#red-ui-main-container");
var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(dialog);
searchInput = $('<input type="text" data-i18n="[placeholder]keyboard.filterActions">').appendTo(searchDiv).searchBox({
change: function() {
filterTerm = $(this).val().trim();
filterTerms = filterTerm.split(" ");
searchResults.editableList('filter');
searchResults.find("li.selected").removeClass("selected");
var children = searchResults.children(":visible");
if (children.length) {
$(children[0]).addClass('selected');
}
}
});
searchInput.on('keydown',function(evt) {
var selectedChild;
if (evt.keyCode === 40) {
// Down
selectedChild = searchResults.find("li.selected");
if (!selectedChild.length) {
var children = searchResults.children(":visible");
if (children.length) {
$(children[0]).addClass('selected');
}
} else {
var nextChild = selectedChild.nextAll(":visible").first();
if (nextChild.length) {
selectedChild.removeClass('selected');
nextChild.addClass('selected');
}
}
ensureSelectedIsVisible();
evt.preventDefault();
} else if (evt.keyCode === 38) {
// Up
selectedChild = searchResults.find("li.selected");
var nextChild = selectedChild.prevAll(":visible").first();
if (nextChild.length) {
selectedChild.removeClass('selected');
nextChild.addClass('selected');
}
ensureSelectedIsVisible();
evt.preventDefault();
} else if (evt.keyCode === 13) {
// Enter
selectedChild = searchResults.find("li.selected");
selectCommand(searchResults.editableList('getItem',selectedChild));
}
});
searchInput.i18n();
var searchResultsDiv = $("<div>",{class:"red-ui-search-results-container"}).appendTo(dialog);
searchResults = $('<ol>',{style:"position: absolute;top: 5px;bottom: 5px;left: 5px;right: 5px;"}).appendTo(searchResultsDiv).editableList({
addButton: false,
addItem: function(container,i,action) {
if (action.id === undefined) {
$('<div>',{class:"red-ui-search-empty"}).text(RED._('search.empty')).appendTo(container);
} else {
var div = $('<a>',{href:'#',class:"red-ui-search-result"}).appendTo(container);
var contentDiv = $('<div>',{class:"red-ui-search-result-action"}).appendTo(div);
$('<div>').text(action.label).appendTo(contentDiv);
// $('<div>',{class:"red-ui-search-result-node-type"}).text(node.type).appendTo(contentDiv);
// $('<div>',{class:"red-ui-search-result-node-id"}).text(node.id).appendTo(contentDiv);
if (action.key) {
$('<div>',{class:"red-ui-search-result-action-key"}).html(RED.keyboard.formatKey(action.key)).appendTo(contentDiv);
}
div.on("click", function(evt) {
evt.preventDefault();
selectCommand(action);
});
}
},
scrollOnAdd: false,
filter: function(item) {
if (filterTerm !== "") {
var pos=0;
for (var i=0;i<filterTerms.length;i++) {
var j = item._label.indexOf(filterTerms[i],pos);
if (j > -1) {
pos = j;
} else {
return false;
}
}
return true;
}
return true;
}
});
}
function selectCommand(command) {
hide();
if (command) {
RED.actions.invoke(command.id);
}
}
function show(v) {
if (disabled) {
return;
}
if (!visible) {
previousActiveElement = document.activeElement;
RED.keyboard.add("*","escape",function(){hide()});
$("#red-ui-header-shade").show();
$("#red-ui-editor-shade").show();
$("#red-ui-palette-shade").show();
$("#red-ui-sidebar-shade").show();
$("#red-ui-sidebar-separator").hide();
if (dialog === null) {
createDialog();
}
dialog.slideDown(300);
searchInput.searchBox('value',v)
searchResults.editableList('empty');
results = [];
var actions = RED.actions.list();
actions.sort(function(A,B) {
return A.id.localeCompare(B.id);
});
actions.forEach(function(action) {
action.label = action.id.replace(/:/,": ").replace(/-/g," ").replace(/(^| )./g,function() { return arguments[0].toUpperCase()});
action._label = action.label.toLowerCase();
searchResults.editableList('addItem',action)
})
RED.events.emit("actionList:open");
visible = true;
}
searchInput.trigger("focus");
var children = searchResults.children(":visible");
if (children.length) {
$(children[0]).addClass('selected');
}
}
function hide() {
if (visible) {
RED.keyboard.remove("escape");
visible = false;
$("#red-ui-header-shade").hide();
$("#red-ui-editor-shade").hide();
$("#red-ui-palette-shade").hide();
$("#red-ui-sidebar-shade").hide();
$("#red-ui-sidebar-separator").show();
if (dialog !== null) {
dialog.slideUp(200,function() {
searchInput.searchBox('value','');
});
}
RED.events.emit("actionList:close");
if (previousActiveElement) {
$(previousActiveElement).trigger("focus");
previousActiveElement = null;
}
}
}
function init() {
RED.actions.add("core:show-action-list",show);
RED.events.on("editor:open",function() { disabled = true; });
RED.events.on("editor:close",function() { disabled = false; });
RED.events.on("search:open",function() { disabled = true; });
RED.events.on("search:close",function() { disabled = false; });
RED.events.on("type-search:open",function() { disabled = true; });
RED.events.on("type-search:close",function() { disabled = false; });
$("#red-ui-header-shade").on('mousedown',hide);
$("#red-ui-editor-shade").on('mousedown',hide);
$("#red-ui-palette-shade").on('mousedown',hide);
$("#red-ui-sidebar-shade").on('mousedown',hide);
}
return {
init: init,
show: show,
hide: hide
};
})();

View File

@@ -59,7 +59,7 @@ RED.clipboard = (function() {
element.setAttribute('download', "flows.json");
element.style.display = 'none';
document.body.appendChild(element);
element.trigger("click");
element.click();
document.body.removeChild(element);
$( this ).dialog( "close" );
}
@@ -396,14 +396,6 @@ RED.clipboard = (function() {
label: RED._("library.types.examples")
});
tabs.activateTab("red-ui-clipboard-dialog-import-tab-"+mode);
if (mode === 'clipboard') {
setTimeout(function() {
$("#red-ui-clipboard-dialog-import-text").trigger("focus");
},100)
}
$("#red-ui-clipboard-dialog-tab-library-name").on("keyup", validateExportFilename);
$("#red-ui-clipboard-dialog-tab-library-name").on('paste',function() { setTimeout(validateExportFilename,10)});
$("#red-ui-clipboard-dialog-export").button("enable");
@@ -475,6 +467,14 @@ RED.clipboard = (function() {
$("#red-ui-clipboard-dialog-import-file-upload").trigger("click");
})
tabs.activateTab("red-ui-clipboard-dialog-import-tab-"+mode);
if (mode === 'clipboard') {
setTimeout(function() {
$("#red-ui-clipboard-dialog-import-text").trigger("focus");
},100)
}
dialog.dialog("option","title",RED._("clipboard.importNodes")).dialog("open");
popover = RED.popover.create({
target: $("#red-ui-clipboard-dialog-import-text"),
@@ -521,8 +521,6 @@ RED.clipboard = (function() {
label: RED._("library.library")
});
tabs.activateTab("red-ui-clipboard-dialog-export-tab-"+mode);
$("#red-ui-clipboard-dialog-tab-library-name").on("keyup", validateExportFilename);
$("#red-ui-clipboard-dialog-tab-library-name").on('paste',function() { setTimeout(validateExportFilename,10)});
$("#red-ui-clipboard-dialog-export").button("enable");
@@ -638,6 +636,7 @@ RED.clipboard = (function() {
} else {
$("#red-ui-clipboard-dialog-export-fmt-mini").trigger("click");
}
tabs.activateTab("red-ui-clipboard-dialog-export-tab-"+mode);
dialog.dialog("option","title",RED._("clipboard.exportNodes")).dialog( "open" );
$("#red-ui-clipboard-dialog-export-text").trigger("focus");
@@ -655,7 +654,7 @@ RED.clipboard = (function() {
// icon: 'fa fa-hdd-o',
// label: RED._("library.types.examples"),
// path: "",
// children: function(item,done) {
// children: function(done,item) {
// RED.library.loadLibraryFolder("_examples_","flows","",function(children) {
// item.children = children;
// done(children);
@@ -670,13 +669,14 @@ RED.clipboard = (function() {
label: label,
path: "",
expanded: true,
children: function(item,done) {
children: function(done, item) {
RED.library.loadLibraryFolder(library,"flows","",function(children) {
item.children = children;
done(children);
})
}
}]);
}], true);
}
function hideDropTarget() {
@@ -730,17 +730,20 @@ RED.clipboard = (function() {
init: function() {
setupDialogs();
$('<input type="text" id="red-ui-clipboard-hidden">').appendTo("#red-ui-editor");
$('<input type="text" id="red-ui-clipboard-hidden" tabIndex="-1">').appendTo("#red-ui-editor");
RED.actions.add("core:show-export-dialog",exportNodes);
RED.actions.add("core:show-import-dialog",importNodes);
RED.actions.add("core:library-export",function() { exportNodes('library') });
RED.actions.add("core:show-library-export-dialog",function() { exportNodes('library') });
RED.actions.add("core:show-library-import-dialog",function() { importNodes('library') });
RED.events.on("editor:open",function() { disabled = true; });
RED.events.on("editor:close",function() { disabled = false; });
RED.events.on("search:open",function() { disabled = true; });
RED.events.on("search:close",function() { disabled = false; });
RED.events.on("actionList:open",function() { disabled = true; });
RED.events.on("actionList:close",function() { disabled = false; });
RED.events.on("type-search:open",function() { disabled = true; });
RED.events.on("type-search:close",function() { disabled = false; });

View File

@@ -32,7 +32,10 @@
* - scrollOnAdd : boolean - whether to scroll to newly added items
* methods:
* - addItem(itemData)
* - insertItemAt : function(data,index) - add an item at the specified index
* - removeItem(itemData)
* - getItemAt(index)
* - indexOf(itemData)
* - width(width)
* - height(height)
* - items()
@@ -185,6 +188,11 @@
}
},
_destroy: function() {
if (this.topContainer) {
var tc = this.topContainer;
delete this.topContainer;
tc.remove();
}
},
_refreshFilter: function() {
var that = this;
@@ -230,7 +238,24 @@
this.uiHeight = desiredHeight;
this._resize();
},
addItem: function(data) {
getItemAt: function(index) {
var items = this.items();
if (index >= 0 && index < items.length) {
return $(items[index]).data('data');
} else {
return;
}
},
indexOf: function(data) {
var items = this.items();
for (var i=0;i<items.length;i++) {
if ($(items[i]).data('data') === data) {
return i
}
}
return -1
},
insertItemAt: function(data,index) {
var that = this;
data = data || {};
var li = $('<li>');
@@ -248,7 +273,13 @@
});
}
if (!added) {
li.appendTo(this.element);
if (index <= 0) {
li.prependTo(this.element);
} else if (index > that.element.children().length-1) {
li.appendTo(this.element);
} else {
li.insertBefore(this.element.children().eq(index));
}
}
var row = $('<div/>').addClass("red-ui-editableList-item-content").appendTo(li);
row.data('data',data);
@@ -293,6 +324,9 @@
},0);
}
},
addItem: function(data) {
this.insertItemAt(data,this.element.children().length)
},
addItems: function(items) {
for (var i=0; i<items.length;i++) {
this.addItem(items[i]);
@@ -312,6 +346,7 @@
},
empty: function() {
this.element.empty();
this.uiContainer.scrollTop(0);
},
filter: function(filter) {
if (filter !== undefined) {
@@ -335,6 +370,14 @@
if (items.length > 0) {
this.uiContainer.scrollTop(this.uiContainer.scrollTop()+items.position().top)
}
},
getItem: function(li) {
var el = li.find(".red-ui-editableList-item-content");
if (el.length) {
return el.data('data');
} else {
return null;
}
}
});
})(jQuery);

View File

@@ -71,7 +71,7 @@ RED.menu = (function() {
}
if (opt.icon !== undefined) {
if (/\.png/.test(opt.icon)) {
if (/\.(png|svg)/.test(opt.icon)) {
linkContent += '<img src="'+opt.icon+'"/> ';
} else {
linkContent += '<i class="'+(opt.icon?opt.icon:'" style="display: inline-block;"')+'"></i> ';
@@ -98,21 +98,10 @@ RED.menu = (function() {
return;
}
if (opt.toggle) {
var selected = isSelected(opt.id);
if (typeof opt.toggle === "string") {
if (!selected) {
for (var m in menuItems) {
if (menuItems.hasOwnProperty(m)) {
var mi = menuItems[m];
if (mi.id != opt.id && opt.toggle == mi.toggle) {
setSelected(mi.id,false);
}
}
}
setSelected(opt.id,true);
}
if (opt.toggle === true) {
setSelected(opt.id, !isSelected(opt.id));
} else {
setSelected(opt.id, !selected);
setSelected(opt.id, true);
}
} else {
triggerAction(opt.id);
@@ -209,8 +198,9 @@ RED.menu = (function() {
}
function setSelected(id,state) {
var alreadySet = false;
if (isSelected(id) == state) {
return;
alreadySet = true;
}
var opt = menuItems[id];
if (state) {
@@ -218,10 +208,26 @@ RED.menu = (function() {
} else {
$("#"+id).removeClass("active");
}
if (opt && opt.onselect) {
triggerAction(opt.id,state);
if (opt) {
if (opt.toggle && typeof opt.toggle === "string") {
if (state) {
for (var m in menuItems) {
if (menuItems.hasOwnProperty(m)) {
var mi = menuItems[m];
if (mi.id != opt.id && opt.toggle == mi.toggle) {
setSelected(mi.id,false);
}
}
}
}
}
if (!alreadySet && opt.onselect) {
triggerAction(opt.id,state);
}
if (!opt.local && !alreadySet) {
RED.settings.set(opt.setting||("menu-"+opt.id), state);
}
}
RED.settings.set(opt.setting||("menu-"+opt.id), state);
}
function toggleSelected(id) {
@@ -238,7 +244,7 @@ RED.menu = (function() {
function addItem(id,opt) {
var item = createMenuItem(opt);
if (opt.group) {
if (opt !== null && opt.group) {
var groupItems = $("#"+id+"-submenu").children(".red-ui-menu-group-"+opt.group);
if (groupItems.length === 0) {
item.appendTo("#"+id+"-submenu");

View File

@@ -52,6 +52,11 @@ RED.popover = (function() {
var openPopup = function(instant) {
if (active) {
var existingPopover = target.data("red-ui-popover");
if (options.tooltip && existingPopover) {
active = false;
return;
}
div = $('<div class="red-ui-popover"></div>');
if (size !== "default") {
div.addClass("red-ui-popover-size-"+size);
@@ -122,7 +127,15 @@ RED.popover = (function() {
}
}
div.addClass('red-ui-popover-'+d).css({top: top, left: left});
if (existingPopover) {
existingPopover.close(true);
}
target.data("red-ui-popover",res)
if (options.tooltip) {
div.on("mousedown", function(evt) {
closePopup(true);
});
}
if (instant) {
div.show();
} else {
@@ -142,6 +155,7 @@ RED.popover = (function() {
});
}
div = null;
target.removeData("red-ui-popover",res)
}
}
}
@@ -236,6 +250,7 @@ RED.popover = (function() {
}
}
return RED.popover.create({
tooltip: true,
target:target,
trigger: "hover",
size: "small",
@@ -243,6 +258,71 @@ RED.popover = (function() {
content: label,
delay: { show: 750, hide: 50 }
});
},
panel: function(content) {
var panel = $('<div class="red-ui-editor-dialog red-ui-popover-panel"></div>');
panel.css({ display: "none" });
panel.appendTo(document.body);
content.appendTo(panel);
var closeCallback;
function hide() {
$(document).off("mousedown.red-ui-popover-panel-close");
panel.hide();
panel.css({
height: "auto"
});
panel.remove();
}
function show(options) {
var closeCallback = options.onclose;
var target = options.target;
var align = options.align || "left";
var pos = target.offset();
var targetWidth = target.width();
var targetHeight = target.height();
var panelHeight = panel.height();
var panelWidth = panel.width();
var top = (targetHeight+pos.top);
if (top+panelHeight > $(window).height()) {
top -= (top+panelHeight)-$(window).height() + 5;
}
if (top < 0) {
panelHeight.height(panelHeight+top)
top = 0;
}
if (align === "left") {
panel.css({
top: top+"px",
left: (pos.left)+"px",
});
} else if(align === "right") {
panel.css({
top: top+"px",
left: (pos.left-panelWidth)+"px",
});
}
panel.slideDown(100);
$(document).on("mousedown.red-ui-popover-panel-close", function(event) {
if(!$(event.target).closest(panel).length && !$(event.target).closest(".red-ui-editor-dialog").length) {
if (closeCallback) {
closeCallback();
}
hide();
}
// if ($(event.target).closest(target).length) {
// event.preventDefault();
// }
})
}
return {
container: panel,
show:show,
hide:hide
}
}
}

View File

@@ -87,6 +87,7 @@
that._trigger("change");
},this.options.delay);
} else {
this.lastSent = this.element.val();
this._trigger("change");
}
}

View File

@@ -19,6 +19,9 @@
RED.tabs = (function() {
var defaultTabIcon = "fa fa-lemon-o";
var dragActive = false;
var dblClickTime;
var dblClickArmed = false;
function createTabs(options) {
var tabs = {};
@@ -201,12 +204,21 @@ RED.tabs = (function() {
}
function onTabClick(evt) {
evt.preventDefault();
if (dragActive) {
return
}
if (dblClickTime && Date.now()-dblClickTime < 400) {
dblClickTime = 0;
dblClickArmed = true;
return onTabDblClick.call(this,evt);
}
dblClickTime = Date.now();
var currentTab = ul.find("li.red-ui-tab.active");
var thisTab = $(this).parent();
var fireSelectionChanged = false;
if (options.onselect) {
if (evt.metaKey) {
if (evt.metaKey || evt.ctrlKey) {
if (thisTab.hasClass("selected")) {
thisTab.removeClass("selected");
if (thisTab[0] !== currentTab[0]) {
@@ -267,7 +279,6 @@ RED.tabs = (function() {
if (fireSelectionChanged) {
selectionChanged();
}
return false;
}
function updateScroll() {
@@ -289,7 +300,6 @@ RED.tabs = (function() {
}
function onTabDblClick(evt) {
evt.preventDefault();
evt.stopPropagation();
if (evt.metaKey || evt.shiftKey) {
return;
}
@@ -418,7 +428,11 @@ RED.tabs = (function() {
}
ul.find("li.red-ui-tab a").on("click",onTabClick).on("dblclick",onTabDblClick);
ul.find("li.red-ui-tab a")
.on("mouseup",onTabClick)
.on("click", function(evt) {evt.preventDefault(); })
.on("dblclick", function(evt) {evt.stopPropagation(); evt.preventDefault(); })
setTimeout(function() {
updateTabWidths();
},0);
@@ -524,8 +538,9 @@ RED.tabs = (function() {
RED.popover.tooltip($(pinnedLink), tab.name, tab.action);
}
link.on("click",onTabClick);
link.on("dblclick",onTabDblClick);
link.on("mouseup",onTabClick);
link.on("click", function(evt) { evt.preventDefault(); })
link.on("dblclick", function(evt) { evt.stopPropagation(); evt.preventDefault(); })
if (tab.closeable) {
@@ -560,6 +575,8 @@ RED.tabs = (function() {
axis:"x",
distance: 20,
start: function(event,ui) {
if (dblClickArmed) { dblClickArmed = false; return false }
dragActive = true;
originalTabOrder = [];
tabElements = [];
ul.children().each(function(i) {
@@ -615,6 +632,7 @@ RED.tabs = (function() {
}
},
stop: function(event,ui) {
dragActive = false;
ul.children().css({position:"relative",left:"",transition:""});
if (!li.hasClass('active')) {
li.css({zIndex:""});

View File

@@ -39,15 +39,14 @@
var baseClass = this.options.baseClass || "red-ui-button";
var enabledIcon = this.options.enabledIcon || "fa-check-square-o";
var disabledIcon = this.options.disabledIcon || "fa-square-o";
var enabledLabel = this.options.enabledLabel || RED._("editor:workspace.enabled");
var disabledLabel = this.options.disabledLabel || RED._("editor:workspace.disabled");
var enabledLabel = this.options.hasOwnProperty('enabledLabel') ? this.options.enabledLabel : RED._("editor:workspace.enabled");
var disabledLabel = this.options.hasOwnProperty('disabledLabel') ? this.options.disabledLabel : RED._("editor:workspace.disabled");
this.element.addClass("red-ui-toggleButton");
this.element.css("display","none");
this.element.on("focus", function() {
that.button.focus();
});
this.button = $('<button type="button" class="'+baseClass+' toggle single"><i class="fa"></i> <span></span></button>');
this.button = $('<button type="button" class="red-ui-toggleButton '+baseClass+' toggle single"><i class="fa"></i> <span></span></button>');
if (this.options.class) {
this.button.addClass(this.options.class)
}

View File

@@ -20,6 +20,10 @@
* - data : array - initial items to display in tree
* - multi : boolean - if true, .selected will return an array of results
* otherwise, returns the first selected item
* - sortable: boolean/string - TODO: see editableList
* - rootSortable: boolean - if 'sortable' is set, then setting this to
* false, prevents items being sorted to the
* top level of the tree
*
* methods:
* - data(items) - clears existing items and replaces with new data
@@ -27,25 +31,57 @@
* events:
* - treelistselect : function(event, item) {}
* - treelistconfirm : function(event,item) {}
* - treelistchangeparent: function(event,item, oldParent, newParent) {}
*
* data:
* [
* {
* label: 'Local', // label for the item
* sublabel: 'Local', // a sub-label for the item
* icon: 'fa fa-rocket', // (optional) icon for the item
* selected: true/false, // (optional) if present, display checkbox accordingly
* children: [] | function(item,done) // (optional) an array of child items, or a function
* children: [] | function(done,item) // (optional) an array of child items, or a function
* // that will call the `done` callback with an array
* // of child items
* expanded: true/false, // show the child items by default
* deferBuild: true/false, // don't build any ui elements for the item's children
* until it is expanded by the user.
* element: // custom dom element to use for the item - ignored if `label` is set
* }
* ]
*
*
*
* var treeList = $("<div>").css({width: "100%", height: "100%"}).treeList({data:[...]})
* treeList.on('treelistselect', function(e,item) { console.log(item)})
* treeList.treeList('data',[ ... ] )
*
*
* After `data` has been added to the tree, each item is augmented the following
* properties and functions:
*
* item.parent - set to the parent item
* item.treeList.container
* item.treeList.label - the label element for the item
* item.treeList.depth - the depth in the tree (0 == root)
* item.treeList.parentList - the editableList instance this item is in
* item.treeList.remove() - removes the item from the tree
* item.treeList.makeLeaf(detachChildElements) - turns an element with children into a leaf node,
* removing the UI decoration etc.
* detachChildElements - any children with custom
* elements will be detached rather than removed
* so jQuery event handlers are preserved in case
* the child elements need to be reattached later
* item.treeList.makeParent(children) - turns an element into a parent node, adding the necessary
* UI decoration.
* item.treeList.insertChildAt(newItem,position,select) - adds a child item an the specified position.
* Optionally selects the item after adding.
* item.treeList.addChild(newItem,select) - appends a child item.
* Optionally selects the item after adding.
* item.treeList.expand(done) - expands the parent item to show children. Optional 'done' callback.
* item.treeList.collapse() - collapse the parent item to hide children.
*
*
*
*
*/
$.widget( "nodered.treeList", {
@@ -116,20 +152,30 @@
});
this._data = [];
this._topList = $('<ol>').css({
this._topList = $('<ol class="red-ui-treeList-list">').css({
position:'absolute',
top: 0,
left:0,
right:0,
bottom:0
}).appendTo(wrapper).editableList({
}).appendTo(wrapper);
var topListOptions = {
addButton: false,
scrollOnAdd: false,
height: '100%',
addItem: function(container,i,item) {
that._addSubtree(that._topList,container,item,0);
}
})
};
if (this.options.rootSortable !== false && !!this.options.sortable) {
topListOptions.sortable = this.options.sortable;
topListOptions.connectWith = '.red-ui-treeList-sortable';
this._topList.addClass('red-ui-treeList-sortable');
}
this._topList.editableList(topListOptions)
if (this.options.data) {
this.data(this.options.data);
}
@@ -171,23 +217,82 @@
},
_addChildren: function(container,parent,children,depth) {
var that = this;
var subtree = $('<ol>').appendTo(container).editableList({
var subtree = $('<ol class="red-ui-treeList-list">').appendTo(container).editableList({
connectWith: ".red-ui-treeList-sortable",
sortable: that.options.sortable,
addButton: false,
scrollOnAdd: false,
height: 'auto',
addItem: function(container,i,item) {
that._addSubtree(subtree,container,item,depth+1);
},
sortItems: function(data) {
var children = [];
var reparented = [];
data.each(function() {
var child = $(this).data('data');
children.push(child);
var evt = that._fixDepths(parent,child);
if (evt) {
reparented.push(evt);
}
})
if (Array.isArray(parent.children)) {
parent.children = children;
}
reparented.forEach(function(evt) {
that._trigger("changeparent",null,evt);
});
that._trigger("sort",null,parent);
}
});
if (!!that.options.sortable) {
subtree.addClass('red-ui-treeList-sortable');
}
for (var i=0;i<children.length;i++) {
children[i].parent = parent;
subtree.editableList('addItem',children[i])
}
return subtree;
},
_fixDepths: function(parent,child) {
// If child has just been moved into parent in the UI
// this will fix up the internal data structures to match.
// The calling function must take care of getting child
// into the parent.children array. The rest is up to us.
var that = this;
var reparentedEvent = null;
if (child.parent !== parent) {
reparented = true;
var oldParent = child.parent;
child.parent = parent;
reparentedEvent = {
item: child,
old: oldParent,
}
}
if (child.depth !== parent.depth+1) {
child.depth = parent.depth+1;
var labelPaddingWidth = ((child.gutter?child.gutter.width()+2:0)+(child.depth*20));
child.treeList.labelPadding.width(labelPaddingWidth+'px');
if (child.element) {
$(child.element).css({
width: "calc(100% - "+(labelPaddingWidth+20+(child.icon?20:0))+"px)"
})
}
// This corrects all child item depths
if (child.children && Array.isArray(child.children)) {
child.children.forEach(function(item) {
that._fixDepths(child,item);
})
}
}
return reparentedEvent;
},
_addSubtree: function(parentList, container, item, depth) {
var that = this;
item.treeList = {};
item.treeList.depth = depth;
item.treeList.container = container;
item.treeList.parentList = parentList;
@@ -196,87 +301,80 @@
if (item.parent) {
var index = item.parent.children.indexOf(item);
item.parent.children.splice(index,1)
that._trigger("sort",null,item.parent);
}
}
var labelNodeType = "<div>";
// if (item.children && item.hasOwnProperty('selected')) {
// labelNodeType = "<div>";
// }
var label = $(labelNodeType,{class:"red-ui-treeList-label"}).appendTo(container);
var label = $("<div>",{class:"red-ui-treeList-label"}).appendTo(container);
item.treeList.label = label;
if (item.class) {
label.addClass(item.class);
}
label.css({
paddingLeft: (depth*15)+'px'
})
if (item.gutter) {
item.gutter.css({
position: 'absolute'
}).appendTo(label)
}
var labelPaddingWidth = (item.gutter?item.gutter.width()+2:0)+(depth*20);
item.treeList.labelPadding = $('<span>').css({
display: "inline-block",
width: labelPaddingWidth+'px'
}).appendTo(label);
label.on('mouseover',function(e) { that._trigger('itemmouseover',e,item); })
label.on('mouseout',function(e) { that._trigger('itemmouseout',e,item); })
label.on('mouseenter',function(e) { that._trigger('itemmouseenter',e,item); })
label.on('mouseleave',function(e) { that._trigger('itemmouseleave',e,item); })
if (item.children) {
item.treeList.addChild = function(newItem,select) {
item.treeList.childList.editableList('addItem',newItem)
newItem.parent = item;
item.children.push(newItem);
if (select) {
setTimeout(function() {
that.select(newItem)
},100);
}
item.treeList.makeLeaf = function(detachChildElements) {
if (!treeListIcon.children().length) {
// Already a leaf
return
}
item.treeList.expand = function(done) {
if (container.hasClass("expanded")) {
done && done();
return;
}
if (!container.hasClass("built") && typeof item.children === 'function') {
container.addClass('built');
var childrenAdded = false;
var spinner;
var startTime = 0;
item.children(item,function(children) {
childrenAdded = true;
item.treeList.childList = that._addChildren(container,item,children,depth).hide();
var delta = Date.now() - startTime;
if (delta < 400) {
setTimeout(function() {
item.treeList.childList.slideDown('fast');
if (spinner) {
spinner.remove();
}
},400-delta);
} else {
item.treeList.childList.slideDown('fast');
if (spinner) {
spinner.remove();
if (detachChildElements && item.children) {
var detachChildren = function(item) {
if (item.children) {
item.children.forEach(function(child) {
if (child.element) {
child.element.detach();
}
}
done && done();
that._trigger("childrenloaded",null,item)
});
if (!childrenAdded) {
startTime = Date.now();
spinner = $('<div class="red-ui-treeList-spinner">').css({
"background-position": (35+depth*15)+'px 50%'
}).appendTo(container);
if (child.gutter) {
child.gutter.detach();
}
detachChildren(child);
});
}
} else {
item.treeList.childList.slideDown('fast');
done && done();
}
container.addClass("expanded");
detachChildren(item);
}
item.treeList.collapse = function() {
item.treeList.childList.slideUp('fast');
container.removeClass("expanded");
treeListIcon.empty();
if (!item.deferBuild) {
item.treeList.childList.remove();
delete item.treeList.childList;
}
$('<span class="red-ui-treeList-icon"><i class="fa fa-angle-right" /></span>').appendTo(label);
label.off("click.red-ui-treeList-expand");
treeListIcon.off("click.red-ui-treeList-expand");
delete item.children;
container.removeClass("expanded");
}
item.treeList.makeParent = function(children) {
if (treeListIcon.children().length) {
// Already a parent because we've got the angle-right icon
return;
}
$('<i class="fa fa-angle-right" />').appendTo(treeListIcon);
treeListIcon.on("click.red-ui-treeList-expand", function(e) {
e.stopPropagation();
e.preventDefault();
if (container.hasClass("expanded")) {
item.treeList.collapse();
} else {
item.treeList.expand();
}
});
// $('<span class="red-ui-treeList-icon"><i class="fa fa-folder-o" /></span>').appendTo(label);
label.on("click", function(e) {
label.on("click.red-ui-treeList-expand", function(e) {
if (container.hasClass("expanded")) {
if (item.hasOwnProperty('selected') || label.hasClass("selected")) {
item.treeList.collapse();
@@ -285,9 +383,97 @@
item.treeList.expand();
}
})
} else {
$('<span class="red-ui-treeList-icon"></span>').appendTo(label);
if (!item.children) {
item.children = children||[];
item.treeList.childList = that._addChildren(container,item,item.children,depth).hide();
}
}
item.treeList.insertChildAt = function(newItem,position,select) {
newItem.parent = item;
item.children.splice(position,0,newItem);
if (!item.deferBuild) {
item.treeList.childList.editableList('insertItemAt',newItem,position)
if (select) {
setTimeout(function() {
that.select(newItem)
},100);
}
that._trigger("sort",null,item);
}
}
item.treeList.addChild = function(newItem,select) {
item.treeList.insertChildAt(newItem,item.children.length,select);
}
item.treeList.expand = function(done) {
if (!item.children) {
return;
}
if (container.hasClass("expanded")) {
if (done) { done() }
return;
}
if (!container.hasClass("built") && (item.deferBuild || typeof item.children === 'function')) {
container.addClass('built');
var childrenAdded = false;
var spinner;
var startTime = 0;
var completeBuild = function(children) {
childrenAdded = true;
item.treeList.childList = that._addChildren(container,item,children,depth).hide();
var delta = Date.now() - startTime;
if (delta < 400) {
setTimeout(function() {
item.treeList.childList.slideDown('fast');
if (spinner) {
spinner.remove();
}
},400-delta);
} else {
item.treeList.childList.slideDown('fast');
if (spinner) {
spinner.remove();
}
}
if (done) { done() }
that._trigger("childrenloaded",null,item)
}
if (typeof item.children === 'function') {
item.children(completeBuild,item);
} else {
delete item.deferBuild;
completeBuild(item.children);
}
if (!childrenAdded) {
startTime = Date.now();
spinner = $('<div class="red-ui-treeList-spinner">').css({
"background-position": (35+depth*20)+'px 50%'
}).appendTo(container);
}
} else {
if (that._loadingData) {
item.treeList.childList.show();
} else {
item.treeList.childList.slideDown('fast');
}
if (done) { done() }
}
container.addClass("expanded");
}
item.treeList.collapse = function() {
if (!item.children) {
return;
}
item.treeList.childList.slideUp('fast');
container.removeClass("expanded");
}
var treeListIcon = $('<span class="red-ui-treeList-icon"></span>').appendTo(label);
if (item.children) {
item.treeList.makeParent();
}
if (item.hasOwnProperty('selected')) {
var selectWrapper = $('<span class="red-ui-treeList-icon"></span>').appendTo(label);
var cb = $('<input class="red-ui-treeList-checkbox" type="checkbox">').prop('checked',item.selected).appendTo(selectWrapper);
@@ -326,19 +512,22 @@
if (item.icon) {
$('<span class="red-ui-treeList-icon"><i class="'+item.icon+'" /></span>').appendTo(label);
}
if (item.label || item.sublabel) {
if (item.label) {
if (item.hasOwnProperty('label') || item.hasOwnProperty('sublabel')) {
if (item.hasOwnProperty('label')) {
$('<span class="red-ui-treeList-label-text"></span>').text(item.label).appendTo(label);
}
if (item.sublabel) {
if (item.hasOwnProperty('sublabel')) {
$('<span class="red-ui-treeList-sublabel-text"></span>').text(item.sublabel).appendTo(label);
}
} else if (item.element) {
$(item.element).appendTo(label);
$(item.element).css({
width: "calc(100% - "+(labelPaddingWidth+20+(item.icon?20:0))+"px)"
})
}
if (item.children) {
if (Array.isArray(item.children)) {
if (Array.isArray(item.children) && !item.deferBuild) {
item.treeList.childList = that._addChildren(container,item,item.children,depth).hide();
}
if (item.expanded) {
@@ -350,12 +539,17 @@
this._topList.editableList('empty');
},
data: function(items) {
var that = this;
if (items !== undefined) {
this._data = items;
this._topList.editableList('empty');
this._loadingData = true;
for (var i=0; i<items.length;i++) {
this._topList.editableList('addItem',items[i]);
}
setTimeout(function() {
delete that._loadingData;
},200);
this._trigger("select")
} else {
@@ -384,7 +578,11 @@
})
return res;
}
return s.parent().data('data');
if (s.length) {
return s.parent().data('data');
} else {
return undefined;
}
}
});

View File

@@ -32,6 +32,12 @@
return v;
}
}
var mapDeprecatedIcon = function(icon) {
if (/^red\/images\/typedInput\/.+\.png$/.test(icon)) {
icon = icon.replace(/.png$/,".svg");
}
return icon;
}
var allOptions = {
msg: {value:"msg",label:"msg.",validate:RED.utils.validatePropertyExpression},
flow: {value:"flow",label:"flow.",hasValue:true,
@@ -46,13 +52,13 @@
parse: contextParse,
export: contextExport
},
str: {value:"str",label:"string",icon:"red/images/typedInput/az.png"},
num: {value:"num",label:"number",icon:"red/images/typedInput/09.png",validate:/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/},
bool: {value:"bool",label:"boolean",icon:"red/images/typedInput/bool.png",options:["true","false"]},
str: {value:"str",label:"string",icon:"red/images/typedInput/az.svg"},
num: {value:"num",label:"number",icon:"red/images/typedInput/09.svg",validate:/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/},
bool: {value:"bool",label:"boolean",icon:"red/images/typedInput/bool.svg",options:["true","false"]},
json: {
value:"json",
label:"JSON",
icon:"red/images/typedInput/json.png",
icon:"red/images/typedInput/json.svg",
validate: function(v) { try{JSON.parse(v);return true;}catch(e){return false;}},
expand: function() {
var that = this;
@@ -74,12 +80,12 @@
})
}
},
re: {value:"re",label:"regular expression",icon:"red/images/typedInput/re.png"},
date: {value:"date",label:"timestamp",hasValue:false},
re: {value:"re",label:"regular expression",icon:"red/images/typedInput/re.svg"},
date: {value:"date",label:"timestamp",icon:"fa fa-clock-o",hasValue:false},
jsonata: {
value: "jsonata",
label: "expression",
icon: "red/images/typedInput/expr.png",
icon: "red/images/typedInput/expr.svg",
validate: function(v) { try{jsonata(v);return true;}catch(e){return false;}},
expand:function() {
var that = this;
@@ -94,7 +100,7 @@
bin: {
value: "bin",
label: "buffer",
icon: "red/images/typedInput/bin.png",
icon: "red/images/typedInput/bin.svg",
expand: function() {
var that = this;
RED.editor.editBuffer({
@@ -108,12 +114,12 @@
env: {
value: "env",
label: "env variable",
icon: "red/images/typedInput/env.png"
icon: "red/images/typedInput/env.svg"
},
node: {
value: "node",
label: "node",
icon: "red/images/typedInput/target.png",
icon: "red/images/typedInput/target.svg",
valueLabel: function(container,value) {
var node = RED.nodes.node(value);
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).css({
@@ -209,7 +215,7 @@
that.input.css("margin"+d,0);
});
["type","placeholder"].forEach(function(d) {
["type","placeholder","autocomplete","data-i18n"].forEach(function(d) {
var m = that.element.attr(d);
that.input.attr(d,m);
});
@@ -225,6 +231,8 @@
this.selectLabel = $('<span class="red-ui-typedInput-type-label"></span>').appendTo(this.selectTrigger);
this.valueLabelContainer = $('<div class="red-ui-typedInput-value-label">').appendTo(this.uiSelect)
this.types(this.options.types);
if (this.options.typeField) {
@@ -247,9 +255,15 @@
that.validate();
that.element.val(that.value());
that.element.trigger('change',that.propertyType,that.value());
});
this.input.on('keydown', function(evt) {
if (evt.keyCode >= 37 && evt.keyCode <= 40) {
evt.stopPropagation();
}
})
this.selectTrigger.on("click", function(event) {
event.preventDefault();
event.stopPropagation();
that._showTypeMenu();
});
this.selectTrigger.on('keydown',function(evt) {
@@ -257,12 +271,11 @@
// Down
that._showTypeMenu();
}
evt.stopPropagation();
}).on('focus', function() {
that.uiSelect.addClass('red-ui-typedInput-focus');
})
this.valueLabelContainer = $('<div class="red-ui-typedInput-value-label">').appendTo(this.uiSelect)
// 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.optionSelectLabel = $('<span class="red-ui-typedInput-option-label"></span>').prependTo(this.optionSelectTrigger);
@@ -271,19 +284,22 @@
});
this.optionSelectTrigger.on("click", function(event) {
event.preventDefault();
event.stopPropagation();
that._showOptionSelectMenu();
}).on('keydown', function(evt) {
if (evt.keyCode === 40) {
// Down
that._showOptionSelectMenu();
}
evt.stopPropagation();
}).on('blur', function() {
that.uiSelect.removeClass('red-ui-typedInput-focus');
}).on('focus', function() {
that.uiSelect.addClass('red-ui-typedInput-focus');
});
this.optionExpandButton = $('<button tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"><i class="red-ui-typedInput-icon fa fa-ellipsis-h"></i></button>').appendTo(this.uiSelect);
this.optionExpandButton = $('<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.options.default||this.typeList[0].value);
}catch(err) {
console.log(err.stack);
@@ -321,6 +337,17 @@
menu.css({
height: "auto"
});
if (menu.opts.multiple) {
var selected = [];
menu.find('input[type="checkbox"]').each(function() {
if ($(this).prop("checked")) {
selected.push($(this).data('value'))
}
})
menu.callback(selected);
}
if (this.elementDiv.is(":visible")) {
this.input.trigger("focus");
} else if (this.optionSelectTrigger.is(":visible")){
@@ -329,10 +356,12 @@
this.selectTrigger.trigger("focus");
}
},
_createMenu: function(opts,callback) {
_createMenu: function(menuOptions,opts,callback) {
var that = this;
var menu = $("<div>").addClass("red-ui-typedInput-options");
opts.forEach(function(opt) {
var menu = $("<div>").addClass("red-ui-typedInput-options red-ui-editor-dialog");
menu.opts = opts;
menu.callback = callback;
menuOptions.forEach(function(opt) {
if (typeof opt === 'string') {
opt = {value:opt,label:opt};
}
@@ -344,7 +373,7 @@
if (opt.icon.indexOf("<") === 0) {
$(opt.icon).prependTo(op);
} else if (opt.icon.indexOf("/") !== -1) {
$('<img>',{src:opt.icon,style:"margin-right: 4px; height: 18px;"}).prependTo(op);
$('<img>',{src:mapDeprecatedIcon(opt.icon),style:"margin-right: 4px; height: 18px;"}).prependTo(op);
} else {
$('<i>',{class:"red-ui-typedInput-icon "+opt.icon}).prependTo(op);
}
@@ -354,11 +383,20 @@
if (!opt.icon && !opt.label) {
op.text(opt.value);
}
var cb;
if (opts.multiple) {
cb = $('<input type="checkbox">').css("pointer-events","none").data('value',opt.value).prependTo(op).on("mousedown", function(evt) { evt.preventDefault() });
}
op.on("click", function(event) {
event.preventDefault();
callback(opt.value);
that._hideMenu(menu);
event.stopPropagation();
if (!opts.multiple) {
callback(opt.value);
that._hideMenu(menu);
} else {
cb.prop("checked",!cb.prop("checked"));
}
});
});
menu.css({
@@ -376,13 +414,12 @@
// UP
$(this).children(":focus").prev().trigger("focus");
} else if (evt.keyCode === 27) {
// ESCAPE
evt.preventDefault();
that._hideMenu(menu);
}
evt.stopPropagation();
})
return menu;
},
@@ -391,11 +428,22 @@
this.disarmClick = false;
return
}
if (menu.opts.multiple) {
var selected = {};
this.value().split(",").forEach(function(f) {
selected[f] = true;
})
menu.find('input[type="checkbox"]').each(function() {
$(this).prop("checked",selected[$(this).data('value')])
})
}
var that = this;
var pos = relativeTo.offset();
var height = relativeTo.height();
var menuHeight = menu.height();
var top = (height+pos.top-3);
var top = (height+pos.top);
if (top+menuHeight > $(window).height()) {
top -= (top+menuHeight)-$(window).height()+5;
}
@@ -405,7 +453,7 @@
}
menu.css({
top: top+"px",
left: (2+pos.left)+"px",
left: (pos.left)+"px",
});
menu.slideDown(100);
this._delay(function() {
@@ -421,20 +469,27 @@
})
});
},
_getLabelWidth: function(label) {
_getLabelWidth: function(label, done) {
var labelWidth = label.outerWidth();
if (labelWidth === 0) {
var container = $('<div class="red-ui-typedInput-container"></div>').css({
var wrapper = $('<div class="red-ui-editor"></div>').css({
position:"absolute",
top:0
"white-space": "nowrap",
top:-2000
}).appendTo(document.body);
var container = $('<div class="red-ui-typedInput-container"></div>').appendTo(wrapper);
var newTrigger = label.clone().appendTo(container);
labelWidth = newTrigger.outerWidth();
container.remove();
setTimeout(function() {
labelWidth = newTrigger.outerWidth();
wrapper.remove();
done(labelWidth);
},50)
} else {
done(labelWidth);
}
return labelWidth;
},
_resize: function() {
var that = this;
if (this.uiWidth !== null) {
this.uiSelect.width(this.uiWidth);
}
@@ -443,71 +498,78 @@
this.selectTrigger.addClass("red-ui-typedInput-full-width");
} else {
this.selectTrigger.removeClass("red-ui-typedInput-full-width");
var labelWidth = this._getLabelWidth(this.selectTrigger);
this.elementDiv.css('left',labelWidth+"px");
this.valueLabelContainer.css('left',labelWidth+"px");
if (this.optionExpandButton.is(":visible")) {
this.elementDiv.css('right',"22px");
this.valueLabelContainer.css('right',"22px");
} else {
this.elementDiv.css('right','0');
this.valueLabelContainer.css('right','0');
this.input.css({
'border-top-right-radius': '4px',
'border-bottom-right-radius': '4px'
});
}
// if (this.optionSelectTrigger) {
// this.optionSelectTrigger.css({'left':(labelWidth)+"px",'width':'calc( 100% - '+labelWidth+'px )'});
// }
if (this.optionSelectTrigger) {
if (type && type.options && type.hasValue === true) {
this.optionSelectLabel.css({'left':'auto'})
var lw = this._getLabelWidth(this.optionSelectLabel);
this.optionSelectTrigger.css({'width':(23+lw)+"px"});
this.elementDiv.css('right',(23+lw)+"px");
this.input.css({
'border-top-right-radius': 0,
'border-bottom-right-radius': 0
});
this._getLabelWidth(this.selectTrigger, function(labelWidth) {
that.elementDiv.css('left',labelWidth+"px");
that.valueLabelContainer.css('left',labelWidth+"px");
if (that.optionExpandButton.shown) {
that.elementDiv.css('right',"22px");
that.valueLabelContainer.css('right',"22px");
} else {
this.optionSelectLabel.css({'left':'0'})
this.optionSelectTrigger.css({'width':'calc( 100% - '+labelWidth+'px )'});
if (!this.optionExpandButton.is(":visible")) {
this.elementDiv.css({'right':0});
this.input.css({
'border-top-right-radius': '4px',
'border-bottom-right-radius': '4px'
that.elementDiv.css('right','0');
that.valueLabelContainer.css('right','0');
that.input.css({
'border-top-right-radius': '4px',
'border-bottom-right-radius': '4px'
});
}
if (that.optionSelectTrigger) {
if (type && type.options && type.hasValue === true) {
that.optionSelectLabel.css({'left':'auto'})
that._getLabelWidth(that.optionSelectLabel, function(lw) {
that.optionSelectTrigger.css({'width':(23+lw)+"px"});
that.elementDiv.css('right',(23+lw)+"px");
that.input.css({
'border-top-right-radius': 0,
'border-bottom-right-radius': 0
});
});
} else {
that.optionSelectLabel.css({'left':'0'})
that.optionSelectTrigger.css({'width':'calc( 100% - '+labelWidth+'px )'});
if (!that.optionExpandButton.shown) {
that.elementDiv.css({'right':0});
that.input.css({
'border-top-right-radius': '4px',
'border-bottom-right-radius': '4px'
});
}
}
}
}
});
}
},
_updateOptionSelectLabel: function(o) {
var opt = this.typeMap[this.propertyType];
this.optionSelectLabel.empty();
if (o.icon) {
if (o.icon.indexOf("<") === 0) {
$(o.icon).prependTo(this.optionSelectLabel);
} else if (o.icon.indexOf("/") !== -1) {
// url
$('<img>',{src:o.icon,style:"height: 18px;"}).prependTo(this.optionSelectLabel);
if (this.typeMap[this.propertyType].valueLabel) {
if (opt.multiple) {
this.typeMap[this.propertyType].valueLabel.call(this,this.optionSelectLabel,o);
} else {
// icon class
$('<i>',{class:"red-ui-typedInput-icon "+o.icon}).prependTo(this.optionSelectLabel);
this.typeMap[this.propertyType].valueLabel.call(this,this.optionSelectLabel,o.value);
}
} else if (!opt.multiple) {
if (o.icon) {
if (o.icon.indexOf("<") === 0) {
$(o.icon).prependTo(this.optionSelectLabel);
} else if (o.icon.indexOf("/") !== -1) {
// url
$('<img>',{src:mapDeprecatedIcon(o.icon),style:"height: 18px;"}).prependTo(this.optionSelectLabel);
} else {
// icon class
$('<i>',{class:"red-ui-typedInput-icon "+o.icon}).prependTo(this.optionSelectLabel);
}
} else if (o.label) {
this.optionSelectLabel.text(o.label);
} else {
this.optionSelectLabel.text(o.value);
}
if (opt.hasValue) {
this.optionValue = o.value;
this._resize();
this.input.trigger('change',this.propertyType,this.value());
}
} else if (o.label) {
this.optionSelectLabel.text(o.label);
} else {
this.optionSelectLabel.text(o.value);
}
if (opt.hasValue) {
this.optionValue = o.value;
this._resize();
this.input.trigger('change',this.propertyType,this.value());
this.optionSelectLabel.text(o.length+" selected");
}
},
_destroy: function() {
@@ -515,6 +577,7 @@
this.optionMenu.remove();
}
this.menu.remove();
this.uiSelect.remove();
},
types: function(types) {
var that = this;
@@ -535,7 +598,7 @@
if (this.menu) {
this.menu.remove();
}
this.menu = this._createMenu(this.typeList, function(v) { that.type(v) });
this.menu = this._createMenu(this.typeList,{},function(v) { that.type(v) });
if (currentType && !this.typeMap.hasOwnProperty(currentType)) {
this.type(this.typeList[0].value);
} else {
@@ -549,37 +612,51 @@
this._resize();
},
value: function(value) {
var that = this;
var opt = this.typeMap[this.propertyType];
if (!arguments.length) {
var v = this.input.val();
if (this.typeMap[this.propertyType].export) {
v = this.typeMap[this.propertyType].export(v,this.optionValue)
if (opt.export) {
v = opt.export(v,this.optionValue)
}
return v;
} else {
var selectedOption;
if (this.typeMap[this.propertyType].options) {
for (var i=0;i<this.typeMap[this.propertyType].options.length;i++) {
var op = this.typeMap[this.propertyType].options[i];
if (typeof op === "string") {
if (op === value) {
selectedOption = this.activeOptions[op];
var selectedOption = [];
if (opt.options) {
var checkValues = [value];
if (opt.multiple) {
selectedOption = [];
checkValues = value.split(",");
}
checkValues.forEach(function(value) {
for (var i=0;i<opt.options.length;i++) {
var op = opt.options[i];
if (typeof op === "string") {
if (op === value || op === ""+value) {
selectedOption.push(that.activeOptions[op]);
break;
}
} else if (op.value === value) {
selectedOption.push(op);
break;
}
} else if (op.value === value) {
selectedOption = op;
break;
}
})
this.input.val(value);
if (!opt.multiple) {
if (selectedOption.length === 0) {
selectedOption = [{value:""}];
}
this._updateOptionSelectLabel(selectedOption[0])
} else {
this._updateOptionSelectLabel(selectedOption)
}
if (!selectedOption) {
selectedOption = {value:""}
}
this._updateOptionSelectLabel(selectedOption)
} else {
this.input.val(value);
}
if (this.typeMap[this.propertyType].valueLabel) {
this.valueLabelContainer.empty();
this.typeMap[this.propertyType].valueLabel.call(this,this.valueLabelContainer,value);
if (opt.valueLabel) {
this.valueLabelContainer.empty();
opt.valueLabel.call(this,this.valueLabelContainer,value);
}
}
this.input.trigger('change',this.type(),value);
}
@@ -597,20 +674,23 @@
}
this.selectLabel.empty();
var image;
if (opt.icon) {
if (opt.icon && opt.showLabel !== false) {
if (opt.icon.indexOf("<") === 0) {
$(opt.icon).prependTo(this.selectLabel);
}
else if (opt.icon.indexOf("/") !== -1) {
image = new Image();
image.onload = function() { that._resize(); }
image.onerror = function() { that._resize(); }
image.name = opt.icon;
image.src = opt.icon;
$('<img>',{src:opt.icon,style:"margin-right: 4px;height: 18px;"}).prependTo(this.selectLabel);
image.src = mapDeprecatedIcon(opt.icon);
$('<img>',{src:mapDeprecatedIcon(opt.icon),style:"margin-right: 4px;height: 18px;"}).prependTo(this.selectLabel);
}
else {
$('<i>',{class:"red-ui-typedInput-icon "+opt.icon}).prependTo(this.selectLabel);
}
} else {
}
if (opt.hasValue === false || (opt.showLabel !== false && !opt.icon)) {
this.selectLabel.text(opt.label);
}
if (this.optionMenu) {
@@ -620,6 +700,7 @@
if (opt.options) {
if (this.optionExpandButton) {
this.optionExpandButton.hide();
this.optionExpandButton.shown = false;
}
if (this.optionSelectTrigger) {
this.optionSelectTrigger.show();
@@ -642,36 +723,50 @@
if (!that.activeOptions.hasOwnProperty(that.optionValue)) {
that.optionValue = null;
}
this.optionMenu = this._createMenu(opt.options,function(v){
that._updateOptionSelectLabel(that.activeOptions[v]);
if (!opt.hasValue) {
that.value(that.activeOptions[v].value)
}
});
var op;
if (!opt.hasValue) {
var currentVal = this.input.val();
var validValue = false;
for (var i=0;i<opt.options.length;i++) {
op = opt.options[i];
if (typeof op === "string" && op === currentVal) {
that._updateOptionSelectLabel({value:currentVal});
validValue = true;
break;
} else if (op.value === currentVal) {
that._updateOptionSelectLabel(op);
validValue = true;
break;
var currentVal = this.input.val();
if (!opt.multiple) {
for (var i=0;i<opt.options.length;i++) {
op = opt.options[i];
if (typeof op === "string" && op === currentVal) {
that._updateOptionSelectLabel({value:currentVal});
validValue = true;
break;
} else if (op.value === currentVal) {
that._updateOptionSelectLabel(op);
validValue = true;
break;
}
}
}
if (!validValue) {
op = opt.options[0];
if (typeof op === "string") {
this.value(op);
that._updateOptionSelectLabel({value:op});
} else {
this.value(op.value);
that._updateOptionSelectLabel(op);
if (!validValue) {
op = opt.options[0];
if (typeof op === "string") {
this.value(op);
that._updateOptionSelectLabel({value:op});
} else {
this.value(op.value);
that._updateOptionSelectLabel(op);
}
}
} else {
// Check to see if value is a valid csv of
// options.
var currentValues = {};
currentVal.split(",").forEach(function(v) {
if (v) {
currentValues[v] = true;
}
});
for (var i=0;i<opt.options.length;i++) {
op = opt.options[i];
delete currentValues[op.value||op];
}
if (!$.isEmptyObject(currentValues)) {
// Invalid, set to default/empty
this.value((opt.default||[]).join(","));
}
}
} else {
@@ -707,7 +802,21 @@
this.optionSelectTrigger.hide();
}
}
this.optionMenu = this._createMenu(opt.options,opt,function(v){
if (!opt.multiple) {
that._updateOptionSelectLabel(that.activeOptions[v]);
if (!opt.hasValue) {
that.value(that.activeOptions[v].value)
}
} else {
that._updateOptionSelectLabel(v);
if (!opt.hasValue) {
that.value(v.join(","))
}
}
});
}
this._trigger("typechange",null,this.propertyType);
this.input.trigger('change',this.propertyType,this.value());
} else {
if (this.optionSelectTrigger) {
@@ -732,23 +841,47 @@
this.elementDiv.show();
}
if (this.optionExpandButton) {
if (opt.expand && typeof opt.expand === 'function') {
if (opt.expand) {
if (opt.expand.icon) {
this.optionExpandButtonIcon.removeClass().addClass("red-ui-typedInput-icon fa "+opt.expand.icon)
} else {
this.optionExpandButtonIcon.removeClass().addClass("red-ui-typedInput-icon fa fa-ellipsis-h")
}
this.optionExpandButton.shown = true;
this.optionExpandButton.show();
this.optionExpandButton.off('click');
this.optionExpandButton.on('click',function(evt) {
evt.preventDefault();
opt.expand.call(that);
if (typeof opt.expand === 'function') {
opt.expand.call(that);
} else {
var container = $('<div>');
var content = opt.expand.content.call(that,container);
var panel = RED.popover.panel(container);
panel.container.css({
width:that.valueLabelContainer.width()
});
if (opt.expand.minWidth) {
panel.container.css({
minWidth: opt.expand.minWidth+"px"
});
}
panel.show({
target:that.optionExpandButton,
onclose:content.onclose,
align: "right"
});
}
})
} else {
this.optionExpandButton.shown = false;
this.optionExpandButton.hide();
}
}
this._trigger("typechange",null,this.propertyType);
this.input.trigger('change',this.propertyType,this.value());
}
if (image) {
image.onload = function() { that._resize(); }
image.onerror = function() { that._resize(); }
} else {
if (!image) {
this._resize();
}
}

View File

@@ -17,9 +17,9 @@
RED.deploy = (function() {
var deploymentTypes = {
"full":{img:"red/images/deploy-full-o.png"},
"nodes":{img:"red/images/deploy-nodes-o.png"},
"flows":{img:"red/images/deploy-flows-o.png"}
"full":{img:"red/images/deploy-full-o.svg"},
"nodes":{img:"red/images/deploy-nodes-o.svg"},
"flows":{img:"red/images/deploy-flows-o.svg"}
}
var ignoreDeployWarnings = {
@@ -44,7 +44,7 @@ RED.deploy = (function() {
* type: "default" - Button with drop-down options - no further customisation available
* type: "simple" - Button without dropdown. Customisations:
* label: the text to display - default: "Deploy"
* icon : the icon to use. Null removes the icon. default: "red/images/deploy-full-o.png"
* icon : the icon to use. Null removes the icon. default: "red/images/deploy-full-o.svg"
*/
function init(options) {
options = options || {};
@@ -54,7 +54,7 @@ RED.deploy = (function() {
$('<li><span class="red-ui-deploy-button-group button-group">'+
'<a id="red-ui-header-button-deploy" class="red-ui-deploy-button disabled" href="#">'+
'<span class="red-ui-deploy-button-content">'+
'<img id="red-ui-header-button-deploy-icon" src="red/images/deploy-full-o.png"> '+
'<img id="red-ui-header-button-deploy-icon" src="red/images/deploy-full-o.svg"> '+
'<span>'+RED._("deploy.deploy")+'</span>'+
'</span>'+
'<span class="red-ui-deploy-button-spinner hide">'+
@@ -65,17 +65,17 @@ RED.deploy = (function() {
'</span></li>').prependTo(".red-ui-header-toolbar");
RED.menu.init({id:"red-ui-header-button-deploy-options",
options: [
{id:"deploymenu-item-full",toggle:"deploy-type",icon:"red/images/deploy-full.png",label:RED._("deploy.full"),sublabel:RED._("deploy.fullDesc"),selected: true, onselect:function(s) { if(s){changeDeploymentType("full")}}},
{id:"deploymenu-item-flow",toggle:"deploy-type",icon:"red/images/deploy-flows.png",label:RED._("deploy.modifiedFlows"),sublabel:RED._("deploy.modifiedFlowsDesc"), onselect:function(s) {if(s){changeDeploymentType("flows")}}},
{id:"deploymenu-item-node",toggle:"deploy-type",icon:"red/images/deploy-nodes.png",label:RED._("deploy.modifiedNodes"),sublabel:RED._("deploy.modifiedNodesDesc"),onselect:function(s) { if(s){changeDeploymentType("nodes")}}},
{id:"deploymenu-item-full",toggle:"deploy-type",icon:"red/images/deploy-full.svg",label:RED._("deploy.full"),sublabel:RED._("deploy.fullDesc"),selected: true, onselect:function(s) { if(s){changeDeploymentType("full")}}},
{id:"deploymenu-item-flow",toggle:"deploy-type",icon:"red/images/deploy-flows.svg",label:RED._("deploy.modifiedFlows"),sublabel:RED._("deploy.modifiedFlowsDesc"), onselect:function(s) {if(s){changeDeploymentType("flows")}}},
{id:"deploymenu-item-node",toggle:"deploy-type",icon:"red/images/deploy-nodes.svg",label:RED._("deploy.modifiedNodes"),sublabel:RED._("deploy.modifiedNodesDesc"),onselect:function(s) { if(s){changeDeploymentType("nodes")}}},
null,
{id:"deploymenu-item-reload", icon:"red/images/deploy-reload.png",label:RED._("deploy.restartFlows"),sublabel:RED._("deploy.restartFlowsDesc"),onselect:"core:restart-flows"},
{id:"deploymenu-item-reload", icon:"red/images/deploy-reload.svg",label:RED._("deploy.restartFlows"),sublabel:RED._("deploy.restartFlowsDesc"),onselect:"core:restart-flows"},
]
});
} else if (type == "simple") {
var label = options.label || RED._("deploy.deploy");
var icon = 'red/images/deploy-full-o.png';
var icon = 'red/images/deploy-full-o.svg';
if (options.hasOwnProperty('icon')) {
icon = options.icon;
}
@@ -99,7 +99,13 @@ RED.deploy = (function() {
});
RED.actions.add("core:deploy-flows",save);
RED.actions.add("core:restart-flows",restart);
if (type === "default") {
RED.actions.add("core:restart-flows",restart);
RED.actions.add("core:set-deploy-type-to-full",function() { RED.menu.setSelected("deploymenu-item-full",true);});
RED.actions.add("core:set-deploy-type-to-modified-flows",function() { RED.menu.setSelected("deploymenu-item-flow",true); });
RED.actions.add("core:set-deploy-type-to-modified-nodes",function() { RED.menu.setSelected("deploymenu-item-node",true); });
}
RED.events.on('nodes:change',function(state) {

View File

@@ -399,9 +399,9 @@ RED.diff = (function() {
diff: localDiff,
def: {
defaults:{},
icon:"subflow.png",
icon:"subflow.svg",
category: "subflows",
color: "#da9"
color: "#DDAA99"
},
tab:currentConfig.subflows[subflowId]
}
@@ -422,9 +422,9 @@ RED.diff = (function() {
diff: localDiff,
def: {
defaults:{},
icon:"subflow.png",
icon:"subflow.svg",
category: "subflows",
color: "#da9"
color: "#DDAA99"
},
tab:newConfig.subflows[subflowId],
newTab:newConfig.subflows[subflowId]
@@ -443,9 +443,9 @@ RED.diff = (function() {
remoteDiff: remoteDiff,
def: {
defaults:{},
icon:"subflow.png",
icon:"subflow.svg",
category: "subflows",
color: "#da9"
color: "#DDAA99"
},
tab:remoteDiff.newConfig.subflows[subflowId],
remoteTab: remoteDiff.newConfig.subflows[subflowId]
@@ -549,9 +549,9 @@ RED.diff = (function() {
if (def === undefined) {
if (/^subflow:/.test(node.type)) {
def = {
icon:"subflow.png",
icon:"subflow.svg",
category: "subflows",
color: "#da9",
color: "#DDAA99",
defaults:{name:{value:""}}
}
} else {
@@ -1029,9 +1029,9 @@ RED.diff = (function() {
}
var localSelectDiv = $('<label>',{class:"red-ui-diff-selectbox",for:safeNodeId+"-local"}).on("click", function(e) { e.stopPropagation();}).appendTo(localDiv);
var localRadio = $('<input>',{class:"red-ui-diff-selectbox-input",id:safeNodeId+"-local",type:'radio',value:"local",name:safeNodeId,class:className+"-local"}).data('node-id',node.id).on("change", changeHandler).appendTo(localSelectDiv);
var localRadio = $('<input>',{class:"red-ui-diff-selectbox-input "+className+"-local",id:safeNodeId+"-local",type:'radio',value:"local",name:safeNodeId}).data('node-id',node.id).on("change", changeHandler).appendTo(localSelectDiv);
var remoteSelectDiv = $('<label>',{class:"red-ui-diff-selectbox",for:safeNodeId+"-remote"}).on("click", function(e) { e.stopPropagation();}).appendTo(remoteDiv);
var remoteRadio = $('<input>',{class:"red-ui-diff-selectbox-input",id:safeNodeId+"-remote",type:'radio',value:"remote",name:safeNodeId,class:className+"-remote"}).data('node-id',node.id).on("change", changeHandler).appendTo(remoteSelectDiv);
var remoteRadio = $('<input>',{class:"red-ui-diff-selectbox-input "+className+"-remote",id:safeNodeId+"-remote",type:'radio',value:"remote",name:safeNodeId}).data('node-id',node.id).on("change", changeHandler).appendTo(remoteSelectDiv);
if (state === 'local') {
localRadio.prop('checked',true);
} else if (state === 'remote') {

View File

@@ -19,7 +19,6 @@
*/
RED.editor = (function() {
var editStack = [];
var editing_node = null;
var editing_config_node = null;
@@ -203,6 +202,7 @@ RED.editor = (function() {
function updateNodeProperties(node, outputMap) {
node.resize = true;
node.dirty = true;
node.dirtyStatus = true;
var removedLinks = [];
if (node.ports) {
if (outputMap) {
@@ -231,8 +231,12 @@ RED.editor = (function() {
}
}
}
node.inputs = Math.min(1,Math.max(0,parseInt(node.inputs)));
if (isNaN(node.inputs)) {
node.inputs = 0;
}
if (node.inputs === 0) {
removedLinks.concat(RED.nodes.filterLinks({target:node}));
removedLinks = removedLinks.concat(RED.nodes.filterLinks({target:node}));
}
for (var l=0;l<removedLinks.length;l++) {
RED.nodes.removeLink(removedLinks[l]);
@@ -526,7 +530,7 @@ RED.editor = (function() {
} else if (node.type.indexOf("subflow:")===0) {
var subflow = RED.nodes.subflow(node.type.substring(8));
label = RED._("subflow.editSubflowInstance",{name:RED.utils.sanitize(subflow.name)})
} else {
} else if (node._def !== undefined) {
if (typeof node._def.paletteLabel !== "undefined") {
try {
label = RED.utils.sanitize((typeof node._def.paletteLabel === "function" ? node._def.paletteLabel.call(node._def) : node._def.paletteLabel)||"");
@@ -546,146 +550,7 @@ RED.editor = (function() {
return label;
}
function buildEnvForm(container, node) {
var env_container = $('#node-input-env-container');
env_container
.css({
'min-height':'150px',
'min-width':'450px'
})
.editableList({
addItem: function(container, i, opt) {
var row = $('<div/>').appendTo(container);
if (opt.parent) {
$('<div/>', {
class:"uneditable-input",
style: "margin-left: 5px; width: calc(40% - 8px)",
}).appendTo(row).text(opt.name);
} else {
$('<input/>', {
class: "node-input-env-name",
type: "text",
style: "margin-left: 5px; width: calc(40% - 8px)",
placeholder: RED._("common.label.name")
}).appendTo(row).val(opt.name);
}
var valueField = $('<input/>',{
class: "node-input-env-value",
type: "text",
style: "margin-left: 5px; width: calc(60% - 8px)"
}).appendTo(row)
valueField.typedInput({default:'str',
types:['str','num','bool','json','bin','env']
});
valueField.typedInput('type', opt.parent?(opt.type||opt.parent.type):opt.type);
valueField.typedInput('value', opt.parent?((opt.value !== undefined)?opt.value:opt.parent.value):opt.value);
var actionButton = $('<a/>',{href:"#",class:"red-ui-editableList-item-remove red-ui-button red-ui-button-small"}).appendTo(container);
$('<i/>',{class:"fa "+(opt.parent?"fa-reply":"fa-remove")}).appendTo(actionButton);
container.parent().addClass("red-ui-editableList-item-removable");
if (opt.parent) {
if ((opt.value !== undefined) && (opt.value !== opt.parent.value || opt.type !== opt.parent.type)) {
actionButton.show();
} else {
actionButton.hide();
}
var restoreTip = RED.popover.tooltip(actionButton,RED._("subflow.env.restore"));
valueField.on("change", function(evt) {
var newType = valueField.typedInput('type');
var newValue = valueField.typedInput('value');
if (newType === opt.parent.type && newValue === opt.parent.value) {
actionButton.hide();
} else {
actionButton.show();
}
})
actionButton.on("click", function(evt) {
evt.preventDefault();
restoreTip.close();
valueField.typedInput('type', opt.parent.type);
valueField.typedInput('value', opt.parent.value);
})
} else {
var removeTip = RED.popover.tooltip(actionButton,RED._("subflow.env.remove"));
actionButton.on("click", function(evt) {
evt.preventDefault();
removeTip.close();
container.parent().addClass("red-ui-editableList-item-deleting")
container.fadeOut(300, function() {
env_container.editableList('removeItem',opt);
});
});
}
},
sortable: false,
removable: false
});
var parentEnv = {};
var envList = [];
if (/^subflow:/.test(node.type)) {
var subflowDef = RED.nodes.subflow(node.type.substring(8));
if (subflowDef.env) {
subflowDef.env.forEach(function(env) {
var item = {
name:env.name,
parent: {
type: env.type,
value: env.value
}
}
envList.push(item);
parentEnv[env.name] = item;
})
}
}
if (node.env) {
for (var i = 0; i < node.env.length; i++) {
var env = node.env[i];
if (parentEnv.hasOwnProperty(env.name)) {
parentEnv[env.name].type = env.type;
parentEnv[env.name].value = env.value;
} else {
envList.push({
name: env.name,
type: env.type,
value: env.value
});
}
}
}
envList.forEach(function(env) {
env_container.editableList('addItem', env);
})
}
function exportEnvList(list) {
if (list) {
var env = [];
list.each(function(i) {
var entry = $(this);
var item = entry.data('data');
var name = item.parent?item.name:entry.find(".node-input-env-name").val();
var valueInput = entry.find(".node-input-env-value");
var value = valueInput.typedInput("value");
var type = valueInput.typedInput("type");
if (!item.parent || (item.parent.value !== value || item.parent.type !== type)) {
var item = {
name: name,
type: type,
value: value
};
env.push(item);
}
});
return env;
}
return null;
}
function isSameEnv(env0, env1) {
function isSameObj(env0, env1) {
return (JSON.stringify(env0) === JSON.stringify(env1));
}
@@ -711,8 +576,8 @@ RED.editor = (function() {
$(this).attr("data-i18n",keys.join(";"));
});
if ((type === "subflow") || (type === "subflow-template")) {
buildEnvForm(dialogForm, node);
if (type === "subflow-template" || type === "subflow") {
RED.subflow.buildEditForm(dialogForm,type,node);
}
// Add dummy fields to prevent 'Enter' submitting the form in some
@@ -721,6 +586,7 @@ RED.editor = (function() {
$('<input type="password" style="display: none;" />').prependTo(dialogForm);
$('<input type="text" style="display: none;" />').prependTo(dialogForm);
dialogForm.on("submit", function(e) { e.preventDefault();});
dialogForm.find('input').attr("autocomplete","disable");
return dialogForm;
}
@@ -733,10 +599,18 @@ RED.editor = (function() {
var outputsDiv = $("#red-ui-editor-node-label-form-outputs");
var inputCount;
if (node.type === 'subflow') {
inputCount = node.in.length;
var formInputs = $("#node-input-inputs").val();
if (formInputs === undefined) {
if (node.type === 'subflow') {
inputCount = node.in.length;
} else {
inputCount = node.inputs || node._def.inputs || 0;
}
} else {
inputCount = node.inputs || node._def.inputs || 0;
inputCount = Math.min(1,Math.max(0,parseInt(formInputs)));
if (isNaN(inputCount)) {
inputCount = 0;
}
}
var children = inputsDiv.children();
@@ -854,30 +728,8 @@ RED.editor = (function() {
}
return result;
}
function showIconPicker(container, node, iconPath, done) {
var containerPos = container.offset();
var pickerBackground = $('<div>').css({
position: "absolute",top:0,bottom:0,left:0,right:0,zIndex:20
}).appendTo("body");
var top = containerPos.top - 30;
if (top+280 > $( window ).height()) {
top = $( window ).height() - 280;
}
var picker = $('<div class="red-ui-icon-picker">').css({
top: top+"px",
left: containerPos.left+"px",
}).appendTo("#red-ui-editor");
var hide = function() {
pickerBackground.remove();
picker.remove();
RED.keyboard.remove("escape");
}
RED.keyboard.add("*","escape",function(){hide()});
pickerBackground.on("mousedown", hide);
function showIconPicker(container, backgroundColor, iconPath, faOnly, done) {
var picker = $('<div class="red-ui-icon-picker">');
var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(picker);
searchInput = $('<input type="text">').attr("placeholder",RED._("editor.searchIcons")).appendTo(searchDiv).searchBox({
delay: 50,
@@ -905,89 +757,256 @@ RED.editor = (function() {
var summary = $('<span>').appendTo(metaRow);
var resetButton = $('<button type="button" class="red-ui-button red-ui-button-small">'+RED._("editor.useDefault")+'</button>').appendTo(metaRow).on("click", function(e) {
e.preventDefault();
hide();
iconPanel.hide();
done(null);
});
var iconSets = RED.nodes.getIconSets();
Object.keys(iconSets).forEach(function(moduleName) {
var icons = iconSets[moduleName];
if (icons.length > 0) {
// selectIconModule.append($("<option></option>").val(moduleName).text(moduleName));
var header = $('<div class="red-ui-icon-list-module"></div>').text(moduleName).appendTo(iconList);
$('<i class="fa fa-cube"></i>').prependTo(header);
icons.forEach(function(icon) {
var iconDiv = $('<div>',{class:"red-ui-icon-list-icon"}).appendTo(iconList);
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(iconDiv);
var colour = RED.utils.getNodeColor(node.type, node._def);
var icon_url = RED.settings.apiRootUrl+"icons/"+moduleName+"/"+icon;
iconDiv.data('icon',icon_url);
nodeDiv.css('backgroundColor',colour);
var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
RED.utils.createIconElement(icon_url, iconContainer, true);
if (!backgroundColor && faOnly) {
iconList.addClass("red-ui-icon-list-dark");
}
setTimeout(function() {
var iconSets = RED.nodes.getIconSets();
Object.keys(iconSets).forEach(function(moduleName) {
if (faOnly && (moduleName !== "font-awesome")) {
return;
}
var icons = iconSets[moduleName];
if (icons.length > 0) {
// selectIconModule.append($("<option></option>").val(moduleName).text(moduleName));
var header = $('<div class="red-ui-icon-list-module"></div>').text(moduleName).appendTo(iconList);
$('<i class="fa fa-cube"></i>').prependTo(header);
icons.forEach(function(icon) {
var iconDiv = $('<div>',{class:"red-ui-icon-list-icon"}).appendTo(iconList);
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(iconDiv);
var icon_url = RED.settings.apiRootUrl+"icons/"+moduleName+"/"+icon;
iconDiv.data('icon',icon_url);
if (backgroundColor) {
nodeDiv.css({
'backgroundColor': backgroundColor
});
}
var iconContainer = $('<div/>',{class:"red-ui-palette-icon-container"}).appendTo(nodeDiv);
RED.utils.createIconElement(icon_url, iconContainer, true);
if (iconPath.module === moduleName && iconPath.file === icon) {
iconDiv.addClass("selected");
}
iconDiv.on("mouseover", function() {
summary.text(icon);
if (iconPath.module === moduleName && iconPath.file === icon) {
iconDiv.addClass("selected");
}
iconDiv.on("mouseover", function() {
summary.text(icon);
})
iconDiv.on("mouseout", function() {
summary.html("&nbsp;");
})
iconDiv.on("click", function() {
iconPanel.hide();
done(moduleName+"/"+icon);
})
})
iconDiv.on("mouseout", function() {
summary.html("&nbsp;");
})
iconDiv.on("click", function() {
hide();
done(moduleName+"/"+icon);
})
})
}
});
}
});
setTimeout(function() {
spinner.remove();
},50);
},300);
var spinner = RED.utils.addSpinnerOverlay(iconList,true);
var iconPanel = RED.popover.panel(picker);
iconPanel.show({
target: container
})
picker.slideDown(100);
searchInput.trigger("focus");
}
function createColorPicker(colorRow, color) {
var colorButton = $('<button type="button" class="red-ui-button red-ui-editor-node-appearance-button">').appendTo(colorRow);
$('<i class="fa fa-caret-down"></i>').appendTo(colorButton);
var colorDisp = $('<div>',{class:"red-ui-search-result-node"}).appendTo(colorButton);
var selector = $("<input/>", {
id: "red-ui-editor-node-color",
type: "text",
value: color
}).css({
marginLeft: "10px",
width: "150px",
}).appendTo(colorRow);
selector.on("change", function (e) {
var color = selector.val();
$(".red-ui-editor-node-appearance-button .red-ui-search-result-node").css({
"background-color": color
});
});
selector.trigger("change");
colorButton.on("click", function (e) {
var recommendedColors = [
"#DDAA99",
"#3FADB5", "#87A980", "#A6BBCF",
"#AAAA66", "#C0C0C0", "#C0DEED",
"#C7E9C0", "#D7D7A0", "#D8BFD8",
"#DAC4B4", "#DEB887", "#DEBD5C",
"#E2D96E", "#E6E0F8", "#E7E7AE",
"#E9967A", "#F3B567", "#FDD0A2",
"#FDF0C2", "#FFAAAA", "#FFCC66",
"#FFF0F0", "#FFFFFF"
].map(function(c) {
var r = parseInt(c.substring(1, 3), 16) / 255;
var g = parseInt(c.substring(3, 5), 16) / 255;
var b = parseInt(c.substring(5, 7), 16) / 255;
return {
hex: c,
r: r,
g: g,
b: b,
l: 0.3 * r + 0.59 * g + 0.11 * b
}
});
// Sort by luminosity.
recommendedColors.sort(function (a, b) {
return a.l - b.l;
});
var numColors = recommendedColors.length;
var width = 30;
var height = 30;
var margin = 2;
var perRow = 6;
var picker = $("<div/>", {
class: "red-ui-color-picker"
}).css({
width: ((width+margin+margin)*perRow)+"px",
height: Math.ceil(numColors/perRow)*(height+margin+margin)+"+px"
});
var count = 0;
var row = null;
recommendedColors.forEach(function (col) {
if ((count % perRow) == 0) {
row = $("<div/>").appendTo(picker);
}
var button = $("<button/>", {
}).css({
width: width+"px",
height: height+"px",
margin: margin+"px",
backgroundColor: col.hex,
"border-style": "solid",
"border-width": "1px",
"border-color": col.luma<0.92?col.hex:'#ccc'
}).appendTo(row);
button.on("click", function (e) {
e.preventDefault();
colorPanel.hide();
selector.val(col.hex);
selector.trigger("change");
});
count++;
});
var colorPanel = RED.popover.panel(picker);
colorPanel.show({
target: colorButton
})
});
}
function buildAppearanceForm(container,node) {
var dialogForm = $('<form class="dialog-form form-horizontal" autocomplete="off"></form>').appendTo(container);
var i,row;
if (node.type === "subflow") {
var categoryRow = $("<div/>", {
class: "form-row"
}).appendTo(dialogForm);
$("<label/>", {
for: "subflow-appearance-input-category",
"data-i18n": "editor:subflow.category"
}).appendTo(categoryRow);
var categorySelector = $("<select/>", {
id: "subflow-appearance-input-category"
}).css({
width: "250px"
}).appendTo(categoryRow);
$("<input/>", {
type: "text",
id: "subflow-appearance-input-custom-category"
}).css({
display: "none",
"margin-left": "10px",
width: "calc(100% - 250px)"
}).appendTo(categoryRow);
var categories = RED.palette.getCategories();
categories.sort(function(A,B) {
return A.label.localeCompare(B.label);
})
categories.forEach(function(cat) {
categorySelector.append($("<option/>").val(cat.id).text(cat.label));
})
categorySelector.append($("<option/>").attr('disabled',true).text("---"));
categorySelector.append($("<option/>").val("_custom_").text(RED._("palette.addCategory")));
$("#subflow-appearance-input-category").on("change", function() {
var val = $(this).val();
if (val === "_custom_") {
$("#subflow-appearance-input-category").width(120);
$("#subflow-appearance-input-custom-category").show();
} else {
$("#subflow-appearance-input-category").width(250);
$("#subflow-appearance-input-custom-category").hide();
}
})
$("#subflow-appearance-input-category").val(node.category||"subflows");
var userCount = 0;
var subflowType = "subflow:"+node.id;
RED.nodes.eachNode(function(n) {
if (n.type === subflowType) {
userCount++;
}
});
$("#red-ui-editor-subflow-user-count")
.text(RED._("subflow.subflowInstances", {count:userCount})).show();
}
$('<div class="form-row">'+
'<label for="node-input-show-label-btn" data-i18n="editor.label"></label>'+
'<button type="button" id="node-input-show-label-btn" class="red-ui-button" style="min-width: 80px; text-align: left;" type="button"><i id="node-input-show-label-btn-i" class="fa fa-toggle-on"></i> <span id="node-input-show-label-label"></span></button> '+
'<input type="checkbox" id="node-input-show-label" style="display: none;"/>'+
'<span style="margin-right: 2px;"/>'+
'<input type="checkbox" id="node-input-show-label"/>'+
'</div>').appendTo(dialogForm);
var setToggleState = function(state) {
var i = $("#node-input-show-label-btn-i");
if (!state) {
i.addClass('fa-toggle-off');
i.removeClass('fa-toggle-on');
$("#node-input-show-label").prop("checked",false);
$("#node-input-show-label-label").text(RED._("editor.hide"));
} else {
i.addClass('fa-toggle-on');
i.removeClass('fa-toggle-off');
$("#node-input-show-label").prop("checked",true);
$("#node-input-show-label-label").text(RED._("editor.show"));
}
}
dialogForm.find('#node-input-show-label-btn').on("click",function(e) {
e.preventDefault();
var i = $("#node-input-show-label-btn-i");
setToggleState(i.hasClass('fa-toggle-off'));
$("#node-input-show-label").toggleButton({
enabledLabel: RED._("editor.show"),
disabledLabel: RED._("editor.hide")
})
if (!node.hasOwnProperty("l")) {
// Show label if type not link
node.l = !/^link (in|out)$/.test(node._def.type);
}
setToggleState(node.l);
$("#node-input-show-label").prop("checked",node.l).trigger("change");
if (node.type === "subflow") {
// subflow template can select its color
var color = node.color ? node.color : "#DDAA99";
var colorRow = $("<div/>", {
class: "form-row"
}).appendTo(dialogForm);
$("<label/>").text(RED._("editor.color")).appendTo(colorRow);
createColorPicker(colorRow, color);
}
// If a node has icon property in defaults, the icon of the node cannot be modified. (e.g, ui_button node in dashboard)
if ((!node._def.defaults || !node._def.defaults.hasOwnProperty("icon"))) {
var iconRow = $('<div class="form-row"></div>').appendTo(dialogForm);
$('<label data-i18n="editor.settingIcon">').appendTo(iconRow);
var iconButton = $('<button type="button" class="red-ui-button" id="red-ui-editor-node-icon-button">').appendTo(iconRow);
var iconButton = $('<button type="button" class="red-ui-button red-ui-editor-node-appearance-button">').appendTo(iconRow);
$('<i class="fa fa-caret-down"></i>').appendTo(iconButton);
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(iconButton);
var colour = RED.utils.getNodeColor(node.type, node._def);
var icon_url = RED.utils.getNodeIcon(node._def,node);
@@ -998,21 +1017,30 @@ RED.editor = (function() {
iconButton.on("click", function(e) {
e.preventDefault();
var iconPath;
var icon = $("#red-ui-editor-node-icon").text()||"";
var icon = $("#red-ui-editor-node-icon").val()||"";
if (icon) {
iconPath = RED.utils.separateIconPath(icon);
} else {
iconPath = RED.utils.getDefaultNodeIcon(node._def, node);
}
showIconPicker(iconRow,node,iconPath,function(newIcon) {
$("#red-ui-editor-node-icon").text(newIcon||"");
var backgroundColor = RED.utils.getNodeColor(node.type, node._def);
if (node.type === "subflow") {
backgroundColor = $("#red-ui-editor-node-color").val();
}
showIconPicker(iconButton,backgroundColor,iconPath,false,function(newIcon) {
$("#red-ui-editor-node-icon").val(newIcon||"");
var icon_url = RED.utils.getNodeIcon(node._def,{type:node.type,icon:newIcon});
RED.utils.createIconElement(icon_url, iconContainer, true);
});
});
$('<div id="red-ui-editor-node-icon">').text(node.icon).appendTo(iconButton);
RED.popover.tooltip(iconButton, function() {
return $("#red-ui-editor-node-icon").val() || RED._("editor.default");
})
$('<input type="hidden" id="red-ui-editor-node-icon">').val(node.icon).appendTo(iconRow);
}
$('<div class="form-row"><span data-i18n="editor.portLabels"></span></div>').appendTo(dialogForm);
var inputCount = node.inputs || node._def.inputs || 0;
@@ -1048,6 +1076,7 @@ RED.editor = (function() {
}
}
function updateLabels(editing_node, changes, outputMap) {
var inputLabels = $("#red-ui-editor-node-label-form-inputs").children().find("input");
var outputLabels = $("#red-ui-editor-node-label-form-outputs").children().find("input");
@@ -1291,11 +1320,13 @@ RED.editor = (function() {
newValue = parseInt(newValue);
}
}
if (editing_node._def.defaults[d].type) {
if (newValue == "_ADD_") {
newValue = "";
}
}
if (editing_node[d] != newValue) {
if (editing_node._def.defaults[d].type) {
if (newValue == "_ADD_") {
newValue = "";
}
// Change to a related config node
var configNode = RED.nodes.node(editing_node[d]);
if (configNode) {
@@ -1335,7 +1366,7 @@ RED.editor = (function() {
}
if (!editing_node._def.defaults || !editing_node._def.defaults.hasOwnProperty("icon")) {
var icon = $("#red-ui-editor-node-icon").text()||""
var icon = $("#red-ui-editor-node-icon").val()||""
if (!isDefaultIcon) {
if (icon !== editing_node.icon) {
changes.icon = editing_node.icon;
@@ -1393,6 +1424,20 @@ RED.editor = (function() {
node.l = true;
}
}
if ($("#node-input-node-disabled").prop('checked')) {
if (node.d !== true) {
changes.d = node.d;
changed = true;
node.d = true;
}
} else {
if (node.d === true) {
changes.d = node.d;
changed = true;
delete node.d;
}
}
node.resize = true;
var oldInfo = node.info;
@@ -1424,13 +1469,13 @@ RED.editor = (function() {
if (type === "subflow") {
var old_env = editing_node.env;
var new_env = exportEnvList($("#node-input-env-container").editableList("items"));
if (!isSameEnv(old_env, new_env)) {
var new_env = RED.subflow.exportSubflowInstanceEnv(editing_node);
if (!isSameObj(old_env, new_env)) {
editing_node.env = new_env;
changes.env = editing_node.env;
changed = true;
}
}
}
if (changed) {
var wasChanged = editing_node.changed;
@@ -1495,6 +1540,14 @@ RED.editor = (function() {
var trayBody = tray.find('.red-ui-tray-body');
trayBody.parent().css('overflow','hidden');
var trayFooterLeft = $('<div class="red-ui-tray-footer-left"></div>').appendTo(trayFooter)
$('<input id="node-input-node-disabled" type="checkbox">').prop("checked",!!node.d).appendTo(trayFooterLeft).toggleButton({
enabledIcon: "fa-circle-thin",
disabledIcon: "fa-ban",
invertState: true
})
var editorTabEl = $('<ul></ul>').appendTo(trayBody);
var editorContent = $('<div></div>').appendTo(trayBody);
@@ -1540,6 +1593,19 @@ RED.editor = (function() {
buildEditForm(nodePropertiesTab.content,"dialog-form",type,ns,node);
editorTabs.addTab(nodePropertiesTab);
if (/^subflow:/.test(node.type)) {
var subflowPropertiesTab = {
id: "editor-subflow-envProperties",
label: RED._("editor-tab.envProperties"),
name: RED._("editor-tab.envProperties"),
content: $('<div>', {class:"red-ui-tray-content"}).appendTo(editorContent).hide(),
iconClass: "fa fa-list"
};
RED.subflow.buildPropertiesForm(subflowPropertiesTab.content,node);
editorTabs.addTab(subflowPropertiesTab);
}
if (!node._def.defaults || !node._def.defaults.hasOwnProperty('info')) {
var descriptionTab = {
id: "editor-tab-description",
@@ -1672,9 +1738,17 @@ RED.editor = (function() {
var trayHeader = tray.find(".red-ui-tray-header");
var trayBody = tray.find('.red-ui-tray-body');
var trayFooter = tray.find(".red-ui-tray-footer");
var userCountDiv;
var trayFooterLeft = $('<div class="red-ui-tray-footer-left"></div>').appendTo(trayFooter)
$('<input id="node-config-input-node-disabled" type="checkbox">').prop("checked",!!editing_config_node.d).appendTo(trayFooterLeft).toggleButton({
enabledIcon: "fa-circle-thin",
disabledIcon: "fa-ban",
invertState: true
})
if (node_def.hasUsers !== false) {
userCountDiv = $('<div class="red-ui-tray-footer-left"><i class="fa fa-info-circle"></i> <span></span></div>').prependTo(trayFooter);
$('<span><i class="fa fa-info-circle"></i> <span id="red-ui-editor-config-user-count"></span></span>').css("margin-left", "10px").appendTo(trayFooterLeft);
}
trayFooter.append('<span class="red-ui-tray-footer-right"><span id="red-ui-editor-config-scope-warning" data-i18n="[title]editor.errors.scopeChange"><i class="fa fa-warning"></i></span><select id="red-ui-editor-config-scope"></select></span>');
@@ -1693,7 +1767,8 @@ RED.editor = (function() {
RED.tray.resize();
}
},
collapsible: true
collapsible: true,
menu: false
});
var nodePropertiesTab = {
@@ -1768,8 +1843,8 @@ RED.editor = (function() {
}
});
}
if (node_def.hasUsers !== false && userCountDiv) {
userCountDiv.find("span").text(RED._("editor.nodesUse", {count:editing_config_node.users.length})).parent().show();
if (node_def.hasUsers !== false) {
$("#red-ui-editor-config-user-count").text(RED._("editor.nodesUse", {count:editing_config_node.users.length})).parent().show();
}
trayBody.i18n();
trayFooter.i18n();
@@ -1800,7 +1875,6 @@ RED.editor = (function() {
var configId = editing_config_node.id;
var configAdding = adding;
var configTypeDef = RED.nodes.getType(configType);
if (configTypeDef.oneditcancel) {
// TODO: what to pass as this to call
if (configTypeDef.oneditcancel) {
@@ -1904,6 +1978,16 @@ RED.editor = (function() {
editing_config_node.label = configTypeDef.label;
editing_config_node.z = scope;
if ($("#node-config-input-node-disabled").prop('checked')) {
if (editing_config_node.d !== true) {
editing_config_node.d = true;
}
} else {
if (editing_config_node.d === true) {
delete editing_config_node.d;
}
}
if (scope) {
// Search for nodes that use this one that are no longer
// in scope, so must be removed
@@ -2058,7 +2142,7 @@ RED.editor = (function() {
RED.nodes.eachConfig(function(config) {
if (config.type == type && (!config.z || config.z === activeWorkspace.id)) {
var label = RED.utils.getNodeLabel(config,config.id);
config.__label__ = label;
config.__label__ = label+(config.d?" ["+RED._("workspace.disabled")+"]":"");
configNodes.push(config);
}
});
@@ -2127,16 +2211,16 @@ RED.editor = (function() {
if (updateLabels(editing_node, changes, null)) {
changed = true;
}
var icon = $("#red-ui-editor-node-icon").text()||"";
if ((editing_node.icon === undefined && icon !== "node-red/subflow.png") ||
var icon = $("#red-ui-editor-node-icon").val()||"";
if ((editing_node.icon === undefined && icon !== "node-red/subflow.svg") ||
(editing_node.icon !== undefined && editing_node.icon !== icon)) {
changes.icon = editing_node.icon;
editing_node.icon = icon;
changed = true;
}
var newCategory = $("#subflow-input-category").val().trim();
var newCategory = $("#subflow-appearance-input-category").val().trim();
if (newCategory === "_custom_") {
newCategory = $("#subflow-input-custom-category").val().trim();
newCategory = $("#subflow-appearance-input-custom-category").val().trim();
if (newCategory === "") {
newCategory = editing_node.category;
}
@@ -2150,14 +2234,28 @@ RED.editor = (function() {
changed = true;
}
var oldColor = editing_node.color;
var newColor = $("#red-ui-editor-node-color").val();
if (oldColor !== newColor) {
editing_node.color = newColor;
changes.color = newColor;
changed = true;
RED.utils.clearNodeColorCache();
if (editing_node.type === "subflow") {
var nodeDefinition = RED.nodes.getType(
"subflow:" + editing_node.id
);
nodeDefinition["color"] = newColor;
}
}
var old_env = editing_node.env;
var new_env = exportEnvList($("#node-input-env-container").editableList("items"));
if (!isSameEnv(old_env, new_env)) {
var new_env = RED.subflow.exportSubflowTemplateEnv($("#node-input-env-container").editableList("items"));
if (!isSameObj(old_env, new_env)) {
editing_node.env = new_env;
changes.env = editing_node.env;
changed = true;
}
RED.palette.refresh();
if (changed) {
@@ -2171,6 +2269,7 @@ RED.editor = (function() {
id:n.id,
changed:n.changed
})
n._def.color = editing_node.color;
n.changed = true;
n.dirty = true;
updateNodeProperties(n);
@@ -2198,21 +2297,39 @@ RED.editor = (function() {
],
resize: function(size) {
$(".red-ui-tray-content").height(size.height - 50);
// var form = $(".red-ui-tray-content form").height(size.height - 50 - 40);
var rows = $("#dialog-form>div:not(.node-input-env-container-row)");
var height = size.height;
for (var i=0; i<rows.size(); i++) {
height -= $(rows[i]).outerHeight(true);
var envContainer = $("#node-input-env-container");
if (envContainer.length) {
// var form = $(".red-ui-tray-content form").height(size.height - 50 - 40);
var rows = $("#dialog-form>div:not(#subflow-env-tabs-content)");
var height = size.height;
for (var i=0; i<rows.size(); i++) {
height -= $(rows[i]).outerHeight(true);
}
// var editorRow = $("#dialog-form>div.node-input-env-container-row");
// height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
$("#node-input-env-container").editableList('height',height-95);
}
var editorRow = $("#dialog-form>div.node-input-env-container-row");
height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
$("#node-input-env-container").editableList('height',height-80);
},
open: function(tray) {
var trayFooter = tray.find(".red-ui-tray-footer");
var trayFooterLeft = $("<div/>", {
class: "red-ui-tray-footer-left"
}).appendTo(trayFooter)
var trayBody = tray.find('.red-ui-tray-body');
trayBody.parent().css('overflow','hidden');
if (editing_node.type === "subflow") {
var span = $("<span/>").css({
"margin-left": "10px"
}).appendTo(trayFooterLeft);
$("<i/>", {
class: "fa fa-info-circle"
}).appendTo(span);
$("<span/>").text(" ").appendTo(span);
$("<i/>", {
id: "red-ui-editor-subflow-user-count"
}).appendTo(span);
}
if (editing_node) {
RED.sidebar.info.refresh(editing_node);
@@ -2233,7 +2350,8 @@ RED.editor = (function() {
RED.tray.resize();
}
},
collapsible: true
collapsible: true,
menu: false
});
var nodePropertiesTab = {
@@ -2272,46 +2390,9 @@ RED.editor = (function() {
buildAppearanceForm(appearanceTab.content,editing_node);
editorTabs.addTab(appearanceTab);
$("#subflow-input-name").val(subflow.name);
RED.text.bidi.prepareInput($("#subflow-input-name"));
$("#subflow-input-category").empty();
var categories = RED.palette.getCategories();
categories.sort(function(A,B) {
return A.label.localeCompare(B.label);
})
categories.forEach(function(cat) {
$("#subflow-input-category").append($("<option></option>").val(cat.id).text(cat.label));
})
$("#subflow-input-category").append($("<option></option>").attr('disabled',true).text("---"));
$("#subflow-input-category").append($("<option></option>").val("_custom_").text(RED._("palette.addCategory")));
$("#subflow-input-category").on("change", function() {
var val = $(this).val();
if (val === "_custom_") {
$("#subflow-input-category").width(120);
$("#subflow-input-custom-category").show();
} else {
$("#subflow-input-category").width(250);
$("#subflow-input-custom-category").hide();
}
})
$("#subflow-input-category").val(subflow.category||"subflows");
var userCount = 0;
var subflowType = "subflow:"+editing_node.id;
RED.nodes.eachNode(function(n) {
if (n.type === subflowType) {
userCount++;
}
});
$("#subflow-dialog-user-count").text(RED._("subflow.subflowInstances", {count:userCount})).show();
trayBody.i18n();
finishedBuilding = true;
},
@@ -2405,7 +2486,7 @@ RED.editor = (function() {
editor.toolbar = customEditTypes['_markdown'].buildToolbar(toolbarRow,editor);
if (options.expandable !== false) {
var expandButton = $('<button type="button" class="red-ui-button" style="float: right;"><i class="fa fa-expand"></i></button>').appendTo(editor.toolbar);
RED.popover.tooltip(expandButton, RED._("markdownEditor.expand"));
expandButton.on("click", function(e) {
e.preventDefault();
var value = editor.getValue();
@@ -2432,6 +2513,7 @@ RED.editor = (function() {
content: RED._("markdownEditor.format"),
autoClose: 50
});
session.setUseWrapMode(true);
}
return editor;
}
@@ -2464,6 +2546,8 @@ RED.editor = (function() {
validateNode: validateNode,
updateNodeProperties: updateNodeProperties, // TODO: only exposed for edit-undo
showIconPicker:showIconPicker,
/**
* Show a type editor.
* @param {string} type - the type to display
@@ -2476,7 +2560,7 @@ RED.editor = (function() {
/**
* Register a type editor.
* @param {string} type - the type name
* @param {object} options - the editor definition
* @param {object} definition - the editor definition
* @function
* @memberof RED.editor
*/

View File

@@ -207,6 +207,7 @@
}
expressionEditor.getSession().setValue(v||"",-1);
});
funcSelect.change();
var tabs = RED.tabs.create({
element: $("#red-ui-editor-type-expression-tabs"),

View File

@@ -16,7 +16,420 @@
(function() {
var template = '<script type="text/x-red" data-template-name="_json"><div class="form-row" style="margin-bottom: 3px; text-align: right;"><button id="node-input-json-reformat" class="red-ui-button red-ui-button-small"><span data-i18n="jsonEditor.format"></span></button></div><div class="form-row node-text-editor-row"><div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-json"></div></div></script>';
// var template = '<script type="text/x-red" data-template-name="_json"></script>';
var template = '<script type="text/x-red" data-template-name="_json">'+
'<ul id="red-ui-editor-type-json-tabs"></ul>'+
'<div id="red-ui-editor-type-json-tab-raw" class="red-ui-editor-type-json-tab-content hide">'+
'<div class="form-row" style="margin-bottom: 3px; text-align: right;">'+
'<button id="node-input-json-reformat" class="red-ui-button red-ui-button-small"><span data-i18n="jsonEditor.format"></span></button>'+
'</div>'+
'<div class="form-row node-text-editor-row">'+
'<div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-json"></div>'+
'</div>'+
'</div>'+
'<div id="red-ui-editor-type-json-tab-ui" class="red-ui-editor-type-json-tab-content hide">'+
'<div id="red-ui-editor-type-json-tab-ui-container"></div>'+
'</div>'+
'</script>';
var activeTab;
function insertNewItem(parent,index,copyIndex) {
var newValue = "";
if (parent.children.length > 0) {
switch (parent.children[Math.max(0,Math.min(parent.children.length-1,copyIndex))].type) {
case 'string': newValue = ""; break;
case 'number': newValue = 0; break;
case 'boolean': newValue = true; break;
case 'null': newValue = null; break;
case 'object': newValue = {}; break;
case 'array': newValue = []; break;
}
}
var newKey;
if (parent.type === 'array') {
newKey = parent.children.length;
} else {
var usedKeys = {};
parent.children.forEach(function(child) { usedKeys[child.key] = true })
var keyRoot = "item";
var keySuffix = 2;
newKey = keyRoot;
while(usedKeys[newKey]) {
newKey = keyRoot+"-"+(keySuffix++);
}
}
var newItem = handleItem(newKey,newValue,parent.depth+1,parent);
parent.treeList.insertChildAt(newItem, index, true);
parent.treeList.expand();
}
function showObjectMenu(button,item) {
var elementPos = button.offset();
var options = [];
if (item.parent) {
options.push({id:"red-ui-editor-type-json-menu-insert-above", icon:"fa fa-toggle-up", label:RED._('jsonEditor.insertAbove'),onselect:function(){
var index = item.parent.children.indexOf(item);
insertNewItem(item.parent,index,index);
}});
options.push({id:"red-ui-editor-type-json-menu-insert-below", icon:"fa fa-toggle-down", label:RED._('jsonEditor.insertBelow'),onselect:function(){
var index = item.parent.children.indexOf(item)+1;
insertNewItem(item.parent,index,index-1);
}});
}
if (item.type === 'array' || item.type === 'object') {
options.push({id:"red-ui-editor-type-json-menu-add-child", icon:"fa fa-plus", label:RED._('jsonEditor.addItem'),onselect:function(){
insertNewItem(item,item.children.length,item.children.length-1);
}});
}
if (item.parent) {
options.push({id:"red-ui-editor-type-json-menu-copy-path", icon:"fa fa-terminal", label:RED._('jsonEditor.copyPath'),onselect:function(){
var i = item;
var path = "";
var newPath;
while(i.parent) {
if (i.parent.type === "array") {
newPath = "["+i.key+"]";
} else {
if (/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(i.key)) {
newPath = i.key;
} else {
newPath = "[\""+i.key.replace(/"/,"\\\"")+"\"]"
}
}
path = newPath+(path.length>0 && path[0] !== "["?".":"")+path;
i = i.parent;
}
RED.clipboard.copyText(path,item.element,"clipboard.copyMessagePath");
}});
options.push({id:"red-ui-editor-type-json-menu-duplicate", icon:"fa fa-copy", label:RED._("jsonEditor.duplicate"),onselect:function(){
var newKey = item.key;
if (item.parent.type === 'array') {
newKey = parent.children.length;
} else {
var m = /^(.*?)(-(\d+))?$/.exec(newKey);
var usedKeys = {};
item.parent.children.forEach(function(child) { usedKeys[child.key] = true })
var keyRoot = m[1];
var keySuffix = 2;
if (m[3] !== undefined) {
keySuffix = parseInt(m[3]);
}
newKey = keyRoot;
while(usedKeys[newKey]) {
newKey = keyRoot+"-"+(keySuffix++);
}
}
var newItem = handleItem(newKey,convertToObject(item),item.parent.depth+1,item.parent);
var index = item.parent.children.indexOf(item)+1;
item.parent.treeList.insertChildAt(newItem, index, true);
item.parent.treeList.expand();
}});
options.push({id:"red-ui-editor-type-json-menu-delete", icon:"fa fa-times", label:RED._('common.label.delete'),onselect:function(){
item.treeList.remove();
}});
}
if (item.type === 'array' || item.type === 'object') {
options.push(null)
options.push({id:"red-ui-editor-type-json-menu-expand-children",icon:"fa fa-angle-double-down", label:RED._('jsonEditor.expandItems'),onselect:function(){
item.treeList.expand();
item.children.forEach(function(child) {
child.treeList.expand();
})
}});
options.push({id:"red-ui-editor-type-json-menu-collapse-children",icon:"fa fa-angle-double-up", label:RED._('jsonEditor.collapseItems'),onselect:function(){
item.treeList.collapse();
item.children.forEach(function(child) {
child.treeList.collapse();
})
}});
}
var menuOptionMenu = RED.menu.init({
id:"red-ui-editor-type-json-menu",
options: options
});
menuOptionMenu.css({
position: "absolute"
})
menuOptionMenu.on('mouseleave', function(){ $(this).hide() });
menuOptionMenu.on('mouseup', function() { $(this).hide() });
menuOptionMenu.appendTo("body");
var top = elementPos.top;
var height = menuOptionMenu.height();
var winHeight = $(window).height();
if (top+height > winHeight) {
top -= (top+height)-winHeight + 20;
}
menuOptionMenu.css({
top: top+"px",
left: elementPos.left+"px"
})
menuOptionMenu.show();
}
function parseObject(obj,depth,parent) {
var result = [];
for (var prop in obj) {
if (obj.hasOwnProperty(prop)) {
result.push(handleItem(prop,obj[prop],depth,parent));
}
}
return result;
}
function parseArray(obj,depth,parent) {
var result = [];
var l = obj.length;
for (var i=0;i<l;i++) {
result.push(handleItem(i,obj[i],depth,parent));
}
return result;
}
function handleItem(key,val,depth,parent) {
var item = {depth:depth, type: typeof val};
var container = $('<span class="red-ui-editor-type-json-editor-label">');
if (key != null) {
item.key = key;
var keyText;
if (typeof key === 'string') {
keyText = '"'+key+'"';
} else {
keyText = key;
}
var keyLabel = $('<span class="red-ui-debug-msg-object-key red-ui-editor-type-json-editor-label-key">').text(keyText).appendTo(container);
keyLabel.addClass('red-ui-debug-msg-type-'+(typeof key));
if (parent && parent.type === "array") {
keyLabel.addClass("red-ui-editor-type-json-editor-label-array-key")
}
keyLabel.on("click", function(evt) {
if (item.parent.type === 'array') {
return;
}
evt.preventDefault();
evt.stopPropagation();
var w = Math.max(150,keyLabel.width());
var keyInput = $('<input type="text" class="red-ui-editor-type-json-editor-key">').css({width:w+"px"}).val(""+item.key).insertAfter(keyLabel).typedInput({types:['str']});
$(document).on("mousedown.nr-ui-json-editor", function(evt) {
var typedInputElement = keyInput.next(".red-ui-typedInput-container")[0];
var target = evt.target;
while (target.nodeName !== 'BODY' && target !== typedInputElement && !$(target).hasClass("red-ui-typedInput-options")) {
target = target.parentElement;
}
if (target.nodeName === 'BODY') {
var newKey = keyInput.typedInput("value");
item.key = newKey;
var keyText;
if (typeof newKey === 'string') {
keyText = '"'+newKey+'"';
} else {
keyText = newKey;
}
keyLabel.text(keyText);
keyInput.remove();
keyLabel.show();
$(document).off("mousedown.nr-ui-json-editor");
$(document).off("keydown.nr-ui-json-editor");
}
});
$(document).on("keydown.nr-ui-json-editor",function(evt) {
if (evt.keyCode === 27) {
// Escape
keyInput.remove();
keyLabel.show();
$(document).off("mousedown.nr-ui-json-editor");
$(document).off("keydown.nr-ui-json-editor");
}
});
keyLabel.hide();
});
$('<span>').text(" : ").appendTo(container);
}
if (Array.isArray(val)) {
item.expanded = depth < 2;
item.type = "array";
item.deferBuild = depth >= 2;
item.children = parseArray(val,depth+1,item);
} else if (val !== null && item.type === "object") {
item.expanded = depth < 2;
item.children = parseObject(val,depth+1,item);
item.deferBuild = depth >= 2;
} else {
item.value = val;
if (val === null) {
item.type = 'null'
}
}
var valType;
var valValue = "";
var valClass;
switch(item.type) {
case 'string': valType = 'str'; valValue = '"'+item.value+'"'; valClass = "red-ui-debug-msg-type-string"; break;
case 'number': valType = 'num'; valValue = item.value; valClass = "red-ui-debug-msg-type-number";break;
case 'boolean': valType = 'bool'; valValue = item.value; valClass = "red-ui-debug-msg-type-other";break;
case 'null': valType = item.type; valValue = item.type; valClass = "red-ui-debug-msg-type-null";break;
case 'object':
valType = item.type;
valValue = item.type;//+"{"+item.children.length+"}";
valClass = "red-ui-debug-msg-type-meta";
break;
case 'array':
valType = item.type;
valValue = item.type+"["+item.children.length+"]";
valClass = "red-ui-debug-msg-type-meta";
break;
}
//
var orphanedChildren;
var valueLabel = $('<span class="red-ui-editor-type-json-editor-label-value">').addClass(valClass).text(valValue).appendTo(container);
valueLabel.on("click", function(evt) {
evt.preventDefault();
evt.stopPropagation();
if (valType === 'str') {
valValue = valValue.substring(1,valValue.length-1);
} else if (valType === 'array') {
valValue = "";
} else if (valType === 'object') {
valValue = "";
}
var w = Math.max(150,valueLabel.width());
var val = $('<input type="text" class="red-ui-editor-type-json-editor-value">').css({width:w+"px"}).val(""+valValue).insertAfter(valueLabel).typedInput({
types:[
'str','num','bool',
{value:"null",label:RED._("common.type.null"),hasValue:false},
{value:"array",label:RED._("common.type.array"),hasValue:false,icon:"red/images/typedInput/json.png"},
{value:"object",label:RED._("common.type.object"),hasValue:false,icon:"red/images/typedInput/json.png"}
],
default: valType
});
$(document).on("mousedown.nr-ui-json-editor", function(evt) {
var typedInputElement = val.next(".red-ui-typedInput-container")[0];
var target = evt.target;
while (target.nodeName !== 'BODY' && target !== typedInputElement && !$(target).hasClass("red-ui-typedInput-options")) {
target = target.parentElement;
}
if (target.nodeName === 'BODY') {
valType = val.typedInput("type");
valValue = val.typedInput("value");
if (valType === 'num') {
valValue = valValue.trim();
if (isNaN(valValue)) {
valType = 'str';
} else if (valValue === "") {
valValue = 0;
}
}
item.value = valValue;
var valClass;
switch(valType) {
case 'str': if (item.children) { orphanedChildren = item.children } item.treeList.makeLeaf(true); item.type = "string"; valClass = "red-ui-debug-msg-type-string"; valValue = '"'+valValue+'"'; break;
case 'num': if (item.children) { orphanedChildren = item.children } item.treeList.makeLeaf(true); item.type = "number"; valClass = "red-ui-debug-msg-type-number"; break;
case 'bool': if (item.children) { orphanedChildren = item.children } item.treeList.makeLeaf(true); item.type = "boolean"; valClass = "red-ui-debug-msg-type-other"; item.value = (valValue === "true"); break;
case 'null': if (item.children) { orphanedChildren = item.children } item.treeList.makeLeaf(true); item.type = "null"; valClass = "red-ui-debug-msg-type-null"; item.value = valValue = "null"; break;
case 'object':
item.treeList.makeParent(orphanedChildren);
item.type = "object";
valClass = "red-ui-debug-msg-type-meta";
item.value = valValue = "object";
item.children.forEach(function(child,i) {
if (child.hasOwnProperty('_key')) {
child.key = child._key;
delete child._key;
var keyText;
var keyLabel = child.element.find(".red-ui-editor-type-json-editor-label-key");
keyLabel.removeClass("red-ui-editor-type-json-editor-label-array-key");
if (typeof child.key === 'string') {
keyText = '"'+child.key+'"';
keyLabel.addClass('red-ui-debug-msg-type-string');
keyLabel.removeClass('red-ui-debug-msg-type-number');
} else {
keyText = child.key;
keyLabel.removeClass('red-ui-debug-msg-type-string');
keyLabel.addClass('red-ui-debug-msg-type-number');
}
keyLabel.text(keyText);
}
})
break;
case 'array':
item.treeList.makeParent(orphanedChildren);
item.type = "array";
valClass = "red-ui-debug-msg-type-meta";
item.value = valValue = "array["+(item.children.length)+"]";
item.children.forEach(function(child,i) {
child._key = child.key;
child.key = i;
child.element.find(".red-ui-editor-type-json-editor-label-key")
.addClass("red-ui-editor-type-json-editor-label-array-key")
.text(""+child.key)
.removeClass('red-ui-debug-msg-type-string')
.addClass('red-ui-debug-msg-type-number');
})
break;
}
valueLabel.text(valValue).removeClass().addClass("red-ui-editor-type-json-editor-label-value "+valClass);
val.remove();
valueLabel.show();
$(document).off("mousedown.nr-ui-json-editor");
$(document).off("keydown.nr-ui-json-editor");
}
})
$(document).on("keydown.nr-ui-json-editor",function(evt) {
if (evt.keyCode === 27) {
// Escape
val.remove();
valueLabel.show();
if (valType === 'str') {
valValue = '"'+valValue+'"';
}
$(document).off("mousedown.nr-ui-json-editor");
$(document).off("keydown.nr-ui-json-editor");
}
});
valueLabel.hide();
})
item.gutter = $('<span class="red-ui-editor-type-json-editor-item-gutter"></span>');
if (parent) {//red-ui-editor-type-json-editor-item-handle
$('<span class="red-ui-editor-type-json-editor-item-handle"><i class="fa fa-bars"></span>').appendTo(item.gutter);
} else {
$('<span></span>').appendTo(item.gutter);
}
$('<button type="button" class="editor-button editor-button-small"><i class="fa fa-caret-down"></button>').appendTo(item.gutter).on("click", function(evt) {
evt.preventDefault();
evt.stopPropagation();
showObjectMenu($(this), item);
});
item.element = container;
return item;
}
function convertToObject(item) {
var element;
switch (item.type) {
case 'string': element = item.value; break;
case 'number': element = Number(item.value); break;
case 'boolean': element = item.value; break;
case 'null': element = null; break;
case 'object':
element = {};
item.children.forEach(function(child) {
element[child.key] = convertToObject(child);
})
break;
case 'array':
element = item.children.map(function(child) {
return convertToObject(child);
})
break;
}
return element;
}
var definition = {
show: function(options) {
@@ -41,9 +454,11 @@
return false;
}
}
var rootNode;
var trayOptions = {
title: options.title,
width: "inherit",
width: options.width||700,
buttons: [
{
id: "node-dialog-cancel",
@@ -60,25 +475,60 @@
if (options.requireValid && !checkValid()) {
return;
}
onComplete(expressionEditor.getValue());
var result;
if (activeTab === "json-ui") {
if (rootNode) {
result = JSON.stringify(convertToObject(rootNode),null,4);
} else {
result = expressionEditor.getValue();
}
} else if (activeTab === "json-raw") {
result = expressionEditor.getValue();
}
if (onComplete) { onComplete(result) }
RED.tray.close();
}
}
],
resize: function(dimensions) {
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
var editorRow = $("#dialog-form>div.node-text-editor-row");
var height = $("#dialog-form").height();
for (var i=0;i<rows.size();i++) {
height -= $(rows[i]).outerHeight(true);
}
height -= (parseInt($("#dialog-form").css("marginTop"))+parseInt($("#dialog-form").css("marginBottom")));
$(".node-text-editor").css("height",height+"px");
var height = $(".red-ui-editor-type-json-tab-content").height();
$(".node-text-editor").css("height",(height-45)+"px");
expressionEditor.resize();
},
open: function(tray) {
var trayBody = tray.find('.red-ui-tray-body');
var dialogForm = RED.editor.buildEditForm(tray.find('.red-ui-tray-body'),'dialog-form',type,'editor');
var container = $("#red-ui-editor-type-json-tab-ui-container").css({"height":"100%"});
var filterDepth = Infinity;
var list = $('<div class="red-ui-debug-msg-payload red-ui-editor-type-json-editor">').appendTo(container).treeList({
rootSortable: false,
sortable: ".red-ui-editor-type-json-editor-item-handle",
}).on("treelistchangeparent", function(event, evt) {
if (evt.old.type === 'array') {
evt.old.element.find(".red-ui-editor-type-json-editor-label-type").text("array["+evt.old.children.length+"]");
}
if (evt.item.parent.type === 'array') {
evt.item.parent.element.find(".red-ui-editor-type-json-editor-label-type").text("array["+evt.item.parent.children.length+"]");
}
}).on("treelistsort", function(event, item) {
item.children.forEach(function(child,i) {
if (item.type === 'array') {
child.key = i;
child.element.find(".red-ui-editor-type-json-editor-label-key")
.text(child.key)
.removeClass('red-ui-debug-msg-type-string')
.addClass('red-ui-debug-msg-type-number');
} else {
child.element.find(".red-ui-editor-type-json-editor-label-key")
.text('"'+child.key+'"')
.removeClass('red-ui-debug-msg-type-number')
.addClass('red-ui-debug-msg-type-string');
}
})
});
expressionEditor = RED.editor.createEditor({
id: 'node-input-json',
value: "",
@@ -103,9 +553,56 @@
expressionEditor.getSession().setValue(v||"",-1);
});
dialogForm.i18n();
var finishedBuild = false;
var tabs = RED.tabs.create({
element: $("#red-ui-editor-type-json-tabs"),
onchange:function(tab) {
activeTab = tab.id;
$(".red-ui-editor-type-json-tab-content").hide();
if (finishedBuild) {
if (tab.id === "json-raw") {
if (rootNode) {
var result = JSON.stringify(convertToObject(rootNode),null,4);
expressionEditor.getSession().setValue(result||"",-1);
}
} else if (tab.id === "json-ui") {
var raw = expressionEditor.getValue().trim() ||"{}";
try {
var parsed = JSON.parse(raw);
rootNode = handleItem(null,parsed,0,null);
rootNode.class = "red-ui-editor-type-json-root-node"
list.treeList('data',[rootNode]);
} catch(err) {
rootNode = null;
list.treeList('data',[{
label: RED._("jsonEditor.error.invalidJSON")+err.toString()
}]);
}
}
}
tab.content.show();
trayOptions.resize();
}
})
tabs.addTab({
id: 'json-raw',
label: RED._('jsonEditor.rawMode'),
content: $("#red-ui-editor-type-json-tab-raw")
});
tabs.addTab({
id: 'json-ui',
label: RED._('jsonEditor.uiMode'),
content: $("#red-ui-editor-type-json-tab-ui")
});
finishedBuild = true;
},
close: function() {
expressionEditor.destroy();
// expressionEditor.destroy();
if (options.onclose) {
options.onclose();
}

View File

@@ -32,13 +32,13 @@
'<button type="button" class="red-ui-button" data-style="bq"><i class="fa fa-quote-left"></i></button>'+
'<button type="button" class="red-ui-button" data-style="hr"><i class="fa fa-minus"></i></button>'+
'<button type="button" class="red-ui-button" data-style="link"><i class="fa fa-link"></i></button>'+
'</span>'
'</span>'+
'</div>';
var template = '<script type="text/x-red" data-template-name="_markdown">'+
'<div id="red-ui-editor-type-markdown-panels">'+
'<div id="red-ui-editor-type-markdown-panel-editor" class="red-ui-panel">'+
'<div style="height: 100%; margin: auto; max-width: 1000px;">'+
'<div style="height: 100%; margin: auto;">'+
'<div id="red-ui-editor-type-markdown-toolbar"></div>'+
'<div class="node-text-editor" style="height: 100%" id="red-ui-editor-type-markdown"></div>'+
'</div>'+

View File

@@ -19,7 +19,7 @@ RED.keyboard = (function() {
var handlers = {};
var partialState;
RED.h = handlers;
var keyMap = {
"left":37,
"up":38,

View File

@@ -133,7 +133,7 @@ RED.library = (function() {
icon: 'fa fa-folder',
label: d,
path: root+d+"/",
children: function(item,done) {
children: function(done, item) {
loadLibraryFolder(library,type,root+d+"/", function(children) {
item.children = children; // TODO: should this be done by treeList for us
done(children);
@@ -325,7 +325,7 @@ RED.library = (function() {
var menuOptionMenu = RED.menu.init({id:"red-ui-library-browser-menu",
options: [
{id:"red-ui-library-browser-menu-addFolder",label:"New folder", onselect: function() {
{id:"red-ui-library-browser-menu-addFolder",label:RED._("library.newFolder"), onselect: function() {
var defaultFolderName = "new-folder";
var defaultFolderNameMatches = {};
@@ -431,11 +431,13 @@ RED.library = (function() {
focus: function() {
dirList.focus();
},
data: function(content) {
data: function(content,selectFirst) {
dirList.treeList('data',content);
// setTimeout(function() {
// dirList.treeList('select',content[0]);
// },100);
if (selectFirst) {
setTimeout(function() {
dirList.treeList('select',content[0]);
},100);
}
}
}
}

View File

@@ -788,7 +788,7 @@ RED.palette.editor = (function() {
initInstallTab();
})
packageList = $('<ol>',{style:"position: absolute;top: 78px;bottom: 0;left: 0;right: 0px;"}).appendTo(installTab).editableList({
packageList = $('<ol>',{style:"position: absolute;top: 79px;bottom: 0;left: 0;right: 0px;"}).appendTo(installTab).editableList({
addButton: false,
scrollOnAdd: false,
addItem: function(container,i,object) {

View File

@@ -17,7 +17,20 @@
RED.palette = (function() {
var exclusion = ['config','unknown','deprecated'];
var coreCategories = ['subflows', 'input', 'output', 'function', 'social', 'mobile', 'storage', 'analysis', 'advanced'];
var coreCategories = [
'subflows',
'common',
'function',
'network',
'input',
'output',
'sequence',
'parser',
'storage',
'analysis',
'social',
'advanced'
];
var categoryContainers = {};
var sidebarControls;
@@ -37,6 +50,7 @@ RED.palette = (function() {
var catDiv = $('<div id="red-ui-palette-container-'+category+'" class="red-ui-palette-category hide">'+
'<div id="red-ui-palette-header-'+category+'" class="red-ui-palette-header"><i class="expanded fa fa-angle-down"></i><span>'+label+'</span></div>'+
'<div class="red-ui-palette-content" id="red-ui-palette-base-category-'+category+'">'+
'<div id="red-ui-palette-'+category+'"></div>'+
'<div id="red-ui-palette-'+category+'-input"></div>'+
'<div id="red-ui-palette-'+category+'-output"></div>'+
'<div id="red-ui-palette-'+category+'-function"></div>'+
@@ -84,18 +98,36 @@ RED.palette = (function() {
var displayLines = [];
var currentLine = words[0];
var currentLineWidth = RED.view.calculateTextWidth(currentLine, "red-ui-palette-label", 0);
for (var i=1;i<words.length;i++) {
var newWidth = RED.view.calculateTextWidth(currentLine+" "+words[i], "red-ui-palette-label", 0);
var currentLine = "";
for (var i=0;i<words.length;i++) {
var word = words[i];
var sep = (i == 0) ? "" : " ";
var newWidth = RED.view.calculateTextWidth(currentLine+sep+word, "red-ui-palette-label", 0);
if (newWidth < nodeWidth) {
currentLine += " "+words[i];
currentLineWidth = newWidth;
currentLine += sep +word;
} else {
displayLines.push(currentLine);
currentLine = words[i];
currentLineWidth = RED.view.calculateTextWidth(currentLine, "red-ui-palette-label", 0);
if (i > 0) {
displayLines.push(currentLine);
}
while (true) {
var wordWidth = RED.view.calculateTextWidth(word, "red-ui-palette-label", 0);
if (wordWidth >= nodeWidth) {
// break word if too wide
for(var j = word.length; j > 0; j--) {
var s = word.substring(0, j);
var width = RED.view.calculateTextWidth(s, "red-ui-palette-label", 0);
if (width < nodeWidth) {
displayLines.push(s);
word = word.substring(j);
break;
}
}
}
else {
currentLine = word;
break;
}
}
}
}
displayLines.push(currentLine);
@@ -149,26 +181,28 @@ RED.palette = (function() {
RED.utils.createIconElement(icon_url, iconContainer, true);
}
function escapeNodeType(nt) {
return nt.replace(" ","_").replace(".","_").replace(":","_");
function getPaletteNode(type) {
return $(".red-ui-palette-node[data-palette-type='"+type+"']");
}
function escapeCategory(category) {
return category.replace(/[ /.]/g,"_");
}
function addNodeType(nt,def) {
var nodeTypeId = escapeNodeType(nt);
if ($("#red-ui-palette-node_"+nodeTypeId).length) {
if (getPaletteNode(nt).length) {
return;
}
if (exclusion.indexOf(def.category)===-1) {
var nodeCategory = def.category;
var originalCategory = def.category;
var category = def.category.replace(/ /g,"_");
if (exclusion.indexOf(nodeCategory)===-1) {
var originalCategory = nodeCategory;
var category = escapeCategory(nodeCategory);
var rootCategory = category.split("-")[0];
var d = document.createElement("div");
d.id = "red-ui-palette-node_"+nodeTypeId;
d.type = nt;
var d = $('<div>',{class:"red-ui-palette-node"}).attr("data-palette-type",nt).data('category',rootCategory);
var label = /^(.*?)([ -]in|[ -]out)?$/.exec(nt)[1];
var label = nt;///^(.*?)([ -]in|[ -]out)?$/.exec(nt)[1];
if (typeof def.paletteLabel !== "undefined") {
try {
label = (typeof def.paletteLabel === "function" ? def.paletteLabel.call(def) : def.paletteLabel)||"";
@@ -178,51 +212,47 @@ RED.palette = (function() {
}
$('<div/>', {
class: "red-ui-palette-label"
+ (((!def.align && def.inputs !== 0 && def.outputs === 0) || "right" === def.align) ? " red-ui-palette-label-right" : "")
class: "red-ui-palette-label"+(((!def.align && def.inputs !== 0 && def.outputs === 0) || "right" === def.align) ? " red-ui-palette-label-right" : "")
}).appendTo(d);
d.className="red-ui-palette-node";
if (def.icon) {
var icon_url = RED.utils.getNodeIcon(def);
var iconContainer = $('<div/>', {
class: "red-ui-palette-icon-container"
+ (((!def.align && def.inputs !== 0 && def.outputs === 0) || "right" === def.align) ? " red-ui-palette-icon-container-right" : "")
class: "red-ui-palette-icon-container"+(((!def.align && def.inputs !== 0 && def.outputs === 0) || "right" === def.align) ? " red-ui-palette-icon-container-right" : "")
}).appendTo(d);
RED.utils.createIconElement(icon_url, iconContainer, true);
}
d.style.backgroundColor = RED.utils.getNodeColor(nt,def);
d.css("backgroundColor", RED.utils.getNodeColor(nt,def));
if (def.outputs > 0) {
var portOut = document.createElement("div");
portOut.className = "red-ui-palette-port red-ui-palette-port-output";
d.appendChild(portOut);
d.append(portOut);
}
if (def.inputs > 0) {
var portIn = document.createElement("div");
portIn.className = "red-ui-palette-port red-ui-palette-port-input";
d.appendChild(portIn);
d.append(portIn);
}
createCategory(def.category,rootCategory,category,(coreCategories.indexOf(rootCategory) !== -1)?"node-red":def.set.id);
createCategory(nodeCategory,rootCategory,category,(coreCategories.indexOf(rootCategory) !== -1)?"node-red":def.set.id);
$("#red-ui-palette-"+category).append(d);
$(d).data('category',rootCategory);
d.onmousedown = function(e) { e.preventDefault(); };
d.on("mousedown", function(e) { e.preventDefault();});
var popover = RED.popover.create({
target:$(d),
target:d,
trigger: "hover",
width: "300px",
content: "hi",
delay: { show: 750, hide: 50 }
});
$(d).data('popover',popover);
d.data('popover',popover);
// $(d).popover({
// title:d.type,
@@ -232,18 +262,20 @@ RED.palette = (function() {
// html: true,
// container:'body'
// });
$(d).on("click", function() {
d.on("click", function() {
RED.view.focus();
var helpText;
if (nt.indexOf("subflow:") === 0) {
helpText = marked(RED.nodes.subflow(nt.substring(8)).info||"")||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
} else {
helpText = $("script[data-help-name='"+d.type+"']").html()||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
helpText = $("script[data-help-name='"+d.attr("data-palette-type")+"']").html()||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
}
// Don't look too closely. RED.sidebar.info.set will set the 'Description'
// section of the sidebar. Pass in the title of the Help section so it looks
// right.
RED.sidebar.info.set(helpText,RED._("sidebar.info.nodeHelp"));
});
var chart = $("#red-ui-workspace-chart");
var chartOffset = chart.offset();
var chartSVG = $("#red-ui-workspace-chart>svg").get(0);
var activeSpliceLink;
var mouseX;
@@ -264,11 +296,12 @@ RED.palette = (function() {
},
stop: function() { d3.select('.red-ui-flow-link-splice').classed('red-ui-flow-link-splice',false); if (spliceTimer) { clearTimeout(spliceTimer); spliceTimer = null;}},
drag: function(e,ui) {
ui.originalPosition.left = $('#' + e.target.id).offset().left;
var paletteNode = getPaletteNode(nt);
ui.originalPosition.left = paletteNode.offset().left;
if (def.inputs > 0 && def.outputs > 0) {
mouseX = ui.position.left-paletteWidth+(ui.helper.width()/2) - chartOffset.left + chart.scrollLeft();
mouseY = ui.position.top-paletteTop+(ui.helper.height()/2) - chartOffset.top + chart.scrollTop();
mouseX = ui.position.left - paletteWidth + (ui.helper.width()/2) + chart.scrollLeft();
mouseY = ui.position.top - paletteTop + (ui.helper.height()/2) + chart.scrollTop();
if (!spliceTimer) {
spliceTimer = setTimeout(function() {
var nodes = [];
@@ -330,13 +363,13 @@ RED.palette = (function() {
var nodeInfo = null;
if (nt.indexOf("subflow:") === 0) {
$(d).on("dblclick", function(e) {
d.on("dblclick", function(e) {
RED.workspaces.show(nt.substring(8));
e.preventDefault();
});
nodeInfo = marked(def.info||"");
}
setLabel(nt,$(d),label,nodeInfo);
setLabel(nt,d,label,nodeInfo);
var categoryNode = $("#red-ui-palette-container-"+rootCategory);
if (categoryNode.find(".red-ui-palette-node").length === 1) {
@@ -347,8 +380,7 @@ RED.palette = (function() {
}
function removeNodeType(nt) {
var nodeTypeId = escapeNodeType(nt);
var paletteNode = $("#red-ui-palette-node_"+nodeTypeId);
var paletteNode = getPaletteNode(nt);
var categoryNode = paletteNode.closest(".red-ui-palette-category");
paletteNode.remove();
if (categoryNode.find(".red-ui-palette-node").length === 0) {
@@ -360,8 +392,7 @@ RED.palette = (function() {
}
function hideNodeType(nt) {
var nodeTypeId = escapeNodeType(nt);
var paletteNode = $("#red-ui-palette-node_"+nodeTypeId);
var paletteNode = getPaletteNode(nt);
paletteNode.hide();
var categoryNode = paletteNode.closest(".red-ui-palette-category");
var cl = categoryNode.find(".red-ui-palette-node");
@@ -373,8 +404,7 @@ RED.palette = (function() {
}
function showNodeType(nt) {
var nodeTypeId = escapeNodeType(nt);
var paletteNode = $("#red-ui-palette-node_"+nodeTypeId);
var paletteNode = getPaletteNode(nt);
var categoryNode = paletteNode.closest(".red-ui-palette-category");
categoryNode.show();
paletteNode.show();
@@ -382,20 +412,15 @@ RED.palette = (function() {
function refreshNodeTypes() {
RED.nodes.eachSubflow(function(sf) {
var paletteNode = $("#red-ui-palette-node_subflow_"+sf.id.replace(".","_"));
var paletteNode = getPaletteNode('subflow:'+sf.id);
var portInput = paletteNode.find(".red-ui-palette-port-input");
var portOutput = paletteNode.find(".red-ui-palette-port-output");
var paletteLabel = paletteNode.find(".red-ui-palette-label");
paletteLabel.attr("class","red-ui-palette-label"
+ (((!sf._def.align && sf.in.length !== 0 && sf.out.length === 0) || "right" === sf._def.align) ? " red-ui-palette-label-right" : "")
);
paletteLabel.attr("class","red-ui-palette-label" + (((!sf._def.align && sf.in.length !== 0 && sf.out.length === 0) || "right" === sf._def.align) ? " red-ui-palette-label-right" : ""));
var paletteIconContainer = paletteNode.find(".red-ui-palette-icon-container");
paletteIconContainer.attr("class","red-ui-palette-icon-container"
+ (((!sf._def.align && sf.in.length !== 0 && sf.out.length === 0) || "right" === sf._def.align) ? " red-ui-palette-icon-container-right" : "")
);
paletteIconContainer.attr("class","red-ui-palette-icon-container" + (((!sf._def.align && sf.in.length !== 0 && sf.out.length === 0) || "right" === sf._def.align) ? " red-ui-palette-icon-container-right" : ""));
if (portInput.length === 0 && sf.in.length > 0) {
var portIn = document.createElement("div");
@@ -418,11 +443,11 @@ RED.palette = (function() {
var currentCategory = paletteNode.data('category');
var newCategory = (sf.category||"subflows");
if (currentCategory !== newCategory) {
var category = newCategory.replace(/ /g,"_");
var category = escapeCategory(newCategory);
createCategory(newCategory,category,category,"node-red");
var currentCategoryNode = paletteNode.closest(".red-ui-palette-category");
var newCategoryNode = $("#palette-"+category);
var newCategoryNode = $("#red-ui-palette-"+category);
newCategoryNode.append(paletteNode);
if (newCategoryNode.find(".red-ui-palette-node").length === 1) {
categoryContainers[category].open();
@@ -435,10 +460,9 @@ RED.palette = (function() {
currentCategoryNode.find("i").toggleClass("expanded");
}
}
}
paletteNode.css("backgroundColor", sf.color);
});
}
@@ -446,7 +470,8 @@ RED.palette = (function() {
var re = new RegExp(val.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'),'i');
$("#red-ui-palette-container .red-ui-palette-node").each(function(i,el) {
var currentLabel = $(el).find(".red-ui-palette-label").text();
if (val === "" || re.test(el.id) || re.test(currentLabel)) {
var type = $(el).attr("data-palette-type");
if (val === "" || re.test(type) || re.test(currentLabel)) {
$(this).show();
} else {
$(this).hide();
@@ -459,8 +484,10 @@ RED.palette = (function() {
.find(".red-ui-palette-node")
.filter(function() { return $(this).css('display') !== 'none'}).length === 0) {
categoryContainers[category].close();
categoryContainers[category].container.slideUp();
} else {
categoryContainers[category].open();
categoryContainers[category].container.show();
}
}
}
@@ -538,23 +565,26 @@ RED.palette = (function() {
sidebarControls.stop(false,true);
sidebarControls.hide();
})
var categoryList = coreCategories;
var userCategories = [];
if (RED.settings.paletteCategories) {
categoryList = RED.settings.paletteCategories;
userCategories = RED.settings.paletteCategories;
} else if (RED.settings.theme('palette.categories')) {
categoryList = RED.settings.theme('palette.categories');
userCategories = RED.settings.theme('palette.categories');
}
if (!Array.isArray(categoryList)) {
categoryList = coreCategories
if (!Array.isArray(userCategories)) {
userCategories = [];
}
categoryList.forEach(function(category){
createCategoryContainer(category, category, "palette.label."+category);
});
var addedCategories = {};
userCategories.forEach(function(category){
addedCategories[category] = true;
createCategoryContainer(category, escapeCategory(category), "palette.label."+escapeCategory(category));
});
coreCategories.forEach(function(category){
if (!addedCategories[category]) {
createCategoryContainer(category, escapeCategory(category), "palette.label."+escapeCategory(category));
}
});
var paletteFooterButtons = $('<span class="button-group"></span>').appendTo("#red-ui-palette .red-ui-component-footer");
var paletteCollapseAll = $('<button type="button" class="red-ui-footer-button"><i class="fa fa-angle-double-up"></i></button>').appendTo(paletteFooterButtons);
@@ -599,7 +629,6 @@ RED.palette = (function() {
setTimeout(function() { $(window).trigger("resize"); } ,200);
}
function getCategories() {
var categories = [];
$("#red-ui-palette-container .red-ui-palette-category").each(function(i,d) {

View File

@@ -160,7 +160,7 @@ RED.projects.settings = (function() {
if (activeProject.description) {
desc = marked(activeProject.description);
} else {
desc = '<span class="red-ui-help-info-none">'+'No description available'+'</span>';
desc = '<span class="red-ui-help-info-none">' + RED._("sidebar.project.noDescriptionAvailable") + '</span>';
}
var description = addTargetToExternalLinks($('<span class="red-ui-text-bidi-aware" dir=\"'+RED.text.bidi.resolveBaseTextDir(desc)+'">'+desc+'</span>')).appendTo(container);
description.find(".red-ui-text-bidi-aware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "<span></span>" );
@@ -222,7 +222,7 @@ RED.projects.settings = (function() {
if (summary) {
container.text(summary).removeClass('node-info-node');
} else {
container.text(RED._("sidebar.project.projectSettings.noSummaryAvailable")).addClass('red-ui-help-info-none');
container.text(RED._("sidebar.project.noSummaryAvailable")).addClass('red-ui-help-info-none');
}
}

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