Compare commits

..

183 Commits

Author SHA1 Message Date
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
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
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
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
d06dbbb4bd changed to color change reflect immediately on OK 2019-07-11 08:22:31 +09: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
Hiroyasu Nishiyama
3ee8bcad8c add support for specifying subflow template color 2019-07-08 23:52:08 +09: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
Kunihiko Toumura
b1bff62bf7 Merge remote-tracking branch 'upstream/dev' into dev-redo 2019-06-23 16:19:15 +09:00
Kunihiko Toumura
7adf102d8d Initial implementation of redo (un-undo) 2019-06-22 16:05:50 +09:00
308 changed files with 5568 additions and 2044 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

@@ -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,143 @@
#### 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,6 +186,11 @@ 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
@@ -725,7 +870,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

@@ -276,7 +276,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: [
@@ -496,7 +496,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');
@@ -555,8 +557,8 @@ 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;
}
});
@@ -579,9 +581,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',

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.0",
"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",
@@ -41,7 +41,7 @@
"fs-extra": "8.1.0",
"fs.notify": "0.0.4",
"hash-sum": "2.0.0",
"https-proxy-agent": "2.2.1",
"https-proxy-agent": "2.2.2",
"i18next": "15.1.2",
"iconv-lite": "0.5.0",
"is-utf8": "0.2.1",
@@ -52,11 +52,11 @@
"memorystore": "1.6.1",
"mime": "2.4.4",
"mqtt": "2.18.8",
"multer": "1.4.1",
"mustache": "3.0.1",
"node-red-node-rbe": "^0.2.4",
"node-red-node-sentiment": "^0.1.3",
"node-red-node-tail": "^0.0.2",
"multer": "1.4.2",
"mustache": "3.0.2",
"node-red-node-rbe": "^0.2.5",
"node-red-node-sentiment": "^0.1.4",
"node-red-node-tail": "^0.0.3",
"nopt": "4.0.1",
"oauth2orize": "1.11.0",
"on-headers": "1.0.2",
@@ -65,7 +65,7 @@
"passport-oauth2-client-password": "0.1.2",
"raw-body": "2.4.1",
"request": "2.88.0",
"semver": "6.2.0",
"semver": "6.3.0",
"uglify-js": "3.6.0",
"when": "3.7.8",
"ws": "6.2.1",
@@ -79,16 +79,16 @@
"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",

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

@@ -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

@@ -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.0",
"license": "Apache-2.0",
"main": "./lib/index.js",
"repository": {
@@ -16,8 +16,8 @@
}
],
"dependencies": {
"@node-red/util": "1.0.0-beta.2",
"@node-red/editor-client": "1.0.0-beta.2",
"@node-red/util": "1.0.0",
"@node-red/editor-client": "1.0.0",
"bcryptjs": "2.4.3",
"body-parser": "1.19.0",
"clone": "2.1.2",
@@ -26,7 +26,7 @@
"express": "4.17.1",
"memorystore": "1.6.1",
"mime": "2.4.4",
"mustache": "3.0.1",
"mustache": "3.0.2",
"oauth2orize": "1.11.0",
"passport-http-bearer": "1.0.1",
"passport-oauth2-client-password": "0.1.2",

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"

View File

@@ -310,6 +310,7 @@
"addNewType": "Add new __type__...",
"nodeProperties": "node properties",
"label": "Label",
"color": "Color",
"portLabels": "Port labels",
"labelInputs": "Inputs",
"labelOutputs": "Outputs",
@@ -321,6 +322,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:"
@@ -379,9 +414,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",
@@ -532,7 +571,7 @@
"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"
},
@@ -549,6 +588,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": {
@@ -939,9 +979,11 @@
},
"editor-tab": {
"properties": "Properties",
"envProperties": "Environment Variables",
"description": "Description",
"appearance": "Appearance",
"env": "Environment Variables"
"preview": "UI Preview",
"defaultValue": "Default value"
},
"languages" : {
"de": "German",

View File

@@ -80,7 +80,7 @@
"projects-new": "新規",
"projects-open": "開く",
"projects-settings": "設定",
"showNodeLabelDefault": "追加したノードのラベルを表示する"
"showNodeLabelDefault": "追加したノードのラベルを表示"
}
},
"actions": {
@@ -310,6 +310,7 @@
"addNewType": "新規に __type__ を追加...",
"nodeProperties": "プロパティ",
"label": "ラベル",
"color": "色",
"portLabels": "ポートラベル",
"labelInputs": "入力",
"labelOutputs": "出力",
@@ -321,6 +322,40 @@
"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": "スコープの変更は、他のフローで使われているノードを無効にします",
"invalidProperties": "プロパティが不正です:"
@@ -351,7 +386,8 @@
"pasteNode": "ノードを貼り付け",
"undoChange": "変更操作を戻す",
"searchBox": "ノードを検索",
"managePalette": "パレットの管理"
"managePalette": "パレットの管理",
"actionList": "動作一覧"
},
"library": {
"library": "ライブラリ",
@@ -378,9 +414,13 @@
"addCategory": "新規追加...",
"label": {
"subflows": "サブフロー",
"network": "ネットワーク",
"common": "共通",
"input": "入力",
"output": "出力",
"function": "機能",
"sequence": "シーケンス",
"parser": "パーサ",
"social": "ソーシャル",
"storage": "ストレージ",
"analysis": "分析",
@@ -527,11 +567,13 @@
"none": "選択されていません",
"refresh": "読み込みのため更新してください",
"empty": "データが存在しません",
"node": "Node",
"flow": "Flow",
"global": "Global",
"node": "ノード",
"flow": "フロー",
"global": "グローバル",
"deleteConfirm": "データを削除しても良いですか?",
"autoRefresh": "自動更新"
"autoRefresh": "選択対象が変化した場合更新",
"refrsh": "更新",
"delete": "削除"
},
"palette": {
"name": "パレットの管理",
@@ -543,9 +585,10 @@
"description": "詳細",
"dependencies": "依存関係",
"settings": "設定",
"noSummaryAvailable": "サマリが存在しません",
"noSummaryAvailable": "要約が存在しません",
"editDescription": "プロジェクトの詳細を編集",
"editDependencies": "プロジェクトの依存関係を編集",
"noDescriptionAvailable": "詳細が存在しません",
"editReadme": "README.mdを編集",
"showProjectSettings": "プロジェクト設定を表示",
"projectSettings": {
@@ -736,7 +779,16 @@
},
"jsonEditor": {
"title": "JSONエディタ",
"format": "JSONフォーマット"
"format": "JSONフォーマット",
"rawMode": "JSONを編集",
"uiMode": "ビジュアルエディタ",
"insertAbove": "上に挿入",
"insertBelow": "下に挿入",
"addItem": "要素を追加",
"copyPath": "要素のパスをコピー",
"expandItems": "要素を展開",
"collapseItems": "要素を折り畳む",
"duplicate": "複製"
},
"markdownEditor": {
"title": "マークダウンエディタ",
@@ -926,11 +978,13 @@
},
"editor-tab": {
"properties": "プロパティ",
"envProperties": "環境変数",
"description": "説明",
"appearance": "外観",
"env": "環境変数"
"preview": "UIプレビュー",
"defaultValue": "デフォルト値"
},
"languages" : {
"languages": {
"de": "ドイツ語",
"en-US": "英語",
"ja": "日本語",

View File

@@ -273,7 +273,6 @@
"deleteSubflow": "서브 플로우 삭제",
"info": "상세내역",
"category": "카테고리",
"format": "Markdown 형식",
"errors": {
"noNodesSelected": "<strong>서브 플로우를 생성할 수 없습니다</strong> : 노드가 선택되지 않았습니다",
"multipleInputsToSelection": "<strong>서브 플로우를 생성할 수 없습니다</strong> : 복수의 입력이 선택되었습니다"

View File

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

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]);
@@ -219,22 +288,29 @@ RED.history = (function() {
$("#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;
@@ -258,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;
}
}
}
@@ -268,41 +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);
}
@@ -322,6 +466,8 @@ RED.history = (function() {
RED.workspaces.refresh();
RED.sidebar.config.refresh();
RED.subflow.refresh();
return inverseEv;
}
}
@@ -329,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,6 +50,19 @@ 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(localStorage.getItem("editor-language")||i18n.detectLanguage());
var toLoad = languageList.length;

View File

@@ -30,7 +30,8 @@
"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",
@@ -40,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

@@ -311,7 +311,7 @@ RED.nodes = (function() {
nodeTabMap[z][node.id] = node;
node.z = z;
}
function removeLink(l) {
var index = links.indexOf(l);
if (index != -1) {
@@ -392,21 +392,21 @@ RED.nodes = (function() {
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"
@@ -578,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:[]};
@@ -1193,6 +1194,7 @@ RED.nodes = (function() {
var nodeTypeArrayReferences = {
"catch":"scope",
"status":"scope",
"complete": "scope",
"link in":"links",
"link out":"links"
}
@@ -1294,8 +1296,13 @@ RED.nodes = (function() {
function filterNodes(filter) {
var result = [];
var searchSet = nodes;
if (filter.hasOwnProperty("z") && Object.hasOwnProperty("values") && nodeTabMap.hasOwnProperty(filter.z) ) {
searchSet = Object.values(nodeTabMap[filter.z]);
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<searchSet.length;n++) {
@@ -1303,6 +1310,9 @@ RED.nodes = (function() {
if (filter.hasOwnProperty("type") && node.type !== filter.type) {
continue;
}
if (doZFilter && node.z !== filter.z) {
continue;
}
result.push(node);
}
return result;
@@ -1478,7 +1488,7 @@ RED.nodes = (function() {
clear: clear,
moveNodeToTab: moveNodeToTab,
addLink: addLink,
removeLink: removeLink,

View File

@@ -455,8 +455,12 @@ var RED = (function() {
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);
@@ -479,7 +483,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")

View File

@@ -34,6 +34,8 @@
* - addItem(itemData)
* - insertItemAt : function(data,index) - add an item at the specified index
* - removeItem(itemData)
* - getItemAt(index)
* - indexOf(itemData)
* - width(width)
* - height(height)
* - items()
@@ -186,7 +188,11 @@
}
},
_destroy: function() {
this.topContainer.remove();
if (this.topContainer) {
var tc = this.topContainer;
delete this.topContainer;
tc.remove();
}
},
_refreshFilter: function() {
var that = this;
@@ -232,6 +238,23 @@
this.uiHeight = desiredHeight;
this._resize();
},
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 || {};

View File

@@ -224,9 +224,9 @@ RED.menu = (function() {
if (!alreadySet && opt.onselect) {
triggerAction(opt.id,state);
}
}
if (!alreadySet) {
RED.settings.set(opt.setting||("menu-"+opt.id), state);
if (!opt.local && !alreadySet) {
RED.settings.set(opt.setting||("menu-"+opt.id), state);
}
}
}

View File

@@ -131,6 +131,11 @@ RED.popover = (function() {
existingPopover.close(true);
}
target.data("red-ui-popover",res)
if (options.tooltip) {
div.on("mousedown", function(evt) {
closePopup(true);
});
}
if (instant) {
div.show();
} else {
@@ -253,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

@@ -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,7 +204,16 @@ 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;
@@ -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,8 +39,8 @@
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.css("display","none");
this.element.on("focus", function() {

View File

@@ -81,7 +81,7 @@
}
},
re: {value:"re",label:"regular expression",icon:"red/images/typedInput/re.svg"},
date: {value:"date",label:"timestamp",hasValue:false},
date: {value:"date",label:"timestamp",icon:"fa fa-clock-o",hasValue:false},
jsonata: {
value: "jsonata",
label: "expression",
@@ -298,7 +298,8 @@
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);
@@ -336,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")){
@@ -344,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};
}
@@ -369,12 +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();
event.stopPropagation();
callback(opt.value);
that._hideMenu(menu);
if (!opts.multiple) {
callback(opt.value);
that._hideMenu(menu);
} else {
cb.prop("checked",!cb.prop("checked"));
}
});
});
menu.css({
@@ -398,9 +420,6 @@
}
evt.stopPropagation();
})
return menu;
},
@@ -409,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;
}
@@ -423,7 +453,7 @@
}
menu.css({
top: top+"px",
left: (2+pos.left)+"px",
left: (pos.left)+"px",
});
menu.slideDown(100);
this._delay(function() {
@@ -471,7 +501,7 @@
this._getLabelWidth(this.selectTrigger, function(labelWidth) {
that.elementDiv.css('left',labelWidth+"px");
that.valueLabelContainer.css('left',labelWidth+"px");
if (that.optionExpandButton.is(":visible")) {
if (that.optionExpandButton.shown) {
that.elementDiv.css('right',"22px");
that.valueLabelContainer.css('right',"22px");
} else {
@@ -496,7 +526,7 @@
} else {
that.optionSelectLabel.css({'left':'0'})
that.optionSelectTrigger.css({'width':'calc( 100% - '+labelWidth+'px )'});
if (!that.optionExpandButton.is(":visible")) {
if (!that.optionExpandButton.shown) {
that.elementDiv.css({'right':0});
that.input.css({
'border-top-right-radius': '4px',
@@ -511,25 +541,35 @@
_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:mapDeprecatedIcon(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() {
@@ -558,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 {
@@ -572,38 +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) {
selectedOption.push(that.activeOptions[op]);
break;
}
} else if (op.value === value) {
selectedOption.push(op);
break;
}
} else if (op.value === value) {
selectedOption = op;
break;
}
}
if (!selectedOption) {
selectedOption = {value:""}
}
})
this.input.val(value);
this._updateOptionSelectLabel(selectedOption)
if (!opt.multiple) {
if (!selectedOption.length === 0) {
selectedOption = [{value:""}];
}
this._updateOptionSelectLabel(selectedOption[0])
} else {
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);
}
@@ -621,7 +674,7 @@
}
this.selectLabel.empty();
var image;
if (opt.icon) {
if (opt.icon && opt.showLabel !== false) {
if (opt.icon.indexOf("<") === 0) {
$(opt.icon).prependTo(this.selectLabel);
}
@@ -636,7 +689,8 @@
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) {
@@ -646,6 +700,7 @@
if (opt.options) {
if (this.optionExpandButton) {
this.optionExpandButton.hide();
this.optionExpandButton.shown = false;
}
if (this.optionSelectTrigger) {
this.optionSelectTrigger.show();
@@ -668,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 {
@@ -733,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) {
@@ -758,17 +841,44 @@
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) {

View File

@@ -401,7 +401,7 @@ RED.diff = (function() {
defaults:{},
icon:"subflow.svg",
category: "subflows",
color: "#da9"
color: "#DDAA99"
},
tab:currentConfig.subflows[subflowId]
}
@@ -424,7 +424,7 @@ RED.diff = (function() {
defaults:{},
icon:"subflow.svg",
category: "subflows",
color: "#da9"
color: "#DDAA99"
},
tab:newConfig.subflows[subflowId],
newTab:newConfig.subflows[subflowId]
@@ -445,7 +445,7 @@ RED.diff = (function() {
defaults:{},
icon:"subflow.svg",
category: "subflows",
color: "#da9"
color: "#DDAA99"
},
tab:remoteDiff.newConfig.subflows[subflowId],
remoteTab: remoteDiff.newConfig.subflows[subflowId]
@@ -551,7 +551,7 @@ RED.diff = (function() {
def = {
icon:"subflow.svg",
category: "subflows",
color: "#da9",
color: "#DDAA99",
defaults:{name:{value:""}}
}
} else {

View File

@@ -19,7 +19,6 @@
*/
RED.editor = (function() {
var editStack = [];
var editing_node = null;
var editing_config_node = null;
@@ -231,8 +230,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 +529,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,148 +549,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")
}).attr("autocomplete","disable").appendTo(row).val(opt.name);
}
var valueField = $('<input/>',{
class: "node-input-env-value",
type: "text",
style: "margin-left: 5px; width: calc(60% - 8px)"
}).attr("autocomplete","disable").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()).trim();
if (name !== "") {
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));
}
@@ -713,8 +575,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
@@ -736,10 +598,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();
@@ -857,30 +727,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,
@@ -908,46 +756,160 @@ 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);
@@ -1026,13 +988,24 @@ RED.editor = (function() {
}
$("#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);
@@ -1043,21 +1016,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()||"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;
@@ -1093,6 +1075,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");
@@ -1380,7 +1363,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;
@@ -1483,13 +1466,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;
@@ -1607,6 +1590,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",
@@ -1768,7 +1764,8 @@ RED.editor = (function() {
RED.tray.resize();
}
},
collapsible: true
collapsible: true,
menu: false
});
var nodePropertiesTab = {
@@ -1875,7 +1872,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) {
@@ -2212,7 +2208,7 @@ RED.editor = (function() {
if (updateLabels(editing_node, changes, null)) {
changed = true;
}
var icon = $("#red-ui-editor-node-icon").text()||"";
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;
@@ -2234,6 +2230,23 @@ RED.editor = (function() {
editing_node.category = newCategory;
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();
}
var old_env = editing_node.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) {
@@ -2247,6 +2260,7 @@ RED.editor = (function() {
id:n.id,
changed:n.changed
})
n._def.color = editing_node.color;
n.changed = true;
n.dirty = true;
updateNodeProperties(n);
@@ -2274,15 +2288,18 @@ 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-60);
},
open: function(tray) {
var trayFooter = tray.find(".red-ui-tray-footer");
@@ -2324,7 +2341,8 @@ RED.editor = (function() {
RED.tray.resize();
}
},
collapsible: true
collapsible: true,
menu: false
});
var nodePropertiesTab = {
@@ -2486,6 +2504,7 @@ RED.editor = (function() {
content: RED._("markdownEditor.format"),
autoClose: 50
});
session.setUseWrapMode(true);
}
return editor;
}
@@ -2518,6 +2537,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

View File

@@ -38,7 +38,7 @@
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

@@ -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);
@@ -152,20 +184,25 @@ RED.palette = (function() {
function getPaletteNode(type) {
return $(".red-ui-palette-node[data-palette-type='"+type+"']");
}
function escapeCategory(category) {
return category.replace(/[ /.]/g,"_");
}
function addNodeType(nt,def) {
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 = $('<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)||"";
@@ -203,7 +240,7 @@ RED.palette = (function() {
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);
@@ -241,7 +278,6 @@ RED.palette = (function() {
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;
@@ -262,11 +298,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 = [];
@@ -412,11 +449,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();
@@ -429,10 +466,9 @@ RED.palette = (function() {
currentCategoryNode.find("i").toggleClass("expanded");
}
}
}
paletteNode.css("backgroundColor", sf.color);
});
}
@@ -535,20 +571,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);
@@ -593,7 +635,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');
}
}

View File

@@ -125,6 +125,14 @@ RED.search = (function() {
for (i=0;i<Math.min(results.length,25);i++) {
searchResults.editableList('addItem',results[i])
}
if (results.length > 25) {
searchResults.editableList('addItem', {
more: {
results: results,
start: 25
}
})
}
} else {
searchResults.editableList('addItem',{});
}
@@ -186,8 +194,27 @@ RED.search = (function() {
evt.preventDefault();
} else if (evt.keyCode === 13) {
// Enter
if (results.length > 0) {
reveal(results[Math.max(0,selected)].node);
children = searchResults.children();
if ($(children[selected]).hasClass("red-ui-search-more")) {
var object = $(children[selected]).find(".red-ui-editableList-item-content").data('data');
if (object) {
searchResults.editableList('removeItem',object);
for (i=object.more.start;i<Math.min(results.length,object.more.start+25);i++) {
searchResults.editableList('addItem',results[i])
}
if (results.length > object.more.start+25) {
searchResults.editableList('addItem', {
more: {
results: results,
start: object.more.start+25
}
})
}
}
} else {
if (results.length > 0) {
reveal(results[Math.max(0,selected)].node);
}
}
}
}
@@ -199,12 +226,32 @@ RED.search = (function() {
addButton: false,
addItem: function(container,i,object) {
var node = object.node;
if (node === undefined) {
$('<div>',{class:"red-ui-search-empty"}).text(RED._('search.empty')).appendTo(container);
var div;
if (object.more) {
container.parent().addClass("red-ui-search-more")
div = $('<a>',{href:'#',class:"red-ui-search-result red-ui-search-empty"}).appendTo(container);
div.text(RED._("palette.editor.more",{count:object.more.results.length-object.more.start}));
div.on("click", function(evt) {
evt.preventDefault();
searchResults.editableList('removeItem',object);
for (i=object.more.start;i<Math.min(results.length,object.more.start+25);i++) {
searchResults.editableList('addItem',results[i])
}
if (results.length > object.more.start+25) {
searchResults.editableList('addItem', {
more: {
results: results,
start: object.more.start+25
}
})
}
});
} else if (node === undefined) {
$('<div>',{class:"red-ui-search-empty"}).text(RED._('search.empty')).appendTo(container);
} else {
var def = node._def;
var div = $('<a>',{href:'#',class:"red-ui-search-result"}).appendTo(container);
div = $('<a>',{href:'#',class:"red-ui-search-result"}).appendTo(container);
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(div);
var colour = RED.utils.getNodeColor(node.type,def);

File diff suppressed because it is too large Load Diff

View File

@@ -21,6 +21,7 @@ RED.sidebar.context = (function() {
var localCache = {};
var flowAutoRefresh;
var nodeAutoRefresh;
var nodeSection;
// var subflowSection;
var flowSection;
@@ -34,18 +35,6 @@ RED.sidebar.context = (function() {
content = $("<div>").css({"position":"relative","height":"100%"});
content.className = "red-ui-sidebar-context"
var header = $('<div class="red-ui-sidebar-header"></div>').appendTo(content);
var autoUpdate = RED.settings.get("editor.context.refresh",false);
flowAutoRefresh = $('<input type="checkbox">').prop("checked",autoUpdate).appendTo(header).toggleButton({
baseClass: "red-ui-sidebar-header-button",
enabledLabel: RED._("sidebar.context.autoRefresh"),
disabledLabel: RED._("sidebar.context.autoRefresh")
}).on("change", function() {
var value = $(this).prop("checked");
RED.settings.set("editor.context.refresh",value);
});
var footerToolbar = $('<div></div>');
var stackContainer = $("<div>",{class:"red-ui-sidebar-context-stack"}).appendTo(content);
@@ -55,10 +44,7 @@ RED.sidebar.context = (function() {
nodeSection = sections.add({
title: RED._("sidebar.context.node"),
collapsible: true,
// onexpand: function() {
// updateNode(currentNode,true);
// }
collapsible: true
});
nodeSection.expand();
nodeSection.content.css({height:"100%"});
@@ -66,30 +52,27 @@ RED.sidebar.context = (function() {
var table = $('<table class="red-ui-info-table"></table>').appendTo(nodeSection.content);
nodeSection.table = $('<tbody>').appendTo(table);
var bg = $('<div style="float: right"></div>').appendTo(nodeSection.header);
$('<button class="red-ui-button red-ui-button-small"><i class="fa fa-refresh"></i></button>')
var nodeAutoRefreshSetting = RED.settings.get("editor.context.nodeRefresh",false);
nodeAutoRefresh = $('<input type="checkbox">').prop("checked",nodeAutoRefreshSetting).appendTo(bg).toggleButton({
baseClass: "red-ui-sidebar-header-button red-ui-button-small",
enabledLabel: "",
disabledLabel: ""
}).on("change", function() {
var value = $(this).prop("checked");
RED.settings.set("editor.context.flowRefresh",value);
});
RED.popover.tooltip(nodeAutoRefresh.next(),RED._("sidebar.context.autoRefresh"));
var manualRefreshNode = $('<button class="red-ui-button red-ui-button-small" style="margin-left: 5px"><i class="fa fa-refresh"></i></button>')
.appendTo(bg)
.on("click", function(evt) {
evt.stopPropagation();
evt.preventDefault();
updateNode(currentNode, true);
})
RED.popover.tooltip(bg,RED._("sidebar.context.refrsh"));
// subflowSection = sections.add({
// title: "Subflow",
// collapsible: true
// });
// subflowSection.expand();
// subflowSection.content.css({height:"100%"});
// bg = $('<div style="float: right"></div>').appendTo(subflowSection.header);
// $('<button class="red-ui-button red-ui-button-small"><i class="fa fa-refresh"></i></button>')
// .appendTo(bg)
// .on("click", function(evt) {
// evt.stopPropagation();
// evt.preventDefault();
// })
// RED.popover.tooltip(bg,RED._("sidebar.context.refrsh"));
// subflowSection.container.hide();
RED.popover.tooltip(manualRefreshNode,RED._("sidebar.context.refrsh"));
flowSection = sections.add({
title: RED._("sidebar.context.flow"),
@@ -101,14 +84,26 @@ RED.sidebar.context = (function() {
var table = $('<table class="red-ui-info-table"></table>').appendTo(flowSection.content);
flowSection.table = $('<tbody>').appendTo(table);
bg = $('<div style="float: right"></div>').appendTo(flowSection.header);
$('<button class="red-ui-button red-ui-button-small"><i class="fa fa-refresh"></i></button>')
var flowAutoRefreshSetting = RED.settings.get("editor.context.flowRefresh",false);
flowAutoRefresh = $('<input type="checkbox">').prop("checked",flowAutoRefreshSetting).appendTo(bg).toggleButton({
baseClass: "red-ui-sidebar-header-button red-ui-button-small",
enabledLabel: "",
disabledLabel: ""
}).on("change", function() {
var value = $(this).prop("checked");
RED.settings.set("editor.context.flowRefresh",value);
});
RED.popover.tooltip(flowAutoRefresh.next(),RED._("sidebar.context.autoRefresh"));
var manualRefreshFlow = $('<button class="red-ui-button red-ui-button-small" style="margin-left: 5px"><i class="fa fa-refresh"></i></button>')
.appendTo(bg)
.on("click", function(evt) {
evt.stopPropagation();
evt.preventDefault();
updateFlow(currentFlow, true);
})
RED.popover.tooltip(bg,RED._("sidebar.context.refrsh"));
RED.popover.tooltip(manualRefreshFlow,RED._("sidebar.context.refrsh"));
globalSection = sections.add({
title: RED._("sidebar.context.global"),
@@ -144,28 +139,6 @@ RED.sidebar.context = (function() {
action: "core:show-context-tab"
});
// var toggleLiveButton = $("#sidebar-context-toggle-live");
// toggleLiveButton.on("click", function(evt) {
// evt.preventDefault();
// if ($(this).hasClass("selected")) {
// $(this).removeClass("selected");
// $(this).find("i").removeClass("fa-pause");
// $(this).find("i").addClass("fa-play");
// } else {
// $(this).addClass("selected");
// $(this).find("i").removeClass("fa-play");
// $(this).find("i").addClass("fa-pause");
// }
// });
// RED.popover.tooltip(toggleLiveButton, function() {
// if (toggleLiveButton.hasClass("selected")) {
// return "Pause live updates"
// } else {
// return "Start live updates"
// }
// });
RED.events.on("view:selection-changed", function(event) {
var selectedNode = event.nodes && event.nodes.length === 1 && event.nodes[0];
updateNode(selectedNode);
@@ -174,29 +147,18 @@ RED.sidebar.context = (function() {
RED.events.on("workspace:change", function(event) {
updateFlow(RED.nodes.workspace(event.workspace));
})
if (autoUpdate) {
updateEntry(globalSection,"context/global","global");
} else {
$(globalSection.table).empty();
$('<tr class="red-ui-help-info-row red-ui-search-empty blank" colspan="2"><td data-i18n="sidebar.context.refresh"></td></tr>').appendTo(globalSection.table).i18n();
globalSection.timestamp.html("&nbsp;");
}
$(globalSection.table).empty();
$('<tr class="red-ui-help-info-row red-ui-search-empty blank" colspan="2"><td data-i18n="sidebar.context.refresh"></td></tr>').appendTo(globalSection.table).i18n();
globalSection.timestamp.html("&nbsp;");
}
function updateNode(node,force) {
currentNode = node;
if (force) {
if (force || nodeAutoRefresh.prop("checked")) {
if (node) {
updateEntry(nodeSection,"context/node/"+node.id,node.id);
// if (/^subflow:/.test(node.type)) {
// subflowSection.container.show();
// updateEntry(subflowSection,"context/flow/"+node.id,node.id);
// } else {
// subflowSection.container.hide();
// }
} else {
// subflowSection.container.hide();
updateEntry(nodeSection)
}
} else {

View File

@@ -140,7 +140,7 @@ RED.sidebar.info = (function() {
var activeProject = RED.projects.getActiveProject();
if (activeProject) {
propRow = $('<tr class="red-ui-help-info-row"><td>Project</td><td></td></tr>').appendTo(tableBody);
propRow = $('<tr class="red-ui-help-info-row"><td>'+ RED._("sidebar.project.name") + '</td><td></td></tr>').appendTo(tableBody);
$(propRow.children()[1]).text(activeProject.name||"");
$('<tr class="red-ui-help-property-expand blank"><td colspan="2"></td></tr>').appendTo(tableBody);
var editProjectButton = $('<button class="red-ui-button red-ui-button-small" style="position:absolute;right:2px;"><i class="fa fa-ellipsis-h"></i></button>')

View File

@@ -27,15 +27,7 @@ RED.touch.radialMenu = (function() {
function createRadial(obj,pos,options) {
isActive = true;
try {
touchMenu = d3.select("body").append("div")
.style({
position:"absolute",
top: 0,
left:0,
bottom:0,
right:0,
"z-index": 1000
})
touchMenu = d3.select("body").append("div").classed("red-ui-editor-radial-menu",true)
.on('touchstart',function() {
hide();
d3.event.preventDefault();
@@ -43,43 +35,27 @@ RED.touch.radialMenu = (function() {
var menu = touchMenu.append("div")
.style({
position: "absolute",
top: (pos[1]-80)+"px",
left:(pos[0]-80)+"px",
"border-radius": "80px",
width: "160px",
height: "160px",
background: "rgba(255,255,255,0.6)",
border: "1px solid #666"
top: (pos[1]-80)+"px",
left:(pos[0]-80)+"px",
});
var menuOpts = [];
var createMenuOpt = function(x,y,opt) {
opt.el = menu.append("div")
opt.el = menu.append("div").classed("red-ui-editor-radial-menu-opt",true)
.style({
position: "absolute",
top: (y+80-25)+"px",
left:(x+80-25)+"px",
"border-radius": "20px",
width: "50px",
height: "50px",
background: "#fff",
border: "2px solid #666",
"text-align": "center",
"line-height":"50px"
});
left:(x+80-25)+"px"
})
.classed("red-ui-editor-radial-menu-opt-disabled",!!opt.disabled)
opt.el.html(opt.name);
if (opt.disabled) {
opt.el.style({"border-color":"#ccc",color:"#ccc"});
}
opt.x = x;
opt.y = y;
menuOpts.push(opt);
opt.el.on('touchstart',function() {
opt.el.style("background","#999");
opt.el.classed("red-ui-editor-radial-menu-opt-active",true)
d3.event.preventDefault();
d3.event.stopPropagation();
});

View File

@@ -912,6 +912,10 @@ RED.utils = (function() {
}
var nodeColorCache = {};
function clearNodeColorCache() {
nodeColorCache = {};
}
function getNodeColor(type, def) {
var result = def.color;
var paletteTheme = RED.settings.theme('palette.theme') || [];
@@ -1044,6 +1048,7 @@ RED.utils = (function() {
getNodeIcon: getNodeIcon,
getNodeLabel: getNodeLabel,
getNodeColor: getNodeColor,
clearNodeColorCache: clearNodeColorCache,
addSpinnerOverlay: addSpinnerOverlay,
decodeObject: decodeObject,
parseContextKey: parseContextKey,

View File

@@ -291,6 +291,7 @@ RED.view = (function() {
}
RED.nodes.eachNode(function(n) {
n.dirty = true;
n.dirtyStatus = true;
});
updateSelection();
updateActiveNodes();
@@ -358,7 +359,7 @@ RED.view = (function() {
var spliceLink = $(ui.helper).data("splice");
if (spliceLink) {
// TODO: DRY - droppable/nodeMouseDown/canvasMouseUp
// TODO: DRY - droppable/nodeMouseDown/canvasMouseUp/showQuickAddDialog
RED.nodes.removeLink(spliceLink);
var link1 = {
source:spliceLink.source,
@@ -406,6 +407,7 @@ RED.view = (function() {
RED.actions.add("core:delete-selection",deleteSelection);
RED.actions.add("core:edit-selected-node",editSelection);
RED.actions.add("core:undo",RED.history.pop);
RED.actions.add("core:redo",RED.history.redo);
RED.actions.add("core:select-all-nodes",selectAll);
RED.actions.add("core:zoom-in",zoomIn);
RED.actions.add("core:zoom-out",zoomOut);
@@ -694,280 +696,8 @@ RED.view = (function() {
}
if (mouse_mode === 0 || mouse_mode === RED.state.QUICK_JOINING) {
if (d3.event.metaKey || d3.event.ctrlKey) {
point = d3.mouse(this);
var ox = point[0];
var oy = point[1];
if (RED.settings.get("editor").view['view-snap-grid']) {
// eventLayer.append("circle").attr("cx",point[0]).attr("cy",point[1]).attr("r","2").attr('fill','red')
point[0] = Math.round(point[0] / gridSize) * gridSize;
point[1] = Math.round(point[1] / gridSize) * gridSize;
// eventLayer.append("circle").attr("cx",point[0]).attr("cy",point[1]).attr("r","2").attr('fill','blue')
}
d3.event.stopPropagation();
var mainPos = $("#red-ui-main-container").position();
if (mouse_mode !== RED.state.QUICK_JOINING) {
mouse_mode = RED.state.QUICK_JOINING;
$(window).on('keyup',disableQuickJoinEventHandler);
}
quickAddActive = true;
if (ghostNode) {
ghostNode.remove();
}
ghostNode = eventLayer.append("g").attr('transform','translate('+(point[0] - node_width/2)+','+(point[1] - node_height/2)+')');
ghostNode.append("rect")
.attr("class","red-ui-flow-node-placeholder")
.attr("rx", 5)
.attr("ry", 5)
.attr("width",node_width)
.attr("height",node_height)
.attr("fill","none")
// var ghostLink = ghostNode.append("svg:path")
// .attr("class","red-ui-flow-link-link")
// .attr("d","M 0 "+(node_height/2)+" H "+(gridSize * -2))
// .attr("opacity",0);
var filter = undefined;
if (drag_lines.length > 0) {
if (drag_lines[0].virtualLink) {
filter = {type:drag_lines[0].node.type === 'link in'?'link out':'link in'}
} else if (drag_lines[0].portType === PORT_TYPE_OUTPUT) {
filter = {input:true}
} else {
filter = {output:true}
}
quickAddLink = {
node: drag_lines[0].node,
port: drag_lines[0].port,
portType: drag_lines[0].portType,
}
if (drag_lines[0].virtualLink) {
quickAddLink.virtualLink = true;
}
hideDragLines();
}
var rebuildQuickAddLink = function() {
if (!quickAddLink) {
return;
}
if (!quickAddLink.el) {
quickAddLink.el = dragGroupLayer.append("svg:path").attr("class", "red-ui-flow-drag-line");
}
var numOutputs = (quickAddLink.portType === PORT_TYPE_OUTPUT)?(quickAddLink.node.outputs || 1):1;
var sourcePort = quickAddLink.port;
var portY = -((numOutputs-1)/2)*13 +13*sourcePort;
var sc = (quickAddLink.portType === PORT_TYPE_OUTPUT)?1:-1;
quickAddLink.el.attr("d",generateLinkPath(quickAddLink.node.x+sc*quickAddLink.node.w/2,quickAddLink.node.y+portY,point[0]-sc*node_width/2,point[1],sc));
}
if (quickAddLink) {
rebuildQuickAddLink();
}
var lastAddedX;
var lastAddedWidth;
RED.typeSearch.show({
x:d3.event.clientX-mainPos.left-node_width/2 - (ox-point[0]),
y:d3.event.clientY-mainPos.top+ node_height/2 + 5 - (oy-point[1]),
filter: filter,
move: function(dx,dy) {
if (ghostNode) {
var pos = d3.transform(ghostNode.attr("transform")).translate;
ghostNode.attr("transform","translate("+(pos[0]+dx)+","+(pos[1]+dy)+")")
point[0] += dx;
point[1] += dy;
rebuildQuickAddLink();
}
},
cancel: function() {
if (quickAddLink) {
if (quickAddLink.el) {
quickAddLink.el.remove();
}
quickAddLink = null;
}
quickAddActive = false;
if (ghostNode) {
ghostNode.remove();
}
resetMouseVars();
updateSelection();
hideDragLines();
redraw();
},
add: function(type,keepAdding) {
var result = addNode(type);
if (!result) {
return;
}
if (keepAdding) {
mouse_mode = RED.state.QUICK_JOINING;
}
var nn = result.node;
var historyEvent = result.historyEvent;
nn.x = point[0];
nn.y = point[1];
var showLabel = RED.utils.getMessageProperty(RED.settings.get('editor'),"view.view-node-show-label");
if (showLabel !== undefined && !/^link (in|out)$/.test(nn._def.type) && !nn._def.defaults.hasOwnProperty("l")) {
nn.l = showLabel;
}
if (quickAddLink) {
var drag_line = quickAddLink;
var src = null,dst,src_port;
if (drag_line.portType === PORT_TYPE_OUTPUT && (nn.inputs > 0 || drag_line.virtualLink) ) {
src = drag_line.node;
src_port = drag_line.port;
dst = nn;
} else if (drag_line.portType === PORT_TYPE_INPUT && (nn.outputs > 0 || drag_line.virtualLink)) {
src = nn;
dst = drag_line.node;
src_port = 0;
}
if (src !== null) {
// Joining link nodes via virual wires. Need to update
// the src and dst links property
if (drag_line.virtualLink) {
historyEvent = {
t:'multi',
events: [historyEvent]
}
var oldSrcLinks = $.extend(true,{},{v:src.links}).v
var oldDstLinks = $.extend(true,{},{v:dst.links}).v
src.links.push(dst.id);
dst.links.push(src.id);
src.dirty = true;
dst.dirty = true;
historyEvent.events.push({
t:'edit',
node: src,
dirty: RED.nodes.dirty(),
changed: src.changed,
changes: {
links:oldSrcLinks
}
});
historyEvent.events.push({
t:'edit',
node: dst,
dirty: RED.nodes.dirty(),
changed: dst.changed,
changes: {
links:oldDstLinks
}
});
src.changed = true;
dst.changed = true;
} else {
var link = {source: src, sourcePort:src_port, target: dst};
RED.nodes.addLink(link);
historyEvent.links = [link];
}
if (!keepAdding) {
quickAddLink.el.remove();
quickAddLink = null;
if (mouse_mode === RED.state.QUICK_JOINING) {
if (drag_line.portType === PORT_TYPE_OUTPUT && nn.outputs > 0) {
showDragLines([{node:nn,port:0,portType:PORT_TYPE_OUTPUT}]);
} else if (!quickAddLink && drag_line.portType === PORT_TYPE_INPUT && nn.inputs > 0) {
showDragLines([{node:nn,port:0,portType:PORT_TYPE_INPUT}]);
} else {
resetMouseVars();
}
}
} else {
quickAddLink.node = nn;
quickAddLink.port = 0;
}
} else {
hideDragLines();
resetMouseVars();
}
} else {
if (!keepAdding) {
if (mouse_mode === RED.state.QUICK_JOINING) {
if (nn.outputs > 0) {
showDragLines([{node:nn,port:0,portType:PORT_TYPE_OUTPUT}]);
} else if (nn.inputs > 0) {
showDragLines([{node:nn,port:0,portType:PORT_TYPE_INPUT}]);
} else {
resetMouseVars();
}
}
} else {
if (nn.outputs > 0) {
quickAddLink = {
node: nn,
port: 0,
portType: PORT_TYPE_OUTPUT
}
} else if (nn.inputs > 0) {
quickAddLink = {
node: nn,
port: 0,
portType: PORT_TYPE_INPUT
}
} else {
resetMouseVars();
}
}
}
RED.history.push(historyEvent);
RED.nodes.add(nn);
RED.editor.validateNode(nn);
RED.nodes.dirty(true);
// auto select dropped node - so info shows (if visible)
clearSelection();
nn.selected = true;
moving_set.push({n:nn});
updateActiveNodes();
updateSelection();
redraw();
// At this point the newly added node will have a real width,
// so check if the position needs nudging
if (lastAddedX !== undefined) {
var lastNodeRHEdge = lastAddedX + lastAddedWidth/2;
var thisNodeLHEdge = nn.x - nn.w/2;
var gap = thisNodeLHEdge - lastNodeRHEdge;
if (gap != gridSize *2) {
nn.x = nn.x + gridSize * 2 - gap;
nn.dirty = true;
nn.x = Math.ceil(nn.x / gridSize) * gridSize;
redraw();
}
}
if (keepAdding) {
if (lastAddedX === undefined) {
// ghostLink.attr("opacity",1);
setTimeout(function() {
RED.typeSearch.refresh({filter:{input:true}});
},100);
}
lastAddedX = nn.x;
lastAddedWidth = nn.w;
point[0] = nn.x + nn.w/2 + node_width/2 + gridSize * 2;
ghostNode.attr('transform','translate('+(point[0] - node_width/2)+','+(point[1] - node_height/2)+')');
rebuildQuickAddLink();
} else {
quickAddActive = false;
ghostNode.remove();
}
}
});
updateActiveNodes();
updateSelection();
redraw();
showQuickAddDialog(d3.mouse(this));
}
}
if (mouse_mode === 0 && !(d3.event.metaKey || d3.event.ctrlKey)) {
@@ -988,6 +718,303 @@ RED.view = (function() {
}
}
function showQuickAddDialog(point,spliceLink) {
var ox = point[0];
var oy = point[1];
if (RED.settings.get("editor").view['view-snap-grid']) {
// eventLayer.append("circle").attr("cx",point[0]).attr("cy",point[1]).attr("r","2").attr('fill','red')
point[0] = Math.round(point[0] / gridSize) * gridSize;
point[1] = Math.round(point[1] / gridSize) * gridSize;
// eventLayer.append("circle").attr("cx",point[0]).attr("cy",point[1]).attr("r","2").attr('fill','blue')
}
var mainPos = $("#red-ui-main-container").position();
if (mouse_mode !== RED.state.QUICK_JOINING) {
mouse_mode = RED.state.QUICK_JOINING;
$(window).on('keyup',disableQuickJoinEventHandler);
}
quickAddActive = true;
if (ghostNode) {
ghostNode.remove();
}
ghostNode = eventLayer.append("g").attr('transform','translate('+(point[0] - node_width/2)+','+(point[1] - node_height/2)+')');
ghostNode.append("rect")
.attr("class","red-ui-flow-node-placeholder")
.attr("rx", 5)
.attr("ry", 5)
.attr("width",node_width)
.attr("height",node_height)
.attr("fill","none")
// var ghostLink = ghostNode.append("svg:path")
// .attr("class","red-ui-flow-link-link")
// .attr("d","M 0 "+(node_height/2)+" H "+(gridSize * -2))
// .attr("opacity",0);
var filter = undefined;
if (drag_lines.length > 0) {
if (drag_lines[0].virtualLink) {
filter = {type:drag_lines[0].node.type === 'link in'?'link out':'link in'}
} else if (drag_lines[0].portType === PORT_TYPE_OUTPUT) {
filter = {input:true}
} else {
filter = {output:true}
}
quickAddLink = {
node: drag_lines[0].node,
port: drag_lines[0].port,
portType: drag_lines[0].portType,
}
if (drag_lines[0].virtualLink) {
quickAddLink.virtualLink = true;
}
hideDragLines();
}
if (spliceLink) {
filter = {input:true, output:true}
}
var rebuildQuickAddLink = function() {
if (!quickAddLink) {
return;
}
if (!quickAddLink.el) {
quickAddLink.el = dragGroupLayer.append("svg:path").attr("class", "red-ui-flow-drag-line");
}
var numOutputs = (quickAddLink.portType === PORT_TYPE_OUTPUT)?(quickAddLink.node.outputs || 1):1;
var sourcePort = quickAddLink.port;
var portY = -((numOutputs-1)/2)*13 +13*sourcePort;
var sc = (quickAddLink.portType === PORT_TYPE_OUTPUT)?1:-1;
quickAddLink.el.attr("d",generateLinkPath(quickAddLink.node.x+sc*quickAddLink.node.w/2,quickAddLink.node.y+portY,point[0]-sc*node_width/2,point[1],sc));
}
if (quickAddLink) {
rebuildQuickAddLink();
}
var lastAddedX;
var lastAddedWidth;
RED.typeSearch.show({
x:d3.event.clientX-mainPos.left-node_width/2 - (ox-point[0]),
y:d3.event.clientY-mainPos.top+ node_height/2 + 5 - (oy-point[1]),
filter: filter,
move: function(dx,dy) {
if (ghostNode) {
var pos = d3.transform(ghostNode.attr("transform")).translate;
ghostNode.attr("transform","translate("+(pos[0]+dx)+","+(pos[1]+dy)+")")
point[0] += dx;
point[1] += dy;
rebuildQuickAddLink();
}
},
cancel: function() {
if (quickAddLink) {
if (quickAddLink.el) {
quickAddLink.el.remove();
}
quickAddLink = null;
}
quickAddActive = false;
if (ghostNode) {
ghostNode.remove();
}
resetMouseVars();
updateSelection();
hideDragLines();
redraw();
},
add: function(type,keepAdding) {
var result = addNode(type);
if (!result) {
return;
}
if (keepAdding) {
mouse_mode = RED.state.QUICK_JOINING;
}
var nn = result.node;
var historyEvent = result.historyEvent;
nn.x = point[0];
nn.y = point[1];
var showLabel = RED.utils.getMessageProperty(RED.settings.get('editor'),"view.view-node-show-label");
if (showLabel !== undefined && !/^link (in|out)$/.test(nn._def.type) && !nn._def.defaults.hasOwnProperty("l")) {
nn.l = showLabel;
}
if (quickAddLink) {
var drag_line = quickAddLink;
var src = null,dst,src_port;
if (drag_line.portType === PORT_TYPE_OUTPUT && (nn.inputs > 0 || drag_line.virtualLink) ) {
src = drag_line.node;
src_port = drag_line.port;
dst = nn;
} else if (drag_line.portType === PORT_TYPE_INPUT && (nn.outputs > 0 || drag_line.virtualLink)) {
src = nn;
dst = drag_line.node;
src_port = 0;
}
if (src !== null) {
// Joining link nodes via virual wires. Need to update
// the src and dst links property
if (drag_line.virtualLink) {
historyEvent = {
t:'multi',
events: [historyEvent]
}
var oldSrcLinks = $.extend(true,{},{v:src.links}).v
var oldDstLinks = $.extend(true,{},{v:dst.links}).v
src.links.push(dst.id);
dst.links.push(src.id);
src.dirty = true;
dst.dirty = true;
historyEvent.events.push({
t:'edit',
node: src,
dirty: RED.nodes.dirty(),
changed: src.changed,
changes: {
links:oldSrcLinks
}
});
historyEvent.events.push({
t:'edit',
node: dst,
dirty: RED.nodes.dirty(),
changed: dst.changed,
changes: {
links:oldDstLinks
}
});
src.changed = true;
dst.changed = true;
} else {
var link = {source: src, sourcePort:src_port, target: dst};
RED.nodes.addLink(link);
historyEvent.links = [link];
}
if (!keepAdding) {
quickAddLink.el.remove();
quickAddLink = null;
if (mouse_mode === RED.state.QUICK_JOINING) {
if (drag_line.portType === PORT_TYPE_OUTPUT && nn.outputs > 0) {
showDragLines([{node:nn,port:0,portType:PORT_TYPE_OUTPUT}]);
} else if (!quickAddLink && drag_line.portType === PORT_TYPE_INPUT && nn.inputs > 0) {
showDragLines([{node:nn,port:0,portType:PORT_TYPE_INPUT}]);
} else {
resetMouseVars();
}
}
} else {
quickAddLink.node = nn;
quickAddLink.port = 0;
}
} else {
hideDragLines();
resetMouseVars();
}
} else {
if (!keepAdding) {
if (mouse_mode === RED.state.QUICK_JOINING) {
if (nn.outputs > 0) {
showDragLines([{node:nn,port:0,portType:PORT_TYPE_OUTPUT}]);
} else if (nn.inputs > 0) {
showDragLines([{node:nn,port:0,portType:PORT_TYPE_INPUT}]);
} else {
resetMouseVars();
}
}
} else {
if (nn.outputs > 0) {
quickAddLink = {
node: nn,
port: 0,
portType: PORT_TYPE_OUTPUT
}
} else if (nn.inputs > 0) {
quickAddLink = {
node: nn,
port: 0,
portType: PORT_TYPE_INPUT
}
} else {
resetMouseVars();
}
}
}
if (spliceLink) {
resetMouseVars();
// TODO: DRY - droppable/nodeMouseDown/canvasMouseUp/showQuickAddDialog
RED.nodes.removeLink(spliceLink);
var link1 = {
source:spliceLink.source,
sourcePort:spliceLink.sourcePort,
target: nn
};
var link2 = {
source:nn,
sourcePort:0,
target: spliceLink.target
};
RED.nodes.addLink(link1);
RED.nodes.addLink(link2);
historyEvent.links = (historyEvent.links || []).concat([link1,link2]);
historyEvent.removedLinks = [spliceLink];
}
RED.history.push(historyEvent);
RED.nodes.add(nn);
RED.editor.validateNode(nn);
RED.nodes.dirty(true);
// auto select dropped node - so info shows (if visible)
clearSelection();
nn.selected = true;
moving_set.push({n:nn});
updateActiveNodes();
updateSelection();
redraw();
// At this point the newly added node will have a real width,
// so check if the position needs nudging
if (lastAddedX !== undefined) {
var lastNodeRHEdge = lastAddedX + lastAddedWidth/2;
var thisNodeLHEdge = nn.x - nn.w/2;
var gap = thisNodeLHEdge - lastNodeRHEdge;
if (gap != gridSize *2) {
nn.x = nn.x + gridSize * 2 - gap;
nn.dirty = true;
nn.x = Math.ceil(nn.x / gridSize) * gridSize;
redraw();
}
}
if (keepAdding) {
if (lastAddedX === undefined) {
// ghostLink.attr("opacity",1);
setTimeout(function() {
RED.typeSearch.refresh({filter:{input:true}});
},100);
}
lastAddedX = nn.x;
lastAddedWidth = nn.w;
point[0] = nn.x + nn.w/2 + node_width/2 + gridSize * 2;
ghostNode.attr('transform','translate('+(point[0] - node_width/2)+','+(point[1] - node_height/2)+')');
rebuildQuickAddLink();
} else {
quickAddActive = false;
ghostNode.remove();
}
}
});
updateActiveNodes();
updateSelection();
redraw();
}
function canvasMouseMove() {
var i;
var node;
@@ -1134,8 +1161,8 @@ RED.view = (function() {
if (moving_set.length === 1) {
node = moving_set[0];
spliceActive = node.n.hasOwnProperty("_def") &&
node.n._def.inputs > 0 &&
node.n._def.outputs > 0 &&
((node.n.hasOwnProperty("inputs") && node.n.inputs > 0) || (!node.n.hasOwnProperty("inputs") && node.n._def.inputs > 0)) &&
((node.n.hasOwnProperty("outputs") && node.n.outputs > 0) || (!node.n.hasOwnProperty("outputs") && node.n._def.outputs > 0)) &&
RED.nodes.filterLinks({ source: node.n }).length === 0 &&
RED.nodes.filterLinks({ target: node.n }).length === 0;
}
@@ -1268,12 +1295,15 @@ RED.view = (function() {
removedLinks.push(drag_lines[i].link)
}
}
historyEvent = {
t:"delete",
links: removedLinks,
dirty:RED.nodes.dirty()
};
RED.history.push(historyEvent);
if (removedLinks.length > 0) {
historyEvent = {
t:"delete",
links: removedLinks,
dirty:RED.nodes.dirty()
};
RED.history.push(historyEvent);
RED.nodes.dirty(true);
}
hideDragLines();
}
if (lasso) {
@@ -1721,7 +1751,7 @@ RED.view = (function() {
],
dirty:RED.nodes.dirty()
}
RED.nodes.dirty(true);
selected_link.source.changed = true;
selected_link.target.changed = true;
selected_link.target.links.splice(sourceIdIndex,1);
@@ -2540,8 +2570,8 @@ RED.view = (function() {
.on("mouseover",function(d){portMouseOver(d3.select(this),d,PORT_TYPE_INPUT,0);})
.on("mouseout",function(d){portMouseOut(d3.select(this),d,PORT_TYPE_INPUT,0);});
outGroup.append("svg:text").attr("class","red-ui-flow-port-label").attr("x",20).attr("y",8).style("font-size","10px").text("output");
outGroup.append("svg:text").attr("class","red-ui-flow-port-label red-ui-flow-port-index").attr("x",20).attr("y",24).text(function(d,i){ return i+1});
outGroup.append("svg:text").attr("class","red-ui-flow-port-label").attr("x",20).attr("y",12).style("font-size","10px").text("output");
outGroup.append("svg:text").attr("class","red-ui-flow-port-label red-ui-flow-port-index").attr("x",20).attr("y",28).text(function(d,i){ return i+1});
var subflowInputs = nodeLayer.selectAll(".red-ui-flow-subflow-port-input").data(activeSubflow.in,function(d,i){ return d.id;});
subflowInputs.exit().remove();
@@ -2967,7 +2997,7 @@ RED.view = (function() {
//thisNode.selectAll(".red-ui-flow-node-icon-shade-border-right").attr("d",function(d){return "M "+(d.w-30)+" 1 l 0 "+(d.h-2)});
var inputPorts = thisNode.selectAll(".red-ui-flow-port-input");
if (isLink && showAllLinkPorts === -1 && !activeLinkNodes[d.id] && d.inputs === 0 && !inputPorts.empty()) {
if ((!isLink || (showAllLinkPorts === -1 && !activeLinkNodes[d.id])) && d.inputs === 0 && !inputPorts.empty()) {
inputPorts.remove();
} else if (((isLink && (showAllLinkPorts===PORT_TYPE_INPUT||activeLinkNodes[d.id]))|| d.inputs === 1) && inputPorts.empty()) {
var inputGroup = thisNode.append("g").attr("class","red-ui-flow-port-input");
@@ -3166,7 +3196,7 @@ RED.view = (function() {
var statusClass = "red-ui-flow-node-status-"+(d.status.shape||"dot")+"-"+d.status.fill;
thisNode.selectAll(".red-ui-flow-node-status").style("display","inline").attr("class","red-ui-flow-node-status "+statusClass);
}
if (d.status.text) {
if (d.status.hasOwnProperty('text')) {
thisNode.selectAll(".red-ui-flow-node-status-label").text(d.status.text);
} else {
thisNode.selectAll(".red-ui-flow-node-status-label").text("");
@@ -3204,6 +3234,10 @@ RED.view = (function() {
redraw();
focusView();
d3.event.stopPropagation();
if (d3.event.metaKey || d3.event.ctrlKey) {
l.classed("red-ui-flow-link-splice",true);
showQuickAddDialog(d3.mouse(this), selected_link);
}
})
.on("touchstart",function(d) {
if (mouse_mode === RED.state.SELECTING_NODE) {

View File

@@ -70,7 +70,7 @@ RED.workspaces = (function() {
RED.view.state(RED.state.EDITING);
var tabflowEditor;
var trayOptions = {
title: RED._("workspace.editFlow",{name:workspace.label}),
title: RED._("workspace.editFlow",{name:RED.utils.sanitize(workspace.label)}),
buttons: [
{
id: "node-dialog-delete",
@@ -157,17 +157,27 @@ RED.workspaces = (function() {
tabflowEditor.resize();
},
open: function(tray) {
var trayFooter = tray.find(".red-ui-tray-footer");
var trayBody = tray.find('.red-ui-tray-body');
var trayFooterLeft = $('<div class="red-ui-tray-footer-left"></div>').appendTo(trayFooter)
var dialogForm = $('<form id="dialog-form" class="form-horizontal"></form>').appendTo(trayBody);
$('<div class="form-row">'+
'<label for="node-input-name" data-i18n="[append]editor:common.label.name"><i class="fa fa-tag"></i> </label>'+
'<input type="text" id="node-input-name">'+
'</div>').appendTo(dialogForm);
$('<div class="form-row">'+
'<label for="node-input-disabled" data-i18n="editor:workspace.status"></label>'+
'<input type="checkbox" id="node-input-disabled"/>'+
'</div>').appendTo(dialogForm);
if (!workspace.hasOwnProperty("disabled")) {
workspace.disabled = false;
}
$('<input id="node-input-disabled" type="checkbox">').prop("checked",workspace.disabled).appendTo(trayFooterLeft).toggleButton({
enabledIcon: "fa-circle-thin",
disabledIcon: "fa-ban",
invertState: true
})
var row = $('<div class="form-row node-text-editor-row">'+
'<label for="node-input-info" data-i18n="editor:workspace.info" style="width:300px;"></label>'+
@@ -196,16 +206,7 @@ RED.workspaces = (function() {
})
});
if (workspace.hasOwnProperty("disabled")) {
$("#node-input-disabled").prop("checked",workspace.disabled);
} else {
workspace.disabled = false;
}
$("#node-input-disabled").toggleButton({
enabledIcon: "fa-circle-thin",
disabledIcon: "fa-ban",
invertState: true
})
$('<input type="text" style="display: none;" />').prependTo(dialogForm);
dialogForm.on("submit", function(e) { e.preventDefault();});

View File

@@ -73,8 +73,8 @@ RED.user = (function() {
row.appendTo("#node-dialog-login-fields");
}
$('<div class="form-row" style="text-align: right; margin-top: 10px;"><span id="node-dialog-login-failed" style="line-height: 2em;float:left;" class="hide">'+RED._("user.loginFailed")+'</span><img src="red/images/spin.svg" style="height: 30px; margin-right: 10px; " class="login-spinner hide"/>'+
(opts.cancelable?'<a href="#" id="node-dialog-login-cancel" style="margin-right: 20px;" tabIndex="'+(i+1)+'">'+RED._("common.label.cancel")+'</a>':'')+
'<input type="submit" id="node-dialog-login-submit" style="width: auto;" tabIndex="'+(i+2)+'" value="'+RED._("user.login")+'"></div>').appendTo("#node-dialog-login-fields");
(opts.cancelable?'<a href="#" id="node-dialog-login-cancel" class="red-ui-button" style="margin-right: 20px;" tabIndex="'+(i+1)+'">'+RED._("common.label.cancel")+'</a>':'')+
'<input type="submit" id="node-dialog-login-submit" class="red-ui-button" style="width: auto;" tabIndex="'+(i+2)+'" value="'+RED._("user.login")+'"></div>').appendTo("#node-dialog-login-fields");
$("#node-dialog-login-submit").button();
@@ -119,7 +119,7 @@ RED.user = (function() {
var field = data.prompts[i];
var row = $("<div/>",{class:"form-row",style:"text-align: center"}).appendTo("#node-dialog-login-fields");
var loginButton = $('<a href="#"></a>',{style: "padding: 10px"}).appendTo(row).on("click", function() {
var loginButton = $('<a href="#" class="red-ui-button"></a>',{style: "padding: 10px"}).appendTo(row).on("click", function() {
document.location = field.url;
});
if (field.image) {

View File

@@ -60,10 +60,12 @@
.red-ui-icon-picker {
a {
text-decoration: none;
color: $primary-text-color;
}
a:hover,
a:focus {
text-decoration: none;
color: $primary-text-color;
}
p {

View File

@@ -79,6 +79,9 @@
}
a {
img {
max-width: 14px;
}
.fa {
width: 20px;
margin-left: -25px;

View File

@@ -190,6 +190,10 @@ button.red-ui-tray-resize-button {
border-color: $form-input-border-error-color !important;
}
.input-updated {
border-color: $node-selected-color !important;
}
.form-row {
clear: both;
color: $form-text-color;
@@ -388,28 +392,26 @@ button.red-ui-button-small
}
}
#red-ui-editor-node-icon-button {
button.red-ui-button.red-ui-editor-node-appearance-button {
position: relative;
padding-left: 30px;
width: calc(100% - 150px);
height: 35px !important;
text-align: left;
padding: 0 6px 0 3px;
>i {
width: 15px;
vertical-align: middle;
padding-left: 2px;
}
.red-ui-search-result-node {
position: absolute;
top: 2px;
left: 2px;
vertical-align: middle;
float: none;
position: relative;
top: -1px;
}
}
#red-ui-editor-node-icon {
margin-left: 10px;
width: calc(100% - 163px);
}
.red-ui-icon-picker {
position: absolute;
border: 1px solid $primary-border-color;
box-shadow: 0 1px 6px -3px black;
background: $secondary-background;
z-Index: 21;
display: none;
select {
box-sizing: border-box;
margin: 3px;
@@ -421,6 +423,16 @@ button.red-ui-button-small
height: 200px;
overflow-y: scroll;
line-height: 0px;
position: relative;
&.red-ui-icon-list-dark {
.red-ui-palette-icon-fa {
color: $secondary-text-color;
}
.red-ui-palette-icon-container {
background: $secondary-background;
border-radius: 4px;
}
}
}
.red-ui-icon-list-icon {
display: inline-block;
@@ -428,6 +440,7 @@ button.red-ui-button-small
padding: 4px;
cursor: pointer;
border-radius: 4px;
&:hover {
background: $list-item-background-hover;
}
@@ -579,3 +592,407 @@ button.red-ui-button-small
button.red-ui-toggleButton.toggle {
text-align: left;
}
.red-ui-editor-subflow-env-ui-row {
margin-right: 3px;
>div {
display: grid;
grid-template-columns: 16px 40px 35% auto;
}
>div:first-child {
font-size: 0.9em;
color: $tertiary-text-color;
margin: 3px 0 -4px;
>div {
padding-left: 3px;
}
}
>div:last-child {
>div {
height: 40px;
line-height: 30px;
display: inline-block;
box-sizing: border-box;
// border-left: 2px dashed $secondary-border-color;
// border-bottom: 2px dashed $secondary-border-color;
// border: 1px dashed $secondary-border-color;
border-right: none;
&:not(:first-child) {
padding: 3px;
}
// &:last-child {
// border-right: 1px dashed $secondary-border-color;
// }
.placeholder-input {
position: relative;
padding: 0 3px;
line-height: 24px;
opacity: 0.8
}
.red-ui-typedInput-value-label,.red-ui-typedInput-option-label {
select,.placeholder-input {
margin: 3px;
height: 26px;
width: calc(100% - 10px);
padding-left: 3px;
}
.placeholder-input {
span:first-child {
display:inline-block;
height: 100%;
width: 20px;
text-align:center;
border-right: 1px solid $secondary-border-color;
background: $tertiary-background;
}
}
input[type="checkbox"] {
margin-left: 8px;
margin-top: 0;
height: 100%;
}
}
}
>div:nth-child(1) {
border: none;
padding: 2px;
.red-ui-editableList-item-handle {
position:relative;
top: 0px;
color: $tertiary-text-color;
}
}
>div:nth-child(2) {
margin: 4px;
height: 32px;
border: 1px dashed $secondary-border-color;
text-align: center;
a {
display: block;
width: 100%;
height: 100%;
line-height: 32px;
&:hover {
background: $secondary-background-hover;
}
i {
height: 100%;
vertical-align: middle;
}
}
}
>div:nth-child(3) {
position: relative;
input {
width: 100%;
}
}
}
}
span.red-ui-editor-subflow-env-lang-icon {
position: absolute;
display: inline-block;
background: $secondary-background;
opacity: 0.8;
width: 20px;
line-height: 32px;
height: 32px;
text-align: center;
top: 4px;
right: 4px;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
// .red-ui-editor-subflow-ui-grid {
// width: 100%;
// .red-ui-editableList-container {
// border: none;
// border-radius: 0;
// }
// .red-ui-editableList-container li {
// border: none;
// padding: 0;
// &:not(:first-child) .red-ui-editableList-item-content >div:first-child >div {
// border-top: none;
// }
// &.ui-sortable-helper {
// border: 2px dashed $secondary-border-color;
// .red-ui-editableList-item-content {
// >div {
// border: none;
// opacity: 0.7
// }
//
// }
// }
// }
//
// .red-ui-editableList-item-content {
// >div>div {
// display: inline-block;
// box-sizing: border-box;
// border-left: 1px dashed $secondary-border-color;
// border-bottom: 1px dashed $secondary-border-color;
// }
// >div:first-child {
// font-size: 0.9em;
// display: grid;
// grid-template-columns: 25px auto 20px;
// >div {
// border-top: 1px dashed $secondary-border-color;
// padding: 1px;
// }
// >div:nth-child(3) {
// border-top: none;
// border-bottom: none;
// // width: 20px;
// }
// }
// >div:last-child {
// display: grid;
// grid-template-columns: 25px 140px auto 20px;
// >div {
// height: 48px;
// line-height: 30px;
// // display: inline-block;
// // height: 48px;
// // line-height: 30px;
// // box-sizing: border-box;
// //
// // border-left: 2px dashed $secondary-border-color;
// border-top: none;
// // border-bottom: 2px dashed $secondary-border-color;
// &:not(:first-child) {
// padding: 6px 3px;
// }
// .placeholder-input {
// position: relative;
// padding: 0 3px;
// line-height: 24px;
// opacity: 0.8
// }
// .red-ui-typedInput-value-label,.red-ui-typedInput-option-label {
// select,.placeholder-input {
// margin: 3px;
// height: 26px;
// width: calc(100% - 10px);
// padding-left: 3px;
// }
// input[type="checkbox"] {
// margin-left: 8px;
// margin-top: 0;
// height: 100%;
// }
// }
// }
// >div:nth-child(1) {
// text-align: center;
// a {
// display: block;
// width: 100%;
// height: 100%;
// line-height: 45px;
// &:hover {
// background: $secondary-background-hover;
// }
// }
// }
// >div:nth-child(2) {
// input {
// width: 100%;
// }
// // width: 140px;
// }
// >div:nth-child(3) {
// position: relative;
// .options-button {
// position: absolute;
// top: calc(50% - 10px);
// margin-right: 2px;
// right: 2px;
// }
// }
// >div:nth-child(4) {
// border-top: none;
// border-bottom: none;
// // width: 20px;
// }
//
// }
// }
// }
.red-ui-editor-subflow-ui-edit-panel {
padding-bottom: 3px;
background: $primary-background;
.red-ui-editableList-border {
border: none;
border-radius: 0;
border-bottom: 1px solid $secondary-border-color;
}
.red-ui-editableList-container {
}
.red-ui-editableList-addButton {
margin-left: 2px;
}
.red-ui-editableList-header {
background: $primary-background;
display: grid;
grid-template-columns: 50% 50%;
color: $secondary-text-color;
div:first-child {
padding-left: 23px;
}
div:last-child {
padding-left: 3px;
}
}
.red-ui-editableList-container {
padding: 0 1px;
li {
background: $secondary-background;
// border-bottom: none;
padding: 0;
.red-ui-editableList-item-content {
display: grid;
grid-template-columns: 50% 50%;
>div {
position:relative;
}
}
input {
margin-bottom: 0;
border:none;
width: 100%;
border-right: 1px solid $secondary-border-color;
border-radius: 0;
&:focus {
box-shadow: 0 0 0 1px inset $form-input-focus-color;
}
&:first-child {
border-left: 1px solid $secondary-border-color;
}
}
button.red-ui-typedInput-type-select, button.red-ui-typedInput-option-expand, button.red-ui-typedInput-option-trigger {
border-radius: 0;
height: 34px;
}
.red-ui-typedInput-container {
border-radius: 0;
border: none;
input.red-ui-typedInput-input {
height: 34px;
border-right: none;
}
}
.red-ui-editor-subflow-env-lang-icon {
top: 1px;
right: 1px;
border-top-right-radius:0;
border-bottom-right-radius:0;
}
.red-ui-editableList-item-remove {
right: 3px;
}
}
}
}
.node-input-env-locales-row {
position: relative;
top: -20px;
float: right;
select {
padding: 2px;
width: 160px;
height: auto;
min-width: 20px;
line-height: 18px;
font-size: 10px;
}
}
.node-input-env-container-row {
min-width: 470px;
position: relative;
.red-ui-editableList-item-content {
label {
margin-bottom: 0;
line-height: 32px;
span {
display: inline-block;
width: 20px;
text-align: center;
}
}
>div:first-child {
display: grid;
padding-left: 5px;
grid-template-columns: 40% auto 37px;
> :first-child {
width: calc(100% - 5px);
}
input {
width: calc(100% - 5px);
}
}
&.red-ui-editor-subflow-env-editable {
>div:first-child {
padding-left: 0;
grid-template-columns: 24px 40% auto 37px;
> a:first-child {
text-align: center;
line-height: 32px;
i.fa-angle-right {
transition: all 0.2s linear;
}
&.expanded {
i.fa-angle-right {
transform: rotate(90deg);
}
}
}
}
}
}
.red-ui-editableList-border .red-ui-editableList-header {
border-top-left-radius: 4px;
border-top-right-radius: 4px;
background: $tertiary-background;
padding: 0;
>div {
display: grid;
grid-template-columns: 24px 40% auto 37px;
>div {
display: inline-block;
}
}
}
.red-ui-editableList-container {
padding: 0;
.red-ui-editableList-item-handle {
top: 25px;
}
.red-ui-editableList-item-remove {
top: 25px;
right: 5px;
}
}
}
#subflow-input-ui {
// .form-row {
// display: grid;
// grid-template-columns: 120px auto;
// label span {
// display: inline-block;
// width: 20px;
// text-align: center;
// }
// }
}

View File

@@ -150,7 +150,8 @@
input[type="tel"],
input[type="color"],
div[contenteditable="true"],
.uneditable-input {
.uneditable-input,
.placeholder-input {
box-sizing: border-box;
display: inline-block;
height: 34px;
@@ -190,7 +191,8 @@
input[type="tel"],
input[type="color"],
div[contenteditable="true"],
.uneditable-input {
.uneditable-input,
.placeholder-input {
background-color: $form-input-background;
border: 1px solid $form-input-border-color;
}

View File

@@ -36,6 +36,7 @@
font-size: 30px;
line-height: 30px;
text-decoration: none;
white-space: nowrap;
span {
vertical-align: middle;
@@ -192,6 +193,7 @@
color: $header-menu-color;
padding: 3px 40px;
img {
max-width: 100%;
margin-right: 10px;
padding: 4px;
border: 3px solid transparent;
@@ -271,3 +273,9 @@
vertical-align: middle;
}
}
@media only screen and (max-width: 450px) {
span.red-ui-header-logo > span {
display: none;
}
}

View File

@@ -119,10 +119,10 @@
}
.red-ui-palette-node {
display: inline-block;
// display: inline-block;
cursor: move;
background: $secondary-background;
margin: 5px auto;
margin: 10px auto;
height: 25px;
border-radius: 5px;
border: 1px solid $node-border;
@@ -131,23 +131,16 @@
width: 120px;
background-size: contain;
position: relative;
&:first-child {
margin-top: 10px;
&:not(.red-ui-palette-node-config):first-child {
margin-top: 15px;
}
&:last-child {
margin-bottom: 10px;
&:not(.red-ui-palette-node-config):last-child {
margin-bottom: 15px;
}
}
.red-ui-palette-node:hover {
margin: 4px auto;
border-color: $node-selected-color;
border-width: 2px;
&:first-child {
margin-top: 9px;
}
&:last-child {
margin-bottom: 9px;
}
border-color: transparent;
box-shadow: 0 0 0 2px $node-selected-color;
}
.red-ui-palette-port {
position: absolute;

View File

@@ -162,3 +162,15 @@
background: none;
color: $tertiary-text-color;
}
.red-ui-popover-panel {
@include component-shadow;
font-family: $primary-font;
font-size: $primary-font-size;
position: absolute;
box-sizing: border-box;
border: 1px solid $primary-border-color;
background: $secondary-background;
z-index: 2000;
}

View File

@@ -0,0 +1,54 @@
/**
* 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-ui-editor-radial-menu {
font-size: $primary-font-size;
font-family: $primary-font;
position: absolute;
top: 0;
left:0;
bottom:0;
right:0;
z-index: 1000;
& > div {
position: absolute;
border-radius: 80px;
width: 160px;
height: 160px;
background: $shadow;
border: 1px solid $primary-border-color;
}
}
.red-ui-editor-radial-menu-opt {
position: absolute;
border-radius: 20px;
width: 50px;
height: 50px;
background: $secondary-background;
border: 2px solid $primary-border-color;
text-align: center;
line-height:50px
}
.red-ui-editor-radial-menu-opt-disabled {
border-color: $tertiary-border-color;
color: $tertiary-border-color;
}
.red-ui-editor-radial-menu-opt-active {
background: $secondary-background-hover;
}

View File

@@ -65,3 +65,5 @@
@import "keyboard";
@import "debug";
@import "radialMenu";

View File

@@ -35,15 +35,8 @@ ul.red-ui-sidebar-node-config-list {
overflow: hidden;
&.selected {
margin: 4px auto;
border-color: $node-selected-color;
border-width: 2px;
&:first-child {
margin-top: 9px;
}
&:last-child {
margin-bottom: 9px;
}
border-color: transparent;
box-shadow: 0 0 0 2px $node-selected-color;
}
}
.red-ui-palette-label {

View File

@@ -16,7 +16,7 @@
.red-ui-sidebar-context-stack {
position: absolute;
top: 42px;
top: 0;
bottom: 0;
left: 0;
right: 0;

View File

@@ -58,118 +58,6 @@
text-overflow: ellipsis;
}
button.red-ui-typedInput-type-select,
button.red-ui-typedInput-option-expand,
button.red-ui-typedInput-option-trigger
{
text-align: left;
border: none;
position: absolute;
box-sizing: border-box;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
padding: 0 1px 0 5px;
display:inline-block;
background: $form-button-background;
height: 32px;
line-height: 32px;
vertical-align: middle;
color: $form-text-color;
i.red-ui-typedInput-icon {
margin-left: 1px;
margin-right: 2px;
vertical-align: middle;
}
&.disabled {
cursor: default;
i.red-ui-typedInput-icon {
color: $secondary-text-color-disabled;
}
}
.red-ui-typedInput-type-label,.red-ui-typedInput-option-label {
display: inline-block;
height: 100%;
padding: 0 1px 0 5px;
img {
max-width: none;
}
}
&:not(.disabled):hover {
text-decoration: none;
background: $workspace-button-background-hover;
}
&:focus {
text-decoration: none;
outline: none;
box-shadow: inset 0 0 0 1px $form-input-focus-color;
}
&:not(.disabled):active {
background: $workspace-button-background-active;
text-decoration: none;
}
&.red-ui-typedInput-full-width {
width: 100%;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
&:before {
content:'';
display: inline-block;
height: 100%;
vertical-align: middle;
}
}
button.red-ui-typedInput-option-expand {
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
right: 0;
}
button.red-ui-typedInput-option-trigger {
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
padding: 0 0 0 0;
position:absolute;
right: 0;
.red-ui-typedInput-option-label {
background:$form-button-background;
color: $form-text-color;
position:absolute;
left:0;
right:23px;
top: 0;
padding: 0 5px 0 8px;
i.red-ui-typedInput-icon {
margin-right: 4px;
}
}
.red-ui-typedInput-option-caret {
top: 0;
position: absolute;
right: 0;
bottom: 0;
width: 17px;
padding-left: 6px;
&:before {
content:'';
display: inline-block;
height: 100%;
vertical-align: middle;
}
}
&:focus {
box-shadow: none;
}
&:focus .red-ui-typedInput-option-caret {
box-shadow: inset 0 0 0 1px $form-input-focus-color;
}
}
}
.red-ui-typedInput-options {
@include component-shadow;
@@ -180,6 +68,7 @@
max-height: 350px;
overflow-y: auto;
border: 1px solid $primary-border-color;
box-sizing: border-box;
background: $secondary-background;
z-index: 2000;
a {
@@ -200,8 +89,124 @@
text-decoration: none;
background: $workspace-button-background-active;
}
input[type="checkbox"] {
margin-right: 6px;
}
}
.red-ui-typedInput-icon {
margin-right: 4px;
margin-right: 6px;
}
}
button.red-ui-typedInput-type-select,
button.red-ui-typedInput-option-expand,
button.red-ui-typedInput-option-trigger
{
text-align: left;
border: none;
position: absolute;
box-sizing: border-box;
border-top-left-radius: 4px;
border-bottom-left-radius: 4px;
padding: 0 1px 0 5px;
display:inline-block;
background: $form-button-background;
height: 32px;
line-height: 30px;
min-width: 23px;
vertical-align: middle;
color: $form-text-color;
i.red-ui-typedInput-icon {
margin-left: 1px;
margin-right: 2px;
vertical-align: middle;
}
&.disabled {
cursor: default;
i.red-ui-typedInput-icon {
color: $secondary-text-color-disabled;
}
}
.red-ui-typedInput-type-label,.red-ui-typedInput-option-label {
display: inline-block;
vertical-align: middle;
height: 100%;
padding: 0 1px 0 5px;
img {
max-width: none;
}
}
&:not(.disabled):hover {
text-decoration: none;
background: $workspace-button-background-hover;
}
&:focus {
text-decoration: none;
outline: none;
box-shadow: inset 0 0 0 1px $form-input-focus-color;
}
&:not(.disabled):active {
background: $workspace-button-background-active;
text-decoration: none;
}
&.red-ui-typedInput-full-width {
width: 100%;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
}
&:before {
content:'';
display: inline-block;
height: 100%;
vertical-align: middle;
}
}
button.red-ui-typedInput-option-expand {
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
border-top-left-radius: 0;
border-bottom-left-radius: 0;
right: 0;
}
button.red-ui-typedInput-option-trigger {
border-top-left-radius: 0px;
border-bottom-left-radius: 0px;
border-top-right-radius: 4px;
border-bottom-right-radius: 4px;
padding: 0 0 0 0;
position:absolute;
right: 0;
.red-ui-typedInput-option-label {
background:$form-button-background;
color: $form-text-color;
position:absolute;
left:0;
right:23px;
top: 0;
padding: 0 5px 0 8px;
i.red-ui-typedInput-icon {
margin-right: 4px;
}
}
.red-ui-typedInput-option-caret {
top: 0;
position: absolute;
right: 0;
bottom: 0;
width: 17px;
padding-left: 5px;
&:before {
content:'';
display: inline-block;
height: 100%;
vertical-align: middle;
}
}
&:focus {
box-shadow: none;
}
&:focus .red-ui-typedInput-option-caret {
box-shadow: inset 0 0 0 1px $form-input-focus-color;
}
}

View File

@@ -1,5 +1,6 @@
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
@@ -20,7 +21,6 @@
See the License for the specific language governing permissions and
limitations under the License.
-->
<head>
<title>{{ page.title }}</title>
<link rel="icon" type="image/png" href="{{ page.favicon }}">
<link rel="mask-icon" href="{{ page.tabicon }}" color="#8f0000">

View File

@@ -156,7 +156,7 @@
<script type="text/javascript">
RED.nodes.registerType('inject',{
category: 'input',
category: 'common',
color:"#a6bbcf",
defaults: {
name: {value:""},

View File

@@ -37,7 +37,7 @@
(function() {
var subWindow = null;
RED.nodes.registerType('debug',{
category: 'output',
category: 'common',
defaults: {
name: {value:""},
active: {value:true},

View File

@@ -81,7 +81,7 @@ module.exports = function(RED) {
}
}
this.on("input", function(msg) {
this.on("input", function(msg, send, done) {
if (this.complete === "true") {
// debug complete msg object
if (this.console === "true") {
@@ -90,13 +90,14 @@ module.exports = function(RED) {
if (this.active && this.tosidebar) {
sendDebug({id:node.id, name:node.name, topic:msg.topic, msg:msg, _path:msg._path});
}
done();
} else {
prepareValue(msg,function(err,msg) {
prepareValue(msg,function(err,debugMsg) {
if (err) {
node.error(err);
return;
}
var output = msg.msg;
var output = debugMsg.msg;
if (node.console === "true") {
if (typeof output === "string") {
node.log((output.indexOf("\n") !== -1 ? "\n" : "") + output);
@@ -114,9 +115,10 @@ module.exports = function(RED) {
}
if (node.active) {
if (node.tosidebar == true) {
sendDebug(msg);
sendDebug(debugMsg);
}
}
done();
});
}
})

View File

@@ -0,0 +1,136 @@
<script type="text/x-red" data-template-name="complete">
<div class="form-row node-input-target-row">
<button id="node-input-complete-target-select" class="red-ui-button" data-i18n="common.label.selectNodes"></button>
</div>
<div class="form-row node-input-target-row node-input-target-list-row" style="min-height: 100px">
<div id="node-input-complete-target-container-div"></div>
</div>
<div class="form-row">
<label for="node-input-name"><i class="fa fa-tag"></i> <span data-i18n="common.label.name"></span></label>
<input type="text" id="node-input-name" data-i18n="[placeholder]common.label.name">
</div>
</script>
<script type="text/javascript">
RED.nodes.registerType('complete',{
category: 'common',
color:"#c0edc0",
defaults: {
name: {value:""},
scope: {value:[]},
uncaught: {value:false}
},
inputs:0,
outputs:1,
icon: "alert.svg",
label: function() {
if (this.name) {
return this.name;
}
return this._("complete.completeNodes",{number:this.scope.length});
},
labelStyle: function() {
return this.name?"node_label_italic":"";
},
oneditprepare: function() {
var node = this;
var scope = node.scope || [];
this._resize = function() {
var rows = $("#dialog-form>div:not(.node-input-target-list-row)");
var height = $("#dialog-form").height();
for (var i=0;i<rows.length;i++) {
height -= $(rows[i]).outerHeight(true);
}
var editorRow = $("#dialog-form>div.node-input-target-list-row");
editorRow.css("height",height+"px");
};
var dirList = $("#node-input-complete-target-container-div").css({width: "100%", height: "100%"})
.treeList({multi:true}).on("treelistitemmouseover", function(e, item) {
item.node.highlighted = true;
item.node.dirty = true;
RED.view.redraw();
}).on("treelistitemmouseout", function(e, item) {
item.node.highlighted = false;
item.node.dirty = true;
RED.view.redraw();
})
var candidateNodes = RED.nodes.filterNodes({z:node.z});
var allChecked = true;
var items = [];
var nodeItemMap = {};
candidateNodes.forEach(function(n) {
if (n.id === node.id) {
return;
}
var isChecked = scope.indexOf(n.id) !== -1;
allChecked = allChecked && isChecked;
var nodeDef = RED.nodes.getType(n.type);
var label;
var sublabel;
if (nodeDef) {
var l = nodeDef.label;
label = (typeof l === "function" ? l.call(n) : l)||"";
sublabel = n.type;
if (sublabel.indexOf("subflow:") === 0) {
var subflowId = sublabel.substring(8);
var subflow = RED.nodes.subflow(subflowId);
sublabel = "subflow : "+subflow.name;
}
}
if (!nodeDef || !label) {
label = n.type;
}
nodeItemMap[n.id] = {
node: n,
label: label,
sublabel: sublabel,
selected: isChecked
};
items.push(nodeItemMap[n.id]);
});
dirList.treeList('data',items);
$("#node-input-complete-target-select").on("click", function(e) {
e.preventDefault();
var preselected = dirList.treeList('selected').map(function(n) {return n.node.id});
RED.tray.hide();
RED.view.selectNodes({
selected: preselected,
onselect: function(selection) {
RED.tray.show();
var newlySelected = {};
selection.forEach(function(n) {
newlySelected[n.id] = true;
if (nodeItemMap[n.id]) {
nodeItemMap[n.id].treeList.select(true);
}
})
preselected.forEach(function(id) {
if (!newlySelected[id]) {
nodeItemMap[id].treeList.select(false);
}
})
},
oncancel: function() {
RED.tray.show();
},
filter: function(n) {
return n.id !== node.id;
}
});
})
},
oneditsave: function() {
this.scope = $("#node-input-complete-target-container-div").treeList('selected').map(function(i) { return i.node.id})
},
oneditresize: function(size) {
this._resize();
}
});
</script>

View File

@@ -0,0 +1,30 @@
/**
* 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.
**/
module.exports = function(RED) {
"use strict";
function CompleteNode(n) {
RED.nodes.createNode(this,n);
var node = this;
this.scope = n.scope;
this.on("input",function(msg) {
this.send(msg);
});
}
RED.nodes.registerType("complete",CompleteNode);
}

View File

@@ -25,7 +25,7 @@
</script>
<script type="text/javascript">
RED.nodes.registerType('catch',{
category: 'input',
category: 'common',
color:"#e49191",
defaults: {
name: {value:""},

View File

@@ -21,15 +21,15 @@
<script type="text/javascript">
RED.nodes.registerType('status',{
category: 'input',
color:"#d9f4fd",
category: 'common',
color:"#94c1d0",
defaults: {
name: {value:""},
scope: {value:null}
},
inputs:0,
outputs:1,
icon: "alert.svg",
icon: "status.svg",
label: function() {
return this.name||(this.scope?this._("status.statusNodes",{number:this.scope.length}):this._("status.status"));
},

View File

@@ -162,7 +162,7 @@
}
RED.nodes.registerType('link in',{
category: 'input',
category: 'common',
color:"#ddd",//"#87D8CF",
defaults: {
name: {value:""},
@@ -191,7 +191,7 @@
});
RED.nodes.registerType('link out',{
category: 'output',
category: 'common',
color:"#ddd",//"#87D8CF",
defaults: {
name: {value:""},

View File

@@ -12,7 +12,7 @@
<script type="text/javascript">
RED.nodes.registerType('comment',{
category: 'function',
category: 'common',
color:"#ffffff",
defaults: {
name: {value:""},

View File

@@ -42,14 +42,14 @@ RED.debug = (function() {
var content = $("<div>").css({"position":"relative","height":"100%"});
var toolbar = $('<div class="red-ui-sidebar-header">'+
'<span class="button-group"><a id="red-ui-sidebar-debug-filter" class="red-ui-sidebar-header-button" href="#"><i class="fa fa-filter"></i> <span></span></a></span>'+
'<span class="button-group"><a id="red-ui-sidebar-debug-clear" class="red-ui-sidebar-header-button" href="#" data-i18n="[title]node-red:debug.sidebar.clearLog"><i class="fa fa-trash"></i></a></span></div>').appendTo(content);
'<span class="button-group"><a id="red-ui-sidebar-debug-clear" class="red-ui-sidebar-header-button" href="#"><i class="fa fa-trash"></i></a></span></div>').appendTo(content);
var footerToolbar = $('<div>'+
// '<span class="button-group">'+
// '<a class="red-ui-footer-button-toggle text-button selected" id="red-ui-sidebar-debug-view-list" href="#"><span data-i18n="">list</span></a>'+
// '<a class="red-ui-footer-button-toggle text-button" id="red-ui-sidebar-debug-view-table" href="#"><span data-i18n="">table</span></a> '+
// '</span>'+
'<span class="button-group"><a id="red-ui-sidebar-debug-open" class="red-ui-footer-button" href="#" data-i18n="[title]node-red:debug.sidebar.openWindow"><i class="fa fa-desktop"></i></a></span> ' +
'<span class="button-group"><a id="red-ui-sidebar-debug-open" class="red-ui-footer-button" href="#"><i class="fa fa-desktop"></i></a></span> ' +
'</div>');
messageList = $('<div class="red-ui-debug-content red-ui-debug-content-list"/>').appendTo(content);
@@ -222,7 +222,7 @@ RED.debug = (function() {
e.preventDefault();
clearMessageList(false);
});
RED.popover.tooltip(toolbar.find("#red-ui-sidebar-debug-clear"),RED._('node-red:debug.sidebar.clearLog'));
RED.popover.tooltip(toolbar.find("#red-ui-sidebar-debug-clear"),RED._('node-red:debug.sidebar.clearLog'),"core:clear-debug-messages");

View File

@@ -41,7 +41,7 @@
oneditprepare: function() {
var that = this;
$( "#node-input-outputs" ).spinner({
min:1,
min:0,
change: function(event, ui) {
var value = this.value;
if (!value.match(/^\d+$/)) { value = 1; }

View File

@@ -19,7 +19,7 @@ module.exports = function(RED) {
var util = require("util");
var vm = require("vm");
function sendResults(node,_msgid,msgs) {
function sendResults(node,send,_msgid,msgs,cloneFirstMessage) {
if (msgs == null) {
return;
} else if (!util.isArray(msgs)) {
@@ -35,6 +35,10 @@ module.exports = function(RED) {
var msg = msgs[m][n];
if (msg !== null && msg !== undefined) {
if (typeof msg === 'object' && !Buffer.isBuffer(msg) && !util.isArray(msg)) {
if (msgCount === 0 && cloneFirstMessage !== false) {
msgs[m][n] = RED.util.cloneMessage(msgs[m][n]);
msg = msgs[m][n];
}
msg._msgid = _msgid;
msgCount++;
} else {
@@ -49,7 +53,7 @@ module.exports = function(RED) {
}
}
if (msgCount>0) {
node.send(msgs);
send(msgs);
}
}
@@ -58,8 +62,17 @@ module.exports = function(RED) {
var node = this;
this.name = n.name;
this.func = n.func;
var handleNodeDoneCall = true;
// Check to see if the Function appears to call `node.done()`. If so,
// we will assume it is well written and does actually call node.done().
// Otherwise, we will call node.done() after the function returns regardless.
if (/node\.done\s*\(\s*\)/.test(this.func)) {
handleNodeDoneCall = false;
}
var functionText = "var results = null;"+
"results = (function(msg){ "+
"results = (function(msg,__send__,__done__){ "+
"var __msgid__ = msg._msgid;"+
"var node = {"+
"id:__node__.id,"+
@@ -71,10 +84,11 @@ module.exports = function(RED) {
"trace:__node__.trace,"+
"on:__node__.on,"+
"status:__node__.status,"+
"send:function(msgs){ __node__.send(__msgid__,msgs);}"+
"send:function(msgs,cloneMsg){ __node__.send(__send__,__msgid__,msgs,cloneMsg);},"+
"done:__done__"+
"};\n"+
this.func+"\n"+
"})(msg);";
"})(msg,send,done);";
this.topic = n.topic;
this.outstandingTimers = [];
this.outstandingIntervals = [];
@@ -104,8 +118,8 @@ module.exports = function(RED) {
trace: function() {
node.trace.apply(node, arguments);
},
send: function(id, msgs) {
sendResults(node, id, msgs);
send: function(send, id, msgs, cloneMsg) {
sendResults(node, send, id, msgs, cloneMsg);
},
on: function() {
if (arguments[0] === "input") {
@@ -223,12 +237,18 @@ module.exports = function(RED) {
// lineOffset: -11, // line number offset to be used for stack traces
// columnOffset: 0, // column number offset to be used for stack traces
});
this.on("input", function(msg) {
this.on("input", function(msg,send,done) {
try {
var start = process.hrtime();
context.msg = msg;
context.send = send;
context.done = done;
this.script.runInContext(context);
sendResults(this,msg._msgid,context.results);
sendResults(this,send,msg._msgid,context.results,false);
if (handleNodeDoneCall) {
done();
}
var duration = process.hrtime(start);
var converted = Math.floor((duration[0] * 1e9 + duration[1])/10000)/100;
@@ -237,35 +257,43 @@ module.exports = function(RED) {
this.status({fill:"yellow",shape:"dot",text:""+converted});
}
} catch(err) {
//remove unwanted part
var index = err.stack.search(/\n\s*at ContextifyScript.Script.runInContext/);
err.stack = err.stack.slice(0, index).split('\n').slice(0,-1).join('\n');
var stack = err.stack.split(/\r?\n/);
if ((typeof err === "object") && err.hasOwnProperty("stack")) {
//remove unwanted part
var index = err.stack.search(/\n\s*at ContextifyScript.Script.runInContext/);
err.stack = err.stack.slice(0, index).split('\n').slice(0,-1).join('\n');
var stack = err.stack.split(/\r?\n/);
//store the error in msg to be used in flows
msg.error = err;
//store the error in msg to be used in flows
msg.error = err;
var line = 0;
var errorMessage;
if (stack.length > 0) {
while (line < stack.length && stack[line].indexOf("ReferenceError") !== 0) {
line++;
}
var line = 0;
var errorMessage;
if (stack.length > 0) {
while (line < stack.length && stack[line].indexOf("ReferenceError") !== 0) {
line++;
}
if (line < stack.length) {
errorMessage = stack[line];
var m = /:(\d+):(\d+)$/.exec(stack[line+1]);
if (m) {
var lineno = Number(m[1])-1;
var cha = m[2];
errorMessage += " (line "+lineno+", col "+cha+")";
if (line < stack.length) {
errorMessage = stack[line];
var m = /:(\d+):(\d+)$/.exec(stack[line+1]);
if (m) {
var lineno = Number(m[1])-1;
var cha = m[2];
errorMessage += " (line "+lineno+", col "+cha+")";
}
}
}
if (!errorMessage) {
errorMessage = err.toString();
}
done(errorMessage);
}
if (!errorMessage) {
errorMessage = err.toString();
else if (typeof err === "string") {
done(err);
}
else {
done(JSON.stringify(err));
}
this.error(errorMessage, msg);
}
});
this.on("close", function() {

View File

@@ -162,8 +162,6 @@
numField.typedInput("width",(newWidth-selectWidth-70));
} else if (type === "jsonata_exp") {
expField.typedInput("width",(newWidth-selectWidth-70));
} else if (type === "hask") {
keyField.typedInput("width",(newWidth-selectWidth-70));
} else if (type === "istype") {
typeField.typedInput("width",(newWidth-selectWidth-70));
} else {
@@ -212,15 +210,33 @@
selectField.append($("<option></option>").val(operators[d].v).text(/^switch/.test(operators[d].t)?node._(operators[d].t):operators[d].t));
}
}
var valueField = $('<input/>',{class:"node-input-rule-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'str',types:['msg','flow','global','str','num','jsonata','env',previousValueType]});
var numValueField = $('<input/>',{class:"node-input-rule-num-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'num',types:['flow','global','num','jsonata','env']});
var expValueField = $('<input/>',{class:"node-input-rule-exp-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'jsonata',types:['jsonata']});
var btwnValueField = $('<input/>',{class:"node-input-rule-btwn-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'num',types:['msg','flow','global','str','num','jsonata','env',previousValueType]});
var btwnAndLabel = $('<span/>',{class:"node-input-rule-btwn-label"}).text(" "+andLabel+" ").appendTo(row3);
var btwnValue2Field = $('<input/>',{class:"node-input-rule-btwn-value2",type:"text",style:"margin-left:2px;"}).appendTo(row3).typedInput({default:'num',types:['msg','flow','global','str','num','jsonata','env',previousValueType]});
var keyValueField = $('<input/>',{class:"node-input-rule-key-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'str',types:['str','msg','flow','global','env']});
var typeValueField = $('<input/>',{class:"node-input-rule-type-value",type:"text",style:"margin-left: 5px;"}).appendTo(row)
.typedInput({default:'string',types:[
function createValueField(){
return $('<input/>',{class:"node-input-rule-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'str',types:['msg','flow','global','str','num','jsonata','env',previousValueType]});
}
function createNumValueField(){
return $('<input/>',{class:"node-input-rule-num-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'num',types:['flow','global','num','jsonata','env']});
}
function createExpValueField(){
return $('<input/>',{class:"node-input-rule-exp-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'jsonata',types:['jsonata']});
}
function createBtwnValueField(){
return $('<input/>',{class:"node-input-rule-btwn-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'num',types:['msg','flow','global','str','num','jsonata','env',previousValueType]});
}
function createBtwnAndLabel(){
return $('<span/>',{class:"node-input-rule-btwn-label"}).text(" "+andLabel+" ").appendTo(row3);
}
function createBtwnValue2Field(){
return $('<input/>',{class:"node-input-rule-btwn-value2",type:"text",style:"margin-left:2px;"}).appendTo(row3).typedInput({default:'num',types:['msg','flow','global','str','num','jsonata','env',previousValueType]});
}
function createTypeValueField(){
return $('<input/>',{class:"node-input-rule-type-value",type:"text",style:"margin-left: 5px;"}).appendTo(row).typedInput({default:'string',types:[
{value:"string",label:"string",hasValue:false},
{value:"number",label:"number",hasValue:false},
{value:"boolean",label:"boolean",hasValue:false},
@@ -231,64 +247,66 @@
{value:"undefined",label:"undefined",hasValue:false},
{value:"null",label:"null",hasValue:false}
]});
}
var valueField = null;
var numValueField = null;
var expValueField = null;
var btwnAndLabel = null;
var btwnValueField = null;
var btwnValue2Field = null;
var typeValueField = null;
var finalspan = $('<span/>',{style:"float: right;margin-top: 6px;"}).appendTo(row);
finalspan.append(' &#8594; <span class="node-input-rule-index">'+(i+1)+'</span> ');
var caseSensitive = $('<input/>',{id:"node-input-rule-case-"+i,class:"node-input-rule-case",type:"checkbox",style:"width:auto;vertical-align:top"}).appendTo(row2);
$('<label/>',{for:"node-input-rule-case-"+i,style:"margin-left: 3px;"}).text(caseLabel).appendTo(row2);
selectField.on("change", function() {
resizeRule(container);
var type = selectField.val();
if ((type === "btwn") || (type === "index")) {
if (valueField){
valueField.typedInput('hide');
}
if (expValueField){
expValueField.typedInput('hide');
keyValueField.typedInput('hide');
}
if (numValueField){
numValueField.typedInput('hide');
}
if (typeValueField){
typeValueField.typedInput('hide');
}
if (btwnValueField){
btwnValueField.typedInput('hide');
}
if (btwnValue2Field){
btwnValue2Field.typedInput('hide');
}
if ((type === "btwn") || (type === "index")) {
if (!btwnValueField){
btwnValueField = createBtwnValueField();
}
btwnValueField.typedInput('show');
} else if ((type === "head") || (type === "tail")) {
btwnValueField.typedInput('hide');
btwnValue2Field.typedInput('hide');
expValueField.typedInput('hide');
keyValueField.typedInput('hide');
if (!numValueField){
numValueField = createNumValueField();
}
numValueField.typedInput('show');
typeValueField.typedInput('hide');
valueField.typedInput('hide');
} else if (type === "hask") {
btwnValueField.typedInput('hide');
btwnValue2Field.typedInput('hide');
expValueField.typedInput('hide');
keyValueField.typedInput('show');
numValueField.typedInput('hide');
typeValueField.typedInput('hide');
valueField.typedInput('hide');
} else if (type === "jsonata_exp") {
btwnValueField.typedInput('hide');
btwnValue2Field.typedInput('hide');
if (!expValueField){
expValueField = createExpValueField();
}
expValueField.typedInput('show');
keyValueField.typedInput('hide');
numValueField.typedInput('hide');
typeValueField.typedInput('hide');
valueField.typedInput('hide');
} else {
btwnValueField.typedInput('hide');
expValueField.typedInput('hide');
keyValueField.typedInput('hide');
numValueField.typedInput('hide');
typeValueField.typedInput('hide');
valueField.typedInput('hide');
if (type === "true" || type === "false" || type === "null" || type === "nnull" || type === "empty" || type === "nempty" || type === "else") {
valueField.typedInput('hide');
typeValueField.typedInput('hide');
} else if (type === "istype") {
if (!typeValueField){
typeValueField = createTypeValueField();
}
else
if (type === "istype") {
valueField.typedInput('hide');
typeValueField.typedInput('show');
}
else {
typeValueField.typedInput('hide');
typeValueField.typedInput('show');
} else if (! (type === "true" || type === "false" || type === "null" || type === "nnull" || type === "empty" || type === "nempty" || type === "else" )) {
if (!valueField){
valueField = createValueField();
}
valueField.typedInput('show');
}
}
if (type === "regex") {
row2.show();
@@ -296,31 +314,52 @@
} else if ((type === "btwn") || (type === "index")) {
row2.hide();
row3.show();
if (!btwnValue2Field){
btwnValue2Field = createBtwnValue2Field();
}
btwnValue2Field.typedInput('show');
} else {
row2.hide();
row3.hide();
}
resizeRule(container);
});
selectField.val(rule.t);
if ((rule.t == "btwn") || (rule.t == "index")) {
if (!btwnValueField){
btwnValueField = createBtwnValueField();
}
btwnValueField.typedInput('value',rule.v);
btwnValueField.typedInput('type',rule.vt||'num');
if (!btwnValue2Field){
btwnValue2Field = createBtwnValue2Field();
}
btwnValue2Field.typedInput('value',rule.v2);
btwnValue2Field.typedInput('type',rule.v2t||'num');
} else if ((rule.t === "head") || (rule.t === "tail")) {
if (!numValueField){
numValueField = createNumValueField();
}
numValueField.typedInput('value',rule.v);
numValueField.typedInput('type',rule.vt||'num');
} else if (rule.t === "istype") {
if (!typeValueField){
typeValueField =createTypeValueField();
}
typeValueField.typedInput('value',rule.vt);
typeValueField.typedInput('type',rule.vt);
} else if (rule.t === "hask") {
keyValueField.typedInput('value',rule.v);
keyValueField.typedInput('type',rule.vt);
}else if (rule.t === "jsonata_exp") {
} else if (rule.t === "jsonata_exp") {
if (!expValueField){
expValueField = createExpValueField();
}
expValueField.typedInput('value',rule.v);
expValueField.typedInput('type',rule.vt||'jsonata');
} else if (typeof rule.v != "undefined") {
if (!valueField){
valueField = createValueField();
}
valueField.typedInput('value',rule.v);
valueField.typedInput('type',rule.vt||'str');
}
@@ -372,7 +411,6 @@
},
oneditsave: function() {
var rules = $("#node-input-rule-container").editableList('items');
var ruleset;
var node = this;
node.rules = [];
rules.each(function(i) {
@@ -392,9 +430,6 @@
} else if (type === "istype") {
r.v = rule.find(".node-input-rule-type-value").typedInput('type');
r.vt = rule.find(".node-input-rule-type-value").typedInput('type');
} else if (type === "hask") {
r.v = rule.find(".node-input-rule-key-value").typedInput('value');
r.vt = rule.find(".node-input-rule-key-value").typedInput('type');
} else if (type === "jsonata_exp") {
r.v = rule.find(".node-input-rule-exp-value").typedInput('value');
r.vt = rule.find(".node-input-rule-exp-value").typedInput('type');

View File

@@ -226,7 +226,6 @@
},
oneditsave: function() {
var rules = $("#node-input-rule-container").editableList('items');
var ruleset;
var node = this;
node.rules= [];
rules.each(function(i) {

View File

@@ -328,13 +328,14 @@ module.exports = function(RED) {
}
if (valid) {
this.on('input', function(msg) {
this.on('input', function(msg, send, done) {
applyRules(msg, 0, (err,msg) => {
if (err) {
node.error(err,msg);
} else if (msg) {
node.send(msg);
send(msg);
}
done();
})
});
}

View File

@@ -21,6 +21,8 @@
<option value="javascript">Javascript</option>
<option value="css">CSS</option>
<option value="markdown">Markdown</option>
<option value="python">Python</option>
<option value="sql">SQL</option>
<option value="yaml">YAML</option>
<option value="text" data-i18n="template.label.none"></option>
</select>

View File

@@ -35,11 +35,6 @@
<option value="true" data-i18n="exec.opt.spawn"></option>
</select>
</div>
<div class="form-row">
<label>&nbsp;</label>
<input type="checkbox" id="node-input-oldrc" style="display:inline-block; width:auto; vertical-align:top;">
<label for="node-input-oldrc" style="width:70%;"><span data-i18n="exec.oldrc"></span></label>
</div>
<div class="form-row">
<label for="node-input-timer"><i class="fa fa-clock-o"></i> <span data-i18n="exec.label.timeout"></span></label>
<input type="text" id="node-input-timer" style="width:65px;" data-i18n="[placeholder]exec.label.timeoutplace">
@@ -53,7 +48,7 @@
<script type="text/javascript">
RED.nodes.registerType('exec',{
category: 'advanced-function',
category: 'function',
color:"darksalmon",
defaults: {
command: {value:""},
@@ -73,8 +68,7 @@
this._("exec.label.retcode")
][i];
},
icon: "arrow-in.svg",
align: "right",
icon: "cog.svg",
label: function() {
return this.name||this.command||(this.useSpawn=="true"?this._("exec.spawn"):this._("exec.exec"));
},

View File

@@ -38,7 +38,7 @@ module.exports = function(RED) {
//node.error("Exec node timeout");
}
this.on("input", function(msg) {
this.on("input", function(msg, nodeSend, nodeDone) {
if (msg.hasOwnProperty("kill")) {
if (typeof msg.kill !== "string" || msg.kill.length === 0 || !msg.kill.toUpperCase().startsWith("SIG") ) { msg.kill = "SIGTERM"; }
if (msg.hasOwnProperty("pid")) {
@@ -53,6 +53,7 @@ module.exports = function(RED) {
node.status({fill:"red",shape:"dot",text:"killed"});
}
}
nodeDone();
}
else {
var child;
@@ -85,14 +86,14 @@ module.exports = function(RED) {
// console.log('[exec] stdout: ' + data,child.pid);
if (isUtf8(data)) { msg.payload = data.toString(); }
else { msg.payload = data; }
node.send([RED.util.cloneMessage(msg),null,null]);
nodeSend([RED.util.cloneMessage(msg),null,null]);
}
});
child.stderr.on('data', function (data) {
if (node.activeProcesses.hasOwnProperty(child.pid) && node.activeProcesses[child.pid] !== null) {
if (isUtf8(data)) { msg.payload = data.toString(); }
else { msg.payload = Buffer.from(data); }
node.send([null,RED.util.cloneMessage(msg),null]);
nodeSend([null,RED.util.cloneMessage(msg),null]);
}
});
child.on('close', function (code,signal) {
@@ -108,8 +109,9 @@ module.exports = function(RED) {
if (code === null) { node.status({fill:"red",shape:"dot",text:"killed"}); }
else if (code < 0) { node.status({fill:"red",shape:"dot",text:"rc:"+code}); }
else { node.status({fill:"yellow",shape:"dot",text:"rc:"+code}); }
node.send([null,null,RED.util.cloneMessage(msg)]);
nodeSend([null,null,RED.util.cloneMessage(msg)]);
}
nodeDone();
});
child.on('error', function (code) {
if (child.tout) { clearTimeout(child.tout); }
@@ -154,9 +156,10 @@ module.exports = function(RED) {
msg.rc = msg3.payload;
if (msg2) { msg2.rc = msg3.payload; }
}
node.send([msg,msg2,msg3]);
nodeSend([msg,msg2,msg3]);
if (child.tout) { clearTimeout(child.tout); }
delete node.activeProcesses[child.pid];
nodeDone();
});
node.status({fill:"blue",shape:"dot",text:"pid:"+child.pid});
child.on('error',function() {});

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