Compare commits
2079 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
50d7e16365 | ||
|
|
ef7bc931b7 | ||
|
|
a713c92530 | ||
|
|
1db1ec7b5e | ||
|
|
a6ef755139 | ||
|
|
7b80ae42e1 | ||
|
|
06a1f30350 | ||
|
|
2f93bb969b | ||
|
|
e094ea3d2a | ||
|
|
c685a31056 | ||
|
|
c32ce3bb7b | ||
|
|
4f87ebdf0a | ||
|
|
19b6cba398 | ||
|
|
5cf9c07b73 | ||
|
|
211eeea05d | ||
|
|
51a3521834 | ||
|
|
6a9575e9f4 | ||
|
|
62088259ae | ||
|
|
925ebcc06e | ||
|
|
673a6bbe2c | ||
|
|
cf32a33984 | ||
|
|
98c1bc276d | ||
|
|
629536b562 | ||
|
|
1441042458 | ||
|
|
58c8311d56 | ||
|
|
e03a0fffa9 | ||
|
|
8e2c12f8d9 | ||
|
|
7cec7ae608 | ||
|
|
c49f722e4f | ||
|
|
d4d95a43b6 | ||
|
|
a345089c8b | ||
|
|
67c268e13d | ||
|
|
ce85c8d986 | ||
|
|
cb35604ef5 | ||
|
|
61681bb1d6 | ||
|
|
1a226c4dc6 | ||
|
|
08fccc4e77 | ||
|
|
c1d50e82e1 | ||
|
|
9777af7cb5 | ||
|
|
fd86035865 | ||
|
|
a8ec032553 | ||
|
|
66ee27c5fa | ||
|
|
17a737ca88 | ||
|
|
75e7c0e50d | ||
|
|
fc0cf1ff51 | ||
|
|
0f4d46671f | ||
|
|
048f9c0294 | ||
|
|
ca77842b5b | ||
|
|
6fa8b7f5f1 | ||
|
|
a2d03c14ae | ||
|
|
c667a0e74c | ||
|
|
8123828113 | ||
|
|
72b8dbb45b | ||
|
|
7703875740 | ||
|
|
6442bb8a13 | ||
|
|
f29d7c9252 | ||
|
|
2f7f53ed96 | ||
|
|
94031a52a5 | ||
|
|
d67f91e7ed | ||
|
|
f37697c4fb | ||
|
|
69448c7329 | ||
|
|
8e9815fb91 | ||
|
|
4cdd7978cf | ||
|
|
40d81358f4 | ||
|
|
c7b62aed91 | ||
|
|
c0e7d6d826 | ||
|
|
f809377de8 | ||
|
|
9767bd9697 | ||
|
|
3a55528552 | ||
|
|
56197ffe3a | ||
|
|
0f0d0c046c | ||
|
|
ecc4973645 | ||
|
|
3169f93cc2 | ||
|
|
c1a1a73599 | ||
|
|
db1b0ccb79 | ||
|
|
df161ce672 | ||
|
|
72fe30892e | ||
|
|
d373105b32 | ||
|
|
28b311b7ed | ||
|
|
dcda513901 | ||
|
|
72c400794c | ||
|
|
042409f870 | ||
|
|
5b8f4f4069 | ||
|
|
d132d63c1d | ||
|
|
4374506981 | ||
|
|
ef8b936069 | ||
|
|
36e3bfffb4 | ||
|
|
91a38bdb60 | ||
|
|
f169a68319 | ||
|
|
ee886f98dd | ||
|
|
a3826cc6a7 | ||
|
|
ba33b832ba | ||
|
|
f6c017176b | ||
|
|
7a01b115bb | ||
|
|
1dc021e871 | ||
|
|
c9f916ebab | ||
|
|
ff627fd128 | ||
|
|
695873d35a | ||
|
|
15da19dcea | ||
|
|
d5bdc1600b | ||
|
|
dfa077fd5f | ||
|
|
5155770213 | ||
|
|
f1d5bbb036 | ||
|
|
69ed0aebc3 | ||
|
|
549e56e220 | ||
|
|
450f4d9a5a | ||
|
|
6533a9793c | ||
|
|
2000cadb17 | ||
|
|
083c321efa | ||
|
|
f64c4a981f | ||
|
|
3ac8ce03bf | ||
|
|
66fca8710e | ||
|
|
1e245ece46 | ||
|
|
81efce03ba | ||
|
|
4e549dd426 | ||
|
|
52f74ff7e0 | ||
|
|
3c71b815f5 | ||
|
|
9efd48fe51 | ||
|
|
4609ee75b6 | ||
|
|
963ea4177e | ||
|
|
17e6940a42 | ||
|
|
315a9ceba3 | ||
|
|
a2bdeedb09 | ||
|
|
da5700d2d7 | ||
|
|
90e7f30247 | ||
|
|
3ccf6ba892 | ||
|
|
e50cd5b745 | ||
|
|
db77be5d72 | ||
|
|
c36870c23e | ||
|
|
e9be007040 | ||
|
|
9e400d9aa6 | ||
|
|
490c8dae75 | ||
|
|
3bcffe375d | ||
|
|
9f81a591e1 | ||
|
|
3db5306c70 | ||
|
|
45029dd084 | ||
|
|
b01cd30339 | ||
|
|
09329e1104 | ||
|
|
ab0fc2ecfa | ||
|
|
bf5d36d6bd | ||
|
|
a29527ec96 | ||
|
|
45e7ad8049 | ||
|
|
4d54663efd | ||
|
|
29d386cc51 | ||
|
|
ba1a67969b | ||
|
|
390ea5419e | ||
|
|
0fdeec7cc4 | ||
|
|
e34d883e50 | ||
|
|
507871687b | ||
|
|
ed58f62cd1 | ||
|
|
94bc4e7125 | ||
|
|
5832f7930d | ||
|
|
0066a20c22 | ||
|
|
774e4bfced | ||
|
|
054c7a76a4 | ||
|
|
c7f3b77aac | ||
|
|
a6a4620374 | ||
|
|
5148c62d1c | ||
|
|
6fc863a91e | ||
|
|
e066a154a1 | ||
|
|
d432edaed2 | ||
|
|
8f34f4e80b | ||
|
|
39b751acf5 | ||
|
|
bd5e8ba961 | ||
|
|
ed20327c41 | ||
|
|
991c68c394 | ||
|
|
2acc31a4e7 | ||
|
|
b9733e3dfa | ||
|
|
bb106bfce7 | ||
|
|
daf1388a6a | ||
|
|
8226f1fa75 | ||
|
|
e675512fa3 | ||
|
|
65e67b6c3e | ||
|
|
7612481570 | ||
|
|
f6c7cb5804 | ||
|
|
2201c9062f | ||
|
|
ca3da262da | ||
|
|
5847f92bef | ||
|
|
31ee1be81e | ||
|
|
6bccdd015f | ||
|
|
cecea318da | ||
|
|
8663ec6880 | ||
|
|
9b03f128aa | ||
|
|
8a51f97616 | ||
|
|
ee74ed9ce9 | ||
|
|
0f947c756e | ||
|
|
cae7949a48 | ||
|
|
be58b614e1 | ||
|
|
b0a01fa4b2 | ||
|
|
9734228001 | ||
|
|
9df1d44bc4 | ||
|
|
13d887028a | ||
|
|
83a8979309 | ||
|
|
75c29f1cb7 | ||
|
|
d9d15e41c7 | ||
|
|
d3598d5854 | ||
|
|
3a8aaee5d7 | ||
|
|
4fcf57d42c | ||
|
|
adb0891335 | ||
|
|
d21e719cc1 | ||
|
|
5807ab82c1 | ||
|
|
65cb04da63 | ||
|
|
312e3611b1 | ||
|
|
46acc62279 | ||
|
|
529b358c9b | ||
|
|
7fca04404e | ||
|
|
3a1cc6a2be | ||
|
|
5b76c91004 | ||
|
|
cf87837f7d | ||
|
|
5a0a7b907b | ||
|
|
6a2b1669b3 | ||
|
|
ca8264b3f4 | ||
|
|
b44ecd8819 | ||
|
|
987942959e | ||
|
|
91992b48c1 | ||
|
|
c9a335a6f9 | ||
|
|
b7ed159b50 | ||
|
|
c72961a52a | ||
|
|
afe6afca36 | ||
|
|
050acd239c | ||
|
|
24505ee4f5 | ||
|
|
63a249aba3 | ||
|
|
7bd94df2a0 | ||
|
|
761161a8e5 | ||
|
|
513579a7ee | ||
|
|
7165483d83 | ||
|
|
f8bcf219cb | ||
|
|
590506e306 | ||
|
|
9a5439c580 | ||
|
|
6b2f5fbb19 | ||
|
|
051c147b41 | ||
|
|
9111adf15f | ||
|
|
ba18b27371 | ||
|
|
2a287b2ae6 | ||
|
|
fc9040f715 | ||
|
|
0029022ef6 | ||
|
|
94f728d3fd | ||
|
|
d53ced7830 | ||
|
|
053d8c44c2 | ||
|
|
9f5767ea16 | ||
|
|
e8d76b0555 | ||
|
|
c2675600f6 | ||
|
|
6f087b4ec1 | ||
|
|
e94708606d | ||
|
|
c248f1a762 | ||
|
|
28402b0894 | ||
|
|
7dd98e99f9 | ||
|
|
dba195b396 | ||
|
|
88b153bc12 | ||
|
|
d4a47dc974 | ||
|
|
fe3ea6edfd | ||
|
|
6c8fc4846b | ||
|
|
54d9656f09 | ||
|
|
49da324c5d | ||
|
|
9bf87697fd | ||
|
|
f368f5a9c4 | ||
|
|
eea85485e6 | ||
|
|
1a544b3b82 | ||
|
|
8b38fe9fe0 | ||
|
|
1bf4addf63 | ||
|
|
407e16e900 | ||
|
|
6e9fe3248a | ||
|
|
d8cf86fd6f | ||
|
|
f8aa4a9588 | ||
|
|
c249907846 | ||
|
|
57c1524a9a | ||
|
|
d8d82e2ba3 | ||
|
|
807b512ef7 | ||
|
|
b2f06b6777 | ||
|
|
d7adff9a65 | ||
|
|
b0d7e11d48 | ||
|
|
fc9cdb61f2 | ||
|
|
9c00492dc2 | ||
|
|
1a6babd199 | ||
|
|
1b693eed37 | ||
|
|
afb566b6b4 | ||
|
|
f870e9ed3e | ||
|
|
4bcf13cb58 | ||
|
|
946a6d6041 | ||
|
|
372c213c2c | ||
|
|
a5a79d3ab7 | ||
|
|
e6c5cfb703 | ||
|
|
7843eccae8 | ||
|
|
7ca153abd0 | ||
|
|
33b4774c49 | ||
|
|
c243481432 | ||
|
|
80873e4ea9 | ||
|
|
4e4a1f11e6 | ||
|
|
9bbe405cd0 | ||
|
|
c440a4c730 | ||
|
|
a1251371d7 | ||
|
|
7d702e8332 | ||
|
|
43d7c8d48c | ||
|
|
7423583508 | ||
|
|
08b0838f9a | ||
|
|
038d821a7c | ||
|
|
6a218814d3 | ||
|
|
905f89b0f5 | ||
|
|
14882bda78 | ||
|
|
781fa4634b | ||
|
|
cdb173fd6e | ||
|
|
466cb4be89 | ||
|
|
c39e2ffd56 | ||
|
|
17bf09e276 | ||
|
|
bc01f9f8fd | ||
|
|
c0870c5694 | ||
|
|
3b5174a2ea | ||
|
|
af6885f3e8 | ||
|
|
e01996095f | ||
|
|
5d86f7b6ba | ||
|
|
8d6ac6406d | ||
|
|
40ff54f67e | ||
|
|
cce7ac09d0 | ||
|
|
73a18891c5 | ||
|
|
fe22cedc1d | ||
|
|
fa09c7c8b2 | ||
|
|
15e28e3cc0 | ||
|
|
2cb4f6b1fc | ||
|
|
b17a483b85 | ||
|
|
7c3e5443ab | ||
|
|
f95a2851c8 | ||
|
|
2b2eee352f | ||
|
|
11569d8056 | ||
|
|
bdf87452b6 | ||
|
|
0c6bf81c24 | ||
|
|
f2fa26fb07 | ||
|
|
f5e212ff1e | ||
|
|
461e6562ca | ||
|
|
fd67d08402 | ||
|
|
e6411d11b1 | ||
|
|
dd81d947fc | ||
|
|
23b887c30e | ||
|
|
c4eae3f130 | ||
|
|
41a04a2849 | ||
|
|
ed1d34e678 | ||
|
|
f44487338d | ||
|
|
7aced85a31 | ||
|
|
fbe0e2d6eb | ||
|
|
6e34f0697c | ||
|
|
a835f9f0cb | ||
|
|
16715673c3 | ||
|
|
c48c74f173 | ||
|
|
f262348497 | ||
|
|
7185bcd51f | ||
|
|
28d05e2449 | ||
|
|
7fafa21a1b | ||
|
|
84f598e143 | ||
|
|
e30f8628db | ||
|
|
0be9c88106 | ||
|
|
e046fc1ac5 | ||
|
|
3a476ac493 | ||
|
|
e33ec0cf50 | ||
|
|
b4b70a988e | ||
|
|
e66b381070 | ||
|
|
771b598c09 | ||
|
|
cd44f13171 | ||
|
|
aa6b72ac87 | ||
|
|
a467fe5ed7 | ||
|
|
467411c6c3 | ||
|
|
2648b7ca54 | ||
|
|
de35c7024a | ||
|
|
9d219c163d | ||
|
|
f7434b5ec8 | ||
|
|
5ed3360c0b | ||
|
|
6f5974f875 | ||
|
|
56db1da3cf | ||
|
|
fef71f29c4 | ||
|
|
d46b66878a | ||
|
|
6cad80c4ad | ||
|
|
68779caa2e | ||
|
|
2a122ed283 | ||
|
|
17c5fdf0d5 | ||
|
|
f6274445a2 | ||
|
|
3b0300b834 | ||
|
|
4fbf1fe780 | ||
|
|
dcf44fed58 | ||
|
|
7136dc1c72 | ||
|
|
0e4cedbc5e | ||
|
|
dc139bcc30 | ||
|
|
b204b183de | ||
|
|
ab788bc1e3 | ||
|
|
95b4c8d515 | ||
|
|
b025644525 | ||
|
|
9e87a60597 | ||
|
|
5a70bea67a | ||
|
|
2a95af3928 | ||
|
|
0a0ca380d3 | ||
|
|
4cfbf7f71c | ||
|
|
de43148341 | ||
|
|
0a2aab7d68 | ||
|
|
745821c420 | ||
|
|
57c4c754d0 | ||
|
|
4b5c437533 | ||
|
|
8d63b6a1ed | ||
|
|
245a8adbf9 | ||
|
|
4f7d98aace | ||
|
|
b0c693cc3a | ||
|
|
b2cca10e8b | ||
|
|
a84b2ab5bb | ||
|
|
4565342b05 | ||
|
|
0ad54cc2d1 | ||
|
|
865853da19 | ||
|
|
392ed706fd | ||
|
|
0ff0f25aaf | ||
|
|
c157960846 | ||
|
|
a5c00b5c81 | ||
|
|
472bbdb59f | ||
|
|
7877093713 | ||
|
|
8cb2e51407 | ||
|
|
d5cee81fb6 | ||
|
|
bca020bc4d | ||
|
|
5069f2844c | ||
|
|
252df81f59 | ||
|
|
7f89a4a26f | ||
|
|
40f4167894 | ||
|
|
0ef16989cd | ||
|
|
3df3d6f516 | ||
|
|
10395ef254 | ||
|
|
83854c28db | ||
|
|
fcbea2629c | ||
|
|
26bc142cc2 | ||
|
|
a4eb8e11c3 | ||
|
|
9fd5d1db56 | ||
|
|
1d05b4c981 | ||
|
|
61f6535be8 | ||
|
|
7dd329b5ee | ||
|
|
b761904424 | ||
|
|
36105412b1 | ||
|
|
184b1b018c | ||
|
|
f3e1b85d82 | ||
|
|
626d012775 | ||
|
|
9ad9c0ec6a | ||
|
|
e13fed9fc6 | ||
|
|
eb6d093e56 | ||
|
|
af1ea610ea | ||
|
|
d4d9190919 | ||
|
|
4d3d1a02a8 | ||
|
|
30c2aa96d6 | ||
|
|
4edb1f80b0 | ||
|
|
0a82459233 | ||
|
|
db87b0dfa5 | ||
|
|
cd42cf7583 | ||
|
|
2d5980ff2a | ||
|
|
d49c7a3adb | ||
|
|
4fdd09a262 | ||
|
|
d6878512c4 | ||
|
|
8b1b8250ff | ||
|
|
9dccbf747e | ||
|
|
08727e1938 | ||
|
|
7584820987 | ||
|
|
d572356642 | ||
|
|
3b5a2815a9 | ||
|
|
f3cf01df25 | ||
|
|
63e6e64ad3 | ||
|
|
e8d7b48bff | ||
|
|
12944d1ebd | ||
|
|
fa1ff6e393 | ||
|
|
98546b6e6a | ||
|
|
2fef6fd1fa | ||
|
|
20cf91f1dc | ||
|
|
2efa78d590 | ||
|
|
880af0671a | ||
|
|
62471e4531 | ||
|
|
b15f8535f8 | ||
|
|
7a3a4493da | ||
|
|
11078235c4 | ||
|
|
f3e05cd08a | ||
|
|
0ca3cabbe8 | ||
|
|
44a75c1291 | ||
|
|
4a4513a746 | ||
|
|
60ff8660de | ||
|
|
6fa0d671c0 | ||
|
|
f478d7c9f0 | ||
|
|
53e3e08d70 | ||
|
|
c4d1ccb6f5 | ||
|
|
e3520309fc | ||
|
|
27bf72372e | ||
|
|
ae4b1b17a9 | ||
|
|
94cb03f4b5 | ||
|
|
e691351976 | ||
|
|
3190de873e | ||
|
|
e8a637498d | ||
|
|
e1195ac00a | ||
|
|
6cd9ccc37c | ||
|
|
25345302e8 | ||
|
|
eccd5e9801 | ||
|
|
ff355af9f2 | ||
|
|
5967f4b0d4 | ||
|
|
ff18618032 | ||
|
|
20f03c356c | ||
|
|
27fdc9e56e | ||
|
|
52d9578a19 | ||
|
|
f4c2938b41 | ||
|
|
9f703de5ec | ||
|
|
a327fd85e2 | ||
|
|
9d22a86ec8 | ||
|
|
29e0b194dd | ||
|
|
ae9cf13fc2 | ||
|
|
64ae67586a | ||
|
|
838c7a5e89 | ||
|
|
89bfc90f40 | ||
|
|
acad9f57f9 | ||
|
|
0d08dc410e | ||
|
|
ebb3fb96cd | ||
|
|
f31f23ff07 | ||
|
|
d2aa3d1868 | ||
|
|
c9e2fce94d | ||
|
|
8b0e76dd55 | ||
|
|
884618adfe | ||
|
|
6e2e36e7a0 | ||
|
|
9994df9601 | ||
|
|
98f7271ac8 | ||
|
|
087cd121b8 | ||
|
|
2d52527fb4 | ||
|
|
fe289e62b5 | ||
|
|
2845475e3f | ||
|
|
b307492487 | ||
|
|
d48284f7ea | ||
|
|
7e416797e9 | ||
|
|
5d54ca7477 | ||
|
|
b979b4e61a | ||
|
|
2527f7984a | ||
|
|
d9350b2362 | ||
|
|
bd0b903f1a | ||
|
|
f243c0df19 | ||
|
|
7482978953 | ||
|
|
77966689d4 | ||
|
|
cf43939d65 | ||
|
|
391ac4b351 | ||
|
|
e1e48aadd9 | ||
|
|
0681f206c4 | ||
|
|
d257c6f3d3 | ||
|
|
fa45c82cdc | ||
|
|
e805b58da6 | ||
|
|
943976d207 | ||
|
|
3a2e5a6ccd | ||
|
|
35ef036246 | ||
|
|
e09c3bbdd3 | ||
|
|
3b12076d4b | ||
|
|
cfcf78ae28 | ||
|
|
341ff9bf5c | ||
|
|
10d8ca30b0 | ||
|
|
4ebb5d099e | ||
|
|
1e82b66bf0 | ||
|
|
06a5e4273b | ||
|
|
e123e7b0b0 | ||
|
|
aeadc40c65 | ||
|
|
7ef418ec52 | ||
|
|
2ed52820b6 | ||
|
|
e8fd7484b6 | ||
|
|
ce5242cfe8 | ||
|
|
af947879d8 | ||
|
|
3ed112cde6 | ||
|
|
99c6a9eccd | ||
|
|
2029f6ea0a | ||
|
|
e984e1f30f | ||
|
|
f21260370f | ||
|
|
fdae75c99b | ||
|
|
a0489f2a0d | ||
|
|
0123eacbdb | ||
|
|
53401b6aa7 | ||
|
|
9a5139f452 | ||
|
|
2ee0c8c228 | ||
|
|
c53562cc9c | ||
|
|
ec5d7c2e5c | ||
|
|
d6fc258485 | ||
|
|
f953612695 | ||
|
|
2ab93acca8 | ||
|
|
326c6c496e | ||
|
|
9f7f50664c | ||
|
|
f6f1436123 | ||
|
|
c3c519419d | ||
|
|
e569a80b72 | ||
|
|
284f437c1a | ||
|
|
1fd44a9958 | ||
|
|
cad34742f6 | ||
|
|
323359b3c8 | ||
|
|
35db8b45f0 | ||
|
|
50ae815ceb | ||
|
|
1a4389c90d | ||
|
|
fdaa5ce1da | ||
|
|
09d9936aed | ||
|
|
b3f6109b1c | ||
|
|
5fb3ffc240 | ||
|
|
360db252bb | ||
|
|
0b6e290271 | ||
|
|
7f0174e6db | ||
|
|
a25dad6c2e | ||
|
|
6191a49ed3 | ||
|
|
6252b075bc | ||
|
|
7face138fd | ||
|
|
382b83b093 | ||
|
|
691687d1bc | ||
|
|
5814b80a72 | ||
|
|
e147fbb1fa | ||
|
|
b9e256adfa | ||
|
|
3b7bf04e22 | ||
|
|
43408a724c | ||
|
|
5fbd5bf9e2 | ||
|
|
5e87828b29 | ||
|
|
9066cedc29 | ||
|
|
aa1cf0b228 | ||
|
|
06a6a4408f | ||
|
|
d5619d2b9d | ||
|
|
2f6ac42efe | ||
|
|
0bba3dd83d | ||
|
|
abe60b62e6 | ||
|
|
555b7df986 | ||
|
|
b3786700e6 | ||
|
|
ce9643d21b | ||
|
|
4a5cb7f2f5 | ||
|
|
42a7e902e6 | ||
|
|
aebe080e85 | ||
|
|
c316284924 | ||
|
|
8d98b228ab | ||
|
|
5b4c42ff05 | ||
|
|
a596a4551a | ||
|
|
0968f96982 | ||
|
|
5931e13b9c | ||
|
|
415c768ae4 | ||
|
|
b4c8bf21d5 | ||
|
|
5fe5db603d | ||
|
|
9f7dd7f5d4 | ||
|
|
e6d32aab7b | ||
|
|
08bd6d963c | ||
|
|
ff05fb14a6 | ||
|
|
22d942b705 | ||
|
|
0526372f28 | ||
|
|
f99051906a | ||
|
|
d1f7fd8bfd | ||
|
|
fc1436a96d | ||
|
|
d21568497b | ||
|
|
df4beef060 | ||
|
|
a52f195d41 | ||
|
|
419019a656 | ||
|
|
42b5635485 | ||
|
|
a8fc5b01f3 | ||
|
|
ead841d844 | ||
|
|
67d7930aef | ||
|
|
6f69995f4e | ||
|
|
05252fa239 | ||
|
|
1377439bb0 | ||
|
|
407123a280 | ||
|
|
750dd590c8 | ||
|
|
44112a9d18 | ||
|
|
b220bf0d99 | ||
|
|
d0d93d7070 | ||
|
|
4117961236 | ||
|
|
68a3d71ee6 | ||
|
|
bf5d741f0d | ||
|
|
55a33bc408 | ||
|
|
3ec35ed119 | ||
|
|
3d8d6953ec | ||
|
|
528db67c34 | ||
|
|
b847e962aa | ||
|
|
bbb9a3c63b | ||
|
|
322cebc48c | ||
|
|
1cceb3d880 | ||
|
|
effc64db9a | ||
|
|
7e5bd5f2c1 | ||
|
|
e32cc4d1af | ||
|
|
09a3cd850e | ||
|
|
b0c876019a | ||
|
|
6725f870d2 | ||
|
|
0e5adc1f0a | ||
|
|
57ebb93dc0 | ||
|
|
05dc0bfa1d | ||
|
|
2d0264116c | ||
|
|
3938550ea8 | ||
|
|
9f0c567794 | ||
|
|
8672fcd2bb | ||
|
|
3f2a92e801 | ||
|
|
771e43583a | ||
|
|
9353d5c1c4 | ||
|
|
5e462f0f02 | ||
|
|
a25f6fec9f | ||
|
|
519edce0ed | ||
|
|
0bc7702d95 | ||
|
|
18be0d6d26 | ||
|
|
1d4a435f20 | ||
|
|
34e46fc6d3 | ||
|
|
50956c51f7 | ||
|
|
dd7bb28b6a | ||
|
|
8516f41ba8 | ||
|
|
15c3cc60f6 | ||
|
|
716bca211b | ||
|
|
8179813fe1 | ||
|
|
d355de509b | ||
|
|
b04a2d4c08 | ||
|
|
6d3232a4f0 | ||
|
|
2753075180 | ||
|
|
d0166b25e4 | ||
|
|
73ee657d74 | ||
|
|
45913e5ee8 | ||
|
|
e6369820a9 | ||
|
|
22a5b339f7 | ||
|
|
2cea3b6435 | ||
|
|
5d2d06fb3e | ||
|
|
0dd7bc7fb9 | ||
|
|
0b0005337c | ||
|
|
d26fb02bb9 | ||
|
|
af683835d9 | ||
|
|
c43647ca86 | ||
|
|
6d02e70025 | ||
|
|
5498c6f87d | ||
|
|
11f59bc3ac | ||
|
|
94cb7de79f | ||
|
|
838f45775b | ||
|
|
1c1422e4b5 | ||
|
|
cd8ca6fc62 | ||
|
|
b7a0a9d7c2 | ||
|
|
7822ab113a | ||
|
|
e250a91f09 | ||
|
|
92a65dcda5 | ||
|
|
4b129d94e4 | ||
|
|
e7960d1d44 | ||
|
|
95589307cd | ||
|
|
20a0e4f3e0 | ||
|
|
6a9213da64 | ||
|
|
7a89e3cf33 | ||
|
|
64607df929 | ||
|
|
a62a1012fa | ||
|
|
14efd0b2f9 | ||
|
|
7ad2192df8 | ||
|
|
3cb5cbd8d5 | ||
|
|
cc9011cd68 | ||
|
|
dc3d89008d | ||
|
|
1893642187 | ||
|
|
a9ece5772d | ||
|
|
cf34716a57 | ||
|
|
1337831061 | ||
|
|
757e72100d | ||
|
|
a75b819858 | ||
|
|
da4a0f09ed | ||
|
|
87d847a074 | ||
|
|
84711beec0 | ||
|
|
f3cf58c8ff | ||
|
|
cf40497e6e | ||
|
|
dfebc4b78d | ||
|
|
15f41a2e7c | ||
|
|
ad6e55ca17 | ||
|
|
6b466d217a | ||
|
|
00dcb304c7 | ||
|
|
c6fb3d6f41 | ||
|
|
ac3143811f | ||
|
|
7e27dd7678 | ||
|
|
c2508296a5 | ||
|
|
a9b50ce6fc | ||
|
|
eac98a6d4d | ||
|
|
7e2b2a9a02 | ||
|
|
353de471eb | ||
|
|
85fc20b52d | ||
|
|
cc25a781f8 | ||
|
|
fc3012ba72 | ||
|
|
d93a92c1c8 | ||
|
|
f7f795f58a | ||
|
|
2700f8cdd2 | ||
|
|
6310de0d20 | ||
|
|
218794be77 | ||
|
|
af71ae649b | ||
|
|
9bc72c1a06 | ||
|
|
8d7c157751 | ||
|
|
558a66fbe5 | ||
|
|
f95b414d22 | ||
|
|
e793a1e1aa | ||
|
|
b76010cb5a | ||
|
|
52475df783 | ||
|
|
1f3f32d377 | ||
|
|
3f5ba10354 | ||
|
|
25f4a018d9 | ||
|
|
a11a279c00 | ||
|
|
fd4fdb31b5 | ||
|
|
1921796d6d | ||
|
|
543a2b9dc7 | ||
|
|
dd23e03342 | ||
|
|
5307c74f85 | ||
|
|
d701c406e2 | ||
|
|
3ba56a0a65 | ||
|
|
4adafb6d1e | ||
|
|
4453a51211 | ||
|
|
14429d2943 | ||
|
|
1a62a7831b | ||
|
|
242e35c212 | ||
|
|
ea763fdfd5 | ||
|
|
e762b7ff48 | ||
|
|
298068b2b9 | ||
|
|
cb4120ec4b | ||
|
|
5cfbb87bee | ||
|
|
9e472ed83c | ||
|
|
ebca753fc4 | ||
|
|
548f45cd56 | ||
|
|
8ffabf1813 | ||
|
|
1f40d4f941 | ||
|
|
41582045d0 | ||
|
|
fd9e3fc03a | ||
|
|
8c42b2bdb4 | ||
|
|
7b1787fdbb | ||
|
|
71fee0025d | ||
|
|
1204cf1ba0 | ||
|
|
7bd8d8c3ae | ||
|
|
2c4d5fa38d | ||
|
|
bedb2d943e | ||
|
|
a3640bd9bf | ||
|
|
7c0b9ffe06 | ||
|
|
161c7d30ca | ||
|
|
4ff6e792cd | ||
|
|
af5df890a5 | ||
|
|
9ba011003a | ||
|
|
bb168d35a8 | ||
|
|
3306d30094 | ||
|
|
6516e0dfd2 | ||
|
|
00a396014b | ||
|
|
13356047dc | ||
|
|
8a6488b067 | ||
|
|
1c2ea56f42 | ||
|
|
1d7ae300e2 | ||
|
|
6013e186ed | ||
|
|
207d3d3340 | ||
|
|
5a6cde1446 | ||
|
|
63f7d826bc | ||
|
|
ff8773f6bd | ||
|
|
a868cb97d9 | ||
|
|
915d73e6f2 | ||
|
|
5f4f6e37b5 | ||
|
|
9c350311e8 | ||
|
|
3c6ba72a2a | ||
|
|
816442f5f0 | ||
|
|
3b51d18ce7 | ||
|
|
6696b6661a | ||
|
|
8c87478636 | ||
|
|
d870b072d7 | ||
|
|
2ea2af7d2a | ||
|
|
f737ea96f3 | ||
|
|
05f90394db | ||
|
|
c24b0c6bb4 | ||
|
|
e07a4dc7ba | ||
|
|
fc6748a46b | ||
|
|
7697c46652 | ||
|
|
ed52e5afd1 | ||
|
|
33a5b84181 | ||
|
|
c09a407f4c | ||
|
|
d35784ec61 | ||
|
|
53e012f296 | ||
|
|
2a9d0a5e7d | ||
|
|
474f4572f2 | ||
|
|
bf57cb209f | ||
|
|
9bc41c1709 | ||
|
|
fe10b8650f | ||
|
|
3a311c9584 | ||
|
|
d1106f53e0 | ||
|
|
a3a1bba5ef | ||
|
|
028d66befc | ||
|
|
bb59cd5742 | ||
|
|
604e3068b2 | ||
|
|
27f1d3b704 | ||
|
|
d007623347 | ||
|
|
6a5cf7a1fa | ||
|
|
3adfe249b0 | ||
|
|
923893e160 | ||
|
|
256e5360d4 | ||
|
|
304c597a2f | ||
|
|
f86d3a69d2 | ||
|
|
d7c8adfd82 | ||
|
|
55cd069043 | ||
|
|
3ca0e9c420 | ||
|
|
1dd4323613 | ||
|
|
d78916f85f | ||
|
|
1840d15397 | ||
|
|
b98d1216b1 | ||
|
|
27db727321 | ||
|
|
3f6b1f6ccb | ||
|
|
6d633b372a | ||
|
|
91352e855a | ||
|
|
8bb9b594cf | ||
|
|
6d2fd2e641 | ||
|
|
422fbcb0b7 | ||
|
|
afce106186 | ||
|
|
f21c8154ed | ||
|
|
3988a648d6 | ||
|
|
1b632894d3 | ||
|
|
5e128f89f6 | ||
|
|
fff0b15ae5 | ||
|
|
a7e14f1093 | ||
|
|
94eeaeb8d3 | ||
|
|
64191e8303 | ||
|
|
21cfb71617 | ||
|
|
806457063f | ||
|
|
b9213b73bd | ||
|
|
d7f0102aa2 | ||
|
|
f09e61a59a | ||
|
|
d426aaa88a | ||
|
|
19e45389e1 | ||
|
|
6d2389945b | ||
|
|
14c48253f6 | ||
|
|
e5ff25b92d | ||
|
|
5c88888e02 | ||
|
|
10057de9b3 | ||
|
|
cc88ebd2b9 | ||
|
|
6baedf909d | ||
|
|
f39d9d6f1b | ||
|
|
ab61a95f83 | ||
|
|
10ceed30c6 | ||
|
|
2b9aa94f3a | ||
|
|
848fb975ed | ||
|
|
d7f59dac84 | ||
|
|
dd47e615ee | ||
|
|
8f2f7ea1a5 | ||
|
|
80a8efd8ce | ||
|
|
d9dce77ef4 | ||
|
|
ce7053a1fe | ||
|
|
0db1530171 | ||
|
|
3745504107 | ||
|
|
57533fd831 | ||
|
|
f57a0d4d6b | ||
|
|
22772ca33e | ||
|
|
dba6ff1d51 | ||
|
|
40146dedaf | ||
|
|
387b822f53 | ||
|
|
b9a3563e5b | ||
|
|
3d6468326a | ||
|
|
298e37ec53 | ||
|
|
5b137c457b | ||
|
|
5218a3fbac | ||
|
|
4569cb432d | ||
|
|
611e598756 | ||
|
|
937d79d28f | ||
|
|
23c2a771d3 | ||
|
|
58a890e836 | ||
|
|
6a869e120c | ||
|
|
ae7c298b1a | ||
|
|
53bfe12ac1 | ||
|
|
140ea683a6 | ||
|
|
0634a97598 | ||
|
|
3479c794de | ||
|
|
89cad116f7 | ||
|
|
19c84eb694 | ||
|
|
eae390acf5 | ||
|
|
10567afbb9 | ||
|
|
51bad3bf3c | ||
|
|
9134d8841d | ||
|
|
e9a026c131 | ||
|
|
9a2fd0e2b2 | ||
|
|
522f7e6844 | ||
|
|
cb4f46decc | ||
|
|
81256279a8 | ||
|
|
039bd1ddc0 | ||
|
|
0791d4797f | ||
|
|
6a06142e1e | ||
|
|
ef53dca062 | ||
|
|
6ce761edda | ||
|
|
d8fd218409 | ||
|
|
edc2310599 | ||
|
|
b1cd13d629 | ||
|
|
b81940351f | ||
|
|
a42e99c4aa | ||
|
|
ff40b521b7 | ||
|
|
85392496e7 | ||
|
|
29cae9975e | ||
|
|
170d6b28f8 | ||
|
|
9a8b404054 | ||
|
|
41af5187aa | ||
|
|
a844ca161f | ||
|
|
e09efba313 | ||
|
|
96a0dbea2d | ||
|
|
5b3b5271ad | ||
|
|
d7d13c12fe | ||
|
|
54220d0e71 | ||
|
|
4a2e3586f1 | ||
|
|
f808e85da9 | ||
|
|
1671d1f580 | ||
|
|
7de1bf9d95 | ||
|
|
7368b0cefb | ||
|
|
4af43d676a | ||
|
|
67dc848b2d | ||
|
|
7ec8f0d26b | ||
|
|
eaf08a9971 | ||
|
|
5bdb9e972e | ||
|
|
d4d87054c4 | ||
|
|
0f93929544 | ||
|
|
1c0e794f87 | ||
|
|
f9bce5a5f9 | ||
|
|
797ae096c8 | ||
|
|
6d76918424 | ||
|
|
2aced893c6 | ||
|
|
f0373cd789 | ||
|
|
2f88dc64fc | ||
|
|
781ca77794 | ||
|
|
c6e453fb00 | ||
|
|
a40b3dd377 | ||
|
|
096b3534d8 | ||
|
|
5324244c55 | ||
|
|
993f1dc853 | ||
|
|
d8a4e9e1ab | ||
|
|
b3ffd33507 | ||
|
|
c93870316c | ||
|
|
fc9906624e | ||
|
|
ba6209ba54 | ||
|
|
f9769a73fe | ||
|
|
3a2f56cb95 | ||
|
|
a4d33879dc | ||
|
|
e2a91d1ea9 | ||
|
|
f30f80d117 | ||
|
|
266274135e | ||
|
|
a10439b67c | ||
|
|
0fd8d0e2bf | ||
|
|
47e2707fd3 | ||
|
|
f7bb4a7d60 | ||
|
|
6102a31a31 | ||
|
|
1692c3b102 | ||
|
|
ac60725d2a | ||
|
|
1542f73fa5 | ||
|
|
70a22187f7 | ||
|
|
347e598715 | ||
|
|
a737810c50 | ||
|
|
92654a71fb | ||
|
|
18615640e0 | ||
|
|
b8c80a2310 | ||
|
|
c34c98386e | ||
|
|
d8a3d2793f | ||
|
|
360b0d9997 | ||
|
|
356f46aaf4 | ||
|
|
87ac0507d9 | ||
|
|
63657c18e2 | ||
|
|
817f92a50e | ||
|
|
304be96dd6 | ||
|
|
9639081e7e | ||
|
|
dca553048a | ||
|
|
6201ed4d55 | ||
|
|
6db2c04585 | ||
|
|
f3840512ba | ||
|
|
9a6cf58565 | ||
|
|
78076122ba | ||
|
|
7429f66d6b | ||
|
|
e59eff83b9 | ||
|
|
2083d85afa | ||
|
|
4c9f1369c8 | ||
|
|
adca1d7855 | ||
|
|
dfc4e99560 | ||
|
|
344076c943 | ||
|
|
710f1e2ca0 | ||
|
|
74ea85d19c | ||
|
|
dded98e30c | ||
|
|
160c27c15a | ||
|
|
a6a9025bab | ||
|
|
a780d4463c | ||
|
|
23539ee907 | ||
|
|
b515df611d | ||
|
|
0d896fef0b | ||
|
|
283d5c64cb | ||
|
|
3134bc432b | ||
|
|
fd93fef73e | ||
|
|
8939a9c786 | ||
|
|
52c0d360b2 | ||
|
|
d99432bff1 | ||
|
|
4dd2d3ac7d | ||
|
|
aa7fe3668c | ||
|
|
83ebcf1dae | ||
|
|
c9317659c5 | ||
|
|
6562c558de | ||
|
|
303f67c036 | ||
|
|
2482d122b8 | ||
|
|
1733c38b5c | ||
|
|
7a1e4e9e99 | ||
|
|
e590313297 | ||
|
|
b63d243e33 | ||
|
|
e9c1216d5c | ||
|
|
df9e50445e | ||
|
|
61339face6 | ||
|
|
9cd751e977 | ||
|
|
7aa08ff885 | ||
|
|
a824caf712 | ||
|
|
395210e4f0 | ||
|
|
e23354b2bb | ||
|
|
bc472eb0b3 | ||
|
|
256f8e7226 | ||
|
|
f41959537b | ||
|
|
c9e05cf9f6 | ||
|
|
82d9a02d92 | ||
|
|
dc9fa81346 | ||
|
|
b91c178200 | ||
|
|
adebdf36a5 | ||
|
|
4f34980c9f | ||
|
|
e70766a535 | ||
|
|
55110dfbac | ||
|
|
56405ac903 | ||
|
|
2b2136c468 | ||
|
|
f12031ee9e | ||
|
|
c26852da77 | ||
|
|
d9dc171c28 | ||
|
|
d407f31ae5 | ||
|
|
f688b8d299 | ||
|
|
d8e6a7b687 | ||
|
|
7c42b04eff | ||
|
|
f527841c29 | ||
|
|
48a8dc0989 | ||
|
|
7e35c9c754 | ||
|
|
7502a2b1ff | ||
|
|
6c2de40dba | ||
|
|
ef90f19eaa | ||
|
|
90ab34591a | ||
|
|
21d3a3dd1e | ||
|
|
b44e70115b | ||
|
|
ac31957707 | ||
|
|
65e27a268d | ||
|
|
6bd59b10c7 | ||
|
|
6a6a692891 | ||
|
|
479b18354d | ||
|
|
9c6452544b | ||
|
|
0a6ff900da | ||
|
|
f54f863611 | ||
|
|
9cc04da7b2 | ||
|
|
d7f5b0c9d7 | ||
|
|
9bd4598c6a | ||
|
|
e3b052bc38 | ||
|
|
f215970649 | ||
|
|
dfe1cd4f90 | ||
|
|
3d2e6aea7b | ||
|
|
749b0d7019 | ||
|
|
7978f85f7a | ||
|
|
bd14acb68a | ||
|
|
1e9ce550db | ||
|
|
6278dfa77e | ||
|
|
2a3e355437 | ||
|
|
f6b0459d27 | ||
|
|
790d6912fd | ||
|
|
e69e5b4f50 | ||
|
|
483306e73c | ||
|
|
1148a0b637 | ||
|
|
524021f0fa | ||
|
|
5b5f9aa01d | ||
|
|
f97f92c297 | ||
|
|
9d4139085b | ||
|
|
0ee7ffb5e5 | ||
|
|
8a7bb1be9f | ||
|
|
d4135e80a6 | ||
|
|
a5ade39d7c | ||
|
|
f39b4e7d22 | ||
|
|
080469cdf5 | ||
|
|
835ad29417 | ||
|
|
c09bea4710 | ||
|
|
879c0f4114 | ||
|
|
5feb07583b | ||
|
|
5388002f54 | ||
|
|
c80fa9914b | ||
|
|
b43d566968 | ||
|
|
6b4e15dd0f | ||
|
|
d9ef32d7e8 | ||
|
|
49389d6f06 | ||
|
|
c75dc3cc36 | ||
|
|
c0eabf0438 | ||
|
|
7730d0a4f8 | ||
|
|
e79da408a8 | ||
|
|
7381784d0f | ||
|
|
085fb283e5 | ||
|
|
61e0e50e7b | ||
|
|
00460d856b | ||
|
|
48958f392f | ||
|
|
a84efeb5d5 | ||
|
|
1c8c05ae04 | ||
|
|
401d386812 | ||
|
|
6b07f58e8e | ||
|
|
6e8c978d12 | ||
|
|
5b2296b056 | ||
|
|
dbf0486acb | ||
|
|
b030e935ce | ||
|
|
29bd43413a | ||
|
|
2249b9449c | ||
|
|
30920b1b78 | ||
|
|
8f92a3e875 | ||
|
|
ed1a55d9cd | ||
|
|
93ef84f495 | ||
|
|
ccfcbe8526 | ||
|
|
5938143002 | ||
|
|
8135da71bd | ||
|
|
a3c73a04c2 | ||
|
|
7f90d31846 | ||
|
|
45fbd22e28 | ||
|
|
4689d56955 | ||
|
|
aa1b2808e7 | ||
|
|
40ad4bdbd8 | ||
|
|
b6510d66e0 | ||
|
|
4ea33ea482 | ||
|
|
e13d410b4a | ||
|
|
72da7e6c54 | ||
|
|
fb05960d79 | ||
|
|
7bd0943412 | ||
|
|
bb2649d063 | ||
|
|
d743bdbf5a | ||
|
|
61890f19bc | ||
|
|
b756a8edef | ||
|
|
adcb2f1aa8 | ||
|
|
e574f4516f | ||
|
|
2ac9c11ec9 | ||
|
|
1c470ab9e3 | ||
|
|
08b8a8e3af | ||
|
|
11ee1a7dcb | ||
|
|
a281b8c74e | ||
|
|
5cb37148c6 | ||
|
|
05878d3176 | ||
|
|
d1c42262d6 | ||
|
|
8dcc114873 | ||
|
|
c54cf26848 | ||
|
|
bfb548636e | ||
|
|
36e1b2ba08 | ||
|
|
301ac279ff | ||
|
|
08d21ccba7 | ||
|
|
62876ca377 | ||
|
|
10f94148af | ||
|
|
31502c2ebc | ||
|
|
62b29ecb65 | ||
|
|
67337e013a | ||
|
|
f987fa13ea | ||
|
|
73dfe631ce | ||
|
|
83ca8147ca | ||
|
|
1c11e7f97b | ||
|
|
aefae79186 | ||
|
|
4b05a9bb6f | ||
|
|
2453719a87 | ||
|
|
ea929b00e3 | ||
|
|
ede940a398 | ||
|
|
67da853146 | ||
|
|
624befd704 | ||
|
|
203539841d | ||
|
|
262db23f7d | ||
|
|
28ea22f0e1 | ||
|
|
3f349c3531 | ||
|
|
9928e8562a | ||
|
|
b1e3fc5761 | ||
|
|
b2390f1caf | ||
|
|
8cc9aeba4a | ||
|
|
ba0823c38c | ||
|
|
b9379f2ddf | ||
|
|
38a950a6dc | ||
|
|
fb24dca019 | ||
|
|
07d131c945 | ||
|
|
0c1c710afe | ||
|
|
15cd93c30f | ||
|
|
a5d9e17a8c | ||
|
|
a82926dd0d | ||
|
|
12435b997a | ||
|
|
5945be95cf | ||
|
|
5c2e7ce407 | ||
|
|
834e894b1d | ||
|
|
d25dac69d2 | ||
|
|
3cc4173399 | ||
|
|
36ab16c1ed | ||
|
|
5356373681 | ||
|
|
f45a2643f2 | ||
|
|
e55933706d | ||
|
|
3b3d696e45 | ||
|
|
281351e6b3 | ||
|
|
34089aec70 | ||
|
|
3658d0e039 | ||
|
|
7a10636128 | ||
|
|
604ba7f4bc | ||
|
|
27b7fb54e8 | ||
|
|
d351aa842c | ||
|
|
59da705b8f | ||
|
|
99b8f16d88 | ||
|
|
06ffe722d4 | ||
|
|
6264104642 | ||
|
|
c97812c340 | ||
|
|
bd4c578230 | ||
|
|
6ec2949b6f | ||
|
|
1ff23ebfd9 | ||
|
|
7698990e37 | ||
|
|
17e092afb3 | ||
|
|
2db65b9d1f | ||
|
|
c6436f47eb | ||
|
|
e88b4a4412 | ||
|
|
01a177adfb | ||
|
|
052b5e0ea8 | ||
|
|
68cd447109 | ||
|
|
4a8a5ed8d4 | ||
|
|
84077505b0 | ||
|
|
c4554b71d3 | ||
|
|
63ce743571 | ||
|
|
6cf53c611b | ||
|
|
d8720ee325 | ||
|
|
73501f3ad3 | ||
|
|
54ee655472 | ||
|
|
571b9fb8e0 | ||
|
|
cdd6b243ff | ||
|
|
fca77a868f | ||
|
|
424e854778 | ||
|
|
0979d565bb | ||
|
|
f5e6ca3e10 | ||
|
|
2bde07561f | ||
|
|
16c92cc739 | ||
|
|
8b31a918a4 | ||
|
|
ee0bd49918 | ||
|
|
a625eeeac8 | ||
|
|
bfcd795687 | ||
|
|
e2a9be9cec | ||
|
|
37dd075309 | ||
|
|
89769fb0e5 | ||
|
|
b24fac3dd8 | ||
|
|
4794fe495c | ||
|
|
869fdbcc6a | ||
|
|
702e6d3b51 | ||
|
|
2913e13a30 | ||
|
|
5f1e37b7fa | ||
|
|
ec0209b175 | ||
|
|
a17dcbde0f | ||
|
|
fbd159a23a | ||
|
|
599a6bf050 | ||
|
|
185b16a858 | ||
|
|
e7e3ed4923 | ||
|
|
47df5476ba | ||
|
|
d7c516ab00 | ||
|
|
50838970ec | ||
|
|
1d15ee7034 | ||
|
|
7029541b4f | ||
|
|
ada8e447cc | ||
|
|
1841fc18fa | ||
|
|
94ee465682 | ||
|
|
3e021b3a75 | ||
|
|
0643f149b7 | ||
|
|
939768eec0 | ||
|
|
f2235dacdc | ||
|
|
50017c28da | ||
|
|
85b2a03a42 | ||
|
|
829087550d | ||
|
|
dd6f71fe85 | ||
|
|
92a928680c | ||
|
|
d008b1970c | ||
|
|
4affbb8c6b | ||
|
|
ddb2ea4b5f | ||
|
|
a69683183f | ||
|
|
8d34f87667 | ||
|
|
128c4fe222 | ||
|
|
b10141d71f | ||
|
|
68e0b35364 | ||
|
|
1324f5e59c | ||
|
|
7759aacb35 | ||
|
|
fd6f7cd881 | ||
|
|
3fdeb38bb7 | ||
|
|
e27f5d0460 | ||
|
|
0720128bd4 | ||
|
|
540472a093 | ||
|
|
daca78b6cd | ||
|
|
4195840b2c | ||
|
|
57c529758e | ||
|
|
5ba9a0eb3f | ||
|
|
b8888a5d46 | ||
|
|
0857f979ff | ||
|
|
11f4ae019c | ||
|
|
0ffeb0c5af | ||
|
|
d6f6b41145 | ||
|
|
64daaeb310 | ||
|
|
0646b0060e | ||
|
|
c794ca85fd | ||
|
|
5b4019dd3d | ||
|
|
a03ccd7b59 | ||
|
|
4b64aad5ce | ||
|
|
d146ff8794 | ||
|
|
5349bf7628 | ||
|
|
a79e4d1bb3 | ||
|
|
f462435dc2 | ||
|
|
48ad614441 | ||
|
|
f699516fdb | ||
|
|
ca5cbb640a | ||
|
|
0a96259ddf | ||
|
|
d99b9c04e4 | ||
|
|
64d261e053 | ||
|
|
eb027d98aa | ||
|
|
a95727b654 | ||
|
|
4e636d7eec | ||
|
|
3cd53f617a | ||
|
|
b1684e82d8 | ||
|
|
a55027b838 | ||
|
|
28678acf74 | ||
|
|
ce6594c8cc | ||
|
|
75855d5450 | ||
|
|
f248699a30 | ||
|
|
29594726ca | ||
|
|
0a41b07297 | ||
|
|
e45cb7fac1 | ||
|
|
489dbfc72a | ||
|
|
a89ae7d77a | ||
|
|
a1eeff4034 | ||
|
|
0e1013a570 | ||
|
|
4562b06a60 | ||
|
|
3c96218338 | ||
|
|
f0a4ea099c | ||
|
|
c8d6693fba | ||
|
|
81bbdfe413 | ||
|
|
0e362943bf | ||
|
|
1e37fed90b | ||
|
|
aafcfef387 | ||
|
|
4b83d8160f | ||
|
|
73a41707e5 | ||
|
|
c989c533e8 | ||
|
|
707dc8c65c | ||
|
|
4c6157a06e | ||
|
|
f973396821 | ||
|
|
e73216d4c1 | ||
|
|
e6de26736b | ||
|
|
d131addd63 | ||
|
|
0c7705beff | ||
|
|
08b11addec | ||
|
|
555f96cfaf | ||
|
|
59ffacb3df | ||
|
|
83acb66f00 | ||
|
|
1f9ae45875 | ||
|
|
ffa628be2d | ||
|
|
8916f6f829 | ||
|
|
215c8fd261 | ||
|
|
061cc908a7 | ||
|
|
18a519f9ed | ||
|
|
7970c9dbe5 | ||
|
|
5ca0c066e2 | ||
|
|
563728c7b8 | ||
|
|
31a72b6562 | ||
|
|
d3dfbc3034 | ||
|
|
f143a6ba08 | ||
|
|
28a65923b6 | ||
|
|
4ca3df77b3 | ||
|
|
4cbe264869 | ||
|
|
b6b65b6bf7 | ||
|
|
e7cc42a927 | ||
|
|
bba3ca8cc0 | ||
|
|
8423e2d245 | ||
|
|
fc263718a1 | ||
|
|
c3a99cf5a4 | ||
|
|
f6820ec615 | ||
|
|
226ad3fe22 | ||
|
|
a9b17e930c | ||
|
|
932ea7ba8f | ||
|
|
c720d78c39 | ||
|
|
8d21e441a0 | ||
|
|
16ecb1a9cb | ||
|
|
f68acca427 | ||
|
|
671d7e2beb | ||
|
|
52fc497412 | ||
|
|
2084ad318f | ||
|
|
b530c1a43d | ||
|
|
f2797a4153 | ||
|
|
659c326f89 | ||
|
|
534b07d120 | ||
|
|
de64fc8b8d | ||
|
|
1e234fcb73 | ||
|
|
fa9a7e725b | ||
|
|
95b2675f03 | ||
|
|
564902b886 | ||
|
|
071a04595a | ||
|
|
eaa4b76ede | ||
|
|
74a1713e99 | ||
|
|
5f5aa0b2f7 | ||
|
|
eef59fd40e | ||
|
|
361ff315e9 | ||
|
|
eeea8e530e | ||
|
|
8d5286703f | ||
|
|
74f2180fa4 | ||
|
|
d042169f2e | ||
|
|
1fd87bf664 | ||
|
|
eeaff6b553 | ||
|
|
6efd048fd6 | ||
|
|
6e9e694f66 | ||
|
|
44a0f1b505 | ||
|
|
9790211891 | ||
|
|
be18cc9f2d | ||
|
|
8caee09ea4 | ||
|
|
26f5305593 | ||
|
|
d33029027f | ||
|
|
339aaaec57 | ||
|
|
db2425c473 | ||
|
|
18731f6055 | ||
|
|
34f1f7a31d | ||
|
|
7ef153756b | ||
|
|
bf90509526 | ||
|
|
d853eca489 | ||
|
|
869ae01da9 | ||
|
|
d63996eea1 | ||
|
|
9bbc8eda9d | ||
|
|
9cc1b03c56 | ||
|
|
b1ab26e3ad | ||
|
|
96820418b5 | ||
|
|
385d9f16e9 | ||
|
|
d56fce37dd | ||
|
|
aef2c9e5cf | ||
|
|
89a05c580f | ||
|
|
b85e562980 | ||
|
|
a0e6628757 | ||
|
|
60a41524f0 | ||
|
|
6042395b81 | ||
|
|
8a5db8ce4b | ||
|
|
196d6e79e2 | ||
|
|
91f16215e5 | ||
|
|
9c675a7847 | ||
|
|
f9e09e87d6 | ||
|
|
73574d6293 | ||
|
|
0a5a42b32a | ||
|
|
de225205bd | ||
|
|
8a47d36480 | ||
|
|
d5f3ba8d8a | ||
|
|
782a06ce84 | ||
|
|
5cdafc50fb | ||
|
|
0ca3cdb9ae | ||
|
|
a1d6cbd5fd | ||
|
|
6c36778cac | ||
|
|
1c3a97a71a | ||
|
|
3489fe0cf4 | ||
|
|
74b6d9dff9 | ||
|
|
06ee9aa05c | ||
|
|
f0f40a8606 | ||
|
|
1f2c9879bd | ||
|
|
d1eb82bdf6 | ||
|
|
8167f623e3 | ||
|
|
9555e296a2 | ||
|
|
f460283fa1 | ||
|
|
79da8e5a37 | ||
|
|
a35ce22218 | ||
|
|
1c905da8c2 | ||
|
|
2b558768f1 | ||
|
|
7607c4c882 | ||
|
|
c9f4813ce1 | ||
|
|
0428e27039 | ||
|
|
e30da2168d | ||
|
|
0cd20768f4 | ||
|
|
ab31f34862 | ||
|
|
9a4ff5cb43 | ||
|
|
f66c91e18e | ||
|
|
a235745be7 | ||
|
|
9516da01e3 | ||
|
|
7657bd2375 | ||
|
|
0adcea9e7c | ||
|
|
aa8ad60083 | ||
|
|
5d98a86a6b | ||
|
|
4418fdaed6 | ||
|
|
c58c45c917 | ||
|
|
45eba5cabd | ||
|
|
3ab0d0d865 | ||
|
|
a6803081ab | ||
|
|
8debed805b | ||
|
|
fc9835512d | ||
|
|
5f0cab8cc2 | ||
|
|
bd391963bc | ||
|
|
97fa28fb10 | ||
|
|
67d5b39c96 | ||
|
|
dbceef2581 | ||
|
|
5b22ccfca6 | ||
|
|
714c254bab | ||
|
|
90f4db9158 | ||
|
|
eed470ddae | ||
|
|
49f72881f4 | ||
|
|
a76674032d | ||
|
|
ec392a7f9a | ||
|
|
8a2ae6c480 | ||
|
|
b3796a8e24 | ||
|
|
b9144ff987 | ||
|
|
5344949c71 | ||
|
|
05cbba9a35 | ||
|
|
325c6135cf | ||
|
|
fdea19a45b | ||
|
|
fad63c0c18 | ||
|
|
f002560616 | ||
|
|
8e7d52e645 | ||
|
|
d119594cbf | ||
|
|
84f7da6e93 | ||
|
|
22e1bafe1b | ||
|
|
3f8e42e510 | ||
|
|
9704fb04d9 | ||
|
|
dcfaf1e2b9 | ||
|
|
42f7dc1947 | ||
|
|
eb1a597456 | ||
|
|
8368815db5 | ||
|
|
9c6295d0d8 | ||
|
|
4d19f881e9 | ||
|
|
3a8820397b | ||
|
|
85b1c1fe97 | ||
|
|
a4de9e94dd | ||
|
|
0dd2c7fe24 | ||
|
|
f22c3b549e | ||
|
|
3c60b3d2c9 | ||
|
|
f2d36b84b5 | ||
|
|
9af08ef26a | ||
|
|
b4be1184fd | ||
|
|
c60e0d389c | ||
|
|
d658fe7709 | ||
|
|
54036a2b4d | ||
|
|
2da9572a45 | ||
|
|
306825aa90 | ||
|
|
c797073c05 | ||
|
|
d9d65d59d1 | ||
|
|
aad29e4487 | ||
|
|
b00985f99f | ||
|
|
538a16a5fb | ||
|
|
300a8d3a89 | ||
|
|
e3b7c5fce7 | ||
|
|
2e87ebe800 | ||
|
|
7ed9e7cdd4 | ||
|
|
7ff9c2885d | ||
|
|
18c8bbb0fc | ||
|
|
9a49fb9450 | ||
|
|
84457bc7b4 | ||
|
|
15f1e2c85c | ||
|
|
15e828e975 | ||
|
|
e4626ee52b | ||
|
|
1866c9c7ef | ||
|
|
a0f91aa814 | ||
|
|
a89c7b1a70 | ||
|
|
ded1376957 | ||
|
|
252040f03b | ||
|
|
d29abc2724 | ||
|
|
44c35d2644 | ||
|
|
f9b972349d | ||
|
|
e06cadd761 | ||
|
|
ee45d6b48f | ||
|
|
d915b280d4 | ||
|
|
39d90fe881 | ||
|
|
b9da1f18b4 | ||
|
|
69a0934173 | ||
|
|
289de85754 | ||
|
|
0ec95041d9 | ||
|
|
fcb6f78d54 | ||
|
|
29e9740668 | ||
|
|
ea8c6d5cce | ||
|
|
e4c951984a | ||
|
|
0071afb205 | ||
|
|
d3c7ac75be | ||
|
|
55d7420abf | ||
|
|
489b56456f | ||
|
|
1f24fcb364 | ||
|
|
722b31edee | ||
|
|
765f0393b0 | ||
|
|
6868ef044b | ||
|
|
5dd0622e40 | ||
|
|
48bdab1dcf | ||
|
|
aee483e9f1 | ||
|
|
8542b9bf67 | ||
|
|
feaf6f2501 | ||
|
|
d7d30aa972 | ||
|
|
91c23d1f7d | ||
|
|
57479edc59 | ||
|
|
4b462eaae9 | ||
|
|
c60fb3bc25 | ||
|
|
b17c34402d | ||
|
|
6ad71bd222 | ||
|
|
ccc08be0ee | ||
|
|
2a2fc80931 | ||
|
|
9ebca91775 | ||
|
|
456fc23463 | ||
|
|
eb17562f4d | ||
|
|
b7dbfd5cfc | ||
|
|
cdc7ab562a | ||
|
|
e6b5552cba | ||
|
|
eecf92183f | ||
|
|
11656382a7 | ||
|
|
e4d788ad0b | ||
|
|
3017442702 | ||
|
|
ba37db275c | ||
|
|
521e669879 | ||
|
|
12e302c10a | ||
|
|
7220af3ef0 | ||
|
|
42f4e0fa86 | ||
|
|
022d066fe0 | ||
|
|
4c9d7cbeed | ||
|
|
1541e382e4 | ||
|
|
1d9488d24f | ||
|
|
6cbc1afb9b | ||
|
|
3f86b660ed | ||
|
|
4603f2d9ca | ||
|
|
da818cf420 | ||
|
|
86a2ed652d | ||
|
|
269761f222 | ||
|
|
53ca3046b3 | ||
|
|
f484156d8e | ||
|
|
1da8712a4a | ||
|
|
dd47eba88c | ||
|
|
0ade8ff7a2 | ||
|
|
6a528b5fdb | ||
|
|
7f63ddc9ea | ||
|
|
d6b326c134 | ||
|
|
d944298dd7 | ||
|
|
0136ebd2b4 | ||
|
|
45f8def1ed | ||
|
|
7c6e8eeefc | ||
|
|
e81e48cde3 | ||
|
|
8eebb6ea2d | ||
|
|
ad8290ebcb | ||
|
|
15b6f6268b | ||
|
|
92d5af7446 | ||
|
|
d57425a15e | ||
|
|
a457c06500 | ||
|
|
906bbae899 | ||
|
|
e360e57a5b | ||
|
|
c5753a013c | ||
|
|
691b083364 | ||
|
|
b74a35b9d1 | ||
|
|
82269462a4 | ||
|
|
d7943aab28 | ||
|
|
446eb8e978 | ||
|
|
d91a99c833 | ||
|
|
dc00870461 | ||
|
|
b8f578862e | ||
|
|
dc24c05229 | ||
|
|
f62cf6818b | ||
|
|
c05e9da9c5 | ||
|
|
6c00194d35 | ||
|
|
6bc3f82afe | ||
|
|
12e46deea2 | ||
|
|
8608d010b8 | ||
|
|
9d4d1acf2d | ||
|
|
23087447f1 | ||
|
|
3008e4e60f | ||
|
|
9d52ed5ff6 | ||
|
|
5f047633c3 | ||
|
|
d3be1f1e2c | ||
|
|
c3b1cf7c35 | ||
|
|
682345da22 | ||
|
|
82f289c42e | ||
|
|
78eae99bd4 | ||
|
|
9ec7bb8d41 | ||
|
|
2b9bfbc309 | ||
|
|
e50d04077b | ||
|
|
b6fcaacb77 | ||
|
|
939da4e551 | ||
|
|
f30ce1f9eb | ||
|
|
343588b2a0 | ||
|
|
77b13ce9d4 | ||
|
|
7cb41d2ca9 | ||
|
|
8bbc9e6502 | ||
|
|
e29a0df3fd | ||
|
|
0eba04aac0 | ||
|
|
b78210e3be | ||
|
|
958de21be8 | ||
|
|
0eb4742982 | ||
|
|
78b1bf8f25 | ||
|
|
08f2741871 | ||
|
|
98b24ae630 | ||
|
|
7fc056c8e3 | ||
|
|
0411623857 | ||
|
|
365d71264f | ||
|
|
0d4d51fc39 | ||
|
|
b21745808b | ||
|
|
e4d5271d58 | ||
|
|
8f2f3bf75d | ||
|
|
9e96eba98f | ||
|
|
0441c83fd7 | ||
|
|
d8405052d8 | ||
|
|
cc02b07ff0 | ||
|
|
2d6aac7d6f | ||
|
|
589d43f0e5 | ||
|
|
13c1d1df7a | ||
|
|
08ade44dc8 | ||
|
|
8fb1c76247 | ||
|
|
3ad9053d65 | ||
|
|
8fe07e0f07 | ||
|
|
09b069c129 | ||
|
|
b2db083f39 | ||
|
|
53e2f3e263 | ||
|
|
945fbbc065 | ||
|
|
4dc9c7714c | ||
|
|
7302ac5871 | ||
|
|
1cfad27d6f | ||
|
|
d82fe95076 | ||
|
|
8f8df4971c | ||
|
|
fd66569950 | ||
|
|
e97d9fb0b2 | ||
|
|
04424c2a7c | ||
|
|
241e2828e7 | ||
|
|
5f6a0141f0 | ||
|
|
ef2f71859c | ||
|
|
fdaeeb5d01 | ||
|
|
e594ffe0f8 | ||
|
|
9f8c32ce8f | ||
|
|
762eb07dd4 | ||
|
|
0300458ba8 | ||
|
|
3959fcdc88 | ||
|
|
ea76c18f59 | ||
|
|
d125ecc671 | ||
|
|
7d9b90a1f3 | ||
|
|
7402c27b6a | ||
|
|
4e762e2063 | ||
|
|
0afe98b399 | ||
|
|
daed059c47 | ||
|
|
f1ce0fab8b | ||
|
|
b5d3f505e3 | ||
|
|
6c8f688f33 | ||
|
|
ed1b601a84 | ||
|
|
add541f67f | ||
|
|
bea8eb799f | ||
|
|
3cac48e86f | ||
|
|
64722da4a7 | ||
|
|
ada1e624d8 | ||
|
|
69f83cb905 | ||
|
|
807873f685 | ||
|
|
8d4be848b0 | ||
|
|
59a7c46482 | ||
|
|
eabfeb9502 | ||
|
|
291240dd94 | ||
|
|
2f6ed47168 | ||
|
|
9a73568c7a | ||
|
|
acdef87be7 | ||
|
|
b14546605d | ||
|
|
5ad46106f4 | ||
|
|
3e9be9eed3 | ||
|
|
7318a7b767 | ||
|
|
b78682f413 | ||
|
|
e50659af09 | ||
|
|
3454e5ac77 | ||
|
|
9e26aeea1d | ||
|
|
d7715b05ee | ||
|
|
db433efbef | ||
|
|
f1f8c887c6 | ||
|
|
9ae4745ca5 | ||
|
|
726d9c8ec5 | ||
|
|
a9bfa4e79b | ||
|
|
8e6bba143a | ||
|
|
feeba77f16 | ||
|
|
ea41a0e842 | ||
|
|
74b7500181 | ||
|
|
594ff8cd3d | ||
|
|
337f5f9b98 | ||
|
|
41445a1b48 | ||
|
|
269763fa0c | ||
|
|
fa90eeac55 | ||
|
|
edceffdaaf | ||
|
|
ce25fc658b | ||
|
|
b27db3e2e7 | ||
|
|
622d4214f7 | ||
|
|
0c53b5310a | ||
|
|
45ff86eae5 | ||
|
|
47316b0fb7 | ||
|
|
c09be02e4e | ||
|
|
bd59398cab | ||
|
|
8080ebceb4 | ||
|
|
1e2521c37a | ||
|
|
b744491dd2 | ||
|
|
2a089f7d90 | ||
|
|
088e3e5374 | ||
|
|
bac8a3092f | ||
|
|
e56da17957 | ||
|
|
71b2e714ee | ||
|
|
1b06afb81c | ||
|
|
819e48b03a | ||
|
|
1861c1feb6 | ||
|
|
0efccc4758 | ||
|
|
a9feeaa1c9 | ||
|
|
f9c869f521 | ||
|
|
9c766d76f3 | ||
|
|
333acccff6 | ||
|
|
1790ebf567 | ||
|
|
6354b68bae | ||
|
|
41b10fd5e4 | ||
|
|
4ad540412a | ||
|
|
8916cf273e | ||
|
|
b2923d0fc4 | ||
|
|
8fc0018cb9 | ||
|
|
d0f57efe0b | ||
|
|
595ff63b72 | ||
|
|
9990046abb | ||
|
|
8dacf72b3c | ||
|
|
2801838ffa | ||
|
|
59b34c2b3f | ||
|
|
f55f85aa14 | ||
|
|
627a80419a | ||
|
|
4bc482bc85 | ||
|
|
0a1257a23a | ||
|
|
51d99248d7 | ||
|
|
af9aa74337 | ||
|
|
321f5e615b | ||
|
|
95c31f3e17 | ||
|
|
cf69dbe1dc | ||
|
|
e92241bf97 | ||
|
|
44dc37ef6d | ||
|
|
6b0bef61a5 | ||
|
|
0c227be02d | ||
|
|
08794bad74 | ||
|
|
44693dd23a | ||
|
|
75a7be41eb | ||
|
|
913b09570c | ||
|
|
1c9b5dfd00 | ||
|
|
2954ae917b | ||
|
|
736ddaeca4 | ||
|
|
b909e32201 | ||
|
|
bcff74327b | ||
|
|
e60b63e72f | ||
|
|
2bf5d2b4e5 | ||
|
|
e1d09349ff | ||
|
|
f07c8108fc | ||
|
|
39f5078d6b | ||
|
|
1d54761d48 | ||
|
|
7cb9b2da66 | ||
|
|
b1896e3737 | ||
|
|
6fa78bdb04 | ||
|
|
ee96f7d937 | ||
|
|
129ca0e39f | ||
|
|
906703db5f | ||
|
|
0cd4a2b4ec | ||
|
|
aef8aaa0bd | ||
|
|
428fbb8622 | ||
|
|
b9f03e7d80 | ||
|
|
db686388b9 | ||
|
|
626cba4002 | ||
|
|
37d4a6b9e2 | ||
|
|
12c4561aba | ||
|
|
fed49e3718 | ||
|
|
3af37d3984 | ||
|
|
0f49a11228 | ||
|
|
27d3e165b0 | ||
|
|
e941c22f6c | ||
|
|
7281e4deb6 | ||
|
|
f2191e94b3 | ||
|
|
349ebfe4db | ||
|
|
708365c4ac | ||
|
|
0e9ea0aff1 | ||
|
|
63ba05a193 | ||
|
|
4b702815cf | ||
|
|
55e66ebcac | ||
|
|
dcd8b3699c | ||
|
|
0e2d13172a | ||
|
|
2e2556fdad | ||
|
|
859a7538e1 | ||
|
|
0d1543ee8a | ||
|
|
d3a98dd355 | ||
|
|
ad10125303 | ||
|
|
b89e866d39 | ||
|
|
afbaf1cfe0 | ||
|
|
b3be8b30e7 | ||
|
|
8bfab8f73d | ||
|
|
c6ad2c9ad2 | ||
|
|
3b44d9972e | ||
|
|
af736c98f2 | ||
|
|
f1377fa217 | ||
|
|
2ba146b9ff | ||
|
|
2361607aa3 | ||
|
|
86ffc80098 | ||
|
|
7f6915eb59 | ||
|
|
d69bcad028 | ||
|
|
4cb45e2712 | ||
|
|
b7a0ad703a | ||
|
|
7610b9a975 | ||
|
|
7d95f621df | ||
|
|
bba210e112 | ||
|
|
3a97e20bde | ||
|
|
4fe7ea00b0 | ||
|
|
3ec8ecd4de | ||
|
|
401e65e852 | ||
|
|
e7c5b691a0 | ||
|
|
9f3ea8da67 | ||
|
|
d1269b441d | ||
|
|
7615743aa5 | ||
|
|
dcaa0eeea4 | ||
|
|
1d5e2f703e | ||
|
|
4d84d624b1 | ||
|
|
633a6a0ee6 | ||
|
|
c7bcd3f438 | ||
|
|
d3a29a6f16 | ||
|
|
827711ca89 | ||
|
|
76e98f74fa | ||
|
|
fb09f4b22d | ||
|
|
bb06585748 | ||
|
|
c76ba1dcc7 | ||
|
|
a115301b04 | ||
|
|
72917117a9 | ||
|
|
6567739236 | ||
|
|
4aa6b47c0e | ||
|
|
03558b012c | ||
|
|
3288efdad6 | ||
|
|
3902a343f3 | ||
|
|
882b7d0391 | ||
|
|
81f082825d | ||
|
|
392fd6fed3 | ||
|
|
51afed4041 | ||
|
|
17e3b71d9c | ||
|
|
6e75089f3a | ||
|
|
6dc640b129 | ||
|
|
27cbaac343 | ||
|
|
fa4006619e | ||
|
|
cb8fe8462a | ||
|
|
abd51a5511 | ||
|
|
a0cc1e6b0c | ||
|
|
50399c6bfa | ||
|
|
de48c1be44 | ||
|
|
0786ec4b66 | ||
|
|
db319e0ebc | ||
|
|
4fc568856a | ||
|
|
4c6771669b | ||
|
|
9bca2a91c9 | ||
|
|
66eaaf5a48 | ||
|
|
9837f0e2e1 | ||
|
|
6b8ffb4c68 | ||
|
|
f35dd34da9 | ||
|
|
ed19e4fa08 | ||
|
|
661e1a4f90 | ||
|
|
5826de76ca | ||
|
|
05888740e5 | ||
|
|
41f3b0c333 | ||
|
|
70f3e72a20 | ||
|
|
e873afd40b | ||
|
|
2777c2937a | ||
|
|
798903e4cc | ||
|
|
58622ba18f | ||
|
|
c368dcd5b7 | ||
|
|
0b4c652ce7 | ||
|
|
dbaacc411a | ||
|
|
1850185d1e | ||
|
|
2e9d445d36 | ||
|
|
aed89d82fb | ||
|
|
231adac6d8 | ||
|
|
587c4e5915 | ||
|
|
55f1cbf18f | ||
|
|
38168a545b | ||
|
|
43c6df49d7 | ||
|
|
f1c59faf72 | ||
|
|
5f7019325c | ||
|
|
fe4dae8518 | ||
|
|
1f848b205b | ||
|
|
742c470d81 | ||
|
|
5ead3342cc | ||
|
|
b95dc2ecce | ||
|
|
4d0950215f | ||
|
|
da0ce9fe0d | ||
|
|
ca62e720b5 | ||
|
|
c4b1795396 | ||
|
|
fd2e47ed73 | ||
|
|
d5f2255a68 | ||
|
|
05b58e9263 | ||
|
|
4a91c27e4b | ||
|
|
3a03d46d8d | ||
|
|
f03aff7006 | ||
|
|
043b8a3105 | ||
|
|
1dd9984521 | ||
|
|
d2be7f8c8f | ||
|
|
88dc202db2 | ||
|
|
083d54b008 | ||
|
|
87d77efa57 | ||
|
|
35c4a41d7b | ||
|
|
1ca3ca07d5 | ||
|
|
d673846e3d | ||
|
|
f62b7afede | ||
|
|
e65770a53a | ||
|
|
a92a741932 | ||
|
|
45f67191ba | ||
|
|
93f5da325b | ||
|
|
8fb955e182 | ||
|
|
9f5e6a4b37 | ||
|
|
f43738446e | ||
|
|
923a46d304 | ||
|
|
b9b5eaccae | ||
|
|
cda11491c2 | ||
|
|
98c539f662 | ||
|
|
9fb958b302 | ||
|
|
8e25e76439 | ||
|
|
62694da7e6 | ||
|
|
86064651af | ||
|
|
65daaeb617 | ||
|
|
08b39f50b3 | ||
|
|
d0f7e5ca4d | ||
|
|
4eb5058e68 | ||
|
|
1054193298 | ||
|
|
38c6cf0450 | ||
|
|
5b04b86867 | ||
|
|
a074bcfd56 | ||
|
|
f93179d946 | ||
|
|
2c347bc092 | ||
|
|
0f7119f468 | ||
|
|
2685a24705 | ||
|
|
371f72f4f1 | ||
|
|
c70c00043b | ||
|
|
50d0a88276 | ||
|
|
5bbf576dae | ||
|
|
5d334e9619 | ||
|
|
98f9353338 | ||
|
|
d3de7037e5 | ||
|
|
64431c6711 | ||
|
|
d4ce193dc8 | ||
|
|
606305aec4 | ||
|
|
a95f44d68b | ||
|
|
ef2dc4b9e1 | ||
|
|
9baca1772b | ||
|
|
04cd19349d | ||
|
|
1280e5bc8b | ||
|
|
dda90f956d | ||
|
|
bc4b599513 | ||
|
|
090d52d678 | ||
|
|
a47ad4842a |
34
.github/ISSUE_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<!--
|
||||
## Before you hit that Submit button....
|
||||
|
||||
This issue tracker is for problems with the Node-RED runtime, the editor or the core nodes.
|
||||
|
||||
If your issue is:
|
||||
- a general 'how-to' type question,
|
||||
- a feature request or suggestion for a change,
|
||||
- or problems with 3rd party (`node-red-contrib-`) nodes
|
||||
|
||||
please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack).
|
||||
|
||||
You could also consider asking a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/node-red) and tag it `node-red`.
|
||||
|
||||
That way the whole Node-RED user community can help, rather than rely on the core development team.
|
||||
|
||||
## So you have a real issue to raise...
|
||||
|
||||
To help us understand the issue, please fill-in as much of the following information as you can:
|
||||
-->
|
||||
|
||||
### What are the steps to reproduce?
|
||||
|
||||
### What happens?
|
||||
|
||||
### What do you expect to happen?
|
||||
|
||||
### Please tell us about your environment:
|
||||
|
||||
- [ ] Node-RED version:
|
||||
- [ ] node.js version:
|
||||
- [ ] npm version:
|
||||
- [ ] Platform/OS:
|
||||
- [ ] Browser:
|
||||
34
.github/PULL_REQUEST_TEMPLATE.md
vendored
Normal file
@@ -0,0 +1,34 @@
|
||||
<!--
|
||||
## Before you hit that Submit button....
|
||||
|
||||
Please read our [contribution guidelines](https://github.com/node-red/node-red/blob/master/CONTRIBUTING.md)
|
||||
before submitting a pull-request.
|
||||
|
||||
## Types of changes
|
||||
|
||||
What types of changes does your code introduce?
|
||||
Put an `x` in the boxes that apply
|
||||
-->
|
||||
|
||||
- [ ] Bugfix (non-breaking change which fixes an issue)
|
||||
- [ ] New feature (non-breaking change which adds functionality)
|
||||
|
||||
<!--
|
||||
If you want to raise a pull-request with a new feature, or a refactoring
|
||||
of existing code, it **may well get rejected** if it hasn't been discussed on
|
||||
the [forum](https://discourse.nodered.org) or
|
||||
[slack team](https://nodered.org/slack) first.
|
||||
|
||||
-->
|
||||
|
||||
## Proposed changes
|
||||
|
||||
<!-- Describe the nature of this change. What problem does it address? -->
|
||||
|
||||
## Checklist
|
||||
<!-- 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.
|
||||
- [ ] I have run `grunt` to verify the unit tests pass
|
||||
- [ ] I have added suitable unit tests to cover the new/changed functionality
|
||||
10
.jshintrc
@@ -2,12 +2,18 @@
|
||||
"asi": true, // allow missing semicolons
|
||||
"curly": true, // require braces
|
||||
"eqnull": true, // ignore ==null
|
||||
//"eqeqeq": true, // enforce ===
|
||||
"freeze": true, // don't allow override
|
||||
"indent": 4, // default indent of 4
|
||||
"forin": true, // require property filtering in "for in" loops
|
||||
"immed": true, // require immediate functions to be wrapped in ( )
|
||||
"nonbsp": true, // warn on unexpected whitespace breaking chars
|
||||
//"strict": true, // commented out for now as it causes 100s of warnings, but want to get there eventually
|
||||
//"unused": true, // Check for unused functions and variables
|
||||
"loopfunc": true, // allow functions to be defined in loops
|
||||
//"expr": true, // allow ternery operator syntax...
|
||||
"sub": true // don't warn that foo['bar'] should be written as foo.bar
|
||||
//"expr": true, // allow ternery operator syntax...
|
||||
"shadow": true, // allow variable shadowing (re-use of names...)
|
||||
"sub": true, // don't warn that foo['bar'] should be written as foo.bar
|
||||
"proto": true, // allow setting of __proto__ in node < v0.12,
|
||||
"esversion": 6 // allow es6
|
||||
}
|
||||
|
||||
32
.travis.yml
@@ -1,26 +1,12 @@
|
||||
sudo: false
|
||||
language: node_js
|
||||
env:
|
||||
- CXX="g++-4.8"
|
||||
addons:
|
||||
apt:
|
||||
sources:
|
||||
- ubuntu-toolchain-r-test
|
||||
packages:
|
||||
- g++-4.8
|
||||
- gcc-4.8
|
||||
matrix:
|
||||
allow_failures:
|
||||
- node_js: "5"
|
||||
before_install:
|
||||
- npm install -g npm@latest-2
|
||||
node_js:
|
||||
- "5"
|
||||
- "4"
|
||||
- "0.12"
|
||||
- "0.10"
|
||||
script:
|
||||
- istanbul cover ./node_modules/.bin/grunt --report lcovonly && istanbul report text && ( cat coverage/lcov.info | ./node_modules/coveralls/bin/coveralls.js || true ) && rm -rf coverage
|
||||
before_script:
|
||||
- npm install -g istanbul
|
||||
- npm install coveralls
|
||||
include:
|
||||
- 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_js: "8"
|
||||
- node_js: "6"
|
||||
- node_js: "4"
|
||||
|
||||
1366
CHANGELOG.md
Normal file
74
CODE_OF_CONDUCT.md
Normal file
@@ -0,0 +1,74 @@
|
||||
# Contributor Covenant Code of Conduct
|
||||
|
||||
## Our Pledge
|
||||
|
||||
In the interest of fostering an open and welcoming environment, we as
|
||||
contributors and maintainers pledge to making participation in our project and
|
||||
our community a harassment-free experience for everyone, regardless of age, body
|
||||
size, disability, ethnicity, gender identity and expression, level of experience,
|
||||
nationality, personal appearance, race, religion, or sexual identity and
|
||||
orientation.
|
||||
|
||||
## Our Standards
|
||||
|
||||
Examples of behavior that contributes to creating a positive environment
|
||||
include:
|
||||
|
||||
* Using welcoming and inclusive language
|
||||
* Being respectful of differing viewpoints and experiences
|
||||
* Gracefully accepting constructive criticism
|
||||
* Focusing on what is best for the community
|
||||
* Showing empathy towards other community members
|
||||
|
||||
Examples of unacceptable behavior by participants include:
|
||||
|
||||
* The use of sexualized language or imagery and unwelcome sexual attention or
|
||||
advances
|
||||
* Trolling, insulting/derogatory comments, and personal or political attacks
|
||||
* Public or private harassment
|
||||
* Publishing others' private information, such as a physical or electronic
|
||||
address, without explicit permission
|
||||
* Other conduct which could reasonably be considered inappropriate in a
|
||||
professional setting
|
||||
|
||||
## Our Responsibilities
|
||||
|
||||
Project maintainers are responsible for clarifying the standards of acceptable
|
||||
behavior and are expected to take appropriate and fair corrective action in
|
||||
response to any instances of unacceptable behavior.
|
||||
|
||||
Project maintainers have the right and responsibility to remove, edit, or
|
||||
reject comments, commits, code, wiki edits, issues, and other contributions
|
||||
that are not aligned to this Code of Conduct, or to ban temporarily or
|
||||
permanently any contributor for other behaviors that they deem inappropriate,
|
||||
threatening, offensive, or harmful.
|
||||
|
||||
## Scope
|
||||
|
||||
This Code of Conduct applies both within project spaces and in public spaces
|
||||
when an individual is representing the project or its community. Examples of
|
||||
representing a project or community include using an official project e-mail
|
||||
address, posting via an official social media account, or acting as an appointed
|
||||
representative at an online or offline event. Representation of a project may be
|
||||
further defined and clarified by project maintainers.
|
||||
|
||||
## Enforcement
|
||||
|
||||
Instances of abusive, harassing, or otherwise unacceptable behavior may be
|
||||
reported by contacting the project team at team@nodered.org. All
|
||||
complaints will be reviewed and investigated and will result in a response that
|
||||
is deemed necessary and appropriate to the circumstances. The project team is
|
||||
obligated to maintain confidentiality with regard to the reporter of an incident.
|
||||
Further details of specific enforcement policies may be posted separately.
|
||||
|
||||
Project maintainers who do not follow or enforce the Code of Conduct in good
|
||||
faith may face temporary or permanent repercussions as determined by other
|
||||
members of the project's leadership.
|
||||
|
||||
## Attribution
|
||||
|
||||
This Code of Conduct is adapted from the [Contributor Covenant][homepage], version 1.4,
|
||||
available at [http://contributor-covenant.org/version/1/4][version]
|
||||
|
||||
[homepage]: http://contributor-covenant.org
|
||||
[version]: http://contributor-covenant.org/version/1/4/
|
||||
@@ -7,6 +7,10 @@ We welcome contributions, but request you follow these guidelines.
|
||||
- [Pull-Requests](#pull-requests)
|
||||
- [Contributor License Agreement](#contributor-license-agreement)
|
||||
|
||||
This project adheres to the [Contributor Covenant 1.4](http://contributor-covenant.org/version/1/4/).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable
|
||||
behavior to the project's core team at team@nodered.org.
|
||||
|
||||
## Raising issues
|
||||
|
||||
Please raise any bug reports on the relevant project's issue tracker. Be sure to
|
||||
@@ -26,29 +30,21 @@ At a minimum, please include:
|
||||
|
||||
## Feature requests
|
||||
|
||||
For feature requests, please raise them on the [mailing list](https://groups.google.com/forum/#!forum/node-red).
|
||||
For feature requests, please raise them on the [forum](https://discourse.nodered.org).
|
||||
|
||||
## Pull-Requests
|
||||
|
||||
If you want to raise a pull-request with a new feature, or a refactoring
|
||||
of existing code, it may well get rejected if you haven't discussed it on
|
||||
the [mailing list](https://groups.google.com/forum/#!forum/node-red) first.
|
||||
the [forum](https://discourse.nodered.org) first.
|
||||
|
||||
### Contributor License Agreement
|
||||
All contributors need to sign the JS Foundation's Contributor License Agreement.
|
||||
It is an online process and quick to do. You can read the details of the agreement
|
||||
here: https://cla.js.foundation/node-red/node-red.
|
||||
|
||||
In order for us to accept pull-requests, the contributor must first complete
|
||||
a Contributor License Agreement (CLA). This clarifies the intellectual
|
||||
property license granted with any contribution. It is for your protection as a
|
||||
Contributor as well as the protection of IBM and its customers; it does not
|
||||
change your rights to use your own Contributions for any other purpose.
|
||||
If you raise a pull-request without having signed the CLA, you will be prompted
|
||||
to do so automatically.
|
||||
|
||||
You can download the CLAs here:
|
||||
|
||||
- [individual](http://nodered.org/cla/node-red-cla-individual.pdf)
|
||||
- [corporate](http://nodered.org/cla/node-red-cla-corporate.pdf)
|
||||
|
||||
If you are an IBMer, please contact us directly as the contribution process is
|
||||
slightly different.
|
||||
|
||||
### Coding standards
|
||||
|
||||
|
||||
264
Gruntfile.js
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013, 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -24,6 +24,10 @@ module.exports = function(grunt) {
|
||||
nodemonArgs.push(flowFile);
|
||||
}
|
||||
|
||||
var nonHeadless = grunt.option('non-headless');
|
||||
if (nonHeadless) {
|
||||
process.env.NODE_RED_NON_HEADLESS = 'true';
|
||||
}
|
||||
grunt.initConfig({
|
||||
pkg: grunt.file.readJSON('package.json'),
|
||||
paths: {
|
||||
@@ -41,6 +45,24 @@ module.exports = function(grunt) {
|
||||
core: { src: ["test/_spec.js","test/red/**/*_spec.js"]},
|
||||
nodes: { src: ["test/nodes/**/*_spec.js"]}
|
||||
},
|
||||
webdriver: {
|
||||
all: {
|
||||
configFile: 'test/editor/wdio.conf.js'
|
||||
}
|
||||
},
|
||||
mocha_istanbul: {
|
||||
options: {
|
||||
globals: ['expect'],
|
||||
timeout: 3000,
|
||||
ignoreLeaks: false,
|
||||
ui: 'bdd',
|
||||
reportFormats: ['lcov','html'],
|
||||
print: 'both'
|
||||
},
|
||||
all: { src: ["test/_spec.js","test/red/**/*_spec.js","test/nodes/**/*_spec.js"] },
|
||||
core: { src: ["test/_spec.js","test/red/**/*_spec.js"]},
|
||||
nodes: { src: ["test/nodes/**/*_spec.js"]}
|
||||
},
|
||||
jshint: {
|
||||
options: {
|
||||
jshintrc:true
|
||||
@@ -86,7 +108,7 @@ module.exports = function(grunt) {
|
||||
src: ['test/**/*.js']
|
||||
},
|
||||
options: {
|
||||
"expr": true
|
||||
"expr": true
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -95,55 +117,84 @@ module.exports = function(grunt) {
|
||||
separator: ";",
|
||||
},
|
||||
build: {
|
||||
src: [
|
||||
// Ensure editor source files are concatenated in
|
||||
// the right order
|
||||
"editor/js/main.js",
|
||||
"editor/js/events.js",
|
||||
"editor/js/i18n.js",
|
||||
"editor/js/settings.js",
|
||||
"editor/js/user.js",
|
||||
"editor/js/comms.js",
|
||||
"editor/js/ui/state.js",
|
||||
"editor/js/nodes.js",
|
||||
"editor/js/history.js",
|
||||
"editor/js/validators.js",
|
||||
"editor/js/ui/deploy.js",
|
||||
"editor/js/ui/menu.js",
|
||||
"editor/js/ui/keyboard.js",
|
||||
"editor/js/ui/tabs.js",
|
||||
"editor/js/ui/popover.js",
|
||||
"editor/js/ui/workspaces.js",
|
||||
"editor/js/ui/view.js",
|
||||
"editor/js/ui/sidebar.js",
|
||||
"editor/js/ui/palette.js",
|
||||
"editor/js/ui/tab-info.js",
|
||||
"editor/js/ui/tab-config.js",
|
||||
"editor/js/ui/editor.js",
|
||||
"editor/js/ui/clipboard.js",
|
||||
"editor/js/ui/library.js",
|
||||
"editor/js/ui/notifications.js",
|
||||
"editor/js/ui/subflow.js",
|
||||
"editor/js/ui/touch/radialMenu.js"
|
||||
],
|
||||
dest: "public/red/red.js"
|
||||
src: [
|
||||
// Ensure editor source files are concatenated in
|
||||
// the right order
|
||||
"editor/js/red.js",
|
||||
"editor/js/events.js",
|
||||
"editor/js/i18n.js",
|
||||
"editor/js/settings.js",
|
||||
"editor/js/user.js",
|
||||
"editor/js/comms.js",
|
||||
"editor/js/text/bidi.js",
|
||||
"editor/js/text/format.js",
|
||||
"editor/js/ui/state.js",
|
||||
"editor/js/nodes.js",
|
||||
"editor/js/history.js",
|
||||
"editor/js/validators.js",
|
||||
"editor/js/ui/utils.js",
|
||||
"editor/js/ui/common/editableList.js",
|
||||
"editor/js/ui/common/checkboxSet.js",
|
||||
"editor/js/ui/common/menu.js",
|
||||
"editor/js/ui/common/panels.js",
|
||||
"editor/js/ui/common/popover.js",
|
||||
"editor/js/ui/common/searchBox.js",
|
||||
"editor/js/ui/common/tabs.js",
|
||||
"editor/js/ui/common/stack.js",
|
||||
"editor/js/ui/common/typedInput.js",
|
||||
"editor/js/ui/actions.js",
|
||||
"editor/js/ui/deploy.js",
|
||||
"editor/js/ui/diff.js",
|
||||
"editor/js/ui/keyboard.js",
|
||||
"editor/js/ui/workspaces.js",
|
||||
"editor/js/ui/view.js",
|
||||
"editor/js/ui/view-navigator.js",
|
||||
"editor/js/ui/sidebar.js",
|
||||
"editor/js/ui/palette.js",
|
||||
"editor/js/ui/tab-info.js",
|
||||
"editor/js/ui/tab-config.js",
|
||||
"editor/js/ui/tab-context.js",
|
||||
"editor/js/ui/palette-editor.js",
|
||||
"editor/js/ui/editor.js",
|
||||
"editor/js/ui/editors/*.js",
|
||||
"editor/js/ui/tray.js",
|
||||
"editor/js/ui/clipboard.js",
|
||||
"editor/js/ui/library.js",
|
||||
"editor/js/ui/notifications.js",
|
||||
"editor/js/ui/search.js",
|
||||
"editor/js/ui/typeSearch.js",
|
||||
"editor/js/ui/subflow.js",
|
||||
"editor/js/ui/userSettings.js",
|
||||
"editor/js/ui/projects/projects.js",
|
||||
"editor/js/ui/projects/projectSettings.js",
|
||||
"editor/js/ui/projects/projectUserSettings.js",
|
||||
"editor/js/ui/projects/tab-versionControl.js",
|
||||
"editor/js/ui/touch/radialMenu.js"
|
||||
],
|
||||
dest: "public/red/red.js"
|
||||
},
|
||||
vendor: {
|
||||
files: {
|
||||
"public/vendor/vendor.js": [
|
||||
"editor/vendor/jquery/js/jquery-1.11.1.min.js",
|
||||
"editor/vendor/jquery/js/jquery-1.11.3.min.js",
|
||||
"editor/vendor/bootstrap/js/bootstrap.min.js",
|
||||
"editor/vendor/jquery/js/jquery-ui-1.10.3.custom.min.js",
|
||||
"editor/vendor/jquery/js/jquery.ui.touch-punch.min.js",
|
||||
"editor/vendor/marked/marked.min.js",
|
||||
"editor/vendor/orion/built-editor.min.js",
|
||||
"editor/vendor/d3/d3.v3.min.js",
|
||||
"editor/vendor/i18next/i18next.min.js"
|
||||
],
|
||||
"public/vendor/vendor.css": [
|
||||
"editor/vendor/orion/built-editor.css"
|
||||
// TODO: resolve relative resource paths in
|
||||
// bootstrap/FA/jquery
|
||||
],
|
||||
"public/vendor/jsonata/jsonata.min.js": [
|
||||
"node_modules/jsonata/jsonata-es5.min.js",
|
||||
"editor/vendor/jsonata/formatter.js"
|
||||
],
|
||||
"public/vendor/ace/worker-jsonata.js": [
|
||||
"node_modules/jsonata/jsonata-es5.min.js",
|
||||
"editor/vendor/jsonata/worker-jsonata.js"
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -151,7 +202,10 @@ module.exports = function(grunt) {
|
||||
uglify: {
|
||||
build: {
|
||||
files: {
|
||||
'public/red/red.min.js': 'public/red/red.js'
|
||||
'public/red/red.min.js': 'public/red/red.js',
|
||||
'public/red/main.min.js': 'public/red/main.js',
|
||||
'public/vendor/ace/mode-jsonata.js': 'editor/vendor/jsonata/mode-jsonata.js',
|
||||
'public/vendor/ace/snippets/jsonata.js': 'editor/vendor/jsonata/snippets-jsonata.js'
|
||||
}
|
||||
}
|
||||
},
|
||||
@@ -174,15 +228,21 @@ module.exports = function(grunt) {
|
||||
messages: {
|
||||
src: [
|
||||
'nodes/core/locales/en-US/messages.json',
|
||||
'locales/en-US/editor.json',
|
||||
'locales/en-US/runtime.json'
|
||||
'red/api/locales/en-US/editor.json',
|
||||
'red/runtime/locales/en-US/runtime.json'
|
||||
]
|
||||
},
|
||||
keymaps: {
|
||||
src: [
|
||||
'editor/js/keymap.json'
|
||||
]
|
||||
}
|
||||
},
|
||||
attachCopyright: {
|
||||
js: {
|
||||
src: [
|
||||
'public/red/red.min.js'
|
||||
'public/red/red.min.js',
|
||||
'public/red/main.min.js'
|
||||
]
|
||||
},
|
||||
css: {
|
||||
@@ -212,7 +272,7 @@ module.exports = function(grunt) {
|
||||
files: [
|
||||
'editor/js/**/*.js'
|
||||
],
|
||||
tasks: ['concat','uglify','attachCopyright:js']
|
||||
tasks: ['copy:build','concat','uglify','attachCopyright:js']
|
||||
},
|
||||
sass: {
|
||||
files: [
|
||||
@@ -223,10 +283,22 @@ module.exports = function(grunt) {
|
||||
json: {
|
||||
files: [
|
||||
'nodes/core/locales/en-US/messages.json',
|
||||
'locales/en-US/editor.json',
|
||||
'locales/en-US/runtime.json'
|
||||
'red/api/locales/en-US/editor.json',
|
||||
'red/runtime/locales/en-US/runtime.json'
|
||||
],
|
||||
tasks: ['jsonlint:messages']
|
||||
},
|
||||
keymaps: {
|
||||
files: [
|
||||
'editor/js/keymap.json'
|
||||
],
|
||||
tasks: ['jsonlint:keymaps','copy:build']
|
||||
},
|
||||
misc: {
|
||||
files: [
|
||||
'CHANGELOG.md'
|
||||
],
|
||||
tasks: ['copy:build']
|
||||
}
|
||||
},
|
||||
|
||||
@@ -238,7 +310,7 @@ module.exports = function(grunt) {
|
||||
args: nodemonArgs,
|
||||
ext: 'js,html,json',
|
||||
watch: [
|
||||
'red','nodes','locales'
|
||||
'red','nodes'
|
||||
]
|
||||
}
|
||||
}
|
||||
@@ -255,36 +327,50 @@ module.exports = function(grunt) {
|
||||
|
||||
copy: {
|
||||
build: {
|
||||
files:[{
|
||||
cwd: 'editor/images',
|
||||
src: '**',
|
||||
expand: true,
|
||||
dest: 'public/red/images/'
|
||||
},
|
||||
{
|
||||
cwd: 'editor/vendor',
|
||||
src: [
|
||||
'ace/**',
|
||||
//'bootstrap/css/**',
|
||||
'bootstrap/img/**',
|
||||
'jquery/css/**',
|
||||
'font-awesome/**'
|
||||
],
|
||||
expand: true,
|
||||
dest: 'public/vendor/'
|
||||
},
|
||||
{
|
||||
cwd: 'editor/icons',
|
||||
src: '**',
|
||||
expand: true,
|
||||
dest: 'public/icons/'
|
||||
},
|
||||
{
|
||||
expand: true,
|
||||
src: ['editor/index.html','editor/favicon.ico'],
|
||||
dest: 'public/',
|
||||
flatten: true
|
||||
}]
|
||||
files:[
|
||||
{
|
||||
src: 'editor/js/main.js',
|
||||
dest: 'public/red/main.js'
|
||||
},
|
||||
{
|
||||
src: 'editor/js/keymap.json',
|
||||
dest: 'public/red/keymap.json'
|
||||
},
|
||||
{
|
||||
cwd: 'editor/images',
|
||||
src: '**',
|
||||
expand: true,
|
||||
dest: 'public/red/images/'
|
||||
},
|
||||
{
|
||||
cwd: 'editor/vendor',
|
||||
src: [
|
||||
'ace/**',
|
||||
//'bootstrap/css/**',
|
||||
'bootstrap/img/**',
|
||||
'jquery/css/**',
|
||||
'font-awesome/**'
|
||||
],
|
||||
expand: true,
|
||||
dest: 'public/vendor/'
|
||||
},
|
||||
{
|
||||
cwd: 'editor/icons',
|
||||
src: '**',
|
||||
expand: true,
|
||||
dest: 'public/icons/'
|
||||
},
|
||||
{
|
||||
expand: true,
|
||||
src: ['editor/index.html','editor/favicon.ico'],
|
||||
dest: 'public/',
|
||||
flatten: true
|
||||
},
|
||||
{
|
||||
src: 'CHANGELOG.md',
|
||||
dest: 'public/red/about'
|
||||
}
|
||||
]
|
||||
},
|
||||
release: {
|
||||
files: [{
|
||||
@@ -302,8 +388,7 @@ module.exports = function(grunt) {
|
||||
'red/**',
|
||||
'public/**',
|
||||
'editor/templates/**',
|
||||
'bin/**',
|
||||
'locales/**'
|
||||
'bin/**'
|
||||
],
|
||||
dest: path.resolve('<%= paths.dist %>/node-red-<%= pkg.version %>')
|
||||
}]
|
||||
@@ -314,9 +399,9 @@ module.exports = function(grunt) {
|
||||
mode: '755'
|
||||
},
|
||||
release: {
|
||||
// Target-specific file/dir lists and/or options go here.
|
||||
src: [
|
||||
path.resolve('<%= paths.dist %>/node-red-<%= pkg.version %>/nodes/core/hardware/nrgpio*')
|
||||
path.resolve('<%= paths.dist %>/node-red-<%= pkg.version %>/nodes/core/hardware/nrgpio*'),
|
||||
path.resolve('<%= paths.dist %>/node-red-<%= pkg.version %>/red/runtime/storage/localfilesystem/projects/git/node-red-*sh')
|
||||
]
|
||||
}
|
||||
},
|
||||
@@ -345,11 +430,13 @@ module.exports = function(grunt) {
|
||||
grunt.loadNpmTasks('grunt-contrib-copy');
|
||||
grunt.loadNpmTasks('grunt-chmod');
|
||||
grunt.loadNpmTasks('grunt-jsonlint');
|
||||
grunt.loadNpmTasks('grunt-mocha-istanbul');
|
||||
grunt.loadNpmTasks('grunt-webdriver');
|
||||
|
||||
grunt.registerMultiTask('attachCopyright', function() {
|
||||
var files = this.data.src;
|
||||
var copyright = "/**\n"+
|
||||
" * Copyright 2013, 2015 IBM Corp.\n"+
|
||||
" * Copyright JS Foundation and other contributors, http://js.foundation\n"+
|
||||
" *\n"+
|
||||
" * Licensed under the Apache License, Version 2.0 (the \"License\");\n"+
|
||||
" * you may not use this file except in compliance with the License.\n"+
|
||||
@@ -365,7 +452,7 @@ module.exports = function(grunt) {
|
||||
" **/\n";
|
||||
|
||||
if (files) {
|
||||
for (var i=0;i<files.length;i++) {
|
||||
for (var i=0; i<files.length; i++) {
|
||||
var file = files[i];
|
||||
if (!grunt.file.exists(file)) {
|
||||
grunt.log.warn('File '+ file + ' not found');
|
||||
@@ -394,23 +481,27 @@ module.exports = function(grunt) {
|
||||
|
||||
grunt.registerTask('default',
|
||||
'Builds editor content then runs code style checks and unit tests on all components',
|
||||
['build','test-core','test-editor','test-nodes']);
|
||||
['build','jshint:editor','mocha_istanbul:all']);
|
||||
|
||||
grunt.registerTask('test-core',
|
||||
'Runs code style check and unit tests on core runtime code',
|
||||
['jshint:core','simplemocha:core']);
|
||||
['build','mocha_istanbul:core']);
|
||||
|
||||
grunt.registerTask('test-editor',
|
||||
'Runs code style check on editor code',
|
||||
['jshint:editor']);
|
||||
|
||||
grunt.registerTask('test-ui',
|
||||
'Builds editor content then runs unit tests on editor ui',
|
||||
['build','jshint:editor','webdriver:all']);
|
||||
|
||||
grunt.registerTask('test-nodes',
|
||||
'Runs unit tests on core nodes',
|
||||
['simplemocha:nodes']);
|
||||
['build','mocha_istanbul:nodes']);
|
||||
|
||||
grunt.registerTask('build',
|
||||
'Builds editor content',
|
||||
['clean:build','concat:build','concat:vendor','uglify:build','sass:build','jsonlint:messages','copy:build','attachCopyright']);
|
||||
['clean:build','jsonlint','concat:build','concat:vendor','copy:build','uglify:build','sass:build','attachCopyright']);
|
||||
|
||||
grunt.registerTask('dev',
|
||||
'Developer mode: run node-red, watch for source changes and build/restart',
|
||||
@@ -420,4 +511,7 @@ module.exports = function(grunt) {
|
||||
'Create distribution zip file',
|
||||
['build','clean:release','copy:release','chmod:release','compress:release']);
|
||||
|
||||
grunt.registerTask('coverage',
|
||||
'Run Istanbul code test coverage task',
|
||||
['build','mocha_istanbul:all']);
|
||||
};
|
||||
|
||||
1
LICENSE
@@ -1,3 +1,4 @@
|
||||
Copyright JS Foundation and other contributors, http://js.foundation
|
||||
|
||||
Apache License
|
||||
Version 2.0, January 2004
|
||||
|
||||
36
README.md
@@ -2,7 +2,7 @@
|
||||
|
||||
http://nodered.org
|
||||
|
||||
[](https://travis-ci.org/node-red/node-red)
|
||||
[](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.
|
||||
@@ -14,7 +14,7 @@ A visual tool for wiring the Internet of Things.
|
||||
Check out http://nodered.org/docs/getting-started/ for full instructions on getting
|
||||
started.
|
||||
|
||||
1. `sudo npm install -g node-red`
|
||||
1. `sudo npm install -g --unsafe-perm node-red`
|
||||
2. `node-red`
|
||||
3. Open <http://localhost:1880>
|
||||
|
||||
@@ -22,31 +22,29 @@ started.
|
||||
|
||||
More documentation can be found [here](http://nodered.org/docs).
|
||||
|
||||
For further help, or general discussion, please use the
|
||||
[mailing list](https://groups.google.com/forum/#!forum/node-red).
|
||||
For further help, or general discussion, please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack).
|
||||
|
||||
## Developers
|
||||
|
||||
If you want to run the latest code from git, here's how to get started:
|
||||
|
||||
1. Install grunt, the build tool
|
||||
|
||||
npm install -g grunt-cli
|
||||
|
||||
2. Clone the code:
|
||||
1. Clone the code:
|
||||
|
||||
git clone https://github.com/node-red/node-red.git
|
||||
cd node-red
|
||||
|
||||
3. Install the node-red dependencies
|
||||
2. Install the node-red dependencies
|
||||
|
||||
npm install
|
||||
|
||||
4. Build the code
|
||||
3. Build the code
|
||||
|
||||
grunt build
|
||||
npm run build
|
||||
|
||||
5. Run
|
||||
4. Run
|
||||
|
||||
npm start
|
||||
or
|
||||
|
||||
node red.js
|
||||
|
||||
@@ -55,15 +53,21 @@ If you want to run the latest code from git, here's how to get started:
|
||||
Before raising a pull-request, please read our
|
||||
[contributing guide](https://github.com/node-red/node-red/blob/master/CONTRIBUTING.md).
|
||||
|
||||
This project adheres to the [Contributor Covenant 1.4](http://contributor-covenant.org/version/1/4/).
|
||||
By participating, you are expected to uphold this code. Please report unacceptable
|
||||
behavior to any of the project's core team at team@nodered.org.
|
||||
|
||||
## Authors
|
||||
|
||||
Node-RED is a creation of [IBM Emerging Technology](http://ibm.com/blogs/et).
|
||||
Node-RED is a project of the [JS Foundation](http://js.foundation).
|
||||
|
||||
It was created by [IBM Emerging Technology](https://www.ibm.com/blogs/emerging-technology/).
|
||||
|
||||
* Nick O'Leary [@knolleary](http://twitter.com/knolleary)
|
||||
* Dave Conway-Jones [@ceejay](http://twitter.com/ceejay)
|
||||
|
||||
For more open-source projects from IBM, head over [here](http://ibm.github.io).
|
||||
|
||||
|
||||
## Copyright and license
|
||||
|
||||
Copyright 2013, 2015 IBM Corp. under [the Apache 2.0 license](LICENSE).
|
||||
Copyright JS Foundation and other contributors, http://js.foundation under [the Apache 2.0 license](LICENSE).
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
#!/bin/bash
|
||||
#
|
||||
# Copyright 2015 IBM Corp.
|
||||
# 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.
|
||||
@@ -31,7 +31,7 @@ done
|
||||
# Find the real location of this script
|
||||
CURRENT_PATH=`pwd`
|
||||
SCRIPT_PATH="${BASH_SOURCE[0]}";
|
||||
while([ -h "${SCRIPT_PATH}" ]); do
|
||||
while [ -h "${SCRIPT_PATH}" ]; do
|
||||
cd "`dirname "${SCRIPT_PATH}"`"
|
||||
SCRIPT_PATH="$(readlink "`basename "${SCRIPT_PATH}"`")";
|
||||
done
|
||||
@@ -40,4 +40,4 @@ SCRIPT_PATH="`pwd`";
|
||||
cd $CURRENT_PATH
|
||||
|
||||
# Run Node-RED
|
||||
/usr/bin/env node $OPTIONS $SCRIPT_PATH/../red.js $ARGS
|
||||
exec /usr/bin/env node $OPTIONS $SCRIPT_PATH/../red.js $ARGS
|
||||
|
||||
BIN
editor/icons/batch.png
Normal file
|
After Width: | Height: | Size: 712 B |
|
Before Width: | Height: | Size: 609 B After Width: | Height: | Size: 508 B |
BIN
editor/icons/cog.png
Normal file
|
After Width: | Height: | Size: 493 B |
BIN
editor/icons/file-in.png
Normal file
|
After Width: | Height: | Size: 542 B |
BIN
editor/icons/file-out.png
Normal file
|
After Width: | Height: | Size: 503 B |
BIN
editor/icons/join.png
Normal file
|
After Width: | Height: | Size: 253 B |
BIN
editor/icons/link-out.png
Normal file
|
After Width: | Height: | Size: 402 B |
BIN
editor/icons/parser-csv.png
Normal file
|
After Width: | Height: | Size: 413 B |
BIN
editor/icons/parser-html.png
Normal file
|
After Width: | Height: | Size: 393 B |
BIN
editor/icons/parser-json.png
Normal file
|
After Width: | Height: | Size: 467 B |
BIN
editor/icons/parser-xml.png
Normal file
|
After Width: | Height: | Size: 393 B |
BIN
editor/icons/parser-yaml.png
Normal file
|
After Width: | Height: | Size: 423 B |
BIN
editor/icons/sort.png
Normal file
|
After Width: | Height: | Size: 793 B |
BIN
editor/icons/split.png
Normal file
|
After Width: | Height: | Size: 256 B |
9
editor/images/node-red-icon-black.svg
Normal file
@@ -0,0 +1,9 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
|
||||
<svg version="1.1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0" y="0" width="480" height="480" viewBox="0, 0, 480, 480">
|
||||
<g id="Calque_1">
|
||||
<path d="M408,16 C438.928,16 464,41.072 464,72 L464,408 C464,438.928 438.928,464 408,464 L72,464 C41.072,464 16,438.928 16,408 L16,296.002 L69.339,296.002 C89.715,296.002 105.993,279.497 105.993,259.12 L105.992,242.19 C190.296,243.397 214.83,265.317 241.661,288.777 C267.502,311.375 296.48,335.662 371.989,336.261 L371.993,344.57 C372.002,364.947 388.693,382 409.069,382 L463.991,382 L463.991,356 L409.069,356 C402.189,356 396.991,351.449 396.991,344.569 L396.991,308.32 C396.991,301.44 402.189,296 409.069,296 L463.991,296 L463.991,272 L409.069,272 C388.693,272 372.002,287.943 371.993,308.32 L371.99,316.908 C300.63,316.672 280.362,296.883 254.41,274.189 C232.267,254.825 206.244,233.534 148.914,225.789 C149.412,225.361 149.872,224.945 150.353,224.505 C161.391,214.382 167.343,202.153 173.167,191.593 C178.99,181.034 184.469,172.221 193.444,166.061 C200.725,161.064 211.08,157.338 226.992,156.647 L226.993,165.123 C226.997,185.5 243.431,202.999 263.808,202.999 L411.141,202.999 C431.517,202.999 447.993,185.5 447.993,165.123 L447.993,128.874 C447.993,108.497 431.517,91.999 411.141,91.999 L263.808,91.999 C243.431,91.999 226.983,108.496 226.993,128.874 L226.998,137.281 C207.794,138.053 193.238,142.713 182.496,150.086 C169.469,159.028 162.277,171.247 156.21,182.247 C150.144,193.247 145.009,203.104 137.25,210.218 C130.497,216.411 121.157,221.193 105.993,222.976 L105.993,222.579 C106.111,202.203 89.715,186.002 69.339,186.002 L16,186.002 L16,72 C16,41.072 41.072,16 72,16 L408,16 z" fill="#000000"/>
|
||||
<path d="M16,211.002 L69.339,211.002 C76.219,211.002 81.992,215.991 81.992,222.871 L81.992,259.12 C81.992,266 76.219,272.002 69.339,272.002 L16,272.002 L16,211.002 z" fill="#000000"/>
|
||||
<path d="M411.135,116.997 C418.015,116.997 422.987,121.992 422.987,128.872 L422.987,165.122 C422.987,172.002 418.015,176.998 411.135,176.998 L263.802,176.998 C256.923,176.998 250.99,172.002 250.99,165.122 L250.99,128.872 C250.99,121.993 256.923,116.997 263.802,116.997 L411.135,116.997 z" fill="#000000"/>
|
||||
</g>
|
||||
</svg>
|
||||
|
After Width: | Height: | Size: 2.3 KiB |
BIN
editor/images/typedInput/09.png
Normal file
|
After Width: | Height: | Size: 638 B |
BIN
editor/images/typedInput/az.png
Normal file
|
After Width: | Height: | Size: 546 B |
BIN
editor/images/typedInput/bin.png
Normal file
|
After Width: | Height: | Size: 638 B |
BIN
editor/images/typedInput/bool.png
Normal file
|
After Width: | Height: | Size: 646 B |
BIN
editor/images/typedInput/env.png
Normal file
|
After Width: | Height: | Size: 809 B |
BIN
editor/images/typedInput/expr.png
Normal file
|
After Width: | Height: | Size: 563 B |
BIN
editor/images/typedInput/json.png
Normal file
|
After Width: | Height: | Size: 588 B |
BIN
editor/images/typedInput/re.png
Normal file
|
After Width: | Height: | Size: 502 B |
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2014, 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -18,13 +18,16 @@ RED.comms = (function() {
|
||||
|
||||
var errornotification = null;
|
||||
var clearErrorTimer = null;
|
||||
|
||||
var connectCountdownTimer = null;
|
||||
var connectCountdown = 10;
|
||||
var subscriptions = {};
|
||||
var ws;
|
||||
var pendingAuth = false;
|
||||
var reconnectAttempts = 0;
|
||||
var active = false;
|
||||
|
||||
function connectWS() {
|
||||
active = true;
|
||||
var path = location.hostname;
|
||||
var port = location.port;
|
||||
if (port.length !== 0) {
|
||||
@@ -61,19 +64,31 @@ RED.comms = (function() {
|
||||
}
|
||||
}
|
||||
ws.onmessage = function(event) {
|
||||
var msg = JSON.parse(event.data);
|
||||
if (pendingAuth && msg.auth == "ok") {
|
||||
pendingAuth = false;
|
||||
completeConnection();
|
||||
} else if (msg.topic) {
|
||||
for (var t in subscriptions) {
|
||||
if (subscriptions.hasOwnProperty(t)) {
|
||||
var re = new RegExp("^"+t.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$");
|
||||
if (re.test(msg.topic)) {
|
||||
var subscribers = subscriptions[t];
|
||||
if (subscribers) {
|
||||
for (var i=0;i<subscribers.length;i++) {
|
||||
subscribers[i](msg.topic,msg.data);
|
||||
var message = JSON.parse(event.data);
|
||||
for (var m = 0; m < message.length; m++) {
|
||||
var msg = message[m];
|
||||
if (pendingAuth && msg.auth) {
|
||||
if (msg.auth === "ok") {
|
||||
pendingAuth = false;
|
||||
completeConnection();
|
||||
} else if (msg.auth === "fail") {
|
||||
// anything else is an error...
|
||||
active = false;
|
||||
RED.user.login({updateMenu:true},function() {
|
||||
connectWS();
|
||||
})
|
||||
}
|
||||
}
|
||||
else if (msg.topic) {
|
||||
for (var t in subscriptions) {
|
||||
if (subscriptions.hasOwnProperty(t)) {
|
||||
var re = new RegExp("^"+t.replace(/([\[\]\?\(\)\\\\$\^\*\.|])/g,"\\$1").replace(/\+/g,"[^/]+").replace(/\/#$/,"(\/.*)?")+"$");
|
||||
if (re.test(msg.topic)) {
|
||||
var subscribers = subscriptions[t];
|
||||
if (subscribers) {
|
||||
for (var i=0;i<subscribers.length;i++) {
|
||||
subscribers[i](msg.topic,msg.data);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -82,14 +97,42 @@ RED.comms = (function() {
|
||||
}
|
||||
};
|
||||
ws.onclose = function() {
|
||||
if (reconnectAttempts > 5 && errornotification == null) {
|
||||
errornotification = RED.notify(RED._("notification.error",{message:RED._("notification.errors.lostConnection")}),"error",true);
|
||||
} else if (clearErrorTimer) {
|
||||
if (!active) {
|
||||
return;
|
||||
}
|
||||
if (clearErrorTimer) {
|
||||
clearTimeout(clearErrorTimer);
|
||||
clearErrorTimer = null;
|
||||
}
|
||||
reconnectAttempts++;
|
||||
setTimeout(connectWS,1000);
|
||||
if (reconnectAttempts < 10) {
|
||||
setTimeout(connectWS,1000);
|
||||
if (reconnectAttempts > 5 && errornotification == null) {
|
||||
errornotification = RED.notify(RED._("notification.errors.lostConnection"),"error",true);
|
||||
}
|
||||
} else if (reconnectAttempts < 20) {
|
||||
setTimeout(connectWS,2000);
|
||||
} else {
|
||||
connectCountdown = 60;
|
||||
connectCountdownTimer = setInterval(function() {
|
||||
connectCountdown--;
|
||||
if (connectCountdown === 0) {
|
||||
errornotification.update(RED._("notification.errors.lostConnection"));
|
||||
clearInterval(connectCountdownTimer);
|
||||
connectWS();
|
||||
} else {
|
||||
var msg = RED._("notification.errors.lostConnectionReconnect",{time: connectCountdown})+' <a href="#">'+ RED._("notification.errors.lostConnectionTry")+'</a>';
|
||||
errornotification.update(msg);
|
||||
$(errornotification).find("a").click(function(e) {
|
||||
e.preventDefault();
|
||||
errornotification.update(RED._("notification.errors.lostConnection"));
|
||||
clearInterval(connectCountdownTimer);
|
||||
connectWS();
|
||||
})
|
||||
}
|
||||
},1000);
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -35,7 +35,12 @@
|
||||
function emit(evt,arg) {
|
||||
if (handlers[evt]) {
|
||||
for (var i=0;i<handlers[evt].length;i++) {
|
||||
handlers[evt][i](arg);
|
||||
try {
|
||||
handlers[evt][i](arg);
|
||||
} catch(err) {
|
||||
console.log("RED.events.emit error: ["+evt+"] "+(err.toString()));
|
||||
console.log(err);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013, 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -16,6 +16,291 @@
|
||||
RED.history = (function() {
|
||||
var undo_history = [];
|
||||
|
||||
function undoEvent(ev) {
|
||||
var i;
|
||||
var len;
|
||||
var node;
|
||||
var subflow;
|
||||
var modifiedTabs = {};
|
||||
if (ev) {
|
||||
if (ev.t == 'multi') {
|
||||
len = ev.events.length;
|
||||
for (i=len-1;i>=0;i--) {
|
||||
undoEvent(ev.events[i]);
|
||||
}
|
||||
} else if (ev.t == 'replace') {
|
||||
RED.nodes.clear();
|
||||
var imported = RED.nodes.import(ev.config);
|
||||
imported[0].forEach(function(n) {
|
||||
if (ev.changed[n.id]) {
|
||||
n.changed = true;
|
||||
}
|
||||
})
|
||||
|
||||
RED.nodes.version(ev.rev);
|
||||
} else if (ev.t == 'add') {
|
||||
if (ev.nodes) {
|
||||
for (i=0;i<ev.nodes.length;i++) {
|
||||
node = RED.nodes.node(ev.nodes[i]);
|
||||
if (node.z) {
|
||||
modifiedTabs[node.z] = true;
|
||||
}
|
||||
RED.nodes.remove(ev.nodes[i]);
|
||||
}
|
||||
}
|
||||
if (ev.links) {
|
||||
for (i=0;i<ev.links.length;i++) {
|
||||
RED.nodes.removeLink(ev.links[i]);
|
||||
}
|
||||
}
|
||||
if (ev.workspaces) {
|
||||
for (i=0;i<ev.workspaces.length;i++) {
|
||||
RED.nodes.removeWorkspace(ev.workspaces[i].id);
|
||||
RED.workspaces.remove(ev.workspaces[i]);
|
||||
}
|
||||
}
|
||||
if (ev.subflows) {
|
||||
for (i=0;i<ev.subflows.length;i++) {
|
||||
RED.nodes.removeSubflow(ev.subflows[i]);
|
||||
RED.workspaces.remove(ev.subflows[i]);
|
||||
}
|
||||
}
|
||||
if (ev.subflow) {
|
||||
if (ev.subflow.instances) {
|
||||
ev.subflow.instances.forEach(function(n) {
|
||||
var node = RED.nodes.node(n.id);
|
||||
if (node) {
|
||||
node.changed = n.changed;
|
||||
node.dirty = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (ev.subflow.hasOwnProperty('changed')) {
|
||||
subflow = RED.nodes.subflow(ev.subflow.id);
|
||||
if (subflow) {
|
||||
subflow.changed = ev.subflow.changed;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (ev.removedLinks) {
|
||||
for (i=0;i<ev.removedLinks.length;i++) {
|
||||
RED.nodes.addLink(ev.removedLinks[i]);
|
||||
}
|
||||
}
|
||||
|
||||
} else if (ev.t == "delete") {
|
||||
if (ev.workspaces) {
|
||||
for (i=0;i<ev.workspaces.length;i++) {
|
||||
RED.nodes.addWorkspace(ev.workspaces[i]);
|
||||
RED.workspaces.add(ev.workspaces[i]);
|
||||
}
|
||||
}
|
||||
if (ev.subflow && ev.subflow.subflow) {
|
||||
RED.nodes.addSubflow(ev.subflow.subflow);
|
||||
}
|
||||
if (ev.subflowInputs && ev.subflowInputs.length > 0) {
|
||||
subflow = RED.nodes.subflow(ev.subflowInputs[0].z);
|
||||
subflow.in.push(ev.subflowInputs[0]);
|
||||
subflow.in[0].dirty = true;
|
||||
}
|
||||
if (ev.subflowOutputs && ev.subflowOutputs.length > 0) {
|
||||
subflow = RED.nodes.subflow(ev.subflowOutputs[0].z);
|
||||
ev.subflowOutputs.sort(function(a,b) { return a.i-b.i});
|
||||
for (i=0;i<ev.subflowOutputs.length;i++) {
|
||||
var output = ev.subflowOutputs[i];
|
||||
subflow.out.splice(output.i,0,output);
|
||||
for (var j=output.i+1;j<subflow.out.length;j++) {
|
||||
subflow.out[j].i++;
|
||||
subflow.out[j].dirty = true;
|
||||
}
|
||||
RED.nodes.eachLink(function(l) {
|
||||
if (l.source.type == "subflow:"+subflow.id) {
|
||||
if (l.sourcePort >= output.i) {
|
||||
l.sourcePort++;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (ev.subflow && ev.subflow.hasOwnProperty('instances')) {
|
||||
ev.subflow.instances.forEach(function(n) {
|
||||
var node = RED.nodes.node(n.id);
|
||||
if (node) {
|
||||
node.changed = n.changed;
|
||||
node.dirty = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (subflow) {
|
||||
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.nodes) {
|
||||
for (i=0;i<ev.nodes.length;i++) {
|
||||
RED.nodes.add(ev.nodes[i]);
|
||||
modifiedTabs[ev.nodes[i].z] = true;
|
||||
}
|
||||
}
|
||||
if (ev.links) {
|
||||
for (i=0;i<ev.links.length;i++) {
|
||||
RED.nodes.addLink(ev.links[i]);
|
||||
}
|
||||
}
|
||||
if (ev.changes) {
|
||||
for (i in ev.changes) {
|
||||
if (ev.changes.hasOwnProperty(i)) {
|
||||
node = RED.nodes.node(i);
|
||||
if (node) {
|
||||
for (var d in ev.changes[i]) {
|
||||
if (ev.changes[i].hasOwnProperty(d)) {
|
||||
node[d] = ev.changes[i][d];
|
||||
}
|
||||
}
|
||||
node.dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else if (ev.t == "move") {
|
||||
for (i=0;i<ev.nodes.length;i++) {
|
||||
var n = ev.nodes[i];
|
||||
n.n.x = n.ox;
|
||||
n.n.y = n.oy;
|
||||
n.n.dirty = true;
|
||||
n.n.moved = n.moved;
|
||||
}
|
||||
// A move could have caused a link splice
|
||||
if (ev.links) {
|
||||
for (i=0;i<ev.links.length;i++) {
|
||||
RED.nodes.removeLink(ev.links[i]);
|
||||
}
|
||||
}
|
||||
if (ev.removedLinks) {
|
||||
for (i=0;i<ev.removedLinks.length;i++) {
|
||||
RED.nodes.addLink(ev.removedLinks[i]);
|
||||
}
|
||||
}
|
||||
} else if (ev.t == "edit") {
|
||||
for (i in ev.changes) {
|
||||
if (ev.changes.hasOwnProperty(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) {
|
||||
currentConfigNode.users.splice(currentConfigNode.users.indexOf(ev.node),1);
|
||||
}
|
||||
var newConfigNode = RED.nodes.node(ev.changes[i]);
|
||||
if (newConfigNode) {
|
||||
newConfigNode.users.push(ev.node);
|
||||
}
|
||||
}
|
||||
ev.node[i] = ev.changes[i];
|
||||
}
|
||||
}
|
||||
if (ev.subflow) {
|
||||
if (ev.subflow.hasOwnProperty('inputCount')) {
|
||||
if (ev.node.in.length > ev.subflow.inputCount) {
|
||||
ev.node.in.splice(ev.subflow.inputCount);
|
||||
} else if (ev.subflow.inputs.length > 0) {
|
||||
ev.node.in = ev.node.in.concat(ev.subflow.inputs);
|
||||
}
|
||||
}
|
||||
if (ev.subflow.hasOwnProperty('outputCount')) {
|
||||
if (ev.node.out.length > ev.subflow.outputCount) {
|
||||
ev.node.out.splice(ev.subflow.outputCount);
|
||||
} else if (ev.subflow.outputs.length > 0) {
|
||||
ev.node.out = ev.node.out.concat(ev.subflow.outputs);
|
||||
}
|
||||
}
|
||||
if (ev.subflow.hasOwnProperty('instances')) {
|
||||
ev.subflow.instances.forEach(function(n) {
|
||||
var node = RED.nodes.node(n.id);
|
||||
if (node) {
|
||||
node.changed = n.changed;
|
||||
node.dirty = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
RED.editor.validateNode(ev.node);
|
||||
RED.nodes.filterNodes({type:"subflow:"+ev.node.id}).forEach(function(n) {
|
||||
n.inputs = ev.node.in.length;
|
||||
n.outputs = ev.node.out.length;
|
||||
RED.editor.updateNodeProperties(n);
|
||||
RED.editor.validateNode(n);
|
||||
});
|
||||
} else {
|
||||
var outputMap;
|
||||
if (ev.outputMap) {
|
||||
outputMap = {};
|
||||
for (var port in ev.outputMap) {
|
||||
if (ev.outputMap.hasOwnProperty(port) && ev.outputMap[port] !== "-1") {
|
||||
outputMap[ev.outputMap[port]] = port;
|
||||
}
|
||||
}
|
||||
}
|
||||
RED.editor.updateNodeProperties(ev.node,outputMap);
|
||||
RED.editor.validateNode(ev.node);
|
||||
}
|
||||
if (ev.links) {
|
||||
for (i=0;i<ev.links.length;i++) {
|
||||
RED.nodes.addLink(ev.links[i]);
|
||||
}
|
||||
}
|
||||
ev.node.dirty = true;
|
||||
ev.node.changed = ev.changed;
|
||||
} else if (ev.t == "createSubflow") {
|
||||
if (ev.nodes) {
|
||||
RED.nodes.filterNodes({z:ev.subflow.subflow.id}).forEach(function(n) {
|
||||
n.z = ev.activeWorkspace;
|
||||
n.dirty = true;
|
||||
});
|
||||
for (i=0;i<ev.nodes.length;i++) {
|
||||
RED.nodes.remove(ev.nodes[i]);
|
||||
}
|
||||
}
|
||||
if (ev.links) {
|
||||
for (i=0;i<ev.links.length;i++) {
|
||||
RED.nodes.removeLink(ev.links[i]);
|
||||
}
|
||||
}
|
||||
|
||||
RED.nodes.removeSubflow(ev.subflow.subflow);
|
||||
RED.workspaces.remove(ev.subflow.subflow);
|
||||
|
||||
if (ev.removedLinks) {
|
||||
for (i=0;i<ev.removedLinks.length;i++) {
|
||||
RED.nodes.addLink(ev.removedLinks[i]);
|
||||
}
|
||||
}
|
||||
} else if (ev.t == "reorder") {
|
||||
if (ev.order) {
|
||||
RED.workspaces.order(ev.order);
|
||||
}
|
||||
}
|
||||
Object.keys(modifiedTabs).forEach(function(id) {
|
||||
var subflow = RED.nodes.subflow(id);
|
||||
if (subflow) {
|
||||
RED.editor.validateNode(subflow);
|
||||
}
|
||||
});
|
||||
|
||||
RED.nodes.dirty(ev.dirty);
|
||||
RED.view.redraw(true);
|
||||
RED.palette.refresh();
|
||||
RED.workspaces.refresh();
|
||||
RED.sidebar.config.refresh();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
//TODO: this function is a placeholder until there is a 'save' event that can be listened to
|
||||
markAllDirty: function() {
|
||||
@@ -23,6 +308,9 @@ RED.history = (function() {
|
||||
undo_history[i].dirty = true;
|
||||
}
|
||||
},
|
||||
list: function() {
|
||||
return undo_history
|
||||
},
|
||||
depth: function() {
|
||||
return undo_history.length;
|
||||
},
|
||||
@@ -31,241 +319,13 @@ RED.history = (function() {
|
||||
},
|
||||
pop: function() {
|
||||
var ev = undo_history.pop();
|
||||
var i;
|
||||
var node;
|
||||
var subflow;
|
||||
var modifiedTabs = {};
|
||||
if (ev) {
|
||||
if (ev.t == 'add') {
|
||||
if (ev.nodes) {
|
||||
for (i=0;i<ev.nodes.length;i++) {
|
||||
node = RED.nodes.node(ev.nodes[i]);
|
||||
if (node.z) {
|
||||
modifiedTabs[node.z] = true;
|
||||
}
|
||||
RED.nodes.remove(ev.nodes[i]);
|
||||
}
|
||||
}
|
||||
if (ev.links) {
|
||||
for (i=0;i<ev.links.length;i++) {
|
||||
RED.nodes.removeLink(ev.links[i]);
|
||||
}
|
||||
}
|
||||
if (ev.workspaces) {
|
||||
for (i=0;i<ev.workspaces.length;i++) {
|
||||
RED.nodes.removeWorkspace(ev.workspaces[i].id);
|
||||
RED.workspaces.remove(ev.workspaces[i]);
|
||||
}
|
||||
}
|
||||
if (ev.subflows) {
|
||||
for (i=0;i<ev.subflows.length;i++) {
|
||||
RED.nodes.removeSubflow(ev.subflows[i]);
|
||||
RED.workspaces.remove(ev.subflows[i]);
|
||||
}
|
||||
}
|
||||
if (ev.subflow) {
|
||||
if (ev.subflow.instances) {
|
||||
ev.subflow.instances.forEach(function(n) {
|
||||
var node = RED.nodes.node(n.id);
|
||||
if (node) {
|
||||
node.changed = n.changed;
|
||||
node.dirty = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (ev.subflow.hasOwnProperty('changed')) {
|
||||
subflow = RED.nodes.subflow(ev.subflow.id);
|
||||
if (subflow) {
|
||||
subflow.changed = ev.subflow.changed;
|
||||
}
|
||||
}
|
||||
}
|
||||
} else if (ev.t == "delete") {
|
||||
if (ev.workspaces) {
|
||||
for (i=0;i<ev.workspaces.length;i++) {
|
||||
RED.nodes.addWorkspace(ev.workspaces[i]);
|
||||
RED.workspaces.add(ev.workspaces[i]);
|
||||
}
|
||||
}
|
||||
if (ev.subflow && ev.subflow.subflow) {
|
||||
RED.nodes.addSubflow(ev.subflow.subflow);
|
||||
}
|
||||
if (ev.subflowInputs && ev.subflowInputs.length > 0) {
|
||||
subflow = RED.nodes.subflow(ev.subflowInputs[0].z);
|
||||
subflow.in.push(ev.subflowInputs[0]);
|
||||
subflow.in[0].dirty = true;
|
||||
}
|
||||
if (ev.subflowOutputs && ev.subflowOutputs.length > 0) {
|
||||
subflow = RED.nodes.subflow(ev.subflowOutputs[0].z);
|
||||
ev.subflowOutputs.sort(function(a,b) { return a.i-b.i});
|
||||
for (i=0;i<ev.subflowOutputs.length;i++) {
|
||||
var output = ev.subflowOutputs[i];
|
||||
subflow.out.splice(output.i,0,output);
|
||||
for (var j=output.i+1;j<subflow.out.length;j++) {
|
||||
subflow.out[j].i++;
|
||||
subflow.out[j].dirty = true;
|
||||
}
|
||||
RED.nodes.eachLink(function(l) {
|
||||
if (l.source.type == "subflow:"+subflow.id) {
|
||||
if (l.sourcePort >= output.i) {
|
||||
l.sourcePort++;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (ev.subflow && ev.subflow.hasOwnProperty('instances')) {
|
||||
ev.subflow.instances.forEach(function(n) {
|
||||
var node = RED.nodes.node(n.id);
|
||||
if (node) {
|
||||
node.changed = n.changed;
|
||||
node.dirty = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (subflow) {
|
||||
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.nodes) {
|
||||
for (i=0;i<ev.nodes.length;i++) {
|
||||
RED.nodes.add(ev.nodes[i]);
|
||||
modifiedTabs[ev.nodes[i].z] = true;
|
||||
}
|
||||
}
|
||||
if (ev.links) {
|
||||
for (i=0;i<ev.links.length;i++) {
|
||||
RED.nodes.addLink(ev.links[i]);
|
||||
}
|
||||
}
|
||||
if (ev.changes) {
|
||||
for (i in ev.changes) {
|
||||
if (ev.changes.hasOwnProperty(i)) {
|
||||
node = RED.nodes.node(i);
|
||||
if (node) {
|
||||
for (var d in ev.changes[i]) {
|
||||
if (ev.changes[i].hasOwnProperty(d)) {
|
||||
node[d] = ev.changes[i][d];
|
||||
}
|
||||
}
|
||||
node.dirty = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
} else if (ev.t == "move") {
|
||||
for (i=0;i<ev.nodes.length;i++) {
|
||||
var n = ev.nodes[i];
|
||||
n.n.x = n.ox;
|
||||
n.n.y = n.oy;
|
||||
n.n.dirty = true;
|
||||
}
|
||||
} else if (ev.t == "edit") {
|
||||
for (i in ev.changes) {
|
||||
if (ev.changes.hasOwnProperty(i)) {
|
||||
if (ev.node._def.defaults[i].type) {
|
||||
// This is a config node property
|
||||
var currentConfigNode = RED.nodes.node(ev.node[i]);
|
||||
if (currentConfigNode) {
|
||||
currentConfigNode.users.splice(currentConfigNode.users.indexOf(ev.node),1);
|
||||
}
|
||||
var newConfigNode = RED.nodes.node(ev.changes[i]);
|
||||
if (newConfigNode) {
|
||||
newConfigNode.users.push(ev.node);
|
||||
}
|
||||
}
|
||||
ev.node[i] = ev.changes[i];
|
||||
}
|
||||
}
|
||||
if (ev.subflow) {
|
||||
if (ev.subflow.hasOwnProperty('inputCount')) {
|
||||
if (ev.node.in.length > ev.subflow.inputCount) {
|
||||
ev.node.in.splice(ev.subflow.inputCount);
|
||||
} else if (ev.subflow.inputs.length > 0) {
|
||||
ev.node.in = ev.node.in.concat(ev.subflow.inputs);
|
||||
}
|
||||
}
|
||||
if (ev.subflow.hasOwnProperty('outputCount')) {
|
||||
if (ev.node.out.length > ev.subflow.outputCount) {
|
||||
ev.node.out.splice(ev.subflow.outputCount);
|
||||
} else if (ev.subflow.outputs.length > 0) {
|
||||
ev.node.out = ev.node.out.concat(ev.subflow.outputs);
|
||||
}
|
||||
}
|
||||
if (ev.subflow.hasOwnProperty('instances')) {
|
||||
ev.subflow.instances.forEach(function(n) {
|
||||
var node = RED.nodes.node(n.id);
|
||||
if (node) {
|
||||
node.changed = n.changed;
|
||||
node.dirty = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
RED.nodes.filterNodes({type:"subflow:"+ev.node.id}).forEach(function(n) {
|
||||
n.inputs = ev.node.in.length;
|
||||
n.outputs = ev.node.out.length;
|
||||
RED.editor.updateNodeProperties(n);
|
||||
});
|
||||
|
||||
if (ev.node.type === 'subflow') {
|
||||
$("#menu-item-workspace-menu-"+ev.node.id.replace(".","-")).text(ev.node.name);
|
||||
}
|
||||
} else {
|
||||
RED.editor.updateNodeProperties(ev.node);
|
||||
RED.editor.validateNode(ev.node);
|
||||
}
|
||||
if (ev.links) {
|
||||
for (i=0;i<ev.links.length;i++) {
|
||||
RED.nodes.addLink(ev.links[i]);
|
||||
}
|
||||
}
|
||||
ev.node.dirty = true;
|
||||
ev.node.changed = ev.changed;
|
||||
} else if (ev.t == "createSubflow") {
|
||||
if (ev.nodes) {
|
||||
RED.nodes.filterNodes({z:ev.subflow.subflow.id}).forEach(function(n) {
|
||||
n.z = ev.activeWorkspace;
|
||||
n.dirty = true;
|
||||
});
|
||||
for (i=0;i<ev.nodes.length;i++) {
|
||||
RED.nodes.remove(ev.nodes[i]);
|
||||
}
|
||||
}
|
||||
if (ev.links) {
|
||||
for (i=0;i<ev.links.length;i++) {
|
||||
RED.nodes.removeLink(ev.links[i]);
|
||||
}
|
||||
}
|
||||
|
||||
RED.nodes.removeSubflow(ev.subflow.subflow);
|
||||
RED.workspaces.remove(ev.subflow.subflow);
|
||||
|
||||
if (ev.removedLinks) {
|
||||
for (i=0;i<ev.removedLinks.length;i++) {
|
||||
RED.nodes.addLink(ev.removedLinks[i]);
|
||||
}
|
||||
}
|
||||
}
|
||||
Object.keys(modifiedTabs).forEach(function(id) {
|
||||
var subflow = RED.nodes.subflow(id);
|
||||
if (subflow) {
|
||||
RED.editor.validateNode(subflow);
|
||||
}
|
||||
});
|
||||
|
||||
RED.nodes.dirty(ev.dirty);
|
||||
RED.view.redraw(true);
|
||||
RED.palette.refresh();
|
||||
RED.workspaces.refresh();
|
||||
}
|
||||
undoEvent(ev);
|
||||
},
|
||||
peek: function() {
|
||||
return undo_history[undo_history.length-1];
|
||||
},
|
||||
clear: function() {
|
||||
undo_history = [];
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013, 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -19,11 +19,11 @@ RED.i18n = (function() {
|
||||
return {
|
||||
init: function(done) {
|
||||
i18n.init({
|
||||
resGetPath: 'locales/__ns__',
|
||||
resGetPath: 'locales/__ns__?lng=__lng__',
|
||||
dynamicLoad: false,
|
||||
load:'current',
|
||||
ns: {
|
||||
namespaces: ["editor","node-red"],
|
||||
namespaces: ["editor","node-red","jsonata","infotips"],
|
||||
defaultNs: "editor"
|
||||
},
|
||||
fallbackLng: ['en-US'],
|
||||
@@ -37,7 +37,50 @@ RED.i18n = (function() {
|
||||
|
||||
},
|
||||
loadCatalog: function(namespace,done) {
|
||||
i18n.loadNamespace(namespace,done);
|
||||
var languageList = i18n.functions.toLanguages(i18n.detectLanguage());
|
||||
var toLoad = languageList.length;
|
||||
languageList.forEach(function(lang) {
|
||||
$.ajax({
|
||||
headers: {
|
||||
"Accept":"application/json"
|
||||
},
|
||||
cache: false,
|
||||
url: 'locales/'+namespace+'?lng='+lang,
|
||||
success: function(data) {
|
||||
i18n.addResourceBundle(lang,namespace,data);
|
||||
toLoad--;
|
||||
if (toLoad === 0) {
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
|
||||
},
|
||||
|
||||
loadNodeCatalogs: function(done) {
|
||||
var languageList = i18n.functions.toLanguages(i18n.detectLanguage());
|
||||
var toLoad = languageList.length;
|
||||
|
||||
languageList.forEach(function(lang) {
|
||||
$.ajax({
|
||||
headers: {
|
||||
"Accept":"application/json"
|
||||
},
|
||||
cache: false,
|
||||
url: 'locales/nodes?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();
|
||||
}
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
}
|
||||
})();
|
||||
|
||||
44
editor/js/keymap.json
Normal file
@@ -0,0 +1,44 @@
|
||||
{
|
||||
"*": {
|
||||
"ctrl-shift-p":"core:manage-palette",
|
||||
"ctrl-f": "core:search",
|
||||
"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-g i": "core:show-info-tab",
|
||||
"ctrl-g d": "core:show-debug-tab",
|
||||
"ctrl-g c": "core:show-config-tab",
|
||||
"ctrl-g x": "core:show-context-tab",
|
||||
"ctrl-e": "core:show-export-dialog",
|
||||
"ctrl-i": "core:show-import-dialog",
|
||||
"ctrl-space": "core:toggle-sidebar",
|
||||
"ctrl-,": "core:show-user-settings",
|
||||
"ctrl-alt-r": "core:show-remote-diff",
|
||||
"ctrl-alt-n": "core:new-project",
|
||||
"ctrl-alt-o": "core:open-project",
|
||||
"ctrl-g v": "core:show-version-control-tab"
|
||||
},
|
||||
"workspace": {
|
||||
"backspace": "core:delete-selection",
|
||||
"delete": "core:delete-selection",
|
||||
"enter": "core:edit-selected-node",
|
||||
"ctrl-c": "core:copy-selection-to-internal-clipboard",
|
||||
"ctrl-x": "core:cut-selection-to-internal-clipboard",
|
||||
"ctrl-v": "core:paste-from-internal-clipboard",
|
||||
"ctrl-z": "core:undo",
|
||||
"ctrl-a": "core:select-all-nodes",
|
||||
"shift-?": "core:show-help",
|
||||
"up": "core:move-selection-up",
|
||||
"right": "core:move-selection-right",
|
||||
"down": "core:move-selection-down",
|
||||
"left": "core:move-selection-left",
|
||||
"shift-up": "core:step-selection-up",
|
||||
"shift-right": "core:step-selection-right",
|
||||
"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"
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013, 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -13,8 +13,26 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
var RED = (function() {
|
||||
(function() {
|
||||
|
||||
function appendNodeConfig(nodeConfig) {
|
||||
var m = /<!-- --- \[red-module:(\S+)\] --- -->/.exec(nodeConfig.trim());
|
||||
var moduleId;
|
||||
if (m) {
|
||||
moduleId = m[1];
|
||||
} else {
|
||||
moduleId = "unknown";
|
||||
}
|
||||
try {
|
||||
$("body").append(nodeConfig);
|
||||
} catch(err) {
|
||||
RED.notify(RED._("notification.errors.failedToAppendNode",{module:moduleId, error:err.toString()}),{
|
||||
type: "error",
|
||||
timeout: 10000
|
||||
});
|
||||
console.log("["+moduleId+"] "+err.toString());
|
||||
}
|
||||
}
|
||||
|
||||
function loadNodeList() {
|
||||
$.ajax({
|
||||
@@ -25,22 +43,24 @@ var RED = (function() {
|
||||
url: 'nodes',
|
||||
success: function(data) {
|
||||
RED.nodes.setNodeList(data);
|
||||
RED.i18n.loadNodeCatalogs(function() {
|
||||
loadIconList(loadNodes);
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var nsCount = 0;
|
||||
for(var i=0;i<data.length;i++) {
|
||||
var ns = data[i];
|
||||
if (ns.module != "node-red") {
|
||||
nsCount++;
|
||||
RED.i18n.loadCatalog(ns.id, function() {
|
||||
nsCount--;
|
||||
if (nsCount === 0) {
|
||||
loadNodes();
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
if (nsCount === 0) {
|
||||
loadNodes();
|
||||
function loadIconList(done) {
|
||||
$.ajax({
|
||||
headers: {
|
||||
"Accept":"application/json"
|
||||
},
|
||||
cache: false,
|
||||
url: 'icons',
|
||||
success: function(data) {
|
||||
RED.nodes.setIconSets(data);
|
||||
if (done) {
|
||||
done();
|
||||
}
|
||||
}
|
||||
});
|
||||
@@ -54,157 +74,410 @@ var RED = (function() {
|
||||
cache: false,
|
||||
url: 'nodes',
|
||||
success: function(data) {
|
||||
$("body").append(data);
|
||||
var configs = data.trim().split(/(?=<!-- --- \[red-module:\S+\] --- -->)/);
|
||||
configs.forEach(function(data) {
|
||||
appendNodeConfig(data);
|
||||
});
|
||||
|
||||
$("body").i18n();
|
||||
|
||||
|
||||
$(".palette-spinner").hide();
|
||||
$(".palette-scroll").show();
|
||||
$("#palette-search").show();
|
||||
loadFlows();
|
||||
$("#palette > .palette-spinner").hide();
|
||||
$(".palette-scroll").removeClass("hide");
|
||||
$("#palette-search").removeClass("hide");
|
||||
loadFlows(function() {
|
||||
if (RED.settings.theme("projects.enabled",false)) {
|
||||
RED.projects.refresh(function(activeProject) {
|
||||
RED.sidebar.info.refresh()
|
||||
if (!activeProject) {
|
||||
// Projects enabled but no active project
|
||||
RED.menu.setDisabled('menu-item-projects-open',true);
|
||||
RED.menu.setDisabled('menu-item-projects-settings',true);
|
||||
if (activeProject === false) {
|
||||
// User previously decline the migration to projects.
|
||||
} else { // null/undefined
|
||||
RED.projects.showStartup();
|
||||
}
|
||||
}
|
||||
completeLoad();
|
||||
});
|
||||
} else {
|
||||
// Projects disabled by the user
|
||||
RED.sidebar.info.refresh()
|
||||
completeLoad();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function loadFlows() {
|
||||
function loadFlows(done) {
|
||||
$.ajax({
|
||||
headers: {
|
||||
"Accept":"application/json"
|
||||
"Accept":"application/json",
|
||||
},
|
||||
cache: false,
|
||||
url: 'flows',
|
||||
success: function(nodes) {
|
||||
RED.nodes.import(nodes);
|
||||
RED.nodes.dirty(false);
|
||||
RED.view.redraw(true);
|
||||
RED.comms.subscribe("status/#",function(topic,msg) {
|
||||
var parts = topic.split("/");
|
||||
var node = RED.nodes.node(parts[1]);
|
||||
if (node) {
|
||||
if (msg.text) {
|
||||
msg.text = node._(msg.text.toString(),{defaultValue:msg.text.toString()});
|
||||
}
|
||||
node.status = msg;
|
||||
if (statusEnabled) {
|
||||
node.dirty = true;
|
||||
RED.view.redraw();
|
||||
}
|
||||
if (nodes) {
|
||||
var currentHash = window.location.hash;
|
||||
RED.nodes.version(nodes.rev);
|
||||
RED.nodes.import(nodes.flows);
|
||||
RED.nodes.dirty(false);
|
||||
RED.view.redraw(true);
|
||||
if (/^#flow\/.+$/.test(currentHash)) {
|
||||
RED.workspaces.show(currentHash.substring(6));
|
||||
}
|
||||
});
|
||||
RED.comms.subscribe("node/#",function(topic,msg) {
|
||||
var i,m;
|
||||
var typeList;
|
||||
var info;
|
||||
|
||||
if (topic == "node/added") {
|
||||
var addedTypes = [];
|
||||
for (i=0;i<msg.length;i++) {
|
||||
m = msg[i];
|
||||
var id = m.id;
|
||||
RED.nodes.addNodeSet(m);
|
||||
addedTypes = addedTypes.concat(m.types);
|
||||
$.get('nodes/'+id, function(data) {
|
||||
$("body").append(data);
|
||||
});
|
||||
}
|
||||
if (addedTypes.length) {
|
||||
typeList = "<ul><li>"+addedTypes.join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeAdded", {count:addedTypes.length})+typeList,"success");
|
||||
}
|
||||
} else if (topic == "node/removed") {
|
||||
for (i=0;i<msg.length;i++) {
|
||||
m = msg[i];
|
||||
info = RED.nodes.removeNodeSet(m.id);
|
||||
if (info.added) {
|
||||
typeList = "<ul><li>"+m.types.join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeRemoved", {count:m.types.length})+typeList,"success");
|
||||
}
|
||||
}
|
||||
} else if (topic == "node/enabled") {
|
||||
if (msg.types) {
|
||||
info = RED.nodes.getNodeSet(msg.id);
|
||||
if (info.added) {
|
||||
RED.nodes.enableNodeSet(msg.id);
|
||||
typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeEnabled", {count:msg.types.length})+typeList,"success");
|
||||
} else {
|
||||
$.get('nodes/'+msg.id, function(data) {
|
||||
$("body").append(data);
|
||||
typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeAdded", {count:msg.types.length})+typeList,"success");
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if (topic == "node/disabled") {
|
||||
if (msg.types) {
|
||||
RED.nodes.disableNodeSet(msg.id);
|
||||
typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeDisabled", {count:msg.types.length})+typeList,"success");
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
done();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
var statusEnabled = false;
|
||||
function toggleStatus(state) {
|
||||
statusEnabled = state;
|
||||
RED.view.status(statusEnabled);
|
||||
function completeLoad() {
|
||||
var persistentNotifications = {};
|
||||
RED.comms.subscribe("notification/#",function(topic,msg) {
|
||||
var parts = topic.split("/");
|
||||
var notificationId = parts[1];
|
||||
if (notificationId === "runtime-deploy") {
|
||||
// handled in ui/deploy.js
|
||||
return;
|
||||
}
|
||||
if (notificationId === "node") {
|
||||
// handled below
|
||||
return;
|
||||
}
|
||||
if (notificationId === "project-update") {
|
||||
RED.nodes.clear();
|
||||
RED.history.clear();
|
||||
RED.view.redraw(true);
|
||||
RED.projects.refresh(function() {
|
||||
loadFlows(function() {
|
||||
var project = RED.projects.getActiveProject();
|
||||
var message = {
|
||||
"change-branch": RED._("notification.project.change-branch", {project: project.git.branches.local}),
|
||||
"merge-abort": RED._("notification.project.merge-abort"),
|
||||
"loaded": RED._("notification.project.loaded", {project: msg.project}),
|
||||
"updated": RED._("notification.project.updated", {project: msg.project}),
|
||||
"pull": RED._("notification.project.pull", {project: msg.project}),
|
||||
"revert": RED._("notification.project.revert", {project: msg.project}),
|
||||
"merge-complete": RED._("notification.project.merge-complete")
|
||||
}[msg.action];
|
||||
RED.notify("<p>"+message+"</p>");
|
||||
RED.sidebar.info.refresh()
|
||||
});
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
if (msg.text) {
|
||||
msg.default = msg.text;
|
||||
var text = RED._(msg.text,msg);
|
||||
var options = {
|
||||
type: msg.type,
|
||||
fixed: msg.timeout === undefined,
|
||||
timeout: msg.timeout,
|
||||
id: notificationId
|
||||
}
|
||||
if (notificationId === "runtime-state") {
|
||||
if (msg.error === "missing-types") {
|
||||
text+="<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
|
||||
if (!!RED.projects.getActiveProject()) {
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("notification.label.manage-project-dep"),
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
RED.projects.settings.show('deps');
|
||||
}
|
||||
}
|
||||
]
|
||||
// } else if (RED.settings.theme('palette.editable') !== false) {
|
||||
} else {
|
||||
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
|
||||
if (RED.user.hasPermission("projects.write")) {
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("notification.label.setup-cred"),
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
RED.projects.showCredentialsPrompt();
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
} else {
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("common.label.close"),
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
} else if (msg.error === "missing_flow_file") {
|
||||
if (RED.user.hasPermission("projects.write")) {
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("notification.label.setup-project"),
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
RED.projects.showFilesPrompt();
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
} else if (msg.error === "missing_package_file") {
|
||||
if (RED.user.hasPermission("projects.write")) {
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("notification.label.create-default-package"),
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
RED.projects.createDefaultPackageFile();
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
} else if (msg.error === "project_empty") {
|
||||
if (RED.user.hasPermission("projects.write")) {
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("notification.label.no-thanks"),
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._("notification.label.create-default-project"),
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
RED.projects.createDefaultFileSet();
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
} else if (msg.error === "git_merge_conflict") {
|
||||
RED.nodes.clear();
|
||||
RED.sidebar.versionControl.refresh(true);
|
||||
if (RED.user.hasPermission("projects.write")) {
|
||||
options.buttons = [
|
||||
{
|
||||
text: RED._("notification.label.show-merge-conflicts"),
|
||||
click: function() {
|
||||
persistentNotifications[notificationId].hideNotification();
|
||||
RED.sidebar.versionControl.showLocalChanges();
|
||||
}
|
||||
}
|
||||
]
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!persistentNotifications.hasOwnProperty(notificationId)) {
|
||||
persistentNotifications[notificationId] = RED.notify(text,options);
|
||||
} else {
|
||||
persistentNotifications[notificationId].update(text,options);
|
||||
}
|
||||
} else if (persistentNotifications.hasOwnProperty(notificationId)) {
|
||||
persistentNotifications[notificationId].close();
|
||||
delete persistentNotifications[notificationId];
|
||||
}
|
||||
});
|
||||
RED.comms.subscribe("status/#",function(topic,msg) {
|
||||
var parts = topic.split("/");
|
||||
var node = RED.nodes.node(parts[1]);
|
||||
if (node) {
|
||||
if (msg.hasOwnProperty("text")) {
|
||||
if (msg.text[0] !== ".") {
|
||||
msg.text = node._(msg.text.toString(),{defaultValue:msg.text.toString()});
|
||||
}
|
||||
}
|
||||
node.status = msg;
|
||||
node.dirty = true;
|
||||
RED.view.redraw();
|
||||
}
|
||||
});
|
||||
RED.comms.subscribe("notification/node/#",function(topic,msg) {
|
||||
var i,m;
|
||||
var typeList;
|
||||
var info;
|
||||
if (topic == "notification/node/added") {
|
||||
var addedTypes = [];
|
||||
msg.forEach(function(m) {
|
||||
var id = m.id;
|
||||
RED.nodes.addNodeSet(m);
|
||||
addedTypes = addedTypes.concat(m.types);
|
||||
RED.i18n.loadCatalog(id, function() {
|
||||
$.get('nodes/'+id, function(data) {
|
||||
appendNodeConfig(data);
|
||||
});
|
||||
});
|
||||
});
|
||||
if (addedTypes.length) {
|
||||
typeList = "<ul><li>"+addedTypes.join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeAdded", {count:addedTypes.length})+typeList,"success");
|
||||
}
|
||||
loadIconList();
|
||||
} else if (topic == "notification/node/removed") {
|
||||
for (i=0;i<msg.length;i++) {
|
||||
m = msg[i];
|
||||
info = RED.nodes.removeNodeSet(m.id);
|
||||
if (info.added) {
|
||||
typeList = "<ul><li>"+m.types.join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeRemoved", {count:m.types.length})+typeList,"success");
|
||||
}
|
||||
}
|
||||
loadIconList();
|
||||
} else if (topic == "notification/node/enabled") {
|
||||
if (msg.types) {
|
||||
info = RED.nodes.getNodeSet(msg.id);
|
||||
if (info.added) {
|
||||
RED.nodes.enableNodeSet(msg.id);
|
||||
typeList = "<ul><li>"+msg.types.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>";
|
||||
RED.notify(RED._("palette.event.nodeAdded", {count:msg.types.length})+typeList,"success");
|
||||
});
|
||||
}
|
||||
}
|
||||
} else if (topic == "notification/node/disabled") {
|
||||
if (msg.types) {
|
||||
RED.nodes.disableNodeSet(msg.id);
|
||||
typeList = "<ul><li>"+msg.types.join("</li><li>")+"</li></ul>";
|
||||
RED.notify(RED._("palette.event.nodeDisabled", {count:msg.types.length})+typeList,"success");
|
||||
}
|
||||
} else if (topic == "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();
|
||||
});
|
||||
}
|
||||
|
||||
function showAbout() {
|
||||
$.get('red/about', function(data) {
|
||||
var aboutHeader = '<div style="text-align:center;">'+
|
||||
'<img width="50px" src="red/images/node-red-icon.svg" />'+
|
||||
'</div>';
|
||||
|
||||
RED.sidebar.info.set(aboutHeader+marked(data));
|
||||
RED.sidebar.info.show();
|
||||
});
|
||||
}
|
||||
|
||||
function loadEditor() {
|
||||
RED.menu.init({id:"btn-sidemenu",
|
||||
options: [
|
||||
{id:"menu-item-sidebar-menu",label:RED._("menu.label.sidebar.sidebar"),options:[
|
||||
{id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:RED.sidebar.toggleSidebar, selected: true},
|
||||
null
|
||||
]},
|
||||
{id:"menu-item-status",label:RED._("menu.label.displayStatus"),toggle:true,onselect:toggleStatus, selected: true},
|
||||
null,
|
||||
{id:"menu-item-import",label:RED._("menu.label.import"),options:[
|
||||
{id:"menu-item-import-clipboard",label:RED._("menu.label.clipboard"),onselect:RED.clipboard.import},
|
||||
{id:"menu-item-import-library",label:RED._("menu.label.library"),options:[]}
|
||||
]},
|
||||
{id:"menu-item-export",label:RED._("menu.label.export"),disabled:true,options:[
|
||||
{id:"menu-item-export-clipboard",label:RED._("menu.label.clipboard"),disabled:true,onselect:RED.clipboard.export},
|
||||
{id:"menu-item-export-library",label:RED._("menu.label.library"),disabled:true,onselect:RED.library.export}
|
||||
]},
|
||||
null,
|
||||
{id:"menu-item-subflow",label:RED._("menu.label.subflows"), options: [
|
||||
{id:"menu-item-subflow-create",label:RED._("menu.label.createSubflow"),onselect:RED.subflow.createSubflow},
|
||||
{id:"menu-item-subflow-convert",label:RED._("menu.label.selectionToSubflow"),disabled:true,onselect:RED.subflow.convertToSubflow},
|
||||
]},
|
||||
null,
|
||||
{id:"menu-item-workspace",label:RED._("menu.label.flows"),options:[
|
||||
{id:"menu-item-workspace-add",label:RED._("menu.label.add"),onselect:RED.workspaces.add},
|
||||
{id:"menu-item-workspace-edit",label:RED._("menu.label.rename"),onselect:RED.workspaces.edit},
|
||||
{id:"menu-item-workspace-delete",label:RED._("menu.label.delete"),onselect:RED.workspaces.remove},
|
||||
null
|
||||
]},
|
||||
null,
|
||||
{id:"menu-item-keyboard-shortcuts",label:RED._("menu.label.keyboardShortcuts"),onselect:RED.keyboard.showHelp},
|
||||
{id:"menu-item-help",
|
||||
label: RED.settings.theme("menu.menu-item-help.label","Node-RED Website"),
|
||||
href: RED.settings.theme("menu.menu-item-help.url","http://nodered.org/docs")
|
||||
}
|
||||
]
|
||||
var menuOptions = [];
|
||||
if (RED.settings.theme("projects.enabled",false)) {
|
||||
menuOptions.push({id:"menu-item-projects-menu",label:RED._("menu.label.projects"),options:[
|
||||
{id:"menu-item-projects-new",label:RED._("menu.label.projects-new"),disabled:false,onselect:"core:new-project"},
|
||||
{id:"menu-item-projects-open",label:RED._("menu.label.projects-open"),disabled:false,onselect:"core:open-project"},
|
||||
{id:"menu-item-projects-settings",label:RED._("menu.label.projects-settings"),disabled:false,onselect:"core:show-project-settings"}
|
||||
]});
|
||||
}
|
||||
|
||||
|
||||
menuOptions.push({id:"menu-item-view-menu",label:RED._("menu.label.view.view"),options:[
|
||||
// {id:"menu-item-view-show-grid",setting:"view-show-grid",label:RED._("menu.label.view.showGrid"),toggle:true,onselect:"core:toggle-show-grid"},
|
||||
// {id:"menu-item-view-snap-grid",setting:"view-snap-grid",label:RED._("menu.label.view.snapGrid"),toggle:true,onselect:"core:toggle-snap-grid"},
|
||||
// {id:"menu-item-status",setting:"node-show-status",label:RED._("menu.label.displayStatus"),toggle:true,onselect:"core:toggle-status", selected: true},
|
||||
//null,
|
||||
// {id:"menu-item-bidi",label:RED._("menu.label.view.textDir"),options:[
|
||||
// {id:"menu-item-bidi-default",toggle:"text-direction",label:RED._("menu.label.view.defaultDir"),selected: true, onselect:function(s) { if(s){RED.text.bidi.setTextDirection("")}}},
|
||||
// {id:"menu-item-bidi-ltr",toggle:"text-direction",label:RED._("menu.label.view.ltr"), onselect:function(s) { if(s){RED.text.bidi.setTextDirection("ltr")}}},
|
||||
// {id:"menu-item-bidi-rtl",toggle:"text-direction",label:RED._("menu.label.view.rtl"), onselect:function(s) { if(s){RED.text.bidi.setTextDirection("rtl")}}},
|
||||
// {id:"menu-item-bidi-auto",toggle:"text-direction",label:RED._("menu.label.view.auto"), onselect:function(s) { if(s){RED.text.bidi.setTextDirection("auto")}}}
|
||||
// ]},
|
||||
// null,
|
||||
{id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true},
|
||||
null
|
||||
]});
|
||||
menuOptions.push(null);
|
||||
menuOptions.push({id:"menu-item-import",label:RED._("menu.label.import"),options:[
|
||||
{id:"menu-item-import-clipboard",label:RED._("menu.label.clipboard"),onselect:"core:show-import-dialog"},
|
||||
{id:"menu-item-import-library",label:RED._("menu.label.library"),options:[]}
|
||||
]});
|
||||
menuOptions.push({id:"menu-item-export",label:RED._("menu.label.export"),options:[
|
||||
{id:"menu-item-export-clipboard",label:RED._("menu.label.clipboard"),onselect:"core:show-export-dialog"},
|
||||
{id:"menu-item-export-library",label:RED._("menu.label.library"),disabled:true,onselect:"core:library-export"}
|
||||
]});
|
||||
menuOptions.push(null);
|
||||
menuOptions.push({id:"menu-item-search",label:RED._("menu.label.search"),onselect:"core:search"});
|
||||
menuOptions.push(null);
|
||||
menuOptions.push({id:"menu-item-config-nodes",label:RED._("menu.label.displayConfig"),onselect:"core:show-config-tab"});
|
||||
menuOptions.push({id:"menu-item-workspace",label:RED._("menu.label.flows"),options:[
|
||||
{id:"menu-item-workspace-add",label:RED._("menu.label.add"),onselect:"core:add-flow"},
|
||||
{id:"menu-item-workspace-edit",label:RED._("menu.label.rename"),onselect:"core:edit-flow"},
|
||||
{id:"menu-item-workspace-delete",label:RED._("menu.label.delete"),onselect:"core:remove-flow"}
|
||||
]});
|
||||
menuOptions.push({id:"menu-item-subflow",label:RED._("menu.label.subflows"), options: [
|
||||
{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(null);
|
||||
if (RED.settings.theme('palette.editable') !== false) {
|
||||
menuOptions.push({id:"menu-item-edit-palette",label:RED._("menu.label.editPalette"),onselect:"core:manage-palette"});
|
||||
menuOptions.push(null);
|
||||
}
|
||||
|
||||
menuOptions.push({id:"menu-item-user-settings",label:RED._("menu.label.settings"),onselect:"core:show-user-settings"});
|
||||
menuOptions.push(null);
|
||||
|
||||
menuOptions.push({id:"menu-item-keyboard-shortcuts",label:RED._("menu.label.keyboardShortcuts"),onselect:"core:show-help"});
|
||||
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")
|
||||
});
|
||||
menuOptions.push({id:"menu-item-node-red-version", label:"v"+RED.settings.version, onselect: "core:show-about" });
|
||||
|
||||
|
||||
RED.view.init();
|
||||
RED.userSettings.init();
|
||||
RED.user.init();
|
||||
|
||||
RED.library.init();
|
||||
RED.keyboard.init();
|
||||
RED.palette.init();
|
||||
if (RED.settings.theme('palette.editable') !== false) {
|
||||
RED.palette.editor.init();
|
||||
} else {
|
||||
console.log("Palette editor disabled");
|
||||
}
|
||||
|
||||
RED.sidebar.init();
|
||||
|
||||
if (RED.settings.theme("projects.enabled",false)) {
|
||||
RED.projects.init();
|
||||
} else {
|
||||
console.log("Projects disabled");
|
||||
}
|
||||
|
||||
RED.subflow.init();
|
||||
RED.workspaces.init();
|
||||
RED.clipboard.init();
|
||||
RED.view.init();
|
||||
RED.search.init();
|
||||
RED.editor.init();
|
||||
RED.diff.init();
|
||||
|
||||
RED.menu.init({id:"btn-sidemenu",options: menuOptions});
|
||||
|
||||
RED.deploy.init(RED.settings.theme("deployButton",null));
|
||||
RED.notifications.init();
|
||||
|
||||
RED.keyboard.add(/* ? */ 191,{shift:true},function(){RED.keyboard.showHelp();d3.event.preventDefault();});
|
||||
RED.actions.add("core:show-about", showAbout);
|
||||
RED.nodes.init();
|
||||
RED.comms.connect();
|
||||
|
||||
$("#main-container").show();
|
||||
@@ -225,8 +498,4 @@ var RED = (function() {
|
||||
RED.settings.init(loadEditor);
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
return {
|
||||
};
|
||||
})();
|
||||
|
||||
16
editor/js/red.js
Normal file
@@ -0,0 +1,16 @@
|
||||
/**
|
||||
* 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 RED = {};
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2014 IBM, Antoine Aflalo
|
||||
* 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.
|
||||
@@ -16,9 +16,12 @@
|
||||
|
||||
|
||||
RED.settings = (function () {
|
||||
|
||||
|
||||
var loadedSettings = {};
|
||||
|
||||
var userSettings = {};
|
||||
var settingsDirty = false;
|
||||
var pendingSave;
|
||||
|
||||
var hasLocalStorage = function () {
|
||||
try {
|
||||
return 'localStorage' in window && window['localStorage'] !== null;
|
||||
@@ -31,8 +34,14 @@ RED.settings = (function () {
|
||||
if (!hasLocalStorage()) {
|
||||
return;
|
||||
}
|
||||
localStorage.setItem(key, JSON.stringify(value));
|
||||
if (key === "auth-tokens") {
|
||||
localStorage.setItem(key, JSON.stringify(value));
|
||||
} else {
|
||||
userSettings[key] = value;
|
||||
saveUserSettings();
|
||||
}
|
||||
};
|
||||
|
||||
/**
|
||||
* If the key is not set in the localStorage it returns <i>undefined</i>
|
||||
* Else return the JSON parsed value
|
||||
@@ -43,14 +52,23 @@ RED.settings = (function () {
|
||||
if (!hasLocalStorage()) {
|
||||
return undefined;
|
||||
}
|
||||
return JSON.parse(localStorage.getItem(key));
|
||||
if (key === "auth-tokens") {
|
||||
return JSON.parse(localStorage.getItem(key));
|
||||
} else {
|
||||
return userSettings[key];
|
||||
}
|
||||
};
|
||||
|
||||
var remove = function (key) {
|
||||
if (!hasLocalStorage()) {
|
||||
return;
|
||||
}
|
||||
localStorage.removeItem(key);
|
||||
if (key === "auth-tokens") {
|
||||
localStorage.removeItem(key);
|
||||
} else {
|
||||
delete userSettings[key];
|
||||
saveUserSettings();
|
||||
}
|
||||
};
|
||||
|
||||
var setProperties = function(data) {
|
||||
@@ -67,6 +85,10 @@ RED.settings = (function () {
|
||||
loadedSettings = data;
|
||||
};
|
||||
|
||||
var setUserSettings = function(data) {
|
||||
userSettings = data;
|
||||
}
|
||||
|
||||
var init = function (done) {
|
||||
var accessTokenMatch = /[?&]access_token=(.*?)(?:$|&)/.exec(window.location.search);
|
||||
if (accessTokenMatch) {
|
||||
@@ -74,7 +96,7 @@ RED.settings = (function () {
|
||||
RED.settings.set("auth-tokens",{access_token: accessToken});
|
||||
window.location.search = "";
|
||||
}
|
||||
|
||||
|
||||
$.ajaxSetup({
|
||||
beforeSend: function(jqXHR,settings) {
|
||||
// Only attach auth header for requests to relative paths
|
||||
@@ -83,13 +105,14 @@ RED.settings = (function () {
|
||||
if (auth_tokens) {
|
||||
jqXHR.setRequestHeader("Authorization","Bearer "+auth_tokens.access_token);
|
||||
}
|
||||
jqXHR.setRequestHeader("Node-RED-API-Version","v2");
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
load(done);
|
||||
}
|
||||
|
||||
|
||||
var load = function(done) {
|
||||
$.ajax({
|
||||
headers: {
|
||||
@@ -100,11 +123,11 @@ RED.settings = (function () {
|
||||
url: 'settings',
|
||||
success: function (data) {
|
||||
setProperties(data);
|
||||
if (RED.settings.user && RED.settings.user.anonymous) {
|
||||
if (!RED.settings.user || RED.settings.user.anonymous) {
|
||||
RED.settings.remove("auth-tokens");
|
||||
}
|
||||
console.log("Node-RED: " + data.version);
|
||||
done();
|
||||
loadUserSettings(done);
|
||||
},
|
||||
error: function(jqXHR,textStatus,errorThrown) {
|
||||
if (jqXHR.status === 401) {
|
||||
@@ -112,13 +135,53 @@ RED.settings = (function () {
|
||||
window.location.search = "";
|
||||
}
|
||||
RED.user.login(function() { load(done); });
|
||||
} else {
|
||||
console.log("Unexpected error:",jqXHR.status,textStatus);
|
||||
}
|
||||
} else {
|
||||
console.log("Unexpected error loading settings:",jqXHR.status,textStatus);
|
||||
}
|
||||
}
|
||||
});
|
||||
};
|
||||
|
||||
function loadUserSettings(done) {
|
||||
$.ajax({
|
||||
headers: {
|
||||
"Accept": "application/json"
|
||||
},
|
||||
dataType: "json",
|
||||
cache: false,
|
||||
url: 'settings/user',
|
||||
success: function (data) {
|
||||
setUserSettings(data);
|
||||
done();
|
||||
},
|
||||
error: function(jqXHR,textStatus,errorThrown) {
|
||||
console.log("Unexpected error loading user settings:",jqXHR.status,textStatus);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function saveUserSettings() {
|
||||
if (RED.user.hasPermission("settings.write")) {
|
||||
if (pendingSave) {
|
||||
clearTimeout(pendingSave);
|
||||
}
|
||||
pendingSave = setTimeout(function() {
|
||||
pendingSave = null;
|
||||
$.ajax({
|
||||
method: 'POST',
|
||||
contentType: 'application/json',
|
||||
url: 'settings/user',
|
||||
data: JSON.stringify(userSettings),
|
||||
success: function (data) {
|
||||
},
|
||||
error: function(jqXHR,textStatus,errorThrown) {
|
||||
console.log("Unexpected error saving user settings:",jqXHR.status,textStatus);
|
||||
}
|
||||
});
|
||||
},300);
|
||||
}
|
||||
}
|
||||
|
||||
function theme(property,defaultValue) {
|
||||
if (!RED.settings.editorTheme) {
|
||||
return defaultValue;
|
||||
@@ -129,6 +192,9 @@ RED.settings = (function () {
|
||||
for (var i=0;i<parts.length;i++) {
|
||||
v = v[parts[i]];
|
||||
}
|
||||
if (v === undefined) {
|
||||
return defaultValue;
|
||||
}
|
||||
return v;
|
||||
} catch(err) {
|
||||
return defaultValue;
|
||||
@@ -138,11 +204,10 @@ RED.settings = (function () {
|
||||
return {
|
||||
init: init,
|
||||
load: load,
|
||||
loadUserSettings: loadUserSettings,
|
||||
set: set,
|
||||
get: get,
|
||||
remove: remove,
|
||||
|
||||
theme: theme
|
||||
}
|
||||
})
|
||||
();
|
||||
})();
|
||||
|
||||
130
editor/js/text/bidi.js
Normal file
@@ -0,0 +1,130 @@
|
||||
/**
|
||||
* 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.text = {};
|
||||
RED.text.bidi = (function() {
|
||||
var textDir = "";
|
||||
var LRE = "\u202A",
|
||||
RLE = "\u202B",
|
||||
PDF = "\u202C";
|
||||
|
||||
function isRTLValue(stringValue) {
|
||||
var length = stringValue.length;
|
||||
for (var i=0;i<length;i++) {
|
||||
if (isBidiChar(stringValue.charCodeAt(i))) {
|
||||
return true;
|
||||
}
|
||||
else if(isLatinChar(stringValue.charCodeAt(i))) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function isBidiChar(c) {
|
||||
return (c >= 0x05d0 && c <= 0x05ff)||
|
||||
(c >= 0x0600 && c <= 0x065f)||
|
||||
(c >= 0x066a && c <= 0x06ef)||
|
||||
(c >= 0x06fa && c <= 0x07ff)||
|
||||
(c >= 0xfb1d && c <= 0xfdff)||
|
||||
(c >= 0xfe70 && c <= 0xfefc);
|
||||
}
|
||||
|
||||
function isLatinChar(c){
|
||||
return (c > 64 && c < 91)||(c > 96 && c < 123)
|
||||
}
|
||||
|
||||
/**
|
||||
* Determines the text direction of a given string.
|
||||
* @param value - the string
|
||||
*/
|
||||
function resolveBaseTextDir(value) {
|
||||
if (textDir == "auto") {
|
||||
if (isRTLValue(value)) {
|
||||
return "rtl";
|
||||
} else {
|
||||
return "ltr";
|
||||
}
|
||||
}
|
||||
else {
|
||||
return textDir;
|
||||
}
|
||||
}
|
||||
|
||||
function onInputChange() {
|
||||
$(this).attr("dir", resolveBaseTextDir($(this).val()));
|
||||
}
|
||||
|
||||
/**
|
||||
* Adds event listeners to the Input to ensure its text-direction attribute
|
||||
* is properly set based on its content.
|
||||
* @param input - the input field
|
||||
*/
|
||||
function prepareInput(input) {
|
||||
input.on("keyup",onInputChange).on("paste",onInputChange).on("cut",onInputChange);
|
||||
// Set the initial text direction
|
||||
onInputChange.call(input);
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforces the text direction of a given string by adding
|
||||
* UCC (Unicode Control Characters)
|
||||
* @param value - the string
|
||||
*/
|
||||
function enforceTextDirectionWithUCC(value) {
|
||||
if (value) {
|
||||
var dir = resolveBaseTextDir(value);
|
||||
if (dir == "ltr") {
|
||||
return LRE + value + PDF;
|
||||
}
|
||||
else if (dir == "rtl") {
|
||||
return RLE + value + PDF;
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
/**
|
||||
* Enforces the text direction for all the spans with style bidiAware under
|
||||
* workspace or sidebar div
|
||||
*/
|
||||
function enforceTextDirectionOnPage() {
|
||||
$("#workspace").find('span.bidiAware').each(function() {
|
||||
$(this).attr("dir", resolveBaseTextDir($(this).html()));
|
||||
});
|
||||
$("#sidebar").find('span.bidiAware').each(function() {
|
||||
$(this).attr("dir", resolveBaseTextDir($(this).text()));
|
||||
});
|
||||
}
|
||||
|
||||
/**
|
||||
* Sets the text direction preference
|
||||
* @param dir - the text direction preference
|
||||
*/
|
||||
function setTextDirection(dir) {
|
||||
textDir = dir;
|
||||
RED.nodes.eachNode(function(n) { n.dirty = true;});
|
||||
RED.view.redraw();
|
||||
RED.palette.refresh();
|
||||
enforceTextDirectionOnPage();
|
||||
}
|
||||
|
||||
return {
|
||||
setTextDirection: setTextDirection,
|
||||
enforceTextDirectionWithUCC: enforceTextDirectionWithUCC,
|
||||
resolveBaseTextDir: resolveBaseTextDir,
|
||||
prepareInput: prepareInput
|
||||
}
|
||||
})();
|
||||
1330
editor/js/text/format.js
Normal file
35
editor/js/ui/actions.js
Normal file
@@ -0,0 +1,35 @@
|
||||
RED.actions = (function() {
|
||||
var actions = {
|
||||
|
||||
}
|
||||
|
||||
function addAction(name,handler) {
|
||||
actions[name] = handler;
|
||||
}
|
||||
function removeAction(name) {
|
||||
delete actions[name];
|
||||
}
|
||||
function getAction(name) {
|
||||
return actions[name];
|
||||
}
|
||||
function invokeAction(name) {
|
||||
if (actions.hasOwnProperty(name)) {
|
||||
actions[name]();
|
||||
}
|
||||
}
|
||||
function listActions() {
|
||||
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})
|
||||
})
|
||||
return result;
|
||||
}
|
||||
return {
|
||||
add: addAction,
|
||||
remove: removeAction,
|
||||
get: getAction,
|
||||
invoke: invokeAction,
|
||||
list: listActions
|
||||
}
|
||||
})();
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -21,9 +21,10 @@ RED.clipboard = (function() {
|
||||
var dialogContainer;
|
||||
var exportNodesDialog;
|
||||
var importNodesDialog;
|
||||
var disabled = false;
|
||||
|
||||
function setupDialogs(){
|
||||
dialog = $('<div id="clipboard-dialog" class="hide"><form class="dialog-form form-horizontal"></form></div>')
|
||||
function setupDialogs() {
|
||||
dialog = $('<div id="clipboard-dialog" class="hide node-red-dialog"><form class="dialog-form form-horizontal"></form></div>')
|
||||
.appendTo("body")
|
||||
.dialog({
|
||||
modal: true,
|
||||
@@ -31,16 +32,6 @@ RED.clipboard = (function() {
|
||||
width: 500,
|
||||
resizable: false,
|
||||
buttons: [
|
||||
{
|
||||
id: "clipboard-dialog-ok",
|
||||
text: RED._("common.label.ok"),
|
||||
click: function() {
|
||||
if (/Import/.test(dialog.dialog("option","title"))) {
|
||||
RED.view.importNodes($("#clipboard-import").val());
|
||||
}
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "clipboard-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
@@ -50,44 +41,84 @@ RED.clipboard = (function() {
|
||||
},
|
||||
{
|
||||
id: "clipboard-dialog-close",
|
||||
class: "primary",
|
||||
text: RED._("common.label.close"),
|
||||
click: function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "clipboard-dialog-copy",
|
||||
class: "primary",
|
||||
text: RED._("clipboard.export.copy"),
|
||||
click: function() {
|
||||
$("#clipboard-export").select();
|
||||
document.execCommand("copy");
|
||||
document.getSelection().removeAllRanges();
|
||||
RED.notify(RED._("clipboard.nodesExported"));
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "clipboard-dialog-ok",
|
||||
class: "primary",
|
||||
text: RED._("common.label.import"),
|
||||
click: function() {
|
||||
RED.view.importNodes($("#clipboard-import").val(),$("#import-tab > a.selected").attr('id') === 'import-tab-new');
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
],
|
||||
open: function(e) {
|
||||
$(this).parent().find(".ui-dialog-titlebar-close").hide();
|
||||
RED.keyboard.disable();
|
||||
},
|
||||
close: function(e) {
|
||||
RED.keyboard.enable();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
dialogContainer = dialog.children(".dialog-form");
|
||||
|
||||
exportNodesDialog = '<div class="form-row">'+
|
||||
'<label for="node-input-export" style="display: block; width:100%;"><i class="fa fa-clipboard"></i> '+RED._("clipboard.nodes")+'</label>'+
|
||||
'<textarea readonly style="resize: none; width: 100%; border-radius: 0px;font-family: monospace; font-size: 12px; background:#eee; padding-left: 0.5em; box-sizing:border-box;" id="clipboard-export" rows="5"></textarea>'+
|
||||
exportNodesDialog =
|
||||
'<div class="form-row">'+
|
||||
'<label style="width:auto;margin-right: 10px;" data-i18n="clipboard.export.copy"></label>'+
|
||||
'<span id="export-range-group" class="button-group">'+
|
||||
'<a id="export-range-selected" class="editor-button toggle" href="#" data-i18n="clipboard.export.selected"></a>'+
|
||||
'<a id="export-range-flow" class="editor-button toggle" href="#" data-i18n="clipboard.export.current"></a>'+
|
||||
'<a id="export-range-full" class="editor-button toggle" href="#" data-i18n="clipboard.export.all"></a>'+
|
||||
'</span>'+
|
||||
'</div>'+
|
||||
'<div class="form-row">'+
|
||||
'<textarea readonly style="resize: none; width: 100%; border-radius: 4px;font-family: monospace; font-size: 12px; background:#f3f3f3; padding-left: 0.5em; box-sizing:border-box;" id="clipboard-export" rows="5"></textarea>'+
|
||||
'</div>'+
|
||||
'<div class="form-tips">'+
|
||||
RED._("clipboard.selectNodes")+
|
||||
'<div class="form-row" style="text-align: right;">'+
|
||||
'<span id="export-format-group" class="button-group">'+
|
||||
'<a id="export-format-mini" class="editor-button editor-button-small toggle" href="#" data-i18n="clipboard.export.compact"></a>'+
|
||||
'<a id="export-format-full" class="editor-button editor-button-small toggle" href="#" data-i18n="clipboard.export.formatted"></a>'+
|
||||
'</span>'+
|
||||
'</div>';
|
||||
|
||||
importNodesDialog = '<div class="form-row">'+
|
||||
'<textarea style="resize: none; width: 100%; border-radius: 0px;font-family: monospace; font-size: 12px; background:#eee; padding-left: 0.5em; box-sizing:border-box;" id="clipboard-import" rows="5" placeholder="'+
|
||||
RED._("clipboard.pasteNodes")+
|
||||
'"></textarea>'+
|
||||
'</div>'+
|
||||
'<div class="form-row">'+
|
||||
'<label style="width:auto;margin-right: 10px;" data-i18n="clipboard.import.import"></label>'+
|
||||
'<span id="import-tab" class="button-group">'+
|
||||
'<a id="import-tab-current" class="editor-button toggle selected" href="#" data-i18n="clipboard.export.current"></a>'+
|
||||
'<a id="import-tab-new" class="editor-button toggle" href="#" data-i18n="clipboard.import.newFlow"></a>'+
|
||||
'</span>'+
|
||||
'</div>';
|
||||
}
|
||||
|
||||
function validateImport() {
|
||||
var importInput = $("#clipboard-import");
|
||||
var v = importInput.val();
|
||||
v = v.substring(v.indexOf('['),v.lastIndexOf(']')+1);
|
||||
try {
|
||||
JSON.parse(v);
|
||||
importInput.removeClass("input-error");
|
||||
importInput.val(v);
|
||||
$("#clipboard-dialog-ok").button("enable");
|
||||
} catch(err) {
|
||||
if (v !== "") {
|
||||
@@ -98,74 +129,220 @@ RED.clipboard = (function() {
|
||||
}
|
||||
|
||||
function importNodes() {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
dialogContainer.empty();
|
||||
dialogContainer.append($(importNodesDialog));
|
||||
dialogContainer.i18n();
|
||||
|
||||
$("#clipboard-dialog-ok").show();
|
||||
$("#clipboard-dialog-cancel").show();
|
||||
$("#clipboard-dialog-close").hide();
|
||||
$("#clipboard-dialog-copy").hide();
|
||||
$("#clipboard-dialog-ok").button("disable");
|
||||
$("#clipboard-import").keyup(validateImport);
|
||||
$("#clipboard-import").on('paste',function() { setTimeout(validateImport,10)});
|
||||
|
||||
$("#import-tab > a").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
|
||||
return;
|
||||
}
|
||||
$(this).parent().children().removeClass('selected');
|
||||
$(this).addClass('selected');
|
||||
});
|
||||
|
||||
dialog.dialog("option","title",RED._("clipboard.importNodes")).dialog("open");
|
||||
}
|
||||
|
||||
function exportNodes() {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
|
||||
dialogContainer.empty();
|
||||
dialogContainer.append($(exportNodesDialog));
|
||||
dialogContainer.i18n();
|
||||
var format = RED.settings.flowFilePretty ? "export-format-full" : "export-format-mini";
|
||||
|
||||
$("#export-format-group > a").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
|
||||
$("#clipboard-export").focus();
|
||||
return;
|
||||
}
|
||||
$(this).parent().children().removeClass('selected');
|
||||
$(this).addClass('selected');
|
||||
|
||||
var flow = $("#clipboard-export").val();
|
||||
if (flow.length > 0) {
|
||||
var nodes = JSON.parse(flow);
|
||||
|
||||
format = $(this).attr('id');
|
||||
if (format === 'export-format-full') {
|
||||
flow = JSON.stringify(nodes,null,4);
|
||||
} else {
|
||||
flow = JSON.stringify(nodes);
|
||||
}
|
||||
$("#clipboard-export").val(flow);
|
||||
$("#clipboard-export").focus();
|
||||
}
|
||||
});
|
||||
|
||||
$("#export-range-group > a").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
if ($(this).hasClass('disabled') || $(this).hasClass('selected')) {
|
||||
$("#clipboard-export").focus();
|
||||
return;
|
||||
}
|
||||
$(this).parent().children().removeClass('selected');
|
||||
$(this).addClass('selected');
|
||||
var type = $(this).attr('id');
|
||||
var flow = "";
|
||||
var nodes = null;
|
||||
if (type === 'export-range-selected') {
|
||||
var selection = RED.view.selection();
|
||||
// Don't include the subflow meta-port nodes in the exported selection
|
||||
nodes = RED.nodes.createExportableNodeSet(selection.nodes.filter(function(n) { return n.type !== 'subflow'}));
|
||||
} else if (type === 'export-range-flow') {
|
||||
var activeWorkspace = RED.workspaces.active();
|
||||
nodes = RED.nodes.filterNodes({z:activeWorkspace});
|
||||
var parentNode = RED.nodes.workspace(activeWorkspace)||RED.nodes.subflow(activeWorkspace);
|
||||
nodes.unshift(parentNode);
|
||||
nodes = RED.nodes.createExportableNodeSet(nodes);
|
||||
} else if (type === 'export-range-full') {
|
||||
nodes = RED.nodes.createCompleteNodeSet(false);
|
||||
}
|
||||
if (nodes !== null) {
|
||||
if (format === "export-format-full") {
|
||||
flow = JSON.stringify(nodes,null,4);
|
||||
} else {
|
||||
flow = JSON.stringify(nodes);
|
||||
}
|
||||
}
|
||||
if (flow.length > 0) {
|
||||
$("#export-copy").removeClass('disabled');
|
||||
} else {
|
||||
$("#export-copy").addClass('disabled');
|
||||
}
|
||||
$("#clipboard-export").val(flow);
|
||||
$("#clipboard-export").focus();
|
||||
})
|
||||
|
||||
$("#clipboard-dialog-ok").hide();
|
||||
$("#clipboard-dialog-cancel").hide();
|
||||
$("#clipboard-dialog-close").show();
|
||||
$("#clipboard-dialog-copy").hide();
|
||||
$("#clipboard-dialog-close").hide();
|
||||
var selection = RED.view.selection();
|
||||
if (selection.nodes) {
|
||||
var nns = RED.nodes.createExportableNodeSet(selection.nodes);
|
||||
$("#clipboard-export")
|
||||
.val(JSON.stringify(nns))
|
||||
.focus(function() {
|
||||
var textarea = $(this);
|
||||
textarea.select();
|
||||
textarea.mouseup(function() {
|
||||
textarea.unbind("mouseup");
|
||||
return false;
|
||||
})
|
||||
});
|
||||
dialog.dialog("option","title",RED._("clipboard.exportNodes")).dialog( "open" );
|
||||
$("#export-range-selected").click();
|
||||
} else {
|
||||
$("#export-range-selected").addClass('disabled').removeClass('selected');
|
||||
$("#export-range-flow").click();
|
||||
}
|
||||
if (format === "export-format-full") {
|
||||
$("#export-format-full").click();
|
||||
} else {
|
||||
$("#export-format-mini").click();
|
||||
}
|
||||
$("#clipboard-export")
|
||||
.focus(function() {
|
||||
var textarea = $(this);
|
||||
textarea.select();
|
||||
textarea.mouseup(function() {
|
||||
textarea.unbind("mouseup");
|
||||
return false;
|
||||
})
|
||||
});
|
||||
dialog.dialog("option","title",RED._("clipboard.exportNodes")).dialog( "open" );
|
||||
|
||||
$("#clipboard-export").focus();
|
||||
if (!document.queryCommandSupported("copy")) {
|
||||
$("#clipboard-dialog-cancel").hide();
|
||||
$("#clipboard-dialog-close").show();
|
||||
} else {
|
||||
$("#clipboard-dialog-cancel").show();
|
||||
$("#clipboard-dialog-copy").show();
|
||||
}
|
||||
}
|
||||
|
||||
function hideDropTarget() {
|
||||
$("#dropTarget").hide();
|
||||
RED.keyboard.remove(/* ESCAPE */ 27);
|
||||
RED.keyboard.remove("escape");
|
||||
}
|
||||
function copyText(value,element,msg) {
|
||||
var truncated = false;
|
||||
if (typeof value !== "string" ) {
|
||||
value = JSON.stringify(value, function(key,value) {
|
||||
if (value !== null && typeof value === 'object') {
|
||||
if (value.__enc__) {
|
||||
if (value.hasOwnProperty('data') && value.hasOwnProperty('length')) {
|
||||
truncated = value.data.length !== value.length;
|
||||
return value.data;
|
||||
}
|
||||
if (value.type === 'function' || value.type === 'internal') {
|
||||
return undefined
|
||||
}
|
||||
if (value.type === 'number') {
|
||||
// Handle NaN and Infinity - they are not permitted
|
||||
// in JSON. We can either substitute with a String
|
||||
// representation or null
|
||||
return null;
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
});
|
||||
}
|
||||
if (truncated) {
|
||||
msg += "_truncated";
|
||||
}
|
||||
$("#clipboard-hidden").val(value).select();
|
||||
var result = document.execCommand("copy");
|
||||
if (result && element) {
|
||||
var popover = RED.popover.create({
|
||||
target: element,
|
||||
direction: 'left',
|
||||
size: 'small',
|
||||
content: RED._(msg)
|
||||
});
|
||||
setTimeout(function() {
|
||||
popover.close();
|
||||
},1000);
|
||||
popover.open();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
setupDialogs();
|
||||
RED.events.on("view:selection-changed",function(selection) {
|
||||
if (!selection.nodes) {
|
||||
RED.menu.setDisabled("menu-item-export",true);
|
||||
RED.menu.setDisabled("menu-item-export-clipboard",true);
|
||||
RED.menu.setDisabled("menu-item-export-library",true);
|
||||
} else {
|
||||
RED.menu.setDisabled("menu-item-export",false);
|
||||
RED.menu.setDisabled("menu-item-export-clipboard",false);
|
||||
RED.menu.setDisabled("menu-item-export-library",false);
|
||||
}
|
||||
});
|
||||
RED.keyboard.add(/* e */ 69,{ctrl:true},function(){exportNodes();d3.event.preventDefault();});
|
||||
RED.keyboard.add(/* i */ 73,{ctrl:true},function(){importNodes();d3.event.preventDefault();});
|
||||
|
||||
$('<input type="text" id="clipboard-hidden">').appendTo("body");
|
||||
|
||||
RED.actions.add("core:show-export-dialog",exportNodes);
|
||||
RED.actions.add("core:show-import-dialog",importNodes);
|
||||
|
||||
|
||||
RED.events.on("editor:open",function() { disabled = true; });
|
||||
RED.events.on("editor:close",function() { disabled = false; });
|
||||
RED.events.on("search:open",function() { disabled = true; });
|
||||
RED.events.on("search:close",function() { disabled = false; });
|
||||
RED.events.on("type-search:open",function() { disabled = true; });
|
||||
RED.events.on("type-search:close",function() { disabled = false; });
|
||||
|
||||
|
||||
$('#chart').on("dragenter",function(event) {
|
||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
|
||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 ||
|
||||
$.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
|
||||
$("#dropTarget").css({display:'table'});
|
||||
RED.keyboard.add(/* ESCAPE */ 27,hideDropTarget);
|
||||
RED.keyboard.add("*", "escape" ,hideDropTarget);
|
||||
}
|
||||
});
|
||||
|
||||
$('#dropTarget').on("dragover",function(event) {
|
||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
|
||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 ||
|
||||
$.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
|
||||
event.preventDefault();
|
||||
}
|
||||
})
|
||||
@@ -173,20 +350,30 @@ RED.clipboard = (function() {
|
||||
hideDropTarget();
|
||||
})
|
||||
.on("drop",function(event) {
|
||||
var data = event.originalEvent.dataTransfer.getData("text/plain");
|
||||
if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1) {
|
||||
var data = event.originalEvent.dataTransfer.getData("text/plain");
|
||||
data = data.substring(data.indexOf('['),data.lastIndexOf(']')+1);
|
||||
RED.view.importNodes(data);
|
||||
} else if ($.inArray("Files",event.originalEvent.dataTransfer.types) != -1) {
|
||||
var files = event.originalEvent.dataTransfer.files;
|
||||
if (files.length === 1) {
|
||||
var file = files[0];
|
||||
var reader = new FileReader();
|
||||
reader.onload = (function(theFile) {
|
||||
return function(e) {
|
||||
RED.view.importNodes(e.target.result);
|
||||
};
|
||||
})(file);
|
||||
reader.readAsText(file);
|
||||
}
|
||||
}
|
||||
hideDropTarget();
|
||||
RED.view.importNodes(data);
|
||||
event.preventDefault();
|
||||
});
|
||||
|
||||
|
||||
},
|
||||
import: importNodes,
|
||||
export: exportNodes
|
||||
export: exportNodes,
|
||||
copyText: copyText
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
})();
|
||||
|
||||
131
editor/js/ui/common/checkboxSet.js
Normal file
@@ -0,0 +1,131 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
(function($) {
|
||||
$.widget( "nodered.checkboxSet", {
|
||||
_create: function() {
|
||||
var that = this;
|
||||
this.uiElement = this.element.wrap( "<span>" ).parent();
|
||||
this.uiElement.addClass("red-ui-checkboxSet");
|
||||
if (this.options.parent) {
|
||||
this.parent = this.options.parent;
|
||||
this.parent.checkboxSet('addChild',this.element);
|
||||
}
|
||||
this.children = [];
|
||||
this.partialFlag = false;
|
||||
this.stateValue = 0;
|
||||
var initialState = this.element.prop('checked');
|
||||
this.options = [
|
||||
$('<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();
|
||||
} else {
|
||||
this.options[0].show();
|
||||
}
|
||||
|
||||
this.element.change(function() {
|
||||
if (this.checked) {
|
||||
that.options[0].hide();
|
||||
that.options[1].show();
|
||||
that.options[2].hide();
|
||||
} else {
|
||||
that.options[1].hide();
|
||||
that.options[0].show();
|
||||
that.options[2].hide();
|
||||
}
|
||||
var isChecked = this.checked;
|
||||
that.children.forEach(function(child) {
|
||||
child.checkboxSet('state',isChecked,false,true);
|
||||
})
|
||||
})
|
||||
this.uiElement.click(function(e) {
|
||||
e.stopPropagation();
|
||||
// state returns null for a partial state. Clicking on that should
|
||||
// result in false.
|
||||
that.state((that.state()===false)?true:false);
|
||||
})
|
||||
if (this.parent) {
|
||||
this.parent.checkboxSet('updateChild',this);
|
||||
}
|
||||
},
|
||||
_destroy: function() {
|
||||
if (this.parent) {
|
||||
this.parent.checkboxSet('removeChild',this.element);
|
||||
}
|
||||
},
|
||||
addChild: function(child) {
|
||||
var that = this;
|
||||
this.children.push(child);
|
||||
},
|
||||
removeChild: function(child) {
|
||||
var index = this.children.indexOf(child);
|
||||
if (index > -1) {
|
||||
this.children.splice(index,1);
|
||||
}
|
||||
},
|
||||
updateChild: function(child) {
|
||||
var checkedCount = 0;
|
||||
this.children.forEach(function(c,i) {
|
||||
if (c.checkboxSet('state') === true) {
|
||||
checkedCount++;
|
||||
}
|
||||
});
|
||||
if (checkedCount === 0) {
|
||||
|
||||
this.state(false,true);
|
||||
} else if (checkedCount === this.children.length) {
|
||||
this.state(true,true);
|
||||
} else {
|
||||
this.state(null,true);
|
||||
}
|
||||
},
|
||||
disable: function() {
|
||||
this.uiElement.addClass('disabled');
|
||||
},
|
||||
state: function(state,suppressEvent,suppressParentUpdate) {
|
||||
|
||||
if (arguments.length === 0) {
|
||||
return this.partialFlag?null:this.element.is(":checked");
|
||||
} else {
|
||||
this.partialFlag = (state === null);
|
||||
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();
|
||||
} else if (state === false) {
|
||||
this.options[2].hide();
|
||||
this.options[1].hide();
|
||||
this.options[0].show();
|
||||
} else if (state === null) {
|
||||
this.options[0].hide();
|
||||
this.options[1].hide();
|
||||
this.options[2].show();
|
||||
}
|
||||
if (!suppressEvent) {
|
||||
this.element.trigger('change',null);
|
||||
}
|
||||
if (!suppressParentUpdate && this.parent) {
|
||||
this.parent.checkboxSet('updateChild',this);
|
||||
}
|
||||
}
|
||||
}
|
||||
})
|
||||
|
||||
})(jQuery);
|
||||
332
editor/js/ui/common/editableList.js
Normal file
@@ -0,0 +1,332 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
(function($) {
|
||||
|
||||
/**
|
||||
* options:
|
||||
* - addButton : boolean|string - text for add label, default 'add'
|
||||
* - height : number|'auto'
|
||||
* - resize : function - called when list as a whole is resized
|
||||
* - resizeItem : function(item) - called to resize individual item
|
||||
* - sortable : boolean|string - string is the css selector for handle
|
||||
* - sortItems : function(items) - when order of items changes
|
||||
* - connectWith : css selector of other sortables
|
||||
* - removable : boolean - whether to display delete button on items
|
||||
* - addItem : function(row,index,itemData) - when an item is added
|
||||
* - removeItem : function(itemData) - called when an item is removed
|
||||
* - filter : function(itemData) - called for each item to determine if it should be shown
|
||||
* - sort : function(itemDataA,itemDataB) - called to sort items
|
||||
* - scrollOnAdd : boolean - whether to scroll to newly added items
|
||||
* methods:
|
||||
* - addItem(itemData)
|
||||
* - removeItem(itemData)
|
||||
* - width(width)
|
||||
* - height(height)
|
||||
* - items()
|
||||
* - empty()
|
||||
* - filter(filter)
|
||||
* - sort(sort)
|
||||
* - length()
|
||||
*/
|
||||
$.widget( "nodered.editableList", {
|
||||
_create: function() {
|
||||
var that = this;
|
||||
|
||||
this.element.addClass('red-ui-editableList-list');
|
||||
this.uiWidth = this.element.width();
|
||||
this.uiContainer = this.element
|
||||
.wrap( "<div>" )
|
||||
.parent();
|
||||
|
||||
if (this.options.header) {
|
||||
this.options.header.addClass("red-ui-editableList-header");
|
||||
this.borderContainer = this.uiContainer.wrap("<div>").parent();
|
||||
this.borderContainer.prepend(this.options.header);
|
||||
this.topContainer = this.borderContainer.wrap("<div>").parent();
|
||||
} else {
|
||||
this.topContainer = this.uiContainer.wrap("<div>").parent();
|
||||
}
|
||||
this.topContainer.addClass('red-ui-editableList');
|
||||
if (this.options.class) {
|
||||
this.topContainer.addClass(this.options.class);
|
||||
}
|
||||
|
||||
if (this.options.addButton !== false) {
|
||||
var addLabel;
|
||||
if (typeof this.options.addButton === 'string') {
|
||||
addLabel = this.options.addButton
|
||||
} else {
|
||||
if (RED && RED._) {
|
||||
addLabel = RED._("editableList.add");
|
||||
} else {
|
||||
addLabel = 'add';
|
||||
}
|
||||
}
|
||||
$('<a href="#" class="editor-button editor-button-small red-ui-editableList-addButton" style="margin-top: 4px;"><i class="fa fa-plus"></i> '+addLabel+'</a>')
|
||||
.appendTo(this.topContainer)
|
||||
.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
that.addItem({});
|
||||
});
|
||||
}
|
||||
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");
|
||||
that.element.css(s,'auto');
|
||||
}
|
||||
})
|
||||
this.element.css("position","static");
|
||||
this.topContainer.css("position","absolute");
|
||||
this.uiContainer.css("position","absolute");
|
||||
|
||||
}
|
||||
if (this.options.header) {
|
||||
this.borderContainer.addClass("red-ui-editableList-border");
|
||||
} else {
|
||||
this.uiContainer.addClass("red-ui-editableList-border");
|
||||
}
|
||||
this.uiContainer.addClass("red-ui-editableList-container");
|
||||
|
||||
this.uiHeight = this.element.height();
|
||||
|
||||
this.activeFilter = this.options.filter||null;
|
||||
this.activeSort = this.options.sort||null;
|
||||
this.scrollOnAdd = this.options.scrollOnAdd;
|
||||
if (this.scrollOnAdd === undefined) {
|
||||
this.scrollOnAdd = true;
|
||||
}
|
||||
var minHeight = this.element.css("minHeight");
|
||||
if (minHeight !== '0px') {
|
||||
this.uiContainer.css("minHeight",minHeight);
|
||||
this.element.css("minHeight",0);
|
||||
}
|
||||
var maxHeight = this.element.css("maxHeight");
|
||||
if (maxHeight !== '0px') {
|
||||
this.uiContainer.css("maxHeight",maxHeight);
|
||||
this.element.css("maxHeight",null);
|
||||
}
|
||||
if (this.options.height !== 'auto') {
|
||||
this.uiContainer.css("overflow-y","scroll");
|
||||
if (!isNaN(this.options.height)) {
|
||||
this.uiHeight = this.options.height;
|
||||
}
|
||||
}
|
||||
this.element.height('auto');
|
||||
|
||||
var attrStyle = this.element.attr('style');
|
||||
var m;
|
||||
if ((m = /width\s*:\s*(\d+%)/i.exec(attrStyle)) !== null) {
|
||||
this.element.width('100%');
|
||||
this.uiContainer.width(m[1]);
|
||||
}
|
||||
if (this.options.sortable) {
|
||||
var handle = (typeof this.options.sortable === 'string')?
|
||||
this.options.sortable :
|
||||
".red-ui-editableList-item-handle";
|
||||
var sortOptions = {
|
||||
axis: "y",
|
||||
update: function( event, ui ) {
|
||||
if (that.options.sortItems) {
|
||||
that.options.sortItems(that.items());
|
||||
}
|
||||
},
|
||||
handle:handle,
|
||||
cursor: "move",
|
||||
tolerance: "pointer",
|
||||
forcePlaceholderSize:true,
|
||||
placeholder: "red-ui-editabelList-item-placeholder",
|
||||
start: function(e, ui){
|
||||
ui.placeholder.height(ui.item.height()-4);
|
||||
}
|
||||
};
|
||||
if (this.options.connectWith) {
|
||||
sortOptions.connectWith = this.options.connectWith;
|
||||
}
|
||||
|
||||
this.element.sortable(sortOptions);
|
||||
}
|
||||
|
||||
this._resize();
|
||||
|
||||
// this.menu = this._createMenu(this.types, function(v) { that.type(v) });
|
||||
// this.type(this.options.default||this.types[0].value);
|
||||
},
|
||||
_resize: function() {
|
||||
var currentFullHeight = this.topContainer.height();
|
||||
var innerHeight = this.uiContainer.height();
|
||||
var delta = currentFullHeight - innerHeight;
|
||||
if (this.uiHeight !== 0) {
|
||||
this.uiContainer.height(this.uiHeight-delta);
|
||||
}
|
||||
if (this.options.resize) {
|
||||
this.options.resize();
|
||||
}
|
||||
if (this.options.resizeItem) {
|
||||
var that = this;
|
||||
this.element.children().each(function(i) {
|
||||
that.options.resizeItem($(this).find(".red-ui-editableList-item-content"),i);
|
||||
});
|
||||
}
|
||||
},
|
||||
_destroy: function() {
|
||||
},
|
||||
_refreshFilter: function() {
|
||||
var that = this;
|
||||
var count = 0;
|
||||
if (!this.activeFilter) {
|
||||
return this.element.children().show();
|
||||
}
|
||||
var items = this.items();
|
||||
items.each(function (i,el) {
|
||||
var data = el.data('data');
|
||||
try {
|
||||
if (that.activeFilter(data)) {
|
||||
el.parent().show();
|
||||
count++;
|
||||
} else {
|
||||
el.parent().hide();
|
||||
}
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
el.parent().show();
|
||||
count++;
|
||||
}
|
||||
});
|
||||
return count;
|
||||
},
|
||||
_refreshSort: function() {
|
||||
if (this.activeSort) {
|
||||
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'));
|
||||
});
|
||||
$.each(items,function(idx,li) {
|
||||
that.element.append(li);
|
||||
})
|
||||
}
|
||||
},
|
||||
width: function(desiredWidth) {
|
||||
this.uiWidth = desiredWidth;
|
||||
this._resize();
|
||||
},
|
||||
height: function(desiredHeight) {
|
||||
this.uiHeight = desiredHeight;
|
||||
this._resize();
|
||||
},
|
||||
addItem: function(data) {
|
||||
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) {
|
||||
li.appendTo(this.element);
|
||||
}
|
||||
var row = $('<div/>').addClass("red-ui-editableList-item-content").appendTo(li);
|
||||
row.data('data',data);
|
||||
if (this.options.sortable === true) {
|
||||
$('<i class="red-ui-editableList-item-handle fa fa-bars"></i>').appendTo(li);
|
||||
li.addClass("red-ui-editableList-item-sortable");
|
||||
}
|
||||
if (this.options.removable) {
|
||||
var deleteButton = $('<a/>',{href:"#",class:"red-ui-editableList-item-remove editor-button editor-button-small"}).appendTo(li);
|
||||
$('<i/>',{class:"fa fa-remove"}).appendTo(deleteButton);
|
||||
li.addClass("red-ui-editableList-item-removable");
|
||||
deleteButton.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
var data = row.data('data');
|
||||
li.addClass("red-ui-editableList-item-deleting")
|
||||
li.fadeOut(300, function() {
|
||||
$(this).remove();
|
||||
if (that.options.removeItem) {
|
||||
that.options.removeItem(data);
|
||||
}
|
||||
});
|
||||
});
|
||||
}
|
||||
if (this.options.addItem) {
|
||||
var index = that.element.children().length-1;
|
||||
setTimeout(function() {
|
||||
that.options.addItem(row,index,data);
|
||||
if (that.activeFilter) {
|
||||
try {
|
||||
if (!that.activeFilter(data)) {
|
||||
li.hide();
|
||||
}
|
||||
} catch(err) {
|
||||
}
|
||||
}
|
||||
|
||||
if (!that.activeSort && that.scrollOnAdd) {
|
||||
setTimeout(function() {
|
||||
that.uiContainer.scrollTop(that.element.height());
|
||||
},0);
|
||||
}
|
||||
},0);
|
||||
}
|
||||
},
|
||||
addItems: function(items) {
|
||||
for (var i=0; i<items.length;i++) {
|
||||
this.addItem(items[i]);
|
||||
}
|
||||
},
|
||||
removeItem: function(data) {
|
||||
var items = this.element.children().filter(function(f) {
|
||||
return data === $(this).find(".red-ui-editableList-item-content").data('data');
|
||||
});
|
||||
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"); });
|
||||
},
|
||||
empty: function() {
|
||||
this.element.empty();
|
||||
},
|
||||
filter: function(filter) {
|
||||
if (filter !== undefined) {
|
||||
this.activeFilter = filter;
|
||||
}
|
||||
return this._refreshFilter();
|
||||
},
|
||||
sort: function(sort) {
|
||||
if (sort !== undefined) {
|
||||
this.activeSort = sort;
|
||||
}
|
||||
return this._refreshSort();
|
||||
},
|
||||
length: function() {
|
||||
return this.element.children().length;
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2014 IBM Corp.
|
||||
* 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.
|
||||
@@ -13,9 +13,6 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
|
||||
|
||||
RED.menu = (function() {
|
||||
|
||||
var menuItems = {};
|
||||
@@ -31,20 +28,30 @@ RED.menu = (function() {
|
||||
}
|
||||
|
||||
function setInitialState() {
|
||||
var savedStateActive = isSavedStateActive(opt.id);
|
||||
var savedStateActive = RED.settings.get("menu-" + opt.id);
|
||||
if (opt.setting) {
|
||||
// May need to migrate pre-0.17 setting
|
||||
|
||||
if (savedStateActive !== null) {
|
||||
RED.settings.set(opt.setting,savedStateActive);
|
||||
RED.settings.remove("menu-" + opt.id);
|
||||
} else {
|
||||
savedStateActive = RED.settings.get(opt.setting);
|
||||
}
|
||||
}
|
||||
if (savedStateActive) {
|
||||
link.addClass("active");
|
||||
opt.onselect.call(opt, true);
|
||||
triggerAction(opt.id,true);
|
||||
} else if (savedStateActive === false) {
|
||||
link.removeClass("active");
|
||||
opt.onselect.call(opt, false);
|
||||
triggerAction(opt.id,false);
|
||||
} else if (opt.hasOwnProperty("selected")) {
|
||||
if (opt.selected) {
|
||||
link.addClass("active");
|
||||
} else {
|
||||
link.removeClass("active");
|
||||
}
|
||||
opt.onselect.call(opt, opt.selected);
|
||||
triggerAction(opt.id,opt.selected);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -85,7 +92,8 @@ RED.menu = (function() {
|
||||
menuItems[opt.id] = opt;
|
||||
|
||||
if (opt.onselect) {
|
||||
link.click(function() {
|
||||
link.click(function(e) {
|
||||
e.preventDefault();
|
||||
if ($(this).parent().hasClass("disabled")) {
|
||||
return;
|
||||
}
|
||||
@@ -107,10 +115,12 @@ RED.menu = (function() {
|
||||
setSelected(opt.id, !selected);
|
||||
}
|
||||
} else {
|
||||
opt.onselect.call(opt);
|
||||
triggerAction(opt.id);
|
||||
}
|
||||
});
|
||||
setInitialState();
|
||||
if (opt.toggle) {
|
||||
setInitialState();
|
||||
}
|
||||
} else if (opt.href) {
|
||||
link.attr("target","_blank").attr("href",opt.href);
|
||||
} else if (!opt.options) {
|
||||
@@ -141,15 +151,13 @@ RED.menu = (function() {
|
||||
}
|
||||
function createMenu(options) {
|
||||
|
||||
var button = $("#"+options.id);
|
||||
var menuParent = $("#"+options.id);
|
||||
|
||||
//button.click(function(event) {
|
||||
// $("#"+options.id+"-submenu").show();
|
||||
// event.preventDefault();
|
||||
//});
|
||||
var topMenu = $("<ul/>",{id:options.id+"-submenu", class:"dropdown-menu pull-right"});
|
||||
|
||||
|
||||
var topMenu = $("<ul/>",{id:options.id+"-submenu", class:"dropdown-menu pull-right"}).insertAfter(button);
|
||||
if (menuParent.length === 1) {
|
||||
topMenu.insertAfter(menuParent);
|
||||
}
|
||||
|
||||
var lastAddedSeparator = false;
|
||||
for (var i=0;i<options.options.length;i++) {
|
||||
@@ -162,20 +170,27 @@ RED.menu = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return topMenu;
|
||||
}
|
||||
|
||||
function isSavedStateActive(id) {
|
||||
return RED.settings.get("menu-" + id);
|
||||
function triggerAction(id, args) {
|
||||
var opt = menuItems[id];
|
||||
var callback = opt.onselect;
|
||||
if (typeof opt.onselect === 'string') {
|
||||
callback = RED.actions.get(opt.onselect);
|
||||
}
|
||||
if (callback) {
|
||||
callback.call(opt,args);
|
||||
} else {
|
||||
console.log("No callback for",id,opt.onselect);
|
||||
}
|
||||
}
|
||||
|
||||
function isSelected(id) {
|
||||
return $("#" + id).hasClass("active");
|
||||
}
|
||||
|
||||
function setSavedState(id, state) {
|
||||
RED.settings.set("menu-" + id, state);
|
||||
}
|
||||
|
||||
function setSelected(id,state) {
|
||||
if (isSelected(id) == state) {
|
||||
return;
|
||||
@@ -187,9 +202,13 @@ RED.menu = (function() {
|
||||
$("#"+id).removeClass("active");
|
||||
}
|
||||
if (opt && opt.onselect) {
|
||||
opt.onselect.call(opt,state);
|
||||
triggerAction(opt.id,state);
|
||||
}
|
||||
setSavedState(id, state);
|
||||
RED.settings.set(opt.setting||("menu-"+opt.id), state);
|
||||
}
|
||||
|
||||
function toggleSelected(id) {
|
||||
setSelected(id,!isSelected(id));
|
||||
}
|
||||
|
||||
function setDisabled(id,state) {
|
||||
@@ -231,16 +250,6 @@ RED.menu = (function() {
|
||||
var opt = menuItems[id];
|
||||
if (opt) {
|
||||
opt.onselect = action;
|
||||
$("#"+id).click(function() {
|
||||
if ($(this).parent().hasClass("disabled")) {
|
||||
return;
|
||||
}
|
||||
if (menuItems[id].toggle) {
|
||||
setSelected(id,!isSelected(id));
|
||||
} else {
|
||||
menuItems[id].onselect.call(menuItems[id]);
|
||||
}
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
@@ -248,6 +257,7 @@ RED.menu = (function() {
|
||||
init: createMenu,
|
||||
setSelected: setSelected,
|
||||
isSelected: isSelected,
|
||||
toggleSelected: toggleSelected,
|
||||
setDisabled: setDisabled,
|
||||
addItem: addItem,
|
||||
removeItem: removeItem,
|
||||
81
editor/js/ui/common/panels.js
Normal file
@@ -0,0 +1,81 @@
|
||||
/**
|
||||
* 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.panels = (function() {
|
||||
|
||||
function createPanel(options) {
|
||||
var container = options.container || $("#"+options.id);
|
||||
var children = container.children();
|
||||
if (children.length !== 2) {
|
||||
throw new Error("Container must have exactly two children");
|
||||
}
|
||||
|
||||
container.addClass("red-ui-panels");
|
||||
var separator = $('<div class="red-ui-panels-separator"></div>').insertAfter(children[0]);
|
||||
var startPosition;
|
||||
var panelHeights = [];
|
||||
var modifiedHeights = false;
|
||||
var panelRatio;
|
||||
|
||||
separator.draggable({
|
||||
axis: "y",
|
||||
containment: container,
|
||||
scroll: false,
|
||||
start:function(event,ui) {
|
||||
var height = container.height();
|
||||
startPosition = ui.position.top;
|
||||
panelHeights = [$(children[0]).height(),$(children[1]).height()];
|
||||
},
|
||||
drag: function(event,ui) {
|
||||
var height = container.height();
|
||||
var delta = ui.position.top-startPosition;
|
||||
var newHeights = [panelHeights[0]+delta,panelHeights[1]-delta];
|
||||
$(children[0]).height(newHeights[0]);
|
||||
$(children[1]).height(newHeights[1]);
|
||||
if (options.resize) {
|
||||
options.resize(newHeights[0],newHeights[1]);
|
||||
}
|
||||
ui.position.top -= delta;
|
||||
panelRatio = newHeights[0]/height;
|
||||
},
|
||||
stop:function(event,ui) {
|
||||
modifiedHeights = true;
|
||||
}
|
||||
});
|
||||
|
||||
return {
|
||||
resize: function(height) {
|
||||
var panelHeights = [$(children[0]).height(),$(children[1]).height()];
|
||||
container.height(height);
|
||||
if (modifiedHeights) {
|
||||
var topPanelHeight = panelRatio*height;
|
||||
var bottomPanelHeight = height - topPanelHeight - 48;
|
||||
panelHeights = [topPanelHeight,bottomPanelHeight];
|
||||
$(children[0]).height(panelHeights[0]);
|
||||
$(children[1]).height(panelHeights[1]);
|
||||
}
|
||||
if (options.resize) {
|
||||
options.resize(panelHeights[0],panelHeights[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
create: createPanel
|
||||
}
|
||||
})();
|
||||
171
editor/js/ui/common/popover.js
Normal file
@@ -0,0 +1,171 @@
|
||||
/**
|
||||
* 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.popover = (function() {
|
||||
var deltaSizes = {
|
||||
"default": {
|
||||
top: 10,
|
||||
leftRight: 17,
|
||||
leftLeft: 25,
|
||||
leftBottom: 8,
|
||||
},
|
||||
"small": {
|
||||
top: 5,
|
||||
leftRight: 17,
|
||||
leftLeft: 16,
|
||||
leftBottom: 3,
|
||||
}
|
||||
}
|
||||
function createPopover(options) {
|
||||
var target = options.target;
|
||||
var direction = options.direction || "right";
|
||||
var trigger = options.trigger;
|
||||
var content = options.content;
|
||||
var delay = options.delay;
|
||||
var autoClose = options.autoClose;
|
||||
var width = options.width||"auto";
|
||||
var size = options.size||"default";
|
||||
if (!deltaSizes[size]) {
|
||||
throw new Error("Invalid RED.popover size value:",size);
|
||||
}
|
||||
|
||||
var timer = null;
|
||||
var active;
|
||||
var div;
|
||||
|
||||
var openPopup = function(instant) {
|
||||
if (active) {
|
||||
div = $('<div class="red-ui-popover red-ui-popover-'+direction+'"></div>');
|
||||
if (size !== "default") {
|
||||
div.addClass("red-ui-popover-size-"+size);
|
||||
}
|
||||
if (typeof content === 'function') {
|
||||
var result = content.call(res);
|
||||
if (result === null) {
|
||||
return;
|
||||
}
|
||||
if (typeof result === 'string') {
|
||||
div.text(result);
|
||||
} else {
|
||||
div.append(result);
|
||||
}
|
||||
} else {
|
||||
div.html(content);
|
||||
}
|
||||
if (width !== "auto") {
|
||||
div.width(width);
|
||||
}
|
||||
div.appendTo("body");
|
||||
|
||||
var targetPos = target.offset();
|
||||
var targetWidth = target.outerWidth();
|
||||
var targetHeight = target.outerHeight();
|
||||
var divHeight = div.height();
|
||||
var divWidth = div.width();
|
||||
if (direction === 'right') {
|
||||
div.css({top: targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top,left:targetPos.left+targetWidth+deltaSizes[size].leftRight});
|
||||
} else if (direction === 'left') {
|
||||
div.css({top: targetPos.top+targetHeight/2-divHeight/2-deltaSizes[size].top,left:targetPos.left-deltaSizes[size].leftLeft-divWidth});
|
||||
} else if (direction === 'bottom') {
|
||||
div.css({top: targetPos.top+targetHeight+deltaSizes[size].top,left:targetPos.left+targetWidth/2-divWidth/2 - deltaSizes[size].leftBottom});
|
||||
}
|
||||
if (instant) {
|
||||
div.show();
|
||||
} else {
|
||||
div.fadeIn("fast");
|
||||
}
|
||||
}
|
||||
}
|
||||
var closePopup = function(instant) {
|
||||
if (!active) {
|
||||
if (div) {
|
||||
if (instant) {
|
||||
$(this).remove();
|
||||
} else {
|
||||
div.fadeOut("fast",function() {
|
||||
$(this).remove();
|
||||
});
|
||||
}
|
||||
div = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (trigger === 'hover') {
|
||||
target.on('mouseenter',function(e) {
|
||||
clearTimeout(timer);
|
||||
active = true;
|
||||
timer = setTimeout(openPopup,delay.show);
|
||||
});
|
||||
target.on('mouseleave', function(e) {
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
active = false;
|
||||
setTimeout(closePopup,delay.hide);
|
||||
});
|
||||
} else if (trigger === 'click') {
|
||||
target.click(function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
active = !active;
|
||||
if (!active) {
|
||||
closePopup();
|
||||
} else {
|
||||
openPopup();
|
||||
}
|
||||
});
|
||||
} else if (autoClose) {
|
||||
setTimeout(function() {
|
||||
active = false;
|
||||
closePopup();
|
||||
},autoClose);
|
||||
}
|
||||
var res = {
|
||||
setContent: function(_content) {
|
||||
content = _content;
|
||||
return res;
|
||||
},
|
||||
open: function (instant) {
|
||||
active = true;
|
||||
openPopup(instant);
|
||||
return res;
|
||||
},
|
||||
close: function (instant) {
|
||||
active = false;
|
||||
closePopup(instant);
|
||||
return res;
|
||||
}
|
||||
}
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
create: createPopover,
|
||||
tooltip: function(target,content) {
|
||||
RED.popover.create({
|
||||
target:target,
|
||||
trigger: "hover",
|
||||
size: "small",
|
||||
direction: "bottom",
|
||||
content: content,
|
||||
delay: { show: 550, hide: 10 }
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
})();
|
||||
99
editor/js/ui/common/searchBox.js
Normal file
@@ -0,0 +1,99 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
(function($) {
|
||||
|
||||
$.widget( "nodered.searchBox", {
|
||||
_create: function() {
|
||||
var that = this;
|
||||
|
||||
this.currentTimeout = null;
|
||||
this.lastSent = "";
|
||||
this.element.val("");
|
||||
this.uiContainer = this.element.wrap("<div>").parent();
|
||||
this.uiContainer.addClass("red-ui-searchBox-container");
|
||||
|
||||
$('<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.on("click",function(e) {
|
||||
e.preventDefault();
|
||||
that.element.val("");
|
||||
that._change("",true);
|
||||
that.element.focus();
|
||||
});
|
||||
|
||||
this.resultCount = $('<span>',{class:"red-ui-searchBox-resultCount hide"}).appendTo(this.uiContainer);
|
||||
|
||||
this.element.val("");
|
||||
this.element.on("keydown",function(evt) {
|
||||
if (evt.keyCode === 27) {
|
||||
that.element.val("");
|
||||
}
|
||||
})
|
||||
this.element.on("keyup",function(evt) {
|
||||
that._change($(this).val());
|
||||
});
|
||||
|
||||
this.element.on("focus",function() {
|
||||
$("body").one("mousedown",function() {
|
||||
that.element.blur();
|
||||
});
|
||||
});
|
||||
|
||||
},
|
||||
_change: function(val,instant) {
|
||||
var fireEvent = false;
|
||||
if (val === "") {
|
||||
this.clearButton.hide();
|
||||
fireEvent = true;
|
||||
} else {
|
||||
this.clearButton.show();
|
||||
fireEvent = (val.length >= (this.options.minimumLength||0));
|
||||
}
|
||||
var current = this.element.val();
|
||||
fireEvent = fireEvent && current !== this.lastSent;
|
||||
if (fireEvent) {
|
||||
if (!instant && this.options.delay > 0) {
|
||||
clearTimeout(this.currentTimeout);
|
||||
var that = this;
|
||||
this.currentTimeout = setTimeout(function() {
|
||||
that.lastSent = that.element.val();
|
||||
that._trigger("change");
|
||||
},this.options.delay);
|
||||
} else {
|
||||
this._trigger("change");
|
||||
}
|
||||
}
|
||||
},
|
||||
value: function(val) {
|
||||
if (val === undefined) {
|
||||
return this.element.val();
|
||||
} else {
|
||||
this.element.val(val);
|
||||
this._change(val);
|
||||
}
|
||||
},
|
||||
count: function(val) {
|
||||
if (val === undefined || val === null || val === "") {
|
||||
this.resultCount.text("").hide();
|
||||
} else {
|
||||
this.resultCount.text(val).show();
|
||||
}
|
||||
},
|
||||
change: function() {
|
||||
this._trigger("change");
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
161
editor/js/ui/common/stack.js
Normal file
@@ -0,0 +1,161 @@
|
||||
/**
|
||||
* 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.stack = (function() {
|
||||
function createStack(options) {
|
||||
var container = options.container;
|
||||
container.addClass("red-ui-stack");
|
||||
var contentHeight = 0;
|
||||
var entries = [];
|
||||
|
||||
var visible = true;
|
||||
// TODO: make this a singleton function - and watch out for stacks no longer
|
||||
// in the DOM
|
||||
var resizeStack = function() {
|
||||
if (entries.length > 0) {
|
||||
var headerHeight = 0;
|
||||
entries.forEach(function(entry) {
|
||||
headerHeight += entry.header.outerHeight();
|
||||
});
|
||||
|
||||
var height = container.innerHeight();
|
||||
contentHeight = height - headerHeight - (entries.length-1);
|
||||
entries.forEach(function(e) {
|
||||
e.contentWrap.height(contentHeight);
|
||||
});
|
||||
}
|
||||
}
|
||||
if (options.fill && options.singleExpanded) {
|
||||
$(window).resize(resizeStack);
|
||||
$(window).focus(resizeStack);
|
||||
}
|
||||
return {
|
||||
add: function(entry) {
|
||||
entries.push(entry);
|
||||
entry.container = $('<div class="palette-category">').appendTo(container);
|
||||
if (!visible) {
|
||||
entry.container.hide();
|
||||
}
|
||||
var header = $('<div class="palette-header"></div>').appendTo(entry.container);
|
||||
entry.header = header;
|
||||
entry.contentWrap = $('<div></div>',{style:"position:relative"}).appendTo(entry.container);
|
||||
if (options.fill) {
|
||||
entry.contentWrap.css("height",contentHeight);
|
||||
}
|
||||
entry.content = $('<div></div>').appendTo(entry.contentWrap);
|
||||
if (entry.collapsible !== false) {
|
||||
header.click(function() {
|
||||
if (options.singleExpanded) {
|
||||
if (!entry.isExpanded()) {
|
||||
for (var i=0;i<entries.length;i++) {
|
||||
if (entries[i].isExpanded()) {
|
||||
entries[i].collapse();
|
||||
}
|
||||
}
|
||||
entry.expand();
|
||||
}
|
||||
} else {
|
||||
entry.toggle();
|
||||
}
|
||||
});
|
||||
var icon = $('<i class="fa fa-angle-down"></i>').appendTo(header);
|
||||
|
||||
if (entry.expanded) {
|
||||
entry.container.addClass("palette-category-expanded");
|
||||
icon.addClass("expanded");
|
||||
} else {
|
||||
entry.contentWrap.hide();
|
||||
}
|
||||
} else {
|
||||
$('<i style="opacity: 0.5;" class="fa fa-angle-down expanded"></i>').appendTo(header);
|
||||
header.css("cursor","default");
|
||||
}
|
||||
entry.title = $('<span></span>').html(entry.title).appendTo(header);
|
||||
|
||||
|
||||
|
||||
entry.toggle = function() {
|
||||
if (entry.isExpanded()) {
|
||||
entry.collapse();
|
||||
return false;
|
||||
} else {
|
||||
entry.expand();
|
||||
return true;
|
||||
}
|
||||
};
|
||||
entry.expand = function() {
|
||||
if (!entry.isExpanded()) {
|
||||
if (entry.onexpand) {
|
||||
entry.onexpand.call(entry);
|
||||
}
|
||||
if (options.singleExpanded) {
|
||||
entries.forEach(function(e) {
|
||||
if (e !== entry) {
|
||||
e.collapse();
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
icon.addClass("expanded");
|
||||
entry.container.addClass("palette-category-expanded");
|
||||
entry.contentWrap.slideDown(200);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
entry.collapse = function() {
|
||||
if (entry.isExpanded()) {
|
||||
icon.removeClass("expanded");
|
||||
entry.container.removeClass("palette-category-expanded");
|
||||
entry.contentWrap.slideUp(200);
|
||||
return true;
|
||||
}
|
||||
};
|
||||
entry.isExpanded = function() {
|
||||
return entry.container.hasClass("palette-category-expanded");
|
||||
};
|
||||
if (options.fill && options.singleExpanded) {
|
||||
resizeStack();
|
||||
}
|
||||
return entry;
|
||||
},
|
||||
|
||||
hide: function() {
|
||||
visible = false;
|
||||
entries.forEach(function(entry) {
|
||||
entry.container.hide();
|
||||
});
|
||||
return this;
|
||||
},
|
||||
|
||||
show: function() {
|
||||
visible = true;
|
||||
entries.forEach(function(entry) {
|
||||
entry.container.show();
|
||||
});
|
||||
return this;
|
||||
},
|
||||
resize: function() {
|
||||
if (resizeStack) {
|
||||
resizeStack();
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
create: createStack
|
||||
}
|
||||
})();
|
||||
508
editor/js/ui/common/tabs.js
Normal file
@@ -0,0 +1,508 @@
|
||||
/**
|
||||
* 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.tabs = (function() {
|
||||
|
||||
var defaultTabIcon = "fa fa-lemon-o";
|
||||
|
||||
function createTabs(options) {
|
||||
var tabs = {};
|
||||
var pinnedTabsCount = 0;
|
||||
var currentTabWidth;
|
||||
var currentActiveTabWidth = 0;
|
||||
var collapsibleMenu;
|
||||
|
||||
var ul = options.element || $("#"+options.id);
|
||||
var wrapper = ul.wrap( "<div>" ).parent();
|
||||
var scrollContainer = ul.wrap( "<div>" ).parent();
|
||||
wrapper.addClass("red-ui-tabs");
|
||||
if (options.vertical) {
|
||||
wrapper.addClass("red-ui-tabs-vertical");
|
||||
}
|
||||
if (options.addButton && typeof options.addButton === 'function') {
|
||||
wrapper.addClass("red-ui-tabs-add");
|
||||
var addButton = $('<div class="red-ui-tab-button"><a href="#"><i class="fa fa-plus"></i></a></div>').appendTo(wrapper);
|
||||
addButton.find('a').click(function(evt) {
|
||||
evt.preventDefault();
|
||||
options.addButton();
|
||||
})
|
||||
|
||||
}
|
||||
var scrollLeft;
|
||||
var scrollRight;
|
||||
|
||||
if (options.scrollable) {
|
||||
wrapper.addClass("red-ui-tabs-scrollable");
|
||||
scrollContainer.addClass("red-ui-tabs-scroll-container");
|
||||
scrollContainer.scroll(updateScroll);
|
||||
scrollLeft = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-left"><a href="#" style="display:none;"><i class="fa fa-caret-left"></i></a></div>').appendTo(wrapper).find("a");
|
||||
scrollLeft.on('mousedown',function(evt) { scrollEventHandler(evt,'-=150') }).on('click',function(evt){ evt.preventDefault();});
|
||||
scrollRight = $('<div class="red-ui-tab-button red-ui-tab-scroll red-ui-tab-scroll-right"><a href="#" style="display:none;"><i class="fa fa-caret-right"></i></a></div>').appendTo(wrapper).find("a");
|
||||
scrollRight.on('mousedown',function(evt) { scrollEventHandler(evt,'+=150') }).on('click',function(evt){ evt.preventDefault();});
|
||||
}
|
||||
|
||||
if (options.collapsible) {
|
||||
// var dropDown = $('<div>',{class:"red-ui-tabs-select"}).appendTo(wrapper);
|
||||
// ul.hide();
|
||||
wrapper.addClass("red-ui-tabs-collapsible");
|
||||
|
||||
var collapsedButtonsRow = $('<div class="red-ui-tab-link-buttons"></div>').appendTo(wrapper);
|
||||
|
||||
var selectButton = $('<a href="#"><i class="fa fa-caret-down"></i></a>').appendTo(collapsedButtonsRow);
|
||||
selectButton.addClass("red-ui-tab-link-button-menu")
|
||||
selectButton.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
if (!collapsibleMenu) {
|
||||
var pinnedOptions = [];
|
||||
var options = [];
|
||||
ul.children().each(function(i,el) {
|
||||
var id = $(el).data('tabId');
|
||||
var opt = {
|
||||
id:"red-ui-tabs-menu-option-"+id,
|
||||
icon: tabs[id].iconClass || defaultTabIcon,
|
||||
label: tabs[id].name,
|
||||
onselect: function() {
|
||||
activateTab(id);
|
||||
}
|
||||
};
|
||||
if (tabs[id].pinned) {
|
||||
pinnedOptions.push(opt);
|
||||
} else {
|
||||
options.push(opt);
|
||||
}
|
||||
});
|
||||
options = pinnedOptions.concat(options);
|
||||
collapsibleMenu = RED.menu.init({id:"debug-message-option-menu",options: options});
|
||||
collapsibleMenu.css({
|
||||
position: "absolute"
|
||||
})
|
||||
collapsibleMenu.on('mouseleave', function(){ $(this).hide() });
|
||||
collapsibleMenu.on('mouseup', function() { $(this).hide() });
|
||||
collapsibleMenu.appendTo("body");
|
||||
}
|
||||
var elementPos = selectButton.offset();
|
||||
collapsibleMenu.css({
|
||||
top: (elementPos.top+selectButton.height()-20)+"px",
|
||||
left: (elementPos.left - collapsibleMenu.width() + selectButton.width())+"px"
|
||||
})
|
||||
collapsibleMenu.toggle();
|
||||
})
|
||||
|
||||
}
|
||||
|
||||
function scrollEventHandler(evt,dir) {
|
||||
evt.preventDefault();
|
||||
if ($(this).hasClass('disabled')) {
|
||||
return;
|
||||
}
|
||||
var currentScrollLeft = scrollContainer.scrollLeft();
|
||||
scrollContainer.animate( { scrollLeft: dir }, 100);
|
||||
var interval = setInterval(function() {
|
||||
var newScrollLeft = scrollContainer.scrollLeft()
|
||||
if (newScrollLeft === currentScrollLeft) {
|
||||
clearInterval(interval);
|
||||
return;
|
||||
}
|
||||
currentScrollLeft = newScrollLeft;
|
||||
scrollContainer.animate( { scrollLeft: dir }, 100);
|
||||
},100);
|
||||
$(this).one('mouseup',function() {
|
||||
clearInterval(interval);
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
ul.children().first().addClass("active");
|
||||
ul.children().addClass("red-ui-tab");
|
||||
|
||||
function onTabClick() {
|
||||
if (options.onclick) {
|
||||
options.onclick(tabs[$(this).attr('href').slice(1)]);
|
||||
}
|
||||
activateTab($(this));
|
||||
return false;
|
||||
}
|
||||
|
||||
function updateScroll() {
|
||||
if (ul.children().length !== 0) {
|
||||
var sl = scrollContainer.scrollLeft();
|
||||
var scWidth = scrollContainer.width();
|
||||
var ulWidth = ul.width();
|
||||
if (sl === 0) {
|
||||
scrollLeft.hide();
|
||||
} else {
|
||||
scrollLeft.show();
|
||||
}
|
||||
if (sl === ulWidth-scWidth) {
|
||||
scrollRight.hide();
|
||||
} else {
|
||||
scrollRight.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
function onTabDblClick() {
|
||||
if (options.ondblclick) {
|
||||
options.ondblclick(tabs[$(this).attr('href').slice(1)]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function activateTab(link) {
|
||||
if (typeof link === "string") {
|
||||
link = ul.find("a[href='#"+link+"']");
|
||||
}
|
||||
if (link.length === 0) {
|
||||
return;
|
||||
}
|
||||
if (!link.parent().hasClass("active")) {
|
||||
ul.children().removeClass("active");
|
||||
ul.children().css({"transition": "width 100ms"});
|
||||
link.parent().addClass("active");
|
||||
var parentId = link.parent().attr('id');
|
||||
wrapper.find(".red-ui-tab-link-button").removeClass("active selected");
|
||||
$("#"+parentId+"-link-button").addClass("active selected");
|
||||
if (options.scrollable) {
|
||||
var pos = link.parent().position().left;
|
||||
if (pos-21 < 0) {
|
||||
scrollContainer.animate( { scrollLeft: '+='+(pos-50) }, 300);
|
||||
} else if (pos + 120 > scrollContainer.width()) {
|
||||
scrollContainer.animate( { scrollLeft: '+='+(pos + 140-scrollContainer.width()) }, 300);
|
||||
}
|
||||
}
|
||||
if (options.onchange) {
|
||||
options.onchange(tabs[link.attr('href').slice(1)]);
|
||||
}
|
||||
updateTabWidths();
|
||||
setTimeout(function() {
|
||||
ul.children().css({"transition": ""});
|
||||
},100);
|
||||
}
|
||||
}
|
||||
function activatePreviousTab() {
|
||||
var previous = ul.find("li.active").prev();
|
||||
if (previous.length > 0) {
|
||||
activateTab(previous.find("a"));
|
||||
}
|
||||
}
|
||||
function activateNextTab() {
|
||||
var next = ul.find("li.active").next();
|
||||
if (next.length > 0) {
|
||||
activateTab(next.find("a"));
|
||||
}
|
||||
}
|
||||
|
||||
function updateTabWidths() {
|
||||
if (options.vertical) {
|
||||
return;
|
||||
}
|
||||
var tabs = ul.find("li.red-ui-tab");
|
||||
var width = wrapper.width();
|
||||
var tabCount = tabs.size();
|
||||
var tabWidth;
|
||||
|
||||
if (options.collapsible) {
|
||||
tabWidth = width - collapsedButtonsRow.width()-10;
|
||||
if (tabWidth < 198) {
|
||||
var delta = 198 - tabWidth;
|
||||
var b = collapsedButtonsRow.find("a:last").prev();
|
||||
while (b.is(":not(:visible)")) {
|
||||
b = b.prev();
|
||||
}
|
||||
if (!b.hasClass("red-ui-tab-link-button-pinned")) {
|
||||
b.hide();
|
||||
}
|
||||
tabWidth = width - collapsedButtonsRow.width()-10;
|
||||
} else {
|
||||
var space = width - 198 - collapsedButtonsRow.width();
|
||||
if (space > 40) {
|
||||
collapsedButtonsRow.find("a:not(:visible):first").show();
|
||||
tabWidth = width - collapsedButtonsRow.width()-10;
|
||||
}
|
||||
}
|
||||
tabs.css({width:tabWidth});
|
||||
|
||||
} else {
|
||||
var tabWidth = (width-12-(tabCount*6))/tabCount;
|
||||
currentTabWidth = (100*tabWidth/width)+"%";
|
||||
currentActiveTabWidth = currentTabWidth+"%";
|
||||
if (options.scrollable) {
|
||||
tabWidth = Math.max(tabWidth,140);
|
||||
currentTabWidth = tabWidth+"px";
|
||||
currentActiveTabWidth = 0;
|
||||
var listWidth = Math.max(wrapper.width(),12+(tabWidth+6)*tabCount);
|
||||
ul.width(listWidth);
|
||||
updateScroll();
|
||||
} else if (options.hasOwnProperty("minimumActiveTabWidth")) {
|
||||
if (tabWidth < options.minimumActiveTabWidth) {
|
||||
tabCount -= 1;
|
||||
tabWidth = (width-12-options.minimumActiveTabWidth-(tabCount*6))/tabCount;
|
||||
currentTabWidth = (100*tabWidth/width)+"%";
|
||||
currentActiveTabWidth = options.minimumActiveTabWidth+"px";
|
||||
} else {
|
||||
currentActiveTabWidth = 0;
|
||||
}
|
||||
}
|
||||
if (options.collapsible) {
|
||||
console.log(currentTabWidth);
|
||||
}
|
||||
|
||||
tabs.css({width:currentTabWidth});
|
||||
if (tabWidth < 50) {
|
||||
ul.find(".red-ui-tab-close").hide();
|
||||
ul.find(".red-ui-tab-icon").hide();
|
||||
ul.find(".red-ui-tab-label").css({paddingLeft:Math.min(12,Math.max(0,tabWidth-38))+"px"})
|
||||
} else {
|
||||
ul.find(".red-ui-tab-close").show();
|
||||
ul.find(".red-ui-tab-icon").show();
|
||||
ul.find(".red-ui-tab-label").css({paddingLeft:""})
|
||||
}
|
||||
if (currentActiveTabWidth !== 0) {
|
||||
ul.find("li.red-ui-tab.active").css({"width":options.minimumActiveTabWidth});
|
||||
ul.find("li.red-ui-tab.active .red-ui-tab-close").show();
|
||||
ul.find("li.red-ui-tab.active .red-ui-tab-icon").show();
|
||||
ul.find("li.red-ui-tab.active .red-ui-tab-label").css({paddingLeft:""})
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ul.find("li.red-ui-tab a").on("click",onTabClick).on("dblclick",onTabDblClick);
|
||||
setTimeout(function() {
|
||||
updateTabWidths();
|
||||
},0);
|
||||
|
||||
|
||||
function removeTab(id) {
|
||||
var li = ul.find("a[href='#"+id+"']").parent();
|
||||
if (li.hasClass("active")) {
|
||||
var tab = li.prev();
|
||||
if (tab.size() === 0) {
|
||||
tab = li.next();
|
||||
}
|
||||
activateTab(tab.find("a"));
|
||||
}
|
||||
li.remove();
|
||||
if (tabs[id].pinned) {
|
||||
pinnedTabsCount--;
|
||||
}
|
||||
if (options.onremove) {
|
||||
options.onremove(tabs[id]);
|
||||
}
|
||||
delete tabs[id];
|
||||
updateTabWidths();
|
||||
collapsibleMenu = null;
|
||||
}
|
||||
|
||||
return {
|
||||
addTab: function(tab) {
|
||||
tabs[tab.id] = tab;
|
||||
var li = $("<li/>",{class:"red-ui-tab"}).appendTo(ul);
|
||||
li.attr('id',"red-ui-tab-"+(tab.id.replace(".","-")));
|
||||
li.data("tabId",tab.id);
|
||||
|
||||
if (options.maximumTabWidth) {
|
||||
li.css("maxWidth",options.maximumTabWidth+"px");
|
||||
}
|
||||
var link = $("<a/>",{href:"#"+tab.id, class:"red-ui-tab-label"}).appendTo(li);
|
||||
if (tab.icon) {
|
||||
$('<img src="'+tab.icon+'" class="red-ui-tab-icon"/>').appendTo(link);
|
||||
} else if (tab.iconClass) {
|
||||
$('<i>',{class:"red-ui-tab-icon "+tab.iconClass}).appendTo(link);
|
||||
}
|
||||
var span = $('<span/>',{class:"bidiAware"}).text(tab.label).appendTo(link);
|
||||
span.attr('dir', RED.text.bidi.resolveBaseTextDir(tab.label));
|
||||
if (options.collapsible) {
|
||||
li.addClass("red-ui-tab-pinned");
|
||||
var pinnedLink = $('<a href="#'+tab.id+'" class="red-ui-tab-link-button"></a>');
|
||||
if (tab.pinned) {
|
||||
if (pinnedTabsCount === 0) {
|
||||
pinnedLink.prependTo(collapsedButtonsRow)
|
||||
} else {
|
||||
pinnedLink.insertAfter(collapsedButtonsRow.find("a.red-ui-tab-link-button-pinned:last"));
|
||||
}
|
||||
} else {
|
||||
pinnedLink.insertBefore(collapsedButtonsRow.find("a:last"));
|
||||
}
|
||||
|
||||
pinnedLink.attr('id',li.attr('id')+"-link-button");
|
||||
if (tab.iconClass) {
|
||||
$('<i>',{class:tab.iconClass}).appendTo(pinnedLink);
|
||||
} else {
|
||||
$('<i>',{class:defaultTabIcon}).appendTo(pinnedLink);
|
||||
}
|
||||
pinnedLink.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
activateTab(tab.id);
|
||||
});
|
||||
if (tab.pinned) {
|
||||
pinnedLink.addClass("red-ui-tab-link-button-pinned");
|
||||
pinnedTabsCount++;
|
||||
}
|
||||
RED.popover.tooltip($(pinnedLink), tab.name);
|
||||
|
||||
}
|
||||
link.on("click",onTabClick);
|
||||
link.on("dblclick",onTabDblClick);
|
||||
if (tab.closeable) {
|
||||
var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close"}).appendTo(li);
|
||||
closeLink.append('<i class="fa fa-times" />');
|
||||
|
||||
closeLink.on("click",function(event) {
|
||||
event.preventDefault();
|
||||
removeTab(tab.id);
|
||||
});
|
||||
}
|
||||
if (options.onadd) {
|
||||
options.onadd(tab);
|
||||
}
|
||||
link.attr("title",tab.label);
|
||||
if (ul.find("li.red-ui-tab").size() == 1) {
|
||||
activateTab(link);
|
||||
}
|
||||
if (options.onreorder) {
|
||||
var originalTabOrder;
|
||||
var tabDragIndex;
|
||||
var tabElements = [];
|
||||
var startDragIndex;
|
||||
|
||||
li.draggable({
|
||||
axis:"x",
|
||||
distance: 20,
|
||||
start: function(event,ui) {
|
||||
originalTabOrder = [];
|
||||
tabElements = [];
|
||||
ul.children().each(function(i) {
|
||||
tabElements[i] = {
|
||||
el:$(this),
|
||||
text: $(this).text(),
|
||||
left: $(this).position().left,
|
||||
width: $(this).width()
|
||||
};
|
||||
if ($(this).is(li)) {
|
||||
tabDragIndex = i;
|
||||
startDragIndex = i;
|
||||
}
|
||||
originalTabOrder.push($(this).data("tabId"));
|
||||
});
|
||||
ul.children().each(function(i) {
|
||||
if (i!==tabDragIndex) {
|
||||
$(this).css({
|
||||
position: 'absolute',
|
||||
left: tabElements[i].left+"px",
|
||||
width: tabElements[i].width+2,
|
||||
transition: "left 0.3s"
|
||||
});
|
||||
}
|
||||
|
||||
})
|
||||
if (!li.hasClass('active')) {
|
||||
li.css({'zIndex':1});
|
||||
}
|
||||
},
|
||||
drag: function(event,ui) {
|
||||
ui.position.left += tabElements[tabDragIndex].left+scrollContainer.scrollLeft();
|
||||
var tabCenter = ui.position.left + tabElements[tabDragIndex].width/2 - scrollContainer.scrollLeft();
|
||||
for (var i=0;i<tabElements.length;i++) {
|
||||
if (i === tabDragIndex) {
|
||||
continue;
|
||||
}
|
||||
if (tabCenter > tabElements[i].left && tabCenter < tabElements[i].left+tabElements[i].width) {
|
||||
if (i < tabDragIndex) {
|
||||
tabElements[i].left += tabElements[tabDragIndex].width+8;
|
||||
tabElements[tabDragIndex].el.detach().insertBefore(tabElements[i].el);
|
||||
} else {
|
||||
tabElements[i].left -= tabElements[tabDragIndex].width+8;
|
||||
tabElements[tabDragIndex].el.detach().insertAfter(tabElements[i].el);
|
||||
}
|
||||
tabElements[i].el.css({left:tabElements[i].left+"px"});
|
||||
|
||||
tabElements.splice(i, 0, tabElements.splice(tabDragIndex, 1)[0]);
|
||||
|
||||
tabDragIndex = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
},
|
||||
stop: function(event,ui) {
|
||||
ul.children().css({position:"relative",left:"",transition:""});
|
||||
if (!li.hasClass('active')) {
|
||||
li.css({zIndex:""});
|
||||
}
|
||||
updateTabWidths();
|
||||
if (startDragIndex !== tabDragIndex) {
|
||||
options.onreorder(originalTabOrder, $.makeArray(ul.children().map(function() { return $(this).data('tabId');})));
|
||||
}
|
||||
activateTab(tabElements[tabDragIndex].el.data('tabId'));
|
||||
}
|
||||
})
|
||||
}
|
||||
setTimeout(function() {
|
||||
updateTabWidths();
|
||||
},10);
|
||||
collapsibleMenu = null;
|
||||
},
|
||||
removeTab: removeTab,
|
||||
activateTab: activateTab,
|
||||
nextTab: activateNextTab,
|
||||
previousTab: activatePreviousTab,
|
||||
resize: updateTabWidths,
|
||||
count: function() {
|
||||
return ul.find("li.red-ui-tab").size();
|
||||
},
|
||||
contains: function(id) {
|
||||
return ul.find("a[href='#"+id+"']").length > 0;
|
||||
},
|
||||
renameTab: function(id,label) {
|
||||
tabs[id].label = label;
|
||||
var tab = ul.find("a[href='#"+id+"']");
|
||||
tab.attr("title",label);
|
||||
tab.find("span.bidiAware").text(label).attr('dir', RED.text.bidi.resolveBaseTextDir(label));
|
||||
updateTabWidths();
|
||||
},
|
||||
order: function(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++) {
|
||||
if (order[i] !== existingTabOrder[i]) {
|
||||
match = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (match) {
|
||||
return;
|
||||
}
|
||||
var existingTabMap = {};
|
||||
var existingTabs = ul.children().detach().each(function() {
|
||||
existingTabMap[$(this).data("tabId")] = $(this);
|
||||
});
|
||||
for (i=0;i<order.length;i++) {
|
||||
existingTabMap[order[i]].appendTo(ul);
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
create: createTabs
|
||||
}
|
||||
})();
|
||||
700
editor/js/ui/common/typedInput.js
Normal file
@@ -0,0 +1,700 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
(function($) {
|
||||
var contextParse = function(v) {
|
||||
var parts = RED.utils.parseContextKey(v);
|
||||
return {
|
||||
option: parts.store,
|
||||
value: parts.key
|
||||
}
|
||||
}
|
||||
var contextExport = function(v,opt) {
|
||||
if (!opt) {
|
||||
return v;
|
||||
}
|
||||
var store = ((typeof opt === "string")?opt:opt.value)
|
||||
if (store !== RED.settings.context.default) {
|
||||
return "#:("+store+")::"+v;
|
||||
} else {
|
||||
return v;
|
||||
}
|
||||
}
|
||||
var allOptions = {
|
||||
msg: {value:"msg",label:"msg.",validate:RED.utils.validatePropertyExpression},
|
||||
flow: {value:"flow",label:"flow.",hasValue:true,
|
||||
options:[],
|
||||
validate:RED.utils.validatePropertyExpression,
|
||||
parse: contextParse,
|
||||
export: contextExport
|
||||
},
|
||||
global: {value:"global",label:"global.",hasValue:true,
|
||||
options:[],
|
||||
validate:RED.utils.validatePropertyExpression,
|
||||
parse: contextParse,
|
||||
export: contextExport
|
||||
},
|
||||
str: {value:"str",label:"string",icon:"red/images/typedInput/az.png"},
|
||||
num: {value:"num",label:"number",icon:"red/images/typedInput/09.png",validate:/^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/},
|
||||
bool: {value:"bool",label:"boolean",icon:"red/images/typedInput/bool.png",options:["true","false"]},
|
||||
json: {
|
||||
value:"json",
|
||||
label:"JSON",
|
||||
icon:"red/images/typedInput/json.png",
|
||||
validate: function(v) { try{JSON.parse(v);return true;}catch(e){return false;}},
|
||||
expand: function() {
|
||||
var that = this;
|
||||
var value = this.value();
|
||||
try {
|
||||
value = JSON.stringify(JSON.parse(value),null,4);
|
||||
} catch(err) {
|
||||
}
|
||||
RED.editor.editJSON({
|
||||
value: value,
|
||||
complete: function(v) {
|
||||
var value = v;
|
||||
try {
|
||||
value = JSON.stringify(JSON.parse(v));
|
||||
} catch(err) {
|
||||
}
|
||||
that.value(value);
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
re: {value:"re",label:"regular expression",icon:"red/images/typedInput/re.png"},
|
||||
date: {value:"date",label:"timestamp",hasValue:false},
|
||||
jsonata: {
|
||||
value: "jsonata",
|
||||
label: "expression",
|
||||
icon: "red/images/typedInput/expr.png",
|
||||
validate: function(v) { try{jsonata(v);return true;}catch(e){return false;}},
|
||||
expand:function() {
|
||||
var that = this;
|
||||
RED.editor.editExpression({
|
||||
value: this.value().replace(/\t/g,"\n"),
|
||||
complete: function(v) {
|
||||
that.value(v.replace(/\n/g,"\t"));
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
bin: {
|
||||
value: "bin",
|
||||
label: "buffer",
|
||||
icon: "red/images/typedInput/bin.png",
|
||||
expand: function() {
|
||||
var that = this;
|
||||
RED.editor.editBuffer({
|
||||
value: this.value(),
|
||||
complete: function(v) {
|
||||
that.value(v);
|
||||
}
|
||||
})
|
||||
}
|
||||
},
|
||||
env: {
|
||||
value: "env",
|
||||
label: "env variable",
|
||||
icon: "red/images/typedInput/env.png"
|
||||
}
|
||||
};
|
||||
var nlsd = false;
|
||||
|
||||
$.widget( "nodered.typedInput", {
|
||||
_create: function() {
|
||||
try {
|
||||
if (!nlsd && RED && RED._) {
|
||||
for (var i in allOptions) {
|
||||
if (allOptions.hasOwnProperty(i)) {
|
||||
allOptions[i].label = RED._("typedInput.type."+i,{defaultValue:allOptions[i].label});
|
||||
}
|
||||
}
|
||||
var contextStores = RED.settings.context.stores;
|
||||
var contextOptions = contextStores.map(function(store) {
|
||||
return {value:store,label: store, icon:'<i class="red-ui-typedInput-icon fa fa-database" style="color: #'+(store==='memory'?'ddd':'777')+'"></i>'}
|
||||
})
|
||||
if (contextOptions.length < 2) {
|
||||
allOptions.flow.options = [];
|
||||
allOptions.global.options = [];
|
||||
} else {
|
||||
allOptions.flow.options = contextOptions;
|
||||
allOptions.global.options = contextOptions;
|
||||
}
|
||||
}
|
||||
nlsd = true;
|
||||
var that = this;
|
||||
|
||||
this.disarmClick = false;
|
||||
this.input = $('<input type="text"></input>');
|
||||
this.input.insertAfter(this.element);
|
||||
this.input.val(this.element.val());
|
||||
this.element.addClass('red-ui-typedInput');
|
||||
this.uiWidth = this.element.outerWidth();
|
||||
this.elementDiv = this.input.wrap("<div>").parent().addClass('red-ui-typedInput-input');
|
||||
this.uiSelect = this.elementDiv.wrap( "<div>" ).parent();
|
||||
var attrStyle = this.element.attr('style');
|
||||
var m;
|
||||
if ((m = /width\s*:\s*(calc\s*\(.*\)|\d+(%|px))/i.exec(attrStyle)) !== null) {
|
||||
this.input.css('width','100%');
|
||||
this.uiSelect.width(m[1]);
|
||||
this.uiWidth = null;
|
||||
} else {
|
||||
this.uiSelect.width(this.uiWidth);
|
||||
}
|
||||
["Right","Left"].forEach(function(d) {
|
||||
var m = that.element.css("margin"+d);
|
||||
that.uiSelect.css("margin"+d,m);
|
||||
that.input.css("margin"+d,0);
|
||||
});
|
||||
|
||||
this.uiSelect.addClass("red-ui-typedInput-container");
|
||||
|
||||
this.element.attr('type','hidden');
|
||||
|
||||
this.options.types = this.options.types||Object.keys(allOptions);
|
||||
|
||||
this.selectTrigger = $('<button tabindex="0"></button>').prependTo(this.uiSelect);
|
||||
$('<i class="red-ui-typedInput-icon fa fa-sort-desc"></i>').toggle(this.options.types.length > 1).appendTo(this.selectTrigger);
|
||||
|
||||
this.selectLabel = $('<span class="red-ui-typedInput-type-label"></span>').appendTo(this.selectTrigger);
|
||||
|
||||
this.types(this.options.types);
|
||||
|
||||
if (this.options.typeField) {
|
||||
this.typeField = $(this.options.typeField).hide();
|
||||
var t = this.typeField.val();
|
||||
if (t && this.typeMap[t]) {
|
||||
this.options.default = t;
|
||||
}
|
||||
} else {
|
||||
this.typeField = $("<input>",{type:'hidden'}).appendTo(this.uiSelect);
|
||||
}
|
||||
|
||||
this.input.on('focus', function() {
|
||||
that.uiSelect.addClass('red-ui-typedInput-focus');
|
||||
});
|
||||
this.input.on('blur', function() {
|
||||
that.uiSelect.removeClass('red-ui-typedInput-focus');
|
||||
});
|
||||
this.input.on('change', function() {
|
||||
that.validate();
|
||||
that.element.val(that.value());
|
||||
that.element.trigger('change',that.propertyType,that.value());
|
||||
})
|
||||
this.selectTrigger.click(function(event) {
|
||||
event.preventDefault();
|
||||
that._showTypeMenu();
|
||||
});
|
||||
this.selectTrigger.on('keydown',function(evt) {
|
||||
if (evt.keyCode === 40) {
|
||||
// Down
|
||||
that._showTypeMenu();
|
||||
}
|
||||
}).on('focus', function() {
|
||||
that.uiSelect.addClass('red-ui-typedInput-focus');
|
||||
})
|
||||
|
||||
// explicitly set optionSelectTrigger display to inline-block otherwise jQ sets it to 'inline'
|
||||
this.optionSelectTrigger = $('<button tabindex="0" class="red-ui-typedInput-option-trigger" style="display:inline-block"><span class="red-ui-typedInput-option-caret"><i class="red-ui-typedInput-icon fa fa-sort-desc"></i></span></button>').appendTo(this.uiSelect);
|
||||
this.optionSelectLabel = $('<span class="red-ui-typedInput-option-label"></span>').prependTo(this.optionSelectTrigger);
|
||||
RED.popover.tooltip(this.optionSelectLabel,function() {
|
||||
return that.optionValue;
|
||||
});
|
||||
this.optionSelectTrigger.click(function(event) {
|
||||
event.preventDefault();
|
||||
that._showOptionSelectMenu();
|
||||
}).on('keydown', function(evt) {
|
||||
if (evt.keyCode === 40) {
|
||||
// Down
|
||||
that._showOptionSelectMenu();
|
||||
}
|
||||
}).on('blur', function() {
|
||||
that.uiSelect.removeClass('red-ui-typedInput-focus');
|
||||
}).on('focus', function() {
|
||||
that.uiSelect.addClass('red-ui-typedInput-focus');
|
||||
});
|
||||
|
||||
this.optionExpandButton = $('<button tabindex="0" class="red-ui-typedInput-option-expand" style="display:inline-block"><i class="red-ui-typedInput-icon fa fa-ellipsis-h"></i></button>').appendTo(this.uiSelect);
|
||||
this.type(this.options.default||this.typeList[0].value);
|
||||
}catch(err) {
|
||||
console.log(err.stack);
|
||||
}
|
||||
},
|
||||
_showTypeMenu: function() {
|
||||
if (this.typeList.length > 1) {
|
||||
this._showMenu(this.menu,this.selectTrigger);
|
||||
this.menu.find("[value='"+this.propertyType+"']").focus();
|
||||
} else {
|
||||
this.input.focus();
|
||||
}
|
||||
},
|
||||
_showOptionSelectMenu: function() {
|
||||
if (this.optionMenu) {
|
||||
this.optionMenu.css({
|
||||
minWidth:this.optionSelectLabel.width()
|
||||
});
|
||||
|
||||
this._showMenu(this.optionMenu,this.optionSelectTrigger);
|
||||
var selectedOption = this.optionMenu.find("[value='"+this.optionValue+"']");
|
||||
if (selectedOption.length === 0) {
|
||||
selectedOption = this.optionMenu.children(":first");
|
||||
}
|
||||
selectedOption.focus();
|
||||
|
||||
}
|
||||
},
|
||||
_hideMenu: function(menu) {
|
||||
$(document).off("mousedown.close-property-select");
|
||||
menu.hide();
|
||||
if (this.elementDiv.is(":visible")) {
|
||||
this.input.focus();
|
||||
} else if (this.optionSelectTrigger.is(":visible")){
|
||||
this.optionSelectTrigger.focus();
|
||||
} else {
|
||||
this.selectTrigger.focus();
|
||||
}
|
||||
},
|
||||
_createMenu: function(opts,callback) {
|
||||
var that = this;
|
||||
var menu = $("<div>").addClass("red-ui-typedInput-options");
|
||||
opts.forEach(function(opt) {
|
||||
if (typeof opt === 'string') {
|
||||
opt = {value:opt,label:opt};
|
||||
}
|
||||
var op = $('<a href="#"></a>').attr("value",opt.value).appendTo(menu);
|
||||
if (opt.label) {
|
||||
op.text(opt.label);
|
||||
}
|
||||
if (opt.icon) {
|
||||
if (opt.icon.indexOf("<") === 0) {
|
||||
$(opt.icon).prependTo(op);
|
||||
} else if (opt.icon.indexOf("/") !== -1) {
|
||||
$('<img>',{src:opt.icon,style:"margin-right: 4px; height: 18px;"}).prependTo(op);
|
||||
} else {
|
||||
$('<i>',{class:"red-ui-typedInput-icon "+opt.icon}).prependTo(op);
|
||||
}
|
||||
} else {
|
||||
op.css({paddingLeft: "18px"});
|
||||
}
|
||||
if (!opt.icon && !opt.label) {
|
||||
op.text(opt.value);
|
||||
}
|
||||
|
||||
op.click(function(event) {
|
||||
event.preventDefault();
|
||||
callback(opt.value);
|
||||
that._hideMenu(menu);
|
||||
});
|
||||
});
|
||||
menu.css({
|
||||
display: "none",
|
||||
});
|
||||
menu.appendTo(document.body);
|
||||
|
||||
menu.on('keydown', function(evt) {
|
||||
if (evt.keyCode === 40) {
|
||||
// DOWN
|
||||
$(this).children(":focus").next().focus();
|
||||
} else if (evt.keyCode === 38) {
|
||||
// UP
|
||||
$(this).children(":focus").prev().focus();
|
||||
} else if (evt.keyCode === 27) {
|
||||
that._hideMenu(menu);
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
|
||||
return menu;
|
||||
|
||||
},
|
||||
_showMenu: function(menu,relativeTo) {
|
||||
if (this.disarmClick) {
|
||||
this.disarmClick = false;
|
||||
return
|
||||
}
|
||||
var that = this;
|
||||
var pos = relativeTo.offset();
|
||||
var height = relativeTo.height();
|
||||
var menuHeight = menu.height();
|
||||
var top = (height+pos.top-3);
|
||||
if (top+menuHeight > $(window).height()) {
|
||||
top -= (top+menuHeight)-$(window).height()+5;
|
||||
}
|
||||
menu.css({
|
||||
top: top+"px",
|
||||
left: (2+pos.left)+"px",
|
||||
});
|
||||
menu.slideDown(100);
|
||||
this._delay(function() {
|
||||
that.uiSelect.addClass('red-ui-typedInput-focus');
|
||||
$(document).on("mousedown.close-property-select", function(event) {
|
||||
if(!$(event.target).closest(menu).length) {
|
||||
that._hideMenu(menu);
|
||||
}
|
||||
if ($(event.target).closest(relativeTo).length) {
|
||||
that.disarmClick = true;
|
||||
event.preventDefault();
|
||||
}
|
||||
})
|
||||
});
|
||||
},
|
||||
_getLabelWidth: function(label) {
|
||||
var labelWidth = label.outerWidth();
|
||||
if (labelWidth === 0) {
|
||||
var container = $('<div class="red-ui-typedInput-container"></div>').css({
|
||||
position:"absolute",
|
||||
top:0,
|
||||
left:-1000
|
||||
}).appendTo(document.body);
|
||||
var newTrigger = label.clone().appendTo(container);
|
||||
labelWidth = newTrigger.outerWidth();
|
||||
container.remove();
|
||||
}
|
||||
return labelWidth;
|
||||
},
|
||||
_resize: function() {
|
||||
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");
|
||||
var labelWidth = this._getLabelWidth(this.selectTrigger);
|
||||
this.elementDiv.css('left',labelWidth+"px");
|
||||
if (this.optionExpandButton.is(":visible")) {
|
||||
this.elementDiv.css('right',"22px");
|
||||
} else {
|
||||
this.elementDiv.css('right','0');
|
||||
this.input.css({
|
||||
'border-top-right-radius': '4px',
|
||||
'border-bottom-right-radius': '4px'
|
||||
});
|
||||
}
|
||||
|
||||
// if (this.optionSelectTrigger) {
|
||||
// this.optionSelectTrigger.css({'left':(labelWidth)+"px",'width':'calc( 100% - '+labelWidth+'px )'});
|
||||
// }
|
||||
|
||||
if (this.optionSelectTrigger) {
|
||||
if (type && type.options && type.hasValue === true) {
|
||||
this.optionSelectLabel.css({'left':'auto'})
|
||||
var lw = this._getLabelWidth(this.optionSelectLabel);
|
||||
this.optionSelectTrigger.css({'width':(23+lw)+"px"});
|
||||
this.elementDiv.css('right',(23+lw)+"px");
|
||||
this.input.css({
|
||||
'border-top-right-radius': 0,
|
||||
'border-bottom-right-radius': 0
|
||||
});
|
||||
} else {
|
||||
this.optionSelectLabel.css({'left':'0'})
|
||||
this.optionSelectTrigger.css({'width':'calc( 100% - '+labelWidth+'px )'});
|
||||
if (!this.optionExpandButton.is(":visible")) {
|
||||
this.elementDiv.css({'right':0});
|
||||
this.input.css({
|
||||
'border-top-right-radius': '4px',
|
||||
'border-bottom-right-radius': '4px'
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
_updateOptionSelectLabel: function(o) {
|
||||
var opt = this.typeMap[this.propertyType];
|
||||
this.optionSelectLabel.empty();
|
||||
if (o.icon) {
|
||||
if (o.icon.indexOf("<") === 0) {
|
||||
$(o.icon).prependTo(this.optionSelectLabel);
|
||||
} else if (o.icon.indexOf("/") !== -1) {
|
||||
// url
|
||||
$('<img>',{src:o.icon,style:"height: 18px;"}).prependTo(this.optionSelectLabel);
|
||||
} else {
|
||||
// icon class
|
||||
$('<i>',{class:"red-ui-typedInput-icon "+o.icon}).prependTo(this.optionSelectLabel);
|
||||
}
|
||||
} else if (o.label) {
|
||||
this.optionSelectLabel.text(o.label);
|
||||
} else {
|
||||
this.optionSelectLabel.text(o.value);
|
||||
}
|
||||
if (opt.hasValue) {
|
||||
this.optionValue = o.value;
|
||||
this._resize();
|
||||
this.input.trigger('change',this.propertyType,this.value());
|
||||
}
|
||||
},
|
||||
_destroy: function() {
|
||||
if (this.optionMenu) {
|
||||
this.optionMenu.remove();
|
||||
}
|
||||
this.menu.remove();
|
||||
},
|
||||
types: function(types) {
|
||||
var that = this;
|
||||
var currentType = this.type();
|
||||
this.typeMap = {};
|
||||
this.typeList = types.map(function(opt) {
|
||||
var result;
|
||||
if (typeof opt === 'string') {
|
||||
result = allOptions[opt];
|
||||
} else {
|
||||
result = opt;
|
||||
}
|
||||
that.typeMap[result.value] = result;
|
||||
return result;
|
||||
});
|
||||
this.selectTrigger.toggleClass("disabled", this.typeList.length === 1);
|
||||
this.selectTrigger.find(".fa-sort-desc").toggle(this.typeList.length > 1)
|
||||
if (this.menu) {
|
||||
this.menu.remove();
|
||||
}
|
||||
this.menu = this._createMenu(this.typeList, function(v) { that.type(v) });
|
||||
if (currentType && !this.typeMap.hasOwnProperty(currentType)) {
|
||||
this.type(this.typeList[0].value);
|
||||
} else {
|
||||
this.propertyType = null;
|
||||
this.type(currentType);
|
||||
}
|
||||
setTimeout(function() {that._resize();},0);
|
||||
},
|
||||
width: function(desiredWidth) {
|
||||
this.uiWidth = desiredWidth;
|
||||
this._resize();
|
||||
},
|
||||
value: function(value) {
|
||||
if (!arguments.length) {
|
||||
var v = this.input.val();
|
||||
if (this.typeMap[this.propertyType].export) {
|
||||
v = this.typeMap[this.propertyType].export(v,this.optionValue)
|
||||
}
|
||||
return v;
|
||||
} else {
|
||||
var selectedOption;
|
||||
if (this.typeMap[this.propertyType].options) {
|
||||
for (var i=0;i<this.typeMap[this.propertyType].options.length;i++) {
|
||||
var op = this.typeMap[this.propertyType].options[i];
|
||||
if (typeof op === "string") {
|
||||
if (op === value) {
|
||||
selectedOption = this.activeOptions[op];
|
||||
break;
|
||||
}
|
||||
} else if (op.value === value) {
|
||||
selectedOption = op;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!selectedOption) {
|
||||
selectedOption = {value:""}
|
||||
}
|
||||
this._updateOptionSelectLabel(selectedOption)
|
||||
}
|
||||
this.input.val(value);
|
||||
this.input.trigger('change',this.type(),value);
|
||||
}
|
||||
},
|
||||
type: function(type) {
|
||||
if (!arguments.length) {
|
||||
return this.propertyType;
|
||||
} else {
|
||||
var that = this;
|
||||
var opt = this.typeMap[type];
|
||||
if (opt && this.propertyType !== type) {
|
||||
this.propertyType = type;
|
||||
if (this.typeField) {
|
||||
this.typeField.val(type);
|
||||
}
|
||||
this.selectLabel.empty();
|
||||
var image;
|
||||
if (opt.icon) {
|
||||
if (opt.icon.indexOf("<") === 0) {
|
||||
$(opt.icon).prependTo(this.selectLabel);
|
||||
}
|
||||
else if (opt.icon.indexOf("/") !== -1) {
|
||||
image = new Image();
|
||||
image.name = opt.icon;
|
||||
image.src = opt.icon;
|
||||
$('<img>',{src:opt.icon,style:"margin-right: 4px;height: 18px;"}).prependTo(this.selectLabel);
|
||||
}
|
||||
else {
|
||||
$('<i>',{class:"red-ui-typedInput-icon "+opt.icon}).prependTo(this.selectLabel);
|
||||
}
|
||||
} else {
|
||||
this.selectLabel.text(opt.label);
|
||||
}
|
||||
if (this.optionMenu) {
|
||||
this.optionMenu.remove();
|
||||
this.optionMenu = null;
|
||||
}
|
||||
if (opt.options) {
|
||||
if (this.optionExpandButton) {
|
||||
this.optionExpandButton.hide();
|
||||
}
|
||||
if (this.optionSelectTrigger) {
|
||||
this.optionSelectTrigger.show();
|
||||
if (!opt.hasValue) {
|
||||
this.elementDiv.hide();
|
||||
} else {
|
||||
this.elementDiv.show();
|
||||
}
|
||||
this.activeOptions = {};
|
||||
opt.options.forEach(function(o) {
|
||||
if (typeof o === 'string') {
|
||||
that.activeOptions[o] = {label:o,value:o};
|
||||
} else {
|
||||
that.activeOptions[o.value] = o;
|
||||
}
|
||||
});
|
||||
|
||||
if (!that.activeOptions.hasOwnProperty(that.optionValue)) {
|
||||
that.optionValue = null;
|
||||
}
|
||||
this.optionMenu = this._createMenu(opt.options,function(v){
|
||||
that._updateOptionSelectLabel(that.activeOptions[v]);
|
||||
if (!opt.hasValue) {
|
||||
that.value(that.activeOptions[v].value)
|
||||
}
|
||||
});
|
||||
var op;
|
||||
if (!opt.hasValue) {
|
||||
var currentVal = this.input.val();
|
||||
var validValue = false;
|
||||
for (var i=0;i<opt.options.length;i++) {
|
||||
op = opt.options[i];
|
||||
if (typeof op === "string" && op === currentVal) {
|
||||
that._updateOptionSelectLabel({value:currentVal});
|
||||
validValue = true;
|
||||
break;
|
||||
} else if (op.value === currentVal) {
|
||||
that._updateOptionSelectLabel(op);
|
||||
validValue = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
if (!validValue) {
|
||||
op = opt.options[0];
|
||||
if (typeof op === "string") {
|
||||
this.value(op);
|
||||
that._updateOptionSelectLabel({value:op});
|
||||
} else {
|
||||
this.value(op.value);
|
||||
that._updateOptionSelectLabel(op);
|
||||
}
|
||||
}
|
||||
} else {
|
||||
var selectedOption = this.optionValue||opt.options[0];
|
||||
if (opt.parse) {
|
||||
var parts = opt.parse(this.input.val());
|
||||
if (parts.option) {
|
||||
selectedOption = parts.option;
|
||||
if (!this.activeOptions.hasOwnProperty(selectedOption)) {
|
||||
parts.option = Object.keys(this.activeOptions)[0];
|
||||
selectedOption = parts.option
|
||||
}
|
||||
}
|
||||
this.input.val(parts.value);
|
||||
if (opt.export) {
|
||||
this.element.val(opt.export(parts.value,parts.option||selectedOption));
|
||||
}
|
||||
}
|
||||
if (typeof selectedOption === "string") {
|
||||
this.optionValue = selectedOption;
|
||||
if (!this.activeOptions.hasOwnProperty(selectedOption)) {
|
||||
selectedOption = Object.keys(this.activeOptions)[0];
|
||||
}
|
||||
if (!selectedOption) {
|
||||
this.optionSelectTrigger.hide();
|
||||
} else {
|
||||
this._updateOptionSelectLabel(this.activeOptions[selectedOption]);
|
||||
}
|
||||
} else if (selectedOption) {
|
||||
this.optionValue = selectedOption.value;
|
||||
this._updateOptionSelectLabel(selectedOption);
|
||||
} else {
|
||||
this.optionSelectTrigger.hide();
|
||||
}
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (this.optionSelectTrigger) {
|
||||
this.optionSelectTrigger.hide();
|
||||
}
|
||||
if (opt.hasValue === false) {
|
||||
this.oldValue = this.input.val();
|
||||
this.input.val("");
|
||||
this.elementDiv.hide();
|
||||
} else {
|
||||
if (this.oldValue !== undefined) {
|
||||
this.input.val(this.oldValue);
|
||||
delete this.oldValue;
|
||||
}
|
||||
this.elementDiv.show();
|
||||
}
|
||||
if (this.optionExpandButton) {
|
||||
if (opt.expand && typeof opt.expand === 'function') {
|
||||
this.optionExpandButton.show();
|
||||
this.optionExpandButton.off('click');
|
||||
this.optionExpandButton.on('click',function(evt) {
|
||||
evt.preventDefault();
|
||||
opt.expand.call(that);
|
||||
})
|
||||
} else {
|
||||
this.optionExpandButton.hide();
|
||||
}
|
||||
}
|
||||
this.input.trigger('change',this.propertyType,this.value());
|
||||
}
|
||||
if (image) {
|
||||
image.onload = function() { that._resize(); }
|
||||
image.onerror = function() { that._resize(); }
|
||||
} else {
|
||||
this._resize();
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
validate: function() {
|
||||
var result;
|
||||
var value = this.value();
|
||||
var type = this.type();
|
||||
if (this.typeMap[type] && this.typeMap[type].validate) {
|
||||
var val = this.typeMap[type].validate;
|
||||
if (typeof val === 'function') {
|
||||
result = val(value);
|
||||
} else {
|
||||
result = val.test(value);
|
||||
}
|
||||
} else {
|
||||
result = true;
|
||||
}
|
||||
if (result) {
|
||||
this.uiSelect.removeClass('input-error');
|
||||
} else {
|
||||
this.uiSelect.addClass('input-error');
|
||||
}
|
||||
return result;
|
||||
},
|
||||
show: function() {
|
||||
this.uiSelect.show();
|
||||
this._resize();
|
||||
},
|
||||
hide: function() {
|
||||
this.uiSelect.hide();
|
||||
}
|
||||
});
|
||||
})(jQuery);
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -30,12 +30,15 @@ RED.deploy = (function() {
|
||||
|
||||
var deploymentType = "full";
|
||||
|
||||
var deployInflight = false;
|
||||
|
||||
var currentDiff = null;
|
||||
|
||||
function changeDeploymentType(type) {
|
||||
deploymentType = type;
|
||||
$("#btn-deploy img").attr("src",deploymentTypes[type].img);
|
||||
$("#btn-deploy-icon").attr("src",deploymentTypes[type].img);
|
||||
}
|
||||
|
||||
|
||||
/**
|
||||
* options:
|
||||
* type: "default" - Button with drop-down options - no further customisation available
|
||||
@@ -49,7 +52,15 @@ RED.deploy = (function() {
|
||||
|
||||
if (type == "default") {
|
||||
$('<li><span class="deploy-button-group button-group">'+
|
||||
'<a id="btn-deploy" class="deploy-button disabled" href="#"><img id="btn-deploy-icon" src="red/images/deploy-full-o.png"> <span>'+RED._("deploy.deploy")+'</span></a>'+
|
||||
'<a id="btn-deploy" class="deploy-button disabled" href="#">'+
|
||||
'<span class="deploy-button-content">'+
|
||||
'<img id="btn-deploy-icon" src="red/images/deploy-full-o.png"> '+
|
||||
'<span>'+RED._("deploy.deploy")+'</span>'+
|
||||
'</span>'+
|
||||
'<span class="deploy-button-spinner hide">'+
|
||||
'<img src="red/images/spin.svg"/>'+
|
||||
'</span>'+
|
||||
'</a>'+
|
||||
'<a id="btn-deploy-options" data-toggle="dropdown" class="deploy-button" href="#"><i class="fa fa-caret-down"></i></a>'+
|
||||
'</span></li>').prependTo(".header-toolbar");
|
||||
RED.menu.init({id:"btn-deploy-options",
|
||||
@@ -68,49 +79,25 @@ RED.deploy = (function() {
|
||||
|
||||
$('<li><span class="deploy-button-group button-group">'+
|
||||
'<a id="btn-deploy" class="deploy-button disabled" href="#">'+
|
||||
(icon?'<img id="btn-deploy-icon" src="'+icon+'"> ':'')+
|
||||
'<span>'+label+'</span></a>'+
|
||||
'<span class="deploy-button-content">'+
|
||||
(icon?'<img id="btn-deploy-icon" src="'+icon+'"> ':'')+
|
||||
'<span>'+label+'</span>'+
|
||||
'</span>'+
|
||||
'<span class="deploy-button-spinner hide">'+
|
||||
'<img src="red/images/spin.svg"/>'+
|
||||
'</span>'+
|
||||
'</a>'+
|
||||
'</span></li>').prependTo(".header-toolbar");
|
||||
}
|
||||
|
||||
$('#btn-deploy').click(function() { save(); });
|
||||
|
||||
$( "#node-dialog-confirm-deploy" ).dialog({
|
||||
title: "Confirm deploy",
|
||||
modal: true,
|
||||
autoOpen: false,
|
||||
width: 550,
|
||||
height: "auto",
|
||||
buttons: [
|
||||
{
|
||||
text: RED._("deploy.confirm.button.confirm"),
|
||||
click: function() {
|
||||
|
||||
var ignoreChecked = $( "#node-dialog-confirm-deploy-hide" ).prop("checked");
|
||||
if (ignoreChecked) {
|
||||
ignoreDeployWarnings[$( "#node-dialog-confirm-deploy-type" ).val()] = true;
|
||||
}
|
||||
save(true);
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._("deploy.confirm.button.cancel"),
|
||||
click: function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
],
|
||||
create: function() {
|
||||
$("#node-dialog-confirm-deploy").parent().find("div.ui-dialog-buttonpane")
|
||||
.prepend('<div style="height:0; vertical-align: middle; display:inline-block; margin-top: 13px; float:left;">'+
|
||||
'<input style="vertical-align:top;" type="checkbox" id="node-dialog-confirm-deploy-hide">'+
|
||||
'<label style="display:inline;" for="node-dialog-confirm-deploy-hide"> do not warn about this again</label>'+
|
||||
'<input type="hidden" id="node-dialog-confirm-deploy-type">'+
|
||||
'</div>');
|
||||
}
|
||||
$('#btn-deploy').click(function(event) {
|
||||
event.preventDefault();
|
||||
save();
|
||||
});
|
||||
|
||||
RED.actions.add("core:deploy-flows",save);
|
||||
|
||||
|
||||
RED.events.on('nodes:change',function(state) {
|
||||
if (state.dirty) {
|
||||
window.onbeforeunload = function() {
|
||||
@@ -122,6 +109,40 @@ RED.deploy = (function() {
|
||||
$("#btn-deploy").addClass("disabled");
|
||||
}
|
||||
});
|
||||
|
||||
var activeNotifyMessage;
|
||||
RED.comms.subscribe("notification/runtime-deploy",function(topic,msg) {
|
||||
if (!activeNotifyMessage) {
|
||||
var currentRev = RED.nodes.version();
|
||||
if (currentRev === null || deployInflight || currentRev === msg.revision) {
|
||||
return;
|
||||
}
|
||||
var message = $('<p>').text(RED._('deploy.confirm.backgroundUpdate'));
|
||||
activeNotifyMessage = RED.notify(message,{
|
||||
modal: true,
|
||||
fixed: true,
|
||||
buttons: [
|
||||
{
|
||||
text: RED._('deploy.confirm.button.ignore'),
|
||||
click: function() {
|
||||
activeNotifyMessage.close();
|
||||
activeNotifyMessage = null;
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._('deploy.confirm.button.review'),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
activeNotifyMessage.close();
|
||||
var nns = RED.nodes.createCompleteNodeSet();
|
||||
resolveConflict(nns,false);
|
||||
activeNotifyMessage = null;
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getNodeInfo(node) {
|
||||
@@ -135,13 +156,7 @@ RED.deploy = (function() {
|
||||
tabLabel = tab.label;
|
||||
}
|
||||
}
|
||||
var label = "";
|
||||
if (typeof node._def.label == "function") {
|
||||
label = node._def.label.call(node);
|
||||
} else {
|
||||
label = node._def.label;
|
||||
}
|
||||
label = label || node.id;
|
||||
var label = RED.utils.getNodeLabel(node,node.id);
|
||||
return {tab:tabLabel,type:node.type,label:label};
|
||||
}
|
||||
function sortNodeInfo(A,B) {
|
||||
@@ -154,11 +169,101 @@ RED.deploy = (function() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
function save(force) {
|
||||
if (RED.nodes.dirty()) {
|
||||
//$("#debug-tab-clear").click(); // uncomment this to auto clear debug on deploy
|
||||
function resolveConflict(currentNodes, activeDeploy) {
|
||||
var message = $('<div>');
|
||||
$('<p data-i18n="deploy.confirm.conflict"></p>').appendTo(message);
|
||||
var conflictCheck = $('<div id="node-dialog-confirm-deploy-conflict-checking" class="node-dialog-confirm-conflict-row">'+
|
||||
'<img src="red/images/spin.svg"/><div data-i18n="deploy.confirm.conflictChecking"></div>'+
|
||||
'</div>').appendTo(message);
|
||||
var conflictAutoMerge = $('<div class="node-dialog-confirm-conflict-row">'+
|
||||
'<i style="color: #3a3;" class="fa fa-check"></i><div data-i18n="deploy.confirm.conflictAutoMerge"></div>'+
|
||||
'</div>').hide().appendTo(message);
|
||||
var conflictManualMerge = $('<div id="node-dialog-confirm-deploy-conflict-manual-merge" class="node-dialog-confirm-conflict-row">'+
|
||||
'<i style="color: #999;" class="fa fa-exclamation"></i><div data-i18n="deploy.confirm.conflictManualMerge"></div>'+
|
||||
'</div>').hide().appendTo(message);
|
||||
|
||||
if (!force) {
|
||||
message.i18n();
|
||||
currentDiff = null;
|
||||
var buttons = [
|
||||
{
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
conflictNotification.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-confirm-deploy-review",
|
||||
text: RED._("deploy.confirm.button.review"),
|
||||
class: "primary disabled",
|
||||
click: function() {
|
||||
if (!$("#node-dialog-confirm-deploy-review").hasClass('disabled')) {
|
||||
RED.diff.showRemoteDiff();
|
||||
conflictNotification.close();
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-confirm-deploy-merge",
|
||||
text: RED._("deploy.confirm.button.merge"),
|
||||
class: "primary disabled",
|
||||
click: function() {
|
||||
if (!$("#node-dialog-confirm-deploy-merge").hasClass('disabled')) {
|
||||
RED.diff.mergeDiff(currentDiff);
|
||||
conflictNotification.close();
|
||||
}
|
||||
}
|
||||
}
|
||||
];
|
||||
if (activeDeploy) {
|
||||
buttons.push({
|
||||
id: "node-dialog-confirm-deploy-overwrite",
|
||||
text: RED._("deploy.confirm.button.overwrite"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
save(true,activeDeploy);
|
||||
conflictNotification.close();
|
||||
}
|
||||
})
|
||||
}
|
||||
var conflictNotification = RED.notify(message,{
|
||||
modal: true,
|
||||
fixed: true,
|
||||
width: 600,
|
||||
buttons: buttons
|
||||
});
|
||||
|
||||
var now = Date.now();
|
||||
RED.diff.getRemoteDiff(function(diff) {
|
||||
var ellapsed = Math.max(1000 - (Date.now()-now), 0);
|
||||
currentDiff = diff;
|
||||
setTimeout(function() {
|
||||
conflictCheck.hide();
|
||||
var d = Object.keys(diff.conflicts);
|
||||
if (d.length === 0) {
|
||||
conflictAutoMerge.show();
|
||||
$("#node-dialog-confirm-deploy-merge").removeClass('disabled')
|
||||
} else {
|
||||
conflictManualMerge.show();
|
||||
}
|
||||
$("#node-dialog-confirm-deploy-review").removeClass('disabled')
|
||||
},ellapsed);
|
||||
})
|
||||
}
|
||||
function cropList(list) {
|
||||
if (list.length > 5) {
|
||||
var remainder = list.length - 5;
|
||||
list = list.slice(0,5);
|
||||
list.push(RED._("deploy.confirm.plusNMore",{count:remainder}));
|
||||
}
|
||||
return list;
|
||||
}
|
||||
function save(skipValidation,force) {
|
||||
if (!$("#btn-deploy").hasClass("disabled")) {
|
||||
if (!RED.user.hasPermission("flows.write")) {
|
||||
RED.notify(RED._("user.errors.deploy"),"error");
|
||||
return;
|
||||
}
|
||||
if (!skipValidation) {
|
||||
var hasUnknown = false;
|
||||
var hasInvalid = false;
|
||||
var hasUnusedConfig = false;
|
||||
@@ -181,100 +286,169 @@ RED.deploy = (function() {
|
||||
|
||||
var unusedConfigNodes = [];
|
||||
RED.nodes.eachConfig(function(node) {
|
||||
if (node.users.length === 0) {
|
||||
if (node.users.length === 0 && (node._def.hasUsers !== false)) {
|
||||
unusedConfigNodes.push(getNodeInfo(node));
|
||||
hasUnusedConfig = true;
|
||||
}
|
||||
});
|
||||
|
||||
$( "#node-dialog-confirm-deploy-config" ).hide();
|
||||
$( "#node-dialog-confirm-deploy-unknown" ).hide();
|
||||
$( "#node-dialog-confirm-deploy-unused" ).hide();
|
||||
|
||||
var showWarning = false;
|
||||
|
||||
var notificationMessage;
|
||||
var notificationButtons = [];
|
||||
var notification;
|
||||
if (hasUnknown && !ignoreDeployWarnings.unknown) {
|
||||
showWarning = true;
|
||||
$( "#node-dialog-confirm-deploy-type" ).val("unknown");
|
||||
$( "#node-dialog-confirm-deploy-unknown" ).show();
|
||||
$( "#node-dialog-confirm-deploy-unknown-list" )
|
||||
.html("<li>"+unknownNodes.join("</li><li>")+"</li>");
|
||||
notificationMessage = "<p>"+RED._('deploy.confirm.unknown')+"</p>"+
|
||||
'<ul class="node-dialog-configm-deploy-list"><li>'+cropList(unknownNodes).join("</li><li>")+"</li></ul><p>"+
|
||||
RED._('deploy.confirm.confirm')+
|
||||
"</p>";
|
||||
|
||||
notificationButtons= [
|
||||
{
|
||||
id: "node-dialog-confirm-deploy-deploy",
|
||||
text: RED._("deploy.confirm.button.confirm"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
save(true);
|
||||
notification.close();
|
||||
}
|
||||
}
|
||||
];
|
||||
} else if (hasInvalid && !ignoreDeployWarnings.invalid) {
|
||||
showWarning = true;
|
||||
$( "#node-dialog-confirm-deploy-type" ).val("invalid");
|
||||
$( "#node-dialog-confirm-deploy-config" ).show();
|
||||
invalidNodes.sort(sortNodeInfo);
|
||||
$( "#node-dialog-confirm-deploy-invalid-list" )
|
||||
.html("<li>"+invalidNodes.map(function(A) { return (A.tab?"["+A.tab+"] ":"")+A.label+" ("+A.type+")"}).join("</li><li>")+"</li>");
|
||||
|
||||
} else if (hasUnusedConfig && !ignoreDeployWarnings.unusedConfig) {
|
||||
showWarning = true;
|
||||
$( "#node-dialog-confirm-deploy-type" ).val("unusedConfig");
|
||||
$( "#node-dialog-confirm-deploy-unused" ).show();
|
||||
|
||||
unusedConfigNodes.sort(sortNodeInfo);
|
||||
$( "#node-dialog-confirm-deploy-unused-list" )
|
||||
.html("<li>"+unusedConfigNodes.map(function(A) { return (A.tab?"["+A.tab+"] ":"")+A.label+" ("+A.type+")"}).join("</li><li>")+"</li>");
|
||||
notificationMessage = "<p>"+RED._('deploy.confirm.improperlyConfigured')+"</p>"+
|
||||
'<ul class="node-dialog-configm-deploy-list"><li>'+cropList(invalidNodes.map(function(A) { return (A.tab?"["+A.tab+"] ":"")+A.label+" ("+A.type+")"})).join("</li><li>")+"</li></ul><p>"+
|
||||
RED._('deploy.confirm.confirm')+
|
||||
"</p>";
|
||||
notificationButtons= [
|
||||
{
|
||||
id: "node-dialog-confirm-deploy-deploy",
|
||||
text: RED._("deploy.confirm.button.confirm"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
save(true);
|
||||
notification.close();
|
||||
}
|
||||
}
|
||||
];
|
||||
}
|
||||
if (showWarning) {
|
||||
$( "#node-dialog-confirm-deploy-hide" ).prop("checked",false);
|
||||
$( "#node-dialog-confirm-deploy" ).dialog( "open" );
|
||||
notificationButtons.unshift(
|
||||
{
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
notification.close();
|
||||
}
|
||||
}
|
||||
);
|
||||
notification = RED.notify(notificationMessage,{
|
||||
modal: true,
|
||||
fixed: true,
|
||||
buttons:notificationButtons
|
||||
});
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
var nns = RED.nodes.createCompleteNodeSet();
|
||||
|
||||
$("#btn-deploy-icon").removeClass('fa-download');
|
||||
$("#btn-deploy-icon").addClass('spinner');
|
||||
RED.nodes.dirty(false);
|
||||
var startTime = Date.now();
|
||||
$(".deploy-button-content").css('opacity',0);
|
||||
$(".deploy-button-spinner").show();
|
||||
$("#btn-deploy").addClass("disabled");
|
||||
|
||||
var data = {flows:nns};
|
||||
|
||||
if (!force) {
|
||||
data.rev = RED.nodes.version();
|
||||
}
|
||||
|
||||
deployInflight = true;
|
||||
$("#header-shade").show();
|
||||
$("#editor-shade").show();
|
||||
$("#palette-shade").show();
|
||||
$("#sidebar-shade").show();
|
||||
$.ajax({
|
||||
url:"flows",
|
||||
type: "POST",
|
||||
data: JSON.stringify(nns),
|
||||
data: JSON.stringify(data),
|
||||
contentType: "application/json; charset=utf-8",
|
||||
headers: {
|
||||
"Node-RED-Deployment-Type":deploymentType
|
||||
}
|
||||
}).done(function(data,textStatus,xhr) {
|
||||
RED.notify(RED._("deploy.successfulDeploy"),"success");
|
||||
RED.nodes.dirty(false);
|
||||
RED.nodes.version(data.rev);
|
||||
RED.nodes.originalFlow(nns);
|
||||
if (hasUnusedConfig) {
|
||||
RED.notify(
|
||||
'<p>'+RED._("deploy.successfulDeploy")+'</p>'+
|
||||
'<p>'+RED._("deploy.unusedConfigNodes")+' <a href="#" onclick="RED.sidebar.config.show(true); return false;">'+RED._("deploy.unusedConfigNodesLink")+'</a></p>',"success",false,6000);
|
||||
} else {
|
||||
RED.notify('<p>'+RED._("deploy.successfulDeploy")+'</p>',"success");
|
||||
}
|
||||
RED.nodes.eachNode(function(node) {
|
||||
if (node.changed) {
|
||||
node.dirty = true;
|
||||
node.changed = false;
|
||||
}
|
||||
if (node.moved) {
|
||||
node.dirty = true;
|
||||
node.moved = false;
|
||||
}
|
||||
if(node.credentials) {
|
||||
delete node.credentials;
|
||||
}
|
||||
});
|
||||
RED.nodes.eachConfig(function (confNode) {
|
||||
confNode.changed = false;
|
||||
if (confNode.credentials) {
|
||||
delete confNode.credentials;
|
||||
}
|
||||
});
|
||||
RED.nodes.eachSubflow(function(subflow) {
|
||||
subflow.changed = false;
|
||||
});
|
||||
RED.nodes.eachWorkspace(function(ws) {
|
||||
ws.changed = false;
|
||||
});
|
||||
// Once deployed, cannot undo back to a clean state
|
||||
RED.history.markAllDirty();
|
||||
RED.view.redraw();
|
||||
RED.events.emit("deploy");
|
||||
}).fail(function(xhr,textStatus,err) {
|
||||
RED.nodes.dirty(true);
|
||||
if (xhr.responseText) {
|
||||
RED.notify(RED._("notification.error",{message:xhr.responseText}),"error");
|
||||
$("#btn-deploy").removeClass("disabled");
|
||||
if (xhr.status === 401) {
|
||||
RED.notify(RED._("deploy.deployFailed",{message:RED._("user.notAuthorized")}),"error");
|
||||
} else if (xhr.status === 409) {
|
||||
resolveConflict(nns, true);
|
||||
} else if (xhr.responseText) {
|
||||
RED.notify(RED._("deploy.deployFailed",{message:xhr.responseText}),"error");
|
||||
} else {
|
||||
RED.notify(RED._("notification.error",{message:RED._("deploy.errors.noResponse")}),"error");
|
||||
RED.notify(RED._("deploy.deployFailed",{message:RED._("deploy.errors.noResponse")}),"error");
|
||||
}
|
||||
}).always(function() {
|
||||
$("#btn-deploy-icon").removeClass('spinner');
|
||||
$("#btn-deploy-icon").addClass('fa-download');
|
||||
deployInflight = false;
|
||||
var delta = Math.max(0,300-(Date.now()-startTime));
|
||||
setTimeout(function() {
|
||||
$(".deploy-button-content").css('opacity',1);
|
||||
$(".deploy-button-spinner").hide();
|
||||
$("#header-shade").hide();
|
||||
$("#editor-shade").hide();
|
||||
$("#palette-shade").hide();
|
||||
$("#sidebar-shade").hide();
|
||||
},delta);
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
init: init
|
||||
init: init,
|
||||
setDeployInflight: function(state) {
|
||||
deployInflight = state;
|
||||
}
|
||||
|
||||
}
|
||||
})();
|
||||
|
||||
2199
editor/js/ui/diff.js
Normal file
209
editor/js/ui/editors/buffer.js
Normal file
@@ -0,0 +1,209 @@
|
||||
/**
|
||||
* 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.editor.types._buffer = (function() {
|
||||
|
||||
|
||||
var template = '<script type="text/x-red" data-template-name="_buffer"><div id="node-input-buffer-panels"><div id="node-input-buffer-panel-str" class="red-ui-panel"><div class="form-row" style="margin-bottom: 3px; text-align: right;"><span class="node-input-buffer-type"><i class="fa fa-exclamation-circle"></i> <span id="node-input-buffer-type-string" data-i18n="bufferEditor.modeString"></span><span id="node-input-buffer-type-array" data-i18n="bufferEditor.modeArray"></span></span></div><div class="form-row node-text-editor-row"><div class="node-text-editor" id="node-input-buffer-str"></div></div></div><div id="node-input-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="node-input-buffer-bin"></div></div></div></div></script>';
|
||||
|
||||
function stringToUTF8Array(str) {
|
||||
var data = [];
|
||||
var i=0, l = str.length;
|
||||
for (i=0; i<l; i++) {
|
||||
var char = str.charCodeAt(i);
|
||||
if (char < 0x80) {
|
||||
data.push(char);
|
||||
} else if (char < 0x800) {
|
||||
data.push(0xc0 | (char >> 6));
|
||||
data.push(0x80 | (char & 0x3f));
|
||||
} else if (char < 0xd800 || char >= 0xe000) {
|
||||
data.push(0xe0 | (char >> 12));
|
||||
data.push(0x80 | ((char>>6) & 0x3f));
|
||||
data.push(0x80 | (char & 0x3f));
|
||||
} else {
|
||||
i++;
|
||||
char = 0x10000 + (((char & 0x3ff)<<10) | (str.charAt(i) & 0x3ff));
|
||||
data.push(0xf0 | (char >>18));
|
||||
data.push(0x80 | ((char>>12) & 0x3f));
|
||||
data.push(0x80 | ((char>>6) & 0x3f));
|
||||
data.push(0x80 | (char & 0x3f));
|
||||
}
|
||||
}
|
||||
return data;
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
$(template).appendTo(document.body);
|
||||
},
|
||||
show: function(options) {
|
||||
var value = options.value;
|
||||
var onComplete = options.complete;
|
||||
var type = "_buffer"
|
||||
RED.view.state(RED.state.EDITING);
|
||||
var bufferStringEditor = [];
|
||||
var bufferBinValue;
|
||||
|
||||
var panels;
|
||||
|
||||
var trayOptions = {
|
||||
title: options.title,
|
||||
width: "inherit",
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
RED.tray.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-ok",
|
||||
text: RED._("common.label.done"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
onComplete(JSON.stringify(bufferBinValue));
|
||||
RED.tray.close();
|
||||
}
|
||||
}
|
||||
],
|
||||
resize: function(dimensions) {
|
||||
var height = $("#dialog-form").height();
|
||||
if (panels) {
|
||||
panels.resize(height);
|
||||
}
|
||||
},
|
||||
open: function(tray) {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
var dialogForm = RED.editor.buildEditForm(tray.find('.editor-tray-body'),'dialog-form',type,'editor');
|
||||
|
||||
bufferStringEditor = RED.editor.createEditor({
|
||||
id: 'node-input-buffer-str',
|
||||
value: "",
|
||||
mode:"ace/mode/text"
|
||||
});
|
||||
bufferStringEditor.getSession().setValue(value||"",-1);
|
||||
|
||||
bufferBinEditor = RED.editor.createEditor({
|
||||
id: 'node-input-buffer-bin',
|
||||
value: "",
|
||||
mode:"ace/mode/text",
|
||||
readOnly: true
|
||||
});
|
||||
|
||||
var changeTimer;
|
||||
var buildBuffer = function(data) {
|
||||
var valid = true;
|
||||
var isString = typeof data === 'string';
|
||||
var binBuffer = [];
|
||||
if (isString) {
|
||||
bufferBinValue = stringToUTF8Array(data);
|
||||
} else {
|
||||
bufferBinValue = data;
|
||||
}
|
||||
var i=0,l=bufferBinValue.length;
|
||||
var c = 0;
|
||||
for(i=0;i<l;i++) {
|
||||
var d = parseInt(bufferBinValue[i]);
|
||||
if (!isString && (isNaN(d) || d < 0 || d > 255)) {
|
||||
valid = false;
|
||||
break;
|
||||
}
|
||||
if (i>0) {
|
||||
if (i%8 === 0) {
|
||||
if (i%16 === 0) {
|
||||
binBuffer.push("\n");
|
||||
} else {
|
||||
binBuffer.push(" ");
|
||||
}
|
||||
} else {
|
||||
binBuffer.push(" ");
|
||||
}
|
||||
}
|
||||
binBuffer.push((d<16?"0":"")+d.toString(16).toUpperCase());
|
||||
}
|
||||
if (valid) {
|
||||
$("#node-input-buffer-type-string").toggle(isString);
|
||||
$("#node-input-buffer-type-array").toggle(!isString);
|
||||
bufferBinEditor.setValue(binBuffer.join(""),1);
|
||||
}
|
||||
return valid;
|
||||
}
|
||||
var bufferStringUpdate = function() {
|
||||
var value = bufferStringEditor.getValue();
|
||||
var isValidArray = false;
|
||||
if (/^[\s]*\[[\s\S]*\][\s]*$/.test(value)) {
|
||||
isValidArray = true;
|
||||
try {
|
||||
var data = JSON.parse(value);
|
||||
isValidArray = buildBuffer(data);
|
||||
} catch(err) {
|
||||
isValidArray = false;
|
||||
}
|
||||
}
|
||||
if (!isValidArray) {
|
||||
buildBuffer(value);
|
||||
}
|
||||
|
||||
}
|
||||
bufferStringEditor.getSession().on('change', function() {
|
||||
clearTimeout(changeTimer);
|
||||
changeTimer = setTimeout(bufferStringUpdate,200);
|
||||
});
|
||||
|
||||
bufferStringUpdate();
|
||||
|
||||
dialogForm.i18n();
|
||||
|
||||
panels = RED.panels.create({
|
||||
id:"node-input-buffer-panels",
|
||||
resize: function(p1Height,p2Height) {
|
||||
var p1 = $("#node-input-buffer-panel-str");
|
||||
p1Height -= $(p1.children()[0]).outerHeight(true);
|
||||
var editorRow = $(p1.children()[1]);
|
||||
p1Height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
|
||||
$("#node-input-buffer-str").css("height",(p1Height-5)+"px");
|
||||
bufferStringEditor.resize();
|
||||
|
||||
var p2 = $("#node-input-buffer-panel-bin");
|
||||
editorRow = $(p2.children()[0]);
|
||||
p2Height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
|
||||
$("#node-input-buffer-bin").css("height",(p2Height-5)+"px");
|
||||
bufferBinEditor.resize();
|
||||
}
|
||||
});
|
||||
|
||||
$(".node-input-buffer-type").click(function(e) {
|
||||
e.preventDefault();
|
||||
RED.sidebar.info.set(RED._("bufferEditor.modeDesc"));
|
||||
RED.sidebar.info.show();
|
||||
})
|
||||
|
||||
|
||||
},
|
||||
close: function() {
|
||||
if (options.onclose) {
|
||||
options.onclose();
|
||||
}
|
||||
bufferStringEditor.destroy();
|
||||
bufferBinEditor.destroy();
|
||||
},
|
||||
show: function() {}
|
||||
}
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
}
|
||||
})();
|
||||
325
editor/js/ui/editors/expression.js
Normal file
@@ -0,0 +1,325 @@
|
||||
/**
|
||||
* 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.editor.types._expression = (function() {
|
||||
|
||||
|
||||
var template = '<script type="text/x-red" data-template-name="_expression"><div id="node-input-expression-panels"><div id="node-input-expression-panel-expr" class="red-ui-panel"><div class="form-row" style="margin-bottom: 3px; text-align: right;"><span class="node-input-expression-legacy"><i class="fa fa-exclamation-circle"></i> <span data-i18n="expressionEditor.compatMode"></span></span><button id="node-input-expression-reformat" class="editor-button editor-button-small"><span data-i18n="expressionEditor.format"></span></button></div><div class="form-row node-text-editor-row"><div class="node-text-editor" id="node-input-expression"></div></div></div><div id="node-input-expression-panel-info" class="red-ui-panel"><div class="form-row"><ul id="node-input-expression-tabs"></ul><div id="node-input-expression-tab-help" class="node-input-expression-tab-content hide"><div><select id="node-input-expression-func"></select><button id="node-input-expression-func-insert" class="editor-button" data-i18n="expressionEditor.insert"></button></div><div id="node-input-expression-help"></div></div><div id="node-input-expression-tab-test" class="node-input-expression-tab-content hide"><div><span style="display: inline-block; width: calc(50% - 5px);"><span data-i18n="expressionEditor.data"></span><button style="float: right; margin-right: 5px;" id="node-input-example-reformat" class="editor-button editor-button-small"><span data-i18n="jsonEditor.format"></span></button></span><span style="display: inline-block; width: calc(50% - 5px);" data-i18n="expressionEditor.result"></span></div><div style="display: inline-block; width: calc(50% - 5px);" class="node-text-editor" id="node-input-expression-test-data"></div><div style="display: inline-block; width: calc(50% - 5px);" class="node-text-editor" id="node-input-expression-test-result"></div></div></div></div></div></script>';
|
||||
var expressionTestCache = {};
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
$(template).appendTo(document.body);
|
||||
},
|
||||
show: function(options) {
|
||||
var expressionTestCacheId = options.parent||"_";
|
||||
var value = options.value;
|
||||
var onComplete = options.complete;
|
||||
var type = "_expression"
|
||||
RED.view.state(RED.state.EDITING);
|
||||
var expressionEditor;
|
||||
var testDataEditor;
|
||||
var testResultEditor
|
||||
var panels;
|
||||
|
||||
var trayOptions = {
|
||||
title: options.title,
|
||||
width: "inherit",
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
RED.tray.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-ok",
|
||||
text: RED._("common.label.done"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
$("#node-input-expression-help").text("");
|
||||
onComplete(expressionEditor.getValue());
|
||||
RED.tray.close();
|
||||
}
|
||||
}
|
||||
],
|
||||
resize: function(dimensions) {
|
||||
var height = $("#dialog-form").height();
|
||||
if (panels) {
|
||||
panels.resize(height);
|
||||
}
|
||||
|
||||
},
|
||||
open: function(tray) {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
trayBody.addClass("node-input-expression-editor")
|
||||
var dialogForm = RED.editor.buildEditForm(tray.find('.editor-tray-body'),'dialog-form','_expression','editor');
|
||||
var funcSelect = $("#node-input-expression-func");
|
||||
Object.keys(jsonata.functions).forEach(function(f) {
|
||||
funcSelect.append($("<option></option>").val(f).text(f));
|
||||
})
|
||||
funcSelect.change(function(e) {
|
||||
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:''}));
|
||||
$("#node-input-expression-help").html(title+"<p>"+body+"</p>");
|
||||
|
||||
})
|
||||
expressionEditor = RED.editor.createEditor({
|
||||
id: 'node-input-expression',
|
||||
value: "",
|
||||
mode:"ace/mode/jsonata",
|
||||
options: {
|
||||
enableBasicAutocompletion:true,
|
||||
enableSnippets:true,
|
||||
enableLiveAutocompletion: true
|
||||
}
|
||||
});
|
||||
var currentToken = null;
|
||||
var currentTokenPos = -1;
|
||||
var currentFunctionMarker = null;
|
||||
|
||||
expressionEditor.getSession().setValue(value||"",-1);
|
||||
expressionEditor.on("changeSelection", function() {
|
||||
var c = expressionEditor.getCursorPosition();
|
||||
var token = expressionEditor.getSession().getTokenAt(c.row,c.column);
|
||||
if (token !== currentToken || (token && /paren/.test(token.type) && c.column !== currentTokenPos)) {
|
||||
currentToken = token;
|
||||
var r,p;
|
||||
var scopedFunction = null;
|
||||
if (token && token.type === 'keyword') {
|
||||
r = c.row;
|
||||
scopedFunction = token;
|
||||
} else {
|
||||
var depth = 0;
|
||||
var next = false;
|
||||
if (token) {
|
||||
if (token.type === 'paren.rparen') {
|
||||
// If this is a block of parens ')))', set
|
||||
// depth to offset against the cursor position
|
||||
// within the block
|
||||
currentTokenPos = c.column;
|
||||
depth = c.column - (token.start + token.value.length);
|
||||
}
|
||||
r = c.row;
|
||||
p = token.index;
|
||||
} else {
|
||||
r = c.row-1;
|
||||
p = -1;
|
||||
}
|
||||
while ( scopedFunction === null && r > -1) {
|
||||
var rowTokens = expressionEditor.getSession().getTokens(r);
|
||||
if (p === -1) {
|
||||
p = rowTokens.length-1;
|
||||
}
|
||||
while (p > -1) {
|
||||
var type = rowTokens[p].type;
|
||||
if (next) {
|
||||
if (type === 'keyword') {
|
||||
scopedFunction = rowTokens[p];
|
||||
// console.log("HIT",scopedFunction);
|
||||
break;
|
||||
}
|
||||
next = false;
|
||||
}
|
||||
if (type === 'paren.lparen') {
|
||||
depth-=rowTokens[p].value.length;
|
||||
} else if (type === 'paren.rparen') {
|
||||
depth+=rowTokens[p].value.length;
|
||||
}
|
||||
if (depth < 0) {
|
||||
next = true;
|
||||
depth = 0;
|
||||
}
|
||||
// console.log(r,p,depth,next,rowTokens[p]);
|
||||
p--;
|
||||
}
|
||||
if (!scopedFunction) {
|
||||
r--;
|
||||
}
|
||||
}
|
||||
}
|
||||
expressionEditor.session.removeMarker(currentFunctionMarker);
|
||||
if (scopedFunction) {
|
||||
//console.log(token,.map(function(t) { return t.type}));
|
||||
funcSelect.val(scopedFunction.value).change();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
dialogForm.i18n();
|
||||
$("#node-input-expression-func-insert").click(function(e) {
|
||||
e.preventDefault();
|
||||
var pos = expressionEditor.getCursorPosition();
|
||||
var f = funcSelect.val();
|
||||
var snippet = jsonata.getFunctionSnippet(f);
|
||||
expressionEditor.insertSnippet(snippet);
|
||||
expressionEditor.focus();
|
||||
});
|
||||
$("#node-input-expression-reformat").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
var v = expressionEditor.getValue()||"";
|
||||
try {
|
||||
v = jsonata.format(v);
|
||||
} catch(err) {
|
||||
// TODO: do an optimistic auto-format
|
||||
}
|
||||
expressionEditor.getSession().setValue(v||"",-1);
|
||||
});
|
||||
|
||||
var tabs = RED.tabs.create({
|
||||
element: $("#node-input-expression-tabs"),
|
||||
onchange:function(tab) {
|
||||
$(".node-input-expression-tab-content").hide();
|
||||
tab.content.show();
|
||||
trayOptions.resize();
|
||||
}
|
||||
})
|
||||
|
||||
tabs.addTab({
|
||||
id: 'expression-help',
|
||||
label: RED._('expressionEditor.functionReference'),
|
||||
content: $("#node-input-expression-tab-help")
|
||||
});
|
||||
tabs.addTab({
|
||||
id: 'expression-tests',
|
||||
label: RED._('expressionEditor.test'),
|
||||
content: $("#node-input-expression-tab-test")
|
||||
});
|
||||
testDataEditor = RED.editor.createEditor({
|
||||
id: 'node-input-expression-test-data',
|
||||
value: expressionTestCache[expressionTestCacheId] || '{\n "payload": "hello world"\n}',
|
||||
mode:"ace/mode/json",
|
||||
lineNumbers: false
|
||||
});
|
||||
var changeTimer;
|
||||
$(".node-input-expression-legacy").click(function(e) {
|
||||
e.preventDefault();
|
||||
RED.sidebar.info.set(RED._("expressionEditor.compatModeDesc"));
|
||||
RED.sidebar.info.show();
|
||||
})
|
||||
var testExpression = function() {
|
||||
var value = testDataEditor.getValue();
|
||||
var parsedData;
|
||||
var currentExpression = expressionEditor.getValue();
|
||||
var expr;
|
||||
var usesContext = false;
|
||||
var legacyMode = /(^|[^a-zA-Z0-9_'"])msg([^a-zA-Z0-9_'"]|$)/.test(currentExpression);
|
||||
$(".node-input-expression-legacy").toggle(legacyMode);
|
||||
try {
|
||||
expr = jsonata(currentExpression);
|
||||
expr.assign('flowContext',function(val) {
|
||||
usesContext = true;
|
||||
return null;
|
||||
});
|
||||
expr.assign('globalContext',function(val) {
|
||||
usesContext = true;
|
||||
return null;
|
||||
});
|
||||
} catch(err) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.invalid-expr",{message:err.message}),-1);
|
||||
return;
|
||||
}
|
||||
try {
|
||||
parsedData = JSON.parse(value);
|
||||
} catch(err) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.invalid-msg",{message:err.toString()}))
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
var result = expr.evaluate(legacyMode?{msg:parsedData}:parsedData);
|
||||
if (usesContext) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.context-unsupported"),-1);
|
||||
return;
|
||||
}
|
||||
|
||||
var formattedResult;
|
||||
if (result !== undefined) {
|
||||
formattedResult = JSON.stringify(result,null,4);
|
||||
} else {
|
||||
formattedResult = RED._("expressionEditor.noMatch");
|
||||
}
|
||||
testResultEditor.setValue(formattedResult,-1);
|
||||
} catch(err) {
|
||||
testResultEditor.setValue(RED._("expressionEditor.errors.eval",{message:err.message}),-1);
|
||||
}
|
||||
}
|
||||
|
||||
testDataEditor.getSession().on('change', function() {
|
||||
clearTimeout(changeTimer);
|
||||
changeTimer = setTimeout(testExpression,200);
|
||||
expressionTestCache[expressionTestCacheId] = testDataEditor.getValue();
|
||||
});
|
||||
expressionEditor.getSession().on('change', function() {
|
||||
clearTimeout(changeTimer);
|
||||
changeTimer = setTimeout(testExpression,200);
|
||||
});
|
||||
|
||||
testResultEditor = RED.editor.createEditor({
|
||||
id: 'node-input-expression-test-result',
|
||||
value: "",
|
||||
mode:"ace/mode/json",
|
||||
lineNumbers: false,
|
||||
readOnly: true
|
||||
});
|
||||
panels = RED.panels.create({
|
||||
id:"node-input-expression-panels",
|
||||
resize: function(p1Height,p2Height) {
|
||||
var p1 = $("#node-input-expression-panel-expr");
|
||||
p1Height -= $(p1.children()[0]).outerHeight(true);
|
||||
var editorRow = $(p1.children()[1]);
|
||||
p1Height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom")));
|
||||
$("#node-input-expression").css("height",(p1Height-5)+"px");
|
||||
expressionEditor.resize();
|
||||
|
||||
var p2 = $("#node-input-expression-panel-info > .form-row > div:first-child");
|
||||
p2Height -= p2.outerHeight(true) + 20;
|
||||
$(".node-input-expression-tab-content").height(p2Height);
|
||||
$("#node-input-expression-test-data").css("height",(p2Height-5)+"px");
|
||||
testDataEditor.resize();
|
||||
$("#node-input-expression-test-result").css("height",(p2Height-5)+"px");
|
||||
testResultEditor.resize();
|
||||
}
|
||||
});
|
||||
|
||||
$("#node-input-example-reformat").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
var v = testDataEditor.getValue()||"";
|
||||
try {
|
||||
v = JSON.stringify(JSON.parse(v),null,4);
|
||||
} catch(err) {
|
||||
// TODO: do an optimistic auto-format
|
||||
}
|
||||
testDataEditor.getSession().setValue(v||"",-1);
|
||||
});
|
||||
|
||||
testExpression();
|
||||
},
|
||||
close: function() {
|
||||
if (options.onclose) {
|
||||
options.onclose();
|
||||
}
|
||||
expressionEditor.destroy();
|
||||
testDataEditor.destroy();
|
||||
},
|
||||
show: function() {}
|
||||
}
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
}
|
||||
})();
|
||||
102
editor/js/ui/editors/js.js
Normal file
@@ -0,0 +1,102 @@
|
||||
/**
|
||||
* 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.editor.types._js = (function() {
|
||||
|
||||
|
||||
var template = '<script type="text/x-red" data-template-name="_js"><div class="form-row node-text-editor-row"><div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-js"></div></div></script>';
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
$(template).appendTo(document.body);
|
||||
},
|
||||
show: function(options) {
|
||||
var value = options.value;
|
||||
var onComplete = options.complete;
|
||||
var type = "_js"
|
||||
RED.view.state(RED.state.EDITING);
|
||||
var expressionEditor;
|
||||
var changeTimer;
|
||||
|
||||
var trayOptions = {
|
||||
title: options.title,
|
||||
width: options.width||"inherit",
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
RED.tray.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-ok",
|
||||
text: RED._("common.label.done"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
onComplete(expressionEditor.getValue(),expressionEditor.getCursorPosition());
|
||||
RED.tray.close();
|
||||
}
|
||||
}
|
||||
],
|
||||
resize: function(dimensions) {
|
||||
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
|
||||
var editorRow = $("#dialog-form>div.node-text-editor-row");
|
||||
var height = $("#dialog-form").height();
|
||||
for (var i=0;i<rows.size();i++) {
|
||||
height -= $(rows[i]).outerHeight(true);
|
||||
}
|
||||
$(".node-text-editor").css("height",height+"px");
|
||||
expressionEditor.resize();
|
||||
},
|
||||
open: function(tray) {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
var dialogForm = RED.editor.buildEditForm(tray.find('.editor-tray-body'),'dialog-form',type,'editor');
|
||||
expressionEditor = RED.editor.createEditor({
|
||||
id: 'node-input-js',
|
||||
mode: 'ace/mode/javascript',
|
||||
value: value,
|
||||
globals: {
|
||||
msg:true,
|
||||
context:true,
|
||||
RED: true,
|
||||
util: true,
|
||||
flow: true,
|
||||
global: true,
|
||||
console: true,
|
||||
Buffer: true,
|
||||
setTimeout: true,
|
||||
clearTimeout: true,
|
||||
setInterval: true,
|
||||
clearInterval: true
|
||||
}
|
||||
});
|
||||
if (options.cursor) {
|
||||
expressionEditor.gotoLine(options.cursor.row+1,options.cursor.column,false);
|
||||
}
|
||||
dialogForm.i18n();
|
||||
},
|
||||
close: function() {
|
||||
expressionEditor.destroy();
|
||||
if (options.onclose) {
|
||||
options.onclose();
|
||||
}
|
||||
},
|
||||
show: function() {}
|
||||
}
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
}
|
||||
})();
|
||||
118
editor/js/ui/editors/json.js
Normal file
@@ -0,0 +1,118 @@
|
||||
/**
|
||||
* 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.editor.types._json = (function() {
|
||||
|
||||
|
||||
var template = '<script type="text/x-red" data-template-name="_json"><div class="form-row" style="margin-bottom: 3px; text-align: right;"><button id="node-input-json-reformat" class="editor-button editor-button-small"><span data-i18n="jsonEditor.format"></span></button></div><div class="form-row node-text-editor-row"><div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-json"></div></div></script>';
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
$(template).appendTo(document.body);
|
||||
},
|
||||
show: function(options) {
|
||||
var value = options.value;
|
||||
var onComplete = options.complete;
|
||||
var type = "_json"
|
||||
RED.view.state(RED.state.EDITING);
|
||||
var expressionEditor;
|
||||
var changeTimer;
|
||||
|
||||
var checkValid = function() {
|
||||
var v = expressionEditor.getValue();
|
||||
try {
|
||||
JSON.parse(v);
|
||||
$("#node-dialog-ok").removeClass('disabled');
|
||||
return true;
|
||||
} catch(err) {
|
||||
$("#node-dialog-ok").addClass('disabled');
|
||||
return false;
|
||||
}
|
||||
}
|
||||
var trayOptions = {
|
||||
title: options.title,
|
||||
width: "inherit",
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
RED.tray.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-ok",
|
||||
text: RED._("common.label.done"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
if (options.requireValid && !checkValid()) {
|
||||
return;
|
||||
}
|
||||
onComplete(expressionEditor.getValue());
|
||||
RED.tray.close();
|
||||
}
|
||||
}
|
||||
],
|
||||
resize: function(dimensions) {
|
||||
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
|
||||
var editorRow = $("#dialog-form>div.node-text-editor-row");
|
||||
var height = $("#dialog-form").height();
|
||||
for (var i=0;i<rows.size();i++) {
|
||||
height -= $(rows[i]).outerHeight(true);
|
||||
}
|
||||
height -= (parseInt($("#dialog-form").css("marginTop"))+parseInt($("#dialog-form").css("marginBottom")));
|
||||
$(".node-text-editor").css("height",height+"px");
|
||||
expressionEditor.resize();
|
||||
},
|
||||
open: function(tray) {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
var dialogForm = RED.editor.buildEditForm(tray.find('.editor-tray-body'),'dialog-form',type,'editor');
|
||||
expressionEditor = RED.editor.createEditor({
|
||||
id: 'node-input-json',
|
||||
value: "",
|
||||
mode:"ace/mode/json"
|
||||
});
|
||||
expressionEditor.getSession().setValue(value||"",-1);
|
||||
if (options.requireValid) {
|
||||
expressionEditor.getSession().on('change', function() {
|
||||
clearTimeout(changeTimer);
|
||||
changeTimer = setTimeout(checkValid,200);
|
||||
});
|
||||
checkValid();
|
||||
}
|
||||
$("#node-input-json-reformat").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
var v = expressionEditor.getValue()||"";
|
||||
try {
|
||||
v = JSON.stringify(JSON.parse(v),null,4);
|
||||
} catch(err) {
|
||||
// TODO: do an optimistic auto-format
|
||||
}
|
||||
expressionEditor.getSession().setValue(v||"",-1);
|
||||
});
|
||||
dialogForm.i18n();
|
||||
},
|
||||
close: function() {
|
||||
expressionEditor.destroy();
|
||||
if (options.onclose) {
|
||||
options.onclose();
|
||||
}
|
||||
},
|
||||
show: function() {}
|
||||
}
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
}
|
||||
})();
|
||||
90
editor/js/ui/editors/markdown.js
Normal file
@@ -0,0 +1,90 @@
|
||||
/**
|
||||
* 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.editor.types._markdown = (function() {
|
||||
|
||||
|
||||
var template = '<script type="text/x-red" data-template-name="_markdown"><div class="form-row" id="node-input-markdown-title" style="margin-bottom: 3px; text-align: right;"></div><div class="form-row node-text-editor-row"><div style="height: 200px;min-height: 150px;" class="node-text-editor" id="node-input-markdown"></div></div></script>';
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
$(template).appendTo(document.body);
|
||||
},
|
||||
show: function(options) {
|
||||
var value = options.value;
|
||||
var onComplete = options.complete;
|
||||
var type = "_markdown"
|
||||
RED.view.state(RED.state.EDITING);
|
||||
var expressionEditor;
|
||||
|
||||
var trayOptions = {
|
||||
title: options.title,
|
||||
width: "inherit",
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
RED.tray.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-ok",
|
||||
text: RED._("common.label.done"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
onComplete(expressionEditor.getValue());
|
||||
RED.tray.close();
|
||||
}
|
||||
}
|
||||
],
|
||||
resize: function(dimensions) {
|
||||
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
|
||||
var editorRow = $("#dialog-form>div.node-text-editor-row");
|
||||
var height = $("#dialog-form").height();
|
||||
for (var i=0;i<rows.size();i++) {
|
||||
height -= $(rows[i]).outerHeight(true);
|
||||
}
|
||||
height -= (parseInt($("#dialog-form").css("marginTop"))+parseInt($("#dialog-form").css("marginBottom")));
|
||||
$(".node-text-editor").css("height",height+"px");
|
||||
expressionEditor.resize();
|
||||
},
|
||||
open: function(tray) {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
var dialogForm = RED.editor.buildEditForm(tray.find('.editor-tray-body'),'dialog-form',type,'editor');
|
||||
expressionEditor = RED.editor.createEditor({
|
||||
id: 'node-input-markdown',
|
||||
value: value,
|
||||
mode:"ace/mode/markdown"
|
||||
});
|
||||
if (options.header) {
|
||||
options.header.appendTo(tray.find('#node-input-markdown-title'));
|
||||
}
|
||||
|
||||
dialogForm.i18n();
|
||||
},
|
||||
close: function() {
|
||||
expressionEditor.destroy();
|
||||
if (options.onclose) {
|
||||
options.onclose();
|
||||
}
|
||||
},
|
||||
show: function() {}
|
||||
}
|
||||
RED.tray.show(trayOptions);
|
||||
|
||||
}
|
||||
}
|
||||
})();
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013 IBM Corp.
|
||||
* 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.
|
||||
@@ -15,107 +15,539 @@
|
||||
**/
|
||||
RED.keyboard = (function() {
|
||||
|
||||
var active = true;
|
||||
var isMac = /Mac/i.test(window.navigator.platform);
|
||||
|
||||
var handlers = {};
|
||||
var partialState;
|
||||
|
||||
var keyMap = {
|
||||
"left":37,
|
||||
"up":38,
|
||||
"right":39,
|
||||
"down":40,
|
||||
"escape":27,
|
||||
"enter": 13,
|
||||
"backspace": 8,
|
||||
"delete": 46,
|
||||
"space": 32,
|
||||
";":186,
|
||||
"=":187,
|
||||
",":188,
|
||||
"-":189,
|
||||
".":190,
|
||||
"/":191,
|
||||
"\\":220,
|
||||
"'":222,
|
||||
"?":191 // <- QWERTY specific
|
||||
}
|
||||
var metaKeyCodes = {
|
||||
16:true,
|
||||
17:true,
|
||||
18: true,
|
||||
91:true,
|
||||
93: true
|
||||
}
|
||||
var actionToKeyMap = {}
|
||||
var defaultKeyMap = {};
|
||||
|
||||
// FF generates some different keycodes because reasons.
|
||||
var firefoxKeyCodeMap = {
|
||||
59:186,
|
||||
61:187,
|
||||
173:189
|
||||
}
|
||||
|
||||
function migrateOldKeymap() {
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
function init() {
|
||||
// Migrate from pre-0.18
|
||||
migrateOldKeymap();
|
||||
|
||||
var currentEditorSettings = RED.settings.get('editor') || {};
|
||||
var userKeymap = currentEditorSettings.keymap || {};
|
||||
|
||||
$.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
|
||||
};
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
for (var action in userKeymap) {
|
||||
if (userKeymap.hasOwnProperty(action)) {
|
||||
var obj = userKeymap[action];
|
||||
if (obj.hasOwnProperty('key')) {
|
||||
addHandler(obj.scope, obj.key, action, true);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
RED.userSettings.add({
|
||||
id:'keyboard',
|
||||
title: RED._("keyboard.keyboard"),
|
||||
get: getSettingsPane,
|
||||
focus: function() {
|
||||
setTimeout(function() {
|
||||
$("#user-settings-tab-keyboard-filter").focus();
|
||||
},200);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function revertToDefault(action) {
|
||||
var currentAction = actionToKeyMap[action];
|
||||
if (currentAction) {
|
||||
removeHandler(currentAction.key);
|
||||
}
|
||||
if (defaultKeyMap.hasOwnProperty(action)) {
|
||||
var obj = defaultKeyMap[action];
|
||||
addHandler(obj.scope, obj.key, action, false);
|
||||
}
|
||||
}
|
||||
function parseKeySpecifier(key) {
|
||||
var parts = key.toLowerCase().split("-");
|
||||
var modifiers = {};
|
||||
var keycode;
|
||||
var blank = 0;
|
||||
for (var i=0;i<parts.length;i++) {
|
||||
switch(parts[i]) {
|
||||
case "ctrl":
|
||||
case "cmd":
|
||||
modifiers.ctrl = true;
|
||||
modifiers.meta = true;
|
||||
break;
|
||||
case "alt":
|
||||
modifiers.alt = true;
|
||||
break;
|
||||
case "shift":
|
||||
modifiers.shift = true;
|
||||
break;
|
||||
case "":
|
||||
blank++;
|
||||
keycode = keyMap["-"];
|
||||
break;
|
||||
default:
|
||||
if (keyMap.hasOwnProperty(parts[i])) {
|
||||
keycode = keyMap[parts[i]];
|
||||
} else if (parts[i].length > 1) {
|
||||
return null;
|
||||
} else {
|
||||
keycode = parts[i].toUpperCase().charCodeAt(0);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
return [keycode,modifiers];
|
||||
}
|
||||
|
||||
function resolveKeyEvent(evt) {
|
||||
var slot = partialState||handlers;
|
||||
if (evt.ctrlKey || evt.metaKey) {
|
||||
slot = slot.ctrl;
|
||||
}
|
||||
if (slot && evt.shiftKey) {
|
||||
slot = slot.shift;
|
||||
}
|
||||
if (slot && evt.altKey) {
|
||||
slot = slot.alt;
|
||||
}
|
||||
var keyCode = firefoxKeyCodeMap[evt.keyCode] || evt.keyCode;
|
||||
if (slot && slot[keyCode]) {
|
||||
var handler = slot[keyCode];
|
||||
if (!handler.scope) {
|
||||
if (partialState) {
|
||||
partialState = null;
|
||||
return resolveKeyEvent(evt);
|
||||
} else if (Object.keys(handler).length > 0) {
|
||||
partialState = handler;
|
||||
evt.preventDefault();
|
||||
return null;
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} else if (handler.scope && handler.scope !== "*") {
|
||||
var target = evt.target;
|
||||
while (target.nodeName !== 'BODY' && target.id !== handler.scope) {
|
||||
target = target.parentElement;
|
||||
}
|
||||
if (target.nodeName === 'BODY') {
|
||||
handler = null;
|
||||
}
|
||||
}
|
||||
partialState = null;
|
||||
return handler;
|
||||
} else if (partialState) {
|
||||
partialState = null;
|
||||
return resolveKeyEvent(evt);
|
||||
}
|
||||
}
|
||||
d3.select(window).on("keydown",function() {
|
||||
if (!active) { return; }
|
||||
var handler = handlers[d3.event.keyCode];
|
||||
if (handler && handler.ondown) {
|
||||
if (!handler.modifiers ||
|
||||
((!handler.modifiers.shift || d3.event.shiftKey) &&
|
||||
(!handler.modifiers.ctrl || d3.event.ctrlKey || d3.event.metaKey) &&
|
||||
(!handler.modifiers.alt || d3.event.altKey) )) {
|
||||
handler.ondown();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
d3.select(window).on("keyup",function() {
|
||||
if (!active) { return; }
|
||||
var handler = handlers[d3.event.keyCode];
|
||||
if (handler && handler.onup) {
|
||||
if (!handler.modifiers ||
|
||||
((!handler.modifiers.shift || d3.event.shiftKey) &&
|
||||
(!handler.modifiers.ctrl || d3.event.ctrlKey || d3.event.metaKey) &&
|
||||
(!handler.modifiers.alt || d3.event.altKey) )) {
|
||||
handler.onup();
|
||||
}
|
||||
}
|
||||
});
|
||||
function addHandler(key,modifiers,ondown,onup) {
|
||||
var mod = modifiers;
|
||||
var cbdown = ondown;
|
||||
var cbup = onup;
|
||||
if (typeof modifiers == "function") {
|
||||
mod = {};
|
||||
cbdown = modifiers;
|
||||
cbup = ondown;
|
||||
}
|
||||
handlers[key] = {modifiers:mod, ondown:cbdown, onup:cbup};
|
||||
}
|
||||
function removeHandler(key) {
|
||||
delete handlers[key];
|
||||
}
|
||||
|
||||
|
||||
var dialog = null;
|
||||
|
||||
function showKeyboardHelp() {
|
||||
if (!RED.settings.theme("menu.menu-item-keyboard-shortcuts",true)) {
|
||||
if (metaKeyCodes[d3.event.keyCode]) {
|
||||
return;
|
||||
}
|
||||
if (!dialog) {
|
||||
dialog = $('<div id="keyboard-help-dialog" class="hide">'+
|
||||
'<div style="vertical-align: top;display:inline-block; box-sizing: border-box; width:50%; padding: 10px;">'+
|
||||
'<table class="keyboard-shortcuts">'+
|
||||
'<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">a</span></td><td>'+RED._("keyboard.selectAll")+'</td></tr>'+
|
||||
'<tr><td><span class="help-key">Shift</span> + <span class="help-key">Click</span></td><td>'+RED._("keyboard.selectAllConnected")+'</td></tr>'+
|
||||
'<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">Click</span></td><td>'+RED._("keyboard.addRemoveNode")+'</td></tr>'+
|
||||
'<tr><td><span class="help-key">Delete</span></td><td>'+RED._("keyboard.deleteSelected")+'</td></tr>'+
|
||||
'<tr><td> </td><td></td></tr>'+
|
||||
'<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">i</span></td><td>'+RED._("keyboard.importNode")+'</td></tr>'+
|
||||
'<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">e</span></td><td>'+RED._("keyboard.exportNode")+'</td></tr>'+
|
||||
'</table>'+
|
||||
'</div>'+
|
||||
'<div style="vertical-align: top;display:inline-block; box-sizing: border-box; width:50%; padding: 10px;">'+
|
||||
'<table class="keyboard-shortcuts">'+
|
||||
'<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">Space</span></td><td>'+RED._("keyboard.toggleSidebar")+'</td></tr>'+
|
||||
'<tr><td></td><td></td></tr>'+
|
||||
'<tr><td><span class="help-key">Delete</span></td><td>'+RED._("keyboard.deleteNode")+'</td></tr>'+
|
||||
'<tr><td></td><td></td></tr>'+
|
||||
'<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">c</span></td><td>'+RED._("keyboard.copyNode")+'</td></tr>'+
|
||||
'<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">x</span></td><td>'+RED._("keyboard.cutNode")+'</td></tr>'+
|
||||
'<tr><td><span class="help-key">Ctrl/⌘</span> + <span class="help-key">v</span></td><td>'+RED._("keyboard.pasteNode")+'</td></tr>'+
|
||||
'</table>'+
|
||||
'</div>'+
|
||||
'</div>')
|
||||
.appendTo("body")
|
||||
.dialog({
|
||||
modal: true,
|
||||
autoOpen: false,
|
||||
width: "800",
|
||||
title:"Keyboard shortcuts",
|
||||
resizable: false,
|
||||
open: function() {
|
||||
RED.keyboard.disable();
|
||||
},
|
||||
close: function() {
|
||||
RED.keyboard.enable();
|
||||
}
|
||||
});
|
||||
var handler = resolveKeyEvent(d3.event);
|
||||
if (handler && handler.ondown) {
|
||||
if (typeof handler.ondown === "string") {
|
||||
RED.actions.invoke(handler.ondown);
|
||||
} else {
|
||||
handler.ondown();
|
||||
}
|
||||
d3.event.preventDefault();
|
||||
}
|
||||
|
||||
dialog.dialog("open");
|
||||
});
|
||||
|
||||
function addHandler(scope,key,modifiers,ondown) {
|
||||
var mod = modifiers;
|
||||
var cbdown = ondown;
|
||||
if (typeof modifiers == "function" || typeof modifiers === "string") {
|
||||
mod = {};
|
||||
cbdown = modifiers;
|
||||
}
|
||||
var keys = [];
|
||||
var i=0;
|
||||
if (typeof key === 'string') {
|
||||
if (typeof cbdown === 'string') {
|
||||
actionToKeyMap[cbdown] = {scope:scope,key:key};
|
||||
if (typeof ondown === 'boolean') {
|
||||
actionToKeyMap[cbdown].user = ondown;
|
||||
}
|
||||
}
|
||||
var parts = key.split(" ");
|
||||
for (i=0;i<parts.length;i++) {
|
||||
var parsedKey = parseKeySpecifier(parts[i]);
|
||||
if (parsedKey) {
|
||||
keys.push(parsedKey);
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
keys.push([key,mod])
|
||||
}
|
||||
var slot = handlers;
|
||||
for (i=0;i<keys.length;i++) {
|
||||
key = keys[i][0];
|
||||
mod = keys[i][1];
|
||||
if (mod.ctrl) {
|
||||
slot.ctrl = slot.ctrl||{};
|
||||
slot = slot.ctrl;
|
||||
}
|
||||
if (mod.shift) {
|
||||
slot.shift = slot.shift||{};
|
||||
slot = slot.shift;
|
||||
}
|
||||
if (mod.alt) {
|
||||
slot.alt = slot.alt||{};
|
||||
slot = slot.alt;
|
||||
}
|
||||
slot[key] = slot[key] || {};
|
||||
slot = slot[key];
|
||||
//slot[key] = {scope: scope, ondown:cbdown};
|
||||
}
|
||||
slot.scope = scope;
|
||||
slot.ondown = cbdown;
|
||||
}
|
||||
|
||||
|
||||
function removeHandler(key,modifiers) {
|
||||
var mod = modifiers || {};
|
||||
var keys = [];
|
||||
var i=0;
|
||||
if (typeof key === 'string') {
|
||||
|
||||
var parts = key.split(" ");
|
||||
for (i=0;i<parts.length;i++) {
|
||||
var parsedKey = parseKeySpecifier(parts[i]);
|
||||
if (parsedKey) {
|
||||
keys.push(parsedKey);
|
||||
} else {
|
||||
console.log("Unrecognised key specifier:",key)
|
||||
return;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
keys.push([key,mod])
|
||||
}
|
||||
var slot = handlers;
|
||||
for (i=0;i<keys.length;i++) {
|
||||
key = keys[i][0];
|
||||
mod = keys[i][1];
|
||||
if (mod.ctrl) {
|
||||
slot = slot.ctrl;
|
||||
}
|
||||
if (slot && mod.shift) {
|
||||
slot = slot.shift;
|
||||
}
|
||||
if (slot && mod.alt) {
|
||||
slot = slot.alt;
|
||||
}
|
||||
if (!slot[key]) {
|
||||
return;
|
||||
}
|
||||
slot = slot[key];
|
||||
}
|
||||
if (typeof slot.ondown === "string") {
|
||||
if (typeof modifiers === 'boolean' && modifiers) {
|
||||
actionToKeyMap[slot.ondown] = {user: modifiers}
|
||||
} else {
|
||||
delete actionToKeyMap[slot.ondown];
|
||||
}
|
||||
}
|
||||
delete slot.scope;
|
||||
delete slot.ondown;
|
||||
}
|
||||
|
||||
var cmdCtrlKey = '<span class="help-key">'+(isMac?'⌘':'Ctrl')+'</span>';
|
||||
|
||||
function formatKey(key) {
|
||||
var formattedKey = isMac?key.replace(/ctrl-?/,"⌘"):key;
|
||||
formattedKey = isMac?formattedKey.replace(/alt-?/,"⌥"):key;
|
||||
formattedKey = formattedKey.replace(/shift-?/,"⇧")
|
||||
formattedKey = formattedKey.replace(/left/,"←")
|
||||
formattedKey = formattedKey.replace(/up/,"↑")
|
||||
formattedKey = formattedKey.replace(/right/,"→")
|
||||
formattedKey = formattedKey.replace(/down/,"↓")
|
||||
return '<span class="help-key-block"><span class="help-key">'+formattedKey.split(" ").join('</span> <span class="help-key">')+'</span></span>';
|
||||
}
|
||||
|
||||
function validateKey(key) {
|
||||
key = key.trim();
|
||||
var parts = key.split(" ");
|
||||
for (i=0;i<parts.length;i++) {
|
||||
var parsedKey = parseKeySpecifier(parts[i]);
|
||||
if (!parsedKey) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
function editShortcut(e) {
|
||||
e.preventDefault();
|
||||
var container = $(this);
|
||||
var object = container.data('data');
|
||||
|
||||
|
||||
if (!container.hasClass('keyboard-shortcut-entry-expanded')) {
|
||||
endEditShortcut();
|
||||
|
||||
var key = container.find(".keyboard-shortcut-entry-key");
|
||||
var scope = container.find(".keyboard-shortcut-entry-scope");
|
||||
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) {
|
||||
return endEditShortcut();
|
||||
}
|
||||
var currentVal = $(this).val();
|
||||
currentVal = currentVal.trim();
|
||||
var valid = (currentVal === "" || RED.keyboard.validateKey(currentVal));
|
||||
$(this).toggleClass("input-error",!valid);
|
||||
})
|
||||
|
||||
var scopeSelect = $('<select><option value="*" data-i18n="keyboard.global"></option><option value="workspace" data-i18n="keyboard.workspace"></option></select>').appendTo(scope);
|
||||
scopeSelect.i18n();
|
||||
scopeSelect.val(object.scope||'*');
|
||||
|
||||
var div = $('<div class="keyboard-shortcut-edit button-group-vertical"></div>').appendTo(scope);
|
||||
var okButton = $('<button class="editor-button editor-button-small"><i class="fa fa-check"></i></button>').appendTo(div);
|
||||
var revertButton = $('<button class="editor-button editor-button-small"><i class="fa fa-reply"></i></button>').appendTo(div);
|
||||
|
||||
okButton.click(function(e) {
|
||||
e.stopPropagation();
|
||||
endEditShortcut();
|
||||
});
|
||||
revertButton.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 || {};
|
||||
userKeymap[object.id] = null;
|
||||
currentEditorSettings.keymap = userKeymap;
|
||||
RED.settings.set('editor',currentEditorSettings);
|
||||
|
||||
var obj = {
|
||||
id:object.id,
|
||||
scope:shortcut?shortcut.scope:undefined,
|
||||
key:shortcut?shortcut.key:undefined,
|
||||
user:shortcut?shortcut.user:undefined
|
||||
}
|
||||
buildShortcutRow(container,obj);
|
||||
})
|
||||
|
||||
keyInput.focus();
|
||||
}
|
||||
}
|
||||
|
||||
function endEditShortcut(cancel) {
|
||||
var container = $('.keyboard-shortcut-entry-expanded');
|
||||
if (container.length === 1) {
|
||||
var object = container.data('data');
|
||||
var keyInput = container.find(".keyboard-shortcut-entry-key input");
|
||||
var scopeSelect = container.find(".keyboard-shortcut-entry-scope select");
|
||||
if (!cancel) {
|
||||
var key = keyInput.val().trim();
|
||||
var scope = scopeSelect.val();
|
||||
var valid = (key === "" || RED.keyboard.validateKey(key));
|
||||
if (valid) {
|
||||
var current = RED.keyboard.getShortcut(object.id);
|
||||
if ((!current && key) || (current && (current.scope !== scope || current.key !== key))) {
|
||||
var keyDiv = container.find(".keyboard-shortcut-entry-key");
|
||||
var scopeDiv = container.find(".keyboard-shortcut-entry-scope");
|
||||
keyDiv.empty();
|
||||
scopeDiv.empty();
|
||||
if (object.key) {
|
||||
RED.keyboard.remove(object.key,true);
|
||||
}
|
||||
container.find(".keyboard-shortcut-entry-text i").css("opacity",1);
|
||||
if (key === "") {
|
||||
keyDiv.parent().addClass("keyboard-shortcut-entry-unassigned");
|
||||
keyDiv.append($('<span>').text(RED._('keyboard.unassigned')) );
|
||||
delete object.key;
|
||||
delete object.scope;
|
||||
} else {
|
||||
keyDiv.parent().removeClass("keyboard-shortcut-entry-unassigned");
|
||||
keyDiv.append(RED.keyboard.formatKey(key))
|
||||
$("<span>").text(scope).appendTo(scopeDiv);
|
||||
object.key = key;
|
||||
object.scope = scope;
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
keyInput.remove();
|
||||
scopeSelect.remove();
|
||||
$('.keyboard-shortcut-edit').remove();
|
||||
container.removeClass('keyboard-shortcut-entry-expanded');
|
||||
}
|
||||
}
|
||||
|
||||
function buildShortcutRow(container,object) {
|
||||
var item = $('<div class="keyboard-shortcut-entry">').appendTo(container);
|
||||
container.data('data',object);
|
||||
|
||||
var text = object.id.replace(/(^.+:([a-z]))|(-([a-z]))/g,function() {
|
||||
if (arguments[5] === 0) {
|
||||
return arguments[2].toUpperCase();
|
||||
} else {
|
||||
return " "+arguments[4].toUpperCase();
|
||||
}
|
||||
});
|
||||
var label = $('<div>').addClass("keyboard-shortcut-entry-text").text(text).appendTo(item);
|
||||
|
||||
var user = $('<i class="fa fa-user"></i>').prependTo(label);
|
||||
|
||||
if (!object.user) {
|
||||
user.css("opacity",0);
|
||||
}
|
||||
|
||||
var key = $('<div class="keyboard-shortcut-entry-key">').appendTo(item);
|
||||
if (object.key) {
|
||||
key.append(RED.keyboard.formatKey(object.key));
|
||||
} else {
|
||||
item.addClass("keyboard-shortcut-entry-unassigned");
|
||||
key.append($('<span>').text(RED._('keyboard.unassigned')) );
|
||||
}
|
||||
|
||||
var scope = $('<div class="keyboard-shortcut-entry-scope">').appendTo(item);
|
||||
|
||||
$("<span>").text(object.scope === '*'?'global':object.scope||"").appendTo(scope);
|
||||
container.click(editShortcut);
|
||||
}
|
||||
|
||||
function getSettingsPane() {
|
||||
var pane = $('<div id="user-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="user-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({
|
||||
delay: 100,
|
||||
change: function() {
|
||||
var filterValue = $(this).val().trim();
|
||||
if (filterValue === "") {
|
||||
shortcutList.editableList('filter', null);
|
||||
} else {
|
||||
filterValue = filterValue.replace(/\s/g,"");
|
||||
shortcutList.editableList('filter', function(data) {
|
||||
return data.id.toLowerCase().replace(/^.*:/,"").replace("-","").indexOf(filterValue) > -1;
|
||||
})
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var shortcutList = $('<ol class="keyboard-shortcut-list"></ol>').css({
|
||||
position: "absolute",
|
||||
top: "32px",
|
||||
bottom: "0",
|
||||
left: "0",
|
||||
right: "0"
|
||||
}).appendTo(pane).editableList({
|
||||
addButton: false,
|
||||
scrollOnAdd: false,
|
||||
addItem: function(container,i,object) {
|
||||
buildShortcutRow(container,object);
|
||||
},
|
||||
|
||||
});
|
||||
var shortcuts = RED.actions.list();
|
||||
shortcuts.sort(function(A,B) {
|
||||
var Aid = A.id.replace(/^.*:/,"").replace(/[ -]/g,"").toLowerCase();
|
||||
var Bid = B.id.replace(/^.*:/,"").replace(/[ -]/g,"").toLowerCase();
|
||||
return Aid.localeCompare(Bid);
|
||||
});
|
||||
shortcuts.forEach(function(s) {
|
||||
shortcutList.editableList('addItem',s);
|
||||
});
|
||||
return pane;
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
add: addHandler,
|
||||
remove: removeHandler,
|
||||
disable: function(){ active = false;},
|
||||
enable: function(){ active = true; },
|
||||
|
||||
showHelp: showKeyboardHelp
|
||||
getShortcut: function(actionName) {
|
||||
return actionToKeyMap[actionName];
|
||||
},
|
||||
revertToDefault: revertToDefault,
|
||||
formatKey: formatKey,
|
||||
validateKey: validateKey
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013, 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -15,6 +15,8 @@
|
||||
**/
|
||||
RED.library = (function() {
|
||||
|
||||
var exportToLibraryDialog;
|
||||
var elementPrefix = "node-input-";
|
||||
|
||||
function loadFlowLibrary() {
|
||||
$.getJSON("library/flows",function(data) {
|
||||
@@ -25,7 +27,9 @@ RED.library = (function() {
|
||||
var li;
|
||||
var a;
|
||||
var ul = document.createElement("ul");
|
||||
ul.id = "menu-item-import-library-submenu";
|
||||
if (root === "") {
|
||||
ul.id = "menu-item-import-library-submenu";
|
||||
}
|
||||
ul.className = "dropdown-menu";
|
||||
if (data.d) {
|
||||
for (i in data.d) {
|
||||
@@ -34,7 +38,8 @@ RED.library = (function() {
|
||||
li.className = "dropdown-submenu pull-left";
|
||||
a = document.createElement("a");
|
||||
a.href="#";
|
||||
a.innerHTML = i;
|
||||
var label = i.replace(/^@.*\//,"").replace(/^node-red-contrib-/,"").replace(/^node-red-node-/,"").replace(/-/," ").replace(/_/," ");
|
||||
a.innerHTML = label;
|
||||
li.appendChild(a);
|
||||
li.appendChild(buildMenu(data.d[i],root+(root!==""?"/":"")+i));
|
||||
ul.appendChild(li);
|
||||
@@ -51,7 +56,7 @@ RED.library = (function() {
|
||||
a.flowName = root+(root!==""?"/":"")+data.f[i];
|
||||
a.onclick = function() {
|
||||
$.get('library/flows/'+this.flowName, function(data) {
|
||||
RED.view.importNodes(data);
|
||||
RED.view.importNodes(data);
|
||||
});
|
||||
};
|
||||
li.appendChild(a);
|
||||
@@ -61,7 +66,17 @@ RED.library = (function() {
|
||||
}
|
||||
return ul;
|
||||
};
|
||||
var examples;
|
||||
if (data.d && data.d._examples_) {
|
||||
examples = data.d._examples_;
|
||||
delete data.d._examples_;
|
||||
}
|
||||
var menu = buildMenu(data,"");
|
||||
$("#menu-item-import-examples").remove();
|
||||
if (examples) {
|
||||
RED.menu.addItem("menu-item-import",{id:"menu-item-import-examples",label:RED._("menu.label.examples"),options:[]})
|
||||
$("#menu-item-import-examples-submenu").replaceWith(buildMenu(examples,"_examples_"));
|
||||
}
|
||||
//TODO: need an api in RED.menu for this
|
||||
$("#menu-item-import-library-submenu").replaceWith(menu);
|
||||
});
|
||||
@@ -71,6 +86,7 @@ RED.library = (function() {
|
||||
var libraryData = {};
|
||||
var selectedLibraryItem = null;
|
||||
var libraryEditor = null;
|
||||
elementPrefix = options.elementPrefix || "node-input-";
|
||||
|
||||
// Orion editor has set/getText
|
||||
// ACE editor has set/getValue
|
||||
@@ -95,7 +111,7 @@ RED.library = (function() {
|
||||
function buildFileList(root,data) {
|
||||
var ul = document.createElement("ul");
|
||||
var li;
|
||||
for (var i=0;i<data.length;i++) {
|
||||
for (var i=0; i<data.length; i++) {
|
||||
var v = data[i];
|
||||
if (typeof v === "string") {
|
||||
// directory
|
||||
@@ -115,7 +131,7 @@ RED.library = (function() {
|
||||
$(".active",bc).removeClass("active");
|
||||
bc.append(bcli);
|
||||
$.getJSON("library/"+options.url+root+dirName,function(data) {
|
||||
$("#node-select-library").children().first().replaceWith(buildFileList(root+dirName+"/",data));
|
||||
$("#node-select-library").children().first().replaceWith(buildFileList(root+dirName+"/",data));
|
||||
});
|
||||
}
|
||||
})();
|
||||
@@ -123,27 +139,27 @@ RED.library = (function() {
|
||||
ul.appendChild(li);
|
||||
} else {
|
||||
// file
|
||||
li = buildFileListItem(v);
|
||||
li.innerHTML = v.name;
|
||||
li.onclick = (function() {
|
||||
var item = v;
|
||||
return function(e) {
|
||||
$(".list-selected",ul).removeClass("list-selected");
|
||||
$(this).addClass("list-selected");
|
||||
$.get("library/"+options.url+root+item.fn, function(data) {
|
||||
selectedLibraryItem = item;
|
||||
libraryEditor.setValue(data,-1);
|
||||
});
|
||||
}
|
||||
})();
|
||||
ul.appendChild(li);
|
||||
li = buildFileListItem(v);
|
||||
li.innerHTML = v.name;
|
||||
li.onclick = (function() {
|
||||
var item = v;
|
||||
return function(e) {
|
||||
$(".list-selected",ul).removeClass("list-selected");
|
||||
$(this).addClass("list-selected");
|
||||
$.get("library/"+options.url+root+item.fn, function(data) {
|
||||
selectedLibraryItem = item;
|
||||
libraryEditor.setValue(data,-1);
|
||||
});
|
||||
}
|
||||
})();
|
||||
ul.appendChild(li);
|
||||
}
|
||||
}
|
||||
return ul;
|
||||
}
|
||||
|
||||
$('#node-input-name').css("width","60%").after(
|
||||
'<div class="btn-group" style="margin-left: 5px;">'+
|
||||
$('#'+elementPrefix+"name").css("width","calc(100% - 52px)").after(
|
||||
'<div class="btn-group" style="margin-left:5px;">'+
|
||||
'<a id="node-input-'+options.type+'-lookup" class="editor-button" data-toggle="dropdown"><i class="fa fa-book"></i> <i class="fa fa-caret-down"></i></a>'+
|
||||
'<ul class="dropdown-menu pull-right" role="menu">'+
|
||||
'<li><a id="node-input-'+options.type+'-menu-open-library" tabindex="-1" href="#">'+RED._("library.openLibrary")+'</a></li>'+
|
||||
@@ -151,8 +167,6 @@ RED.library = (function() {
|
||||
'</ul></div>'
|
||||
);
|
||||
|
||||
|
||||
|
||||
$('#node-input-'+options.type+'-menu-open-library').click(function(e) {
|
||||
$("#node-select-library").children().remove();
|
||||
var bc = $("#node-dialog-library-breadcrumbs");
|
||||
@@ -174,7 +188,7 @@ RED.library = (function() {
|
||||
|
||||
$('#node-input-'+options.type+'-menu-save-library').click(function(e) {
|
||||
//var found = false;
|
||||
var name = $("#node-input-name").val().replace(/(^\s*)|(\s*$)/g,"");
|
||||
var name = $("#"+elementPrefix+"name").val().replace(/(^\s*)|(\s*$)/g,"");
|
||||
|
||||
//var buildPathList = function(data,root) {
|
||||
// var paths = [];
|
||||
@@ -239,21 +253,22 @@ RED.library = (function() {
|
||||
height: 450,
|
||||
buttons: [
|
||||
{
|
||||
text: RED._("common.label.ok"),
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
if (selectedLibraryItem) {
|
||||
for (var i=0;i<options.fields.length;i++) {
|
||||
var field = options.fields[i];
|
||||
$("#node-input-"+field).val(selectedLibraryItem[field]);
|
||||
}
|
||||
options.editor.setValue(libraryEditor.getValue(),-1);
|
||||
}
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._("common.label.cancel"),
|
||||
text: RED._("common.label.load"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
if (selectedLibraryItem) {
|
||||
for (var i=0; i<options.fields.length; i++) {
|
||||
var field = options.fields[i];
|
||||
$("#"+elementPrefix+field).val(selectedLibraryItem[field]);
|
||||
}
|
||||
options.editor.setValue(libraryEditor.getValue(),-1);
|
||||
}
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
@@ -272,7 +287,7 @@ RED.library = (function() {
|
||||
});
|
||||
|
||||
function saveToLibrary(overwrite) {
|
||||
var name = $("#node-input-name").val().replace(/(^\s*)|(\s*$)/g,"");
|
||||
var name = $("#"+elementPrefix+"name").val().replace(/(^\s*)|(\s*$)/g,"");
|
||||
if (name === "") {
|
||||
name = RED._("library.unnamedType",{type:options.type});
|
||||
}
|
||||
@@ -311,12 +326,12 @@ RED.library = (function() {
|
||||
}
|
||||
var queryArgs = [];
|
||||
var data = {};
|
||||
for (var i=0;i<options.fields.length;i++) {
|
||||
for (var i=0; i<options.fields.length; i++) {
|
||||
var field = options.fields[i];
|
||||
if (field == "name") {
|
||||
data.name = name;
|
||||
} else {
|
||||
data[field] = $("#node-input-"+field).val();
|
||||
data[field] = $("#"+elementPrefix+field).val();
|
||||
}
|
||||
}
|
||||
|
||||
@@ -329,7 +344,11 @@ RED.library = (function() {
|
||||
}).done(function(data,textStatus,xhr) {
|
||||
RED.notify(RED._("library.savedType", {type:options.type}),"success");
|
||||
}).fail(function(xhr,textStatus,err) {
|
||||
RED.notify(RED._("library.saveFailed",{message:xhr.responseText}),"error");
|
||||
if (xhr.status === 401) {
|
||||
RED.notify(RED._("library.saveFailed",{message:RED._("user.notAuthorized")}),"error");
|
||||
} else {
|
||||
RED.notify(RED._("library.saveFailed",{message:xhr.responseText}),"error");
|
||||
}
|
||||
});
|
||||
}
|
||||
$( "#node-dialog-library-save-confirm" ).dialog({
|
||||
@@ -340,15 +359,16 @@ RED.library = (function() {
|
||||
height: 230,
|
||||
buttons: [
|
||||
{
|
||||
text: RED._("common.label.ok"),
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
saveToLibrary(true);
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._("common.label.cancel"),
|
||||
text: RED._("common.label.save"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
saveToLibrary(true);
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
@@ -362,15 +382,16 @@ RED.library = (function() {
|
||||
height: 230,
|
||||
buttons: [
|
||||
{
|
||||
text: RED._("common.label.ok"),
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
saveToLibrary(false);
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._("common.label.cancel"),
|
||||
text: RED._("common.label.save"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
saveToLibrary(false);
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
@@ -382,22 +403,19 @@ RED.library = (function() {
|
||||
function exportFlow() {
|
||||
//TODO: don't rely on the main dialog
|
||||
var nns = RED.nodes.createExportableNodeSet(RED.view.selection().nodes);
|
||||
$("#dialog-form").html($("script[data-template-name='export-library-dialog']").html());
|
||||
$("#node-input-filename").attr('nodes',JSON.stringify(nns));
|
||||
$("#dialog").i18n();
|
||||
$("#dialog").dialog("option","title",RED._("library.exportToLibrary")).dialog( "open" );
|
||||
$("#node-input-library-filename").attr('nodes',JSON.stringify(nns));
|
||||
exportToLibraryDialog.dialog( "open" );
|
||||
}
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
|
||||
RED.actions.add("core:library-export",exportFlow);
|
||||
|
||||
RED.events.on("view:selection-changed",function(selection) {
|
||||
if (!selection.nodes) {
|
||||
RED.menu.setDisabled("menu-item-export",true);
|
||||
RED.menu.setDisabled("menu-item-export-clipboard",true);
|
||||
RED.menu.setDisabled("menu-item-export-library",true);
|
||||
} else {
|
||||
RED.menu.setDisabled("menu-item-export",false);
|
||||
RED.menu.setDisabled("menu-item-export-clipboard",false);
|
||||
RED.menu.setDisabled("menu-item-export-library",false);
|
||||
}
|
||||
});
|
||||
@@ -405,6 +423,67 @@ RED.library = (function() {
|
||||
if (RED.settings.theme("menu.menu-item-import-library") !== false) {
|
||||
loadFlowLibrary();
|
||||
}
|
||||
|
||||
exportToLibraryDialog = $('<div id="library-dialog" class="hide"><form class="dialog-form form-horizontal"></form></div>')
|
||||
.appendTo("body")
|
||||
.dialog({
|
||||
modal: true,
|
||||
autoOpen: false,
|
||||
width: 500,
|
||||
resizable: false,
|
||||
title: RED._("library.exportToLibrary"),
|
||||
buttons: [
|
||||
{
|
||||
id: "library-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "library-dialog-ok",
|
||||
class: "primary",
|
||||
text: RED._("common.label.export"),
|
||||
click: function() {
|
||||
//TODO: move this to RED.library
|
||||
var flowName = $("#node-input-library-filename").val();
|
||||
flowName = flowName.trim();
|
||||
if(flowName === "" || flowName.endsWith("/")) {
|
||||
RED.notify(RED._("library.invalidFilename"),"warning");
|
||||
} else {
|
||||
$.ajax({
|
||||
url:'library/flows/'+flowName,
|
||||
type: "POST",
|
||||
data: $("#node-input-library-filename").attr('nodes'),
|
||||
contentType: "application/json; charset=utf-8"
|
||||
}).done(function() {
|
||||
RED.library.loadFlowLibrary();
|
||||
RED.notify(RED._("library.savedNodes"),"success");
|
||||
}).fail(function(xhr,textStatus,err) {
|
||||
if (xhr.status === 401) {
|
||||
RED.notify(RED._("library.saveFailed",{message:RED._("user.notAuthorized")}),"error");
|
||||
} else {
|
||||
RED.notify(RED._("library.saveFailed",{message:xhr.responseText}),"error");
|
||||
}
|
||||
});
|
||||
}
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
],
|
||||
open: function(e) {
|
||||
$(this).parent().find(".ui-dialog-titlebar-close").hide();
|
||||
},
|
||||
close: function(e) {
|
||||
}
|
||||
});
|
||||
exportToLibraryDialog.children(".dialog-form").append($(
|
||||
'<div class="form-row">'+
|
||||
'<label for="node-input-library-filename" data-i18n="[append]editor:library.filename"><i class="fa fa-file"></i> </label>'+
|
||||
'<input type="text" id="node-input-library-filename" data-i18n="[placeholder]editor:library.fullFilenamePlaceholder">'+
|
||||
'<input type="text" style="display: none;" />'+ // Second hidden input to prevent submit on Enter
|
||||
'</div>'
|
||||
));
|
||||
},
|
||||
create: createUI,
|
||||
loadFlowLibrary: loadFlowLibrary,
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013 IBM Corp.
|
||||
* 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.
|
||||
@@ -13,10 +13,49 @@
|
||||
* See the License for the specific language governing permissions and
|
||||
* limitations under the License.
|
||||
**/
|
||||
RED.notify = (function() {
|
||||
RED.notifications = (function() {
|
||||
|
||||
/*
|
||||
// Example usage for a modal dialog with buttons
|
||||
var myNotification = RED.notify("This is the message to display",{
|
||||
modal: true,
|
||||
fixed: true,
|
||||
type: 'warning',
|
||||
buttons: [
|
||||
{
|
||||
text: "cancel",
|
||||
click: function(e) {
|
||||
myNotification.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: "okay",
|
||||
class:"primary",
|
||||
click: function(e) {
|
||||
myNotification.close();
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
*/
|
||||
|
||||
var persistentNotifications = {};
|
||||
|
||||
var currentNotifications = [];
|
||||
var c = 0;
|
||||
return function(msg,type,fixed,timeout) {
|
||||
function notify(msg,type,fixed,timeout) {
|
||||
var options = {};
|
||||
if (type !== null && typeof type === 'object') {
|
||||
options = type;
|
||||
fixed = options.fixed;
|
||||
timeout = options.timeout;
|
||||
type = options.type;
|
||||
}
|
||||
|
||||
if (options.modal) {
|
||||
$("#full-shade").show();
|
||||
}
|
||||
|
||||
if (currentNotifications.length > 4) {
|
||||
var ll = currentNotifications.length;
|
||||
for (var i = 0;ll > 4 && i<currentNotifications.length;i+=1) {
|
||||
@@ -35,24 +74,176 @@ RED.notify = (function() {
|
||||
if (type) {
|
||||
n.className = "notification notification-"+type;
|
||||
}
|
||||
if (options.width) {
|
||||
var parentWidth = $("#notifications").width();
|
||||
if (options.width > parentWidth) {
|
||||
var margin = -(options.width-parentWidth)/2;
|
||||
$(n).css({
|
||||
width: options.width+"px",
|
||||
marginLeft: margin+"px"
|
||||
})
|
||||
}
|
||||
}
|
||||
n.style.display = "none";
|
||||
n.innerHTML = msg;
|
||||
if (typeof msg === "string") {
|
||||
if (!/<p>/i.test(msg)) {
|
||||
msg = "<p>"+msg+"</p>";
|
||||
}
|
||||
n.innerHTML = msg;
|
||||
} else {
|
||||
$(n).append(msg);
|
||||
}
|
||||
if (options.buttons) {
|
||||
var buttonSet = $('<div style="margin-top: 20px;" class="ui-dialog-buttonset"></div>').appendTo(n)
|
||||
options.buttons.forEach(function(buttonDef) {
|
||||
var b = $('<button>').html(buttonDef.text).click(buttonDef.click).appendTo(buttonSet);
|
||||
if (buttonDef.id) {
|
||||
b.attr('id',buttonDef.id);
|
||||
}
|
||||
if (buttonDef.class) {
|
||||
b.addClass(buttonDef.class);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
|
||||
$("#notifications").append(n);
|
||||
$(n).slideDown(300);
|
||||
n.close = (function() {
|
||||
var nn = n;
|
||||
return function() {
|
||||
if (nn.closed) {
|
||||
return;
|
||||
}
|
||||
nn.closed = true;
|
||||
currentNotifications.splice(currentNotifications.indexOf(nn),1);
|
||||
if (options.id) {
|
||||
delete persistentNotifications[options.id];
|
||||
if (Object.keys(persistentNotifications).length === 0) {
|
||||
notificationButtonWrapper.hide();
|
||||
}
|
||||
}
|
||||
$(nn).slideUp(300, function() {
|
||||
nn.parentNode.removeChild(nn);
|
||||
});
|
||||
if (options.modal) {
|
||||
$("#full-shade").hide();
|
||||
}
|
||||
};
|
||||
})();
|
||||
n.hideNotification = (function() {
|
||||
var nn = n;
|
||||
return function() {
|
||||
if (nn.closed) {
|
||||
return
|
||||
}
|
||||
nn.hidden = true;
|
||||
$(nn).slideUp(300);
|
||||
}
|
||||
})();
|
||||
n.showNotification = (function() {
|
||||
var nn = n;
|
||||
return function() {
|
||||
if (nn.closed || !nn.hidden) {
|
||||
return
|
||||
}
|
||||
nn.hidden = false;
|
||||
$(nn).slideDown(300);
|
||||
}
|
||||
})();
|
||||
|
||||
n.update = (function() {
|
||||
var nn = n;
|
||||
return function(msg,options) {
|
||||
if (typeof msg === "string") {
|
||||
if (!/<p>/i.test(msg)) {
|
||||
msg = "<p>"+msg+"</p>";
|
||||
}
|
||||
nn.innerHTML = msg;
|
||||
} else {
|
||||
$(nn).empty().append(msg);
|
||||
}
|
||||
var timeout;
|
||||
if (typeof options === 'number') {
|
||||
timeout = options;
|
||||
} else if (options !== undefined) {
|
||||
timeout = options.timeout;
|
||||
if (options.buttons) {
|
||||
var buttonSet = $('<div style="margin-top: 20px;" class="ui-dialog-buttonset"></div>').appendTo(nn)
|
||||
options.buttons.forEach(function(buttonDef) {
|
||||
var b = $('<button>').text(buttonDef.text).click(buttonDef.click).appendTo(buttonSet);
|
||||
if (buttonDef.id) {
|
||||
b.attr('id',buttonDef.id);
|
||||
}
|
||||
if (buttonDef.class) {
|
||||
b.addClass(buttonDef.class);
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
if (timeout !== undefined && timeout > 0) {
|
||||
window.clearTimeout(nn.timeoutid);
|
||||
nn.timeoutid = window.setTimeout(nn.close,timeout);
|
||||
} else {
|
||||
window.clearTimeout(nn.timeoutid);
|
||||
}
|
||||
if (nn.hidden) {
|
||||
nn.showNotification();
|
||||
}
|
||||
|
||||
}
|
||||
})();
|
||||
|
||||
if (!fixed) {
|
||||
n.timeoutid = window.setTimeout(n.close,timeout||3000);
|
||||
$(n).click((function() {
|
||||
var nn = n;
|
||||
return function() {
|
||||
nn.close();
|
||||
window.clearTimeout(nn.timeoutid);
|
||||
};
|
||||
})());
|
||||
n.timeoutid = window.setTimeout(n.close,timeout||5000);
|
||||
}
|
||||
currentNotifications.push(n);
|
||||
if (options.id) {
|
||||
persistentNotifications[options.id] = n;
|
||||
notificationButtonWrapper.show();
|
||||
}
|
||||
c+=1;
|
||||
return n;
|
||||
}
|
||||
|
||||
RED.notify = notify;
|
||||
|
||||
|
||||
function hidePersistent() {
|
||||
for(var i in persistentNotifications) {
|
||||
if (persistentNotifications.hasOwnProperty(i)) {
|
||||
persistentNotifications[i].hideNotification();
|
||||
}
|
||||
}
|
||||
}
|
||||
function showPersistent() {
|
||||
for(var i in persistentNotifications) {
|
||||
if (persistentNotifications.hasOwnProperty(i)) {
|
||||
persistentNotifications[i].showNotification();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
var notificationButtonWrapper;
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
notificationButtonWrapper = $('<li>'+
|
||||
'<a id="btn-notifications" class="button" href="#">'+
|
||||
'<i class="fa fa-warning"></i>'+
|
||||
'</a>'+
|
||||
'</li>').prependTo(".header-toolbar").hide();
|
||||
$('#btn-notifications').click(function() {
|
||||
showPersistent();
|
||||
})
|
||||
},
|
||||
notify: notify
|
||||
}
|
||||
})();
|
||||
|
||||
967
editor/js/ui/palette-editor.js
Normal file
@@ -0,0 +1,967 @@
|
||||
/**
|
||||
* 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.palette.editor = (function() {
|
||||
|
||||
var disabled = false;
|
||||
|
||||
var editorTabs;
|
||||
var filterInput;
|
||||
var searchInput;
|
||||
var nodeList;
|
||||
var packageList;
|
||||
var loadedList = [];
|
||||
var filteredList = [];
|
||||
var loadedIndex = {};
|
||||
|
||||
var typesInUse = {};
|
||||
var nodeEntries = {};
|
||||
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 }
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
function delayCallback(start,callback) {
|
||||
var delta = Date.now() - start;
|
||||
if (delta < 300) {
|
||||
delta = 300;
|
||||
} else {
|
||||
delta = 0;
|
||||
}
|
||||
setTimeout(function() {
|
||||
callback();
|
||||
},delta);
|
||||
}
|
||||
function changeNodeState(id,state,shade,callback) {
|
||||
shade.show();
|
||||
var start = Date.now();
|
||||
$.ajax({
|
||||
url:"nodes/"+id,
|
||||
type: "PUT",
|
||||
data: JSON.stringify({
|
||||
enabled: state
|
||||
}),
|
||||
contentType: "application/json; charset=utf-8"
|
||||
}).done(function(data,textStatus,xhr) {
|
||||
delayCallback(start,function() {
|
||||
shade.hide();
|
||||
callback();
|
||||
});
|
||||
}).fail(function(xhr,textStatus,err) {
|
||||
delayCallback(start,function() {
|
||||
shade.hide();
|
||||
callback(xhr);
|
||||
});
|
||||
})
|
||||
}
|
||||
function installNodeModule(id,version,callback) {
|
||||
var requestBody = {
|
||||
module: id
|
||||
};
|
||||
if (version) {
|
||||
requestBody.version = version;
|
||||
}
|
||||
$.ajax({
|
||||
url:"nodes",
|
||||
type: "POST",
|
||||
data: JSON.stringify(requestBody),
|
||||
contentType: "application/json; charset=utf-8"
|
||||
}).done(function(data,textStatus,xhr) {
|
||||
callback();
|
||||
}).fail(function(xhr,textStatus,err) {
|
||||
callback(xhr);
|
||||
});
|
||||
}
|
||||
function removeNodeModule(id,callback) {
|
||||
$.ajax({
|
||||
url:"nodes/"+id,
|
||||
type: "DELETE"
|
||||
}).done(function(data,textStatus,xhr) {
|
||||
callback();
|
||||
}).fail(function(xhr,textStatus,err) {
|
||||
callback(xhr);
|
||||
})
|
||||
}
|
||||
|
||||
function refreshNodeModuleList() {
|
||||
for (var id in nodeEntries) {
|
||||
if (nodeEntries.hasOwnProperty(id)) {
|
||||
_refreshNodeModule(id);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function refreshNodeModule(module) {
|
||||
if (!eventTimers.hasOwnProperty(module)) {
|
||||
eventTimers[module] = setTimeout(function() {
|
||||
delete eventTimers[module];
|
||||
_refreshNodeModule(module);
|
||||
},100);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function getContrastingBorder(rgbColor){
|
||||
var parts = /^rgba?\(\s*(\d+),\s*(\d+),\s*(\d+)[,)]/.exec(rgbColor);
|
||||
if (parts) {
|
||||
var r = parseInt(parts[1]);
|
||||
var g = parseInt(parts[2]);
|
||||
var b = parseInt(parts[3]);
|
||||
var yiq = ((r*299)+(g*587)+(b*114))/1000;
|
||||
if (yiq > 160) {
|
||||
r = Math.floor(r*0.8);
|
||||
g = Math.floor(g*0.8);
|
||||
b = Math.floor(b*0.8);
|
||||
return "rgb("+r+","+g+","+b+")";
|
||||
}
|
||||
}
|
||||
return rgbColor;
|
||||
}
|
||||
|
||||
function formatUpdatedAt(dateString) {
|
||||
var now = new Date();
|
||||
var d = new Date(dateString);
|
||||
var delta = (Date.now() - new Date(dateString).getTime())/1000;
|
||||
|
||||
if (delta < 60) {
|
||||
return RED._('palette.editor.times.seconds');
|
||||
}
|
||||
delta = Math.floor(delta/60);
|
||||
if (delta < 10) {
|
||||
return RED._('palette.editor.times.minutes');
|
||||
}
|
||||
if (delta < 60) {
|
||||
return RED._('palette.editor.times.minutesV',{count:delta});
|
||||
}
|
||||
|
||||
delta = Math.floor(delta/60);
|
||||
|
||||
if (delta < 24) {
|
||||
return RED._('palette.editor.times.hoursV',{count:delta});
|
||||
}
|
||||
|
||||
delta = Math.floor(delta/24);
|
||||
|
||||
if (delta < 7) {
|
||||
return RED._('palette.editor.times.daysV',{count:delta})
|
||||
}
|
||||
var weeks = Math.floor(delta/7);
|
||||
var days = delta%7;
|
||||
|
||||
if (weeks < 4) {
|
||||
return RED._('palette.editor.times.weeksV',{count:weeks})
|
||||
}
|
||||
|
||||
var months = Math.floor(weeks/4);
|
||||
weeks = weeks%4;
|
||||
|
||||
if (months < 12) {
|
||||
return RED._('palette.editor.times.monthsV',{count:months})
|
||||
}
|
||||
var years = Math.floor(months/12);
|
||||
months = months%12;
|
||||
|
||||
if (months === 0) {
|
||||
return RED._('palette.editor.times.yearsV',{count:years})
|
||||
} else {
|
||||
return RED._('palette.editor.times.year'+(years>1?'s':'')+'MonthsV',{y:years,count:months})
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
function _refreshNodeModule(module) {
|
||||
if (!nodeEntries.hasOwnProperty(module)) {
|
||||
nodeEntries[module] = {info:RED.nodes.registry.getModule(module)};
|
||||
var index = [module];
|
||||
for (var s in nodeEntries[module].info.sets) {
|
||||
if (nodeEntries[module].info.sets.hasOwnProperty(s)) {
|
||||
index.push(s);
|
||||
index = index.concat(nodeEntries[module].info.sets[s].types)
|
||||
}
|
||||
}
|
||||
nodeEntries[module].index = index.join(",").toLowerCase();
|
||||
nodeList.editableList('addItem', nodeEntries[module]);
|
||||
} else {
|
||||
var moduleInfo = nodeEntries[module].info;
|
||||
var nodeEntry = nodeEntries[module].elements;
|
||||
if (nodeEntry) {
|
||||
var activeTypeCount = 0;
|
||||
var typeCount = 0;
|
||||
var errorCount = 0;
|
||||
nodeEntry.errorList.empty();
|
||||
nodeEntries[module].totalUseCount = 0;
|
||||
nodeEntries[module].setUseCount = {};
|
||||
|
||||
for (var setName in moduleInfo.sets) {
|
||||
if (moduleInfo.sets.hasOwnProperty(setName)) {
|
||||
var inUseCount = 0;
|
||||
var set = moduleInfo.sets[setName];
|
||||
var setElements = nodeEntry.sets[setName];
|
||||
if (set.err) {
|
||||
errorCount++;
|
||||
$("<li>").text(set.err).appendTo(nodeEntry.errorList);
|
||||
}
|
||||
if (set.enabled) {
|
||||
activeTypeCount += set.types.length;
|
||||
}
|
||||
typeCount += set.types.length;
|
||||
for (var i=0;i<moduleInfo.sets[setName].types.length;i++) {
|
||||
var t = moduleInfo.sets[setName].types[i];
|
||||
inUseCount += (typesInUse[t]||0);
|
||||
var swatch = setElements.swatches[t];
|
||||
if (set.enabled) {
|
||||
var def = RED.nodes.getType(t);
|
||||
if (def && def.color) {
|
||||
swatch.css({background:RED.utils.getNodeColor(t,def)});
|
||||
swatch.css({border: "1px solid "+getContrastingBorder(swatch.css('backgroundColor'))})
|
||||
|
||||
} else {
|
||||
swatch.css({background:"#eee",border:"1px dashed #999"})
|
||||
}
|
||||
} else {
|
||||
swatch.css({background:"#eee",border:"1px dashed #999"})
|
||||
}
|
||||
}
|
||||
nodeEntries[module].setUseCount[setName] = inUseCount;
|
||||
nodeEntries[module].totalUseCount += inUseCount;
|
||||
|
||||
if (inUseCount > 0) {
|
||||
setElements.enableButton.text(RED._('palette.editor.inuse'));
|
||||
setElements.enableButton.addClass('disabled');
|
||||
} else {
|
||||
setElements.enableButton.removeClass('disabled');
|
||||
if (set.enabled) {
|
||||
setElements.enableButton.text(RED._('palette.editor.disable'));
|
||||
} else {
|
||||
setElements.enableButton.text(RED._('palette.editor.enable'));
|
||||
}
|
||||
}
|
||||
setElements.setRow.toggleClass("palette-module-set-disabled",!set.enabled);
|
||||
}
|
||||
}
|
||||
|
||||
if (errorCount === 0) {
|
||||
nodeEntry.errorRow.hide()
|
||||
} else {
|
||||
nodeEntry.errorRow.show();
|
||||
}
|
||||
|
||||
var nodeCount = (activeTypeCount === typeCount)?typeCount:activeTypeCount+" / "+typeCount;
|
||||
nodeEntry.setCount.text(RED._('palette.editor.nodeCount',{count:typeCount,label:nodeCount}));
|
||||
|
||||
if (nodeEntries[module].totalUseCount > 0) {
|
||||
nodeEntry.enableButton.text(RED._('palette.editor.inuse'));
|
||||
nodeEntry.enableButton.addClass('disabled');
|
||||
nodeEntry.removeButton.hide();
|
||||
} else {
|
||||
nodeEntry.enableButton.removeClass('disabled');
|
||||
if (moduleInfo.local) {
|
||||
nodeEntry.removeButton.css('display', 'inline-block');
|
||||
}
|
||||
if (activeTypeCount === 0) {
|
||||
nodeEntry.enableButton.text(RED._('palette.editor.enableall'));
|
||||
} else {
|
||||
nodeEntry.enableButton.text(RED._('palette.editor.disableall'));
|
||||
}
|
||||
nodeEntry.container.toggleClass("disabled",(activeTypeCount === 0));
|
||||
}
|
||||
}
|
||||
if (moduleInfo.pending_version) {
|
||||
nodeEntry.versionSpan.html(moduleInfo.version+' <i class="fa fa-long-arrow-right"></i> '+moduleInfo.pending_version).appendTo(nodeEntry.metaRow)
|
||||
nodeEntry.updateButton.text(RED._('palette.editor.updated')).addClass('disabled').show();
|
||||
} else if (loadedIndex.hasOwnProperty(module)) {
|
||||
if (semVerCompare(loadedIndex[module].version,moduleInfo.version) === 1) {
|
||||
nodeEntry.updateButton.show();
|
||||
nodeEntry.updateButton.text(RED._('palette.editor.update',{version:loadedIndex[module].version}));
|
||||
} else {
|
||||
nodeEntry.updateButton.hide();
|
||||
}
|
||||
} else {
|
||||
nodeEntry.updateButton.hide();
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function filterChange(val) {
|
||||
activeFilter = val.toLowerCase();
|
||||
var visible = nodeList.editableList('filter');
|
||||
var size = nodeList.editableList('length');
|
||||
if (val === "") {
|
||||
filterInput.searchBox('count');
|
||||
} else {
|
||||
filterInput.searchBox('count',visible+" / "+size);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
var catalogueCount;
|
||||
var catalogueLoadStatus = [];
|
||||
var catalogueLoadStart;
|
||||
var catalogueLoadErrors = false;
|
||||
|
||||
var activeSort = sortModulesAZ;
|
||||
|
||||
function handleCatalogResponse(err,catalog,index,v) {
|
||||
catalogueLoadStatus.push(err||v);
|
||||
if (!err) {
|
||||
if (v.modules) {
|
||||
v.modules.forEach(function(m) {
|
||||
loadedIndex[m.id] = m;
|
||||
m.index = [m.id];
|
||||
if (m.keywords) {
|
||||
m.index = m.index.concat(m.keywords);
|
||||
}
|
||||
if (m.updated_at) {
|
||||
m.timestamp = new Date(m.updated_at).getTime();
|
||||
} else {
|
||||
m.timestamp = 0;
|
||||
}
|
||||
m.index = m.index.join(",").toLowerCase();
|
||||
})
|
||||
loadedList = loadedList.concat(v.modules);
|
||||
}
|
||||
searchInput.searchBox('count',loadedList.length);
|
||||
} else {
|
||||
catalogueLoadErrors = true;
|
||||
}
|
||||
if (catalogueCount > 1) {
|
||||
$(".palette-module-shade-status").html(RED._('palette.editor.loading')+"<br>"+catalogueLoadStatus.length+"/"+catalogueCount);
|
||||
}
|
||||
if (catalogueLoadStatus.length === catalogueCount) {
|
||||
if (catalogueLoadErrors) {
|
||||
RED.notify(RED._('palette.editor.errors.catalogLoadFailed',{url: catalog}),"error",false,8000);
|
||||
}
|
||||
var delta = 250-(Date.now() - catalogueLoadStart);
|
||||
setTimeout(function() {
|
||||
$("#palette-module-install-shade").hide();
|
||||
},Math.max(delta,0));
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
function initInstallTab() {
|
||||
if (loadedList.length === 0) {
|
||||
loadedList = [];
|
||||
loadedIndex = {};
|
||||
packageList.editableList('empty');
|
||||
|
||||
$(".palette-module-shade-status").text(RED._('palette.editor.loading'));
|
||||
var catalogues = RED.settings.theme('palette.catalogues')||['https://catalogue.nodered.org/catalogue.json'];
|
||||
catalogueLoadStatus = [];
|
||||
catalogueLoadErrors = false;
|
||||
catalogueCount = catalogues.length;
|
||||
if (catalogues.length > 1) {
|
||||
$(".palette-module-shade-status").html(RED._('palette.editor.loading')+"<br>0/"+catalogues.length);
|
||||
}
|
||||
$("#palette-module-install-shade").show();
|
||||
catalogueLoadStart = Date.now();
|
||||
var handled = 0;
|
||||
catalogues.forEach(function(catalog,index) {
|
||||
$.getJSON(catalog, {_: new Date().getTime()},function(v) {
|
||||
handleCatalogResponse(null,catalog,index,v);
|
||||
refreshNodeModuleList();
|
||||
}).fail(function(jqxhr, textStatus, error) {
|
||||
handleCatalogResponse(jqxhr,catalog,index);
|
||||
}).always(function() {
|
||||
handled++;
|
||||
if (handled === catalogueCount) {
|
||||
searchInput.searchBox('change');
|
||||
}
|
||||
})
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
function refreshFilteredItems() {
|
||||
packageList.editableList('empty');
|
||||
var currentFilter = searchInput.searchBox('value').trim();
|
||||
if (currentFilter === ""){
|
||||
packageList.editableList('addItem',{count:loadedList.length})
|
||||
return;
|
||||
}
|
||||
filteredList.sort(activeSort);
|
||||
for (var i=0;i<Math.min(10,filteredList.length);i++) {
|
||||
packageList.editableList('addItem',filteredList[i]);
|
||||
}
|
||||
if (filteredList.length === 0) {
|
||||
packageList.editableList('addItem',{});
|
||||
}
|
||||
|
||||
if (filteredList.length > 10) {
|
||||
packageList.editableList('addItem',{start:10,more:filteredList.length-10})
|
||||
}
|
||||
}
|
||||
function sortModulesAZ(A,B) {
|
||||
return A.info.id.localeCompare(B.info.id);
|
||||
}
|
||||
function sortModulesRecent(A,B) {
|
||||
return -1 * (A.info.timestamp-B.info.timestamp);
|
||||
}
|
||||
|
||||
|
||||
function init() {
|
||||
if (RED.settings.theme('palette.editable') === false) {
|
||||
return;
|
||||
}
|
||||
createSettingsPane();
|
||||
|
||||
RED.userSettings.add({
|
||||
id:'palette',
|
||||
title: RED._("palette.editor.palette"),
|
||||
get: getSettingsPane,
|
||||
close: function() {
|
||||
settingsPane.detach();
|
||||
},
|
||||
focus: function() {
|
||||
editorTabs.resize();
|
||||
setTimeout(function() {
|
||||
filterInput.focus();
|
||||
},200);
|
||||
}
|
||||
})
|
||||
|
||||
RED.actions.add("core:manage-palette",function() {
|
||||
RED.userSettings.show('palette');
|
||||
});
|
||||
|
||||
RED.events.on('registry:module-updated', function(ns) {
|
||||
refreshNodeModule(ns.module);
|
||||
});
|
||||
RED.events.on('registry:node-set-enabled', function(ns) {
|
||||
refreshNodeModule(ns.module);
|
||||
});
|
||||
RED.events.on('registry:node-set-disabled', function(ns) {
|
||||
refreshNodeModule(ns.module);
|
||||
});
|
||||
RED.events.on('registry:node-type-added', function(nodeType) {
|
||||
if (!/^subflow:/.test(nodeType)) {
|
||||
var ns = RED.nodes.registry.getNodeSetForType(nodeType);
|
||||
refreshNodeModule(ns.module);
|
||||
}
|
||||
});
|
||||
RED.events.on('registry:node-type-removed', function(nodeType) {
|
||||
if (!/^subflow:/.test(nodeType)) {
|
||||
var ns = RED.nodes.registry.getNodeSetForType(nodeType);
|
||||
refreshNodeModule(ns.module);
|
||||
}
|
||||
});
|
||||
RED.events.on('registry:node-set-added', function(ns) {
|
||||
refreshNodeModule(ns.module);
|
||||
for (var i=0;i<filteredList.length;i++) {
|
||||
if (filteredList[i].info.id === ns.module) {
|
||||
var installButton = filteredList[i].elements.installButton;
|
||||
installButton.addClass('disabled');
|
||||
installButton.text(RED._('palette.editor.installed'));
|
||||
break;
|
||||
}
|
||||
}
|
||||
});
|
||||
RED.events.on('registry:node-set-removed', function(ns) {
|
||||
var module = RED.nodes.registry.getModule(ns.module);
|
||||
if (!module) {
|
||||
var entry = nodeEntries[ns.module];
|
||||
if (entry) {
|
||||
nodeList.editableList('removeItem', entry);
|
||||
delete nodeEntries[ns.module];
|
||||
for (var i=0;i<filteredList.length;i++) {
|
||||
if (filteredList[i].info.id === ns.module) {
|
||||
var installButton = filteredList[i].elements.installButton;
|
||||
installButton.removeClass('disabled');
|
||||
installButton.text(RED._('palette.editor.install'));
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
RED.events.on('nodes:add', function(n) {
|
||||
if (!/^subflow:/.test(n.type)) {
|
||||
typesInUse[n.type] = (typesInUse[n.type]||0)+1;
|
||||
if (typesInUse[n.type] === 1) {
|
||||
var ns = RED.nodes.registry.getNodeSetForType(n.type);
|
||||
refreshNodeModule(ns.module);
|
||||
}
|
||||
}
|
||||
})
|
||||
RED.events.on('nodes:remove', function(n) {
|
||||
if (typesInUse.hasOwnProperty(n.type)) {
|
||||
typesInUse[n.type]--;
|
||||
if (typesInUse[n.type] === 0) {
|
||||
delete typesInUse[n.type];
|
||||
var ns = RED.nodes.registry.getNodeSetForType(n.type);
|
||||
refreshNodeModule(ns.module);
|
||||
}
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
var settingsPane;
|
||||
|
||||
function getSettingsPane() {
|
||||
initInstallTab();
|
||||
editorTabs.activateTab('nodes');
|
||||
return settingsPane;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function createSettingsPane() {
|
||||
settingsPane = $('<div id="user-settings-tab-palette"></div>');
|
||||
var content = $('<div id="palette-editor">'+
|
||||
'<ul id="palette-editor-tabs"></ul>'+
|
||||
'</div>').appendTo(settingsPane);
|
||||
|
||||
editorTabs = RED.tabs.create({
|
||||
element: settingsPane.find('#palette-editor-tabs'),
|
||||
onchange:function(tab) {
|
||||
content.find(".palette-editor-tab").hide();
|
||||
tab.content.show();
|
||||
if (filterInput) {
|
||||
filterInput.searchBox('value',"");
|
||||
}
|
||||
if (searchInput) {
|
||||
searchInput.searchBox('value',"");
|
||||
}
|
||||
if (tab.id === 'install') {
|
||||
if (searchInput) {
|
||||
searchInput.focus();
|
||||
}
|
||||
} else {
|
||||
if (filterInput) {
|
||||
filterInput.focus();
|
||||
}
|
||||
}
|
||||
},
|
||||
minimumActiveTabWidth: 110
|
||||
});
|
||||
|
||||
|
||||
var modulesTab = $('<div>',{class:"palette-editor-tab"}).appendTo(content);
|
||||
|
||||
editorTabs.addTab({
|
||||
id: 'nodes',
|
||||
label: RED._('palette.editor.tab-nodes'),
|
||||
content: modulesTab
|
||||
})
|
||||
|
||||
var filterDiv = $('<div>',{class:"palette-search"}).appendTo(modulesTab);
|
||||
filterInput = $('<input type="text" data-i18n="[placeholder]palette.filter"></input>')
|
||||
.appendTo(filterDiv)
|
||||
.searchBox({
|
||||
delay: 200,
|
||||
change: function() {
|
||||
filterChange($(this).val());
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
nodeList = $('<ol>',{id:"palette-module-list", style:"position: absolute;top: 35px;bottom: 0;left: 0;right: 0px;"}).appendTo(modulesTab).editableList({
|
||||
addButton: false,
|
||||
scrollOnAdd: false,
|
||||
sort: function(A,B) {
|
||||
return A.info.name.localeCompare(B.info.name);
|
||||
},
|
||||
filter: function(data) {
|
||||
if (activeFilter === "" ) {
|
||||
return true;
|
||||
}
|
||||
|
||||
return (activeFilter==="")||(data.index.indexOf(activeFilter) > -1);
|
||||
},
|
||||
addItem: function(container,i,object) {
|
||||
var entry = object.info;
|
||||
if (entry) {
|
||||
var headerRow = $('<div>',{class:"palette-module-header"}).appendTo(container);
|
||||
var titleRow = $('<div class="palette-module-meta palette-module-name"><i class="fa fa-cube"></i></div>').appendTo(headerRow);
|
||||
$('<span>').text(entry.name).appendTo(titleRow);
|
||||
var metaRow = $('<div class="palette-module-meta palette-module-version"><i class="fa fa-tag"></i></div>').appendTo(headerRow);
|
||||
var versionSpan = $('<span>').text(entry.version).appendTo(metaRow);
|
||||
|
||||
var errorRow = $('<div class="palette-module-meta palette-module-errors"><i class="fa fa-warning"></i></div>').hide().appendTo(headerRow);
|
||||
var errorList = $('<ul class="palette-module-error-list"></ul>').appendTo(errorRow);
|
||||
var buttonRow = $('<div>',{class:"palette-module-meta"}).appendTo(headerRow);
|
||||
var setButton = $('<a href="#" class="editor-button editor-button-small palette-module-set-button"><i class="fa fa-angle-right palette-module-node-chevron"></i> </a>').appendTo(buttonRow);
|
||||
var setCount = $('<span>').appendTo(setButton);
|
||||
var buttonGroup = $('<div>',{class:"palette-module-button-group"}).appendTo(buttonRow);
|
||||
|
||||
var updateButton = $('<a href="#" class="editor-button editor-button-small"></a>').text(RED._('palette.editor.update')).appendTo(buttonGroup);
|
||||
updateButton.attr('id','up_'+Math.floor(Math.random()*1000000000));
|
||||
updateButton.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
if ($(this).hasClass('disabled')) {
|
||||
return;
|
||||
}
|
||||
update(entry,loadedIndex[entry.name].version,container,function(err){});
|
||||
})
|
||||
|
||||
|
||||
var removeButton = $('<a href="#" class="editor-button editor-button-small"></a>').text(RED._('palette.editor.remove')).appendTo(buttonGroup);
|
||||
removeButton.attr('id','up_'+Math.floor(Math.random()*1000000000));
|
||||
removeButton.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
remove(entry,container,function(err){});
|
||||
})
|
||||
if (!entry.local) {
|
||||
removeButton.hide();
|
||||
}
|
||||
var enableButton = $('<a href="#" class="editor-button editor-button-small"></a>').text(RED._('palette.editor.disableall')).appendTo(buttonGroup);
|
||||
|
||||
var contentRow = $('<div>',{class:"palette-module-content"}).appendTo(container);
|
||||
var shade = $('<div class="palette-module-shade hide"><img src="red/images/spin.svg" class="palette-spinner"/></div>').appendTo(container);
|
||||
|
||||
object.elements = {
|
||||
updateButton: updateButton,
|
||||
removeButton: removeButton,
|
||||
enableButton: enableButton,
|
||||
errorRow: errorRow,
|
||||
errorList: errorList,
|
||||
setCount: setCount,
|
||||
container: container,
|
||||
shade: shade,
|
||||
versionSpan: versionSpan,
|
||||
sets: {}
|
||||
}
|
||||
setButton.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
if (container.hasClass('expanded')) {
|
||||
container.removeClass('expanded');
|
||||
contentRow.slideUp();
|
||||
} else {
|
||||
container.addClass('expanded');
|
||||
contentRow.slideDown();
|
||||
}
|
||||
})
|
||||
|
||||
var setList = Object.keys(entry.sets)
|
||||
setList.sort(function(A,B) {
|
||||
return A.toLowerCase().localeCompare(B.toLowerCase());
|
||||
});
|
||||
setList.forEach(function(setName) {
|
||||
var set = entry.sets[setName];
|
||||
var setRow = $('<div>',{class:"palette-module-set"}).appendTo(contentRow);
|
||||
var buttonGroup = $('<div>',{class:"palette-module-set-button-group"}).appendTo(setRow);
|
||||
var typeSwatches = {};
|
||||
set.types.forEach(function(t) {
|
||||
var typeDiv = $('<div>',{class:"palette-module-type"}).appendTo(setRow);
|
||||
typeSwatches[t] = $('<span>',{class:"palette-module-type-swatch"}).appendTo(typeDiv);
|
||||
$('<span>',{class:"palette-module-type-node"}).text(t).appendTo(typeDiv);
|
||||
})
|
||||
var enableButton = $('<a href="#" class="editor-button editor-button-small"></a>').appendTo(buttonGroup);
|
||||
enableButton.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
if (object.setUseCount[setName] === 0) {
|
||||
var currentSet = RED.nodes.registry.getNodeSet(set.id);
|
||||
shade.show();
|
||||
var newState = !currentSet.enabled
|
||||
changeNodeState(set.id,newState,shade,function(xhr){
|
||||
if (xhr) {
|
||||
if (xhr.responseJSON) {
|
||||
RED.notify(RED._('palette.editor.errors.'+(newState?'enable':'disable')+'Failed',{module: id,message:xhr.responseJSON.message}));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
|
||||
object.elements.sets[set.name] = {
|
||||
setRow: setRow,
|
||||
enableButton: enableButton,
|
||||
swatches: typeSwatches
|
||||
};
|
||||
});
|
||||
enableButton.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
if (object.totalUseCount === 0) {
|
||||
changeNodeState(entry.name,(container.hasClass('disabled')),shade,function(xhr){
|
||||
if (xhr) {
|
||||
if (xhr.responseJSON) {
|
||||
RED.notify(RED._('palette.editor.errors.installFailed',{module: id,message:xhr.responseJSON.message}));
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
})
|
||||
refreshNodeModule(entry.name);
|
||||
} else {
|
||||
$('<div>',{class:"red-ui-search-empty"}).text(RED._('search.empty')).appendTo(container);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
|
||||
var installTab = $('<div>',{class:"palette-editor-tab hide"}).appendTo(content);
|
||||
|
||||
editorTabs.addTab({
|
||||
id: 'install',
|
||||
label: RED._('palette.editor.tab-install'),
|
||||
content: installTab
|
||||
})
|
||||
|
||||
var toolBar = $('<div>',{class:"palette-editor-toolbar"}).appendTo(installTab);
|
||||
|
||||
var searchDiv = $('<div>',{class:"palette-search"}).appendTo(installTab);
|
||||
searchInput = $('<input type="text" data-i18n="[placeholder]palette.search"></input>')
|
||||
.appendTo(searchDiv)
|
||||
.searchBox({
|
||||
delay: 300,
|
||||
change: function() {
|
||||
var searchTerm = $(this).val().trim().toLowerCase();
|
||||
if (searchTerm.length > 0) {
|
||||
filteredList = loadedList.filter(function(m) {
|
||||
return (m.index.indexOf(searchTerm) > -1);
|
||||
}).map(function(f) { return {info:f}});
|
||||
refreshFilteredItems();
|
||||
searchInput.searchBox('count',filteredList.length+" / "+loadedList.length);
|
||||
} else {
|
||||
searchInput.searchBox('count',loadedList.length);
|
||||
packageList.editableList('empty');
|
||||
packageList.editableList('addItem',{count:loadedList.length});
|
||||
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
$('<span>').text(RED._("palette.editor.sort")+' ').appendTo(toolBar);
|
||||
var sortGroup = $('<span class="button-group"></span>').appendTo(toolBar);
|
||||
var sortAZ = $('<a href="#" class="sidebar-header-button-toggle selected" data-i18n="palette.editor.sortAZ"></a>').appendTo(sortGroup);
|
||||
var sortRecent = $('<a href="#" class="sidebar-header-button-toggle" data-i18n="palette.editor.sortRecent"></a>').appendTo(sortGroup);
|
||||
|
||||
sortAZ.click(function(e) {
|
||||
e.preventDefault();
|
||||
if ($(this).hasClass("selected")) {
|
||||
return;
|
||||
}
|
||||
$(this).addClass("selected");
|
||||
sortRecent.removeClass("selected");
|
||||
activeSort = sortModulesAZ;
|
||||
refreshFilteredItems();
|
||||
});
|
||||
|
||||
sortRecent.click(function(e) {
|
||||
e.preventDefault();
|
||||
if ($(this).hasClass("selected")) {
|
||||
return;
|
||||
}
|
||||
$(this).addClass("selected");
|
||||
sortAZ.removeClass("selected");
|
||||
activeSort = sortModulesRecent;
|
||||
refreshFilteredItems();
|
||||
});
|
||||
|
||||
|
||||
var refreshSpan = $('<span>').appendTo(toolBar);
|
||||
var refreshButton = $('<a href="#" class="sidebar-header-button"><i class="fa fa-refresh"></i></a>').appendTo(refreshSpan);
|
||||
refreshButton.click(function(e) {
|
||||
e.preventDefault();
|
||||
loadedList = [];
|
||||
loadedIndex = {};
|
||||
initInstallTab();
|
||||
})
|
||||
|
||||
packageList = $('<ol>',{style:"position: absolute;top: 78px;bottom: 0;left: 0;right: 0px;"}).appendTo(installTab).editableList({
|
||||
addButton: false,
|
||||
scrollOnAdd: false,
|
||||
addItem: function(container,i,object) {
|
||||
if (object.count) {
|
||||
$('<div>',{class:"red-ui-search-empty"}).text(RED._('palette.editor.moduleCount',{count:object.count})).appendTo(container);
|
||||
return
|
||||
}
|
||||
if (object.more) {
|
||||
container.addClass('palette-module-more');
|
||||
var moreRow = $('<div>',{class:"palette-module-header palette-module"}).appendTo(container);
|
||||
var moreLink = $('<a href="#"></a>').text(RED._('palette.editor.more',{count:object.more})).appendTo(moreRow);
|
||||
moreLink.click(function(e) {
|
||||
e.preventDefault();
|
||||
packageList.editableList('removeItem',object);
|
||||
for (var i=object.start;i<Math.min(object.start+10,object.start+object.more);i++) {
|
||||
packageList.editableList('addItem',filteredList[i]);
|
||||
}
|
||||
if (object.more > 10) {
|
||||
packageList.editableList('addItem',{start:object.start+10, more:object.more-10})
|
||||
}
|
||||
})
|
||||
return;
|
||||
}
|
||||
if (object.info) {
|
||||
var entry = object.info;
|
||||
var headerRow = $('<div>',{class:"palette-module-header"}).appendTo(container);
|
||||
var titleRow = $('<div class="palette-module-meta"><i class="fa fa-cube"></i></div>').appendTo(headerRow);
|
||||
$('<span>',{class:"palette-module-name"}).text(entry.name||entry.id).appendTo(titleRow);
|
||||
$('<a target="_blank" class="palette-module-link"><i class="fa fa-external-link"></i></a>').attr('href',entry.url).appendTo(titleRow);
|
||||
var descRow = $('<div class="palette-module-meta"></div>').appendTo(headerRow);
|
||||
$('<div>',{class:"palette-module-description"}).text(entry.description).appendTo(descRow);
|
||||
|
||||
var metaRow = $('<div class="palette-module-meta"></div>').appendTo(headerRow);
|
||||
$('<span class="palette-module-version"><i class="fa fa-tag"></i> '+entry.version+'</span>').appendTo(metaRow);
|
||||
$('<span class="palette-module-updated"><i class="fa fa-calendar"></i> '+formatUpdatedAt(entry.updated_at)+'</span>').appendTo(metaRow);
|
||||
var buttonRow = $('<div>',{class:"palette-module-meta"}).appendTo(headerRow);
|
||||
var buttonGroup = $('<div>',{class:"palette-module-button-group"}).appendTo(buttonRow);
|
||||
var installButton = $('<a href="#" class="editor-button editor-button-small"></a>').text(RED._('palette.editor.install')).appendTo(buttonGroup);
|
||||
installButton.click(function(e) {
|
||||
e.preventDefault();
|
||||
if (!$(this).hasClass('disabled')) {
|
||||
install(entry,container,function(xhr) {});
|
||||
}
|
||||
})
|
||||
if (nodeEntries.hasOwnProperty(entry.id)) {
|
||||
installButton.addClass('disabled');
|
||||
installButton.text(RED._('palette.editor.installed'));
|
||||
}
|
||||
|
||||
object.elements = {
|
||||
installButton:installButton
|
||||
}
|
||||
} else {
|
||||
$('<div>',{class:"red-ui-search-empty"}).text(RED._('search.empty')).appendTo(container);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$('<div id="palette-module-install-shade" class="palette-module-shade hide"><div class="palette-module-shade-status"></div><img src="red/images/spin.svg" class="palette-spinner"/></div>').appendTo(installTab);
|
||||
}
|
||||
function update(entry,version,container,done) {
|
||||
if (RED.settings.theme('palette.editable') === false) {
|
||||
done(new Error('Palette not editable'));
|
||||
return;
|
||||
}
|
||||
var notification = RED.notify(RED._("palette.editor.confirm.update.body",{module:entry.name}),{
|
||||
modal: true,
|
||||
fixed: true,
|
||||
buttons: [
|
||||
{
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
notification.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._("palette.editor.confirm.button.update"),
|
||||
class: "primary palette-module-install-confirm-button-update",
|
||||
click: function() {
|
||||
var spinner = RED.utils.addSpinnerOverlay(container, true);
|
||||
installNodeModule(entry.name,version,function(xhr) {
|
||||
spinner.remove();
|
||||
if (xhr) {
|
||||
if (xhr.responseJSON) {
|
||||
RED.notify(RED._('palette.editor.errors.updateFailed',{module: entry.name,message:xhr.responseJSON.message}));
|
||||
}
|
||||
}
|
||||
done(xhr);
|
||||
});
|
||||
notification.close();
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
function remove(entry,container,done) {
|
||||
if (RED.settings.theme('palette.editable') === false) {
|
||||
done(new Error('Palette not editable'));
|
||||
return;
|
||||
}
|
||||
var notification = RED.notify(RED._("palette.editor.confirm.remove.body",{module:entry.name}),{
|
||||
modal: true,
|
||||
fixed: true,
|
||||
buttons: [
|
||||
{
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
notification.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._("palette.editor.confirm.button.remove"),
|
||||
class: "primary palette-module-install-confirm-button-remove",
|
||||
click: function() {
|
||||
var spinner = RED.utils.addSpinnerOverlay(container, true);
|
||||
removeNodeModule(entry.name, function(xhr) {
|
||||
spinner.remove();
|
||||
if (xhr) {
|
||||
if (xhr.responseJSON) {
|
||||
RED.notify(RED._('palette.editor.errors.removeFailed',{module: entry.name,message:xhr.responseJSON.message}));
|
||||
}
|
||||
}
|
||||
})
|
||||
notification.close();
|
||||
}
|
||||
}
|
||||
]
|
||||
})
|
||||
}
|
||||
function install(entry,container,done) {
|
||||
if (RED.settings.theme('palette.editable') === false) {
|
||||
done(new Error('Palette not editable'));
|
||||
return;
|
||||
}
|
||||
var buttons = [
|
||||
{
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
notification.close();
|
||||
}
|
||||
}
|
||||
];
|
||||
if (entry.url) {
|
||||
buttons.push({
|
||||
text: RED._("palette.editor.confirm.button.review"),
|
||||
class: "primary palette-module-install-confirm-button-install",
|
||||
click: function() {
|
||||
var url = entry.url||"";
|
||||
window.open(url);
|
||||
}
|
||||
});
|
||||
}
|
||||
buttons.push({
|
||||
text: RED._("palette.editor.confirm.button.install"),
|
||||
class: "primary palette-module-install-confirm-button-install",
|
||||
click: function() {
|
||||
var spinner = RED.utils.addSpinnerOverlay(container, true);
|
||||
installNodeModule(entry.id,entry.version,function(xhr) {
|
||||
spinner.remove();
|
||||
if (xhr) {
|
||||
if (xhr.responseJSON) {
|
||||
RED.notify(RED._('palette.editor.errors.installFailed',{module: entry.id,message:xhr.responseJSON.message}));
|
||||
}
|
||||
}
|
||||
done(xhr);
|
||||
});
|
||||
notification.close();
|
||||
}
|
||||
});
|
||||
|
||||
var notification = RED.notify(RED._("palette.editor.confirm.install.body",{module:entry.id}),{
|
||||
modal: true,
|
||||
fixed: true,
|
||||
buttons: buttons
|
||||
})
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
install: install
|
||||
}
|
||||
})();
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013, 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -17,12 +17,23 @@
|
||||
RED.palette = (function() {
|
||||
|
||||
var exclusion = ['config','unknown','deprecated'];
|
||||
var core = ['subflows', 'input', 'output', 'function', 'social', 'mobile', 'storage', 'analysis', 'advanced'];
|
||||
var coreCategories = ['subflows', 'input', 'output', 'function', 'social', 'mobile', 'storage', 'analysis', 'advanced'];
|
||||
|
||||
var categoryContainers = {};
|
||||
|
||||
function createCategoryContainer(category, label){
|
||||
label = label || category.replace("_", " ");
|
||||
|
||||
function createCategory(originalCategory,rootCategory,category,ns) {
|
||||
if ($("#palette-base-category-"+rootCategory).length === 0) {
|
||||
createCategoryContainer(originalCategory,rootCategory, ns+":palette.label."+rootCategory);
|
||||
}
|
||||
$("#palette-container-"+rootCategory).show();
|
||||
if ($("#palette-"+category).length === 0) {
|
||||
$("#palette-base-category-"+rootCategory).append('<div id="palette-'+category+'"></div>');
|
||||
}
|
||||
}
|
||||
function createCategoryContainer(originalCategory,category, labelId) {
|
||||
var label = RED._(labelId, {defaultValue:category});
|
||||
label = (label || category).replace(/_/g, " ");
|
||||
var catDiv = $('<div id="palette-container-'+category+'" class="palette-category palette-close hide">'+
|
||||
'<div id="palette-header-'+category+'" class="palette-header"><i class="expanded fa fa-angle-down"></i><span>'+label+'</span></div>'+
|
||||
'<div class="palette-content" id="palette-base-category-'+category+'">'+
|
||||
@@ -31,7 +42,8 @@ RED.palette = (function() {
|
||||
'<div id="palette-'+category+'-function"></div>'+
|
||||
'</div>'+
|
||||
'</div>').appendTo("#palette-container");
|
||||
|
||||
catDiv.data('category',originalCategory);
|
||||
catDiv.data('label',label);
|
||||
categoryContainers[category] = {
|
||||
container: catDiv,
|
||||
close: function() {
|
||||
@@ -66,7 +78,7 @@ RED.palette = (function() {
|
||||
var lineHeight = 20;
|
||||
var portHeight = 10;
|
||||
|
||||
var words = label.split(" ");
|
||||
var words = label.split(/[ -]/);
|
||||
|
||||
var displayLines = [];
|
||||
|
||||
@@ -91,17 +103,17 @@ RED.palette = (function() {
|
||||
el.css({height:multiLineNodeHeight+"px"});
|
||||
|
||||
var labelElement = el.find(".palette_label");
|
||||
labelElement.html(lines);
|
||||
labelElement.html(lines).attr('dir', RED.text.bidi.resolveBaseTextDir(lines));
|
||||
|
||||
el.find(".palette_port").css({top:(multiLineNodeHeight/2-5)+"px"});
|
||||
|
||||
var popOverContent;
|
||||
try {
|
||||
var l = "<p><b>"+label+"</b></p>";
|
||||
var l = "<p><b>"+RED.text.bidi.enforceTextDirectionWithUCC(label)+"</b></p>";
|
||||
if (label != type) {
|
||||
l = "<p><b>"+label+"</b><br/><i>"+type+"</i></p>";
|
||||
l = "<p><b>"+RED.text.bidi.enforceTextDirectionWithUCC(label)+"</b><br/><i>"+type+"</i></p>";
|
||||
}
|
||||
popOverContent = $(l+(info?info:$("script[data-help-name|='"+type+"']").html()||"<p>"+RED._("palette.noInfo")+"</p>").trim())
|
||||
popOverContent = $(l+(info?info:$("script[data-help-name='"+type+"']").html()||"<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);
|
||||
@@ -116,6 +128,12 @@ RED.palette = (function() {
|
||||
el.data('popover').setContent(popOverContent);
|
||||
}
|
||||
|
||||
function setIcon(element,sf) {
|
||||
var iconElement = element.find(".palette_icon");
|
||||
var icon_url = RED.utils.getNodeIcon(sf._def,sf);
|
||||
iconElement.attr("style", "background-image: url("+icon_url+")");
|
||||
}
|
||||
|
||||
function escapeNodeType(nt) {
|
||||
return nt.replace(" ","_").replace(".","_").replace(":","_");
|
||||
}
|
||||
@@ -127,34 +145,34 @@ RED.palette = (function() {
|
||||
}
|
||||
if (exclusion.indexOf(def.category)===-1) {
|
||||
|
||||
var category = def.category.replace(" ","_");
|
||||
var originalCategory = def.category;
|
||||
var category = def.category.replace(/ /g,"_");
|
||||
var rootCategory = category.split("-")[0];
|
||||
|
||||
var d = document.createElement("div");
|
||||
d.id = "palette_node_"+nodeTypeId;
|
||||
d.type = nt;
|
||||
|
||||
var label;
|
||||
|
||||
if (typeof def.paletteLabel === "undefined") {
|
||||
label = /^(.*?)([ -]in|[ -]out)?$/.exec(nt)[1];
|
||||
} else {
|
||||
label = (typeof def.paletteLabel === "function" ? def.paletteLabel.call(def) : def.paletteLabel)||"";
|
||||
var label = /^(.*?)([ -]in|[ -]out)?$/.exec(nt)[1];
|
||||
if (typeof def.paletteLabel !== "undefined") {
|
||||
try {
|
||||
label = (typeof def.paletteLabel === "function" ? def.paletteLabel.call(def) : def.paletteLabel)||"";
|
||||
} catch(err) {
|
||||
console.log("Definition error: "+nt+".paletteLabel",err);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
$('<div/>',{class:"palette_label"+(def.align=="right"?" palette_label_right":"")}).appendTo(d);
|
||||
|
||||
d.className="palette_node";
|
||||
|
||||
|
||||
if (def.icon) {
|
||||
var icon_url = (typeof def.icon === "function" ? def.icon.call({}) : def.icon);
|
||||
var icon_url = RED.utils.getNodeIcon(def);
|
||||
var iconContainer = $('<div/>',{class:"palette_icon_container"+(def.align=="right"?" palette_icon_container_right":"")}).appendTo(d);
|
||||
$('<div/>',{class:"palette_icon",style:"background-image: url(icons/"+icon_url+")"}).appendTo(iconContainer);
|
||||
$('<div/>',{class:"palette_icon",style:"background-image: url("+icon_url+")"}).appendTo(iconContainer);
|
||||
}
|
||||
|
||||
d.style.backgroundColor = def.color;
|
||||
d.style.backgroundColor = RED.utils.getNodeColor(nt,def);
|
||||
|
||||
if (def.outputs > 0) {
|
||||
var portOut = document.createElement("div");
|
||||
@@ -168,28 +186,22 @@ RED.palette = (function() {
|
||||
d.appendChild(portIn);
|
||||
}
|
||||
|
||||
if ($("#palette-base-category-"+rootCategory).length === 0) {
|
||||
if(core.indexOf(rootCategory) !== -1){
|
||||
createCategoryContainer(rootCategory, RED._("node-red:palette.label."+rootCategory, {defaultValue:rootCategory}));
|
||||
} else {
|
||||
var ns = def.set.id;
|
||||
createCategoryContainer(rootCategory, RED._(ns+":palette.label."+rootCategory, {defaultValue:rootCategory}));
|
||||
}
|
||||
}
|
||||
$("#palette-container-"+rootCategory).show();
|
||||
|
||||
if ($("#palette-"+category).length === 0) {
|
||||
$("#palette-base-category-"+rootCategory).append('<div id="palette-'+category+'"></div>');
|
||||
}
|
||||
createCategory(def.category,rootCategory,category,(coreCategories.indexOf(rootCategory) !== -1)?"node-red":def.set.id);
|
||||
|
||||
$("#palette-"+category).append(d);
|
||||
|
||||
$(d).data('category',rootCategory);
|
||||
|
||||
d.onmousedown = function(e) { e.preventDefault(); };
|
||||
|
||||
RED.popover.create({
|
||||
var popover = RED.popover.create({
|
||||
target:$(d),
|
||||
trigger: "hover",
|
||||
width: "300px",
|
||||
content: "hi",
|
||||
delay: { show: 750, hide: 50 }
|
||||
});
|
||||
$(d).data('popover',popover);
|
||||
|
||||
// $(d).popover({
|
||||
// title:d.type,
|
||||
@@ -203,23 +215,104 @@ RED.palette = (function() {
|
||||
RED.view.focus();
|
||||
var helpText;
|
||||
if (nt.indexOf("subflow:") === 0) {
|
||||
helpText = marked(RED.nodes.subflow(nt.substring(8)).info||"");
|
||||
helpText = marked(RED.nodes.subflow(nt.substring(8)).info||"")||('<span class="node-info-none">'+RED._("sidebar.info.none")+'</span>');
|
||||
} else {
|
||||
helpText = $("script[data-help-name|='"+d.type+"']").html()||"";
|
||||
helpText = $("script[data-help-name='"+d.type+"']").html()||('<span class="node-info-none">'+RED._("sidebar.info.none")+'</span>');
|
||||
}
|
||||
var help = '<div class="node-help">'+helpText+"</div>";
|
||||
RED.sidebar.info.set(help);
|
||||
RED.sidebar.info.set(helpText,RED._("sidebar.info.nodeHelp"));
|
||||
});
|
||||
var chart = $("#chart");
|
||||
var chartOffset = chart.offset();
|
||||
var chartSVG = $("#chart>svg").get(0);
|
||||
var activeSpliceLink;
|
||||
var mouseX;
|
||||
var mouseY;
|
||||
var spliceTimer;
|
||||
var paletteWidth;
|
||||
var paletteTop;
|
||||
$(d).draggable({
|
||||
helper: 'clone',
|
||||
appendTo: 'body',
|
||||
revert: true,
|
||||
revertDuration: 50,
|
||||
start: function() {RED.view.focus();}
|
||||
containment:'#main-container',
|
||||
start: function() {
|
||||
paletteWidth = $("#palette").width();
|
||||
paletteTop = $("#palette").parent().position().top + $("#palette-container").position().top;
|
||||
RED.view.focus();
|
||||
},
|
||||
stop: function() { d3.select('.link_splice').classed('link_splice',false); if (spliceTimer) { clearTimeout(spliceTimer); spliceTimer = null;}},
|
||||
drag: function(e,ui) {
|
||||
|
||||
// TODO: this is the margin-left of palette node. Hard coding
|
||||
// it here makes me sad
|
||||
//console.log(ui.helper.position());
|
||||
ui.position.left += 17.5;
|
||||
|
||||
if (def.inputs > 0 && def.outputs > 0) {
|
||||
mouseX = ui.position.left-paletteWidth+(ui.helper.width()/2) - chartOffset.left + chart.scrollLeft();
|
||||
mouseY = ui.position.top-paletteTop+(ui.helper.height()/2) - chartOffset.top + chart.scrollTop();
|
||||
if (!spliceTimer) {
|
||||
spliceTimer = setTimeout(function() {
|
||||
var nodes = [];
|
||||
var bestDistance = Infinity;
|
||||
var bestLink = null;
|
||||
if (chartSVG.getIntersectionList) {
|
||||
var svgRect = chartSVG.createSVGRect();
|
||||
svgRect.x = mouseX;
|
||||
svgRect.y = mouseY;
|
||||
svgRect.width = 1;
|
||||
svgRect.height = 1;
|
||||
nodes = chartSVG.getIntersectionList(svgRect,chartSVG);
|
||||
mouseX /= RED.view.scale();
|
||||
mouseY /= RED.view.scale();
|
||||
} else {
|
||||
// Firefox doesn't do getIntersectionList and that
|
||||
// makes us sad
|
||||
mouseX /= RED.view.scale();
|
||||
mouseY /= RED.view.scale();
|
||||
nodes = RED.view.getLinksAtPoint(mouseX,mouseY);
|
||||
}
|
||||
|
||||
for (var i=0;i<nodes.length;i++) {
|
||||
var node = d3.select(nodes[i]);
|
||||
if (node.classed('link_background') && !node.classed('link_link')) {
|
||||
var length = nodes[i].getTotalLength();
|
||||
for (var j=0;j<length;j+=10) {
|
||||
var p = nodes[i].getPointAtLength(j);
|
||||
var d2 = ((p.x-mouseX)*(p.x-mouseX))+((p.y-mouseY)*(p.y-mouseY));
|
||||
if (d2 < 200 && d2 < bestDistance) {
|
||||
bestDistance = d2;
|
||||
bestLink = nodes[i];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (activeSpliceLink && activeSpliceLink !== bestLink) {
|
||||
d3.select(activeSpliceLink.parentNode).classed('link_splice',false);
|
||||
}
|
||||
if (bestLink) {
|
||||
d3.select(bestLink.parentNode).classed('link_splice',true)
|
||||
} else {
|
||||
d3.select('.link_splice').classed('link_splice',false);
|
||||
}
|
||||
if (activeSpliceLink !== bestLink) {
|
||||
if (bestLink) {
|
||||
$(ui.helper).data('splice',d3.select(bestLink).data()[0]);
|
||||
} else {
|
||||
$(ui.helper).removeData('splice');
|
||||
}
|
||||
}
|
||||
activeSpliceLink = bestLink;
|
||||
spliceTimer = null;
|
||||
},200);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var nodeInfo = null;
|
||||
if (def.category == "subflows") {
|
||||
if (nt.indexOf("subflow:") === 0) {
|
||||
$(d).dblclick(function(e) {
|
||||
RED.workspaces.show(nt.substring(8));
|
||||
e.preventDefault();
|
||||
@@ -228,9 +321,9 @@ RED.palette = (function() {
|
||||
}
|
||||
setLabel(nt,$(d),label,nodeInfo);
|
||||
|
||||
var categoryNode = $("#palette-container-"+category);
|
||||
var categoryNode = $("#palette-container-"+rootCategory);
|
||||
if (categoryNode.find(".palette_node").length === 1) {
|
||||
categoryContainers[category].open();
|
||||
categoryContainers[rootCategory].open();
|
||||
}
|
||||
|
||||
}
|
||||
@@ -248,14 +341,26 @@ RED.palette = (function() {
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function hideNodeType(nt) {
|
||||
var nodeTypeId = escapeNodeType(nt);
|
||||
$("#palette_node_"+nodeTypeId).hide();
|
||||
var paletteNode = $("#palette_node_"+nodeTypeId);
|
||||
paletteNode.hide();
|
||||
var categoryNode = paletteNode.closest(".palette-category");
|
||||
var cl = categoryNode.find(".palette_node");
|
||||
var c = 0;
|
||||
for (var i = 0; i < cl.length; i++) {
|
||||
if ($(cl[i]).css('display') === 'none') { c += 1; }
|
||||
}
|
||||
if (c === cl.length) { categoryNode.hide(); }
|
||||
}
|
||||
|
||||
function showNodeType(nt) {
|
||||
var nodeTypeId = escapeNodeType(nt);
|
||||
$("#palette_node_"+nodeTypeId).show();
|
||||
var paletteNode = $("#palette_node_"+nodeTypeId);
|
||||
var categoryNode = paletteNode.closest(".palette-category");
|
||||
categoryNode.show();
|
||||
paletteNode.show();
|
||||
}
|
||||
|
||||
function refreshNodeTypes() {
|
||||
@@ -280,19 +385,38 @@ RED.palette = (function() {
|
||||
portOutput.remove();
|
||||
}
|
||||
setLabel(sf.type+":"+sf.id,paletteNode,sf.name,marked(sf.info||""));
|
||||
setIcon(paletteNode,sf);
|
||||
|
||||
var currentCategory = paletteNode.data('category');
|
||||
var newCategory = (sf.category||"subflows");
|
||||
if (currentCategory !== newCategory) {
|
||||
var category = newCategory.replace(/ /g,"_");
|
||||
createCategory(newCategory,category,category,"node-red");
|
||||
|
||||
var currentCategoryNode = paletteNode.closest(".palette-category");
|
||||
var newCategoryNode = $("#palette-"+category);
|
||||
newCategoryNode.append(paletteNode);
|
||||
if (newCategoryNode.find(".palette_node").length === 1) {
|
||||
categoryContainers[category].open();
|
||||
}
|
||||
|
||||
paletteNode.data('category',newCategory);
|
||||
if (currentCategoryNode.find(".palette_node").length === 0) {
|
||||
if (currentCategoryNode.find("i").hasClass("expanded")) {
|
||||
currentCategoryNode.find(".palette-content").slideToggle();
|
||||
currentCategoryNode.find("i").toggleClass("expanded");
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function filterChange() {
|
||||
var val = $("#palette-search-input").val();
|
||||
if (val === "") {
|
||||
$("#palette-search-clear").hide();
|
||||
} else {
|
||||
$("#palette-search-clear").show();
|
||||
}
|
||||
|
||||
var re = new RegExp(val,'i');
|
||||
$(".palette_node").each(function(i,el) {
|
||||
function filterChange(val) {
|
||||
var re = new RegExp(val.replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&'),'i');
|
||||
$("#palette-container .palette_node").each(function(i,el) {
|
||||
var currentLabel = $(el).find(".palette_label").text();
|
||||
if (val === "" || re.test(el.id) || re.test(currentLabel)) {
|
||||
$(this).show();
|
||||
@@ -315,40 +439,67 @@ RED.palette = (function() {
|
||||
}
|
||||
|
||||
function init() {
|
||||
$(".palette-spinner").show();
|
||||
|
||||
RED.events.on('registry:node-type-added', function(nodeType) {
|
||||
var def = RED.nodes.getType(nodeType);
|
||||
addNodeType(nodeType,def);
|
||||
if (def.onpaletteadd && typeof def.onpaletteadd === "function") {
|
||||
def.onpaletteadd.call(def);
|
||||
}
|
||||
});
|
||||
RED.events.on('registry:node-type-removed', function(nodeType) {
|
||||
removeNodeType(nodeType);
|
||||
});
|
||||
RED.events.on('registry:node-set-enabled', function(nodeSet) {
|
||||
for (var j=0;j<nodeSet.types.length;j++) {
|
||||
showNodeType(nodeSet.types[j]);
|
||||
var def = RED.nodes.getType(nodeSet.types[j]);
|
||||
if (def && def.onpaletteadd && typeof def.onpaletteadd === "function") {
|
||||
def.onpaletteadd.call(def);
|
||||
}
|
||||
}
|
||||
});
|
||||
RED.events.on('registry:node-set-disabled', function(nodeSet) {
|
||||
for (var j=0;j<nodeSet.types.length;j++) {
|
||||
hideNodeType(nodeSet.types[j]);
|
||||
var def = RED.nodes.getType(nodeSet.types[j]);
|
||||
if (def && def.onpaletteremove && typeof def.onpaletteremove === "function") {
|
||||
def.onpaletteremove.call(def);
|
||||
}
|
||||
}
|
||||
});
|
||||
RED.events.on('registry:node-set-removed', function(nodeSet) {
|
||||
if (nodeSet.added) {
|
||||
for (var j=0;j<nodeSet.types.length;j++) {
|
||||
removeNodeType(nodeSet.types[j]);
|
||||
var def = RED.nodes.getType(nodeSet.types[j]);
|
||||
if (def && def.onpaletteremove && typeof def.onpaletteremove === "function") {
|
||||
def.onpaletteremove.call(def);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
$("#palette > .palette-spinner").show();
|
||||
|
||||
$("#palette-search input").searchBox({
|
||||
delay: 100,
|
||||
change: function() {
|
||||
filterChange($(this).val());
|
||||
}
|
||||
})
|
||||
|
||||
var categoryList = coreCategories;
|
||||
if (RED.settings.paletteCategories) {
|
||||
RED.settings.paletteCategories.forEach(function(category){
|
||||
createCategoryContainer(category, RED._("palette.label."+category,{defaultValue:category}));
|
||||
});
|
||||
} else {
|
||||
core.forEach(function(category){
|
||||
createCategoryContainer(category, RED._("palette.label."+category,{defaultValue:category}));
|
||||
});
|
||||
categoryList = RED.settings.paletteCategories;
|
||||
} else if (RED.settings.theme('palette.categories')) {
|
||||
categoryList = RED.settings.theme('palette.categories');
|
||||
}
|
||||
|
||||
$("#palette-search-input").focus(function(e) {
|
||||
RED.keyboard.disable();
|
||||
});
|
||||
$("#palette-search-input").blur(function(e) {
|
||||
RED.keyboard.enable();
|
||||
});
|
||||
|
||||
$("#palette-search-clear").on("click",function(e) {
|
||||
e.preventDefault();
|
||||
$("#palette-search-input").val("");
|
||||
filterChange();
|
||||
$("#palette-search-input").focus();
|
||||
});
|
||||
|
||||
$("#palette-search-input").val("");
|
||||
$("#palette-search-input").on("keyup",function() {
|
||||
filterChange();
|
||||
});
|
||||
|
||||
$("#palette-search-input").on("focus",function() {
|
||||
$("body").one("mousedown",function() {
|
||||
$("#palette-search-input").blur();
|
||||
});
|
||||
if (!Array.isArray(categoryList)) {
|
||||
categoryList = coreCategories
|
||||
}
|
||||
categoryList.forEach(function(category){
|
||||
createCategoryContainer(category, category, "palette.label."+category);
|
||||
});
|
||||
|
||||
$("#palette-collapse-all").on("click", function(e) {
|
||||
@@ -368,13 +519,20 @@ RED.palette = (function() {
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function getCategories() {
|
||||
var categories = [];
|
||||
$("#palette-container .palette-category").each(function(i,d) {
|
||||
categories.push({id:$(d).data('category'),label:$(d).data('label')});
|
||||
})
|
||||
return categories;
|
||||
}
|
||||
return {
|
||||
init: init,
|
||||
add:addNodeType,
|
||||
remove:removeNodeType,
|
||||
hide:hideNodeType,
|
||||
show:showNodeType,
|
||||
refresh:refreshNodeTypes
|
||||
refresh:refreshNodeTypes,
|
||||
getCategories: getCategories
|
||||
};
|
||||
})();
|
||||
|
||||
@@ -1,79 +0,0 @@
|
||||
/**
|
||||
* Copyright 2015 IBM Corp.
|
||||
*
|
||||
* 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.popover = (function() {
|
||||
|
||||
|
||||
function createPopover(options) {
|
||||
var target = options.target;
|
||||
|
||||
var content = options.content;
|
||||
var delay = options.delay;
|
||||
var timer = null;
|
||||
var active;
|
||||
var div;
|
||||
|
||||
var openPopup = function() {
|
||||
if (active) {
|
||||
div = $('<div class="red-ui-popover"></div>').html(content).appendTo("body");
|
||||
var targetPos = target.offset();
|
||||
var targetWidth = target.width();
|
||||
var targetHeight = target.height();
|
||||
|
||||
var divHeight = div.height();
|
||||
div.css({top: targetPos.top+targetHeight/2-divHeight/2-10,left:targetPos.left+targetWidth+17});
|
||||
|
||||
div.fadeIn("fast");
|
||||
}
|
||||
}
|
||||
var closePopup = function() {
|
||||
if (!active) {
|
||||
if (div) {
|
||||
div.fadeOut("fast",function() {
|
||||
$(this).remove();
|
||||
});
|
||||
div = null;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
target.on('mouseenter',function(e) {
|
||||
clearTimeout(timer);
|
||||
active = true;
|
||||
timer = setTimeout(openPopup,delay.show);
|
||||
});
|
||||
target.on('mouseleave', function(e) {
|
||||
if (timer) {
|
||||
clearTimeout(timer);
|
||||
}
|
||||
active = false;
|
||||
setTimeout(closePopup,delay.hide);
|
||||
});
|
||||
var res = {
|
||||
setContent: function(_content) {
|
||||
content = _content;
|
||||
}
|
||||
}
|
||||
target.data('popover',res);
|
||||
return res;
|
||||
|
||||
}
|
||||
|
||||
return {
|
||||
create: createPopover
|
||||
}
|
||||
|
||||
})();
|
||||
1539
editor/js/ui/projects/projectSettings.js
Normal file
418
editor/js/ui/projects/projectUserSettings.js
Normal file
@@ -0,0 +1,418 @@
|
||||
/**
|
||||
* 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.projects.userSettings = (function() {
|
||||
|
||||
var gitUsernameInput;
|
||||
var gitEmailInput;
|
||||
|
||||
function createGitUserSection(pane) {
|
||||
|
||||
var currentGitSettings = RED.settings.get('git') || {};
|
||||
currentGitSettings.user = currentGitSettings.user || {};
|
||||
|
||||
var title = $('<h3></h3>').text(RED._("editor:sidebar.project.userSettings.committerDetail")).appendTo(pane);
|
||||
|
||||
var gitconfigContainer = $('<div class="user-settings-section"></div>').appendTo(pane);
|
||||
$('<div style="color:#aaa;"></div>').appendTo(gitconfigContainer).text(RED._("editor:sidebar.project.userSettings.committerTip"));
|
||||
|
||||
var row = $('<div class="user-settings-row"></div>').appendTo(gitconfigContainer);
|
||||
$('<label for=""></label>').text(RED._("editor:sidebar.project.userSettings.userName")).appendTo(row);
|
||||
gitUsernameInput = $('<input type="text">').appendTo(row);
|
||||
gitUsernameInput.val(currentGitSettings.user.name||"");
|
||||
|
||||
row = $('<div class="user-settings-row"></div>').appendTo(gitconfigContainer);
|
||||
$('<label for=""></label>').text(RED._("editor:sidebar.project.userSettings.email")).appendTo(row);
|
||||
gitEmailInput = $('<input type="text">').appendTo(row);
|
||||
gitEmailInput.val(currentGitSettings.user.email||"");
|
||||
}
|
||||
|
||||
|
||||
function createSSHKeySection(pane) {
|
||||
var container = $('<div class="user-settings-section"></div>').appendTo(pane);
|
||||
var popover;
|
||||
var title = $('<h3></h3>').text(RED._("editor:sidebar.project.userSettings.sshKeys")).appendTo(container);
|
||||
var subtitle = $('<div style="color:#aaa;"></div>').appendTo(container).text(RED._("editor:sidebar.project.userSettings.sshKeysTip"));
|
||||
|
||||
var addKeyButton = $('<button id="user-settings-gitconfig-add-key" class="editor-button editor-button-small" style="float: right; margin-right: 10px;">'+RED._("editor:sidebar.project.userSettings.add")+'</button>')
|
||||
.appendTo(subtitle)
|
||||
.click(function(evt) {
|
||||
addKeyButton.attr('disabled',true);
|
||||
saveButton.attr('disabled',true);
|
||||
// bg.children().removeClass("selected");
|
||||
// addLocalButton.click();
|
||||
addKeyDialog.slideDown(200);
|
||||
keyNameInput.focus();
|
||||
});
|
||||
|
||||
var validateForm = function() {
|
||||
var valid = /^[a-zA-Z0-9\-_]+$/.test(keyNameInput.val());
|
||||
keyNameInput.toggleClass('input-error',keyNameInputChanged&&!valid);
|
||||
|
||||
// var selectedButton = bg.find(".selected");
|
||||
// if (selectedButton[0] === addLocalButton[0]) {
|
||||
// valid = valid && localPublicKeyPathInput.val().length > 0 && localPrivateKeyPathInput.val().length > 0;
|
||||
// } else if (selectedButton[0] === uploadButton[0]) {
|
||||
// valid = valid && publicKeyInput.val().length > 0 && privateKeyInput.val().length > 0;
|
||||
// } else if (selectedButton[0] === generateButton[0]) {
|
||||
var passphrase = passphraseInput.val();
|
||||
var validPassphrase = passphrase.length === 0 || passphrase.length >= 8;
|
||||
passphraseInput.toggleClass('input-error',!validPassphrase);
|
||||
if (!validPassphrase) {
|
||||
passphraseInputSubLabel.text(RED._("editor:sidebar.project.userSettings.passphraseShort"));
|
||||
} else if (passphrase.length === 0) {
|
||||
passphraseInputSubLabel.text(RED._("editor:sidebar.project.userSettings.optional"));
|
||||
} else {
|
||||
passphraseInputSubLabel.text("");
|
||||
}
|
||||
valid = valid && validPassphrase;
|
||||
// }
|
||||
|
||||
saveButton.attr('disabled',!valid);
|
||||
|
||||
if (popover) {
|
||||
popover.close();
|
||||
popover = null;
|
||||
}
|
||||
};
|
||||
|
||||
var row = $('<div class="user-settings-row"></div>').appendTo(container);
|
||||
var addKeyDialog = $('<div class="projects-dialog-list-dialog"></div>').hide().appendTo(row);
|
||||
$('<div class="projects-dialog-list-dialog-header">').text(RED._("editor:sidebar.project.userSettings.addSshKey")).appendTo(addKeyDialog);
|
||||
var addKeyDialogBody = $('<div>').appendTo(addKeyDialog);
|
||||
|
||||
row = $('<div class="user-settings-row"></div>').appendTo(addKeyDialogBody);
|
||||
$('<div style="color:#aaa;"></div>').appendTo(row).text(RED._("editor:sidebar.project.userSettings.addSshKeyTip"));
|
||||
// var bg = $('<div></div>',{class:"button-group", style:"text-align: center"}).appendTo(row);
|
||||
// var addLocalButton = $('<button class="editor-button toggle selected">use local key</button>').appendTo(bg);
|
||||
// var uploadButton = $('<button class="editor-button toggle">upload key</button>').appendTo(bg);
|
||||
// var generateButton = $('<button class="editor-button toggle">generate key</button>').appendTo(bg);
|
||||
// bg.children().click(function(e) {
|
||||
// e.preventDefault();
|
||||
// if ($(this).hasClass("selected")) {
|
||||
// return;
|
||||
// }
|
||||
// bg.children().removeClass("selected");
|
||||
// $(this).addClass("selected");
|
||||
// if (this === addLocalButton[0]) {
|
||||
// addLocalKeyPane.show();
|
||||
// generateKeyPane.hide();
|
||||
// uploadKeyPane.hide();
|
||||
// } else if (this === uploadButton[0]) {
|
||||
// addLocalKeyPane.hide();
|
||||
// generateKeyPane.hide();
|
||||
// uploadKeyPane.show();
|
||||
// } else if (this === generateButton[0]){
|
||||
// addLocalKeyPane.hide();
|
||||
// generateKeyPane.show();
|
||||
// uploadKeyPane.hide();
|
||||
// }
|
||||
// validateForm();
|
||||
// })
|
||||
|
||||
|
||||
row = $('<div class="user-settings-row"></div>').appendTo(addKeyDialogBody);
|
||||
$('<label for=""></label>').text(RED._("editor:sidebar.project.userSettings.name")).appendTo(row);
|
||||
var keyNameInputChanged = false;
|
||||
var keyNameInput = $('<input type="text">').appendTo(row).on("change keyup paste",function() {
|
||||
keyNameInputChanged = true;
|
||||
validateForm();
|
||||
});
|
||||
$('<label class="projects-edit-form-sublabel"><small>'+RED._("editor:sidebar.project.userSettings.nameRule")+'</small></label>').appendTo(row).find("small");
|
||||
|
||||
var generateKeyPane = $('<div>').appendTo(addKeyDialogBody);
|
||||
row = $('<div class="user-settings-row"></div>').appendTo(generateKeyPane);
|
||||
$('<label for=""></label>').text(RED._("editor:sidebar.project.userSettings.passphrase")).appendTo(row);
|
||||
var passphraseInput = $('<input type="password">').appendTo(row).on("change keyup paste",validateForm);
|
||||
var passphraseInputSubLabel = $('<label class="projects-edit-form-sublabel"><small>'+RED._("editor:sidebar.project.userSettings.optional")+'</small></label>').appendTo(row).find("small");
|
||||
|
||||
// var addLocalKeyPane = $('<div>').hide().appendTo(addKeyDialogBody);
|
||||
// row = $('<div class="user-settings-row"></div>').appendTo(addLocalKeyPane);
|
||||
// $('<label for=""></label>').text('Public key').appendTo(row);
|
||||
// var localPublicKeyPathInput = $('<input type="text">').appendTo(row).on("change keyup paste",validateForm);
|
||||
// $('<label class="projects-edit-form-sublabel"><small>Public key file path, for example: ~/.ssh/id_rsa.pub</small></label>').appendTo(row).find("small");
|
||||
// row = $('<div class="user-settings-row"></div>').appendTo(addLocalKeyPane);
|
||||
// $('<label for=""></label>').text('Private key').appendTo(row);
|
||||
// var localPrivateKeyPathInput = $('<input type="text">').appendTo(row).on("change keyup paste",validateForm);
|
||||
// $('<label class="projects-edit-form-sublabel"><small>Private key file path, for example: ~/.ssh/id_rsa</small></label>').appendTo(row).find("small");
|
||||
//
|
||||
// var uploadKeyPane = $('<div>').hide().appendTo(addKeyDialogBody);
|
||||
// row = $('<div class="user-settings-row"></div>').appendTo(uploadKeyPane);
|
||||
// $('<label for=""></label>').text('Public key').appendTo(row);
|
||||
// var publicKeyInput = $('<textarea>').appendTo(row).on("change keyup paste",validateForm);
|
||||
// $('<label class="projects-edit-form-sublabel"><small>Paste in public key contents, for example: ~/.ssh/id_rsa.pub</small></label>').appendTo(row).find("small");
|
||||
// row = $('<div class="user-settings-row"></div>').appendTo(uploadKeyPane);
|
||||
// $('<label for=""></label>').text('Private key').appendTo(row);
|
||||
// var privateKeyInput = $('<textarea>').appendTo(row).on("change keyup paste",validateForm);
|
||||
// $('<label class="projects-edit-form-sublabel"><small>Paste in private key contents, for example: ~/.ssh/id_rsa</small></label>').appendTo(row).find("small");
|
||||
|
||||
|
||||
|
||||
|
||||
var hideEditForm = function() {
|
||||
addKeyButton.attr('disabled',false);
|
||||
addKeyDialog.hide();
|
||||
|
||||
keyNameInput.val("");
|
||||
keyNameInputChanged = false;
|
||||
passphraseInput.val("");
|
||||
// localPublicKeyPathInput.val("");
|
||||
// localPrivateKeyPathInput.val("");
|
||||
// publicKeyInput.val("");
|
||||
// privateKeyInput.val("");
|
||||
if (popover) {
|
||||
popover.close();
|
||||
popover = null;
|
||||
}
|
||||
}
|
||||
var formButtons = $('<span class="button-row" style="position: relative; float: right; margin: 10px;"></span>').appendTo(addKeyDialog);
|
||||
$('<button class="editor-button">'+RED._("editor:sidebar.project.userSettings.cancel")+'</button>')
|
||||
.appendTo(formButtons)
|
||||
.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
hideEditForm();
|
||||
});
|
||||
var saveButton = $('<button class="editor-button">'+RED._("editor:sidebar.project.userSettings.generate")+'</button>')
|
||||
.appendTo(formButtons)
|
||||
.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
var spinner = utils.addSpinnerOverlay(addKeyDialog).addClass('projects-dialog-spinner-contain');
|
||||
var payload = {
|
||||
name: keyNameInput.val()
|
||||
};
|
||||
|
||||
// var selectedButton = bg.find(".selected");
|
||||
// if (selectedButton[0] === addLocalButton[0]) {
|
||||
// payload.type = "local";
|
||||
// payload.publicKeyPath = localPublicKeyPathInput.val();
|
||||
// payload.privateKeyPath = localPrivateKeyPathInput.val();
|
||||
// } else if (selectedButton[0] === uploadButton[0]) {
|
||||
// payload.type = "upload";
|
||||
// payload.publicKey = publicKeyInput.val();
|
||||
// payload.privateKey = privateKeyInput.val();
|
||||
// } else if (selectedButton[0] === generateButton[0]) {
|
||||
payload.type = "generate";
|
||||
payload.comment = gitEmailInput.val();
|
||||
payload.password = passphraseInput.val();
|
||||
payload.size = 4096;
|
||||
// }
|
||||
var done = function(err) {
|
||||
spinner.remove();
|
||||
if (err) {
|
||||
return;
|
||||
}
|
||||
hideEditForm();
|
||||
}
|
||||
// console.log(JSON.stringify(payload,null,4));
|
||||
RED.deploy.setDeployInflight(true);
|
||||
utils.sendRequest({
|
||||
url: "settings/user/keys",
|
||||
type: "POST",
|
||||
responses: {
|
||||
0: function(error) {
|
||||
done(error);
|
||||
},
|
||||
200: function(data) {
|
||||
refreshSSHKeyList(payload.name);
|
||||
done();
|
||||
},
|
||||
400: {
|
||||
'unexpected_error': function(error) {
|
||||
console.log(error);
|
||||
done(error);
|
||||
}
|
||||
},
|
||||
}
|
||||
},payload);
|
||||
});
|
||||
|
||||
row = $('<div class="user-settings-row projects-dialog-list"></div>').appendTo(container);
|
||||
var emptyItem = { empty: true };
|
||||
var expandKey = function(container,entry) {
|
||||
var row = $('<div class="projects-dialog-ssh-public-key">',{style:"position:relative"}).appendTo(container);
|
||||
var keyBox = $('<pre>',{style:"min-height: 80px"}).appendTo(row);
|
||||
var spinner = utils.addSpinnerOverlay(keyBox).addClass('projects-dialog-spinner-contain');
|
||||
var options = {
|
||||
url: 'settings/user/keys/'+entry.name,
|
||||
type: "GET",
|
||||
responses: {
|
||||
200: function(data) {
|
||||
keyBox.text(data.publickey);
|
||||
spinner.remove();
|
||||
},
|
||||
400: {
|
||||
'unexpected_error': function(error) {
|
||||
console.log(error);
|
||||
spinner.remove();
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
utils.sendRequest(options);
|
||||
|
||||
var formButtons = $('<span class="button-row" style="position: relative; float: right; margin: 10px;"></span>').appendTo(row);
|
||||
$('<button class="editor-button editor-button-small">'+RED._("editor:sidebar.project.userSettings.copyPublicKey")+'</button>')
|
||||
.appendTo(formButtons)
|
||||
.click(function(evt) {
|
||||
try {
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
document.getSelection().selectAllChildren(keyBox[0]);
|
||||
var ret = document.execCommand('copy');
|
||||
document.getSelection().empty();
|
||||
} catch(err) {
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
return row;
|
||||
}
|
||||
var keyList = $('<ol class="projects-dialog-ssh-key-list">').appendTo(row).editableList({
|
||||
height: 'auto',
|
||||
addButton: false,
|
||||
scrollOnAdd: false,
|
||||
addItem: function(row,index,entry) {
|
||||
var container = $('<div class="projects-dialog-list-entry">').appendTo(row);
|
||||
if (entry.empty) {
|
||||
container.addClass('red-ui-search-empty');
|
||||
container.text(RED._("editor:sidebar.project.userSettings.noSshKeys"));
|
||||
return;
|
||||
}
|
||||
var topRow = $('<div class="projects-dialog-ssh-key-header">').appendTo(container);
|
||||
$('<span class="entry-icon"><i class="fa fa-key"></i></span>').appendTo(topRow);
|
||||
$('<span class="entry-name">').text(entry.name).appendTo(topRow);
|
||||
var tools = $('<span class="button-row entry-tools">').appendTo(topRow);
|
||||
var expandedRow;
|
||||
topRow.click(function(e) {
|
||||
if (expandedRow) {
|
||||
expandedRow.slideUp(200,function() {
|
||||
expandedRow.remove();
|
||||
expandedRow = null;
|
||||
})
|
||||
} else {
|
||||
expandedRow = expandKey(container,entry);
|
||||
}
|
||||
})
|
||||
if (!entry.system) {
|
||||
$('<button class="editor-button editor-button-small"><i class="fa fa-trash"></i></button>')
|
||||
.appendTo(tools)
|
||||
.click(function(e) {
|
||||
e.stopPropagation();
|
||||
var spinner = utils.addSpinnerOverlay(row).addClass('projects-dialog-spinner-contain');
|
||||
var notification = RED.notify(RED._("editor:sidebar.project.userSettings.deleteConfirm", {name:entry.name}), {
|
||||
type: 'warning',
|
||||
modal: true,
|
||||
fixed: true,
|
||||
buttons: [
|
||||
{
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
spinner.remove();
|
||||
notification.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._("editor:sidebar.project.userSettings.delete"),
|
||||
click: function() {
|
||||
notification.close();
|
||||
var url = "settings/user/keys/"+entry.name;
|
||||
var options = {
|
||||
url: url,
|
||||
type: "DELETE",
|
||||
responses: {
|
||||
200: function(data) {
|
||||
row.fadeOut(200,function() {
|
||||
keyList.editableList('removeItem',entry);
|
||||
setTimeout(spinner.remove, 100);
|
||||
if (keyList.editableList('length') === 0) {
|
||||
keyList.editableList('addItem',emptyItem);
|
||||
}
|
||||
});
|
||||
},
|
||||
400: {
|
||||
'unexpected_error': function(error) {
|
||||
console.log(error);
|
||||
spinner.remove();
|
||||
}
|
||||
},
|
||||
}
|
||||
}
|
||||
utils.sendRequest(options);
|
||||
}
|
||||
}
|
||||
]
|
||||
});
|
||||
});
|
||||
}
|
||||
if (entry.expand) {
|
||||
expandedRow = expandKey(container,entry);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
var refreshSSHKeyList = function(justAdded) {
|
||||
$.getJSON("settings/user/keys",function(result) {
|
||||
if (result.keys) {
|
||||
result.keys.sort(function(A,B) {
|
||||
return A.name.localeCompare(B.name);
|
||||
});
|
||||
keyList.editableList('empty');
|
||||
result.keys.forEach(function(key) {
|
||||
if (key.name === justAdded) {
|
||||
key.expand = true;
|
||||
}
|
||||
keyList.editableList('addItem',key);
|
||||
});
|
||||
if (keyList.editableList('length') === 0) {
|
||||
keyList.editableList('addItem',emptyItem);
|
||||
}
|
||||
|
||||
}
|
||||
})
|
||||
}
|
||||
refreshSSHKeyList();
|
||||
|
||||
}
|
||||
|
||||
function createSettingsPane(activeProject) {
|
||||
var pane = $('<div id="user-settings-tab-gitconfig" class="project-settings-tab-pane node-help"></div>');
|
||||
createGitUserSection(pane);
|
||||
createSSHKeySection(pane);
|
||||
return pane;
|
||||
}
|
||||
|
||||
var utils;
|
||||
function init(_utils) {
|
||||
utils = _utils;
|
||||
RED.userSettings.add({
|
||||
id:'gitconfig',
|
||||
title: RED._("editor:sidebar.project.userSettings.gitConfig"),
|
||||
get: createSettingsPane,
|
||||
close: function() {
|
||||
var currentGitSettings = RED.settings.get('git') || {};
|
||||
currentGitSettings.user = currentGitSettings.user || {};
|
||||
currentGitSettings.user.name = gitUsernameInput.val();
|
||||
currentGitSettings.user.email = gitEmailInput.val();
|
||||
RED.settings.set('git', currentGitSettings);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
};
|
||||
})();
|
||||
2377
editor/js/ui/projects/projects.js
Normal file
1374
editor/js/ui/projects/tab-versionControl.js
Normal file
298
editor/js/ui/search.js
Normal file
@@ -0,0 +1,298 @@
|
||||
/**
|
||||
* 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.search = (function() {
|
||||
|
||||
var disabled = false;
|
||||
var dialog = null;
|
||||
var searchInput;
|
||||
var searchResults;
|
||||
var selected = -1;
|
||||
var visible = false;
|
||||
|
||||
var index = {};
|
||||
var keys = [];
|
||||
var results = [];
|
||||
|
||||
|
||||
function indexProperty(node,label,property) {
|
||||
if (typeof property === 'string' || typeof property === 'number') {
|
||||
property = (""+property).toLowerCase();
|
||||
index[property] = index[property] || {};
|
||||
index[property][node.id] = {node:node,label:label};
|
||||
} else if (Array.isArray(property)) {
|
||||
property.forEach(function(prop) {
|
||||
indexProperty(node,label,prop);
|
||||
})
|
||||
} else if (typeof property === 'object') {
|
||||
for (var prop in property) {
|
||||
if (property.hasOwnProperty(prop)) {
|
||||
indexProperty(node,label,property[prop])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
function indexNode(n) {
|
||||
var l = RED.utils.getNodeLabel(n);
|
||||
if (l) {
|
||||
l = (""+l).toLowerCase();
|
||||
index[l] = index[l] || {};
|
||||
index[l][n.id] = {node:n,label:l}
|
||||
}
|
||||
l = l||n.label||n.name||n.id||"";
|
||||
|
||||
|
||||
var properties = ['id','type','name','label','info'];
|
||||
if (n._def && n._def.defaults) {
|
||||
properties = properties.concat(Object.keys(n._def.defaults));
|
||||
}
|
||||
for (var i=0;i<properties.length;i++) {
|
||||
if (n.hasOwnProperty(properties[i])) {
|
||||
indexProperty(n, l, n[properties[i]]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function indexWorkspace() {
|
||||
index = {};
|
||||
RED.nodes.eachWorkspace(indexNode);
|
||||
RED.nodes.eachSubflow(indexNode);
|
||||
RED.nodes.eachConfig(indexNode);
|
||||
RED.nodes.eachNode(indexNode);
|
||||
keys = Object.keys(index);
|
||||
keys.sort();
|
||||
keys.forEach(function(key) {
|
||||
index[key] = Object.keys(index[key]).map(function(id) {
|
||||
return index[key][id];
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
function search(val) {
|
||||
searchResults.editableList('empty');
|
||||
selected = -1;
|
||||
results = [];
|
||||
if (val.length > 0) {
|
||||
val = val.toLowerCase();
|
||||
var i;
|
||||
var j;
|
||||
var list = [];
|
||||
var nodes = {};
|
||||
for (i=0;i<keys.length;i++) {
|
||||
var key = keys[i];
|
||||
var kpos = keys[i].indexOf(val);
|
||||
if (kpos > -1) {
|
||||
for (j=0;j<index[key].length;j++) {
|
||||
var node = index[key][j];
|
||||
nodes[node.node.id] = nodes[node.node.id] = node;
|
||||
nodes[node.node.id].index = Math.min(nodes[node.node.id].index||Infinity,kpos);
|
||||
}
|
||||
}
|
||||
}
|
||||
list = Object.keys(nodes);
|
||||
list.sort(function(A,B) {
|
||||
return nodes[A].index - nodes[B].index;
|
||||
});
|
||||
|
||||
for (i=0;i<list.length;i++) {
|
||||
results.push(nodes[list[i]]);
|
||||
}
|
||||
if (results.length > 0) {
|
||||
for (i=0;i<Math.min(results.length,25);i++) {
|
||||
searchResults.editableList('addItem',results[i])
|
||||
}
|
||||
} else {
|
||||
searchResults.editableList('addItem',{});
|
||||
}
|
||||
}
|
||||
}
|
||||
function ensureSelectedIsVisible() {
|
||||
var selectedEntry = searchResults.find("li.selected");
|
||||
if (selectedEntry.length === 1) {
|
||||
var scrollWindow = searchResults.parent();
|
||||
var scrollHeight = scrollWindow.height();
|
||||
var scrollOffset = scrollWindow.scrollTop();
|
||||
var y = selectedEntry.position().top;
|
||||
var h = selectedEntry.height();
|
||||
if (y+h > scrollHeight) {
|
||||
scrollWindow.animate({scrollTop: '-='+(scrollHeight-(y+h)-10)},50);
|
||||
} else if (y<0) {
|
||||
scrollWindow.animate({scrollTop: '+='+(y-10)},50);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createDialog() {
|
||||
dialog = $("<div>",{id:"red-ui-search",class:"red-ui-search"}).appendTo("#main-container");
|
||||
var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(dialog);
|
||||
searchInput = $('<input type="text" data-i18n="[placeholder]menu.label.searchInput">').appendTo(searchDiv).searchBox({
|
||||
delay: 200,
|
||||
change: function() {
|
||||
search($(this).val());
|
||||
}
|
||||
});
|
||||
searchInput.on('keydown',function(evt) {
|
||||
var children;
|
||||
if (results.length > 0) {
|
||||
if (evt.keyCode === 40) {
|
||||
// Down
|
||||
children = searchResults.children();
|
||||
if (selected < children.length-1) {
|
||||
if (selected > -1) {
|
||||
$(children[selected]).removeClass('selected');
|
||||
}
|
||||
selected++;
|
||||
}
|
||||
$(children[selected]).addClass('selected');
|
||||
ensureSelectedIsVisible();
|
||||
evt.preventDefault();
|
||||
} else if (evt.keyCode === 38) {
|
||||
// Up
|
||||
children = searchResults.children();
|
||||
if (selected > 0) {
|
||||
if (selected < children.length) {
|
||||
$(children[selected]).removeClass('selected');
|
||||
}
|
||||
selected--;
|
||||
}
|
||||
$(children[selected]).addClass('selected');
|
||||
ensureSelectedIsVisible();
|
||||
evt.preventDefault();
|
||||
} else if (evt.keyCode === 13) {
|
||||
// Enter
|
||||
if (results.length > 0) {
|
||||
reveal(results[Math.max(0,selected)].node);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
searchInput.i18n();
|
||||
|
||||
var searchResultsDiv = $("<div>",{class:"red-ui-search-results-container"}).appendTo(dialog);
|
||||
searchResults = $('<ol>',{id:"search-result-list", style:"position: absolute;top: 5px;bottom: 5px;left: 5px;right: 5px;"}).appendTo(searchResultsDiv).editableList({
|
||||
addButton: false,
|
||||
addItem: function(container,i,object) {
|
||||
var node = object.node;
|
||||
if (node === undefined) {
|
||||
$('<div>',{class:"red-ui-search-empty"}).text(RED._('search.empty')).appendTo(container);
|
||||
|
||||
} else {
|
||||
var def = node._def;
|
||||
var div = $('<a>',{href:'#',class:"red-ui-search-result"}).appendTo(container);
|
||||
|
||||
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(div);
|
||||
var colour = RED.utils.getNodeColor(node.type,def);
|
||||
var icon_url = RED.utils.getNodeIcon(def,node);
|
||||
if (node.type === 'tab') {
|
||||
colour = "#C0DEED";
|
||||
}
|
||||
nodeDiv.css('backgroundColor',colour);
|
||||
|
||||
var iconContainer = $('<div/>',{class:"palette_icon_container"}).appendTo(nodeDiv);
|
||||
$('<div/>',{class:"palette_icon",style:"background-image: url("+icon_url+")"}).appendTo(iconContainer);
|
||||
|
||||
var contentDiv = $('<div>',{class:"red-ui-search-result-description"}).appendTo(div);
|
||||
if (node.z) {
|
||||
var workspace = RED.nodes.workspace(node.z);
|
||||
if (!workspace) {
|
||||
workspace = RED.nodes.subflow(node.z);
|
||||
workspace = "subflow:"+workspace.name;
|
||||
} else {
|
||||
workspace = "flow:"+workspace.label;
|
||||
}
|
||||
$('<div>',{class:"red-ui-search-result-node-flow"}).text(workspace).appendTo(contentDiv);
|
||||
}
|
||||
|
||||
$('<div>',{class:"red-ui-search-result-node-label"}).text(object.label || node.id).appendTo(contentDiv);
|
||||
$('<div>',{class:"red-ui-search-result-node-type"}).text(node.type).appendTo(contentDiv);
|
||||
$('<div>',{class:"red-ui-search-result-node-id"}).text(node.id).appendTo(contentDiv);
|
||||
|
||||
div.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
reveal(node);
|
||||
});
|
||||
}
|
||||
},
|
||||
scrollOnAdd: false
|
||||
});
|
||||
|
||||
}
|
||||
function reveal(node) {
|
||||
hide();
|
||||
RED.view.reveal(node.id);
|
||||
}
|
||||
|
||||
function show() {
|
||||
if (disabled) {
|
||||
return;
|
||||
}
|
||||
if (!visible) {
|
||||
RED.keyboard.add("*","escape",function(){hide()});
|
||||
$("#header-shade").show();
|
||||
$("#editor-shade").show();
|
||||
$("#palette-shade").show();
|
||||
$("#sidebar-shade").show();
|
||||
$("#sidebar-separator").hide();
|
||||
indexWorkspace();
|
||||
if (dialog === null) {
|
||||
createDialog();
|
||||
}
|
||||
dialog.slideDown(300);
|
||||
RED.events.emit("search:open");
|
||||
visible = true;
|
||||
}
|
||||
searchInput.focus();
|
||||
}
|
||||
function hide() {
|
||||
if (visible) {
|
||||
RED.keyboard.remove("escape");
|
||||
visible = false;
|
||||
$("#header-shade").hide();
|
||||
$("#editor-shade").hide();
|
||||
$("#palette-shade").hide();
|
||||
$("#sidebar-shade").hide();
|
||||
$("#sidebar-separator").show();
|
||||
if (dialog !== null) {
|
||||
dialog.slideUp(200,function() {
|
||||
searchInput.searchBox('value','');
|
||||
});
|
||||
}
|
||||
RED.events.emit("search:close");
|
||||
}
|
||||
}
|
||||
|
||||
function init() {
|
||||
RED.actions.add("core:search",show);
|
||||
|
||||
RED.events.on("editor:open",function() { disabled = true; });
|
||||
RED.events.on("editor:close",function() { disabled = false; });
|
||||
RED.events.on("type-search:open",function() { disabled = true; });
|
||||
RED.events.on("type-search:close",function() { disabled = false; });
|
||||
|
||||
|
||||
|
||||
$("#header-shade").on('mousedown',hide);
|
||||
$("#editor-shade").on('mousedown',hide);
|
||||
$("#palette-shade").on('mousedown',hide);
|
||||
$("#sidebar-shade").on('mousedown',hide);
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
show: show,
|
||||
hide: hide
|
||||
};
|
||||
|
||||
})();
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013, 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -20,18 +20,24 @@ RED.sidebar = (function() {
|
||||
id:"sidebar-tabs",
|
||||
onchange:function(tab) {
|
||||
$("#sidebar-content").children().hide();
|
||||
$("#sidebar-footer").children().hide();
|
||||
if (tab.onchange) {
|
||||
tab.onchange.call(tab);
|
||||
}
|
||||
$(tab.content).show();
|
||||
$(tab.wrapper).show();
|
||||
if (tab.toolbar) {
|
||||
$(tab.toolbar).show();
|
||||
}
|
||||
},
|
||||
onremove: function(tab) {
|
||||
$(tab.content).hide();
|
||||
$(tab.wrapper).hide();
|
||||
if (tab.onremove) {
|
||||
tab.onremove.call(tab);
|
||||
}
|
||||
},
|
||||
minimumActiveTabWidth: 110
|
||||
// minimumActiveTabWidth: 70,
|
||||
collapsible: true
|
||||
// scrollable: true
|
||||
});
|
||||
|
||||
var knownTabs = {
|
||||
@@ -54,14 +60,24 @@ RED.sidebar = (function() {
|
||||
options = title;
|
||||
}
|
||||
|
||||
delete options.closeable;
|
||||
|
||||
options.wrapper = $('<div>',{style:"height:100%"}).appendTo("#sidebar-content")
|
||||
options.wrapper.append(options.content);
|
||||
options.wrapper.hide();
|
||||
|
||||
$("#sidebar-content").append(options.content);
|
||||
$(options.content).hide();
|
||||
if (!options.enableOnEdit) {
|
||||
options.shade = $('<div>',{class:"sidebar-shade hide"}).appendTo(options.wrapper);
|
||||
}
|
||||
|
||||
if (options.toolbar) {
|
||||
$("#sidebar-footer").append(options.toolbar);
|
||||
$(options.toolbar).hide();
|
||||
}
|
||||
var id = options.id;
|
||||
|
||||
RED.menu.addItem("menu-item-sidebar-menu",{
|
||||
id:"menu-item-sidebar-menu-"+options.id,
|
||||
RED.menu.addItem("menu-item-view-menu",{
|
||||
id:"menu-item-view-menu-"+options.id,
|
||||
label:options.name,
|
||||
onselect:function() {
|
||||
showSidebar(options.id);
|
||||
@@ -69,6 +85,8 @@ RED.sidebar = (function() {
|
||||
group: "sidebar-tabs"
|
||||
});
|
||||
|
||||
options.iconClass = options.iconClass || "fa fa-square-o"
|
||||
|
||||
knownTabs[options.id] = options;
|
||||
|
||||
if (options.visible !== false) {
|
||||
@@ -78,9 +96,12 @@ RED.sidebar = (function() {
|
||||
|
||||
function removeTab(id) {
|
||||
sidebar_tabs.removeTab(id);
|
||||
$(knownTabs[id].content).remove();
|
||||
$(knownTabs[id].wrapper).remove();
|
||||
if (knownTabs[id].footer) {
|
||||
knownTabs[id].footer.remove();
|
||||
}
|
||||
delete knownTabs[id];
|
||||
RED.menu.removeItem("menu-item-sidebar-menu-"+id);
|
||||
RED.menu.removeItem("menu-item-view-menu-"+id);
|
||||
}
|
||||
|
||||
var sidebarSeparator = {};
|
||||
@@ -94,12 +115,12 @@ RED.sidebar = (function() {
|
||||
sidebarSeparator.chartWidth = $("#workspace").width();
|
||||
sidebarSeparator.chartRight = winWidth-$("#workspace").width()-$("#workspace").offset().left-2;
|
||||
|
||||
|
||||
if (!RED.menu.isSelected("menu-item-sidebar")) {
|
||||
sidebarSeparator.opening = true;
|
||||
var newChartRight = 7;
|
||||
$("#sidebar").addClass("closing");
|
||||
$("#workspace").css("right",newChartRight);
|
||||
$("#editor-stack").css("right",newChartRight+1);
|
||||
$("#sidebar").width(0);
|
||||
RED.menu.setSelected("menu-item-sidebar",true);
|
||||
RED.events.emit("sidebar:resize");
|
||||
@@ -138,6 +159,7 @@ RED.sidebar = (function() {
|
||||
|
||||
var newChartRight = sidebarSeparator.chartRight-d;
|
||||
$("#workspace").css("right",newChartRight);
|
||||
$("#editor-stack").css("right",newChartRight+1);
|
||||
$("#sidebar").width(newSidebarWidth);
|
||||
|
||||
sidebar_tabs.resize();
|
||||
@@ -150,6 +172,7 @@ RED.sidebar = (function() {
|
||||
if ($("#sidebar").width() < 180) {
|
||||
$("#sidebar").width(180);
|
||||
$("#workspace").css("right",187);
|
||||
$("#editor-stack").css("right",188);
|
||||
}
|
||||
}
|
||||
$("#sidebar-separator").css("left","auto");
|
||||
@@ -185,12 +208,19 @@ RED.sidebar = (function() {
|
||||
}
|
||||
|
||||
function init () {
|
||||
RED.keyboard.add(/* SPACE */ 32,{ctrl:true},function(){RED.menu.setSelected("menu-item-sidebar",!RED.menu.isSelected("menu-item-sidebar"));d3.event.preventDefault();});
|
||||
RED.actions.add("core:toggle-sidebar",function(state){
|
||||
if (state === undefined) {
|
||||
RED.menu.toggleSelected("menu-item-sidebar");
|
||||
} else {
|
||||
toggleSidebar(state);
|
||||
}
|
||||
});
|
||||
showSidebar();
|
||||
RED.sidebar.info.init();
|
||||
RED.sidebar.config.init();
|
||||
RED.sidebar.context.init();
|
||||
// hide info bar at start if screen rather narrow...
|
||||
if ($(window).width() < 600) { toggleSidebar(); }
|
||||
if ($(window).width() < 600) { RED.menu.setSelected("menu-item-sidebar",false); }
|
||||
}
|
||||
|
||||
return {
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013 IBM Corp.
|
||||
* 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.
|
||||
@@ -22,5 +22,7 @@ RED.state = {
|
||||
EDITING: 5,
|
||||
EXPORT: 6,
|
||||
IMPORT: 7,
|
||||
IMPORT_DRAGGING: 8
|
||||
IMPORT_DRAGGING: 8,
|
||||
QUICK_JOINING: 9,
|
||||
PANNING: 10
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -139,7 +139,7 @@ RED.subflow = (function() {
|
||||
RED.view.select();
|
||||
RED.nodes.dirty(true);
|
||||
RED.view.redraw();
|
||||
$("#workspace-subflow-output .spinner-value").html(subflow.out.length);
|
||||
$("#workspace-subflow-output .spinner-value").text(subflow.out.length);
|
||||
}
|
||||
|
||||
function removeSubflowOutput(removedSubflowOutputs) {
|
||||
@@ -216,7 +216,7 @@ RED.subflow = (function() {
|
||||
$("#workspace-subflow-input-add").toggleClass("active", activeSubflow.in.length !== 0);
|
||||
$("#workspace-subflow-input-remove").toggleClass("active",activeSubflow.in.length === 0);
|
||||
|
||||
$("#workspace-subflow-output .spinner-value").html(activeSubflow.out.length);
|
||||
$("#workspace-subflow-output .spinner-value").text(activeSubflow.out.length);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -306,50 +306,13 @@ RED.subflow = (function() {
|
||||
|
||||
$("#workspace-subflow-delete").click(function(event) {
|
||||
event.preventDefault();
|
||||
var removedNodes = [];
|
||||
var removedLinks = [];
|
||||
var startDirty = RED.nodes.dirty();
|
||||
var historyEvent = removeSubflow(RED.workspaces.active());
|
||||
historyEvent.t = 'delete';
|
||||
historyEvent.dirty = startDirty;
|
||||
|
||||
var activeSubflow = getSubflow();
|
||||
RED.history.push(historyEvent);
|
||||
|
||||
RED.nodes.eachNode(function(n) {
|
||||
if (n.type == "subflow:"+activeSubflow.id) {
|
||||
removedNodes.push(n);
|
||||
}
|
||||
if (n.z == activeSubflow.id) {
|
||||
removedNodes.push(n);
|
||||
}
|
||||
});
|
||||
RED.nodes.eachConfig(function(n) {
|
||||
if (n.z == activeSubflow.id) {
|
||||
removedNodes.push(n);
|
||||
}
|
||||
});
|
||||
|
||||
var removedConfigNodes = [];
|
||||
for (var i=0;i<removedNodes.length;i++) {
|
||||
var removedEntities = RED.nodes.remove(removedNodes[i].id);
|
||||
removedLinks = removedLinks.concat(removedEntities.links);
|
||||
removedConfigNodes = removedConfigNodes.concat(removedEntities.nodes);
|
||||
}
|
||||
// TODO: this whole delete logic should be in RED.nodes.removeSubflow..
|
||||
removedNodes = removedNodes.concat(removedConfigNodes);
|
||||
|
||||
RED.nodes.removeSubflow(activeSubflow);
|
||||
|
||||
RED.history.push({
|
||||
t:'delete',
|
||||
nodes:removedNodes,
|
||||
links:removedLinks,
|
||||
subflow: {
|
||||
subflow: activeSubflow
|
||||
},
|
||||
dirty:startDirty
|
||||
});
|
||||
|
||||
RED.workspaces.remove(activeSubflow);
|
||||
RED.nodes.dirty(true);
|
||||
RED.view.redraw();
|
||||
});
|
||||
|
||||
refreshToolbar(activeSubflow);
|
||||
@@ -362,7 +325,48 @@ RED.subflow = (function() {
|
||||
$("#chart").css({"margin-top": "0"});
|
||||
}
|
||||
|
||||
function removeSubflow(id) {
|
||||
var removedNodes = [];
|
||||
var removedLinks = [];
|
||||
|
||||
var activeSubflow = RED.nodes.subflow(id);
|
||||
|
||||
RED.nodes.eachNode(function(n) {
|
||||
if (n.type == "subflow:"+activeSubflow.id) {
|
||||
removedNodes.push(n);
|
||||
}
|
||||
if (n.z == activeSubflow.id) {
|
||||
removedNodes.push(n);
|
||||
}
|
||||
});
|
||||
RED.nodes.eachConfig(function(n) {
|
||||
if (n.z == activeSubflow.id) {
|
||||
removedNodes.push(n);
|
||||
}
|
||||
});
|
||||
|
||||
var removedConfigNodes = [];
|
||||
for (var i=0;i<removedNodes.length;i++) {
|
||||
var removedEntities = RED.nodes.remove(removedNodes[i].id);
|
||||
removedLinks = removedLinks.concat(removedEntities.links);
|
||||
removedConfigNodes = removedConfigNodes.concat(removedEntities.nodes);
|
||||
}
|
||||
// TODO: this whole delete logic should be in RED.nodes.removeSubflow..
|
||||
removedNodes = removedNodes.concat(removedConfigNodes);
|
||||
|
||||
RED.nodes.removeSubflow(activeSubflow);
|
||||
RED.workspaces.remove(activeSubflow);
|
||||
RED.nodes.dirty(true);
|
||||
RED.view.redraw();
|
||||
|
||||
return {
|
||||
nodes:removedNodes,
|
||||
links:removedLinks,
|
||||
subflow: {
|
||||
subflow: activeSubflow
|
||||
}
|
||||
}
|
||||
}
|
||||
function init() {
|
||||
RED.events.on("workspace:change",function(event) {
|
||||
var activeSubflow = RED.nodes.subflow(event.workspace);
|
||||
@@ -380,6 +384,8 @@ RED.subflow = (function() {
|
||||
}
|
||||
});
|
||||
|
||||
RED.actions.add("core:create-subflow",createSubflow);
|
||||
RED.actions.add("core:convert-to-subflow",convertToSubflow);
|
||||
}
|
||||
|
||||
function createSubflow() {
|
||||
@@ -420,7 +426,7 @@ RED.subflow = (function() {
|
||||
RED.notify(RED._("subflow.errors.noNodesSelected"),"error");
|
||||
return;
|
||||
}
|
||||
var i;
|
||||
var i,n;
|
||||
var nodes = {};
|
||||
var new_links = [];
|
||||
var removedLinks = [];
|
||||
@@ -436,7 +442,7 @@ RED.subflow = (function() {
|
||||
selection.nodes[0].y];
|
||||
|
||||
for (i=0;i<selection.nodes.length;i++) {
|
||||
var n = selection.nodes[i];
|
||||
n = selection.nodes[i];
|
||||
nodes[n.id] = {n:n,outputs:{}};
|
||||
boundingBox = [
|
||||
Math.min(boundingBox[0],n.x),
|
||||
@@ -573,7 +579,23 @@ RED.subflow = (function() {
|
||||
}
|
||||
|
||||
for (i=0;i<selection.nodes.length;i++) {
|
||||
selection.nodes[i].z = subflow.id;
|
||||
n = selection.nodes[i];
|
||||
if (/^link /.test(n.type)) {
|
||||
n.links = n.links.filter(function(id) {
|
||||
var isLocalLink = nodes.hasOwnProperty(id);
|
||||
if (!isLocalLink) {
|
||||
var otherNode = RED.nodes.node(id);
|
||||
if (otherNode && otherNode.links) {
|
||||
var i = otherNode.links.indexOf(n.id);
|
||||
if (i > -1) {
|
||||
otherNode.links.splice(i,1);
|
||||
}
|
||||
}
|
||||
}
|
||||
return isLocalLink;
|
||||
});
|
||||
}
|
||||
n.z = subflow.id;
|
||||
}
|
||||
|
||||
RED.history.push({
|
||||
@@ -589,7 +611,7 @@ RED.subflow = (function() {
|
||||
|
||||
dirty:RED.nodes.dirty()
|
||||
});
|
||||
|
||||
RED.view.select(null);
|
||||
RED.editor.validateNode(subflow);
|
||||
RED.nodes.dirty(true);
|
||||
RED.view.redraw(true);
|
||||
@@ -601,6 +623,7 @@ RED.subflow = (function() {
|
||||
init: init,
|
||||
createSubflow: createSubflow,
|
||||
convertToSubflow: convertToSubflow,
|
||||
removeSubflow: removeSubflow,
|
||||
refresh: refresh,
|
||||
removeInput: removeSubflowInput,
|
||||
removeOutput: removeSubflowOutput
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013, 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -17,47 +17,133 @@ RED.sidebar.config = (function() {
|
||||
|
||||
|
||||
var content = document.createElement("div");
|
||||
content.className = "sidebar-node-config"
|
||||
content.className = "sidebar-node-config";
|
||||
|
||||
$('<div class="palette-category">'+
|
||||
'<div class="workspace-config-node-tray-header palette-header"><i class="fa fa-angle-down expanded"></i><span data-i18n="sidebar.config.local"></span></div>'+
|
||||
'<ul id="workspace-config-node-tray-locals" class="palette-content config-node-list"></ul>'+
|
||||
'</div>'+
|
||||
'<div class="palette-category">'+
|
||||
'<div class="workspace-config-node-tray-header palette-header"><i class="fa fa-angle-down expanded"></i><span data-i18n="sidebar.config.global"></span></div>'+
|
||||
'<ul id="workspace-config-node-tray-globals" class="palette-content config-node-list"></ul>'+
|
||||
'</div>').appendTo(content);
|
||||
$('<div class="button-group sidebar-header">'+
|
||||
'<a class="sidebar-header-button-toggle selected" id="workspace-config-node-filter-all" href="#"><span data-i18n="sidebar.config.filterAll"></span></a>'+
|
||||
'<a class="sidebar-header-button-toggle" id="workspace-config-node-filter-unused" href="#"><span data-i18n="sidebar.config.filterUnused"></span></a> '+
|
||||
'</div>'
|
||||
).appendTo(content);
|
||||
|
||||
|
||||
var toolbar = $('<div>'+
|
||||
'<a class="sidebar-footer-button" id="workspace-config-node-collapse-all" href="#"><i class="fa fa-angle-double-up"></i></a> '+
|
||||
'<a class="sidebar-footer-button" id="workspace-config-node-expand-all" href="#"><i class="fa fa-angle-double-down"></i></a>'+
|
||||
'</div>');
|
||||
|
||||
var globalCategories = $("<div>").appendTo(content);
|
||||
var flowCategories = $("<div>").appendTo(content);
|
||||
var subflowCategories = $("<div>").appendTo(content);
|
||||
|
||||
var showUnusedOnly = false;
|
||||
|
||||
var categories = {};
|
||||
|
||||
function getOrCreateCategory(name,parent,label) {
|
||||
name = name.replace(/\./i,"-");
|
||||
if (!categories[name]) {
|
||||
var container = $('<div class="palette-category workspace-config-node-category" id="workspace-config-node-category-'+name+'"></div>').appendTo(parent);
|
||||
var header = $('<div class="workspace-config-node-tray-header palette-header"><i class="fa fa-angle-down expanded"></i></div>').appendTo(container);
|
||||
if (label) {
|
||||
$('<span class="config-node-label"/>').text(label).appendTo(header);
|
||||
} else {
|
||||
$('<span class="config-node-label" data-i18n="sidebar.config.'+name+'">').appendTo(header);
|
||||
}
|
||||
$('<span class="config-node-filter-info"></span>').appendTo(header);
|
||||
category = $('<ul class="palette-content config-node-list"></ul>').appendTo(container);
|
||||
container.i18n();
|
||||
var icon = header.find("i");
|
||||
var result = {
|
||||
label: label,
|
||||
list: category,
|
||||
size: function() {
|
||||
return result.list.find("li:not(.config_node_none)").length
|
||||
},
|
||||
open: function(snap) {
|
||||
if (!icon.hasClass("expanded")) {
|
||||
icon.addClass("expanded");
|
||||
if (snap) {
|
||||
result.list.show();
|
||||
} else {
|
||||
result.list.slideDown();
|
||||
}
|
||||
}
|
||||
},
|
||||
close: function(snap) {
|
||||
if (icon.hasClass("expanded")) {
|
||||
icon.removeClass("expanded");
|
||||
if (snap) {
|
||||
result.list.hide();
|
||||
} else {
|
||||
result.list.slideUp();
|
||||
}
|
||||
}
|
||||
},
|
||||
isOpen: function() {
|
||||
return icon.hasClass("expanded");
|
||||
}
|
||||
};
|
||||
|
||||
header.on('click', function(e) {
|
||||
if (result.isOpen()) {
|
||||
result.close();
|
||||
} else {
|
||||
result.open();
|
||||
}
|
||||
});
|
||||
categories[name] = result;
|
||||
} else {
|
||||
if (categories[name].label !== label) {
|
||||
categories[name].list.parent().find('.config-node-label').text(label);
|
||||
categories[name].label = label;
|
||||
}
|
||||
}
|
||||
return categories[name];
|
||||
}
|
||||
|
||||
function createConfigNodeList(id,nodes) {
|
||||
var category = getOrCreateCategory(id.replace(/\./i,"-"))
|
||||
var list = category.list;
|
||||
|
||||
function createConfigNodeList(nodes,list) {
|
||||
nodes.sort(function(A,B) {
|
||||
if (A.type < B.type) { return -1;}
|
||||
if (A.type > B.type) { return 1;}
|
||||
return 0;
|
||||
});
|
||||
if (showUnusedOnly) {
|
||||
var hiddenCount = nodes.length;
|
||||
nodes = nodes.filter(function(n) {
|
||||
return n._def.hasUsers!==false && n.users.length === 0;
|
||||
})
|
||||
hiddenCount = hiddenCount - nodes.length;
|
||||
if (hiddenCount > 0) {
|
||||
list.parent().find('.config-node-filter-info').text(RED._('sidebar.config.filtered',{count:hiddenCount})).show();
|
||||
} else {
|
||||
list.parent().find('.config-node-filter-info').hide();
|
||||
}
|
||||
} else {
|
||||
list.parent().find('.config-node-filter-info').hide();
|
||||
}
|
||||
list.empty();
|
||||
if (nodes.length === 0) {
|
||||
$('<li class="config_node_none" data-i18n="sidebar.config.none">NONE</li>').i18n().appendTo(list);
|
||||
category.close(true);
|
||||
} else {
|
||||
var currentType = "";
|
||||
nodes.forEach(function(node) {
|
||||
var label = "";
|
||||
if (typeof node._def.label == "function") {
|
||||
label = node._def.label.call(node);
|
||||
} else {
|
||||
label = node._def.label;
|
||||
}
|
||||
label = label || node.id;
|
||||
var label = RED.utils.getNodeLabel(node,node.id);
|
||||
if (node.type != currentType) {
|
||||
$('<li class="config_node_type">'+node.type+'</li>').appendTo(list);
|
||||
currentType = node.type;
|
||||
}
|
||||
|
||||
var entry = $('<li class="palette_node config_node"></li>').appendTo(list);
|
||||
var entry = $('<li class="palette_node config_node palette_node_id_'+node.id.replace(/\./g,"-")+'"></li>').appendTo(list);
|
||||
$('<div class="palette_label"></div>').text(label).appendTo(entry);
|
||||
|
||||
var iconContainer = $('<div/>',{class:"palette_icon_container palette_icon_container_right"}).text(node.users.length).appendTo(entry);
|
||||
if (node.users.length === 0) {
|
||||
entry.addClass("config_node_unused");
|
||||
if (node._def.hasUsers !== false) {
|
||||
var iconContainer = $('<div/>',{class:"palette_icon_container palette_icon_container_right"}).text(node.users.length).appendTo(entry);
|
||||
if (node.users.length === 0) {
|
||||
entry.addClass("config_node_unused");
|
||||
}
|
||||
}
|
||||
entry.on('click',function(e) {
|
||||
RED.sidebar.info.refresh(node);
|
||||
@@ -86,23 +172,46 @@ RED.sidebar.config = (function() {
|
||||
RED.view.redraw();
|
||||
});
|
||||
});
|
||||
category.open(true);
|
||||
}
|
||||
}
|
||||
|
||||
function refreshConfigNodeList() {
|
||||
var validList = {"global":true};
|
||||
|
||||
var localConfigNodes = [];
|
||||
getOrCreateCategory("global",globalCategories);
|
||||
|
||||
RED.nodes.eachWorkspace(function(ws) {
|
||||
validList[ws.id.replace(/\./g,"-")] = true;
|
||||
getOrCreateCategory(ws.id,flowCategories,ws.label);
|
||||
})
|
||||
RED.nodes.eachSubflow(function(sf) {
|
||||
validList[sf.id.replace(/\./g,"-")] = true;
|
||||
getOrCreateCategory(sf.id,subflowCategories,sf.name);
|
||||
})
|
||||
$(".workspace-config-node-category").each(function() {
|
||||
var id = $(this).attr('id').substring("workspace-config-node-category-".length);
|
||||
if (!validList[id]) {
|
||||
$(this).remove();
|
||||
delete categories[id];
|
||||
}
|
||||
})
|
||||
var globalConfigNodes = [];
|
||||
|
||||
var configList = {};
|
||||
RED.nodes.eachConfig(function(cn) {
|
||||
if (cn.z == RED.workspaces.active()) {
|
||||
localConfigNodes.push(cn);
|
||||
if (cn.z) {//} == RED.workspaces.active()) {
|
||||
configList[cn.z.replace(/\./g,"-")] = configList[cn.z.replace(/\./g,"-")]||[];
|
||||
configList[cn.z.replace(/\./g,"-")].push(cn);
|
||||
} else if (!cn.z) {
|
||||
globalConfigNodes.push(cn);
|
||||
}
|
||||
});
|
||||
createConfigNodeList(localConfigNodes,$("#workspace-config-node-tray-locals"));
|
||||
createConfigNodeList(globalConfigNodes,$("#workspace-config-node-tray-globals"));
|
||||
for (var id in validList) {
|
||||
if (validList.hasOwnProperty(id)) {
|
||||
createConfigNodeList(id,configList[id]||[]);
|
||||
}
|
||||
}
|
||||
createConfigNodeList('global',globalConfigNodes);
|
||||
}
|
||||
|
||||
function init() {
|
||||
@@ -111,26 +220,90 @@ RED.sidebar.config = (function() {
|
||||
label: RED._("sidebar.config.label"),
|
||||
name: RED._("sidebar.config.name"),
|
||||
content: content,
|
||||
closeable: true,
|
||||
visible: false,
|
||||
toolbar: toolbar,
|
||||
iconClass: "fa fa-cog",
|
||||
onchange: function() { refreshConfigNodeList(); }
|
||||
});
|
||||
RED.actions.add("core:show-config-tab",function() {RED.sidebar.show('config')});
|
||||
|
||||
$(".workspace-config-node-tray-header").on('click', function(e) {
|
||||
var icon = $(this).find("i");
|
||||
if (icon.hasClass("expanded")) {
|
||||
icon.removeClass("expanded");
|
||||
$(this).next().slideUp();
|
||||
} else {
|
||||
icon.addClass("expanded");
|
||||
$(this).next().slideDown();
|
||||
$("#workspace-config-node-collapse-all").on("click", function(e) {
|
||||
e.preventDefault();
|
||||
for (var cat in categories) {
|
||||
if (categories.hasOwnProperty(cat)) {
|
||||
categories[cat].close();
|
||||
}
|
||||
}
|
||||
});
|
||||
$("#workspace-config-node-expand-all").on("click", function(e) {
|
||||
e.preventDefault();
|
||||
for (var cat in categories) {
|
||||
if (categories.hasOwnProperty(cat)) {
|
||||
if (categories[cat].size() > 0) {
|
||||
categories[cat].open();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
$('#workspace-config-node-filter-all').on("click",function(e) {
|
||||
e.preventDefault();
|
||||
if (showUnusedOnly) {
|
||||
$(this).addClass('selected');
|
||||
$('#workspace-config-node-filter-unused').removeClass('selected');
|
||||
showUnusedOnly = !showUnusedOnly;
|
||||
refreshConfigNodeList();
|
||||
}
|
||||
});
|
||||
$('#workspace-config-node-filter-unused').on("click",function(e) {
|
||||
e.preventDefault();
|
||||
if (!showUnusedOnly) {
|
||||
$(this).addClass('selected');
|
||||
$('#workspace-config-node-filter-all').removeClass('selected');
|
||||
showUnusedOnly = !showUnusedOnly;
|
||||
refreshConfigNodeList();
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
|
||||
}
|
||||
function show() {
|
||||
function show(id) {
|
||||
if (typeof id === 'boolean') {
|
||||
if (id) {
|
||||
$('#workspace-config-node-filter-unused').click();
|
||||
} else {
|
||||
$('#workspace-config-node-filter-all').click();
|
||||
}
|
||||
}
|
||||
refreshConfigNodeList();
|
||||
if (typeof id === "string") {
|
||||
$('#workspace-config-node-filter-all').click();
|
||||
id = id.replace(/\./g,"-");
|
||||
setTimeout(function() {
|
||||
var node = $(".palette_node_id_"+id);
|
||||
var y = node.position().top;
|
||||
var h = node.height();
|
||||
var scrollWindow = $(".sidebar-node-config");
|
||||
var scrollHeight = scrollWindow.height();
|
||||
|
||||
if (y+h > scrollHeight) {
|
||||
scrollWindow.animate({scrollTop: '-='+(scrollHeight-(y+h)-30)},150);
|
||||
} else if (y<0) {
|
||||
scrollWindow.animate({scrollTop: '+='+(y-10)},150);
|
||||
}
|
||||
var flash = 21;
|
||||
var flashFunc = function() {
|
||||
if ((flash%2)===0) {
|
||||
node.removeClass('node_highlighted');
|
||||
} else {
|
||||
node.addClass('node_highlighted');
|
||||
}
|
||||
flash--;
|
||||
if (flash >= 0) {
|
||||
setTimeout(flashFunc,100);
|
||||
}
|
||||
}
|
||||
flashFunc();
|
||||
},100);
|
||||
}
|
||||
RED.sidebar.show("config");
|
||||
}
|
||||
return {
|
||||
|
||||
292
editor/js/ui/tab-context.js
Normal file
@@ -0,0 +1,292 @@
|
||||
/**
|
||||
* 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.sidebar.context = (function() {
|
||||
|
||||
var content;
|
||||
var sections;
|
||||
|
||||
var localCache = {};
|
||||
|
||||
|
||||
var nodeSection;
|
||||
// var subflowSection;
|
||||
var flowSection;
|
||||
var globalSection;
|
||||
|
||||
var currentNode;
|
||||
var currentFlow;
|
||||
|
||||
function init() {
|
||||
|
||||
content = $("<div>").css({"position":"relative","height":"100%"});
|
||||
content.className = "sidebar-context"
|
||||
// var toolbar = $('<div class="sidebar-header">'+
|
||||
// '</div>').appendTo(content);
|
||||
|
||||
var footerToolbar = $('<div>'+
|
||||
// '<span class="button-group"><a class="sidebar-footer-button" href="#" data-i18n="[title]node-red:debug.sidebar.openWindow"><i class="fa fa-desktop"></i></a></span> ' +
|
||||
'</div>');
|
||||
|
||||
|
||||
|
||||
var stackContainer = $("<div>",{class:"sidebar-context-stack"}).appendTo(content);
|
||||
sections = RED.stack.create({
|
||||
container: stackContainer
|
||||
});
|
||||
|
||||
nodeSection = sections.add({
|
||||
title: RED._("sidebar.context.node"),
|
||||
collapsible: true,
|
||||
// onexpand: function() {
|
||||
// updateNode(currentNode,true);
|
||||
// }
|
||||
});
|
||||
nodeSection.expand();
|
||||
nodeSection.content.css({height:"100%"});
|
||||
nodeSection.timestamp = $('<div class="sidebar-context-updated"> </div>').appendTo(nodeSection.content);
|
||||
var table = $('<table class="node-info"></table>').appendTo(nodeSection.content);
|
||||
nodeSection.table = $('<tbody>').appendTo(table);
|
||||
var bg = $('<div style="float: right"></div>').appendTo(nodeSection.header);
|
||||
$('<button class="editor-button editor-button-small"><i class="fa fa-refresh"></i></button>')
|
||||
.appendTo(bg)
|
||||
.click(function(evt) {
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
updateNode(currentNode, true);
|
||||
})
|
||||
|
||||
// subflowSection = sections.add({
|
||||
// title: "Subflow",
|
||||
// collapsible: true
|
||||
// });
|
||||
// subflowSection.expand();
|
||||
// subflowSection.content.css({height:"100%"});
|
||||
// bg = $('<div style="float: right"></div>').appendTo(subflowSection.header);
|
||||
// $('<button class="editor-button editor-button-small"><i class="fa fa-refresh"></i></button>')
|
||||
// .appendTo(bg)
|
||||
// .click(function(evt) {
|
||||
// evt.stopPropagation();
|
||||
// evt.preventDefault();
|
||||
// })
|
||||
//
|
||||
// subflowSection.container.hide();
|
||||
|
||||
flowSection = sections.add({
|
||||
title: RED._("sidebar.context.flow"),
|
||||
collapsible: true
|
||||
});
|
||||
flowSection.expand();
|
||||
flowSection.content.css({height:"100%"});
|
||||
flowSection.timestamp = $('<div class="sidebar-context-updated"> </div>').appendTo(flowSection.content);
|
||||
var table = $('<table class="node-info"></table>').appendTo(flowSection.content);
|
||||
flowSection.table = $('<tbody>').appendTo(table);
|
||||
bg = $('<div style="float: right"></div>').appendTo(flowSection.header);
|
||||
$('<button class="editor-button editor-button-small"><i class="fa fa-refresh"></i></button>')
|
||||
.appendTo(bg)
|
||||
.click(function(evt) {
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
updateFlow(currentFlow);
|
||||
})
|
||||
|
||||
globalSection = sections.add({
|
||||
title: RED._("sidebar.context.global"),
|
||||
collapsible: true
|
||||
});
|
||||
globalSection.expand();
|
||||
globalSection.content.css({height:"100%"});
|
||||
globalSection.timestamp = $('<div class="sidebar-context-updated"> </div>').appendTo(globalSection.content);
|
||||
var table = $('<table class="node-info"></table>').appendTo(globalSection.content);
|
||||
globalSection.table = $('<tbody>').appendTo(table);
|
||||
|
||||
bg = $('<div style="float: right"></div>').appendTo(globalSection.header);
|
||||
$('<button class="editor-button editor-button-small"><i class="fa fa-refresh"></i></button>')
|
||||
.appendTo(bg)
|
||||
.click(function(evt) {
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
updateEntry(globalSection,"context/global","global");
|
||||
})
|
||||
|
||||
|
||||
RED.actions.add("core:show-context-tab",show);
|
||||
|
||||
RED.sidebar.addTab({
|
||||
id: "context",
|
||||
label: RED._("sidebar.context.label"),
|
||||
name: RED._("sidebar.context.name"),
|
||||
iconClass: "fa fa-database",
|
||||
content: content,
|
||||
toolbar: footerToolbar,
|
||||
// pinned: true,
|
||||
enableOnEdit: true
|
||||
});
|
||||
|
||||
// var toggleLiveButton = $("#sidebar-context-toggle-live");
|
||||
// toggleLiveButton.click(function(evt) {
|
||||
// evt.preventDefault();
|
||||
// if ($(this).hasClass("selected")) {
|
||||
// $(this).removeClass("selected");
|
||||
// $(this).find("i").removeClass("fa-pause");
|
||||
// $(this).find("i").addClass("fa-play");
|
||||
// } else {
|
||||
// $(this).addClass("selected");
|
||||
// $(this).find("i").removeClass("fa-play");
|
||||
// $(this).find("i").addClass("fa-pause");
|
||||
// }
|
||||
// });
|
||||
// RED.popover.tooltip(toggleLiveButton, function() {
|
||||
// if (toggleLiveButton.hasClass("selected")) {
|
||||
// return "Pause live updates"
|
||||
// } else {
|
||||
// return "Start live updates"
|
||||
// }
|
||||
// });
|
||||
|
||||
|
||||
RED.events.on("view:selection-changed", function(event) {
|
||||
var selectedNode = event.nodes && event.nodes.length === 1 && event.nodes[0];
|
||||
updateNode(selectedNode);
|
||||
})
|
||||
|
||||
RED.events.on("workspace:change", function(event) {
|
||||
updateFlow(RED.nodes.workspace(event.workspace));
|
||||
})
|
||||
|
||||
updateEntry(globalSection,"context/global","global");
|
||||
|
||||
}
|
||||
|
||||
function updateNode(node,force) {
|
||||
currentNode = node;
|
||||
if (force) {
|
||||
if (node) {
|
||||
updateEntry(nodeSection,"context/node/"+node.id,node.id);
|
||||
// if (/^subflow:/.test(node.type)) {
|
||||
// subflowSection.container.show();
|
||||
// updateEntry(subflowSection,"context/flow/"+node.id,node.id);
|
||||
// } else {
|
||||
// subflowSection.container.hide();
|
||||
// }
|
||||
} else {
|
||||
// subflowSection.container.hide();
|
||||
updateEntry(nodeSection)
|
||||
}
|
||||
} else {
|
||||
$(nodeSection.table).empty();
|
||||
if (node) {
|
||||
$('<tr class="node-info-node-row red-ui-search-empty blank" colspan="2"><td data-i18n="sidebar.context.refresh"></td></tr>').appendTo(nodeSection.table).i18n();
|
||||
} else {
|
||||
$('<tr class="node-info-node-row red-ui-search-empty blank" colspan="2"><td data-i18n="sidebar.context.none"></td></tr>').appendTo(nodeSection.table).i18n();
|
||||
}
|
||||
nodeSection.timestamp.html(" ");
|
||||
|
||||
}
|
||||
}
|
||||
function updateFlow(flow) {
|
||||
currentFlow = flow;
|
||||
if (flow) {
|
||||
updateEntry(flowSection,"context/flow/"+flow.id,flow.id);
|
||||
} else {
|
||||
updateEntry(flowSection)
|
||||
}
|
||||
}
|
||||
|
||||
function refreshEntry(section,baseUrl,id) {
|
||||
|
||||
var contextStores = RED.settings.context.stores;
|
||||
var container = section.table;
|
||||
|
||||
$.getJSON(baseUrl, function(data) {
|
||||
$(container).empty();
|
||||
var sortedData = {};
|
||||
for (var store in data) {
|
||||
if (data.hasOwnProperty(store)) {
|
||||
for (var key in data[store]) {
|
||||
if (data[store].hasOwnProperty(key)) {
|
||||
if (!sortedData.hasOwnProperty(key)) {
|
||||
sortedData[key] = [];
|
||||
}
|
||||
data[store][key].store = store;
|
||||
sortedData[key].push(data[store][key])
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
var keys = Object.keys(sortedData);
|
||||
keys.sort();
|
||||
var l = keys.length;
|
||||
for (var i = 0; i < l; i++) {
|
||||
sortedData[keys[i]].forEach(function(v) {
|
||||
var k = keys[i];
|
||||
var l2 = sortedData[k].length;
|
||||
var propRow = $('<tr class="node-info-node-row"><td class="sidebar-context-property"></td><td></td></tr>').appendTo(container);
|
||||
var obj = $(propRow.children()[0]);
|
||||
obj.text(k);
|
||||
var tools = $('<span class="debug-message-tools button-group"></span>').appendTo(obj);
|
||||
var refreshItem = $('<button class="editor-button editor-button-small"><i class="fa fa-refresh"></i></button>').appendTo(tools).click(function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
$.getJSON(baseUrl+"/"+k+"?store="+v.store, function(data) {
|
||||
$(propRow.children()[1]).empty();
|
||||
var payload = data.msg;
|
||||
var format = data.format;
|
||||
payload = RED.utils.decodeObject(payload,format);
|
||||
RED.utils.createObjectElement(payload, {
|
||||
typeHint: data.format,
|
||||
sourceId: id+"."+k
|
||||
}).appendTo(propRow.children()[1]);
|
||||
})
|
||||
});
|
||||
|
||||
|
||||
var payload = v.msg;
|
||||
var format = v.format;
|
||||
payload = RED.utils.decodeObject(payload,format);
|
||||
RED.utils.createObjectElement(payload, {
|
||||
typeHint: v.format,
|
||||
sourceId: id+"."+k
|
||||
}).appendTo(propRow.children()[1]);
|
||||
if (contextStores.length > 1) {
|
||||
$("<span>",{class:"sidebar-context-property-storename"}).text(v.store).appendTo($(propRow.children()[0]))
|
||||
}
|
||||
});
|
||||
}
|
||||
if (l === 0) {
|
||||
$('<tr class="node-info-node-row red-ui-search-empty blank" colspan="2"><td data-i18n="sidebar.context.empty"></td></tr>').appendTo(container).i18n();
|
||||
}
|
||||
$(section.timestamp).text(new Date().toLocaleString());
|
||||
});
|
||||
}
|
||||
function updateEntry(section,baseUrl,id) {
|
||||
var container = section.table;
|
||||
if (id) {
|
||||
refreshEntry(section,baseUrl,id);
|
||||
} else {
|
||||
$(container).empty();
|
||||
$('<tr class="node-info-node-row red-ui-search-empty blank" colspan="2"><td data-i18n="sidebar.context.none"></td></tr>').appendTo(container).i18n();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
function show() {
|
||||
RED.sidebar.show("context");
|
||||
}
|
||||
return {
|
||||
init: init
|
||||
}
|
||||
})();
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013, 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -26,21 +26,73 @@ RED.sidebar.info = (function() {
|
||||
smartypants: false
|
||||
});
|
||||
|
||||
var content = document.createElement("div");
|
||||
content.style.paddingTop = "4px";
|
||||
content.style.paddingLeft = "4px";
|
||||
content.style.paddingRight = "4px";
|
||||
content.className = "sidebar-node-info"
|
||||
var content;
|
||||
var sections;
|
||||
var nodeSection;
|
||||
var infoSection;
|
||||
var tipBox;
|
||||
|
||||
var propertiesExpanded = false;
|
||||
var expandedSections = {
|
||||
"property": false
|
||||
};
|
||||
|
||||
function init() {
|
||||
|
||||
content = document.createElement("div");
|
||||
content.className = "sidebar-node-info"
|
||||
|
||||
RED.actions.add("core:show-info-tab",show);
|
||||
|
||||
var stackContainer = $("<div>",{class:"sidebar-node-info-stack"}).appendTo(content);
|
||||
|
||||
sections = RED.stack.create({
|
||||
container: stackContainer
|
||||
}).hide();
|
||||
|
||||
nodeSection = sections.add({
|
||||
title: RED._("sidebar.info.info"),
|
||||
collapsible: true
|
||||
});
|
||||
nodeSection.expand();
|
||||
infoSection = sections.add({
|
||||
title: RED._("sidebar.info.nodeHelp"),
|
||||
collapsible: true
|
||||
});
|
||||
infoSection.expand();
|
||||
infoSection.content.css("padding","6px");
|
||||
infoSection.container.css("border-bottom","none");
|
||||
|
||||
var tipContainer = $('<div class="node-info-tips"></div>').appendTo(content);
|
||||
tipBox = $('<div class="node-info-tip"></div>').appendTo(tipContainer);
|
||||
var tipButtons = $('<div class="node-info-tips-buttons"></div>').appendTo(tipContainer);
|
||||
|
||||
var tipRefresh = $('<a href="#" class="workspace-footer-button"><i class="fa fa-refresh"></a>').appendTo(tipButtons);
|
||||
tipRefresh.click(function(e) {
|
||||
e.preventDefault();
|
||||
tips.next();
|
||||
})
|
||||
|
||||
var tipClose = $('<a href="#" class="workspace-footer-button"><i class="fa fa-times"></a>').appendTo(tipButtons);
|
||||
tipClose.click(function(e) {
|
||||
e.preventDefault();
|
||||
RED.actions.invoke("core:toggle-show-tips");
|
||||
RED.notify(RED._("sidebar.info.showTips"));
|
||||
});
|
||||
|
||||
RED.sidebar.addTab({
|
||||
id: "info",
|
||||
label: RED._("sidebar.info.label"),
|
||||
name: RED._("sidebar.info.name"),
|
||||
content: content
|
||||
iconClass: "fa fa-info",
|
||||
content: content,
|
||||
pinned: true,
|
||||
enableOnEdit: true
|
||||
});
|
||||
if (tips.enabled()) {
|
||||
tips.start();
|
||||
} else {
|
||||
tips.stop();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@@ -48,134 +100,311 @@ RED.sidebar.info = (function() {
|
||||
RED.sidebar.show("info");
|
||||
}
|
||||
|
||||
function jsonFilter(key,value) {
|
||||
if (key === "") {
|
||||
return value;
|
||||
}
|
||||
var t = typeof value;
|
||||
if ($.isArray(value)) {
|
||||
return "[array:"+value.length+"]";
|
||||
} else if (t === "object") {
|
||||
return "[object]"
|
||||
} else if (t === "string") {
|
||||
if (value.length > 30) {
|
||||
return value.substring(0,30)+" ...";
|
||||
// TODO: DRY - projects.js
|
||||
function addTargetToExternalLinks(el) {
|
||||
$(el).find("a").each(function(el) {
|
||||
var href = $(this).attr('href');
|
||||
if (/^https?:/.test(href)) {
|
||||
$(this).attr('target','_blank');
|
||||
}
|
||||
}
|
||||
return value;
|
||||
});
|
||||
return el;
|
||||
}
|
||||
|
||||
function refresh(node) {
|
||||
var table = '<table class="node-info"><tbody>';
|
||||
table += '<tr class="blank"><td colspan="2">'+RED._("sidebar.info.node")+'</td></tr>';
|
||||
if (node.type != "subflow" && node.name) {
|
||||
table += "<tr><td>"+RED._("common.label.name")+"</td><td> "+node.name+"</td></tr>";
|
||||
if (node === undefined) {
|
||||
refreshSelection();
|
||||
return;
|
||||
}
|
||||
table += "<tr><td>"+RED._("sidebar.info.type")+"</td><td> "+node.type+"</td></tr>";
|
||||
table += "<tr><td>"+RED._("sidebar.info.id")+"</td><td> "+node.id+"</td></tr>";
|
||||
sections.show();
|
||||
$(nodeSection.content).empty();
|
||||
$(infoSection.content).empty();
|
||||
|
||||
var m = /^subflow(:(.+))?$/.exec(node.type);
|
||||
var propRow;
|
||||
|
||||
var table = $('<table class="node-info"></table>').appendTo(nodeSection.content);
|
||||
var tableBody = $('<tbody>').appendTo(table);
|
||||
var subflowNode;
|
||||
if (m) {
|
||||
if (m[2]) {
|
||||
subflowNode = RED.nodes.subflow(m[2]);
|
||||
} else {
|
||||
subflowNode = node;
|
||||
}
|
||||
var subflowUserCount;
|
||||
|
||||
table += '<tr class="blank"><td colspan="2">'+RED._("sidebar.info.subflow")+'</td></tr>';
|
||||
|
||||
var userCount = 0;
|
||||
var subflowType = "subflow:"+subflowNode.id;
|
||||
RED.nodes.eachNode(function(n) {
|
||||
if (n.type === subflowType) {
|
||||
userCount++;
|
||||
}
|
||||
});
|
||||
table += "<tr><td>"+RED._("common.label.name")+"</td><td>"+subflowNode.name+"</td></tr>";
|
||||
table += "<tr><td>"+RED._("sidebar.info.instances")+"</td><td>"+userCount+"</td></tr>";
|
||||
var activeProject = RED.projects.getActiveProject();
|
||||
if (activeProject) {
|
||||
propRow = $('<tr class="node-info-node-row"><td>Project</td><td></td></tr>').appendTo(tableBody);
|
||||
$(propRow.children()[1]).text(activeProject.name||"");
|
||||
$('<tr class="node-info-property-expand blank"><td colspan="2"></td></tr>').appendTo(tableBody);
|
||||
$('<button class="editor-button editor-button-small" style="position:absolute;right:2px;"><i class="fa fa-ellipsis-h"></i></button>')
|
||||
.appendTo(propRow.children()[1])
|
||||
.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
RED.projects.editProject();
|
||||
});
|
||||
}
|
||||
infoSection.container.show();
|
||||
if (node === null) {
|
||||
return;
|
||||
} else if (Array.isArray(node)) {
|
||||
infoSection.container.hide();
|
||||
propRow = $('<tr class="node-info-node-row"><td>'+RED._("sidebar.info.selection")+"</td><td></td></tr>").appendTo(tableBody);
|
||||
$(propRow.children()[1]).text(RED._("sidebar.info.nodes",{count:node.length}))
|
||||
} else {
|
||||
var m = /^subflow(:(.+))?$/.exec(node.type);
|
||||
if (m) {
|
||||
if (m[2]) {
|
||||
subflowNode = RED.nodes.subflow(m[2]);
|
||||
} else {
|
||||
subflowNode = node;
|
||||
}
|
||||
|
||||
if (!m && node.type != "subflow" && node.type != "comment") {
|
||||
table += '<tr class="blank"><td colspan="2"><a href="#" class="node-info-property-header"><i style="width: 10px; text-align: center;" class="fa fa-caret-'+(propertiesExpanded?"down":"right")+'"></i> '+RED._("sidebar.info.properties")+'</a></td></tr>';
|
||||
if (node._def) {
|
||||
for (var n in node._def.defaults) {
|
||||
if (n != "name" && node._def.defaults.hasOwnProperty(n)) {
|
||||
var val = node[n]||"";
|
||||
var type = typeof val;
|
||||
if (type === "string") {
|
||||
if (val.length === 0) {
|
||||
val += '<span style="font-style: italic; color: #ccc;">'+RED._("sidebar.info.blank")+'</span>';
|
||||
} else {
|
||||
if (val.length > 30) {
|
||||
val = val.substring(0,30)+" ...";
|
||||
subflowUserCount = 0;
|
||||
var subflowType = "subflow:"+subflowNode.id;
|
||||
RED.nodes.eachNode(function(n) {
|
||||
if (n.type === subflowType) {
|
||||
subflowUserCount++;
|
||||
}
|
||||
});
|
||||
}
|
||||
if (node.type === "tab" || node.type === "subflow") {
|
||||
propRow = $('<tr class="node-info-node-row"><td>'+RED._("sidebar.info."+(node.type==='tab'?'flow':'subflow'))+'</td><td></td></tr>').appendTo(tableBody);
|
||||
RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]);
|
||||
propRow = $('<tr class="node-info-node-row"><td>'+RED._("sidebar.info.tabName")+"</td><td></td></tr>").appendTo(tableBody);
|
||||
$(propRow.children()[1]).text(node.label||node.name||"");
|
||||
if (node.type === "tab") {
|
||||
propRow = $('<tr class="node-info-node-row"><td>'+RED._("sidebar.info.status")+'</td><td></td></tr>').appendTo(tableBody);
|
||||
$(propRow.children()[1]).text((!!!node.disabled)?RED._("sidebar.info.enabled"):RED._("sidebar.info.disabled"))
|
||||
} else if (node.type === "subflow") {
|
||||
propRow = $('<tr class="node-info-node-row"><td>'+RED._("subflow.category")+'</td><td></td></tr>').appendTo(tableBody);
|
||||
var category = node.category||"subflows";
|
||||
$(propRow.children()[1]).text(RED._("palette.label."+category,{defaultValue:category}))
|
||||
}
|
||||
} else {
|
||||
propRow = $('<tr class="node-info-node-row"><td>'+RED._("sidebar.info.node")+"</td><td></td></tr>").appendTo(tableBody);
|
||||
RED.utils.createObjectElement(node.id).appendTo(propRow.children()[1]);
|
||||
|
||||
|
||||
if (node.type !== "subflow" && node.type !== "unknown" && node.name) {
|
||||
propRow = $('<tr class="node-info-node-row"><td>'+RED._("common.label.name")+'</td><td></td></tr>').appendTo(tableBody);
|
||||
$('<span class="bidiAware" dir="'+RED.text.bidi.resolveBaseTextDir(node.name)+'"></span>').text(node.name).appendTo(propRow.children()[1]);
|
||||
}
|
||||
if (!m) {
|
||||
propRow = $('<tr class="node-info-node-row"><td>'+RED._("sidebar.info.type")+"</td><td></td></tr>").appendTo(tableBody);
|
||||
$(propRow.children()[1]).text((node.type === "unknown")?node._orig.type:node.type);
|
||||
if (node.type === "unknown") {
|
||||
$('<span style="float: right; font-size: 0.8em"><i class="fa fa-warning"></i></span>').prependTo($(propRow.children()[1]))
|
||||
}
|
||||
}
|
||||
if (!m && node.type != "subflow" && node.type != "comment") {
|
||||
var defaults;
|
||||
if (node.type === 'unknown') {
|
||||
defaults = {};
|
||||
Object.keys(node._orig).forEach(function(k) {
|
||||
if (k !== 'type') {
|
||||
defaults[k] = {};
|
||||
}
|
||||
})
|
||||
} else if (node._def) {
|
||||
defaults = node._def.defaults;
|
||||
}
|
||||
if (defaults) {
|
||||
var count = 0;
|
||||
for (var n in defaults) {
|
||||
if (n != "name" && defaults.hasOwnProperty(n)) {
|
||||
var val = node[n];
|
||||
var type = typeof val;
|
||||
count++;
|
||||
propRow = $('<tr class="node-info-property-row'+(expandedSections.property?"":" hide")+'"><td>'+n+"</td><td></td></tr>").appendTo(tableBody);
|
||||
if (defaults[n].type) {
|
||||
var configNode = RED.nodes.node(val);
|
||||
if (!configNode) {
|
||||
RED.utils.createObjectElement(undefined).appendTo(propRow.children()[1]);
|
||||
} else {
|
||||
var configLabel = RED.utils.getNodeLabel(configNode,val);
|
||||
var container = propRow.children()[1];
|
||||
|
||||
var div = $('<span>',{class:""}).appendTo(container);
|
||||
var nodeDiv = $('<div>',{class:"palette_node palette_node_small"}).appendTo(div);
|
||||
var colour = RED.utils.getNodeColor(configNode.type,configNode._def);
|
||||
var icon_url = RED.utils.getNodeIcon(configNode._def);
|
||||
nodeDiv.css({'backgroundColor':colour, "cursor":"pointer"});
|
||||
var iconContainer = $('<div/>',{class:"palette_icon_container"}).appendTo(nodeDiv);
|
||||
$('<div/>',{class:"palette_icon",style:"background-image: url("+icon_url+")"}).appendTo(iconContainer);
|
||||
var nodeContainer = $('<span></span>').css({"verticalAlign":"top","marginLeft":"6px"}).text(configLabel).appendTo(container);
|
||||
|
||||
nodeDiv.on('dblclick',function() {
|
||||
RED.editor.editConfig("", configNode.type, configNode.id);
|
||||
})
|
||||
|
||||
}
|
||||
} else {
|
||||
RED.utils.createObjectElement(val).appendTo(propRow.children()[1]);
|
||||
}
|
||||
val = val.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");
|
||||
}
|
||||
} else if (type === "number") {
|
||||
val = val.toString();
|
||||
} else if ($.isArray(val)) {
|
||||
val = "[<br/>";
|
||||
for (var i=0;i<Math.min(node[n].length,10);i++) {
|
||||
var vv = JSON.stringify(node[n][i],jsonFilter," ").replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");
|
||||
val += " "+i+": "+vv+"<br/>";
|
||||
}
|
||||
if (node[n].length > 10) {
|
||||
val += " ... "+RED._("sidebar.info.arrayItems",{count:node[n].length})+"<br/>";
|
||||
}
|
||||
val += "]";
|
||||
} else {
|
||||
val = JSON.stringify(val,jsonFilter," ");
|
||||
val = val.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");
|
||||
}
|
||||
|
||||
table += '<tr class="node-info-property-row'+(propertiesExpanded?"":" hide")+'"><td>'+n+"</td><td>"+val+"</td></tr>";
|
||||
if (count > 0) {
|
||||
$('<tr class="node-info-property-expand blank"><td colspan="2"><a href="#" class=" node-info-property-header'+(expandedSections.property?" expanded":"")+'"><span class="node-info-property-show-more">'+RED._("sidebar.info.showMore")+'</span><span class="node-info-property-show-less">'+RED._("sidebar.info.showLess")+'</span> <i class="fa fa-caret-down"></i></a></td></tr>').appendTo(tableBody);
|
||||
}
|
||||
}
|
||||
}
|
||||
if (node.type !== 'tab') {
|
||||
if (m) {
|
||||
$('<tr class="blank"><th colspan="2">'+RED._("sidebar.info.subflow")+'</th></tr>').appendTo(tableBody);
|
||||
$('<tr class="node-info-subflow-row"><td>'+RED._("common.label.name")+'</td><td><span class="bidiAware" dir=\"'+RED.text.bidi.resolveBaseTextDir(subflowNode.name)+'">'+subflowNode.name+'</span></td></tr>').appendTo(tableBody);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
table += "</tbody></table><hr/>";
|
||||
if (!subflowNode && node.type != "comment") {
|
||||
var helpText = $("script[data-help-name|='"+node.type+"']").html()||"";
|
||||
table += '<div class="node-help">'+helpText+"</div>";
|
||||
}
|
||||
if (subflowNode) {
|
||||
table += '<div class="node-help">'+marked(subflowNode.info||"")+'</div>';
|
||||
} else if (node._def && node._def.info) {
|
||||
var info = node._def.info;
|
||||
table += '<div class="node-help">'+marked(typeof info === "function" ? info.call(node) : info)+'</div>';
|
||||
//table += '<div class="node-help">'+(typeof info === "function" ? info.call(node) : info)+'</div>';
|
||||
}
|
||||
|
||||
$(content).html(table);
|
||||
|
||||
$(".node-info-property-header").click(function(e) {
|
||||
var icon = $(this).find("i");
|
||||
if (icon.hasClass("fa-caret-right")) {
|
||||
icon.removeClass("fa-caret-right");
|
||||
icon.addClass("fa-caret-down");
|
||||
$(".node-info-property-row").show();
|
||||
propertiesExpanded = true;
|
||||
} else {
|
||||
icon.addClass("fa-caret-right");
|
||||
icon.removeClass("fa-caret-down");
|
||||
$(".node-info-property-row").hide();
|
||||
propertiesExpanded = false;
|
||||
if (m) {
|
||||
propRow = $('<tr class="node-info-node-row"><td>'+RED._("subflow.category")+'</td><td></td></tr>').appendTo(tableBody);
|
||||
var category = subflowNode.category||"subflows";
|
||||
$(propRow.children()[1]).text(RED._("palette.label."+category,{defaultValue:category}))
|
||||
$('<tr class="node-info-subflow-row"><td>'+RED._("sidebar.info.instances")+"</td><td>"+subflowUserCount+'</td></tr>').appendTo(tableBody);
|
||||
}
|
||||
|
||||
e.preventDefault();
|
||||
});
|
||||
var infoText = "";
|
||||
if (!subflowNode && node.type !== "comment" && node.type !== "tab") {
|
||||
infoSection.title.text(RED._("sidebar.info.nodeHelp"));
|
||||
var helpText = $("script[data-help-name='"+node.type+"']").html()||('<span class="node-info-none">'+RED._("sidebar.info.none")+'</span>');
|
||||
infoText = helpText;
|
||||
} else if (node.type === "tab") {
|
||||
infoSection.title.text(RED._("sidebar.info.flowDesc"));
|
||||
infoText = marked(node.info||"")||('<span class="node-info-none">'+RED._("sidebar.info.none")+'</span>');
|
||||
}
|
||||
|
||||
if (subflowNode) {
|
||||
infoText = infoText + (marked(subflowNode.info||"")||('<span class="node-info-none">'+RED._("sidebar.info.none")+'</span>'));
|
||||
infoSection.title.text(RED._("sidebar.info.subflowDesc"));
|
||||
} else if (node._def && node._def.info) {
|
||||
infoSection.title.text(RED._("sidebar.info.nodeHelp"));
|
||||
var info = node._def.info;
|
||||
var textInfo = (typeof info === "function" ? info.call(node) : info);
|
||||
// TODO: help
|
||||
infoText = infoText + marked(textInfo);
|
||||
}
|
||||
if (infoText) {
|
||||
setInfoText(infoText);
|
||||
}
|
||||
$(".sidebar-node-info-stack").scrollTop(0);
|
||||
$(".node-info-property-header").click(function(e) {
|
||||
e.preventDefault();
|
||||
expandedSections["property"] = !expandedSections["property"];
|
||||
$(this).toggleClass("expanded",expandedSections["property"]);
|
||||
$(".node-info-property-row").toggle(expandedSections["property"]);
|
||||
});
|
||||
}
|
||||
}
|
||||
function setInfoText(infoText) {
|
||||
var info = addTargetToExternalLinks($('<div class="node-help"><span class="bidiAware" dir=\"'+RED.text.bidi.resolveBaseTextDir(infoText)+'">'+infoText+'</span></div>')).appendTo(infoSection.content);
|
||||
info.find(".bidiAware").contents().filter(function() { return this.nodeType === 3 && this.textContent.trim() !== "" }).wrap( "<span></span>" );
|
||||
var foldingHeader = "H3";
|
||||
info.find(foldingHeader).wrapInner('<a class="node-info-header expanded" href="#"></a>')
|
||||
.find("a").prepend('<i class="fa fa-angle-right">').click(function(e) {
|
||||
e.preventDefault();
|
||||
var isExpanded = $(this).hasClass('expanded');
|
||||
var el = $(this).parent().next();
|
||||
while(el.length === 1 && el[0].nodeName !== foldingHeader) {
|
||||
el.toggle(!isExpanded);
|
||||
el = el.next();
|
||||
}
|
||||
$(this).toggleClass('expanded',!isExpanded);
|
||||
})
|
||||
}
|
||||
var tips = (function() {
|
||||
var enabled = true;
|
||||
var startDelay = 1000;
|
||||
var cycleDelay = 15000;
|
||||
var startTimeout;
|
||||
var refreshTimeout;
|
||||
var tipCount = -1;
|
||||
|
||||
RED.actions.add("core:toggle-show-tips",function(state) {
|
||||
if (state === undefined) {
|
||||
RED.userSettings.toggle("view-show-tips");
|
||||
} else {
|
||||
enabled = state;
|
||||
if (enabled) {
|
||||
startTips();
|
||||
} else {
|
||||
stopTips();
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
function setTip() {
|
||||
var r = Math.floor(Math.random() * tipCount);
|
||||
var tip = RED._("infotips:info.tip"+r);
|
||||
|
||||
var m;
|
||||
while ((m=/({{(.*?)}})/.exec(tip))) {
|
||||
var shortcut = RED.keyboard.getShortcut(m[2]);
|
||||
if (shortcut) {
|
||||
tip = tip.replace(m[1],RED.keyboard.formatKey(shortcut.key));
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
while ((m=/(\[(.*?)\])/.exec(tip))) {
|
||||
tip = tip.replace(m[1],RED.keyboard.formatKey(m[2]));
|
||||
}
|
||||
tipBox.html(tip).fadeIn(200);
|
||||
if (startTimeout) {
|
||||
startTimeout = null;
|
||||
refreshTimeout = setInterval(cycleTips,cycleDelay);
|
||||
}
|
||||
}
|
||||
function cycleTips() {
|
||||
tipBox.fadeOut(300,function() {
|
||||
setTip();
|
||||
})
|
||||
}
|
||||
function startTips() {
|
||||
$(".sidebar-node-info").addClass('show-tips');
|
||||
if (enabled) {
|
||||
if (!startTimeout && !refreshTimeout) {
|
||||
if (tipCount === -1) {
|
||||
do {
|
||||
tipCount++;
|
||||
} while(RED._("infotips:info.tip"+tipCount)!=="infotips:info.tip"+tipCount);
|
||||
}
|
||||
startTimeout = setTimeout(setTip,startDelay);
|
||||
}
|
||||
}
|
||||
}
|
||||
function stopTips() {
|
||||
$(".sidebar-node-info").removeClass('show-tips');
|
||||
clearInterval(refreshTimeout);
|
||||
clearTimeout(startTimeout);
|
||||
refreshTimeout = null;
|
||||
startTimeout = null;
|
||||
}
|
||||
function nextTip() {
|
||||
clearInterval(refreshTimeout);
|
||||
startTimeout = true;
|
||||
setTip();
|
||||
}
|
||||
return {
|
||||
start: startTips,
|
||||
stop: stopTips,
|
||||
next: nextTip,
|
||||
enabled: function() { return enabled; }
|
||||
}
|
||||
})();
|
||||
|
||||
function clear() {
|
||||
$(content).html("");
|
||||
// sections.hide();
|
||||
refresh(null);
|
||||
}
|
||||
|
||||
function set(html) {
|
||||
$(content).html(html);
|
||||
function set(html,title) {
|
||||
// tips.stop();
|
||||
// sections.show();
|
||||
refresh(null);
|
||||
nodeSection.container.hide();
|
||||
infoSection.title.text(title||RED._("sidebar.info.info"));
|
||||
setInfoText(html);
|
||||
$(".sidebar-node-info-stack").scrollTop(0);
|
||||
}
|
||||
|
||||
RED.events.on("view:selection-changed",function(selection) {
|
||||
function refreshSelection(selection) {
|
||||
if (selection === undefined) {
|
||||
selection = RED.view.selection();
|
||||
}
|
||||
if (selection.nodes) {
|
||||
if (selection.nodes.length == 1) {
|
||||
var node = selection.nodes[0];
|
||||
@@ -184,21 +413,34 @@ RED.sidebar.info = (function() {
|
||||
} else {
|
||||
refresh(node);
|
||||
}
|
||||
} else {
|
||||
refresh(selection.nodes);
|
||||
}
|
||||
} else {
|
||||
var subflow = RED.nodes.subflow(RED.workspaces.active());
|
||||
if (subflow) {
|
||||
refresh(subflow);
|
||||
var activeWS = RED.workspaces.active();
|
||||
|
||||
var flow = RED.nodes.workspace(activeWS) || RED.nodes.subflow(activeWS);
|
||||
if (flow) {
|
||||
refresh(flow);
|
||||
} else {
|
||||
clear();
|
||||
var workspace = RED.nodes.workspace(RED.workspaces.active());
|
||||
if (workspace && workspace.info) {
|
||||
refresh(workspace);
|
||||
} else {
|
||||
refresh(null)
|
||||
// clear();
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
RED.events.on("view:selection-changed",refreshSelection);
|
||||
|
||||
return {
|
||||
init: init,
|
||||
show: show,
|
||||
refresh:refresh,
|
||||
refresh: refresh,
|
||||
clear: clear,
|
||||
set: set
|
||||
}
|
||||
|
||||
@@ -1,169 +0,0 @@
|
||||
/**
|
||||
* Copyright 2013, 2015 IBM Corp.
|
||||
*
|
||||
* 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.tabs = (function() {
|
||||
|
||||
|
||||
function createTabs(options) {
|
||||
var tabs = {};
|
||||
var currentTabWidth;
|
||||
var currentActiveTabWidth = 0;
|
||||
|
||||
var ul = $("#"+options.id)
|
||||
ul.addClass("red-ui-tabs");
|
||||
ul.children().first().addClass("active");
|
||||
ul.children().addClass("red-ui-tab");
|
||||
|
||||
function onTabClick() {
|
||||
activateTab($(this));
|
||||
return false;
|
||||
}
|
||||
|
||||
function onTabDblClick() {
|
||||
if (options.ondblclick) {
|
||||
options.ondblclick(tabs[$(this).attr('href').slice(1)]);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function activateTab(link) {
|
||||
if (typeof link === "string") {
|
||||
link = ul.find("a[href='#"+link+"']");
|
||||
}
|
||||
if (!link.parent().hasClass("active")) {
|
||||
ul.children().removeClass("active");
|
||||
ul.children().css({"transition": "width 100ms"});
|
||||
link.parent().addClass("active");
|
||||
if (options.onchange) {
|
||||
options.onchange(tabs[link.attr('href').slice(1)]);
|
||||
}
|
||||
updateTabWidths();
|
||||
setTimeout(function() {
|
||||
ul.children().css({"transition": ""});
|
||||
},100);
|
||||
}
|
||||
}
|
||||
|
||||
function updateTabWidths() {
|
||||
var tabs = ul.find("li.red-ui-tab");
|
||||
var width = ul.width();
|
||||
var tabCount = tabs.size();
|
||||
var tabWidth = (width-12-(tabCount*6))/tabCount;
|
||||
currentTabWidth = 100*tabWidth/width;
|
||||
currentActiveTabWidth = currentTabWidth+"%";
|
||||
|
||||
if (options.hasOwnProperty("minimumActiveTabWidth")) {
|
||||
if (tabWidth < options.minimumActiveTabWidth) {
|
||||
tabCount -= 1;
|
||||
tabWidth = (width-12-options.minimumActiveTabWidth-(tabCount*6))/tabCount;
|
||||
currentTabWidth = 100*tabWidth/width;
|
||||
currentActiveTabWidth = options.minimumActiveTabWidth+"px";
|
||||
} else {
|
||||
currentActiveTabWidth = 0;
|
||||
}
|
||||
}
|
||||
tabs.css({width:currentTabWidth+"%"});
|
||||
if (tabWidth < 50) {
|
||||
ul.find(".red-ui-tab-close").hide();
|
||||
ul.find(".red-ui-tab-icon").hide();
|
||||
} else {
|
||||
ul.find(".red-ui-tab-close").show();
|
||||
ul.find(".red-ui-tab-icon").show();
|
||||
}
|
||||
if (currentActiveTabWidth !== 0) {
|
||||
ul.find("li.red-ui-tab.active").css({"width":options.minimumActiveTabWidth});
|
||||
ul.find("li.red-ui-tab.active .red-ui-tab-close").show();
|
||||
ul.find("li.red-ui-tab.active .red-ui-tab-icon").show();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
ul.find("li.red-ui-tab a").on("click",onTabClick).on("dblclick",onTabDblClick);
|
||||
updateTabWidths();
|
||||
|
||||
|
||||
function removeTab(id) {
|
||||
var li = ul.find("a[href='#"+id+"']").parent();
|
||||
if (li.hasClass("active")) {
|
||||
var tab = li.prev();
|
||||
if (tab.size() === 0) {
|
||||
tab = li.next();
|
||||
}
|
||||
activateTab(tab.find("a"));
|
||||
}
|
||||
li.remove();
|
||||
if (options.onremove) {
|
||||
options.onremove(tabs[id]);
|
||||
}
|
||||
delete tabs[id];
|
||||
updateTabWidths();
|
||||
}
|
||||
|
||||
return {
|
||||
addTab: function(tab) {
|
||||
tabs[tab.id] = tab;
|
||||
var li = $("<li/>",{class:"red-ui-tab"}).appendTo(ul);
|
||||
var link = $("<a/>",{href:"#"+tab.id, class:"red-ui-tab-label"}).appendTo(li);
|
||||
if (tab.icon) {
|
||||
$('<img src="'+tab.icon+'" class="red-ui-tab-icon"/>').appendTo(link);
|
||||
}
|
||||
$('<span/>').text(tab.label).appendTo(link);
|
||||
|
||||
link.on("click",onTabClick);
|
||||
link.on("dblclick",onTabDblClick);
|
||||
if (tab.closeable) {
|
||||
var closeLink = $("<a/>",{href:"#",class:"red-ui-tab-close"}).appendTo(li);
|
||||
closeLink.append('<i class="fa fa-times" />');
|
||||
|
||||
closeLink.on("click",function(event) {
|
||||
removeTab(tab.id);
|
||||
});
|
||||
}
|
||||
updateTabWidths();
|
||||
if (options.onadd) {
|
||||
options.onadd(tab);
|
||||
}
|
||||
link.attr("title",tab.label);
|
||||
if (ul.find("li.red-ui-tab").size() == 1) {
|
||||
activateTab(link);
|
||||
}
|
||||
},
|
||||
removeTab: removeTab,
|
||||
activateTab: activateTab,
|
||||
resize: updateTabWidths,
|
||||
count: function() {
|
||||
return ul.find("li.red-ui-tab").size();
|
||||
},
|
||||
contains: function(id) {
|
||||
return ul.find("a[href='#"+id+"']").length > 0;
|
||||
},
|
||||
renameTab: function(id,label) {
|
||||
tabs[id].label = label;
|
||||
var tab = ul.find("a[href='#"+id+"']");
|
||||
tab.attr("title",label);
|
||||
tab.find("span").text(label);
|
||||
updateTabWidths();
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
create: createTabs
|
||||
}
|
||||
})();
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2014 IBM Corp.
|
||||
* 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.
|
||||
|
||||
279
editor/js/ui/tray.js
Normal file
@@ -0,0 +1,279 @@
|
||||
/**
|
||||
* 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.tray = (function() {
|
||||
|
||||
var stack = [];
|
||||
var editorStack = $("#editor-stack");
|
||||
var openingTray = false;
|
||||
|
||||
function resize() {
|
||||
|
||||
}
|
||||
function showTray(options) {
|
||||
var el = $('<div class="editor-tray"></div>');
|
||||
var header = $('<div class="editor-tray-header"></div>').appendTo(el);
|
||||
var bodyWrapper = $('<div class="editor-tray-body-wrapper"></div>').appendTo(el);
|
||||
var body = $('<div class="editor-tray-body"></div>').appendTo(bodyWrapper);
|
||||
var footer = $('<div class="editor-tray-footer"></div>').appendTo(el);
|
||||
var resizer = $('<div class="editor-tray-resize-handle"></div>').appendTo(el);
|
||||
// var growButton = $('<a class="editor-tray-resize-button" style="cursor: w-resize;"><i class="fa fa-angle-left"></i></a>').appendTo(resizer);
|
||||
// var shrinkButton = $('<a class="editor-tray-resize-button" style="cursor: e-resize;"><i style="margin-left: 1px;" class="fa fa-angle-right"></i></a>').appendTo(resizer);
|
||||
if (options.title) {
|
||||
var titles = stack.map(function(e) { return e.options.title });
|
||||
titles.push(options.title);
|
||||
var title = '<ul class="editor-tray-breadcrumbs"><li>'+titles.join("</li><li>")+'</li></ul>';
|
||||
|
||||
$('<div class="editor-tray-titlebar">'+title+'</div>').appendTo(header);
|
||||
}
|
||||
if (options.width === Infinity) {
|
||||
options.maximized = true;
|
||||
resizer.addClass('editor-tray-resize-maximised');
|
||||
}
|
||||
var buttonBar = $('<div class="editor-tray-toolbar"></div>').appendTo(header);
|
||||
var primaryButton;
|
||||
if (options.buttons) {
|
||||
for (var i=0;i<options.buttons.length;i++) {
|
||||
var button = options.buttons[i];
|
||||
var b = $('<button>').button().appendTo(buttonBar);
|
||||
if (button.id) {
|
||||
b.attr('id',button.id);
|
||||
}
|
||||
if (button.text) {
|
||||
b.text(button.text);
|
||||
}
|
||||
if (button.click) {
|
||||
b.click((function(action) {
|
||||
return function(evt) {
|
||||
if (!$(this).hasClass('disabled')) {
|
||||
action(evt);
|
||||
}
|
||||
};
|
||||
})(button.click));
|
||||
}
|
||||
if (button.class) {
|
||||
b.addClass(button.class);
|
||||
if (button.class === "primary") {
|
||||
primaryButton = button;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
el.appendTo(editorStack);
|
||||
var tray = {
|
||||
tray: el,
|
||||
header: header,
|
||||
body: body,
|
||||
footer: footer,
|
||||
options: options,
|
||||
primaryButton: primaryButton
|
||||
};
|
||||
stack.push(tray);
|
||||
|
||||
if (!options.maximized) {
|
||||
el.draggable({
|
||||
handle: resizer,
|
||||
axis: "x",
|
||||
start:function(event,ui) {
|
||||
el.width('auto');
|
||||
},
|
||||
drag: function(event,ui) {
|
||||
var absolutePosition = editorStack.position().left+ui.position.left
|
||||
if (absolutePosition < 7) {
|
||||
ui.position.left += 7-absolutePosition;
|
||||
} else if (ui.position.left > -tray.preferredWidth-1) {
|
||||
ui.position.left = -Math.min(editorStack.position().left-7,tray.preferredWidth-1);
|
||||
}
|
||||
if (tray.options.resize) {
|
||||
setTimeout(function() {
|
||||
tray.options.resize({width: -ui.position.left});
|
||||
},0);
|
||||
}
|
||||
tray.width = -ui.position.left;
|
||||
},
|
||||
stop:function(event,ui) {
|
||||
el.width(-ui.position.left);
|
||||
el.css({left:''});
|
||||
if (tray.options.resize) {
|
||||
tray.options.resize({width: -ui.position.left});
|
||||
}
|
||||
tray.width = -ui.position.left;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function finishBuild() {
|
||||
$("#header-shade").show();
|
||||
$("#editor-shade").show();
|
||||
$("#palette-shade").show();
|
||||
$(".sidebar-shade").show();
|
||||
tray.preferredWidth = Math.max(el.width(),500);
|
||||
if (!options.maximized) {
|
||||
body.css({"minWidth":tray.preferredWidth-40});
|
||||
}
|
||||
if (options.width) {
|
||||
if (options.width > $("#editor-stack").position().left-8) {
|
||||
options.width = $("#editor-stack").position().left-8;
|
||||
}
|
||||
el.width(options.width);
|
||||
} else {
|
||||
el.width(tray.preferredWidth);
|
||||
}
|
||||
|
||||
tray.width = el.width();
|
||||
if (tray.width > $("#editor-stack").position().left-8) {
|
||||
tray.width = Math.max(0/*tray.preferredWidth*/,$("#editor-stack").position().left-8);
|
||||
el.width(tray.width);
|
||||
}
|
||||
|
||||
// tray.body.parent().width(Math.min($("#editor-stack").position().left-8,tray.width));
|
||||
|
||||
el.css({
|
||||
right: -(el.width()+10)+"px",
|
||||
transition: "right 0.25s ease"
|
||||
});
|
||||
$("#workspace").scrollLeft(0);
|
||||
handleWindowResize();
|
||||
openingTray = true;
|
||||
setTimeout(function() {
|
||||
setTimeout(function() {
|
||||
if (!options.width) {
|
||||
el.width(Math.min(tray.preferredWidth,$("#editor-stack").position().left-8));
|
||||
}
|
||||
if (options.resize) {
|
||||
options.resize({width:el.width()});
|
||||
}
|
||||
if (options.show) {
|
||||
options.show();
|
||||
}
|
||||
setTimeout(function() {
|
||||
// Delay resetting the flag, so we don't close prematurely
|
||||
openingTray = false;
|
||||
},200);
|
||||
body.find(":focusable:first").focus();
|
||||
|
||||
},150);
|
||||
el.css({right:0});
|
||||
},0);
|
||||
}
|
||||
if (options.open) {
|
||||
if (options.open.length === 1) {
|
||||
options.open(el);
|
||||
finishBuild();
|
||||
} else {
|
||||
options.open(el,finishBuild);
|
||||
}
|
||||
} else {
|
||||
finishBuild();
|
||||
}
|
||||
}
|
||||
|
||||
function handleWindowResize() {
|
||||
if (stack.length > 0) {
|
||||
var tray = stack[stack.length-1];
|
||||
var trayHeight = tray.tray.height()-tray.header.outerHeight()-tray.footer.outerHeight();
|
||||
tray.body.height(trayHeight);
|
||||
if (tray.options.maximized || tray.width > $("#editor-stack").position().left-8) {
|
||||
tray.width = $("#editor-stack").position().left-8;
|
||||
tray.tray.width(tray.width);
|
||||
// tray.body.parent().width(tray.width);
|
||||
} else if (tray.width < tray.preferredWidth) {
|
||||
tray.width = Math.min($("#editor-stack").position().left-8,tray.preferredWidth);
|
||||
tray.tray.width(tray.width);
|
||||
// tray.body.parent().width(tray.width);
|
||||
}
|
||||
if (tray.options.resize) {
|
||||
tray.options.resize({width:tray.width, height:trayHeight});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
init: function init() {
|
||||
$(window).resize(handleWindowResize);
|
||||
RED.events.on("sidebar:resize",handleWindowResize);
|
||||
$("#editor-shade").click(function() {
|
||||
if (!openingTray) {
|
||||
var tray = stack[stack.length-1];
|
||||
if (tray && tray.primaryButton) {
|
||||
tray.primaryButton.click();
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
show: function show(options) {
|
||||
if (stack.length > 0 && !options.overlay) {
|
||||
var oldTray = stack[stack.length-1];
|
||||
if (options.width === "inherit") {
|
||||
options.width = oldTray.tray.width();
|
||||
}
|
||||
oldTray.tray.css({
|
||||
right: -(oldTray.tray.width()+10)+"px"
|
||||
});
|
||||
setTimeout(function() {
|
||||
oldTray.tray.detach();
|
||||
showTray(options);
|
||||
},250)
|
||||
} else {
|
||||
RED.events.emit("editor:open");
|
||||
showTray(options);
|
||||
}
|
||||
|
||||
},
|
||||
close: function close(done) {
|
||||
if (stack.length > 0) {
|
||||
var tray = stack.pop();
|
||||
tray.tray.css({
|
||||
right: -(tray.tray.width()+10)+"px"
|
||||
});
|
||||
setTimeout(function() {
|
||||
if (tray.options.close) {
|
||||
tray.options.close();
|
||||
}
|
||||
tray.tray.remove();
|
||||
if (stack.length > 0) {
|
||||
var oldTray = stack[stack.length-1];
|
||||
if (!oldTray.options.overlay) {
|
||||
oldTray.tray.appendTo("#editor-stack");
|
||||
setTimeout(function() {
|
||||
handleWindowResize();
|
||||
oldTray.tray.css({right:0});
|
||||
if (oldTray.options.show) {
|
||||
oldTray.options.show();
|
||||
}
|
||||
},0);
|
||||
} else {
|
||||
handleWindowResize();
|
||||
if (oldTray.options.show) {
|
||||
oldTray.options.show();
|
||||
}
|
||||
}
|
||||
}
|
||||
if (done) {
|
||||
done();
|
||||
}
|
||||
if (stack.length === 0) {
|
||||
$("#header-shade").hide();
|
||||
$("#editor-shade").hide();
|
||||
$("#palette-shade").hide();
|
||||
$(".sidebar-shade").hide();
|
||||
RED.events.emit("editor:close");
|
||||
RED.view.focus();
|
||||
}
|
||||
},250)
|
||||
}
|
||||
}
|
||||
}
|
||||
})();
|
||||
330
editor/js/ui/typeSearch.js
Normal file
@@ -0,0 +1,330 @@
|
||||
RED.typeSearch = (function() {
|
||||
|
||||
var shade;
|
||||
|
||||
var disabled = false;
|
||||
var dialog = null;
|
||||
var searchInput;
|
||||
var searchResults;
|
||||
var searchResultsDiv;
|
||||
var selected = -1;
|
||||
var visible = false;
|
||||
|
||||
var activeFilter = "";
|
||||
var addCallback;
|
||||
var cancelCallback;
|
||||
|
||||
var typesUsed = {};
|
||||
|
||||
function search(val) {
|
||||
activeFilter = val.toLowerCase();
|
||||
var visible = searchResults.editableList('filter');
|
||||
searchResults.editableList('sort');
|
||||
setTimeout(function() {
|
||||
selected = 0;
|
||||
searchResults.children().removeClass('selected');
|
||||
searchResults.children(":visible:first").addClass('selected');
|
||||
},100);
|
||||
|
||||
}
|
||||
|
||||
function ensureSelectedIsVisible() {
|
||||
var selectedEntry = searchResults.find("li.selected");
|
||||
if (selectedEntry.length === 1) {
|
||||
var scrollWindow = searchResults.parent();
|
||||
var scrollHeight = scrollWindow.height();
|
||||
var scrollOffset = scrollWindow.scrollTop();
|
||||
var y = selectedEntry.position().top;
|
||||
var h = selectedEntry.height();
|
||||
if (y+h > scrollHeight) {
|
||||
scrollWindow.animate({scrollTop: '-='+(scrollHeight-(y+h)-10)},50);
|
||||
} else if (y<0) {
|
||||
scrollWindow.animate({scrollTop: '+='+(y-10)},50);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
function createDialog() {
|
||||
//shade = $('<div>',{class:"red-ui-type-search-shade"}).appendTo("#main-container");
|
||||
dialog = $("<div>",{id:"red-ui-type-search",class:"red-ui-search red-ui-type-search"}).appendTo("#main-container");
|
||||
var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(dialog);
|
||||
searchInput = $('<input type="text">').attr("placeholder",RED._("search.addNode")).appendTo(searchDiv).searchBox({
|
||||
delay: 50,
|
||||
change: function() {
|
||||
search($(this).val());
|
||||
}
|
||||
});
|
||||
searchInput.on('keydown',function(evt) {
|
||||
var children = searchResults.children(":visible");
|
||||
if (children.length > 0) {
|
||||
if (evt.keyCode === 40) {
|
||||
// Down
|
||||
if (selected < children.length-1) {
|
||||
if (selected > -1) {
|
||||
$(children[selected]).removeClass('selected');
|
||||
}
|
||||
selected++;
|
||||
}
|
||||
$(children[selected]).addClass('selected');
|
||||
ensureSelectedIsVisible();
|
||||
evt.preventDefault();
|
||||
} else if (evt.keyCode === 38) {
|
||||
// Up
|
||||
if (selected > 0) {
|
||||
if (selected < children.length) {
|
||||
$(children[selected]).removeClass('selected');
|
||||
}
|
||||
selected--;
|
||||
}
|
||||
$(children[selected]).addClass('selected');
|
||||
ensureSelectedIsVisible();
|
||||
evt.preventDefault();
|
||||
} else if (evt.keyCode === 13) {
|
||||
// Enter
|
||||
var index = Math.max(0,selected);
|
||||
if (index < children.length) {
|
||||
// TODO: dips into editableList impl details
|
||||
confirm($(children[index]).find(".red-ui-editableList-item-content").data('data'));
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
searchResultsDiv = $("<div>",{class:"red-ui-search-results-container"}).appendTo(dialog);
|
||||
searchResults = $('<ol>',{id:"search-result-list", style:"position: absolute;top: 0;bottom: 0;left: 0;right: 0;"}).appendTo(searchResultsDiv).editableList({
|
||||
addButton: false,
|
||||
filter: function(data) {
|
||||
if (activeFilter === "" ) {
|
||||
return true;
|
||||
}
|
||||
if (data.recent || data.common) {
|
||||
return false;
|
||||
}
|
||||
return (activeFilter==="")||(data.index.indexOf(activeFilter) > -1);
|
||||
},
|
||||
sort: function(A,B) {
|
||||
if (activeFilter === "") {
|
||||
return A.i - B.i;
|
||||
}
|
||||
var Ai = A.index.indexOf(activeFilter);
|
||||
var Bi = B.index.indexOf(activeFilter);
|
||||
if (Ai === -1) {
|
||||
return 1;
|
||||
}
|
||||
if (Bi === -1) {
|
||||
return -1;
|
||||
}
|
||||
if (Ai === Bi) {
|
||||
return sortTypeLabels(A,B);
|
||||
}
|
||||
return Ai-Bi;
|
||||
},
|
||||
addItem: function(container,i,object) {
|
||||
var def = object.def;
|
||||
object.index = object.type.toLowerCase();
|
||||
if (object.separator) {
|
||||
container.addClass("red-ui-search-result-separator")
|
||||
}
|
||||
var div = $('<a>',{href:'#',class:"red-ui-search-result"}).appendTo(container);
|
||||
|
||||
var nodeDiv = $('<div>',{class:"red-ui-search-result-node"}).appendTo(div);
|
||||
var colour = RED.utils.getNodeColor(object.type,def);
|
||||
var icon_url = RED.utils.getNodeIcon(def);
|
||||
nodeDiv.css('backgroundColor',colour);
|
||||
|
||||
var iconContainer = $('<div/>',{class:"palette_icon_container"}).appendTo(nodeDiv);
|
||||
$('<div/>',{class:"palette_icon",style:"background-image: url("+icon_url+")"}).appendTo(iconContainer);
|
||||
|
||||
if (def.inputs > 0) {
|
||||
$('<div/>',{class:"red-ui-search-result-node-port"}).appendTo(nodeDiv);
|
||||
}
|
||||
if (def.outputs > 0) {
|
||||
$('<div/>',{class:"red-ui-search-result-node-port red-ui-search-result-node-output"}).appendTo(nodeDiv);
|
||||
}
|
||||
|
||||
var contentDiv = $('<div>',{class:"red-ui-search-result-description"}).appendTo(div);
|
||||
|
||||
var label = object.label;
|
||||
object.index += "|"+label.toLowerCase();
|
||||
|
||||
$('<div>',{class:"red-ui-search-result-node-label"}).text(label).appendTo(contentDiv);
|
||||
|
||||
div.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
confirm(object);
|
||||
});
|
||||
},
|
||||
scrollOnAdd: false
|
||||
});
|
||||
|
||||
}
|
||||
function confirm(def) {
|
||||
hide();
|
||||
typesUsed[def.type] = Date.now();
|
||||
addCallback(def.type);
|
||||
}
|
||||
|
||||
function handleMouseActivity(evt) {
|
||||
if (visible) {
|
||||
var t = $(evt.target);
|
||||
while (t.prop('nodeName').toLowerCase() !== 'body') {
|
||||
if (t.attr('id') === 'red-ui-type-search') {
|
||||
return;
|
||||
}
|
||||
t = t.parent();
|
||||
}
|
||||
hide(true);
|
||||
if (cancelCallback) {
|
||||
cancelCallback();
|
||||
}
|
||||
}
|
||||
}
|
||||
function show(opts) {
|
||||
if (!visible) {
|
||||
RED.keyboard.add("*","escape",function(){
|
||||
hide();
|
||||
if (cancelCallback) {
|
||||
cancelCallback();
|
||||
}
|
||||
});
|
||||
if (dialog === null) {
|
||||
createDialog();
|
||||
}
|
||||
visible = true;
|
||||
setTimeout(function() {
|
||||
$(document).on('mousedown.type-search',handleMouseActivity);
|
||||
$(document).on('mouseup.type-search',handleMouseActivity);
|
||||
$(document).on('click.type-search',handleMouseActivity);
|
||||
},200);
|
||||
} else {
|
||||
dialog.hide();
|
||||
searchResultsDiv.hide();
|
||||
}
|
||||
refreshTypeList();
|
||||
addCallback = opts.add;
|
||||
closeCallback = opts.close;
|
||||
RED.events.emit("type-search:open");
|
||||
//shade.show();
|
||||
dialog.css({left:opts.x+"px",top:opts.y+"px"}).show();
|
||||
searchResultsDiv.slideDown(300);
|
||||
setTimeout(function() {
|
||||
searchResultsDiv.find(".red-ui-editableList-container").scrollTop(0);
|
||||
searchInput.focus();
|
||||
},100);
|
||||
}
|
||||
function hide(fast) {
|
||||
if (visible) {
|
||||
RED.keyboard.remove("escape");
|
||||
visible = false;
|
||||
if (dialog !== null) {
|
||||
searchResultsDiv.slideUp(fast?50:200,function() {
|
||||
dialog.hide();
|
||||
searchInput.searchBox('value','');
|
||||
});
|
||||
//shade.hide();
|
||||
}
|
||||
RED.events.emit("type-search:close");
|
||||
RED.view.focus();
|
||||
$(document).off('mousedown.type-search');
|
||||
$(document).off('mouseup.type-search');
|
||||
$(document).off('click.type-search');
|
||||
}
|
||||
}
|
||||
|
||||
function getTypeLabel(type, def) {
|
||||
var label = type;
|
||||
if (typeof def.paletteLabel !== "undefined") {
|
||||
try {
|
||||
label = (typeof def.paletteLabel === "function" ? def.paletteLabel.call(def) : def.paletteLabel)||"";
|
||||
label += " ("+type+")";
|
||||
} catch(err) {
|
||||
console.log("Definition error: "+type+".paletteLabel",err);
|
||||
}
|
||||
}
|
||||
return label;
|
||||
}
|
||||
function sortTypeLabels(a,b) {
|
||||
var al = a.label.toLowerCase();
|
||||
var bl = b.label.toLowerCase();
|
||||
if (al < bl) {
|
||||
return -1;
|
||||
} else if (al === bl) {
|
||||
return 0;
|
||||
} else {
|
||||
return 1;
|
||||
}
|
||||
}
|
||||
function refreshTypeList() {
|
||||
var i;
|
||||
searchResults.editableList('empty');
|
||||
searchInput.searchBox('value','');
|
||||
selected = -1;
|
||||
var common = [
|
||||
'inject','debug','function','change','switch'
|
||||
];
|
||||
|
||||
var recentlyUsed = Object.keys(typesUsed);
|
||||
recentlyUsed.sort(function(a,b) {
|
||||
return typesUsed[b]-typesUsed[a];
|
||||
});
|
||||
recentlyUsed = recentlyUsed.filter(function(t) {
|
||||
return common.indexOf(t) === -1;
|
||||
});
|
||||
|
||||
var items = [];
|
||||
RED.nodes.registry.getNodeTypes().forEach(function(t) {
|
||||
var def = RED.nodes.getType(t);
|
||||
if (def.category !== 'config' && t !== 'unknown' && t !== 'tab') {
|
||||
items.push({type:t,def: def, label:getTypeLabel(t,def)});
|
||||
}
|
||||
});
|
||||
items.sort(sortTypeLabels);
|
||||
|
||||
var commonCount = 0;
|
||||
var item;
|
||||
var index = 0;
|
||||
for(i=0;i<common.length;i++) {
|
||||
var itemDef = RED.nodes.getType(common[i]);
|
||||
if (itemDef) {
|
||||
item = {
|
||||
type: common[i],
|
||||
common: true,
|
||||
def: itemDef,
|
||||
i: index++
|
||||
};
|
||||
item.label = getTypeLabel(item.type,item.def);
|
||||
if (i === common.length-1) {
|
||||
item.separator = true;
|
||||
}
|
||||
searchResults.editableList('addItem', item);
|
||||
}
|
||||
}
|
||||
for(i=0;i<Math.min(5,recentlyUsed.length);i++) {
|
||||
item = {
|
||||
type:recentlyUsed[i],
|
||||
def: RED.nodes.getType(recentlyUsed[i]),
|
||||
recent: true,
|
||||
i: index++
|
||||
};
|
||||
item.label = getTypeLabel(item.type,item.def);
|
||||
if (i === recentlyUsed.length-1) {
|
||||
item.separator = true;
|
||||
}
|
||||
searchResults.editableList('addItem', item);
|
||||
}
|
||||
for (i=0;i<items.length;i++) {
|
||||
items[i].i = index++;
|
||||
searchResults.editableList('addItem', items[i]);
|
||||
}
|
||||
setTimeout(function() {
|
||||
selected = 0;
|
||||
searchResults.children(":first").addClass('selected');
|
||||
},100);
|
||||
}
|
||||
|
||||
return {
|
||||
show: show,
|
||||
hide: hide
|
||||
};
|
||||
|
||||
})();
|
||||
242
editor/js/ui/userSettings.js
Normal file
@@ -0,0 +1,242 @@
|
||||
/**
|
||||
* 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.userSettings = (function() {
|
||||
|
||||
var trayWidth = 700;
|
||||
var settingsVisible = false;
|
||||
|
||||
var panes = [];
|
||||
|
||||
function addPane(options) {
|
||||
panes.push(options);
|
||||
}
|
||||
|
||||
function show(initialTab) {
|
||||
if (settingsVisible) {
|
||||
return;
|
||||
}
|
||||
if (!RED.user.hasPermission("settings.write")) {
|
||||
RED.notify(RED._("user.errors.settings"),"error");
|
||||
return;
|
||||
}
|
||||
settingsVisible = true;
|
||||
var tabContainer;
|
||||
|
||||
var trayOptions = {
|
||||
title: RED._("menu.label.userSettings"),
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-ok",
|
||||
text: RED._("common.label.close"),
|
||||
class: "primary",
|
||||
click: function() {
|
||||
RED.tray.close();
|
||||
}
|
||||
}
|
||||
],
|
||||
resize: function(dimensions) {
|
||||
trayWidth = dimensions.width;
|
||||
},
|
||||
open: function(tray) {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
var settingsContent = $('<div></div>').appendTo(trayBody);
|
||||
var tabContainer = $('<div></div>',{id:"user-settings-tabs-container"}).appendTo(settingsContent);
|
||||
|
||||
$('<ul></ul>',{id:"user-settings-tabs"}).appendTo(tabContainer);
|
||||
var settingsTabs = RED.tabs.create({
|
||||
id: "user-settings-tabs",
|
||||
vertical: true,
|
||||
onchange: function(tab) {
|
||||
setTimeout(function() {
|
||||
$("#user-settings-tabs-content").children().hide();
|
||||
$("#" + tab.id).show();
|
||||
if (tab.pane.focus) {
|
||||
tab.pane.focus();
|
||||
}
|
||||
},50);
|
||||
}
|
||||
});
|
||||
var tabContents = $('<div></div>',{id:"user-settings-tabs-content"}).appendTo(settingsContent);
|
||||
|
||||
panes.forEach(function(pane) {
|
||||
settingsTabs.addTab({
|
||||
id: "user-settings-tab-"+pane.id,
|
||||
label: pane.title,
|
||||
pane: pane
|
||||
});
|
||||
pane.get().hide().appendTo(tabContents);
|
||||
});
|
||||
settingsContent.i18n();
|
||||
settingsTabs.activateTab("user-settings-tab-"+(initialTab||'view'))
|
||||
$("#sidebar-shade").show();
|
||||
},
|
||||
close: function() {
|
||||
settingsVisible = false;
|
||||
panes.forEach(function(pane) {
|
||||
if (pane.close) {
|
||||
pane.close();
|
||||
}
|
||||
});
|
||||
$("#sidebar-shade").hide();
|
||||
|
||||
},
|
||||
show: function() {}
|
||||
}
|
||||
if (trayWidth !== null) {
|
||||
trayOptions.width = trayWidth;
|
||||
}
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
|
||||
var viewSettings = [
|
||||
{
|
||||
title: "menu.label.view.grid",
|
||||
options: [
|
||||
{setting:"view-show-grid",oldSetting:"menu-menu-item-view-show-grid",label:"menu.label.view.showGrid",toggle:true,onchange:"core:toggle-show-grid"},
|
||||
{setting:"view-snap-grid",oldSetting:"menu-menu-item-view-snap-grid",label:"menu.label.view.snapGrid",toggle:true,onchange:"core:toggle-snap-grid"},
|
||||
{setting:"view-grid-size",label:"menu.label.view.gridSize",type:"number",default: 20, onchange:RED.view.gridSize}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "menu.label.nodes",
|
||||
options: [
|
||||
{setting:"view-node-status",oldSetting:"menu-menu-item-status",label:"menu.label.displayStatus",default: true, toggle:true,onchange:"core:toggle-status"}
|
||||
]
|
||||
},
|
||||
{
|
||||
title: "menu.label.other",
|
||||
options: [
|
||||
{setting:"view-show-tips",oldSettings:"menu-menu-item-show-tips",label:"menu.label.showTips",toggle:true,default:true,onchange:"core:toggle-show-tips"}
|
||||
]
|
||||
}
|
||||
];
|
||||
|
||||
var allSettings = {};
|
||||
|
||||
function createViewPane() {
|
||||
|
||||
var pane = $('<div id="user-settings-tab-view" class="node-help"></div>');
|
||||
|
||||
var currentEditorSettings = RED.settings.get('editor') || {};
|
||||
currentEditorSettings.view = currentEditorSettings.view || {};
|
||||
|
||||
viewSettings.forEach(function(section) {
|
||||
$('<h3></h3>').text(RED._(section.title)).appendTo(pane);
|
||||
section.options.forEach(function(opt) {
|
||||
var initialState = currentEditorSettings.view[opt.setting];
|
||||
var row = $('<div class="user-settings-row"></div>').appendTo(pane);
|
||||
var input;
|
||||
if (opt.toggle) {
|
||||
input = $('<label for="user-settings-'+opt.setting+'"><input id="user-settings-'+opt.setting+'" type="checkbox"> '+RED._(opt.label)+'</label>').appendTo(row).find("input");
|
||||
input.prop('checked',initialState);
|
||||
} else {
|
||||
$('<label for="user-settings-'+opt.setting+'">'+RED._(opt.label)+'</label>').appendTo(row);
|
||||
$('<input id="user-settings-'+opt.setting+'" type="'+(opt.type||"text")+'">').appendTo(row).val(initialState);
|
||||
}
|
||||
});
|
||||
})
|
||||
return pane;
|
||||
}
|
||||
|
||||
function setSelected(id, value) {
|
||||
var opt = allSettings[id];
|
||||
var currentEditorSettings = RED.settings.get('editor') || {};
|
||||
currentEditorSettings.view = currentEditorSettings.view || {};
|
||||
currentEditorSettings.view[opt.setting] = value;
|
||||
RED.settings.set('editor', currentEditorSettings);
|
||||
var callback = opt.onchange;
|
||||
if (typeof callback === 'string') {
|
||||
callback = RED.actions.get(callback);
|
||||
}
|
||||
if (callback) {
|
||||
callback.call(opt,value);
|
||||
}
|
||||
}
|
||||
function toggle(id) {
|
||||
var opt = allSettings[id];
|
||||
var currentEditorSettings = RED.settings.get('editor') || {};
|
||||
currentEditorSettings.view = currentEditorSettings.view || {};
|
||||
setSelected(id,!currentEditorSettings.view[opt.setting]);
|
||||
}
|
||||
|
||||
|
||||
function init() {
|
||||
RED.actions.add("core:show-user-settings",show);
|
||||
RED.actions.add("core:show-help", function() { show('keyboard')});
|
||||
|
||||
addPane({
|
||||
id:'view',
|
||||
title: RED._("menu.label.view.view"),
|
||||
get: createViewPane,
|
||||
close: function() {
|
||||
viewSettings.forEach(function(section) {
|
||||
section.options.forEach(function(opt) {
|
||||
var input = $("#user-settings-"+opt.setting);
|
||||
if (opt.toggle) {
|
||||
setSelected(opt.setting,input.prop('checked'));
|
||||
} else {
|
||||
setSelected(opt.setting,input.val());
|
||||
}
|
||||
});
|
||||
})
|
||||
}
|
||||
})
|
||||
|
||||
var currentEditorSettings = RED.settings.get('editor') || {};
|
||||
currentEditorSettings.view = currentEditorSettings.view || {};
|
||||
var editorSettingsChanged = false;
|
||||
viewSettings.forEach(function(section) {
|
||||
section.options.forEach(function(opt) {
|
||||
if (opt.oldSetting) {
|
||||
var oldValue = RED.settings.get(opt.oldSetting);
|
||||
if (oldValue !== undefined && oldValue !== null) {
|
||||
currentEditorSettings.view[opt.setting] = oldValue;
|
||||
editorSettingsChanged = true;
|
||||
RED.settings.remove(opt.oldSetting);
|
||||
}
|
||||
}
|
||||
allSettings[opt.setting] = opt;
|
||||
if (opt.onchange) {
|
||||
var value = currentEditorSettings.view[opt.setting];
|
||||
if ((value === null || value === undefined) && opt.hasOwnProperty('default')) {
|
||||
value = opt.default;
|
||||
currentEditorSettings.view[opt.setting] = value;
|
||||
editorSettingsChanged = true;
|
||||
}
|
||||
|
||||
var callback = opt.onchange;
|
||||
if (typeof callback === 'string') {
|
||||
callback = RED.actions.get(callback);
|
||||
}
|
||||
if (callback) {
|
||||
callback.call(opt,value);
|
||||
}
|
||||
}
|
||||
});
|
||||
});
|
||||
if (editorSettingsChanged) {
|
||||
RED.settings.set('editor',currentEditorSettings);
|
||||
}
|
||||
|
||||
}
|
||||
return {
|
||||
init: init,
|
||||
toggle: toggle,
|
||||
show: show,
|
||||
add: addPane
|
||||
};
|
||||
})();
|
||||
899
editor/js/ui/utils.js
Normal file
@@ -0,0 +1,899 @@
|
||||
/**
|
||||
* 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.utils = (function() {
|
||||
|
||||
function formatString(str) {
|
||||
return str.replace(/\r?\n/g,"↵").replace(/\t/g,"→");
|
||||
}
|
||||
function sanitize(m) {
|
||||
return m.replace(/&/g,"&").replace(/</g,"<").replace(/>/g,">");
|
||||
}
|
||||
|
||||
function buildMessageSummaryValue(value) {
|
||||
var result;
|
||||
if (Array.isArray(value)) {
|
||||
result = $('<span class="debug-message-object-value debug-message-type-meta"></span>').text('array['+value.length+']');
|
||||
} else if (value === null) {
|
||||
result = $('<span class="debug-message-object-value debug-message-type-null">null</span>');
|
||||
} else if (typeof value === 'object') {
|
||||
if (value.hasOwnProperty('type') && value.type === 'Buffer' && value.hasOwnProperty('data')) {
|
||||
result = $('<span class="debug-message-object-value debug-message-type-meta"></span>').text('buffer['+value.length+']');
|
||||
} else if (value.hasOwnProperty('type') && value.type === 'array' && value.hasOwnProperty('data')) {
|
||||
result = $('<span class="debug-message-object-value debug-message-type-meta"></span>').text('array['+value.length+']');
|
||||
} else if (value.hasOwnProperty('type') && value.type === 'function') {
|
||||
result = $('<span class="debug-message-object-value debug-message-type-meta"></span>').text('function');
|
||||
} else if (value.hasOwnProperty('type') && value.type === 'number') {
|
||||
result = $('<span class="debug-message-object-value debug-message-type-number"></span>').text(value.data);
|
||||
} else {
|
||||
result = $('<span class="debug-message-object-value debug-message-type-meta">object</span>');
|
||||
}
|
||||
} else if (typeof value === 'string') {
|
||||
var subvalue;
|
||||
if (value.length > 30) {
|
||||
subvalue = sanitize(value.substring(0,30))+"…";
|
||||
} else {
|
||||
subvalue = sanitize(value);
|
||||
}
|
||||
result = $('<span class="debug-message-object-value debug-message-type-string"></span>').html('"'+formatString(subvalue)+'"');
|
||||
} else if (typeof value === 'number') {
|
||||
result = $('<span class="debug-message-object-value debug-message-type-number"></span>').text(""+value);
|
||||
} else {
|
||||
result = $('<span class="debug-message-object-value debug-message-type-other"></span>').text(""+value);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
function makeExpandable(el,onbuild,ontoggle,expand) {
|
||||
el.addClass("debug-message-expandable");
|
||||
el.prop('toggle',function() {
|
||||
return function(state) {
|
||||
var parent = el.parent();
|
||||
if (parent.hasClass('collapsed')) {
|
||||
if (state) {
|
||||
if (onbuild && !parent.hasClass('built')) {
|
||||
onbuild();
|
||||
parent.addClass('built');
|
||||
}
|
||||
parent.removeClass('collapsed');
|
||||
return true;
|
||||
}
|
||||
} else {
|
||||
if (!state) {
|
||||
parent.addClass('collapsed');
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
});
|
||||
el.click(function(e) {
|
||||
var parent = $(this).parent();
|
||||
var currentState = !parent.hasClass('collapsed');
|
||||
if ($(this).prop('toggle')(!currentState)) {
|
||||
if (ontoggle) {
|
||||
ontoggle(!currentState);
|
||||
}
|
||||
}
|
||||
// if (parent.hasClass('collapsed')) {
|
||||
// if (onbuild && !parent.hasClass('built')) {
|
||||
// onbuild();
|
||||
// parent.addClass('built');
|
||||
// }
|
||||
// if (ontoggle) {
|
||||
// ontoggle(true);
|
||||
// }
|
||||
// parent.removeClass('collapsed');
|
||||
// } else {
|
||||
// parent.addClass('collapsed');
|
||||
// if (ontoggle) {
|
||||
// ontoggle(false);
|
||||
// }
|
||||
// }
|
||||
e.preventDefault();
|
||||
});
|
||||
if (expand) {
|
||||
el.click();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var pinnedPaths = {};
|
||||
var formattedPaths = {};
|
||||
|
||||
function addMessageControls(obj,sourceId,key,msg,rootPath,strippedKey) {
|
||||
if (!pinnedPaths.hasOwnProperty(sourceId)) {
|
||||
pinnedPaths[sourceId] = {}
|
||||
}
|
||||
var tools = $('<span class="debug-message-tools"></span>').appendTo(obj);
|
||||
var copyTools = $('<span class="debug-message-tools-copy button-group"></span>').appendTo(tools);
|
||||
if (!!key) {
|
||||
var copyPath = $('<button class="editor-button editor-button-small"><i class="fa fa-terminal"></i></button>').appendTo(copyTools).click(function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
RED.clipboard.copyText(key,copyPath,"clipboard.copyMessagePath");
|
||||
})
|
||||
}
|
||||
var copyPayload = $('<button class="editor-button editor-button-small"><i class="fa fa-clipboard"></i></button>').appendTo(copyTools).click(function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
RED.clipboard.copyText(msg,copyPayload,"clipboard.copyMessageValue");
|
||||
})
|
||||
if (strippedKey !== undefined && strippedKey !== '') {
|
||||
var isPinned = pinnedPaths[sourceId].hasOwnProperty(strippedKey);
|
||||
|
||||
var pinPath = $('<button class="editor-button editor-button-small debug-message-tools-pin"><i class="fa fa-map-pin"></i></button>').appendTo(tools).click(function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
if (pinnedPaths[sourceId].hasOwnProperty(strippedKey)) {
|
||||
delete pinnedPaths[sourceId][strippedKey];
|
||||
$(this).removeClass("selected");
|
||||
obj.removeClass("debug-message-row-pinned");
|
||||
} else {
|
||||
var rootedPath = "$"+(strippedKey[0] === '['?"":".")+strippedKey;
|
||||
pinnedPaths[sourceId][strippedKey] = normalisePropertyExpression(rootedPath);
|
||||
$(this).addClass("selected");
|
||||
obj.addClass("debug-message-row-pinned");
|
||||
}
|
||||
}).toggleClass("selected",isPinned);
|
||||
obj.toggleClass("debug-message-row-pinned",isPinned);
|
||||
}
|
||||
}
|
||||
function checkExpanded(strippedKey,expandPaths,minRange,maxRange) {
|
||||
if (expandPaths && expandPaths.length > 0) {
|
||||
if (strippedKey === '' && minRange === undefined) {
|
||||
return true;
|
||||
}
|
||||
for (var i=0;i<expandPaths.length;i++) {
|
||||
var p = expandPaths[i];
|
||||
if (p.indexOf(strippedKey) === 0 && (p[strippedKey.length] === "." || p[strippedKey.length] === "[") ) {
|
||||
|
||||
if (minRange !== undefined && p[strippedKey.length] === "[") {
|
||||
var subkey = p.substring(strippedKey.length);
|
||||
var m = (/\[(\d+)\]/.exec(subkey));
|
||||
if (m) {
|
||||
var index = parseInt(m[1]);
|
||||
return minRange<=index && index<=maxRange;
|
||||
}
|
||||
} else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
function formatNumber(element,obj,sourceId,path,cycle,initialFormat) {
|
||||
var format = (formattedPaths[sourceId] && formattedPaths[sourceId][path] && formattedPaths[sourceId][path]['number']) || initialFormat || "dec";
|
||||
if (cycle) {
|
||||
if (format === 'dec') {
|
||||
if ((obj.toString().length===13) && (obj<=2147483647000)) {
|
||||
format = 'dateMS';
|
||||
} else if ((obj.toString().length===10) && (obj<=2147483647)) {
|
||||
format = 'dateS';
|
||||
} else {
|
||||
format = 'hex'
|
||||
}
|
||||
} else if (format === 'dateMS' || format == 'dateS') {
|
||||
format = 'hex';
|
||||
} else {
|
||||
format = 'dec';
|
||||
}
|
||||
formattedPaths[sourceId] = formattedPaths[sourceId]||{};
|
||||
formattedPaths[sourceId][path] = formattedPaths[sourceId][path]||{};
|
||||
formattedPaths[sourceId][path]['number'] = format;
|
||||
} else if (initialFormat !== undefined){
|
||||
formattedPaths[sourceId] = formattedPaths[sourceId]||{};
|
||||
formattedPaths[sourceId][path] = formattedPaths[sourceId][path]||{};
|
||||
formattedPaths[sourceId][path]['number'] = format;
|
||||
}
|
||||
if (format === 'dec') {
|
||||
element.text(""+obj);
|
||||
} else if (format === 'dateMS') {
|
||||
element.text((new Date(obj)).toISOString());
|
||||
} else if (format === 'dateS') {
|
||||
element.text((new Date(obj*1000)).toISOString());
|
||||
} else if (format === 'hex') {
|
||||
element.text("0x"+(obj).toString(16));
|
||||
}
|
||||
}
|
||||
|
||||
function formatBuffer(element,button,sourceId,path,cycle) {
|
||||
var format = (formattedPaths[sourceId] && formattedPaths[sourceId][path] && formattedPaths[sourceId][path]['buffer']) || "raw";
|
||||
if (cycle) {
|
||||
if (format === 'raw') {
|
||||
format = 'string';
|
||||
} else {
|
||||
format = 'raw';
|
||||
}
|
||||
formattedPaths[sourceId] = formattedPaths[sourceId]||{};
|
||||
formattedPaths[sourceId][path] = formattedPaths[sourceId][path]||{};
|
||||
formattedPaths[sourceId][path]['buffer'] = format;
|
||||
}
|
||||
if (format === 'raw') {
|
||||
button.text('raw');
|
||||
element.removeClass('debug-message-buffer-string').addClass('debug-message-buffer-raw');
|
||||
} else if (format === 'string') {
|
||||
button.text('string');
|
||||
element.addClass('debug-message-buffer-string').removeClass('debug-message-buffer-raw');
|
||||
}
|
||||
}
|
||||
|
||||
function buildMessageElement(obj,options) {
|
||||
options = options || {};
|
||||
var key = options.key;
|
||||
var typeHint = options.typeHint;
|
||||
var hideKey = options.hideKey;
|
||||
var path = options.path;
|
||||
var sourceId = options.sourceId;
|
||||
var rootPath = options.rootPath;
|
||||
var expandPaths = options.expandPaths;
|
||||
var ontoggle = options.ontoggle;
|
||||
var exposeApi = options.exposeApi;
|
||||
|
||||
var subElements = {};
|
||||
var i;
|
||||
var e;
|
||||
var entryObj;
|
||||
var expandableHeader;
|
||||
var header;
|
||||
var headerHead;
|
||||
var value;
|
||||
var strippedKey;
|
||||
if (path !== undefined && rootPath !== undefined) {
|
||||
strippedKey = path.substring(rootPath.length+(path[rootPath.length]==="."?1:0));
|
||||
}
|
||||
var element = $('<span class="debug-message-element"></span>');
|
||||
element.collapse = function() {
|
||||
element.find(".debug-message-expandable").parent().addClass("collapsed");
|
||||
}
|
||||
header = $('<span class="debug-message-row"></span>').appendTo(element);
|
||||
if (sourceId) {
|
||||
addMessageControls(header,sourceId,path,obj,rootPath,strippedKey);
|
||||
}
|
||||
if (!key) {
|
||||
element.addClass("debug-message-top-level");
|
||||
if (sourceId) {
|
||||
var pinned = pinnedPaths[sourceId];
|
||||
expandPaths = [];
|
||||
if (pinned) {
|
||||
for (var pinnedPath in pinned) {
|
||||
if (pinned.hasOwnProperty(pinnedPath)) {
|
||||
try {
|
||||
var res = getMessageProperty({$:obj},pinned[pinnedPath]);
|
||||
if (res !== undefined) {
|
||||
expandPaths.push(pinnedPath);
|
||||
}
|
||||
} catch(err) {
|
||||
}
|
||||
}
|
||||
}
|
||||
expandPaths.sort();
|
||||
}
|
||||
element.clearPinned = function() {
|
||||
element.find(".debug-message-row-pinned").removeClass("debug-message-row-pinned");
|
||||
pinnedPaths[sourceId] = {};
|
||||
}
|
||||
}
|
||||
} else {
|
||||
if (!hideKey) {
|
||||
$('<span class="debug-message-object-key"></span>').text(key).appendTo(header);
|
||||
$('<span>: </span>').appendTo(header);
|
||||
}
|
||||
}
|
||||
entryObj = $('<span class="debug-message-object-value"></span>').appendTo(header);
|
||||
|
||||
var isArray = Array.isArray(obj);
|
||||
var isArrayObject = false;
|
||||
if (obj && typeof obj === 'object' && obj.hasOwnProperty('type') && obj.hasOwnProperty('data') && ((obj.__enc__ && obj.type === 'array') || obj.type === 'Buffer')) {
|
||||
isArray = true;
|
||||
isArrayObject = true;
|
||||
}
|
||||
if (obj === null || obj === undefined) {
|
||||
$('<span class="debug-message-type-null">'+obj+'</span>').appendTo(entryObj);
|
||||
} else if (obj.__enc__ && obj.type === 'number') {
|
||||
e = $('<span class="debug-message-type-number debug-message-object-header"></span>').text(obj.data).appendTo(entryObj);
|
||||
} else if (typeHint === "function" || (obj.__enc__ && obj.type === 'function')) {
|
||||
e = $('<span class="debug-message-type-meta debug-message-object-header"></span>').text("function").appendTo(entryObj);
|
||||
} else if (typeHint === "internal" || (obj.__enc__ && obj.type === 'internal')) {
|
||||
e = $('<span class="debug-message-type-meta debug-message-object-header"></span>').text("[internal]").appendTo(entryObj);
|
||||
} else if (typeof obj === 'string') {
|
||||
if (/[\t\n\r]/.test(obj)) {
|
||||
element.addClass('collapsed');
|
||||
$('<i class="fa fa-caret-right debug-message-object-handle"></i> ').prependTo(header);
|
||||
makeExpandable(header, function() {
|
||||
$('<span class="debug-message-type-meta debug-message-object-type-header"></span>').text(typeHint||'string').appendTo(header);
|
||||
var row = $('<div class="debug-message-object-entry collapsed"></div>').appendTo(element);
|
||||
$('<pre class="debug-message-type-string"></pre>').text(obj).appendTo(row);
|
||||
},function(state) {if (ontoggle) { ontoggle(path,state);}}, checkExpanded(strippedKey,expandPaths));
|
||||
}
|
||||
e = $('<span class="debug-message-type-string debug-message-object-header"></span>').html('"'+formatString(sanitize(obj))+'"').appendTo(entryObj);
|
||||
if (/^#[0-9a-f]{6}$/i.test(obj)) {
|
||||
$('<span class="debug-message-type-string-swatch"></span>').css('backgroundColor',obj).appendTo(e);
|
||||
}
|
||||
|
||||
} else if (typeof obj === 'number') {
|
||||
e = $('<span class="debug-message-type-number"></span>').appendTo(entryObj);
|
||||
|
||||
if (Number.isInteger(obj) && (obj >= 0)) { // if it's a +ve integer
|
||||
e.addClass("debug-message-type-number-toggle");
|
||||
e.click(function(evt) {
|
||||
evt.preventDefault();
|
||||
formatNumber($(this), obj, sourceId, path, true);
|
||||
});
|
||||
}
|
||||
formatNumber(e,obj,sourceId,path,false,typeHint==='hex'?'hex':undefined);
|
||||
|
||||
} else if (isArray) {
|
||||
element.addClass('collapsed');
|
||||
|
||||
var originalLength = obj.length;
|
||||
if (typeHint) {
|
||||
var m = /\[(\d+)\]/.exec(typeHint);
|
||||
if (m) {
|
||||
originalLength = parseInt(m[1]);
|
||||
}
|
||||
}
|
||||
var data = obj;
|
||||
var type = 'array';
|
||||
if (isArrayObject) {
|
||||
data = obj.data;
|
||||
if (originalLength === undefined) {
|
||||
originalLength = data.length;
|
||||
}
|
||||
if (data.__enc__) {
|
||||
data = data.data;
|
||||
}
|
||||
type = obj.type.toLowerCase();
|
||||
} else if (/buffer/.test(typeHint)) {
|
||||
type = 'buffer';
|
||||
}
|
||||
var fullLength = data.length;
|
||||
|
||||
if (originalLength > 0) {
|
||||
$('<i class="fa fa-caret-right debug-message-object-handle"></i> ').prependTo(header);
|
||||
var arrayRows = $('<div class="debug-message-array-rows"></div>').appendTo(element);
|
||||
element.addClass('debug-message-buffer-raw');
|
||||
}
|
||||
if (key) {
|
||||
headerHead = $('<span class="debug-message-type-meta"></span>').text(typeHint||(type+'['+originalLength+']')).appendTo(entryObj);
|
||||
} else {
|
||||
headerHead = $('<span class="debug-message-object-header"></span>').appendTo(entryObj);
|
||||
$('<span>[ </span>').appendTo(headerHead);
|
||||
var arrayLength = Math.min(originalLength,10);
|
||||
for (i=0;i<arrayLength;i++) {
|
||||
buildMessageSummaryValue(data[i]).appendTo(headerHead);
|
||||
if (i < arrayLength-1) {
|
||||
$('<span>, </span>').appendTo(headerHead);
|
||||
}
|
||||
}
|
||||
if (originalLength > arrayLength) {
|
||||
$('<span> …</span>').appendTo(headerHead);
|
||||
}
|
||||
if (arrayLength === 0) {
|
||||
$('<span class="debug-message-type-meta">empty</span>').appendTo(headerHead);
|
||||
}
|
||||
$('<span> ]</span>').appendTo(headerHead);
|
||||
}
|
||||
if (originalLength > 0) {
|
||||
|
||||
makeExpandable(header,function() {
|
||||
if (!key) {
|
||||
headerHead = $('<span class="debug-message-type-meta debug-message-object-type-header"></span>').text(typeHint||(type+'['+originalLength+']')).appendTo(header);
|
||||
}
|
||||
if (type === 'buffer') {
|
||||
var stringRow = $('<div class="debug-message-string-rows"></div>').appendTo(element);
|
||||
var sr = $('<div class="debug-message-object-entry collapsed"></div>').appendTo(stringRow);
|
||||
var stringEncoding = "";
|
||||
try {
|
||||
stringEncoding = String.fromCharCode.apply(null, new Uint16Array(data))
|
||||
} catch(err) {
|
||||
console.log(err);
|
||||
}
|
||||
$('<pre class="debug-message-type-string"></pre>').text(stringEncoding).appendTo(sr);
|
||||
var bufferOpts = $('<span class="debug-message-buffer-opts"></span>').appendTo(headerHead);
|
||||
var switchFormat = $('<a href="#"></a>').addClass('selected').text('raw').appendTo(bufferOpts).click(function(e) {
|
||||
e.preventDefault();
|
||||
e.stopPropagation();
|
||||
formatBuffer(element,$(this),sourceId,path,true);
|
||||
});
|
||||
formatBuffer(element,switchFormat,sourceId,path,false);
|
||||
|
||||
}
|
||||
var row;
|
||||
if (fullLength <= 10) {
|
||||
for (i=0;i<fullLength;i++) {
|
||||
row = $('<div class="debug-message-object-entry collapsed"></div>').appendTo(arrayRows);
|
||||
subElements[path+"["+i+"]"] = buildMessageElement(
|
||||
data[i],
|
||||
{
|
||||
key: ""+i,
|
||||
typeHint: type==='buffer'?'hex':false,
|
||||
hideKey: false,
|
||||
path: path+"["+i+"]",
|
||||
sourceId: sourceId,
|
||||
rootPath: rootPath,
|
||||
expandPaths: expandPaths,
|
||||
ontoggle: ontoggle,
|
||||
exposeApi: exposeApi
|
||||
}
|
||||
).appendTo(row);
|
||||
}
|
||||
} else {
|
||||
for (i=0;i<fullLength;i+=10) {
|
||||
var minRange = i;
|
||||
row = $('<div class="debug-message-object-entry collapsed"></div>').appendTo(arrayRows);
|
||||
header = $('<span></span>').appendTo(row);
|
||||
$('<i class="fa fa-caret-right debug-message-object-handle"></i> ').appendTo(header);
|
||||
makeExpandable(header, (function() {
|
||||
var min = minRange;
|
||||
var max = Math.min(fullLength-1,(minRange+9));
|
||||
var parent = row;
|
||||
return function() {
|
||||
for (var i=min;i<=max;i++) {
|
||||
var row = $('<div class="debug-message-object-entry collapsed"></div>').appendTo(parent);
|
||||
subElements[path+"["+i+"]"] = buildMessageElement(
|
||||
data[i],
|
||||
{
|
||||
key: ""+i,
|
||||
typeHint: type==='buffer'?'hex':false,
|
||||
hideKey: false,
|
||||
path: path+"["+i+"]",
|
||||
sourceId: sourceId,
|
||||
rootPath: rootPath,
|
||||
expandPaths: expandPaths,
|
||||
ontoggle: ontoggle,
|
||||
exposeApi: exposeApi
|
||||
|
||||
}
|
||||
).appendTo(row);
|
||||
}
|
||||
}
|
||||
})(),
|
||||
(function() { var path = path+"["+i+"]"; return function(state) {if (ontoggle) { ontoggle(path,state);}}})(),
|
||||
checkExpanded(strippedKey,expandPaths,minRange,Math.min(fullLength-1,(minRange+9))));
|
||||
$('<span class="debug-message-object-key"></span>').html("["+minRange+" … "+Math.min(fullLength-1,(minRange+9))+"]").appendTo(header);
|
||||
}
|
||||
if (fullLength < originalLength) {
|
||||
$('<div class="debug-message-object-entry collapsed"><span class="debug-message-object-key">['+fullLength+' … '+originalLength+']</span></div>').appendTo(arrayRows);
|
||||
}
|
||||
}
|
||||
},
|
||||
function(state) {if (ontoggle) { ontoggle(path,state);}},
|
||||
checkExpanded(strippedKey,expandPaths));
|
||||
}
|
||||
} else if (typeof obj === 'object') {
|
||||
element.addClass('collapsed');
|
||||
var keys = Object.keys(obj);
|
||||
if (key || keys.length > 0) {
|
||||
$('<i class="fa fa-caret-right debug-message-object-handle"></i> ').prependTo(header);
|
||||
makeExpandable(header, function() {
|
||||
if (!key) {
|
||||
$('<span class="debug-message-type-meta debug-message-object-type-header"></span>').text('object').appendTo(header);
|
||||
}
|
||||
for (i=0;i<keys.length;i++) {
|
||||
var row = $('<div class="debug-message-object-entry collapsed"></div>').appendTo(element);
|
||||
var newPath = path;
|
||||
if (newPath !== undefined) {
|
||||
if (/^[a-zA-Z_$][0-9a-zA-Z_$]*$/.test(keys[i])) {
|
||||
newPath += (newPath.length > 0?".":"")+keys[i];
|
||||
} else {
|
||||
newPath += "[\""+keys[i].replace(/"/,"\\\"")+"\"]"
|
||||
}
|
||||
}
|
||||
subElements[newPath] = buildMessageElement(
|
||||
obj[keys[i]],
|
||||
{
|
||||
key: keys[i],
|
||||
typeHint: false,
|
||||
hideKey: false,
|
||||
path: newPath,
|
||||
sourceId: sourceId,
|
||||
rootPath: rootPath,
|
||||
expandPaths: expandPaths,
|
||||
ontoggle: ontoggle,
|
||||
exposeApi: exposeApi
|
||||
|
||||
}
|
||||
).appendTo(row);
|
||||
}
|
||||
if (keys.length === 0) {
|
||||
$('<div class="debug-message-object-entry debug-message-type-meta collapsed"></div>').text("empty").appendTo(element);
|
||||
}
|
||||
},
|
||||
function(state) {if (ontoggle) { ontoggle(path,state);}},
|
||||
checkExpanded(strippedKey,expandPaths));
|
||||
}
|
||||
if (key) {
|
||||
$('<span class="debug-message-type-meta"></span>').text('object').appendTo(entryObj);
|
||||
} else {
|
||||
headerHead = $('<span class="debug-message-object-header"></span>').appendTo(entryObj);
|
||||
$('<span>{ </span>').appendTo(headerHead);
|
||||
var keysLength = Math.min(keys.length,5);
|
||||
for (i=0;i<keysLength;i++) {
|
||||
$('<span class="debug-message-object-key"></span>').text(keys[i]).appendTo(headerHead);
|
||||
$('<span>: </span>').appendTo(headerHead);
|
||||
buildMessageSummaryValue(obj[keys[i]]).appendTo(headerHead);
|
||||
if (i < keysLength-1) {
|
||||
$('<span>, </span>').appendTo(headerHead);
|
||||
}
|
||||
}
|
||||
if (keys.length > keysLength) {
|
||||
$('<span> …</span>').appendTo(headerHead);
|
||||
}
|
||||
if (keysLength === 0) {
|
||||
$('<span class="debug-message-type-meta">empty</span>').appendTo(headerHead);
|
||||
}
|
||||
$('<span> }</span>').appendTo(headerHead);
|
||||
}
|
||||
} else {
|
||||
$('<span class="debug-message-type-other"></span>').text(""+obj).appendTo(entryObj);
|
||||
}
|
||||
if (exposeApi) {
|
||||
element.prop('expand', function() { return function(targetPath, state) {
|
||||
if (path === targetPath) {
|
||||
if (header.prop('toggle')) {
|
||||
header.prop('toggle')(state);
|
||||
}
|
||||
} else if (subElements[targetPath] && subElements[targetPath].prop('expand') ) {
|
||||
subElements[targetPath].prop('expand')(targetPath,state);
|
||||
} else {
|
||||
for (var p in subElements) {
|
||||
if (subElements.hasOwnProperty(p)) {
|
||||
if (targetPath.indexOf(p) === 0) {
|
||||
if (subElements[p].prop('expand') ) {
|
||||
subElements[p].prop('expand')(targetPath,state);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}});
|
||||
}
|
||||
return element;
|
||||
}
|
||||
|
||||
function normalisePropertyExpression(str) {
|
||||
// This must be kept in sync with validatePropertyExpression
|
||||
// in editor/js/ui/utils.js
|
||||
|
||||
var length = str.length;
|
||||
if (length === 0) {
|
||||
throw new Error("Invalid property expression: zero-length");
|
||||
}
|
||||
var parts = [];
|
||||
var start = 0;
|
||||
var inString = false;
|
||||
var inBox = false;
|
||||
var quoteChar;
|
||||
var v;
|
||||
for (var i=0;i<length;i++) {
|
||||
var c = str[i];
|
||||
if (!inString) {
|
||||
if (c === "'" || c === '"') {
|
||||
if (i != start) {
|
||||
throw new Error("Invalid property expression: unexpected "+c+" at position "+i);
|
||||
}
|
||||
inString = true;
|
||||
quoteChar = c;
|
||||
start = i+1;
|
||||
} else if (c === '.') {
|
||||
if (i===0) {
|
||||
throw new Error("Invalid property expression: unexpected . at position 0");
|
||||
}
|
||||
if (start != i) {
|
||||
v = str.substring(start,i);
|
||||
if (/^\d+$/.test(v)) {
|
||||
parts.push(parseInt(v));
|
||||
} else {
|
||||
parts.push(v);
|
||||
}
|
||||
}
|
||||
if (i===length-1) {
|
||||
throw new Error("Invalid property expression: unterminated expression");
|
||||
}
|
||||
// Next char is first char of an identifier: a-z 0-9 $ _
|
||||
if (!/[a-z0-9\$\_]/i.test(str[i+1])) {
|
||||
throw new Error("Invalid property expression: unexpected "+str[i+1]+" at position "+(i+1));
|
||||
}
|
||||
start = i+1;
|
||||
} else if (c === '[') {
|
||||
if (i === 0) {
|
||||
throw new Error("Invalid property expression: unexpected "+c+" at position "+i);
|
||||
}
|
||||
if (start != i) {
|
||||
parts.push(str.substring(start,i));
|
||||
}
|
||||
if (i===length-1) {
|
||||
throw new Error("Invalid property expression: unterminated expression");
|
||||
}
|
||||
// Next char is either a quote or a number
|
||||
if (!/["'\d]/.test(str[i+1])) {
|
||||
throw new Error("Invalid property expression: unexpected "+str[i+1]+" at position "+(i+1));
|
||||
}
|
||||
start = i+1;
|
||||
inBox = true;
|
||||
} else if (c === ']') {
|
||||
if (!inBox) {
|
||||
throw new Error("Invalid property expression: unexpected "+c+" at position "+i);
|
||||
}
|
||||
if (start != i) {
|
||||
v = str.substring(start,i);
|
||||
if (/^\d+$/.test(v)) {
|
||||
parts.push(parseInt(v));
|
||||
} else {
|
||||
throw new Error("Invalid property expression: unexpected array expression at position "+start);
|
||||
}
|
||||
}
|
||||
start = i+1;
|
||||
inBox = false;
|
||||
} else if (c === ' ') {
|
||||
throw new Error("Invalid property expression: unexpected ' ' at position "+i);
|
||||
}
|
||||
} else {
|
||||
if (c === quoteChar) {
|
||||
if (i-start === 0) {
|
||||
throw new Error("Invalid property expression: zero-length string at position "+start);
|
||||
}
|
||||
parts.push(str.substring(start,i));
|
||||
// If inBox, next char must be a ]. Otherwise it may be [ or .
|
||||
if (inBox && !/\]/.test(str[i+1])) {
|
||||
throw new Error("Invalid property expression: unexpected array expression at position "+start);
|
||||
} else if (!inBox && i+1!==length && !/[\[\.]/.test(str[i+1])) {
|
||||
throw new Error("Invalid property expression: unexpected "+str[i+1]+" expression at position "+(i+1));
|
||||
}
|
||||
start = i+1;
|
||||
inString = false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
if (inBox || inString) {
|
||||
throw new Error("Invalid property expression: unterminated expression");
|
||||
}
|
||||
if (start < length) {
|
||||
parts.push(str.substring(start));
|
||||
}
|
||||
return parts;
|
||||
}
|
||||
|
||||
function validatePropertyExpression(str) {
|
||||
try {
|
||||
var parts = normalisePropertyExpression(str);
|
||||
return true;
|
||||
} catch(err) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getMessageProperty(msg,expr) {
|
||||
var result = null;
|
||||
var msgPropParts;
|
||||
|
||||
if (typeof expr === 'string') {
|
||||
if (expr.indexOf('msg.')===0) {
|
||||
expr = expr.substring(4);
|
||||
}
|
||||
msgPropParts = normalisePropertyExpression(expr);
|
||||
} else {
|
||||
msgPropParts = expr;
|
||||
}
|
||||
var m;
|
||||
msgPropParts.reduce(function(obj, key) {
|
||||
result = (typeof obj[key] !== "undefined" ? obj[key] : undefined);
|
||||
if (result === undefined && obj.hasOwnProperty('type') && obj.hasOwnProperty('data')&& obj.hasOwnProperty('length')) {
|
||||
result = (typeof obj.data[key] !== "undefined" ? obj.data[key] : undefined);
|
||||
}
|
||||
return result;
|
||||
}, msg);
|
||||
return result;
|
||||
}
|
||||
|
||||
function separateIconPath(icon) {
|
||||
var result = {module: "", file: ""};
|
||||
if (icon) {
|
||||
var index = icon.indexOf('/');
|
||||
if (index !== -1) {
|
||||
result.module = icon.slice(0, index);
|
||||
result.file = icon.slice(index + 1);
|
||||
} else {
|
||||
result.file = icon;
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
function getDefaultNodeIcon(def,node) {
|
||||
var icon_url;
|
||||
if (node && node.type === "subflow") {
|
||||
icon_url = "node-red/subflow.png";
|
||||
} else if (typeof def.icon === "function") {
|
||||
try {
|
||||
icon_url = def.icon.call(node);
|
||||
} catch(err) {
|
||||
console.log("Definition error: "+def.type+".icon",err);
|
||||
icon_url = "arrow-in.png";
|
||||
}
|
||||
} else {
|
||||
icon_url = def.icon;
|
||||
}
|
||||
|
||||
var iconPath = separateIconPath(icon_url);
|
||||
if (!iconPath.module) {
|
||||
if (def.set) {
|
||||
iconPath.module = def.set.module;
|
||||
} else {
|
||||
// Handle subflow instance nodes that don't have def.set
|
||||
iconPath.module = "node-red";
|
||||
}
|
||||
}
|
||||
return iconPath;
|
||||
}
|
||||
|
||||
function isIconExists(iconPath) {
|
||||
var iconSets = RED.nodes.getIconSets();
|
||||
var iconFileList = iconSets[iconPath.module];
|
||||
if (iconFileList && iconFileList.indexOf(iconPath.file) !== -1) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
function getNodeIcon(def,node) {
|
||||
if (def.category === 'config') {
|
||||
return "icons/node-red/cog.png"
|
||||
} else if (node && node.type === 'tab') {
|
||||
return "icons/node-red/subflow.png"
|
||||
} else if (node && node.type === 'unknown') {
|
||||
return "icons/node-red/alert.png"
|
||||
} else if (node && node.icon) {
|
||||
var iconPath = separateIconPath(node.icon);
|
||||
if (isIconExists(iconPath)) {
|
||||
return "icons/" + node.icon;
|
||||
}
|
||||
}
|
||||
|
||||
var iconPath = getDefaultNodeIcon(def, node);
|
||||
if (def.category === 'subflows') {
|
||||
if (!isIconExists(iconPath)) {
|
||||
return "icons/node-red/subflow.png";
|
||||
}
|
||||
}
|
||||
return "icons/"+iconPath.module+"/"+iconPath.file;
|
||||
}
|
||||
|
||||
function getNodeLabel(node,defaultLabel) {
|
||||
defaultLabel = defaultLabel||"";
|
||||
var l;
|
||||
if (node.type === 'tab') {
|
||||
l = node.label || defaultLabel
|
||||
} else {
|
||||
l = node._def.label;
|
||||
try {
|
||||
l = (typeof l === "function" ? l.call(node) : l)||defaultLabel;
|
||||
} catch(err) {
|
||||
console.log("Definition error: "+node.type+".label",err);
|
||||
l = defaultLabel;
|
||||
}
|
||||
}
|
||||
return RED.text.bidi.enforceTextDirectionWithUCC(l);
|
||||
}
|
||||
|
||||
var nodeColorCache = {};
|
||||
function getNodeColor(type, def) {
|
||||
var result = def.color;
|
||||
var paletteTheme = RED.settings.theme('palette.theme') || [];
|
||||
if (paletteTheme.length > 0) {
|
||||
if (!nodeColorCache.hasOwnProperty(type)) {
|
||||
nodeColorCache[type] = def.color;
|
||||
var l = paletteTheme.length;
|
||||
for (var i = 0; i < l; i++ ){
|
||||
var themeRule = paletteTheme[i];
|
||||
if (themeRule.hasOwnProperty('category')) {
|
||||
if (!themeRule.hasOwnProperty('_category')) {
|
||||
themeRule._category = new RegExp(themeRule.category);
|
||||
}
|
||||
if (!themeRule._category.test(def.category)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
if (themeRule.hasOwnProperty('type')) {
|
||||
if (!themeRule.hasOwnProperty('_type')) {
|
||||
themeRule._type = new RegExp(themeRule.type);
|
||||
}
|
||||
if (!themeRule._type.test(type)) {
|
||||
continue;
|
||||
}
|
||||
}
|
||||
nodeColorCache[type] = themeRule.color || def.color;
|
||||
break;
|
||||
}
|
||||
}
|
||||
result = nodeColorCache[type];
|
||||
}
|
||||
if (result) {
|
||||
return result;
|
||||
} else {
|
||||
return "#ddd";
|
||||
}
|
||||
}
|
||||
|
||||
function addSpinnerOverlay(container,contain) {
|
||||
var spinner = $('<div class="projects-dialog-spinner "><img src="red/images/spin.svg"/></div>').appendTo(container);
|
||||
if (contain) {
|
||||
spinner.addClass('projects-dialog-spinner-contain');
|
||||
}
|
||||
return spinner;
|
||||
}
|
||||
|
||||
function decodeObject(payload,format) {
|
||||
if ((format === 'number') && (payload === "NaN")) {
|
||||
payload = Number.NaN;
|
||||
} else if ((format === 'number') && (payload === "Infinity")) {
|
||||
payload = Infinity;
|
||||
} else if ((format === 'number') && (payload === "-Infinity")) {
|
||||
payload = -Infinity;
|
||||
} else if (format === 'Object' || /^array/.test(format) || format === 'boolean' || format === 'number' ) {
|
||||
payload = JSON.parse(payload);
|
||||
} else if (/error/i.test(format)) {
|
||||
payload = JSON.parse(payload);
|
||||
payload = (payload.name?payload.name+": ":"")+payload.message;
|
||||
} else if (format === 'null') {
|
||||
payload = null;
|
||||
} else if (format === 'undefined') {
|
||||
payload = undefined;
|
||||
} else if (/^buffer/.test(format)) {
|
||||
var buffer = payload;
|
||||
payload = [];
|
||||
for (var c = 0; c < buffer.length; c += 2) {
|
||||
payload.push(parseInt(buffer.substr(c, 2), 16));
|
||||
}
|
||||
}
|
||||
return payload;
|
||||
}
|
||||
|
||||
function parseContextKey(key) {
|
||||
var parts = {};
|
||||
var m = /^#:\((\S+?)\)::(.*)$/.exec(key);
|
||||
if (m) {
|
||||
parts.store = m[1];
|
||||
parts.key = m[2];
|
||||
} else {
|
||||
parts.key = key;
|
||||
if (RED.settings.context) {
|
||||
parts.store = RED.settings.context.default;
|
||||
}
|
||||
}
|
||||
return parts;
|
||||
}
|
||||
|
||||
return {
|
||||
createObjectElement: buildMessageElement,
|
||||
getMessageProperty: getMessageProperty,
|
||||
normalisePropertyExpression: normalisePropertyExpression,
|
||||
validatePropertyExpression: validatePropertyExpression,
|
||||
separateIconPath: separateIconPath,
|
||||
getDefaultNodeIcon: getDefaultNodeIcon,
|
||||
getNodeIcon: getNodeIcon,
|
||||
getNodeLabel: getNodeLabel,
|
||||
getNodeColor: getNodeColor,
|
||||
addSpinnerOverlay: addSpinnerOverlay,
|
||||
decodeObject: decodeObject,
|
||||
parseContextKey: parseContextKey
|
||||
}
|
||||
})();
|
||||
168
editor/js/ui/view-navigator.js
Normal file
@@ -0,0 +1,168 @@
|
||||
/**
|
||||
* Copyright 2016 IBM Corp.
|
||||
*
|
||||
* 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.view.navigator = (function() {
|
||||
|
||||
var nav_scale = 25;
|
||||
var nav_width = 5000/nav_scale;
|
||||
var nav_height = 5000/nav_scale;
|
||||
|
||||
var navContainer;
|
||||
var navBox;
|
||||
var navBorder;
|
||||
var navVis;
|
||||
var scrollPos;
|
||||
var scaleFactor;
|
||||
var chartSize;
|
||||
var dimensions;
|
||||
var isDragging;
|
||||
var isShowing = false;
|
||||
|
||||
function refreshNodes() {
|
||||
if (!isShowing) {
|
||||
return;
|
||||
}
|
||||
var navNode = navVis.selectAll(".navnode").data(RED.view.getActiveNodes(),function(d){return d.id});
|
||||
navNode.exit().remove();
|
||||
navNode.enter().insert("rect")
|
||||
.attr('class','navnode')
|
||||
.attr("pointer-events", "none");
|
||||
navNode.each(function(d) {
|
||||
d3.select(this).attr("x",function(d) { return (d.x-d.w/2)/nav_scale })
|
||||
.attr("y",function(d) { return (d.y-d.h/2)/nav_scale })
|
||||
.attr("width",function(d) { return Math.max(9,d.w/nav_scale) })
|
||||
.attr("height",function(d) { return Math.max(3,d.h/nav_scale) })
|
||||
.attr("fill",function(d) { return RED.utils.getNodeColor(d.type,d._def);})
|
||||
});
|
||||
}
|
||||
function onScroll() {
|
||||
if (!isDragging) {
|
||||
resizeNavBorder();
|
||||
}
|
||||
}
|
||||
function resizeNavBorder() {
|
||||
if (navBorder) {
|
||||
scaleFactor = RED.view.scale();
|
||||
chartSize = [ $("#chart").width(), $("#chart").height()];
|
||||
scrollPos = [$("#chart").scrollLeft(),$("#chart").scrollTop()];
|
||||
navBorder.attr('x',scrollPos[0]/nav_scale)
|
||||
.attr('y',scrollPos[1]/nav_scale)
|
||||
.attr('width',chartSize[0]/nav_scale/scaleFactor)
|
||||
.attr('height',chartSize[1]/nav_scale/scaleFactor)
|
||||
}
|
||||
}
|
||||
function toggle() {
|
||||
if (!isShowing) {
|
||||
isShowing = true;
|
||||
$("#btn-navigate").addClass("selected");
|
||||
resizeNavBorder();
|
||||
refreshNodes();
|
||||
$("#chart").on("scroll",onScroll);
|
||||
navContainer.fadeIn(200);
|
||||
} else {
|
||||
isShowing = false;
|
||||
navContainer.fadeOut(100);
|
||||
$("#chart").off("scroll",onScroll);
|
||||
$("#btn-navigate").removeClass("selected");
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
init: function() {
|
||||
|
||||
$(window).resize(resizeNavBorder);
|
||||
RED.events.on("sidebar:resize",resizeNavBorder);
|
||||
RED.actions.add("core:toggle-navigator",toggle);
|
||||
var hideTimeout;
|
||||
|
||||
navContainer = $('<div>').css({
|
||||
"position":"absolute",
|
||||
"bottom":$("#workspace-footer").height(),
|
||||
"right":0,
|
||||
zIndex: 1
|
||||
}).appendTo("#workspace").hide();
|
||||
|
||||
navBox = d3.select(navContainer[0])
|
||||
.append("svg:svg")
|
||||
.attr("width", nav_width)
|
||||
.attr("height", nav_height)
|
||||
.attr("pointer-events", "all")
|
||||
.style({
|
||||
position: "absolute",
|
||||
bottom: 0,
|
||||
right:0,
|
||||
zIndex: 101,
|
||||
"border-left": "1px solid #ccc",
|
||||
"border-top": "1px solid #ccc",
|
||||
background: "rgba(245,245,245,0.5)",
|
||||
"box-shadow": "-1px 0 3px rgba(0,0,0,0.1)"
|
||||
});
|
||||
|
||||
navBox.append("rect").attr("x",0).attr("y",0).attr("width",nav_width).attr("height",nav_height).style({
|
||||
fill:"none",
|
||||
stroke:"none",
|
||||
pointerEvents:"all"
|
||||
}).on("mousedown", function() {
|
||||
// Update these in case they have changed
|
||||
scaleFactor = RED.view.scale();
|
||||
chartSize = [ $("#chart").width(), $("#chart").height()];
|
||||
dimensions = [chartSize[0]/nav_scale/scaleFactor, chartSize[1]/nav_scale/scaleFactor];
|
||||
var newX = Math.max(0,Math.min(d3.event.offsetX+dimensions[0]/2,nav_width)-dimensions[0]);
|
||||
var newY = Math.max(0,Math.min(d3.event.offsetY+dimensions[1]/2,nav_height)-dimensions[1]);
|
||||
navBorder.attr('x',newX).attr('y',newY);
|
||||
isDragging = true;
|
||||
$("#chart").scrollLeft(newX*nav_scale*scaleFactor);
|
||||
$("#chart").scrollTop(newY*nav_scale*scaleFactor);
|
||||
}).on("mousemove", function() {
|
||||
if (!isDragging) { return }
|
||||
if (d3.event.buttons === 0) {
|
||||
isDragging = false;
|
||||
return;
|
||||
}
|
||||
var newX = Math.max(0,Math.min(d3.event.offsetX+dimensions[0]/2,nav_width)-dimensions[0]);
|
||||
var newY = Math.max(0,Math.min(d3.event.offsetY+dimensions[1]/2,nav_height)-dimensions[1]);
|
||||
navBorder.attr('x',newX).attr('y',newY);
|
||||
$("#chart").scrollLeft(newX*nav_scale*scaleFactor);
|
||||
$("#chart").scrollTop(newY*nav_scale*scaleFactor);
|
||||
}).on("mouseup", function() {
|
||||
isDragging = false;
|
||||
})
|
||||
|
||||
navBorder = navBox.append("rect")
|
||||
.attr("stroke-dasharray","5,5")
|
||||
.attr("pointer-events", "none")
|
||||
.style({
|
||||
stroke: "#999",
|
||||
strokeWidth: 1,
|
||||
fill: "white",
|
||||
});
|
||||
|
||||
navVis = navBox.append("svg:g")
|
||||
|
||||
|
||||
$("#btn-navigate").click(function(evt) {
|
||||
evt.preventDefault();
|
||||
toggle();
|
||||
})
|
||||
},
|
||||
refresh: refreshNodes,
|
||||
resize: resizeNavBorder,
|
||||
toggle: toggle
|
||||
}
|
||||
|
||||
|
||||
})();
|
||||
2062
editor/js/ui/view.js
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -20,7 +20,7 @@ RED.workspaces = (function() {
|
||||
var activeWorkspace = 0;
|
||||
var workspaceIndex = 0;
|
||||
|
||||
function addWorkspace(ws) {
|
||||
function addWorkspace(ws,skipHistoryEntry) {
|
||||
if (ws) {
|
||||
workspace_tabs.addTab(ws);
|
||||
workspace_tabs.resize();
|
||||
@@ -28,59 +28,194 @@ RED.workspaces = (function() {
|
||||
var tabId = RED.nodes.id();
|
||||
do {
|
||||
workspaceIndex += 1;
|
||||
//TODO: nls of Sheet
|
||||
} while($("#workspace-tabs a[title='"+RED._('workspace.defaultName',{number:workspaceIndex})+"']").size() !== 0);
|
||||
} while ($("#workspace-tabs a[title='"+RED._('workspace.defaultName',{number:workspaceIndex})+"']").size() !== 0);
|
||||
|
||||
ws = {type:"tab",id:tabId,label:RED._('workspace.defaultName',{number:workspaceIndex})};
|
||||
ws = {type:"tab",id:tabId,disabled: false,info:"",label:RED._('workspace.defaultName',{number:workspaceIndex})};
|
||||
RED.nodes.addWorkspace(ws);
|
||||
workspace_tabs.addTab(ws);
|
||||
workspace_tabs.activateTab(tabId);
|
||||
RED.history.push({t:'add',workspaces:[ws],dirty:RED.nodes.dirty()});
|
||||
RED.nodes.dirty(true);
|
||||
if (!skipHistoryEntry) {
|
||||
RED.history.push({t:'add',workspaces:[ws],dirty:RED.nodes.dirty()});
|
||||
RED.nodes.dirty(true);
|
||||
}
|
||||
}
|
||||
RED.view.focus();
|
||||
return ws;
|
||||
}
|
||||
function deleteWorkspace(ws,force) {
|
||||
if (workspace_tabs.count() == 1) {
|
||||
function deleteWorkspace(ws) {
|
||||
if (workspaceTabCount === 1) {
|
||||
return;
|
||||
}
|
||||
var nodes = [];
|
||||
if (!force) {
|
||||
nodes = RED.nodes.filterNodes({z:ws.id});
|
||||
}
|
||||
if (force || nodes.length === 0) {
|
||||
removeWorkspace(ws);
|
||||
var historyEvent = RED.nodes.removeWorkspace(ws.id);
|
||||
historyEvent.t = 'delete';
|
||||
historyEvent.dirty = RED.nodes.dirty();
|
||||
historyEvent.workspaces = [ws];
|
||||
RED.history.push(historyEvent);
|
||||
RED.nodes.dirty(true);
|
||||
} else {
|
||||
$( "#node-dialog-delete-workspace" ).dialog('option','workspace',ws);
|
||||
$( "#node-dialog-delete-workspace-content" ).text(RED._("workspace.delete",{label:ws.label}));
|
||||
$( "#node-dialog-delete-workspace" ).dialog('open');
|
||||
}
|
||||
removeWorkspace(ws);
|
||||
var historyEvent = RED.nodes.removeWorkspace(ws.id);
|
||||
historyEvent.t = 'delete';
|
||||
historyEvent.dirty = RED.nodes.dirty();
|
||||
historyEvent.workspaces = [ws];
|
||||
RED.history.push(historyEvent);
|
||||
RED.nodes.dirty(true);
|
||||
RED.sidebar.config.refresh();
|
||||
}
|
||||
|
||||
function showRenameWorkspaceDialog(id) {
|
||||
var ws = RED.nodes.workspace(id);
|
||||
$( "#node-dialog-rename-workspace" ).dialog("option","workspace",ws);
|
||||
var workspace = RED.nodes.workspace(id);
|
||||
RED.view.state(RED.state.EDITING);
|
||||
var tabflowEditor;
|
||||
var trayOptions = {
|
||||
title: RED._("workspace.editFlow",{name:workspace.label}),
|
||||
buttons: [
|
||||
{
|
||||
id: "node-dialog-delete",
|
||||
class: 'leftButton'+((workspaceTabCount === 1)?" disabled":""),
|
||||
text: RED._("common.label.delete"), //'<i class="fa fa-trash"></i>',
|
||||
click: function() {
|
||||
deleteWorkspace(workspace);
|
||||
RED.tray.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-cancel",
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
RED.tray.close();
|
||||
}
|
||||
},
|
||||
{
|
||||
id: "node-dialog-ok",
|
||||
class: "primary",
|
||||
text: RED._("common.label.done"),
|
||||
click: function() {
|
||||
var label = $( "#node-input-name" ).val();
|
||||
var changed = false;
|
||||
var changes = {};
|
||||
if (workspace.label != label) {
|
||||
changes.label = workspace.label;
|
||||
changed = true;
|
||||
workspace.label = label;
|
||||
workspace_tabs.renameTab(workspace.id,label);
|
||||
}
|
||||
var disabled = $("#node-input-disabled").prop("checked");
|
||||
if (workspace.disabled !== disabled) {
|
||||
changes.disabled = workspace.disabled;
|
||||
changed = true;
|
||||
workspace.disabled = disabled;
|
||||
}
|
||||
var info = tabflowEditor.getValue();
|
||||
if (workspace.info !== info) {
|
||||
changes.info = workspace.info;
|
||||
changed = true;
|
||||
workspace.info = info;
|
||||
}
|
||||
$("#red-ui-tab-"+(workspace.id.replace(".","-"))).toggleClass('workspace-disabled',workspace.disabled);
|
||||
// $("#workspace").toggleClass("workspace-disabled",workspace.disabled);
|
||||
|
||||
if (workspace_tabs.count() == 1) {
|
||||
$( "#node-dialog-rename-workspace").next().find(".leftButton")
|
||||
.prop('disabled',true)
|
||||
.addClass("ui-state-disabled");
|
||||
} else {
|
||||
$( "#node-dialog-rename-workspace").next().find(".leftButton")
|
||||
.prop('disabled',false)
|
||||
.removeClass("ui-state-disabled");
|
||||
if (changed) {
|
||||
var historyEvent = {
|
||||
t: "edit",
|
||||
changes:changes,
|
||||
node: workspace,
|
||||
dirty: RED.nodes.dirty()
|
||||
}
|
||||
workspace.changed = true;
|
||||
RED.history.push(historyEvent);
|
||||
RED.nodes.dirty(true);
|
||||
RED.sidebar.config.refresh();
|
||||
var selection = RED.view.selection();
|
||||
if (!selection.nodes && !selection.links) {
|
||||
RED.sidebar.info.refresh(workspace);
|
||||
}
|
||||
}
|
||||
RED.tray.close();
|
||||
}
|
||||
}
|
||||
],
|
||||
resize: function(dimensions) {
|
||||
var rows = $("#dialog-form>div:not(.node-text-editor-row)");
|
||||
var editorRow = $("#dialog-form>div.node-text-editor-row");
|
||||
var height = $("#dialog-form").height();
|
||||
for (var i=0; i<rows.size(); i++) {
|
||||
height -= $(rows[i]).outerHeight(true);
|
||||
}
|
||||
height -= (parseInt($("#dialog-form").css("marginTop"))+parseInt($("#dialog-form").css("marginBottom")));
|
||||
height -= 28;
|
||||
$(".node-text-editor").css("height",height+"px");
|
||||
tabflowEditor.resize();
|
||||
},
|
||||
open: function(tray) {
|
||||
var trayBody = tray.find('.editor-tray-body');
|
||||
var dialogForm = $('<form id="dialog-form" class="form-horizontal"></form>').appendTo(trayBody);
|
||||
$('<div class="form-row">'+
|
||||
'<label for="node-input-name" data-i18n="[append]editor:common.label.name"><i class="fa fa-tag"></i> </label>'+
|
||||
'<input type="text" id="node-input-name">'+
|
||||
'</div>').appendTo(dialogForm);
|
||||
|
||||
$('<div class="form-row">'+
|
||||
'<label for="node-input-disabled-btn" data-i18n="editor:workspace.status"></label>'+
|
||||
'<button id="node-input-disabled-btn" class="editor-button"><i class="fa fa-toggle-on"></i> <span id="node-input-disabled-label"></span></button> '+
|
||||
'<input type="checkbox" id="node-input-disabled" style="display: none;"/>'+
|
||||
'</div>').appendTo(dialogForm);
|
||||
|
||||
$('<div class="form-row node-text-editor-row">'+
|
||||
'<label for="node-input-info" data-i18n="editor:workspace.info" style="width:300px;"></label>'+
|
||||
'<div style="height:250px;" class="node-text-editor" id="node-input-info"></div>'+
|
||||
'</div>').appendTo(dialogForm);
|
||||
tabflowEditor = RED.editor.createEditor({
|
||||
id: 'node-input-info',
|
||||
mode: 'ace/mode/markdown',
|
||||
value: ""
|
||||
});
|
||||
|
||||
$('<div class="form-tips" data-i18n="editor:workspace.tip"></div>').appendTo(dialogForm);
|
||||
|
||||
dialogForm.find('#node-input-disabled-btn').on("click",function(e) {
|
||||
var i = $(this).find("i");
|
||||
if (i.hasClass('fa-toggle-off')) {
|
||||
i.addClass('fa-toggle-on');
|
||||
i.removeClass('fa-toggle-off');
|
||||
$("#node-input-disabled").prop("checked",false);
|
||||
$("#node-input-disabled-label").text(RED._("editor:workspace.enabled"));
|
||||
} else {
|
||||
i.addClass('fa-toggle-off');
|
||||
i.removeClass('fa-toggle-on');
|
||||
$("#node-input-disabled").prop("checked",true);
|
||||
$("#node-input-disabled-label").text(RED._("editor:workspace.disabled"));
|
||||
}
|
||||
})
|
||||
|
||||
if (workspace.hasOwnProperty("disabled")) {
|
||||
$("#node-input-disabled").prop("checked",workspace.disabled);
|
||||
if (workspace.disabled) {
|
||||
dialogForm.find("#node-input-disabled-btn i").removeClass('fa-toggle-on').addClass('fa-toggle-off');
|
||||
$("#node-input-disabled-label").text(RED._("editor:workspace.disabled"));
|
||||
} else {
|
||||
$("#node-input-disabled-label").text(RED._("editor:workspace.enabled"));
|
||||
}
|
||||
} else {
|
||||
workspace.disabled = false;
|
||||
$("#node-input-disabled-label").text(RED._("editor:workspace.enabled"));
|
||||
}
|
||||
|
||||
$('<input type="text" style="display: none;" />').prependTo(dialogForm);
|
||||
dialogForm.submit(function(e) { e.preventDefault();});
|
||||
$("#node-input-name").val(workspace.label);
|
||||
RED.text.bidi.prepareInput($("#node-input-name"));
|
||||
tabflowEditor.getSession().setValue(workspace.info || "", -1);
|
||||
dialogForm.i18n();
|
||||
},
|
||||
close: function() {
|
||||
if (RED.view.state() != RED.state.IMPORT_DRAGGING) {
|
||||
RED.view.state(RED.state.DEFAULT);
|
||||
}
|
||||
RED.sidebar.info.refresh(workspace);
|
||||
tabflowEditor.destroy();
|
||||
}
|
||||
}
|
||||
|
||||
$( "#node-input-workspace-name" ).val(ws.label);
|
||||
$( "#node-dialog-rename-workspace" ).dialog("open");
|
||||
RED.tray.show(trayOptions);
|
||||
}
|
||||
|
||||
|
||||
var workspace_tabs;
|
||||
function createWorkspaceTabs(){
|
||||
var workspaceTabCount = 0;
|
||||
function createWorkspaceTabs() {
|
||||
workspace_tabs = RED.tabs.create({
|
||||
id: "workspace-tabs",
|
||||
onchange: function(tab) {
|
||||
@@ -89,8 +224,14 @@ RED.workspaces = (function() {
|
||||
}
|
||||
activeWorkspace = tab.id;
|
||||
event.workspace = activeWorkspace;
|
||||
// $("#workspace").toggleClass("workspace-disabled",tab.disabled);
|
||||
RED.events.emit("workspace:change",event);
|
||||
window.location.hash = 'flow/'+tab.id;
|
||||
RED.sidebar.config.refresh();
|
||||
RED.view.focus();
|
||||
},
|
||||
onclick: function(tab) {
|
||||
RED.view.focus();
|
||||
},
|
||||
ondblclick: function(tab) {
|
||||
if (tab.type != "subflow") {
|
||||
@@ -100,103 +241,58 @@ RED.workspaces = (function() {
|
||||
}
|
||||
},
|
||||
onadd: function(tab) {
|
||||
RED.menu.addItem("menu-item-workspace",{
|
||||
id:"menu-item-workspace-menu-"+tab.id.replace(".","-"),
|
||||
label:tab.label,
|
||||
onselect:function() {
|
||||
workspace_tabs.activateTab(tab.id);
|
||||
}
|
||||
});
|
||||
RED.menu.setDisabled("menu-item-workspace-delete",workspace_tabs.count() == 1);
|
||||
if (tab.type === "tab") {
|
||||
workspaceTabCount++;
|
||||
}
|
||||
$('<span class="workspace-disabled-icon"><i class="fa fa-ban"></i> </span>').prependTo("#red-ui-tab-"+(tab.id.replace(".","-"))+" .red-ui-tab-label");
|
||||
if (tab.disabled) {
|
||||
$("#red-ui-tab-"+(tab.id.replace(".","-"))).addClass('workspace-disabled');
|
||||
}
|
||||
RED.menu.setDisabled("menu-item-workspace-delete",workspaceTabCount <= 1);
|
||||
if (workspaceTabCount === 1) {
|
||||
showWorkspace();
|
||||
}
|
||||
},
|
||||
onremove: function(tab) {
|
||||
RED.menu.setDisabled("menu-item-workspace-delete",workspace_tabs.count() == 1);
|
||||
RED.menu.removeItem("menu-item-workspace-menu-"+tab.id.replace(".","-"));
|
||||
},
|
||||
minimumActiveTabWidth: 150
|
||||
});
|
||||
|
||||
|
||||
$("#node-dialog-rename-workspace form" ).submit(function(e) { e.preventDefault();});
|
||||
$( "#node-dialog-rename-workspace" ).dialog({
|
||||
modal: true,
|
||||
autoOpen: false,
|
||||
width: 500,
|
||||
title: RED._("workspace.renameSheet"),
|
||||
buttons: [
|
||||
{
|
||||
class: 'leftButton',
|
||||
text: RED._("common.label.delete"),
|
||||
click: function() {
|
||||
var workspace = $(this).dialog('option','workspace');
|
||||
$( this ).dialog( "close" );
|
||||
deleteWorkspace(workspace);
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._("common.label.ok"),
|
||||
click: function() {
|
||||
var workspace = $(this).dialog('option','workspace');
|
||||
var label = $( "#node-input-workspace-name" ).val();
|
||||
if (workspace.label != label) {
|
||||
workspace_tabs.renameTab(workspace.id,label);
|
||||
RED.nodes.dirty(true);
|
||||
$("#menu-item-workspace-menu-"+workspace.id.replace(".","-")).text(label);
|
||||
// TODO: update entry in menu
|
||||
}
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
if (tab.type === "tab") {
|
||||
workspaceTabCount--;
|
||||
}
|
||||
RED.menu.setDisabled("menu-item-workspace-delete",workspaceTabCount <= 1);
|
||||
if (workspaceTabCount === 0) {
|
||||
hideWorkspace();
|
||||
}
|
||||
],
|
||||
open: function(e) {
|
||||
RED.keyboard.disable();
|
||||
},
|
||||
close: function(e) {
|
||||
RED.keyboard.enable();
|
||||
onreorder: function(oldOrder, newOrder) {
|
||||
RED.history.push({t:'reorder',order:oldOrder,dirty:RED.nodes.dirty()});
|
||||
RED.nodes.dirty(true);
|
||||
setWorkspaceOrder(newOrder);
|
||||
},
|
||||
minimumActiveTabWidth: 150,
|
||||
scrollable: true,
|
||||
addButton: function() {
|
||||
addWorkspace();
|
||||
}
|
||||
});
|
||||
$( "#node-dialog-delete-workspace" ).dialog({
|
||||
modal: true,
|
||||
autoOpen: false,
|
||||
width: 500,
|
||||
title: RED._("workspace.confirmDelete"),
|
||||
buttons: [
|
||||
{
|
||||
text: RED._("common.label.ok"),
|
||||
click: function() {
|
||||
var workspace = $(this).dialog('option','workspace');
|
||||
deleteWorkspace(workspace,true);
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
},
|
||||
{
|
||||
text: RED._("common.label.cancel"),
|
||||
click: function() {
|
||||
$( this ).dialog( "close" );
|
||||
}
|
||||
}
|
||||
],
|
||||
open: function(e) {
|
||||
RED.keyboard.disable();
|
||||
},
|
||||
close: function(e) {
|
||||
RED.keyboard.enable();
|
||||
}
|
||||
|
||||
});
|
||||
workspaceTabCount = 0;
|
||||
}
|
||||
function showWorkspace() {
|
||||
$("#workspace .red-ui-tabs").show()
|
||||
$("#chart").show()
|
||||
$("#workspace-footer").children().show()
|
||||
}
|
||||
function hideWorkspace() {
|
||||
$("#workspace .red-ui-tabs").hide()
|
||||
$("#chart").hide()
|
||||
$("#workspace-footer").children().hide()
|
||||
}
|
||||
|
||||
function init() {
|
||||
createWorkspaceTabs();
|
||||
$('#btn-workspace-add-tab').on("click",function(e) {addWorkspace(); e.preventDefault()});
|
||||
RED.events.on("sidebar:resize",workspace_tabs.resize);
|
||||
|
||||
RED.actions.add("core:show-next-tab",workspace_tabs.nextTab);
|
||||
RED.actions.add("core:show-previous-tab",workspace_tabs.previousTab);
|
||||
|
||||
RED.menu.setAction('menu-item-workspace-delete',function() {
|
||||
deleteWorkspace(RED.nodes.workspace(activeWorkspace));
|
||||
});
|
||||
@@ -204,6 +300,16 @@ RED.workspaces = (function() {
|
||||
$(window).resize(function() {
|
||||
workspace_tabs.resize();
|
||||
});
|
||||
|
||||
RED.actions.add("core:add-flow",addWorkspace);
|
||||
RED.actions.add("core:edit-flow",editWorkspace);
|
||||
RED.actions.add("core:remove-flow",removeWorkspace);
|
||||
|
||||
hideWorkspace();
|
||||
}
|
||||
|
||||
function editWorkspace(id) {
|
||||
showRenameWorkspaceDialog(id||activeWorkspace);
|
||||
}
|
||||
|
||||
function removeWorkspace(ws) {
|
||||
@@ -214,21 +320,29 @@ RED.workspaces = (function() {
|
||||
workspace_tabs.removeTab(ws.id);
|
||||
}
|
||||
}
|
||||
if (ws.id === activeWorkspace) {
|
||||
activeWorkspace = 0;
|
||||
}
|
||||
}
|
||||
|
||||
function setWorkspaceOrder(order) {
|
||||
RED.nodes.setWorkspaceOrder(order.filter(function(id) {
|
||||
return RED.nodes.workspace(id) !== undefined;
|
||||
}));
|
||||
workspace_tabs.order(order);
|
||||
}
|
||||
|
||||
return {
|
||||
init: init,
|
||||
add: addWorkspace,
|
||||
remove: removeWorkspace,
|
||||
|
||||
edit: function(id) {
|
||||
showRenameWorkspaceDialog(id||activeWorkspace);
|
||||
},
|
||||
order: setWorkspaceOrder,
|
||||
edit: editWorkspace,
|
||||
contains: function(id) {
|
||||
return workspace_tabs.contains(id);
|
||||
},
|
||||
count: function() {
|
||||
return workspace_tabs.count();
|
||||
return workspaceTabCount;
|
||||
},
|
||||
active: function() {
|
||||
return activeWorkspace
|
||||
@@ -238,11 +352,17 @@ RED.workspaces = (function() {
|
||||
var sf = RED.nodes.subflow(id);
|
||||
if (sf) {
|
||||
addWorkspace({type:"subflow",id:id,icon:"red/images/subflow_tab.png",label:sf.name, closeable: true});
|
||||
} else {
|
||||
return;
|
||||
}
|
||||
}
|
||||
workspace_tabs.activateTab(id);
|
||||
},
|
||||
refresh: function() {
|
||||
RED.nodes.eachWorkspace(function(ws) {
|
||||
workspace_tabs.renameTab(ws.id,ws.label);
|
||||
|
||||
})
|
||||
RED.nodes.eachSubflow(function(sf) {
|
||||
if (workspace_tabs.contains(sf.id)) {
|
||||
workspace_tabs.renameTab(sf.id,sf.name);
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2014, 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -32,7 +32,7 @@ RED.user = (function() {
|
||||
autoOpen: false,
|
||||
dialogClass: "ui-dialog-no-close",
|
||||
modal: true,
|
||||
closeOnEscape: false,
|
||||
closeOnEscape: !!opts.cancelable,
|
||||
width: 600,
|
||||
resizable: false,
|
||||
draggable: false
|
||||
@@ -43,18 +43,14 @@ RED.user = (function() {
|
||||
dataType: "json",
|
||||
url: "auth/login",
|
||||
success: function(data) {
|
||||
if (data.type == "credentials") {
|
||||
var i=0;
|
||||
var i=0;
|
||||
|
||||
if (data.type == "credentials") {
|
||||
|
||||
if (data.image) {
|
||||
$("#node-dialog-login-image").attr("src",data.image);
|
||||
} else {
|
||||
$("#node-dialog-login-image").attr("src","red/images/node-red-256.png");
|
||||
}
|
||||
for (;i<data.prompts.length;i++) {
|
||||
var field = data.prompts[i];
|
||||
var row = $("<div/>",{id:"rrr"+i,class:"form-row"});
|
||||
$('<label for="node-dialog-login-'+field.id+'">'+field.label+':</label><br/>').appendTo(row);
|
||||
var row = $("<div/>",{class:"form-row"});
|
||||
$('<label for="node-dialog-login-'+field.id+'">'+RED._(field.label)+':</label><br/>').appendTo(row);
|
||||
var input = $('<input style="width: 100%" id="node-dialog-login-'+field.id+'" type="'+field.type+'" tabIndex="'+(i+1)+'"/>').appendTo(row);
|
||||
|
||||
if (i<data.prompts.length-1) {
|
||||
@@ -99,6 +95,9 @@ RED.user = (function() {
|
||||
}).done(function(data,textStatus,xhr) {
|
||||
RED.settings.set("auth-tokens",data);
|
||||
$("#node-dialog-login").dialog('destroy').remove();
|
||||
if (opts.updateMenu) {
|
||||
updateUserMenu();
|
||||
}
|
||||
done();
|
||||
}).fail(function(jqXHR,textStatus,errorThrown) {
|
||||
RED.settings.remove("auth-tokens");
|
||||
@@ -109,31 +108,77 @@ RED.user = (function() {
|
||||
});
|
||||
event.preventDefault();
|
||||
});
|
||||
if (opts.cancelable) {
|
||||
$("#node-dialog-login-cancel").button().click(function( event ) {
|
||||
$("#node-dialog-login").dialog('destroy').remove();
|
||||
|
||||
} else if (data.type == "strategy") {
|
||||
i = 0;
|
||||
for (;i<data.prompts.length;i++) {
|
||||
var field = data.prompts[i];
|
||||
var row = $("<div/>",{class:"form-row",style:"text-align: center"}).appendTo("#node-dialog-login-fields");
|
||||
|
||||
var loginButton = $('<a href="#"></a>',{style: "padding: 10px"}).appendTo(row).click(function() {
|
||||
document.location = field.url;
|
||||
});
|
||||
if (field.image) {
|
||||
$("<img>",{src:field.image}).appendTo(loginButton);
|
||||
} else if (field.label) {
|
||||
var label = $('<span></span>').text(field.label);
|
||||
if (field.icon) {
|
||||
$('<i></i>',{class: "fa fa-2x "+field.icon, style:"vertical-align: middle"}).appendTo(loginButton);
|
||||
label.css({
|
||||
"verticalAlign":"middle",
|
||||
"marginLeft":"8px"
|
||||
});
|
||||
|
||||
}
|
||||
label.appendTo(loginButton);
|
||||
}
|
||||
loginButton.button();
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
dialog.dialog("open");
|
||||
if (opts.cancelable) {
|
||||
$("#node-dialog-login-cancel").button().click(function( event ) {
|
||||
$("#node-dialog-login").dialog('destroy').remove();
|
||||
});
|
||||
}
|
||||
|
||||
var loginImageSrc = data.image || "red/images/node-red-256.png";
|
||||
|
||||
$("#node-dialog-login-image").load(function() {
|
||||
dialog.dialog("open");
|
||||
}).attr("src",loginImageSrc);
|
||||
|
||||
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function logout() {
|
||||
var tokens = RED.settings.get("auth-tokens");
|
||||
var token = tokens?tokens.access_token:"";
|
||||
$.ajax({
|
||||
url: "auth/revoke",
|
||||
type: "POST",
|
||||
data: {token:RED.settings.get("auth-tokens").access_token},
|
||||
success: function() {
|
||||
RED.settings.remove("auth-tokens");
|
||||
data: {token:token}
|
||||
}).done(function(data,textStatus,xhr) {
|
||||
RED.settings.remove("auth-tokens");
|
||||
if (data && data.redirect) {
|
||||
document.location.href = data.redirect;
|
||||
} else {
|
||||
document.location.reload(true);
|
||||
}
|
||||
}).fail(function(jqXHR,textStatus,errorThrown) {
|
||||
if (jqXHR.status === 401) {
|
||||
document.location.reload(true);
|
||||
} else {
|
||||
console.log(textStatus);
|
||||
}
|
||||
})
|
||||
}
|
||||
|
||||
function updateUserMenu() {
|
||||
$("#usermenu-submenu li").remove();
|
||||
$("#btn-usermenu-submenu li").remove();
|
||||
if (RED.settings.user.anonymous) {
|
||||
RED.menu.addItem("btn-usermenu",{
|
||||
id:"usermenu-item-login",
|
||||
@@ -143,6 +188,7 @@ RED.user = (function() {
|
||||
RED.settings.load(function() {
|
||||
RED.notify(RED._("user.loggedInAs",{name:RED.settings.user.username}),"success");
|
||||
updateUserMenu();
|
||||
RED.events.emit("login",RED.settings.user.username);
|
||||
});
|
||||
});
|
||||
}
|
||||
@@ -163,14 +209,19 @@ RED.user = (function() {
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function init() {
|
||||
if (RED.settings.user) {
|
||||
if (!RED.settings.editorTheme || !RED.settings.editorTheme.hasOwnProperty("userMenu")) {
|
||||
|
||||
$('<li><a id="btn-usermenu" class="button hide" data-toggle="dropdown" href="#"><i class="fa fa-user"></i></a></li>')
|
||||
var userMenu = $('<li><a id="btn-usermenu" class="button hide" data-toggle="dropdown" href="#"></a></li>')
|
||||
.prependTo(".header-toolbar");
|
||||
if (RED.settings.user.image) {
|
||||
$('<span class="user-profile"></span>').css({
|
||||
backgroundImage: "url("+RED.settings.user.image+")",
|
||||
}).appendTo(userMenu.find("a"));
|
||||
} else {
|
||||
$('<i class="fa fa-user"></i>').appendTo(userMenu.find("a"));
|
||||
}
|
||||
|
||||
RED.menu.init({id:"btn-usermenu",
|
||||
options: []
|
||||
@@ -180,10 +231,66 @@ RED.user = (function() {
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
var readRE = /^((.+)\.)?read$/
|
||||
var writeRE = /^((.+)\.)?write$/
|
||||
|
||||
function hasPermission(permission) {
|
||||
if (permission === "") {
|
||||
return true;
|
||||
}
|
||||
if (!RED.settings.user) {
|
||||
return true;
|
||||
}
|
||||
return checkPermission(RED.settings.user.permissions||"",permission);
|
||||
}
|
||||
function checkPermission(userScope,permission) {
|
||||
if (permission === "") {
|
||||
return true;
|
||||
}
|
||||
var i;
|
||||
|
||||
if (Array.isArray(permission)) {
|
||||
// Multiple permissions requested - check each one
|
||||
for (i=0;i<permission.length;i++) {
|
||||
if (!checkPermission(userScope,permission[i])) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
// All permissions check out
|
||||
return true;
|
||||
}
|
||||
|
||||
if (Array.isArray(userScope)) {
|
||||
if (userScope.length === 0) {
|
||||
return false;
|
||||
}
|
||||
for (i=0;i<userScope.length;i++) {
|
||||
if (checkPermission(userScope[i],permission)) {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
if (userScope === "*" || userScope === permission) {
|
||||
return true;
|
||||
}
|
||||
|
||||
if (userScope === "read" || userScope === "*.read") {
|
||||
return readRE.test(permission);
|
||||
} else if (userScope === "write" || userScope === "*.write") {
|
||||
return writeRE.test(permission);
|
||||
}
|
||||
return false;
|
||||
}
|
||||
|
||||
|
||||
return {
|
||||
init: init,
|
||||
login: login,
|
||||
logout: logout
|
||||
logout: logout,
|
||||
hasPermission: hasPermission
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2013 IBM Corp.
|
||||
* 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.
|
||||
@@ -14,6 +14,22 @@
|
||||
* limitations under the License.
|
||||
**/
|
||||
RED.validators = {
|
||||
number: function(){return function(v) { return v!=='' && !isNaN(v);}},
|
||||
regex: function(re){return function(v) { return re.test(v);}}
|
||||
number: function(blankAllowed){return function(v) { return (blankAllowed&&(v===''||v===undefined)) || (v!=='' && !isNaN(v));}},
|
||||
regex: function(re){return function(v) { return re.test(v);}},
|
||||
typedInput: function(ptypeName,isConfig) { return function(v) {
|
||||
var ptype = $("#node-"+(isConfig?"config-":"")+"input-"+ptypeName).val() || this[ptypeName];
|
||||
if (ptype === 'json') {
|
||||
try {
|
||||
JSON.parse(v);
|
||||
return true;
|
||||
} catch(err) {
|
||||
return false;
|
||||
}
|
||||
} else if (ptype === 'msg' || ptype === 'flow' || ptype === 'global' ) {
|
||||
return RED.utils.validatePropertyExpression(v);
|
||||
} else if (ptype === 'num') {
|
||||
return /^[+-]?[0-9]*\.?[0-9]*([eE][-+]?[0-9]+)?$/.test(v);
|
||||
}
|
||||
return true;
|
||||
}}
|
||||
};
|
||||
|
||||
8
editor/sass/ace.scss
Normal file
@@ -0,0 +1,8 @@
|
||||
.ace_gutter {
|
||||
border-top-left-radius: 4px;
|
||||
border-bottom-left-radius: 4px;
|
||||
}
|
||||
.ace_scroller {
|
||||
border-top-right-radius: 4px;
|
||||
border-bottom-right-radius: 4px;
|
||||
}
|
||||
6
editor/sass/bootstrap.scss
vendored
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -19,3 +19,7 @@
|
||||
div.btn-group, a.btn {
|
||||
@include disable-selection;
|
||||
}
|
||||
|
||||
.dropdown-menu>li>a {
|
||||
color: #444;
|
||||
}
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -14,15 +14,20 @@
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
$background-color: #f3f3f3;
|
||||
|
||||
$form-placeholder-color: #bbbbbb;
|
||||
$form-text-color: #444;
|
||||
$form-input-focus-color: rgba(85,150,230,0.8);
|
||||
$form-input-border-color: #ccc;
|
||||
$form-input-border-selected-color: #aaa;
|
||||
|
||||
|
||||
$node-selected-color: #ff7f0e;
|
||||
$port-selected-color: #ff7f0e;
|
||||
$link-color: #888;
|
||||
$link-link-color: #ccc;
|
||||
$link-link-active-color: #ff7f0e;
|
||||
$link-subflow-color: #bbb;
|
||||
$link-unknown-color: #f00;
|
||||
|
||||
@@ -38,8 +43,27 @@ $palette-header-background: #f3f3f3;
|
||||
$workspace-button-background: #fff;
|
||||
$workspace-button-background-hover: #ddd;
|
||||
$workspace-button-background-active: #efefef;
|
||||
$workspace-button-color: #999;
|
||||
$workspace-button-color: #888;
|
||||
$workspace-button-color-disabled: #ccc;
|
||||
$workspace-button-color-focus: #999;
|
||||
$workspace-button-color-hover: #666;
|
||||
$workspace-button-color-active: #666;
|
||||
$workspace-button-color-selected: #AAA;
|
||||
|
||||
$workspace-button-toggle-color: #999;
|
||||
$workspace-button-toggle-color-selected: #888;
|
||||
$workspace-button-toggle-color-disabled: #ddd;
|
||||
|
||||
$workspace-button-color-focus-outline: rgba(85,150,230,0.2);
|
||||
|
||||
$typedInput-button-background: #efefef;
|
||||
$typedInput-button-background-hover: #ddd;
|
||||
$typedInput-button-background-active: #ddd;
|
||||
|
||||
$editor-button-color-primary: #eee;
|
||||
$editor-button-background-primary: #AD1625;
|
||||
$editor-button-background-primary-hover: #6E0A1E;
|
||||
$editor-button-color: #999;
|
||||
$editor-button-background: #fff;
|
||||
|
||||
$shade-color: rgba(160,160,160,0.5);
|
||||
|
||||
262
editor/sass/debug.scss
Normal file
@@ -0,0 +1,262 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
|
||||
.debug-window {
|
||||
padding:0;
|
||||
margin:0;
|
||||
background: #fff;
|
||||
line-height: 20px;
|
||||
}
|
||||
.debug-window .debug-message-payload {
|
||||
font-size: 14px;
|
||||
}
|
||||
.debug-content {
|
||||
position: absolute;
|
||||
top: 43px;
|
||||
bottom: 0px;
|
||||
left:0px;
|
||||
right: 0px;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
.debug-filter-box {
|
||||
position:absolute;
|
||||
top: 42px;
|
||||
left: 0px;
|
||||
right: 0px;
|
||||
z-index: 20;
|
||||
background: #f9f9f9;
|
||||
padding: 10px;
|
||||
border-bottom: 1px solid #ddd;
|
||||
box-shadow: 0 2px 6px rgba(0,0,0,0.1);
|
||||
}
|
||||
.debug-filter-row {
|
||||
.red-ui-nodeList {
|
||||
margin: 10px 0;
|
||||
}
|
||||
}
|
||||
|
||||
.debug-message {
|
||||
position: relative;
|
||||
border-bottom: 1px solid #eee;
|
||||
border-left: 8px solid #eee;
|
||||
border-right: 8px solid #eee;
|
||||
padding: 2px;
|
||||
&>.debug-message-meta .debug-message-tools {
|
||||
display: none;
|
||||
}
|
||||
|
||||
&.debug-message-hover {
|
||||
border-right-color: #999;
|
||||
&>.debug-message-meta .debug-message-tools {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
.debug-message-row {
|
||||
.debug-message-tools-pin {
|
||||
display: none;
|
||||
}
|
||||
&.debug-message-row-pinned .debug-message-tools-pin {
|
||||
display: inline-block;
|
||||
}
|
||||
&:hover {
|
||||
background: #f3f3f3;
|
||||
&>.debug-message-tools {
|
||||
.debug-message-tools-copy {
|
||||
display: inline-block;
|
||||
}
|
||||
.debug-message-tools-pin {
|
||||
display: inline-block;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
.debug-message-meta .debug-message-tools {
|
||||
.editor-button-small {
|
||||
font-size: 11px;
|
||||
}
|
||||
}
|
||||
.debug-message-tools {
|
||||
.button-group:not(:last-child) {
|
||||
margin-right: 3px;
|
||||
}
|
||||
.editor-button-small {
|
||||
height: 16px;
|
||||
line-height: 14px;
|
||||
font-size: 8px;
|
||||
border-radius: 1px;
|
||||
padding: 0 3px;
|
||||
min-width: 18px;
|
||||
i.fa-terminal {
|
||||
// terminal icon is a bit thin, so darken its color for better contrast
|
||||
color: darken($editor-button-color, 30%) !important;
|
||||
}
|
||||
&.selected {
|
||||
color: darken($workspace-button-color-selected, 10%) !important;
|
||||
background: darken($workspace-button-background-active,10%);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.debug-message-meta {
|
||||
background: #fff;
|
||||
font-size: 11px;
|
||||
color: #707070;
|
||||
}
|
||||
.debug-message-date {
|
||||
padding: 1px 5px 1px 1px;
|
||||
}
|
||||
.debug-message-topic {
|
||||
display: block;
|
||||
color: #a66;
|
||||
}
|
||||
.debug-message-name {
|
||||
padding: 1px 5px;
|
||||
color: #707070;
|
||||
}
|
||||
.debug-message-tools {
|
||||
position: absolute;
|
||||
top: 3px;
|
||||
right: 1px;
|
||||
.debug-message-tools-copy {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
.debug-message-payload {
|
||||
display: block;
|
||||
padding: 2px;
|
||||
background: #fff;
|
||||
}
|
||||
.debug-message-level-log {
|
||||
border-left-color: #eee;
|
||||
border-right-color: #eee;
|
||||
}
|
||||
.debug-message-level-30 {
|
||||
border-left-color: #ffdf9d;
|
||||
border-right-color: #ffdf9d;
|
||||
}
|
||||
.debug-message-level-20 {
|
||||
border-left-color: #f99;
|
||||
border-right-color: #f99;
|
||||
}
|
||||
.debug-message-object-entry {
|
||||
position: relative;
|
||||
padding-left: 15px;
|
||||
}
|
||||
.debug-message-element {
|
||||
color: #333;
|
||||
font-family: Menlo, monospace;
|
||||
font-size: 13px !important;
|
||||
line-height: 1.3em;
|
||||
}
|
||||
.debug-message-object-key {
|
||||
color: #792e90;
|
||||
}
|
||||
.debug-message-object-value {
|
||||
|
||||
}
|
||||
.debug-message-object-handle {
|
||||
color: #666;
|
||||
font-size: 1em;
|
||||
width: 1em;
|
||||
text-align: center;
|
||||
transition: transform 0.1s ease-in-out;
|
||||
transform: rotate(90deg);
|
||||
}
|
||||
.debug-message-element:not(.debug-message-top-level)>.debug-message-expandable>.debug-message-object-handle {
|
||||
margin-left: -1em;
|
||||
}
|
||||
.debug-message-object-entry>.debug-message-expandable>.debug-message-object-handle {
|
||||
margin-left: -1em;
|
||||
}
|
||||
.debug-message-object-entry.collapsed>span>.debug-message-object-handle {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
.debug-message-element.collapsed>span>.debug-message-object-handle {
|
||||
transform: rotate(0deg);
|
||||
}
|
||||
.debug-message-object-entry.collapsed > .debug-message-object-entry {
|
||||
display:none;
|
||||
}
|
||||
.debug-message-element.collapsed .debug-message-object-entry {
|
||||
display:none;
|
||||
}
|
||||
.debug-message-element:not(.collapsed)>.debug-message-expandable>.debug-message-object-value>.debug-message-object-header {
|
||||
display:none;
|
||||
}
|
||||
.debug-message-element.collapsed .debug-message-buffer-opts {
|
||||
display: none;
|
||||
}
|
||||
.debug-message-element.collapsed .debug-message-object-type-header {
|
||||
display:none;
|
||||
}
|
||||
.debug-message-object-entry pre {
|
||||
font-family: Menlo, monospace;
|
||||
font-size: 13px;
|
||||
line-height: 1.2em;
|
||||
margin: 0 0 0 -1em;
|
||||
}
|
||||
|
||||
.debug-message-type-other { color: #2033d6; }
|
||||
.debug-message-type-string { color: #b72828; }
|
||||
.debug-message-type-null { color: #666; font-style: italic;}
|
||||
.debug-message-type-meta { color: #666; font-style: italic;}
|
||||
.debug-message-type-number { color: #2033d6; };
|
||||
.debug-message-type-number-toggle { cursor: pointer;}
|
||||
|
||||
.debug-message-row {
|
||||
display: block;
|
||||
padding: 4px 2px 2px;
|
||||
position: relative;
|
||||
&.debug-message-row-pinned {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
}
|
||||
.debug-message-expandable {
|
||||
cursor: pointer;
|
||||
}
|
||||
.debug-message-expandable:hover .debug-message-object-handle {
|
||||
color: #b72828 !important;
|
||||
}
|
||||
|
||||
.debug-message-buffer-opts a {
|
||||
font-size: 9px;
|
||||
color: #bbb;
|
||||
border: 1px solid #bbb;
|
||||
border-radius: 2px;
|
||||
padding: 2px 5px;
|
||||
margin-left: 5px;
|
||||
}
|
||||
.debug-message-buffer-opts a:hover {
|
||||
text-decoration: none;
|
||||
color: #999;
|
||||
border: 1px solid #999;
|
||||
background: #f3f3f3;
|
||||
}
|
||||
.debug-message-buffer-raw > .debug-message-string-rows {
|
||||
display: none;
|
||||
}
|
||||
.debug-message-buffer-string > .debug-message-array-rows {
|
||||
display: none;
|
||||
}
|
||||
.debug-message-type-string-swatch {
|
||||
display: inline-block;
|
||||
width: 1.1em;
|
||||
height: 0.9em;
|
||||
vertical-align: middle;
|
||||
border-radius: 3px;
|
||||
margin: 0 4px;
|
||||
}
|
||||
676
editor/sass/diff.scss
Normal file
@@ -0,0 +1,676 @@
|
||||
/**
|
||||
* 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.
|
||||
**/
|
||||
|
||||
|
||||
.node-dialog-view-diff-panel {
|
||||
padding: 5px;
|
||||
padding-top: 30px;
|
||||
position: relative;
|
||||
|
||||
.red-ui-editableList-container {
|
||||
border-radius:1px;
|
||||
padding:0;
|
||||
background: #f9f9f9;
|
||||
}
|
||||
.node-dialog-view-diff-diff {
|
||||
li {
|
||||
background: #f9f9f9;
|
||||
padding: 0px;
|
||||
border: none;
|
||||
min-height: 0;
|
||||
}
|
||||
}
|
||||
.red-ui-editableList-item-content {
|
||||
padding: 5px;
|
||||
// padding-bottom: 5px;
|
||||
}
|
||||
}
|
||||
.node-diff-container {
|
||||
position: absolute;
|
||||
top: 40px;
|
||||
right:0;
|
||||
bottom: 0;
|
||||
left: 0;
|
||||
overflow-y: scroll;
|
||||
}
|
||||
|
||||
.node-dialog-view-diff-headers {
|
||||
position: absolute;
|
||||
left:232px;
|
||||
right:12px;
|
||||
top: 5px;
|
||||
height: 25px;
|
||||
div {
|
||||
height: 25px;
|
||||
display: inline-block;
|
||||
box-sizing: border-box;
|
||||
padding-top: 2px;
|
||||
overflow: hidden;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
width: 50%;
|
||||
background: #f9f9f9;
|
||||
text-align: center;
|
||||
border-top: 1px solid $secondary-border-color;
|
||||
border-color:$secondary-border-color;
|
||||
border-left: 1px solid $secondary-border-color;
|
||||
}
|
||||
div:last-child {
|
||||
border-right: 1px solid $secondary-border-color;
|
||||
}
|
||||
}
|
||||
|
||||
.node-diff-toolbar {
|
||||
box-sizing: border-box;
|
||||
color: #666;
|
||||
text-align: right;
|
||||
padding: 8px 10px;
|
||||
background: #f3f3f3;
|
||||
border-bottom: 1px solid $secondary-border-color;
|
||||
white-space: nowrap;
|
||||
}
|
||||
.node-diff-tab {
|
||||
background: #fff;
|
||||
border: 1px solid #ddd;
|
||||
border-radius: 1px;
|
||||
overflow: hidden;
|
||||
|
||||
&.collapsed {
|
||||
.node-diff-tab-title .node-diff-chevron {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
.node-diff-node-entry {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.node-diff-tab-stats {
|
||||
font-size: 0.9em;
|
||||
}
|
||||
|
||||
.node-diff-chevron {
|
||||
display: inline-block;
|
||||
width: 15px;
|
||||
text-align: center;
|
||||
margin-left: 3px;
|
||||
transition: transform 0.1s ease-in-out;
|
||||
|
||||
}
|
||||
.node-diff-node-entry {
|
||||
margin-left: 20px;
|
||||
font-size: 0.9em;
|
||||
|
||||
&:first-child {
|
||||
border-top: 1px solid $secondary-border-color;
|
||||
}
|
||||
&:not(:last-child) {
|
||||
border-bottom: 1px solid $secondary-border-color;
|
||||
}
|
||||
|
||||
&.collapsed {
|
||||
.node-diff-chevron {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
.node-diff-node-entry-properties {
|
||||
display: none;
|
||||
}
|
||||
}
|
||||
&:not(.collapsed) {
|
||||
.node-diff-node-entry-cell:not(:first-child) {
|
||||
//display: none;
|
||||
}
|
||||
.node-diff-node-entry-cell:first-child {
|
||||
//width: 100%
|
||||
}
|
||||
}
|
||||
|
||||
table {
|
||||
border-collapse: collapse;
|
||||
table-layout:fixed;
|
||||
width: calc(100% - 20px);
|
||||
margin-left: 20px;
|
||||
}
|
||||
col:first-child {
|
||||
width: 180px;
|
||||
}
|
||||
col:not(:first-child) {
|
||||
width: 100%;
|
||||
}
|
||||
td, th {
|
||||
border-top: 1px solid #f3f3f3;
|
||||
border-left: 1px solid $secondary-border-color;
|
||||
&:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
padding: 0 0 0 3px;
|
||||
text-align: left;
|
||||
overflow-x: auto;
|
||||
}
|
||||
tr {
|
||||
vertical-align: top;
|
||||
&:first-child td {
|
||||
white-space:nowrap;
|
||||
overflow:hidden;
|
||||
}
|
||||
&:hover {
|
||||
background: #f9f9f9;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
td {
|
||||
.node-diff-status {
|
||||
margin-left: 0;
|
||||
}
|
||||
}
|
||||
tr:not(.node-diff-property-header) {
|
||||
.node-diff-status {
|
||||
width: 12px;
|
||||
margin-left: 0;
|
||||
margin-top: 0;
|
||||
margin-bottom: 0;
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.node-diff-three-way {
|
||||
.node-diff-node-entry-cell {
|
||||
width: calc((100% - 220px) / 2);
|
||||
&:first-child {
|
||||
width: 220px;
|
||||
}
|
||||
}
|
||||
col:not(:first-child) {
|
||||
width:50%;
|
||||
}
|
||||
|
||||
.node-diff-node-entry {
|
||||
.node-diff-node-entry-cell {
|
||||
width: calc((100% + 20px - 220px) / 2);
|
||||
&:first-child {
|
||||
width: 200px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.node-diff-column {
|
||||
display:inline-block;
|
||||
height:100%;
|
||||
width:50%;
|
||||
box-sizing: border-box;
|
||||
white-space:nowrap;
|
||||
overflow: hidden;
|
||||
&:first-child {
|
||||
border-right: 1px solid $secondary-border-color
|
||||
}
|
||||
}
|
||||
|
||||
.node-diff-tab-title {
|
||||
cursor: pointer;
|
||||
padding: 0;
|
||||
// background: #f6f6f6;
|
||||
&:hover {
|
||||
background: #f9f9f9;
|
||||
}
|
||||
}
|
||||
.node-diff-tab-title-meta {
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
padding-top: 2px;
|
||||
}
|
||||
.node-diff-node-entry-header {
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background: #f9f9f9;
|
||||
}
|
||||
}
|
||||
.node-diff-node-entry-node {
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
margin: 5px;
|
||||
width: 18px;
|
||||
height: 15px;
|
||||
background: #ddd;
|
||||
border-radius: 2px;
|
||||
border: 1px solid #999;
|
||||
background-position: 5% 50%;
|
||||
background-repeat: no-repeat;
|
||||
background-size: contain;
|
||||
position: relative;
|
||||
|
||||
.palette_icon {
|
||||
background-position: 49% 50%;
|
||||
width: 15px;
|
||||
}
|
||||
.palette_icon_container {
|
||||
width: 18px;
|
||||
}
|
||||
}
|
||||
.node-diff-tab-empty {
|
||||
.node-diff-chevron i {
|
||||
display: none;
|
||||
}
|
||||
.node-diff-tab-title {
|
||||
cursor: default;
|
||||
&:hover {
|
||||
background: none;
|
||||
}
|
||||
}
|
||||
}
|
||||
.node-diff-node-deleted {
|
||||
//background: #fadddd;
|
||||
cursor: default !important;
|
||||
.node-diff-status {
|
||||
color: #f80000;
|
||||
}
|
||||
.node-diff-node-entry-node {
|
||||
opacity: 0.5;
|
||||
}
|
||||
.node-diff-node-description {
|
||||
opacity: 0.5;
|
||||
text-decoration: line-through;
|
||||
}
|
||||
}
|
||||
.node-diff-node-added {
|
||||
//background: #eefaee;
|
||||
cursor: default !important;
|
||||
.node-diff-status {
|
||||
color: #009900;
|
||||
}
|
||||
}
|
||||
.node-diff-node-moved {
|
||||
//background: #eefaee;
|
||||
.node-diff-status {
|
||||
color: #3f81b3;
|
||||
}
|
||||
}
|
||||
|
||||
.node-diff-node-changed {
|
||||
//background: #fff2ca;
|
||||
.node-diff-status {
|
||||
color: #f89406;
|
||||
}
|
||||
}
|
||||
.node-diff-node-unchanged {
|
||||
//background: #fff2ca;
|
||||
.node-diff-status {
|
||||
color: #bbb;
|
||||
}
|
||||
}
|
||||
.node-diff-node-conflict {
|
||||
.node-diff-status {
|
||||
color: #9b45ce;
|
||||
}
|
||||
}
|
||||
.node-diff-node-entry-title {
|
||||
display: inline-block;
|
||||
.node-diff-status {
|
||||
margin-left: 15px;
|
||||
}
|
||||
}
|
||||
.node-diff-node-entry-properties {
|
||||
margin: 0;
|
||||
color: #666;
|
||||
}
|
||||
.node-diff-status {
|
||||
display: inline-block;
|
||||
height: 20px;
|
||||
margin-left: 5px;
|
||||
vertical-align: top;
|
||||
margin-top: 6px;
|
||||
margin-bottom: 6px;
|
||||
text-align: center;
|
||||
}
|
||||
.node-diff-element {
|
||||
display: inline-block;
|
||||
width: calc(100% - 20px);
|
||||
}
|
||||
|
||||
.node-diff-node-description {
|
||||
color: $form-text-color;
|
||||
margin-right: 5px;
|
||||
padding-top: 5px;
|
||||
display: inline-block;
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
.node-diff-node-meta {
|
||||
float: right;
|
||||
//font-size: 0.9em;
|
||||
color: #999;
|
||||
margin-top: 7px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
|
||||
.node-diff-count { color: #999}
|
||||
.node-diff-added { color: #009900}
|
||||
.node-diff-deleted { color: #f80000}
|
||||
.node-diff-changed { color: #f89406}
|
||||
.node-diff-unchanged { color: #bbb}
|
||||
.node-diff-conflicted { color: purple}
|
||||
|
||||
|
||||
.node-diff-node-entry-cell {
|
||||
display: inline-block;
|
||||
vertical-align: top;
|
||||
box-sizing: border-box;
|
||||
width: calc( (100% - 20px) / 2);
|
||||
height: 32px;
|
||||
border-left: 1px solid $secondary-border-color;
|
||||
padding-top: 2px;
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
position: relative;
|
||||
}
|
||||
.node-diff-empty {
|
||||
background: #f3f3f3;
|
||||
background: repeating-linear-gradient(
|
||||
20deg,
|
||||
#fff, #fff 5px,
|
||||
#f6f6f6 5px,
|
||||
#f6f6f6 10px
|
||||
);
|
||||
}
|
||||
.node-diff-node-entry-cell:first-child {
|
||||
border-left: none;
|
||||
}
|
||||
.node-diff-property-cell-label {
|
||||
margin-left: 20px;
|
||||
vertical-align: top;
|
||||
box-sizing: border-box;
|
||||
padding-left: 8px;
|
||||
width: 120px;
|
||||
}
|
||||
.node-diff-property-wires {
|
||||
display: inline-block;
|
||||
.node-diff-node-entry-node {
|
||||
width: 18px;
|
||||
height: 15px;
|
||||
}
|
||||
.palette_icon_container {
|
||||
width: 18px;
|
||||
}
|
||||
.palette_icon {
|
||||
width: 15px;
|
||||
}
|
||||
ul,li,ol {
|
||||
background: none !important;
|
||||
}
|
||||
ul {
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
margin-left: 5px;
|
||||
}
|
||||
li {
|
||||
list-style-type: none !important;
|
||||
}
|
||||
ol {
|
||||
font-size: 0.9em;
|
||||
margin: 0;
|
||||
& > span {
|
||||
vertical-align: middle;
|
||||
display: inline-block;
|
||||
width: 30px;
|
||||
text-align: center;
|
||||
}
|
||||
& > li:not(:last-child) {
|
||||
border-bottom: 1px solid #999;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
.node-diff-node-props .node-diff-node-entry-cell:first-child {
|
||||
padding: 6px 0px;
|
||||
span:not(.node-diff-chevron) {
|
||||
margin-left: 5px;
|
||||
}
|
||||
|
||||
}
|
||||
.node-diff-property-cell {
|
||||
// vertical-align: top;
|
||||
// display:inline-block;
|
||||
//
|
||||
// box-sizing: border-box;
|
||||
// padding: 1px 5px;
|
||||
//min-height: 30px;
|
||||
|
||||
&.node-diff-node-changed {
|
||||
background: #fff2e1 !important;
|
||||
}
|
||||
&.node-diff-node-conflict {
|
||||
background: #ffdad4 !important;
|
||||
}
|
||||
}
|
||||
|
||||
.node-diff-selectbox {
|
||||
position: absolute;
|
||||
top:0;
|
||||
right:0;
|
||||
bottom:0;
|
||||
width: 35px;
|
||||
text-align: center;
|
||||
border-left: 1px solid #eee;
|
||||
margin:0;
|
||||
input {
|
||||
margin-top: 8px;
|
||||
}
|
||||
|
||||
&:hover {
|
||||
background: #f3f3f3;
|
||||
}
|
||||
}
|
||||
|
||||
.node-diff-node-entry-conflict.node-diff-select-remote {
|
||||
.node-diff-node-remote {
|
||||
background: #e7ffe3;
|
||||
label {
|
||||
border-left-color: #b8daad;
|
||||
}
|
||||
}
|
||||
.node-diff-node-local {
|
||||
background: #ffe1e1;
|
||||
label {
|
||||
border-left-color: #e4bcbc;
|
||||
}
|
||||
}
|
||||
}
|
||||
.node-diff-node-entry-conflict.node-diff-select-local {
|
||||
.node-diff-node-local {
|
||||
background: #e7ffe3;
|
||||
label {
|
||||
border-left-color: #b8daad;
|
||||
}
|
||||
}
|
||||
.node-diff-node-remote {
|
||||
background: #ffe1e1;
|
||||
label {
|
||||
border-left-color: #e4bcbc;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
ul.node-dialog-configm-deploy-list {
|
||||
font-size: 0.9em;
|
||||
width: 400px;
|
||||
margin: 10px auto;
|
||||
text-align: left;
|
||||
}
|
||||
|
||||
.node-dialog-confirm-conflict-row {
|
||||
img {
|
||||
vertical-align:middle;
|
||||
height: 30px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
i {
|
||||
vertical-align:middle;
|
||||
text-align: center;
|
||||
font-size: 30px;
|
||||
width: 30px;
|
||||
margin-right: 10px;
|
||||
}
|
||||
div {
|
||||
vertical-align: middle;
|
||||
width: calc(100% - 60px);
|
||||
display:inline-block;
|
||||
}
|
||||
}
|
||||
|
||||
#node-diff-toolbar-resolved-conflicts .node-diff-status {
|
||||
margin:0;
|
||||
}
|
||||
.node-diff-text-diff-button {
|
||||
float: right;
|
||||
margin: 2px 3px;
|
||||
line-height: 14px;
|
||||
height: 16px;
|
||||
|
||||
}
|
||||
.node-text-diff {
|
||||
height: 100%;
|
||||
overflow-y:auto;
|
||||
|
||||
table.node-text-diff-content {
|
||||
margin: 10px;
|
||||
border: 1px solid $secondary-border-color;
|
||||
border-radius: 3px;
|
||||
table-layout: fixed;
|
||||
width: calc(100% - 20px);
|
||||
td {
|
||||
vertical-align: top;
|
||||
word-wrap: break-word;
|
||||
}
|
||||
td.lineno {
|
||||
font-family: monospace;
|
||||
text-align: right;
|
||||
color: #aaa;
|
||||
background: #f6f6f6;
|
||||
padding: 1px 5px;
|
||||
}
|
||||
td.lineno:nth-child(3) {
|
||||
border-left: 1px solid $secondary-border-color;
|
||||
}
|
||||
td.linetext {
|
||||
font-family: monospace;
|
||||
white-space: pre-wrap;
|
||||
padding: 1px 5px;
|
||||
span.prefix {
|
||||
width: 30px;
|
||||
display: inline-block;
|
||||
text-align: center;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
td.blank {
|
||||
background: #f6f6f6;
|
||||
}
|
||||
td.added {
|
||||
background: #eefaee;
|
||||
}
|
||||
td.removed {
|
||||
background: #fadddd;
|
||||
}
|
||||
tr.mergeHeader td {
|
||||
color: #800080;
|
||||
background: #e5f9ff;
|
||||
height: 26px;
|
||||
vertical-align: middle;
|
||||
}
|
||||
tr.mergeHeader-separator td {
|
||||
color: #800080;
|
||||
background: darken(#e5f9ff, 10%);
|
||||
height: 0px;
|
||||
}
|
||||
tr.mergeHeader-ours td {
|
||||
border-top: 2px solid darken(#e5f9ff, 10%);
|
||||
}
|
||||
tr.mergeHeader-theirs td {
|
||||
border-bottom: 2px solid darken(#e5f9ff, 10%);
|
||||
}
|
||||
td.unchanged {
|
||||
color: #999;
|
||||
}
|
||||
tr.unchanged {
|
||||
background: #fefefe;
|
||||
}
|
||||
tr.start-block {
|
||||
border-top: 1px solid #f0f0f0;
|
||||
}
|
||||
tr.end-block {
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
tr.node-text-diff-file-header td {
|
||||
.filename {
|
||||
font-family: monospace;
|
||||
}
|
||||
background: #f3f3f3;
|
||||
padding: 5px 10px 5px 0;
|
||||
color: #333;
|
||||
cursor: pointer;
|
||||
i.node-diff-chevron {
|
||||
width: 30px;
|
||||
}
|
||||
}
|
||||
tr.node-text-diff-file-header.collapsed {
|
||||
td i.node-diff-chevron {
|
||||
transform: rotate(-90deg);
|
||||
}
|
||||
}
|
||||
tr.node-text-diff-commit-header td {
|
||||
background: #f3f3f3;
|
||||
padding: 5px 10px;
|
||||
color: #333;
|
||||
h3 {
|
||||
font-size: 1.4em;
|
||||
margin: 0;
|
||||
}
|
||||
.commit-summary {
|
||||
border-top: 1px solid $secondary-border-color;
|
||||
padding-top: 5px;
|
||||
color: #999;
|
||||
}
|
||||
.commit-body {
|
||||
margin-bottom:15px;
|
||||
white-space: pre;
|
||||
line-height: 1.2em;
|
||||
}
|
||||
}
|
||||
|
||||
tr.node-text-diff-header > td:not(.flow-diff) {
|
||||
font-family: monospace;
|
||||
padding: 5px 10px;
|
||||
text-align: left;
|
||||
color: #666;
|
||||
background: #ffd;
|
||||
height: 30px;
|
||||
vertical-align: middle;
|
||||
border-top: 1px solid #f0f0f0;
|
||||
border-bottom: 1px solid #f0f0f0;
|
||||
}
|
||||
tr.node-text-diff-expand td {
|
||||
cursor: pointer;
|
||||
&:hover {
|
||||
background: #ffc;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -23,6 +23,7 @@
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
display: none;
|
||||
z-index:100;
|
||||
}
|
||||
#dropTarget div {
|
||||
display: table-cell;
|
||||
@@ -34,4 +35,3 @@
|
||||
#dropTarget div i {
|
||||
font-size: 80px;
|
||||
}
|
||||
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2015 IBM Corp.
|
||||
* 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.
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
/**
|
||||
* Copyright 2015 IBM Corp.
|
||||
* 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.
|
||||
@@ -14,8 +14,156 @@
|
||||
* limitations under the License.
|
||||
**/
|
||||
|
||||
.dialog-form, #dialog-form, #dialog-config-form {
|
||||
|
||||
#editor-stack {
|
||||
position: absolute;
|
||||
margin: 0;
|
||||
top: 0;
|
||||
bottom: 0px;
|
||||
right: 323px;
|
||||
width: 0;
|
||||
z-index: 5;
|
||||
}
|
||||
.editor-tray {
|
||||
position:absolute;
|
||||
margin: 0;
|
||||
top: 0;
|
||||
//min-width: 500px;
|
||||
width: auto;
|
||||
right: -1000px;
|
||||
bottom: 0;
|
||||
background: #fff;
|
||||
border-left: 1px solid $secondary-border-color;
|
||||
border-bottom: 1px solid $primary-border-color;
|
||||
box-sizing: content-box;
|
||||
}
|
||||
.editor-tray.open {
|
||||
right: 0;
|
||||
}
|
||||
.editor-tray-body-wrapper {
|
||||
width: 100%;
|
||||
box-sizing: border-box;
|
||||
overflow: auto;
|
||||
}
|
||||
.editor-tray-body {
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
padding: 0.1px; // prevent margin collapsing
|
||||
.dialog-form,#dialog-form, #node-config-dialog-edit-form {
|
||||
margin: 20px;
|
||||
height: calc(100% - 40px);
|
||||
}
|
||||
}
|
||||
.editor-tray-content {
|
||||
overflow: auto;
|
||||
}
|
||||
.editor-tray-header {
|
||||
@include disable-selection;
|
||||
position: relative;
|
||||
box-sizing: border-box;
|
||||
font-weight: bold;
|
||||
border-bottom: 1px solid $secondary-border-color;
|
||||
background: $palette-header-background;
|
||||
&:after {
|
||||
content: "";
|
||||
display: table;
|
||||
clear: both;
|
||||
}
|
||||
}
|
||||
|
||||
.editor-tray-footer {
|
||||
@include component-footer;
|
||||
height: 35px;
|
||||
|
||||
button {
|
||||
@include editor-button;
|
||||
padding: 3px 7px;
|
||||
font-size: 11px;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
.editor-tray-toolbar {
|
||||
text-align: right;
|
||||
padding: 6px;
|
||||
|
||||
button {
|
||||
@include editor-button;
|
||||
&.toggle {
|
||||
@include workspace-button-toggle;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
.editor-tray-titlebar {
|
||||
border-bottom: 1px solid $secondary-border-color;
|
||||
padding: 8px;
|
||||
}
|
||||
.editor-tray-breadcrumbs {
|
||||
list-style-type: none;
|
||||
margin: 0;
|
||||
padding:0;
|
||||
|
||||
li {
|
||||
display: inline-block;
|
||||
padding:0;
|
||||
margin:0;
|
||||
|
||||
&:not(:last-child) {
|
||||
color: $editor-button-color;
|
||||
font-weight: normal;
|
||||
|
||||
&:after {
|
||||
display: inline-block;
|
||||
content: '>';
|
||||
margin: 0 5px;
|
||||
}
|
||||
|
||||
}
|
||||
}
|
||||
}
|
||||
.editor-tray-resize-handle {
|
||||
position: absolute;
|
||||
top: 0px;
|
||||
bottom: 0px;
|
||||
width: 7px;
|
||||
left: -9px;
|
||||
background: $background-color url(images/grip.png) no-repeat 50% 50%;
|
||||
cursor: col-resize;
|
||||
border-left: 1px solid $primary-border-color;
|
||||
box-shadow: -1px 0 6px rgba(0,0,0,0.1);
|
||||
|
||||
&.editor-tray-resize-maximised {
|
||||
background: $background-color;
|
||||
cursor: default;
|
||||
}
|
||||
}
|
||||
.editor-tray-resize-button {
|
||||
@include workspace-button;
|
||||
display: block;
|
||||
height: 37px;
|
||||
line-height: 35px;
|
||||
border: none;
|
||||
border-bottom: 1px solid $secondary-border-color;
|
||||
margin: 0;
|
||||
background: $background-color;
|
||||
color: $workspace-button-color;
|
||||
}
|
||||
#palette-shade, #editor-shade, #header-shade, #sidebar-shade {
|
||||
@include shade;
|
||||
z-index: 2;
|
||||
}
|
||||
#sidebar-shade {
|
||||
left: -8px;
|
||||
top: -1px;
|
||||
bottom: -1px;
|
||||
}
|
||||
#full-shade {
|
||||
@include shade;
|
||||
z-index: 15;
|
||||
}
|
||||
|
||||
.dialog-form,#dialog-form, #node-config-dialog-edit-form {
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
@@ -23,10 +171,6 @@
|
||||
border-color: rgb(214, 97, 95) !important;
|
||||
}
|
||||
|
||||
.ui-dialog .ui-dialog-buttonpane button.leftButton {
|
||||
margin-right: 40px;
|
||||
}
|
||||
|
||||
.form-row {
|
||||
clear: both;
|
||||
color: $form-text-color;
|
||||
@@ -36,7 +180,7 @@
|
||||
display: inline-block;
|
||||
width: 100px;
|
||||
}
|
||||
.form-row input {
|
||||
.form-row input, .form-row div[contenteditable="true"] {
|
||||
width:70%;
|
||||
}
|
||||
|
||||
@@ -55,12 +199,16 @@
|
||||
text-decoration: underline;
|
||||
}
|
||||
|
||||
.form-warning {
|
||||
border-color: #d6615f;
|
||||
}
|
||||
|
||||
.node-text-editor {
|
||||
border:1px solid #ccc;
|
||||
border-radius:5px;
|
||||
overflow: hidden;
|
||||
font-size: 14px !important;
|
||||
font-family: monospace !important;
|
||||
font-family: Menlo, Consolas, 'DejaVu Sans Mono', Courier, monospace !important;
|
||||
}
|
||||
|
||||
.editor-button {
|
||||
@@ -68,11 +216,19 @@
|
||||
height: 34px;
|
||||
line-height: 32px;
|
||||
font-size: 13px;
|
||||
border-radius: 4px;
|
||||
border-radius: 2px;
|
||||
padding: 0 10px;
|
||||
white-space: nowrap;
|
||||
text-overflow: ellipsis;
|
||||
&.toggle {
|
||||
@include workspace-button-toggle;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
.editor-button-small {
|
||||
height: 20px;
|
||||
min-width: 20px;
|
||||
line-height: 18px;
|
||||
font-size: 10px;
|
||||
border-radius: 2px;
|
||||
@@ -83,6 +239,7 @@
|
||||
cursor: auto;
|
||||
float: right;
|
||||
font-size: 12px !important;
|
||||
line-height: 35px;
|
||||
}
|
||||
#node-config-dialog-scope-warning {
|
||||
display: inline-block;
|
||||
@@ -94,13 +251,166 @@
|
||||
margin: 1px 0 0 0;
|
||||
padding: 0;
|
||||
height: 22px;
|
||||
width: 110px;
|
||||
width: 200px;
|
||||
|
||||
}
|
||||
#node-config-dialog-user-count {
|
||||
vertical-align: middle;
|
||||
display:inline-block;
|
||||
margin-top: 10px;
|
||||
margin-right: 20px;
|
||||
float:left;
|
||||
font-size: 12px;
|
||||
line-height: 35px;
|
||||
}
|
||||
.node-input-expression-editor #dialog-form {
|
||||
margin: 0;
|
||||
height: 100%;
|
||||
.red-ui-panel {
|
||||
&:first-child {
|
||||
padding: 20px 20px 0;
|
||||
}
|
||||
&:last-child {
|
||||
padding-bottom: 20px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.node-input-expression-tab-content {
|
||||
position: relative;
|
||||
padding: 0 20px;
|
||||
}
|
||||
|
||||
#node-input-expression-help {
|
||||
position: absolute;
|
||||
top: 35px;
|
||||
left:0;
|
||||
right: 0;
|
||||
bottom:0;
|
||||
padding: 0 20px;
|
||||
overflow: auto;
|
||||
box-sizing: border-box;
|
||||
}
|
||||
#node-input-expression-panel-info {
|
||||
& > .form-row {
|
||||
margin: 0;
|
||||
& > div:first-child {
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
}
|
||||
.node-input-expression-legacy, .node-input-buffer-type {
|
||||
font-size: 0.8em;
|
||||
float: left;
|
||||
cursor: pointer;
|
||||
border: 1px solid white;
|
||||
padding: 2px 5px;
|
||||
border-radius: 2px;
|
||||
&:hover {
|
||||
border-color: $form-input-border-color;
|
||||
}
|
||||
}
|
||||
.node-input-buffer-type {
|
||||
float: none;
|
||||
text-align: right;
|
||||
}
|
||||
|
||||
#clipboard-hidden {
|
||||
position: absolute;
|
||||
top: -3000px;
|
||||
}
|
||||
.node-label-form-row {
|
||||
margin: 5px 0;
|
||||
label {
|
||||
margin-right: 20px;
|
||||
text-align: right;
|
||||
width: 30px;
|
||||
}
|
||||
button {
|
||||
margin-left: 10px;
|
||||
}
|
||||
input {
|
||||
width: calc(100% - 100px);
|
||||
}
|
||||
#node-settings-icon-module {
|
||||
width: calc(55% - 50px);
|
||||
}
|
||||
#node-settings-icon-file {
|
||||
width: calc(45% - 55px);
|
||||
margin-left: 5px;
|
||||
}
|
||||
}
|
||||
.node-label-form-none {
|
||||
span {
|
||||
padding-left: 50px;
|
||||
width: 100px;
|
||||
color: #999;
|
||||
}
|
||||
}
|
||||
|
||||
.ace_read-only {
|
||||
background: #eee !important;
|
||||
.ace_cursor {
|
||||
color: transparent !important;
|
||||
}
|
||||
|
||||
}
|
||||
#node-settings-icon {
|
||||
margin-left: 10px;
|
||||
width: calc(100% - 163px);
|
||||
}
|
||||
.red-ui-icon-picker {
|
||||
position: absolute;
|
||||
border: 1px solid $primary-border-color;
|
||||
box-shadow: 0 1px 6px -3px black;
|
||||
background: white;
|
||||
z-Index: 21;
|
||||
display: none;
|
||||
select {
|
||||
box-sizing: border-box;
|
||||
margin: 3px;
|
||||
width: calc(100% - 6px);
|
||||
}
|
||||
}
|
||||
.red-ui-icon-list {
|
||||
width: 308px;
|
||||
height: 200px;
|
||||
overflow-y: scroll;
|
||||
line-height: 0px;
|
||||
}
|
||||
.red-ui-icon-list-icon {
|
||||
display: inline-block;
|
||||
margin: 2px;
|
||||
padding: 4px;
|
||||
cursor: pointer;
|
||||
border-radius: 4px;
|
||||
&:hover {
|
||||
background: lighten($node-selected-color,20%);
|
||||
}
|
||||
&.selected {
|
||||
background: lighten($node-selected-color,20%);
|
||||
.red-ui-search-result-node {
|
||||
border-color: white;
|
||||
}
|
||||
}
|
||||
}
|
||||
.red-ui-icon-list-module {
|
||||
background: $palette-header-background;
|
||||
font-size: 0.9em;
|
||||
padding: 3px;
|
||||
color: #666;
|
||||
clear: both;
|
||||
i {
|
||||
margin-right: 5px;
|
||||
}
|
||||
}
|
||||
.red-ui-icon-meta {
|
||||
border-top: 1px solid $secondary-border-color;
|
||||
span {
|
||||
padding: 4px;
|
||||
color: #666;
|
||||
font-size: 0.9em;
|
||||
}
|
||||
button {
|
||||
float: right;
|
||||
margin: 2px;
|
||||
}
|
||||
}
|
||||
|
||||