Compare commits
1301 Commits
1.0.0-beta
...
1.3.0-beta
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
15715a2968 | ||
|
|
b5751e5746 | ||
|
|
7e40cb5331 | ||
|
|
4b1a86ee02 | ||
|
|
6c66ca8acf | ||
|
|
d58a091bb7 | ||
|
|
0566a2d9b1 | ||
|
|
3d23d1de4f | ||
|
|
c9c5f7f088 | ||
|
|
8e65408b1c | ||
|
|
c3adc956d7 | ||
|
|
f69d6b4eb1 | ||
|
|
916d377aaa | ||
|
|
39532a9d65 | ||
|
|
3dc696b2a9 | ||
|
|
7be7dec19a | ||
|
|
fc709ba266 | ||
|
|
080e2f2589 | ||
|
|
0dc4440a99 | ||
|
|
f770786b89 | ||
|
|
46bc331428 | ||
|
|
3af77b6a31 | ||
|
|
8c4461c4f8 | ||
|
|
bccfd21cf4 | ||
|
|
e6f1394a74 | ||
|
|
de24831fb9 | ||
|
|
e5716162ad | ||
|
|
5809a3af0d | ||
|
|
11a385550a | ||
|
|
255b8f2005 | ||
|
|
3d398cfd53 | ||
|
|
5f8804c25c | ||
|
|
02d1369d5b | ||
|
|
0fef2ab509 | ||
|
|
16088b8a08 | ||
|
|
69befe8f0e | ||
|
|
ae7a3981c0 | ||
|
|
8b4aa3f5af | ||
|
|
60c8a2c598 | ||
|
|
fbb7dd4c3f | ||
|
|
833ecfb1af | ||
|
|
c20bab2436 | ||
|
|
afb17af571 | ||
|
|
5012568464 | ||
|
|
02dd141095 | ||
|
|
0be82d964e | ||
|
|
b41c7962c2 | ||
|
|
6f9e06e78d | ||
|
|
c2347076f4 | ||
|
|
c744af161d | ||
|
|
74ea382cf2 | ||
|
|
ab4a9e72d4 | ||
|
|
3f9a29730f | ||
|
|
8a076c01ab | ||
|
|
ca75efcbaf | ||
|
|
f96ce2fd83 | ||
|
|
d5f4f987f2 | ||
|
|
11475b0c38 | ||
|
|
137fa98903 | ||
|
|
ea62c1806e | ||
|
|
45afd06047 | ||
|
|
e6ec59092c | ||
|
|
35f788693d | ||
|
|
d5314d2a85 | ||
|
|
efd8c3d6d2 | ||
|
|
7d04353843 | ||
|
|
644da0b77b | ||
|
|
785c349adc | ||
|
|
1608196cd2 | ||
|
|
9d34abf603 | ||
|
|
05beb6ca79 | ||
|
|
12c7238c72 | ||
|
|
ed359ca10c | ||
|
|
b66468c4ea | ||
|
|
d2c9ccbfdd | ||
|
|
85e05b787f | ||
|
|
e5471b44e0 | ||
|
|
e0f0a76ae4 | ||
|
|
6336ab121e | ||
|
|
e899d2d5b8 | ||
|
|
a94c19a6cf | ||
|
|
9c09ee3b71 | ||
|
|
d8e68a75b9 | ||
|
|
302c5cfe09 | ||
|
|
1be337fbc5 | ||
|
|
3ec37e2c66 | ||
|
|
3740c21bee | ||
|
|
5a6568e7c2 | ||
|
|
4cd9b7b050 | ||
|
|
dd780945e1 | ||
|
|
e86f6a841a | ||
|
|
fad8dcd304 | ||
|
|
1633a2ff70 | ||
|
|
a2878fa066 | ||
|
|
735de2908a | ||
|
|
818021e0b7 | ||
|
|
3cc6c4433f | ||
|
|
8306ddd40f | ||
|
|
024e71cdf5 | ||
|
|
4313cbaa5c | ||
|
|
f5da2eb633 | ||
|
|
23f0cd3a26 | ||
|
|
74db3e17d0 | ||
|
|
7bde7f0cfd | ||
|
|
ac68e9c6b5 | ||
|
|
32692dce07 | ||
|
|
64d3b8e104 | ||
|
|
a03edf3d58 | ||
|
|
e5b7ccb612 | ||
|
|
9c1ce5543d | ||
|
|
ba387a8e4e | ||
|
|
7fa25c1ff4 | ||
|
|
3bd1bfc769 | ||
|
|
dad47ade38 | ||
|
|
fa6e0c8964 | ||
|
|
bb4b252401 | ||
|
|
a50404b141 | ||
|
|
61690ecf4a | ||
|
|
f4c87af5c1 | ||
|
|
83d12f7d39 | ||
|
|
2e73b229d7 | ||
|
|
3a0074d96e | ||
|
|
7068c175f2 | ||
|
|
9b5ed8407f | ||
|
|
7d08de9c99 | ||
|
|
575d07e41a | ||
|
|
24da3608c4 | ||
|
|
37935bf388 | ||
|
|
9eb7fad621 | ||
|
|
438d51d26e | ||
|
|
34ef055d7b | ||
|
|
4a1d66f210 | ||
|
|
1f6328bf4e | ||
|
|
8e7a230dbc | ||
|
|
6e718ca772 | ||
|
|
70554e24b1 | ||
|
|
a0f736bb88 | ||
|
|
79473c243d | ||
|
|
441eb3bb29 | ||
|
|
ca44af0625 | ||
|
|
9e179170ee | ||
|
|
9f71dbb006 | ||
|
|
7531314e3f | ||
|
|
a006b52052 | ||
|
|
bebebaa3dd | ||
|
|
55ff035fc9 | ||
|
|
d8c8d7bc57 | ||
|
|
b0acb58442 | ||
|
|
2b28ae3402 | ||
|
|
aa47bae2ad | ||
|
|
ccfde84769 | ||
|
|
b1df6d5149 | ||
|
|
d51aefa156 | ||
|
|
c40412d7c6 | ||
|
|
b0bc7ecacb | ||
|
|
5489bd37c9 | ||
|
|
ea2e3f25d8 | ||
|
|
09b37cf538 | ||
|
|
e30a01310e | ||
|
|
d5cc5b2574 | ||
|
|
160ca6add4 | ||
|
|
da96c85d32 | ||
|
|
de15a1c36f | ||
|
|
814fc8bc69 | ||
|
|
0c9fd25d3e | ||
|
|
9a660f3fe9 | ||
|
|
6e1466e411 | ||
|
|
7913b3cbc2 | ||
|
|
87c9ed6356 | ||
|
|
06ceb056f3 | ||
|
|
65b4ef6c3d | ||
|
|
0284ef401e | ||
|
|
8a87f93741 | ||
|
|
af19536222 | ||
|
|
abe77ab96f | ||
|
|
ea720bb4a5 | ||
|
|
6ee2e2b570 | ||
|
|
3885107e6e | ||
|
|
30a68fefec | ||
|
|
fa84c4e461 | ||
|
|
5743a5f91d | ||
|
|
9d2d060dec | ||
|
|
b36e7e172e | ||
|
|
aacb92a7ae | ||
|
|
4943bde3d4 | ||
|
|
fc459be531 | ||
|
|
3151502a3f | ||
|
|
79b10ed18a | ||
|
|
34b27f2e68 | ||
|
|
c433f736a5 | ||
|
|
55e6c6e01a | ||
|
|
496b5a092f | ||
|
|
02510efda1 | ||
|
|
be828af3e2 | ||
|
|
9b1c114c3f | ||
|
|
4df27d4b0b | ||
|
|
e3445dae46 | ||
|
|
f5fcf23678 | ||
|
|
0a6c08e2c3 | ||
|
|
b80a7459cf | ||
|
|
f6480e6e0c | ||
|
|
41d12c433e | ||
|
|
169a2484f2 | ||
|
|
be52ec1390 | ||
|
|
00db43198d | ||
|
|
6bac207611 | ||
|
|
df1eb631e1 | ||
|
|
6150ae787d | ||
|
|
fc7967d455 | ||
|
|
fca21ac126 | ||
|
|
6fb96fa3c1 | ||
|
|
a1f565f756 | ||
|
|
5992ed1fab | ||
|
|
beccdac717 | ||
|
|
9f3e9786a8 | ||
|
|
b72ea63100 | ||
|
|
27550f2d4b | ||
|
|
6917919f35 | ||
|
|
48d6fe5918 | ||
|
|
c9bc530df0 | ||
|
|
0b569a4120 | ||
|
|
950fd7d2cf | ||
|
|
50dd0354d1 | ||
|
|
78f1cb8a66 | ||
|
|
4bfe9a9ae9 | ||
|
|
c5d38d8962 | ||
|
|
bbe3ee701f | ||
|
|
2f86bb1ca5 | ||
|
|
3999690062 | ||
|
|
b1c0d6b452 | ||
|
|
d57edaa4c1 | ||
|
|
3033d2086e | ||
|
|
0f7d185a61 | ||
|
|
81f200641b | ||
|
|
c6129b44a1 | ||
|
|
088419b38e | ||
|
|
8ebcee32c2 | ||
|
|
2b801a756a | ||
|
|
98b639540b | ||
|
|
e0b797fc7e | ||
|
|
795416a84d | ||
|
|
545dda166f | ||
|
|
f19ec5d9b6 | ||
|
|
6ea978d83d | ||
|
|
42f3b70a22 | ||
|
|
1cd10f074b | ||
|
|
bed1d31bc8 | ||
|
|
99478897c5 | ||
|
|
d79cd463a0 | ||
|
|
2a8290a4b7 | ||
|
|
ccf4e73701 | ||
|
|
01b67c692b | ||
|
|
4023ab3f28 | ||
|
|
70f3b7450f | ||
|
|
ca4960e097 | ||
|
|
ebe604e1af | ||
|
|
32b04cd32f | ||
|
|
e149174696 | ||
|
|
f878ffc01b | ||
|
|
15b49f4db8 | ||
|
|
b1cc7b3296 | ||
|
|
65d90a6dff | ||
|
|
a58f4c2ec2 | ||
|
|
f038069fe2 | ||
|
|
407cb3e7d5 | ||
|
|
b8bc62ee11 | ||
|
|
ccbd179f23 | ||
|
|
dac7830bd4 | ||
|
|
75d7ac2d8a | ||
|
|
468cfeffb6 | ||
|
|
bc82ca2106 | ||
|
|
725c962236 | ||
|
|
6720c1aa46 | ||
|
|
280203e64e | ||
|
|
281d8b7cec | ||
|
|
2c6cda1f27 | ||
|
|
d7dfeaf0c1 | ||
|
|
fa532da8c7 | ||
|
|
cbf84647de | ||
|
|
dbfbd54e1f | ||
|
|
c38a490a6f | ||
|
|
9d7a450821 | ||
|
|
8007bea7db | ||
|
|
dc1ab7e331 | ||
|
|
a0d197d0c0 | ||
|
|
a776ba248e | ||
|
|
0ecd9673b8 | ||
|
|
97aa1230ef | ||
|
|
ff0be73b1f | ||
|
|
8049e44dec | ||
|
|
dc26022fb4 | ||
|
|
e8e44f9a32 | ||
|
|
12d56b8b03 | ||
|
|
e62fd7ed15 | ||
|
|
978eb95acd | ||
|
|
e34f4acb22 | ||
|
|
195aeb5caf | ||
|
|
15a600c763 | ||
|
|
82ad5839fa | ||
|
|
9af883231d | ||
|
|
9bfe8ac007 | ||
|
|
f46367d77b | ||
|
|
38649de85f | ||
|
|
eb2e1c0c45 | ||
|
|
33bb86cbcf | ||
|
|
baffc2d6ca | ||
|
|
96ab508c91 | ||
|
|
57e42659e3 | ||
|
|
f059e97697 | ||
|
|
516e6430eb | ||
|
|
f194a8ecf4 | ||
|
|
13f046f310 | ||
|
|
1edf5acb87 | ||
|
|
af636870d4 | ||
|
|
379b8ada61 | ||
|
|
5e63471983 | ||
|
|
086f0f8450 | ||
|
|
97a4b3dc2a | ||
|
|
4eb8d681c1 | ||
|
|
2066584164 | ||
|
|
a954c198fb | ||
|
|
bb1f8cd5e8 | ||
|
|
101e96dcb3 | ||
|
|
59adf82895 | ||
|
|
3b68f56b15 | ||
|
|
2962c4372c | ||
|
|
517e376582 | ||
|
|
7a90fe5aec | ||
|
|
ea45dde63a | ||
|
|
22a301b55e | ||
|
|
605177dcf0 | ||
|
|
460e1f5563 | ||
|
|
6f25337b99 | ||
|
|
08148a07b2 | ||
|
|
27c0e45940 | ||
|
|
bdd736315a | ||
|
|
d57ec0cd53 | ||
|
|
952c9d8bdb | ||
|
|
cf84ec78fa | ||
|
|
b595e84c30 | ||
|
|
6e5f115bd5 | ||
|
|
a1ab00c93e | ||
|
|
6e5c4e832e | ||
|
|
48ea487974 | ||
|
|
54dc98a90b | ||
|
|
c5bdd3d056 | ||
|
|
64d6e1f8e1 | ||
|
|
69d60ffb24 | ||
|
|
e6ffa3d143 | ||
|
|
bb4330e486 | ||
|
|
1a4d720978 | ||
|
|
91c2f479bb | ||
|
|
b61701fa17 | ||
|
|
cb9f910642 | ||
|
|
4b8d07f301 | ||
|
|
2db3a4f1ef | ||
|
|
ead1f65887 | ||
|
|
aae9866866 | ||
|
|
085ff84bc9 | ||
|
|
e12975cf0b | ||
|
|
a33cf6b532 | ||
|
|
5be25d9538 | ||
|
|
2b29eeb795 | ||
|
|
785561a0cc | ||
|
|
b46dc88346 | ||
|
|
96d81ef72b | ||
|
|
81dc3de26a | ||
|
|
4d0c572c2e | ||
|
|
fb2da0ee9e | ||
|
|
b8b0247717 | ||
|
|
103e212aee | ||
|
|
2f33575907 | ||
|
|
576c528573 | ||
|
|
3c444d3fb3 | ||
|
|
7cb499cde9 | ||
|
|
5a174ba014 | ||
|
|
041feb4e86 | ||
|
|
19726cf428 | ||
|
|
aaf134b1c5 | ||
|
|
9d5f5ee94b | ||
|
|
a48f0827ae | ||
|
|
5686158245 | ||
|
|
3824cdde68 | ||
|
|
e619b9bf7b | ||
|
|
b7243c2226 | ||
|
|
70b6674f44 | ||
|
|
ef67b8481e | ||
|
|
baffe4861c | ||
|
|
5cf489a270 | ||
|
|
44b1819926 | ||
|
|
d84c2b780b | ||
|
|
dc8991a1da | ||
|
|
7bd0ca2212 | ||
|
|
4dd619b8c6 | ||
|
|
3a86ab186c | ||
|
|
2f2a6367c2 | ||
|
|
be880c25f9 | ||
|
|
17812f0d77 | ||
|
|
0c5eae2349 | ||
|
|
3ad1803057 | ||
|
|
02c20e97b7 | ||
|
|
716dc781e4 | ||
|
|
d9900d8e4c | ||
|
|
3b9065b057 | ||
|
|
e73b748b95 | ||
|
|
b309161f00 | ||
|
|
b21667834e | ||
|
|
183fa59c83 | ||
|
|
0c5586ddfb | ||
|
|
33855bcb8b | ||
|
|
dc81b7a699 | ||
|
|
b0b2c32654 | ||
|
|
6f1ed76b4c | ||
|
|
f81cee0be2 | ||
|
|
bcd85b11a1 | ||
|
|
ec368ae3fd | ||
|
|
d28c264422 | ||
|
|
fba505bc90 | ||
|
|
c50ed2c328 | ||
|
|
7e11ff2b20 | ||
|
|
3fb83c46e2 | ||
|
|
763f2bd5c5 | ||
|
|
85edee288f | ||
|
|
1aa494a97a | ||
|
|
a8e7627184 | ||
|
|
d590bbdd2c | ||
|
|
80d65b5acb | ||
|
|
1d250f7491 | ||
|
|
dd741ec6d8 | ||
|
|
e741af6d55 | ||
|
|
e691b1b7c3 | ||
|
|
29142128f2 | ||
|
|
758f44e25f | ||
|
|
16c26d8098 | ||
|
|
a004c61afc | ||
|
|
a9d1a64c32 | ||
|
|
889224715b | ||
|
|
442b9d23f1 | ||
|
|
e4dd895709 | ||
|
|
82677c304e | ||
|
|
73d8dfe381 | ||
|
|
1177aa8aca | ||
|
|
0eda0a4935 | ||
|
|
a19dab0dc9 | ||
|
|
d8eb80b72e | ||
|
|
4f3a6821d1 | ||
|
|
77bd7541ca | ||
|
|
ca46bc5366 | ||
|
|
2e19bc07df | ||
|
|
3f4de43b67 | ||
|
|
0d0bf62fc4 | ||
|
|
3c8654fa25 | ||
|
|
756a6ec5aa | ||
|
|
98c7364924 | ||
|
|
62c01b59b2 | ||
|
|
43db1824be | ||
|
|
7f671c9f3f | ||
|
|
410009dd61 | ||
|
|
580cc00967 | ||
|
|
612c565cfd | ||
|
|
979c5351a8 | ||
|
|
97b7479081 | ||
|
|
1df2f5e96a | ||
|
|
0601833387 | ||
|
|
8b36279e52 | ||
|
|
32163d5f21 | ||
|
|
1c337f6817 | ||
|
|
6df26f2400 | ||
|
|
a9431a5aee | ||
|
|
5a3c832a98 | ||
|
|
c4b5bb22db | ||
|
|
2b5a976f35 | ||
|
|
5d7a625883 | ||
|
|
ae1ca85924 | ||
|
|
c9acfdb1d7 | ||
|
|
11ac8fbf13 | ||
|
|
dc541444ba | ||
|
|
8ea25bcd1c | ||
|
|
f5e46a663a | ||
|
|
64ec415a54 | ||
|
|
57154b2853 | ||
|
|
0243a902b2 | ||
|
|
6c04402a98 | ||
|
|
ef7c9b5c2a | ||
|
|
73448a6039 | ||
|
|
176a0ff99b | ||
|
|
b96d562700 | ||
|
|
7a3ead8f3b | ||
|
|
f72903ccc2 | ||
|
|
668678b2c4 | ||
|
|
e2802175a5 | ||
|
|
71c5b1be86 | ||
|
|
44da085e0b | ||
|
|
362554ad3b | ||
|
|
f01866d76f | ||
|
|
53490cd368 | ||
|
|
c171088838 | ||
|
|
0cc944dc5a | ||
|
|
8bd8834237 | ||
|
|
84fc739c8d | ||
|
|
a7fa2cf0c9 | ||
|
|
1137cd5ca5 | ||
|
|
d47906b525 | ||
|
|
13a59a882e | ||
|
|
3b7348f862 | ||
|
|
07585f01e3 | ||
|
|
5042137006 | ||
|
|
a2ea79130c | ||
|
|
979401f3ac | ||
|
|
4c98db2269 | ||
|
|
209c5f337c | ||
|
|
8080ed4787 | ||
|
|
f3be5f0e67 | ||
|
|
fb2d185c5f | ||
|
|
f2d696b48e | ||
|
|
5596d2df8e | ||
|
|
b72ca439e2 | ||
|
|
432ed264c2 | ||
|
|
0a411cbe4f | ||
|
|
581f71911a | ||
|
|
e548bf8bc2 | ||
|
|
1d944bab51 | ||
|
|
6f407750f5 | ||
|
|
19ffe8f308 | ||
|
|
c9069d472f | ||
|
|
68d3cc7507 | ||
|
|
0c90376752 | ||
|
|
f5eb832cd2 | ||
|
|
c3a058a479 | ||
|
|
bc87210ce3 | ||
|
|
d595eb2614 | ||
|
|
cb4d118ccc | ||
|
|
62c723866a | ||
|
|
c9e54f2ba9 | ||
|
|
e2c86c4b96 | ||
|
|
4469a334fd | ||
|
|
aca379db6e | ||
|
|
9ce5210c33 | ||
|
|
4dd68452b4 | ||
|
|
714b3d3fe0 | ||
|
|
2378e0d961 | ||
|
|
f78bbdc29f | ||
|
|
708620f929 | ||
|
|
9f0490fc12 | ||
|
|
d37eebd8ed | ||
|
|
bfeda23ce5 | ||
|
|
52eb158231 | ||
|
|
afb782410d | ||
|
|
aebb7da3c7 | ||
|
|
b90710945a | ||
|
|
56efd51c06 | ||
|
|
76728d1783 | ||
|
|
5b1fe9aa0a | ||
|
|
e3c8466819 | ||
|
|
6a70cd1975 | ||
|
|
2c45771024 | ||
|
|
ebca8c0217 | ||
|
|
752a080876 | ||
|
|
0541d9189d | ||
|
|
0e454b08c8 | ||
|
|
2d0ca20a03 | ||
|
|
61d9ccf263 | ||
|
|
1c30584153 | ||
|
|
5c5bebd689 | ||
|
|
d9548a2891 | ||
|
|
d25e027201 | ||
|
|
93211470d1 | ||
|
|
b5800205c4 | ||
|
|
eeebf04509 | ||
|
|
f4f99f594d | ||
|
|
5e8e739f78 | ||
|
|
a15adc43af | ||
|
|
07556592c1 | ||
|
|
7694349078 | ||
|
|
4f3cb3103e | ||
|
|
842cd1ecf0 | ||
|
|
81a4f42673 | ||
|
|
152e695f4c | ||
|
|
5a0c10b80e | ||
|
|
06adf3d346 | ||
|
|
7be824640c | ||
|
|
c061487a16 | ||
|
|
97fd34150f | ||
|
|
6d294a0c74 | ||
|
|
fe4ef354ac | ||
|
|
d28b8b5e8d | ||
|
|
f2b30d9a3f | ||
|
|
0a614f2741 | ||
|
|
a9fb50787b | ||
|
|
ce7d7a8e01 | ||
|
|
7006c00233 | ||
|
|
21866634b3 | ||
|
|
34dfd50702 | ||
|
|
d9502a6c00 | ||
|
|
95f7b9205a | ||
|
|
d14d4944a0 | ||
|
|
b4b2729e96 | ||
|
|
299b81f51b | ||
|
|
ad6b18e66f | ||
|
|
091a462a42 | ||
|
|
cb218a57f1 | ||
|
|
ba8649117d | ||
|
|
20daebd965 | ||
|
|
7c2786969a | ||
|
|
565aae5967 | ||
|
|
16a634063a | ||
|
|
4c28b5b227 | ||
|
|
a7a949377b | ||
|
|
c048b1a25b | ||
|
|
f7e7f7ed01 | ||
|
|
5dfcb80de8 | ||
|
|
c8f6100a6a | ||
|
|
c0f4e07e10 | ||
|
|
3c259b2c22 | ||
|
|
3b3a2d4edc | ||
|
|
e930098b51 | ||
|
|
43d5df4a12 | ||
|
|
914cfdbc55 | ||
|
|
aa8f4af339 | ||
|
|
b6fbe7d07d | ||
|
|
bf9d6c7ac4 | ||
|
|
139ae547c6 | ||
|
|
8b252b458c | ||
|
|
efecfa328b | ||
|
|
5651e7107f | ||
|
|
b6b3ceef4d | ||
|
|
e44d89c2af | ||
|
|
3e74d75f28 | ||
|
|
6d737b9e4c | ||
|
|
dec82589d1 | ||
|
|
f0193b0f67 | ||
|
|
fdf8eb0657 | ||
|
|
2ce424b567 | ||
|
|
8995fa9ed1 | ||
|
|
dc412b305c | ||
|
|
d7505da997 | ||
|
|
4b54a81dfd | ||
|
|
132254b3a5 | ||
|
|
9128b12960 | ||
|
|
e9104df047 | ||
|
|
bae52613ab | ||
|
|
18af906fd3 | ||
|
|
d45415ab22 | ||
|
|
c6c42740c5 | ||
|
|
b4c033ca50 | ||
|
|
b67f2d874b | ||
|
|
a8d8540346 | ||
|
|
cbf1afc9fe | ||
|
|
8a798e620a | ||
|
|
774751a25c | ||
|
|
13718032f6 | ||
|
|
1b497b340b | ||
|
|
bb41ab482c | ||
|
|
215aab0fe4 | ||
|
|
666822cf51 | ||
|
|
40101df6ec | ||
|
|
4adcb9c439 | ||
|
|
a6cd0bf7e9 | ||
|
|
8158744829 | ||
|
|
70c0c7bc14 | ||
|
|
fdda29f048 | ||
|
|
95cc8ea80d | ||
|
|
18f8dde712 | ||
|
|
effff3405b | ||
|
|
9d8cbcb993 | ||
|
|
3345f2f3b8 | ||
|
|
bcf1d986a4 | ||
|
|
a51e74bfa1 | ||
|
|
cf00acac04 | ||
|
|
876a7a4646 | ||
|
|
95d1b7bc36 | ||
|
|
d4ae0b0a2e | ||
|
|
36739fb444 | ||
|
|
7906c28abb | ||
|
|
f87b40941f | ||
|
|
05f816fc5d | ||
|
|
f9a157fe18 | ||
|
|
ca213589ac | ||
|
|
c5ca9fafee | ||
|
|
82b3a97d99 | ||
|
|
1c94064c57 | ||
|
|
7969dd431f | ||
|
|
22e7ddcb1d | ||
|
|
b1eafac67a | ||
|
|
5d81cec00c | ||
|
|
9512450d7c | ||
|
|
ed1998162f | ||
|
|
ac2a21f992 | ||
|
|
ad78ce0eb6 | ||
|
|
8ce49c25d4 | ||
|
|
4c24bd4ab9 | ||
|
|
0de49e2a75 | ||
|
|
05c3f459ad | ||
|
|
50aaef5103 | ||
|
|
38872049fd | ||
|
|
5dc1cc54d5 | ||
|
|
57f0fbbb98 | ||
|
|
977fef03b0 | ||
|
|
7d67e6a276 | ||
|
|
0832be5970 | ||
|
|
2343fbd86a | ||
|
|
367ebc1dd4 | ||
|
|
15cc88de6c | ||
|
|
64b3c11682 | ||
|
|
b8784185e8 | ||
|
|
fdc721baa1 | ||
|
|
03b64bc493 | ||
|
|
a6a781f67c | ||
|
|
fe1f8ca0a8 | ||
|
|
a600feb5de | ||
|
|
1f2c0a78c2 | ||
|
|
e4b9c6a2ee | ||
|
|
a69db4d572 | ||
|
|
12c92072d0 | ||
|
|
e674d9246b | ||
|
|
b71f81af57 | ||
|
|
b3535281ef | ||
|
|
5f5e6ea845 | ||
|
|
64d2e80690 | ||
|
|
b6e0568e76 | ||
|
|
dca5b3b2a0 | ||
|
|
243915516e | ||
|
|
bc3683d8f6 | ||
|
|
1d36ce0fdf | ||
|
|
88d4d306f3 | ||
|
|
184d928cf7 | ||
|
|
fbd911ed27 | ||
|
|
dec3762b7a | ||
|
|
a849872c21 | ||
|
|
1d71fb3554 | ||
|
|
0d3bf0cd00 | ||
|
|
6c766eba86 | ||
|
|
cc760acb62 | ||
|
|
f4d4bf8779 | ||
|
|
90f62e5e4a | ||
|
|
f1bd3e1711 | ||
|
|
01dde8bea5 | ||
|
|
341c66a199 | ||
|
|
bc1fb2770b | ||
|
|
9f1373945b | ||
|
|
266ee2ca81 | ||
|
|
35738cc1a3 | ||
|
|
ff310f89bd | ||
|
|
2dd004f6cd | ||
|
|
964b7e0e23 | ||
|
|
bc039bde81 | ||
|
|
9505f82d9b | ||
|
|
9189db5531 | ||
|
|
bfa5f39b6d | ||
|
|
15f97bbf26 | ||
|
|
90ba761325 | ||
|
|
ddd428f76e | ||
|
|
0c83fa7060 | ||
|
|
f2e2c7e4d0 | ||
|
|
717bfffa63 | ||
|
|
a764a4a44b | ||
|
|
247fa0ce7c | ||
|
|
13932b2cfb | ||
|
|
0bd0540d2f | ||
|
|
9a17cc503c | ||
|
|
89a048e5fa | ||
|
|
88bc022e2a | ||
|
|
00e080459e | ||
|
|
5b197adf33 | ||
|
|
9019c31f91 | ||
|
|
2e14703b16 | ||
|
|
f87698438d | ||
|
|
4af1cf1d1f | ||
|
|
d6ad7dc6eb | ||
|
|
f25e4ea520 | ||
|
|
17891d373b | ||
|
|
9f29149d87 | ||
|
|
010e20989a | ||
|
|
c885f2edaa | ||
|
|
ae5a7176ba | ||
|
|
ee13cd10fe | ||
|
|
b0f9bf2c62 | ||
|
|
9fbfc3d677 | ||
|
|
189389f96a | ||
|
|
2af7066512 | ||
|
|
9cbc40a229 | ||
|
|
18bf220ca4 | ||
|
|
8750c4b121 | ||
|
|
417d2cb40a | ||
|
|
36b0698432 | ||
|
|
0edc57f0e3 | ||
|
|
3d76137247 | ||
|
|
df9d231389 | ||
|
|
e2aebaf0e7 | ||
|
|
20e84a847a | ||
|
|
ad4779e32f | ||
|
|
90537e42ba | ||
|
|
4615465599 | ||
|
|
95418724fa | ||
|
|
989cb05257 | ||
|
|
d7df20413d | ||
|
|
f7e0f55c13 | ||
|
|
e16f48c9fd | ||
|
|
4694644043 | ||
|
|
f468d6e947 | ||
|
|
9a19477796 | ||
|
|
00d41c6de2 | ||
|
|
fc2a9a85ff | ||
|
|
78c86880e4 | ||
|
|
aca61c0354 | ||
|
|
73dde4de51 | ||
|
|
597c4a2e4f | ||
|
|
62ec7f4d37 | ||
|
|
319c7e9e9f | ||
|
|
580492b0c8 | ||
|
|
655ce7b87a | ||
|
|
4e09b404a2 | ||
|
|
748f831495 | ||
|
|
bb3b87814c | ||
|
|
0bfe20182f | ||
|
|
4245c0a0ad | ||
|
|
25aadc690a | ||
|
|
12dc4ab1fa | ||
|
|
55a5917282 | ||
|
|
a5b33d11fc | ||
|
|
d2d872f51c | ||
|
|
5c0b500f48 | ||
|
|
28418288e3 | ||
|
|
0150769c17 | ||
|
|
2eaea02489 | ||
|
|
1a9c4b7714 | ||
|
|
d9f710aa52 | ||
|
|
2069cc4392 | ||
|
|
f78be9050a | ||
|
|
feb5d13e1c | ||
|
|
a3b0448f53 | ||
|
|
3dfbefb9f5 | ||
|
|
9f6bac1b1b | ||
|
|
0f2ed14d16 | ||
|
|
3e898c487a | ||
|
|
efb9dce92f | ||
|
|
f024e0bbed | ||
|
|
3f1bb6771a | ||
|
|
0b3ced5203 | ||
|
|
373267c53b | ||
|
|
ae3e250269 | ||
|
|
33200b2d08 | ||
|
|
b032e00d01 | ||
|
|
fda95dfc5d | ||
|
|
bc96f2d0cb | ||
|
|
c649e1b4a2 | ||
|
|
f54ed8ebd1 | ||
|
|
b82167fefa | ||
|
|
2efc2bc186 | ||
|
|
f572c11912 | ||
|
|
4595a77c41 | ||
|
|
7c1853431a | ||
|
|
e26eb85718 | ||
|
|
821b5686f2 | ||
|
|
c989f466ed | ||
|
|
97c771f93a | ||
|
|
54dbdde9cb | ||
|
|
513957eea1 | ||
|
|
5eed4672ed | ||
|
|
aafa4fe0b9 | ||
|
|
572c03631d | ||
|
|
2f869a55e2 | ||
|
|
161f6090c1 | ||
|
|
efad7270b7 | ||
|
|
24eb78d137 | ||
|
|
e969a1c97c | ||
|
|
4f31632863 | ||
|
|
1d417c07cd | ||
|
|
344c9fe57e | ||
|
|
9d4400349b | ||
|
|
24f7000918 | ||
|
|
6ff3286d78 | ||
|
|
f058de8bcd | ||
|
|
fbfc74e5ca | ||
|
|
1b5654001c | ||
|
|
e0f3e94e2b | ||
|
|
5da89892b4 | ||
|
|
a6ecb54cc4 | ||
|
|
04da13eaf9 | ||
|
|
7fa4df082e | ||
|
|
ae001c5e82 | ||
|
|
e7f942eda7 | ||
|
|
fa8236ee2c | ||
|
|
08ec04c889 | ||
|
|
e5150ea012 | ||
|
|
222ece2533 | ||
|
|
294696daf5 | ||
|
|
d099356207 | ||
|
|
5c06761b1a | ||
|
|
05fc3c5eca | ||
|
|
9d4e2adde4 | ||
|
|
a8db3d8dd3 | ||
|
|
6ae7c51dc5 | ||
|
|
84771f5864 | ||
|
|
4304d44851 | ||
|
|
1018c0e8a5 | ||
|
|
b1d0013214 | ||
|
|
94ef25bbb9 | ||
|
|
13830ffc9c | ||
|
|
e0bef941b4 | ||
|
|
03e9522d98 | ||
|
|
1bdbd31b96 | ||
|
|
ef9db701f8 | ||
|
|
afb564a4fc | ||
|
|
3e7f58dedd | ||
|
|
e46d8345db | ||
|
|
2e364b6d9a | ||
|
|
b4177836a8 | ||
|
|
5b2ee21204 | ||
|
|
9b6e798eb6 | ||
|
|
7c91c4ae5a | ||
|
|
7bc3b662e4 | ||
|
|
64af1f7e9b | ||
|
|
f0038e9796 | ||
|
|
768aa4ac92 | ||
|
|
f61c137ea3 | ||
|
|
20a8059758 | ||
|
|
58696c6ad4 | ||
|
|
b5ed018bae | ||
|
|
91b7dd988e | ||
|
|
b0c3c78899 | ||
|
|
282f00e091 | ||
|
|
5cd2791506 | ||
|
|
9b2e9ec41a | ||
|
|
08ef9ee682 | ||
|
|
a8bc753720 | ||
|
|
266df86d98 | ||
|
|
85a1f59a93 | ||
|
|
43258ee816 | ||
|
|
c4ca0b6e91 | ||
|
|
1bf3b3077e | ||
|
|
c9194c3635 | ||
|
|
27c462fee9 | ||
|
|
7886e5d57c | ||
|
|
6912dec166 | ||
|
|
b8e610e1b6 | ||
|
|
421b5846f2 | ||
|
|
6a30f2cbc8 | ||
|
|
a8b1e91843 | ||
|
|
20f97d0d13 | ||
|
|
4c78f06c2b | ||
|
|
c700d5c922 | ||
|
|
a9508a2c04 | ||
|
|
09d55a0cbd | ||
|
|
b165129388 | ||
|
|
0ef3471f8f | ||
|
|
9ba9998bd6 | ||
|
|
72126730ef | ||
|
|
fd2213232c | ||
|
|
369c5754f2 | ||
|
|
fc3d0ab053 | ||
|
|
1c63d7ff31 | ||
|
|
de971fa53f | ||
|
|
d005eb46cf | ||
|
|
d1dd7d1d51 | ||
|
|
b78ef006ec | ||
|
|
134c68c98e | ||
|
|
82539fc420 | ||
|
|
7a5604697f | ||
|
|
84d2b8ad6d | ||
|
|
9a0c843f29 | ||
|
|
4d96d95370 | ||
|
|
51ea5dc342 | ||
|
|
97d58e34f2 | ||
|
|
86ce5c591b | ||
|
|
dea47a6e3d | ||
|
|
7621cf3377 | ||
|
|
5090b01b8e | ||
|
|
6675fdf3c2 | ||
|
|
491812fac5 | ||
|
|
8a82552bdc | ||
|
|
bd4fc2e5cc | ||
|
|
32aa4c41ce | ||
|
|
2a6bedbd8d | ||
|
|
83942c2551 | ||
|
|
458d794f52 | ||
|
|
95982ad464 | ||
|
|
7723ff461b | ||
|
|
0ca36a89e3 | ||
|
|
cc5fdd9844 | ||
|
|
d09ee6611f | ||
|
|
bba6855872 | ||
|
|
43970b404e | ||
|
|
1868289b71 | ||
|
|
37bcd5c603 | ||
|
|
c9ad5bea93 | ||
|
|
a09b3bb6c7 | ||
|
|
3d6170be5e | ||
|
|
00477fd67a | ||
|
|
21c57f968a | ||
|
|
f7d2314d64 | ||
|
|
5ecf8c83db | ||
|
|
608834eafb | ||
|
|
1fd4b2b9fc | ||
|
|
01a143cd5a | ||
|
|
6321b21a1a | ||
|
|
8405826fab | ||
|
|
22de8855c1 | ||
|
|
1830478ec3 | ||
|
|
6d98b93135 | ||
|
|
54978e4d64 | ||
|
|
9d567d61fe | ||
|
|
79feb691bd | ||
|
|
e16fe1e6a5 | ||
|
|
04d3981921 | ||
|
|
40c3099e4e | ||
|
|
3f86fd7176 | ||
|
|
9e6bc46540 | ||
|
|
5e892f222b | ||
|
|
2da1554caa | ||
|
|
a53d0c091e | ||
|
|
f88bfa059d | ||
|
|
2e38999506 | ||
|
|
42b841cb78 | ||
|
|
c0d007ffa9 | ||
|
|
127b361979 | ||
|
|
e3dab3cf20 | ||
|
|
569b9f3d06 | ||
|
|
d6b5494625 | ||
|
|
f76edf74f9 | ||
|
|
5c199d3bb4 | ||
|
|
634a51635c | ||
|
|
4f9395e881 | ||
|
|
8035531a27 | ||
|
|
cc177533e8 | ||
|
|
cd210d9fbf | ||
|
|
87b9b56b65 | ||
|
|
bffcaa1c17 | ||
|
|
33cbb2ada8 | ||
|
|
d08e77cf36 | ||
|
|
1f8ed9dcb9 | ||
|
|
53b127902c | ||
|
|
389cbf4900 | ||
|
|
80d100f3f9 | ||
|
|
a05589c5a6 | ||
|
|
7d32636133 | ||
|
|
3db5f928ee | ||
|
|
797da3bc8e | ||
|
|
1e8d695311 | ||
|
|
00eb474e02 | ||
|
|
ad6104baeb | ||
|
|
cd552ab202 | ||
|
|
bbd471ad93 | ||
|
|
0f1ca1c7cf | ||
|
|
62fc554d25 | ||
|
|
84dc34e68f | ||
|
|
0bb77bfa7f | ||
|
|
b6702a0c3b | ||
|
|
a781a1dd4d | ||
|
|
d771527f77 | ||
|
|
3d9945b60c | ||
|
|
5897045f24 | ||
|
|
b2f53a183e | ||
|
|
be3dd63360 | ||
|
|
f951fe6939 | ||
|
|
0622be843b | ||
|
|
272fbc0cb0 | ||
|
|
36bf2a3c38 | ||
|
|
663ed9833a | ||
|
|
fcf757f715 | ||
|
|
88e729664a | ||
|
|
c03abdb5e7 | ||
|
|
6d3eb7bb4b | ||
|
|
7ffd37d9cb | ||
|
|
87aacb4270 | ||
|
|
3f756aac21 | ||
|
|
504d13943d | ||
|
|
59b1466e5d | ||
|
|
d5d9ac5c76 | ||
|
|
bb12ec702a | ||
|
|
82490b0a58 | ||
|
|
2cbf625483 | ||
|
|
44f2a986a2 | ||
|
|
c3df1c6cde | ||
|
|
6b52206186 | ||
|
|
9d4238e5cc | ||
|
|
c16c119a7d | ||
|
|
b49835c72f | ||
|
|
ee6f6ae391 | ||
|
|
95a51aafdc | ||
|
|
5e7cd79ed9 | ||
|
|
aba6173e23 | ||
|
|
468beee045 | ||
|
|
70ad66bcff | ||
|
|
e2c3b35391 | ||
|
|
448de23f59 | ||
|
|
74a015c329 | ||
|
|
44a07c74fd | ||
|
|
0f8af4ba1c | ||
|
|
214d788029 | ||
|
|
530bf22bd5 | ||
|
|
ccc98370eb | ||
|
|
7640bc029c | ||
|
|
3f72eb51a0 | ||
|
|
8801ace247 | ||
|
|
faf46e4447 | ||
|
|
63978e226b | ||
|
|
b96164d4f5 | ||
|
|
944070dfb1 | ||
|
|
f0584df1d0 | ||
|
|
ba209c2bdd | ||
|
|
c6e2f28b97 | ||
|
|
2436bb0128 | ||
|
|
9c4640e010 | ||
|
|
1ee43113b1 | ||
|
|
902f477ee3 | ||
|
|
9c1d46ff92 | ||
|
|
fe0d4f08f3 | ||
|
|
9cbd0fceea | ||
|
|
b22a4f94ab | ||
|
|
14c2005bbc | ||
|
|
a4c351fd4f | ||
|
|
a364d4950d | ||
|
|
d017dd75cd | ||
|
|
021df83c3f | ||
|
|
7805974736 | ||
|
|
c1dae95f71 | ||
|
|
e7c2ff3bd2 | ||
|
|
25459b52a1 | ||
|
|
d45274494d | ||
|
|
b81be8f358 | ||
|
|
aa6c0b9d6e | ||
|
|
64580237d5 | ||
|
|
b93165592e | ||
|
|
83c1e44925 | ||
|
|
3088115aba | ||
|
|
fc93e502b8 | ||
|
|
e90e6eaac3 | ||
|
|
2f4dcba54d | ||
|
|
683c6a748e | ||
|
|
175a871ee0 | ||
|
|
b4e2061e85 | ||
|
|
2aef99c440 | ||
|
|
6c125e125f | ||
|
|
88cbc32abc | ||
|
|
8f45e8f84a | ||
|
|
21635aadfe | ||
|
|
d5234888b3 | ||
|
|
f478afb58a | ||
|
|
a54ca699b5 | ||
|
|
1f5ff0c6d3 | ||
|
|
2a2541df59 | ||
|
|
cd629c1699 | ||
|
|
ff96773295 | ||
|
|
4d6828ec14 | ||
|
|
dae1d6057e | ||
|
|
6726c42cc8 | ||
|
|
4f6023e44c | ||
|
|
9e16d7f433 | ||
|
|
aa86cfc55f | ||
|
|
6931cb9895 | ||
|
|
d32d04bd4e | ||
|
|
0b3e9bf5e2 | ||
|
|
a4af7b8e21 | ||
|
|
72deee5d74 | ||
|
|
5e9e523d4c | ||
|
|
c54509df3d | ||
|
|
63cc9adeaa | ||
|
|
74d760a46d | ||
|
|
d46531def8 | ||
|
|
eb09ec6834 | ||
|
|
9bd9c6a400 | ||
|
|
7321e206c5 | ||
|
|
2c7917f0ca | ||
|
|
d94b20a908 | ||
|
|
b1b1fe21dd | ||
|
|
1db3af7c8e | ||
|
|
397fe31f97 | ||
|
|
bc283aa025 | ||
|
|
9dbdf0947b | ||
|
|
7c21bf4555 | ||
|
|
361dc194ee | ||
|
|
8c1aa83d12 | ||
|
|
d2755a8049 | ||
|
|
1b78bd1684 | ||
|
|
5f67f1f078 | ||
|
|
07061928df | ||
|
|
18ff2df65c | ||
|
|
7b1411d171 | ||
|
|
3a1d0f3695 | ||
|
|
2cd5e1d3c5 | ||
|
|
000765fb77 | ||
|
|
0ff324b0db | ||
|
|
a96d5096fe | ||
|
|
e8ef476a6d | ||
|
|
22b9df62d1 | ||
|
|
6026da867b | ||
|
|
4d58902ba7 | ||
|
|
4dc1343445 | ||
|
|
080487cb33 | ||
|
|
0febcf4f9e | ||
|
|
cd23f711ed | ||
|
|
f9b147af42 | ||
|
|
775f1110d3 | ||
|
|
57649a9b81 | ||
|
|
72a268b70a | ||
|
|
f86a171dff | ||
|
|
e022b782a9 | ||
|
|
bd67731bb7 | ||
|
|
25de4e4782 | ||
|
|
c590247afa | ||
|
|
5d36539271 | ||
|
|
0d673486a3 | ||
|
|
29f1651a18 | ||
|
|
dd20a3e685 | ||
|
|
75a5b1354c | ||
|
|
dae9ac8173 | ||
|
|
78b735276b | ||
|
|
e10dd54e2b | ||
|
|
cb8deab1f9 | ||
|
|
e5c27d0236 | ||
|
|
faf6fa9450 | ||
|
|
873bdc6733 | ||
|
|
8a40b075b5 | ||
|
|
56c41374bf | ||
|
|
a08c2c6437 | ||
|
|
e94634544c | ||
|
|
07fe5b247b | ||
|
|
c1c694035d | ||
|
|
147d2a02be | ||
|
|
6f91786f4d | ||
|
|
f62a933d1c | ||
|
|
451835fbeb | ||
|
|
547e7a1b21 | ||
|
|
053e3ba923 | ||
|
|
bf65dcd49b | ||
|
|
a1d186112a | ||
|
|
ca7a298509 | ||
|
|
ff4d58f648 | ||
|
|
a1e10e99fa | ||
|
|
16bda530f6 | ||
|
|
bf9e04d9db | ||
|
|
8df86a75b1 | ||
|
|
5056203023 | ||
|
|
a0026e66ce | ||
|
|
f75dd2209d | ||
|
|
e35f6d9e35 | ||
|
|
3cb00ce4e0 | ||
|
|
8e18cf5986 | ||
|
|
81f80600f5 | ||
|
|
895156675f | ||
|
|
1c424e2e0a | ||
|
|
0124bb17e8 | ||
|
|
2c89b2d262 | ||
|
|
c7bbe2f1fe | ||
|
|
88609a8829 | ||
|
|
329beb166c | ||
|
|
e36f3d937c | ||
|
|
1395092ca6 | ||
|
|
c09004dbc8 | ||
|
|
7efe4a2776 | ||
|
|
b763e0b0cb | ||
|
|
ddd0d1bef3 | ||
|
|
dbca2178c0 | ||
|
|
af742ea536 | ||
|
|
14c1a86b9b | ||
|
|
ee3dc8c4cd | ||
|
|
1ed148aaf5 | ||
|
|
3327adb1ae | ||
|
|
4d5f771f9f | ||
|
|
aa69d663ed | ||
|
|
29d1894f9a | ||
|
|
e5738d608c | ||
|
|
9775d3a33d | ||
|
|
ad4cf8d631 | ||
|
|
a27e8777aa | ||
|
|
d23edcc0b5 | ||
|
|
52373e5bef | ||
|
|
bb70e796a1 | ||
|
|
7957ec4369 | ||
|
|
3365d26b40 | ||
|
|
d3c111b533 | ||
|
|
ec876eb102 | ||
|
|
dddfb1ec08 | ||
|
|
6fc9c03d70 | ||
|
|
199ff071e8 | ||
|
|
7e4a06044a | ||
|
|
d047b75cb7 | ||
|
|
6fb6b13037 | ||
|
|
460c5a1ae3 | ||
|
|
9955bcc339 | ||
|
|
0a3ab996eb | ||
|
|
46f912a6f9 | ||
|
|
01e0f24752 | ||
|
|
7178c63e10 | ||
|
|
30c402eb83 | ||
|
|
2601cc898c | ||
|
|
d2a8823808 | ||
|
|
6b61fa9f6f | ||
|
|
247052df5f | ||
|
|
8eb28555bc | ||
|
|
73132475dc | ||
|
|
42c6487ff3 | ||
|
|
1b2e442513 | ||
|
|
a4d48077ba | ||
|
|
901e2527d8 | ||
|
|
17653761b9 | ||
|
|
bca9b5d8c0 | ||
|
|
bc789c7f9f | ||
|
|
a42d7d867e | ||
|
|
d517697564 |
1
.github/ISSUE_TEMPLATE.md
vendored
@@ -32,3 +32,4 @@ To help us understand the issue, please fill-in as much of the following informa
|
||||
- [ ] npm version:
|
||||
- [ ] Platform/OS:
|
||||
- [ ] Browser:
|
||||
- [ ] running in Docker:
|
||||
|
||||
2
.github/ISSUE_TEMPLATE/--bug_report.md
vendored
@@ -1,6 +1,6 @@
|
||||
---
|
||||
name: Bug report
|
||||
about: Reproducable software issues in the core of Node-RED
|
||||
about: Reproducible software issues in the core of Node-RED
|
||||
title: ''
|
||||
labels: ''
|
||||
assignees: ''
|
||||
|
||||
2
.github/PULL_REQUEST_TEMPLATE.md
vendored
@@ -29,6 +29,6 @@ the [forum](https://discourse.nodered.org) or
|
||||
<!-- Put an `x` in the boxes that apply -->
|
||||
|
||||
- [ ] I have read the [contribution guidelines](https://github.com/node-red/node-red/blob/master/CONTRIBUTING.md)
|
||||
- [ ] For non-bugfix PRs, I have discussed this change on the mailing list/slack team.
|
||||
- [ ] For non-bugfix PRs, I have discussed this change on the forum/slack team.
|
||||
- [ ] I have run `grunt` to verify the unit tests pass
|
||||
- [ ] I have added suitable unit tests to cover the new/changed functionality
|
||||
|
||||
29
.github/scripts/update-node-red-docker.js
vendored
Normal file
@@ -0,0 +1,29 @@
|
||||
const fs = require("fs");
|
||||
|
||||
const newVersion = require("../../package.json").version;
|
||||
|
||||
if (process.env.GITHUB_REF !== "refs/tags/"+newVersion) {
|
||||
console.log(`GITHUB_REF doesn't match the package.json version: ${process.env.GITHUB_REF} !== ${newVersion}`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (!/^\d+\.\d+\.\d+$/.test(newVersion)) {
|
||||
console.log(`Not updating for a non-stable release - ${newVersion}`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const currentVersion = require("../../../node-red-docker/package.json").version;
|
||||
|
||||
console.log(`Update from ${currentVersion} to ${newVersion}`)
|
||||
|
||||
updateFile(__dirname+"/../../../node-red-docker/package.json", currentVersion, newVersion);
|
||||
updateFile(__dirname+"/../../../node-red-docker/docker-custom/package.json", currentVersion, newVersion);
|
||||
updateFile(__dirname+"/../../../node-red-docker/README.md", currentVersion, newVersion);
|
||||
|
||||
console.log(`::set-env name=newVersion::${newVersion}`);
|
||||
|
||||
function updateFile(path,from,to) {
|
||||
let contents = fs.readFileSync(path,"utf8");
|
||||
contents = contents.replace(new RegExp(from.replace(/\./g,"\\."),"g"), to);
|
||||
fs.writeFileSync(path, contents);
|
||||
}
|
||||
18
.github/scripts/update-node-red-website.js
vendored
Normal file
@@ -0,0 +1,18 @@
|
||||
const fs = require("fs");
|
||||
|
||||
const newVersion = require("../../package.json").version;
|
||||
|
||||
if (process.env.GITHUB_REF !== "refs/tags/"+newVersion) {
|
||||
console.log(`GITHUB_REF doesn't match the package.json version: ${process.env.GITHUB_REF} !== ${newVersion}`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
if (!/^\d+\.\d+\.\d+$/.test(newVersion)) {
|
||||
console.log(`Not updating for a non-stable release - ${newVersion}`);
|
||||
process.exit(0);
|
||||
}
|
||||
|
||||
const path = __dirname+"/../../../node-red.github.io/index.html";
|
||||
let contents = fs.readFileSync(path, "utf8");
|
||||
contents = contents.replace(/<span class="node-red-latest-version">v\d+\.\d+\.\d+<\/span>/, `<span class="node-red-latest-version">v${newVersion}<\/span>` );
|
||||
fs.writeFileSync(path, contents);
|
||||
59
.github/workflows/build.yml
vendored
Normal file
@@ -0,0 +1,59 @@
|
||||
name: PublishDockerImage
|
||||
env:
|
||||
ACTIONS_ALLOW_UNSECURE_COMMANDS: true
|
||||
on:
|
||||
release:
|
||||
types: [published]
|
||||
|
||||
jobs:
|
||||
generate:
|
||||
name: 'Update node-red-docker image'
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Check out node-red repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
path: 'node-red'
|
||||
- name: Check out node-red-docker repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: 'node-red/node-red-docker'
|
||||
path: 'node-red-docker'
|
||||
- name: Check out node-red.github.io repository
|
||||
uses: actions/checkout@v2
|
||||
with:
|
||||
repository: 'node-red/node-red.github.io'
|
||||
path: 'node-red.github.io'
|
||||
- uses: actions/setup-node@v1
|
||||
with:
|
||||
node-version: '12'
|
||||
- run: node ./node-red/.github/scripts/update-node-red-docker.js
|
||||
- name: Create Docker Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.NR_REPO_TOKEN }}
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||
path: 'node-red-docker'
|
||||
commit-message: 'Bump to ${{ env.newVersion }}'
|
||||
title: '🚀 Update to Node-RED ${{ env.newVersion }} release'
|
||||
body: |
|
||||
Updates the Node-RED Docker repo for the ${{ env.newVersion }} release.
|
||||
|
||||
Once this is merged, you will need to create a new release with the tag `v${{ env.newVersion }}`.
|
||||
|
||||
This PR was auto-generated by a GitHub Action. Any questions, speak to @knolleary
|
||||
- run: node ./node-red/.github/scripts/update-node-red-website.js
|
||||
- name: Create Website Pull Request
|
||||
uses: peter-evans/create-pull-request@v2
|
||||
with:
|
||||
token: ${{ secrets.NR_REPO_TOKEN }}
|
||||
committer: GitHub <noreply@github.com>
|
||||
author: ${{ github.actor }} <${{ github.actor }}@users.noreply.github.com>
|
||||
path: 'node-red.github.io'
|
||||
commit-message: 'Bump to ${{ env.newVersion }}'
|
||||
title: '🚀 Update to Node-RED ${{ env.newVersion }} release'
|
||||
body: |
|
||||
Updates the Node-RED Website repo for the ${{ env.newVersion }} release.
|
||||
|
||||
This PR was auto-generated by a GitHub Action. Any questions, speak to @knolleary
|
||||
2
.gitignore
vendored
@@ -22,3 +22,5 @@ packages/node_modules/@node-red/editor-client/public
|
||||
!test/**/node_modules
|
||||
docs
|
||||
!packages/node_modules/**/docs
|
||||
.vscode
|
||||
.nyc_output
|
||||
|
||||
16
.travis.yml
@@ -1,11 +1,21 @@
|
||||
sudo: false
|
||||
addons:
|
||||
chrome: stable
|
||||
language: node_js
|
||||
matrix:
|
||||
include:
|
||||
- node_js: "14"
|
||||
script:
|
||||
- ./node_modules/.bin/grunt && ( cat coverage/lcov.info | $(npm get prefix)/bin/coveralls || true ) && rm -rf coverage
|
||||
# - scripts/install-ui-test-dependencies.sh && grunt test-ui
|
||||
before_script:
|
||||
- npm install -g coveralls
|
||||
- node_js: "12"
|
||||
script:
|
||||
- ./node_modules/.bin/grunt no-coverage
|
||||
- node_js: "10"
|
||||
script:
|
||||
- ./node_modules/.bin/grunt && istanbul report text && ( cat coverage/lcov.info | $(npm get prefix)/bin/coveralls || true ) && rm -rf coverage
|
||||
before_script:
|
||||
- npm install -g istanbul coveralls
|
||||
- ./node_modules/.bin/grunt no-coverage
|
||||
- node_js: "8"
|
||||
script:
|
||||
- ./node_modules/.bin/grunt no-coverage
|
||||
|
||||
2
API.md
@@ -10,6 +10,6 @@ Module | Description
|
||||
[@node-red/editor-api](@node-red_editor-api.html) | an Express application that serves the Node-RED editor and provides the Admin HTTP API
|
||||
[@node-red/runtime](@node-red_runtime.html) | the core runtime of Node-RED
|
||||
[@node-red/util](@node-red_util.html) | common utilities for the Node-RED runtime and editor modules
|
||||
@node-red/registry | the internal node registry
|
||||
[@node-red/registry](@node-red_registry.html) | the internal node registry
|
||||
@node-red/nodes | the default set of core nodes
|
||||
@node-red/editor-client | the client-side resources of the Node-RED editor application
|
||||
|
||||
1220
CHANGELOG.md
143
Gruntfile.js
@@ -16,18 +16,29 @@
|
||||
|
||||
var path = require("path");
|
||||
var fs = require("fs-extra");
|
||||
var sass = require("node-sass");
|
||||
|
||||
module.exports = function(grunt) {
|
||||
|
||||
var nodemonArgs = ["-v"];
|
||||
var nodemonArgs = ["-V"];
|
||||
var flowFile = grunt.option('flowFile');
|
||||
if (flowFile) {
|
||||
nodemonArgs.push(flowFile);
|
||||
process.env.NODE_RED_ENABLE_PROJECTS=false;
|
||||
}
|
||||
var userDir = grunt.option('userDir');
|
||||
if (userDir) {
|
||||
nodemonArgs.push("-u");
|
||||
nodemonArgs.push(userDir);
|
||||
}
|
||||
|
||||
var browserstack = grunt.option('browserstack');
|
||||
if (browserstack) {
|
||||
process.env.BROWSERSTACK = true;
|
||||
}
|
||||
var nonHeadless = grunt.option('non-headless');
|
||||
if (nonHeadless) {
|
||||
process.env.NODE_RED_NON_HEADLESS = 'true';
|
||||
process.env.NODE_RED_NON_HEADLESS = true;
|
||||
}
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
@@ -42,8 +53,8 @@ module.exports = function(grunt) {
|
||||
ui: 'bdd',
|
||||
reporter: 'spec'
|
||||
},
|
||||
all: { src: ['test/**/*_spec.js'] },
|
||||
core: { src: ["test/_spec.js","test/unit/**/*_spec.js"]},
|
||||
all: { src: ["test/unit/_spec.js","test/unit/**/*_spec.js","test/nodes/**/*_spec.js"] },
|
||||
core: { src: ["test/unit/_spec.js","test/unit/**/*_spec.js"]},
|
||||
nodes: { src: ["test/nodes/**/*_spec.js"]}
|
||||
},
|
||||
webdriver: {
|
||||
@@ -51,19 +62,19 @@ module.exports = function(grunt) {
|
||||
configFile: 'test/editor/wdio.conf.js'
|
||||
}
|
||||
},
|
||||
mocha_istanbul: {
|
||||
nyc: {
|
||||
options: {
|
||||
globals: ['expect'],
|
||||
timeout: 3000,
|
||||
ignoreLeaks: false,
|
||||
ui: 'bdd',
|
||||
reportFormats: ['lcov','html'],
|
||||
print: 'both',
|
||||
istanbulOptions: ['--no-default-excludes', '-i','**/packages/node_modules/**']
|
||||
cwd: '.',
|
||||
include: ['packages/node_modules/**'],
|
||||
excludeNodeModules: false,
|
||||
exclude: ['packages/node_modules/@node-red/editor-client/**'],
|
||||
reporter: ['lcov', 'html','text-summary'],
|
||||
reportDir: 'coverage',
|
||||
all: true
|
||||
},
|
||||
all: { src: ["test/unit/_spec.js","test/unit/**/*_spec.js","test/nodes/**/*_spec.js"] },
|
||||
core: { src: ["test/unit/_spec.js","test/unit/**/*_spec.js"]},
|
||||
nodes: { src: ["test/nodes/**/*_spec.js"]}
|
||||
all: { cmd: false, args: ['grunt', 'simplemocha:all'] },
|
||||
core: { options: { exclude:['packages/node_modules/@node-red/editor-client/**', 'packages/node_modules/@node-red/nodes/**']},cmd: false, args: ['grunt', 'simplemocha:core'] },
|
||||
nodes: { cmd: false, args: ['grunt', 'simplemocha:nodes'] }
|
||||
},
|
||||
jshint: {
|
||||
options: {
|
||||
@@ -79,20 +90,20 @@ module.exports = function(grunt) {
|
||||
//"loopfunc": true, // allow functions to be defined in loops
|
||||
//"sub": true // don't warn that foo['bar'] should be written as foo.bar
|
||||
},
|
||||
all: [
|
||||
'Gruntfile.js',
|
||||
'red.js',
|
||||
'packages/**/*.js'
|
||||
],
|
||||
core: {
|
||||
files: {
|
||||
src: [
|
||||
'Gruntfile.js',
|
||||
'red.js',
|
||||
'packages/**/*.js',
|
||||
]
|
||||
}
|
||||
},
|
||||
// all: [
|
||||
// 'Gruntfile.js',
|
||||
// 'red.js',
|
||||
// 'packages/**/*.js'
|
||||
// ],
|
||||
// core: {
|
||||
// files: {
|
||||
// src: [
|
||||
// 'Gruntfile.js',
|
||||
// 'red.js',
|
||||
// 'packages/**/*.js',
|
||||
// ]
|
||||
// }
|
||||
// },
|
||||
nodes: {
|
||||
files: {
|
||||
src: [ 'nodes/core/*/*.js' ]
|
||||
@@ -100,7 +111,7 @@ module.exports = function(grunt) {
|
||||
},
|
||||
editor: {
|
||||
files: {
|
||||
src: [ 'editor/js/**/*.js' ]
|
||||
src: [ 'packages/node_modules/@node-red/editor-client/src/js/**/*.js' ]
|
||||
}
|
||||
},
|
||||
tests: {
|
||||
@@ -120,6 +131,7 @@ module.exports = function(grunt) {
|
||||
src: [
|
||||
// Ensure editor source files are concatenated in
|
||||
// the right order
|
||||
"packages/node_modules/@node-red/editor-client/src/js/polyfills.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/jquery-addons.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/red.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/events.js",
|
||||
@@ -130,6 +142,7 @@ module.exports = function(grunt) {
|
||||
"packages/node_modules/@node-red/editor-client/src/js/text/bidi.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/text/format.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/state.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/plugins.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/nodes.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/font-awesome.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/history.js",
|
||||
@@ -146,6 +159,7 @@ module.exports = function(grunt) {
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/stack.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/toggleButton.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/common/colorPicker.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/actions.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/deploy.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/diff.js",
|
||||
@@ -158,6 +172,8 @@ module.exports = function(grunt) {
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/sidebar.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/palette.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-info.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-info-outliner.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-help.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-config.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/tab-context.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/palette-editor.js",
|
||||
@@ -172,6 +188,7 @@ module.exports = function(grunt) {
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/actionList.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/typeSearch.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/group.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/userSettings.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projects.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/js/ui/projects/projectSettings.js",
|
||||
@@ -184,11 +201,12 @@ module.exports = function(grunt) {
|
||||
vendor: {
|
||||
files: {
|
||||
"packages/node_modules/@node-red/editor-client/public/vendor/vendor.js": [
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-3.4.1.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-migrate-3.0.1.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-3.5.1.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-migrate-3.3.0.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-ui.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery.ui.touch-punch.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/marked/marked.min.js",
|
||||
"node_modules/marked/marked.min.js",
|
||||
"node_modules/dompurify/dist/purify.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/d3/d3.v3.min.js",
|
||||
"packages/node_modules/@node-red/editor-client/src/vendor/i18next/i18next.min.js",
|
||||
"node_modules/jsonata/jsonata-es5.min.js",
|
||||
@@ -220,6 +238,7 @@ module.exports = function(grunt) {
|
||||
sass: {
|
||||
build: {
|
||||
options: {
|
||||
implementation: sass,
|
||||
outputStyle: 'compressed'
|
||||
},
|
||||
files: [{
|
||||
@@ -440,9 +459,11 @@ module.exports = function(grunt) {
|
||||
'packages/node_modules/@node-red/runtime/lib/index.js',
|
||||
'packages/node_modules/@node-red/runtime/lib/api/*.js',
|
||||
'packages/node_modules/@node-red/runtime/lib/events.js',
|
||||
'packages/node_modules/@node-red/runtime/lib/hooks.js',
|
||||
'packages/node_modules/@node-red/util/**/*.js',
|
||||
'packages/node_modules/@node-red/editor-api/lib/index.js',
|
||||
'packages/node_modules/@node-red/editor-api/lib/auth/index.js'
|
||||
'packages/node_modules/@node-red/editor-api/lib/auth/index.js',
|
||||
'packages/node_modules/@node-red/registry/lib/index.js'
|
||||
],
|
||||
options: {
|
||||
destination: 'docs',
|
||||
@@ -490,12 +511,10 @@ module.exports = function(grunt) {
|
||||
grunt.loadNpmTasks('grunt-contrib-watch');
|
||||
grunt.loadNpmTasks('grunt-concurrent');
|
||||
grunt.loadNpmTasks('grunt-sass');
|
||||
grunt.loadNpmTasks('grunt-nodemon');
|
||||
grunt.loadNpmTasks('grunt-contrib-compress');
|
||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||
grunt.loadNpmTasks('grunt-chmod');
|
||||
grunt.loadNpmTasks('grunt-jsonlint');
|
||||
grunt.loadNpmTasks('grunt-mocha-istanbul');
|
||||
if (fs.existsSync(path.join("node_modules", "grunt-webdriver"))) {
|
||||
grunt.loadNpmTasks('grunt-webdriver');
|
||||
}
|
||||
@@ -503,6 +522,26 @@ module.exports = function(grunt) {
|
||||
grunt.loadNpmTasks('grunt-jsdoc-to-markdown');
|
||||
grunt.loadNpmTasks('grunt-npm-command');
|
||||
grunt.loadNpmTasks('grunt-mkdir');
|
||||
grunt.loadNpmTasks('grunt-simple-nyc');
|
||||
|
||||
grunt.registerMultiTask('nodemon', 'Runs a nodemon monitor of your node.js server.', function () {
|
||||
const nodemon = require('nodemon');
|
||||
this.async();
|
||||
const options = this.options();
|
||||
options.script = this.data.script;
|
||||
let callback;
|
||||
if (options.callback) {
|
||||
callback = options.callback;
|
||||
delete options.callback;
|
||||
} else {
|
||||
callback = function(nodemonApp) {
|
||||
nodemonApp.on('log', function (event) {
|
||||
console.log(event.colour);
|
||||
});
|
||||
};
|
||||
}
|
||||
callback(nodemon(options));
|
||||
});
|
||||
|
||||
grunt.registerMultiTask('attachCopyright', function() {
|
||||
var files = this.data.src;
|
||||
@@ -562,7 +601,20 @@ module.exports = function(grunt) {
|
||||
return false;
|
||||
}
|
||||
});
|
||||
grunt.registerTask('generatePublishScript',
|
||||
'Generates a script to publish build output to npm',
|
||||
function () {
|
||||
const done = this.async();
|
||||
const generatePublishScript = require("./scripts/generate-publish-script.js");
|
||||
generatePublishScript().then(function(output) {
|
||||
grunt.log.writeln(output);
|
||||
|
||||
const filePath = path.join(grunt.config.get('paths.dist'),"modules","publish.sh");
|
||||
grunt.file.write(filePath,output);
|
||||
|
||||
done();
|
||||
});
|
||||
});
|
||||
grunt.registerTask('setDevEnv',
|
||||
'Sets NODE_ENV=development so non-minified assets are used',
|
||||
function () {
|
||||
@@ -571,11 +623,16 @@ module.exports = function(grunt) {
|
||||
|
||||
grunt.registerTask('default',
|
||||
'Builds editor content then runs code style checks and unit tests on all components',
|
||||
['build','verifyPackageDependencies','jshint:editor','mocha_istanbul:all']);
|
||||
['build','verifyPackageDependencies','jshint:editor','nyc:all']);
|
||||
|
||||
grunt.registerTask('no-coverage',
|
||||
'Builds editor content then runs code style checks and unit tests on all components without code coverage',
|
||||
['build','verifyPackageDependencies','jshint:editor','simplemocha:all']);
|
||||
|
||||
|
||||
grunt.registerTask('test-core',
|
||||
'Runs code style check and unit tests on core runtime code',
|
||||
['build','mocha_istanbul:core']);
|
||||
['build','nyc:core']);
|
||||
|
||||
grunt.registerTask('test-editor',
|
||||
'Runs code style check on editor code',
|
||||
@@ -593,19 +650,23 @@ module.exports = function(grunt) {
|
||||
|
||||
grunt.registerTask('test-nodes',
|
||||
'Runs unit tests on core nodes',
|
||||
['build','mocha_istanbul:nodes']);
|
||||
['build','nyc:nodes']);
|
||||
|
||||
grunt.registerTask('build',
|
||||
'Builds editor content',
|
||||
['clean:build','jsonlint','concat:build','concat:vendor','copy:build','uglify:build','sass:build','attachCopyright']);
|
||||
|
||||
grunt.registerTask('build-dev',
|
||||
'Developer mode: build dev version',
|
||||
['clean:build','concat:build','concat:vendor','copy:build','sass:build','setDevEnv']);
|
||||
|
||||
grunt.registerTask('dev',
|
||||
'Developer mode: run node-red, watch for source changes and build/restart',
|
||||
['build','setDevEnv','concurrent:dev']);
|
||||
|
||||
grunt.registerTask('release',
|
||||
'Create distribution zip file',
|
||||
['build','verifyPackageDependencies','clean:release','mkdir:release','chmod:release','compress:release','pack-modules']);
|
||||
['build','verifyPackageDependencies','clean:release','mkdir:release','chmod:release','compress:release','pack-modules','generatePublishScript']);
|
||||
|
||||
grunt.registerTask('pack-modules',
|
||||
'Create module pack files for release',
|
||||
@@ -614,7 +675,7 @@ module.exports = function(grunt) {
|
||||
|
||||
grunt.registerTask('coverage',
|
||||
'Run Istanbul code test coverage task',
|
||||
['build','mocha_istanbul:all']);
|
||||
['build','nyc:all']);
|
||||
|
||||
grunt.registerTask('docs',
|
||||
'Generates API documentation',
|
||||
|
||||
2
LICENSE
@@ -1,4 +1,4 @@
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
Copyright OpenJS Foundation and other contributors, https://openjsf.org/
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
|
||||
@@ -5,9 +5,9 @@ http://nodered.org
|
||||
[](https://travis-ci.org/node-red/node-red)
|
||||
[](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.
|
||||
|
||||

|
||||

|
||||
|
||||
## 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 OpenJS Foundation and other contributors, https://openjsf.org under [the Apache 2.0 license](LICENSE).
|
||||
|
||||
@@ -1,13 +1,5 @@
|
||||
# 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.
|
||||
|
||||
91
package.json
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"name": "node-red",
|
||||
"version": "1.0.0-beta.4",
|
||||
"description": "A visual tool for wiring the Internet of Things",
|
||||
"version": "1.3.0-beta.1",
|
||||
"description": "Low-code programming for event-driven applications",
|
||||
"homepage": "http://nodered.org",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
@@ -13,6 +13,8 @@
|
||||
"start": "node packages/node_modules/node-red/red.js",
|
||||
"test": "grunt",
|
||||
"build": "grunt build",
|
||||
"dev": "grunt dev",
|
||||
"build-dev": "grunt build-dev",
|
||||
"docs": "grunt docs"
|
||||
},
|
||||
"contributors": [
|
||||
@@ -24,88 +26,93 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"ajv": "6.10.2",
|
||||
"ajv": "6.12.6",
|
||||
"async-mutex": "0.2.6",
|
||||
"basic-auth": "2.0.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.19.0",
|
||||
"cheerio": "0.22.0",
|
||||
"clone": "2.1.2",
|
||||
"content-type": "1.0.4",
|
||||
"cookie": "0.4.0",
|
||||
"cookie-parser": "1.4.4",
|
||||
"cookie": "0.4.1",
|
||||
"cookie-parser": "1.4.5",
|
||||
"cors": "2.8.5",
|
||||
"cron": "1.7.1",
|
||||
"denque": "1.4.1",
|
||||
"cron": "1.7.2",
|
||||
"denque": "1.5.0",
|
||||
"express": "4.17.1",
|
||||
"express-session": "1.16.2",
|
||||
"express-session": "1.17.1",
|
||||
"fs-extra": "8.1.0",
|
||||
"fs.notify": "0.0.4",
|
||||
"hash-sum": "2.0.0",
|
||||
"https-proxy-agent": "2.2.2",
|
||||
"https-proxy-agent": "5.0.0",
|
||||
"i18next": "15.1.2",
|
||||
"iconv-lite": "0.5.0",
|
||||
"iconv-lite": "0.6.2",
|
||||
"is-utf8": "0.2.1",
|
||||
"js-yaml": "3.13.1",
|
||||
"js-yaml": "3.14.0",
|
||||
"json-stringify-safe": "5.0.1",
|
||||
"jsonata": "1.6.5",
|
||||
"jsonata": "1.8.4",
|
||||
"lodash.clonedeep": "^4.5.0",
|
||||
"media-typer": "1.1.0",
|
||||
"memorystore": "1.6.1",
|
||||
"mime": "2.4.4",
|
||||
"mqtt": "2.18.8",
|
||||
"memorystore": "1.6.4",
|
||||
"mime": "2.4.7",
|
||||
"moment-timezone": "0.5.32",
|
||||
"mqtt": "4.2.6",
|
||||
"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",
|
||||
"mustache": "4.1.0",
|
||||
"node-red-admin": "^0.2.6",
|
||||
"node-red-node-rbe": "^0.2.9",
|
||||
"node-red-node-sentiment": "^0.1.6",
|
||||
"node-red-node-tail": "^0.1.0",
|
||||
"nopt": "5.0.0",
|
||||
"oauth2orize": "1.11.0",
|
||||
"on-headers": "1.0.2",
|
||||
"passport": "0.4.0",
|
||||
"passport": "0.4.1",
|
||||
"passport-http-bearer": "1.0.1",
|
||||
"passport-oauth2-client-password": "0.1.2",
|
||||
"raw-body": "2.4.1",
|
||||
"request": "2.88.0",
|
||||
"semver": "6.3.0",
|
||||
"uglify-js": "3.6.0",
|
||||
"when": "3.7.8",
|
||||
"tar": "6.0.5",
|
||||
"uglify-js": "3.12.4",
|
||||
"ws": "6.2.1",
|
||||
"xml2js": "0.4.19"
|
||||
"xml2js": "0.4.23"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
"bcrypt": "3.0.6"
|
||||
"bcrypt": "3.0.8"
|
||||
},
|
||||
"devDependencies": {
|
||||
"grunt": "~1.0.4",
|
||||
"dompurify": "2.2.6",
|
||||
"grunt": "1.3.0",
|
||||
"grunt-chmod": "~1.1.1",
|
||||
"grunt-cli": "~1.3.2",
|
||||
"grunt-concurrent": "~2.3.1",
|
||||
"grunt-concurrent": "3.0.0",
|
||||
"grunt-contrib-clean": "~2.0.0",
|
||||
"grunt-contrib-compress": "~1.5.0",
|
||||
"grunt-contrib-compress": "1.6.0",
|
||||
"grunt-contrib-concat": "~1.0.1",
|
||||
"grunt-contrib-copy": "~1.0.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": "~2.0.0",
|
||||
"grunt-mkdir": "~1.0.0",
|
||||
"grunt-mocha-istanbul": "5.0.2",
|
||||
"grunt-nodemon": "~0.4.2",
|
||||
"grunt-jsdoc": "2.4.1",
|
||||
"grunt-jsdoc-to-markdown": "5.0.0",
|
||||
"grunt-jsonlint": "2.1.3",
|
||||
"grunt-mkdir": "~1.1.0",
|
||||
"grunt-npm-command": "~0.1.2",
|
||||
"grunt-sass": "~2.0.0",
|
||||
"grunt-sass": "~3.1.0",
|
||||
"grunt-simple-mocha": "~0.4.1",
|
||||
"http-proxy": "^1.16.2",
|
||||
"istanbul": "0.4.5",
|
||||
"grunt-simple-nyc": "^3.0.1",
|
||||
"http-proxy": "1.18.1",
|
||||
"jsdoc-nr-template": "github:node-red/jsdoc-nr-template",
|
||||
"marked": "2.0.0",
|
||||
"minami": "1.2.3",
|
||||
"mocha": "^5.2.0",
|
||||
"mosca": "^2.8.3",
|
||||
"should": "^8.4.0",
|
||||
"node-red-node-test-helper": "^0.2.7",
|
||||
"node-sass": "^4.14.1",
|
||||
"nodemon": "2.0.6",
|
||||
"should": "13.2.3",
|
||||
"sinon": "1.17.7",
|
||||
"stoppable": "^1.1.0",
|
||||
"supertest": "3.4.2",
|
||||
"node-red-node-test-helper": "^0.2.3",
|
||||
"jsdoc-nr-template": "node-red/jsdoc-nr-template"
|
||||
"supertest": "5.0.0"
|
||||
},
|
||||
"engines": {
|
||||
"node": ">=8"
|
||||
|
||||
@@ -21,15 +21,19 @@ var flows = require("./flows");
|
||||
var flow = require("./flow");
|
||||
var context = require("./context");
|
||||
var auth = require("../auth");
|
||||
var info = require("./settings");
|
||||
var plugins = require("./plugins");
|
||||
|
||||
var apiUtil = require("../util");
|
||||
|
||||
module.exports = {
|
||||
init: function(runtimeAPI) {
|
||||
init: function(settings,runtimeAPI) {
|
||||
flows.init(runtimeAPI);
|
||||
flow.init(runtimeAPI);
|
||||
nodes.init(runtimeAPI);
|
||||
context.init(runtimeAPI);
|
||||
info.init(settings,runtimeAPI);
|
||||
plugins.init(runtimeAPI);
|
||||
|
||||
var needsPermission = auth.needsPermission;
|
||||
|
||||
@@ -47,7 +51,16 @@ module.exports = {
|
||||
|
||||
// Nodes
|
||||
adminApp.get("/nodes",needsPermission("nodes.read"),nodes.getAll,apiUtil.errorHandler);
|
||||
|
||||
if (!settings.externalModules || !settings.externalModules.palette || settings.externalModules.palette.allowInstall !== false) {
|
||||
if (!settings.externalModules || !settings.externalModules.palette || settings.externalModules.palette.allowUpload !== false) {
|
||||
const multer = require('multer');
|
||||
const upload = multer({ storage: multer.memoryStorage() });
|
||||
adminApp.post("/nodes",needsPermission("nodes.write"),upload.single("tarball"),nodes.post,apiUtil.errorHandler);
|
||||
} else {
|
||||
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);
|
||||
@@ -67,6 +80,12 @@ module.exports = {
|
||||
// adminApp.delete("/context/:scope(node|flow)/:id",needsPermission("context.write"),context.delete,apiUtil.errorHandler);
|
||||
adminApp.delete("/context/:scope(node|flow)/:id/*",needsPermission("context.write"),context.delete,apiUtil.errorHandler);
|
||||
|
||||
adminApp.get("/settings",needsPermission("settings.read"),info.runtimeSettings,apiUtil.errorHandler);
|
||||
|
||||
// Plugins
|
||||
adminApp.get("/plugins", needsPermission("plugins.read"), plugins.getAll, apiUtil.errorHandler);
|
||||
adminApp.get("/plugins/messages", needsPermission("plugins.read"), plugins.getCatalogs, apiUtil.errorHandler);
|
||||
|
||||
return adminApp;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -33,6 +33,9 @@ module.exports = {
|
||||
})
|
||||
} else {
|
||||
opts.lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
|
||||
if (/[^0-9a-z=\-\*]/i.test(opts.lang)) {
|
||||
opts.lang = "en-US";
|
||||
}
|
||||
runtimeAPI.nodes.getNodeConfigs(opts).then(function(configs) {
|
||||
res.send(configs);
|
||||
})
|
||||
@@ -44,11 +47,23 @@ module.exports = {
|
||||
user: req.user,
|
||||
module: req.body.module,
|
||||
version: req.body.version,
|
||||
url: req.body.url,
|
||||
tarball: undefined,
|
||||
req: apiUtils.getRequestLogObject(req)
|
||||
}
|
||||
if (!runtimeAPI.settings.editorTheme || !runtimeAPI.settings.editorTheme.palette || runtimeAPI.settings.editorTheme.palette.upload !== false) {
|
||||
if (req.file) {
|
||||
opts.tarball = {
|
||||
name: req.file.originalname,
|
||||
size: req.file.size,
|
||||
buffer: req.file.buffer
|
||||
}
|
||||
}
|
||||
}
|
||||
runtimeAPI.nodes.addModule(opts).then(function(info) {
|
||||
res.json(info);
|
||||
}).catch(function(err) {
|
||||
console.log(err.stack);
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
},
|
||||
@@ -80,6 +95,9 @@ module.exports = {
|
||||
})
|
||||
} else {
|
||||
opts.lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
|
||||
if (/[^0-9a-z=\-\*]/i.test(opts.lang)) {
|
||||
opts.lang = "en-US";
|
||||
}
|
||||
runtimeAPI.nodes.getNodeConfig(opts).then(function(result) {
|
||||
return res.send(result);
|
||||
}).catch(function(err) {
|
||||
@@ -149,6 +167,9 @@ module.exports = {
|
||||
lang: req.query.lng,
|
||||
req: apiUtils.getRequestLogObject(req)
|
||||
}
|
||||
if (/[^0-9a-z=\-\*]/i.test(opts.lang)) {
|
||||
opts.lang = "en-US";
|
||||
}
|
||||
runtimeAPI.nodes.getModuleCatalog(opts).then(function(result) {
|
||||
res.json(result);
|
||||
}).catch(function(err) {
|
||||
@@ -163,6 +184,9 @@ module.exports = {
|
||||
lang: req.query.lng,
|
||||
req: apiUtils.getRequestLogObject(req)
|
||||
}
|
||||
if (/[^0-9a-z=\-\*]/i.test(opts.lang)) {
|
||||
opts.lang = "en-US";
|
||||
}
|
||||
runtimeAPI.nodes.getModuleCatalogs(opts).then(function(result) {
|
||||
res.json(result);
|
||||
}).catch(function(err) {
|
||||
|
||||
46
packages/node_modules/@node-red/editor-api/lib/admin/plugins.js
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
var apiUtils = require("../util");
|
||||
|
||||
var runtimeAPI;
|
||||
|
||||
module.exports = {
|
||||
init: function(_runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
},
|
||||
getAll: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
req: apiUtils.getRequestLogObject(req)
|
||||
}
|
||||
if (req.get("accept") == "application/json") {
|
||||
runtimeAPI.plugins.getPluginList(opts).then(function(list) {
|
||||
res.json(list);
|
||||
})
|
||||
} else {
|
||||
opts.lang = apiUtils.determineLangFromHeaders(req.acceptsLanguages());
|
||||
if (/[^a-z\-\*]/i.test(opts.lang)) {
|
||||
res.json({});
|
||||
return;
|
||||
}
|
||||
runtimeAPI.plugins.getPluginConfigs(opts).then(function(configs) {
|
||||
res.send(configs);
|
||||
})
|
||||
}
|
||||
},
|
||||
getCatalogs: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
lang: req.query.lng,
|
||||
req: apiUtils.getRequestLogObject(req)
|
||||
}
|
||||
if (/[^a-z\-\*]/i.test(opts.lang)) {
|
||||
res.json({});
|
||||
return;
|
||||
}
|
||||
runtimeAPI.plugins.getPluginCatalogs(opts).then(function(result) {
|
||||
res.json(result);
|
||||
}).catch(function(err) {
|
||||
console.log(err.stack);
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
}
|
||||
};
|
||||
72
packages/node_modules/@node-red/editor-api/lib/admin/settings.js
vendored
Normal file
@@ -0,0 +1,72 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
var apiUtils = require("../util");
|
||||
var runtimeAPI;
|
||||
var settings;
|
||||
var theme = require("../editor/theme");
|
||||
var clone = require("clone");
|
||||
|
||||
var i18n = require("@node-red/util").i18n
|
||||
|
||||
function extend(target, source) {
|
||||
var keys = Object.keys(source);
|
||||
var i = keys.length;
|
||||
while(i--) {
|
||||
var value = source[keys[i]]
|
||||
var type = typeof value;
|
||||
if (type === 'string' || type === 'number' || type === 'boolean' || Array.isArray(value)) {
|
||||
target[keys[i]] = value;
|
||||
} else if (value === null) {
|
||||
if (target.hasOwnProperty(keys[i])) {
|
||||
delete target[keys[i]];
|
||||
}
|
||||
} else {
|
||||
// Object
|
||||
if (target.hasOwnProperty(keys[i])) {
|
||||
target[keys[i]] = extend(target[keys[i]],value);
|
||||
} else {
|
||||
target[keys[i]] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: function(_settings,_runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
settings = _settings;
|
||||
},
|
||||
runtimeSettings: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user
|
||||
}
|
||||
runtimeAPI.settings.getRuntimeSettings(opts).then(function(result) {
|
||||
if (!settings.disableEditor) {
|
||||
result.editorTheme = result.editorTheme||{};
|
||||
var themeSettings = theme.settings();
|
||||
if (themeSettings) {
|
||||
// result.editorTheme may already exist with the palette
|
||||
// disabled. Need to merge that into the receive settings
|
||||
result.editorTheme = extend(clone(themeSettings),result.editorTheme);
|
||||
}
|
||||
result.editorTheme.languages = i18n.availableLanguages("editor");
|
||||
}
|
||||
res.json(result);
|
||||
});
|
||||
},
|
||||
|
||||
}
|
||||
@@ -36,6 +36,7 @@ var log = require("@node-red/util").log; // TODO: separate module
|
||||
passport.use(strategies.bearerStrategy.BearerStrategy);
|
||||
passport.use(strategies.clientPasswordStrategy.ClientPasswordStrategy);
|
||||
passport.use(strategies.anonymousStrategy);
|
||||
passport.use(strategies.tokensStrategy);
|
||||
|
||||
var server = oauth2orize.createServer();
|
||||
|
||||
@@ -60,7 +61,7 @@ function init(_settings,storage) {
|
||||
function needsPermission(permission) {
|
||||
return function(req,res,next) {
|
||||
if (settings && settings.adminAuth) {
|
||||
return passport.authenticate(['bearer','anon'],{ session: false })(req,res,function() {
|
||||
return passport.authenticate(['bearer','tokens','anon'],{ session: false })(req,res,function() {
|
||||
if (!req.user) {
|
||||
return next();
|
||||
}
|
||||
@@ -100,7 +101,10 @@ function login(req,res) {
|
||||
}
|
||||
} else if (mergedAdminAuth.type === "strategy") {
|
||||
|
||||
var urlPrefix = (settings.httpAdminRoot==='/')?"":settings.httpAdminRoot;
|
||||
var urlPrefix = (settings.httpAdminRoot||"").replace(/\/$/,"");
|
||||
if (urlPrefix.length > 0) {
|
||||
urlPrefix += "/";
|
||||
}
|
||||
response = {
|
||||
"type":"strategy",
|
||||
"prompts":[{type:"button",label:mergedAdminAuth.strategy.label, url: urlPrefix + "auth/strategy"}]
|
||||
|
||||
@@ -123,9 +123,57 @@ AnonymousStrategy.prototype.authenticate = function(req) {
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function authenticateUserToken(req) {
|
||||
return new Promise( (resolve,reject) => {
|
||||
var token = null;
|
||||
var tokenHeader = Users.tokenHeader();
|
||||
if (Users.tokenHeader() === null) {
|
||||
// No custom user token provided. Fail the request
|
||||
reject();
|
||||
return;
|
||||
} else if (Users.tokenHeader() === 'authorization') {
|
||||
if (req.headers.authorization && req.headers.authorization.split(' ')[0] === 'Bearer') {
|
||||
token = req.headers.authorization.split(' ')[1];
|
||||
}
|
||||
} else {
|
||||
token = req.headers[Users.tokenHeader()];
|
||||
}
|
||||
if (token) {
|
||||
Users.tokens(token).then(function(user) {
|
||||
if (user) {
|
||||
resolve(user);
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
});
|
||||
} else {
|
||||
reject();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
function TokensStrategy() {
|
||||
passport.Strategy.call(this);
|
||||
this.name = 'tokens';
|
||||
}
|
||||
util.inherits(TokensStrategy, passport.Strategy);
|
||||
TokensStrategy.prototype.authenticate = function(req) {
|
||||
authenticateUserToken(req).then(user => {
|
||||
this.success(user,{scope:user.permissions});
|
||||
}).catch(err => {
|
||||
this.fail(401);
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
module.exports = {
|
||||
bearerStrategy: bearerStrategy,
|
||||
clientPasswordStrategy: clientPasswordStrategy,
|
||||
passwordTokenExchange: passwordTokenExchange,
|
||||
anonymousStrategy: new AnonymousStrategy()
|
||||
anonymousStrategy: new AnonymousStrategy(),
|
||||
tokensStrategy: new TokensStrategy(),
|
||||
authenticateUserToken: authenticateUserToken
|
||||
}
|
||||
|
||||
@@ -14,15 +14,7 @@
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
function generateToken(length) {
|
||||
var c = "ABCDEFGHIJKLMNOPQRSTUZWXYZabcdefghijklmnopqrstuvwxyz1234567890";
|
||||
var token = [];
|
||||
for (var i=0;i<length;i++) {
|
||||
token.push(c[Math.floor(Math.random()*c.length)]);
|
||||
}
|
||||
return token.join("");
|
||||
}
|
||||
|
||||
const crypto = require("crypto");
|
||||
|
||||
var storage;
|
||||
var sessionExpiryTime
|
||||
@@ -115,7 +107,7 @@ module.exports = {
|
||||
},
|
||||
create: function(user,client,scope) {
|
||||
return loadSessions().then(function() {
|
||||
var accessToken = generateToken(128);
|
||||
var accessToken = crypto.randomBytes(128).toString('base64');
|
||||
|
||||
var accessTokenExpiresAt = Date.now() + (sessionExpiryTime*1000);
|
||||
|
||||
|
||||
@@ -59,7 +59,9 @@ function getDefaultUser() {
|
||||
var api = {
|
||||
get: get,
|
||||
authenticate: authenticate,
|
||||
default: getDefaultUser
|
||||
default: getDefaultUser,
|
||||
tokens: getDefaultUser,
|
||||
tokenHeader: null
|
||||
}
|
||||
|
||||
function init(config) {
|
||||
@@ -105,6 +107,14 @@ function init(config) {
|
||||
} else {
|
||||
api.default = getDefaultUser;
|
||||
}
|
||||
if (config.tokens && typeof config.tokens === "function") {
|
||||
api.tokens = config.tokens;
|
||||
if (config.tokenHeader && typeof config.tokenHeader === "string") {
|
||||
api.tokenHeader = config.tokenHeader.toLowerCase();
|
||||
} else {
|
||||
api.tokenHeader = "authorization";
|
||||
}
|
||||
}
|
||||
}
|
||||
function cleanUser(user) {
|
||||
if (user && user.hasOwnProperty('password')) {
|
||||
@@ -118,5 +128,7 @@ module.exports = {
|
||||
init: init,
|
||||
get: function(username) { return api.get(username).then(cleanUser)},
|
||||
authenticate: function() { return api.authenticate.apply(null, arguments) },
|
||||
default: function() { return api.default(); }
|
||||
default: function() { return api.default(); },
|
||||
tokens: function(token) { return api.tokens(token); },
|
||||
tokenHeader: function() { return api.tokenHeader }
|
||||
};
|
||||
|
||||
@@ -16,11 +16,13 @@
|
||||
|
||||
var ws = require("ws");
|
||||
var url = require("url");
|
||||
const crypto = require("crypto");
|
||||
|
||||
var log = require("@node-red/util").log; // TODO: separate module
|
||||
var Tokens;
|
||||
var Users;
|
||||
var Permissions;
|
||||
var Strategies;
|
||||
|
||||
var server;
|
||||
var settings;
|
||||
@@ -31,8 +33,6 @@ var activeConnections = [];
|
||||
|
||||
var anonymousUser;
|
||||
|
||||
var retained = {};
|
||||
|
||||
var heartbeatTimer;
|
||||
var lastSentTime;
|
||||
|
||||
@@ -44,6 +44,7 @@ function init(_server,_settings,_runtimeAPI) {
|
||||
Tokens.onSessionExpiry(handleSessionExpiry);
|
||||
Users = require("../auth/users");
|
||||
Permissions = require("../auth/permissions");
|
||||
Strategies = require("../auth/strategies");
|
||||
|
||||
}
|
||||
function handleSessionExpiry(session) {
|
||||
@@ -54,26 +55,19 @@ function handleSessionExpiry(session) {
|
||||
}
|
||||
})
|
||||
}
|
||||
function generateSession(length) {
|
||||
var c = "ABCDEFGHIJKLMNOPQRSTUZWXYZabcdefghijklmnopqrstuvwxyz1234567890";
|
||||
var token = [];
|
||||
for (var i=0;i<length;i++) {
|
||||
token.push(c[Math.floor(Math.random()*c.length)]);
|
||||
}
|
||||
return token.join("");
|
||||
}
|
||||
|
||||
function CommsConnection(ws) {
|
||||
this.session = generateSession(32);
|
||||
function CommsConnection(ws, user) {
|
||||
this.session = crypto.randomBytes(32).toString('base64');
|
||||
this.ws = ws;
|
||||
this.stack = [];
|
||||
this.user = null;
|
||||
this.user = user;
|
||||
this.lastSentTime = 0;
|
||||
var self = this;
|
||||
|
||||
log.audit({event: "comms.open"});
|
||||
log.trace("comms.open "+self.session);
|
||||
var pendingAuth = (settings.adminAuth != null);
|
||||
var preAuthed = !!user;
|
||||
var pendingAuth = !this.user && (settings.adminAuth != null);
|
||||
|
||||
if (!pendingAuth) {
|
||||
addActiveConnection(self);
|
||||
@@ -129,11 +123,19 @@ function CommsConnection(ws) {
|
||||
completeConnection(null,null,false);
|
||||
}
|
||||
});
|
||||
} else {
|
||||
Users.tokens(msg.auth).then(function(user) {
|
||||
if (user) {
|
||||
self.user = user;
|
||||
log.audit({event: "comms.auth",user:self.user});
|
||||
completeConnection(user.permissions,msg.auth,true);
|
||||
} else {
|
||||
log.audit({event: "comms.auth.fail"});
|
||||
completeConnection(null,null,false);
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
} else {
|
||||
if (anonymousUser) {
|
||||
log.audit({event: "comms.auth",user:anonymousUser});
|
||||
@@ -191,8 +193,8 @@ function start() {
|
||||
var commsPath = settings.httpAdminRoot || "/";
|
||||
commsPath = (commsPath.slice(0,1) != "/" ? "/":"") + commsPath + (commsPath.slice(-1) == "/" ? "":"/") + "comms";
|
||||
wsServer = new ws.Server({ noServer: true });
|
||||
wsServer.on('connection',function(ws) {
|
||||
var commsConnection = new CommsConnection(ws);
|
||||
wsServer.on('connection',function(ws, request, user) {
|
||||
var commsConnection = new CommsConnection(ws, user);
|
||||
});
|
||||
wsServer.on('error', function(err) {
|
||||
log.warn(log._("comms.error-server",{message:err.toString()}));
|
||||
@@ -201,8 +203,26 @@ function start() {
|
||||
server.on('upgrade', function upgrade(request, socket, head) {
|
||||
const pathname = url.parse(request.url).pathname;
|
||||
if (pathname === commsPath) {
|
||||
if (Users.tokenHeader() !== null && request.headers[Users.tokenHeader()]) {
|
||||
// The user has provided custom token handling. For the websocket,
|
||||
// the token could be provided in two ways:
|
||||
// - as an http header (only possible with a reverse proxy setup)
|
||||
// - passed over the connected websock in an auth packet
|
||||
// If the header is present, verify the token. If not, use the auth
|
||||
// packet over the connected socket
|
||||
//
|
||||
Strategies.authenticateUserToken(request).then(user => {
|
||||
wsServer.handleUpgrade(request, socket, head, function done(ws) {
|
||||
wsServer.emit('connection', ws, request);
|
||||
wsServer.emit('connection', ws, request, user);
|
||||
});
|
||||
}).catch(err => {
|
||||
log.audit({event: "comms.auth.fail"});
|
||||
socket.destroy();
|
||||
})
|
||||
return
|
||||
}
|
||||
wsServer.handleUpgrade(request, socket, head, function done(ws) {
|
||||
wsServer.emit('connection', ws, request, null);
|
||||
});
|
||||
}
|
||||
// Don't destroy the socket as other listeners may want to handle the
|
||||
|
||||
@@ -76,7 +76,7 @@ module.exports = {
|
||||
editorApp.get("/icons/:scope/:module/:icon",ui.icon);
|
||||
|
||||
var theme = require("./theme");
|
||||
theme.init(settings);
|
||||
theme.init(settings, runtimeAPI);
|
||||
editorApp.use("/theme",theme.app());
|
||||
editorApp.use("/",ui.editorResources);
|
||||
|
||||
@@ -88,13 +88,14 @@ module.exports = {
|
||||
// Locales
|
||||
var locales = require("./locales");
|
||||
locales.init(runtimeAPI);
|
||||
editorApp.get(/locales\/(.+)\/?$/,locales.get,apiUtil.errorHandler);
|
||||
editorApp.get(/^\/locales\/(.+)\/?$/,locales.get,apiUtil.errorHandler);
|
||||
|
||||
// Library
|
||||
var library = require("./library");
|
||||
library.init(runtimeAPI);
|
||||
editorApp.get(/library\/([^\/]+)\/([^\/]+)(?:$|\/(.*))/,needsPermission("library.read"),library.getEntry);
|
||||
editorApp.post(/library\/([^\/]+)\/([^\/]+)\/(.*)/,needsPermission("library.write"),library.saveEntry);
|
||||
// editorApp.get("/library/:id",needsPermission("library.read"),library.getLibraryConfig);
|
||||
editorApp.get(/^\/library\/([^\/]+)\/([^\/]+)(?:$|\/(.*))/,needsPermission("library.read"),library.getEntry);
|
||||
editorApp.post(/^\/library\/([^\/]+)\/([^\/]+)\/(.*)/,needsPermission("library.write"),library.saveEntry);
|
||||
|
||||
|
||||
// Credentials
|
||||
@@ -103,7 +104,7 @@ module.exports = {
|
||||
editorApp.get('/credentials/:type/:id', needsPermission("credentials.read"),credentials.get,apiUtil.errorHandler);
|
||||
|
||||
// Settings
|
||||
editorApp.get("/settings",needsPermission("settings.read"),info.runtimeSettings,apiUtil.errorHandler);
|
||||
// Main /settings route is an admin route - see lib/admin/settings.js
|
||||
// User Settings
|
||||
editorApp.get("/settings/user",needsPermission("settings.read"),info.userSettings,apiUtil.errorHandler);
|
||||
// User Settings
|
||||
|
||||
@@ -17,7 +17,6 @@
|
||||
var apiUtils = require("../util");
|
||||
var fs = require('fs');
|
||||
var fspath = require('path');
|
||||
var when = require('when');
|
||||
|
||||
var runtimeAPI;
|
||||
|
||||
@@ -25,6 +24,17 @@ module.exports = {
|
||||
init: function(_runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
},
|
||||
// getLibraryConfig: function(req,res) {
|
||||
// var opts = {
|
||||
// user: req.user,
|
||||
// library: req.params.id
|
||||
// }
|
||||
// runtimeAPI.library.getConfig(opts).then(function(result) {
|
||||
// res.json(result);
|
||||
// }).catch(function(err) {
|
||||
// apiUtils.rejectHandler(req,res,err);
|
||||
// });
|
||||
// },
|
||||
getEntry: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user,
|
||||
|
||||
@@ -39,9 +39,12 @@ module.exports = {
|
||||
},
|
||||
get: function(req,res) {
|
||||
var namespace = req.params[0];
|
||||
var lngs = req.query.lng;
|
||||
namespace = namespace.replace(/\.json$/,"");
|
||||
var lang = req.query.lng; //apiUtil.determineLangFromHeaders(req.acceptsLanguages() || []);
|
||||
var lang = req.query.lng || i18n.defaultLang; //apiUtil.determineLangFromHeaders(req.acceptsLanguages() || []);
|
||||
if (/[^0-9a-z=\-\*]/i.test(lang)) {
|
||||
res.json({});
|
||||
return;
|
||||
}
|
||||
var prevLang = i18n.i.language;
|
||||
// Trigger a load from disk of the language if it is not the default
|
||||
i18n.i.changeLanguage(lang, function(){
|
||||
|
||||
@@ -137,6 +137,7 @@ module.exports = {
|
||||
req.body.hasOwnProperty('description') ||
|
||||
req.body.hasOwnProperty('dependencies')||
|
||||
req.body.hasOwnProperty('summary') ||
|
||||
req.body.hasOwnProperty('version') ||
|
||||
req.body.hasOwnProperty('files') ||
|
||||
req.body.hasOwnProperty('git')) {
|
||||
runtimeAPI.projects.updateProject(opts).then(function() {
|
||||
|
||||
@@ -16,56 +16,12 @@
|
||||
var apiUtils = require("../util");
|
||||
var runtimeAPI;
|
||||
var sshkeys = require("./sshkeys");
|
||||
var theme = require("./theme");
|
||||
var clone = require("clone");
|
||||
|
||||
var i18n = require("@node-red/util").i18n
|
||||
|
||||
function extend(target, source) {
|
||||
var keys = Object.keys(source);
|
||||
var i = keys.length;
|
||||
while(i--) {
|
||||
var value = source[keys[i]]
|
||||
var type = typeof value;
|
||||
if (type === 'string' || type === 'number' || type === 'boolean' || Array.isArray(value)) {
|
||||
target[keys[i]] = value;
|
||||
} else if (value === null) {
|
||||
if (target.hasOwnProperty(keys[i])) {
|
||||
delete target[keys[i]];
|
||||
}
|
||||
} else {
|
||||
// Object
|
||||
if (target.hasOwnProperty(keys[i])) {
|
||||
target[keys[i]] = extend(target[keys[i]],value);
|
||||
} else {
|
||||
target[keys[i]] = value;
|
||||
}
|
||||
}
|
||||
}
|
||||
return target;
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: function(_runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
sshkeys.init(runtimeAPI);
|
||||
},
|
||||
runtimeSettings: function(req,res) {
|
||||
var opts = {
|
||||
user: req.user
|
||||
}
|
||||
runtimeAPI.settings.getRuntimeSettings(opts).then(function(result) {
|
||||
result.editorTheme = result.editorTheme||{};
|
||||
var themeSettings = theme.settings();
|
||||
if (themeSettings) {
|
||||
// result.editorTheme may already exist with the palette
|
||||
// disabled. Need to merge that into the receive settings
|
||||
result.editorTheme = extend(clone(themeSettings),result.editorTheme);
|
||||
}
|
||||
result.editorTheme.languages = i18n.availableLanguages("editor");
|
||||
res.json(result);
|
||||
});
|
||||
},
|
||||
userSettings: function(req, res) {
|
||||
var opts = {
|
||||
user: req.user
|
||||
|
||||
@@ -41,6 +41,10 @@ var theme = null;
|
||||
var themeContext = clone(defaultContext);
|
||||
var themeSettings = null;
|
||||
|
||||
var activeTheme = null;
|
||||
var activeThemeInitialised = false;
|
||||
|
||||
var runtimeAPI;
|
||||
var themeApp;
|
||||
|
||||
function serveFile(app,baseUrl,file) {
|
||||
@@ -58,7 +62,7 @@ function serveFile(app,baseUrl,file) {
|
||||
}
|
||||
}
|
||||
|
||||
function serveFilesFromTheme(themeValue, themeApp, directory) {
|
||||
function serveFilesFromTheme(themeValue, themeApp, directory, baseDirectory) {
|
||||
var result = [];
|
||||
if (themeValue) {
|
||||
var array = themeValue;
|
||||
@@ -67,7 +71,14 @@ function serveFilesFromTheme(themeValue, themeApp, directory) {
|
||||
}
|
||||
|
||||
for (var i=0;i<array.length;i++) {
|
||||
var url = serveFile(themeApp,directory,array[i]);
|
||||
let fullPath = array[i];
|
||||
if (baseDirectory) {
|
||||
fullPath = path.resolve(baseDirectory,array[i]);
|
||||
if (fullPath.indexOf(baseDirectory) !== 0) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
var url = serveFile(themeApp,directory,fullPath);
|
||||
if (url) {
|
||||
result.push(url);
|
||||
}
|
||||
@@ -77,10 +88,12 @@ function serveFilesFromTheme(themeValue, themeApp, directory) {
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
init: function(settings) {
|
||||
init: function(settings, _runtimeAPI) {
|
||||
runtimeAPI = _runtimeAPI;
|
||||
themeContext = clone(defaultContext);
|
||||
themeSettings = null;
|
||||
theme = settings.editorTheme || {};
|
||||
activeTheme = theme.theme;
|
||||
},
|
||||
|
||||
app: function() {
|
||||
@@ -169,7 +182,9 @@ module.exports = {
|
||||
}
|
||||
}
|
||||
}
|
||||
themeApp.get("/", function(req,res) {
|
||||
themeApp.get("/", async function(req,res) {
|
||||
const themePluginList = await runtimeAPI.plugins.getPluginsByType({type:"node-red-theme"});
|
||||
themeContext.themes = themePluginList.map(theme => theme.id);
|
||||
res.json(themeContext);
|
||||
})
|
||||
|
||||
@@ -185,10 +200,42 @@ module.exports = {
|
||||
themeSettings.projects = theme.projects;
|
||||
}
|
||||
|
||||
if (theme.hasOwnProperty("keymap")) {
|
||||
themeSettings.keymap = theme.keymap;
|
||||
}
|
||||
|
||||
if (theme.theme) {
|
||||
themeSettings.theme = theme.theme;
|
||||
}
|
||||
return themeApp;
|
||||
},
|
||||
context: function() {
|
||||
context: async function() {
|
||||
if (activeTheme && !activeThemeInitialised) {
|
||||
const themePlugin = await runtimeAPI.plugins.getPlugin({
|
||||
id:activeTheme
|
||||
});
|
||||
if (themePlugin) {
|
||||
if (themePlugin.css) {
|
||||
const cssFiles = serveFilesFromTheme(
|
||||
themePlugin.css,
|
||||
themeApp,
|
||||
"/css/",
|
||||
themePlugin.path
|
||||
);
|
||||
themeContext.page.css = cssFiles.concat(themeContext.page.css || [])
|
||||
}
|
||||
if (themePlugin.scripts) {
|
||||
const scriptFiles = serveFilesFromTheme(
|
||||
themePlugin.scripts,
|
||||
themeApp,
|
||||
"/scripts/",
|
||||
themePlugin.path
|
||||
)
|
||||
themeContext.page.scripts = scriptFiles.concat(themeContext.page.scripts || [])
|
||||
}
|
||||
}
|
||||
activeThemeInitialised = true;
|
||||
}
|
||||
return themeContext;
|
||||
},
|
||||
settings: function() {
|
||||
|
||||
@@ -68,8 +68,8 @@ module.exports = {
|
||||
apiUtils.rejectHandler(req,res,err);
|
||||
})
|
||||
},
|
||||
editor: function(req,res) {
|
||||
res.send(Mustache.render(editorTemplate,theme.context()));
|
||||
editor: async function(req,res) {
|
||||
res.send(Mustache.render(editorTemplate,await theme.context()));
|
||||
},
|
||||
editorResources: express.static(path.join(editorClientDir,'public'))
|
||||
};
|
||||
|
||||
@@ -28,7 +28,6 @@ var express = require("express");
|
||||
var bodyParser = require("body-parser");
|
||||
var util = require('util');
|
||||
var passport = require('passport');
|
||||
var when = require('when');
|
||||
var cors = require('cors');
|
||||
|
||||
var auth = require("./auth");
|
||||
@@ -42,7 +41,7 @@ var editor;
|
||||
/**
|
||||
* Initialise the module.
|
||||
* @param {Object} settings The runtime settings
|
||||
* @param {HTTPServer} server An instance of HTTP Server
|
||||
* @param {HTTPServer} _server An instance of HTTP Server
|
||||
* @param {Storage} storage An instance of Node-RED Storage
|
||||
* @param {Runtime} runtimeAPI An instance of Node-RED Runtime
|
||||
* @memberof @node-red/editor-api
|
||||
@@ -59,6 +58,12 @@ function init(settings,_server,storage,runtimeAPI) {
|
||||
});
|
||||
adminApp.use(corsHandler);
|
||||
|
||||
if (settings.httpAdminMiddleware) {
|
||||
if (typeof settings.httpAdminMiddleware === "function" || Array.isArray(settings.httpAdminMiddleware)) {
|
||||
adminApp.use(settings.httpAdminMiddleware);
|
||||
}
|
||||
}
|
||||
|
||||
auth.init(settings,storage);
|
||||
|
||||
var maxApiRequestSize = settings.apiMaxLength || '5mb';
|
||||
@@ -93,7 +98,7 @@ function init(settings,_server,storage,runtimeAPI) {
|
||||
adminApp.use(corsHandler);
|
||||
}
|
||||
|
||||
var adminApiApp = require("./admin").init(runtimeAPI);
|
||||
var adminApiApp = require("./admin").init(settings, runtimeAPI);
|
||||
adminApp.use(adminApiApp);
|
||||
} else {
|
||||
adminApp = null;
|
||||
@@ -105,11 +110,9 @@ function init(settings,_server,storage,runtimeAPI) {
|
||||
* @return {Promise} resolves when the application is ready to handle requests
|
||||
* @memberof @node-red/editor-api
|
||||
*/
|
||||
function start() {
|
||||
async function start() {
|
||||
if (editor) {
|
||||
return editor.start();
|
||||
} else {
|
||||
return when.resolve();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -118,11 +121,10 @@ function start() {
|
||||
* @return {Promise} resolves when the application is stopped
|
||||
* @memberof @node-red/editor-api
|
||||
*/
|
||||
function stop() {
|
||||
async function stop() {
|
||||
if (editor) {
|
||||
editor.stop();
|
||||
}
|
||||
return when.resolve();
|
||||
}
|
||||
module.exports = {
|
||||
init: init,
|
||||
|
||||
@@ -43,10 +43,20 @@ module.exports = {
|
||||
rejectHandler: function(req,res,err) {
|
||||
//TODO: why this when errorHandler also?!
|
||||
log.audit({event: "api.error",error:err.code||"unexpected_error",message:err.message||err.toString()},req);
|
||||
res.status(err.status||400).json({
|
||||
if (!err.code) {
|
||||
// by definition, an unexpected_error to log
|
||||
log.error(err);
|
||||
}
|
||||
var response = {
|
||||
code: err.code||"unexpected_error",
|
||||
message: err.message||err.toString()
|
||||
});
|
||||
};
|
||||
// Handle auth failures on a specific remote
|
||||
// TODO: don't hardcode this here - allow users of rejectHandler to identify extra props to send
|
||||
if (err.remote) {
|
||||
response.remote = err.remote;
|
||||
}
|
||||
res.status(err.status||400).json(response);
|
||||
},
|
||||
getRequestLogObject: function(req) {
|
||||
return {
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/editor-api",
|
||||
"version": "1.0.0-beta.4",
|
||||
"version": "1.3.0-beta.1",
|
||||
"license": "Apache-2.0",
|
||||
"main": "./lib/index.js",
|
||||
"repository": {
|
||||
@@ -16,22 +16,22 @@
|
||||
}
|
||||
],
|
||||
"dependencies": {
|
||||
"@node-red/util": "1.0.0-beta.4",
|
||||
"@node-red/editor-client": "1.0.0-beta.4",
|
||||
"@node-red/util": "1.3.0-beta.1",
|
||||
"@node-red/editor-client": "1.3.0-beta.1",
|
||||
"bcryptjs": "2.4.3",
|
||||
"body-parser": "1.19.0",
|
||||
"clone": "2.1.2",
|
||||
"cors": "2.8.5",
|
||||
"express-session": "1.16.2",
|
||||
"express-session": "1.17.1",
|
||||
"express": "4.17.1",
|
||||
"memorystore": "1.6.1",
|
||||
"mime": "2.4.4",
|
||||
"mustache": "3.0.2",
|
||||
"memorystore": "1.6.4",
|
||||
"mime": "2.4.7",
|
||||
"multer": "1.4.2",
|
||||
"mustache": "4.1.0",
|
||||
"oauth2orize": "1.11.0",
|
||||
"passport-http-bearer": "1.0.1",
|
||||
"passport-oauth2-client-password": "0.1.2",
|
||||
"passport": "0.4.0",
|
||||
"when": "3.7.8",
|
||||
"passport": "0.4.1",
|
||||
"ws": "6.2.1"
|
||||
},
|
||||
"optionalDependencies": {
|
||||
|
||||
@@ -32,13 +32,13 @@
|
||||
"label" : {
|
||||
"view" : {
|
||||
"view" : "Ansicht",
|
||||
"grid" : "Gitter",
|
||||
"grid" : "Raster",
|
||||
"showGrid" : "Raster anzeigen",
|
||||
"snapGrid" : "Einrasten am Raster",
|
||||
"snapGrid" : "Am Raster ausrichten",
|
||||
"gridSize" : "Rastergröße",
|
||||
"textDir" : "Textrichtung",
|
||||
"defaultDir" : "Standard",
|
||||
"ltr" : "Links-nach-rechts",
|
||||
"ltr" : "Von links nach rechts",
|
||||
"rtl" : "Von rechts nach links",
|
||||
"auto" : "Kontextuell"
|
||||
},
|
||||
@@ -53,15 +53,15 @@
|
||||
"import" : "Import",
|
||||
"export" : "Exportieren",
|
||||
"search" : "Flows durchsuchen",
|
||||
"searchInput" : "durchsuchen Sie Ihre Flows",
|
||||
"searchInput" : "Flows durchsuchen",
|
||||
"subflows" : "Subflow",
|
||||
"createSubflow" : "Subflow erstellen",
|
||||
"selectionToSubflow" : "Auswahl für Subflow",
|
||||
"selectionToSubflow" : "Auswahl zu Subflow",
|
||||
"flows" : "Flows",
|
||||
"add" : "Hinzufügen",
|
||||
"rename" : "Umbenennen",
|
||||
"delete" : "Löschen",
|
||||
"keyboardShortcuts" : "Tastaturkurzbefehle",
|
||||
"keyboardShortcuts" : "Tastenkürzel",
|
||||
"login" : "Anmelden",
|
||||
"logout" : "Abmelden",
|
||||
"editPalette" : "Palette verwalten",
|
||||
@@ -217,7 +217,7 @@
|
||||
"remote" : "Ferne Änderungen",
|
||||
"reviewChanges" : "Änderungen prüfen",
|
||||
"noBinaryFileShowed" : "Der Inhalt der Binärdatei kann nicht angezeigt",
|
||||
"viewCommitDiff" : "Änderungen festschreiben",
|
||||
"viewCommitDiff" : "Änderungen committen",
|
||||
"compareChanges" : "Änderungen vergleichen",
|
||||
"saveConflict" : "Konfliktlösung speichern",
|
||||
"conflictHeader" : "<span> __resolved__ </span> von <span> __unresolved__ </span> -Konflikten behoben",
|
||||
@@ -226,8 +226,8 @@
|
||||
"newVersionError" : "Neue Version enthält keine gültige JSON-Datei:"
|
||||
},
|
||||
"subflow" : {
|
||||
"editSubflow" : "Flowschablone bearbeiten: __name__",
|
||||
"edit" : "Flowsschablone bearbeiten",
|
||||
"editSubflow" : "Subflow bearbeiten: __name__",
|
||||
"edit" : "Subflow bearbeiten",
|
||||
"subflowInstances" : "Es ist __count__ Instanz dieser Subflow-Vorlage vorhanden.",
|
||||
"subflowInstances_plural" : "Es gibt __count__ Instanzen dieser Subflow-Vorlage.",
|
||||
"editSubflowProperties" : "Eigenschaften bearbeiten",
|
||||
@@ -266,7 +266,7 @@
|
||||
}
|
||||
},
|
||||
"keyboard" : {
|
||||
"title" : "Tastaturkurzbefehle",
|
||||
"title" : "Tastenkürzel",
|
||||
"keyboard" : "Tastatur",
|
||||
"filterActions" : "Filteraktionen",
|
||||
"shortcut" : "Direktaufruf",
|
||||
@@ -283,7 +283,7 @@
|
||||
"exportNode" : "Node exportieren",
|
||||
"nudgeNode" : "Ausgewählte Nodes verschieben (1px)",
|
||||
"moveNode" : "Ausgewählte Nodes verschieben (20px)",
|
||||
"toggleSidebar" : "Seitenleiste ein-/ausschalten",
|
||||
"toggleSidebar" : "Seitenleiste ein-/ausblenden",
|
||||
"copyNode" : "Ausgewählte Nodes kopieren",
|
||||
"cutNode" : "Ausgewählte Nodes ausschneiden",
|
||||
"pasteNode" : "Node einfügen",
|
||||
@@ -308,7 +308,7 @@
|
||||
},
|
||||
"palette" : {
|
||||
"noInfo" : "Keine Informationen verfügbar",
|
||||
"filter" : "Filter Nodes",
|
||||
"filter" : "Nodes filtern",
|
||||
"search" : "Suchmodule",
|
||||
"addCategory" : "Neu hinzufügen ...",
|
||||
"label" : {
|
||||
@@ -366,11 +366,11 @@
|
||||
"remove" : "entfernen",
|
||||
"update" : "Update auf __version__",
|
||||
"updated" : "aktualisiert",
|
||||
"install" : "installieren",
|
||||
"installed" : "installiert",
|
||||
"install" : "Installieren",
|
||||
"installed" : "Installiert",
|
||||
"loading" : "Kataloge werden geladen ...",
|
||||
"tab-nodes" : "Nodes",
|
||||
"tab-install" : "installieren",
|
||||
"tab-install" : "Installieren",
|
||||
"sort" : "Sortierung:",
|
||||
"sortAZ" : "a-z",
|
||||
"sortRecent" : "kürzlich",
|
||||
@@ -444,15 +444,15 @@
|
||||
"none" : "keine",
|
||||
"subflows" : "Subflows",
|
||||
"flows" : "Flows",
|
||||
"filterUnused" : "Nicht verwendet",
|
||||
"filterAll" : "alle",
|
||||
"filterUnused" : "Nicht verwendet",
|
||||
"filtered" : "__count__ verdeckt"
|
||||
},
|
||||
"context" : {
|
||||
"name" : "Kontextdaten",
|
||||
"label" : "Kontext",
|
||||
"none" : "keine ausgewählt",
|
||||
"refresh" : "Aktualisierung zum Laden",
|
||||
"refresh" : "Zum Aktualisieren neu laden",
|
||||
"empty" : "leer",
|
||||
"node" : "Node",
|
||||
"flow" : "Flow",
|
||||
@@ -477,7 +477,7 @@
|
||||
"none" : "Keine",
|
||||
"install" : "installieren",
|
||||
"removeFromProject" : "Aus Projekt entfernen",
|
||||
"addToProject" : "zu Projekt hinzufügen",
|
||||
"addToProject" : "Zu Projekt hinzufügen",
|
||||
"files" : "Dateien",
|
||||
"flow" : "Flow",
|
||||
"credentials" : "Berechtigungsnachweis",
|
||||
@@ -510,7 +510,7 @@
|
||||
},
|
||||
"userSettings" : {
|
||||
"committerDetail" : "Committer-Details",
|
||||
"committerTip" : "Leer Wert für Systemstandardwert belassen",
|
||||
"committerTip" : "Leer lassen für Systemstandard",
|
||||
"userName" : "Benutzername",
|
||||
"email" : "E-Mail",
|
||||
"sshKeys" : "SSH-Schlüssel",
|
||||
@@ -544,7 +544,7 @@
|
||||
"revertChanges" : "Änderungen zurücksetzen",
|
||||
"localChanges" : "Lokale Änderungen",
|
||||
"none" : "Keine",
|
||||
"conflictResolve" : "Alle Konflikte wurden aufgelöst. Festschreiben der Änderungen, um den Mischvorgang abzuschließen.",
|
||||
"conflictResolve" : "Alle Konflikte wurden aufgelöst. Committe die Änderungen, um den Merge Request abzuschließen.",
|
||||
"localFiles" : "Lokale Dateien",
|
||||
"all" : "alle",
|
||||
"unmergedChanges" : "Nicht zusammengeführte Änderungen",
|
||||
|
||||
@@ -14,9 +14,38 @@
|
||||
"back": "Back",
|
||||
"next": "Next",
|
||||
"clone": "Clone project",
|
||||
"cont": "Continue"
|
||||
"cont": "Continue",
|
||||
"style": "Style",
|
||||
"line": "Outline",
|
||||
"fill": "Fill",
|
||||
"label": "Label",
|
||||
"color": "Color",
|
||||
"position": "Position",
|
||||
"enable": "Enable",
|
||||
"disable": "Disable",
|
||||
"upload": "Upload"
|
||||
},
|
||||
"type": {
|
||||
"string": "string",
|
||||
"number": "number",
|
||||
"boolean": "boolean",
|
||||
"array": "array",
|
||||
"buffer": "buffer",
|
||||
"object": "object",
|
||||
"jsonString": "JSON string",
|
||||
"undefined": "undefined",
|
||||
"null": "null"
|
||||
}
|
||||
},
|
||||
"event": {
|
||||
"loadPlugins": "Loading Plugins",
|
||||
"loadPalette": "Loading Palette",
|
||||
"loadNodeCatalogs": "Loading Node catalogs",
|
||||
"loadNodes": "Loading Nodes __count__",
|
||||
"loadFlows": "Loading Flows",
|
||||
"importFlows": "Adding Flows to workspace",
|
||||
"importError": "<p>Error adding flows</p><p>__message__</p>"
|
||||
},
|
||||
"workspace": {
|
||||
"defaultName": "Flow __number__",
|
||||
"editFlow": "Edit flow: __name__",
|
||||
@@ -80,7 +109,12 @@
|
||||
"projects-new": "New",
|
||||
"projects-open": "Open",
|
||||
"projects-settings": "Project Settings",
|
||||
"showNodeLabelDefault": "Show label of newly added nodes"
|
||||
"showNodeLabelDefault": "Show label of newly added nodes",
|
||||
"groups": "Groups",
|
||||
"groupSelection": "Group selection",
|
||||
"ungroupSelection": "Ungroup selection",
|
||||
"groupMergeSelection": "Merge selection",
|
||||
"groupRemoveSelection": "Remove from group"
|
||||
}
|
||||
},
|
||||
"actions": {
|
||||
@@ -109,6 +143,7 @@
|
||||
"nodeActionDisabled": "node actions disabled",
|
||||
"nodeActionDisabledSubflow": "node actions disabled within subflow",
|
||||
"missing-types": "<p>Flows stopped due to missing node types.</p>",
|
||||
"missing-modules": "<p>Flows stopped due to missing modules.</p>",
|
||||
"safe-mode":"<p>Flows stopped in safe mode.</p><p>You can modify your flows and deploy the changes to restart.</p>",
|
||||
"restartRequired": "Node-RED must be restarted to enable upgraded modules",
|
||||
"credentials_load_failed": "<p>Flows stopped as the credentials could not be decrypted.</p><p>The flow credential file is encrypted, but the project's encryption key is missing or invalid.</p>",
|
||||
@@ -160,10 +195,14 @@
|
||||
"node_plural": "__count__ nodes",
|
||||
"configNode": "__count__ configuration node",
|
||||
"configNode_plural": "__count__ configuration nodes",
|
||||
"group": "__count__ group",
|
||||
"group_plural": "__count__ groups",
|
||||
"flow": "__count__ flow",
|
||||
"flow_plural": "__count__ flows",
|
||||
"subflow": "__count__ subflow",
|
||||
"subflow_plural": "__count__ subflows",
|
||||
"replacedNodes": "__count__ node replaced",
|
||||
"replacedNodes_plural": "__count__ nodes replaced",
|
||||
"pasteNodes": "Paste flow json or",
|
||||
"selectFile": "select a file to import",
|
||||
"importNodes": "Import nodes",
|
||||
@@ -171,11 +210,19 @@
|
||||
"download": "Download",
|
||||
"importUnrecognised": "Imported unrecognised type:",
|
||||
"importUnrecognised_plural": "Imported unrecognised types:",
|
||||
"importDuplicate": "Imported duplicate node:",
|
||||
"importDuplicate_plural": "Imported duplicate nodes:",
|
||||
"nodesExported": "Nodes exported to clipboard",
|
||||
"nodesImported": "Imported:",
|
||||
"nodeCopied": "__count__ node copied",
|
||||
"nodeCopied_plural": "__count__ nodes copied",
|
||||
"groupCopied": "__count__ group copied",
|
||||
"groupCopied_plural": "__count__ groups copied",
|
||||
"groupStyleCopied": "Group style copied",
|
||||
"invalidFlow": "Invalid flow: __message__",
|
||||
"recoveredNodes": "Recovered Nodes",
|
||||
"recoveredNodesInfo": "The nodes on this flow were missing a valid flow id when they were imported. They have been added to this flow so you can either restore or delete them.",
|
||||
"recoveredNodesNotification": "<p>Imported nodes without a valid flow id</p><p>They have been added to a new flow called '__flowName__'.</p>",
|
||||
"export": {
|
||||
"selected":"selected nodes",
|
||||
"current":"current flow",
|
||||
@@ -190,13 +237,19 @@
|
||||
},
|
||||
"import": {
|
||||
"import": "Import to",
|
||||
"importSelected": "Import selected",
|
||||
"importCopy": "Import copy",
|
||||
"viewNodes": "View nodes...",
|
||||
"newFlow": "new flow",
|
||||
"replace": "replace",
|
||||
"errors": {
|
||||
"notArray": "Input not a JSON Array",
|
||||
"itemNotObject": "Input not a valid flow - item __index__ not a node object",
|
||||
"missingId": "Input not a valid flow - item __index__ missing 'id' property",
|
||||
"missingType": "Input not a valid flow - item __index__ missing 'type' property"
|
||||
}
|
||||
},
|
||||
"conflictNotification1": "Some of the nodes you are importing already exist in your workspace.",
|
||||
"conflictNotification2": "Select which nodes to import and whether to replace the existing nodes, or to import a copy of them."
|
||||
},
|
||||
"copyMessagePath": "Path copied",
|
||||
"copyMessageValue": "Value copied",
|
||||
@@ -286,8 +339,21 @@
|
||||
"output": "outputs:",
|
||||
"status": "status node",
|
||||
"deleteSubflow": "delete subflow",
|
||||
"confirmDelete": "Are you sure you want to delete this subflow?",
|
||||
"info": "Description",
|
||||
"category": "Category",
|
||||
"module": "Module",
|
||||
"license": "License",
|
||||
"licenseNone": "none",
|
||||
"licenseOther": "Other",
|
||||
"type": "Node Type",
|
||||
"version": "Version",
|
||||
"versionPlaceholder": "x.y.z",
|
||||
"keys": "Keywords",
|
||||
"keysPlaceholder": "Comma-separated keywords",
|
||||
"author": "Author",
|
||||
"authorPlaceholder": "Your Name <email@example.com>",
|
||||
"desc": "Description",
|
||||
"env": {
|
||||
"restore": "Restore to subflow default",
|
||||
"remove": "Remove environment variable"
|
||||
@@ -297,6 +363,13 @@
|
||||
"multipleInputsToSelection": "<strong>Cannot create subflow</strong>: multiple inputs to selection"
|
||||
}
|
||||
},
|
||||
"group": {
|
||||
"editGroup": "Edit group: __name__",
|
||||
"errors": {
|
||||
"cannotCreateDiffGroups": "Cannot create group using nodes from different groups",
|
||||
"cannotAddSubflowPorts": "Cannot add subflow ports to a group"
|
||||
}
|
||||
},
|
||||
"editor": {
|
||||
"configEdit": "Edit",
|
||||
"configAdd": "Add",
|
||||
@@ -315,6 +388,7 @@
|
||||
"labelInputs": "Inputs",
|
||||
"labelOutputs": "Outputs",
|
||||
"settingIcon": "Icon",
|
||||
"default": "default",
|
||||
"noDefaultLabel": "none",
|
||||
"defaultLabel": "use default label",
|
||||
"searchIcons": "Search icons",
|
||||
@@ -325,6 +399,8 @@
|
||||
"locale": "Select UI Language",
|
||||
"icon": "Icon",
|
||||
"inputType": "Input type",
|
||||
"selectType": "select types...",
|
||||
"loadCredentials": "Loading node credentials",
|
||||
"inputs" : {
|
||||
"input": "input",
|
||||
"select": "select",
|
||||
@@ -339,7 +415,8 @@
|
||||
"bool": "bool",
|
||||
"json": "JSON",
|
||||
"bin": "buffer",
|
||||
"env": "env variable"
|
||||
"env": "env variable",
|
||||
"cred": "credential"
|
||||
},
|
||||
"menu": {
|
||||
"input": "input",
|
||||
@@ -358,7 +435,8 @@
|
||||
},
|
||||
"errors": {
|
||||
"scopeChange": "Changing the scope will make it unavailable to nodes in other flows that use it",
|
||||
"invalidProperties": "Invalid properties:"
|
||||
"invalidProperties": "Invalid properties:",
|
||||
"credentialLoadFailed": "Failed to load node credentials"
|
||||
}
|
||||
},
|
||||
"keyboard": {
|
||||
@@ -486,6 +564,8 @@
|
||||
"sortAZ": "a-z",
|
||||
"sortRecent": "recent",
|
||||
"more": "+ __count__ more",
|
||||
"upload": "Upload module tgz file",
|
||||
"refresh": "Refresh module list",
|
||||
"errors": {
|
||||
"catalogLoadFailed": "<p>Failed to load node catalogue.</p><p>Check the browser console for more information</p>",
|
||||
"installFailed": "<p>Failed to install: __module__</p><p>__message__</p><p>Check the log for more information</p>",
|
||||
@@ -521,11 +601,12 @@
|
||||
},
|
||||
"sidebar": {
|
||||
"info": {
|
||||
"name": "Node information",
|
||||
"name": "Information",
|
||||
"tabName": "Name",
|
||||
"label": "info",
|
||||
"node": "Node",
|
||||
"type": "Type",
|
||||
"group": "Group",
|
||||
"module": "Module",
|
||||
"id": "ID",
|
||||
"status": "Status",
|
||||
@@ -548,7 +629,29 @@
|
||||
"nodeHelp": "Node Help",
|
||||
"none":"None",
|
||||
"arrayItems": "__count__ items",
|
||||
"showTips":"You can open the tips from the settings panel"
|
||||
"showTips":"You can open the tips from the settings panel",
|
||||
"outline": "Outline",
|
||||
"empty": "empty",
|
||||
"globalConfig": "Global Configuration Nodes",
|
||||
"triggerAction": "Trigger action",
|
||||
"find": "Find in workspace",
|
||||
"search": {
|
||||
"configNodes": "Configuration nodes",
|
||||
"unusedConfigNodes": "Unused configuration nodes",
|
||||
"invalidNodes": "Invalid nodes",
|
||||
"uknownNodes": "Unknown nodes",
|
||||
"unusedSubflows": "Unused subflows"
|
||||
}
|
||||
},
|
||||
"help": {
|
||||
"name": "Help",
|
||||
"label": "help",
|
||||
"search": "Search help",
|
||||
"nodeHelp": "Node Help",
|
||||
"showHelp": "Show help",
|
||||
"showInOutline": "Show in outline",
|
||||
"showTopics": "Show topics",
|
||||
"noHelp": "No help topic selected"
|
||||
},
|
||||
"config": {
|
||||
"name": "Configuration nodes",
|
||||
@@ -557,8 +660,10 @@
|
||||
"none": "none",
|
||||
"subflows": "subflows",
|
||||
"flows": "flows",
|
||||
"filterUnused":"unused",
|
||||
"filterAll": "all",
|
||||
"showAllConfigNodes": "Show all config nodes",
|
||||
"filterUnused": "unused",
|
||||
"showAllUnusedConfigNodes": "Show all unused config nodes",
|
||||
"filtered": "__count__ hidden"
|
||||
},
|
||||
"context": {
|
||||
@@ -588,6 +693,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": {
|
||||
@@ -598,7 +704,6 @@
|
||||
"removeFromProject": "remove from project",
|
||||
"addToProject": "add to project",
|
||||
"files": "Files",
|
||||
"package": "Package",
|
||||
"flow": "Flow",
|
||||
"credentials": "Credentials",
|
||||
"package":"Package",
|
||||
@@ -637,6 +742,12 @@
|
||||
"committerTip": "Leave blank to use system default",
|
||||
"userName": "Username",
|
||||
"email": "Email",
|
||||
"workflow": "Workflow",
|
||||
"workfowTip": "Choose your preferred git workflow",
|
||||
"workflowManual": "Manual",
|
||||
"workflowManualTip": "All changes must be manually committed under the 'history' sidebar",
|
||||
"workflowAuto": "Automatic",
|
||||
"workflowAutoTip": "Changes are committed automatically with every deploy",
|
||||
"sshKeys": "SSH Keys",
|
||||
"sshKeysTip": "Allows you to create secure connections to remote git repositories.",
|
||||
"add": "add key",
|
||||
@@ -742,11 +853,13 @@
|
||||
"bin": "buffer",
|
||||
"date": "timestamp",
|
||||
"jsonata": "expression",
|
||||
"env": "env variable"
|
||||
"env": "env variable",
|
||||
"cred": "credential"
|
||||
}
|
||||
},
|
||||
"editableList": {
|
||||
"add": "add"
|
||||
"add": "add",
|
||||
"addTitle": "add an item"
|
||||
},
|
||||
"search": {
|
||||
"empty": "No matches found",
|
||||
@@ -788,10 +901,14 @@
|
||||
"copyPath": "Copy path to item",
|
||||
"expandItems": "Expand items",
|
||||
"collapseItems": "Collapse items",
|
||||
"duplicate": "Duplicate"
|
||||
"duplicate": "Duplicate",
|
||||
"error": {
|
||||
"invalidJSON": "Invalid JSON: "
|
||||
}
|
||||
},
|
||||
"markdownEditor": {
|
||||
"title": "Markdown editor",
|
||||
"expand": "Expand",
|
||||
"format": "Formatted with markdown",
|
||||
"heading1": "Heading 1",
|
||||
"heading2": "Heading 2",
|
||||
@@ -958,7 +1075,8 @@
|
||||
"passphrase": "Passphrase",
|
||||
"retry": "Retry",
|
||||
"update-failed": "Failed to update auth",
|
||||
"unhandled": "Unhandled error response"
|
||||
"unhandled": "Unhandled error response",
|
||||
"host-key-verify-failed": "<p>Host key verification failed.</p><p>The repository host key could not be verified. Please update your <code>known_hosts</code> file and try again.</p>"
|
||||
},
|
||||
"create-branch-list": {
|
||||
"invalid": "Invalid branch",
|
||||
@@ -979,6 +1097,7 @@
|
||||
"editor-tab": {
|
||||
"properties": "Properties",
|
||||
"envProperties": "Environment Variables",
|
||||
"module": "Module Properties",
|
||||
"description": "Description",
|
||||
"appearance": "Appearance",
|
||||
"preview": "UI Preview",
|
||||
@@ -989,6 +1108,8 @@
|
||||
"en-US": "English",
|
||||
"ja": "Japanese",
|
||||
"ko": "Korean",
|
||||
"zh-CN": "Chinese(Simplified)"
|
||||
"ru": "Russian",
|
||||
"zh-CN": "Chinese(Simplified)",
|
||||
"zh-TW": "Chinese(Traditional)"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$string": {
|
||||
"args": "arg",
|
||||
"desc": "Casts the *arg* parameter to a string using the following casting rules:\n\n - Strings are unchanged\n - Functions are converted to an empty string\n - Numeric infinity and NaN throw an error because they cannot be represented as a JSON number\n - All other values are converted to a JSON string using the `JSON.stringify` function"
|
||||
"args": "arg[, prettify]",
|
||||
"desc": "Casts the `arg` parameter to a string using the following casting rules:\n\n - Strings are unchanged\n - Functions are converted to an empty string\n - Numeric infinity and NaN throw an error because they cannot be represented as a JSON number\n - All other values are converted to a JSON string using the `JSON.stringify` function. If `prettify` is true, then \"prettified\" JSON is produced. i.e One line per field and lines will be indented based on the field depth."
|
||||
},
|
||||
"$length": {
|
||||
"args": "str",
|
||||
@@ -185,7 +185,7 @@
|
||||
},
|
||||
"$reduce": {
|
||||
"args":"array, function [, init]",
|
||||
"desc":"Returns an aggregated value derived from applying the `function` parameter successively to each value in `array` in combination with the result of the previous application of the function.\n\nThe function must accept two arguments, and behaves like an infix operator between each value within the `array`.\n\nThe optional `init` parameter is used as the initial value in the aggregation."
|
||||
"desc":"Returns an aggregated value derived from applying the `function` parameter successively to each value in `array` in combination with the result of the previous application of the function.\n\nThe function must accept two arguments, and behaves like an infix operator between each value within the `array`. The signature of `function` must be of the form: `myfunc($accumulator, $value[, $index[, $array]])`\n\nThe optional `init` parameter is used as the initial value in the aggregation."
|
||||
},
|
||||
"$flowContext": {
|
||||
"args": "string[, string]",
|
||||
@@ -230,6 +230,45 @@
|
||||
"$parseInteger": {
|
||||
"args": "string, picture",
|
||||
"desc": "Parses the contents of the `string` parameter to an integer (as a JSON number) using the format specified by the `picture` string. The `picture` string parameter has the same format as `$formatInteger`."
|
||||
|
||||
},
|
||||
"$error": {
|
||||
"args": "[str]",
|
||||
"desc": "Throws an error with a message. The optional `str` will replace the default message of `$error() function evaluated`"
|
||||
},
|
||||
"$assert": {
|
||||
"args": "arg, str",
|
||||
"desc": "If `arg` is true the function returns undefined. If `arg` is false an exception is thrown with `str` as the message of the exception."
|
||||
},
|
||||
"$single": {
|
||||
"args": "array, function",
|
||||
"desc": "Returns the one and only value in the `array` parameter that satisfies the `function` predicate (i.e. the `function` returns Boolean `true` when passed the value). Throws an exception if the number of matching values is not exactly one.\n\nThe function should be supplied in the following signature: `function(value [, index [, array]])` where value is each input of the array, index is the position of that value and the whole array is passed as the third argument"
|
||||
},
|
||||
"$encodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "Encodes a Uniform Resource Locator (URL) component by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character.\n\nExample: `$encodeUrlComponent(\"?x=test\")` => `\"%3Fx%3Dtest\"`"
|
||||
},
|
||||
"$encodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "Encodes a Uniform Resource Locator (URL) by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character. \n\nExample: `$encodeUrl(\"https://mozilla.org/?x=шеллы\")` => `\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\"`"
|
||||
},
|
||||
"$decodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "Decodes a Uniform Resource Locator (URL) component previously created by encodeUrlComponent. \n\nExample: `$decodeUrlComponent(\"%3Fx%3Dtest\")` => `\"?x=test\"`"
|
||||
},
|
||||
"$decodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "Decodes a Uniform Resource Locator (URL) previously created by encodeUrl. \n\nExample: `$decodeUrl(\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\")` => `\"https://mozilla.org/?x=шеллы\"`"
|
||||
},
|
||||
"$distinct": {
|
||||
"args": "array",
|
||||
"desc": "Returns an array with duplicate values removed from `array`"
|
||||
},
|
||||
"$type": {
|
||||
"args": "value",
|
||||
"desc": "Returns the type of `value` as a string. If `value` is undefined, this will return `undefined`"
|
||||
},
|
||||
"$moment": {
|
||||
"args": "[str]",
|
||||
"desc": "Gets a date object using the Moment library."
|
||||
}
|
||||
}
|
||||
|
||||
170
packages/node_modules/@node-red/editor-client/locales/ja/editor.json
vendored
Executable file → Normal file
@@ -14,9 +14,38 @@
|
||||
"back": "戻る",
|
||||
"next": "進む",
|
||||
"clone": "プロジェクトをクローン",
|
||||
"cont": "続ける"
|
||||
"cont": "続ける",
|
||||
"style": "形式",
|
||||
"line": "線",
|
||||
"fill": "塗りつぶし",
|
||||
"label": "ラベル",
|
||||
"color": "色",
|
||||
"position": "配置",
|
||||
"enable": "有効",
|
||||
"disable": "無効",
|
||||
"upload": "アップロード"
|
||||
},
|
||||
"type": {
|
||||
"string": "文字列",
|
||||
"number": "数値",
|
||||
"boolean": "真偽値",
|
||||
"array": "配列",
|
||||
"buffer": "バッファ",
|
||||
"object": "オブジェクト",
|
||||
"jsonString": "JSON文字列",
|
||||
"undefined": "undefined",
|
||||
"null": "null"
|
||||
}
|
||||
},
|
||||
"event": {
|
||||
"loadPlugins": "プラグインを読み込み中",
|
||||
"loadPalette": "パレットを読み込み中",
|
||||
"loadNodeCatalogs": "ノードカタログを読み込み中",
|
||||
"loadNodes": "ノードを読み込み中 __count__",
|
||||
"loadFlows": "フローを読み込み中",
|
||||
"importFlows": "ワークスペースにフローを追加中",
|
||||
"importError": "<p>フロー追加エラー</p><p>__message__</p>"
|
||||
},
|
||||
"workspace": {
|
||||
"defaultName": "フロー __number__",
|
||||
"editFlow": "フローを編集: __name__",
|
||||
@@ -56,8 +85,8 @@
|
||||
"settings": "設定",
|
||||
"userSettings": "ユーザ設定",
|
||||
"nodes": "ノード",
|
||||
"displayStatus": "ノードの状態を表示",
|
||||
"displayConfig": "ノードの設定",
|
||||
"displayStatus": "ノードのステータスを表示",
|
||||
"displayConfig": "設定ノード",
|
||||
"import": "読み込み",
|
||||
"export": "書き出し",
|
||||
"search": "ノードを検索",
|
||||
@@ -80,7 +109,12 @@
|
||||
"projects-new": "新規",
|
||||
"projects-open": "開く",
|
||||
"projects-settings": "設定",
|
||||
"showNodeLabelDefault": "追加したノードのラベルを表示"
|
||||
"showNodeLabelDefault": "追加したノードのラベルを表示",
|
||||
"groups": "グループ",
|
||||
"groupSelection": "選択部分をグループ化",
|
||||
"ungroupSelection": "選択部分をグループ解除",
|
||||
"groupMergeSelection": "選択部分をマージ",
|
||||
"groupRemoveSelection": "グループから削除"
|
||||
}
|
||||
},
|
||||
"actions": {
|
||||
@@ -160,22 +194,34 @@
|
||||
"node_plural": "__count__ 個のノード",
|
||||
"configNode": "__count__ 個の設定ノード",
|
||||
"configNode_plural": "__count__ 個の設定ノード",
|
||||
"group": "__count__ 個のグループ",
|
||||
"group_plural": "__count__ 個のグループ",
|
||||
"flow": "__count__ 個のフロー",
|
||||
"flow_plural": "__count__ 個のフロー",
|
||||
"subflow": "__count__ 個のサブフロー",
|
||||
"subflow_plural": "__count__ 個のサブフロー",
|
||||
"pasteNodes": "JSON形式のフローデータを貼り付けてください",
|
||||
"selectFile": "読み込むファイルを選択してください",
|
||||
"importNodes": "フローをクリップボートから読み込み",
|
||||
"exportNodes": "フローをクリップボードへ書き出し",
|
||||
"replacedNodes": "置換された __count__ 個のノード",
|
||||
"replacedNodes_plural": "置換された __count__ 個のノード",
|
||||
"pasteNodes": "JSON形式のフローデータを貼り付け",
|
||||
"selectFile": "読み込むファイルを選択",
|
||||
"importNodes": "フローを読み込み",
|
||||
"exportNodes": "フローを書き出し",
|
||||
"download": "ダウンロード",
|
||||
"importUnrecognised": "認識できない型が読み込まれました:",
|
||||
"importUnrecognised_plural": "認識できない型が読み込まれました:",
|
||||
"importDuplicate": "重複したノードを読み込みました:",
|
||||
"importDuplicate_plural": "重複したノードを読み込みました:",
|
||||
"nodesExported": "クリップボードへフローを書き出しました",
|
||||
"nodesImported": "読み込みました:",
|
||||
"nodeCopied": "__count__ 個のノードをコピーしました",
|
||||
"nodeCopied_plural": "__count__ 個のノードをコピーしました",
|
||||
"groupCopied": "__count__ 個のグループをコピーしました",
|
||||
"groupCopied_plural": "__count__ 個のグループをコピーしました",
|
||||
"groupStyleCopied": "グループの形式をコピーしました",
|
||||
"invalidFlow": "不正なフロー: __message__",
|
||||
"recoveredNodes": "復旧したノード",
|
||||
"recoveredNodesInfo": "このフロー内のノードは読み込み時に、有効なフローIDがありませんでした。これらフローIDは、フローに追加されているため、復元または削除できます。",
|
||||
"recoveredNodesNotification": "<p>有効なフローIDを持たないノードが読み込まれました</p><p>これらノードは '__flowName__' という新しいフローへ追加されました。</p>",
|
||||
"export": {
|
||||
"selected": "選択したフロー",
|
||||
"current": "現在のタブ",
|
||||
@@ -190,13 +236,19 @@
|
||||
},
|
||||
"import": {
|
||||
"import": "読み込み先",
|
||||
"importSelected": "選択したノードを読み込み",
|
||||
"importCopy": "コピーを読み込み",
|
||||
"viewNodes": "ノードを参照...",
|
||||
"newFlow": "新規のタブ",
|
||||
"replace": "置換",
|
||||
"errors": {
|
||||
"notArray": "JSON形式の配列ではありません",
|
||||
"itemNotObject": "不正なフロー - __index__ 番目の要素はノードオブジェクトではありません",
|
||||
"missingId": "不正なフロー - __index__ 番目の要素に'id'プロパティがありません",
|
||||
"missingType": "不正なフロー - __index__ 番目の要素に'type'プロパティがありません"
|
||||
}
|
||||
},
|
||||
"conflictNotification1": "読み込もうとしているノードのいくつかは、既にワークスペース内に存在しています。",
|
||||
"conflictNotification2": "読み込むノードを選択し、また既存のノードを置き換えるか、もしくはそれらのコピーを読み込むかも選択してください。"
|
||||
},
|
||||
"copyMessagePath": "パスをコピーしました",
|
||||
"copyMessageValue": "値をコピーしました",
|
||||
@@ -215,7 +267,7 @@
|
||||
"successfulDeploy": "デプロイが成功しました",
|
||||
"successfulRestart": "フローの再起動が成功しました",
|
||||
"deployFailed": "デプロイが失敗しました: __message__",
|
||||
"unusedConfigNodes": "使われていない「ノードの設定」があります。",
|
||||
"unusedConfigNodes": "使われていない設定ノードがあります。",
|
||||
"unusedConfigNodesLink": "設定を参照する",
|
||||
"errors": {
|
||||
"noResponse": "サーバの応答がありません"
|
||||
@@ -286,8 +338,21 @@
|
||||
"output": "出力:",
|
||||
"status": "ステータスノード",
|
||||
"deleteSubflow": "サブフローを削除",
|
||||
"confirmDelete": "このサブフローを削除しても良いですか?",
|
||||
"info": "詳細",
|
||||
"category": "カテゴリ",
|
||||
"module": "モジュール",
|
||||
"license": "ライセンス",
|
||||
"licenseNone": "なし",
|
||||
"licenseOther": "その他",
|
||||
"type": "ノードの型",
|
||||
"version": "バージョン",
|
||||
"versionPlaceholder": "x.y.z",
|
||||
"keys": "キーワード",
|
||||
"keysPlaceholder": "カンマ区切りのキーワード",
|
||||
"author": "作者",
|
||||
"authorPlaceholder": "名前 <email@example.com>",
|
||||
"desc": "説明",
|
||||
"env": {
|
||||
"restore": "デフォルト値に戻す",
|
||||
"remove": "環境変数を削除"
|
||||
@@ -297,6 +362,13 @@
|
||||
"multipleInputsToSelection": "<strong>サブフローを作成できません</strong>: 複数の入力が選択されています"
|
||||
}
|
||||
},
|
||||
"group": {
|
||||
"editGroup": "__name__ グループを編集",
|
||||
"errors": {
|
||||
"cannotCreateDiffGroups": "異なるグループのノードを使用してグループを作成することはできません",
|
||||
"cannotAddSubflowPorts": "グループにサブフローの端子を追加できません"
|
||||
}
|
||||
},
|
||||
"editor": {
|
||||
"configEdit": "編集",
|
||||
"configAdd": "追加",
|
||||
@@ -304,9 +376,9 @@
|
||||
"configDelete": "削除",
|
||||
"nodesUse": "__count__ 個のノードが、この設定を使用しています",
|
||||
"nodesUse_plural": "__count__ 個のノードが、この設定を使用しています",
|
||||
"addNewConfig": "新規に __type__ ノードの設定を追加",
|
||||
"addNewConfig": "新規に __type__ 設定ノードを追加",
|
||||
"editNode": "__type__ ノードを編集",
|
||||
"editConfig": "__type__ ノードの設定を編集",
|
||||
"editConfig": "__type__ 設定ノードを編集",
|
||||
"addNewType": "新規に __type__ を追加...",
|
||||
"nodeProperties": "プロパティ",
|
||||
"label": "ラベル",
|
||||
@@ -315,6 +387,7 @@
|
||||
"labelInputs": "入力",
|
||||
"labelOutputs": "出力",
|
||||
"settingIcon": "アイコン",
|
||||
"default": "デフォルト",
|
||||
"noDefaultLabel": "なし",
|
||||
"defaultLabel": "既定のラベルを使用",
|
||||
"searchIcons": "アイコンを検索",
|
||||
@@ -325,6 +398,8 @@
|
||||
"locale": "UI言語の選択",
|
||||
"icon": "記号",
|
||||
"inputType": "入力形式",
|
||||
"selectType": "形式選択...",
|
||||
"loadCredentials": "ノードの認証情報を読み込み中",
|
||||
"inputs": {
|
||||
"input": "入力",
|
||||
"select": "メニュー",
|
||||
@@ -339,7 +414,8 @@
|
||||
"bool": "真偽",
|
||||
"json": "JSON",
|
||||
"bin": "バッファ",
|
||||
"env": "環境変数"
|
||||
"env": "環境変数",
|
||||
"cred": "認証情報"
|
||||
},
|
||||
"menu": {
|
||||
"input": "入力",
|
||||
@@ -358,7 +434,8 @@
|
||||
},
|
||||
"errors": {
|
||||
"scopeChange": "スコープの変更は、他のフローで使われているノードを無効にします",
|
||||
"invalidProperties": "プロパティが不正です:"
|
||||
"invalidProperties": "プロパティが不正です:",
|
||||
"credentialLoadFailed": "ノードの認証情報の読み込みに失敗"
|
||||
}
|
||||
},
|
||||
"keyboard": {
|
||||
@@ -486,6 +563,8 @@
|
||||
"sortAZ": "辞書順",
|
||||
"sortRecent": "日付順",
|
||||
"more": "+ さらに __count__ 個",
|
||||
"upload": "モジュールのtgzファイルをアップロード",
|
||||
"refresh": "モジュールリスト更新",
|
||||
"errors": {
|
||||
"catalogLoadFailed": "<p>ノードのカタログの読み込みに失敗しました。</p><p>詳細はブラウザのコンソールを確認してください。</p>",
|
||||
"installFailed": "<p>追加処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>",
|
||||
@@ -526,6 +605,7 @@
|
||||
"label": "情報",
|
||||
"node": "ノード",
|
||||
"type": "型",
|
||||
"group": "グループ",
|
||||
"module": "モジュール",
|
||||
"id": "ID",
|
||||
"status": "状態",
|
||||
@@ -548,17 +628,41 @@
|
||||
"nodeHelp": "ノードのヘルプ",
|
||||
"none": "なし",
|
||||
"arrayItems": "__count__ 要素",
|
||||
"showTips": "設定からヒントを表示できます"
|
||||
"showTips": "設定からヒントを表示できます",
|
||||
"outline": "アウトライン",
|
||||
"empty": "空",
|
||||
"globalConfig": "グローバル設定ノード",
|
||||
"triggerAction": "アクションを実行",
|
||||
"find": "ワークスペース内を検索",
|
||||
"search": {
|
||||
"configNodes": "設定ノード",
|
||||
"unusedConfigNodes": "未使用の設定ノード",
|
||||
"invalidNodes": "不正なノード",
|
||||
"uknownNodes": "未知のノード",
|
||||
"unusedSubflows": "未使用のサブフロー"
|
||||
}
|
||||
},
|
||||
"help": {
|
||||
"name": "ヘルプ",
|
||||
"label": "ヘルプ",
|
||||
"search": "ヘルプを検索",
|
||||
"nodeHelp": "ノードヘルプ",
|
||||
"showHelp": "ヘルプを表示",
|
||||
"showInOutline": "アウトラインに表示",
|
||||
"showTopics": "トピックを表示",
|
||||
"noHelp": "ヘルプのトピックが未選択"
|
||||
},
|
||||
"config": {
|
||||
"name": "ノードの設定を表示",
|
||||
"label": "ノードの設定",
|
||||
"name": "設定ノードを表示",
|
||||
"label": "設定ノード",
|
||||
"global": "全てのフロー上",
|
||||
"none": "なし",
|
||||
"subflows": "サブフロー",
|
||||
"flows": "フロー",
|
||||
"filterUnused": "未使用",
|
||||
"filterAll": "全て",
|
||||
"showAllConfigNodes": "全設定ノードを表示",
|
||||
"filterUnused": "未使用",
|
||||
"showAllUnusedConfigNodes": "未使用の全設定ノードを表示",
|
||||
"filtered": "__count__ 個が無効"
|
||||
},
|
||||
"context": {
|
||||
@@ -585,9 +689,10 @@
|
||||
"description": "詳細",
|
||||
"dependencies": "依存関係",
|
||||
"settings": "設定",
|
||||
"noSummaryAvailable": "サマリが存在しません",
|
||||
"noSummaryAvailable": "要約が存在しません",
|
||||
"editDescription": "プロジェクトの詳細を編集",
|
||||
"editDependencies": "プロジェクトの依存関係を編集",
|
||||
"noDescriptionAvailable": "詳細が存在しません",
|
||||
"editReadme": "README.mdを編集",
|
||||
"showProjectSettings": "プロジェクト設定を表示",
|
||||
"projectSettings": {
|
||||
@@ -598,9 +703,9 @@
|
||||
"removeFromProject": "プロジェクトから削除",
|
||||
"addToProject": "プロジェクトへ追加",
|
||||
"files": "ファイル",
|
||||
"package": "パッケージ",
|
||||
"flow": "フロー",
|
||||
"credentials": "認証情報",
|
||||
"package": "パッケージ",
|
||||
"packageCreate": "変更が保存された時にファイルが作成されます",
|
||||
"fileNotExist": "ファイルが存在しません",
|
||||
"selectFile": "ファイルを選択",
|
||||
@@ -636,6 +741,12 @@
|
||||
"committerTip": "システムのデフォルトを使用する場合、空白のままにしてください",
|
||||
"userName": "ユーザ名",
|
||||
"email": "メールアドレス",
|
||||
"workflow": "ワークフロー",
|
||||
"workfowTip": "望ましいgitワークフローを選択してください",
|
||||
"workflowManual": "手動",
|
||||
"workflowManualTip": "全ての変更は「履歴」サイドバー内で手動でコミットする必要があります",
|
||||
"workflowAuto": "自動",
|
||||
"workflowAutoTip": "変更はデプロイの度に自動的にコミットされます",
|
||||
"sshKeys": "SSH キー",
|
||||
"sshKeysTip": "gitリポジトリへのセキュアな接続を作成できます。",
|
||||
"add": "キーを追加",
|
||||
@@ -741,7 +852,8 @@
|
||||
"bin": "バッファ",
|
||||
"date": "日時",
|
||||
"jsonata": "JSONata式",
|
||||
"env": "環境変数"
|
||||
"env": "環境変数",
|
||||
"cred": "認証情報"
|
||||
}
|
||||
},
|
||||
"editableList": {
|
||||
@@ -787,10 +899,14 @@
|
||||
"copyPath": "要素のパスをコピー",
|
||||
"expandItems": "要素を展開",
|
||||
"collapseItems": "要素を折り畳む",
|
||||
"duplicate": "複製"
|
||||
"duplicate": "複製",
|
||||
"error": {
|
||||
"invalidJSON": "不正なJSON: "
|
||||
}
|
||||
},
|
||||
"markdownEditor": {
|
||||
"title": "マークダウンエディタ",
|
||||
"expand": "拡大",
|
||||
"format": "マークダウン形式で記述",
|
||||
"heading1": "見出しレベル1",
|
||||
"heading2": "見出しレベル2",
|
||||
@@ -951,13 +1067,14 @@
|
||||
"confirm": "<p>デプロイされていない変更は失われます。</p><p>続けますか?</p>"
|
||||
},
|
||||
"send-req": {
|
||||
"auth-req": "リポジトリ対する認証が必要です",
|
||||
"auth-req": "リポジトリに対する認証が必要です",
|
||||
"username": "ユーザ名",
|
||||
"password": "パスワード",
|
||||
"passphrase": "パスフレーズ",
|
||||
"retry": "リトライ",
|
||||
"update-failed": "認証の更新に失敗しました",
|
||||
"unhandled": "エラー応答が処理されませんでした"
|
||||
"unhandled": "エラー応答が処理されませんでした",
|
||||
"host-key-verify-failed": "<p>ホストキーの検証に失敗</p><p>リポジトリのホストキーを検証できませんでした。<code>known_hosts</code>ファイルを更新して、もう一度試してください。</p>"
|
||||
},
|
||||
"create-branch-list": {
|
||||
"invalid": "不正なブランチ",
|
||||
@@ -978,6 +1095,7 @@
|
||||
"editor-tab": {
|
||||
"properties": "プロパティ",
|
||||
"envProperties": "環境変数",
|
||||
"module": "モジュールプロパティ",
|
||||
"description": "説明",
|
||||
"appearance": "外観",
|
||||
"preview": "UIプレビュー",
|
||||
@@ -988,6 +1106,8 @@
|
||||
"en-US": "英語",
|
||||
"ja": "日本語",
|
||||
"ko": "韓国語",
|
||||
"zh-CN": "中国語(簡体)"
|
||||
"ru": "ロシア語",
|
||||
"zh-CN": "中国語(簡体)",
|
||||
"zh-TW": "中国語(繁体)"
|
||||
}
|
||||
}
|
||||
|
||||
46
packages/node_modules/@node-red/editor-client/locales/ja/jsonata.json
vendored
Executable file → Normal file
@@ -1,7 +1,7 @@
|
||||
{
|
||||
"$string": {
|
||||
"args": "arg",
|
||||
"desc": "以下の型変換ルールを用いて、引数 *arg* を文字列へ型変換します。:\n\n - 文字列は変換しません。\n - 関数は空の文字列に変換します。\n - JSONの数値として表現できないため、無限大やNaNはエラーになります。\n - 他の値は `JSON.stringify` 関数を用いて、JSONの文字列へ変換します。"
|
||||
"args": "arg[, prettify]",
|
||||
"desc": "以下の型変換ルールを用いて、引数 *arg* を文字列へ型変換します。:\n\n - 文字列は変換しません。\n - 関数は空の文字列に変換します。\n - JSONの数値として表現できないため、無限大やNaNはエラーになります。\n - 他の値は `JSON.stringify` 関数を用いて、JSONの文字列へ変換します。`prettify`が真の場合、JSONを整形出力します。フィールドを1行毎に出力。フィールドのネスト深さによってインデントを行います。"
|
||||
},
|
||||
"$length": {
|
||||
"args": "str",
|
||||
@@ -185,7 +185,7 @@
|
||||
},
|
||||
"$reduce": {
|
||||
"args": "array, function [, init]",
|
||||
"desc": "配列の各要素値に関数 `function` を連続的に適用して得られる集約値を返します。 `function` の適用の際には、直前の `function` の適用結果と要素値が引数として与えられます。\n\n関数 `function` は引数を2つ取り、配列の各要素の間に配置する中置演算子のように作用しなくてはなりません。\n\n任意の引数 `init` には、集約時の初期値を設定します。"
|
||||
"desc": "配列の各要素値に関数 `function` を連続的に適用して得られる集約値を返します。 `function` の適用の際には、直前の `function` の適用結果と要素値が引数として与えられます。\n\n関数 `function` は引数を2つ取り、配列の各要素の間に配置する中置演算子のように作用しなくてはなりません。関数`function`のシグネチャは`myfunc($accumulator, $value[, $index[, $array]])`という形式でなければなりません。\n\n任意の引数 `init` には、集約時の初期値を設定します。"
|
||||
},
|
||||
"$flowContext": {
|
||||
"args": "string",
|
||||
@@ -230,5 +230,45 @@
|
||||
"$parseInteger": {
|
||||
"args": "string, picture",
|
||||
"desc": "`picture`文字列の指定に従って、`string`パラメータを整数(JSON数値)に変換します。`picture`文字列は`$formatInteger`と同じ形式です。"
|
||||
},
|
||||
"$error": {
|
||||
"args": "[str]",
|
||||
"desc": "メッセージを指定して例外を送出します。メッセージ`str`を省略した場合は`$error() function evaluated`をメッセージとします。"
|
||||
},
|
||||
"$assert": {
|
||||
"args": "arg, str",
|
||||
"desc": "`arg`が真の場合、undefinedを返します。偽の場合、`str`をメッセージとする例外を送出します。"
|
||||
},
|
||||
"$single": {
|
||||
"args": "array, function",
|
||||
"desc": "`array`の要素のうち、条件判定関数`function`を満たす(`function`に与えた場合に真偽値`true`を返す)要素が1つのみである場合、それを返します。マッチする要素が1つのみでない場合、例外を送出します。\n\n指定する関数は`function(value [, index [, array]])`というシグネチャでなければなりません。ここで、`value`は`array`の要素値、`index`は要素の添字、第三引数には配列全体を渡します。"
|
||||
},
|
||||
"$encodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "Uniform Resource Locator (URL)を構成する文字を1、2、3、もしくは、4文字エスケープシーケンスのUTF-8文字エンコーディングで置換します。\n\n例: `$encodeUrlComponent(\"?x=test\")` => `\"%3Fx%3Dtest\"`"
|
||||
},
|
||||
"$encodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "Uniform Resource Locator (URL)要素を構成する文字を1、2、3、もしくは、4文字エスケープシーケンスのUTF-8文字エンコーディングで置換します。\n\n例: `$encodeUrl(\"https://mozilla.org/?x=шеллы\")` => `\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\"`"
|
||||
},
|
||||
"$decodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "encodeUrlComponentで置換したUniform Resource Locator (URL)をデコードします。\n\n例: `$decodeUrlComponent(\"%3Fx%3Dtest\")` => `\"?x=test\"`"
|
||||
},
|
||||
"$decodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "encodeUrlで置換したUniform Resource Locator (URL)要素をデコードします。 \n\n例: `$decodeUrl(\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\")` => `\"https://mozilla.org/?x=шеллы\"`"
|
||||
},
|
||||
"$distinct": {
|
||||
"args": "array",
|
||||
"desc": "配列`array`から重複要素を削除した配列を返します。"
|
||||
},
|
||||
"$type": {
|
||||
"args": "value",
|
||||
"desc": "`value` の型を文字列として返します。もし `value` が未定義の場合、 `undefined` が返されます。"
|
||||
},
|
||||
"$moment": {
|
||||
"args": "[str]",
|
||||
"desc": "Momentライブラリを使用して日付オブジェクトを取得します。"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -494,8 +494,8 @@
|
||||
"none": "없음",
|
||||
"subflows": "보조 플로우",
|
||||
"flows": "플로우",
|
||||
"filterUnused": "미사용",
|
||||
"filterAll": "전체",
|
||||
"filterUnused": "미사용",
|
||||
"filtered": "__count__ 개 숨김"
|
||||
},
|
||||
"context": {
|
||||
|
||||
1139
packages/node_modules/@node-red/editor-client/locales/ru/editor.json
vendored
Executable file
23
packages/node_modules/@node-red/editor-client/locales/ru/infotips.json
vendored
Executable file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"info": {
|
||||
"tip0" : "Вы можете удалить выбранные узлы или провода с {{core:delete-selection}}",
|
||||
"tip1" : "Ищите узлы с {{core:search}}",
|
||||
"tip2" : "{{core:toggle-sidebar}} показывает/скрывает эту боковою панель",
|
||||
"tip3" : "Вы можете управлять палитрой узлов с помощью {{core:manage-palette}}",
|
||||
"tip4" : "Узлы конфигурации потока перечисляются на боковой панели. Доступ к списку можно получить из меню или с помощью {{core:show-config-tab}}",
|
||||
"tip5" : "Эти советы можно включить/выключить через настройки",
|
||||
"tip6" : "Перемещайте выбранные узлы клавишами [влево] [вверх] [вниз] и [вправо]. Удерживайте [Shift], чтобы увеличить шаг",
|
||||
"tip7" : "Перетаскивание узла на провод соединит его с обеих сторон",
|
||||
"tip8" : "Экспортируйте выбранные узлы или текущую вкладку с {{core:show-export-dialog}}",
|
||||
"tip9" : "Импортируйте поток, перетаскивая его JSON в редактор или с помощью {{core:show-import-dialog}}",
|
||||
"tip10" : "Нажмите [Shift], [кликните] по порту узла и перетаскивайте подключенные провода на другой узел",
|
||||
"tip11" : "Открывайте вкладку Информация с {{core:show-info-tab}} или вкладку Отладка с {{core:show-debug-tab}}",
|
||||
"tip12" : "Нажмите [ctrl] и [кликните] в рабочей области, чтобы открыть диалог быстрого добавления",
|
||||
"tip13" : "Нажмите [ctrl] и [кликните] по порту узла, чтобы начать быстрое подключение",
|
||||
"tip14" : "Нажмите [Shift] и [кликните] по узлу, чтобы выбрать все соединенные узлы",
|
||||
"tip15" : "Нажмите [ctrl] и [кликните] по узлу, чтобы добавить или убрать его из текущего выбора",
|
||||
"tip16" : "Переключайте вкладки потока с помощью {{core:show-previous-tab}} и {{core:show-next-tab}}",
|
||||
"tip17" : "Вы можете подтвердить изменения в редакторе узла с {{core:confirm-edit-tray}} или отменить их с {{core:cancel-edit-tray}}",
|
||||
"tip18" : "Нажатие {{core:edit-selected-node}} откроет редактор первого узла в текущем выборе"
|
||||
}
|
||||
}
|
||||
274
packages/node_modules/@node-red/editor-client/locales/ru/jsonata.json
vendored
Executable file
@@ -0,0 +1,274 @@
|
||||
{
|
||||
"$string": {
|
||||
"args": "arg[, prettify]",
|
||||
"desc": "Преобразует параметр `arg` в строку, используя следующие правила приведения:\n\n - Строки возвращаются как есть\n - Функции преобразуются в пустую строку\n - Числовая бесконечность и NaN выдают ошибку, поскольку они не могут быть представлены числом в JSON\n - Все остальные значения преобразуются в строку JSON с помощью функции `JSON.stringify`. Если значение `prettify` равно true, тогда будет сгенерирован \"отформатированный\" JSON. То есть каждое поле будет в отдельной строке, а строки будут иметь отступ в зависимости от глубины поля."
|
||||
},
|
||||
"$length": {
|
||||
"args": "str",
|
||||
"desc": "Возвращает количество символов в строке `str`. Выдается ошибка, если `str` не является строкой."
|
||||
},
|
||||
"$substring": {
|
||||
"args": "str, start[, length]",
|
||||
"desc": "Возвращает строку, содержащую символы из первого параметра `str`, начиная с позиции `start` (отсчет с нуля). Если указан `length`, то подстрока будет содержать максимум `length` символов. Если `start` отрицателен, то это означает количество символов с конца `str`."
|
||||
},
|
||||
"$substringBefore": {
|
||||
"args": "str, chars",
|
||||
"desc": "Возвращает подстроку перед первым вхождением последовательности символов `chars` в строке `str`. Если `str` не содержит `chars`, то он возвращает `str`."
|
||||
},
|
||||
"$substringAfter": {
|
||||
"args": "str, chars",
|
||||
"desc": "Возвращает подстроку после первого вхождения последовательности символов `chars` в строке `str`. Если `str` не содержит `chars`, то он возвращает `str`."
|
||||
},
|
||||
"$uppercase": {
|
||||
"args": "str",
|
||||
"desc": "Возвращает строку со всеми символами `str`, преобразованными в верхний регистр."
|
||||
},
|
||||
"$lowercase": {
|
||||
"args": "str",
|
||||
"desc": "Возвращает строку со всеми символами `str`, преобразованными в нижний регистр."
|
||||
},
|
||||
"$trim": {
|
||||
"args": "str",
|
||||
"desc": "Нормализует и обрезает все пробельные символы в строке `str`, выполняя следующие шаги:\n\n - Все символы табуляции, возврата каретки и перевода строки заменяются пробелами.\n- Последовательности пробелов сокращаются до одного пробела.\n- Пробелы в начале и конце `str` удаляются.\n\n Если `str` не указан (то есть эта функция вызывается без аргументов), тогда значение контекста используется в качестве значения `str`. Выдается ошибка, если `str` не является строкой."
|
||||
},
|
||||
"$contains": {
|
||||
"args": "str, pattern",
|
||||
"desc": "Возвращает `true`, если строка `str` соответствует шаблону `pattern`, в противном случае возвращает `false`. Если `str` не указан (то есть эта функция вызывается с одним аргументом), то значение контекста используется как значение `str`. Параметр `pattern` может быть либо строкой, либо регулярным выражением."
|
||||
},
|
||||
"$split": {
|
||||
"args": "str[, separator][, limit]",
|
||||
"desc": "Разбивает строку `str` на массив подстрок. Выдает ошибку, если `str` не является строкой. Необязательный параметр `separator` (строка или регулярное выражение) указывает символы внутри строки `str`, относительно которых она должна быть разделена. Если `separator` не указан, то предполагается пустая строка, и `str` будет разбит на массив из отдельных символов. Выдает ошибку, если `separator` не является строкой. Необязательный параметр `limit` - это число, указывающее максимальное количество подстрок для включения в результирующий массив. Любые дополнительные подстроки отбрасываются. Если `limit` не указан, то весь `str` разделяется без ограничения размера результирующего массива. Выдает ошибку, если `limit` не является положительным числом."
|
||||
},
|
||||
"$join": {
|
||||
"args": "array[, separator]",
|
||||
"desc": "Объединяет массив подстрок в одну объединенную строку, в которой каждая подстрока отделена необязательным параметром `separator`. Выдает ошибку, если входной массив содержит элемент, который не является строкой. Если `separator` не указан, то предполагается, что это пустая строка, то есть нет `separator` между подстроками. Выдает ошибку, если `separator` не является строкой."
|
||||
},
|
||||
"$match": {
|
||||
"args": "str, pattern [, limit]",
|
||||
"desc": "Применяет строку `str` к регулярному выражению `pattern` и возвращает массив объектов, каждый из которых содержит информацию о каждом совпадении внутри `str`."
|
||||
},
|
||||
"$replace": {
|
||||
"args": "str, pattern, replacement [, limit]",
|
||||
"desc": "Находит вхождения шаблона `pattern` в строке `str` и заменяет их на строку `replacement`.\n\nНеобязательный параметр `limit` - это максимальное количество замен."
|
||||
},
|
||||
"$now": {
|
||||
"args":"",
|
||||
"desc":"Создает отметку времени в формате, совместимом с ISO 8601, и возвращает ее как строку."
|
||||
},
|
||||
"$base64encode": {
|
||||
"args":"string",
|
||||
"desc":"Преобразует ASCII-строку в base-64 кодировку. Каждый символ в строке обрабатывается как байт двоичных данных. Для этого необходимо, чтобы все символы в строке находились в диапазоне от 0x00 до 0xFF, который включает все символы строк в URI-кодировке. Символы Юникода за пределами этого диапазона не поддерживаются."
|
||||
},
|
||||
"$base64decode": {
|
||||
"args":"string",
|
||||
"desc":"Преобразует байты в кодировке base-64 в строку, используя кодовую страницу Юникод UTF-8."
|
||||
},
|
||||
"$number": {
|
||||
"args": "arg",
|
||||
"desc": "Преобразует параметр `arg` в число с использованием следующих правил приведения:\n\n - Числа возвращаются как есть\n - Строки, которые содержат последовательность символов, представляющих допустимое в JSON число, преобразуются в это число\n - Все остальные значения вызывают ошибку."
|
||||
},
|
||||
"$abs": {
|
||||
"args":"number",
|
||||
"desc":"Возвращает абсолютное значение числа `number`."
|
||||
},
|
||||
"$floor": {
|
||||
"args":"number",
|
||||
"desc":"Возвращает значение числа `number`, округленное до ближайшего целого числа, которое меньше или равно `number`."
|
||||
},
|
||||
"$ceil": {
|
||||
"args":"number",
|
||||
"desc":"Возвращает значение числа `number`, округленное до ближайшего целого числа, которое больше или равно `number`."
|
||||
},
|
||||
"$round": {
|
||||
"args":"number [, precision]",
|
||||
"desc":"Возвращает значение числа `number`, округленное до количества десятичных знаков, указанных необязательным параметром `precision`."
|
||||
},
|
||||
"$power": {
|
||||
"args":"base, exponent",
|
||||
"desc":"Возвращает значение числа `base`, возведенное в степень `exponent`."
|
||||
},
|
||||
"$sqrt": {
|
||||
"args":"number",
|
||||
"desc":"Возвращает квадратный корень из значения числа `number`."
|
||||
},
|
||||
"$random": {
|
||||
"args":"",
|
||||
"desc":"Возвращает псевдослучайное число, которе больше или равно нулю и меньше единицы."
|
||||
},
|
||||
"$millis": {
|
||||
"args":"",
|
||||
"desc":"Возвращает число миллисекунд с начала Unix-эпохи (1 января 1970 года по Гринвичу) в виде числа. Все вызовы `$millis()` в пределах выполнения выражения будут возвращать одно и то же значение."
|
||||
},
|
||||
"$sum": {
|
||||
"args": "array",
|
||||
"desc": "Возвращает арифметическую сумму массива чисел `array`. Вызывает ошибку, если входной массив `array` содержит элемент, который не является числом."
|
||||
},
|
||||
"$max": {
|
||||
"args": "array",
|
||||
"desc": "Возвращает максимальное число в массиве чисел `array`. Вызывает ошибку, если входной массив `array` содержит элемент, который не является числом."
|
||||
},
|
||||
"$min": {
|
||||
"args": "array",
|
||||
"desc": "Возвращает минимальное число в массиве чисел `array`. Вызывает ошибку, если входной массив `array` содержит элемент, который не является числом."
|
||||
},
|
||||
"$average": {
|
||||
"args": "array",
|
||||
"desc": "Возвращает среднее значение массива чисел `array`. Вызывает ошибку, если входной массив `array` содержит элемент, который не является числом."
|
||||
},
|
||||
"$boolean": {
|
||||
"args": "arg",
|
||||
"desc": "Приводит аргумент к логическому значению, используя следующие правила: \n\n - Логические значения возвращаются как есть\n - пустая строка: `false`\n - непустая строка: `true`\n - число равное `0`: `false`\n - ненулевое число: `true`\n - `null` : `false`\n - пустой массив: `false`\n - массив, который содержит хотя бы один элемент, приводимый к `true`: `true`\n - массив, все элементы которого приводятся к `false`: `false`\n - пустой объект: `false`\n - непустой объект: `true`\n - функция: `false`"
|
||||
},
|
||||
"$not": {
|
||||
"args": "arg",
|
||||
"desc": "Возвращает логическое НЕ для аргумента. `arg` сначала приводится к логическому значению"
|
||||
},
|
||||
"$exists": {
|
||||
"args": "arg",
|
||||
"desc": "Возвращает логическое `true`, если выполнение выражения `arg` возвращает значение, или `false`, если выражение ничему не соответствует (например, путь к несуществующему полю)."
|
||||
},
|
||||
"$count": {
|
||||
"args": "array",
|
||||
"desc": "Возвращает количество элементов в массиве"
|
||||
},
|
||||
"$append": {
|
||||
"args": "array, array",
|
||||
"desc": "Присоединяет один массив к другому"
|
||||
},
|
||||
"$sort": {
|
||||
"args":"array [, function]",
|
||||
"desc":"Возвращает массив, содержащий все значения параметра `array`, но отсортированные по порядку.\n\nЕсли указан компаратор `function`, то это должна быть функция, которая принимает два параметра:\n\n`function(val1, val2)`\n\nЭту функцию вызывает алгоритм сортировки для сравнения двух значений: val1 и val2. Если значение val1 следует поместить после значения val2 в желаемом порядке сортировки, то функция должна возвращать логическое значение `true`, чтобы обозначить замену. В противном случае она должна вернуть `false`."
|
||||
},
|
||||
"$reverse": {
|
||||
"args":"array",
|
||||
"desc":"Возвращает массив, содержащий все значения из параметра `array`, но в обратном порядке."
|
||||
},
|
||||
"$shuffle": {
|
||||
"args":"array",
|
||||
"desc":"Возвращает массив, содержащий все значения из параметра `array`, но перемешанный в случайном порядке."
|
||||
},
|
||||
"$zip": {
|
||||
"args":"array, ...",
|
||||
"desc":"Возвращает свернутый (сжатый) массив, содержащий сгруппированные массивы значений из аргументов `array1` … `arrayN` по индексам 0, 1, 2...."
|
||||
},
|
||||
"$keys": {
|
||||
"args": "object",
|
||||
"desc": "Возвращает массив, содержащий ключи объекта. Если аргумент является массивом объектов, то возвращаемый массив содержит недублированный список всех ключей из всех объектов."
|
||||
},
|
||||
"$lookup": {
|
||||
"args": "object, key",
|
||||
"desc": "Возвращает значение, связанное с ключом в объекте. Если первый аргумент является массивом объектов, то просходит поиск по всем объектам в массиве, и возвращаются значения, связанные со всеми вхождениями ключа."
|
||||
},
|
||||
"$spread": {
|
||||
"args": "object",
|
||||
"desc": "Разбивает объект, содержащий пары ключ / значение, на массив объектов, каждый из которых имеет одну пару ключ / значение из входного объекта. Если параметр является массивом объектов, то результирующий массив содержит объект для каждой пары ключ / значение из каждого объекта предоставленного массива."
|
||||
},
|
||||
"$merge": {
|
||||
"args": "array<object>",
|
||||
"desc": "Объединяет массив объектов в один объект, содержащий все пары ключ / значение каждого из объектов входного массива. Если какой-либо из входных объектов содержит один и тот же ключ, возвращаемый объект будет содержать значение последнего в массиве. Вызывает ошибку, если входной массив содержит элемент, который не является объектом."
|
||||
},
|
||||
"$sift": {
|
||||
"args":"object, function",
|
||||
"desc":"Возвращает объект, который содержит только пары ключ / значение из параметра `object`, которые удовлетворяют предикату `function`, переданному в качестве второго параметра.\n\n`function`, которая передается в качестве второго параметра, должна иметь следующую сигнатуру:\n\n`function(value [, key [, object]])`"
|
||||
},
|
||||
"$each": {
|
||||
"args":"object, function",
|
||||
"desc":"Возвращает массив, который содержит значения, возвращаемые функцией `function` при применении к каждой паре ключ/значение из объекта `object`."
|
||||
},
|
||||
"$map": {
|
||||
"args":"array, function",
|
||||
"desc":"Возвращает массив, содержащий результаты применения функции `function` к каждому значению массива `array`.\n\nФункция `function`, указанная в качестве второго параметра, должна иметь следующую сигнатуру:\n\n`function(value [, index [, array]])`"
|
||||
},
|
||||
"$filter": {
|
||||
"args":"array, function",
|
||||
"desc":"Возвращает массив, содержащий только те значения из массива `array`, которые удовлетворяют предикату `function`.\n\nФункция `function`, указанная в качестве второго параметра, должна иметь следующую сигнатуру:\n\n`function(value [, index [, array]])`"
|
||||
},
|
||||
"$reduce": {
|
||||
"args":"array, function [, init]",
|
||||
"desc":"Возвращает агрегированное значение, полученное в результате последовательного применения функции `function` к каждому значению в массиве в сочетании с результатом от предыдущего применения функции.\n\nФункция должна принимать два аргумента и вести себя как инфиксный оператор между каждым значением в массиве `array`. Сигнатура `function` должна иметь форму: `myfunc($accumulator, $value[, $index[, $array]])`\n\nНеобязательный параметр `init` используется в качестве начального значения в агрегации."
|
||||
},
|
||||
"$flowContext": {
|
||||
"args": "string[, string]",
|
||||
"desc": "Извлекает свойство контекста потока.\n\nЭто функция от Node-RED."
|
||||
},
|
||||
"$globalContext": {
|
||||
"args": "string[, string]",
|
||||
"desc": "Извлекает свойство глобального контекста.\n\nЭто функция от Node-RED."
|
||||
},
|
||||
"$pad": {
|
||||
"args": "string, width [, char]",
|
||||
"desc": "Возвращает копию строки `string` с дополнительным заполнением, если необходимо, чтобы общее количество символов как минимум соответствовало абсолютному значению параметра `width`.\n\nЕсли `width` является положительным числом, то строка дополняется справа; если отрицательным, то дополняется слева.\n\nНеобязательный аргумент `char` указывает символ(ы) для заполнения. Если не указано, по умолчанию используется пробел."
|
||||
},
|
||||
"$fromMillis": {
|
||||
"args": "number",
|
||||
"desc": "Преобразует число, представляющее миллисекунды с начала Unix-эпохи (1 января 1970 года по Гринвичу), в строку отметки времени в формате ISO 8601."
|
||||
},
|
||||
"$formatNumber": {
|
||||
"args": "number, picture [, options]",
|
||||
"desc": "Преобразует число `number` в строку и форматирует ее в десятичное представление, как указано в строке `picture`.\n\nПоведение этой функции соответствует XPath/XQuery-функции fn:format-number, как определено в спецификация XPath F&O 3.1. Строка `picture` определяет, как форматируется число и имеет тот же синтаксис, что и fn:format-number.\n\nНеобязательный третий аргумент `options` используется для переопределения символов форматирования, специфичных для локали по умолчанию, таких как десятичный разделитель. Если аргумент указан, то это должен быть объект, содержащий пары имя/значение, указанные в разделе десятичного формата спецификации XPath F&O 3.1."
|
||||
},
|
||||
"$formatBase": {
|
||||
"args": "number [, radix]",
|
||||
"desc": "Преобразует число `number` в строку и форматирует ее в целое число, представленное в системе счисления, указанной аргументом `radix`. Если `radix` не указан, то по умолчанию используется десятичная. Значение 'radix` может быть от 2 до 36, в противном случае выдается ошибка."
|
||||
},
|
||||
"$toMillis": {
|
||||
"args": "timestamp",
|
||||
"desc": "Преобразует строку `timestamp` в формате ISO 8601 в число миллисекунд с начала Unix-эпохи (1 января 1970 года по Гринвичу). Вызывает ошибку, если строка в неправильном формате."
|
||||
},
|
||||
"$env": {
|
||||
"args": "arg",
|
||||
"desc": "Возвращает значение переменной среды.\n\nЭто функция от Node-RED."
|
||||
},
|
||||
"$eval": {
|
||||
"args": "expr [, context]",
|
||||
"desc": "Анализирует и исполняет строку `expr`, которая содержит JSON или выражение JSONata, используя текущий контекст в качестве контекста для исполнения."
|
||||
},
|
||||
"$formatInteger": {
|
||||
"args": "number, picture",
|
||||
"desc": "Преобразует число `number` в строку и форматирует ее в целочисленное представление, как указано в строке `picture`. Строка `picture` определяет, как форматируется число и имеет тот же синтаксис, что и `fn:format-integer` из спецификации XPath F&O 3.1."
|
||||
},
|
||||
"$parseInteger": {
|
||||
"args": "string, picture",
|
||||
"desc": "Разбирает содержимое строки `string` в целое число (как число JSON), используя формат, указанный в строке `picture`. Строковый параметр `picture` имеет тот же формат, что и `$formatInteger`."
|
||||
},
|
||||
"$error": {
|
||||
"args": "[str]",
|
||||
"desc": "Вызывает ошибку с сообщением. Необязательная строка `str` заменяет сообщение по умолчанию $error() function evaluated`"
|
||||
},
|
||||
"$assert": {
|
||||
"args": "arg, str",
|
||||
"desc": "Если значение `arg` равно true, функция возвращает значение undefined. Если значение `arg` равно false, генерируется исключение с `str` в качестве сообщения об исключении."
|
||||
},
|
||||
"$single": {
|
||||
"args": "array, function",
|
||||
"desc": "Возвращает одно-единственное значение из массива `array`, которое удовлетворяет предикату `function` (то есть когда `function` возвращает логическое `true` при передаче значения). Выдает исключение, если число подходящих значений не одно.\n\nФункция должна соответствовать следующей сигнатуре: `function(value [, index [, array]])` где value - элемент массива, index - позиция этого значения, а весь массив передается в качестве третьего аргумента"
|
||||
},
|
||||
"$encodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "Кодирует компонент Uniform Resource Locator (URL), заменяя каждый экземпляр определенных символов одной, двумя, тремя или четырьмя escape-последовательностями, представляющими кодировку UTF-8 символа.\n\nПример: `$encodeUrlComponent(\"?x=test\")` => `\"%3Fx%3Dtest\"`"
|
||||
},
|
||||
"$encodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "Кодирует Uniform Resource Locator (URL), заменяя каждый экземпляр определенных символов одной, двумя, тремя или четырьмя escape-последовательностями, представляющими кодировку UTF-8 символа.\n\nПример: `$encodeUrl(\"https://mozilla.org/?x=шеллы\")` => `\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\"`"
|
||||
},
|
||||
"$decodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "Декодирует компонент Uniform Resource Locator (URL), ранее созданный с помощью encodeUrlComponent.\n\nПример: `$decodeUrlComponent(\"%3Fx%3Dtest\")` => `\"?x=test\"`"
|
||||
},
|
||||
"$decodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "Декодирует компонент Uniform Resource Locator (URL), ранее созданный с помощью encodeUrl. \n\nПример: `$decodeUrl(\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\")` => `\"https://mozilla.org/?x=шеллы\"`"
|
||||
},
|
||||
"$distinct": {
|
||||
"args": "array",
|
||||
"desc": "Возвращает массив содержащий все элементы из массива `array`, с удаленными дупликатами"
|
||||
},
|
||||
"$type": {
|
||||
"args": "value",
|
||||
"desc": "Возвращает тип значения `value` в виде строки. Если `value` не определено, то будет возвращено `undefined`"
|
||||
},
|
||||
"$moment": {
|
||||
"args": "[str]",
|
||||
"desc": "Получает date объект, используя библиотеку Moment."
|
||||
}
|
||||
}
|
||||
@@ -10,19 +10,53 @@
|
||||
"load": "读取",
|
||||
"save": "保存",
|
||||
"import": "导入",
|
||||
"export": "导出"
|
||||
"export": "导出",
|
||||
"back": "后退",
|
||||
"next": "下一个",
|
||||
"clone": "克隆项目",
|
||||
"cont": "继续",
|
||||
"style": "风格",
|
||||
"line": "大纲",
|
||||
"fill": "填充",
|
||||
"label": "标签",
|
||||
"color": "颜色",
|
||||
"position": "位置",
|
||||
"enable": "启用",
|
||||
"disable": "禁用",
|
||||
"upload": "上传"
|
||||
},
|
||||
"type": {
|
||||
"string": "字符串",
|
||||
"number": "数字",
|
||||
"boolean": "布尔值",
|
||||
"array": "数组",
|
||||
"buffer": "buffer",
|
||||
"object": "对象",
|
||||
"jsonString": "JSON字符串",
|
||||
"undefined": "未定义",
|
||||
"null": "空"
|
||||
}
|
||||
},
|
||||
"event": {
|
||||
"loadPalette": "加载控制板",
|
||||
"loadNodeCatalogs": "加载节点目录",
|
||||
"loadNodes": "加载 __count__ 个节点",
|
||||
"loadFlows": "加载流程",
|
||||
"importFlows": "往工作区中加载流程"
|
||||
},
|
||||
"workspace": {
|
||||
"defaultName": "流程 __number__",
|
||||
"editFlow": "编辑流程: __name__",
|
||||
"confirmDelete": "确认删除",
|
||||
"delete": "你确定想删除 '__label__'?",
|
||||
"delete": "你确定要删除 __label__ ?",
|
||||
"dropFlowHere": "把流程放到这里",
|
||||
"addFlow": "添加流程",
|
||||
"listFlows": "流程一览",
|
||||
"status": "状态",
|
||||
"enabled": "有效",
|
||||
"disabled": "无效",
|
||||
"info": "详细描述"
|
||||
"info": "详细描述",
|
||||
"selectNodes": "点击节点来选择"
|
||||
},
|
||||
"menu": {
|
||||
"label": {
|
||||
@@ -36,11 +70,16 @@
|
||||
"defaultDir": "默认方向",
|
||||
"ltr": "从左到右",
|
||||
"rtl": "从右到左",
|
||||
"auto": "上下文"
|
||||
"auto": "上下文",
|
||||
"language": "语言",
|
||||
"browserDefault": "浏览器默认"
|
||||
},
|
||||
"sidebar": {
|
||||
"show": "显示侧边栏"
|
||||
},
|
||||
"palette": {
|
||||
"show": "显示控制板"
|
||||
},
|
||||
"settings": "设置",
|
||||
"userSettings": "用户设置",
|
||||
"nodes": "节点",
|
||||
@@ -62,9 +101,26 @@
|
||||
"logout": "退出",
|
||||
"editPalette": "节点管理",
|
||||
"other": "其他",
|
||||
"showTips": "显示小提示"
|
||||
"showTips": "显示小提示",
|
||||
"help": "Node-RED网页",
|
||||
"projects": "项目",
|
||||
"projects-new": "新建",
|
||||
"projects-open": "打开",
|
||||
"projects-settings": "项目设定",
|
||||
"showNodeLabelDefault": "显示新添加的节点的标签",
|
||||
"groups": "组",
|
||||
"groupSelection": "选择组",
|
||||
"ungroupSelection": "取消选择组",
|
||||
"groupMergeSelection": "合并选择",
|
||||
"groupRemoveSelection": "从组中移除"
|
||||
}
|
||||
},
|
||||
"actions": {
|
||||
"toggle-navigator": "切换导航器",
|
||||
"zoom-out": "缩小",
|
||||
"zoom-reset": "重设缩放",
|
||||
"zoom-in": "放大"
|
||||
},
|
||||
"user": {
|
||||
"loggedInAs": "作为 __name__ 登陆",
|
||||
"username": "账号",
|
||||
@@ -82,43 +138,113 @@
|
||||
"warning": "<strong>警告</strong>: __message__",
|
||||
"warnings": {
|
||||
"undeployedChanges": "节点中存在未部署的更改",
|
||||
"nodeActionDisabled": "节点操作已禁用",
|
||||
"nodeActionDisabledSubflow": "节点动作在子流程中被禁用",
|
||||
"missing-types": "流程由于缺少节点类型而停止。请检查日志的详细信息",
|
||||
"restartRequired": "Node-RED必须重新启动,以启用升级的模块"
|
||||
"safe-mode": "<p>流程以安全模式停止。</p><p>您可以修改流程并部署更改以重新启动。</p>",
|
||||
"restartRequired": "Node-RED必须重新启动,以启用升级的模块",
|
||||
"credentials_load_failed": "<p>由于无法解密凭据,因此流程停止。</p><p>流程凭据文件已加密,但是项目的加密密钥丢失或无效。</p>",
|
||||
"credentials_load_failed_reset": "<p>凭据无法解密</p><p>流凭据文件已加密,但是项目的加密密钥丢失或无效。</p><p>流凭据文件将在下一次部署时重置。任何现有的流凭证将被清除。</p>",
|
||||
"missing_flow_file": "<p>找不到项目流程文件。</p><p>该项目未配置流程文件。</p>",
|
||||
"missing_package_file": "<p>找不到项目包文件。</p><p>项目缺少package.json文件。</p>",
|
||||
"project_empty": "<p>该项目为空。</p><p>是否要创建一组默认的项目文件?<br/>否则,您将必须在编辑器外部手动将文件添加到项目中。</p>",
|
||||
"project_not_found": "<p>未找到项目 __project__ 。</p>",
|
||||
"git_merge_conflict": "<p>自动合并更改失败。</p><p>修复未合并的冲突,然后提交结果。</p>"
|
||||
},
|
||||
"error": "<strong>Error</strong>: __message__",
|
||||
"error": "<strong>错误</strong>: __message__",
|
||||
"errors": {
|
||||
"lostConnection": "丢失与服务器的连接,重新连接...",
|
||||
"lostConnectionReconnect": "丢失与服务器的连接, __time__ 秒后重新连接",
|
||||
"lostConnectionTry": "现在尝试",
|
||||
"cannotAddSubflowToItself": "无法向其自身添加子流程",
|
||||
"cannotAddCircularReference": "无法添加子流程 - 循环引用",
|
||||
"unsupportedVersion": "您正在使用不受支持的Node.js版本<br/>请升级到最新版本的Node.js LTS"
|
||||
"unsupportedVersion": "您正在使用不受支持的Node.js版本<br/>请升级到最新版本的Node.js LTS",
|
||||
"failedToAppendNode": "<p>'__module__'加载失败</p><p>__error__</p>"
|
||||
},
|
||||
"project": {
|
||||
"change-branch": "转到本地分支'__project__'",
|
||||
"merge-abort": "Git合并中止",
|
||||
"loaded": "项目'__project__'已加载",
|
||||
"updated": "项目'__project__'已更新",
|
||||
"pull": "项目'__project__'已重新加载",
|
||||
"revert": "项目 '__project__'已还原",
|
||||
"merge-complete": "Git合并完成",
|
||||
"setupCredentials": "设定证书",
|
||||
"setupProjectFiles": "设置项目文件",
|
||||
"no": "不了,谢谢",
|
||||
"createDefault": "创建默认项目文件",
|
||||
"mergeConflict": "显示合并冲突"
|
||||
},
|
||||
"label": {
|
||||
"manage-project-dep": "管理项目依赖性",
|
||||
"setup-cred": "设定证书",
|
||||
"setup-project": "设置项目文件",
|
||||
"create-default-package": "创建默认的包文件",
|
||||
"no-thanks": "不了,谢谢",
|
||||
"create-default-project": "创建默认项目文件",
|
||||
"show-merge-conflicts": "显示合并冲突"
|
||||
}
|
||||
},
|
||||
"clipboard": {
|
||||
"clipboard": "剪贴板",
|
||||
"nodes": "节点",
|
||||
"node": "__count__ 个节点",
|
||||
"node_plural": "__count__ 个节点",
|
||||
"configNode": "__count__ 个配置节点",
|
||||
"configNode_plural": "__count__ 个配置节点",
|
||||
"group": "__count__ 个组",
|
||||
"group_plural": "__count__ 个组",
|
||||
"flow": "__count__ 个流程",
|
||||
"flow_plural": "__count__ 个流程",
|
||||
"subflow": "__count__ 个子流程",
|
||||
"subflow_plural": "__count__ 子流程",
|
||||
"replacedNodes": "__count__ 个节点被置换",
|
||||
"replacedNodes_plural": "__count__ 个节点被置换",
|
||||
"pasteNodes": "在这里粘贴节点",
|
||||
"selectFile": "选择要导入的文件",
|
||||
"importNodes": "导入节点",
|
||||
"exportNodes": "导出节点至剪贴板",
|
||||
"download": "下载",
|
||||
"importUnrecognised": "导入了无法识别的类型:",
|
||||
"importUnrecognised_plural": "导入了无法识别的类型:",
|
||||
"nodesExported": "节点导出到了剪贴板",
|
||||
"nodesImported": "导入:",
|
||||
"nodeCopied": "已复制 __count__ 个节点",
|
||||
"nodeCopied_plural": "已复制 __count__ 个节点",
|
||||
"groupCopied": "复制 __count__ 个组",
|
||||
"groupCopied_plural": "已复制 __count__ 个groups",
|
||||
"groupStyleCopied": "已复制组风格",
|
||||
"invalidFlow": "无效的流程: __message__",
|
||||
"recoveredNodes": "复原的节点",
|
||||
"recoveredNodesInfo": "导入节点时,此流上的节点缺少有效的流ID。 它们已被添加到此流中,您可以复原或删除它们。",
|
||||
"recoveredNodesNotification": "<p>导入的节点缺少有效的流ID</p><p>已将它们添加到名为 '__flowName__'的新流中。</p>",
|
||||
"export": {
|
||||
"selected": "已选择的节点",
|
||||
"current": "现在的节点",
|
||||
"all": "所有流程",
|
||||
"compact": "紧凑",
|
||||
"formatted": "已格式化",
|
||||
"copy": "导出到剪贴板"
|
||||
"copy": "导出到剪贴板",
|
||||
"export": "到处到库",
|
||||
"exportAs": "导出为",
|
||||
"overwrite": "替换",
|
||||
"exists": "<p><b>\"__file__\"</b>已存在</p><p>是否要替换它?</p>"
|
||||
},
|
||||
"import": {
|
||||
"import": "导入到",
|
||||
"newFlow": "新流程"
|
||||
"importSelected": "导入所选项",
|
||||
"importCopy": "导入副本",
|
||||
"viewNodes": "查看节点",
|
||||
"newFlow": "新流程",
|
||||
"replace": "置换",
|
||||
"errors": {
|
||||
"notArray": "输入的不是JSON数组",
|
||||
"itemNotObject": "输入的流无效 - 项目 __index__ 不是节点对象",
|
||||
"missingId": "输入的流无效-项 __index__ 缺少'id'属性",
|
||||
"missingType": "输入的流程无效-项 __index__ 缺少'类型'属性"
|
||||
},
|
||||
"conflictNotification1": "您要导入的某些节点已经存在于工作空间中。",
|
||||
"conflictNotification2": "选择要导入的节点,并确认要替换现有的节点还是导入它们的副本"
|
||||
},
|
||||
"copyMessagePath": "已复制路径",
|
||||
"copyMessageValue": "已复制数值",
|
||||
@@ -132,7 +258,10 @@
|
||||
"modifiedFlowsDesc": "只部署包含已更改节点的流",
|
||||
"modifiedNodes": "已更改的节点",
|
||||
"modifiedNodesDesc": "只部署已经更改的节点",
|
||||
"restartFlows": "重启流程",
|
||||
"restartFlowsDesc": "重新启动当前部署的流程",
|
||||
"successfulDeploy": "部署成功",
|
||||
"successfulRestart": "成功重启流程",
|
||||
"deployFailed": "部署失败: __message__",
|
||||
"unusedConfigNodes": "您有一些未使用的配置节点",
|
||||
"unusedConfigNodesLink": "点击此处查看它们",
|
||||
@@ -152,16 +281,24 @@
|
||||
"improperlyConfigured": "工作区包含一些未正确配置的节点:",
|
||||
"unknown": "工作区包含一些未知的节点类型:",
|
||||
"confirm": "你确定要部署吗?",
|
||||
"doNotWarn": "不要再对此发出警告",
|
||||
"conflict": "服务器正在运行较新的一组流程。",
|
||||
"backgroundUpdate": "服务器上的流程已更新。",
|
||||
"conflictChecking": "检查是否可以自动合并更改",
|
||||
"conflictAutoMerge": "此更改不包括冲突,可以自动合并",
|
||||
"conflictManualMerge": "这些更改包括了在部署之前必须解决的冲突。"
|
||||
"conflictManualMerge": "这些更改包括了在部署之前必须解决的冲突。",
|
||||
"plusNMore": "+ __count__ 更多"
|
||||
}
|
||||
},
|
||||
"eventLog": {
|
||||
"title": "事件记录日志",
|
||||
"view": "查看日志"
|
||||
},
|
||||
"diff": {
|
||||
"unresolvedCount": "__count__个未解决的冲突",
|
||||
"unresolvedCount_plural": "__count__个未解决的冲突",
|
||||
"globalNodes": "全局节点",
|
||||
"flowProperties": "流程属性",
|
||||
"type": {
|
||||
"added": "已添加",
|
||||
"changed": "已更改",
|
||||
@@ -175,23 +312,46 @@
|
||||
"nodeCount": "__count__个节点",
|
||||
"nodeCount_plural": "__count__个节点",
|
||||
"local": "本地",
|
||||
"remote": "远程"
|
||||
"remote": "远程",
|
||||
"reviewChanges": "查看变更",
|
||||
"noBinaryFileShowed": "无法显示二进制文件内容",
|
||||
"viewCommitDiff": "查看提交更改",
|
||||
"compareChanges": "比较变更",
|
||||
"saveConflict": "保存冲突解决",
|
||||
"conflictHeader": "已解决<span>__unresolved__</span>中的<span>__resolved__</span>个冲突",
|
||||
"commonVersionError": "通用版本不包含有效的JSON:",
|
||||
"oldVersionError": "旧版本不包含有效的JSON:",
|
||||
"newVersionError": "新版本不包含有效的JSON:"
|
||||
},
|
||||
"subflow": {
|
||||
"editSubflow": "编辑流程模板: __name__",
|
||||
"editSubflowInstance": "编辑子流实例: __name__",
|
||||
"editSubflow": "编辑流程模板: __name__",
|
||||
"edit": "编辑流程模板",
|
||||
"subflowInstances": "这个子流程模板有 __count__ 个实例",
|
||||
"subflowInstances_plural": "这个子流程模板有 __count__ 个实例",
|
||||
"editSubflowProperties": "编辑属性",
|
||||
"input": "输入:",
|
||||
"output": "输出:",
|
||||
"status": "状态节点",
|
||||
"deleteSubflow": "删除子流程",
|
||||
"info": "详细描述",
|
||||
"category": "类别",
|
||||
"env": {
|
||||
"restore": "恢复为默认子流",
|
||||
"remove": "删除环境变量"
|
||||
},
|
||||
"errors": {
|
||||
"noNodesSelected": "<strong>无法创建子流程</strong>: 未选择节点",
|
||||
"multipleInputsToSelection": "<strong>无法创建子流程</strong>: 多个输入到了选择"
|
||||
}
|
||||
},
|
||||
"group": {
|
||||
"editGroup": "编辑组: __name__",
|
||||
"errors": {
|
||||
"cannotCreateDiffGroups": "无法使用来自不同组的节点创建组",
|
||||
"cannotAddSubflowPorts": "无法将子流程的端口添加到组"
|
||||
}
|
||||
},
|
||||
"editor": {
|
||||
"configEdit": "编辑",
|
||||
"configAdd": "添加",
|
||||
@@ -204,18 +364,70 @@
|
||||
"editConfig": "编辑 __type__ 配置",
|
||||
"addNewType": "添加新的 __type__ 节点",
|
||||
"nodeProperties": "节点属性",
|
||||
"label": "标签",
|
||||
"color": "颜色",
|
||||
"portLabels": "端口标签",
|
||||
"labelInputs": "输入",
|
||||
"labelOutputs": "输出",
|
||||
"settingIcon": "图标",
|
||||
"default": "默认",
|
||||
"noDefaultLabel": "无",
|
||||
"defaultLabel": "使用默认标签",
|
||||
"searchIcons": "搜索图标",
|
||||
"useDefault": "使用默认",
|
||||
"description": "描述",
|
||||
"show": "显示",
|
||||
"hide": "隐藏",
|
||||
"locale": "选择界面语言",
|
||||
"icon": "图标",
|
||||
"inputType": "输入类型",
|
||||
"selectType": "选择类型...",
|
||||
"inputs": {
|
||||
"input": "输入",
|
||||
"select": "选择",
|
||||
"checkbox": "复选框",
|
||||
"spinner": "微调器",
|
||||
"none": "空",
|
||||
"hidden": "隐藏属性"
|
||||
},
|
||||
"types": {
|
||||
"str": "字符串",
|
||||
"num": "数字",
|
||||
"bool": "布尔",
|
||||
"json": "JSON",
|
||||
"bin": "buffer",
|
||||
"env": "环境变量",
|
||||
"cred": "证书"
|
||||
},
|
||||
"menu": {
|
||||
"input": "输入",
|
||||
"select": "选择",
|
||||
"checkbox": "复选框",
|
||||
"spinner": "微调器",
|
||||
"hidden": "仅标签"
|
||||
},
|
||||
"select": {
|
||||
"label": "标签",
|
||||
"value": "值"
|
||||
},
|
||||
"spinner": {
|
||||
"min": "最小值",
|
||||
"max": "最大值"
|
||||
},
|
||||
"errors": {
|
||||
"scopeChange": "更改范围将使其他流中的节点无法使用"
|
||||
"scopeChange": "更改范围将使其他流中的节点无法使用",
|
||||
"invalidProperties": "无效的属性:"
|
||||
}
|
||||
},
|
||||
"keyboard": {
|
||||
"title": "键盘快捷键",
|
||||
"keyboard": "键盘",
|
||||
"filterActions": "筛选动作",
|
||||
"shortcut": "快捷键",
|
||||
"scope": "范围",
|
||||
"unassigned": "未分配",
|
||||
"global": "全局",
|
||||
"workspace": "工作区",
|
||||
"selectAll": "选择所有节点",
|
||||
"selectAllConnected": "选择所有连接的节点",
|
||||
"addRemoveNode": "从选择中添加/删除节点",
|
||||
@@ -226,12 +438,14 @@
|
||||
"nudgeNode": "移动所选节点(1px)",
|
||||
"moveNode": "移动所选节点(20px)",
|
||||
"toggleSidebar": "切换侧边栏",
|
||||
"togglePalette": "切换控制板",
|
||||
"copyNode": "复制所选节点",
|
||||
"cutNode": "剪切所选节点",
|
||||
"pasteNode": "粘贴节点",
|
||||
"undoChange": "撤消上次执行的更改",
|
||||
"searchBox": "打开搜索框",
|
||||
"managePalette": "管理面板"
|
||||
"managePalette": "管理面板",
|
||||
"actionList": "动作列表"
|
||||
},
|
||||
"library": {
|
||||
"library": "库",
|
||||
@@ -239,30 +453,42 @@
|
||||
"saveToLibrary": "保存到库...",
|
||||
"typeLibrary": "__type__类型库",
|
||||
"unnamedType": "无名__type__",
|
||||
"exportToLibrary": "将节点导出到库",
|
||||
"exportedToLibrary": "节点导出到库",
|
||||
"dialogSaveOverwrite": "一个叫做__libraryName__的__libraryType__已经存在,您需要覆盖么?",
|
||||
"invalidFilename": "无效的文件名",
|
||||
"savedNodes": "保存的节点",
|
||||
"savedType": "已保存__type__",
|
||||
"saveFailed": "保存失败: __message__",
|
||||
"newFolder": "新文件夹",
|
||||
"types": {
|
||||
"local": "本地的",
|
||||
"examples": "例子"
|
||||
}
|
||||
},
|
||||
"exportToLibrary": "将节点导出到库"
|
||||
},
|
||||
"palette": {
|
||||
"noInfo": "无可用信息",
|
||||
"filter": "过滤节点",
|
||||
"search": "搜索模块",
|
||||
"addCategory": "添加新的...",
|
||||
"label": {
|
||||
"subflows": "子流程",
|
||||
"network": "网络",
|
||||
"common": "共通",
|
||||
"input": "输入",
|
||||
"output": "输出",
|
||||
"function": "功能",
|
||||
"sequence": "序列",
|
||||
"parser": "解析",
|
||||
"social": "社交",
|
||||
"storage": "存储",
|
||||
"analysis": "分析",
|
||||
"advanced": "高级"
|
||||
},
|
||||
"actions": {
|
||||
"collapse-all": "收起所有类别",
|
||||
"expand-all": "展开所有类别"
|
||||
},
|
||||
"event": {
|
||||
"nodeAdded": "添加到面板中的节点:",
|
||||
"nodeAdded_plural": "添加到面板中的多个节点",
|
||||
@@ -276,6 +502,7 @@
|
||||
},
|
||||
"editor": {
|
||||
"title": "面板管理",
|
||||
"palette": "控制板",
|
||||
"times": {
|
||||
"seconds": "秒前",
|
||||
"minutes": "分前",
|
||||
@@ -309,6 +536,8 @@
|
||||
"updated": "已更新",
|
||||
"install": "安装",
|
||||
"installed": "已安装",
|
||||
"conflict": "冲突",
|
||||
"conflictTip": "<p>无法安装此模块,因为它包含已安装的<br/>节点类型</p><p>与<code>__module__</code>冲突</p>",
|
||||
"loading": "加载目录...",
|
||||
"tab-nodes": "节点",
|
||||
"tab-install": "安装",
|
||||
@@ -316,6 +545,7 @@
|
||||
"sortAZ": "a-z顺序",
|
||||
"sortRecent": "日期顺序",
|
||||
"more": "增加 __count__ 个",
|
||||
"upload": "上传模块tgz文件",
|
||||
"errors": {
|
||||
"catalogLoadFailed": "无法加载节点目录。<br>查看浏览器控制台了解更多信息",
|
||||
"installFailed": "无法安装: __module__<br>__message__<br>查看日志了解更多信息",
|
||||
@@ -356,6 +586,8 @@
|
||||
"label": "信息",
|
||||
"node": "节点",
|
||||
"type": "类型",
|
||||
"group": "组",
|
||||
"module": "模组",
|
||||
"id": "ID",
|
||||
"status": "状态",
|
||||
"enabled": "启用",
|
||||
@@ -364,6 +596,7 @@
|
||||
"instances": "实例",
|
||||
"properties": "属性",
|
||||
"info": "信息",
|
||||
"desc": "描述",
|
||||
"blank": "空白",
|
||||
"null": "空",
|
||||
"showMore": "展开",
|
||||
@@ -376,7 +609,29 @@
|
||||
"nodeHelp": "节点帮助",
|
||||
"none": "无",
|
||||
"arrayItems": "__count__ 个项目",
|
||||
"showTips": "您可以从设置面板启用提示信息"
|
||||
"showTips": "您可以从设置面板启用提示信息",
|
||||
"outline": "大纲",
|
||||
"empty": "空的",
|
||||
"globalConfig": "全局配置节点",
|
||||
"triggerAction": "触发动作",
|
||||
"find": "在工作区中查找",
|
||||
"search": {
|
||||
"configNodes": "配置节点",
|
||||
"unusedConfigNodes": "未使用的配置节点",
|
||||
"invalidNodes": "无效的节点",
|
||||
"uknownNodes": "未知的节点",
|
||||
"unusedSubflows": "未使用的子流程"
|
||||
}
|
||||
},
|
||||
"help": {
|
||||
"name": "帮助",
|
||||
"label": "帮助",
|
||||
"search": "搜索帮助",
|
||||
"nodeHelp": "节点帮助",
|
||||
"showHelp": "显示帮助",
|
||||
"showInOutline": "在大纲中显示",
|
||||
"showTopics": "显示主题",
|
||||
"noHelp": "未选择帮助主题"
|
||||
},
|
||||
"config": {
|
||||
"name": "配置节点",
|
||||
@@ -385,10 +640,26 @@
|
||||
"none": "无",
|
||||
"subflows": "子流程",
|
||||
"flows": "流程",
|
||||
"filterUnused": "未使用",
|
||||
"filterAll": "所有",
|
||||
"showAllConfigNodes": "显示所有配置节点",
|
||||
"filterUnused": "未使用",
|
||||
"showAllUnusedConfigNodes": "显示所有未使用的配置节点",
|
||||
"filtered": "__count__ 个隐藏"
|
||||
},
|
||||
"context": {
|
||||
"name": "上下文数据",
|
||||
"label": "上下午",
|
||||
"none": "未选择",
|
||||
"refresh": "刷新以加载",
|
||||
"empty": "空",
|
||||
"node": "节点",
|
||||
"flow": "流程",
|
||||
"global": "全局",
|
||||
"deleteConfirm": "你确定要删除这个项目吗?",
|
||||
"autoRefresh": "刷新选择更改",
|
||||
"refrsh": "刷新",
|
||||
"delete": "删除"
|
||||
},
|
||||
"palette": {
|
||||
"name": "节点管理",
|
||||
"label": "节点"
|
||||
@@ -399,8 +670,157 @@
|
||||
"description": "描述",
|
||||
"dependencies": "依赖",
|
||||
"settings": "设置",
|
||||
"noSummaryAvailable": "无可用摘要",
|
||||
"editDescription": "编辑项目描述",
|
||||
"editDependencies": "编辑项目依赖"
|
||||
"editDependencies": "编辑项目依赖",
|
||||
"noDescriptionAvailable": "没有可用的描述",
|
||||
"editReadme": "编辑README.md",
|
||||
"showProjectSettings": "显示项目设置",
|
||||
"projectSettings": {
|
||||
"title": "项目设置",
|
||||
"edit": "编辑",
|
||||
"none": "空",
|
||||
"install": "安装",
|
||||
"removeFromProject": "从项目中删除",
|
||||
"addToProject": "添加到项目",
|
||||
"files": "文件",
|
||||
"flow": "流程",
|
||||
"credentials": "证书",
|
||||
"package": "包",
|
||||
"packageCreate": "保存更改后将创建文件",
|
||||
"fileNotExist": "文件不存在",
|
||||
"selectFile": "选择文件",
|
||||
"invalidEncryptionKey": "无效的加密密钥",
|
||||
"encryptionEnabled": "启用加密",
|
||||
"encryptionDisabled": "加密已禁用",
|
||||
"setTheEncryptionKey": "设置加密密钥",
|
||||
"resetTheEncryptionKey": "重置加密密钥",
|
||||
"changeTheEncryptionKey": "更改加密密钥",
|
||||
"currentKey": "当前密钥",
|
||||
"newKey": "新密钥",
|
||||
"credentialsAlert": "这将删除所有现有证书",
|
||||
"versionControl": "版本控制",
|
||||
"branches": "分支",
|
||||
"noBranches": "没有分支",
|
||||
"deleteConfirm": "您确定要删除本地分支'__name__'吗? 这不能被撤消。",
|
||||
"unmergedConfirm": "本地分支'__name__'具有未合并的更改,这些更改将丢失。你确定要删除吗?",
|
||||
"deleteUnmergedBranch": "删除未合并的分支",
|
||||
"gitRemotes": "Git远程仓库",
|
||||
"addRemote": "添加远程仓库",
|
||||
"addRemote2": "添加远程仓库",
|
||||
"remoteName": "远程仓库名",
|
||||
"nameRule": "只能包含A-Z 0-9 _ -",
|
||||
"url": "URL",
|
||||
"urlRule": "https://, ssh:// or file://",
|
||||
"urlRule2": "网址中不能包含用户名/密码",
|
||||
"noRemotes": "没有远程仓库",
|
||||
"deleteRemoteConfrim": "您确定要删除远程仓库'__name__'吗?",
|
||||
"deleteRemote": "删除远程仓库"
|
||||
},
|
||||
"userSettings": {
|
||||
"committerDetail": "提交者详细信息",
|
||||
"committerTip": "保留空白以使用系统默认值",
|
||||
"userName": "用户名",
|
||||
"email": "电子邮件",
|
||||
"workflow": "工作流",
|
||||
"workfowTip": "选择您偏好的工作流",
|
||||
"workflowManual": "手动",
|
||||
"workflowManualTip": "所有更改都必须在“历史记录”侧边栏中手动提交",
|
||||
"workflowAuto": "自动",
|
||||
"workflowAutoTip": "每次部署后都会自动提交更改",
|
||||
"sshKeys": "SSH密钥",
|
||||
"sshKeysTip": "允许您创建到远程git存储库的安全连接。",
|
||||
"add": "添加密钥",
|
||||
"addSshKey": "添加SSH密钥",
|
||||
"addSshKeyTip": "生成新的公钥/私钥对",
|
||||
"name": "名字",
|
||||
"nameRule": "只能包含A-Z 0-9 _ -",
|
||||
"passphrase": "密码短语",
|
||||
"passphraseShort": "密码短语过短",
|
||||
"optional": "可选的",
|
||||
"cancel": "取消",
|
||||
"generate": "生成密钥",
|
||||
"noSshKeys": "没有SSH密钥",
|
||||
"copyPublicKey": "将公钥复制到剪贴板",
|
||||
"delete": "删除密钥",
|
||||
"gitConfig": "Git配置",
|
||||
"deleteConfirm": "您确定要删除SSH密钥 __name__ 吗?这不能被撤消。"
|
||||
},
|
||||
"versionControl": {
|
||||
"unstagedChanges": "未暂存的变更",
|
||||
"stagedChanges": "暂存的变更",
|
||||
"unstageChange": "取消变更的暂存",
|
||||
"stageChange": "暂存变更",
|
||||
"unstageAllChange": "取消所有变更的暂存",
|
||||
"stageAllChange": "暂存所有变更",
|
||||
"commitChanges": "提交变更",
|
||||
"resolveConflicts": "解决冲突",
|
||||
"head": "HEAD",
|
||||
"staged": "暂存的",
|
||||
"unstaged": "未暂存的",
|
||||
"local": "本地的",
|
||||
"remote": "远程的",
|
||||
"revert": "您确定要将更改恢复为'__file__'吗?这不能被撤消。",
|
||||
"revertChanges": "还原变更",
|
||||
"localChanges": "本地变更",
|
||||
"none": "None",
|
||||
"conflictResolve": "解决所有冲突。提交更改以完成合并。",
|
||||
"localFiles": "本地文件",
|
||||
"all": "所有的",
|
||||
"unmergedChanges": "未合并的更改",
|
||||
"abortMerge": "中止合并",
|
||||
"commit": "提交",
|
||||
"changeToCommit": "提交变更",
|
||||
"commitPlaceholder": "输入您的提交信息",
|
||||
"cancelCapital": "取消",
|
||||
"commitCapital": "提交",
|
||||
"commitHistory": "提交历史",
|
||||
"branch": "分支:",
|
||||
"moreCommits": "更多提交",
|
||||
"changeLocalBranch": "变更本地分支",
|
||||
"createBranchPlaceholder": "查找或创建分支",
|
||||
"upstream": "上游",
|
||||
"localOverwrite": "切换分支会覆盖您现有的本地更改。您必须先提交或撤消那些更改。",
|
||||
"manageRemoteBranch": "管理远程分支",
|
||||
"unableToAccess": "无法访问远程存储库",
|
||||
"retry": "重试",
|
||||
"setUpstreamBranch": "设置为上游分支",
|
||||
"createRemoteBranchPlaceholder": "查找或创建远程分支",
|
||||
"trackedUpstreamBranch": "创建的分支将被设置为跟踪的上游分支。",
|
||||
"selectUpstreamBranch": "分支将被创建。 在下面选择以将其设置为被跟踪的上游分支。",
|
||||
"pushFailed": "推送失败,因为远程具有更多的最新提交。请先拉取并合并,然后再尝试推送。",
|
||||
"push": "推送",
|
||||
"pull": "拉取",
|
||||
"unablePull": "<p>无法提取远程更改;您未暂存的本地更改将被覆盖。</p><p>请先提交更改,然后重试。</p>",
|
||||
"showUnstagedChanges": "显示未暂存的更改",
|
||||
"connectionFailed": "无法连接到远程存储库:",
|
||||
"pullUnrelatedHistory": "<p>远程有无关的提交历史</p><p>您确定要将这些更改拉入本地仓库吗?</p>",
|
||||
"pullChanges": "拉取更改",
|
||||
"history": "历史",
|
||||
"projectHistory": "项目历史",
|
||||
"daysAgo": "__count__ 天前",
|
||||
"daysAgo_plural": "__count__ 天前",
|
||||
"hoursAgo": "__count__ 小时前",
|
||||
"hoursAgo_plural": "__count__ 小时前",
|
||||
"minsAgo": "__count__ 分钟前",
|
||||
"minsAgo_plural": "__count__ 分钟前",
|
||||
"secondsAgo": "秒前",
|
||||
"notTracking": "您的本地分支当前未跟踪一个远程分支。",
|
||||
"statusUnmergedChanged": "您的仓库中有未合并的更改。您需要解决冲突并提交结果。",
|
||||
"repositoryUpToDate": "您的仓库是最新的。",
|
||||
"commitsAhead": "您的存储库领先远程仓库 __count__ 次提交。您现在可以推送这些提交。",
|
||||
"commitsAhead_plural": "您的存储库领先远程仓库 __count__ 次提交。您现在可以推送这些提交。",
|
||||
"commitsBehind": "您的存储库落后远程仓库 __count__ 次提交。您现在可以拉取这些提交。",
|
||||
"commitsBehind_plural": "您的存储库落后远程仓库 __count__ 次提交。您现在可以拉取这些提交。",
|
||||
"commitsAheadAndBehind1": "您的存储库落后远程仓库 __count__ 次提交",
|
||||
"commitsAheadAndBehind1_plural": "您的存储库落后远程仓库 __count__ 次提交",
|
||||
"commitsAheadAndBehind2": "领先远程仓库 __count__ 次提交。",
|
||||
"commitsAheadAndBehind2_plural": "领先远程仓库 __count__ 次提交。",
|
||||
"commitsAheadAndBehind3": "您必须先拉取远程提交,然后才能进行推送。",
|
||||
"commitsAheadAndBehind3_plural": "您必须先拉取远程提交,然后才能进行推送。",
|
||||
"refreshCommitHistory": "刷新提交历史",
|
||||
"refreshChanges": "刷新更改"
|
||||
}
|
||||
}
|
||||
},
|
||||
"typedInput": {
|
||||
@@ -408,10 +828,13 @@
|
||||
"str": "文字列",
|
||||
"num": "数字",
|
||||
"re": "正则表达式",
|
||||
"bool": "布尔",
|
||||
"bool": "布尔值",
|
||||
"json": "JSON",
|
||||
"bin": "二进制流",
|
||||
"date": "时间戳"
|
||||
"date": "时间戳",
|
||||
"jsonata": "表达式",
|
||||
"env": "环境变量",
|
||||
"cred": "证书"
|
||||
}
|
||||
},
|
||||
"editableList": {
|
||||
@@ -423,8 +846,10 @@
|
||||
},
|
||||
"expressionEditor": {
|
||||
"functions": "功能",
|
||||
"functionReference": "功能reference",
|
||||
"insert": "插入",
|
||||
"title": "JSONata表达式编辑器",
|
||||
"test": "测试",
|
||||
"data": "示例消息",
|
||||
"result": "结果",
|
||||
"format": "格式表达方法",
|
||||
@@ -438,14 +863,230 @@
|
||||
"eval": "评估表达式错误:\n __message__"
|
||||
}
|
||||
},
|
||||
"jsEditor": {
|
||||
"title": "JavaScript编辑器"
|
||||
},
|
||||
"textEditor": {
|
||||
"title": "文本编辑器"
|
||||
},
|
||||
"jsonEditor": {
|
||||
"title": "JSON编辑器",
|
||||
"format": "格式化JSON"
|
||||
"format": "格式化JSON",
|
||||
"rawMode": "编辑 JSON",
|
||||
"uiMode": "Visual编辑器",
|
||||
"insertAbove": "在上方插入",
|
||||
"insertBelow": "在下方插入",
|
||||
"addItem": "添加项目",
|
||||
"copyPath": "复制路径到项目",
|
||||
"expandItems": "展开项目",
|
||||
"collapseItems": "收合项目",
|
||||
"duplicate": "重复",
|
||||
"error": {
|
||||
"invalidJSON": "无效的JSON: "
|
||||
}
|
||||
},
|
||||
"markdownEditor": {
|
||||
"title": "Markdown编辑器",
|
||||
"expand": "展开",
|
||||
"format": "格式化为markdown",
|
||||
"heading1": "标题 1",
|
||||
"heading2": "标题 2",
|
||||
"heading3": "标题 3",
|
||||
"bold": "粗体",
|
||||
"italic": "斜体",
|
||||
"code": "代码",
|
||||
"ordered-list": "排序的列表",
|
||||
"unordered-list": "非排序的列表",
|
||||
"quote": "引用",
|
||||
"link": "链接",
|
||||
"horizontal-rule": "水平线",
|
||||
"toggle-preview": "切换预览"
|
||||
},
|
||||
"bufferEditor": {
|
||||
"title": "缓冲区编辑器",
|
||||
"modeString": "作为UTF-8字符串处理",
|
||||
"modeArray": "作为JSON数组处理",
|
||||
"modeDesc": "<h3>缓冲区编辑器</h3><p>缓冲区类型被存储为字节值的JSON数组。编辑器将尝试将输入的数值解析为JSON数组。如果它不是有效的JSON,它将被视为UTF-8字符串,并被转换为单个字符代码点的数组。</p><p>例如,<code>Hello World</code>的值会被转换为JSON数组:<pre>[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]</pre></p>"
|
||||
},
|
||||
"projects": {
|
||||
"config-git": "配置Git客户端",
|
||||
"welcome": {
|
||||
"hello": "你好! 我们已经将“项目”引入了Node-RED。",
|
||||
"desc0": "这是一种用于管理流程文件的新方法,并且包括对流程的版本控制。",
|
||||
"desc1": "首先,您可以创建您的第一个项目或从git存储库克隆现有项目。",
|
||||
"desc2": "如果不确定,可以暂时跳过此步骤。您仍然可以随时通过“项目”菜单创建第一个项目。",
|
||||
"create": "建立专案",
|
||||
"clone": "克隆仓库",
|
||||
"openExistingProject": "打开现有项目",
|
||||
"not-right-now": "不是现在"
|
||||
},
|
||||
"git-config": {
|
||||
"setup": "设置您的版本控制客户端",
|
||||
"desc0": "Node-RED使用开源工具Git进行版本控制。它跟踪对项目文件的更改,并允许您将其推送到远程存储库。",
|
||||
"desc1": "提交一组更改时,Git会使用用户名和电子邮件地址记录谁进行了更改。用户名可以是您想要的任何名称-不必是您的真实姓名。",
|
||||
"desc2": "您的Git客户端已经配置了以下详细信息。",
|
||||
"desc3": "您可以稍后在设置对话框的'Git config'标签下更改这些设置。",
|
||||
"username": "用户名",
|
||||
"email": "电子邮件"
|
||||
},
|
||||
"project-details": {
|
||||
"create": "创建你的项目",
|
||||
"desc0": "项目被维护为Git仓库。与他人一起共享您的流程",
|
||||
"desc1": "您可以创建多个项目,并通过编辑器在它们之间快速切换。",
|
||||
"desc2": "首先,您的项目需要一个名称和一个可选的描述。",
|
||||
"already-exists": "项目已存在",
|
||||
"must-contain": "只能包含A-Z 0-9 _ -",
|
||||
"project-name": "项目名",
|
||||
"desc": "描述",
|
||||
"opt": "可选的"
|
||||
},
|
||||
"clone-project": {
|
||||
"clone": "克隆一个项目",
|
||||
"desc0": "如果您已经有一个包含项目的git仓库,则可以对其进行克隆以开始使用。",
|
||||
"already-exists": "项目已存在",
|
||||
"must-contain": "只能包含A-Z 0-9 _ -",
|
||||
"project-name": "项目名",
|
||||
"no-info-in-url": "网址中不要包含用户名/密码",
|
||||
"git-url": "Git仓库的url",
|
||||
"protocols": "https://, ssh:// or file://",
|
||||
"auth-failed": "认证失败",
|
||||
"username": "用户名",
|
||||
"passwd": "秘密啊",
|
||||
"ssh-key": "SSH密钥",
|
||||
"passphrase": "密码短语",
|
||||
"ssh-key-desc": "在通过ssh克隆仓库之前,必须添加SSH密钥才能访问它。",
|
||||
"ssh-key-add": "添加一个ssh密钥",
|
||||
"credential-key": "证书加密密钥",
|
||||
"cant-get-ssh-key": "错误! 无法获取所选的SSH密钥路径。",
|
||||
"already-exists2": "已存在",
|
||||
"git-error": "git错误",
|
||||
"connection-failed": "连接失败",
|
||||
"not-git-repo": "不是一个git仓库",
|
||||
"repo-not-found": "未发现仓库"
|
||||
},
|
||||
"default-files": {
|
||||
"create": "创建您的项目文件",
|
||||
"desc0": "一个包含您的流程文件,Readme文件和package.json文件的项目。",
|
||||
"desc1": "它可以包含您要在Git仓库中维护的任何其他文件。",
|
||||
"desc2": "您现有的流程和凭证文件将被复制到项目中。",
|
||||
"flow-file": "流程文件",
|
||||
"credentials-file": "证书文件"
|
||||
},
|
||||
"encryption-config": {
|
||||
"setup": "设置证书文件的加密",
|
||||
"desc0": "您的流程证书文件可以被加密以确保其内容安全。",
|
||||
"desc1": "如果要将这些证书存储在公共Git存储库中,则必须通过提供密钥短语来对它们进行加密。",
|
||||
"desc2": "您的流程证书文件当前未加密。",
|
||||
"desc3": "这意味着任何有权访问该文件的人都可以读取其内容,例如密码和访问令牌。",
|
||||
"desc4": "如果要将这些证书存储在公共Git仓库中,则必须通过提供密钥短语来对它们进行加密。",
|
||||
"desc5": "当前,使用设置文件中的credentialSecret属性作为密钥来加密流程证书文件。",
|
||||
"desc6": "您的流程证书文件当前使用系统生成的密钥加密。您应该为此项目提供一个新的密钥。",
|
||||
"desc7": "密钥将与项目文件分开存储。您将需要提供在另一个Node-RED实例中使用该项目的密钥。",
|
||||
"credentials": "证书",
|
||||
"enable": "启用加密",
|
||||
"disable": "禁用加密",
|
||||
"disabled": "禁用的",
|
||||
"copy": "复制现有密钥",
|
||||
"use-custom": "使用自定义密钥",
|
||||
"desc8": "证书文件不会被加密,其内容很容易阅读",
|
||||
"create-project-files": "创建项目文件",
|
||||
"create-project": "创建项目",
|
||||
"already-exists": "已存在",
|
||||
"git-error": "git错误",
|
||||
"git-auth-error": "git认证错误"
|
||||
},
|
||||
"create-success": {
|
||||
"success": "您已经成功创建了第一个项目!",
|
||||
"desc0": "现在,您可以像往常一样继续使用Node-RED。",
|
||||
"desc1": "侧栏中的“信息”标签显示了您当前的活动项目。名称旁边的按钮可用于访问项目设置视图。",
|
||||
"desc2": "侧栏中的“历史记录”标签可用于查看项目中已更改的文件并提交。它向您显示了提交的完整历史记录,并允许您将更改推送到远程存储库。"
|
||||
},
|
||||
"create": {
|
||||
"projects": "项目",
|
||||
"already-exists": "项目已存在",
|
||||
"must-contain": "只能包含A-Z 0-9 _ -",
|
||||
"no-info-in-url": "网址中不要包含用户名/密码",
|
||||
"open": "打开项目",
|
||||
"create": "创建项目",
|
||||
"clone": "克隆仓库",
|
||||
"project-name": "项目名",
|
||||
"desc": "描述",
|
||||
"opt": "可选的",
|
||||
"flow-file": "流程文件",
|
||||
"credentials": "证书",
|
||||
"enable-encryption": "启用加密",
|
||||
"disable-encryption": "禁用加密",
|
||||
"encryption-key": "加密密钥",
|
||||
"desc0": "用来保护您的凭证的短语",
|
||||
"desc1": "凭证文件不会被加密,其内容很容易阅读",
|
||||
"git-url": "Git存储库URL",
|
||||
"protocols": "https://, ssh:// or file://",
|
||||
"auth-failed": "验证失败",
|
||||
"username": "用户名",
|
||||
"password": "密码",
|
||||
"ssh-key": "SSH密钥",
|
||||
"passphrase": "密码短语",
|
||||
"desc2": "在通过ssh克隆存储库之前,必须添加SSH密钥才能访问它。",
|
||||
"add-ssh-key": "添加一个ssh密钥",
|
||||
"credentials-encryption-key": "证书加密密钥",
|
||||
"already-exists-2": "已存在",
|
||||
"git-error": "git错误",
|
||||
"con-failed": "连接失败",
|
||||
"not-git": "不是git仓库",
|
||||
"no-resource": "找不到存储库",
|
||||
"cant-get-ssh-key-path": "错误!无法获取所选的SSH密钥路径。",
|
||||
"unexpected_error": "意外的错误"
|
||||
},
|
||||
"delete": {
|
||||
"confirm": "您确定要删除此项目吗?"
|
||||
},
|
||||
"create-project-list": {
|
||||
"search": "搜索您的项目",
|
||||
"current": "当前的"
|
||||
},
|
||||
"require-clean": {
|
||||
"confirm": "<p>您有未部署的更改,这些更改将丢失。</p><p>您要继续吗?</p>"
|
||||
},
|
||||
"send-req": {
|
||||
"auth-req": "存储库需要认证",
|
||||
"username": "用户名",
|
||||
"password": "秘密",
|
||||
"passphrase": "密码短语",
|
||||
"retry": "重试",
|
||||
"update-failed": "无法更新身份验证",
|
||||
"unhandled": "未处理的错误响应",
|
||||
"host-key-verify-failed": "<p>主机密钥验证失败。</p><p>无法验证存储库主机密钥。请更新您的<code>known_hosts</code>文件,然后重试。</p>"
|
||||
},
|
||||
"create-branch-list": {
|
||||
"invalid": "无效的分支",
|
||||
"create": "创建分支",
|
||||
"current": "当前的"
|
||||
},
|
||||
"create-default-file-set": {
|
||||
"no-active": "没有活动项目就无法创建默认文件集",
|
||||
"no-empty": "无法在非空项目上创建默认文件集",
|
||||
"git-error": "git错误"
|
||||
},
|
||||
"errors": {
|
||||
"no-username-email": "您的Git客户端未配置用户名/电子邮件。",
|
||||
"unexpected": "发生了一个意料之外的问题",
|
||||
"code": "代码"
|
||||
}
|
||||
},
|
||||
"editor-tab": {
|
||||
"properties": "属性",
|
||||
"envProperties": "环境变量",
|
||||
"description": "描述",
|
||||
"appearance": "外观",
|
||||
"preview": "UI预览",
|
||||
"defaultValue": "默认值"
|
||||
},
|
||||
"languages": {
|
||||
"de": "德语",
|
||||
"en-US": "英文",
|
||||
"ja": "日语",
|
||||
"ko": "韩文",
|
||||
"zh-CN": "简体中文",
|
||||
"zh-TW": "繁体中文"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
{
|
||||
"$string": {
|
||||
"args": "arg",
|
||||
"desc": "通过以下的类型转换规则将参数*arg*转换成字符串:\n\n - 字符串不转换。\n -函数转换成空的字符串。\n - JSON的值无法用数字表示所以用无限大或者NaN(非数)表示。\n - 用’JSON.stringify’函数将其他值转换成JSON字符串。"
|
||||
"desc": "通过以下的类型转换规则将参数 *arg* 转换成字符串:\n\n - 字符串不转换。\n -函数转换成空的字符串。\n - JSON的值无法用数字表示所以用无限大或者NaN(非数)表示。\n - 用 `JSON.stringify` 函数将其他值转换成JSON字符串。"
|
||||
},
|
||||
"$length": {
|
||||
"args": "str",
|
||||
"desc": "输出字符串’str’的字数。如果’str’不是字符串,抛出错误。"
|
||||
"desc": "输出字符串 `str` 的字数。如果 `str` 不是字符串,抛出错误。"
|
||||
},
|
||||
"$substring": {
|
||||
"args": "str, start[, length]",
|
||||
@@ -17,11 +17,11 @@
|
||||
},
|
||||
"$substringAfter": {
|
||||
"args": "str, chars",
|
||||
"desc": "输出’str’中首次出现的’chars’之后的子字符串,如果’str’中不包括’chars’则输出’str’。"
|
||||
"desc": "输出 `str` 中首次出现的 `chars` 之后的子字符串,如果 `str` 中不包括 `chars` 则输出 `str` 。"
|
||||
},
|
||||
"$uppercase": {
|
||||
"args": "str",
|
||||
"desc": "`将’str’中的所有字母变为大写后输出。"
|
||||
"desc": "将 `str` 中的所有字母变为大写后输出。"
|
||||
},
|
||||
"$lowercase": {
|
||||
"args": "str",
|
||||
@@ -214,5 +214,61 @@
|
||||
"$toMillis": {
|
||||
"args": "timestamp",
|
||||
"desc": "将ISO 8601格式的字符串 `timestamp` 转换为从UNIX时间 (1970年1月1日 UTC/GMT的午夜)开始到现在的毫秒数。如果该字符串的格式不正确,则抛出错误。"
|
||||
},
|
||||
"$env": {
|
||||
"args": "arg",
|
||||
"desc": "返回环境变量的值。\n\n这是Node-RED定义的函数。"
|
||||
},
|
||||
"$eval": {
|
||||
"args": "expr [, context]",
|
||||
"desc": "使用当前上下文来作为评估依据,分析并评估字符串 `expr` ,其中包含文字JSON或JSONata表达式。"
|
||||
},
|
||||
"$formatInteger": {
|
||||
"args": "number, picture",
|
||||
"desc": "将“数字”转换为字符串,并将其格式化为“图片”字符串指定的整数表示形式。图片字符串参数定义了数字的格式,并具有与XPath F&O 3.1 规范中的fn:format-integer相同的语法。"
|
||||
},
|
||||
"$parseInteger": {
|
||||
"args": "string, picture",
|
||||
"desc": "使用“图片”字符串指定的格式将“字符串”参数的内容解析为整数(作为JSON数字)。图片字符串参数与$formatInteger格式相同。."
|
||||
},
|
||||
"$error": {
|
||||
"args": "[str]",
|
||||
"desc": "引发错误并显示一条消息。 可选的 `str` 将替代$error()函数评估的默认消息。"
|
||||
},
|
||||
"$assert": {
|
||||
"args": "arg, str",
|
||||
"desc": "如果 `arg` 为真,则该函数返回。 如果arg为假,则抛出带有str的异常作为异常消息。"
|
||||
},
|
||||
"$single": {
|
||||
"args": "array, function",
|
||||
"desc": "返回满足参数function谓语的array参数中的唯一值 (比如:传递值时,函数返回布尔值“true”)。如果匹配值的数量不唯一时,则抛出异常。\n\n应在以下签名中提供函数: `function(value [,index [,array []]])` 其中value是数组的每个输入,index是该值的位置,整个数组作为第三个参数传递。"
|
||||
},
|
||||
"$encodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "通过用表示字符的UTF-8编码的一个,两个,三个或四个转义序列替换某些字符的每个实例,对统一资源定位符(URL)组件进行编码。\n\n示例: `$encodeUrlComponent(\"?x=test\")` => `\"%3Fx%3Dtest\"`"
|
||||
},
|
||||
"$encodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "通过用表示字符的UTF-8编码的一个,两个,三个或四个转义序列替换某些字符的每个实例,对统一资源定位符(URL)进行编码。\n\n示例: `$encodeUrl(\"https://mozilla.org/?x=шеллы\")` => `\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\"`"
|
||||
},
|
||||
"$decodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "解码以前由encodeUrlComponent创建的统一资源定位器(URL)组件。 \n\n示例: `$decodeUrlComponent(\"%3Fx%3Dtest\")` => `\"?x=test\"`"
|
||||
},
|
||||
"$decodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "解码先前由encodeUrl创建的统一资源定位符(URL)。 \n\n示例: `$decodeUrl(\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\")` => `\"https://mozilla.org/?x=шеллы\"`"
|
||||
},
|
||||
"$distinct": {
|
||||
"args": "array",
|
||||
"desc": "返回一个数组,其中重复的值已从 `数组` 中删除"
|
||||
},
|
||||
"$type": {
|
||||
"args": "value",
|
||||
"desc": "以字符串形式返回 `值` 的类型。 如果该 `值` 未定义,则将返回 `未定义` "
|
||||
},
|
||||
"$moment": {
|
||||
"args": "[str]",
|
||||
"desc": "使用Moment库获取日期对象。"
|
||||
}
|
||||
}
|
||||
|
||||
1093
packages/node_modules/@node-red/editor-client/locales/zh-TW/editor.json
vendored
Normal file
23
packages/node_modules/@node-red/editor-client/locales/zh-TW/infotips.json
vendored
Normal file
@@ -0,0 +1,23 @@
|
||||
{
|
||||
"info": {
|
||||
"tip0" : "您可以用 {{core:delete-selection}} 刪除選擇的節點或連結。",
|
||||
"tip1" : "{{core:search}} 可以在流程內搜索節點。",
|
||||
"tip2": "{{core:toggle-sidebar}} 可以顯示或隱藏邊側欄。",
|
||||
"tip3": "您可以在 {{core:manage-palette}} 中管理節點的控制台。",
|
||||
"tip4": "側邊欄中會列出流程中所有的配置節點。您可以通過功能表或者 {{core:show-config-tab}} 來訪問這些節點。",
|
||||
"tip5": "您可以在設定中選擇顯示或隱藏這些提示。",
|
||||
"tip6": "您可以用[left] [up] [down] [right]鍵來移動被選中的節點。按住[shift]可以更快地移動節點。",
|
||||
"tip7": "把節點拖到連接上可以向連接中插入節點。",
|
||||
"tip8": "您可以用 {{core:show-export-dialog}} 來匯出被選中的節點或標籤頁中的流程。",
|
||||
"tip9": "您可以將流程的json文字檔拖入編輯方塊或 {{core:show-import-dialog}} 來導入流程。",
|
||||
"tip10": "按住[shift]後按一下並拖動節點可以將該節點的多個連接一併移動到其他節點的埠。",
|
||||
"tip11": "{{core:show-info-tab}} 可以顯示「資訊」標籤頁。 {{core:show-debug-tab}} 可以顯示「調試」標籤頁。",
|
||||
"tip12": "按住[ctrl]的同時點擊工作介面可以在節點的對話欄中快速添加節點。",
|
||||
"tip13": "按住[ctrl]的同時點擊節點的埠或後續節點可以快速連接多個節點。",
|
||||
"tip14": "按住[shift]的同時點擊節點會選中所有被連接的節點。",
|
||||
"tip15": "按住[ctrl]的同時點擊節點可以在選中或取消選中節點。",
|
||||
"tip16": "{{core:show-previous-tab}} 和 {{core:show-next-tab}} 可以切換標籤頁。",
|
||||
"tip17": "您可以在節點的屬性配置畫面中通過 {{core:confirm-edit-tray}} 來更改設置,或者用 {{core:cancel-edit-tray}} 來取消更改。",
|
||||
"tip18": "您可以通過點擊 {{core:edit-selected-node}} 來顯示被選中節點的屬性設置畫面。"
|
||||
}
|
||||
}
|
||||
274
packages/node_modules/@node-red/editor-client/locales/zh-TW/jsonata.json
vendored
Normal file
@@ -0,0 +1,274 @@
|
||||
{
|
||||
"$string": {
|
||||
"args": "arg",
|
||||
"desc": "通過以下的類型轉換規則將參數*arg*轉換成字串:\n\n - 字串不轉換。\n -函數轉換成空的字串。\n - JSON的值無法用數字表示所以用無限大或者NaN(非數)表示。\n - 用’JSON.stringify’函數將其他值轉換成JSON字串。"
|
||||
},
|
||||
"$length": {
|
||||
"args": "str",
|
||||
"desc": "輸出字串’str’的字數。如果’str’不是字串,拋出錯誤。"
|
||||
},
|
||||
"$substring": {
|
||||
"args": "str, start[, length]",
|
||||
"desc": "輸出`start`位置後的的首次出現的包括`str`的子字串。 如果`length`被指定,那麼的字串中將只包括前`length`個文字。如果`start`是負數則輸出從`str`末尾開始的`length`個文字"
|
||||
},
|
||||
"$substringBefore": {
|
||||
"args": "str, chars",
|
||||
"desc": "輸出’str’中首次出現的’chars’之前的子字串,如果’str’中不包括’chars’則輸出’str’。"
|
||||
},
|
||||
"$substringAfter": {
|
||||
"args": "str, chars",
|
||||
"desc": "輸出’str’中首次出現的’chars’之後的子字串,如果’str’中不包括’chars’則輸出’str’。"
|
||||
},
|
||||
"$uppercase": {
|
||||
"args": "str",
|
||||
"desc": "`將’str’中的所有字母變為大寫後輸出。"
|
||||
},
|
||||
"$lowercase": {
|
||||
"args": "str",
|
||||
"desc": "將’str’中的所有字母變為小寫後輸出。"
|
||||
},
|
||||
"$trim": {
|
||||
"args": "str",
|
||||
"desc": "將以下步驟應用於`str`來去除所有空白文字並實現標準化。\n\n – 將全部tab定位字元、Enter鍵、換行字元用空白代替。\n- 將連續的空白文字變成一個空白文字。\n- 消除開頭和末尾的空白文字。\n\n如果`str`沒有被指定(即在無輸入參數的情況下調用本函數),將上下文的值作為`str`來使用。 如果`str` 不是字串則拋出錯誤。"
|
||||
},
|
||||
"$contains": {
|
||||
"args": "str, pattern",
|
||||
"desc": "字串`str` 和 `pattern`匹配的話輸出`true`,不匹配的情況下輸出 `false`。 不指定`str`的情況下(比如用一個參數調用本函數時)、將上下文的值作為`str`來使用。參數 `pattern`可以為字串或正則表達。"
|
||||
},
|
||||
"$split": {
|
||||
"args": "str[, separator][, limit]",
|
||||
"desc": "將參數`str`分解成由子字串組成的陣列。 如果`str`不是字串拋出錯誤。可以省略的參數 `separator`中指定字串`str`的分隔符號。分隔符號可以是文字或規則運算式。在不指定`separator`的情況下、將分隔符號看作空的字串並把`str`拆分成由單個字母組成的陣列。如果`separator`不是字串則拋出錯誤。在可省略的參數`limit`中指定分割後的子字串的最大個數。超出個數的子字串將被捨棄。如果`limit`沒有被指定,`str` 將不考慮子字串的個數而將字串完全分隔。如果`limit`是負數則拋出錯誤。"
|
||||
},
|
||||
"$join": {
|
||||
"args": "array[, separator]",
|
||||
"desc": "用可以省略的參數 `separator`來把多個字元串連接。如果`array`不是字串則拋出錯誤。 如果沒有指定`separator`,則用空字串來連接字元(即字串之間沒有`separator`)。 如果`separator`不是字元則拋出錯誤。"
|
||||
},
|
||||
"$match": {
|
||||
"args": "str, pattern [, limit]",
|
||||
"desc": "對字串`str`使用規則運算式`pattern`並輸出與`str`相匹配的部分資訊。"
|
||||
},
|
||||
"$replace": {
|
||||
"args": "str, pattern, replacement [, limit]",
|
||||
"desc": "在字串`str`中搜索`pattern`並用`replacement`來替換。\n\n可選參數`limit`用來指定替換次數的上限。"
|
||||
},
|
||||
"$now": {
|
||||
"args": "",
|
||||
"desc": "生成ISO 8601互換格式的時刻,並作為字串輸出。"
|
||||
},
|
||||
"$base64encode": {
|
||||
"args": "string",
|
||||
"desc": "將ASCII格式的字串轉換為Base 64格式。將字串中的文字視作二進位形式的資料處理。包含URI編碼在內的字串文字必須在0x00到0xFF的範圍內,否則不會被支持。"
|
||||
},
|
||||
"$base64decode": {
|
||||
"args": "string",
|
||||
"desc": "用UTF-8內碼表將Base 64形式二進位值轉換為字串。"
|
||||
},
|
||||
"$number": {
|
||||
"args": "arg",
|
||||
"desc": "用下述的規則將參數 `arg`轉換為數值。:\n\n – 數值不做轉換。\n – 將字串中合法的JSON數値表示轉換成數値。\n – 其他形式的值則拋出錯誤。"
|
||||
},
|
||||
"$abs": {
|
||||
"args": "number",
|
||||
"desc": "輸出參數`number`的絕對值。"
|
||||
},
|
||||
"$floor": {
|
||||
"args": "number",
|
||||
"desc": "輸出比`number`的值小的最大整數。"
|
||||
},
|
||||
"$ceil": {
|
||||
"args": "number",
|
||||
"desc": "輸出比`number`的值大的最小整數。"
|
||||
},
|
||||
"$round": {
|
||||
"args": "number [, precision]",
|
||||
"desc": "輸出四捨五入後的參數`number`。可省略的參數 `precision`指定四捨五入後小數點下的位數。"
|
||||
},
|
||||
"$power": {
|
||||
"args": "base, exponent",
|
||||
"desc": "輸出底數`base`的`exponent`次冪。"
|
||||
},
|
||||
"$sqrt": {
|
||||
"args": "number",
|
||||
"desc": "輸出參數 `number`的平方根。"
|
||||
},
|
||||
"$random": {
|
||||
"args": "",
|
||||
"desc": "輸出比0大,比1小的偽亂數。"
|
||||
},
|
||||
"$millis": {
|
||||
"args": "",
|
||||
"desc": "返回從UNIX時間 (1970年1月1日 UTC/GMT的午夜)開始到現在的毫秒數。在同一個運算式的測試中所有對`$millis()`的調用將會返回相同的值。"
|
||||
},
|
||||
"$sum": {
|
||||
"args": "array",
|
||||
"desc": "輸出陣列`array`的總和。如果`array`不是數值則拋出錯誤。"
|
||||
},
|
||||
"$max": {
|
||||
"args": "array",
|
||||
"desc": "輸出陣列`array`的最大值。如果`array`不是數值則拋出錯誤。"
|
||||
},
|
||||
"$min": {
|
||||
"args": "array",
|
||||
"desc": "輸出陣列`array`的最小值。如果`array`不是數值則拋出錯誤。。"
|
||||
},
|
||||
"$average": {
|
||||
"args": "array",
|
||||
"desc": "輸出陣列`array`的平均數。如果`array`不是數值則拋出錯誤。。"
|
||||
},
|
||||
"$boolean": {
|
||||
"args": "arg",
|
||||
"desc": "用下述規則將資料轉換成布林值。:\n\n - 不轉換布林值`Boolean`。\n – 將空的字串`string`轉換為`false`\n – 將不為空的字串`string`轉換為`true`\n – 將為0的數位`number`轉換成`false`\n –將不為0的數位`number`轉換成`true`\n –將`null`轉換成`false`\n –將空的陣列`array`轉換成`false`\n –如果陣列`array`中含有可以轉換成`true`的要素則轉換成`true`\n –如果`array`中沒有可轉換成`true`的要素則轉換成`false`\n – 空的物件`object`轉換成`false`\n – 非空的物件`object`轉換成`true`\n –將函數`function`轉換成`false`"
|
||||
},
|
||||
"$not": {
|
||||
"args": "arg",
|
||||
"desc": "輸出做反轉運算後的布林值。首先將`arg`轉換為布林值。"
|
||||
},
|
||||
"$exists": {
|
||||
"args": "arg",
|
||||
"desc": "如果算式`arg`的值存在則輸出`true`。如果算式的值不存在(比如指向不存在區域的引用)則輸出`false`。"
|
||||
},
|
||||
"$count": {
|
||||
"args": "array",
|
||||
"desc": "輸出陣列中的元素數。"
|
||||
},
|
||||
"$append": {
|
||||
"args": "array, array",
|
||||
"desc": "將兩個陣列連接。"
|
||||
},
|
||||
"$sort": {
|
||||
"args": "array [, function]",
|
||||
"desc": "輸出排序後的陣列`array`。\n\n如果使用了比較函數`function`,則下述兩個參數需要被指定。\n\n`function(left, right)`\n\n該比較函數是為了比較left和right兩個值而被排序演算法調用的。如果使用者希望left的值被置於right的值之後,那麼該函數必須輸出布林值`true`來表示位置交換。而在不需要位置交換時函數必須輸出`false`。"
|
||||
},
|
||||
"$reverse": {
|
||||
"args": "array",
|
||||
"desc": "輸出倒序後的陣列`array`。"
|
||||
},
|
||||
"$shuffle": {
|
||||
"args": "array",
|
||||
"desc": "輸出隨機排序後的陣列 `array`。"
|
||||
},
|
||||
"$zip": {
|
||||
"args": "array, ...",
|
||||
"desc": "將陣列中的值按索引順序打包後輸出。"
|
||||
},
|
||||
"$keys": {
|
||||
"args": "object",
|
||||
"desc": "輸出由物件內的鍵組成的陣列。如果參數是物件的陣列則輸出由所有物件中的鍵去重後組成的佇列。"
|
||||
},
|
||||
"$lookup": {
|
||||
"args": "object, key",
|
||||
"desc": "輸出對象中與參數`key`對應的值。如果第一個參數`object`是陣列,那麼陣列中所有的物件都將被搜索並輸出這些物件中與參數`key`對應的值。"
|
||||
},
|
||||
"$spread": {
|
||||
"args": "object",
|
||||
"desc": "將物件中的鍵值對分隔成每個要素中只含有一個鍵值對的陣列。如果參數`object`是陣列,那麼返回值的陣列中包含所有物件中的鍵值對。"
|
||||
},
|
||||
"$merge": {
|
||||
"args": "array<object>",
|
||||
"desc": "將輸入陣列`objects`中所有的鍵值對合併到一個`object`中並返回。如果輸入陣列的要素中含有重複的鍵,則返回的`object`中將只包含陣列中最後出現要素的值。如果輸入陣列中包括物件以外的元素,則拋出錯誤。"
|
||||
},
|
||||
"$sift": {
|
||||
"args": "object, function",
|
||||
"desc": "輸出參數`object`中符合`function`的鍵值對。\n\n`function`必須含有下述參數。\n\n`function(value [, key [, object]])`"
|
||||
},
|
||||
"$each": {
|
||||
"args": "object, function",
|
||||
"desc": "將函數`function`應用於`object`中的所有鍵值對並輸出由所有返回值組成的陣列。"
|
||||
},
|
||||
"$map": {
|
||||
"args": "array, function",
|
||||
"desc": "將函數`function`應用於陣列`array`中所有的值並輸出由返回值組成的陣列。\n\n`function`中必須含有下述參數。\n\n`function(value [, index [, array]])`"
|
||||
},
|
||||
"$filter": {
|
||||
"args": "array, function",
|
||||
"desc": "輸出陣列`array`中符合函數`function`條件的值組成的陣列。\n\n`function`必須包括下述參數。\n\n`function(value [, index [, array]])`"
|
||||
},
|
||||
"$reduce": {
|
||||
"args": "array, function [, init]",
|
||||
"desc": "將`function`依次應用於陣列中的各要素值。 其中,前一個要素值的計算結果將參與到下一次的函數運算中。。\n\n函數`function`接受兩個參數並作為中綴標記法中的操作符。\n\n可省略的參數`init`將作為運算的初始值。"
|
||||
},
|
||||
"$flowContext": {
|
||||
"args": "string",
|
||||
"desc": "獲取流上下文(流等級的上下文,可以讓所有節點共用)的屬性。"
|
||||
},
|
||||
"$globalContext": {
|
||||
"args": "string",
|
||||
"desc": "獲取全域上下文的屬性。"
|
||||
},
|
||||
"$pad": {
|
||||
"args": "string, width [, char]",
|
||||
"desc": "根據需要,向字串`string`的副本中填充文字使該字串的字數達到`width`的絕對值並返回填充文字後的字串。\n\n如果`width`的值為正,則向字串`string`的右側填充文字,如果`width`為負,則向字串`string`的左側填充文字。\n\n可選參數`char`用來指定填充的文字。如果未指定該參數,則填充空白文字。"
|
||||
},
|
||||
"$fromMillis": {
|
||||
"args": "number",
|
||||
"desc": "將表示從UNIX時間 (1970年1月1日 UTC/GMT的午夜)開始到現在的毫秒數的數值轉換成ISO 8601形式時間戳記的字串。"
|
||||
},
|
||||
"$formatNumber": {
|
||||
"args": "number, picture [, options]",
|
||||
"desc": "將`number`轉換成具有`picture`所指定的數值格式的字串。\n\n此函數的功能與XPath F&O 3.1規格中定義的XPath/XQuery函數的fn:format-number功能相一致。參數`picture`用於指定數值的轉換格式,其語法與fn:format-number中的定義一致。\n\n可選的第三參數`options`用來覆蓋預設的局部環境格式,如小數點分隔符號。如果指定該參數,那麼該參數必須是包含name/value對的物件,並且name/value對必須符合XPath F&O 3.1規格中記述的數值格式。"
|
||||
},
|
||||
"$formatBase": {
|
||||
"args": "number [, radix]",
|
||||
"desc": "將`number`變換為以參數`radix`的值為基數形式的字串。如果不指定`radix`的值,則默認基數為10。指定的`radix`值必須在2~36之間,否則拋出錯誤。"
|
||||
},
|
||||
"$toMillis": {
|
||||
"args": "timestamp",
|
||||
"desc": "將ISO 8601格式的字串`timestamp`轉換為從UNIX時間 (1970年1月1日 UTC/GMT的午夜)開始到現在的毫秒數。如果該字串的格式不正確,則拋出錯誤。"
|
||||
},
|
||||
"$env": {
|
||||
"args": "arg",
|
||||
"desc": "返回環境變量的值。\n\n這是Node-RED定義的函數。"
|
||||
},
|
||||
"$eval": {
|
||||
"args": "expr [, context]",
|
||||
"desc": "使用當前上下文來作為評估依據,分析並評估字符串`expr`,其中包含文字JSON或JSONata表達式。"
|
||||
},
|
||||
"$formatInteger": {
|
||||
"args": "number, picture",
|
||||
"desc": "將“數字”轉換為字符串,並將其格式化為“圖片”字符串指定的整數表示形式。圖片字符串參數定義了數字的格式,並具有與XPath F&O 3.1 規範中的fn:format-integer相同的語法。"
|
||||
},
|
||||
"$parseInteger": {
|
||||
"args": "string, picture",
|
||||
"desc": "使用“圖片”字符串指定的格式將“字符串”參數的內容解析為整數(作為JSON數字)。圖片字符串參數與$formatInteger格式相同。."
|
||||
},
|
||||
"$error": {
|
||||
"args": "[str]",
|
||||
"desc": "引發錯誤並顯示一條消息。 可選的`str`將替代$error()函數評估的默認消息。"
|
||||
},
|
||||
"$assert": {
|
||||
"args": "arg, str",
|
||||
"desc": "如果`arg`為真,則該函數返回。 如果arg為假,則拋出帶有str的異常作為異常消息。"
|
||||
},
|
||||
"$single": {
|
||||
"args": "array, function",
|
||||
"desc": "返回滿足參數function謂語的array參數中的唯一值 (比如:傳遞值時,函數返回布林值“true”)。如果匹配值的數量不唯一時,則拋出異常。\n\n應在以下簽名中提供函數:`function(value [,index [,array []]])`其中value是數組的每個輸入,index是該值的位置,整個數組作為第三個參數傳遞。"
|
||||
},
|
||||
"$encodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "通過用表示字符的UTF-8編碼的一個,兩個,三個或四個轉義序列替換某些字符的每個實例,對統一資源定位符(URL)組件進行編碼。\n\n示例:`$encodeUrlComponent(\"?x=test\")` => `\"%3Fx%3Dtest\"`"
|
||||
},
|
||||
"$encodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "通過用表示字符的UTF-8編碼的一個,兩個,三個或四個轉義序列替換某些字符的每個實例,對統一資源定位符(URL)進行編碼。\n\n示例: `$encodeUrl(\"https://mozilla.org/?x=шеллы\")` => `\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\"`"
|
||||
},
|
||||
"$decodeUrlComponent": {
|
||||
"args": "str",
|
||||
"desc": "解碼以前由encodeUrlComponent創建的統一資源定位器(URL)組件。 \n\n示例: `$decodeUrlComponent(\"%3Fx%3Dtest\")` => `\"?x=test\"`"
|
||||
},
|
||||
"$decodeUrl": {
|
||||
"args": "str",
|
||||
"desc": "解碼先前由encodeUrl創建的統一資源定位符(URL)。 \n\n示例: `$decodeUrl(\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\")` => `\"https://mozilla.org/?x=шеллы\"`"
|
||||
},
|
||||
"$distinct": {
|
||||
"args": "array",
|
||||
"desc": "返回一個數組,其中重復的值已從`數組`中刪除"
|
||||
},
|
||||
"$type": {
|
||||
"args": "value",
|
||||
"desc": "以字符串形式返回`值`的類型。 如果該`值`未定義,則將返回`未定義`"
|
||||
},
|
||||
"$moment": {
|
||||
"args": "[str]",
|
||||
"desc": "使用Moment庫獲取日期對象。"
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "@node-red/editor-client",
|
||||
"version": "1.0.0-beta.4",
|
||||
"version": "1.3.0-beta.1",
|
||||
"license": "Apache-2.0",
|
||||
"repository": {
|
||||
"type": "git",
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
ace.define("ace/snippets/nrjavascript",[],function(e,t,n){"use strict";t.snippetText=undefined,t.scope="nrjavascript"});
|
||||
(function() {
|
||||
; (function() {
|
||||
ace.require(["ace/snippets/nrjavascript"], function(m) {
|
||||
if (typeof module == "object" && typeof exports == "object" && module) {
|
||||
module.exports = m;
|
||||
|
||||
@@ -76,13 +76,12 @@ oop.inherits(NRJavaScriptWorker, Mirror);
|
||||
|
||||
(function() {
|
||||
this.setOptions = function(options) {
|
||||
this.options = options || {
|
||||
this.options = {
|
||||
// undef: true,
|
||||
// unused: true,
|
||||
esnext: true,
|
||||
moz: true,
|
||||
esversion: 9,
|
||||
devel: true,
|
||||
browser: true,
|
||||
browser: false,
|
||||
node: true,
|
||||
laxcomma: true,
|
||||
laxbreak: true,
|
||||
@@ -92,8 +91,17 @@ oop.inherits(NRJavaScriptWorker, Mirror);
|
||||
maxerr: 100,
|
||||
expr: true,
|
||||
multistr: true,
|
||||
globalstrict: true
|
||||
strict: false,
|
||||
sub: true,
|
||||
asi: true
|
||||
};
|
||||
if (options) {
|
||||
for (var opt in options) {
|
||||
if (options.hasOwnProperty(opt)) {
|
||||
this.options[opt] = options.opt;
|
||||
}
|
||||
}
|
||||
}
|
||||
this.doc.getValue() && this.deferredUpdate.schedule(100);
|
||||
};
|
||||
|
||||
@@ -119,6 +127,8 @@ oop.inherits(NRJavaScriptWorker, Mirror);
|
||||
if (!value)
|
||||
return this.sender.emit("annotate", []);
|
||||
|
||||
var originalValue = value;
|
||||
|
||||
// [Node-RED] wrap the code in a function
|
||||
value = "async function __nodered__(msg) {\n"+value+"\n}";
|
||||
|
||||
@@ -138,6 +148,7 @@ oop.inherits(NRJavaScriptWorker, Mirror);
|
||||
continue;
|
||||
var raw = error.raw;
|
||||
var type = "warning";
|
||||
var line = error.line - 2;
|
||||
|
||||
if (raw == "Missing semicolon.") {
|
||||
var str = error.evidence.substr(error.character);
|
||||
@@ -166,9 +177,62 @@ oop.inherits(NRJavaScriptWorker, Mirror);
|
||||
type = "info";
|
||||
}
|
||||
|
||||
if (raw === "Unmatched '{a}'." && line === -1) {
|
||||
// This is an unmatched { error. It has incorrectly matched it
|
||||
// against the { in the added line. Need to find the next valid {
|
||||
// This code scans through the original code looking for the first '{'
|
||||
// that is not in a comment or string.
|
||||
// It will incorrectly find a '{' if it is inside a regex... but
|
||||
// at least the error will be shown somwhere. There are only
|
||||
// so many hours in the day to fix every tiny edge case of an
|
||||
// edge case.
|
||||
var inSingleComment = false;
|
||||
var inMultiComment = false;
|
||||
var inString = false;
|
||||
var stringQ;
|
||||
var lineNumber = 0;
|
||||
for (var pos = 0;pos<originalValue.length;pos++) {
|
||||
var c = originalValue[pos];
|
||||
if (c === "\\") {
|
||||
pos++;
|
||||
} else if (inSingleComment) {
|
||||
if (c === "\n") {
|
||||
lineNumber++;
|
||||
inSingleComment = false;
|
||||
}
|
||||
} else if (inMultiComment) {
|
||||
if (c === "*" && originalValue[pos+1] === "/") {
|
||||
pos++;
|
||||
inMultiComment = false;
|
||||
} else if (c === "\n") {
|
||||
lineNumber++;
|
||||
}
|
||||
} else if (inString) {
|
||||
if (c === stringQ) {
|
||||
inString = false;
|
||||
}
|
||||
} else if (c === "'" || c === "\"") {
|
||||
inString = true;
|
||||
stringQ = c;
|
||||
} else if (c === "/") {
|
||||
if (originalValue[pos+1] === "/") {
|
||||
inSingleComment = true;
|
||||
} else if (originalValue[pos+1] === "*") {
|
||||
inMultiComment = true;
|
||||
}
|
||||
} else if (c === "\n") {
|
||||
lineNumber++;
|
||||
} else if (c === "{") {
|
||||
// found it!
|
||||
break;
|
||||
}
|
||||
}
|
||||
line = lineNumber;
|
||||
}
|
||||
|
||||
errors.push({
|
||||
// [Node-RED] offset the row for the added line
|
||||
row: error.line-2,
|
||||
row: Math.max(0,line),
|
||||
column: error.character-1,
|
||||
text: error.reason,
|
||||
type: type,
|
||||
|
||||
@@ -1 +1 @@
|
||||
<svg width="40" height="60" xmlns="http://www.w3.org/2000/svg"><path d="M18 5v12H7v26h11v12l14-25z" fill="#fff"/></svg>
|
||||
<svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="M18 5v12H7v26h11v12l14-25z" fill="#fff"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 120 B After Width: | Height: | Size: 143 B |
@@ -1 +1 @@
|
||||
<svg width="40" height="40" xmlns="http://www.w3.org/2000/svg"><path d="M25 16h7c.58 0 1-.42 1-1v-2c0-.58-.42-1-1-1h-7c-.58 0-1 .42-1 1v2c0 .58.42 1 1 1zM8 28h7c.58 0 1-.42 1-1v-2c0-.58-.42-1-1-1H8c-.58 0-1 .42-1 1v2c0 .58.42 1 1 1zm-.416 11C5.624 39 4 37.375 4 35.416V4.582C4 2.622 5.625 1 7.584 1h24.832C34.376 1 36 2.623 36 4.582v30.834C36 37.376 34.375 39 32.416 39zM32 27H19c0 2.19-1.81 4-4 4H7v4.416c0 .35.235.584.584.584h24.832c.35 0 .584-.235.584-.584v-8.417zm1-2v-6h-8c-2.19 0-4-1.81-4-4h-1c-4.333-.002-8.667.004-13 0v6h8c2.19 0 4 1.81 4 4h13zm0-16V4.582c0-.35-.235-.582-.584-.582H7.584C7.234 4 7 4.233 7 4.582v8.417c4.333.002 8.667.001 13 .001h1c0-2.19 1.81-4 4-4z" color="#000" fill="#333"/></svg>
|
||||
<svg width="40" height="40" viewBox="0, 0, 40, 40" xmlns="http://www.w3.org/2000/svg"><path d="M25 16h7c.58 0 1-.42 1-1v-2c0-.58-.42-1-1-1h-7c-.58 0-1 .42-1 1v2c0 .58.42 1 1 1zM8 28h7c.58 0 1-.42 1-1v-2c0-.58-.42-1-1-1H8c-.58 0-1 .42-1 1v2c0 .58.42 1 1 1zm-.416 11C5.624 39 4 37.375 4 35.416V4.582C4 2.622 5.625 1 7.584 1h24.832C34.376 1 36 2.623 36 4.582v30.834C36 37.376 34.375 39 32.416 39zM32 27H19c0 2.19-1.81 4-4 4H7v4.416c0 .35.235.584.584.584h24.832c.35 0 .584-.235.584-.584v-8.417zm1-2v-6h-8c-2.19 0-4-1.81-4-4h-1c-4.333-.002-8.667.004-13 0v6h8c2.19 0 4 1.81 4 4h13zm0-16V4.582c0-.35-.235-.582-.584-.582H7.584C7.234 4 7 4.233 7 4.582v8.417c4.333.002 8.667.001 13 .001h1c0-2.19 1.81-4 4-4z" color="#000" fill="#333"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 708 B After Width: | Height: | Size: 732 B |
@@ -1 +1 @@
|
||||
<svg width="26" height="36" xmlns="http://www.w3.org/2000/svg"><path d="M14.16 27.38l1.555-.144c.132.731.383 1.261.755 1.591.371.33.848.494 1.429.494.497 0 .931-.114 1.303-.341.377-.228.686-.53.926-.908.24-.383.44-.899.602-1.546a8.122 8.122 0 0 0 .233-2.3 3.732 3.732 0 0 1-1.33 1.258 3.605 3.605 0 0 1-1.815.476c-1.09 0-2.013-.395-2.768-1.186s-1.133-1.834-1.133-3.128c0-1.336.393-2.411 1.178-3.226.79-.815 1.78-1.223 2.966-1.223.856 0 1.638.231 2.345.692.713.462 1.253 1.12 1.618 1.978.372.85.557 2.085.557 3.702 0 1.684-.182 3.026-.548 4.027-.365.994-.91 1.752-1.636 2.274-.719.52-1.563.781-2.534.781-1.03 0-1.872-.284-2.525-.853-.654-.576-1.046-1.381-1.178-2.418zm6.624-5.815c0-.928-.249-1.666-.746-2.21-.492-.546-1.085-.819-1.78-.819-.719 0-1.345.294-1.878.881s-.8 1.348-.8 2.283c0 .839.252 1.522.755 2.05.51.52 1.135.781 1.878.781.75 0 1.363-.26 1.843-.782.485-.527.728-1.255.728-2.184zM4.858 10.466c0-1.558.158-2.81.476-3.757.324-.952.8-1.686 1.429-2.201.635-.516 1.432-.773 2.39-.773.708 0 1.328.143 1.861.431.533.282.974.692 1.321 1.231.348.534.62 1.187.818 1.96.198.767.297 1.803.297 3.11 0 1.545-.16 2.794-.477 3.747-.317.947-.794 1.68-1.429 2.202-.629.515-1.426.773-2.39.773-1.27 0-2.268-.456-2.993-1.366-.869-1.097-1.303-2.882-1.303-5.357zm1.662 0c0 2.163.252 3.604.755 4.323.51.713 1.136 1.07 1.879 1.07.743 0 1.366-.36 1.87-1.079.508-.719.763-2.157.763-4.314 0-2.169-.255-3.61-.764-4.323-.503-.713-1.132-1.07-1.887-1.07-.743 0-1.336.315-1.78.944-.557.803-.836 2.286-.836 4.45z" fill="#444"/></svg>
|
||||
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M14.16 27.38l1.555-.144c.132.731.383 1.261.755 1.591.371.33.848.494 1.429.494.497 0 .931-.114 1.303-.341.377-.228.686-.53.926-.908.24-.383.44-.899.602-1.546a8.122 8.122 0 0 0 .233-2.3 3.732 3.732 0 0 1-1.33 1.258 3.605 3.605 0 0 1-1.815.476c-1.09 0-2.013-.395-2.768-1.186s-1.133-1.834-1.133-3.128c0-1.336.393-2.411 1.178-3.226.79-.815 1.78-1.223 2.966-1.223.856 0 1.638.231 2.345.692.713.462 1.253 1.12 1.618 1.978.372.85.557 2.085.557 3.702 0 1.684-.182 3.026-.548 4.027-.365.994-.91 1.752-1.636 2.274-.719.52-1.563.781-2.534.781-1.03 0-1.872-.284-2.525-.853-.654-.576-1.046-1.381-1.178-2.418zm6.624-5.815c0-.928-.249-1.666-.746-2.21-.492-.546-1.085-.819-1.78-.819-.719 0-1.345.294-1.878.881s-.8 1.348-.8 2.283c0 .839.252 1.522.755 2.05.51.52 1.135.781 1.878.781.75 0 1.363-.26 1.843-.782.485-.527.728-1.255.728-2.184zM4.858 10.466c0-1.558.158-2.81.476-3.757.324-.952.8-1.686 1.429-2.201.635-.516 1.432-.773 2.39-.773.708 0 1.328.143 1.861.431.533.282.974.692 1.321 1.231.348.534.62 1.187.818 1.96.198.767.297 1.803.297 3.11 0 1.545-.16 2.794-.477 3.747-.317.947-.794 1.68-1.429 2.202-.629.515-1.426.773-2.39.773-1.27 0-2.268-.456-2.993-1.366-.869-1.097-1.303-2.882-1.303-5.357zm1.662 0c0 2.163.252 3.604.755 4.323.51.713 1.136 1.07 1.879 1.07.743 0 1.366-.36 1.87-1.079.508-.719.763-2.157.763-4.314 0-2.169-.255-3.61-.764-4.323-.503-.713-1.132-1.07-1.887-1.07-.743 0-1.336.315-1.78.944-.557.803-.836 2.286-.836 4.45z" fill="#444"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.5 KiB After Width: | Height: | Size: 1.5 KiB |
@@ -1 +1 @@
|
||||
<svg width="26" height="36" xmlns="http://www.w3.org/2000/svg"><path d="M13.27 29.15l6.733-8.143h-6.235V19.3h8.8v1.559l-6.69 8.09h6.892v1.707h-9.5zm4.909-10.125zM6.577 12.58q0 .827.604 1.304.605.478 1.432.478 1.007 0 1.95-.467 1.59-.774 1.59-2.534V9.824q-.349.222-.9.37-.552.15-1.082.213l-1.155.148q-1.04.138-1.56.435-.88.498-.88 1.59zM11.2 8.721q.657-.085.88-.551.127-.255.127-.732 0-.975-.7-1.41-.689-.445-1.983-.445-1.495 0-2.12.805-.35.446-.456 1.326H5.167q.053-2.1 1.357-2.916 1.315-.827 3.043-.827 2.004 0 3.255.763 1.24.764 1.24 2.375v6.542q0 .297.117.477.127.18.52.18.127 0 .286-.01.159-.021.34-.053v1.41q-.446.127-.68.16-.233.031-.636.031-.986 0-1.43-.7-.234-.37-.33-1.05-.583.764-1.675 1.326t-2.407.562q-1.58 0-2.587-.954-.996-.965-.996-2.407 0-1.58.986-2.45.986-.869 2.587-1.07zm-1.58-4.75z" fill="#444"/></svg>
|
||||
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M13.27 29.15l6.733-8.143h-6.235V19.3h8.8v1.559l-6.69 8.09h6.892v1.707h-9.5zm4.909-10.125zM6.577 12.58q0 .827.604 1.304.605.478 1.432.478 1.007 0 1.95-.467 1.59-.774 1.59-2.534V9.824q-.349.222-.9.37-.552.15-1.082.213l-1.155.148q-1.04.138-1.56.435-.88.498-.88 1.59zM11.2 8.721q.657-.085.88-.551.127-.255.127-.732 0-.975-.7-1.41-.689-.445-1.983-.445-1.495 0-2.12.805-.35.446-.456 1.326H5.167q.053-2.1 1.357-2.916 1.315-.827 3.043-.827 2.004 0 3.255.763 1.24.764 1.24 2.375v6.542q0 .297.117.477.127.18.52.18.127 0 .286-.01.159-.021.34-.053v1.41q-.446.127-.68.16-.233.031-.636.031-.986 0-1.43-.7-.234-.37-.33-1.05-.583.764-1.675 1.326t-2.407.562q-1.58 0-2.587-.954-.996-.965-.996-2.407 0-1.58.986-2.45.986-.869 2.587-1.07zm-1.58-4.75z" fill="#444"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 822 B After Width: | Height: | Size: 846 B |
@@ -1 +1 @@
|
||||
<svg width="26" height="36" xmlns="http://www.w3.org/2000/svg"><path d="M18.8 33.9c3.328 0 4.776-2.603 4.776-7.066s-1.448-7.066-4.776-7.066-4.776 2.603-4.776 7.066S15.473 33.9 18.8 33.9zm0-1.429c-2.192 0-3.073-1.781-3.073-4.522v-2.23c0-2.741.88-4.523 3.073-4.523s3.073 1.782 3.073 4.522v2.231c0 2.74-.88 4.522-3.073 4.522zm-6.306 1.194v-1.429H8.892V20.002H6.328l-3.621 3.386.959 1.038 3.445-3.21h.137v11.02H3.333v1.429zm11.2-17.7v-1.429h-3.602V2.302h-2.564l-3.621 3.386.959 1.038 3.445-3.21h.137v11.02h-3.915v1.429zM7.5 16.2c3.327 0 4.776-2.603 4.776-7.066S10.828 2.068 7.5 2.068 2.725 4.67 2.725 9.134 4.173 16.2 7.5 16.2zm0-1.429c-2.193 0-3.074-1.781-3.074-4.522V8.02c0-2.741.881-4.523 3.074-4.523s3.073 1.782 3.073 4.522v2.231c0 2.74-.881 4.522-3.073 4.522z" fill="#444"/></svg>
|
||||
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M18.8 33.9c3.328 0 4.776-2.603 4.776-7.066s-1.448-7.066-4.776-7.066-4.776 2.603-4.776 7.066S15.473 33.9 18.8 33.9zm0-1.429c-2.192 0-3.073-1.781-3.073-4.522v-2.23c0-2.741.88-4.523 3.073-4.523s3.073 1.782 3.073 4.522v2.231c0 2.74-.88 4.522-3.073 4.522zm-6.306 1.194v-1.429H8.892V20.002H6.328l-3.621 3.386.959 1.038 3.445-3.21h.137v11.02H3.333v1.429zm11.2-17.7v-1.429h-3.602V2.302h-2.564l-3.621 3.386.959 1.038 3.445-3.21h.137v11.02h-3.915v1.429zM7.5 16.2c3.327 0 4.776-2.603 4.776-7.066S10.828 2.068 7.5 2.068 2.725 4.67 2.725 9.134 4.173 16.2 7.5 16.2zm0-1.429c-2.193 0-3.074-1.781-3.074-4.522V8.02c0-2.741.881-4.523 3.074-4.523s3.073 1.782 3.073 4.522v2.231c0 2.74-.881 4.522-3.073 4.522z" fill="#444"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 781 B After Width: | Height: | Size: 805 B |
@@ -1 +1 @@
|
||||
<svg width="26" height="36" xmlns="http://www.w3.org/2000/svg"><path d="M9.96 21.98a5 5 0 1 1 6.11-7.917zm3.035-13.973c-5.512 0-10 4.488-10 10s4.488 9.998 10 9.998 10-4.486 10-9.998-4.488-10-10-10zm0 1.816c4.53 0 8.182 3.655 8.182 8.184s-3.652 8.182-8.182 8.182-8.181-3.653-8.181-8.182 3.652-8.184 8.181-8.184z" color="#000" fill="#444"/></svg>
|
||||
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M9.96 21.98a5 5 0 1 1 6.11-7.917zm3.035-13.973c-5.512 0-10 4.488-10 10s4.488 9.998 10 9.998 10-4.486 10-9.998-4.488-10-10-10zm0 1.816c4.53 0 8.182 3.655 8.182 8.184s-3.652 8.182-8.182 8.182-8.181-3.653-8.181-8.182 3.652-8.184 8.181-8.184z" color="#000" fill="#444"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 345 B After Width: | Height: | Size: 368 B |
@@ -1 +1 @@
|
||||
<svg width="26" height="36" xmlns="http://www.w3.org/2000/svg"><path d="M14.33 27.19q2.916-.136 4.024-2.131.58-1.024.58-2.37 0-2.132-1.569-3.24-.904-.648-3.035-1.228zM8.55 10.736q0 1.688 1.108 2.643 1.125.955 3.018 1.33V6.695q-2.234.085-3.189 1.364-.937 1.279-.937 2.677zm-3.07.205q0-2.592 1.893-4.672 1.91-2.08 5.337-2.115V1.887h1.62V4.12q3.393.239 5.2 2.012 1.825 1.757 1.91 4.655h-2.984q-.119-1.296-.699-2.233-1.074-1.723-3.427-1.808v8.287q3.956 1.108 5.371 2.08 2.302 1.603 2.302 4.74 0 4.536-2.95 6.446-1.637 1.057-4.723 1.398v3.308h-1.62v-3.308q-4.962-.324-6.735-3.513-.972-1.722-.972-4.655h3.018q.136 2.336.733 3.41 1.057 1.927 3.922 2.166v-9.293q-3.683-.699-5.44-2.336Q5.48 13.84 5.48 10.941z" fill="#444"/></svg>
|
||||
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M14.33 27.19q2.916-.136 4.024-2.131.58-1.024.58-2.37 0-2.132-1.569-3.24-.904-.648-3.035-1.228zM8.55 10.736q0 1.688 1.108 2.643 1.125.955 3.018 1.33V6.695q-2.234.085-3.189 1.364-.937 1.279-.937 2.677zm-3.07.205q0-2.592 1.893-4.672 1.91-2.08 5.337-2.115V1.887h1.62V4.12q3.393.239 5.2 2.012 1.825 1.757 1.91 4.655h-2.984q-.119-1.296-.699-2.233-1.074-1.723-3.427-1.808v8.287q3.956 1.108 5.371 2.08 2.302 1.603 2.302 4.74 0 4.536-2.95 6.446-1.637 1.057-4.723 1.398v3.308h-1.62v-3.308q-4.962-.324-6.735-3.513-.972-1.722-.972-4.655h3.018q.136 2.336.733 3.41 1.057 1.927 3.922 2.166v-9.293q-3.683-.699-5.44-2.336Q5.48 13.84 5.48 10.941z" fill="#444"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 722 B After Width: | Height: | Size: 745 B |
@@ -1 +1 @@
|
||||
<svg width="26" height="36" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-337.103 -913.25) scale(1.2585)" fill="#444" stroke-width=".795"><circle cx="284.36" cy="733.68" r="1.5" color="#000" style="isolation:auto;mix-blend-mode:normal"/><circle cx="284.33" cy="740.74" r="1.5" color="#000" style="isolation:auto;mix-blend-mode:normal"/><path d="M276.18 727.78l4.396-1.565v18.515c-.711 2.606-2.922 4.394-5.812 5.812l-4.135 1.974-.559-1.192 3.353-1.639c1.459-.724 2.689-1.87 2.869-4.955z" fill-rule="evenodd"/></g></svg>
|
||||
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-337.103 -913.25) scale(1.2585)" fill="#444" stroke-width=".795"><circle cx="284.36" cy="733.68" r="1.5" color="#000" style="isolation:auto;mix-blend-mode:normal"/><circle cx="284.33" cy="740.74" r="1.5" color="#000" style="isolation:auto;mix-blend-mode:normal"/><path d="M276.18 727.78l4.396-1.565v18.515c-.711 2.606-2.922 4.394-5.812 5.812l-4.135 1.974-.559-1.192 3.353-1.639c1.459-.724 2.689-1.87 2.869-4.955z" fill-rule="evenodd"/></g></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 532 B After Width: | Height: | Size: 556 B |
@@ -1 +1 @@
|
||||
<svg width="26" height="36" xmlns="http://www.w3.org/2000/svg"><path d="M15 5.225v-1.92h2.24q.608 0 1.216.288.608.256 1.12.8.48.512.8 1.312.32.768.32 1.792v5.824q0 .832.224 1.536t.608 1.216q.352.48.832.768.48.256.992.256v2.176q-.512 0-.992.256t-.832.736q-.384.48-.608 1.184t-.224 1.568v5.792q0 1.024-.32 1.792-.32.8-.8 1.312-.512.544-1.12.8-.608.288-1.216.288H15v-1.92h1.6q.48 0 .768-.256.288-.224.48-.64.16-.384.224-.896.064-.48.064-.96v-5.824q0-1.216.352-2.016.32-.8.768-1.28.448-.512.928-.736.448-.224.736-.256v-.096q-.288-.064-.736-.32-.48-.256-.928-.768t-.768-1.28q-.352-.8-.352-1.92V7.977q0-.512-.064-.992-.064-.512-.224-.896-.192-.384-.48-.608-.288-.256-.768-.256zm-3.648 0v-1.92h-2.24q-.608 0-1.216.288-.608.256-1.12.8-.48.512-.8 1.312-.32.768-.32 1.792v5.824q0 .832-.224 1.536t-.608 1.216q-.352.48-.832.768-.48.256-.992.256v2.176q.512 0 .992.256t.832.736q.384.48.608 1.184t.224 1.568v5.792q0 1.024.32 1.792.32.8.8 1.312.512.544 1.12.8.608.288 1.216.288h2.24v-1.92h-1.6q-.48 0-.768-.256-.288-.224-.48-.64-.16-.384-.224-.896-.064-.48-.064-.96v-5.824q0-1.216-.352-2.016-.32-.8-.768-1.28-.448-.512-.928-.736-.448-.224-.736-.256v-.096q.288-.064.736-.32.48-.256.928-.768t.768-1.28q.352-.8.352-1.92V7.977q0-.512.064-.992.064-.512.224-.896.192-.384.48-.608.288-.256.768-.256z" fill="#444"/></svg>
|
||||
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M15 5.225v-1.92h2.24q.608 0 1.216.288.608.256 1.12.8.48.512.8 1.312.32.768.32 1.792v5.824q0 .832.224 1.536t.608 1.216q.352.48.832.768.48.256.992.256v2.176q-.512 0-.992.256t-.832.736q-.384.48-.608 1.184t-.224 1.568v5.792q0 1.024-.32 1.792-.32.8-.8 1.312-.512.544-1.12.8-.608.288-1.216.288H15v-1.92h1.6q.48 0 .768-.256.288-.224.48-.64.16-.384.224-.896.064-.48.064-.96v-5.824q0-1.216.352-2.016.32-.8.768-1.28.448-.512.928-.736.448-.224.736-.256v-.096q-.288-.064-.736-.32-.48-.256-.928-.768t-.768-1.28q-.352-.8-.352-1.92V7.977q0-.512-.064-.992-.064-.512-.224-.896-.192-.384-.48-.608-.288-.256-.768-.256zm-3.648 0v-1.92h-2.24q-.608 0-1.216.288-.608.256-1.12.8-.48.512-.8 1.312-.32.768-.32 1.792v5.824q0 .832-.224 1.536t-.608 1.216q-.352.48-.832.768-.48.256-.992.256v2.176q.512 0 .992.256t.832.736q.384.48.608 1.184t.224 1.568v5.792q0 1.024.32 1.792.32.8.8 1.312.512.544 1.12.8.608.288 1.216.288h2.24v-1.92h-1.6q-.48 0-.768-.256-.288-.224-.48-.64-.16-.384-.224-.896-.064-.48-.064-.96v-5.824q0-1.216-.352-2.016-.32-.8-.768-1.28-.448-.512-.928-.736-.448-.224-.736-.256v-.096q.288-.064.736-.32.48-.256.928-.768t.768-1.28q.352-.8.352-1.92V7.977q0-.512.064-.992.064-.512.224-.896.192-.384.48-.608.288-.256.768-.256z" fill="#444"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 1.3 KiB After Width: | Height: | Size: 1.3 KiB |
@@ -1 +1 @@
|
||||
<svg width="26" height="36" xmlns="http://www.w3.org/2000/svg"><path d="M2 19h5v5H2zm16.099-3.304v-5.659h-2.654v5.66l-5.309-2.004-.901 2.404L14.543 18l-3.255 4.557 2.254 1.553 3.255-4.808 3.455 4.808 2.054-1.553L19 18l5.46-1.903-1.002-2.404z" color="#000" fill="#444444"/></svg>
|
||||
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M2 19h5v5H2zm16.099-3.304v-5.659h-2.654v5.66l-5.309-2.004-.901 2.404L14.543 18l-3.255 4.557 2.254 1.553 3.255-4.808 3.455 4.808 2.054-1.553L19 18l5.46-1.903-1.002-2.404z" color="#000" fill="#444444"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 279 B After Width: | Height: | Size: 302 B |
@@ -1 +1 @@
|
||||
<svg width="26" height="36" xmlns="http://www.w3.org/2000/svg"><path d="M11 5v5.77a7.542 7.542 0 0 0-5.234 5.25L1 16c-1.432 1.397-1.232 2.722 0 4l4.75-.078a7.542 7.542 0 0 0 5.22 5.297L11 31c1.316 1.303 2.649 1.363 4 0l.009-5.775A7.542 7.542 0 0 0 20.228 20H25c1.261-1.294 1.404-2.623 0-4l-4.774-.01a7.542 7.542 0 0 0-5.23-5.22L15 5c-1.3-1.273-2.63-1.393-4 0zm2 7.499c3.05 0 5.5 2.45 5.5 5.5s-2.45 5.5-5.5 5.5-5.5-2.45-5.5-5.5 2.45-5.5 5.5-5.5z" color="#000" fill="#444"/></svg>
|
||||
<svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M11 5v5.77a7.542 7.542 0 0 0-5.234 5.25L1 16c-1.432 1.397-1.232 2.722 0 4l4.75-.078a7.542 7.542 0 0 0 5.22 5.297L11 31c1.316 1.303 2.649 1.363 4 0l.009-5.775A7.542 7.542 0 0 0 20.228 20H25c1.261-1.294 1.404-2.623 0-4l-4.774-.01a7.542 7.542 0 0 0-5.23-5.22L15 5c-1.3-1.273-2.63-1.393-4 0zm2 7.499c3.05 0 5.5 2.45 5.5 5.5s-2.45 5.5-5.5 5.5-5.5-2.45-5.5-5.5 2.45-5.5 5.5-5.5z" color="#000" fill="#444"/></svg>
|
||||
|
||||
|
Before Width: | Height: | Size: 479 B After Width: | Height: | Size: 502 B |
@@ -32,14 +32,19 @@
|
||||
}
|
||||
}
|
||||
}
|
||||
function emit(evt,arg) {
|
||||
function emit() {
|
||||
var evt = arguments[0]
|
||||
var args = Array.prototype.slice.call(arguments,1);
|
||||
if (RED.events.DEBUG) {
|
||||
console.warn(evt,args);
|
||||
}
|
||||
if (handlers[evt]) {
|
||||
for (var i=0;i<handlers[evt].length;i++) {
|
||||
try {
|
||||
handlers[evt][i](arg);
|
||||
handlers[evt][i].apply(null, args);
|
||||
} catch(err) {
|
||||
console.log("RED.events.emit error: ["+evt+"] "+(err.toString()));
|
||||
console.log(err);
|
||||
console.warn("RED.events.emit error: ["+evt+"] "+(err.toString()));
|
||||
console.warn(err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -808,17 +808,7 @@ RED.nodes.fontAwesome = (function() {
|
||||
"fa-youtube": "\uf167",
|
||||
};
|
||||
|
||||
var iconList = [];
|
||||
var isUsed = {};
|
||||
Object.keys(iconMap).forEach(function(icon) {
|
||||
var unicode = iconMap[icon];
|
||||
// skip icons with a same unicode
|
||||
if (isUsed[unicode] !== true) {
|
||||
iconList.push(icon);
|
||||
isUsed[unicode] = true;
|
||||
}
|
||||
});
|
||||
isUsed = undefined;
|
||||
var iconList = Object.keys(iconMap);
|
||||
|
||||
return {
|
||||
getIconUnicode: function(name) {
|
||||
|
||||
@@ -21,6 +21,7 @@ RED.history = (function() {
|
||||
var i;
|
||||
var len;
|
||||
var node;
|
||||
var group;
|
||||
var subflow;
|
||||
var modifiedTabs = {};
|
||||
var inverseEv;
|
||||
@@ -36,15 +37,20 @@ RED.history = (function() {
|
||||
inverseEv.events.push(r);
|
||||
}
|
||||
} else if (ev.t == 'replace') {
|
||||
if (ev.complete) {
|
||||
// This is a replace of everything. We can short-cut
|
||||
// the logic by clearing everyting first, then importing
|
||||
// the ev.config.
|
||||
// Used by RED.diff.mergeDiff
|
||||
inverseEv = {
|
||||
t: 'replace',
|
||||
config: RED.nodes.createCompleteNodeSet(),
|
||||
changed: [],
|
||||
changed: {},
|
||||
rev: RED.nodes.version()
|
||||
};
|
||||
RED.nodes.clear();
|
||||
var imported = RED.nodes.import(ev.config);
|
||||
imported[0].forEach(function(n) {
|
||||
imported.nodes.forEach(function(n) {
|
||||
if (ev.changed[n.id]) {
|
||||
n.changed = true;
|
||||
inverseEv.changed[n.id] = true;
|
||||
@@ -52,6 +58,17 @@ RED.history = (function() {
|
||||
})
|
||||
|
||||
RED.nodes.version(ev.rev);
|
||||
} else {
|
||||
var importMap = {};
|
||||
ev.config.forEach(function(n) {
|
||||
importMap[n.id] = "replace";
|
||||
})
|
||||
var importedResult = RED.nodes.import(ev.config,{importMap: importMap})
|
||||
inverseEv = {
|
||||
t: 'replace',
|
||||
config: importedResult.removedNodes
|
||||
}
|
||||
}
|
||||
} else if (ev.t == 'add') {
|
||||
inverseEv = {
|
||||
t: "delete",
|
||||
@@ -65,6 +82,14 @@ RED.history = (function() {
|
||||
}
|
||||
inverseEv.nodes.push(node);
|
||||
RED.nodes.remove(ev.nodes[i]);
|
||||
if (node.g) {
|
||||
var group = RED.nodes.group(node.g);
|
||||
var index = group.nodes.indexOf(node);
|
||||
if (index !== -1) {
|
||||
group.nodes.splice(index,1);
|
||||
RED.group.markDirty(group);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ev.links) {
|
||||
@@ -74,6 +99,17 @@ RED.history = (function() {
|
||||
RED.nodes.removeLink(ev.links[i]);
|
||||
}
|
||||
}
|
||||
if (ev.groups) {
|
||||
inverseEv.groups = [];
|
||||
for (i = ev.groups.length - 1;i>=0;i--) {
|
||||
group = ev.groups[i];
|
||||
modifiedTabs[group.z] = true;
|
||||
// The order of groups is important
|
||||
// - to invert the action, the order is reversed
|
||||
inverseEv.groups.unshift(group);
|
||||
RED.nodes.removeGroup(group);
|
||||
}
|
||||
}
|
||||
if (ev.workspaces) {
|
||||
inverseEv.workspaces = [];
|
||||
for (i=0;i<ev.workspaces.length;i++) {
|
||||
@@ -186,19 +222,46 @@ RED.history = (function() {
|
||||
RED.nodes.filterNodes({type:"subflow:"+subflow.id}).forEach(function(n) {
|
||||
n.inputs = subflow.in.length;
|
||||
n.outputs = subflow.out.length;
|
||||
while (n.outputs > n.ports.length) {
|
||||
n.ports.push(n.ports.length);
|
||||
}
|
||||
n.resize = true;
|
||||
n.dirty = true;
|
||||
});
|
||||
}
|
||||
if (ev.groups) {
|
||||
inverseEv.groups = [];
|
||||
var groupsToAdd = {};
|
||||
ev.groups.forEach(function(g) { groupsToAdd[g.id] = g; });
|
||||
for (i = ev.groups.length - 1;i>=0;i--) {
|
||||
RED.nodes.addGroup(ev.groups[i])
|
||||
modifiedTabs[ev.groups[i].z] = true;
|
||||
// The order of groups is important
|
||||
// - to invert the action, the order is reversed
|
||||
inverseEv.groups.unshift(ev.groups[i]);
|
||||
if (ev.groups[i].g) {
|
||||
if (!groupsToAdd[ev.groups[i].g]) {
|
||||
group = RED.nodes.group(ev.groups[i].g);
|
||||
} else {
|
||||
group = groupsToAdd[ev.groups[i].g];
|
||||
}
|
||||
if (group.nodes.indexOf(ev.groups[i]) === -1) {
|
||||
group.nodes.push(ev.groups[i]);
|
||||
}
|
||||
RED.group.markDirty(ev.groups[i])
|
||||
}
|
||||
}
|
||||
}
|
||||
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.nodes[i].g) {
|
||||
group = RED.nodes.group(ev.nodes[i].g);
|
||||
if (group.nodes.indexOf(ev.nodes[i]) === -1) {
|
||||
group.nodes.push(ev.nodes[i]);
|
||||
}
|
||||
RED.group.markDirty(group)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ev.links) {
|
||||
@@ -227,9 +290,12 @@ RED.history = (function() {
|
||||
}
|
||||
node.dirty = true;
|
||||
}
|
||||
RED.events.emit("nodes:change",node);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (subflow) {
|
||||
RED.events.emit("subflows:change", subflow);
|
||||
}
|
||||
} else if (ev.t == "move") {
|
||||
inverseEv = {
|
||||
@@ -260,6 +326,13 @@ RED.history = (function() {
|
||||
RED.nodes.addLink(ev.removedLinks[i]);
|
||||
}
|
||||
}
|
||||
if (ev.addToGroup) {
|
||||
RED.group.removeFromGroup(ev.addToGroup,ev.nodes.map(function(n) { return n.n }),false);
|
||||
inverseEv.removeFromGroup = ev.addToGroup;
|
||||
} else if (ev.removeFromGroup) {
|
||||
RED.group.addToGroup(ev.removeFromGroup,ev.nodes.map(function(n) { return n.n }));
|
||||
inverseEv.addToGroup = ev.removeFromGroup;
|
||||
}
|
||||
} else if (ev.t == "edit") {
|
||||
inverseEv = {
|
||||
t: "edit",
|
||||
@@ -270,19 +343,44 @@ RED.history = (function() {
|
||||
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]);
|
||||
if (currentConfigNode) {
|
||||
// This property is a reference to another node or nodes.
|
||||
var nodeList = ev.node[i];
|
||||
if (!Array.isArray(nodeList)) {
|
||||
nodeList = [nodeList];
|
||||
}
|
||||
nodeList.forEach(function(id) {
|
||||
var currentConfigNode = RED.nodes.node(id);
|
||||
if (currentConfigNode && currentConfigNode._def.category === "config") {
|
||||
currentConfigNode.users.splice(currentConfigNode.users.indexOf(ev.node),1);
|
||||
RED.events.emit("nodes:change",currentConfigNode);
|
||||
}
|
||||
var newConfigNode = RED.nodes.node(ev.changes[i]);
|
||||
if (newConfigNode) {
|
||||
});
|
||||
nodeList = ev.changes[i];
|
||||
if (!Array.isArray(nodeList)) {
|
||||
nodeList = [nodeList];
|
||||
}
|
||||
nodeList.forEach(function(id) {
|
||||
var newConfigNode = RED.nodes.node(id);
|
||||
if (newConfigNode && newConfigNode._def.category === "config") {
|
||||
newConfigNode.users.push(ev.node);
|
||||
RED.events.emit("nodes:change",newConfigNode);
|
||||
}
|
||||
});
|
||||
}
|
||||
ev.node[i] = ev.changes[i];
|
||||
}
|
||||
}
|
||||
var eventType;
|
||||
switch(ev.node.type) {
|
||||
case 'tab': eventType = "flows"; break;
|
||||
case 'group': eventType = "groups"; break;
|
||||
case 'subflow': eventType = "subflows"; break;
|
||||
default: eventType = "nodes"; break;
|
||||
}
|
||||
eventType += ":change";
|
||||
RED.events.emit(eventType,ev.node);
|
||||
|
||||
|
||||
if (ev.node.type === 'tab' && ev.changes.hasOwnProperty('disabled')) {
|
||||
$("#red-ui-tab-"+(ev.node.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!ev.node.disabled);
|
||||
$("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!ev.node.disabled);
|
||||
@@ -342,6 +440,7 @@ RED.history = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
ev.node.__outputs = inverseEv.changes.outputs;
|
||||
RED.editor.updateNodeProperties(ev.node,outputMap);
|
||||
RED.editor.validateNode(ev.node);
|
||||
}
|
||||
@@ -370,7 +469,9 @@ RED.history = (function() {
|
||||
if (ev.nodes) {
|
||||
inverseEv.movedNodes = [];
|
||||
var z = ev.activeWorkspace;
|
||||
RED.nodes.filterNodes({z:ev.subflow.subflow.id}).forEach(function(n) {
|
||||
var fullNodeList = RED.nodes.filterNodes({z:ev.subflow.subflow.id});
|
||||
fullNodeList = fullNodeList.concat(RED.nodes.groups(ev.subflow.subflow.id))
|
||||
fullNodeList.forEach(function(n) {
|
||||
n.x += ev.subflow.offsetX;
|
||||
n.y += ev.subflow.offsetY;
|
||||
n.dirty = true;
|
||||
@@ -411,6 +512,9 @@ RED.history = (function() {
|
||||
if (ev.subflow) {
|
||||
RED.nodes.addSubflow(ev.subflow.subflow);
|
||||
inverseEv.subflow = ev.subflow;
|
||||
if (ev.subflow.subflow.g) {
|
||||
RED.group.addToGroup(RED.nodes.group(ev.subflow.subflow.g),ev.subflow.subflow);
|
||||
}
|
||||
}
|
||||
if (ev.subflows) {
|
||||
inverseEv.nodes = [];
|
||||
@@ -422,6 +526,9 @@ RED.history = (function() {
|
||||
if (ev.movedNodes) {
|
||||
ev.movedNodes.forEach(function(nid) {
|
||||
nn = RED.nodes.node(nid);
|
||||
if (!nn) {
|
||||
nn = RED.nodes.group(nid);
|
||||
}
|
||||
nn.x -= ev.subflow.offsetX;
|
||||
nn.y -= ev.subflow.offsetY;
|
||||
nn.dirty = true;
|
||||
@@ -450,6 +557,60 @@ RED.history = (function() {
|
||||
if (ev.order) {
|
||||
RED.workspaces.order(ev.order);
|
||||
}
|
||||
} else if (ev.t == "createGroup") {
|
||||
inverseEv = {
|
||||
t: "ungroup",
|
||||
dirty: RED.nodes.dirty(),
|
||||
groups: []
|
||||
}
|
||||
if (ev.groups) {
|
||||
for (i=0;i<ev.groups.length;i++) {
|
||||
inverseEv.groups.push(ev.groups[i]);
|
||||
RED.group.ungroup(ev.groups[i]);
|
||||
}
|
||||
}
|
||||
} else if (ev.t == "ungroup") {
|
||||
inverseEv = {
|
||||
t: "createGroup",
|
||||
dirty: RED.nodes.dirty(),
|
||||
groups: []
|
||||
}
|
||||
if (ev.groups) {
|
||||
for (i=0;i<ev.groups.length;i++) {
|
||||
inverseEv.groups.push(ev.groups[i]);
|
||||
var nodes = ev.groups[i].nodes.slice();
|
||||
ev.groups[i].nodes = [];
|
||||
RED.nodes.addGroup(ev.groups[i]);
|
||||
RED.group.addToGroup(ev.groups[i],nodes);
|
||||
}
|
||||
}
|
||||
} else if (ev.t == "addToGroup") {
|
||||
inverseEv = {
|
||||
t: "removeFromGroup",
|
||||
dirty: RED.nodes.dirty(),
|
||||
group: ev.group,
|
||||
nodes: ev.nodes,
|
||||
reparent: ev.reparent
|
||||
}
|
||||
if (ev.nodes) {
|
||||
RED.group.removeFromGroup(ev.group,ev.nodes,(ev.hasOwnProperty('reparent')&&ev.hasOwnProperty('reparent')!==undefined)?ev.reparent:true);
|
||||
}
|
||||
} else if (ev.t == "removeFromGroup") {
|
||||
inverseEv = {
|
||||
t: "addToGroup",
|
||||
dirty: RED.nodes.dirty(),
|
||||
group: ev.group,
|
||||
nodes: ev.nodes,
|
||||
reparent: ev.reparent
|
||||
}
|
||||
if (ev.nodes) {
|
||||
RED.group.addToGroup(ev.group,ev.nodes);
|
||||
}
|
||||
}
|
||||
|
||||
if(ev.callback && typeof ev.callback === 'function') {
|
||||
inverseEv.callback = ev.callback;
|
||||
ev.callback(ev);
|
||||
}
|
||||
|
||||
Object.keys(modifiedTabs).forEach(function(id) {
|
||||
@@ -460,9 +621,8 @@ RED.history = (function() {
|
||||
});
|
||||
|
||||
RED.nodes.dirty(ev.dirty);
|
||||
RED.view.updateActive();
|
||||
RED.view.select(null);
|
||||
RED.view.redraw(true);
|
||||
RED.palette.refresh();
|
||||
RED.workspaces.refresh();
|
||||
RED.sidebar.config.refresh();
|
||||
RED.subflow.refresh();
|
||||
@@ -482,6 +642,9 @@ RED.history = (function() {
|
||||
list: function() {
|
||||
return undoHistory;
|
||||
},
|
||||
listRedo: function() {
|
||||
return redoHistory;
|
||||
},
|
||||
depth: function() {
|
||||
return undoHistory.length;
|
||||
},
|
||||
|
||||
@@ -108,6 +108,31 @@ RED.i18n = (function() {
|
||||
}
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
loadPluginCatalogs: function(done) {
|
||||
var languageList = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage());
|
||||
var toLoad = languageList.length;
|
||||
|
||||
languageList.forEach(function(lang) {
|
||||
$.ajax({
|
||||
headers: {
|
||||
"Accept":"application/json"
|
||||
},
|
||||
cache: false,
|
||||
url: apiRootUrl+'plugins/messages?lng='+lang,
|
||||
success: function(data) {
|
||||
var namespaces = Object.keys(data);
|
||||
namespaces.forEach(function(ns) {
|
||||
i18n.addResourceBundle(lang,ns,data[ns]);
|
||||
});
|
||||
toLoad--;
|
||||
if (toLoad === 0) {
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -3,13 +3,14 @@
|
||||
"alt-shift-p":"core:manage-palette",
|
||||
"ctrl-f": "core:search",
|
||||
"ctrl-shift-f": "core:list-flows",
|
||||
"ctrl-=": "core:zoom-in",
|
||||
"ctrl-+": "core:zoom-in",
|
||||
"ctrl--": "core:zoom-out",
|
||||
"ctrl-0": "core:zoom-reset",
|
||||
"ctrl-enter": "core:confirm-edit-tray",
|
||||
"ctrl-escape": "core:cancel-edit-tray",
|
||||
"ctrl-d": "core:deploy-flows",
|
||||
"ctrl-g i": "core:show-info-tab",
|
||||
"ctrl-g h": "core:show-help-tab",
|
||||
"ctrl-g d": "core:show-debug-tab",
|
||||
"ctrl-g c": "core:show-config-tab",
|
||||
"ctrl-g x": "core:show-context-tab",
|
||||
@@ -43,7 +44,18 @@
|
||||
"ctrl-z": "core:undo",
|
||||
"ctrl-y": "core:redo",
|
||||
"ctrl-a": "core:select-all-nodes",
|
||||
"alt-s u": "core:select-upstream-nodes",
|
||||
"alt-s d": "core:select-downstream-nodes",
|
||||
"alt-s c": "core:select-connected-nodes",
|
||||
"shift-?": "core:show-help",
|
||||
"w": "core:scroll-view-up",
|
||||
"d": "core:scroll-view-right",
|
||||
"s": "core:scroll-view-down",
|
||||
"a": "core:scroll-view-left",
|
||||
"shift-w": "core:step-view-up",
|
||||
"shift-d": "core:step-view-right",
|
||||
"shift-s": "core:step-view-down",
|
||||
"shift-a": "core:step-view-left",
|
||||
"up": "core:move-selection-up",
|
||||
"right": "core:move-selection-right",
|
||||
"down": "core:move-selection-down",
|
||||
@@ -53,6 +65,10 @@
|
||||
"shift-down": "core:step-selection-down",
|
||||
"shift-left": "core:step-selection-left",
|
||||
"ctrl-shift-j": "core:show-previous-tab",
|
||||
"ctrl-shift-k": "core:show-next-tab"
|
||||
"ctrl-shift-k": "core:show-next-tab",
|
||||
"ctrl-shift-g": "core:group-selection",
|
||||
"ctrl-shift-u": "core:ungroup-selection",
|
||||
"ctrl-shift-c": "core:copy-group-style",
|
||||
"ctrl-shift-v": "core:paste-group-style"
|
||||
}
|
||||
}
|
||||
|
||||
46
packages/node_modules/@node-red/editor-client/src/js/plugins.js
vendored
Normal file
@@ -0,0 +1,46 @@
|
||||
RED.plugins = (function() {
|
||||
var plugins = {};
|
||||
var pluginsByType = {};
|
||||
|
||||
function registerPlugin(id,definition) {
|
||||
plugins[id] = definition;
|
||||
if (definition.type) {
|
||||
pluginsByType[definition.type] = pluginsByType[definition.type] || [];
|
||||
pluginsByType[definition.type].push(definition);
|
||||
}
|
||||
if (RED._loadingModule) {
|
||||
definition.module = RED._loadingModule;
|
||||
definition["_"] = function() {
|
||||
var args = Array.prototype.slice.call(arguments);
|
||||
var originalKey = args[0];
|
||||
if (!/:/.test(args[0])) {
|
||||
args[0] = definition.module+":"+args[0];
|
||||
}
|
||||
var result = RED._.apply(null,args);
|
||||
if (result === args[0]) {
|
||||
return originalKey;
|
||||
}
|
||||
return result;
|
||||
}
|
||||
} else {
|
||||
definition["_"] = RED["_"]
|
||||
}
|
||||
if (definition.onadd && typeof definition.onadd === 'function') {
|
||||
definition.onadd();
|
||||
}
|
||||
RED.events.emit("registry:plugin-added",id);
|
||||
}
|
||||
|
||||
function getPlugin(id) {
|
||||
return plugins[id]
|
||||
}
|
||||
|
||||
function getPluginsByType(type) {
|
||||
return pluginsByType[type] || [];
|
||||
}
|
||||
return {
|
||||
registerPlugin: registerPlugin,
|
||||
getPlugin: getPlugin,
|
||||
getPluginsByType: getPluginsByType
|
||||
}
|
||||
})();
|
||||
56
packages/node_modules/@node-red/editor-client/src/js/polyfills.js
vendored
Normal file
@@ -0,0 +1,56 @@
|
||||
(function() {
|
||||
var isIE11 = !!window.MSInputMethodContext && !!document.documentMode;
|
||||
|
||||
if (isIE11) {
|
||||
// IE11 DOMTokenList.toggle does not support the two-argument variety
|
||||
window.DOMTokenList.prototype.toggle = function(cl,bo) {
|
||||
if (arguments.length === 1) {
|
||||
bo = !this.contains(cl);
|
||||
}
|
||||
this[!!bo?"add":"remove"](cl);
|
||||
}
|
||||
|
||||
// IE11 does not provide classList on SVGElements
|
||||
if (! ("classList" in SVGElement.prototype)) {
|
||||
Object.defineProperty(SVGElement.prototype, 'classList', Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'classList'));
|
||||
}
|
||||
|
||||
// IE11 does not provide children on SVGElements
|
||||
if (! ("children" in SVGElement.prototype)) {
|
||||
Object.defineProperty(SVGElement.prototype, 'children', Object.getOwnPropertyDescriptor(HTMLElement.prototype, 'children'));
|
||||
}
|
||||
|
||||
Array.from = function() {
|
||||
if (arguments.length > 1) {
|
||||
throw new Error("Node-RED's IE11 Array.from polyfill doesn't support multiple arguments");
|
||||
}
|
||||
var arrayLike = arguments[0]
|
||||
var result = [];
|
||||
if (arrayLike.forEach) {
|
||||
arrayLike.forEach(function(i) {
|
||||
result.push(i);
|
||||
})
|
||||
} else {
|
||||
for (var i=0;i<arrayLike.length;i++) {
|
||||
result.push(arrayList[i]);
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
if (new Set([0]).size === 0) {
|
||||
// IE does not support passing an iterable to Set constructor
|
||||
var _Set = Set;
|
||||
/*global Set:true */
|
||||
Set = function Set(iterable) {
|
||||
var set = new _Set();
|
||||
if (iterable) {
|
||||
iterable.forEach(set.add, set);
|
||||
}
|
||||
return set;
|
||||
};
|
||||
Set.prototype = _Set.prototype;
|
||||
Set.prototype.constructor = Set;
|
||||
}
|
||||
}
|
||||
})();
|
||||
@@ -15,19 +15,65 @@
|
||||
**/
|
||||
var RED = (function() {
|
||||
|
||||
function appendNodeConfig(nodeConfig,done) {
|
||||
|
||||
function loadPluginList() {
|
||||
loader.reportProgress(RED._("event.loadPlugins"), 10)
|
||||
$.ajax({
|
||||
headers: {
|
||||
"Accept":"application/json"
|
||||
},
|
||||
cache: false,
|
||||
url: 'plugins',
|
||||
success: function(data) {
|
||||
loader.reportProgress(RED._("event.loadPlugins"), 13)
|
||||
RED.i18n.loadPluginCatalogs(function() {
|
||||
loadPlugins(function() {
|
||||
loadNodeList();
|
||||
});
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
function loadPlugins(done) {
|
||||
loader.reportProgress(RED._("event.loadPlugins",{count:""}), 17)
|
||||
var lang = localStorage.getItem("editor-language")||i18n.detectLanguage();
|
||||
|
||||
$.ajax({
|
||||
headers: {
|
||||
"Accept":"text/html",
|
||||
"Accept-Language": lang
|
||||
},
|
||||
cache: false,
|
||||
url: 'plugins',
|
||||
success: function(data) {
|
||||
var configs = data.trim().split(/(?=<!-- --- \[red-plugin:\S+\] --- -->)/);
|
||||
var totalCount = configs.length;
|
||||
var stepConfig = function() {
|
||||
// loader.reportProgress(RED._("event.loadNodes",{count:(totalCount-configs.length)+"/"+totalCount}), 30 + ((totalCount-configs.length)/totalCount)*40 )
|
||||
if (configs.length === 0) {
|
||||
done();
|
||||
} else {
|
||||
var config = configs.shift();
|
||||
appendPluginConfig(config,stepConfig);
|
||||
}
|
||||
}
|
||||
stepConfig();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function appendConfig(config, moduleIdMatch, targetContainer, done) {
|
||||
done = done || function(){};
|
||||
var m = /<!-- --- \[red-module:(\S+)\] --- -->/.exec(nodeConfig.trim());
|
||||
var moduleId;
|
||||
if (m) {
|
||||
moduleId = m[1];
|
||||
if (moduleIdMatch) {
|
||||
moduleId = moduleIdMatch[1];
|
||||
RED._loadingModule = moduleId;
|
||||
} else {
|
||||
moduleId = "unknown";
|
||||
}
|
||||
try {
|
||||
var hasDeferred = false;
|
||||
|
||||
var nodeConfigEls = $("<div>"+nodeConfig+"</div>");
|
||||
var nodeConfigEls = $("<div>"+config+"</div>");
|
||||
var scripts = nodeConfigEls.find("script");
|
||||
var scriptCount = scripts.length;
|
||||
scripts.each(function(i,el) {
|
||||
@@ -38,14 +84,15 @@ var RED = (function() {
|
||||
newScript.onload = function() {
|
||||
scriptCount--;
|
||||
if (scriptCount === 0) {
|
||||
$("#red-ui-editor-node-configs").append(nodeConfigEls);
|
||||
$(targetContainer).append(nodeConfigEls);
|
||||
delete RED._loadingModule;
|
||||
done()
|
||||
}
|
||||
}
|
||||
if ($(el).attr('type') === "module") {
|
||||
newScript.type = "module";
|
||||
}
|
||||
$("#red-ui-editor-node-configs").append(newScript);
|
||||
$(targetContainer).append(newScript);
|
||||
newScript.src = RED.settings.apiRootUrl+srcUrl;
|
||||
hasDeferred = true;
|
||||
} else {
|
||||
@@ -61,7 +108,8 @@ var RED = (function() {
|
||||
}
|
||||
})
|
||||
if (!hasDeferred) {
|
||||
$("#red-ui-editor-node-configs").append(nodeConfigEls);
|
||||
$(targetContainer).append(nodeConfigEls);
|
||||
delete RED._loadingModule;
|
||||
done();
|
||||
}
|
||||
} catch(err) {
|
||||
@@ -70,11 +118,30 @@ var RED = (function() {
|
||||
timeout: 10000
|
||||
});
|
||||
console.log("["+moduleId+"] "+err.toString());
|
||||
delete RED._loadingModule;
|
||||
done();
|
||||
}
|
||||
}
|
||||
function appendPluginConfig(pluginConfig,done) {
|
||||
appendConfig(
|
||||
pluginConfig,
|
||||
/<!-- --- \[red-plugin:(\S+)\] --- -->/.exec(pluginConfig.trim()),
|
||||
"#red-ui-editor-plugin-configs",
|
||||
done
|
||||
);
|
||||
}
|
||||
|
||||
function appendNodeConfig(nodeConfig,done) {
|
||||
appendConfig(
|
||||
nodeConfig,
|
||||
/<!-- --- \[red-module:(\S+)\] --- -->/.exec(nodeConfig.trim()),
|
||||
"#red-ui-editor-node-configs",
|
||||
done
|
||||
);
|
||||
}
|
||||
|
||||
function loadNodeList() {
|
||||
loader.reportProgress(RED._("event.loadPalette"), 20)
|
||||
$.ajax({
|
||||
headers: {
|
||||
"Accept":"application/json"
|
||||
@@ -83,6 +150,7 @@ var RED = (function() {
|
||||
url: 'nodes',
|
||||
success: function(data) {
|
||||
RED.nodes.setNodeList(data);
|
||||
loader.reportProgress(RED._("event.loadNodeCatalogs"), 25)
|
||||
RED.i18n.loadNodeCatalogs(function() {
|
||||
loadIconList(loadNodes);
|
||||
});
|
||||
@@ -107,6 +175,7 @@ var RED = (function() {
|
||||
}
|
||||
|
||||
function loadNodes() {
|
||||
loader.reportProgress(RED._("event.loadNodes",{count:""}), 30)
|
||||
var lang = localStorage.getItem("editor-language")||i18n.detectLanguage();
|
||||
|
||||
$.ajax({
|
||||
@@ -118,15 +187,19 @@ var RED = (function() {
|
||||
url: 'nodes',
|
||||
success: function(data) {
|
||||
var configs = data.trim().split(/(?=<!-- --- \[red-module:\S+\] --- -->)/);
|
||||
var totalCount = configs.length;
|
||||
|
||||
var stepConfig = function() {
|
||||
loader.reportProgress(RED._("event.loadNodes",{count:(totalCount-configs.length)+"/"+totalCount}), 30 + ((totalCount-configs.length)/totalCount)*40 )
|
||||
|
||||
if (configs.length === 0) {
|
||||
$("#red-ui-editor").i18n();
|
||||
$("#red-ui-palette > .red-ui-palette-spinner").hide();
|
||||
$(".red-ui-palette-scroll").removeClass("hide");
|
||||
$("#red-ui-palette-search").removeClass("hide");
|
||||
loadFlows(function() {
|
||||
if (RED.settings.theme("projects.enabled",false)) {
|
||||
RED.projects.refresh(function(activeProject) {
|
||||
loadFlows(function() {
|
||||
RED.sidebar.info.refresh()
|
||||
if (!activeProject) {
|
||||
// Projects enabled but no active project
|
||||
@@ -140,12 +213,14 @@ var RED = (function() {
|
||||
}
|
||||
completeLoad();
|
||||
});
|
||||
});
|
||||
} else {
|
||||
loadFlows(function() {
|
||||
// Projects disabled by the user
|
||||
RED.sidebar.info.refresh()
|
||||
completeLoad();
|
||||
}
|
||||
});
|
||||
}
|
||||
} else {
|
||||
var config = configs.shift();
|
||||
appendNodeConfig(config,stepConfig);
|
||||
@@ -157,6 +232,7 @@ var RED = (function() {
|
||||
}
|
||||
|
||||
function loadFlows(done) {
|
||||
loader.reportProgress(RED._("event.loadFlows"),80 )
|
||||
$.ajax({
|
||||
headers: {
|
||||
"Accept":"application/json",
|
||||
@@ -167,12 +243,24 @@ var RED = (function() {
|
||||
if (nodes) {
|
||||
var currentHash = window.location.hash;
|
||||
RED.nodes.version(nodes.rev);
|
||||
loader.reportProgress(RED._("event.importFlows"),90 )
|
||||
try {
|
||||
RED.nodes.import(nodes.flows);
|
||||
RED.nodes.dirty(false);
|
||||
RED.view.redraw(true);
|
||||
if (/^#flow\/.+$/.test(currentHash)) {
|
||||
RED.workspaces.show(currentHash.substring(6));
|
||||
}
|
||||
} catch(err) {
|
||||
console.warn(err);
|
||||
RED.notify(
|
||||
RED._("event.importError", {message: err.message}),
|
||||
{
|
||||
fixed: true,
|
||||
type: 'error'
|
||||
}
|
||||
);
|
||||
}
|
||||
}
|
||||
done();
|
||||
}
|
||||
@@ -193,6 +281,7 @@ var RED = (function() {
|
||||
return;
|
||||
}
|
||||
if (notificationId === "project-update") {
|
||||
loader.start("Loading project",0)
|
||||
RED.nodes.clear();
|
||||
RED.history.clear();
|
||||
RED.view.redraw(true);
|
||||
@@ -208,7 +297,8 @@ var RED = (function() {
|
||||
"revert": RED._("notification.project.revert", {project: msg.project}),
|
||||
"merge-complete": RED._("notification.project.merge-complete")
|
||||
}[msg.action];
|
||||
RED.notify("<p>"+message+"</p>");
|
||||
loader.end()
|
||||
RED.notify($("<p>").text(message));
|
||||
RED.sidebar.info.refresh()
|
||||
});
|
||||
});
|
||||
@@ -225,6 +315,7 @@ var RED = (function() {
|
||||
id: notificationId
|
||||
}
|
||||
if (notificationId === "runtime-state") {
|
||||
RED.events.emit("runtime-state",msg);
|
||||
if (msg.error === "safe-mode") {
|
||||
options.buttons = [
|
||||
{
|
||||
@@ -246,7 +337,7 @@ var RED = (function() {
|
||||
}
|
||||
}
|
||||
]
|
||||
// } else if (RED.settings.theme('palette.editable') !== false) {
|
||||
// } else if (RED.settings.get('externalModules.palette.allowInstall', true) !== false) {
|
||||
} else {
|
||||
options.buttons = [
|
||||
{
|
||||
@@ -257,6 +348,16 @@ var RED = (function() {
|
||||
}
|
||||
]
|
||||
}
|
||||
} else if (msg.error === "missing-modules") {
|
||||
text+="<ul><li>"+msg.modules.map(function(m) { return RED.utils.sanitize(m.module)+(m.error?(" - <small>"+RED.utils.sanitize(""+m.error)+"</small>"):"")}).join("</li><li>")+"</li></ul>";
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("common.label.close"),
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
}
|
||||
}
|
||||
]
|
||||
} else if (msg.error === "credentials_load_failed") {
|
||||
if (RED.settings.theme("projects.enabled",false)) {
|
||||
// projects enabled
|
||||
@@ -347,19 +448,22 @@ var RED = (function() {
|
||||
} else if (persistentNotifications.hasOwnProperty(notificationId)) {
|
||||
persistentNotifications[notificationId].close();
|
||||
delete persistentNotifications[notificationId];
|
||||
if (notificationId === 'runtime-state') {
|
||||
RED.events.emit("runtime-state",msg);
|
||||
}
|
||||
}
|
||||
});
|
||||
RED.comms.subscribe("status/#",function(topic,msg) {
|
||||
var parts = topic.split("/");
|
||||
var node = RED.nodes.node(parts[1]);
|
||||
if (node) {
|
||||
if (msg.hasOwnProperty("text") && /^[a-zA-Z]/.test(msg.text)) {
|
||||
if (msg.hasOwnProperty("text") && msg.text !== null && /^[a-zA-Z]/.test(msg.text)) {
|
||||
msg.text = node._(msg.text.toString(),{defaultValue:msg.text.toString()});
|
||||
}
|
||||
node.status = msg;
|
||||
node.dirtyStatus = true;
|
||||
node.dirty = true;
|
||||
RED.view.redraw();
|
||||
RED.view.redrawStatus(node);
|
||||
}
|
||||
});
|
||||
RED.comms.subscribe("notification/node/#",function(topic,msg) {
|
||||
@@ -379,7 +483,7 @@ var RED = (function() {
|
||||
});
|
||||
});
|
||||
if (addedTypes.length) {
|
||||
typeList = "<ul><li>"+addedTypes.join("</li><li>")+"</li></ul>";
|
||||
typeList = "<ul><li>"+addedTypes.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeAdded", {count:addedTypes.length})+typeList,"success");
|
||||
}
|
||||
loadIconList();
|
||||
@@ -388,7 +492,7 @@ var RED = (function() {
|
||||
m = msg[i];
|
||||
info = RED.nodes.removeNodeSet(m.id);
|
||||
if (info.added) {
|
||||
typeList = "<ul><li>"+m.types.join("</li><li>")+"</li></ul>";
|
||||
typeList = "<ul><li>"+m.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeRemoved", {count:m.types.length})+typeList,"success");
|
||||
}
|
||||
}
|
||||
@@ -398,12 +502,12 @@ var RED = (function() {
|
||||
info = RED.nodes.getNodeSet(msg.id);
|
||||
if (info.added) {
|
||||
RED.nodes.enableNodeSet(msg.id);
|
||||
typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
|
||||
typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeEnabled", {count:msg.types.length})+typeList,"success");
|
||||
} else {
|
||||
$.get('nodes/'+msg.id, function(data) {
|
||||
appendNodeConfig(data);
|
||||
typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
|
||||
typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeAdded", {count:msg.types.length})+typeList,"success");
|
||||
});
|
||||
}
|
||||
@@ -411,20 +515,27 @@ var RED = (function() {
|
||||
} else if (topic == "notification/node/disabled") {
|
||||
if (msg.types) {
|
||||
RED.nodes.disableNodeSet(msg.id);
|
||||
typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
|
||||
typeList = "<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeDisabled", {count:msg.types.length})+typeList,"success");
|
||||
}
|
||||
} else if (topic == "notification/node/upgraded") {
|
||||
RED.notify(RED._("palette.event.nodeUpgraded", {module:msg.module,version:msg.version}),"success");
|
||||
RED.nodes.registry.setModulePendingUpdated(msg.module,msg.version);
|
||||
}
|
||||
// Refresh flow library to ensure any examples are updated
|
||||
RED.library.loadFlowLibrary();
|
||||
});
|
||||
RED.comms.subscribe("event-log/#", function(topic,payload) {
|
||||
var id = topic.substring(9);
|
||||
RED.eventLog.log(id,payload);
|
||||
});
|
||||
|
||||
$(".red-ui-header-toolbar").show();
|
||||
|
||||
|
||||
RED.sidebar.show(":first");
|
||||
|
||||
setTimeout(function() {
|
||||
loader.end();
|
||||
},100);
|
||||
}
|
||||
|
||||
function showAbout() {
|
||||
@@ -433,8 +544,7 @@ var RED = (function() {
|
||||
'<img width="50px" src="red/images/node-red-icon.svg" />'+
|
||||
'</div>';
|
||||
|
||||
RED.sidebar.info.set(aboutHeader+marked(data));
|
||||
RED.sidebar.info.show();
|
||||
RED.sidebar.help.set(aboutHeader+RED.utils.renderMarkdown(data));
|
||||
});
|
||||
}
|
||||
|
||||
@@ -455,8 +565,12 @@ var RED = (function() {
|
||||
null
|
||||
]});
|
||||
menuOptions.push(null);
|
||||
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);
|
||||
@@ -470,8 +584,16 @@ var RED = (function() {
|
||||
{id:"menu-item-subflow-create",label:RED._("menu.label.createSubflow"),onselect:"core:create-subflow"},
|
||||
{id:"menu-item-subflow-convert",label:RED._("menu.label.selectionToSubflow"),disabled:true,onselect:"core:convert-to-subflow"},
|
||||
]});
|
||||
menuOptions.push({id:"menu-item-group",label:RED._("menu.label.groups"), options: [
|
||||
{id:"menu-item-group-group",label:RED._("menu.label.groupSelection"),disabled:true,onselect:"core:group-selection"},
|
||||
{id:"menu-item-group-ungroup",label:RED._("menu.label.ungroupSelection"),disabled:true,onselect:"core:ungroup-selection"},
|
||||
null,
|
||||
{id:"menu-item-group-merge",label:RED._("menu.label.groupMergeSelection"),disabled:true,onselect:"core:merge-selection-to-group"},
|
||||
{id:"menu-item-group-remove",label:RED._("menu.label.groupRemoveSelection"),disabled:true,onselect:"core:remove-selection-from-group"}
|
||||
]});
|
||||
|
||||
menuOptions.push(null);
|
||||
if (RED.settings.theme('palette.editable') !== false) {
|
||||
if (RED.settings.get('externalModules.palette.allowInstall', true) !== false) {
|
||||
menuOptions.push({id:"menu-item-edit-palette",label:RED._("menu.label.editPalette"),onselect:"core:manage-palette"});
|
||||
menuOptions.push(null);
|
||||
}
|
||||
@@ -479,7 +601,9 @@ var RED = (function() {
|
||||
menuOptions.push({id:"menu-item-user-settings",label:RED._("menu.label.settings"),onselect:"core:show-user-settings"});
|
||||
menuOptions.push(null);
|
||||
|
||||
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")
|
||||
@@ -493,7 +617,6 @@ var RED = (function() {
|
||||
}
|
||||
|
||||
function loadEditor() {
|
||||
|
||||
RED.workspaces.init();
|
||||
RED.statusBar.init();
|
||||
RED.view.init();
|
||||
@@ -505,7 +628,7 @@ var RED = (function() {
|
||||
RED.palette.init();
|
||||
RED.eventLog.init();
|
||||
|
||||
if (RED.settings.theme('palette.editable') !== false) {
|
||||
if (RED.settings.get('externalModules.palette.allowInstall', true) !== false) {
|
||||
RED.palette.editor.init();
|
||||
} else {
|
||||
console.log("Palette editor disabled");
|
||||
@@ -520,6 +643,7 @@ var RED = (function() {
|
||||
}
|
||||
|
||||
RED.subflow.init();
|
||||
RED.group.init();
|
||||
RED.clipboard.init();
|
||||
RED.search.init();
|
||||
RED.actionList.init();
|
||||
@@ -535,13 +659,14 @@ var RED = (function() {
|
||||
RED.comms.connect();
|
||||
|
||||
$("#red-ui-main-container").show();
|
||||
$(".red-ui-header-toolbar").show();
|
||||
|
||||
|
||||
RED.actions.add("core:show-about", showAbout);
|
||||
|
||||
loadNodeList();
|
||||
loadPluginList();
|
||||
}
|
||||
|
||||
|
||||
function buildEditor(options) {
|
||||
var header = $('<div id="red-ui-header"></div>').appendTo(options.target);
|
||||
var logo = $('<span class="red-ui-header-logo"></span>').appendTo(header);
|
||||
@@ -554,8 +679,13 @@ var RED = (function() {
|
||||
'<div id="red-ui-sidebar"></div>'+
|
||||
'<div id="red-ui-sidebar-separator"></div>'+
|
||||
'</div>').appendTo(options.target);
|
||||
$('<div id="red-ui-editor-plugin-configs"></div>').appendTo(options.target);
|
||||
$('<div id="red-ui-editor-node-configs"></div>').appendTo(options.target);
|
||||
$('<div id="red-ui-full-shade" class="hide"></div>').appendTo(options.target);
|
||||
|
||||
loader.init().appendTo("#red-ui-main-container");
|
||||
loader.start("...",0);
|
||||
|
||||
$.getJSON(options.apiRootUrl+"theme", function(theme) {
|
||||
if (theme.header) {
|
||||
if (theme.header.url) {
|
||||
@@ -568,9 +698,12 @@ var RED = (function() {
|
||||
$('<span>').html(theme.header.title).appendTo(logo);
|
||||
}
|
||||
}
|
||||
if (theme.themes) {
|
||||
knownThemes = theme.themes;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var knownThemes = null;
|
||||
var initialised = false;
|
||||
|
||||
function init(options) {
|
||||
@@ -588,12 +721,45 @@ var RED = (function() {
|
||||
options.target.addClass("red-ui-editor");
|
||||
|
||||
buildEditor(options);
|
||||
|
||||
RED.i18n.init(options, function() {
|
||||
RED.settings.init(options, loadEditor);
|
||||
RED.settings.init(options, function() {
|
||||
if (knownThemes) {
|
||||
RED.settings.editorTheme = RED.settings.editorTheme || {};
|
||||
RED.settings.editorTheme.themes = knownThemes;
|
||||
}
|
||||
loadEditor();
|
||||
});
|
||||
})
|
||||
}
|
||||
|
||||
var loader = {
|
||||
init: function() {
|
||||
var wrapper = $('<div id="red-ui-loading-progress"></div>').hide();
|
||||
var container = $('<div>').appendTo(wrapper);
|
||||
var label = $('<div>',{class:"red-ui-loading-bar-label"}).appendTo(container);
|
||||
var bar = $('<div>',{class:"red-ui-loading-bar"}).appendTo(container);
|
||||
var fill =$('<span>').appendTo(bar);
|
||||
return wrapper;
|
||||
},
|
||||
start: function(text, prcnt) {
|
||||
if (text) {
|
||||
loader.reportProgress(text,prcnt)
|
||||
}
|
||||
$("#red-ui-loading-progress").show();
|
||||
},
|
||||
reportProgress: function(text, prcnt) {
|
||||
$(".red-ui-loading-bar-label").text(text);
|
||||
$(".red-ui-loading-bar span").width(prcnt+"%")
|
||||
},
|
||||
end: function() {
|
||||
$("#red-ui-loading-progress").hide();
|
||||
loader.reportProgress("",0);
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
init: init
|
||||
init: init,
|
||||
loader: loader
|
||||
}
|
||||
})();
|
||||
|
||||
@@ -56,12 +56,12 @@ RED.settings = (function () {
|
||||
if (key === "auth-tokens") {
|
||||
return JSON.parse(localStorage.getItem(key));
|
||||
} else {
|
||||
try {
|
||||
var v = RED.utils.getMessageProperty(userSettings,key);
|
||||
var v;
|
||||
try { v = RED.utils.getMessageProperty(userSettings,key); } catch(err) {}
|
||||
if (v === undefined) {
|
||||
v = defaultIfUndefined;
|
||||
try { v = RED.utils.getMessageProperty(RED.settings,key); } catch(err) {}
|
||||
}
|
||||
} catch(err) {
|
||||
if (v === undefined) {
|
||||
v = defaultIfUndefined;
|
||||
}
|
||||
return v;
|
||||
|
||||
@@ -21,7 +21,18 @@ RED.actions = (function() {
|
||||
var result = [];
|
||||
Object.keys(actions).forEach(function(action) {
|
||||
var shortcut = RED.keyboard.getShortcut(action);
|
||||
result.push({id:action,scope:shortcut?shortcut.scope:undefined,key:shortcut?shortcut.key:undefined,user:shortcut?shortcut.user:undefined})
|
||||
var isUser = false;
|
||||
if (shortcut) {
|
||||
isUser = shortcut.user;
|
||||
} else {
|
||||
isUser = !!RED.keyboard.getUserShortcut(action);
|
||||
}
|
||||
result.push({
|
||||
id:action,
|
||||
scope:shortcut?shortcut.scope:undefined,
|
||||
key:shortcut?shortcut.key:undefined,
|
||||
user:isUser
|
||||
})
|
||||
})
|
||||
return result;
|
||||
}
|
||||
|
||||
@@ -27,26 +27,26 @@
|
||||
this.partialFlag = false;
|
||||
this.stateValue = 0;
|
||||
var initialState = this.element.prop('checked');
|
||||
this.options = [
|
||||
this.states = [
|
||||
$('<span class="red-ui-checkboxSet-option hide"><i class="fa fa-square-o"></i></span>').appendTo(this.uiElement),
|
||||
$('<span class="red-ui-checkboxSet-option hide"><i class="fa fa-check-square-o"></i></span>').appendTo(this.uiElement),
|
||||
$('<span class="red-ui-checkboxSet-option hide"><i class="fa fa-minus-square-o"></i></span>').appendTo(this.uiElement)
|
||||
];
|
||||
if (initialState) {
|
||||
this.options[1].show();
|
||||
this.states[1].show();
|
||||
} else {
|
||||
this.options[0].show();
|
||||
this.states[0].show();
|
||||
}
|
||||
|
||||
this.element.on("change", function() {
|
||||
if (this.checked) {
|
||||
that.options[0].hide();
|
||||
that.options[1].show();
|
||||
that.options[2].hide();
|
||||
that.states[0].hide();
|
||||
that.states[1].show();
|
||||
that.states[2].hide();
|
||||
} else {
|
||||
that.options[1].hide();
|
||||
that.options[0].show();
|
||||
that.options[2].hide();
|
||||
that.states[1].hide();
|
||||
that.states[0].show();
|
||||
that.states[2].hide();
|
||||
}
|
||||
var isChecked = this.checked;
|
||||
that.children.forEach(function(child) {
|
||||
@@ -106,17 +106,17 @@
|
||||
var trueState = this.partialFlag||state;
|
||||
this.element.prop('checked',trueState);
|
||||
if (state === true) {
|
||||
this.options[0].hide();
|
||||
this.options[1].show();
|
||||
this.options[2].hide();
|
||||
this.states[0].hide();
|
||||
this.states[1].show();
|
||||
this.states[2].hide();
|
||||
} else if (state === false) {
|
||||
this.options[2].hide();
|
||||
this.options[1].hide();
|
||||
this.options[0].show();
|
||||
this.states[2].hide();
|
||||
this.states[1].hide();
|
||||
this.states[0].show();
|
||||
} else if (state === null) {
|
||||
this.options[0].hide();
|
||||
this.options[1].hide();
|
||||
this.options[2].show();
|
||||
this.states[0].hide();
|
||||
this.states[1].hide();
|
||||
this.states[2].show();
|
||||
}
|
||||
if (!suppressEvent) {
|
||||
this.element.trigger('change',null);
|
||||
|
||||
209
packages/node_modules/@node-red/editor-client/src/js/ui/common/colorPicker.js
vendored
Normal file
@@ -0,0 +1,209 @@
|
||||
RED.colorPicker = (function() {
|
||||
|
||||
function create(options) {
|
||||
var color = options.value;
|
||||
var id = options.id;
|
||||
var colorPalette = options.palette || [];
|
||||
var width = options.cellWidth || 30;
|
||||
var height = options.cellHeight || 30;
|
||||
var margin = options.cellMargin || 2;
|
||||
var perRow = options.cellPerRow || 6;
|
||||
|
||||
var container = $("<div>",{style:"display:inline-block"});
|
||||
var colorHiddenInput = $("<input/>", { id: id, type: "hidden", value: color }).appendTo(container);
|
||||
var opacityHiddenInput = $("<input/>", { id: id+"-opacity", type: "hidden", value: options.hasOwnProperty('opacity')?options.opacity:"1" }).appendTo(container);
|
||||
|
||||
var colorButton = $('<button type="button" class="red-ui-button red-ui-editor-node-appearance-button">').appendTo(container);
|
||||
$('<i class="fa fa-caret-down"></i>').appendTo(colorButton);
|
||||
|
||||
var colorDispContainer = $('<div>',{class:"red-ui-search-result-node"}).appendTo(colorButton);
|
||||
$('<div>',{class:"red-ui-color-picker-cell-none"}).appendTo(colorDispContainer);
|
||||
var colorDisp = $('<div>',{class:"red-ui-color-picker-swatch"}).appendTo(colorDispContainer);
|
||||
|
||||
|
||||
var refreshDisplay = function(color) {
|
||||
if (color === "none") {
|
||||
colorDisp.addClass('red-ui-color-picker-cell-none').css({
|
||||
"background-color": "",
|
||||
opacity: 1
|
||||
});
|
||||
colorDispContainer.css({
|
||||
"border-color":""
|
||||
})
|
||||
} else {
|
||||
var opacity = parseFloat(opacityHiddenInput.val())
|
||||
colorDisp.removeClass('red-ui-color-picker-cell-none').css({
|
||||
"background-color": color,
|
||||
"opacity": opacity
|
||||
});
|
||||
var border = RED.utils.getDarkerColor(color);
|
||||
if (border[0] === '#') {
|
||||
border += Math.round(255*Math.floor(opacity*100)/100).toString(16);
|
||||
} else {
|
||||
border = "";
|
||||
}
|
||||
|
||||
colorDispContainer.css({
|
||||
"border-color": border
|
||||
})
|
||||
}
|
||||
if (options.hasOwnProperty('opacity')) {
|
||||
$(".red-ui-color-picker-opacity-slider-overlay").css({
|
||||
"background-image": "linear-gradient(90deg, transparent 0%, "+color+" 100%)"
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
colorButton.on("click", function (e) {
|
||||
var numColors = colorPalette.length;
|
||||
|
||||
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;
|
||||
row = $("<div/>").appendTo(picker);
|
||||
|
||||
var colorInput = $('<input>',{
|
||||
type:"text",
|
||||
value:colorHiddenInput.val()
|
||||
}).appendTo(row);
|
||||
var focusTarget = colorInput;
|
||||
colorInput.on("change", function (e) {
|
||||
var color = colorInput.val();
|
||||
colorHiddenInput.val(color).trigger('change');
|
||||
refreshDisplay(color);
|
||||
});
|
||||
// if (options.hasOwnProperty('opacity')) {
|
||||
// var sliderContainer = $("<div>",{class:"red-ui-color-picker-opacity-slider"
|
||||
// }
|
||||
|
||||
if (options.none) {
|
||||
row = $("<div/>").appendTo(picker);
|
||||
var button = $("<button/>", {
|
||||
class:"red-ui-color-picker-cell red-ui-color-picker-cell-none"
|
||||
}).css({
|
||||
width: width+"px",
|
||||
height: height+"px",
|
||||
margin: margin+"px"
|
||||
}).appendTo(row);
|
||||
button.on("click", function (e) {
|
||||
e.preventDefault();
|
||||
colorInput.val("none");
|
||||
colorInput.trigger("change");
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
colorPalette.forEach(function (col) {
|
||||
if ((count % perRow) == 0) {
|
||||
row = $("<div/>").appendTo(picker);
|
||||
}
|
||||
var button = $("<button/>", {
|
||||
class:"red-ui-color-picker-cell"
|
||||
}).css({
|
||||
width: width+"px",
|
||||
height: height+"px",
|
||||
margin: margin+"px",
|
||||
backgroundColor: col,
|
||||
"border-color": RED.utils.getDarkerColor(col)
|
||||
}).appendTo(row);
|
||||
button.on("click", function (e) {
|
||||
e.preventDefault();
|
||||
// colorPanel.hide();
|
||||
colorInput.val(col);
|
||||
colorInput.trigger("change");
|
||||
});
|
||||
count++;
|
||||
});
|
||||
if (options.none || options.hasOwnProperty('opacity')) {
|
||||
row = $("<div/>").appendTo(picker);
|
||||
// if (options.none) {
|
||||
// var button = $("<button/>", {
|
||||
// class:"red-ui-color-picker-cell red-ui-color-picker-cell-none"
|
||||
// }).css({
|
||||
// width: width+"px",
|
||||
// height: height+"px",
|
||||
// margin: margin+"px"
|
||||
// }).appendTo(row);
|
||||
// button.on("click", function (e) {
|
||||
// e.preventDefault();
|
||||
// colorPanel.hide();
|
||||
// selector.val("none");
|
||||
// selector.trigger("change");
|
||||
// });
|
||||
// }
|
||||
if (options.hasOwnProperty('opacity')) {
|
||||
var sliderContainer = $("<div>",{class:"red-ui-color-picker-opacity-slider"}).appendTo(row);
|
||||
sliderContainer.on("mousedown", function(evt) {
|
||||
if (evt.target === sliderHandle[0]) {
|
||||
return;
|
||||
}
|
||||
var v = evt.offsetX/sliderContainer.width();
|
||||
sliderHandle.css({
|
||||
left: ( v*(sliderContainer.width() - sliderHandle.outerWidth()))+"px"
|
||||
});
|
||||
v = Math.floor(100*v)
|
||||
opacityHiddenInput.val(v/100)
|
||||
opacityLabel.text(v+"%");
|
||||
refreshDisplay(colorHiddenInput.val());
|
||||
})
|
||||
$("<div>",{class:"red-ui-color-picker-opacity-slider-overlay"}).appendTo(sliderContainer);
|
||||
var sliderHandle = $("<div>",{class:"red-ui-color-picker-opacity-slider-handle red-ui-button red-ui-button-small"}).appendTo(sliderContainer).draggable({
|
||||
containment: "parent",
|
||||
axis: "x",
|
||||
drag: function( event, ui ) {
|
||||
var v = Math.max(0,ui.position.left/($(this).parent().width()-$(this).outerWidth()));
|
||||
// Odd bug that if it is loaded with a non-0 value, the first time
|
||||
// it is dragged it ranges -1 to 99. But every other time, its 0 to 100.
|
||||
// The Math.max above makes the -1 disappear. The follow hack ensures
|
||||
// it always maxes out at a 100, at the cost of not allowing 99% exactly.
|
||||
v = Math.floor(100*v)
|
||||
if ( v === 99 ) {
|
||||
v = 100;
|
||||
}
|
||||
// console.log("uip",ui.position.left);
|
||||
opacityHiddenInput.val(v/100)
|
||||
opacityLabel.text(v+"%");
|
||||
refreshDisplay(colorHiddenInput.val());
|
||||
}
|
||||
});
|
||||
var opacityLabel = $('<small></small>').appendTo(row);
|
||||
setTimeout(function() {
|
||||
sliderHandle.css({
|
||||
left: (parseFloat(opacityHiddenInput.val())*(sliderContainer.width() - sliderHandle.outerWidth()))+"px"
|
||||
})
|
||||
opacityLabel.text(Math.floor(opacityHiddenInput.val()*100)+"%");
|
||||
},50);
|
||||
}
|
||||
}
|
||||
|
||||
var colorPanel = RED.popover.panel(picker);
|
||||
setTimeout(function() {
|
||||
refreshDisplay(colorHiddenInput.val())
|
||||
},50);
|
||||
colorPanel.show({
|
||||
target: colorButton,
|
||||
onclose: function() {
|
||||
colorButton.focus();
|
||||
}
|
||||
})
|
||||
if (focusTarget) {
|
||||
focusTarget.focus();
|
||||
}
|
||||
});
|
||||
setTimeout(function() {
|
||||
refreshDisplay(colorHiddenInput.val())
|
||||
},50);
|
||||
return container;
|
||||
}
|
||||
|
||||
return {
|
||||
create: create
|
||||
}
|
||||
})();
|
||||
@@ -18,6 +18,7 @@
|
||||
/**
|
||||
* options:
|
||||
* - addButton : boolean|string - text for add label, default 'add'
|
||||
* - buttons : array - list of custom buttons (objects with fields 'label', 'icon', 'title', 'click')
|
||||
* - height : number|'auto'
|
||||
* - resize : function - called when list as a whole is resized
|
||||
* - resizeItem : function(item) - called to resize individual item
|
||||
@@ -33,7 +34,7 @@
|
||||
* methods:
|
||||
* - addItem(itemData)
|
||||
* - insertItemAt : function(data,index) - add an item at the specified index
|
||||
* - removeItem(itemData)
|
||||
* - removeItem(itemData, detach) - remove the item. Optionally detach to preserve any event handlers on the item's label
|
||||
* - getItemAt(index)
|
||||
* - indexOf(itemData)
|
||||
* - width(width)
|
||||
@@ -67,30 +68,61 @@
|
||||
this.topContainer.addClass(this.options.class);
|
||||
}
|
||||
|
||||
var buttons = this.options.buttons || [];
|
||||
|
||||
if (this.options.addButton !== false) {
|
||||
var addLabel;
|
||||
var addLabel, addTittle;
|
||||
if (typeof this.options.addButton === 'string') {
|
||||
addLabel = this.options.addButton
|
||||
} else {
|
||||
if (RED && RED._) {
|
||||
addLabel = RED._("editableList.add");
|
||||
addTitle = RED._("editableList.addTitle");
|
||||
} else {
|
||||
addLabel = 'add';
|
||||
addTitle = 'add new item';
|
||||
}
|
||||
}
|
||||
$('<a href="#" class="red-ui-button red-ui-button-small red-ui-editableList-addButton" style="margin-top: 4px;"><i class="fa fa-plus"></i> '+addLabel+'</a>')
|
||||
.appendTo(this.topContainer)
|
||||
.on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
buttons.unshift({
|
||||
label: addLabel,
|
||||
icon: "fa fa-plus",
|
||||
click: function(evt) {
|
||||
that.addItem({});
|
||||
},
|
||||
title: addTitle
|
||||
});
|
||||
}
|
||||
|
||||
buttons.forEach(function(button) {
|
||||
var element = $('<a href="#" class="red-ui-button red-ui-button-small red-ui-editableList-addButton" style="margin-top: 4px; margin-right: 5px;"></a>')
|
||||
.appendTo(that.topContainer)
|
||||
.on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
if (button.click !== undefined) {
|
||||
button.click(evt);
|
||||
}
|
||||
});
|
||||
|
||||
if (button.title) {
|
||||
element.attr("title", button.title);
|
||||
}
|
||||
if (button.icon) {
|
||||
element.append($("<i></i>").attr("class", button.icon));
|
||||
}
|
||||
if (button.label) {
|
||||
element.append($("<span></span>").text(" " + button.label));
|
||||
}
|
||||
});
|
||||
|
||||
if (this.element.css("position") === "absolute") {
|
||||
["top","left","bottom","right"].forEach(function(s) {
|
||||
var v = that.element.css(s);
|
||||
if (v!=="auto" && v!=="") {
|
||||
that.topContainer.css(s,v);
|
||||
that.uiContainer.css(s,"0");
|
||||
if (s === "top" && that.options.header) {
|
||||
that.uiContainer.css(s,"20px")
|
||||
}
|
||||
that.element.css(s,'auto');
|
||||
}
|
||||
})
|
||||
@@ -183,7 +215,7 @@
|
||||
if (this.options.resizeItem) {
|
||||
var that = this;
|
||||
this.element.children().each(function(i) {
|
||||
that.options.resizeItem($(this).find(".red-ui-editableList-item-content"),i);
|
||||
that.options.resizeItem($(this).children(".red-ui-editableList-item-content"),i);
|
||||
});
|
||||
}
|
||||
},
|
||||
@@ -223,7 +255,7 @@
|
||||
var items = this.element.children();
|
||||
var that = this;
|
||||
items.sort(function(A,B) {
|
||||
return that.activeSort($(A).find(".red-ui-editableList-item-content").data('data'),$(B).find(".red-ui-editableList-item-content").data('data'));
|
||||
return that.activeSort($(A).children(".red-ui-editableList-item-content").data('data'),$(B).children(".red-ui-editableList-item-content").data('data'));
|
||||
});
|
||||
$.each(items,function(idx,li) {
|
||||
that.element.append(li);
|
||||
@@ -259,28 +291,6 @@
|
||||
var that = this;
|
||||
data = data || {};
|
||||
var li = $('<li>');
|
||||
var added = false;
|
||||
if (this.activeSort) {
|
||||
var items = this.items();
|
||||
var skip = false;
|
||||
items.each(function(i,el) {
|
||||
if (added) { return }
|
||||
var itemData = el.data('data');
|
||||
if (that.activeSort(data,itemData) < 0) {
|
||||
li.insertBefore(el.closest("li"));
|
||||
added = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!added) {
|
||||
if (index <= 0) {
|
||||
li.prependTo(this.element);
|
||||
} else if (index > that.element.children().length-1) {
|
||||
li.appendTo(this.element);
|
||||
} else {
|
||||
li.insertBefore(this.element.children().eq(index));
|
||||
}
|
||||
}
|
||||
var row = $('<div/>').addClass("red-ui-editableList-item-content").appendTo(li);
|
||||
row.data('data',data);
|
||||
if (this.options.sortable === true) {
|
||||
@@ -303,9 +313,31 @@
|
||||
});
|
||||
});
|
||||
}
|
||||
var added = false;
|
||||
if (this.activeSort) {
|
||||
var items = this.items();
|
||||
var skip = false;
|
||||
items.each(function(i,el) {
|
||||
if (added) { return }
|
||||
var itemData = el.data('data');
|
||||
if (that.activeSort(data,itemData) < 0) {
|
||||
li.insertBefore(el.closest("li"));
|
||||
added = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (!added) {
|
||||
if (index <= 0) {
|
||||
li.prependTo(this.element);
|
||||
} else if (index > that.element.children().length-1) {
|
||||
li.appendTo(this.element);
|
||||
} else {
|
||||
li.insertBefore(this.element.children().eq(index));
|
||||
}
|
||||
}
|
||||
if (this.options.addItem) {
|
||||
var index = that.element.children().length-1;
|
||||
setTimeout(function() {
|
||||
// setTimeout(function() {
|
||||
that.options.addItem(row,index,data);
|
||||
if (that.activeFilter) {
|
||||
try {
|
||||
@@ -321,7 +353,7 @@
|
||||
that.uiContainer.scrollTop(that.element.height());
|
||||
},0);
|
||||
}
|
||||
},0);
|
||||
// },0);
|
||||
}
|
||||
},
|
||||
addItem: function(data) {
|
||||
@@ -332,17 +364,21 @@
|
||||
this.addItem(items[i]);
|
||||
}
|
||||
},
|
||||
removeItem: function(data) {
|
||||
removeItem: function(data,detach) {
|
||||
var items = this.element.children().filter(function(f) {
|
||||
return data === $(this).find(".red-ui-editableList-item-content").data('data');
|
||||
return data === $(this).children(".red-ui-editableList-item-content").data('data');
|
||||
});
|
||||
if (detach) {
|
||||
items.detach();
|
||||
} else {
|
||||
items.remove();
|
||||
}
|
||||
if (this.options.removeItem) {
|
||||
this.options.removeItem(data);
|
||||
}
|
||||
},
|
||||
items: function() {
|
||||
return this.element.children().map(function(i) { return $(this).find(".red-ui-editableList-item-content"); });
|
||||
return this.element.children().map(function(i) { return $(this).children(".red-ui-editableList-item-content"); });
|
||||
},
|
||||
empty: function() {
|
||||
this.element.empty();
|
||||
@@ -365,14 +401,14 @@
|
||||
},
|
||||
show: function(item) {
|
||||
var items = this.element.children().filter(function(f) {
|
||||
return item === $(this).find(".red-ui-editableList-item-content").data('data');
|
||||
return item === $(this).children(".red-ui-editableList-item-content").data('data');
|
||||
});
|
||||
if (items.length > 0) {
|
||||
this.uiContainer.scrollTop(this.uiContainer.scrollTop()+items.position().top)
|
||||
}
|
||||
},
|
||||
getItem: function(li) {
|
||||
var el = li.find(".red-ui-editableList-item-content");
|
||||
var el = li.children(".red-ui-editableList-item-content");
|
||||
if (el.length) {
|
||||
return el.data('data');
|
||||
} else {
|
||||
|
||||
@@ -158,7 +158,7 @@ RED.menu = (function() {
|
||||
activeMenu = null;
|
||||
topMenu.hide();
|
||||
});
|
||||
$(".red-ui-menu").hide();
|
||||
$(".red-ui-menu.red-ui-menu-dropdown").hide();
|
||||
topMenu.show();
|
||||
}
|
||||
})
|
||||
@@ -224,11 +224,11 @@ RED.menu = (function() {
|
||||
if (!alreadySet && opt.onselect) {
|
||||
triggerAction(opt.id,state);
|
||||
}
|
||||
}
|
||||
if (!opt.local && !alreadySet) {
|
||||
RED.settings.set(opt.setting||("menu-"+opt.id), state);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function toggleSelected(id) {
|
||||
setSelected(id,!isSelected(id));
|
||||
@@ -244,7 +244,7 @@ RED.menu = (function() {
|
||||
|
||||
function addItem(id,opt) {
|
||||
var item = createMenuItem(opt);
|
||||
if (opt.group) {
|
||||
if (opt !== null && opt.group) {
|
||||
var groupItems = $("#"+id+"-submenu").children(".red-ui-menu-group-"+opt.group);
|
||||
if (groupItems.length === 0) {
|
||||
item.appendTo("#"+id+"-submenu");
|
||||
|
||||
@@ -29,6 +29,10 @@ RED.panels = (function() {
|
||||
if (!vertical) {
|
||||
container.addClass("red-ui-panels-horizontal");
|
||||
}
|
||||
|
||||
$(children[0]).addClass("red-ui-panel");
|
||||
$(children[1]).addClass("red-ui-panel");
|
||||
|
||||
var separator = $('<div class="red-ui-panels-separator"></div>').insertAfter(children[0]);
|
||||
var startPosition;
|
||||
var panelSizes = [];
|
||||
@@ -52,11 +56,11 @@ RED.panels = (function() {
|
||||
var newSizes = [panelSizes[0]+delta,panelSizes[1]-delta];
|
||||
if (vertical) {
|
||||
$(children[0]).height(newSizes[0]);
|
||||
$(children[1]).height(newSizes[1]);
|
||||
// $(children[1]).height(newSizes[1]);
|
||||
ui.position.top -= delta;
|
||||
} else {
|
||||
$(children[0]).width(newSizes[0]);
|
||||
$(children[1]).width(newSizes[1]);
|
||||
// $(children[1]).width(newSizes[1]);
|
||||
ui.position.left -= delta;
|
||||
}
|
||||
if (options.resize) {
|
||||
@@ -71,6 +75,9 @@ RED.panels = (function() {
|
||||
|
||||
var panel = {
|
||||
ratio: function(ratio) {
|
||||
if (ratio === undefined) {
|
||||
return panelRatio;
|
||||
}
|
||||
panelRatio = ratio;
|
||||
modifiedSizes = true;
|
||||
if (ratio === 0 || ratio === 1) {
|
||||
@@ -99,10 +106,10 @@ RED.panels = (function() {
|
||||
panelSizes = [topPanelSize,bottomPanelSize];
|
||||
if (vertical) {
|
||||
$(children[0]).outerHeight(panelSizes[0]);
|
||||
$(children[1]).outerHeight(panelSizes[1]);
|
||||
// $(children[1]).outerHeight(panelSizes[1]);
|
||||
} else {
|
||||
$(children[0]).outerWidth(panelSizes[0]);
|
||||
$(children[1]).outerWidth(panelSizes[1]);
|
||||
// $(children[1]).outerWidth(panelSizes[1]);
|
||||
}
|
||||
}
|
||||
if (options.resize) {
|
||||
|
||||
@@ -84,6 +84,7 @@ RED.popover = (function() {
|
||||
var targetHeight = target.outerHeight();
|
||||
var divHeight = div.height();
|
||||
var divWidth = div.width();
|
||||
var paddingRight = 10;
|
||||
|
||||
var viewportTop = $(window).scrollTop();
|
||||
var viewportLeft = $(window).scrollLeft();
|
||||
@@ -105,7 +106,7 @@ RED.popover = (function() {
|
||||
d = "right";
|
||||
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
|
||||
left = targetPos.left+targetWidth+deltaSizes[size].leftRight;
|
||||
} else if (left+divWidth > viewportRight) {
|
||||
} else if (left+divWidth+paddingRight > viewportRight) {
|
||||
d = "left";
|
||||
top = targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top;
|
||||
left = targetPos.left-deltaSizes[size].leftLeft-divWidth;
|
||||
@@ -131,6 +132,28 @@ RED.popover = (function() {
|
||||
existingPopover.close(true);
|
||||
}
|
||||
target.data("red-ui-popover",res)
|
||||
if (options.tooltip) {
|
||||
div.on("mousedown", function(evt) {
|
||||
closePopup(true);
|
||||
});
|
||||
}
|
||||
if (trigger === 'hover' && options.interactive) {
|
||||
div.on('mouseenter', function(e) {
|
||||
clearTimeout(timer);
|
||||
active = true;
|
||||
})
|
||||
div.on('mouseleave', function(e) {
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
if (active) {
|
||||
timer = setTimeout(function() {
|
||||
active = false;
|
||||
closePopup();
|
||||
},delay.hide);
|
||||
}
|
||||
})
|
||||
}
|
||||
if (instant) {
|
||||
div.show();
|
||||
} else {
|
||||
@@ -158,8 +181,10 @@ RED.popover = (function() {
|
||||
if (trigger === 'hover') {
|
||||
target.on('mouseenter',function(e) {
|
||||
clearTimeout(timer);
|
||||
if (!active) {
|
||||
active = true;
|
||||
timer = setTimeout(openPopup,delay.show);
|
||||
}
|
||||
});
|
||||
target.on('mouseleave disabled', function(e) {
|
||||
if (timer) {
|
||||
@@ -254,6 +279,85 @@ RED.popover = (function() {
|
||||
delay: { show: 750, hide: 50 }
|
||||
});
|
||||
},
|
||||
menu: function(options) {
|
||||
var list = $('<ul class="red-ui-menu"></ul>');
|
||||
if (options.style === 'compact') {
|
||||
list.addClass("red-ui-menu-compact");
|
||||
}
|
||||
var menuOptions = options.options || [];
|
||||
var first;
|
||||
menuOptions.forEach(function(opt) {
|
||||
var item = $('<li>').appendTo(list);
|
||||
var link = $('<a href="#"></a>').text(opt.label).appendTo(item);
|
||||
link.on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
if (opt.onselect) {
|
||||
opt.onselect();
|
||||
}
|
||||
menu.hide();
|
||||
})
|
||||
if (!first) { first = link}
|
||||
})
|
||||
var container = RED.popover.panel(list);
|
||||
var menu = {
|
||||
show: function(opts) {
|
||||
$(document).on("keydown.red-ui-menu", function(evt) {
|
||||
var currentItem = list.find(":focus").parent();
|
||||
if (evt.keyCode === 40) {
|
||||
evt.preventDefault();
|
||||
// DOWN
|
||||
if (currentItem.length > 0) {
|
||||
if (currentItem.index() === menuOptions.length-1) {
|
||||
console.log("WARP TO TOP")
|
||||
// Wrap to top of list
|
||||
list.children().first().children().first().focus();
|
||||
} else {
|
||||
console.log("GO DOWN ONE")
|
||||
currentItem.next().children().first().focus();
|
||||
}
|
||||
} else {
|
||||
list.children().first().children().first().focus();
|
||||
}
|
||||
} else if (evt.keyCode === 38) {
|
||||
evt.preventDefault();
|
||||
// UP
|
||||
if (currentItem.length > 0) {
|
||||
if (currentItem.index() === 0) {
|
||||
console.log("WARP TO BOTTOM")
|
||||
// Wrap to bottom of list
|
||||
list.children().last().children().first().focus();
|
||||
} else {
|
||||
console.log("GO UP ONE")
|
||||
currentItem.prev().children().first().focus();
|
||||
}
|
||||
} else {
|
||||
list.children().last().children().first().focus();
|
||||
}
|
||||
} else if (evt.keyCode === 27) {
|
||||
// ESCAPE
|
||||
evt.preventDefault();
|
||||
menu.hide(true);
|
||||
}
|
||||
evt.stopPropagation();
|
||||
})
|
||||
opts.onclose = function() {
|
||||
$(document).off("keydown.red-ui-menu");
|
||||
if (options.onclose) {
|
||||
options.onclose(true);
|
||||
}
|
||||
}
|
||||
container.show(opts);
|
||||
},
|
||||
hide: function(cancelled) {
|
||||
$(document).off("keydown.red-ui-menu");
|
||||
container.hide(options.disposeOnClose);
|
||||
if (options.onclose) {
|
||||
options.onclose(cancelled);
|
||||
}
|
||||
}
|
||||
}
|
||||
return menu;
|
||||
},
|
||||
panel: function(content) {
|
||||
var panel = $('<div class="red-ui-editor-dialog red-ui-popover-panel"></div>');
|
||||
panel.css({ display: "none" });
|
||||
@@ -261,18 +365,22 @@ RED.popover = (function() {
|
||||
content.appendTo(panel);
|
||||
var closeCallback;
|
||||
|
||||
function hide() {
|
||||
function hide(dispose) {
|
||||
$(document).off("mousedown.red-ui-popover-panel-close");
|
||||
$(document).off("keydown.red-ui-popover-panel-close");
|
||||
panel.hide();
|
||||
panel.css({
|
||||
height: "auto"
|
||||
});
|
||||
if (dispose !== false) {
|
||||
panel.remove();
|
||||
}
|
||||
}
|
||||
function show(options) {
|
||||
var closeCallback = options.onclose;
|
||||
var target = options.target;
|
||||
var align = options.align || "left";
|
||||
var align = options.align || "right";
|
||||
var offset = options.offset || [0,0];
|
||||
|
||||
var pos = target.offset();
|
||||
var targetWidth = target.width();
|
||||
@@ -280,7 +388,7 @@ RED.popover = (function() {
|
||||
var panelHeight = panel.height();
|
||||
var panelWidth = panel.width();
|
||||
|
||||
var top = (targetHeight+pos.top);
|
||||
var top = (targetHeight+pos.top) + offset[1];
|
||||
if (top+panelHeight > $(window).height()) {
|
||||
top -= (top+panelHeight)-$(window).height() + 5;
|
||||
}
|
||||
@@ -288,25 +396,35 @@ RED.popover = (function() {
|
||||
panelHeight.height(panelHeight+top)
|
||||
top = 0;
|
||||
}
|
||||
if (align === "left") {
|
||||
if (align === "right") {
|
||||
panel.css({
|
||||
top: top+"px",
|
||||
left: (pos.left)+"px",
|
||||
left: (pos.left+offset[0])+"px",
|
||||
});
|
||||
} else if(align === "right") {
|
||||
} else if (align === "left") {
|
||||
panel.css({
|
||||
top: top+"px",
|
||||
left: (pos.left-panelWidth)+"px",
|
||||
left: (pos.left-panelWidth+offset[0])+"px",
|
||||
});
|
||||
}
|
||||
panel.slideDown(100);
|
||||
|
||||
$(document).on("keydown.red-ui-popover-panel-close", function(event) {
|
||||
if (event.keyCode === 27) {
|
||||
// ESCAPE
|
||||
if (closeCallback) {
|
||||
closeCallback();
|
||||
}
|
||||
hide(options.dispose);
|
||||
}
|
||||
});
|
||||
|
||||
$(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();
|
||||
hide(options.dispose);
|
||||
}
|
||||
// if ($(event.target).closest(target).length) {
|
||||
// event.preventDefault();
|
||||
|
||||
@@ -39,8 +39,16 @@
|
||||
this.uiContainer = this.element.wrap("<div>").parent();
|
||||
this.uiContainer.addClass("red-ui-searchBox-container");
|
||||
|
||||
if (this.options.style === "compact") {
|
||||
this.uiContainer.addClass("red-ui-searchBox-compact");
|
||||
}
|
||||
|
||||
if (this.element.parents("form").length === 0) {
|
||||
var form = this.element.wrap("<form>").parent();
|
||||
form.addClass("red-ui-searchBox-form");
|
||||
}
|
||||
$('<i class="fa fa-search"></i>').prependTo(this.uiContainer);
|
||||
this.clearButton = $('<a href="#"><i class="fa fa-times"></i></a>').appendTo(this.uiContainer);
|
||||
this.clearButton = $('<a class="red-ui-searchBox-clear" href="#"><i class="fa fa-times"></i></a>').appendTo(this.uiContainer);
|
||||
this.clearButton.on("click",function(e) {
|
||||
e.preventDefault();
|
||||
that.element.val("");
|
||||
@@ -48,6 +56,62 @@
|
||||
that.element.trigger("focus");
|
||||
});
|
||||
|
||||
if (this.options.options) {
|
||||
this.uiContainer.addClass("red-ui-searchBox-has-options");
|
||||
this.optsButton = $('<a class="red-ui-searchBox-opts" href="#"><i class="fa fa-caret-down"></i></a>').appendTo(this.uiContainer);
|
||||
var menuShown = false;
|
||||
this.optsMenu = RED.popover.menu({
|
||||
style: this.options.style,
|
||||
options: this.options.options.map(function(opt) {
|
||||
return {
|
||||
label: opt.label,
|
||||
onselect: function() {
|
||||
that.element.val(opt.value+" ");
|
||||
that._change(opt.value,true);
|
||||
}
|
||||
}
|
||||
}),
|
||||
onclose: function(cancelled) {
|
||||
menuShown = false;
|
||||
that.element.trigger("focus");
|
||||
},
|
||||
disposeOnClose: false
|
||||
});
|
||||
|
||||
var showMenu = function() {
|
||||
menuShown = true;
|
||||
that.optsMenu.show({
|
||||
target: that.optsButton,
|
||||
align: "left",
|
||||
offset: [that.optsButton.width()-2,-1],
|
||||
dispose: false
|
||||
})
|
||||
}
|
||||
this.optsButton.on("click",function(e) {
|
||||
e.preventDefault();
|
||||
if (!menuShown) {
|
||||
showMenu();
|
||||
} else {
|
||||
// TODO: This doesn't quite work because the panel's own
|
||||
// mousedown handler triggers a close before this click
|
||||
// handler fires.
|
||||
that.optsMenu.hide(true);
|
||||
}
|
||||
});
|
||||
this.optsButton.on("keydown",function(e) {
|
||||
if (!menuShown && e.keyCode === 40) {
|
||||
//DOWN
|
||||
showMenu();
|
||||
}
|
||||
});
|
||||
this.element.on("keydown",function(e) {
|
||||
if (!menuShown && e.keyCode === 40) {
|
||||
//DOWN
|
||||
showMenu();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
this.resultCount = $('<span>',{class:"red-ui-searchBox-resultCount hide"}).appendTo(this.uiContainer);
|
||||
|
||||
this.element.val("");
|
||||
@@ -55,6 +119,9 @@
|
||||
if (evt.keyCode === 27) {
|
||||
that.element.val("");
|
||||
}
|
||||
if (evt.keyCode === 13) {
|
||||
evt.preventDefault();
|
||||
}
|
||||
})
|
||||
this.element.on("keyup",function(evt) {
|
||||
that._change($(this).val());
|
||||
|
||||
@@ -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 = {};
|
||||
@@ -26,7 +29,8 @@ RED.tabs = (function() {
|
||||
var currentTabWidth;
|
||||
var currentActiveTabWidth = 0;
|
||||
var collapsibleMenu;
|
||||
|
||||
var mousedownTab;
|
||||
var preferredOrder = options.order;
|
||||
var ul = options.element || $("#"+options.id);
|
||||
var wrapper = ul.wrap( "<div>" ).parent();
|
||||
var scrollContainer = ul.wrap( "<div>" ).parent();
|
||||
@@ -129,11 +133,11 @@ RED.tabs = (function() {
|
||||
activateTab(id);
|
||||
}
|
||||
};
|
||||
if (tabs[id].pinned) {
|
||||
pinnedOptions.push(opt);
|
||||
} else {
|
||||
// if (tabs[id].pinned) {
|
||||
// pinnedOptions.push(opt);
|
||||
// } else {
|
||||
options.push(opt);
|
||||
}
|
||||
// }
|
||||
});
|
||||
options = pinnedOptions.concat(options);
|
||||
collapsibleMenu = RED.menu.init({options: options});
|
||||
@@ -150,7 +154,7 @@ RED.tabs = (function() {
|
||||
if (collapsibleMenu.is(":visible")) {
|
||||
$(document).off("click.red-ui-tabmenu");
|
||||
} else {
|
||||
$(".red-ui-menu").hide();
|
||||
$(".red-ui-menu.red-ui-menu-dropdown").hide();
|
||||
$(document).on("click.red-ui-tabmenu", function(evt) {
|
||||
$(document).off("click.red-ui-tabmenu");
|
||||
collapsibleMenu.hide();
|
||||
@@ -201,12 +205,26 @@ RED.tabs = (function() {
|
||||
}
|
||||
|
||||
function onTabClick(evt) {
|
||||
evt.preventDefault();
|
||||
if (dragActive) {
|
||||
return
|
||||
}
|
||||
if (evt.currentTarget !== mousedownTab) {
|
||||
mousedownTab = null;
|
||||
return;
|
||||
}
|
||||
mousedownTab = null;
|
||||
if (dblClickTime && Date.now()-dblClickTime < 400) {
|
||||
dblClickTime = 0;
|
||||
dblClickArmed = true;
|
||||
return onTabDblClick.call(this,evt);
|
||||
}
|
||||
dblClickTime = Date.now();
|
||||
|
||||
var currentTab = ul.find("li.red-ui-tab.active");
|
||||
var thisTab = $(this).parent();
|
||||
var fireSelectionChanged = false;
|
||||
if (options.onselect) {
|
||||
if (evt.metaKey) {
|
||||
if (evt.metaKey || evt.ctrlKey) {
|
||||
if (thisTab.hasClass("selected")) {
|
||||
thisTab.removeClass("selected");
|
||||
if (thisTab[0] !== currentTab[0]) {
|
||||
@@ -267,7 +285,6 @@ RED.tabs = (function() {
|
||||
if (fireSelectionChanged) {
|
||||
selectionChanged();
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function updateScroll() {
|
||||
@@ -289,7 +306,6 @@ RED.tabs = (function() {
|
||||
}
|
||||
function onTabDblClick(evt) {
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
if (evt.metaKey || evt.shiftKey) {
|
||||
return;
|
||||
}
|
||||
@@ -353,23 +369,39 @@ RED.tabs = (function() {
|
||||
var tabWidth;
|
||||
|
||||
if (options.collapsible) {
|
||||
var availableCount = collapsedButtonsRow.children().length;
|
||||
var visibleCount = collapsedButtonsRow.children(":visible").length;
|
||||
tabWidth = width - collapsedButtonsRow.width()-10;
|
||||
if (tabWidth < 198) {
|
||||
var delta = 198 - tabWidth;
|
||||
var maxTabWidth = 198;
|
||||
var minTabWidth = 80;
|
||||
if (tabWidth <= minTabWidth || (tabWidth < maxTabWidth && visibleCount > 5)) {
|
||||
// The tab is too small. Hide the next button to make room
|
||||
// Start at the end of the button row, -1 for the menu button
|
||||
var b = collapsedButtonsRow.find("a:last").prev();
|
||||
var index = collapsedButtonsRow.children().length - 2;
|
||||
// Work backwards to find the first visible button
|
||||
while (b.is(":not(:visible)")) {
|
||||
b = b.prev();
|
||||
index--;
|
||||
}
|
||||
if (!b.hasClass("red-ui-tab-link-button-pinned")) {
|
||||
// If it isn't a pinned button, hide it to get the room
|
||||
if (tabWidth <= minTabWidth || visibleCount>6) {//}!b.hasClass("red-ui-tab-link-button-pinned")) {
|
||||
b.hide();
|
||||
}
|
||||
tabWidth = width - collapsedButtonsRow.width()-10;
|
||||
tabWidth = Math.max(minTabWidth,width - collapsedButtonsRow.width()-10);
|
||||
} else {
|
||||
var space = width - 198 - collapsedButtonsRow.width();
|
||||
if (visibleCount !== availableCount) {
|
||||
if (visibleCount < 6) {
|
||||
tabWidth = minTabWidth;
|
||||
} else {
|
||||
tabWidth = maxTabWidth;
|
||||
}
|
||||
}
|
||||
var space = width - tabWidth - collapsedButtonsRow.width();
|
||||
if (space > 40) {
|
||||
collapsedButtonsRow.find("a:not(:visible):first").show();
|
||||
tabWidth = width - collapsedButtonsRow.width()-10;
|
||||
}
|
||||
tabWidth = width - collapsedButtonsRow.width()-10;
|
||||
}
|
||||
tabs.css({width:tabWidth});
|
||||
|
||||
@@ -418,7 +450,12 @@ RED.tabs = (function() {
|
||||
|
||||
}
|
||||
|
||||
ul.find("li.red-ui-tab a").on("click",onTabClick).on("dblclick",onTabDblClick);
|
||||
ul.find("li.red-ui-tab a")
|
||||
.on("mousedown", function(evt) { mousedownTab = evt.currentTarget })
|
||||
.on("mouseup",onTabClick)
|
||||
.on("click", function(evt) {evt.preventDefault(); })
|
||||
.on("dblclick", function(evt) {evt.stopPropagation(); evt.preventDefault(); })
|
||||
|
||||
setTimeout(function() {
|
||||
updateTabWidths();
|
||||
},0);
|
||||
@@ -455,7 +492,7 @@ RED.tabs = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
var tabAPI = {
|
||||
addTab: function(tab,targetIndex) {
|
||||
if (options.onselect) {
|
||||
var selection = ul.find("li.red-ui-tab.selected");
|
||||
@@ -479,8 +516,8 @@ RED.tabs = (function() {
|
||||
li.attr('id',"red-ui-tab-"+(tab.id.replace(".","-")));
|
||||
li.data("tabId",tab.id);
|
||||
|
||||
if (options.maximumTabWidth) {
|
||||
li.css("maxWidth",options.maximumTabWidth+"px");
|
||||
if (options.maximumTabWidth || tab.maximumTabWidth) {
|
||||
li.css("maxWidth",(options.maximumTabWidth || tab.maximumTabWidth) +"px");
|
||||
}
|
||||
var link = $("<a/>",{href:"#"+tab.id, class:"red-ui-tab-label"}).appendTo(li);
|
||||
if (tab.icon) {
|
||||
@@ -517,15 +554,99 @@ RED.tabs = (function() {
|
||||
evt.preventDefault();
|
||||
activateTab(tab.id);
|
||||
});
|
||||
pinnedLink.data("tabId",tab.id)
|
||||
if (tab.pinned) {
|
||||
pinnedLink.addClass("red-ui-tab-link-button-pinned");
|
||||
pinnedTabsCount++;
|
||||
}
|
||||
RED.popover.tooltip($(pinnedLink), tab.name, tab.action);
|
||||
if (options.onreorder) {
|
||||
var pinnedLinkIndex;
|
||||
var pinnedLinks = [];
|
||||
var startPinnedIndex;
|
||||
pinnedLink.draggable({
|
||||
distance: 10,
|
||||
axis:"x",
|
||||
containment: ".red-ui-tab-link-buttons",
|
||||
start: function(event,ui) {
|
||||
dragActive = true;
|
||||
$(".red-ui-tab-link-buttons").width($(".red-ui-tab-link-buttons").width());
|
||||
if (dblClickArmed) { dblClickArmed = false; return false }
|
||||
collapsedButtonsRow.children().each(function(i) {
|
||||
pinnedLinks[i] = {
|
||||
el:$(this),
|
||||
text: $(this).text(),
|
||||
left: $(this).position().left,
|
||||
width: $(this).width(),
|
||||
menu: $(this).hasClass("red-ui-tab-link-button-menu")
|
||||
};
|
||||
if ($(this).is(pinnedLink)) {
|
||||
pinnedLinkIndex = i;
|
||||
startPinnedIndex = i;
|
||||
}
|
||||
});
|
||||
collapsedButtonsRow.children().each(function(i) {
|
||||
if (i!==pinnedLinkIndex) {
|
||||
$(this).css({
|
||||
position: 'absolute',
|
||||
left: pinnedLinks[i].left+"px",
|
||||
width: pinnedLinks[i].width+2,
|
||||
transition: "left 0.3s"
|
||||
});
|
||||
}
|
||||
})
|
||||
if (!pinnedLink.hasClass('active')) {
|
||||
pinnedLink.css({'zIndex':1});
|
||||
}
|
||||
},
|
||||
drag: function(event,ui) {
|
||||
ui.position.left += pinnedLinks[pinnedLinkIndex].left;
|
||||
var tabCenter = ui.position.left + pinnedLinks[pinnedLinkIndex].width/2;
|
||||
for (var i=0;i<pinnedLinks.length;i++) {
|
||||
if (i === pinnedLinkIndex || pinnedLinks[i].menu || pinnedLinks[i].el.is(":not(:visible)")) {
|
||||
continue;
|
||||
}
|
||||
if (tabCenter > pinnedLinks[i].left && tabCenter < pinnedLinks[i].left+pinnedLinks[i].width) {
|
||||
if (i < pinnedLinkIndex) {
|
||||
pinnedLinks[i].left += pinnedLinks[pinnedLinkIndex].width+8;
|
||||
pinnedLinks[pinnedLinkIndex].el.detach().insertBefore(pinnedLinks[i].el);
|
||||
} else {
|
||||
pinnedLinks[i].left -= pinnedLinks[pinnedLinkIndex].width+8;
|
||||
pinnedLinks[pinnedLinkIndex].el.detach().insertAfter(pinnedLinks[i].el);
|
||||
}
|
||||
pinnedLinks[i].el.css({left:pinnedLinks[i].left+"px"});
|
||||
|
||||
pinnedLinks.splice(i, 0, pinnedLinks.splice(pinnedLinkIndex, 1)[0]);
|
||||
|
||||
pinnedLinkIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
stop: function(event,ui) {
|
||||
dragActive = false;
|
||||
collapsedButtonsRow.children().css({position:"relative",left:"",transition:""});
|
||||
$(".red-ui-tab-link-buttons").width('auto');
|
||||
pinnedLink.css({zIndex:""});
|
||||
updateTabWidths();
|
||||
if (startPinnedIndex !== pinnedLinkIndex) {
|
||||
if (collapsibleMenu) {
|
||||
collapsibleMenu.remove();
|
||||
collapsibleMenu = null;
|
||||
}
|
||||
var newOrder = $.makeArray(collapsedButtonsRow.children().map(function() { return $(this).data('tabId');}));
|
||||
tabAPI.order(newOrder);
|
||||
options.onreorder(newOrder);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
}
|
||||
link.on("click",onTabClick);
|
||||
link.on("dblclick",onTabDblClick);
|
||||
link.on("mousedown", function(evt) { mousedownTab = evt.currentTarget })
|
||||
link.on("mouseup",onTabClick);
|
||||
link.on("click", function(evt) { evt.preventDefault(); })
|
||||
link.on("dblclick", function(evt) { evt.stopPropagation(); evt.preventDefault(); })
|
||||
|
||||
|
||||
if (tab.closeable) {
|
||||
@@ -550,7 +671,7 @@ RED.tabs = (function() {
|
||||
if (ul.find("li.red-ui-tab").length == 1) {
|
||||
activateTab(link);
|
||||
}
|
||||
if (options.onreorder) {
|
||||
if (options.onreorder && !options.collapsible) {
|
||||
var originalTabOrder;
|
||||
var tabDragIndex;
|
||||
var tabElements = [];
|
||||
@@ -560,6 +681,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 +738,7 @@ RED.tabs = (function() {
|
||||
}
|
||||
},
|
||||
stop: function(event,ui) {
|
||||
dragActive = false;
|
||||
ul.children().css({position:"relative",left:"",transition:""});
|
||||
if (!li.hasClass('active')) {
|
||||
li.css({zIndex:""});
|
||||
@@ -634,6 +758,9 @@ RED.tabs = (function() {
|
||||
collapsibleMenu.remove();
|
||||
collapsibleMenu = null;
|
||||
}
|
||||
if (preferredOrder) {
|
||||
tabAPI.order(preferredOrder);
|
||||
}
|
||||
},
|
||||
removeTab: removeTab,
|
||||
activateTab: activateTab,
|
||||
@@ -655,10 +782,8 @@ RED.tabs = (function() {
|
||||
},
|
||||
selection: getSelection,
|
||||
order: function(order) {
|
||||
preferredOrder = order;
|
||||
var existingTabOrder = $.makeArray(ul.children().map(function() { return $(this).data('tabId');}));
|
||||
if (existingTabOrder.length !== order.length) {
|
||||
return
|
||||
}
|
||||
var i;
|
||||
var match = true;
|
||||
for (i=0;i<order.length;i++) {
|
||||
@@ -674,13 +799,42 @@ RED.tabs = (function() {
|
||||
var existingTabs = ul.children().detach().each(function() {
|
||||
existingTabMap[$(this).data("tabId")] = $(this);
|
||||
});
|
||||
var pinnedButtons = {};
|
||||
if (options.collapsible) {
|
||||
collapsedButtonsRow.children().detach().each(function() {
|
||||
var id = $(this).data("tabId");
|
||||
if (!id) {
|
||||
id = "__menu__"
|
||||
}
|
||||
pinnedButtons[id] = $(this);
|
||||
});
|
||||
}
|
||||
for (i=0;i<order.length;i++) {
|
||||
if (existingTabMap[order[i]]) {
|
||||
existingTabMap[order[i]].appendTo(ul);
|
||||
if (options.collapsible) {
|
||||
pinnedButtons[order[i]].appendTo(collapsedButtonsRow);
|
||||
}
|
||||
delete existingTabMap[order[i]];
|
||||
}
|
||||
}
|
||||
|
||||
// Add any tabs that aren't known in the order
|
||||
for (i in existingTabMap) {
|
||||
if (existingTabMap.hasOwnProperty(i)) {
|
||||
existingTabMap[i].appendTo(ul);
|
||||
if (options.collapsible) {
|
||||
pinnedButtons[i].appendTo(collapsedButtonsRow);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (options.collapsible) {
|
||||
pinnedButtons["__menu__"].appendTo(collapsedButtonsRow);
|
||||
updateTabWidths();
|
||||
}
|
||||
}
|
||||
}
|
||||
return tabAPI;
|
||||
}
|
||||
|
||||
return {
|
||||
create: createTabs
|
||||
|
||||
@@ -37,8 +37,8 @@
|
||||
invertState = this.options.invertState;
|
||||
}
|
||||
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 enabledIcon = this.options.hasOwnProperty('enabledIcon')?this.options.enabledIcon : "fa-check-square-o";
|
||||
var disabledIcon = this.options.hasOwnProperty('disabledIcon')?this.options.disabledIcon : "fa-square-o";
|
||||
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");
|
||||
|
||||
@@ -46,25 +46,41 @@
|
||||
this.element.on("focus", function() {
|
||||
that.button.focus();
|
||||
});
|
||||
this.button = $('<button type="button" class="red-ui-toggleButton '+baseClass+' toggle single"><i class="fa"></i> <span></span></button>');
|
||||
this.button = $('<button type="button" class="red-ui-toggleButton '+baseClass+' toggle single"></button>');
|
||||
if (enabledLabel || disabledLabel) {
|
||||
this.buttonLabel = $("<span>").appendTo(this.button);
|
||||
}
|
||||
|
||||
if (this.options.class) {
|
||||
this.button.addClass(this.options.class)
|
||||
}
|
||||
this.element.after(this.button);
|
||||
this.buttonIcon = this.button.find("i");
|
||||
this.buttonLabel = this.button.find("span");
|
||||
|
||||
if (enabledIcon && disabledIcon) {
|
||||
this.buttonIcon = $('<i class="fa"></i>').prependTo(this.button);
|
||||
}
|
||||
|
||||
// Quick hack to find the maximum width of the button
|
||||
this.button.addClass("selected");
|
||||
if (this.buttonIcon) {
|
||||
this.buttonIcon.addClass(enabledIcon);
|
||||
}
|
||||
if (this.buttonLabel) {
|
||||
this.buttonLabel.text(enabledLabel);
|
||||
}
|
||||
var width = this.button.width();
|
||||
this.button.removeClass("selected");
|
||||
if (this.buttonIcon) {
|
||||
this.buttonIcon.removeClass(enabledIcon);
|
||||
that.buttonIcon.addClass(disabledIcon);
|
||||
}
|
||||
if (this.buttonLabel) {
|
||||
that.buttonLabel.text(disabledLabel);
|
||||
}
|
||||
width = Math.max(width,this.button.width());
|
||||
if (this.buttonIcon) {
|
||||
this.buttonIcon.removeClass(disabledIcon);
|
||||
}
|
||||
|
||||
// Fix the width of the button so it doesn't jump around when toggled
|
||||
if (width > 0) {
|
||||
@@ -73,7 +89,7 @@
|
||||
|
||||
this.button.on("click",function(e) {
|
||||
e.stopPropagation();
|
||||
if (that.buttonIcon.hasClass(disabledIcon)) {
|
||||
if (!that.state) {
|
||||
that.element.prop("checked",!invertState);
|
||||
} else {
|
||||
that.element.prop("checked",invertState);
|
||||
@@ -84,15 +100,25 @@
|
||||
this.element.on("change", function(e) {
|
||||
if ($(this).prop("checked") !== invertState) {
|
||||
that.button.addClass("selected");
|
||||
that.state = true;
|
||||
if (that.buttonIcon) {
|
||||
that.buttonIcon.addClass(enabledIcon);
|
||||
that.buttonIcon.removeClass(disabledIcon);
|
||||
}
|
||||
if (that.buttonLabel) {
|
||||
that.buttonLabel.text(enabledLabel);
|
||||
}
|
||||
} else {
|
||||
that.button.removeClass("selected");
|
||||
that.state = false;
|
||||
if (that.buttonIcon) {
|
||||
that.buttonIcon.addClass(disabledIcon);
|
||||
that.buttonIcon.removeClass(enabledIcon);
|
||||
}
|
||||
if (that.buttonLabel) {
|
||||
that.buttonLabel.text(disabledLabel);
|
||||
}
|
||||
}
|
||||
})
|
||||
this.element.trigger("change");
|
||||
}
|
||||
|
||||
@@ -27,7 +27,8 @@
|
||||
*
|
||||
* methods:
|
||||
* - data(items) - clears existing items and replaces with new data
|
||||
*
|
||||
* - clearSelection - clears the selected items
|
||||
* - filter(filterFunc) - filters the tree using the provided function
|
||||
* events:
|
||||
* - treelistselect : function(event, item) {}
|
||||
* - treelistconfirm : function(event,item) {}
|
||||
@@ -39,7 +40,8 @@
|
||||
* label: 'Local', // label for the item
|
||||
* sublabel: 'Local', // a sub-label for the item
|
||||
* icon: 'fa fa-rocket', // (optional) icon for the item
|
||||
* selected: true/false, // (optional) if present, display checkbox accordingly
|
||||
* checkbox: true/false, // (optional) if present, display checkbox accordingly
|
||||
* selected: true/false, // (optional) whether the item is selected or not
|
||||
* children: [] | function(done,item) // (optional) an array of child items, or a function
|
||||
* // that will call the `done` callback with an array
|
||||
* // of child items
|
||||
@@ -59,11 +61,11 @@
|
||||
* properties and functions:
|
||||
*
|
||||
* item.parent - set to the parent item
|
||||
* item.depth - the depth in the tree (0 == root)
|
||||
* item.treeList.container
|
||||
* item.treeList.label - the label element for the item
|
||||
* item.treeList.depth - the depth in the tree (0 == root)
|
||||
* item.treeList.parentList - the editableList instance this item is in
|
||||
* item.treeList.remove() - removes the item from the tree
|
||||
* item.treeList.remove(detach) - removes the item from the tree. Optionally detach to preserve any event handlers on the item's label
|
||||
* item.treeList.makeLeaf(detachChildElements) - turns an element with children into a leaf node,
|
||||
* removing the UI decoration etc.
|
||||
* detachChildElements - any children with custom
|
||||
@@ -78,8 +80,8 @@
|
||||
* Optionally selects the item after adding.
|
||||
* item.treeList.expand(done) - expands the parent item to show children. Optional 'done' callback.
|
||||
* item.treeList.collapse() - collapse the parent item to hide children.
|
||||
*
|
||||
*
|
||||
* item.treeList.sortChildren(sortFunction) - does a one-time sort of the children using sortFunction
|
||||
* item.treeList.replaceElement(element) - replace the custom element for the item
|
||||
*
|
||||
*
|
||||
*/
|
||||
@@ -100,6 +102,8 @@
|
||||
var target;
|
||||
switch(evt.keyCode) {
|
||||
case 13: // ENTER
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
if (selected.children) {
|
||||
if (selected.treeList.container.hasClass("expanded")) {
|
||||
selected.treeList.collapse()
|
||||
@@ -112,6 +116,8 @@
|
||||
|
||||
break;
|
||||
case 37: // LEFT
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
if (selected.children&& selected.treeList.container.hasClass("expanded")) {
|
||||
selected.treeList.collapse()
|
||||
} else if (selected.parent) {
|
||||
@@ -119,6 +125,8 @@
|
||||
}
|
||||
break;
|
||||
case 38: // UP
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
target = that._getPreviousSibling(selected);
|
||||
if (target) {
|
||||
target = that._getLastDescendant(target);
|
||||
@@ -128,6 +136,8 @@
|
||||
}
|
||||
break;
|
||||
case 39: // RIGHT
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
if (selected.children) {
|
||||
if (!selected.treeList.container.hasClass("expanded")) {
|
||||
selected.treeList.expand()
|
||||
@@ -135,6 +145,8 @@
|
||||
}
|
||||
break
|
||||
case 40: //DOWN
|
||||
evt.preventDefault();
|
||||
evt.stopPropagation();
|
||||
if (selected.children && Array.isArray(selected.children) && selected.children.length > 0 && selected.treeList.container.hasClass("expanded")) {
|
||||
target = selected.children[0];
|
||||
} else {
|
||||
@@ -151,7 +163,8 @@
|
||||
}
|
||||
});
|
||||
this._data = [];
|
||||
|
||||
this._items = {};
|
||||
this._selected = new Set();
|
||||
this._topList = $('<ol class="red-ui-treeList-list">').css({
|
||||
position:'absolute',
|
||||
top:0,
|
||||
@@ -168,6 +181,9 @@
|
||||
that._addSubtree(that._topList,container,item,0);
|
||||
}
|
||||
};
|
||||
if (this.options.header) {
|
||||
topListOptions.header = this.options.header;
|
||||
}
|
||||
if (this.options.rootSortable !== false && !!this.options.sortable) {
|
||||
topListOptions.sortable = this.options.sortable;
|
||||
topListOptions.connectWith = '.red-ui-treeList-sortable';
|
||||
@@ -215,7 +231,7 @@
|
||||
return candidates[index+1];
|
||||
}
|
||||
},
|
||||
_addChildren: function(container,parent,children,depth) {
|
||||
_addChildren: function(container,parent,children,depth,onCompleteChildren) {
|
||||
var that = this;
|
||||
var subtree = $('<ol class="red-ui-treeList-list">').appendTo(container).editableList({
|
||||
connectWith: ".red-ui-treeList-sortable",
|
||||
@@ -244,15 +260,38 @@
|
||||
that._trigger("changeparent",null,evt);
|
||||
});
|
||||
that._trigger("sort",null,parent);
|
||||
}
|
||||
},
|
||||
filter: parent.treeList.childFilter
|
||||
});
|
||||
if (!!that.options.sortable) {
|
||||
subtree.addClass('red-ui-treeList-sortable');
|
||||
}
|
||||
for (var i=0;i<children.length;i++) {
|
||||
children[i].parent = parent;
|
||||
subtree.editableList('addItem',children[i])
|
||||
var sliceSize = 30;
|
||||
var index = 0;
|
||||
var addSlice = function() {
|
||||
var start = index;
|
||||
for (var i=0;i<sliceSize;i++) {
|
||||
index = start+i;
|
||||
if (index === children.length) {
|
||||
setTimeout(function() {
|
||||
if (onCompleteChildren) {
|
||||
onCompleteChildren();
|
||||
}
|
||||
},10);
|
||||
return;
|
||||
}
|
||||
children[index].parent = parent;
|
||||
subtree.editableList('addItem',children[index])
|
||||
}
|
||||
index++;
|
||||
if (index < children.length) {
|
||||
setTimeout(function() {
|
||||
addSlice();
|
||||
},10);
|
||||
}
|
||||
}
|
||||
addSlice();
|
||||
subtree.hide()
|
||||
return subtree;
|
||||
},
|
||||
_fixDepths: function(parent,child) {
|
||||
@@ -289,23 +328,184 @@
|
||||
}
|
||||
return reparentedEvent;
|
||||
},
|
||||
_addSubtree: function(parentList, container, item, depth) {
|
||||
_initItem: function(item,depth) {
|
||||
if (item.treeList) {
|
||||
return;
|
||||
}
|
||||
var that = this;
|
||||
this._items[item.id] = item;
|
||||
item.treeList = {};
|
||||
item.treeList.depth = depth;
|
||||
item.treeList.container = container;
|
||||
|
||||
item.treeList.parentList = parentList;
|
||||
item.treeList.remove = function() {
|
||||
parentList.editableList('removeItem',item);
|
||||
item.depth = depth;
|
||||
item.treeList.remove = function(detach) {
|
||||
if (item.treeList.parentList) {
|
||||
item.treeList.parentList.editableList('removeItem',item,detach);
|
||||
}
|
||||
if (item.parent) {
|
||||
var index = item.parent.children.indexOf(item);
|
||||
item.parent.children.splice(index,1)
|
||||
that._trigger("sort",null,item.parent);
|
||||
}
|
||||
that._selected.delete(item);
|
||||
delete item.treeList;
|
||||
delete that._items[item.id];
|
||||
}
|
||||
item.treeList.insertChildAt = function(newItem,position,select) {
|
||||
newItem.parent = item;
|
||||
item.children.splice(position,0,newItem);
|
||||
var processChildren = function(parent,i) {
|
||||
that._initItem(i,parent.depth+1)
|
||||
i.parent = parent;
|
||||
if (i.children && typeof i.children !== 'function') {
|
||||
i.children.forEach(function(item) {
|
||||
processChildren(i, item, parent.depth+2)
|
||||
});
|
||||
}
|
||||
}
|
||||
processChildren(item,newItem);
|
||||
|
||||
if (!item.deferBuild && item.treeList.childList) {
|
||||
item.treeList.childList.editableList('insertItemAt',newItem,position)
|
||||
if (select) {
|
||||
setTimeout(function() {
|
||||
that.select(newItem)
|
||||
},100);
|
||||
}
|
||||
that._trigger("sort",null,item);
|
||||
|
||||
if (that.activeFilter) {
|
||||
that.filter(that.activeFilter);
|
||||
}
|
||||
}
|
||||
}
|
||||
item.treeList.addChild = function(newItem,select) {
|
||||
item.treeList.insertChildAt(newItem,item.children.length,select);
|
||||
}
|
||||
item.treeList.expand = function(done) {
|
||||
if (!item.children) {
|
||||
if (done) { done(false) }
|
||||
return;
|
||||
}
|
||||
if (!item.treeList.container) {
|
||||
item.expanded = true;
|
||||
if (done) { done(false) }
|
||||
return;
|
||||
}
|
||||
var container = item.treeList.container;
|
||||
if (container.hasClass("expanded")) {
|
||||
if (done) { done(false) }
|
||||
return;
|
||||
}
|
||||
|
||||
var label = $("<div>",{class:"red-ui-treeList-label"}).appendTo(container);
|
||||
if (!container.hasClass("built") && (item.deferBuild || typeof item.children === 'function')) {
|
||||
container.addClass('built');
|
||||
var childrenAdded = false;
|
||||
var spinner;
|
||||
var startTime = 0;
|
||||
var started = Date.now();
|
||||
var completeBuild = function(children) {
|
||||
childrenAdded = true;
|
||||
item.treeList.childList = that._addChildren(container,item,children,depth, function() {
|
||||
if (done) { done(true) }
|
||||
that._trigger("childrenloaded",null,item)
|
||||
});
|
||||
var delta = Date.now() - startTime;
|
||||
if (delta < 400) {
|
||||
setTimeout(function() {
|
||||
item.treeList.childList.slideDown('fast');
|
||||
if (spinner) {
|
||||
spinner.remove();
|
||||
}
|
||||
},400-delta);
|
||||
} else {
|
||||
item.treeList.childList.slideDown('fast');
|
||||
if (spinner) {
|
||||
spinner.remove();
|
||||
}
|
||||
}
|
||||
item.expanded = true;
|
||||
}
|
||||
if (typeof item.children === 'function') {
|
||||
item.children(completeBuild,item);
|
||||
} else {
|
||||
delete item.deferBuild;
|
||||
completeBuild(item.children);
|
||||
}
|
||||
if (!childrenAdded) {
|
||||
startTime = Date.now();
|
||||
spinner = $('<div class="red-ui-treeList-spinner">').css({
|
||||
"background-position": (35+depth*20)+'px 50%'
|
||||
}).appendTo(container);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (that._loadingData || item.children.length > 20) {
|
||||
item.treeList.childList.show();
|
||||
} else {
|
||||
item.treeList.childList.slideDown('fast');
|
||||
}
|
||||
item.expanded = true;
|
||||
if (done) { done(!that._loadingData) }
|
||||
}
|
||||
container.addClass("expanded");
|
||||
}
|
||||
item.treeList.collapse = function() {
|
||||
if (!item.children) {
|
||||
return;
|
||||
}
|
||||
item.expanded = false;
|
||||
if (item.treeList.container) {
|
||||
if (item.children.length < 20) {
|
||||
item.treeList.childList.slideUp('fast');
|
||||
} else {
|
||||
item.treeList.childList.hide();
|
||||
}
|
||||
item.treeList.container.removeClass("expanded");
|
||||
}
|
||||
}
|
||||
item.treeList.sortChildren = function(sortFunc) {
|
||||
if (!item.children) {
|
||||
return;
|
||||
}
|
||||
item.children.sort(sortFunc);
|
||||
if (item.treeList.childList) {
|
||||
// Do a one-off sort of the list, which means calling sort twice:
|
||||
// 1. first with the desired sort function
|
||||
item.treeList.childList.editableList('sort',sortFunc);
|
||||
// 2. and then with null to remove it
|
||||
item.treeList.childList.editableList('sort',null);
|
||||
}
|
||||
}
|
||||
item.treeList.replaceElement = function (element) {
|
||||
if (item.element) {
|
||||
if (item.treeList.container) {
|
||||
$(item.element).remove();
|
||||
$(element).appendTo(item.treeList.label);
|
||||
var labelPaddingWidth = (item.gutter?item.gutter.width()+2:0)+(item.depth*20);
|
||||
$(element).css({
|
||||
width: "calc(100% - "+(labelPaddingWidth+20+(item.icon?20:0))+"px)"
|
||||
})
|
||||
}
|
||||
item.element = element;
|
||||
}
|
||||
}
|
||||
|
||||
if (item.children && typeof item.children !== "function") {
|
||||
item.children.forEach(function(i) {
|
||||
that._initItem(i,depth+1);
|
||||
})
|
||||
}
|
||||
},
|
||||
_addSubtree: function(parentList, container, item, depth) {
|
||||
var that = this;
|
||||
this._initItem(item,depth);
|
||||
// item.treeList = {};
|
||||
// item.treeList.depth = depth;
|
||||
item.treeList.container = container;
|
||||
|
||||
item.treeList.parentList = parentList;
|
||||
|
||||
var label = $("<div>",{class:"red-ui-treeList-label"});
|
||||
label.appendTo(container);
|
||||
item.treeList.label = label;
|
||||
if (item.class) {
|
||||
label.addClass(item.class);
|
||||
@@ -357,6 +557,7 @@
|
||||
treeListIcon.off("click.red-ui-treeList-expand");
|
||||
delete item.children;
|
||||
container.removeClass("expanded");
|
||||
delete item.expanded;
|
||||
}
|
||||
item.treeList.makeParent = function(children) {
|
||||
if (treeListIcon.children().length) {
|
||||
@@ -385,104 +586,28 @@
|
||||
})
|
||||
if (!item.children) {
|
||||
item.children = children||[];
|
||||
item.treeList.childList = that._addChildren(container,item,item.children,depth).hide();
|
||||
item.treeList.childList = that._addChildren(container,item,item.children,depth);
|
||||
}
|
||||
}
|
||||
item.treeList.insertChildAt = function(newItem,position,select) {
|
||||
newItem.parent = item;
|
||||
item.children.splice(position,0,newItem);
|
||||
|
||||
if (!item.deferBuild) {
|
||||
item.treeList.childList.editableList('insertItemAt',newItem,position)
|
||||
if (select) {
|
||||
setTimeout(function() {
|
||||
that.select(newItem)
|
||||
},100);
|
||||
}
|
||||
that._trigger("sort",null,item);
|
||||
}
|
||||
}
|
||||
item.treeList.addChild = function(newItem,select) {
|
||||
item.treeList.insertChildAt(newItem,item.children.length,select);
|
||||
}
|
||||
item.treeList.expand = function(done) {
|
||||
if (!item.children) {
|
||||
return;
|
||||
}
|
||||
if (container.hasClass("expanded")) {
|
||||
done && done();
|
||||
return;
|
||||
}
|
||||
if (!container.hasClass("built") && (item.deferBuild || typeof item.children === 'function')) {
|
||||
container.addClass('built');
|
||||
var childrenAdded = false;
|
||||
var spinner;
|
||||
var startTime = 0;
|
||||
var completeBuild = function(children) {
|
||||
childrenAdded = true;
|
||||
item.treeList.childList = that._addChildren(container,item,children,depth).hide();
|
||||
var delta = Date.now() - startTime;
|
||||
if (delta < 400) {
|
||||
setTimeout(function() {
|
||||
item.treeList.childList.slideDown('fast');
|
||||
if (spinner) {
|
||||
spinner.remove();
|
||||
}
|
||||
},400-delta);
|
||||
} else {
|
||||
item.treeList.childList.slideDown('fast');
|
||||
if (spinner) {
|
||||
spinner.remove();
|
||||
}
|
||||
}
|
||||
done && done();
|
||||
that._trigger("childrenloaded",null,item)
|
||||
}
|
||||
if (typeof item.children === 'function') {
|
||||
item.children(completeBuild,item);
|
||||
} else {
|
||||
delete item.deferBuild;
|
||||
completeBuild(item.children);
|
||||
}
|
||||
if (!childrenAdded) {
|
||||
startTime = Date.now();
|
||||
spinner = $('<div class="red-ui-treeList-spinner">').css({
|
||||
"background-position": (35+depth*20)+'px 50%'
|
||||
}).appendTo(container);
|
||||
}
|
||||
|
||||
} else {
|
||||
if (that._loadingData) {
|
||||
item.treeList.childList.show();
|
||||
} else {
|
||||
item.treeList.childList.slideDown('fast');
|
||||
}
|
||||
done && done();
|
||||
}
|
||||
container.addClass("expanded");
|
||||
}
|
||||
item.treeList.collapse = function() {
|
||||
if (!item.children) {
|
||||
return;
|
||||
}
|
||||
item.treeList.childList.slideUp('fast');
|
||||
container.removeClass("expanded");
|
||||
}
|
||||
|
||||
var treeListIcon = $('<span class="red-ui-treeList-icon"></span>').appendTo(label);
|
||||
if (item.children) {
|
||||
item.treeList.makeParent();
|
||||
}
|
||||
|
||||
if (item.hasOwnProperty('selected')) {
|
||||
var selectWrapper = $('<span class="red-ui-treeList-icon"></span>').appendTo(label);
|
||||
if (item.checkbox) {
|
||||
var selectWrapper = $('<span class="red-ui-treeList-icon"></span>');
|
||||
var cb = $('<input class="red-ui-treeList-checkbox" type="checkbox">').prop('checked',item.selected).appendTo(selectWrapper);
|
||||
label.toggleClass("selected",item.selected);
|
||||
cb.on('click', function(e) {
|
||||
e.stopPropagation();
|
||||
});
|
||||
cb.on('change', function(e) {
|
||||
item.selected = this.checked;
|
||||
if (item.selected) {
|
||||
that._selected.add(item);
|
||||
} else {
|
||||
that._selected.delete(item);
|
||||
}
|
||||
label.toggleClass("selected",this.checked);
|
||||
that._trigger("select",e,item);
|
||||
})
|
||||
@@ -497,10 +622,15 @@
|
||||
cb.trigger("click");
|
||||
}
|
||||
}
|
||||
selectWrapper.appendTo(label)
|
||||
} else {
|
||||
label.on("click", function(e) {
|
||||
that._topList.find(".selected").removeClass("selected");
|
||||
if (!that.options.multi) {
|
||||
that.clearSelection();
|
||||
}
|
||||
label.addClass("selected");
|
||||
that._selected.add(item);
|
||||
|
||||
that._trigger("select",e,item)
|
||||
})
|
||||
label.on("dblclick", function(e) {
|
||||
@@ -508,9 +638,30 @@
|
||||
that._trigger("confirm",e,item);
|
||||
}
|
||||
})
|
||||
item.treeList.select = function(v) {
|
||||
if (!that.options.multi) {
|
||||
that.clearSelection();
|
||||
}
|
||||
label.toggleClass("selected",v);
|
||||
if (v) {
|
||||
that._selected.add(item);
|
||||
that._trigger("select",null,item)
|
||||
} else {
|
||||
that._selected.delete(item);
|
||||
}
|
||||
that.reveal(item);
|
||||
}
|
||||
}
|
||||
label.toggleClass("selected",!!item.selected);
|
||||
if (item.selected) {
|
||||
that._selected.add(item);
|
||||
}
|
||||
if (item.icon) {
|
||||
if (typeof item.icon === "string") {
|
||||
$('<span class="red-ui-treeList-icon"><i class="'+item.icon+'" /></span>').appendTo(label);
|
||||
} else {
|
||||
$('<span class="red-ui-treeList-icon">').appendTo(label).append(item.icon);
|
||||
}
|
||||
}
|
||||
if (item.hasOwnProperty('label') || item.hasOwnProperty('sublabel')) {
|
||||
if (item.hasOwnProperty('label')) {
|
||||
@@ -528,12 +679,13 @@
|
||||
}
|
||||
if (item.children) {
|
||||
if (Array.isArray(item.children) && !item.deferBuild) {
|
||||
item.treeList.childList = that._addChildren(container,item,item.children,depth).hide();
|
||||
item.treeList.childList = that._addChildren(container,item,item.children,depth);
|
||||
}
|
||||
if (item.expanded) {
|
||||
item.treeList.expand();
|
||||
}
|
||||
}
|
||||
// label.appendTo(container);
|
||||
},
|
||||
empty: function() {
|
||||
this._topList.editableList('empty');
|
||||
@@ -542,6 +694,7 @@
|
||||
var that = this;
|
||||
if (items !== undefined) {
|
||||
this._data = items;
|
||||
this._items = {};
|
||||
this._topList.editableList('empty');
|
||||
this._loadingData = true;
|
||||
for (var i=0; i<items.length;i++) {
|
||||
@@ -556,33 +709,149 @@
|
||||
return this._data;
|
||||
}
|
||||
},
|
||||
show: function(id) {
|
||||
for (var i=0;i<this._data.length;i++) {
|
||||
if (this._data[i].id === id) {
|
||||
this._topList.editableList('show',this._data[i]);
|
||||
show: function(item, done) {
|
||||
if (typeof item === "string") {
|
||||
item = this._items[item]
|
||||
}
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
var that = this;
|
||||
var stack = [];
|
||||
var i = item;
|
||||
while(i) {
|
||||
stack.unshift(i);
|
||||
i = i.parent;
|
||||
}
|
||||
var isOpening = false;
|
||||
var handleStack = function(opening) {
|
||||
isOpening = isOpening ||opening
|
||||
var item = stack.shift();
|
||||
if (stack.length === 0) {
|
||||
setTimeout(function() {
|
||||
that.reveal(item);
|
||||
if (done) { done(); }
|
||||
},isOpening?200:0);
|
||||
} else {
|
||||
item.treeList.expand(handleStack)
|
||||
}
|
||||
}
|
||||
handleStack();
|
||||
},
|
||||
reveal: function(item) {
|
||||
if (typeof item === "string") {
|
||||
item = this._items[item]
|
||||
}
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
var listOffset = this._topList.offset().top;
|
||||
var itemOffset = item.treeList.label.offset().top;
|
||||
var scrollTop = this._topList.parent().scrollTop();
|
||||
itemOffset -= listOffset+scrollTop;
|
||||
var treeHeight = this._topList.parent().height();
|
||||
var itemHeight = item.treeList.label.outerHeight();
|
||||
if (itemOffset < itemHeight/2) {
|
||||
this._topList.parent().scrollTop(scrollTop+itemOffset-itemHeight/2-itemHeight)
|
||||
} else if (itemOffset+itemHeight > treeHeight) {
|
||||
this._topList.parent().scrollTop(scrollTop+((itemOffset+2.5*itemHeight)-treeHeight));
|
||||
}
|
||||
},
|
||||
select: function(item) {
|
||||
this._topList.find(".selected").removeClass("selected");
|
||||
item.treeList.label.addClass("selected");
|
||||
this._trigger("select",null,item)
|
||||
select: function(item, triggerEvent, deselectExisting) {
|
||||
var that = this;
|
||||
if (!this.options.multi && deselectExisting !== false) {
|
||||
this.clearSelection();
|
||||
}
|
||||
if (Array.isArray(item)) {
|
||||
item.forEach(function(i) {
|
||||
that.select(i,triggerEvent,false);
|
||||
})
|
||||
return;
|
||||
}
|
||||
if (typeof item === "string") {
|
||||
item = this._items[item]
|
||||
}
|
||||
if (!item) {
|
||||
return;
|
||||
}
|
||||
// this.show(item.id);
|
||||
item.selected = true;
|
||||
this._selected.add(item);
|
||||
|
||||
if (item.treeList.label) {
|
||||
item.treeList.label.addClass("selected");
|
||||
}
|
||||
if (triggerEvent !== false) {
|
||||
this._trigger("select",null,item)
|
||||
}
|
||||
},
|
||||
clearSelection: function() {
|
||||
this._selected.forEach(function(item) {
|
||||
item.selected = false;
|
||||
if (item.treeList.label) {
|
||||
item.treeList.label.removeClass("selected")
|
||||
}
|
||||
});
|
||||
this._selected.clear();
|
||||
},
|
||||
selected: function() {
|
||||
var s = this._topList.find(".selected");
|
||||
if (this.options.multi) {
|
||||
var res = [];
|
||||
s.each(function() {
|
||||
res.push($(this).parent().data('data'));
|
||||
var selected = [];
|
||||
this._selected.forEach(function(item) {
|
||||
selected.push(item);
|
||||
})
|
||||
return res;
|
||||
if (this.options.multi) {
|
||||
return selected;
|
||||
}
|
||||
if (s.length) {
|
||||
return s.parent().data('data');
|
||||
if (selected.length) {
|
||||
return selected[0]
|
||||
} else {
|
||||
// TODO: This may be a bug.. it causes the call to return itself
|
||||
// not undefined.
|
||||
return undefined;
|
||||
}
|
||||
},
|
||||
filter: function(filterFunc) {
|
||||
this.activeFilter = filterFunc;
|
||||
var totalCount = 0;
|
||||
var filter = function(item) {
|
||||
var matchCount = 0;
|
||||
if (filterFunc && filterFunc(item)) {
|
||||
matchCount++;
|
||||
totalCount++;
|
||||
}
|
||||
var childCount = 0;
|
||||
if (item.children && typeof item.children !== "function") {
|
||||
if (item.treeList.childList) {
|
||||
childCount = item.treeList.childList.editableList('filter', filter);
|
||||
} else {
|
||||
item.treeList.childFilter = filter;
|
||||
if (filterFunc) {
|
||||
item.children.forEach(function(i) {
|
||||
if (filter(i)) {
|
||||
childCount++;
|
||||
}
|
||||
})
|
||||
|
||||
}
|
||||
}
|
||||
matchCount += childCount;
|
||||
if (filterFunc && childCount > 0) {
|
||||
setTimeout(function() {
|
||||
item.treeList.expand();
|
||||
},10);
|
||||
}
|
||||
}
|
||||
if (!filterFunc) {
|
||||
totalCount++;
|
||||
return true
|
||||
}
|
||||
return matchCount > 0
|
||||
}
|
||||
this._topList.editableList('filter', filter);
|
||||
return totalCount;
|
||||
},
|
||||
get: function(id) {
|
||||
return this._items[id] || null;
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
@@ -164,6 +164,88 @@
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
cred:{
|
||||
value:"cred",
|
||||
label:"credential",
|
||||
icon:"fa fa-lock",
|
||||
inputType: "password",
|
||||
valueLabel: function(container,value) {
|
||||
var that = this;
|
||||
container.css("pointer-events","none");
|
||||
container.css("flex-grow",0);
|
||||
this.elementDiv.hide();
|
||||
var buttons = $('<div>').css({
|
||||
position: "absolute",
|
||||
right:"6px",
|
||||
top: "6px",
|
||||
"pointer-events":"all"
|
||||
}).appendTo(container);
|
||||
var eyeButton = $('<button type="button" class="red-ui-button red-ui-button-small"></button>').css({
|
||||
width:"20px"
|
||||
}).appendTo(buttons).on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
var cursorPosition = that.input[0].selectionStart;
|
||||
var currentType = that.input.attr("type");
|
||||
if (currentType === "text") {
|
||||
that.input.attr("type","password");
|
||||
eyeCon.removeClass("fa-eye-slash").addClass("fa-eye");
|
||||
setTimeout(function() {
|
||||
that.input.focus();
|
||||
that.input[0].setSelectionRange(cursorPosition, cursorPosition);
|
||||
},50);
|
||||
} else {
|
||||
that.input.attr("type","text");
|
||||
eyeCon.removeClass("fa-eye").addClass("fa-eye-slash");
|
||||
setTimeout(function() {
|
||||
that.input.focus();
|
||||
that.input[0].setSelectionRange(cursorPosition, cursorPosition);
|
||||
},50);
|
||||
}
|
||||
}).hide();
|
||||
var eyeCon = $('<i class="fa fa-eye"></i>').css("margin-left","-2px").appendTo(eyeButton);
|
||||
|
||||
if (value === "__PWRD__") {
|
||||
var innerContainer = $('<div><i class="fa fa-asterisk"></i><i class="fa fa-asterisk"></i><i class="fa fa-asterisk"></i><i class="fa fa-asterisk"></i><i class="fa fa-asterisk"></i></div>').css({
|
||||
padding:"6px 6px",
|
||||
borderRadius:"4px"
|
||||
}).addClass("red-ui-typedInput-value-label-inactive").appendTo(container);
|
||||
var editButton = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-pencil"></i></button>').appendTo(buttons).on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
innerContainer.hide();
|
||||
container.css("background","none");
|
||||
container.css("pointer-events","none");
|
||||
that.input.val("");
|
||||
that.element.val("");
|
||||
that.elementDiv.show();
|
||||
editButton.hide();
|
||||
cancelButton.show();
|
||||
eyeButton.show();
|
||||
setTimeout(function() {
|
||||
that.input.focus();
|
||||
},50);
|
||||
});
|
||||
var cancelButton = $('<button type="button" class="red-ui-button red-ui-button-small"><i class="fa fa-times"></i></button>').css("margin-left","3px").appendTo(buttons).on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
innerContainer.show();
|
||||
container.css("background","");
|
||||
that.input.val("__PWRD__");
|
||||
that.element.val("__PWRD__");
|
||||
that.elementDiv.hide();
|
||||
editButton.show();
|
||||
cancelButton.hide();
|
||||
eyeButton.hide();
|
||||
that.input.attr("type","password");
|
||||
eyeCon.removeClass("fa-eye-slash").addClass("fa-eye");
|
||||
|
||||
}).hide();
|
||||
} else {
|
||||
container.css("background","none");
|
||||
container.css("pointer-events","none");
|
||||
this.elementDiv.show();
|
||||
eyeButton.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
};
|
||||
var nlsd = false;
|
||||
@@ -206,7 +288,7 @@
|
||||
this.input.css('width','100%');
|
||||
this.uiSelect.width(m[1]);
|
||||
this.uiWidth = null;
|
||||
} else {
|
||||
} else if (this.uiWidth !== 0){
|
||||
this.uiSelect.width(this.uiWidth);
|
||||
}
|
||||
["Right","Left"].forEach(function(d) {
|
||||
@@ -220,11 +302,17 @@
|
||||
that.input.attr(d,m);
|
||||
});
|
||||
|
||||
this.defaultInputType = this.input.attr('type');
|
||||
|
||||
this.uiSelect.addClass("red-ui-typedInput-container");
|
||||
|
||||
this.element.attr('type','hidden');
|
||||
|
||||
if (!this.options.types && this.options.type) {
|
||||
this.options.types = [this.options.type]
|
||||
} else {
|
||||
this.options.types = this.options.types||Object.keys(allOptions);
|
||||
}
|
||||
|
||||
this.selectTrigger = $('<button class="red-ui-typedInput-type-select" tabindex="0"></button>').prependTo(this.uiSelect);
|
||||
$('<i class="red-ui-typedInput-icon fa fa-caret-down"></i>').toggle(this.options.types.length > 1).appendTo(this.selectTrigger);
|
||||
@@ -254,7 +342,17 @@
|
||||
this.input.on('change', function() {
|
||||
that.validate();
|
||||
that.element.val(that.value());
|
||||
that.element.trigger('change',that.propertyType,that.value());
|
||||
that.element.trigger('change',[that.propertyType,that.value()]);
|
||||
});
|
||||
this.input.on('keyup', function(evt) {
|
||||
that.validate();
|
||||
that.element.val(that.value());
|
||||
that.element.trigger('keyup',evt);
|
||||
});
|
||||
this.input.on('paste', function(evt) {
|
||||
that.validate();
|
||||
that.element.val(that.value());
|
||||
that.element.trigger('paste',evt);
|
||||
});
|
||||
this.input.on('keydown', function(evt) {
|
||||
if (evt.keyCode >= 37 && evt.keyCode <= 40) {
|
||||
@@ -369,6 +467,9 @@
|
||||
if (opt.label) {
|
||||
op.text(opt.label);
|
||||
}
|
||||
if (opt.title) {
|
||||
op.prop('title', opt.title)
|
||||
}
|
||||
if (opt.icon) {
|
||||
if (opt.icon.indexOf("<") === 0) {
|
||||
$(opt.icon).prependTo(op);
|
||||
@@ -488,56 +589,6 @@
|
||||
done(labelWidth);
|
||||
}
|
||||
},
|
||||
_resize: function() {
|
||||
var that = this;
|
||||
if (this.uiWidth !== null) {
|
||||
this.uiSelect.width(this.uiWidth);
|
||||
}
|
||||
var type = this.typeMap[this.propertyType];
|
||||
if (type && type.hasValue === false) {
|
||||
this.selectTrigger.addClass("red-ui-typedInput-full-width");
|
||||
} else {
|
||||
this.selectTrigger.removeClass("red-ui-typedInput-full-width");
|
||||
this._getLabelWidth(this.selectTrigger, function(labelWidth) {
|
||||
that.elementDiv.css('left',labelWidth+"px");
|
||||
that.valueLabelContainer.css('left',labelWidth+"px");
|
||||
if (that.optionExpandButton.shown) {
|
||||
that.elementDiv.css('right',"22px");
|
||||
that.valueLabelContainer.css('right',"22px");
|
||||
} else {
|
||||
that.elementDiv.css('right','0');
|
||||
that.valueLabelContainer.css('right','0');
|
||||
that.input.css({
|
||||
'border-top-right-radius': '4px',
|
||||
'border-bottom-right-radius': '4px'
|
||||
});
|
||||
}
|
||||
if (that.optionSelectTrigger) {
|
||||
if (type && type.options && type.hasValue === true) {
|
||||
that.optionSelectLabel.css({'left':'auto'})
|
||||
that._getLabelWidth(that.optionSelectLabel, function(lw) {
|
||||
that.optionSelectTrigger.css({'width':(23+lw)+"px"});
|
||||
that.elementDiv.css('right',(23+lw)+"px");
|
||||
that.input.css({
|
||||
'border-top-right-radius': 0,
|
||||
'border-bottom-right-radius': 0
|
||||
});
|
||||
});
|
||||
} else {
|
||||
that.optionSelectLabel.css({'left':'0'})
|
||||
that.optionSelectTrigger.css({'width':'calc( 100% - '+labelWidth+'px )'});
|
||||
if (!that.optionExpandButton.shown) {
|
||||
that.elementDiv.css({'right':0});
|
||||
that.input.css({
|
||||
'border-top-right-radius': '4px',
|
||||
'border-bottom-right-radius': '4px'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
},
|
||||
_updateOptionSelectLabel: function(o) {
|
||||
var opt = this.typeMap[this.propertyType];
|
||||
this.optionSelectLabel.empty();
|
||||
@@ -565,8 +616,7 @@
|
||||
}
|
||||
if (opt.hasValue) {
|
||||
this.optionValue = o.value;
|
||||
this._resize();
|
||||
this.input.trigger('change',this.propertyType,this.value());
|
||||
this.input.trigger('change',[this.propertyType,this.value()]);
|
||||
}
|
||||
} else {
|
||||
this.optionSelectLabel.text(o.length+" selected");
|
||||
@@ -605,11 +655,12 @@
|
||||
this.propertyType = null;
|
||||
this.type(currentType);
|
||||
}
|
||||
setTimeout(function() {that._resize();},0);
|
||||
},
|
||||
width: function(desiredWidth) {
|
||||
this.uiWidth = desiredWidth;
|
||||
this._resize();
|
||||
if (this.uiWidth !== null) {
|
||||
this.uiSelect.width(this.uiWidth);
|
||||
}
|
||||
},
|
||||
value: function(value) {
|
||||
var that = this;
|
||||
@@ -632,7 +683,7 @@
|
||||
for (var i=0;i<opt.options.length;i++) {
|
||||
var op = opt.options[i];
|
||||
if (typeof op === "string") {
|
||||
if (op === value) {
|
||||
if (op === value || op === ""+value) {
|
||||
selectedOption.push(that.activeOptions[op]);
|
||||
break;
|
||||
}
|
||||
@@ -644,7 +695,7 @@
|
||||
})
|
||||
this.input.val(value);
|
||||
if (!opt.multiple) {
|
||||
if (!selectedOption.length === 0) {
|
||||
if (selectedOption.length === 0) {
|
||||
selectedOption = [{value:""}];
|
||||
}
|
||||
this._updateOptionSelectLabel(selectedOption[0])
|
||||
@@ -658,7 +709,7 @@
|
||||
opt.valueLabel.call(this,this.valueLabelContainer,value);
|
||||
}
|
||||
}
|
||||
this.input.trigger('change',this.type(),value);
|
||||
this.input.trigger('change',[this.type(),value]);
|
||||
}
|
||||
},
|
||||
type: function(type) {
|
||||
@@ -680,19 +731,23 @@
|
||||
}
|
||||
else if (opt.icon.indexOf("/") !== -1) {
|
||||
image = new Image();
|
||||
image.onload = function() { that._resize(); }
|
||||
image.onerror = function() { that._resize(); }
|
||||
image.name = opt.icon;
|
||||
image.src = mapDeprecatedIcon(opt.icon);
|
||||
$('<img>',{src:mapDeprecatedIcon(opt.icon),style:"margin-right: 4px;height: 18px;"}).prependTo(this.selectLabel);
|
||||
}
|
||||
else {
|
||||
$('<i>',{class:"red-ui-typedInput-icon "+opt.icon}).prependTo(this.selectLabel);
|
||||
$('<i>',{class:"red-ui-typedInput-icon "+opt.icon,style:"min-width: 13px; margin-right: 4px;"}).prependTo(this.selectLabel);
|
||||
}
|
||||
}
|
||||
if (opt.hasValue === false || (opt.showLabel !== false && !opt.icon)) {
|
||||
this.selectLabel.text(opt.label);
|
||||
}
|
||||
if (opt.hasValue === false) {
|
||||
this.selectTrigger.addClass("red-ui-typedInput-full-width");
|
||||
} else {
|
||||
this.selectTrigger.removeClass("red-ui-typedInput-full-width");
|
||||
}
|
||||
|
||||
if (this.optionMenu) {
|
||||
this.optionMenu.remove();
|
||||
this.optionMenu = null;
|
||||
@@ -703,11 +758,13 @@
|
||||
this.optionExpandButton.shown = false;
|
||||
}
|
||||
if (this.optionSelectTrigger) {
|
||||
this.optionSelectTrigger.show();
|
||||
this.optionSelectTrigger.css({"display":"inline-flex"});
|
||||
if (!opt.hasValue) {
|
||||
this.optionSelectTrigger.css({"flex-grow":1})
|
||||
this.elementDiv.hide();
|
||||
this.valueLabelContainer.hide();
|
||||
} else {
|
||||
this.optionSelectTrigger.css({"flex-grow":0})
|
||||
this.elementDiv.show();
|
||||
this.valueLabelContainer.hide();
|
||||
}
|
||||
@@ -817,21 +874,29 @@
|
||||
});
|
||||
}
|
||||
this._trigger("typechange",null,this.propertyType);
|
||||
this.input.trigger('change',this.propertyType,this.value());
|
||||
this.input.trigger('change',[this.propertyType,this.value()]);
|
||||
} else {
|
||||
if (this.optionSelectTrigger) {
|
||||
this.optionSelectTrigger.hide();
|
||||
}
|
||||
if (opt.inputType) {
|
||||
this.input.attr('type',opt.inputType)
|
||||
} else {
|
||||
this.input.attr('type',this.defaultInputType)
|
||||
}
|
||||
if (opt.hasValue === false) {
|
||||
this.oldValue = this.input.val();
|
||||
this.input.val("");
|
||||
this.elementDiv.hide();
|
||||
this.valueLabelContainer.hide();
|
||||
} else if (opt.valueLabel) {
|
||||
// Reset any CSS the custom label may have set
|
||||
this.valueLabelContainer.css("pointer-events","");
|
||||
this.valueLabelContainer.css("flex-grow",1);
|
||||
this.valueLabelContainer.show();
|
||||
this.valueLabelContainer.empty();
|
||||
opt.valueLabel.call(this,this.valueLabelContainer,this.input.val());
|
||||
this.elementDiv.hide();
|
||||
opt.valueLabel.call(this,this.valueLabelContainer,this.input.val());
|
||||
} else {
|
||||
if (this.oldValue !== undefined) {
|
||||
this.input.val(this.oldValue);
|
||||
@@ -869,7 +934,7 @@
|
||||
panel.show({
|
||||
target:that.optionExpandButton,
|
||||
onclose:content.onclose,
|
||||
align: "right"
|
||||
align: "left"
|
||||
});
|
||||
}
|
||||
})
|
||||
@@ -879,10 +944,7 @@
|
||||
}
|
||||
}
|
||||
this._trigger("typechange",null,this.propertyType);
|
||||
this.input.trigger('change',this.propertyType,this.value());
|
||||
}
|
||||
if (!image) {
|
||||
this._resize();
|
||||
this.input.trigger('change',[this.propertyType,this.value()]);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -910,10 +972,21 @@
|
||||
},
|
||||
show: function() {
|
||||
this.uiSelect.show();
|
||||
this._resize();
|
||||
},
|
||||
hide: function() {
|
||||
this.uiSelect.hide();
|
||||
},
|
||||
disable: function(val) {
|
||||
if(val === true) {
|
||||
this.uiSelect.attr("disabled", "disabled");
|
||||
} else if (val === false) {
|
||||
this.uiSelect.attr("disabled", null); //remove attr
|
||||
} else {
|
||||
this.uiSelect.attr("disabled", val); //user value
|
||||
}
|
||||
},
|
||||
disabled: function() {
|
||||
return this.uiSelect.attr("disabled");
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
|
||||
@@ -108,7 +108,7 @@ RED.deploy = (function() {
|
||||
|
||||
|
||||
|
||||
RED.events.on('nodes:change',function(state) {
|
||||
RED.events.on('workspace:dirty',function(state) {
|
||||
if (state.dirty) {
|
||||
window.onbeforeunload = function() {
|
||||
return RED._("deploy.confirm.undeployedChanges");
|
||||
@@ -334,8 +334,7 @@ RED.deploy = (function() {
|
||||
var invalidNodes = [];
|
||||
|
||||
RED.nodes.eachNode(function(node) {
|
||||
hasInvalid = hasInvalid || !node.valid;
|
||||
if (!node.valid) {
|
||||
if (!node.valid && !node.d) {
|
||||
invalidNodes.push(getNodeInfo(node));
|
||||
}
|
||||
if (node.type === "unknown") {
|
||||
@@ -345,6 +344,7 @@ RED.deploy = (function() {
|
||||
}
|
||||
});
|
||||
hasUnknown = unknownNodes.length > 0;
|
||||
hasInvalid = invalidNodes.length > 0;
|
||||
|
||||
var unusedConfigNodes = [];
|
||||
RED.nodes.eachConfig(function(node) {
|
||||
|
||||
@@ -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 {
|
||||
@@ -1029,9 +1029,9 @@ RED.diff = (function() {
|
||||
}
|
||||
|
||||
var localSelectDiv = $('<label>',{class:"red-ui-diff-selectbox",for:safeNodeId+"-local"}).on("click", function(e) { e.stopPropagation();}).appendTo(localDiv);
|
||||
var localRadio = $('<input>',{class:"red-ui-diff-selectbox-input",id:safeNodeId+"-local",type:'radio',value:"local",name:safeNodeId,class:className+"-local"}).data('node-id',node.id).on("change", changeHandler).appendTo(localSelectDiv);
|
||||
var localRadio = $('<input>',{class:"red-ui-diff-selectbox-input "+className+"-local",id:safeNodeId+"-local",type:'radio',value:"local",name:safeNodeId}).data('node-id',node.id).on("change", changeHandler).appendTo(localSelectDiv);
|
||||
var remoteSelectDiv = $('<label>',{class:"red-ui-diff-selectbox",for:safeNodeId+"-remote"}).on("click", function(e) { e.stopPropagation();}).appendTo(remoteDiv);
|
||||
var remoteRadio = $('<input>',{class:"red-ui-diff-selectbox-input",id:safeNodeId+"-remote",type:'radio',value:"remote",name:safeNodeId,class:className+"-remote"}).data('node-id',node.id).on("change", changeHandler).appendTo(remoteSelectDiv);
|
||||
var remoteRadio = $('<input>',{class:"red-ui-diff-selectbox-input "+className+"-remote",id:safeNodeId+"-remote",type:'radio',value:"remote",name:safeNodeId}).data('node-id',node.id).on("change", changeHandler).appendTo(remoteSelectDiv);
|
||||
if (state === 'local') {
|
||||
localRadio.prop('checked',true);
|
||||
} else if (state === 'remote') {
|
||||
@@ -1411,7 +1411,7 @@ RED.diff = (function() {
|
||||
// Restore the original flow so subsequent merge resolutions can properly
|
||||
// identify new-vs-old
|
||||
RED.nodes.originalFlow(originalFlow);
|
||||
imported[0].forEach(function(n) {
|
||||
imported.nodes.forEach(function(n) {
|
||||
if (nodeChangedStates[n.id] || localChangedStates[n.id]) {
|
||||
n.changed = true;
|
||||
}
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
**/
|
||||
(function() {
|
||||
|
||||
var template = '<script type="text/x-red" data-template-name="_buffer"><div id="red-ui-editor-type-buffer-panels"><div id="red-ui-editor-type-buffer-panel-str" class="red-ui-panel"><div class="form-row" style="margin-bottom: 3px; text-align: right;"><button class="red-ui-editor-type-buffer-type red-ui-button red-ui-button-small"><i class="fa fa-exclamation-circle"></i> <span id="red-ui-editor-type-buffer-type-string" data-i18n="bufferEditor.modeString"></span><span id="red-ui-editor-type-buffer-type-array" data-i18n="bufferEditor.modeArray"></span></button></div><div class="form-row node-text-editor-row"><div class="node-text-editor" id="red-ui-editor-type-buffer-str"></div></div></div><div id="red-ui-editor-type-buffer-panel-bin" class="red-ui-panel"><div class="form-row node-text-editor-row" style="margin-top: 10px"><div class="node-text-editor" id="red-ui-editor-type-buffer-bin"></div></div></div></div></script>';
|
||||
var template = '<script type="text/x-red" data-template-name="_buffer"><div id="red-ui-editor-type-buffer-panels"><div id="red-ui-editor-type-buffer-panel-str" class="red-ui-panel"><div class="form-row" style="margin-bottom: 3px; text-align: right;"><button class="red-ui-editor-type-buffer-type red-ui-button red-ui-button-small"><i class="fa fa-exclamation-circle"></i> <span id="red-ui-editor-type-buffer-type-string" data-i18n="bufferEditor.modeString"></span><span id="red-ui-editor-type-buffer-type-array" data-i18n="bufferEditor.modeArray"></span></button></div><div class="form-row node-text-editor-row"><div class="node-text-editor" id="red-ui-editor-type-buffer-str"></div></div></div><div id="red-ui-editor-type-buffer-panel-bin" class="red-ui-panel"><div class="form-row node-text-editor-row" style="margin-top: 10px; margin-bottom:0;"><div class="node-text-editor" id="red-ui-editor-type-buffer-bin"></div></div></div></div></script>';
|
||||
|
||||
function stringToUTF8Array(str) {
|
||||
var data = [];
|
||||
@@ -187,8 +187,7 @@
|
||||
|
||||
$(".red-ui-editor-type-buffer-type").on("click", function(e) {
|
||||
e.preventDefault();
|
||||
RED.sidebar.info.set(RED._("bufferEditor.modeDesc"));
|
||||
RED.sidebar.info.show();
|
||||
RED.sidebar.help.set(RED._("bufferEditor.modeDesc"));
|
||||
})
|
||||
|
||||
|
||||
|
||||
@@ -102,7 +102,7 @@
|
||||
var f = $(this).val();
|
||||
var args = RED._('jsonata:'+f+".args",{defaultValue:''});
|
||||
var title = "<h5>"+f+"("+args+")</h5>";
|
||||
var body = marked(RED._('jsonata:'+f+'.desc',{defaultValue:''}));
|
||||
var body = RED.utils.renderMarkdown(RED._('jsonata:'+f+'.desc',{defaultValue:''}));
|
||||
$("#red-ui-editor-type-expression-help").html(title+"<p>"+body+"</p>");
|
||||
|
||||
})
|
||||
@@ -207,6 +207,7 @@
|
||||
}
|
||||
expressionEditor.getSession().setValue(v||"",-1);
|
||||
});
|
||||
funcSelect.change();
|
||||
|
||||
var tabs = RED.tabs.create({
|
||||
element: $("#red-ui-editor-type-expression-tabs"),
|
||||
@@ -236,8 +237,7 @@
|
||||
var changeTimer;
|
||||
$(".red-ui-editor-type-expression-legacy").on("click", function(e) {
|
||||
e.preventDefault();
|
||||
RED.sidebar.info.set(RED._("expressionEditor.compatModeDesc"));
|
||||
RED.sidebar.info.show();
|
||||
RED.sidebar.help.set(RED._("expressionEditor.compatModeDesc"));
|
||||
})
|
||||
var testExpression = function() {
|
||||
var value = testDataEditor.getValue();
|
||||
@@ -317,9 +317,9 @@
|
||||
var p2 = $("#red-ui-editor-type-expression-panel-info > .form-row > div:first-child");
|
||||
p2Height -= p2.outerHeight(true) + 20;
|
||||
$(".red-ui-editor-type-expression-tab-content").height(p2Height);
|
||||
$("#red-ui-editor-type-expression-test-data").css("height",(p2Height-5)+"px");
|
||||
$("#red-ui-editor-type-expression-test-data").css("height",(p2Height-25)+"px");
|
||||
testDataEditor.resize();
|
||||
$("#red-ui-editor-type-expression-test-result").css("height",(p2Height-5)+"px");
|
||||
$("#red-ui-editor-type-expression-test-result").css("height",(p2Height-25)+"px");
|
||||
testResultEditor.resize();
|
||||
}
|
||||
});
|
||||
|
||||
@@ -87,6 +87,9 @@
|
||||
expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false);
|
||||
}
|
||||
dialogForm.i18n();
|
||||
setTimeout(function() {
|
||||
expressionEditor.focus();
|
||||
},300);
|
||||
},
|
||||
close: function() {
|
||||
expressionEditor.destroy();
|
||||
|
||||
@@ -106,7 +106,7 @@
|
||||
options.push({id:"red-ui-editor-type-json-menu-duplicate", icon:"fa fa-copy", label:RED._("jsonEditor.duplicate"),onselect:function(){
|
||||
var newKey = item.key;
|
||||
if (item.parent.type === 'array') {
|
||||
newKey = parent.children.length;
|
||||
newKey = item.parent.children.length;
|
||||
} else {
|
||||
var m = /^(.*?)(-(\d+))?$/.exec(newKey);
|
||||
var usedKeys = {};
|
||||
@@ -141,6 +141,7 @@
|
||||
})
|
||||
}});
|
||||
options.push({id:"red-ui-editor-type-json-menu-collapse-children",icon:"fa fa-angle-double-up", label:RED._('jsonEditor.collapseItems'),onselect:function(){
|
||||
item.treeList.collapse();
|
||||
item.children.forEach(function(child) {
|
||||
child.treeList.collapse();
|
||||
})
|
||||
@@ -300,9 +301,9 @@
|
||||
var val = $('<input type="text" class="red-ui-editor-type-json-editor-value">').css({width:w+"px"}).val(""+valValue).insertAfter(valueLabel).typedInput({
|
||||
types:[
|
||||
'str','num','bool',
|
||||
{value:"null",label:"null",hasValue:false},
|
||||
{value:"array",label:"array",hasValue:false},
|
||||
{value:"object",label:"object",hasValue:false}
|
||||
{value:"null",label:RED._("common.type.null"),hasValue:false},
|
||||
{value:"array",label:RED._("common.type.array"),hasValue:false,icon:"red/images/typedInput/json.png"},
|
||||
{value:"object",label:RED._("common.type.object"),hasValue:false,icon:"red/images/typedInput/json.png"}
|
||||
],
|
||||
default: valType
|
||||
});
|
||||
@@ -326,10 +327,10 @@
|
||||
item.value = valValue;
|
||||
var valClass;
|
||||
switch(valType) {
|
||||
case 'str': item.children && (orphanedChildren = item.children); item.treeList.makeLeaf(true); item.type = "string"; valClass = "red-ui-debug-msg-type-string"; valValue = '"'+valValue+'"'; break;
|
||||
case 'num': item.children && (orphanedChildren = item.children); item.treeList.makeLeaf(true); item.type = "number"; valClass = "red-ui-debug-msg-type-number"; break;
|
||||
case 'bool': item.children && (orphanedChildren = item.children); item.treeList.makeLeaf(true); item.type = "boolean"; valClass = "red-ui-debug-msg-type-other"; item.value = (valValue === "true"); break;
|
||||
case 'null': item.children && (orphanedChildren = item.children); item.treeList.makeLeaf(true); item.type = "null"; valClass = "red-ui-debug-msg-type-null"; item.value = valValue = "null"; break;
|
||||
case 'str': if (item.children) { orphanedChildren = item.children } item.treeList.makeLeaf(true); item.type = "string"; valClass = "red-ui-debug-msg-type-string"; valValue = '"'+valValue+'"'; break;
|
||||
case 'num': if (item.children) { orphanedChildren = item.children } item.treeList.makeLeaf(true); item.type = "number"; valClass = "red-ui-debug-msg-type-number"; break;
|
||||
case 'bool': if (item.children) { orphanedChildren = item.children } item.treeList.makeLeaf(true); item.type = "boolean"; valClass = "red-ui-debug-msg-type-other"; item.value = (valValue === "true"); break;
|
||||
case 'null': if (item.children) { orphanedChildren = item.children } item.treeList.makeLeaf(true); item.type = "null"; valClass = "red-ui-debug-msg-type-null"; item.value = valValue = "null"; break;
|
||||
case 'object':
|
||||
item.treeList.makeParent(orphanedChildren);
|
||||
item.type = "object";
|
||||
@@ -484,7 +485,7 @@
|
||||
} else if (activeTab === "json-raw") {
|
||||
result = expressionEditor.getValue();
|
||||
}
|
||||
onComplete && onComplete(result);
|
||||
if (onComplete) { onComplete(result) }
|
||||
RED.tray.close();
|
||||
}
|
||||
}
|
||||
@@ -576,7 +577,7 @@
|
||||
} catch(err) {
|
||||
rootNode = null;
|
||||
list.treeList('data',[{
|
||||
label: "Invalid JSON: "+err.toString()
|
||||
label: RED._("jsonEditor.error.invalidJSON")+err.toString()
|
||||
}]);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -32,13 +32,13 @@
|
||||
'<button type="button" class="red-ui-button" data-style="bq"><i class="fa fa-quote-left"></i></button>'+
|
||||
'<button type="button" class="red-ui-button" data-style="hr"><i class="fa fa-minus"></i></button>'+
|
||||
'<button type="button" class="red-ui-button" data-style="link"><i class="fa fa-link"></i></button>'+
|
||||
'</span>'
|
||||
'</span>'+
|
||||
'</div>';
|
||||
|
||||
var template = '<script type="text/x-red" data-template-name="_markdown">'+
|
||||
'<div id="red-ui-editor-type-markdown-panels">'+
|
||||
'<div id="red-ui-editor-type-markdown-panel-editor" class="red-ui-panel">'+
|
||||
'<div style="height: 100%; margin: auto; max-width: 1000px;">'+
|
||||
'<div style="height: 100%; margin: auto;">'+
|
||||
'<div id="red-ui-editor-type-markdown-toolbar"></div>'+
|
||||
'<div class="node-text-editor" style="height: 100%" id="red-ui-editor-type-markdown"></div>'+
|
||||
'</div>'+
|
||||
@@ -107,7 +107,7 @@
|
||||
clearTimeout(changeTimer);
|
||||
changeTimer = setTimeout(function() {
|
||||
var currentScrollTop = $(".red-ui-editor-type-markdown-panel-preview").scrollTop();
|
||||
$(".red-ui-editor-type-markdown-panel-preview").html(marked(expressionEditor.getValue()));
|
||||
$(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue()));
|
||||
$(".red-ui-editor-type-markdown-panel-preview").scrollTop(currentScrollTop);
|
||||
},200);
|
||||
})
|
||||
@@ -116,7 +116,7 @@
|
||||
}
|
||||
|
||||
if (value) {
|
||||
$(".red-ui-editor-type-markdown-panel-preview").html(marked(expressionEditor.getValue()));
|
||||
$(".red-ui-editor-type-markdown-panel-preview").html(RED.utils.renderMarkdown(expressionEditor.getValue()));
|
||||
}
|
||||
panels = RED.panels.create({
|
||||
id:"red-ui-editor-type-markdown-panels",
|
||||
|
||||
702
packages/node_modules/@node-red/editor-client/src/js/ui/group.js
vendored
Normal file
@@ -0,0 +1,702 @@
|
||||
/**
|
||||
* 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.group = (function() {
|
||||
|
||||
var _groupEditTemplate = '<script type="text/x-red" data-template-name="group">'+
|
||||
'<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" data-i18n="[placeholder]common.label.name">'+
|
||||
'</div>'+
|
||||
|
||||
// '<div class="node-input-group-style-tools"><span class="button-group"><button class="red-ui-button red-ui-button-small">Use default style</button><button class="red-ui-button red-ui-button-small">Set as default style</button></span></div>'+
|
||||
|
||||
'<div class="form-row" id="node-input-row-style-stroke">'+
|
||||
'<label data-i18n="editor:common.label.style"></label>'+
|
||||
'<label style="width: 70px;margin-right:10px" for="node-input-style-stroke" data-i18n="editor:common.label.line"></label>'+
|
||||
'</div>'+
|
||||
'<div class="form-row" style="padding-left: 100px;" id="node-input-row-style-fill">'+
|
||||
'<label style="width: 70px;margin-right: 10px " for="node-input-style-fill" data-i18n="editor:common.label.fill"></label>'+
|
||||
'</div>'+
|
||||
'<div class="form-row">'+
|
||||
'<label for="node-input-style-label" data-i18n="editor:common.label.label"></label>'+
|
||||
'<input type="checkbox" id="node-input-style-label"/>'+
|
||||
'</div>'+
|
||||
'<div class="form-row" id="node-input-row-style-label-options">'+
|
||||
'<div style="margin-left: 100px; display: inline-block">'+
|
||||
'<div class="form-row">'+
|
||||
'<span style="display: inline-block; min-width: 140px" id="node-input-row-style-label-color">'+
|
||||
'<label style="width: 70px;margin-right: 10px" for="node-input-style-fill" data-i18n="editor:common.label.color"></label>'+
|
||||
'</span>'+
|
||||
'</div>'+
|
||||
'<div class="form-row">'+
|
||||
'<span style="display: inline-block; min-width: 140px;" id="node-input-row-style-label-position">'+
|
||||
'<label style="width: 70px;margin-right: 10px " for="node-input-style-label-position" data-i18n="editor:common.label.position"></label>'+
|
||||
'</span>'+
|
||||
'</div>'+
|
||||
'</div>'+
|
||||
'</div>'+
|
||||
|
||||
'</script>';
|
||||
|
||||
var colorPalette = [
|
||||
"#ff0000",
|
||||
"#ffC000",
|
||||
"#ffff00",
|
||||
"#92d04f",
|
||||
"#0070c0",
|
||||
"#001f60",
|
||||
"#6f2fa0",
|
||||
"#000000",
|
||||
"#777777"
|
||||
]
|
||||
var colorSteps = 3;
|
||||
var colorCount = colorPalette.length;
|
||||
for (var i=0,len=colorPalette.length*colorSteps;i<len;i++) {
|
||||
var ci = i%colorCount;
|
||||
var j = Math.floor(i/colorCount)+1;
|
||||
var c = colorPalette[ci];
|
||||
var r = parseInt(c.substring(1, 3), 16);
|
||||
var g = parseInt(c.substring(3, 5), 16);
|
||||
var b = parseInt(c.substring(5, 7), 16);
|
||||
var dr = (255-r)/(colorSteps+((ci===colorCount-1) ?0:1));
|
||||
var dg = (255-g)/(colorSteps+((ci===colorCount-1) ?0:1));
|
||||
var db = (255-b)/(colorSteps+((ci===colorCount-1) ?0:1));
|
||||
r = Math.min(255,Math.floor(r+j*dr));
|
||||
g = Math.min(255,Math.floor(g+j*dg));
|
||||
b = Math.min(255,Math.floor(b+j*db));
|
||||
var s = ((r<<16) + (g<<8) + b).toString(16);
|
||||
colorPalette.push('#'+'000000'.slice(0, 6-s.length)+s);
|
||||
}
|
||||
|
||||
var defaultGroupStyle = {
|
||||
label: true,
|
||||
"label-position": "nw"
|
||||
};
|
||||
|
||||
var groupDef = {
|
||||
defaults:{
|
||||
name:{value:""},
|
||||
style:{value:{label:true}},
|
||||
nodes:{value:[]}
|
||||
},
|
||||
category: "config",
|
||||
oneditprepare: function() {
|
||||
var style = this.style || {};
|
||||
RED.colorPicker.create({
|
||||
id:"node-input-style-stroke",
|
||||
value: style.stroke || defaultGroupStyle.stroke || "#a4a4a4",
|
||||
palette: colorPalette,
|
||||
cellPerRow: colorCount,
|
||||
cellWidth: 16,
|
||||
cellHeight: 16,
|
||||
cellMargin: 3,
|
||||
none: true,
|
||||
opacity: style.hasOwnProperty('stroke-opacity')?style['stroke-opacity']:(defaultGroupStyle.hasOwnProperty('stroke-opacity')?defaultGroupStyle['stroke-opacity']:1.0)
|
||||
}).appendTo("#node-input-row-style-stroke");
|
||||
RED.colorPicker.create({
|
||||
id:"node-input-style-fill",
|
||||
value: style.fill || defaultGroupStyle.fill ||"none",
|
||||
palette: colorPalette,
|
||||
cellPerRow: colorCount,
|
||||
cellWidth: 16,
|
||||
cellHeight: 16,
|
||||
cellMargin: 3,
|
||||
none: true,
|
||||
opacity: style.hasOwnProperty('fill-opacity')?style['fill-opacity']:(defaultGroupStyle.hasOwnProperty('fill-opacity')?defaultGroupStyle['fill-opacity']:1.0)
|
||||
}).appendTo("#node-input-row-style-fill");
|
||||
|
||||
createLayoutPicker({
|
||||
id:"node-input-style-label-position",
|
||||
value:style["label-position"] || "nw"
|
||||
}).appendTo("#node-input-row-style-label-position");
|
||||
|
||||
RED.colorPicker.create({
|
||||
id:"node-input-style-color",
|
||||
value: style.color || defaultGroupStyle.color ||"#a4a4a4",
|
||||
palette: colorPalette,
|
||||
cellPerRow: colorCount,
|
||||
cellWidth: 16,
|
||||
cellHeight: 16,
|
||||
cellMargin: 3
|
||||
}).appendTo("#node-input-row-style-label-color");
|
||||
|
||||
$("#node-input-style-label").toggleButton({
|
||||
enabledLabel: RED._("editor.show"),
|
||||
disabledLabel: RED._("editor.show"),
|
||||
})
|
||||
|
||||
$("#node-input-style-label").on("change", function(evt) {
|
||||
$("#node-input-row-style-label-options").toggle($(this).prop("checked"));
|
||||
})
|
||||
$("#node-input-style-label").prop("checked", this.style.label)
|
||||
$("#node-input-style-label").trigger("change");
|
||||
|
||||
},
|
||||
oneditresize: function(size) {
|
||||
},
|
||||
oneditsave: function() {
|
||||
this.style.stroke = $("#node-input-style-stroke").val();
|
||||
this.style.fill = $("#node-input-style-fill").val();
|
||||
this.style["stroke-opacity"] = $("#node-input-style-stroke-opacity").val();
|
||||
this.style["fill-opacity"] = $("#node-input-style-fill-opacity").val();
|
||||
this.style.label = $("#node-input-style-label").prop("checked");
|
||||
if (this.style.label) {
|
||||
this.style["label-position"] = $("#node-input-style-label-position").val();
|
||||
this.style.color = $("#node-input-style-color").val();
|
||||
} else {
|
||||
delete this.style["label-position"];
|
||||
delete this.style.color;
|
||||
}
|
||||
|
||||
var node = this;
|
||||
['stroke','fill','stroke-opacity','fill-opacity','color','label-position'].forEach(function(prop) {
|
||||
if (node.style[prop] === defaultGroupStyle[prop]) {
|
||||
delete node.style[prop]
|
||||
}
|
||||
})
|
||||
|
||||
this.resize = true;
|
||||
},
|
||||
set:{
|
||||
module: "node-red"
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
|
||||
RED.events.on("view:selection-changed",function(selection) {
|
||||
var activateGroup = !!selection.nodes;
|
||||
var activateUngroup = false;
|
||||
var activateMerge = false;
|
||||
var activateRemove = false;
|
||||
if (activateGroup) {
|
||||
selection.nodes.forEach(function (n) {
|
||||
if (n.type === "group") {
|
||||
activateUngroup = true;
|
||||
}
|
||||
if (!!n.g) {
|
||||
activateRemove = true;
|
||||
}
|
||||
});
|
||||
if (activateUngroup) {
|
||||
activateMerge = (selection.nodes.length > 1);
|
||||
}
|
||||
}
|
||||
RED.menu.setDisabled("menu-item-group-group", !activateGroup);
|
||||
RED.menu.setDisabled("menu-item-group-ungroup", !activateUngroup);
|
||||
RED.menu.setDisabled("menu-item-group-merge", !activateMerge);
|
||||
RED.menu.setDisabled("menu-item-group-remove", !activateRemove);
|
||||
});
|
||||
|
||||
RED.actions.add("core:group-selection", function() { groupSelection() })
|
||||
RED.actions.add("core:ungroup-selection", function() { ungroupSelection() })
|
||||
RED.actions.add("core:merge-selection-to-group", function() { mergeSelection() })
|
||||
RED.actions.add("core:remove-selection-from-group", function() { removeSelection() })
|
||||
RED.actions.add("core:copy-group-style", function() { copyGroupStyle() });
|
||||
RED.actions.add("core:paste-group-style", function() { pasteGroupStyle() });
|
||||
|
||||
$(_groupEditTemplate).appendTo("#red-ui-editor-node-configs");
|
||||
|
||||
var groupStyleDiv = $("<div>",{
|
||||
class:"red-ui-flow-group-body",
|
||||
style: "position: absolute; top: -1000px;"
|
||||
}).appendTo(document.body);
|
||||
var groupStyle = getComputedStyle(groupStyleDiv[0]);
|
||||
defaultGroupStyle = {
|
||||
stroke: convertColorToHex(groupStyle.stroke),
|
||||
"stroke-opacity": groupStyle.strokeOpacity,
|
||||
fill: convertColorToHex(groupStyle.fill),
|
||||
"fill-opacity": groupStyle.fillOpacity,
|
||||
label: true,
|
||||
"label-position": "nw"
|
||||
}
|
||||
groupStyleDiv.remove();
|
||||
groupStyleDiv = $("<div>",{
|
||||
class:"red-ui-flow-group-label",
|
||||
style: "position: absolute; top: -1000px;"
|
||||
}).appendTo(document.body);
|
||||
groupStyle = getComputedStyle(groupStyleDiv[0]);
|
||||
defaultGroupStyle.color = convertColorToHex(groupStyle.fill);
|
||||
groupStyleDiv.remove();
|
||||
}
|
||||
|
||||
function convertColorToHex(c) {
|
||||
var m = /^rgb\((\d+), (\d+), (\d+)\)$/.exec(c);
|
||||
if (m) {
|
||||
var s = ((parseInt(m[1])<<16) + (parseInt(m[2])<<8) + parseInt(m[3])).toString(16)
|
||||
return '#'+'000000'.slice(0, 6-s.length)+s;
|
||||
}
|
||||
return c;
|
||||
}
|
||||
|
||||
|
||||
var groupStyleClipboard;
|
||||
|
||||
function copyGroupStyle() {
|
||||
if (RED.view.state() !== RED.state.DEFAULT) { return }
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes && selection.nodes.length === 1 && selection.nodes[0].type === 'group') {
|
||||
groupStyleClipboard = JSON.parse(JSON.stringify(selection.nodes[0].style));
|
||||
RED.notify(RED._("clipboard.groupStyleCopied"),{id:"clipboard"})
|
||||
}
|
||||
}
|
||||
function pasteGroupStyle() {
|
||||
if (RED.view.state() !== RED.state.DEFAULT) { return }
|
||||
if (groupStyleClipboard) {
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
var historyEvent = {
|
||||
t:'multi',
|
||||
events:[],
|
||||
dirty: RED.nodes.dirty()
|
||||
}
|
||||
selection.nodes.forEach(function(n) {
|
||||
if (n.type === 'group') {
|
||||
historyEvent.events.push({
|
||||
t: "edit",
|
||||
node: n,
|
||||
changes: {
|
||||
style: JSON.parse(JSON.stringify(n.style))
|
||||
},
|
||||
dirty: RED.nodes.dirty()
|
||||
});
|
||||
n.style = JSON.parse(JSON.stringify(groupStyleClipboard));
|
||||
n.dirty = true;
|
||||
|
||||
}
|
||||
})
|
||||
if (historyEvent.events.length > 0) {
|
||||
RED.history.push(historyEvent);
|
||||
RED.nodes.dirty(true);
|
||||
RED.view.redraw();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function groupSelection() {
|
||||
if (RED.view.state() !== RED.state.DEFAULT) { return }
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
var group = createGroup(selection.nodes);
|
||||
if (group) {
|
||||
var historyEvent = {
|
||||
t:"createGroup",
|
||||
groups: [ group ],
|
||||
dirty: RED.nodes.dirty()
|
||||
}
|
||||
RED.history.push(historyEvent);
|
||||
RED.view.select({nodes:[group]});
|
||||
RED.nodes.dirty(true);
|
||||
}
|
||||
}
|
||||
}
|
||||
function ungroupSelection() {
|
||||
if (RED.view.state() !== RED.state.DEFAULT) { return }
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
var newSelection = [];
|
||||
groups = selection.nodes.filter(function(n) { return n.type === "group" });
|
||||
|
||||
var historyEvent = {
|
||||
t:"ungroup",
|
||||
groups: [ ],
|
||||
dirty: RED.nodes.dirty()
|
||||
}
|
||||
RED.history.push(historyEvent);
|
||||
|
||||
|
||||
groups.forEach(function(g) {
|
||||
newSelection = newSelection.concat(ungroup(g))
|
||||
historyEvent.groups.push(g);
|
||||
})
|
||||
RED.history.push(historyEvent);
|
||||
RED.view.select({nodes:newSelection})
|
||||
RED.nodes.dirty(true);
|
||||
}
|
||||
}
|
||||
|
||||
function ungroup(g) {
|
||||
var nodes = [];
|
||||
var parentGroup = RED.nodes.group(g.g);
|
||||
g.nodes.forEach(function(n) {
|
||||
nodes.push(n);
|
||||
if (parentGroup) {
|
||||
// Move nodes to parent group
|
||||
n.g = parentGroup.id;
|
||||
parentGroup.nodes.push(n);
|
||||
parentGroup.dirty = true;
|
||||
n.dirty = true;
|
||||
} else {
|
||||
delete n.g;
|
||||
}
|
||||
if (n.type === 'group') {
|
||||
RED.events.emit("groups:change",n)
|
||||
} else {
|
||||
RED.events.emit("nodes:change",n)
|
||||
}
|
||||
})
|
||||
RED.nodes.removeGroup(g);
|
||||
return nodes;
|
||||
}
|
||||
|
||||
function mergeSelection() {
|
||||
if (RED.view.state() !== RED.state.DEFAULT) { return }
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
var nodes = [];
|
||||
|
||||
var historyEvent = {
|
||||
t: "multi",
|
||||
events: []
|
||||
}
|
||||
var ungroupHistoryEvent = {
|
||||
t: "ungroup",
|
||||
groups: []
|
||||
}
|
||||
|
||||
|
||||
var n;
|
||||
var parentGroup;
|
||||
// First pass, check they are all in the same parent
|
||||
// TODO: DRY mergeSelection,removeSelection,...
|
||||
for (var i=0; i<selection.nodes.length; i++) {
|
||||
n = selection.nodes[i];
|
||||
if (i === 0) {
|
||||
parentGroup = n.g;
|
||||
} else if (n.g !== parentGroup) {
|
||||
RED.notify(RED._("group.errors.cannotCreateDiffGroups"),"error");
|
||||
return;
|
||||
}
|
||||
}
|
||||
var existingGroup;
|
||||
|
||||
// Second pass, ungroup any groups in the selection and add their contents
|
||||
// to the selection
|
||||
for (var i=0; i<selection.nodes.length; i++) {
|
||||
n = selection.nodes[i];
|
||||
if (n.type === "group") {
|
||||
if (!existingGroup) {
|
||||
existingGroup = n;
|
||||
}
|
||||
ungroupHistoryEvent.groups.push(n);
|
||||
nodes = nodes.concat(ungroup(n));
|
||||
} else {
|
||||
nodes.push(n);
|
||||
}
|
||||
n.dirty = true;
|
||||
}
|
||||
if (ungroupHistoryEvent.groups.length > 0) {
|
||||
historyEvent.events.push(ungroupHistoryEvent);
|
||||
}
|
||||
// Finally, create the new group
|
||||
var group = createGroup(nodes);
|
||||
if (group) {
|
||||
if (existingGroup) {
|
||||
group.style = existingGroup.style;
|
||||
group.name = existingGroup.name;
|
||||
}
|
||||
RED.view.select({nodes:[group]})
|
||||
}
|
||||
historyEvent.events.push({
|
||||
t:"createGroup",
|
||||
groups: [ group ],
|
||||
dirty: RED.nodes.dirty()
|
||||
});
|
||||
RED.history.push(historyEvent);
|
||||
RED.nodes.dirty(true);
|
||||
}
|
||||
}
|
||||
|
||||
function removeSelection() {
|
||||
if (RED.view.state() !== RED.state.DEFAULT) { return }
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
var nodes = [];
|
||||
var n;
|
||||
var parentGroup = RED.nodes.group(selection.nodes[0].g);
|
||||
if (parentGroup) {
|
||||
try {
|
||||
removeFromGroup(parentGroup,selection.nodes,true);
|
||||
var historyEvent = {
|
||||
t: "removeFromGroup",
|
||||
dirty: RED.nodes.dirty(),
|
||||
group: parentGroup,
|
||||
nodes: selection.nodes
|
||||
}
|
||||
RED.history.push(historyEvent);
|
||||
RED.nodes.dirty(true);
|
||||
} catch(err) {
|
||||
RED.notify(err,"error");
|
||||
return;
|
||||
}
|
||||
}
|
||||
RED.view.select({nodes:selection.nodes})
|
||||
}
|
||||
}
|
||||
function createGroup(nodes) {
|
||||
if (nodes.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (nodes.filter(function(n) { return n.type === "subflow" }).length > 0) {
|
||||
RED.notify(RED._("group.errors.cannotAddSubflowPorts"),"error");
|
||||
return;
|
||||
}
|
||||
// nodes is an array
|
||||
// each node must be on the same tab (z)
|
||||
var group = {
|
||||
id: RED.nodes.id(),
|
||||
type: 'group',
|
||||
nodes: [],
|
||||
style: JSON.parse(JSON.stringify(defaultGroupStyle)),
|
||||
x: Number.POSITIVE_INFINITY,
|
||||
y: Number.POSITIVE_INFINITY,
|
||||
w: 0,
|
||||
h: 0,
|
||||
_def: RED.group.def
|
||||
}
|
||||
|
||||
group.z = nodes[0].z;
|
||||
RED.nodes.addGroup(group);
|
||||
|
||||
try {
|
||||
addToGroup(group,nodes);
|
||||
} catch(err) {
|
||||
RED.notify(err,"error");
|
||||
return;
|
||||
}
|
||||
return group;
|
||||
}
|
||||
function addToGroup(group,nodes) {
|
||||
if (!Array.isArray(nodes)) {
|
||||
nodes = [nodes];
|
||||
}
|
||||
var i,n,z;
|
||||
var g;
|
||||
// First pass - validate we can safely add these nodes to the group
|
||||
for (i=0;i<nodes.length;i++) {
|
||||
n = nodes[i]
|
||||
if (!n.z) {
|
||||
throw new Error("Cannot add node without a z property to a group")
|
||||
}
|
||||
if (!z) {
|
||||
z = n.z;
|
||||
} else if (z !== n.z) {
|
||||
throw new Error("Cannot add nooes with different z properties")
|
||||
}
|
||||
if (n.g) {
|
||||
// This is already in a group.
|
||||
// - check they are all in the same group
|
||||
if (!g) {
|
||||
if (i!==0) {
|
||||
// TODO: this might be ok when merging groups
|
||||
throw new Error(RED._("group.errors.cannotCreateDiffGroups"))
|
||||
}
|
||||
g = n.g
|
||||
}
|
||||
}
|
||||
if (g !== n.g) {
|
||||
throw new Error(RED._("group.errors.cannotCreateDiffGroups"))
|
||||
}
|
||||
}
|
||||
// The nodes are already in a group. The assumption is they should be
|
||||
// wrapped in the newly provided group, and that group added to in their
|
||||
// place to the existing containing group.
|
||||
if (g) {
|
||||
g = RED.nodes.group(g);
|
||||
g.nodes.push(group);
|
||||
g.dirty = true;
|
||||
group.g = g.id;
|
||||
}
|
||||
// Second pass - add them to the group
|
||||
for (i=0;i<nodes.length;i++) {
|
||||
n = nodes[i];
|
||||
if (n.type !== "subflow") {
|
||||
if (g && n.g === g.id) {
|
||||
var ni = g.nodes.indexOf(n);
|
||||
if (ni > -1) {
|
||||
g.nodes.splice(ni,1)
|
||||
}
|
||||
}
|
||||
n.g = group.id;
|
||||
n.dirty = true;
|
||||
group.nodes.push(n);
|
||||
group.x = Math.min(group.x,n.x-n.w/2-25-((n._def.button && n._def.align!=="right")?20:0));
|
||||
group.y = Math.min(group.y,n.y-n.h/2-25);
|
||||
group.w = Math.max(group.w,n.x+n.w/2+25+((n._def.button && n._def.align=="right")?20:0) - group.x);
|
||||
group.h = Math.max(group.h,n.y+n.h/2+25-group.y);
|
||||
if (n.type === 'group') {
|
||||
RED.events.emit("groups:change",n)
|
||||
} else {
|
||||
RED.events.emit("nodes:change",n)
|
||||
}
|
||||
}
|
||||
}
|
||||
if (g) {
|
||||
RED.events.emit("groups:change",group)
|
||||
}
|
||||
markDirty(group);
|
||||
}
|
||||
function removeFromGroup(group, nodes, reparent) {
|
||||
if (!Array.isArray(nodes)) {
|
||||
nodes = [nodes];
|
||||
}
|
||||
var n;
|
||||
// First pass, check they are all in the same parent
|
||||
// TODO: DRY mergeSelection,removeSelection,...
|
||||
for (var i=0; i<nodes.length; i++) {
|
||||
if (nodes[i].g !== group.id) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
var parentGroup = RED.nodes.group(group.g);
|
||||
for (var i=0; i<nodes.length; i++) {
|
||||
n = nodes[i];
|
||||
n.dirty = true;
|
||||
var index = group.nodes.indexOf(n);
|
||||
group.nodes.splice(index,1);
|
||||
if (reparent && group.g) {
|
||||
n.g = group.g
|
||||
parentGroup.nodes.push(n);
|
||||
} else {
|
||||
delete n.g;
|
||||
}
|
||||
if (n.type === 'group') {
|
||||
RED.events.emit("groups:change",n)
|
||||
} else {
|
||||
RED.events.emit("nodes:change",n)
|
||||
}
|
||||
}
|
||||
markDirty(group);
|
||||
}
|
||||
|
||||
function getNodes(group,recursive) {
|
||||
var nodes = [];
|
||||
group.nodes.forEach(function(n) {
|
||||
nodes.push(n);
|
||||
if (recursive && n.type === 'group') {
|
||||
nodes = nodes.concat(getNodes(n,recursive))
|
||||
}
|
||||
})
|
||||
return nodes;
|
||||
}
|
||||
|
||||
function groupContains(group,item) {
|
||||
if (item.g === group.id) {
|
||||
return true;
|
||||
}
|
||||
for (var i=0;i<group.nodes.length;i++) {
|
||||
if (group.nodes[i].type === "group") {
|
||||
if (groupContains(group.nodes[i],item)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
function getRootGroup(group) {
|
||||
if (!group.g) {
|
||||
return group;
|
||||
}
|
||||
return getRootGroup(RED.nodes.group(group.g))
|
||||
}
|
||||
|
||||
function createLayoutPicker(options) {
|
||||
|
||||
var container = $("<div>",{style:"display:inline-block"});
|
||||
var layoutHiddenInput = $("<input/>", { id: options.id, type: "hidden", value: options.value }).appendTo(container);
|
||||
|
||||
var layoutButton = $('<button type="button" class="red-ui-button red-ui-editor-node-appearance-button">').appendTo(container);
|
||||
$('<i class="fa fa-caret-down"></i>').appendTo(layoutButton);
|
||||
|
||||
var layoutDispContainer = $('<div>',{class:"red-ui-search-result-node"}).appendTo(layoutButton);
|
||||
var layoutDisp = $('<div>',{class:"red-ui-group-layout-picker-cell-text red-ui-group-layout-text-pos-"}).appendTo(layoutDispContainer);
|
||||
|
||||
var refreshDisplay = function() {
|
||||
var val = layoutHiddenInput.val();
|
||||
layoutDisp.removeClass().addClass("red-ui-group-layout-picker-cell-text red-ui-group-layout-text-pos-"+val)
|
||||
}
|
||||
layoutButton.on("click", function(e) {
|
||||
var picker = $("<div/>", {
|
||||
class: "red-ui-group-layout-picker"
|
||||
}).css({
|
||||
width: "126px"
|
||||
});
|
||||
|
||||
var row = null;
|
||||
|
||||
row = $("<div/>").appendTo(picker);
|
||||
var currentButton;
|
||||
for (var y=0;y<2;y++) { //red-ui-group-layout-text-pos
|
||||
var yComponent= "ns"[y];
|
||||
row = $("<div/>").appendTo(picker);
|
||||
for (var x=0;x<3;x++) {
|
||||
var xComponent = ["w","","e"][x];
|
||||
var val = yComponent+xComponent;
|
||||
var button = $("<button/>", { class:"red-ui-search-result-node red-ui-button","data-pos":val }).appendTo(row);
|
||||
button.on("click", function (e) {
|
||||
e.preventDefault();
|
||||
layoutHiddenInput.val($(this).data("pos"));
|
||||
layoutPanel.hide()
|
||||
refreshDisplay();
|
||||
});
|
||||
$('<div>',{class:"red-ui-group-layout-picker-cell-text red-ui-group-layout-text-pos-"+val}).appendTo(button);
|
||||
if (val === layoutHiddenInput.val()) {
|
||||
currentButton = button;
|
||||
}
|
||||
}
|
||||
}
|
||||
refreshDisplay();
|
||||
var layoutPanel = RED.popover.panel(picker);
|
||||
layoutPanel.show({
|
||||
target: layoutButton,
|
||||
onclose: function() {
|
||||
layoutButton.focus();
|
||||
}
|
||||
});
|
||||
if (currentButton) {
|
||||
currentButton.focus();
|
||||
}
|
||||
})
|
||||
|
||||
refreshDisplay();
|
||||
|
||||
return container;
|
||||
|
||||
}
|
||||
|
||||
function markDirty(group) {
|
||||
group.dirty = true;
|
||||
while(group) {
|
||||
group.dirty = true;
|
||||
group = RED.nodes.group(group.g);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
def: groupDef,
|
||||
init: init,
|
||||
createGroup: createGroup,
|
||||
ungroup: ungroup,
|
||||
addToGroup: addToGroup,
|
||||
removeFromGroup: removeFromGroup,
|
||||
getNodes: getNodes,
|
||||
contains: groupContains,
|
||||
markDirty: markDirty
|
||||
}
|
||||
})();
|
||||
@@ -17,7 +17,12 @@ RED.keyboard = (function() {
|
||||
|
||||
var isMac = /Mac/i.test(window.navigator.platform);
|
||||
|
||||
var handlersActive = true;
|
||||
|
||||
var handlers = {};
|
||||
|
||||
var knownShortcuts;
|
||||
|
||||
var partialState;
|
||||
|
||||
var keyMap = {
|
||||
@@ -32,6 +37,7 @@ RED.keyboard = (function() {
|
||||
"space": 32,
|
||||
";":186,
|
||||
"=":187,
|
||||
"+":187, // <- QWERTY specific
|
||||
",":188,
|
||||
"-":189,
|
||||
".":190,
|
||||
@@ -58,41 +64,90 @@ RED.keyboard = (function() {
|
||||
}
|
||||
|
||||
function migrateOldKeymap() {
|
||||
// pre-0.18
|
||||
if ('localStorage' in window && window['localStorage'] !== null) {
|
||||
var oldKeyMap = localStorage.getItem("keymap");
|
||||
if (oldKeyMap !== null) {
|
||||
localStorage.removeItem("keymap");
|
||||
var currentEditorSettings = RED.settings.get('editor') || {};
|
||||
currentEditorSettings.keymap = JSON.parse(oldKeyMap);
|
||||
RED.settings.set('editor',currentEditorSettings);
|
||||
RED.settings.set('editor.keymap',JSON.parse(oldKeyMap));
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function getUserKey(action) {
|
||||
return RED.settings.get('editor.keymap',{})[action]
|
||||
}
|
||||
|
||||
function mergeKeymaps(defaultKeymap, themeKeymap) {
|
||||
// defaultKeymap has format: { scope: { key: action , key: action }}
|
||||
// themeKeymap has format: {action: {scope,key}, action: {scope:key}}
|
||||
|
||||
|
||||
var mergedKeymap = {};
|
||||
for (var scope in defaultKeymap) {
|
||||
if (defaultKeymap.hasOwnProperty(scope)) {
|
||||
var keys = defaultKeymap[scope];
|
||||
for (var key in keys) {
|
||||
if (keys.hasOwnProperty(key)) {
|
||||
if (!mergedKeymap[keys[key]]) {
|
||||
mergedKeymap[keys[key]] = [{
|
||||
scope:scope,
|
||||
key:key,
|
||||
user:false
|
||||
}];
|
||||
} else {
|
||||
mergedKeymap[keys[key]].push({
|
||||
scope:scope,
|
||||
key:key,
|
||||
user:false
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var action in themeKeymap) {
|
||||
if (themeKeymap.hasOwnProperty(action)) {
|
||||
if (!themeKeymap[action].key) {
|
||||
// No key for this action - default is no keybinding
|
||||
delete mergedKeymap[action]
|
||||
} else {
|
||||
mergedKeymap[action] = [{
|
||||
scope: themeKeymap[action].scope || "*",
|
||||
key: [themeKeymap[action].key],
|
||||
user: false
|
||||
}]
|
||||
if (mergedKeymap[action][0].scope === "workspace") {
|
||||
mergedKeymap[action][0].scope = "red-ui-workspace";
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return mergedKeymap;
|
||||
}
|
||||
|
||||
function init() {
|
||||
// Migrate from pre-0.18
|
||||
migrateOldKeymap();
|
||||
|
||||
var currentEditorSettings = RED.settings.get('editor') || {};
|
||||
var userKeymap = currentEditorSettings.keymap || {};
|
||||
var userKeymap = RED.settings.get('editor.keymap', {});
|
||||
$.getJSON("red/keymap.json",function(defaultKeymap) {
|
||||
var keymap = mergeKeymaps(defaultKeymap, RED.settings.theme('keymap',{}));
|
||||
// keymap has the format: {action: [{scope,key},{scope,key}], action: [{scope:key}]}
|
||||
|
||||
$.getJSON("red/keymap.json",function(data) {
|
||||
for (var scope in data) {
|
||||
if (data.hasOwnProperty(scope)) {
|
||||
var keys = data[scope];
|
||||
for (var key in keys) {
|
||||
if (keys.hasOwnProperty(key)) {
|
||||
if (!userKeymap.hasOwnProperty(keys[key])) {
|
||||
addHandler(scope,key,keys[key],false);
|
||||
}
|
||||
defaultKeyMap[keys[key]] = {
|
||||
scope:scope,
|
||||
key:key,
|
||||
user:false
|
||||
};
|
||||
}
|
||||
var action;
|
||||
for (action in keymap) {
|
||||
if (keymap.hasOwnProperty(action)) {
|
||||
if (!userKeymap.hasOwnProperty(action)) {
|
||||
keymap[action].forEach(function(km) {
|
||||
addHandler(km.scope,km.key,action,false);
|
||||
});
|
||||
}
|
||||
defaultKeyMap[action] = keymap[action][0];
|
||||
}
|
||||
}
|
||||
|
||||
for (var action in userKeymap) {
|
||||
if (userKeymap.hasOwnProperty(action) && userKeymap[action]) {
|
||||
var obj = userKeymap[action];
|
||||
@@ -225,6 +280,9 @@ RED.keyboard = (function() {
|
||||
}
|
||||
}
|
||||
d3.select(window).on("keydown",function() {
|
||||
if (!handlersActive) {
|
||||
return;
|
||||
}
|
||||
if (metaKeyCodes[d3.event.keyCode]) {
|
||||
return;
|
||||
}
|
||||
@@ -250,6 +308,19 @@ RED.keyboard = (function() {
|
||||
var i=0;
|
||||
if (typeof key === 'string') {
|
||||
if (typeof cbdown === 'string') {
|
||||
if (!ondown && !defaultKeyMap.hasOwnProperty(cbdown)) {
|
||||
defaultKeyMap[cbdown] = {
|
||||
scope:scope,
|
||||
key:key,
|
||||
user:false
|
||||
}
|
||||
}
|
||||
if (!ondown) {
|
||||
var userAction = getUserKey(cbdown);
|
||||
if (userAction) {
|
||||
return;
|
||||
}
|
||||
}
|
||||
actionToKeyMap[cbdown] = {scope:scope,key:key};
|
||||
if (typeof ondown === 'boolean') {
|
||||
actionToKeyMap[cbdown].user = ondown;
|
||||
@@ -385,14 +456,21 @@ RED.keyboard = (function() {
|
||||
container.addClass('keyboard-shortcut-entry-expanded');
|
||||
|
||||
var keyInput = $('<input type="text">').attr('placeholder',RED._('keyboard.unassigned')).val(object.key||"").appendTo(key);
|
||||
keyInput.on("keyup",function(e) {
|
||||
if (e.keyCode === 13) {
|
||||
keyInput.on("change paste keyup",function(e) {
|
||||
if (e.keyCode === 13 && !$(this).hasClass("input-error")) {
|
||||
return endEditShortcut();
|
||||
}
|
||||
if (e.keyCode === 27) {
|
||||
return endEditShortcut(true);
|
||||
}
|
||||
var currentVal = $(this).val();
|
||||
currentVal = currentVal.trim();
|
||||
var valid = (currentVal === "" || RED.keyboard.validateKey(currentVal));
|
||||
if (valid && currentVal !== "") {
|
||||
valid = !knownShortcuts.has(scopeSelect.val()+":"+currentVal.toLowerCase());
|
||||
}
|
||||
$(this).toggleClass("input-error",!valid);
|
||||
okButton.attr("disabled",!valid);
|
||||
})
|
||||
|
||||
var scopeSelect = $('<select><option value="*" data-i18n="keyboard.global"></option><option value="red-ui-workspace" data-i18n="keyboard.workspace"></option></select>').appendTo(scope);
|
||||
@@ -401,6 +479,9 @@ RED.keyboard = (function() {
|
||||
object.scope = "red-ui-workspace";
|
||||
}
|
||||
scopeSelect.val(object.scope||'*');
|
||||
scopeSelect.on("change", function() {
|
||||
keyInput.trigger("change");
|
||||
})
|
||||
|
||||
var div = $('<div class="keyboard-shortcut-edit button-group-vertical"></div>').appendTo(scope);
|
||||
var okButton = $('<button class="red-ui-button red-ui-button-small"><i class="fa fa-check"></i></button>').appendTo(div);
|
||||
@@ -412,18 +493,16 @@ RED.keyboard = (function() {
|
||||
});
|
||||
revertButton.on("click", function(e) {
|
||||
e.stopPropagation();
|
||||
RED.keyboard.revertToDefault(object.id);
|
||||
container.empty();
|
||||
container.removeClass('keyboard-shortcut-entry-expanded');
|
||||
var shortcut = RED.keyboard.getShortcut(object.id);
|
||||
var userKeymap = RED.settings.get('keymap') || {};
|
||||
|
||||
var currentEditorSettings = RED.settings.get('editor') || {};
|
||||
var userKeymap = currentEditorSettings.keymap || {};
|
||||
var userKeymap = RED.settings.get('editor.keymap', {});
|
||||
userKeymap[object.id] = null;
|
||||
currentEditorSettings.keymap = userKeymap;
|
||||
RED.settings.set('editor',currentEditorSettings);
|
||||
RED.settings.set('editor.keymap',userKeymap);
|
||||
|
||||
RED.keyboard.revertToDefault(object.id);
|
||||
|
||||
var shortcut = RED.keyboard.getShortcut(object.id);
|
||||
var obj = {
|
||||
id:object.id,
|
||||
scope:shortcut?shortcut.scope:undefined,
|
||||
@@ -455,6 +534,7 @@ RED.keyboard = (function() {
|
||||
keyDiv.empty();
|
||||
scopeDiv.empty();
|
||||
if (object.key) {
|
||||
knownShortcuts.delete(object.scope+":"+object.key);
|
||||
RED.keyboard.remove(object.key,true);
|
||||
}
|
||||
container.find(".keyboard-shortcut-entry-text i").css("opacity",1);
|
||||
@@ -469,14 +549,17 @@ RED.keyboard = (function() {
|
||||
$("<span>").text(scope).appendTo(scopeDiv);
|
||||
object.key = key;
|
||||
object.scope = scope;
|
||||
knownShortcuts.add(object.scope+":"+object.key);
|
||||
RED.keyboard.add(object.scope,object.key,object.id,true);
|
||||
}
|
||||
|
||||
var currentEditorSettings = RED.settings.get('editor') || {};
|
||||
var userKeymap = currentEditorSettings.keymap || {};
|
||||
userKeymap[object.id] = RED.keyboard.getShortcut(object.id);
|
||||
currentEditorSettings.keymap = userKeymap;
|
||||
RED.settings.set('editor',currentEditorSettings);
|
||||
var userKeymap = RED.settings.get('editor.keymap', {});
|
||||
var shortcut = RED.keyboard.getShortcut(object.id);
|
||||
userKeymap[object.id] = {
|
||||
scope:shortcut.scope,
|
||||
key:shortcut.key
|
||||
}
|
||||
RED.settings.set('editor.keymap',userKeymap);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -524,12 +607,12 @@ RED.keyboard = (function() {
|
||||
var pane = $('<div id="red-ui-settings-tab-keyboard"></div>');
|
||||
|
||||
$('<div class="keyboard-shortcut-entry keyboard-shortcut-list-header">'+
|
||||
'<div class="keyboard-shortcut-entry-key keyboard-shortcut-entry-text"><input id="red-ui-settings-tab-keyboard-filter" type="text" data-i18n="[placeholder]keyboard.filterActions"></div>'+
|
||||
'<div class="keyboard-shortcut-entry-key keyboard-shortcut-entry-text"><input autocomplete="off" name="keyboard-filter" id="red-ui-settings-tab-keyboard-filter" type="text" data-i18n="[placeholder]keyboard.filterActions"></div>'+
|
||||
'<div class="keyboard-shortcut-entry-key" data-i18n="keyboard.shortcut"></div>'+
|
||||
'<div class="keyboard-shortcut-entry-scope" data-i18n="keyboard.scope"></div>'+
|
||||
'</div>').appendTo(pane);
|
||||
|
||||
pane.find("input").searchBox({
|
||||
pane.find("#red-ui-settings-tab-keyboard-filter").searchBox({
|
||||
delay: 100,
|
||||
change: function() {
|
||||
var filterValue = $(this).val().trim();
|
||||
@@ -564,12 +647,23 @@ RED.keyboard = (function() {
|
||||
var Bid = B.id.replace(/^.*:/,"").replace(/[ -]/g,"").toLowerCase();
|
||||
return Aid.localeCompare(Bid);
|
||||
});
|
||||
knownShortcuts = new Set();
|
||||
shortcuts.forEach(function(s) {
|
||||
if (s.key) {
|
||||
knownShortcuts.add(s.scope+":"+s.key);
|
||||
}
|
||||
shortcutList.editableList('addItem',s);
|
||||
});
|
||||
return pane;
|
||||
}
|
||||
|
||||
function enable() {
|
||||
handlersActive = true;
|
||||
}
|
||||
function disable() {
|
||||
handlersActive = false;
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
add: addHandler,
|
||||
@@ -577,9 +671,12 @@ RED.keyboard = (function() {
|
||||
getShortcut: function(actionName) {
|
||||
return actionToKeyMap[actionName];
|
||||
},
|
||||
getUserShortcut: getUserKey,
|
||||
revertToDefault: revertToDefault,
|
||||
formatKey: formatKey,
|
||||
validateKey: validateKey
|
||||
validateKey: validateKey,
|
||||
disable: disable,
|
||||
enable: enable
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
@@ -22,7 +22,7 @@ RED.library = (function() {
|
||||
|
||||
var _libraryLookup = '<div id="red-ui-library-dialog-load" class="hide">'+
|
||||
'<form class="form-horizontal">'+
|
||||
'<div style="height: 400px; position:relative; ">'+
|
||||
'<div class="red-ui-library-dialog-box" style="height: 400px; position:relative; ">'+
|
||||
'<div id="red-ui-library-dialog-load-panes">'+
|
||||
'<div class="red-ui-panel" id="red-ui-library-dialog-load-browser"></div>'+
|
||||
'<div class="red-ui-panel">'+
|
||||
@@ -41,7 +41,7 @@ RED.library = (function() {
|
||||
|
||||
var _librarySave = '<div id="red-ui-library-dialog-save" class="hide">'+
|
||||
'<form class="form-horizontal">'+
|
||||
'<div style="height: 400px; position:relative; ">'+
|
||||
'<div class="red-ui-library-dialog-box" style="height: 400px; position:relative; ">'+
|
||||
'<div id="red-ui-library-dialog-save-browser"></div>'+
|
||||
'<div class="form-row">'+
|
||||
'<label data-i18n="clipboard.export.exportAs"></label><input id="red-ui-library-dialog-save-filename" type="text">'+
|
||||
@@ -66,8 +66,10 @@ RED.library = (function() {
|
||||
var data = {};
|
||||
for (var i=0; i < activeLibrary.fields.length; i++) {
|
||||
var field = activeLibrary.fields[i];
|
||||
if (field == "name") {
|
||||
if (field === "name") {
|
||||
data.name = name;
|
||||
} else if (typeof(field) === 'object') {
|
||||
data[field.name] = field.get();
|
||||
} else {
|
||||
data[field] = $("#" + elementPrefix + field).val();
|
||||
}
|
||||
@@ -214,31 +216,7 @@ RED.library = (function() {
|
||||
{ id:'node-input-'+options.type+'-menu-open-library',
|
||||
label: RED._("library.openLibrary"),
|
||||
onselect: function() {
|
||||
activeLibrary = options;
|
||||
loadLibraryFolder("local",options.url, "", function(items) {
|
||||
var listing = [{
|
||||
library: "local",
|
||||
type: options.url,
|
||||
icon: 'fa fa-hdd-o',
|
||||
label: RED._("library.types.local"),
|
||||
path: "",
|
||||
expanded: true,
|
||||
writable: false,
|
||||
children: [{
|
||||
library: "local",
|
||||
type: options.url,
|
||||
icon: 'fa fa-cube',
|
||||
label: options.type,
|
||||
path: "",
|
||||
expanded: true,
|
||||
children: items
|
||||
}]
|
||||
}]
|
||||
loadLibraryBrowser.data(listing);
|
||||
setTimeout(function() {
|
||||
loadLibraryBrowser.select(listing[0].children[0]);
|
||||
},200);
|
||||
});
|
||||
|
||||
libraryEditor = ace.edit('red-ui-library-dialog-load-preview-text',{
|
||||
useWorker: false
|
||||
});
|
||||
@@ -254,6 +232,50 @@ RED.library = (function() {
|
||||
libraryEditor.renderer.$cursorLayer.element.style.opacity=0;
|
||||
libraryEditor.$blockScrolling = Infinity;
|
||||
|
||||
activeLibrary = options;
|
||||
var listing = [];
|
||||
var libraries = RED.settings.libraries || [];
|
||||
libraries.forEach(function(lib) {
|
||||
if (lib.types && lib.types.indexOf(options.url) === -1) {
|
||||
return;
|
||||
}
|
||||
listing.push({
|
||||
library: lib.id,
|
||||
type: options.url,
|
||||
icon: lib.icon || 'fa fa-hdd-o',
|
||||
label: RED._(lib.label||lib.id),
|
||||
path: "",
|
||||
expanded: true,
|
||||
writable: false,
|
||||
children: [{
|
||||
library: lib.id,
|
||||
type: options.url,
|
||||
icon: 'fa fa-cube',
|
||||
label: options.type,
|
||||
path: "",
|
||||
expanded: false,
|
||||
children: function(done, item) {
|
||||
loadLibraryFolder(lib.id, options.url, "", function(children) {
|
||||
item.children = children;
|
||||
done(children);
|
||||
})
|
||||
}
|
||||
}]
|
||||
})
|
||||
});
|
||||
loadLibraryBrowser.data(listing);
|
||||
setTimeout(function() {
|
||||
loadLibraryBrowser.select(listing[0].children[0]);
|
||||
},200);
|
||||
|
||||
|
||||
var dialogHeight = 400;
|
||||
var winHeight = $(window).height();
|
||||
if (winHeight < 570) {
|
||||
dialogHeight = 400 - (570 - winHeight);
|
||||
}
|
||||
$("#red-ui-library-dialog-load .red-ui-library-dialog-box").height(dialogHeight);
|
||||
|
||||
$( "#red-ui-library-dialog-load" ).dialog("option","title",RED._("library.typeLibrary", {type:options.type})).dialog( "open" );
|
||||
}
|
||||
},
|
||||
@@ -269,30 +291,49 @@ RED.library = (function() {
|
||||
}
|
||||
$("#red-ui-library-dialog-save-filename").attr("value",filename+"."+(options.ext||"txt"));
|
||||
|
||||
loadLibraryFolder("local",options.url, "", function(items) {
|
||||
var listing = [{
|
||||
library: "local",
|
||||
var listing = [];
|
||||
var libraries = RED.settings.libraries || [];
|
||||
libraries.forEach(function(lib) {
|
||||
if (lib.types && lib.types.indexOf(options.url) === -1) {
|
||||
return;
|
||||
}
|
||||
listing.push({
|
||||
library: lib.id,
|
||||
type: options.url,
|
||||
icon: 'fa fa-hdd-o',
|
||||
label: RED._("library.types.local"),
|
||||
icon: lib.icon || 'fa fa-hdd-o',
|
||||
label: RED._(lib.label||lib.id),
|
||||
path: "",
|
||||
expanded: true,
|
||||
writable: false,
|
||||
children: [{
|
||||
library: "local",
|
||||
library: lib.id,
|
||||
type: options.url,
|
||||
icon: 'fa fa-cube',
|
||||
label: options.type,
|
||||
path: "",
|
||||
expanded: true,
|
||||
children: items
|
||||
}]
|
||||
expanded: false,
|
||||
children: function(done, item) {
|
||||
loadLibraryFolder(lib.id, options.url, "", function(children) {
|
||||
item.children = children;
|
||||
done(children);
|
||||
})
|
||||
}
|
||||
}]
|
||||
})
|
||||
});
|
||||
saveLibraryBrowser.data(listing);
|
||||
setTimeout(function() {
|
||||
saveLibraryBrowser.select(listing[0].children[0]);
|
||||
},200);
|
||||
});
|
||||
|
||||
var dialogHeight = 400;
|
||||
var winHeight = $(window).height();
|
||||
if (winHeight < 570) {
|
||||
dialogHeight = 400 - (570 - winHeight);
|
||||
}
|
||||
$("#red-ui-library-dialog-save .red-ui-library-dialog-box").height(dialogHeight);
|
||||
|
||||
|
||||
$( "#red-ui-library-dialog-save" ).dialog( "open" );
|
||||
}
|
||||
}
|
||||
@@ -442,9 +483,235 @@ RED.library = (function() {
|
||||
}
|
||||
}
|
||||
|
||||
// var libraryPlugins = {};
|
||||
//
|
||||
// function showLibraryDetailsDialog(container, lib, done) {
|
||||
// var dialog = $('<div>').addClass("red-ui-projects-dialog-list-dialog").hide().appendTo(container);
|
||||
// $('<div>').addClass("red-ui-projects-dialog-list-dialog-header").text(lib?"Edit library source":"Add library source").appendTo(dialog);
|
||||
// var formRow = $('<div class="red-ui-settings-row"></div>').appendTo(dialog);
|
||||
// $('<label>').text("Type").appendTo(formRow);
|
||||
// var typeSelect = $('<select>').appendTo(formRow);
|
||||
// for (var type in libraryPlugins) {
|
||||
// if (libraryPlugins.hasOwnProperty(type)) {
|
||||
// $('<option>').attr('value',type).attr('selected',(lib && lib.type === type)?true:null).text(libraryPlugins[type].name).appendTo(typeSelect);
|
||||
// }
|
||||
// }
|
||||
// var dialogBody = $("<div>").addClass("red-ui-settings-section").appendTo(dialog);
|
||||
// var libraryFields = {};
|
||||
// var fieldsModified = {};
|
||||
// function validateFields() {
|
||||
// var validForm = true;
|
||||
// for (var p in libraryFields) {
|
||||
// if (libraryFields.hasOwnProperty(p)) {
|
||||
// var v = libraryFields[p].input.val().trim();
|
||||
// if (v === "") {
|
||||
// validForm = false;
|
||||
// if (libraryFields[p].modified) {
|
||||
// libraryFields[p].input.addClass("input-error");
|
||||
// }
|
||||
// } else {
|
||||
// libraryFields[p].input.removeClass("input-error");
|
||||
// }
|
||||
// }
|
||||
// }
|
||||
// okayButton.attr("disabled",validForm?null:"disabled");
|
||||
// }
|
||||
// typeSelect.on("change", function(evt) {
|
||||
// dialogBody.empty();
|
||||
// libraryFields = {};
|
||||
// fieldsModified = {};
|
||||
// var libDef = libraryPlugins[$(this).val()];
|
||||
// var defaultIcon = lib?lib.icon:(libDef.icon || "font-awesome/fa-image");
|
||||
// formRow = $('<div class="red-ui-settings-row"></div>').appendTo(dialogBody);
|
||||
// $('<label>').text(RED._("editor.settingIcon")).appendTo(formRow);
|
||||
// libraryFields['icon'] = {input: $('<input type="hidden">').val(defaultIcon) };
|
||||
// var iconButton = $('<button type="button" class="red-ui-button"></button>').appendTo(formRow);
|
||||
// iconButton.on("click", function(evt) {
|
||||
// evt.preventDefault();
|
||||
// var icon = libraryFields['icon'].input.val() || "";
|
||||
// var iconPath = (icon ? RED.utils.separateIconPath(icon) : {});
|
||||
// RED.editor.showIconPicker(iconButton, null, iconPath, true, function (newIcon) {
|
||||
// iconButton.empty();
|
||||
// var path = newIcon || "";
|
||||
// var newPath = RED.utils.separateIconPath(path);
|
||||
// if (newPath) {
|
||||
// $('<i class="fa"></i>').addClass(newPath.file).appendTo(iconButton);
|
||||
// }
|
||||
// libraryFields['icon'].input.val(path);
|
||||
// });
|
||||
// })
|
||||
// var newPath = RED.utils.separateIconPath(defaultIcon);
|
||||
// $('<i class="fa '+newPath.file+'"></i>').appendTo(iconButton);
|
||||
//
|
||||
// var libProps = libDef.defaults;
|
||||
// var libPropKeys = Object.keys(libProps).map(function(p) { return {id: p, def: libProps[p]}});
|
||||
// libPropKeys.unshift({id: "label", def: {value:""}})
|
||||
//
|
||||
// libPropKeys.forEach(function(prop) {
|
||||
// var p = prop.id;
|
||||
// var def = prop.def;
|
||||
// formRow = $('<div class="red-ui-settings-row"></div>').appendTo(dialogBody);
|
||||
// var label = libDef._(def.label || "label."+p,{defaultValue: p});
|
||||
// if (label === p) {
|
||||
// label = libDef._("editor:common.label."+p,{defaultValue:p});
|
||||
// }
|
||||
// $('<label>').text(label).appendTo(formRow);
|
||||
// libraryFields[p] = {
|
||||
// input: $('<input type="text">').val(lib?(lib[p]||lib.config[p]):def.value).appendTo(formRow),
|
||||
// modified: false
|
||||
// }
|
||||
// if (def.type === "password") {
|
||||
// libraryFields[p].input.attr("type","password").typedInput({type:"cred"})
|
||||
// }
|
||||
//
|
||||
// libraryFields[p].input.on("change paste keyup", function(evt) {
|
||||
// if (!evt.key || evt.key.length === 1) {
|
||||
// libraryFields[p].modified = true;
|
||||
// }
|
||||
// validateFields();
|
||||
// })
|
||||
// var desc = libDef._("desc."+p, {defaultValue: ""});
|
||||
// if (desc) {
|
||||
// $('<label class="red-ui-projects-edit-form-sublabel"></label>').append($('<small>').text(desc)).appendTo(formRow);
|
||||
// }
|
||||
// });
|
||||
// validateFields();
|
||||
// })
|
||||
//
|
||||
// var dialogButtons = $('<span class="button-row" style="position: relative; float: right; margin: 10px;"></span>').appendTo(dialog);
|
||||
// var cancelButton = $('<button class="red-ui-button"></button>').text(RED._("common.label.cancel")).appendTo(dialogButtons).on("click", function(evt) {
|
||||
// evt.preventDefault();
|
||||
// done(false);
|
||||
// })
|
||||
// var okayButton = $('<button class="red-ui-button"></button>').text(lib?"Update library":"Add library").appendTo(dialogButtons).on("click", function(evt) {
|
||||
// evt.preventDefault();
|
||||
// var item;
|
||||
// if (!lib) {
|
||||
// item = {
|
||||
// id: libraryFields['label'].input.val().trim().toLowerCase().replace(/( |[^a-z0-9])/g,"-"),
|
||||
// user: true,
|
||||
// type: typeSelect.val(),
|
||||
// config: {}
|
||||
// }
|
||||
// } else {
|
||||
// item = lib;
|
||||
// }
|
||||
//
|
||||
// item.label = libraryFields['label'].input.val().trim();
|
||||
// item.icon = libraryFields['icon'].input.val();
|
||||
//
|
||||
// for (var p in libraryFields) {
|
||||
// if (libraryFields.hasOwnProperty(p) && p !== 'label') {
|
||||
// item.config[p] = libraryFields[p].input.val().trim();
|
||||
// }
|
||||
// }
|
||||
// done(item);
|
||||
// });
|
||||
//
|
||||
// typeSelect.trigger("change");
|
||||
// if (lib) {
|
||||
// typeSelect.attr('disabled',true);
|
||||
// }
|
||||
//
|
||||
// dialog.slideDown(200);
|
||||
// }
|
||||
//
|
||||
// function createSettingsPane() {
|
||||
// var pane = $('<div id="red-ui-settings-tab-library-manager"></div>');
|
||||
// var toolbar = $('<div>').css("text-align","right").appendTo(pane);
|
||||
// var addButton = $('<button class="red-ui-button"><i class="fa fa-plus"></i> Add library</button>').appendTo(toolbar);
|
||||
//
|
||||
// var addingLibrary = false;
|
||||
//
|
||||
// var libraryList = $("<ol>").css({
|
||||
// position: "absolute",
|
||||
// left: "10px",
|
||||
// right: "10px",
|
||||
// top: "50px",
|
||||
// bottom: "10px"
|
||||
// }).appendTo(pane).editableList({
|
||||
// addButton: false,
|
||||
// addItem: function(row,index,itemData) {
|
||||
// if (itemData.id) {
|
||||
// row.addClass("red-ui-settings-tab-library-entry");
|
||||
// var iconCell = $("<span>").appendTo(row);
|
||||
// if (itemData.icon) {
|
||||
// var iconPath = RED.utils.separateIconPath(itemData.icon);
|
||||
// if (iconPath) {
|
||||
// $("<i>").addClass("fa "+iconPath.file).appendTo(iconCell);
|
||||
// }
|
||||
// }
|
||||
// $("<span>").text(RED._(itemData.label)).appendTo(row);
|
||||
// $("<span>").text(RED._(itemData.type)).appendTo(row);
|
||||
// $('<button class="red-ui-button red-ui-button-small"></button>').text(RED._("sidebar.project.projectSettings.edit")).appendTo(
|
||||
// $('<span>').appendTo(row)
|
||||
// ).on("click", function(evt) {
|
||||
// if (addingLibrary) {
|
||||
// return;
|
||||
// }
|
||||
// evt.preventDefault();
|
||||
// addingLibrary = true;
|
||||
// row.empty();
|
||||
// row.removeClass("red-ui-settings-tab-library-entry");
|
||||
// showLibraryDetailsDialog(row,itemData,function(newItem) {
|
||||
// var itemIndex = libraryList.editableList("indexOf", itemData);
|
||||
// libraryList.editableList("removeItem", itemData);
|
||||
// if (newItem) {
|
||||
// libraryList.editableList("insertItemAt", newItem, itemIndex);
|
||||
// } else {
|
||||
// libraryList.editableList("insertItemAt", itemData,itemIndex);
|
||||
// }
|
||||
// addingLibrary = false;
|
||||
//
|
||||
// })
|
||||
// })
|
||||
//
|
||||
// } else {
|
||||
// showLibraryDetailsDialog(row,null,function(newItem) {
|
||||
// libraryList.editableList("removeItem", itemData);
|
||||
// if (newItem) {
|
||||
// libraryList.editableList("addItem", newItem);
|
||||
// }
|
||||
// addingLibrary = false;
|
||||
// })
|
||||
//
|
||||
// }
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// addButton.on('click', function(evt) {
|
||||
// evt.preventDefault();
|
||||
// if (!addingLibrary) {
|
||||
// addingLibrary = true;
|
||||
// libraryList.editableList("addItem",{user:true});
|
||||
// }
|
||||
// })
|
||||
// var libraries = RED.settings.libraries || [];
|
||||
// libraries.forEach(function(library) {
|
||||
// if (library.user) {
|
||||
// libraryList.editableList("addItem",library)
|
||||
// }
|
||||
// })
|
||||
//
|
||||
// return pane;
|
||||
// }
|
||||
//
|
||||
//
|
||||
return {
|
||||
init: function() {
|
||||
|
||||
// RED.events.on("registry:plugin-added", function(id) {
|
||||
// var plugin = RED.plugins.getPlugin(id);
|
||||
// if (plugin.type === "node-red-library-source") {
|
||||
// libraryPlugins[id] = plugin;
|
||||
// }
|
||||
// });
|
||||
//
|
||||
// RED.userSettings.add({
|
||||
// id:'library-manager',
|
||||
// title: "NLS: Libraries",
|
||||
// get: createSettingsPane,
|
||||
// close: function() {}
|
||||
// });
|
||||
$(_librarySave).appendTo("#red-ui-editor").i18n();
|
||||
$(_libraryLookup).appendTo("#red-ui-editor").i18n();
|
||||
|
||||
@@ -454,6 +721,8 @@ RED.library = (function() {
|
||||
autoOpen: false,
|
||||
width: 800,
|
||||
resizable: false,
|
||||
open: function( event, ui ) { RED.keyboard.disable() },
|
||||
close: function( event, ui ) { RED.keyboard.enable() },
|
||||
classes: {
|
||||
"ui-dialog": "red-ui-editor-dialog",
|
||||
"ui-dialog-titlebar-close": "hide",
|
||||
@@ -523,8 +792,14 @@ RED.library = (function() {
|
||||
var elementPrefix = activeLibrary.elementPrefix || "node-input-";
|
||||
for (var i = 0; i < activeLibrary.fields.length; i++) {
|
||||
var field = activeLibrary.fields[i];
|
||||
if (typeof(field) === 'object') {
|
||||
var val = selectedLibraryItem[field.name];
|
||||
field.set(val);
|
||||
}
|
||||
else {
|
||||
$("#"+elementPrefix+field).val(selectedLibraryItem[field]);
|
||||
}
|
||||
}
|
||||
activeLibrary.editor.setValue(libraryEditor.getValue(), -1);
|
||||
}
|
||||
$( this ).dialog( "close" );
|
||||
@@ -532,9 +807,11 @@ RED.library = (function() {
|
||||
}
|
||||
],
|
||||
open: function(e) {
|
||||
RED.keyboard.disable();
|
||||
$(this).parent().find(".ui-dialog-titlebar-close").hide();
|
||||
},
|
||||
close: function(e) {
|
||||
RED.keyboard.enable();
|
||||
if (libraryEditor) {
|
||||
libraryEditor.destroy();
|
||||
libraryEditor = null;
|
||||
|
||||
@@ -31,15 +31,53 @@ RED.palette.editor = (function() {
|
||||
var eventTimers = {};
|
||||
var activeFilter = "";
|
||||
|
||||
function semVerCompare(A,B) {
|
||||
var aParts = A.split(".").map(function(m) { return parseInt(m);});
|
||||
var bParts = B.split(".").map(function(m) { return parseInt(m);});
|
||||
for (var i=0;i<3;i++) {
|
||||
var j = aParts[i]-bParts[i];
|
||||
if (j<0) { return -1 }
|
||||
if (j>0) { return 1 }
|
||||
var semverre = /^(\d+)(\.(\d+))?(\.(\d+))?(-([0-9A-Za-z-]+))?(\.([0-9A-Za-z-.]+))?$/;
|
||||
var NUMBERS_ONLY = /^\d+$/;
|
||||
|
||||
function SemVerPart(part) {
|
||||
this.number = 0;
|
||||
this.text = part;
|
||||
if ( NUMBERS_ONLY.test(part)){
|
||||
this.number = parseInt(part);
|
||||
this.type = "N";
|
||||
} else {
|
||||
this.type = part == undefined || part.length < 1 ? "E" : "T";
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
SemVerPart.prototype.compare = function(other) {
|
||||
var types = this.type + other.type;
|
||||
switch ( types ) {
|
||||
case "EE": return 0;
|
||||
case "NT":
|
||||
case "TE":
|
||||
case "EN": return -1;
|
||||
case "NN": return this.number - other.number;
|
||||
case "TT": return this.text.localeCompare( other.text );
|
||||
case "ET":
|
||||
case "TN":
|
||||
case "NE": return 1;
|
||||
}
|
||||
};
|
||||
|
||||
function SemVer(ver) {
|
||||
var groups = ver.match( semverre );
|
||||
this.parts = [ new SemVerPart( groups[1] ), new SemVerPart( groups[3] ), new SemVerPart( groups[5] ), new SemVerPart( groups[7] ), new SemVerPart( groups[9] ) ];
|
||||
}
|
||||
|
||||
SemVer.prototype.compare = function(other) {
|
||||
var result = 0;
|
||||
for ( var i = 0, n = this.parts.length; result == 0 && i < n; i++ ) {
|
||||
result = this.parts[ i ].compare( other.parts[ i ] );
|
||||
}
|
||||
return result;
|
||||
};
|
||||
|
||||
function semVerCompare(ver1, ver2) {
|
||||
var semver1 = new SemVer(ver1);
|
||||
var semver2 = new SemVer(ver2);
|
||||
var result = semver1.compare(semver2);
|
||||
return result;
|
||||
}
|
||||
|
||||
function delayCallback(start,callback) {
|
||||
@@ -75,13 +113,16 @@ RED.palette.editor = (function() {
|
||||
});
|
||||
})
|
||||
}
|
||||
function installNodeModule(id,version,callback) {
|
||||
function installNodeModule(id,version,url,callback) {
|
||||
var requestBody = {
|
||||
module: id
|
||||
};
|
||||
if (version) {
|
||||
requestBody.version = version;
|
||||
}
|
||||
if (url) {
|
||||
requestBody.url = url;
|
||||
}
|
||||
$.ajax({
|
||||
url:"nodes",
|
||||
type: "POST",
|
||||
@@ -220,7 +261,11 @@ RED.palette.editor = (function() {
|
||||
var setElements = nodeEntry.sets[setName];
|
||||
if (set.err) {
|
||||
errorCount++;
|
||||
$("<li>").text(set.err).appendTo(nodeEntry.errorList);
|
||||
var errMessage = set.err;
|
||||
if (set.err.message) {
|
||||
errMessage = set.err.message;
|
||||
}
|
||||
$("<li>").text(errMessage).appendTo(nodeEntry.errorList);
|
||||
}
|
||||
if (set.enabled) {
|
||||
activeTypeCount += set.types.length;
|
||||
@@ -322,7 +367,9 @@ RED.palette.editor = (function() {
|
||||
catalogueLoadStatus.push(err||v);
|
||||
if (!err) {
|
||||
if (v.modules) {
|
||||
v.modules.forEach(function(m) {
|
||||
var a = false;
|
||||
v.modules = v.modules.filter(function(m) {
|
||||
if (RED.utils.checkModuleAllowed(m.id,m.version,installAllowList,installDenyList)) {
|
||||
loadedIndex[m.id] = m;
|
||||
m.index = [m.id];
|
||||
if (m.keywords) {
|
||||
@@ -337,6 +384,9 @@ RED.palette.editor = (function() {
|
||||
m.timestamp = 0;
|
||||
}
|
||||
m.index = m.index.join(",").toLowerCase();
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
})
|
||||
loadedList = loadedList.concat(v.modules);
|
||||
}
|
||||
@@ -381,6 +431,7 @@ RED.palette.editor = (function() {
|
||||
handleCatalogResponse(null,catalog,index,v);
|
||||
refreshNodeModuleList();
|
||||
}).fail(function(jqxhr, textStatus, error) {
|
||||
console.warn("Error loading catalog",catalog,":",error);
|
||||
handleCatalogResponse(jqxhr,catalog,index);
|
||||
}).always(function() {
|
||||
handled++;
|
||||
@@ -429,11 +480,22 @@ RED.palette.editor = (function() {
|
||||
return -1 * (A.info.timestamp-B.info.timestamp);
|
||||
}
|
||||
|
||||
var installAllowList = ['*'];
|
||||
var installDenyList = [];
|
||||
|
||||
function init() {
|
||||
if (RED.settings.theme('palette.editable') === false) {
|
||||
if (RED.settings.get('externalModules.palette.allowInstall', true) === false) {
|
||||
return;
|
||||
}
|
||||
var settingsAllowList = RED.settings.get("externalModules.palette.allowList")
|
||||
var settingsDenyList = RED.settings.get("externalModules.palette.denyList")
|
||||
if (settingsAllowList || settingsDenyList) {
|
||||
installAllowList = settingsAllowList;
|
||||
installDenyList = settingsDenyList
|
||||
}
|
||||
installAllowList = RED.utils.parseModuleList(installAllowList);
|
||||
installDenyList = RED.utils.parseModuleList(installDenyList);
|
||||
|
||||
createSettingsPane();
|
||||
|
||||
RED.userSettings.add({
|
||||
@@ -534,8 +596,6 @@ RED.palette.editor = (function() {
|
||||
return settingsPane;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function createSettingsPane() {
|
||||
settingsPane = $('<div id="red-ui-settings-tab-palette"></div>');
|
||||
var content = $('<div id="red-ui-palette-editor">'+
|
||||
@@ -566,7 +626,11 @@ RED.palette.editor = (function() {
|
||||
minimumActiveTabWidth: 110
|
||||
});
|
||||
|
||||
createNodeTab(content);
|
||||
createInstallTab(content);
|
||||
}
|
||||
|
||||
function createNodeTab(content) {
|
||||
var modulesTab = $('<div>',{class:"red-ui-palette-editor-tab"}).appendTo(content);
|
||||
|
||||
editorTabs.addTab({
|
||||
@@ -622,7 +686,7 @@ RED.palette.editor = (function() {
|
||||
if ($(this).hasClass('disabled')) {
|
||||
return;
|
||||
}
|
||||
update(entry,loadedIndex[entry.name].version,container,function(err){});
|
||||
update(entry,loadedIndex[entry.name].version,loadedIndex[entry.name].pkg_url,container,function(err){});
|
||||
})
|
||||
|
||||
|
||||
@@ -718,9 +782,9 @@ RED.palette.editor = (function() {
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
function createInstallTab(content) {
|
||||
var installTab = $('<div>',{class:"red-ui-palette-editor-tab hide"}).appendTo(content);
|
||||
|
||||
editorTabs.addTab({
|
||||
@@ -753,7 +817,6 @@ RED.palette.editor = (function() {
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$('<span>').text(RED._("palette.editor.sort")+' ').appendTo(toolBar);
|
||||
var sortGroup = $('<span class="button-group"></span>').appendTo(toolBar);
|
||||
var sortRelevance = $('<a href="#" class="red-ui-palette-editor-install-sort-option red-ui-sidebar-header-button-toggle selected"><i class="fa fa-sort-amount-desc"></i></a>').appendTo(sortGroup);
|
||||
@@ -787,8 +850,9 @@ RED.palette.editor = (function() {
|
||||
loadedIndex = {};
|
||||
initInstallTab();
|
||||
})
|
||||
RED.popover.tooltip(refreshButton,RED._("palette.editor.refresh"));
|
||||
|
||||
packageList = $('<ol>',{style:"position: absolute;top: 78px;bottom: 0;left: 0;right: 0px;"}).appendTo(installTab).editableList({
|
||||
packageList = $('<ol>',{style:"position: absolute;top: 79px;bottom: 0;left: 0;right: 0px;"}).appendTo(installTab).editableList({
|
||||
addButton: false,
|
||||
scrollOnAdd: false,
|
||||
addItem: function(container,i,object) {
|
||||
@@ -870,10 +934,89 @@ RED.palette.editor = (function() {
|
||||
}
|
||||
});
|
||||
|
||||
if (RED.settings.get('externalModules.palette.allowUpload', true) !== false) {
|
||||
var uploadSpan = $('<span class="button-group">').prependTo(toolBar);
|
||||
var uploadButton = $('<button type="button" class="red-ui-sidebar-header-button red-ui-palette-editor-upload-button"><label><i class="fa fa-upload"></i><form id="red-ui-palette-editor-upload-form" enctype="multipart/form-data"><input name="tarball" type="file" accept=".tgz"></label></button>').appendTo(uploadSpan);
|
||||
|
||||
var uploadInput = uploadButton.find('input[type="file"]');
|
||||
uploadInput.on("change", function(evt) {
|
||||
if (this.files.length > 0) {
|
||||
uploadFilenameLabel.text(this.files[0].name)
|
||||
uploadToolbar.slideDown(200);
|
||||
}
|
||||
})
|
||||
|
||||
var uploadToolbar = $('<div class="red-ui-palette-editor-upload"></div>').appendTo(installTab);
|
||||
var uploadForm = $('<div>').appendTo(uploadToolbar);
|
||||
var uploadFilename = $('<div class="placeholder-input"><i class="fa fa-upload"></i> </div>').appendTo(uploadForm);
|
||||
var uploadFilenameLabel = $('<span></span>').appendTo(uploadFilename);
|
||||
var uploadButtons = $('<div class="red-ui-palette-editor-upload-buttons"></div>').appendTo(uploadForm);
|
||||
$('<button class="editor-button"></button>').text(RED._("common.label.cancel")).appendTo(uploadButtons).on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
uploadToolbar.slideUp(200);
|
||||
uploadInput.val("");
|
||||
});
|
||||
$('<button class="editor-button primary"></button>').text(RED._("common.label.upload")).appendTo(uploadButtons).on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
|
||||
var spinner = RED.utils.addSpinnerOverlay(uploadToolbar, true);
|
||||
var buttonRow = $('<div style="position: relative;bottom: calc(50% + 17px); padding-right: 10px;text-align: right;"></div>').appendTo(spinner);
|
||||
$('<button class="red-ui-button"></button>').text(RED._("eventLog.view")).appendTo(buttonRow).on("click", function(evt) {
|
||||
evt.preventDefault();
|
||||
RED.actions.invoke("core:show-event-log");
|
||||
});
|
||||
RED.eventLog.startEvent(RED._("palette.editor.confirm.button.install")+" : "+uploadInput[0].files[0].name);
|
||||
|
||||
var data = new FormData();
|
||||
data.append("tarball",uploadInput[0].files[0]);
|
||||
var filename = uploadInput[0].files[0].name;
|
||||
$.ajax({
|
||||
url: 'nodes',
|
||||
data: data,
|
||||
cache: false,
|
||||
contentType: false,
|
||||
processData: false,
|
||||
method: 'POST',
|
||||
}).always(function(data,textStatus,xhr) {
|
||||
spinner.remove();
|
||||
uploadInput.val("");
|
||||
uploadToolbar.slideUp(200);
|
||||
}).fail(function(xhr,textStatus,err) {
|
||||
var message = textStatus;
|
||||
if (xhr.responseJSON) {
|
||||
message = xhr.responseJSON.message;
|
||||
}
|
||||
var notification = RED.notify(RED._('palette.editor.errors.installFailed',{module: filename,message:message}),{
|
||||
type: 'error',
|
||||
modal: true,
|
||||
fixed: true,
|
||||
buttons: [
|
||||
{
|
||||
text: RED._("common.label.close"),
|
||||
click: function() {
|
||||
notification.close();
|
||||
}
|
||||
},{
|
||||
text: RED._("eventLog.view"),
|
||||
click: function() {
|
||||
notification.close();
|
||||
RED.actions.invoke("core:show-event-log");
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
uploadInput.val("");
|
||||
uploadToolbar.slideUp(200);
|
||||
})
|
||||
})
|
||||
RED.popover.tooltip(uploadButton,RED._("palette.editor.upload"));
|
||||
}
|
||||
|
||||
$('<div id="red-ui-palette-module-install-shade" class="red-ui-palette-module-shade hide"><div class="red-ui-palette-module-shade-status"></div><img src="red/images/spin.svg" class="red-ui-palette-spinner"/></div>').appendTo(installTab);
|
||||
}
|
||||
function update(entry,version,container,done) {
|
||||
if (RED.settings.theme('palette.editable') === false) {
|
||||
|
||||
function update(entry,version,url,container,done) {
|
||||
if (RED.settings.get('externalModules.palette.allowInstall', true) === false) {
|
||||
done(new Error('Palette not editable'));
|
||||
return;
|
||||
}
|
||||
@@ -898,7 +1041,7 @@ RED.palette.editor = (function() {
|
||||
RED.actions.invoke("core:show-event-log");
|
||||
});
|
||||
RED.eventLog.startEvent(RED._("palette.editor.confirm.button.install")+" : "+entry.name+" "+version);
|
||||
installNodeModule(entry.name,version,function(xhr) {
|
||||
installNodeModule(entry.name,version,url,function(xhr) {
|
||||
spinner.remove();
|
||||
if (xhr) {
|
||||
if (xhr.responseJSON) {
|
||||
@@ -932,7 +1075,7 @@ RED.palette.editor = (function() {
|
||||
})
|
||||
}
|
||||
function remove(entry,container,done) {
|
||||
if (RED.settings.theme('palette.editable') === false) {
|
||||
if (RED.settings.get('externalModules.palette.allowInstall', true) === false) {
|
||||
done(new Error('Palette not editable'));
|
||||
return;
|
||||
}
|
||||
@@ -989,7 +1132,7 @@ RED.palette.editor = (function() {
|
||||
})
|
||||
}
|
||||
function install(entry,container,done) {
|
||||
if (RED.settings.theme('palette.editable') === false) {
|
||||
if (RED.settings.get('externalModules.palette.allowInstall', true) === false) {
|
||||
done(new Error('Palette not editable'));
|
||||
return;
|
||||
}
|
||||
@@ -1023,7 +1166,7 @@ RED.palette.editor = (function() {
|
||||
RED.actions.invoke("core:show-event-log");
|
||||
});
|
||||
RED.eventLog.startEvent(RED._("palette.editor.confirm.button.install")+" : "+entry.id+" "+entry.version);
|
||||
installNodeModule(entry.id,entry.version,function(xhr) {
|
||||
installNodeModule(entry.id,entry.version,entry.pkg_url,function(xhr) {
|
||||
spinner.remove();
|
||||
if (xhr) {
|
||||
if (xhr.responseJSON) {
|
||||
|
||||
@@ -92,24 +92,50 @@ RED.palette = (function() {
|
||||
var lineHeight = 20;
|
||||
var portHeight = 10;
|
||||
|
||||
el.attr("data-palette-label",label);
|
||||
|
||||
label = RED.utils.sanitize(label);
|
||||
|
||||
var words = label.split(/[ -]/);
|
||||
|
||||
var words = label.split(/([ -]|\\n )/);
|
||||
|
||||
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);
|
||||
if (newWidth < nodeWidth) {
|
||||
currentLine += " "+words[i];
|
||||
currentLineWidth = newWidth;
|
||||
} else {
|
||||
var currentLine = "";
|
||||
for (var i=0;i<words.length;i++) {
|
||||
var word = words[i];
|
||||
if (word === "\\n ") {
|
||||
displayLines.push(currentLine);
|
||||
currentLine = words[i];
|
||||
currentLineWidth = RED.view.calculateTextWidth(currentLine, "red-ui-palette-label", 0);
|
||||
currentLine = "";
|
||||
continue;
|
||||
}
|
||||
var sep = (i == 0) ? "" : " ";
|
||||
var newWidth = RED.view.calculateTextWidth(currentLine+sep+word, "red-ui-palette-label");
|
||||
if (newWidth < nodeWidth) {
|
||||
currentLine += sep +word;
|
||||
} else {
|
||||
if (i > 0) {
|
||||
displayLines.push(currentLine);
|
||||
}
|
||||
while (true) {
|
||||
var wordWidth = RED.view.calculateTextWidth(word, "red-ui-palette-label");
|
||||
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");
|
||||
if (width < nodeWidth) {
|
||||
displayLines.push(s);
|
||||
word = word.substring(j);
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
else {
|
||||
currentLine = word;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
displayLines.push(currentLine);
|
||||
@@ -126,7 +152,7 @@ RED.palette = (function() {
|
||||
var popOverContent;
|
||||
try {
|
||||
var l = "<p><b>"+RED.text.bidi.enforceTextDirectionWithUCC(label)+"</b></p>";
|
||||
popOverContent = $('<div></div>').append($(l+(info?info:$("script[data-help-name='"+type+"']").html()||"<p>"+RED._("palette.noInfo")+"</p>").trim())
|
||||
popOverContent = $('<div></div>').append($(l+(info?info:RED.nodes.getNodeHelp(type)||"<p>"+RED._("palette.noInfo")+"</p>").trim())
|
||||
.filter(function(n) {
|
||||
return (this.nodeType == 1 && this.nodeName == "P") || (this.nodeType == 3 && this.textContent.trim().length > 0)
|
||||
}).slice(0,2));
|
||||
@@ -144,6 +170,16 @@ RED.palette = (function() {
|
||||
metaData = typeInfo.set.module+" : ";
|
||||
}
|
||||
metaData += type;
|
||||
|
||||
if (/^subflow:/.test(type)) {
|
||||
$('<button type="button" onclick="RED.workspaces.show(\''+type.substring(8).replace(/'/g,"\\'")+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-pencil"></i></button>').appendTo(popOverContent)
|
||||
}
|
||||
|
||||
var safeType = type.replace(/'/g,"\\'");
|
||||
|
||||
$('<button type="button" onclick="RED.search.show(\'type:'+safeType+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-search"></i></button>').appendTo(popOverContent)
|
||||
$('<button type="button" onclick="RED.sidebar.help.show(\''+safeType+'\'); return false;" class="red-ui-button red-ui-button-small" style="float: right; margin-left: 5px;"><i class="fa fa-book"></i></button>').appendTo(popOverContent)
|
||||
|
||||
$('<p>',{style:"font-size: 0.8em"}).text(metaData).appendTo(popOverContent);
|
||||
}
|
||||
} catch(err) {
|
||||
@@ -160,8 +196,12 @@ RED.palette = (function() {
|
||||
function setIcon(element,sf) {
|
||||
var icon_url = RED.utils.getNodeIcon(sf._def);
|
||||
var iconContainer = element.find(".red-ui-palette-icon-container");
|
||||
var currentIcon = iconContainer.attr("data-palette-icon");
|
||||
if (currentIcon !== icon_url) {
|
||||
iconContainer.attr("data-palette-icon", icon_url);
|
||||
RED.utils.createIconElement(icon_url, iconContainer, true);
|
||||
}
|
||||
}
|
||||
|
||||
function getPaletteNode(type) {
|
||||
return $(".red-ui-palette-node[data-palette-type='"+type+"']");
|
||||
@@ -194,17 +234,16 @@ RED.palette = (function() {
|
||||
}
|
||||
|
||||
$('<div/>', {
|
||||
class: "red-ui-palette-label"
|
||||
+ (((!def.align && def.inputs !== 0 && def.outputs === 0) || "right" === def.align) ? " red-ui-palette-label-right" : "")
|
||||
class: "red-ui-palette-label"+(((!def.align && def.inputs !== 0 && def.outputs === 0) || "right" === def.align) ? " red-ui-palette-label-right" : "")
|
||||
}).appendTo(d);
|
||||
|
||||
|
||||
if (def.icon) {
|
||||
var icon_url = RED.utils.getNodeIcon(def);
|
||||
var iconContainer = $('<div/>', {
|
||||
class: "red-ui-palette-icon-container"
|
||||
+ (((!def.align && def.inputs !== 0 && def.outputs === 0) || "right" === def.align) ? " red-ui-palette-icon-container-right" : "")
|
||||
class: "red-ui-palette-icon-container"+(((!def.align && def.inputs !== 0 && def.outputs === 0) || "right" === def.align) ? " red-ui-palette-icon-container-right" : "")
|
||||
}).appendTo(d);
|
||||
iconContainer.attr("data-palette-icon", icon_url);
|
||||
RED.utils.createIconElement(icon_url, iconContainer, true);
|
||||
}
|
||||
|
||||
@@ -231,6 +270,7 @@ RED.palette = (function() {
|
||||
var popover = RED.popover.create({
|
||||
target:d,
|
||||
trigger: "hover",
|
||||
interactive: true,
|
||||
width: "300px",
|
||||
content: "hi",
|
||||
delay: { show: 750, hide: 50 }
|
||||
@@ -238,33 +278,15 @@ RED.palette = (function() {
|
||||
|
||||
d.data('popover',popover);
|
||||
|
||||
// $(d).popover({
|
||||
// title:d.type,
|
||||
// placement:"right",
|
||||
// trigger: "hover",
|
||||
// delay: { show: 750, hide: 50 },
|
||||
// html: true,
|
||||
// container:'body'
|
||||
// });
|
||||
d.on("click", function() {
|
||||
RED.view.focus();
|
||||
var helpText;
|
||||
if (nt.indexOf("subflow:") === 0) {
|
||||
helpText = marked(RED.nodes.subflow(nt.substring(8)).info||"")||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
|
||||
} else {
|
||||
helpText = $("script[data-help-name='"+d.attr("data-palette-type")+"']").html()||('<span class="red-ui-help-info-none">'+RED._("sidebar.info.none")+'</span>');
|
||||
}
|
||||
// Don't look too closely. RED.sidebar.info.set will set the 'Description'
|
||||
// section of the sidebar. Pass in the title of the Help section so it looks
|
||||
// right.
|
||||
RED.sidebar.info.set(helpText,RED._("sidebar.info.nodeHelp"));
|
||||
});
|
||||
var chart = $("#red-ui-workspace-chart");
|
||||
var chartSVG = $("#red-ui-workspace-chart>svg").get(0);
|
||||
var activeSpliceLink;
|
||||
var mouseX;
|
||||
var mouseY;
|
||||
var spliceTimer;
|
||||
var groupTimer;
|
||||
var activeGroup;
|
||||
var hoverGroup;
|
||||
var paletteWidth;
|
||||
var paletteTop;
|
||||
$(d).draggable({
|
||||
@@ -276,15 +298,53 @@ RED.palette = (function() {
|
||||
start: function() {
|
||||
paletteWidth = $("#red-ui-palette").width();
|
||||
paletteTop = $("#red-ui-palette").parent().position().top + $("#red-ui-palette-container").position().top;
|
||||
hoverGroup = null;
|
||||
activeGroup = RED.view.getActiveGroup();
|
||||
if (activeGroup) {
|
||||
document.getElementById("group_select_"+activeGroup.id).classList.add("red-ui-flow-group-active-hovered");
|
||||
}
|
||||
RED.view.focus();
|
||||
},
|
||||
stop: function() { d3.select('.red-ui-flow-link-splice').classed('red-ui-flow-link-splice',false); if (spliceTimer) { clearTimeout(spliceTimer); spliceTimer = null;}},
|
||||
stop: function() {
|
||||
d3.select('.red-ui-flow-link-splice').classed('red-ui-flow-link-splice',false);
|
||||
if (hoverGroup) {
|
||||
document.getElementById("group_select_"+hoverGroup.id).classList.remove("red-ui-flow-group-hovered");
|
||||
}
|
||||
if (activeGroup) {
|
||||
document.getElementById("group_select_"+activeGroup.id).classList.remove("red-ui-flow-group-active-hovered");
|
||||
}
|
||||
if (spliceTimer) { clearTimeout(spliceTimer); spliceTimer = null; }
|
||||
if (groupTimer) { clearTimeout(groupTimer); groupTimer = null; }
|
||||
},
|
||||
drag: function(e,ui) {
|
||||
ui.originalPosition.left = $('#' + e.target.id).offset().left;
|
||||
|
||||
if (def.inputs > 0 && def.outputs > 0) {
|
||||
var paletteNode = getPaletteNode(nt);
|
||||
ui.originalPosition.left = paletteNode.offset().left;
|
||||
mouseX = ui.position.left - paletteWidth + (ui.helper.width()/2) + chart.scrollLeft();
|
||||
mouseY = ui.position.top - paletteTop + (ui.helper.height()/2) + chart.scrollTop();
|
||||
if (!groupTimer) {
|
||||
groupTimer = setTimeout(function() {
|
||||
mouseX /= RED.view.scale();
|
||||
mouseY /= RED.view.scale();
|
||||
var group = RED.view.getGroupAtPoint(mouseX,mouseY);
|
||||
if (group !== hoverGroup) {
|
||||
if (hoverGroup) {
|
||||
document.getElementById("group_select_"+hoverGroup.id).classList.remove("red-ui-flow-group-hovered");
|
||||
}
|
||||
if (group) {
|
||||
document.getElementById("group_select_"+group.id).classList.add("red-ui-flow-group-hovered");
|
||||
}
|
||||
hoverGroup = group;
|
||||
if (hoverGroup) {
|
||||
$(ui.helper).data('group',hoverGroup);
|
||||
} else {
|
||||
$(ui.helper).removeData('group');
|
||||
}
|
||||
}
|
||||
groupTimer = null;
|
||||
|
||||
},200)
|
||||
}
|
||||
if (def.inputs > 0 && def.outputs > 0) {
|
||||
if (!spliceTimer) {
|
||||
spliceTimer = setTimeout(function() {
|
||||
var nodes = [];
|
||||
@@ -350,7 +410,8 @@ RED.palette = (function() {
|
||||
RED.workspaces.show(nt.substring(8));
|
||||
e.preventDefault();
|
||||
});
|
||||
nodeInfo = marked(def.info||"");
|
||||
var subflow = RED.nodes.subflow(nt.substring(8));
|
||||
nodeInfo = RED.utils.renderMarkdown(subflow.info||"");
|
||||
}
|
||||
setLabel(nt,d,label,nodeInfo);
|
||||
|
||||
@@ -392,22 +453,19 @@ RED.palette = (function() {
|
||||
categoryNode.show();
|
||||
paletteNode.show();
|
||||
}
|
||||
|
||||
function refreshNodeTypes() {
|
||||
RED.nodes.eachSubflow(function(sf) {
|
||||
RED.nodes.eachSubflow(refreshSubflow)
|
||||
}
|
||||
function refreshSubflow(sf) {
|
||||
var paletteNode = getPaletteNode('subflow:'+sf.id);
|
||||
var portInput = paletteNode.find(".red-ui-palette-port-input");
|
||||
var portOutput = paletteNode.find(".red-ui-palette-port-output");
|
||||
|
||||
var paletteLabel = paletteNode.find(".red-ui-palette-label");
|
||||
paletteLabel.attr("class","red-ui-palette-label"
|
||||
+ (((!sf._def.align && sf.in.length !== 0 && sf.out.length === 0) || "right" === sf._def.align) ? " red-ui-palette-label-right" : "")
|
||||
);
|
||||
paletteLabel.attr("class","red-ui-palette-label" + (((!sf._def.align && sf.in.length !== 0 && sf.out.length === 0) || "right" === sf._def.align) ? " red-ui-palette-label-right" : ""));
|
||||
|
||||
var paletteIconContainer = paletteNode.find(".red-ui-palette-icon-container");
|
||||
paletteIconContainer.attr("class","red-ui-palette-icon-container"
|
||||
+ (((!sf._def.align && sf.in.length !== 0 && sf.out.length === 0) || "right" === sf._def.align) ? " red-ui-palette-icon-container-right" : "")
|
||||
);
|
||||
paletteIconContainer.attr("class","red-ui-palette-icon-container" + (((!sf._def.align && sf.in.length !== 0 && sf.out.length === 0) || "right" === sf._def.align) ? " red-ui-palette-icon-container-right" : ""));
|
||||
|
||||
if (portInput.length === 0 && sf.in.length > 0) {
|
||||
var portIn = document.createElement("div");
|
||||
@@ -424,7 +482,13 @@ RED.palette = (function() {
|
||||
} else if (portOutput.length !== 0 && sf.out.length === 0) {
|
||||
portOutput.remove();
|
||||
}
|
||||
setLabel(sf.type+":"+sf.id,paletteNode,sf.name,marked(sf.info||""));
|
||||
var currentLabel = paletteNode.attr("data-palette-label");
|
||||
var currentInfo = paletteNode.attr("data-palette-info");
|
||||
|
||||
if (currentLabel !== sf.name || currentInfo !== sf.info) {
|
||||
paletteNode.attr("data-palette-info",sf.info);
|
||||
setLabel(sf.type+":"+sf.id,paletteNode,sf.name,RED.utils.renderMarkdown(sf.info||""));
|
||||
}
|
||||
setIcon(paletteNode,sf);
|
||||
|
||||
var currentCategory = paletteNode.data('category');
|
||||
@@ -450,13 +514,12 @@ RED.palette = (function() {
|
||||
}
|
||||
|
||||
paletteNode.css("backgroundColor", sf.color);
|
||||
});
|
||||
}
|
||||
|
||||
function filterChange(val) {
|
||||
var re = new RegExp(val.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'),'i');
|
||||
$("#red-ui-palette-container .red-ui-palette-node").each(function(i,el) {
|
||||
var currentLabel = $(el).find(".red-ui-palette-label").text();
|
||||
var currentLabel = $(el).attr("data-palette-label");
|
||||
var type = $(el).attr("data-palette-type");
|
||||
if (val === "" || re.test(type) || re.test(currentLabel)) {
|
||||
$(this).show();
|
||||
@@ -488,6 +551,8 @@ RED.palette = (function() {
|
||||
$('<div class="red-ui-component-footer"></div>').appendTo("#red-ui-palette");
|
||||
$('<div id="red-ui-palette-shade" class="hide"></div>').appendTo("#red-ui-palette");
|
||||
|
||||
$("#red-ui-palette > .red-ui-palette-spinner").show();
|
||||
|
||||
|
||||
RED.events.on('registry:node-type-added', function(nodeType) {
|
||||
var def = RED.nodes.getType(nodeType);
|
||||
@@ -529,7 +594,8 @@ RED.palette = (function() {
|
||||
}
|
||||
});
|
||||
|
||||
$("#red-ui-palette > .red-ui-palette-spinner").show();
|
||||
RED.events.on("subflows:change",refreshSubflow);
|
||||
|
||||
|
||||
|
||||
$("#red-ui-palette-search input").searchBox({
|
||||
|
||||