Compare commits
	
		
			790 Commits
		
	
	
		
			0.20.0-bet
			...
			setmessage
		
	
	| Author | SHA1 | Date | |
|---|---|---|---|
|  | d5d9ac5c76 | ||
|  | 9d4238e5cc | ||
|  | ee6f6ae391 | ||
|  | 95a51aafdc | ||
|  | 5e7cd79ed9 | ||
|  | aba6173e23 | ||
|  | e2c3b35391 | ||
|  | 448de23f59 | ||
|  | 44a07c74fd | ||
|  | 0f8af4ba1c | ||
|  | 214d788029 | ||
|  | 530bf22bd5 | ||
|  | ccc98370eb | ||
|  | 7640bc029c | ||
|  | 3f72eb51a0 | ||
|  | 8801ace247 | ||
|  | faf46e4447 | ||
|  | 63978e226b | ||
|  | b96164d4f5 | ||
|  | 944070dfb1 | ||
|  | f0584df1d0 | ||
|  | ba209c2bdd | ||
|  | c6e2f28b97 | ||
|  | 2436bb0128 | ||
|  | 9c4640e010 | ||
|  | 1ee43113b1 | ||
|  | 902f477ee3 | ||
|  | 9c1d46ff92 | ||
|  | 9cbd0fceea | ||
|  | b22a4f94ab | ||
|  | a4c351fd4f | ||
|  | a364d4950d | ||
|  | 7805974736 | ||
|  | c1dae95f71 | ||
|  | e7c2ff3bd2 | ||
|  | 25459b52a1 | ||
|  | b81be8f358 | ||
|  | aa6c0b9d6e | ||
|  | 64580237d5 | ||
|  | b93165592e | ||
|  | 83c1e44925 | ||
|  | 3088115aba | ||
|  | fc93e502b8 | ||
|  | e90e6eaac3 | ||
|  | 2f4dcba54d | ||
|  | 683c6a748e | ||
|  | 175a871ee0 | ||
|  | b4e2061e85 | ||
|  | 2aef99c440 | ||
|  | 6c125e125f | ||
|  | 88cbc32abc | ||
|  | 8f45e8f84a | ||
|  | 21635aadfe | ||
|  | d5234888b3 | ||
|  | 1f5ff0c6d3 | ||
|  | 2a2541df59 | ||
|  | cd629c1699 | ||
|  | 4d6828ec14 | ||
|  | dae1d6057e | ||
|  | 6726c42cc8 | ||
|  | 4f6023e44c | ||
|  | 9e16d7f433 | ||
|  | aa86cfc55f | ||
|  | 6931cb9895 | ||
|  | d32d04bd4e | ||
|  | 0b3e9bf5e2 | ||
|  | a4af7b8e21 | ||
|  | 72deee5d74 | ||
|  | 5e9e523d4c | ||
|  | c54509df3d | ||
|  | 63cc9adeaa | ||
|  | 74d760a46d | ||
|  | d46531def8 | ||
|  | eb09ec6834 | ||
|  | 9bd9c6a400 | ||
|  | 7321e206c5 | ||
|  | 2c7917f0ca | ||
|  | d94b20a908 | ||
|  | b1b1fe21dd | ||
|  | 1db3af7c8e | ||
|  | 397fe31f97 | ||
|  | bc283aa025 | ||
|  | 9dbdf0947b | ||
|  | 7c21bf4555 | ||
|  | 361dc194ee | ||
|  | 8c1aa83d12 | ||
|  | d2755a8049 | ||
|  | 1b78bd1684 | ||
|  | 5f67f1f078 | ||
|  | 07061928df | ||
|  | 18ff2df65c | ||
|  | 7b1411d171 | ||
|  | 3a1d0f3695 | ||
|  | 2cd5e1d3c5 | ||
|  | 000765fb77 | ||
|  | 0ff324b0db | ||
|  | a96d5096fe | ||
|  | e8ef476a6d | ||
|  | 22b9df62d1 | ||
|  | 6026da867b | ||
|  | 4d58902ba7 | ||
|  | 4dc1343445 | ||
|  | 080487cb33 | ||
|  | 0febcf4f9e | ||
|  | cd23f711ed | ||
|  | f9b147af42 | ||
|  | 775f1110d3 | ||
|  | 57649a9b81 | ||
|  | 72a268b70a | ||
|  | f86a171dff | ||
|  | e022b782a9 | ||
|  | bd67731bb7 | ||
|  | 25de4e4782 | ||
|  | c590247afa | ||
|  | 5d36539271 | ||
|  | 0d673486a3 | ||
|  | 29f1651a18 | ||
|  | dd20a3e685 | ||
|  | 75a5b1354c | ||
|  | dae9ac8173 | ||
|  | 78b735276b | ||
|  | e10dd54e2b | ||
|  | cb8deab1f9 | ||
|  | e5c27d0236 | ||
|  | faf6fa9450 | ||
|  | 873bdc6733 | ||
|  | 8a40b075b5 | ||
|  | 56c41374bf | ||
|  | a08c2c6437 | ||
|  | e94634544c | ||
|  | 07fe5b247b | ||
|  | c1c694035d | ||
|  | 147d2a02be | ||
|  | 6f91786f4d | ||
|  | f62a933d1c | ||
|  | 451835fbeb | ||
|  | 547e7a1b21 | ||
|  | 053e3ba923 | ||
|  | bf65dcd49b | ||
|  | a1d186112a | ||
|  | ca7a298509 | ||
|  | ff4d58f648 | ||
|  | a1e10e99fa | ||
|  | 16bda530f6 | ||
|  | bf9e04d9db | ||
|  | 8df86a75b1 | ||
|  | 5056203023 | ||
|  | a0026e66ce | ||
|  | f75dd2209d | ||
|  | e35f6d9e35 | ||
|  | 3cb00ce4e0 | ||
|  | 8e18cf5986 | ||
|  | 81f80600f5 | ||
|  | 895156675f | ||
|  | 1c424e2e0a | ||
|  | 0124bb17e8 | ||
|  | 2c89b2d262 | ||
|  | c7bbe2f1fe | ||
|  | 88609a8829 | ||
|  | 329beb166c | ||
|  | e36f3d937c | ||
|  | 1395092ca6 | ||
|  | c09004dbc8 | ||
|  | 7efe4a2776 | ||
|  | b763e0b0cb | ||
|  | ddd0d1bef3 | ||
|  | dbca2178c0 | ||
|  | af742ea536 | ||
|  | 14c1a86b9b | ||
|  | ee3dc8c4cd | ||
|  | 1ed148aaf5 | ||
|  | 3327adb1ae | ||
|  | 4d5f771f9f | ||
|  | aa69d663ed | ||
|  | 29d1894f9a | ||
|  | e5738d608c | ||
|  | 9775d3a33d | ||
|  | ad4cf8d631 | ||
|  | a27e8777aa | ||
|  | d23edcc0b5 | ||
|  | 52373e5bef | ||
|  | bb70e796a1 | ||
|  | 3365d26b40 | ||
|  | d3c111b533 | ||
|  | ec876eb102 | ||
|  | dddfb1ec08 | ||
|  | 6fc9c03d70 | ||
|  | 199ff071e8 | ||
|  | 7e4a06044a | ||
|  | d047b75cb7 | ||
|  | 6fb6b13037 | ||
|  | 460c5a1ae3 | ||
|  | 9955bcc339 | ||
|  | 0a3ab996eb | ||
|  | 46f912a6f9 | ||
|  | 01e0f24752 | ||
|  | 7178c63e10 | ||
|  | 30c402eb83 | ||
|  | 2601cc898c | ||
|  | d2a8823808 | ||
|  | 6b61fa9f6f | ||
|  | 247052df5f | ||
|  | 8eb28555bc | ||
|  | 73132475dc | ||
|  | 42c6487ff3 | ||
|  | 8d2ca25fd6 | ||
|  | 5c5919a7eb | ||
|  | 34cdbfc852 | ||
|  | 1bc50194aa | ||
|  | 4a75236e74 | ||
|  | 64b2f881c4 | ||
|  | 4709ddea5d | ||
|  | 6ef49152f3 | ||
|  | 1c44b0bc98 | ||
|  | 11bce8c17c | ||
|  | b42fff1055 | ||
|  | 1b2e442513 | ||
|  | a4d48077ba | ||
|  | 901e2527d8 | ||
|  | f0839571d0 | ||
|  | 89d0d6ec93 | ||
|  | 922ab1d17b | ||
|  | 7c7be378bc | ||
|  | ec01f8f54b | ||
|  | 5a094b44c4 | ||
|  | 3c657a6645 | ||
|  | 3129d44ff1 | ||
|  | 00306f82c5 | ||
|  | 7def676a17 | ||
|  | 6c48735854 | ||
|  | a0b1831cdb | ||
|  | db9fb8480a | ||
|  | c138e2ffb4 | ||
|  | 473c45794e | ||
|  | a12aa81d73 | ||
|  | 0033e279f1 | ||
|  | a25e98d0cb | ||
|  | bc65480f27 | ||
|  | 8582cda124 | ||
|  | d963dfdbb6 | ||
|  | f7e9c109f6 | ||
|  | 30c3004f27 | ||
|  | 4f049fd94b | ||
|  | f98d1c95cc | ||
|  | a2b5c0247b | ||
|  | 28bda9fa41 | ||
|  | 18aeeab041 | ||
|  | c7427a5f7c | ||
|  | 03aa6c7d3a | ||
|  | 10077ae750 | ||
|  | 74eec25285 | ||
|  | b6055479a1 | ||
|  | 69b781419f | ||
|  | da6db24f9e | ||
|  | 2b66723d42 | ||
|  | 00a3e25714 | ||
|  | 8ccbd2d8f9 | ||
|  | 8307f26099 | ||
|  | c686f7eefc | ||
|  | 311c7b1158 | ||
|  | a17325f028 | ||
|  | b734097d16 | ||
|  | afaf077aca | ||
|  | bf14af6a1f | ||
|  | e72faef839 | ||
|  | b274bafe8e | ||
|  | 7bed967755 | ||
|  | 944b81b71c | ||
|  | cd529d53ae | ||
|  | 0d680a58f3 | ||
|  | b30d519523 | ||
|  | 83932e1725 | ||
|  | 4ce0e39760 | ||
|  | 84232f25f0 | ||
|  | 2daedf8fd5 | ||
|  | fe084a4478 | ||
|  | 5bf9646a76 | ||
|  | 2b1f28e6c2 | ||
|  | 5b8bd6e64f | ||
|  | 426fd499ce | ||
|  | 17d3a5840d | ||
|  | be49e1d383 | ||
|  | daa98e8925 | ||
|  | 58784b7568 | ||
|  | 419a183167 | ||
|  | 675b4bde14 | ||
|  | ee6ee99577 | ||
|  | 3bc1f69e75 | ||
|  | 5b9df6d5f2 | ||
|  | 9f062ec1b8 | ||
|  | b52a47bd03 | ||
|  | 5e20134f4f | ||
|  | 89d267d6a2 | ||
|  | 607bc42f59 | ||
|  | 880757fb5d | ||
|  | c8acc6a12e | ||
|  | 7d4c2442da | ||
|  | e5255b0c7c | ||
|  | ac3ef9b6fc | ||
|  | 7b5a41c3ff | ||
|  | d5b0d2a886 | ||
|  | 4d60447242 | ||
|  | 78bee3dc59 | ||
|  | e2db958510 | ||
|  | 16440072fb | ||
|  | be2dd6dc32 | ||
|  | 189bde7c9c | ||
|  | 6a4760e291 | ||
|  | c082bb97e0 | ||
|  | c8e14f91e7 | ||
|  | 6032d096ec | ||
|  | defa9a2270 | ||
|  | 77a913f858 | ||
|  | 6e3fa974ba | ||
|  | 7926055b97 | ||
|  | ffd10e656e | ||
|  | 59c1828078 | ||
|  | 6164271fe8 | ||
|  | 26ba35933d | ||
|  | 87359937c9 | ||
|  | 9b938f6515 | ||
|  | 6c3913785d | ||
|  | 542cf3147d | ||
|  | fb9828badc | ||
|  | 2505ac3f98 | ||
|  | fde8548166 | ||
|  | fe91295704 | ||
|  | 15b99c5749 | ||
|  | 9d66ca4a49 | ||
|  | b749a27f86 | ||
|  | 083212cffe | ||
|  | c4e8756210 | ||
|  | 3a6448f727 | ||
|  | fe18df25ba | ||
|  | db65460ec0 | ||
|  | 0ad3eceb82 | ||
|  | a376d6e361 | ||
|  | 45c7f3f3ca | ||
|  | 238de59a2a | ||
|  | 96255e51d2 | ||
|  | 18c3223105 | ||
|  | b9e97792f3 | ||
|  | cbce9b8637 | ||
|  | 5ab90b85da | ||
|  | f3e1e8a2c7 | ||
|  | e41b292e54 | ||
|  | 86928bbb2d | ||
|  | 2f5ec8b5bf | ||
|  | 14ac6446de | ||
|  | 260a9723a4 | ||
|  | 4e7b000dcd | ||
|  | 2254e4c57e | ||
|  | 25a27733b9 | ||
|  | 6ab520984c | ||
|  | 04d7106956 | ||
|  | db5589f2aa | ||
|  | d06dbbb4bd | ||
|  | b7a62bd9e7 | ||
|  | 93ad9a3aa6 | ||
|  | f1855174f0 | ||
|  | a2dedba0ef | ||
|  | 5a65f445f0 | ||
|  | f52289b2c3 | ||
|  | 3b5ea0f15f | ||
|  | 238bcb8698 | ||
|  | 3ee8bcad8c | ||
|  | f0a51bafbe | ||
|  | 944f3bd329 | ||
|  | 8bb7b2e88b | ||
|  | aab0b0b4bf | ||
|  | 083d6c5125 | ||
|  | c2167a2c5f | ||
|  | 1a695e0451 | ||
|  | 8847f325ed | ||
|  | 94c9da468e | ||
|  | 24b38407e4 | ||
|  | f49d1ae860 | ||
|  | 8b3b541a56 | ||
|  | a974e84ad1 | ||
|  | c4f4115bcb | ||
|  | 3c5adbee31 | ||
|  | 55645e3730 | ||
|  | d918bb568c | ||
|  | b1bff62bf7 | ||
|  | d11d389ae4 | ||
|  | a73c159160 | ||
|  | 7adf102d8d | ||
|  | e4d3ff623a | ||
|  | 2433d59f00 | ||
|  | 8c68e76c3e | ||
|  | 0b204de5a9 | ||
|  | 93c811ab70 | ||
|  | 3ff861099a | ||
|  | f22762539f | ||
|  | 677442a3c0 | ||
|  | b73f12cdba | ||
|  | 28fbb61e81 | ||
|  | c1104d1cd6 | ||
|  | e346702292 | ||
|  | 90887779ea | ||
|  | a941b1437c | ||
|  | 04bdcbd490 | ||
|  | 87a815fd6f | ||
|  | d623848c87 | ||
|  | 46abd0cc42 | ||
|  | e315325d91 | ||
|  | f3fc083330 | ||
|  | 92cb57eb7b | ||
|  | d645fbff2f | ||
|  | 8486f4d43a | ||
|  | 60b1a05894 | ||
|  | f955d63707 | ||
|  | f106019938 | ||
|  | 2473249c8b | ||
|  | d13dc4fba3 | ||
|  | 41a0af032c | ||
|  | 70cf7b0c5a | ||
|  | 14f6788ab9 | ||
|  | bb67049d90 | ||
|  | ae2162beaf | ||
|  | 19f2c5e07f | ||
|  | 8abc5b3889 | ||
|  | 4d37c28bc7 | ||
|  | cc0933eee4 | ||
|  | 2de9a804a0 | ||
|  | ffeb2e91f4 | ||
|  | 8cf5ec9e5a | ||
|  | ea0526f29a | ||
|  | cfcb3a69e5 | ||
|  | e3e0378857 | ||
|  | ccc3809daa | ||
|  | c97786e12c | ||
|  | 400071879f | ||
|  | 4cd6e20c91 | ||
|  | 460e3ad395 | ||
|  | 6f08bd6fc5 | ||
|  | eed3a749db | ||
|  | 6587d12fbd | ||
|  | f8dd68ecc4 | ||
|  | f0aef2b853 | ||
|  | 7d27df1b97 | ||
|  | 457ec86c25 | ||
|  | a24c66958f | ||
|  | 617628b886 | ||
|  | 6b7e623d33 | ||
|  | 5ca85b7e83 | ||
|  | 5965bf3332 | ||
|  | baf2dd293b | ||
|  | 2cc19e7e32 | ||
|  | 53ab6f8569 | ||
|  | cf8faac7ef | ||
|  | 86947a384d | ||
|  | 22855279bd | ||
|  | e56fdecdc6 | ||
|  | dc75a5812f | ||
|  | 33e20c9969 | ||
|  | 109204897f | ||
|  | 3b3a2d62f8 | ||
|  | b1b4b3fb63 | ||
|  | d583c68de5 | ||
|  | d360f30af6 | ||
|  | ed033565a4 | ||
|  | 2d6acfae1b | ||
|  | 10da894124 | ||
|  | 6dda8f21e4 | ||
|  | 1a9d759002 | ||
|  | df24e13eb5 | ||
|  | 2ab19937af | ||
|  | 390b86cd8e | ||
|  | 423aba5bab | ||
|  | dc0b9231cd | ||
|  | 3b177bedf8 | ||
|  | 12ce719213 | ||
|  | 320433b1bf | ||
|  | 7f35e2280e | ||
|  | c514d988df | ||
|  | 749a080397 | ||
|  | b105a12505 | ||
|  | abaf363ddd | ||
|  | 16db9d4290 | ||
|  | a694b0364d | ||
|  | b68835f171 | ||
|  | 32714c5dac | ||
|  | 245e06f026 | ||
|  | e0111d3fe6 | ||
|  | a71d4223ff | ||
|  | 20cba6411b | ||
|  | 502a8112b5 | ||
|  | 308c6ee4da | ||
|  | cae003d4fa | ||
|  | b9b900e908 | ||
|  | 8bdba9178a | ||
|  | 97f11e38cd | ||
|  | c4f5df0cd0 | ||
|  | 9ed3a6748a | ||
|  | 359c0354f6 | ||
|  | fc77c089fa | ||
|  | 137a7ac48c | ||
|  | 42b60aef4e | ||
|  | 5ab7380ad1 | ||
|  | afa25df1af | ||
|  | 5cb888328e | ||
|  | 78aeb94917 | ||
|  | 5f3e9a19ea | ||
|  | 420e8c001b | ||
|  | c63b8a4ebc | ||
|  | 5f5feaed5f | ||
|  | 87a1f616b0 | ||
|  | cc051544f9 | ||
|  | 85a438a40f | ||
|  | 877260a243 | ||
|  | 83d99043a8 | ||
|  | 6a57d25f4a | ||
|  | 91473e731e | ||
|  | 1d91ac1169 | ||
|  | 2850477a71 | ||
|  | 651b1c92c3 | ||
|  | 77e74eb37b | ||
|  | 5bb2bc7077 | ||
|  | 98a001a8ca | ||
|  | 0d75ff336d | ||
|  | 8567f1655e | ||
|  | 68b94737ed | ||
|  | 094c92ed85 | ||
|  | 42ab6deff1 | ||
|  | 3a257e1e00 | ||
|  | 2bf9a353a6 | ||
|  | bbe41febf1 | ||
|  | 031362a633 | ||
|  | 4418f8bfce | ||
|  | 364175fa9d | ||
|  | 13cf2b48e1 | ||
|  | e4f6694223 | ||
|  | 59093f1721 | ||
|  | db5e79a19b | ||
|  | f0b1585b52 | ||
|  | 50228c5970 | ||
|  | b98e85016a | ||
|  | bc540eefb6 | ||
|  | 3f1c4b4117 | ||
|  | 5e7689a151 | ||
|  | 42845cfcc0 | ||
|  | caad0eca67 | ||
|  | 67f8ec7f87 | ||
|  | d8d37a66e4 | ||
|  | 69db23f2f6 | ||
|  | c3f6bcad56 | ||
|  | ab1521bf26 | ||
|  | fafe8b88c2 | ||
|  | 9276988ff6 | ||
|  | 85179edf1b | ||
|  | 2f1ba6cf1f | ||
|  | 93674b4e29 | ||
|  | 20851664e8 | ||
|  | 38c87a056c | ||
|  | ad77565508 | ||
|  | 0e02e21967 | ||
|  | 1e35a6ce5e | ||
|  | 90b167eba1 | ||
|  | 5b1defad9f | ||
|  | 8dc1ad8168 | ||
|  | 126a42056d | ||
|  | 5866dad79a | ||
|  | 9dac679b72 | ||
|  | 12ff3abeda | ||
|  | 0f07fb4479 | ||
|  | d9d98439b2 | ||
|  | d251a30cb8 | ||
|  | a2632fdcc8 | ||
|  | 10c818474c | ||
|  | 5e8279cf51 | ||
|  | 4c8c081c31 | ||
|  | bad2baba7f | ||
|  | b5da6f9c74 | ||
|  | 7ec999475e | ||
|  | 742bf85a89 | ||
|  | c9c6f41aad | ||
|  | b0d93df387 | ||
|  | 3e20892fdf | ||
|  | 369f8b3fe0 | ||
|  | 337dfba2b8 | ||
|  | 493687b5bb | ||
|  | c7587960fb | ||
|  | 5c962aa899 | ||
|  | 3e9d2a8062 | ||
|  | c2aa8a206a | ||
|  | 6d8ea2b6a4 | ||
|  | b581e33611 | ||
|  | 5e43a02cd3 | ||
|  | 6f37d5ca5c | ||
|  | 3263008379 | ||
|  | 4588089bd6 | ||
|  | 44b75f0b92 | ||
|  | 162bd6a8c3 | ||
|  | 0c13603185 | ||
|  | ed2a45e975 | ||
|  | 0fa165c606 | ||
|  | fe63ab1242 | ||
|  | faf808da69 | ||
|  | 71709cd662 | ||
|  | d92040b804 | ||
|  | 3662fbb462 | ||
|  | d89ae3ebbf | ||
|  | 6175fecdd8 | ||
|  | fab632da62 | ||
|  | c1e3b0d971 | ||
|  | 7b15ba31ea | ||
|  | f11d4ccd45 | ||
|  | fbec803129 | ||
|  | 0f57d1a433 | ||
|  | 63829b6382 | ||
|  | 8ac3899ddc | ||
|  | 59fb4ea6f8 | ||
|  | 92bb9bb3c3 | ||
|  | 1795c491a8 | ||
|  | ea333c19f7 | ||
|  | 28ef879c07 | ||
|  | 10839abf24 | ||
|  | 9832394f8e | ||
|  | dd89ea3731 | ||
|  | 5d9fd6dc3b | ||
|  | f7c87e26db | ||
|  | f98f4085bf | ||
|  | 543519d055 | ||
|  | 5a9fcd9267 | ||
|  | fe2360883f | ||
|  | b45ddadb09 | ||
|  | a3cbe80a36 | ||
|  | ee6c6266cc | ||
|  | d6bd35287f | ||
|  | 962a29110c | ||
|  | a242475b38 | ||
|  | d59bf84470 | ||
|  | 161ee17f45 | ||
|  | 8aa00b0cfc | ||
|  | afe89c3621 | ||
|  | bdf68311b4 | ||
|  | afa69f4c0e | ||
|  | 6fe2b24592 | ||
|  | 7442b356e3 | ||
|  | 1d7be6457f | ||
|  | c9ff05ba80 | ||
|  | faae184f1c | ||
|  | 515a8a9bbb | ||
|  | 58914e5c5f | ||
|  | c944eaab5c | ||
|  | d3d9533493 | ||
|  | 9c474cc089 | ||
|  | 3f1b0b986f | ||
|  | 28e08ebaf5 | ||
|  | 3213c03754 | ||
|  | 4447288a4c | ||
|  | eee4e83a1e | ||
|  | a67b492620 | ||
|  | 6062ff2748 | ||
|  | 3b11195caa | ||
|  | 9946ea111c | ||
|  | 7074d66f8e | ||
|  | 008b26f329 | ||
|  | b246f0779f | ||
|  | dc89218702 | ||
|  | 3c013b3533 | ||
|  | fe0d0f08e4 | ||
|  | 38b5063038 | ||
|  | e55481a454 | ||
|  | 7063a88513 | ||
|  | a9bf3d0226 | ||
|  | 781b3aff1b | ||
|  | b011b9203b | ||
|  | 39344fcae5 | ||
|  | a046b357da | ||
|  | d8e4020cec | ||
|  | f80b172022 | ||
|  | 66fc4b536c | ||
|  | 1f97ccdddb | ||
|  | 308d6889a7 | ||
|  | c3b9982c44 | ||
|  | fab796e4e4 | ||
|  | 749db6ba82 | ||
|  | 12d6c4ddf5 | ||
|  | 430a03bb14 | ||
|  | 43f21fc7aa | ||
|  | b27da3d1a0 | ||
|  | 4463a8e3b2 | ||
|  | 9e74ddac48 | ||
|  | 5f62e41d62 | ||
|  | 19a103d3a0 | ||
|  | 8fb6bc059e | ||
|  | 8f61a0d258 | ||
|  | 7fa589e430 | ||
|  | 6d8d826764 | ||
|  | a40e84e1f6 | ||
|  | 4844c2123f | ||
|  | 236d437430 | ||
|  | ae726c199b | ||
|  | e7f54f005c | ||
|  | e7b1ec6904 | ||
|  | f4f664a4a2 | ||
|  | fec52a8151 | ||
|  | d8b4c1e209 | ||
|  | eac853c7dd | ||
|  | a04337a270 | ||
|  | 50d7e16365 | ||
|  | ef7bc931b7 | ||
|  | 41de771074 | ||
|  | 2ebdd6c5cb | ||
|  | b51cfcc753 | ||
|  | 91cc03dd80 | ||
|  | 9d673a213e | ||
|  | 97e789538e | ||
|  | e05ff01d57 | ||
|  | 0748dff355 | ||
|  | 28d4084aa0 | ||
|  | afd2ccfb4f | ||
|  | 057127f4de | ||
|  | 2937b25d6d | ||
|  | 419f26db87 | ||
|  | be1b9c0e43 | ||
|  | 894d28c60b | ||
|  | 06cc08d9f7 | ||
|  | 75393c0b28 | ||
|  | bdc1da70c1 | ||
|  | 7cef990ba6 | ||
|  | fb0f12bb20 | ||
|  | e94b8d3e84 | ||
|  | 8c00e1fdf4 | ||
|  | a31fa82284 | ||
|  | 5d0af45d8f | ||
|  | e9f248020e | ||
|  | a8e1058af6 | ||
|  | 1a087fd799 | ||
|  | 50c81533e0 | ||
|  | 5eab9aa4b1 | ||
|  | 1970cbfe37 | ||
|  | 6d736201f9 | ||
|  | 51ec52b573 | ||
|  | d099387186 | ||
|  | 3f91e4da66 | ||
|  | 4124159378 | ||
|  | 18f3789e29 | ||
|  | a713c92530 | ||
|  | 7828af591e | ||
|  | d432dba726 | ||
|  | 72ae87857f | ||
|  | 724acff591 | ||
|  | 482b432e2c | ||
|  | 351c0cb0a8 | ||
|  | 314a0fb5d6 | ||
|  | a301bf8bf5 | ||
|  | 37b3601c47 | ||
|  | 6e944485f0 | ||
|  | 431266069e | ||
|  | d48a09e68b | ||
|  | 1db1ec7b5e | ||
|  | 2a8f0a4eab | ||
|  | 79f3669fac | ||
|  | aab0f2dcd5 | ||
|  | a47831e278 | ||
|  | f1a5e8a42c | ||
|  | 723e9b3cba | ||
|  | ff759a8074 | ||
|  | 4de1056d82 | ||
|  | 884b8da8bf | ||
|  | 044ad77a4b | ||
|  | 1fe8b388a3 | ||
|  | 79fe7d684c | ||
|  | c409af0ea8 | ||
|  | 5110eaff96 | ||
|  | db3eee72b5 | ||
|  | 3bcff91328 | ||
|  | e843f192ec | ||
|  | f3d2053878 | ||
|  | efe8fbbd11 | ||
|  | ce507b3b52 | ||
|  | 85de227003 | ||
|  | 7c6eb7c794 | ||
|  | 2037741b54 | ||
|  | d534a8952d | ||
|  | 0b05b883cb | ||
|  | 6937aa5ddd | ||
|  | 8f6b24e0aa | ||
|  | ba3b64a6c6 | ||
|  | 0881c6a20b | ||
|  | f88a4b1791 | ||
|  | 2b43e3ee23 | ||
|  | a413f3cded | ||
|  | 596fbfb517 | ||
|  | 86bb5503ab | ||
|  | 21ce23d27d | ||
|  | 6c75baecb2 | 
							
								
								
									
										2
									
								
								.github/ISSUE_TEMPLATE.md
									
									
									
									
										vendored
									
									
								
							
							
						
						| @@ -28,7 +28,7 @@ To help us understand the issue, please fill-in as much of the following informa | ||||
| ### Please tell us about your environment: | ||||
|  | ||||
| - [ ] Node-RED version: | ||||
| - [ ] node.js version: | ||||
| - [ ] Node.js version: | ||||
| - [ ] npm version: | ||||
| - [ ] Platform/OS: | ||||
| - [ ] Browser: | ||||
|   | ||||
							
								
								
									
										39
									
								
								.github/ISSUE_TEMPLATE/--bug_report.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,39 @@ | ||||
| --- | ||||
| name: Bug report | ||||
| about: Reproducable software issues in the core of Node-RED | ||||
| title: '' | ||||
| labels: '' | ||||
| assignees: '' | ||||
|  | ||||
| --- | ||||
|  | ||||
| <!-- | ||||
| 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. | ||||
|  | ||||
| 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: | ||||
							
								
								
									
										17
									
								
								.github/ISSUE_TEMPLATE/-anything-else.md
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,17 @@ | ||||
| --- | ||||
| name: Anything Else | ||||
| about: Something that is not a bug report | ||||
| title: '' | ||||
| labels: '' | ||||
| assignees: '' | ||||
|  | ||||
| --- | ||||
|  | ||||
| Please DO NOT raise an issue. | ||||
|  | ||||
| We DO NOT use the issue tracker for general support or feature requests. Only bug reports should be raised here using the 'Bug report' template. | ||||
|  | ||||
| For general support, please use the [Node-RED Forum](https://discourse.nodered.org) or [slack team](https://nodered.org/slack). You could also consider asking a question on [Stack Overflow](https://stackoverflow.com/questions/tagged/node-red) and tag it `node-red`.  | ||||
| That way the whole Node-RED user community can help, rather than rely on the core development team. | ||||
|  | ||||
| For feature requests, please use the Node-RED Forum](https://discourse.nodered.org). Many ideas have already been discussed there and you should search that for your request before starting a new discussion. | ||||
| @@ -2,6 +2,7 @@ sudo: false | ||||
| language: node_js | ||||
| matrix: | ||||
|   include: | ||||
|     - node_js: "12" | ||||
|     - node_js: "10" | ||||
|       script: | ||||
|         - ./node_modules/.bin/grunt && istanbul report text && ( cat coverage/lcov.info | $(npm get prefix)/bin/coveralls || true ) && rm -rf coverage | ||||
|   | ||||
							
								
								
									
										15
									
								
								API.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,15 @@ | ||||
| Node-RED Modules | ||||
| --- | ||||
|  | ||||
| Node-RED provides a set of node modules that implement different parts of the | ||||
| application. | ||||
|  | ||||
| Module | Description | ||||
| -------|------- | ||||
| [node-red](node-red.html) | the main module that pulls together all of the internal modules and provides the executable version of Node-RED | ||||
| [@node-red/editor-api](@node-red_editor-api.html) | an Express application that serves the Node-RED editor and provides the Admin HTTP API | ||||
| [@node-red/runtime](@node-red_runtime.html) | the core runtime of Node-RED | ||||
| [@node-red/util](@node-red_util.html) | common utilities for the Node-RED runtime and editor modules | ||||
| @node-red/registry | the internal node registry | ||||
| @node-red/nodes | the default set of core nodes | ||||
| @node-red/editor-client | the client-side resources of the Node-RED editor application | ||||
							
								
								
									
										409
									
								
								CHANGELOG.md
									
									
									
									
									
								
							
							
						
						| @@ -1,3 +1,407 @@ | ||||
| #### 1.0.3: Maintenance Release | ||||
|  | ||||
| Runtime | ||||
|  - Increase timeouts in Subflow tests to minimise false positives | ||||
|  - Update grunt-sass and add node-sass for node12 support | ||||
|  - Fix timings of Delay node tests | ||||
|  - #2340 Update JSONata to 1.7.0 | ||||
|  - Bump https-proxy-agent version | ||||
|  - #2332 Fix error handling of nodes with multiple input handlers | ||||
|  - Add script to generate npm publish script | ||||
|  - #2371 Ensure folder is present before write (e.g. flows file not in user folder) | ||||
|  - #2371 Handle windows UNC '\\' paths | ||||
|  - #2366 Handle logging of non-JSON encodable objects | ||||
|  | ||||
| Editor | ||||
|  - #2328 Fix language handling in subflow node | ||||
|  - Use default language if lng param not set in i18n req | ||||
|  - #2326 Fix palette editor search visualization | ||||
|  - #2375 Subflow status not showing i18n version of contained core nodes status | ||||
|  - Fix inverse of 'replace' editor event | ||||
|  - #2376 Fallback to base language files if present | ||||
|  - #2373 Support UI testing on the latest Google Chrome | ||||
|  - #2364 Add tooltip to expand button in markdown editor | ||||
|  - #2363 Support ctrl key to select tabs for Windows | ||||
|  - #2356 Make JSONata help initially shown in expression editor | ||||
|  - #2355 Prohibit line break in type menu of typedInput | ||||
|  | ||||
| Nodes | ||||
|  - Delay: Fix delay to not pass through .reset and .flush props consistently | ||||
|  - #2352 File: Using the ‘a msg per line’ the last line does not get msg.topic passed | ||||
|  - #2339 HTTP Request: Check auth type on opening | ||||
|  - HTTP Request: add units info | ||||
|  - #2372 MQTT/WS: Improved proxy support for MQTT and WebSocket nodes | ||||
|  - #2370 MQTT: Add clarification that MQTT Out requires payload to send msg | ||||
|  | ||||
|  | ||||
| #### 1.0.2: Maintenance Release | ||||
|  | ||||
| Runtime | ||||
|  - Allow node.status() to be passed number/bool types | ||||
|  - Allow node emitted events to have multiple arguments | ||||
|  - #2323 Fixed docstrings to have them match the function signature (name of parameters). | ||||
|  - #2318 NLS: Unify translations of "boolean" | ||||
|  | ||||
| Editor | ||||
|  - Ensure node status is refreshed whenever node is edited | ||||
|  - #2315 #2316 Ensure z property included in full message debug payload | ||||
|  - #2321 Fixed editor.json (JA nls) | ||||
|  - #2313 Fix element to collapse items in visual JSON editor | ||||
|  - #2314 Insert divider in menu by calling RED.menu.addItem('id', null); | ||||
|  | ||||
| Nodes | ||||
|  - Change: Fixup use of node.done | ||||
|  - #2322 Template: Fix invalid JSON data in template node docs | ||||
|  - #2320 File: Fixed a typo in 10-file.html (JA nls) | ||||
|  - #2312 Template: Remove unnecessary comma in help text | ||||
|  - #2319 Inject: Interval of inject node should be 596 hours or less. | ||||
|  | ||||
| #### 1.0.1: Maintenance Release | ||||
|  | ||||
| Runtime | ||||
|  - #2301 Add env vars to enable safe mode and projects | ||||
|    - `NODE_RED_ENABLE_SAFE_MODE` | ||||
|    - `NODE_RED_ENABLE_PROJECTS` | ||||
|  | ||||
| Editor | ||||
|  - #2308 Fix grid setting | ||||
|  - #2306 i18n support in tooltips | ||||
|  - Fix error when setting typedInput to boolean true/false | ||||
|  - #2299 Fix SVG icons in IE11 | ||||
|  - #2303 Fix issue where subflow color did not update when not on a flow | ||||
|  | ||||
| Nodes | ||||
|  - #2297 TLS: Allow TLS config node to provide just CA cert | ||||
|  - #2307 Inject: Fix width on inject node property | ||||
|  - #2305 Switch: Let switch node between rule work both ways round | ||||
|  - Range: Add example to range node info and make use of target consistent | ||||
|  - Join: node must clone group message before sending | ||||
|  | ||||
|  | ||||
| #### 1.0.0: Milestone Release | ||||
|  | ||||
| Editor | ||||
|  - Add click-on-tooltip to close | ||||
|  - Fix node draggable handling | ||||
|  - Ensure complete node scope property is remapped on import | ||||
|  - Update i18n for project feature | ||||
|  - Fix menu hiding function for flow editor | ||||
|  - Normalise default subflow color references | ||||
|  - Hide header text of very small screens to deploy is visible | ||||
|  - Fix tab access on touch screens | ||||
|  - Update radialMenu to use standard theme colours | ||||
|  - Fix undefined reference loading on mobile | ||||
|  - Allow word breaking of node name with long word | ||||
|  - Enable wrap mode in Markdown editor | ||||
|  - Maximize the size of markdown editor | ||||
|  | ||||
| Nodes | ||||
|  - remove legacy error option from file in mode | ||||
|  - Change MQTT node default 3.1 compatibility mode to false | ||||
|  - Show clear debug shortcut in tooltip | ||||
|  - Fix file-in port labels for all 4 options | ||||
|  - Add extra comment re Mustache escapes to Template info | ||||
|  - Fix typo in complete node | ||||
|  - Allow Function node output input to go to 0 | ||||
|  | ||||
| #### 1.0.0-beta.4: Beta Release | ||||
|  | ||||
| Runtime | ||||
|  - Clone the first message passed to node.send in Function node | ||||
|  | ||||
| Editor | ||||
|  - Move flow-status button to footer for consistency | ||||
|  - Fix node hover effect to prevent jumping position | ||||
|  - Filter quick-add properly when splicing a wire | ||||
|  - Mark workspace dirty when deleting link node link Fixes #2274 | ||||
|  - Add red-ui-button class to strategy login button | ||||
|  - Fix padding of subflow locale select Closes #2276 | ||||
|  - Update info text of complete node & add JP text | ||||
|  - Add class red-ui-button to cancel button | ||||
|  - Add css class to login submit button (#2275) | ||||
|  - Realign subflow output port labels | ||||
|  - Move context sidebar auto-refresh option to individual sections | ||||
|  - Update Japanese message catalogue | ||||
|  - Fix subflow UI for select | ||||
|  - remove padding before label text for SUBFLOW UI row | ||||
|  - Allow SUBFLOW UI label row without variable name | ||||
|  | ||||
| Nodes | ||||
|  - Remove old rc option from exec node for 1.0 | ||||
|  - Add python and SQL to template language options | ||||
|  - Fix Switch node display of jsonata_exp type | ||||
|  - Remove sentiment from core nodes | ||||
|  | ||||
| #### 1.0.0-beta.3: Beta Release | ||||
|  | ||||
| Runtime | ||||
|  - [FEATURE] Add Node Done API - make message passing async | ||||
|  - Ensure the subflow stop promise is waiting for before restarting | ||||
|  - Limit the regex for the /nodes/ api end points | ||||
|  - Add error event handler to ssh-keygen child_process Fixes #2255 | ||||
|  - Fix default value handling on context array access Fixes #2252 | ||||
|  - Remove all ui test dependencies from package.json | ||||
|  - Add req back to audit log events and extend to Projects api | ||||
|  - Ensure 2nd arg to node.error is an object Fixes #2228 | ||||
|  - Use a more atomic process for writing context files Fixes #2271 | ||||
|  | ||||
|  | ||||
| Editor | ||||
|  - [FEATURE] Change core node categories | ||||
|  - [FEATURE] Subflow Instance property UI (#2236) | ||||
|  - [FEATURE] Add visual JSON editor | ||||
|  - [FEATURE] Add Action List dialog | ||||
|  - [FEATURE] Add new shortcut to clear debug message list - ctrl-alt-l | ||||
|  - [FEATURE] Add show-library dialog actions | ||||
|  - [FEATURE] Add shift-cursor handling for moving quick-add dialog | ||||
|  - [FEATURE] Add enable/disable-flow actions | ||||
|  - [FEATURE] Add actions to change deploy type | ||||
|  - [FEATURE] Allow config nodes to be disabled, tidy css and add actions | ||||
|  - [FEATURE] Add default shortcut (ctrl-d) for deploy | ||||
|  - [FEATURE] Initial implementation of redo (un-undo) - ctrl-y | ||||
|  - [FEATURE] add support for specifying subflow template color | ||||
|  - [FEATURE] Use ctrl-click on wire to splice node in place | ||||
|  - [FEATURE] Allow search results to show more than 25 results | ||||
|  - [FEATURE] Allow a node to change if it has an input port Closes #2268 | ||||
|  - Revealing node position needs to account for zoom level Fixes #2172 | ||||
|  - Fix typedInput option selection Fixes #2174 | ||||
|  - Fix palette node id handling so search works Fixes #2173 | ||||
|  - Add popover tooltips to debug sidebar,function and template | ||||
|  - Add popovers to context sidebar mini buttons | ||||
|  - Ensure node status icon is shown when value set | ||||
|  - Revert treeList children function signature change | ||||
|  - Restore tray component css for compatibility. Mark as deprecated | ||||
|  - fix function name & string compare function | ||||
|  - Handle empty list of example flows Fixes #2171 | ||||
|  - Ensure library list has an item selected when opened | ||||
|  - Ensure tooltip popover doesn't replace normal popover | ||||
|  - Fix clipboard export download button | ||||
|  - Ensure input box has focus on repeated quick add | ||||
|  - Fix width calculation of typedInput | ||||
|  - Remove some hardcoded css colors | ||||
|  - Fix display of node help when clicking in palette Fixes #2194 | ||||
|  - Ensure node help is loaded in the right language Fixes #2195 | ||||
|  - Do not allow tab focus on clipboard hidden element | ||||
|  - Fix undefined error on typedInput due to valueLabel used before being added | ||||
|  - Fix undo of flow disable state change | ||||
|  - Fix select-all action in main view | ||||
|  - Fix delete-all action on config node sidebar | ||||
|  - Update UI tests for new editor css | ||||
|  - Add insertItemAt doc to editableList | ||||
|  - Ensure focus returns to the right element after dialogs shown | ||||
|  - Set autocomplete to disabled in form input elements | ||||
|  - Update all node icons to SVG | ||||
|  - Handle png/svg fallback for def.icon values. Remove old pngs | ||||
|  - Ignore empty examples directories (don't add to import menu) | ||||
|  - better handle example file at any depth - #2222 | ||||
|  - Properly escape node types in palette | ||||
|  - Ensure session expiry timeout doesn't exceed limit | ||||
|  - Use node/tab map to make filterNodes more efficient | ||||
|  - Rearrange contents of subflow template settings tab | ||||
|  - Handle undefined node.\_def in edit stack title. | ||||
|  - fix converting selection to subflow | ||||
|  - Fix inserting new subflow node to existing wire between nodes | ||||
|  - Support displaying falsey node status values Fixes #2246 | ||||
|  - Remove tab menu from node property UI for subflow and config nodes | ||||
|  - Mark workspace dirty when shift-click-drag detaches wires Fixes #2260 | ||||
|  - Fix subflow category change on palette | ||||
|  | ||||
|  | ||||
| Nodes | ||||
|  - Remove pi gpi, twitter, email and feedparser nodes from core | ||||
|  - Fix error handling in Websocket broadcast function Fixes #2182 | ||||
|  - Handle websocket item being parseable but not an object better | ||||
|  - stop join tripping up if last message of buffer is blank. | ||||
|  - Add support for env var propety in switch node | ||||
|  - Improve handling of file upload in request node | ||||
|  - Add "has key" rule to  switch node + tests | ||||
|  - Optimise generation of switch node edit dialog | ||||
|  - Add keep-alive option to HTTP Request - #2261 | ||||
|  | ||||
| #### 1.0.0-beta.2: Beta Release | ||||
|  | ||||
| Runtime | ||||
|  - Fix length calculation when loading library file | ||||
|  | ||||
| #### 1.0.0-beta.1: Beta Release | ||||
|  | ||||
| Runtime | ||||
|  - Update runtime apis to support multiple libraries | ||||
|  - Add Node 12 to travis (allow_failures) | ||||
|  - Bump all dependencies Fixes #2152 | ||||
|  | ||||
| Editor | ||||
|  - [BREAKING] complete overhaul of editor DOM/CSS structure | ||||
|  - [BREAKING] Get rid of Bootstrap | ||||
|  - Simplify index.mst to a single div to insert the editor | ||||
|  - Append node configs to div rather than body | ||||
|  - Only redraw node status when it has changed | ||||
|  - Minimise work done to calculate node label widths | ||||
|  - Allow script tags with src to reference esm modules | ||||
|  - Upgrade to jq 3.4.1 / jq-ui 1.12.1 | ||||
|  - Allow editor language to be chosen in editor settings | ||||
|  - Only NLS status text that starts with a letter Fixes #2128 | ||||
|  - Fix display of link node list within subflow Fixes #2140 | ||||
|  - Blur the active element when closing edit dialog via action Fixes #2097 | ||||
|  - Trigger change evnt on typedInput when type changes and options present Fixes #2160 | ||||
|  - Move library import/export to single dialog | ||||
|  - Move type-library dialogs to new style dialog | ||||
|  - Fix node drag and drop animation | ||||
|  - let status be simple text if wanted | ||||
|  - Add workspace statusBar | ||||
|  - Complete refresh of German translations | ||||
|  - Fix memory leak in Debug sidebar #2163 | ||||
|  - Introduce toggleButton and move flow-disabled to use it | ||||
|  - Allow RED.settings.get/set to use full property desc | ||||
|  - Add auto-refresh toggle to context sidebar | ||||
|  - Add build-custom-theme script | ||||
|  - Add RED.view.selectNodes api for node selection whilst editing | ||||
|  - Add node-select to typedInput | ||||
|  | ||||
| Nodes | ||||
|  - http request node: warn user if msg.requestTimeout == 0 | ||||
|  - hide delay node reset label on deploy | ||||
|  - Fix CSV regex to treat strings starting e as text | ||||
|  - Add "don't parse numbers" option to csv node | ||||
|  - Add expand editor button to Template node | ||||
|  - Update catch/status nodes to use selectNodes api and treeList | ||||
|  | ||||
| #### 0.20.8: Maintenance Release | ||||
|  | ||||
|  - Sanitize tab name in edit dialog | ||||
|  - Pass httpServer to runtime even when httpAdmin disabled Fixes #2272 | ||||
|  | ||||
| #### 0.20.7: Maintenance Release | ||||
|  | ||||
|  - Update jsonata to 1.6.5 which should fix #2183 | ||||
|  - Ensure the subflow stop promise is waiting for before restarting | ||||
|  - Properly escape node types in palette | ||||
|  | ||||
| #### 0.20.6: Maintenance Release | ||||
|  | ||||
|  - Revealing node position needs to account for zoom level Fixes #2172 | ||||
|  - stop join tripping up if last message of buffer is blank. | ||||
|  - Improve handling of file upload in request node | ||||
|  - Handle subflow internal node wired to a non-existant node Fixes #2202 | ||||
|  - Do not save subflow env vars with blank names | ||||
|  - Don't allow a link node virtual wire to connect to normal port | ||||
|  - Clear HTTP Request node authType when auth disabled Fixes #2215 | ||||
|  - Fix parsing of content-type header Fixes #2216 | ||||
|  - Fix join node reset issue with merging objects | ||||
|  - Copy data-i18n attribute on TypedInput Fixes #2211 | ||||
|  | ||||
| #### 0.20.5: Maintenance Release | ||||
|  | ||||
|  - Revert error handling in palette manager | ||||
|  | ||||
| #### 0.20.4: Maintenance Release | ||||
|  | ||||
| - Switch media-typer to content-type module Fixes #2122 #2123 | ||||
| - Use userObj.username and not .name for ssh key lookup Closes #2109 | ||||
| - Ensure mqtt message handlers are tidied up properly on partial deploy | ||||
| - Update package dependencies | ||||
| - Fix encoding menu in file node #2125 | ||||
| - Update ACE to 1.4.3-src-min-noconflict Fixes #2106 | ||||
| - Fix creating missing package.json when existing project imported Fixes #2115 | ||||
| - Allow subflow instance to override env var with falsey values Fixes #2113 | ||||
| - Prevent wire from normal node to link virtual port Fixes #2114 | ||||
| - Add explanation to the help text on the new feature to build query string from msg.payload #2116 | ||||
| - Bump bcrypt to latest | ||||
| - Add Korean locales files for nodes #2100 | ||||
| - Add error message if catalog is invalid json | ||||
| - Reduce udp out timeout to be less than default inject at start #2127 | ||||
|  | ||||
| #### 0.20.3: Maintenance Release | ||||
|  | ||||
| - Do not dynamically add/remove upgrade listener in ws nodes | ||||
| - Avoid env var reference loops and support $parent. prefix Fixes #2099 | ||||
| - Ensure config.\_flow is non-enumerable so is ignored by JSON.stringify | ||||
| - Block loading ACE from cdn | ||||
|  | ||||
| #### 0.20.2: Maintenance Release | ||||
|  | ||||
|  - Filter out duplicate nodes when importing a flow | ||||
|  - Handle node configs with multiple external scripts properly | ||||
|  | ||||
| #### 0.20.1: Maintenance Release | ||||
|  | ||||
|  - Ensure all subflow instances are stopped when flow stopping Fixes #2095 | ||||
|  - modify name of korean locale forders #2091 | ||||
|  - Ensure node names are sanitized before being presented | ||||
|  - Subflow status node must pass status to parent flow Fixes #2087 | ||||
|  - fix problem on displaying option label on Firefox #2090 | ||||
|  | ||||
| #### 0.20.0: Milestone Release | ||||
|  | ||||
| Runtime | ||||
|  - Pass complete status to Status node and filter to editor | ||||
|  - Ensure flows wait for all nodes to close before restarting Fixes #2067 | ||||
|  - Fix git clone with password protected key | ||||
|  - Allow a project to be located below the root of repo | ||||
|  - Detect the cloning of an empty git repo properly | ||||
|  - Fix use of custom auth strategy plugins | ||||
|  - Remove remnants of when library in git/index Fixes #2057 | ||||
|  - Clear subflow status on close | ||||
|  - Add exportGlobalContextKeys to prevent exposing functionGlobalContext keys | ||||
|  - Add --no-audit and --no-update-notifier flags to npm commands to reduce workload | ||||
|  - Add envVarExcludes setting to block named env vars | ||||
|  - Update settings.js docs on userDir to match reality Fixes #2082 | ||||
|  - Add Korean Language | ||||
|  | ||||
|  | ||||
| Editor | ||||
|  - Automatic placing of node icon according to input/output counts | ||||
|  - Transfer placeholder and type to generated TypedInput field | ||||
|  - Hitting enter in Comment node name field clicks markdown button | ||||
|  - Shift status text left if no shape specified | ||||
|  - Better align node status text to status dot | ||||
|  - Handle treeList labels as text not html | ||||
|  - Change subflow edit dialog titles | ||||
|  - Resize subflow edit dialog properly | ||||
|  - Add flow list button to tab bar | ||||
|  - Handle node name as unsanitized text in debug sidebar | ||||
|  | ||||
| Nodes | ||||
|  | ||||
|  - HTTP Request: Add Digest and Bearer Auth modes to http request node (#2061) | ||||
|  - HTTP Request: Add multipart/form-data support to http request node (#2076) | ||||
|  - TCP: include session/event info in status events | ||||
|  - WebSocket: include session/event info in status events | ||||
|  - Add i18n support for port label of inject/exec/httprequest/file nodes | ||||
|  - Join node: handle merged objects with repeated properties and honour parts | ||||
|  - JSON node: handle single booleans and numbers | ||||
|  - File node: add encoding support to file in/out node (#2066) | ||||
|  | ||||
| #### 0.20.0-beta.5: Beta Release | ||||
|  | ||||
| Runtime | ||||
|  | ||||
|  - Bump dependencies | ||||
|  - Allow `$parent` access of flow context | ||||
|  - Make Node.\_flow a writeable property | ||||
|  - Do not propagate Flow.getNode to parent when called from outside flow | ||||
|  - Add support of subflow env var | ||||
|  | ||||
| Editor | ||||
|  | ||||
|  - Properly sanitize node names in deploy warning dialogs | ||||
|  - Fix XSS issues in library ui code | ||||
|  - Add env type to subflow env var types | ||||
|  - Display parent subflow properties in edit dialog | ||||
|  - Fix direction value of subflow output | ||||
|  - Add Status Node to Subflow to allow subflow-specific status Closes #597 | ||||
|  - Better handling of multiple flow merges Fixes #2039 | ||||
|  | ||||
| Nodes | ||||
|  | ||||
|  - Various translation updates | ||||
|  - Catch: Add 'catch uncaught only' mode. Closes #1747 | ||||
|  - Link: scroll to current flow in node list | ||||
|  - HTTPRequest: add option to urlencode cookies | ||||
|  - HTTPRequest: option to use msg.payload as query params on GET. #1981 | ||||
|  - Debug: Add local time display option to numerics in debug window | ||||
|  - MQTT: Add parsed JSON output option | ||||
|  | ||||
| #### 0.20.0-beta.4: Beta Release | ||||
|  | ||||
| Runtime | ||||
| @@ -164,6 +568,9 @@ Nodes | ||||
|  - Watch: add msg.filename so can feed direct to file in node | ||||
|  - WebSocket: preserve \_session on msg but don't send as part of wholemsg | ||||
|  | ||||
| #### 0.19.6: Maintenance Release | ||||
|  | ||||
|  - Fix encoding of file node from binary to utf8 - #2051 | ||||
|  | ||||
| #### 0.19.5: Maintenance Release | ||||
|  | ||||
| @@ -543,7 +950,7 @@ Nodes | ||||
|  - Initial support of sequence rules for SWITCH node (#1545) | ||||
|  - initial support of SORT node (#1500) | ||||
|  - Inject node - let once delay be editable (#1541) | ||||
|  - Introduce `nodeMaxMessageBufferLength` setting for msg sequence nodes | ||||
|  - Introduce `nodeMessageBufferMaxLength` setting for msg sequence nodes | ||||
|  - Let CSV correct parts if we remove header row. | ||||
|  - let default apply if msg.delay not set in override mode. (#1397) | ||||
|  - let trigger node be reset by boolean message (#1554) | ||||
|   | ||||
| @@ -26,7 +26,7 @@ relevant nodes, press Ctrl-E and copy the flow data from the Export dialog. | ||||
| At a minimum, please include: | ||||
|  | ||||
|  - Version of Node-RED - either release number if you downloaded a zip, or the first few lines of `git log` if you are cloning the repository directly. | ||||
|  - Version of node.js - what does `node -v` say? | ||||
|  - Version of Node.js - what does `node -v` say? | ||||
|  | ||||
| ## Feature requests | ||||
|  | ||||
|   | ||||
							
								
								
									
										109
									
								
								Gruntfile.js
									
									
									
									
									
								
							
							
						
						| @@ -16,6 +16,7 @@ | ||||
|  | ||||
| var path = require("path"); | ||||
| var fs = require("fs-extra"); | ||||
| var sass = require("node-sass"); | ||||
|  | ||||
| module.exports = function(grunt) { | ||||
|  | ||||
| @@ -27,7 +28,7 @@ module.exports = function(grunt) { | ||||
|  | ||||
|     var nonHeadless = grunt.option('non-headless'); | ||||
|     if (nonHeadless) { | ||||
|         process.env.NODE_RED_NON_HEADLESS = 'true'; | ||||
|         process.env.NODE_RED_NON_HEADLESS = true; | ||||
|     } | ||||
|     grunt.initConfig({ | ||||
|         pkg: grunt.file.readJSON('package.json'), | ||||
| @@ -79,20 +80,20 @@ module.exports = function(grunt) { | ||||
|                 //"loopfunc": true, // allow functions to be defined in loops | ||||
|                 //"sub": true       // don't warn that foo['bar'] should be written as foo.bar | ||||
|             }, | ||||
|             all: [ | ||||
|                 'Gruntfile.js', | ||||
|                 'red.js', | ||||
|                 'packages/**/*.js' | ||||
|             ], | ||||
|             core: { | ||||
|                 files: { | ||||
|                     src: [ | ||||
|                         'Gruntfile.js', | ||||
|                         'red.js', | ||||
|                         'packages/**/*.js', | ||||
|                     ] | ||||
|                 } | ||||
|             }, | ||||
|             // all: [ | ||||
|             //     'Gruntfile.js', | ||||
|             //     'red.js', | ||||
|             //     'packages/**/*.js' | ||||
|             // ], | ||||
|             // core: { | ||||
|             //     files: { | ||||
|             //         src: [ | ||||
|             //             'Gruntfile.js', | ||||
|             //             'red.js', | ||||
|             //             'packages/**/*.js', | ||||
|             //         ] | ||||
|             //     } | ||||
|             // }, | ||||
|             nodes: { | ||||
|                 files: { | ||||
|                     src: [ 'nodes/core/*/*.js' ] | ||||
| @@ -100,7 +101,7 @@ module.exports = function(grunt) { | ||||
|             }, | ||||
|             editor: { | ||||
|                 files: { | ||||
|                     src: [ 'editor/js/**/*.js' ] | ||||
|                     src: [ 'packages/node_modules/@node-red/editor-client/src/js/**/*.js' ] | ||||
|                 } | ||||
|             }, | ||||
|             tests: { | ||||
| @@ -145,11 +146,13 @@ module.exports = function(grunt) { | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/common/tabs.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/common/stack.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/common/typedInput.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/common/toggleButton.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/actions.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/deploy.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/diff.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/keyboard.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/workspaces.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/statusBar.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/view.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/view-navigator.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/view-tools.js", | ||||
| @@ -167,6 +170,7 @@ module.exports = function(grunt) { | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/library.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/notifications.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/search.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/actionList.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/typeSearch.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/subflow.js", | ||||
|                     "packages/node_modules/@node-red/editor-client/src/js/ui/userSettings.js", | ||||
| @@ -181,22 +185,22 @@ module.exports = function(grunt) { | ||||
|             vendor: { | ||||
|                 files: { | ||||
|                     "packages/node_modules/@node-red/editor-client/public/vendor/vendor.js": [ | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-1.11.3.min.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/bootstrap/js/bootstrap.min.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-ui-1.10.3.custom.min.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-3.4.1.min.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-migrate-3.0.1.min.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery-ui.min.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/jquery/js/jquery.ui.touch-punch.min.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/marked/marked.min.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/d3/d3.v3.min.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/i18next/i18next.min.js" | ||||
|                     ], | ||||
|                     "packages/node_modules/@node-red/editor-client/public/vendor/vendor.css": [ | ||||
|                         // TODO: resolve relative resource paths in | ||||
|                         //       bootstrap/FA/jquery | ||||
|                     ], | ||||
|                     "packages/node_modules/@node-red/editor-client/public/vendor/jsonata/jsonata.min.js": [ | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/i18next/i18next.min.js", | ||||
|                         "node_modules/jsonata/jsonata-es5.min.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/jsonata/formatter.js" | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/jsonata/formatter.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/ace/ace.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/ace/ext-language_tools.js", | ||||
|                     ], | ||||
|                     // "packages/node_modules/@node-red/editor-client/public/vendor/vendor.css": [ | ||||
|                     //     // TODO: resolve relative resource paths in | ||||
|                     //     //       bootstrap/FA/jquery | ||||
|                     // ], | ||||
|                     "packages/node_modules/@node-red/editor-client/public/vendor/ace/worker-jsonata.js": [ | ||||
|                         "node_modules/jsonata/jsonata-es5.min.js", | ||||
|                         "packages/node_modules/@node-red/editor-client/src/vendor/jsonata/worker-jsonata.js" | ||||
| @@ -217,15 +221,12 @@ module.exports = function(grunt) { | ||||
|         sass: { | ||||
|             build: { | ||||
|                 options: { | ||||
|                     implementation: sass, | ||||
|                     outputStyle: 'compressed' | ||||
|                 }, | ||||
|                 files: [{ | ||||
|                     dest: 'packages/node_modules/@node-red/editor-client/public/red/style.min.css', | ||||
|                     src: 'packages/node_modules/@node-red/editor-client/src/sass/style.scss' | ||||
|                 }, | ||||
|                 { | ||||
|                     dest: 'packages/node_modules/@node-red/editor-client/public/vendor/bootstrap/css/bootstrap.min.css', | ||||
|                     src: 'packages/node_modules/@node-red/editor-client/src/vendor/bootstrap/css/bootstrap.css' | ||||
|                 }] | ||||
|             } | ||||
|         }, | ||||
| @@ -277,7 +278,7 @@ module.exports = function(grunt) { | ||||
|                 files: [ | ||||
|                     'packages/node_modules/@node-red/editor-client/src/js/**/*.js' | ||||
|                 ], | ||||
|                 tasks: ['copy:build','concat','uglify','attachCopyright:js'] | ||||
|                 tasks: ['copy:build','concat',/*'uglify',*/ 'attachCopyright:js'] | ||||
|             }, | ||||
|             sass: { | ||||
|                 files: [ | ||||
| @@ -352,9 +353,7 @@ module.exports = function(grunt) { | ||||
|                         cwd: 'packages/node_modules/@node-red/editor-client/src/vendor', | ||||
|                         src: [ | ||||
|                             'ace/**', | ||||
|                             //'bootstrap/css/**', | ||||
|                             'bootstrap/img/**', | ||||
|                             'jquery/css/**', | ||||
|                             'jquery/css/base/**', | ||||
|                             'font-awesome/**' | ||||
|                         ], | ||||
|                         expand: true, | ||||
| @@ -438,6 +437,7 @@ module.exports = function(grunt) { | ||||
|         jsdoc : { | ||||
|             modules: { | ||||
|                 src: [ | ||||
|                     'API.md', | ||||
|                     'packages/node_modules/node-red/lib/red.js', | ||||
|                     'packages/node_modules/@node-red/runtime/lib/index.js', | ||||
|                     'packages/node_modules/@node-red/runtime/lib/api/*.js', | ||||
| @@ -451,7 +451,7 @@ module.exports = function(grunt) { | ||||
|                     configure: './jsdoc.json' | ||||
|                 } | ||||
|             }, | ||||
|             editor: { | ||||
|             _editor: { | ||||
|                 src: [ | ||||
|                     'packages/node_modules/@node-red/editor-client/src/js' | ||||
|                     ], | ||||
| @@ -498,7 +498,9 @@ module.exports = function(grunt) { | ||||
|     grunt.loadNpmTasks('grunt-chmod'); | ||||
|     grunt.loadNpmTasks('grunt-jsonlint'); | ||||
|     grunt.loadNpmTasks('grunt-mocha-istanbul'); | ||||
|     grunt.loadNpmTasks('grunt-webdriver'); | ||||
|     if (fs.existsSync(path.join("node_modules", "grunt-webdriver"))) { | ||||
|         grunt.loadNpmTasks('grunt-webdriver'); | ||||
|     } | ||||
|     grunt.loadNpmTasks('grunt-jsdoc'); | ||||
|     grunt.loadNpmTasks('grunt-jsdoc-to-markdown'); | ||||
|     grunt.loadNpmTasks('grunt-npm-command'); | ||||
| @@ -557,12 +559,25 @@ module.exports = function(grunt) { | ||||
|     }); | ||||
|  | ||||
|     grunt.registerTask('verifyUiTestDependencies', function() { | ||||
|         if (!fs.existsSync(path.join("node_modules", "chromedriver"))) { | ||||
|             grunt.fail.fatal('You need to run "npm install chromedriver@2" before running UI test.'); | ||||
|         if (!fs.existsSync(path.join("node_modules", "grunt-webdriver"))) { | ||||
|             grunt.fail.fatal('You need to install the UI test dependencies first.\nUse the script in "scripts/install-ui-test-dependencies.sh"'); | ||||
|             return false; | ||||
|         } | ||||
|     }); | ||||
|     grunt.registerTask('generatePublishScript', | ||||
|         'Generates a script to publish build output to npm', | ||||
|             function () { | ||||
|                 const done = this.async(); | ||||
|                 const generatePublishScript = require("./scripts/generate-publish-script.js"); | ||||
|                 generatePublishScript().then(function(output) { | ||||
|                     grunt.log.writeln(output); | ||||
|  | ||||
|                     const filePath = path.join(grunt.config.get('paths.dist'),"modules","publish.sh"); | ||||
|                     grunt.file.write(filePath,output); | ||||
|  | ||||
|                     done(); | ||||
|                 }); | ||||
|             }); | ||||
|     grunt.registerTask('setDevEnv', | ||||
|         'Sets NODE_ENV=development so non-minified assets are used', | ||||
|             function () { | ||||
| @@ -581,9 +596,15 @@ module.exports = function(grunt) { | ||||
|         'Runs code style check on editor code', | ||||
|         ['jshint:editor']); | ||||
|  | ||||
|     grunt.registerTask('test-ui', | ||||
|         'Builds editor content then runs unit tests on editor ui', | ||||
|         ['verifyUiTestDependencies','build','jshint:editor','webdriver:all']); | ||||
|     if (!fs.existsSync(path.join("node_modules", "grunt-webdriver"))) { | ||||
|         grunt.registerTask('test-ui', | ||||
|             'Builds editor content then runs unit tests on editor ui', | ||||
|             ['verifyUiTestDependencies']); | ||||
|     } else { | ||||
|         grunt.registerTask('test-ui', | ||||
|             'Builds editor content then runs unit tests on editor ui', | ||||
|             ['verifyUiTestDependencies','build','jshint:editor','webdriver:all']); | ||||
|     } | ||||
|  | ||||
|     grunt.registerTask('test-nodes', | ||||
|         'Runs unit tests on core nodes', | ||||
| @@ -599,7 +620,7 @@ module.exports = function(grunt) { | ||||
|  | ||||
|     grunt.registerTask('release', | ||||
|         'Create distribution zip file', | ||||
|         ['build','verifyPackageDependencies','clean:release','mkdir:release','chmod:release','compress:release','pack-modules']); | ||||
|         ['build','verifyPackageDependencies','clean:release','mkdir:release','chmod:release','compress:release','pack-modules','generatePublishScript']); | ||||
|  | ||||
|     grunt.registerTask('pack-modules', | ||||
|         'Create module pack files for release', | ||||
| @@ -612,5 +633,5 @@ module.exports = function(grunt) { | ||||
|  | ||||
|     grunt.registerTask('docs', | ||||
|         'Generates API documentation', | ||||
|         ['jsdoc','jsdoc2md']); | ||||
|         ['jsdoc']); | ||||
| }; | ||||
|   | ||||
| @@ -5,9 +5,9 @@ http://nodered.org | ||||
| [](https://travis-ci.org/node-red/node-red) | ||||
| [](https://coveralls.io/r/node-red/node-red?branch=master) | ||||
|  | ||||
| A visual tool for wiring the Internet of Things. | ||||
| Low-code programming for event-driven applications. | ||||
|  | ||||
|  | ||||
|  | ||||
|  | ||||
| ## Quick Start | ||||
|  | ||||
| @@ -56,7 +56,7 @@ This project adheres to the [Contributor Covenant 1.4](http://contributor-covena | ||||
|  | ||||
| ## Authors | ||||
|  | ||||
| Node-RED is a project of the [JS Foundation](http://js.foundation). | ||||
| Node-RED is a project of the [OpenJS Foundation](https://openjsf.org). | ||||
|  | ||||
| It was created by [IBM Emerging Technology](https://www.ibm.com/blogs/emerging-technology/). | ||||
|  | ||||
| @@ -67,4 +67,4 @@ It was created by [IBM Emerging Technology](https://www.ibm.com/blogs/emerging-t | ||||
|  | ||||
| ## Copyright and license | ||||
|  | ||||
| Copyright JS Foundation and other contributors, http://js.foundation under [the Apache 2.0 license](LICENSE). | ||||
| Copyright JS Foundation and other contributors, https://openjsf.org under [the Apache 2.0 license](LICENSE). | ||||
|   | ||||
							
								
								
									
										13
									
								
								SECURITY.md
									
									
									
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,13 @@ | ||||
| # Security Policy | ||||
|  | ||||
| ## Supported Versions | ||||
|  | ||||
| | Version | Supported          | | ||||
| | ------- | ------------------ | | ||||
| | 1.0.0   | :white_check_mark: | | ||||
| | 0.20.x  | :white_check_mark: | | ||||
|  | ||||
|  | ||||
| ## Reporting a Vulnerability | ||||
|  | ||||
| Please report any potential security issues to `team@nodered.org`. This will notify the core project team who will respond accordingly. | ||||
							
								
								
									
										95
									
								
								package.json
									
									
									
									
									
								
							
							
						
						| @@ -1,7 +1,7 @@ | ||||
| { | ||||
|     "name": "node-red", | ||||
|     "version": "0.20.0-beta.4", | ||||
|     "description": "A visual tool for wiring the Internet of Things", | ||||
|     "version": "1.0.3", | ||||
|     "description": "Low-code programming for event-driven applications", | ||||
|     "homepage": "http://nodered.org", | ||||
|     "license": "Apache-2.0", | ||||
|     "repository": { | ||||
| @@ -24,94 +24,89 @@ | ||||
|         } | ||||
|     ], | ||||
|     "dependencies": { | ||||
|         "ajv": "6.7.0", | ||||
|         "ajv": "6.10.2", | ||||
|         "basic-auth": "2.0.1", | ||||
|         "bcryptjs": "2.4.3", | ||||
|         "body-parser": "1.18.3", | ||||
|         "body-parser": "1.19.0", | ||||
|         "cheerio": "0.22.0", | ||||
|         "clone": "2.1.2", | ||||
|         "cookie": "0.3.1", | ||||
|         "cookie-parser": "1.4.3", | ||||
|         "content-type": "1.0.4", | ||||
|         "cookie": "0.4.0", | ||||
|         "cookie-parser": "1.4.4", | ||||
|         "cors": "2.8.5", | ||||
|         "cron": "1.6.0", | ||||
|         "denque": "1.4.0", | ||||
|         "express": "4.16.4", | ||||
|         "express-session": "1.15.6", | ||||
|         "fs-extra": "7.0.1", | ||||
|         "cron": "1.7.2", | ||||
|         "denque": "1.4.1", | ||||
|         "express": "4.17.1", | ||||
|         "express-session": "1.17.0", | ||||
|         "fs-extra": "8.1.0", | ||||
|         "fs.notify": "0.0.4", | ||||
|         "hash-sum": "1.0.2", | ||||
|         "https-proxy-agent": "2.2.1", | ||||
|         "i18next": "13.1.0", | ||||
|         "hash-sum": "2.0.0", | ||||
|         "https-proxy-agent": "2.2.4", | ||||
|         "i18next": "15.1.2", | ||||
|         "iconv-lite": "0.5.0", | ||||
|         "is-utf8": "0.2.1", | ||||
|         "js-yaml": "3.12.1", | ||||
|         "js-yaml": "3.13.1", | ||||
|         "json-stringify-safe": "5.0.1", | ||||
|         "jsonata": "1.6.4", | ||||
|         "media-typer": "1.0.1", | ||||
|         "memorystore": "1.6.0", | ||||
|         "mime": "2.4.0", | ||||
|         "jsonata": "1.7.0", | ||||
|         "media-typer": "1.1.0", | ||||
|         "memorystore": "1.6.1", | ||||
|         "mime": "2.4.4", | ||||
|         "mqtt": "2.18.8", | ||||
|         "multer": "1.4.1", | ||||
|         "mustache": "3.0.1", | ||||
|         "node-red-node-email": "1.0.*", | ||||
|         "node-red-node-feedparser": "^0.1.14", | ||||
|         "node-red-node-rbe": "0.2.*", | ||||
|         "node-red-node-sentiment": "^0.1.0", | ||||
|         "node-red-node-tail": "^0.0.2", | ||||
|         "node-red-node-twitter": "^1.1.0", | ||||
|         "multer": "1.4.2", | ||||
|         "mustache": "3.0.2", | ||||
|         "node-red-node-rbe": "^0.2.6", | ||||
|         "node-red-node-sentiment": "^0.1.6", | ||||
|         "node-red-node-tail": "^0.1.0", | ||||
|         "nopt": "4.0.1", | ||||
|         "oauth2orize": "1.11.0", | ||||
|         "on-headers": "1.0.1", | ||||
|         "on-headers": "1.0.2", | ||||
|         "passport": "0.4.0", | ||||
|         "passport-http-bearer": "1.0.1", | ||||
|         "passport-oauth2-client-password": "0.1.2", | ||||
|         "raw-body": "2.3.3", | ||||
|         "raw-body": "2.4.1", | ||||
|         "request": "2.88.0", | ||||
|         "semver": "5.6.0", | ||||
|         "uglify-js": "3.4.9", | ||||
|         "semver": "6.3.0", | ||||
|         "uglify-js": "3.6.9", | ||||
|         "when": "3.7.8", | ||||
|         "ws": "6.1.3", | ||||
|         "xml2js": "0.4.19" | ||||
|         "ws": "6.2.1", | ||||
|         "xml2js": "0.4.22" | ||||
|     }, | ||||
|     "optionalDependencies": { | ||||
|         "bcrypt": "~2.0.0" | ||||
|         "bcrypt": "3.0.6" | ||||
|     }, | ||||
|     "devDependencies": { | ||||
|         "grunt": "~1.0.3", | ||||
|         "grunt": "~1.0.4", | ||||
|         "grunt-chmod": "~1.1.1", | ||||
|         "grunt-cli": "~1.3.2", | ||||
|         "grunt-concurrent": "~2.3.1", | ||||
|         "grunt-contrib-clean": "~1.1.0", | ||||
|         "grunt-contrib-compress": "~1.4.0", | ||||
|         "grunt-contrib-clean": "~2.0.0", | ||||
|         "grunt-contrib-compress": "~1.5.0", | ||||
|         "grunt-contrib-concat": "~1.0.1", | ||||
|         "grunt-contrib-copy": "~1.0.0", | ||||
|         "grunt-contrib-jshint": "~1.1.0", | ||||
|         "grunt-contrib-uglify": "~3.4.0", | ||||
|         "grunt-contrib-jshint": "~2.1.0", | ||||
|         "grunt-contrib-uglify": "~4.0.1", | ||||
|         "grunt-contrib-watch": "~1.1.0", | ||||
|         "grunt-jsdoc": "^2.2.1", | ||||
|         "grunt-jsdoc-to-markdown": "^4.0.0", | ||||
|         "grunt-jsonlint": "~1.1.0", | ||||
|         "grunt-jsonlint": "~2.0.0", | ||||
|         "grunt-mkdir": "~1.0.0", | ||||
|         "grunt-mocha-istanbul": "5.0.2", | ||||
|         "grunt-nodemon": "~0.4.2", | ||||
|         "grunt-npm-command": "~0.1.2", | ||||
|         "grunt-sass": "~2.0.0", | ||||
|         "grunt-sass": "~3.1.0", | ||||
|         "grunt-simple-mocha": "~0.4.1", | ||||
|         "grunt-webdriver": "^2.0.3", | ||||
|         "http-proxy": "^1.16.2", | ||||
|         "http-proxy": "1.18.0", | ||||
|         "istanbul": "0.4.5", | ||||
|         "jsdoc-nr-template": "github:node-red/jsdoc-nr-template", | ||||
|         "minami": "1.2.3", | ||||
|         "mocha": "^5.2.0", | ||||
|         "mosca": "^2.8.3", | ||||
|         "node-red-node-test-helper": "^0.2.3", | ||||
|         "node-sass": "^4.13.0", | ||||
|         "should": "^8.4.0", | ||||
|         "sinon": "1.17.7", | ||||
|         "stoppable": "^1.1.0", | ||||
|         "supertest": "3.4.2", | ||||
|         "wdio-chromedriver-service": "^0.1.5", | ||||
|         "wdio-mocha-framework": "^0.6.4", | ||||
|         "wdio-spec-reporter": "^0.1.5", | ||||
|         "webdriverio": "^4.14.1", | ||||
|         "node-red-node-test-helper": "node-red/node-red-node-test-helper", | ||||
|         "jsdoc-nr-template": "node-red/jsdoc-nr-template" | ||||
|         "supertest": "3.4.2" | ||||
|     }, | ||||
|     "engines": { | ||||
|         "node": ">=8" | ||||
|   | ||||
| @@ -30,7 +30,8 @@ module.exports = { | ||||
|             scope: req.params.scope, | ||||
|             id: req.params.id, | ||||
|             key: req.params[0], | ||||
|             store: req.query['store'] | ||||
|             store: req.query['store'], | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|         runtimeAPI.context.getValue(opts).then(function(result) { | ||||
|             res.json(result); | ||||
| @@ -45,7 +46,8 @@ module.exports = { | ||||
|             scope: req.params.scope, | ||||
|             id: req.params.id, | ||||
|             key: req.params[0], | ||||
|             store: req.query['store'] | ||||
|             store: req.query['store'], | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|         runtimeAPI.context.delete(opts).then(function(result) { | ||||
|             res.status(204).end(); | ||||
|   | ||||
| @@ -24,7 +24,8 @@ module.exports = { | ||||
|     get: function(req,res) { | ||||
|         var opts = { | ||||
|             user: req.user, | ||||
|             id: req.params.id | ||||
|             id: req.params.id, | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|         runtimeAPI.flows.getFlow(opts).then(function(result) { | ||||
|             return res.json(result); | ||||
| @@ -35,7 +36,8 @@ module.exports = { | ||||
|     post: function(req,res) { | ||||
|         var opts = { | ||||
|             user: req.user, | ||||
|             flow: req.body | ||||
|             flow: req.body, | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|         runtimeAPI.flows.addFlow(opts).then(function(id) { | ||||
|             return res.json({id:id}); | ||||
| @@ -47,7 +49,8 @@ module.exports = { | ||||
|         var opts = { | ||||
|             user: req.user, | ||||
|             id: req.params.id, | ||||
|             flow: req.body | ||||
|             flow: req.body, | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|         runtimeAPI.flows.updateFlow(opts).then(function(id) { | ||||
|             return res.json({id:id}); | ||||
| @@ -58,7 +61,8 @@ module.exports = { | ||||
|     delete: function(req,res) { | ||||
|         var opts = { | ||||
|             user: req.user, | ||||
|             id: req.params.id | ||||
|             id: req.params.id, | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|         runtimeAPI.flows.deleteFlow(opts).then(function() { | ||||
|             res.status(204).end(); | ||||
|   | ||||
| @@ -27,7 +27,8 @@ module.exports = { | ||||
|             return res.status(400).json({code:"invalid_api_version", message:"Invalid API Version requested"}); | ||||
|         } | ||||
|         var opts = { | ||||
|             user: req.user | ||||
|             user: req.user, | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|         runtimeAPI.flows.getFlows(opts).then(function(result) { | ||||
|             if (version === "v1") { | ||||
| @@ -46,7 +47,8 @@ module.exports = { | ||||
|         } | ||||
|         var opts = { | ||||
|             user: req.user, | ||||
|             deploymentType: req.get("Node-RED-Deployment-Type")||"full" | ||||
|             deploymentType: req.get("Node-RED-Deployment-Type")||"full", | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|  | ||||
|         if (opts.deploymentType !== 'reload') { | ||||
|   | ||||
| @@ -48,13 +48,13 @@ module.exports = { | ||||
|         // Nodes | ||||
|         adminApp.get("/nodes",needsPermission("nodes.read"),nodes.getAll,apiUtil.errorHandler); | ||||
|         adminApp.post("/nodes",needsPermission("nodes.write"),nodes.post,apiUtil.errorHandler); | ||||
|         adminApp.get(/\/nodes\/messages/,needsPermission("nodes.read"),nodes.getModuleCatalogs,apiUtil.errorHandler); | ||||
|         adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+\/[^\/]+)\/messages/,needsPermission("nodes.read"),nodes.getModuleCatalog,apiUtil.errorHandler); | ||||
|         adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.read"),nodes.getModule,apiUtil.errorHandler); | ||||
|         adminApp.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.putModule,apiUtil.errorHandler); | ||||
|         adminApp.delete(/\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.delete,apiUtil.errorHandler); | ||||
|         adminApp.get(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.read"),nodes.getSet,apiUtil.errorHandler); | ||||
|         adminApp.put(/\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.write"),nodes.putSet,apiUtil.errorHandler); | ||||
|         adminApp.get(/^\/nodes\/messages/,needsPermission("nodes.read"),nodes.getModuleCatalogs,apiUtil.errorHandler); | ||||
|         adminApp.get(/^\/nodes\/((@[^\/]+\/)?[^\/]+\/[^\/]+)\/messages/,needsPermission("nodes.read"),nodes.getModuleCatalog,apiUtil.errorHandler); | ||||
|         adminApp.get(/^\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.read"),nodes.getModule,apiUtil.errorHandler); | ||||
|         adminApp.put(/^\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.putModule,apiUtil.errorHandler); | ||||
|         adminApp.delete(/^\/nodes\/((@[^\/]+\/)?[^\/]+)$/,needsPermission("nodes.write"),nodes.delete,apiUtil.errorHandler); | ||||
|         adminApp.get(/^\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.read"),nodes.getSet,apiUtil.errorHandler); | ||||
|         adminApp.put(/^\/nodes\/((@[^\/]+\/)?[^\/]+)\/([^\/]+)$/,needsPermission("nodes.write"),nodes.putSet,apiUtil.errorHandler); | ||||
|  | ||||
|         // Context | ||||
|         adminApp.get("/context/:scope(global)",needsPermission("context.read"),context.get,apiUtil.errorHandler); | ||||
|   | ||||
| @@ -24,7 +24,8 @@ module.exports = { | ||||
|     }, | ||||
|     getAll: function(req,res) { | ||||
|         var opts = { | ||||
|             user: req.user | ||||
|             user: req.user, | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|         if (req.get("accept") == "application/json") { | ||||
|             runtimeAPI.nodes.getNodeList(opts).then(function(list) { | ||||
| @@ -42,7 +43,8 @@ module.exports = { | ||||
|         var opts = { | ||||
|             user: req.user, | ||||
|             module: req.body.module, | ||||
|             version: req.body.version | ||||
|             version: req.body.version, | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|         runtimeAPI.nodes.addModule(opts).then(function(info) { | ||||
|             res.json(info); | ||||
| @@ -54,7 +56,8 @@ module.exports = { | ||||
|     delete: function(req,res) { | ||||
|         var opts = { | ||||
|             user: req.user, | ||||
|             module: req.params[0] | ||||
|             module: req.params[0], | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|         runtimeAPI.nodes.removeModule(opts).then(function() { | ||||
|             res.status(204).end(); | ||||
| @@ -66,7 +69,8 @@ module.exports = { | ||||
|     getSet: function(req,res) { | ||||
|         var opts = { | ||||
|             user: req.user, | ||||
|             id: req.params[0] + "/" + req.params[2] | ||||
|             id: req.params[0] + "/" + req.params[2], | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|         if (req.get("accept") === "application/json") { | ||||
|             runtimeAPI.nodes.getNodeInfo(opts).then(function(result) { | ||||
| @@ -87,7 +91,8 @@ module.exports = { | ||||
|     getModule: function(req,res) { | ||||
|         var opts = { | ||||
|             user: req.user, | ||||
|             module: req.params[0] | ||||
|             module: req.params[0], | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|         runtimeAPI.nodes.getModuleInfo(opts).then(function(result) { | ||||
|             res.send(result); | ||||
| @@ -106,7 +111,8 @@ module.exports = { | ||||
|         var opts = { | ||||
|             user: req.user, | ||||
|             id: req.params[0] + "/" + req.params[2], | ||||
|             enabled: body.enabled | ||||
|             enabled: body.enabled, | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|         runtimeAPI.nodes.setNodeSetState(opts).then(function(result) { | ||||
|             res.send(result); | ||||
| @@ -125,7 +131,8 @@ module.exports = { | ||||
|         var opts = { | ||||
|             user: req.user, | ||||
|             module: req.params[0], | ||||
|             enabled: body.enabled | ||||
|             enabled: body.enabled, | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|         runtimeAPI.nodes.setModuleState(opts).then(function(result) { | ||||
|             res.send(result); | ||||
| @@ -139,7 +146,8 @@ module.exports = { | ||||
|         var opts = { | ||||
|             user: req.user, | ||||
|             module: req.params[0], | ||||
|             lang: req.query.lng | ||||
|             lang: req.query.lng, | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|         runtimeAPI.nodes.getModuleCatalog(opts).then(function(result) { | ||||
|             res.json(result); | ||||
| @@ -152,7 +160,8 @@ module.exports = { | ||||
|     getModuleCatalogs: function(req,res) { | ||||
|         var opts = { | ||||
|             user: req.user, | ||||
|             lang: req.query.lng | ||||
|             lang: req.query.lng, | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|         runtimeAPI.nodes.getModuleCatalogs(opts).then(function(result) { | ||||
|             res.json(result); | ||||
| @@ -164,7 +173,8 @@ module.exports = { | ||||
|  | ||||
|     getIcons: function(req,res) { | ||||
|         var opts = { | ||||
|             user: req.user | ||||
|             user: req.user, | ||||
|             req: apiUtils.getRequestLogObject(req) | ||||
|         } | ||||
|         runtimeAPI.nodes.getIconList(opts).then(function(list) { | ||||
|             res.json(list); | ||||
|   | ||||
| @@ -199,7 +199,7 @@ function genericStrategy(adminApp,strategy) { | ||||
|     if (/^post$/i.test(options.callbackMethod)) { | ||||
|         callbackMethodFunc = adminApp.post; | ||||
|     } | ||||
|     callbackMethodFunc('/auth/strategy/callback', | ||||
|     callbackMethodFunc.call(adminApp,'/auth/strategy/callback', | ||||
|         passport.authenticate(strategy.name, {session:false, failureRedirect: settings.httpAdminRoot }), | ||||
|         completeGenerateStrategyAuth | ||||
|     ); | ||||
|   | ||||
| @@ -56,7 +56,7 @@ function expireSessions() { | ||||
|     } | ||||
|     if (nextExpiry < Number.MAX_SAFE_INTEGER) { | ||||
|         // Allow 5 seconds grace | ||||
|         expiryTimeout = setTimeout(expireSessions,(nextExpiry - Date.now()) + 5000) | ||||
|         expiryTimeout = setTimeout(expireSessions,Math.min(2147483647,(nextExpiry - Date.now()) + 5000)) | ||||
|     } | ||||
|     if (modified) { | ||||
|         return storage.saveSessions(sessions); | ||||
| @@ -129,7 +129,7 @@ module.exports = { | ||||
|             sessions[accessToken] = session; | ||||
|  | ||||
|             if (!expiryTimeout) { | ||||
|                 expiryTimeout = setTimeout(expireSessions,(accessTokenExpiresAt - Date.now()) + 5000) | ||||
|                 expiryTimeout = setTimeout(expireSessions,Math.min(2147483647,(accessTokenExpiresAt - Date.now()) + 5000)) | ||||
|             } | ||||
|  | ||||
|             return storage.saveSessions(sessions).then(function() { | ||||
|   | ||||
| @@ -25,8 +25,8 @@ var auth = require("../auth"); | ||||
| var nodes = require("../admin/nodes"); // TODO: move /icons into here | ||||
| var needsPermission; | ||||
| var runtimeAPI; | ||||
| var log = require("@node-red/util").log; // TODO: separate module | ||||
| var i18n = require("@node-red/util").i18n; // TODO: separate module | ||||
| var log = require("@node-red/util").log; | ||||
| var i18n = require("@node-red/util").i18n; | ||||
|  | ||||
| var apiUtil = require("../util"); | ||||
|  | ||||
| @@ -88,14 +88,13 @@ module.exports = { | ||||
|             // Locales | ||||
|             var locales = require("./locales"); | ||||
|             locales.init(runtimeAPI); | ||||
|             editorApp.get(/locales\/(.+)\/?$/,locales.get,apiUtil.errorHandler); | ||||
|             editorApp.get(/^\/locales\/(.+)\/?$/,locales.get,apiUtil.errorHandler); | ||||
|  | ||||
|             // Library | ||||
|             var library = require("./library"); | ||||
|             library.init(runtimeAPI); | ||||
|             editorApp.get("/library/flows",needsPermission("library.read"),library.getAll,apiUtil.errorHandler); | ||||
|             editorApp.get(/library\/([^\/]+)(?:$|\/(.*))/,needsPermission("library.read"),library.getEntry); | ||||
|             editorApp.post(/library\/([^\/]+)\/(.*)/,needsPermission("library.write"),library.saveEntry); | ||||
|             editorApp.get(/^\/library\/([^\/]+)\/([^\/]+)(?:$|\/(.*))/,needsPermission("library.read"),library.getEntry); | ||||
|             editorApp.post(/^\/library\/([^\/]+)\/([^\/]+)\/(.*)/,needsPermission("library.write"),library.saveEntry); | ||||
|  | ||||
|  | ||||
|             // Credentials | ||||
|   | ||||
| @@ -25,23 +25,12 @@ module.exports = { | ||||
|     init: function(_runtimeAPI) { | ||||
|         runtimeAPI = _runtimeAPI; | ||||
|     }, | ||||
|  | ||||
|     getAll: function(req,res) { | ||||
|         var opts = { | ||||
|             user: req.user, | ||||
|             type: 'flows' | ||||
|         } | ||||
|         runtimeAPI.library.getEntries(opts).then(function(result) { | ||||
|             res.json(result); | ||||
|         }).catch(function(err) { | ||||
|             apiUtils.rejectHandler(req,res,err); | ||||
|         }); | ||||
|     }, | ||||
|     getEntry: function(req,res) { | ||||
|         var opts = { | ||||
|             user: req.user, | ||||
|             type: req.params[0], | ||||
|             path: req.params[1]||"" | ||||
|             library: req.params[0], | ||||
|             type: req.params[1], | ||||
|             path: req.params[2]||"" | ||||
|         } | ||||
|         runtimeAPI.library.getEntry(opts).then(function(result) { | ||||
|             if (typeof result === "string") { | ||||
| @@ -62,8 +51,9 @@ module.exports = { | ||||
|     saveEntry: function(req,res) { | ||||
|         var opts = { | ||||
|             user: req.user, | ||||
|             type: req.params[0], | ||||
|             path: req.params[1]||"" | ||||
|             library: req.params[0], | ||||
|             type: req.params[1], | ||||
|             path: req.params[2]||"" | ||||
|         } | ||||
|         // TODO: horrible inconsistencies between flows and all other types | ||||
|         if (opts.type === "flows") { | ||||
|   | ||||
| @@ -15,7 +15,7 @@ | ||||
|  **/ | ||||
| var fs = require('fs'); | ||||
| var path = require('path'); | ||||
| //var apiUtil = require('../util'); | ||||
| // var apiUtil = require('../util'); | ||||
|  | ||||
| var i18n = require("@node-red/util").i18n; // TODO: separate module | ||||
|  | ||||
| @@ -41,7 +41,7 @@ module.exports = { | ||||
|         var namespace = req.params[0]; | ||||
|         var lngs = req.query.lng; | ||||
|         namespace = namespace.replace(/\.json$/,""); | ||||
|         var lang = req.query.lng; //apiUtil.determineLangFromHeaders(req.acceptsLanguages() || []); | ||||
|         var lang = req.query.lng || i18n.defaultLang; //apiUtil.determineLangFromHeaders(req.acceptsLanguages() || []); | ||||
|         var prevLang = i18n.i.language; | ||||
|         // Trigger a load from disk of the language if it is not the default | ||||
|         i18n.i.changeLanguage(lang, function(){ | ||||
|   | ||||
| @@ -22,7 +22,8 @@ var needsPermission = require("../auth").needsPermission; | ||||
|  | ||||
| function listProjects(req,res) { | ||||
|     var opts = { | ||||
|         user: req.user | ||||
|         user: req.user, | ||||
|         req: apiUtils.getRequestLogObject(req) | ||||
|     } | ||||
|     runtimeAPI.projects.listProjects(opts).then(function(result) { | ||||
|         res.json(result); | ||||
| @@ -33,7 +34,8 @@ function listProjects(req,res) { | ||||
| function getProject(req,res) { | ||||
|     var opts = { | ||||
|         user: req.user, | ||||
|         id: req.params.id | ||||
|         id: req.params.id, | ||||
|         req: apiUtils.getRequestLogObject(req) | ||||
|     } | ||||
|     runtimeAPI.projects.getProject(opts).then(function(data) { | ||||
|         if (data) { | ||||
| @@ -49,7 +51,8 @@ function getProjectStatus(req,res) { | ||||
|     var opts = { | ||||
|         user: req.user, | ||||
|         id: req.params.id, | ||||
|         remote: req.query.remote | ||||
|         remote: req.query.remote, | ||||
|         req: apiUtils.getRequestLogObject(req) | ||||
|     } | ||||
|     runtimeAPI.projects.getStatus(opts).then(function(data){ | ||||
|         if (data) { | ||||
| @@ -64,7 +67,8 @@ function getProjectStatus(req,res) { | ||||
| function getProjectRemotes(req,res) { | ||||
|     var opts = { | ||||
|         user: req.user, | ||||
|         id: req.params.id | ||||
|         id: req.params.id, | ||||
|         req: apiUtils.getRequestLogObject(req) | ||||
|     } | ||||
|     runtimeAPI.projects.getRemotes(opts).then(function(data) { | ||||
|         res.json(data); | ||||
| @@ -98,7 +102,8 @@ module.exports = { | ||||
|         app.post("/", needsPermission("projects.write"), function(req,res) { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 project: req.body | ||||
|                 project: req.body, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.createProject(opts).then(function(result) { | ||||
|                 res.json(result); | ||||
| @@ -112,7 +117,8 @@ module.exports = { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 project: req.body | ||||
|                 project: req.body, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|  | ||||
|             if (req.body.active) { | ||||
| @@ -150,7 +156,8 @@ module.exports = { | ||||
|         app.delete("/:id", needsPermission("projects.write"), function(req,res) { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id | ||||
|                 id: req.params.id, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.deleteProject(opts).then(function() { | ||||
|                 res.status(204).end(); | ||||
| @@ -168,7 +175,8 @@ module.exports = { | ||||
|         app.get("/:id/files", needsPermission("projects.read"), function(req,res) { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id | ||||
|                 id: req.params.id, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.getFiles(opts).then(function(data) { | ||||
|                 res.json(data); | ||||
| @@ -185,7 +193,8 @@ module.exports = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 path: req.params[0], | ||||
|                 tree: req.params.treeish | ||||
|                 tree: req.params.treeish, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.getFile(opts).then(function(data) { | ||||
|                 res.json({content:data}); | ||||
| @@ -199,7 +208,8 @@ module.exports = { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 path: req.params[0] | ||||
|                 path: req.params[0], | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|  | ||||
|             runtimeAPI.projects.revertFile(opts).then(function() { | ||||
| @@ -214,7 +224,8 @@ module.exports = { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 path: req.params[0] | ||||
|                 path: req.params[0], | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.stageFile(opts).then(function() { | ||||
|                 getProjectStatus(req,res); | ||||
| @@ -228,7 +239,8 @@ module.exports = { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 path: req.body.files | ||||
|                 path: req.body.files, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.stageFile(opts).then(function() { | ||||
|                 getProjectStatus(req,res); | ||||
| @@ -242,7 +254,8 @@ module.exports = { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 message: req.body.message | ||||
|                 message: req.body.message, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.commit(opts).then(function() { | ||||
|                 getProjectStatus(req,res); | ||||
| @@ -256,7 +269,8 @@ module.exports = { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 path: req.params[0] | ||||
|                 path: req.params[0], | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.unstageFile(opts).then(function() { | ||||
|                 getProjectStatus(req,res); | ||||
| @@ -269,7 +283,8 @@ module.exports = { | ||||
|         app.delete("/:id/stage", needsPermission("projects.write"), function(req, res) { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id | ||||
|                 id: req.params.id, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.unstageFile(opts).then(function() { | ||||
|                 getProjectStatus(req,res); | ||||
| @@ -284,7 +299,8 @@ module.exports = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 path: req.params[0], | ||||
|                 type: req.params.type | ||||
|                 type: req.params.type, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.getFileDiff(opts).then(function(data) { | ||||
|                 res.json({ | ||||
| @@ -301,7 +317,8 @@ module.exports = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 limit: req.query.limit || 20, | ||||
|                 before: req.query.before | ||||
|                 before: req.query.before, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.getCommits(opts).then(function(data) { | ||||
|                 res.json(data); | ||||
| @@ -315,7 +332,8 @@ module.exports = { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 sha: req.params.sha | ||||
|                 sha: req.params.sha, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.getCommit(opts).then(function(data) { | ||||
|                 res.json({commit:data}); | ||||
| @@ -330,7 +348,8 @@ module.exports = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 remote: req.params[0], | ||||
|                 track: req.query.u | ||||
|                 track: req.query.u, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.push(opts).then(function(data) { | ||||
|                 res.status(204).end(); | ||||
| @@ -346,7 +365,8 @@ module.exports = { | ||||
|                 id: req.params.id, | ||||
|                 remote: req.params[0], | ||||
|                 track: req.query.setUpstream, | ||||
|                 allowUnrelatedHistories: req.query.allowUnrelatedHistories | ||||
|                 allowUnrelatedHistories: req.query.allowUnrelatedHistories, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.pull(opts).then(function(data) { | ||||
|                 res.status(204).end(); | ||||
| @@ -359,7 +379,8 @@ module.exports = { | ||||
|         app.delete("/:id/merge", needsPermission("projects.write"), function(req, res) { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id | ||||
|                 id: req.params.id, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.abortMerge(opts).then(function() { | ||||
|                 res.status(204).end(); | ||||
| @@ -374,7 +395,8 @@ module.exports = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 path: req.params[0], | ||||
|                 resolution: req.body.resolutions | ||||
|                 resolution: req.body.resolutions, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.resolveMerge(opts).then(function() { | ||||
|                 res.status(204).end(); | ||||
| @@ -388,7 +410,8 @@ module.exports = { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 remote: false | ||||
|                 remote: false, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.getBranches(opts).then(function(data) { | ||||
|                 res.json(data); | ||||
| @@ -403,7 +426,8 @@ module.exports = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 branch: req.params.branchName, | ||||
|                 force: !!req.query.force | ||||
|                 force: !!req.query.force, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.deleteBranch(opts).then(function(data) { | ||||
|                 res.status(204).end(); | ||||
| @@ -417,7 +441,8 @@ module.exports = { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 remote: true | ||||
|                 remote: true, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.getBranches(opts).then(function(data) { | ||||
|                 res.json(data); | ||||
| @@ -431,7 +456,8 @@ module.exports = { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 branch: req.params[0] | ||||
|                 branch: req.params[0], | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.getBranchStatus(opts).then(function(data) { | ||||
|                 res.json(data); | ||||
| @@ -446,7 +472,8 @@ module.exports = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 branch: req.body.name, | ||||
|                 create: req.body.create | ||||
|                 create: req.body.create, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.setBranch(opts).then(function(data) { | ||||
|                 res.json(data); | ||||
| @@ -463,7 +490,8 @@ module.exports = { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 remote: req.body | ||||
|                 remote: req.body, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             if (/^https?:\/\/[^/]+@/i.test(req.body.url)) { | ||||
|                 res.status(400).json({error:"unexpected_error", message:"Git http url must not include username/password"}); | ||||
| @@ -481,7 +509,8 @@ module.exports = { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 remote: req.params.remoteName | ||||
|                 remote: req.params.remoteName, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.removeRemote(opts).then(function(data) { | ||||
|                 getProjectRemotes(req,res); | ||||
| @@ -497,7 +526,8 @@ module.exports = { | ||||
|             var opts = { | ||||
|                 user: req.user, | ||||
|                 id: req.params.id, | ||||
|                 remote: remote | ||||
|                 remote: remote, | ||||
|                 req: apiUtils.getRequestLogObject(req) | ||||
|             } | ||||
|             runtimeAPI.projects.updateRemote(opts).then(function() { | ||||
|                 res.status(204).end(); | ||||
|   | ||||
| @@ -19,6 +19,8 @@ var sshkeys = require("./sshkeys"); | ||||
| var theme = require("./theme"); | ||||
| var clone = require("clone"); | ||||
|  | ||||
| var i18n = require("@node-red/util").i18n | ||||
|  | ||||
| function extend(target, source) { | ||||
|     var keys = Object.keys(source); | ||||
|     var i = keys.length; | ||||
| @@ -53,12 +55,14 @@ module.exports = { | ||||
|             user: req.user | ||||
|         } | ||||
|         runtimeAPI.settings.getRuntimeSettings(opts).then(function(result) { | ||||
|             result.editorTheme = result.editorTheme||{}; | ||||
|             var themeSettings = theme.settings(); | ||||
|             if (themeSettings) { | ||||
|                 // result.editorTheme may already exist with the palette | ||||
|                 // disabled. Need to merge that into the receive settings | ||||
|                 result.editorTheme = extend(clone(themeSettings),result.editorTheme||{}); | ||||
|                 result.editorTheme = extend(clone(themeSettings),result.editorTheme); | ||||
|             } | ||||
|             result.editorTheme.languages = i18n.availableLanguages("editor"); | ||||
|             res.json(result); | ||||
|         }); | ||||
|     }, | ||||
|   | ||||
| @@ -28,7 +28,7 @@ var defaultContext = { | ||||
|     }, | ||||
|     header: { | ||||
|         title: "Node-RED", | ||||
|         image: "red/images/node-red.png" | ||||
|         image: "red/images/node-red.svg" | ||||
|     }, | ||||
|     asset: { | ||||
|         red: (process.env.NODE_ENV == "development")? "red/red.js":"red/red.min.js", | ||||
| @@ -169,6 +169,9 @@ module.exports = { | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|         themeApp.get("/", function(req,res) { | ||||
|             res.json(themeContext); | ||||
|         }) | ||||
|  | ||||
|         if (theme.hasOwnProperty("menu")) { | ||||
|             themeSettings.menu = theme.menu; | ||||
|   | ||||
| @@ -25,7 +25,7 @@ var theme = require("./theme"); | ||||
|  | ||||
| var runtimeAPI; | ||||
| var editorClientDir = path.dirname(require.resolve("@node-red/editor-client")); | ||||
| var defaultNodeIcon = path.join(editorClientDir,"public","red","images","icons","arrow-in.png"); | ||||
| var defaultNodeIcon = path.join(editorClientDir,"public","red","images","icons","arrow-in.svg"); | ||||
| var editorTemplatePath = path.join(editorClientDir,"templates","index.mst"); | ||||
| var editorTemplate; | ||||
|  | ||||
|   | ||||
| @@ -42,7 +42,7 @@ var editor; | ||||
| /** | ||||
|  * Initialise the module. | ||||
|  * @param  {Object}     settings   The runtime settings | ||||
|  * @param  {HTTPServer} server     An instance of HTTP Server | ||||
|  * @param  {HTTPServer} _server     An instance of HTTP Server | ||||
|  * @param  {Storage}    storage    An instance of Node-RED Storage | ||||
|  * @param  {Runtime}    runtimeAPI An instance of Node-RED Runtime | ||||
|  * @memberof @node-red/editor-api | ||||
|   | ||||
| @@ -47,5 +47,12 @@ module.exports = { | ||||
|             code: err.code||"unexpected_error", | ||||
|             message: err.message||err.toString() | ||||
|         }); | ||||
|     }, | ||||
|     getRequestLogObject: function(req) { | ||||
|         return { | ||||
|             user: req.user, | ||||
|             path: req.path, | ||||
|             ip: (req.headers && req.headers['x-forwarded-for']) || (req.connection && req.connection.remoteAddress) || undefined | ||||
|         } | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@node-red/editor-api", | ||||
|     "version": "0.20.0-beta.4", | ||||
|     "version": "1.0.3", | ||||
|     "license": "Apache-2.0", | ||||
|     "main": "./lib/index.js", | ||||
|     "repository": { | ||||
| @@ -16,22 +16,25 @@ | ||||
|         } | ||||
|     ], | ||||
|     "dependencies": { | ||||
|         "@node-red/util": "0.20.0-beta.4", | ||||
|         "@node-red/editor-client": "0.20.0-beta.4", | ||||
|         "@node-red/util": "1.0.3", | ||||
|         "@node-red/editor-client": "1.0.3", | ||||
|         "bcryptjs": "2.4.3", | ||||
|         "body-parser": "1.18.3", | ||||
|         "body-parser": "1.19.0", | ||||
|         "clone": "2.1.2", | ||||
|         "cors": "2.8.5", | ||||
|         "express-session": "1.15.6", | ||||
|         "express": "4.16.4", | ||||
|         "memorystore": "1.6.0", | ||||
|         "mime": "2.4.0", | ||||
|         "mustache": "3.0.1", | ||||
|         "express-session": "1.17.0", | ||||
|         "express": "4.17.1", | ||||
|         "memorystore": "1.6.1", | ||||
|         "mime": "2.4.4", | ||||
|         "mustache": "3.0.2", | ||||
|         "oauth2orize": "1.11.0", | ||||
|         "passport-http-bearer": "1.0.1", | ||||
|         "passport-oauth2-client-password": "0.1.2", | ||||
|         "passport": "0.4.0", | ||||
|         "when": "3.7.8", | ||||
|         "ws": "6.1.3" | ||||
|         "ws": "6.2.1" | ||||
|     }, | ||||
|     "optionalDependencies": { | ||||
|         "bcrypt": "3.0.6" | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -26,8 +26,7 @@ | ||||
|     "status" : "Status", | ||||
|     "enabled" : "Aktiviert", | ||||
|     "disabled" : "Inaktiviert", | ||||
|     "info" : "Beschreibung", | ||||
|     "tip" : "Beschreibung akzeptiert Markdown und wird auf der Registerkarte Info angezeigt." | ||||
|     "info" : "Beschreibung" | ||||
|   }, | ||||
|   "menu" : { | ||||
|     "label" : { | ||||
| @@ -48,16 +47,13 @@ | ||||
|       }, | ||||
|       "settings" : "Einstellungen", | ||||
|       "userSettings" : "Benutzereinstellungen", | ||||
|       "nodes" : "Knoten", | ||||
|       "displayStatus" : "Knotenstatus anzeigen", | ||||
|       "displayConfig" : "Konfigurationsknoten", | ||||
|       "nodes" : "Nodes", | ||||
|       "displayStatus" : "Nodestatus anzeigen", | ||||
|       "displayConfig" : "Konfigurations-Node", | ||||
|       "import" : "Import", | ||||
|       "export" : "Exportieren", | ||||
|       "search" : "Flows durchsuchen", | ||||
|       "searchInput" : "durchsuchen Sie Ihre Flows", | ||||
|       "clipboard" : "Zwischenablage", | ||||
|       "library" : "Bibliothek", | ||||
|       "examples" : "Beispiele", | ||||
|       "subflows" : "Subflow", | ||||
|       "createSubflow" : "Subflow erstellen", | ||||
|       "selectionToSubflow" : "Auswahl für Subflow", | ||||
| @@ -87,17 +83,17 @@ | ||||
|     "notAuthorized" : "Keine Berechtigung", | ||||
|     "errors" : { | ||||
|       "settings" : "Sie müssen angemeldet sein, um auf die Einstellungen zuzugreifen.", | ||||
|       "deploy" : "Sie müssen angemeldet sein, um Änderungen implementieren zu können.", | ||||
|       "deploy" : "Sie müssen angemeldet sein, um Änderungen anwenden zu können.", | ||||
|       "notAuthorized" : "Sie müssen angemeldet sein, um diese Aktion ausführen zu können." | ||||
|     } | ||||
|   }, | ||||
|   "notification" : { | ||||
|     "warning" : "<strong> Warnung </strong>: __message__", | ||||
|     "warnings" : { | ||||
|       "undeployedChanges" : "Knoten hat nicht implementierte Änderungen", | ||||
|       "nodeActionDisabled" : "In Subflow inaktivierte Knotenaktionen", | ||||
|       "missing-types" : "<p> Die Flows wurden aufgrund fehlender Knotentypen gestoppt. </p>", | ||||
|       "restartRequired" : "Knoten-RED muss erneut gestartet werden, damit aufgerüstete Module aktiviert werden können", | ||||
|       "undeployedChanges" : "Node hat nicht implementierte Änderungen", | ||||
|       "nodeActionDisabled" : "In Subflow inaktivierte Nodeaktionen", | ||||
|       "missing-types" : "<p> Die Flows wurden aufgrund fehlender Nodetypen gestoppt. </p>", | ||||
|       "restartRequired" : "Node-RED muss erneut gestartet werden, damit aufgerüstete Module aktiviert werden können", | ||||
|       "credentials_load_failed" : "<p> Die Flows wurden gestoppt, da die Berechtigungsnachweise nicht entschlüsselt werden konnten. </p> <p> Die Datei mit dem Datenflowberechtigungsnachweis ist verschlüsselt, aber der Verschlüsselungsschlüssel des Projekts fehlt oder ist ungültig. </p>", | ||||
|       "credentials_load_failed_reset" : "<p> Die Berechtigungsnachweise konnten nicht entschlüsselt werden </p> <p> Die Datei mit dem Flow-Berechtigungsnachweis ist verschlüsselt, aber der Chiffrierschlüssel des Projekts fehlt oder ist ungültig. </p> <p> Die Datei des Flow-Berechtigungsnachweises wird bei der nächsten Implementierung zurückgesetzt. Alle vorhandenen Datenflowberechtigungsnachweise werden gelöscht. </p>", | ||||
|       "missing_flow_file" : "<p> Die Projektflowdatei wurde nicht gefunden. </p> <p> Das Projekt ist nicht mit einer Flow-Datei konfiguriert. </p>", | ||||
| @@ -136,19 +132,19 @@ | ||||
|     } | ||||
|   }, | ||||
|   "clipboard" : { | ||||
|     "nodes" : "Knoten", | ||||
|     "selectNodes" : "Wählen Sie den Text oben aus, und kopieren Sie die Datei in die Zwischenablage.", | ||||
|     "pasteNodes" : "Knoten hier einfügen", | ||||
|     "importNodes" : "Knoten importieren", | ||||
|     "exportNodes" : "Knoten in Zwischenablage exportieren", | ||||
|     "clipboard" : "Zwischenablage", | ||||
|     "nodes" : "Nodes", | ||||
|     "pasteNodes" : "Nodes hier einfügen", | ||||
|     "importNodes" : "Nodes importieren", | ||||
|     "exportNodes" : "Nodes in Zwischenablage exportieren", | ||||
|     "importUnrecognised" : "Importierter Typ nicht erkannt:", | ||||
|     "importUnrecognised_plural" : "Importierte Typen nicht erkannt:", | ||||
|     "nodesExported" : "Knoten, die in die Zwischenablage exportiert wurden", | ||||
|     "nodeCopied" : "__count__ Knoten kopiert", | ||||
|     "nodeCopied_plural" : "__count__ Knoten kopiert", | ||||
|     "nodesExported" : "Nodes, die in die Zwischenablage exportiert wurden", | ||||
|     "nodeCopied" : "__count__ Node kopiert", | ||||
|     "nodeCopied_plural" : "__count__ Nodes kopiert", | ||||
|     "invalidFlow" : "Ungültiger Nachrichtenflow: __message__", | ||||
|     "export" : { | ||||
|       "selected" : "Ausgewählte Knoten", | ||||
|       "selected" : "Ausgewählte Nodes", | ||||
|       "current" : "Aktueller Flow", | ||||
|       "all" : "alle Flows", | ||||
|       "compact" : "kompakt", | ||||
| @@ -164,16 +160,16 @@ | ||||
|     "copyMessageValue_truncated" : "Abgeschnittene Wert kopiert" | ||||
|   }, | ||||
|   "deploy" : { | ||||
|     "deploy" : "Implementieren", | ||||
|     "deploy" : "deploy", | ||||
|     "full" : "Voll", | ||||
|     "fullDesc" : "Implementiert alles im Arbeitsbereich", | ||||
|     "modifiedFlows" : "Geänderte Flows", | ||||
|     "modifiedFlowsDesc" : "Implementiert nur Flows, die geänderte Knoten enthalten.", | ||||
|     "modifiedNodes" : "Geänderte Knoten", | ||||
|     "modifiedNodesDesc" : "Implementiert nur Knoten, die sich geändert haben.", | ||||
|     "modifiedFlowsDesc" : "Implementiert nur Flows, die geänderte Nodes enthalten.", | ||||
|     "modifiedNodes" : "Geänderte Nodes", | ||||
|     "modifiedNodesDesc" : "Implementiert nur Nodes, die sich geändert haben.", | ||||
|     "successfulDeploy" : "Erfolgreich implementiert", | ||||
|     "deployFailed" : "Implementieren fehlgeschlagen: __message__", | ||||
|     "unusedConfigNodes" : "Sie haben einige nicht verwendete Konfigurationsknoten.", | ||||
|     "deployFailed" : "Deploy fehlgeschlagen: __message__", | ||||
|     "unusedConfigNodes" : "Sie haben einige nicht verwendete Konfigurations-Nodes.", | ||||
|     "unusedConfigNodesLink" : "Klicken Sie hier, um sie zu sehen", | ||||
|     "errors" : { | ||||
|       "noResponse" : "Keine Antwort vom Server" | ||||
| @@ -181,16 +177,16 @@ | ||||
|     "confirm" : { | ||||
|       "button" : { | ||||
|         "ignore" : "Ignorieren", | ||||
|         "confirm" : "Implementieren bestätigen", | ||||
|         "confirm" : "Deploy bestätigen", | ||||
|         "review" : "Änderungen prüfen", | ||||
|         "cancel" : "Abbrechen", | ||||
|         "merge" : "Zusammenführen", | ||||
|         "overwrite" : "Ignorieren & implementieren" | ||||
|         "overwrite" : "Ignorieren & deployen" | ||||
|       }, | ||||
|       "undeployedChanges" : "Sie haben nicht implementierte Änderungen.\n\nWenn Sie diese Seite verlassen, gehen diese Änderungen verloren.", | ||||
|       "improperlyConfigured" : "Der Arbeitsbereich enthält einige Knoten, die nicht ordnungsgemäß konfiguriert sind:", | ||||
|       "unknown" : "Der Arbeitsbereich enthält einige unbekannte Knotentypen:", | ||||
|       "confirm" : "Sind Sie sicher, dass Sie implementieren möchten?", | ||||
|       "improperlyConfigured" : "Der Arbeitsbereich enthält einige Nodes, die nicht ordnungsgemäß konfiguriert sind:", | ||||
|       "unknown" : "Der Arbeitsbereich enthält einige unbekannte Node-Typen:", | ||||
|       "confirm" : "Sind Sie sicher, dass Sie deployen möchten?", | ||||
|       "doNotWarn" : "warnen Sie nicht noch einmal.", | ||||
|       "conflict" : "Auf dem Server wird eine aktuellere Gruppe von Datenflüssen ausgeführt.", | ||||
|       "backgroundUpdate" : "Die Datenflüsse auf dem Server wurden aktualisiert.", | ||||
| @@ -203,7 +199,7 @@ | ||||
|   "diff" : { | ||||
|     "unresolvedCount" : "__count__ unaufgelöster Konflikt", | ||||
|     "unresolvedCount_plural" : "__count__ unaufgelöste Konflikte", | ||||
|     "globalNodes" : "Globale Knoten", | ||||
|     "globalNodes" : "Globale Nodes", | ||||
|     "flowProperties" : "Flow-Eigenschaften", | ||||
|     "type" : { | ||||
|       "added" : "hinzugefügt", | ||||
| @@ -215,8 +211,8 @@ | ||||
|       "movedTo" : "verschoben zu __id__", | ||||
|       "movedFrom" : "verschoben von __id__" | ||||
|     }, | ||||
|     "nodeCount" : "__count__, Knoten", | ||||
|     "nodeCount_plural" : "__count__-Knoten", | ||||
|     "nodeCount" : "__count__, Node", | ||||
|     "nodeCount_plural" : "__count__-Nodes", | ||||
|     "local" : "Lokale Änderungen", | ||||
|     "remote" : "Ferne Änderungen", | ||||
|     "reviewChanges" : "Änderungen prüfen", | ||||
| @@ -240,9 +236,8 @@ | ||||
|     "deleteSubflow" : "Subflow löschen", | ||||
|     "info" : "Beschreibung", | ||||
|     "category" : "Kategorie", | ||||
|     "format" : "Markdown-Format", | ||||
|     "errors" : { | ||||
|       "noNodesSelected" : "<strong> Subflow kann nicht erstellt werden </strong>: Es wurden keine Knoten ausgewählt.", | ||||
|       "noNodesSelected" : "<strong> Subflow kann nicht erstellt werden </strong>: Es wurden keine Nodes ausgewählt.", | ||||
|       "multipleInputsToSelection" : "<strong> Subflow kann nicht erstellt werden </strong>: Mehrere Eingaben zur Auswahl" | ||||
|     } | ||||
|   }, | ||||
| @@ -252,13 +247,13 @@ | ||||
|     "configUpdate" : "Aktualisieren", | ||||
|     "configDelete" : "Löschen", | ||||
|     "nodesUse" : "__count__node verwendet diese Konfiguration", | ||||
|     "nodesUse_plural" : "__count__ -Knoten verwenden diese Konfiguration", | ||||
|     "addNewConfig" : "Neuen __type__config-Knoten hinzufügen", | ||||
|     "editNode" : "__type__ Knoten bearbeiten", | ||||
|     "editConfig" : "__type__config-Knoten bearbeiten", | ||||
|     "nodesUse_plural" : "__count__ -Nodes verwenden diese Konfiguration", | ||||
|     "addNewConfig" : "Neuen __type__config-Node hinzufügen", | ||||
|     "editNode" : "__type__ Node bearbeiten", | ||||
|     "editConfig" : "__type__config-Node bearbeiten", | ||||
|     "addNewType" : "Neuen __type__ hinzufügen ...", | ||||
|     "nodeProperties" : "Knoteneigenschaften", | ||||
|     "portLabels" : "Knoteneinstellungen", | ||||
|     "nodeProperties" : "Node-Eigenschaften", | ||||
|     "portLabels" : "Node-Einstellungen", | ||||
|     "labelInputs" : "Eingänge", | ||||
|     "labelOutputs" : "Ausgänge", | ||||
|     "settingIcon" : "Symbol", | ||||
| @@ -267,7 +262,7 @@ | ||||
|     "searchIcons" : "Suchsymbole", | ||||
|     "useDefault" : "Standardwert verwenden", | ||||
|     "errors" : { | ||||
|       "scopeChange" : "Wenn Sie den Geltungsbereich ändern, wird er für Knoten in anderen Nachrichtenflüssen, die ihn verwenden, nicht verfügbar sein." | ||||
|       "scopeChange" : "Wenn Sie den Geltungsbereich ändern, wird er für Nodes in anderen Nachrichtenflüssen, die ihn verwenden, nicht verfügbar sein." | ||||
|     } | ||||
|   }, | ||||
|   "keyboard" : { | ||||
| @@ -279,48 +274,45 @@ | ||||
|     "unassigned" : "Nicht zugeordnet", | ||||
|     "global" : "global", | ||||
|     "workspace" : "Arbeitsbereich", | ||||
|     "selectAll" : "Alle Knoten auswählen", | ||||
|     "selectAllConnected" : "Alle verbundenen Knoten auswählen", | ||||
|     "addRemoveNode" : "Knoten aus Auswahl hinzufügen/entfernen", | ||||
|     "editSelected" : "Ausgewählten Knoten bearbeiten", | ||||
|     "deleteSelected" : "Ausgewählte Knoten oder ausgewählten Link löschen", | ||||
|     "importNode" : "Knoten importieren", | ||||
|     "exportNode" : "Knoten exportieren", | ||||
|     "nudgeNode" : "Ausgewählte Knoten verschieben (1px)", | ||||
|     "moveNode" : "Ausgewählte Knoten verschieben (20px)", | ||||
|     "selectAll" : "Alle Nodes auswählen", | ||||
|     "selectAllConnected" : "Alle verbundenen Nodes auswählen", | ||||
|     "addRemoveNode" : "Node aus Auswahl hinzufügen/entfernen", | ||||
|     "editSelected" : "Ausgewählten Node bearbeiten", | ||||
|     "deleteSelected" : "Ausgewählte Node oder ausgewählten Link löschen", | ||||
|     "importNode" : "Node importieren", | ||||
|     "exportNode" : "Node exportieren", | ||||
|     "nudgeNode" : "Ausgewählte Nodes verschieben (1px)", | ||||
|     "moveNode" : "Ausgewählte Nodes verschieben (20px)", | ||||
|     "toggleSidebar" : "Seitenleiste ein-/ausschalten", | ||||
|     "copyNode" : "Ausgewählte Knoten kopieren", | ||||
|     "cutNode" : "Ausgewählte Knoten ausschneiden", | ||||
|     "pasteNode" : "Knoten einfügen", | ||||
|     "copyNode" : "Ausgewählte Nodes kopieren", | ||||
|     "cutNode" : "Ausgewählte Nodes ausschneiden", | ||||
|     "pasteNode" : "Node einfügen", | ||||
|     "undoChange" : "Letzte Änderung rückgängig machen", | ||||
|     "searchBox" : "Suchfeld öffnen", | ||||
|     "managePalette" : "Palette verwalten" | ||||
|   }, | ||||
|   "library" : { | ||||
|     "library" : "Bibliothek", | ||||
|     "openLibrary" : "Bibliothek öffnen ...", | ||||
|     "saveToLibrary" : "In Bibliothek speichern ...", | ||||
|     "typeLibrary" : "__type__, Bibliothek", | ||||
|     "unnamedType" : "Unbenannt __type__", | ||||
|     "exportToLibrary" : "Knoten in Bibliothek exportieren", | ||||
|     "dialogSaveOverwrite" : "Ein __libraryType__ mit dem Namen __libraryName__ ist bereits vorhanden. Überschreiben?", | ||||
|     "invalidFilename" : "Ungültiger Dateiname", | ||||
|     "savedNodes" : "Gespeicherte Knoten", | ||||
|     "savedNodes" : "Gespeicherte Nodes", | ||||
|     "savedType" : "Gespeichert __type__", | ||||
|     "saveFailed" : "Speichern fehlgeschlagen: __message__", | ||||
|     "filename" : "Name der Datei", | ||||
|     "folder" : "Ordner", | ||||
|     "filenamePlaceholder" : "Datei", | ||||
|     "fullFilenamePlaceholder" : "a/b/Datei", | ||||
|     "folderPlaceholder" : "a/b", | ||||
|     "breadcrumb" : "Bibliothek" | ||||
|     "types": { | ||||
|         "examples" : "Beispiele" | ||||
|     } | ||||
|   }, | ||||
|   "palette" : { | ||||
|     "noInfo" : "Keine Informationen verfügbar", | ||||
|     "filter" : "Filterknoten", | ||||
|     "filter" : "Filter Nodes", | ||||
|     "search" : "Suchmodule", | ||||
|     "addCategory" : "Neu hinzufügen ...", | ||||
|     "label" : { | ||||
|       "subflows" : "untergeordnete Nachrichtenflüsse", | ||||
|       "subflows" : "Subflows", | ||||
|       "input" : "Eingabe", | ||||
|       "output" : "Ausgabe", | ||||
|       "function" : "Funktion", | ||||
| @@ -330,15 +322,15 @@ | ||||
|       "advanced" : "fortgeschritten" | ||||
|     }, | ||||
|     "event" : { | ||||
|       "nodeAdded" : "Knoten zur Palette hinzugefügt:", | ||||
|       "nodeAdded_plural" : "Die Palette wurde der Palette hinzugefügt.", | ||||
|       "nodeRemoved" : "Knoten aus Palette entfernt:", | ||||
|       "nodeRemoved_plural" : "Knoten aus Palette entfernt:", | ||||
|       "nodeEnabled" : "Knoten aktiviert:", | ||||
|       "nodeEnabled_plural" : "Knoten aktiviert:", | ||||
|       "nodeDisabled" : "Knoten inaktiviert:", | ||||
|       "nodeDisabled_plural" : "Knoten inaktiviert:", | ||||
|       "nodeUpgraded" : "Knotenmodul __module__ aktualisiert auf Version __version__" | ||||
|       "nodeAdded" : "Node zur Palette hinzugefügt:", | ||||
|       "nodeAdded_plural" : "Die Nodes wurde der Palette hinzugefügt.", | ||||
|       "nodeRemoved" : "Node aus Palette entfernt:", | ||||
|       "nodeRemoved_plural" : "Nodes aus Palette entfernt:", | ||||
|       "nodeEnabled" : "Node aktiviert:", | ||||
|       "nodeEnabled_plural" : "Nodes aktiviert:", | ||||
|       "nodeDisabled" : "Node inaktiviert:", | ||||
|       "nodeDisabled_plural" : "Nodes inaktiviert:", | ||||
|       "nodeUpgraded" : "Node-Modul __module__ aktualisiert auf Version __version__" | ||||
|     }, | ||||
|     "editor" : { | ||||
|       "title" : "Palette verwalten", | ||||
| @@ -362,8 +354,8 @@ | ||||
|         "yearsMonthsV" : "____ Jahre, __count__ Monat vor", | ||||
|         "yearsMonthsV_plural" : "____ Jahre, __count__ Monaten" | ||||
|       }, | ||||
|       "nodeCount" : "__label__, Knoten", | ||||
|       "nodeCount_plural" : "__label__ Knoten", | ||||
|       "nodeCount" : "__label__, Node", | ||||
|       "nodeCount_plural" : "__label__ Nodes", | ||||
|       "moduleCount" : "__count__ Modul verfügbar", | ||||
|       "moduleCount_plural" : "__count__-Module verfügbar", | ||||
|       "inuse" : "im Gebrauch", | ||||
| @@ -377,14 +369,14 @@ | ||||
|       "install" : "installieren", | ||||
|       "installed" : "installiert", | ||||
|       "loading" : "Kataloge werden geladen ...", | ||||
|       "tab-nodes" : "Knoten", | ||||
|       "tab-nodes" : "Nodes", | ||||
|       "tab-install" : "installieren", | ||||
|       "sort" : "Sortierung:", | ||||
|       "sortAZ" : "a-z", | ||||
|       "sortRecent" : "kürzlich", | ||||
|       "more" : "+ __count__ mehr", | ||||
|       "errors" : { | ||||
|         "catalogLoadFailed" : "<p> Fehler beim Laden des Knotenkatalogs. </p> <p> Weitere Informationen finden Sie in der Browserkonsole. </p>", | ||||
|         "catalogLoadFailed" : "<p> Fehler beim Laden des Node-Katalogs. </p> <p> Weitere Informationen finden Sie in der Browserkonsole. </p>", | ||||
|         "installFailed" : "<p> Installation fehlgeschlagen: __module__ </p> <p> __message__ </p> <p> Überprüfen Sie das Protokoll auf weitere Informationen. </p>", | ||||
|         "removeFailed" : "<p> Entfernen fehlgeschlagen: __module__ </p> <p> __message__ </p> <p> Überprüfen Sie das Protokoll auf weitere Informationen. </p>", | ||||
|         "updateFailed" : "<p> Aktualisierung fehlgeschlagen: __module__ </p> <p> __message__ </p> <p> Überprüfen Sie das Protokoll auf weitere Informationen. </p>", | ||||
| @@ -393,22 +385,22 @@ | ||||
|       }, | ||||
|       "confirm" : { | ||||
|         "install" : { | ||||
|           "body" : "<p> Installieren von '__module__' </p> <p> Vor der Installation von lesen Sie bitte die Dokumentation des Knotens. Einige Knoten haben Abhängigkeiten, die nicht automatisch aufgelöst werden können und einen Neustart von 'Node-RED' erfordern. </p>", | ||||
|           "title" : "Knoten installieren" | ||||
|           "body" : "<p> Installieren von '__module__' </p> <p> Vor der Installation von lesen Sie bitte die Dokumentation des Nodes. Einige Nodes haben Abhängigkeiten, die nicht automatisch aufgelöst werden können und einen Neustart von 'Node-RED' erfordern. </p>", | ||||
|           "title" : "Nodes installieren" | ||||
|         }, | ||||
|         "remove" : { | ||||
|           "body" : "<p> Entfernen von '__module__' </p> <p>-Der Knoten deinstalliert ihn aus Node-RED. Der Knoten kann weiterhin Ressourcen verwenden, bis Node-RED erneut gestartet wird. </p>", | ||||
|           "title" : "Knoten entfernen" | ||||
|           "body" : "<p> Entfernen von '__module__' </p> <p>-Der Node deinstalliert ihn aus Node-RED. Der Node kann weiterhin Ressourcen verwenden, bis Node-RED erneut gestartet wird. </p>", | ||||
|           "title" : "Nodes entfernen" | ||||
|         }, | ||||
|         "update" : { | ||||
|           "body" : "<p> Aktualisieren von '__module__' </p> <p> Für die Aktualisierung des Knotens ist ein Neustart von 'Node-RED' erforderlich, damit die Aktualisierung abgeschlossen werden kann. Dies muss manuell geschehen. </p>", | ||||
|           "title" : "Knoten aktualisieren" | ||||
|           "body" : "<p> Aktualisieren von '__module__' </p> <p> Für die Aktualisierung des Nodes ist ein Neustart von 'Node-RED' erforderlich, damit die Aktualisierung abgeschlossen werden kann. Dies muss manuell geschehen. </p>", | ||||
|           "title" : "Nodes aktualisieren" | ||||
|         }, | ||||
|         "cannotUpdate" : { | ||||
|           "body" : "Es ist eine Aktualisierung für diesen Knoten verfügbar, aber sie ist nicht an einer Position installiert, die vom Palettenmanager aktualisiert werden kann. <br/> <br/> Weitere Informationen zum Aktualisieren dieses Knotens finden Sie in der Dokumentation." | ||||
|           "body" : "Es ist eine Aktualisierung für diesen Node verfügbar, aber sie ist nicht an einer Position installiert, die vom Palettenmanager aktualisiert werden kann. <br/> <br/> Weitere Informationen zum Aktualisieren dieses Nodes finden Sie in der Dokumentation." | ||||
|         }, | ||||
|         "button" : { | ||||
|           "review" : "Knoteninformationen öffnen", | ||||
|           "review" : "Node-Informationen öffnen", | ||||
|           "install" : "installieren", | ||||
|           "remove" : "Entfernen", | ||||
|           "update" : "Aktualisieren" | ||||
| @@ -418,10 +410,10 @@ | ||||
|   }, | ||||
|   "sidebar" : { | ||||
|     "info" : { | ||||
|       "name" : "Knoteninformationen", | ||||
|       "name" : "Node-Informationen", | ||||
|       "tabName" : "Name", | ||||
|       "label" : "info", | ||||
|       "node" : "Knoten", | ||||
|       "node" : "Node", | ||||
|       "type" : "Typ", | ||||
|       "id" : "ID", | ||||
|       "status" : "Status", | ||||
| @@ -437,23 +429,23 @@ | ||||
|       "showLess" : "Weniger anzeigen", | ||||
|       "flow" : "Flow", | ||||
|       "selection" : "Auswahl", | ||||
|       "nodes" : "__count__ Knoten", | ||||
|       "nodes" : "__count__ Nodes", | ||||
|       "flowDesc" : "Beschreibung des Flows", | ||||
|       "subflowDesc" : "Beschreibung des Subflows", | ||||
|       "nodeHelp" : "Knotenhilfe", | ||||
|       "nodeHelp" : "Node-Hilfe", | ||||
|       "none" : "Keine", | ||||
|       "arrayItems" : "__count__ items", | ||||
|       "showTips" : "Sie können die Tipps in der Anzeige \"Einstellungen\" öffnen." | ||||
|     }, | ||||
|     "config" : { | ||||
|       "name" : "Konfigurationsknoten", | ||||
|       "name" : "Konfigurations-Node", | ||||
|       "label" : "Konfiguration", | ||||
|       "global" : "Bei allen Flows", | ||||
|       "none" : "keine", | ||||
|       "subflows" : "Subflows", | ||||
|       "flows" : "Flows", | ||||
|       "filterUnused" : "Nicht verwendet", | ||||
|       "filterAll" : "alle", | ||||
|       "filterUnused" : "Nicht verwendet", | ||||
|       "filtered" : "__count__ verdeckt" | ||||
|     }, | ||||
|     "context" : { | ||||
| @@ -462,7 +454,7 @@ | ||||
|       "none" : "keine ausgewählt", | ||||
|       "refresh" : "Aktualisierung zum Laden", | ||||
|       "empty" : "leer", | ||||
|       "node" : "Knoten", | ||||
|       "node" : "Node", | ||||
|       "flow" : "Flow", | ||||
|       "global" : "Global" | ||||
|     }, | ||||
| @@ -610,13 +602,13 @@ | ||||
|   }, | ||||
|   "typedInput" : { | ||||
|     "type" : { | ||||
|       "str" : "Zeichenfolge", | ||||
|       "num" : "Anzahl", | ||||
|       "str" : "String", | ||||
|       "num" : "Number", | ||||
|       "re" : "Regulärer Ausdruck", | ||||
|       "bool" : "boolean", | ||||
|       "json" : "JSON", | ||||
|       "bin" : "Puffer", | ||||
|       "date" : "Zeitmarke", | ||||
|       "bin" : "Buffer", | ||||
|       "date" : "timestamp", | ||||
|       "jsonata" : "Ausdruck", | ||||
|       "env" : "env, Variable" | ||||
|     } | ||||
| @@ -626,7 +618,7 @@ | ||||
|   }, | ||||
|   "search" : { | ||||
|     "empty" : "Keine Übereinstimmungen gefunden", | ||||
|     "addNode" : "Knoten hinzufügen ..." | ||||
|     "addNode" : "Node hinzufügen ..." | ||||
|   }, | ||||
|   "expressionEditor" : { | ||||
|     "functions" : "Funktionen", | ||||
| @@ -658,10 +650,10 @@ | ||||
|     "title" : "Markdown-Editor" | ||||
|   }, | ||||
|   "bufferEditor" : { | ||||
|     "title" : "Puffereditor", | ||||
|     "title" : "Buffereditor", | ||||
|     "modeString" : "Als UTF-8-Zeichenfolge bearbeiten", | ||||
|     "modeArray" : "Als JSON-Array bearbeiten", | ||||
|     "modeDesc" : "<h3> Puffereditor </h3> <p> Der Puffertyp wird als JSON-Array mit Bytewerten gespeichert. Der Editor versucht, den eingegebenen Wert als JSON-Array zu parsen. Wenn es sich nicht um ein gültiges JSON handelt, wird es als UTF-8-Zeichenfolge behandelt und in ein Array der einzelnen Zeichencodepunkte konvertiert. </p> <p> Beispiel: Der Wert  <code> Hello World </code>  wird in das JSON-Array konvertiert: <pre> [ 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100] </pre> </p>" | ||||
|     "modeDesc" : "<h3> Buffereditor </h3> <p> Der Buffertyp wird als JSON-Array mit Bytewerten gespeichert. Der Editor versucht, den eingegebenen Wert als JSON-Array zu parsen. Wenn es sich nicht um ein gültiges JSON handelt, wird es als UTF-8-Zeichenfolge behandelt und in ein Array der einzelnen Zeichencodepunkte konvertiert. </p> <p> Beispiel: Der Wert  <code> Hello World </code>  wird in das JSON-Array konvertiert: <pre> [ 72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100] </pre> </p>" | ||||
|   }, | ||||
|   "projects" : { | ||||
|     "config-git" : "Git-Client konfigurieren", | ||||
| @@ -826,4 +818,4 @@ | ||||
|       "code" : "code" | ||||
|     } | ||||
|   } | ||||
| } | ||||
| } | ||||
|   | ||||
| @@ -1,23 +1,23 @@ | ||||
| { | ||||
|   "info" : { | ||||
|     "tip0" : "Sie können die ausgewählten Knoten oder Verbindungen mit {{ core:delete-selection }} entfernen.", | ||||
|     "tip1" : "Suche nach Knoten mit {{ core:search }}", | ||||
|     "tip0" : "Sie können die ausgewählten Nodes oder Verbindungen mit {{ core:delete-selection }} entfernen.", | ||||
|     "tip1" : "Suche nach Nodes mit {{ core:search }}", | ||||
|     "tip2" : "{{ core:toggle-sidebar }} schaltet die Ansicht dieser Seitenleiste ein.", | ||||
|     "tip3" : "Sie können Ihre Palette von Knoten mit {{ core:manage-palette }} verwalten.", | ||||
|     "tip4" : "Ihre Flow-Konfigurationsknoten werden in der Seitenleiste angezeigt. Es kann über das Menü oder mit {{ core:show-config-tab }} aufgerufen werden.", | ||||
|     "tip3" : "Sie können Ihre Palette von Nodes mit {{ core:manage-palette }} verwalten.", | ||||
|     "tip4" : "Ihre Flow-Konfigurations-Nodes werden in der Seitenleiste angezeigt. Es kann über das Menü oder mit {{ core:show-config-tab }} aufgerufen werden.", | ||||
|     "tip5" : "Aktiviert oder inaktiviert diese Tipps von der Option in den Einstellungen", | ||||
|     "tip6" : "Verschieben Sie die ausgewählten Knoten mit Hilfe der [left] [up] [down] und [right] Tasten. Halten Sie [Shift] gedrückt, um das Fenster weiter zu schieben", | ||||
|     "tip7" : "Wenn Sie einen Knoten auf eine Verbindung ziehen, wird er in die Verbindung eingefügt.", | ||||
|     "tip8" : "Die ausgewählten Knoten exportieren oder die aktuelle Registerkarte mit {{ core:show-export-dialog }}", | ||||
|     "tip6" : "Verschieben Sie die ausgewählten Nodes mit Hilfe der [left] [up] [down] und [right] Tasten. Halten Sie [Shift] gedrückt, um das Fenster weiter zu schieben", | ||||
|     "tip7" : "Wenn Sie einen Node auf eine Verbindung ziehen, wird er in die Verbindung eingefügt.", | ||||
|     "tip8" : "Die ausgewählten Nodes exportieren oder die aktuelle Registerkarte mit {{ core:show-export-dialog }}", | ||||
|     "tip9" : "Importieren Sie einen Flow, indem Sie sein JSON in den Editor ziehen oder mit {{ core:show-import-dialog }}.", | ||||
|     "tip10" : "[Umschalt] [Klicken] und ziehen Sie auf einen Knotenanschluss, um alle angeschlossenen Verbindungen oder nur die ausgewählte zu verschieben.", | ||||
|     "tip10" : "[Umschalt] [Klicken] und ziehen Sie auf einen Node-Anschluss, um alle angeschlossenen Verbindungen oder nur die ausgewählte zu verschieben.", | ||||
|     "tip11" : "Die Registerkarte \"Info\" mit {{ core:show-info-tab }} oder der Registerkarte \"Debug\" mit {{ core:show-debug-tab }} anzeigen", | ||||
|     "tip12" : "[ctrl] [Klicken] in den Arbeitsbereich, um den Schnellhinzufügedialog zu öffnen.", | ||||
|     "tip13" : "Halten Sie [ctrl] gedrückt, wenn Sie auf einem Knotenanschluss klicken, um eine Schnellverbindung zu aktivieren.", | ||||
|     "tip14" : "Halten Sie [Umschalt] gedrückt, wenn Sie auf einen Knoten klicken, um auch alle verbundenen Knoten auszuwählen.", | ||||
|     "tip15" : "Halten Sie [ctrl] gedrückt, wenn Sie auf einen Knoten klicken, um ihn aus der aktuellen Auswahl hinzuzufügen oder zu entfernen.", | ||||
|     "tip13" : "Halten Sie [ctrl] gedrückt, wenn Sie auf einem Node-Anschluss klicken, um eine Schnellverbindung zu aktivieren.", | ||||
|     "tip14" : "Halten Sie [Umschalt] gedrückt, wenn Sie auf einen Node klicken, um auch alle verbundenen Nodes auszuwählen.", | ||||
|     "tip15" : "Halten Sie [ctrl] gedrückt, wenn Sie auf einen Node klicken, um ihn aus der aktuellen Auswahl hinzuzufügen oder zu entfernen.", | ||||
|     "tip16" : "Indexzungen wechseln mit {{ core:show-previous-tab }} und {{ core:show-next-tab }}", | ||||
|     "tip17" : "Sie können die Änderungen im Editierrahmen des Knotens mit {{ core:confirm-edit-tray }} bestätigen oder sie mit {{ core:cancel-edit-tray }} abbrechen.", | ||||
|     "tip18" : "Durch Drücken von {{ core:edit-selected-node }} wird der erste Knoten in der aktuellen Auswahl bearbeitet." | ||||
|     "tip17" : "Sie können die Änderungen im Editierrahmen des Nodes mit {{ core:confirm-edit-tray }} bestätigen oder sie mit {{ core:cancel-edit-tray }} abbrechen.", | ||||
|     "tip18" : "Durch Drücken von {{ core:edit-selected-node }} wird der erste Node in der aktuellen Auswahl bearbeitet." | ||||
|   } | ||||
| } | ||||
| @@ -53,7 +53,7 @@ | ||||
|   }, | ||||
|   "$now" : { | ||||
|     "args" : "", | ||||
|     "desc" : "Generiert eine Zeitmarke im ISO-8601-kompatiblen Format und gibt sie als Zeichenfolge zurück." | ||||
|     "desc" : "Generiert einen Zeitstempel im ISO-8601-kompatiblen Format und gibt sie als Zeichenfolge zurück." | ||||
|   }, | ||||
|   "$base64encode" : { | ||||
|     "args" : "Zeichenfolge", | ||||
| @@ -201,7 +201,7 @@ | ||||
|   }, | ||||
|   "$fromMillis" : { | ||||
|     "args" : "Anzahl", | ||||
|     "desc" : "Konvertieren Sie eine Zahl, die Millisekunden seit der Unix-Epoche (1. Januar 1970 (UTC)) in eine Zeitmarkenzeichenfolge im ISO 8601-Format darstellt." | ||||
|     "desc" : "Konvertieren Sie eine Zahl, die Millisekunden seit der Unix-Epoche (1. Januar 1970 (UTC)) enthält in eine Zeitangabe im ISO 8601-Format." | ||||
|   }, | ||||
|   "$formatNumber" : { | ||||
|     "args" : "Zahl, Bild [, Optionen]", | ||||
| @@ -212,8 +212,8 @@ | ||||
|     "desc" : "Transformiere die `Zahl` in eine Zeichenfolge und formatiert sie in eine ganze Zahl, die in der durch das `radix` -Argument angegebenen Zahlenbasis dargestellt wird. Wenn 'radix' nicht angegeben wird, wird standardmäßig die Basis 10 verwendet. 'radix` kann zwischen 2 und 36 liegen, andernfalls wird ein Fehler ausgelöst." | ||||
|   }, | ||||
|   "$toMillis" : { | ||||
|     "args" : "Zeitmarke", | ||||
|     "desc" : "Konvertieren Sie eine Zeichenfolge `Zeitmarke' im ISO 8601-Format in die Anzahl der Millisekunden seit der Unix-Epoche (1. Januar 1970 (UTC)) als Zahl. Es wird ein Fehler ausgelöst, wenn die Zeichenfolge nicht das richtige Format hat." | ||||
|     "args" : "timestamp", | ||||
|     "desc" : "Konvertieren Sie eine Zeitangabe im ISO 8601-Format in die Anzahl der Millisekunden seit der Unix-Epoche (1. Januar 1970 (UTC)) als Zahl. Es wird ein Fehler ausgelöst, wenn die Zeichenfolge nicht das richtige Format hat." | ||||
|   }, | ||||
|   "$env" : { | ||||
|     "args" : "arg", | ||||
|   | ||||
| @@ -15,6 +15,17 @@ | ||||
|             "next": "Next", | ||||
|             "clone": "Clone project", | ||||
|             "cont": "Continue" | ||||
|         }, | ||||
|         "type": { | ||||
|             "string": "string", | ||||
|             "number": "number", | ||||
|             "boolean": "boolean", | ||||
|             "array": "array", | ||||
|             "buffer": "buffer", | ||||
|             "object": "object", | ||||
|             "jsonString": "JSON string", | ||||
|             "undefined": "undefined", | ||||
|             "null": "null" | ||||
|         } | ||||
|     }, | ||||
|     "workspace": { | ||||
| @@ -24,10 +35,12 @@ | ||||
|         "delete": "Are you sure you want to delete '__label__'?", | ||||
|         "dropFlowHere": "Drop the flow here", | ||||
|         "addFlow": "Add Flow", | ||||
|         "listFlows": "List Flows", | ||||
|         "status": "Status", | ||||
|         "enabled": "Enabled", | ||||
|         "disabled":"Disabled", | ||||
|         "info": "Description" | ||||
|         "info": "Description", | ||||
|         "selectNodes": "Click nodes to select" | ||||
|     }, | ||||
|     "menu": { | ||||
|         "label": { | ||||
| @@ -41,7 +54,9 @@ | ||||
|                 "defaultDir": "Default", | ||||
|                 "ltr": "Left-to-right", | ||||
|                 "rtl": "Right-to-left", | ||||
|                 "auto": "Contextual" | ||||
|                 "auto": "Contextual", | ||||
|                 "language": "Language", | ||||
|                 "browserDefault": "Browser default" | ||||
|             }, | ||||
|             "sidebar": { | ||||
|                 "show": "Show sidebar" | ||||
| @@ -58,9 +73,6 @@ | ||||
|             "export": "Export", | ||||
|             "search": "Search flows", | ||||
|             "searchInput": "search your flows", | ||||
|             "clipboard": "Clipboard", | ||||
|             "library": "Library", | ||||
|             "examples": "Examples", | ||||
|             "subflows": "Subflows", | ||||
|             "createSubflow": "Create Subflow", | ||||
|             "selectionToSubflow": "Selection to Subflow", | ||||
| @@ -135,7 +147,12 @@ | ||||
|             "updated": "Project '__project__' updated", | ||||
|             "pull": "Project '__project__' reloaded", | ||||
|             "revert": "Project '__project__' reverted", | ||||
|             "merge-complete": "Git merge completed" | ||||
|             "merge-complete": "Git merge completed", | ||||
|             "setupCredentials": "Setup credentials", | ||||
|             "setupProjectFiles": "Setup project files", | ||||
|             "no": "No thanks", | ||||
|             "createDefault": "Create default project files", | ||||
|             "mergeConflict": "Show merge conflicts" | ||||
|         }, | ||||
|         "label": { | ||||
|             "manage-project-dep": "Manage project dependencies", | ||||
| @@ -148,6 +165,7 @@ | ||||
|         } | ||||
|     }, | ||||
|     "clipboard": { | ||||
|         "clipboard": "Clipboard", | ||||
|         "nodes": "Nodes", | ||||
|         "node": "__count__ node", | ||||
|         "node_plural": "__count__ nodes", | ||||
| @@ -157,7 +175,6 @@ | ||||
|         "flow_plural": "__count__ flows", | ||||
|         "subflow": "__count__ subflow", | ||||
|         "subflow_plural": "__count__ subflows", | ||||
|         "selectNodes": "Select the text above and copy to the clipboard.", | ||||
|         "pasteNodes": "Paste flow json or", | ||||
|         "selectFile": "select a file to import", | ||||
|         "importNodes": "Import nodes", | ||||
| @@ -176,7 +193,11 @@ | ||||
|             "all":"all flows", | ||||
|             "compact":"compact", | ||||
|             "formatted":"formatted", | ||||
|             "copy": "Export to clipboard" | ||||
|             "copy": "Copy to clipboard", | ||||
|             "export": "Export to library", | ||||
|             "exportAs": "Export as", | ||||
|             "overwrite": "Replace", | ||||
|             "exists": "<p><b>\"__file__\"</b> already exists.</p><p>Do you want to replace it?</p>" | ||||
|         }, | ||||
|         "import": { | ||||
|             "import": "Import to", | ||||
| @@ -266,16 +287,22 @@ | ||||
|         "newVersionError": "New Version doesn't contain valid JSON:" | ||||
|     }, | ||||
|     "subflow": { | ||||
|         "editSubflow": "Edit flow template: __name__", | ||||
|         "edit": "Edit flow template", | ||||
|         "editSubflowInstance": "Edit subflow instance: __name__", | ||||
|         "editSubflow": "Edit subflow template: __name__", | ||||
|         "edit": "Edit subflow template", | ||||
|         "subflowInstances": "There is __count__ instance of this subflow template", | ||||
|         "subflowInstances_plural": "There are __count__ instances of this subflow template", | ||||
|         "editSubflowProperties": "edit properties", | ||||
|         "input": "inputs:", | ||||
|         "output": "outputs:", | ||||
|         "status": "status node", | ||||
|         "deleteSubflow": "delete subflow", | ||||
|         "info": "Description", | ||||
|         "category": "Category", | ||||
|         "env": { | ||||
|             "restore": "Restore to subflow default", | ||||
|             "remove": "Remove environment variable" | ||||
|         }, | ||||
|         "errors": { | ||||
|             "noNodesSelected": "<strong>Cannot create subflow</strong>: no nodes selected", | ||||
|             "multipleInputsToSelection": "<strong>Cannot create subflow</strong>: multiple inputs to selection" | ||||
| @@ -294,10 +321,12 @@ | ||||
|         "addNewType": "Add new __type__...", | ||||
|         "nodeProperties": "node properties", | ||||
|         "label": "Label", | ||||
|         "color": "Color", | ||||
|         "portLabels": "Port labels", | ||||
|         "labelInputs": "Inputs", | ||||
|         "labelOutputs": "Outputs", | ||||
|         "settingIcon": "Icon", | ||||
|         "default": "default", | ||||
|         "noDefaultLabel": "none", | ||||
|         "defaultLabel": "use default label", | ||||
|         "searchIcons": "Search icons", | ||||
| @@ -305,8 +334,43 @@ | ||||
|         "description": "Description", | ||||
|         "show": "Show", | ||||
|         "hide": "Hide", | ||||
|         "locale": "Select UI Language", | ||||
|         "icon": "Icon", | ||||
|         "inputType": "Input type", | ||||
|         "inputs" : { | ||||
|             "input": "input", | ||||
|             "select": "select", | ||||
|             "checkbox": "checkbox", | ||||
|             "spinner": "spinner", | ||||
|             "none": "none", | ||||
|             "hidden": "hide property" | ||||
|         }, | ||||
|         "types": { | ||||
|             "str": "string", | ||||
|             "num": "number", | ||||
|             "bool": "bool", | ||||
|             "json": "JSON", | ||||
|             "bin": "buffer", | ||||
|             "env": "env variable" | ||||
|         }, | ||||
|         "menu": { | ||||
|             "input": "input", | ||||
|             "select": "select", | ||||
|             "checkbox": "checkbox", | ||||
|             "spinner": "spinner", | ||||
|             "hidden": "label only" | ||||
|         }, | ||||
|         "select": { | ||||
|             "label": "Label", | ||||
|             "value": "Value" | ||||
|         }, | ||||
|         "spinner": { | ||||
|             "min": "Minimum", | ||||
|             "max": "Maximum" | ||||
|         }, | ||||
|         "errors": { | ||||
|             "scopeChange": "Changing the scope will make it unavailable to nodes in other flows that use it" | ||||
|             "scopeChange": "Changing the scope will make it unavailable to nodes in other flows that use it", | ||||
|             "invalidProperties": "Invalid properties:" | ||||
|         } | ||||
|     }, | ||||
|     "keyboard": { | ||||
| @@ -334,25 +398,26 @@ | ||||
|         "pasteNode": "Paste nodes", | ||||
|         "undoChange": "Undo the last change performed", | ||||
|         "searchBox": "Open search box", | ||||
|         "managePalette": "Manage palette" | ||||
|         "managePalette": "Manage palette", | ||||
|         "actionList":"Action list" | ||||
|     }, | ||||
|     "library": { | ||||
|         "library": "Library", | ||||
|         "openLibrary": "Open Library...", | ||||
|         "saveToLibrary": "Save to Library...", | ||||
|         "typeLibrary": "__type__ library", | ||||
|         "unnamedType": "Unnamed __type__", | ||||
|         "exportToLibrary": "Export nodes to library", | ||||
|         "exportedToLibrary": "Nodes exported to library", | ||||
|         "dialogSaveOverwrite": "A __libraryType__ called __libraryName__ already exists. Overwrite?", | ||||
|         "invalidFilename": "Invalid filename", | ||||
|         "savedNodes": "Saved nodes", | ||||
|         "savedType": "Saved __type__", | ||||
|         "saveFailed": "Save failed: __message__", | ||||
|         "filename": "Filename", | ||||
|         "folder": "Folder", | ||||
|         "filenamePlaceholder": "file", | ||||
|         "fullFilenamePlaceholder": "a/b/file", | ||||
|         "folderPlaceholder": "a/b", | ||||
|         "breadcrumb": "Library" | ||||
|         "newFolder": "New folder", | ||||
|         "types": { | ||||
|             "local": "Local", | ||||
|             "examples": "Examples" | ||||
|         } | ||||
|     }, | ||||
|     "palette": { | ||||
|         "noInfo": "no information available", | ||||
| @@ -361,9 +426,13 @@ | ||||
|         "addCategory": "Add new...", | ||||
|         "label": { | ||||
|             "subflows": "subflows", | ||||
|             "network": "network", | ||||
|             "common": "common", | ||||
|             "input": "input", | ||||
|             "output": "output", | ||||
|             "function": "function", | ||||
|             "sequence": "sequence", | ||||
|             "parser": "parser", | ||||
|             "social": "social", | ||||
|             "storage": "storage", | ||||
|             "analysis": "analysis", | ||||
| @@ -375,7 +444,7 @@ | ||||
|         }, | ||||
|         "event": { | ||||
|             "nodeAdded": "Node added to palette:", | ||||
|             "nodeAdded_plural": "Nodes added to palette", | ||||
|             "nodeAdded_plural": "Nodes added to palette:", | ||||
|             "nodeRemoved": "Node removed from palette:", | ||||
|             "nodeRemoved_plural": "Nodes removed from palette:", | ||||
|             "nodeEnabled": "Node enabled:", | ||||
| @@ -500,8 +569,10 @@ | ||||
|             "none": "none", | ||||
|             "subflows": "subflows", | ||||
|             "flows": "flows", | ||||
|             "filterUnused":"unused", | ||||
|             "filterAll":"all", | ||||
|             "filterAll": "all", | ||||
|             "showAllConfigNodes": "Show all config nodes", | ||||
|             "filterUnused": "unused", | ||||
|             "showAllUnusedConfigNodes": "Show all unused config nodes", | ||||
|             "filtered": "__count__ hidden" | ||||
|         }, | ||||
|         "context": { | ||||
| @@ -513,7 +584,10 @@ | ||||
|             "node": "Node", | ||||
|             "flow": "Flow", | ||||
|             "global": "Global", | ||||
|             "deleteConfirm": "Are you sure you want to delete this item?" | ||||
|             "deleteConfirm": "Are you sure you want to delete this item?", | ||||
|             "autoRefresh": "Refresh on selection change", | ||||
|             "refrsh": "Refresh", | ||||
|             "delete": "Delete" | ||||
|         }, | ||||
|         "palette": { | ||||
|             "name": "Palette management", | ||||
| @@ -528,6 +602,7 @@ | ||||
|             "noSummaryAvailable": "No summary available", | ||||
|             "editDescription": "Edit project description", | ||||
|             "editDependencies": "Edit project dependencies", | ||||
|             "noDescriptionAvailable": "No description available", | ||||
|             "editReadme": "Edit README.md", | ||||
|             "showProjectSettings": "Show project settings", | ||||
|             "projectSettings": { | ||||
| @@ -538,14 +613,19 @@ | ||||
|                 "removeFromProject": "remove from project", | ||||
|                 "addToProject": "add to project", | ||||
|                 "files": "Files", | ||||
|                 "package": "Package", | ||||
|                 "flow": "Flow", | ||||
|                 "credentials": "Credentials", | ||||
|                 "package":"Package", | ||||
|                 "packageCreate":"File will be created when changes are saved", | ||||
|                 "fileNotExist":"File does not exist", | ||||
|                 "selectFile": "Select File", | ||||
|                 "invalidEncryptionKey": "Invalid encryption key", | ||||
|                 "encryptionEnabled": "Encryption enabled", | ||||
|                 "encryptionDisabled": "Encryption disabled", | ||||
|                 "setTheEncryptionKey": "Set the encryption key:", | ||||
|                 "resetTheEncryptionKey": "Reset the encryption key:", | ||||
|                 "changeTheEncryptionKey": "Change the encryption key:", | ||||
|                 "setTheEncryptionKey": "Set the encryption key", | ||||
|                 "resetTheEncryptionKey": "Reset the encryption key", | ||||
|                 "changeTheEncryptionKey": "Change the encryption key", | ||||
|                 "currentKey": "Current key", | ||||
|                 "newKey": "New key", | ||||
|                 "credentialsAlert": "This will delete all existing credentials", | ||||
| @@ -709,12 +789,28 @@ | ||||
|     "jsEditor": { | ||||
|         "title": "JavaScript editor" | ||||
|     }, | ||||
|     "textEditor": { | ||||
|         "title": "Text editor" | ||||
|     }, | ||||
|     "jsonEditor": { | ||||
|         "title": "JSON editor", | ||||
|         "format": "format JSON" | ||||
|         "format": "format JSON", | ||||
|         "rawMode": "Edit JSON", | ||||
|         "uiMode": "Visual editor", | ||||
|         "insertAbove": "Insert above", | ||||
|         "insertBelow": "Insert below", | ||||
|         "addItem": "Add item", | ||||
|         "copyPath": "Copy path to item", | ||||
|         "expandItems": "Expand items", | ||||
|         "collapseItems": "Collapse items", | ||||
|         "duplicate": "Duplicate", | ||||
| 	"error": { | ||||
| 	    "invalidJSON": "Invalid JSON: " | ||||
| 	} | ||||
|     }, | ||||
|     "markdownEditor": { | ||||
|         "title": "Markdown editor", | ||||
|         "expand": "Expand", | ||||
|         "format": "Formatted with markdown", | ||||
|         "heading1": "Heading 1", | ||||
|         "heading2": "Heading 2", | ||||
| @@ -744,6 +840,7 @@ | ||||
|             "desc2": "If you are not sure, you can skip this for now. You will still be able to create your first project from the 'Projects' menu at any time.", | ||||
|             "create": "Create Project", | ||||
|             "clone": "Clone Repository", | ||||
|             "openExistingProject": "Open existing project", | ||||
|             "not-right-now": "Not right now" | ||||
|         }, | ||||
|         "git-config": { | ||||
| @@ -900,7 +997,17 @@ | ||||
|     }, | ||||
|     "editor-tab": { | ||||
|         "properties": "Properties", | ||||
|         "envProperties": "Environment Variables", | ||||
|         "description": "Description", | ||||
|         "appearance": "Appearance" | ||||
|         "appearance": "Appearance", | ||||
|         "preview": "UI Preview", | ||||
|         "defaultValue": "Default value" | ||||
|     }, | ||||
|     "languages" : { | ||||
|         "de": "German", | ||||
|         "en-US": "English", | ||||
|         "ja": "Japanese", | ||||
|         "ko": "Korean", | ||||
|         "zh-CN": "Chinese(Simplified)" | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										2
									
								
								packages/node_modules/@node-red/editor-client/locales/en-US/infotips.json
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						| @@ -4,7 +4,7 @@ | ||||
|         "tip1" : "Search for nodes using {{core:search}}", | ||||
|         "tip2" : "{{core:toggle-sidebar}} will toggle the view of this sidebar", | ||||
|         "tip3" : "You can manage your palette of nodes with {{core:manage-palette}}", | ||||
|         "tip4" : "Your flow configuration nodes are listed in the sidebar panel. It can been accessed from the menu or with {{core:show-config-tab}}", | ||||
|         "tip4" : "Your flow configuration nodes are listed in the sidebar panel. It can be accessed from the menu or with {{core:show-config-tab}}", | ||||
|         "tip5" : "Enable or disable these tips from the option in the settings", | ||||
|         "tip6" : "Move the selected nodes using the [left] [up] [down] and [right] keys. Hold [shift] to nudge them further", | ||||
|         "tip7" : "Dragging a node onto a wire will splice it into the link", | ||||
|   | ||||
| @@ -1,7 +1,7 @@ | ||||
| { | ||||
|     "$string": { | ||||
|         "args": "arg", | ||||
|         "desc": "Casts the *arg* parameter to a string using the following casting rules:\n\n - Strings are unchanged\n - Functions are converted to an empty string\n - Numeric infinity and NaN throw an error because they cannot be represented as a JSON number\n - All other values are converted to a JSON string using the `JSON.stringify` function" | ||||
|         "args": "arg[, prettify]", | ||||
|         "desc": "Casts the `arg` parameter to a string using the following casting rules:\n\n - Strings are unchanged\n - Functions are converted to an empty string\n - Numeric infinity and NaN throw an error because they cannot be represented as a JSON number\n - All other values are converted to a JSON string using the `JSON.stringify` function.  If `prettify` is true, then \"prettified\" JSON is produced. i.e One line per field and lines will be indented based on the field depth." | ||||
|     }, | ||||
|     "$length": { | ||||
|         "args": "str", | ||||
| @@ -185,7 +185,7 @@ | ||||
|     }, | ||||
|     "$reduce": { | ||||
|         "args":"array, function [, init]", | ||||
|         "desc":"Returns an aggregated value derived from applying the `function` parameter successively to each value in `array` in combination with the result of the previous application of the function.\n\nThe function must accept two arguments, and behaves like an infix operator between each value within the `array`.\n\nThe optional `init` parameter is used as the initial value in the aggregation." | ||||
|         "desc":"Returns an aggregated value derived from applying the `function` parameter successively to each value in `array` in combination with the result of the previous application of the function.\n\nThe function must accept two arguments, and behaves like an infix operator between each value within the `array`. The signature of `function` must be of the form: `myfunc($accumulator, $value[, $index[, $array]])`\n\nThe optional `init` parameter is used as the initial value in the aggregation." | ||||
|     }, | ||||
|     "$flowContext": { | ||||
|         "args": "string[, string]", | ||||
| @@ -230,6 +230,37 @@ | ||||
|     "$parseInteger": { | ||||
|         "args": "string, picture", | ||||
|         "desc": "Parses the contents of the `string` parameter to an integer (as a JSON number) using the format specified by the `picture` string. The `picture` string parameter has the same format as `$formatInteger`." | ||||
|  | ||||
|     }, | ||||
|     "$error": { | ||||
|         "args": "[str]", | ||||
|         "desc": "Throws an error with a message.  The optional `str` will replace the default message of `$error() function evaluated`" | ||||
|     }, | ||||
|     "$assert": { | ||||
|         "args": "arg, str", | ||||
|         "desc": "If `arg` is true the function returns undefined.  If `arg` is false an exception is thrown with `str` as the message of the exception." | ||||
|     }, | ||||
|     "$single": { | ||||
|         "args": "array, function", | ||||
|         "desc": "Returns the one and only value in the `array` parameter that satisfies the `function` predicate (i.e. the `function` returns Boolean `true` when passed the value).  Throws an exception if the number of matching values is not exactly one.\n\nThe function should be supplied in the following signature: `function(value [, index [, array]])` where value is each input of the array, index is the position of that value and the whole array is passed as the third argument" | ||||
|     }, | ||||
|     "$encodeUrl": { | ||||
|         "args": "str", | ||||
|         "desc": "Encodes a Uniform Resource Locator (URL) component by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character.\n\nExample: `$encodeUrlComponent(\"?x=test\")` => `\"%3Fx%3Dtest\"`" | ||||
|     }, | ||||
|     "$encodeUrlComponent": { | ||||
|         "args": "str", | ||||
|         "desc": "Encodes a Uniform Resource Locator (URL) by replacing each instance of certain characters by one, two, three, or four escape sequences representing the UTF-8 encoding of the character. \n\nExample: `$encodeUrl(\"https://mozilla.org/?x=шеллы\")` => `\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\"`" | ||||
|     }, | ||||
|     "$decodeUrl": { | ||||
|         "args": "str", | ||||
|         "desc": "Decodes a Uniform Resource Locator (URL) component previously created by encodeUrlComponent. \n\nExample: `$decodeUrlComponent(\"%3Fx%3Dtest\")` => `\"?x=test\"`" | ||||
|     }, | ||||
|     "$decodeUrlComponent": { | ||||
|         "args": "str", | ||||
|         "desc": "Decodes a Uniform Resource Locator (URL) previously created by encodeUrl. \n\nExample: `$decodeUrl(\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\")` => `\"https://mozilla.org/?x=шеллы\"`" | ||||
|     }, | ||||
|     "$distinct": { | ||||
|         "args": "array", | ||||
|         "desc": "Returns an array with duplicate values removed from `array`" | ||||
|     } | ||||
| } | ||||
|   | ||||
| @@ -15,6 +15,17 @@ | ||||
|             "next": "進む", | ||||
|             "clone": "プロジェクトをクローン", | ||||
|             "cont": "続ける" | ||||
|         }, | ||||
|         "type": { | ||||
|             "string": "文字列", | ||||
|             "number": "数値", | ||||
|             "boolean": "真偽値", | ||||
|             "array": "配列", | ||||
|             "buffer": "バッファ", | ||||
|             "object": "オブジェクト", | ||||
|             "jsonString": "JSON文字列", | ||||
|             "undefined": "undefined", | ||||
|             "null": "null" | ||||
|         } | ||||
|     }, | ||||
|     "workspace": { | ||||
| @@ -24,10 +35,12 @@ | ||||
|         "delete": "本当に '__label__' を削除しますか?", | ||||
|         "dropFlowHere": "ここにフローをドロップしてください", | ||||
|         "addFlow": "フローの追加", | ||||
|         "listFlows": "フロー一覧", | ||||
|         "status": "状態", | ||||
|         "enabled": "有効", | ||||
|         "disabled": "無効", | ||||
|         "info": "詳細" | ||||
|         "info": "詳細", | ||||
|         "selectNodes": "ノードをクリックして選択" | ||||
|     }, | ||||
|     "menu": { | ||||
|         "label": { | ||||
| @@ -41,7 +54,9 @@ | ||||
|                 "defaultDir": "標準", | ||||
|                 "ltr": "左から右", | ||||
|                 "rtl": "右から左", | ||||
|                 "auto": "文脈" | ||||
|                 "auto": "文脈", | ||||
|                 "language": "表示言語", | ||||
|                 "browserDefault": "ブラウザのデフォルト" | ||||
|             }, | ||||
|             "sidebar": { | ||||
|                 "show": "サイドバーを表示" | ||||
| @@ -58,9 +73,6 @@ | ||||
|             "export": "書き出し", | ||||
|             "search": "ノードを検索", | ||||
|             "searchInput": "ノードを検索", | ||||
|             "clipboard": "クリップボード", | ||||
|             "library": "ライブラリ", | ||||
|             "examples": "サンプル", | ||||
|             "subflows": "サブフロー", | ||||
|             "createSubflow": "サブフローを作成", | ||||
|             "selectionToSubflow": "選択部分をサブフロー化", | ||||
| @@ -79,7 +91,7 @@ | ||||
|             "projects-new": "新規", | ||||
|             "projects-open": "開く", | ||||
|             "projects-settings": "設定", | ||||
|             "showNodeLabelDefault": "追加したノードのラベルを表示する" | ||||
|             "showNodeLabelDefault": "追加したノードのラベルを表示" | ||||
|         } | ||||
|     }, | ||||
|     "actions": { | ||||
| @@ -107,7 +119,7 @@ | ||||
|             "undeployedChanges": "ノードの変更をデプロイしていません", | ||||
|             "nodeActionDisabled": "ノードのアクションは無効になっています", | ||||
|             "nodeActionDisabledSubflow": "ノードのアクションは、サブフロー内で無効になっています", | ||||
|             "missing-types": "不明なノードが存在するため、フローを停止しました。詳細はログを確認してください。", | ||||
|             "missing-types": "<p>不明なノードが存在するため、フローを停止しました。</p>", | ||||
|             "safe-mode": "<p>セーフモードでフローを停止しました</p><p>フローを変更し、再起動するために変更をデプロイできます</p>", | ||||
|             "restartRequired": "更新されたモジュールを有効化するため、Node-REDを再起動する必要があります", | ||||
|             "credentials_load_failed": "<p>認証情報を復号できないため、フローを停止しました</p><p>フローの認証情報ファイルは暗号化されています。しかし、プロジェクトの暗号鍵が存在しない、または不正です</p>", | ||||
| @@ -125,7 +137,7 @@ | ||||
|             "lostConnectionTry": "すぐに接続", | ||||
|             "cannotAddSubflowToItself": "サブフロー自身を追加できません", | ||||
|             "cannotAddCircularReference": "循環参照を検出したため、サブフローを追加できません", | ||||
|             "unsupportedVersion": "<p>サポートされていないバージョンのNode.jsを使用しています。</p><p><br/>最新のNode.js LTSに更新してください。</p>", | ||||
|             "unsupportedVersion": "<p>サポートされていないバージョンのNode.jsを使用しています。</p><p>最新のNode.js LTSに更新してください。</p>", | ||||
|             "failedToAppendNode": "<p>'__module__'がロードできませんでした。</p><p>__error__</p>" | ||||
|         }, | ||||
|         "project": { | ||||
| @@ -135,7 +147,12 @@ | ||||
|             "updated": "プロジェクト'__project__'を更新しました", | ||||
|             "pull": "プロジェクト'__project__'を再ロードしました", | ||||
|             "revert": "プロジェクト'__project__'を取り消しました", | ||||
|             "merge-complete": "Gitマージが完了しました" | ||||
|             "merge-complete": "Gitマージが完了しました", | ||||
|             "setupCredentials": "認証情報を設定", | ||||
|             "setupProjectFiles": "プロジェクトファイルの設定", | ||||
|             "no": "結構です", | ||||
|             "createDefault": "デフォルトのプロジェクトファイルを作成", | ||||
|             "mergeConflict": "マージの衝突を表示" | ||||
|         }, | ||||
|         "label": { | ||||
|             "manage-project-dep": "プロジェクトの依存関係の管理", | ||||
| @@ -148,6 +165,7 @@ | ||||
|         } | ||||
|     }, | ||||
|     "clipboard": { | ||||
|         "clipboard": "クリップボード", | ||||
|         "nodes": "ノード", | ||||
|         "node": "__count__ 個のノード", | ||||
|         "node_plural": "__count__ 個のノード", | ||||
| @@ -157,7 +175,6 @@ | ||||
|         "flow_plural": "__count__ 個のフロー", | ||||
|         "subflow": "__count__ 個のサブフロー", | ||||
|         "subflow_plural": "__count__ 個のサブフロー", | ||||
|         "selectNodes": "上のテキストを選択し、クリップボードへコピーしてください", | ||||
|         "pasteNodes": "JSON形式のフローデータを貼り付けてください", | ||||
|         "selectFile": "読み込むファイルを選択してください", | ||||
|         "importNodes": "フローをクリップボートから読み込み", | ||||
| @@ -176,7 +193,11 @@ | ||||
|             "all": "全てのタブ", | ||||
|             "compact": "インデントのないJSONフォーマット", | ||||
|             "formatted": "インデント付きのJSONフォーマット", | ||||
|             "copy": "書き出し" | ||||
|             "copy": "書き出し", | ||||
|             "export": "ライブラリに書き出し", | ||||
|             "exportAs": "書き出し先", | ||||
|             "overwrite": "更新", | ||||
|             "exists": "<p><b>\"__file__\"</b>は既に存在します。</p><p>更新しますか?</p>" | ||||
|         }, | ||||
|         "import": { | ||||
|             "import": "読み込み先", | ||||
| @@ -266,16 +287,22 @@ | ||||
|         "newVersionError": "新しいバージョンは正しいJSON形式ではありません:" | ||||
|     }, | ||||
|     "subflow": { | ||||
|         "editSubflow": "フローのテンプレートを編集: __name__", | ||||
|         "edit": "フローのテンプレートを編集", | ||||
|         "editSubflowInstance": "サブフローインスタンスを編集: __name__", | ||||
|         "editSubflow": "サブフローのテンプレートを編集: __name__", | ||||
|         "edit": "サブフローのテンプレートを編集", | ||||
|         "subflowInstances": "このサブフローのテンプレートのインスタンスが __count__ 個存在します", | ||||
|         "subflowInstances_plural": "このサブフローのテンプレートのインスタンスが __count__ 個存在します", | ||||
|         "editSubflowProperties": "プロパティを編集", | ||||
|         "input": "入力:", | ||||
|         "output": "出力:", | ||||
|         "status": "ステータスノード", | ||||
|         "deleteSubflow": "サブフローを削除", | ||||
|         "info": "詳細", | ||||
|         "category": "カテゴリ", | ||||
|         "env": { | ||||
|             "restore": "デフォルト値に戻す", | ||||
|             "remove": "環境変数を削除" | ||||
|         }, | ||||
|         "errors": { | ||||
|             "noNodesSelected": "<strong>サブフローを作成できません</strong>: ノードが選択されていません", | ||||
|             "multipleInputsToSelection": "<strong>サブフローを作成できません</strong>: 複数の入力が選択されています" | ||||
| @@ -294,10 +321,12 @@ | ||||
|         "addNewType": "新規に __type__ を追加...", | ||||
|         "nodeProperties": "プロパティ", | ||||
|         "label": "ラベル", | ||||
|         "color": "色", | ||||
|         "portLabels": "ポートラベル", | ||||
|         "labelInputs": "入力", | ||||
|         "labelOutputs": "出力", | ||||
|         "settingIcon": "アイコン", | ||||
|         "default": "デフォルト", | ||||
|         "noDefaultLabel": "なし", | ||||
|         "defaultLabel": "既定のラベルを使用", | ||||
|         "searchIcons": "アイコンを検索", | ||||
| @@ -305,8 +334,43 @@ | ||||
|         "description": "詳細", | ||||
|         "show": "表示", | ||||
|         "hide": "非表示", | ||||
|         "locale": "UI言語の選択", | ||||
|         "icon": "記号", | ||||
|         "inputType": "入力形式", | ||||
|         "inputs": { | ||||
|             "input": "入力", | ||||
|             "select": "メニュー", | ||||
|             "checkbox": "チェックボックス", | ||||
|             "spinner": "スピナー", | ||||
|             "none": "無し", | ||||
|             "hidden": "非表示" | ||||
|         }, | ||||
|         "types": { | ||||
|             "str": "文字列", | ||||
|             "num": "数値", | ||||
|             "bool": "真偽", | ||||
|             "json": "JSON", | ||||
|             "bin": "バッファ", | ||||
|             "env": "環境変数" | ||||
|         }, | ||||
|         "menu": { | ||||
|             "input": "入力", | ||||
|             "select": "選択", | ||||
|             "checkbox": "チェックボックス", | ||||
|             "spinner": "数値", | ||||
|             "hidden": "ラベルのみ" | ||||
|         }, | ||||
|         "select": { | ||||
|             "label": "ラベル", | ||||
|             "value": "値" | ||||
|         }, | ||||
|         "spinner": { | ||||
|             "min": "最小値", | ||||
|             "max": "最大値" | ||||
|         }, | ||||
|         "errors": { | ||||
|             "scopeChange": "スコープの変更は、他のフローで使われているノードを無効にします" | ||||
|             "scopeChange": "スコープの変更は、他のフローで使われているノードを無効にします", | ||||
|             "invalidProperties": "プロパティが不正です:" | ||||
|         } | ||||
|     }, | ||||
|     "keyboard": { | ||||
| @@ -334,25 +398,26 @@ | ||||
|         "pasteNode": "ノードを貼り付け", | ||||
|         "undoChange": "変更操作を戻す", | ||||
|         "searchBox": "ノードを検索", | ||||
|         "managePalette": "パレットの管理" | ||||
|         "managePalette": "パレットの管理", | ||||
|         "actionList": "動作一覧" | ||||
|     }, | ||||
|     "library": { | ||||
|         "library": "ライブラリ", | ||||
|         "openLibrary": "ライブラリを開く", | ||||
|         "saveToLibrary": "ライブラリへ保存", | ||||
|         "typeLibrary": "__type__ ライブラリ", | ||||
|         "unnamedType": "名前なし __type__", | ||||
|         "exportToLibrary": "ライブラリへフローを書き出す", | ||||
|         "exportedToLibrary": "ライブラリにノードを書き出しました", | ||||
|         "dialogSaveOverwrite": "__libraryName__ という __libraryType__ は既に存在しています 上書きしますか?", | ||||
|         "invalidFilename": "不正なファイル名", | ||||
|         "savedNodes": "フローを保存しました", | ||||
|         "savedType": "__type__ を保存しました", | ||||
|         "saveFailed": "保存に失敗しました: __message__", | ||||
|         "filename": "ファイル名", | ||||
|         "folder": "フォルダ", | ||||
|         "filenamePlaceholder": "ファイル", | ||||
|         "fullFilenamePlaceholder": "a/b/file", | ||||
|         "folderPlaceholder": "a/b", | ||||
|         "breadcrumb": "ライブラリ" | ||||
|         "newFolder": "新規フォルダ", | ||||
|         "types": { | ||||
|             "local": "ローカル", | ||||
|             "examples": "サンプル" | ||||
|         } | ||||
|     }, | ||||
|     "palette": { | ||||
|         "noInfo": "情報がありません", | ||||
| @@ -361,9 +426,13 @@ | ||||
|         "addCategory": "新規追加...", | ||||
|         "label": { | ||||
|             "subflows": "サブフロー", | ||||
|             "network": "ネットワーク", | ||||
|             "common": "共通", | ||||
|             "input": "入力", | ||||
|             "output": "出力", | ||||
|             "function": "機能", | ||||
|             "sequence": "シーケンス", | ||||
|             "parser": "パーサ", | ||||
|             "social": "ソーシャル", | ||||
|             "storage": "ストレージ", | ||||
|             "analysis": "分析", | ||||
| @@ -375,7 +444,7 @@ | ||||
|         }, | ||||
|         "event": { | ||||
|             "nodeAdded": "ノードをパレットへ追加しました:", | ||||
|             "nodeAdded_plural": "ノードをパレットへ追加しました", | ||||
|             "nodeAdded_plural": "ノードをパレットへ追加しました:", | ||||
|             "nodeRemoved": "ノードをパレットから削除しました:", | ||||
|             "nodeRemoved_plural": "ノードをパレットから削除しました:", | ||||
|             "nodeEnabled": "ノードを有効化しました:", | ||||
| @@ -431,7 +500,7 @@ | ||||
|             "more": "+ さらに __count__ 個", | ||||
|             "errors": { | ||||
|                 "catalogLoadFailed": "<p>ノードのカタログの読み込みに失敗しました。</p><p>詳細はブラウザのコンソールを確認してください。</p>", | ||||
|                 "installFailed": "<p.追加処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>", | ||||
|                 "installFailed": "<p>追加処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>", | ||||
|                 "removeFailed": "<p>削除処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>", | ||||
|                 "updateFailed": "<p>更新処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>", | ||||
|                 "enableFailed": "<p>有効化処理が失敗しました: __module__</p><p>__message__</p><p>詳細はログを確認してください。</p>", | ||||
| @@ -500,8 +569,10 @@ | ||||
|             "none": "なし", | ||||
|             "subflows": "サブフロー", | ||||
|             "flows": "フロー", | ||||
|             "filterUnused": "未使用", | ||||
|             "filterAll": "全て", | ||||
|             "showAllConfigNodes": "全設定ノードを表示", | ||||
|             "filterUnused": "未使用", | ||||
|             "showAllUnusedConfigNodes": "未使用の全設定ノードを表示", | ||||
|             "filtered": "__count__ 個が無効" | ||||
|         }, | ||||
|         "context": { | ||||
| @@ -510,10 +581,13 @@ | ||||
|             "none": "選択されていません", | ||||
|             "refresh": "読み込みのため更新してください", | ||||
|             "empty": "データが存在しません", | ||||
|             "node": "Node", | ||||
|             "flow": "Flow", | ||||
|             "global": "Global", | ||||
|             "deleteConfirm": "データを削除しても良いですか?" | ||||
|             "node": "ノード", | ||||
|             "flow": "フロー", | ||||
|             "global": "グローバル", | ||||
|             "deleteConfirm": "データを削除しても良いですか?", | ||||
|             "autoRefresh": "選択対象が変化した場合更新", | ||||
|             "refrsh": "更新", | ||||
|             "delete": "削除" | ||||
|         }, | ||||
|         "palette": { | ||||
|             "name": "パレットの管理", | ||||
| @@ -525,9 +599,10 @@ | ||||
|             "description": "詳細", | ||||
|             "dependencies": "依存関係", | ||||
|             "settings": "設定", | ||||
|             "noSummaryAvailable": "サマリが存在しません", | ||||
|             "noSummaryAvailable": "要約が存在しません", | ||||
|             "editDescription": "プロジェクトの詳細を編集", | ||||
|             "editDependencies": "プロジェクトの依存関係を編集", | ||||
|             "noDescriptionAvailable": "詳細が存在しません", | ||||
|             "editReadme": "README.mdを編集", | ||||
|             "showProjectSettings": "プロジェクト設定を表示", | ||||
|             "projectSettings": { | ||||
| @@ -538,14 +613,18 @@ | ||||
|                 "removeFromProject": "プロジェクトから削除", | ||||
|                 "addToProject": "プロジェクトへ追加", | ||||
|                 "files": "ファイル", | ||||
|                 "package": "パッケージ", | ||||
|                 "flow": "フロー", | ||||
|                 "credentials": "認証情報", | ||||
|                 "packageCreate": "変更が保存された時にファイルが作成されます", | ||||
|                 "fileNotExist": "ファイルが存在しません", | ||||
|                 "selectFile": "ファイルを選択", | ||||
|                 "invalidEncryptionKey": "不正な暗号化キー", | ||||
|                 "encryptionEnabled": "暗号化が有効になっています", | ||||
|                 "encryptionDisabled": "暗号化が無効になっています", | ||||
|                 "setTheEncryptionKey": "暗号化キーを設定:", | ||||
|                 "resetTheEncryptionKey": "暗号化キーを初期化:", | ||||
|                 "changeTheEncryptionKey": "暗号化キーを変更:", | ||||
|                 "setTheEncryptionKey": "暗号化キーを設定", | ||||
|                 "resetTheEncryptionKey": "暗号化キーを初期化", | ||||
|                 "changeTheEncryptionKey": "暗号化キーを変更", | ||||
|                 "currentKey": "現在のキー", | ||||
|                 "newKey": "新規のキー", | ||||
|                 "credentialsAlert": "既存の認証情報は全て削除されます", | ||||
| @@ -709,12 +788,28 @@ | ||||
|     "jsEditor": { | ||||
|         "title": "JavaScriptエディタ" | ||||
|     }, | ||||
|     "textEditor": { | ||||
|         "title": "テキストエディタ" | ||||
|     }, | ||||
|     "jsonEditor": { | ||||
|         "title": "JSONエディタ", | ||||
|         "format": "JSONフォーマット" | ||||
|         "format": "JSONフォーマット", | ||||
|         "rawMode": "JSONを編集", | ||||
|         "uiMode": "ビジュアルエディタ", | ||||
|         "insertAbove": "上に挿入", | ||||
|         "insertBelow": "下に挿入", | ||||
|         "addItem": "要素を追加", | ||||
|         "copyPath": "要素のパスをコピー", | ||||
|         "expandItems": "要素を展開", | ||||
|         "collapseItems": "要素を折り畳む", | ||||
|         "duplicate": "複製", | ||||
| 	"error": { | ||||
| 	    "invalidJSON": "不正なJSON: " | ||||
| 	} | ||||
|     }, | ||||
|     "markdownEditor": { | ||||
|         "title": "マークダウンエディタ", | ||||
|         "expand": "拡大", | ||||
|         "format": "マークダウン形式で記述", | ||||
|         "heading1": "見出しレベル1", | ||||
|         "heading2": "見出しレベル2", | ||||
| @@ -744,6 +839,7 @@ | ||||
|             "desc2": "とりあえずこの処理をスキップしてもかまいません。「プロジェクト」メニューから、いつでもプロジェクトの作成を開始できます。", | ||||
|             "create": "プロジェクトの作成", | ||||
|             "clone": "プロジェクトのクローン", | ||||
|             "openExistingProject": "既存のプロジェクトを開く", | ||||
|             "not-right-now": "後にする" | ||||
|         }, | ||||
|         "git-config": { | ||||
| @@ -874,7 +970,7 @@ | ||||
|             "confirm": "<p>デプロイされていない変更は失われます。</p><p>続けますか?</p>" | ||||
|         }, | ||||
|         "send-req": { | ||||
|             "auth-req": "リポジトリ対する認証が必要です", | ||||
|             "auth-req": "リポジトリに対する認証が必要です", | ||||
|             "username": "ユーザ名", | ||||
|             "password": "パスワード", | ||||
|             "passphrase": "パスフレーズ", | ||||
| @@ -900,7 +996,17 @@ | ||||
|     }, | ||||
|     "editor-tab": { | ||||
|         "properties": "プロパティ", | ||||
|         "envProperties": "環境変数", | ||||
|         "description": "説明", | ||||
|         "appearance": "外観" | ||||
|         "appearance": "外観", | ||||
|         "preview": "UIプレビュー", | ||||
|         "defaultValue": "デフォルト値" | ||||
|     }, | ||||
|     "languages": { | ||||
|         "de": "ドイツ語", | ||||
|         "en-US": "英語", | ||||
|         "ja": "日本語", | ||||
|         "ko": "韓国語", | ||||
|         "zh-CN": "中国語(簡体)" | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										50
									
								
								packages/node_modules/@node-red/editor-client/locales/ja/jsonata.json
									
									
									
									
										vendored
									
									
										
										
										Normal file → Executable file
									
								
							
							
						
						| @@ -1,7 +1,7 @@ | ||||
| { | ||||
|     "$string": { | ||||
|         "args": "arg", | ||||
|         "desc": "以下の型変換ルールを用いて、引数 *arg* を文字列へ型変換します。:\n\n - 文字列は変換しません。\n - 関数は空の文字列に変換します。\n - JSONの数値として表現できないため、無限大やNaNはエラーになります。\n - 他の値は `JSON.stringify` 関数を用いて、JSONの文字列へ変換します。" | ||||
|         "args": "arg[, prettify]", | ||||
|         "desc": "以下の型変換ルールを用いて、引数 *arg* を文字列へ型変換します。:\n\n - 文字列は変換しません。\n - 関数は空の文字列に変換します。\n - JSONの数値として表現できないため、無限大やNaNはエラーになります。\n - 他の値は `JSON.stringify` 関数を用いて、JSONの文字列へ変換します。`prettify`が真の場合、JSONを整形出力します。フィールドを1行毎に出力。フィールドのネスト深さによってインデントを行います。" | ||||
|     }, | ||||
|     "$length": { | ||||
|         "args": "str", | ||||
| @@ -185,7 +185,7 @@ | ||||
|     }, | ||||
|     "$reduce": { | ||||
|         "args": "array, function [, init]", | ||||
|         "desc": "配列の各要素値に関数 `function` を連続的に適用して得られる集約値を返します。 `function` の適用の際には、直前の `function` の適用結果と要素値が引数として与えられます。\n\n関数 `function` は引数を2つ取り、配列の各要素の間に配置する中置演算子のように作用しなくてはなりません。\n\n任意の引数 `init` には、集約時の初期値を設定します。" | ||||
|         "desc": "配列の各要素値に関数 `function` を連続的に適用して得られる集約値を返します。 `function` の適用の際には、直前の `function` の適用結果と要素値が引数として与えられます。\n\n関数 `function` は引数を2つ取り、配列の各要素の間に配置する中置演算子のように作用しなくてはなりません。関数`function`のシグネチャは`myfunc($accumulator, $value[, $index[, $array]])`という形式でなければなりません。\n\n任意の引数 `init` には、集約時の初期値を設定します。" | ||||
|     }, | ||||
|     "$flowContext": { | ||||
|         "args": "string", | ||||
| @@ -218,5 +218,49 @@ | ||||
|     "$env": { | ||||
|         "args": "arg", | ||||
|         "desc": "環境変数の値を返します。\n\n本関数はNode-REDの定義関数です。" | ||||
|     }, | ||||
|     "$eval": { | ||||
|         "args": "expr [, context]", | ||||
|         "desc": "JSONリテラルもしくはJSONata式を表す`expr`を評価します。評価の際には現在のコンテキストをコンテキストとして用います。" | ||||
|     }, | ||||
|     "$formatInteger": { | ||||
|         "args": "number, picture", | ||||
|         "desc": "`number`を`picture`指定に従って文字列に変換します。`picture`文字列は数値の変換方法をXPath F&O 3.1仕様の`fn:format-integer`に従って定義します。" | ||||
|     }, | ||||
|     "$parseInteger": { | ||||
|         "args": "string, picture", | ||||
|         "desc": "`picture`文字列の指定に従って、`string`パラメータを整数(JSON数値)に変換します。`picture`文字列は`$formatInteger`と同じ形式です。" | ||||
|     }, | ||||
|     "$error": { | ||||
|         "args": "[str]", | ||||
|         "desc": "メッセージを指定して例外を送出します。メッセージ`str`を省略した場合は`$error() function evaluated`をメッセージとします。" | ||||
|     }, | ||||
|     "$assert": { | ||||
|         "args": "arg, str", | ||||
|         "desc": "`arg`が真の場合、undefinedを返します。偽の場合、`str`をメッセージとする例外を送出します。" | ||||
|     }, | ||||
|     "$single": { | ||||
|         "args": "array, function", | ||||
|         "desc": "`array`の要素のうち、条件判定関数`function`を満たす(`function`に与えた場合に真偽値`true`を返す)要素が1つのみである場合、それを返します。マッチする要素が1つのみでない場合、例外を送出します。\n\n指定する関数は`function(value [, index [, array]])`というシグネチャでなければなりません。ここで、`value`は`array`の要素値、`index`は要素の添字、第三引数には配列全体を渡します。" | ||||
|     }, | ||||
|     "$encodeUrl": { | ||||
|         "args": "str", | ||||
|         "desc": "Uniform Resource Locator (URL)を構成する文字を1、2、3、もしくは、4文字エスケープシーケンスのUTF-8文字エンコーディングで置換します。\n\n例: `$encodeUrlComponent(\"?x=test\")` => `\"%3Fx%3Dtest\"`" | ||||
|     }, | ||||
|     "$encodeUrlComponent": { | ||||
|         "args": "str", | ||||
|         "desc": "Uniform Resource Locator (URL)要素を構成する文字を1、2、3、もしくは、4文字エスケープシーケンスのUTF-8文字エンコーディングで置換します。\n\n例: `$encodeUrl(\"https://mozilla.org/?x=шеллы\")` => `\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\"`" | ||||
|     }, | ||||
|     "$decodeUrl": { | ||||
|         "args": "str", | ||||
|         "desc": "encodeUrlComponentで置換したUniform Resource Locator (URL)をデコードします。\n\n例: `$decodeUrlComponent(\"%3Fx%3Dtest\")` => `\"?x=test\"`" | ||||
|     }, | ||||
|     "$decodeUrlComponent": { | ||||
|         "args": "str", | ||||
|         "desc": "encodeUrlで置換したUniform Resource Locator (URL)要素をデコードします。 \n\n例: `$decodeUrl(\"https://mozilla.org/?x=%D1%88%D0%B5%D0%BB%D0%BB%D1%8B\")` => `\"https://mozilla.org/?x=шеллы\"`" | ||||
|     }, | ||||
|     "$distinct": { | ||||
|         "args": "array", | ||||
|         "desc": "配列`array`から重複要素を削除した配列を返します。" | ||||
|     } | ||||
| } | ||||
|   | ||||
							
								
								
									
										900
									
								
								packages/node_modules/@node-red/editor-client/locales/ko/editor.json
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						| @@ -0,0 +1,900 @@ | ||||
| { | ||||
|   "common": { | ||||
|     "label": { | ||||
|       "name": "이름", | ||||
|       "ok": "확인", | ||||
|       "done": "완료", | ||||
|       "cancel": "취소", | ||||
|       "delete": "삭제", | ||||
|       "close": "닫기", | ||||
|       "load": "열기", | ||||
|       "save": "저장", | ||||
|       "import": "가져오기", | ||||
|       "export": "내보내기", | ||||
|       "back": "뒤로", | ||||
|       "next": "앞으로", | ||||
|       "clone": "프로젝트 복제", | ||||
|       "cont": "계속하기" | ||||
|     } | ||||
|   }, | ||||
|   "workspace": { | ||||
|     "defaultName": "플로우 __number__", | ||||
|     "editFlow": "플로우 수정 : __name__", | ||||
|     "confirmDelete": "삭제 확인", | ||||
|     "delete": "정말로 '__label__' 을(를) 삭제하시겠습니까?", | ||||
|     "dropFlowHere": "플로우를 이곳에 가져오세요", | ||||
|     "addFlow": "플로우 추가", | ||||
|     "status": "상태", | ||||
|     "enabled": "사용가능", | ||||
|     "disabled": "사용불가능", | ||||
|     "info": "상세내역" | ||||
|   }, | ||||
|   "menu": { | ||||
|     "label": { | ||||
|       "view": { | ||||
|         "view": "창", | ||||
|         "grid": "눈금선", | ||||
|         "showGrid": "눈금선 보이기", | ||||
|         "snapGrid": "노드 배치 보조 켜기", | ||||
|         "gridSize": "눈금선 크기", | ||||
|         "textDir": "텍스트 방향", | ||||
|         "defaultDir": "기본", | ||||
|         "ltr": "왼쪽 -> 오른쪽", | ||||
|         "rtl": "오른쪽 -> 왼쪽", | ||||
|         "auto": "자동배분" | ||||
|       }, | ||||
|       "sidebar": { | ||||
|         "show": "우측사이드바 보이기" | ||||
|       }, | ||||
|       "palette": { | ||||
|         "show": "팔렛트 보이기" | ||||
|       }, | ||||
|       "settings": "설정", | ||||
|       "userSettings": "사용자 설정", | ||||
|       "nodes": "노드설정", | ||||
|       "displayStatus": "노드상태 보이기", | ||||
|       "displayConfig": "설정노드 보기", | ||||
|       "import": "가져오기", | ||||
|       "export": "내보내기", | ||||
|       "search": "플로우 겅색", | ||||
|       "searchInput": "플로우 검색", | ||||
|       "subflows": "보조 플로우", | ||||
|       "createSubflow": "보조 플로우 생성", | ||||
|       "selectionToSubflow": "보조 플로우 선택", | ||||
|       "flows": "플로우", | ||||
|       "add": "추가", | ||||
|       "rename": "이름변경", | ||||
|       "delete": "삭제", | ||||
|       "keyboardShortcuts": "단축키", | ||||
|       "login": "로그인", | ||||
|       "logout": "로그아웃", | ||||
|       "editPalette": "팔렛트 관리", | ||||
|       "other": "기타", | ||||
|       "showTips": "Tip 보기", | ||||
|       "help": "Node-RED 웹사이트", | ||||
|       "projects": "프로젝트", | ||||
|       "projects-new": "신규", | ||||
|       "projects-open": "열기", | ||||
|       "projects-settings": "프로젝트 설정", | ||||
|       "showNodeLabelDefault": "새로 추가된 노드의 라벨 보이기" | ||||
|     } | ||||
|   }, | ||||
|   "actions": { | ||||
|     "toggle-navigator": "네비게이터 표시/비표시", | ||||
|     "zoom-out": "축소하기", | ||||
|     "zoom-reset": "확대/축소 초기화", | ||||
|     "zoom-in": "확대하기" | ||||
|   }, | ||||
|   "user": { | ||||
|     "loggedInAs": "__name__ 에 로그인됨", | ||||
|     "username": "사용자명", | ||||
|     "password": "비밀번호", | ||||
|     "login": "로그인", | ||||
|     "loginFailed": "로그인 실패", | ||||
|     "notAuthorized": "권한이 없습니다", | ||||
|     "errors": { | ||||
|       "settings": "로그인 후 설정이 가능합니다", | ||||
|       "deploy": "로그인 후 배포가 가능합니다", | ||||
|       "notAuthorized": "이 기능은 로그인 후 사용가능합니다" | ||||
|     } | ||||
|   }, | ||||
|   "notification": { | ||||
|     "warning": "<strong>경고</strong>: __message__", | ||||
|     "warnings": { | ||||
|       "undeployedChanges": "변경사항 배포가 취소되었습니다", | ||||
|       "nodeActionDisabled": "노드 실행이 비활성화 되었습니다", | ||||
|       "nodeActionDisabledSubflow": "보조 플로우에서 노드 실행이 비활성화 되었습니다", | ||||
|       "missing-types": "<p>타입이 없는 노드로인해 플로우가 중지되었습니다</p>", | ||||
|       "safe-mode": "<p>[안전모드] 플로우가 정지되었습니다.</p><p>플로우의 수정과 배포가 가능합니다. 다시 배포버튼을 누르세요.</p>", | ||||
|       "restartRequired": "업그레이드한 모듈을 유효화하기 위해 Node-RED를 재시작 합니다 ", | ||||
|       "credentials_load_failed": "<p>인증정보 복호화에 실패하여 플로우가 멈췄습니다. </p><p>인증정보는 암호화 되어있습니다. 프로젝트의 암호화 키가 깨졌거나 정상적이지 않습니다.</p>", | ||||
|       "credentials_load_failed_reset": "<p>인증정보를 복호화할 수 없습니다</p><p>인증정보는 암호화 되어있습니다. 프로젝트의 암호화 키가 깨졌거나 정상적이지 않습니다.</p><p>다음 배포시 플로우의 인증정보는 초기화 될것입니다. 기존 모든 플로우의 인증정보가 지워집니다.</p>", | ||||
|       "missing_flow_file": "<p>프로젝트 플로우 파일을 찾을 수 없습니다</p><p>프로젝트의 플로우 파일이 설정되지 않았습니다</p>", | ||||
|       "missing_package_file": "<p>프로젝트 패키지 파일을 찾을 수 없습니다</p><p>프로젝트의 package.json 파일이 없습니다</p>", | ||||
|       "project_empty": "<p>프로젝트가 누락되어 있습니다.</p><p>기본 프로젝트 파일을 만드시겠습니까?<br/>그렇지 않으면 수동으로 편집가 외부에 프로젝트 파일을 만드셔야 합니다.</p>", | ||||
|       "project_not_found": "<p>'__project__' 가 없습니다.</p>", | ||||
|       "git_merge_conflict": "<p>변경사항 자동병합에 실패했습니다.</p><p>병합되지 않은 충돌을 수정 후 재등록 하세요.</p>" | ||||
|     }, | ||||
|     "error": "<strong>에러</strong>: __message__", | ||||
|     "errors": { | ||||
|       "lostConnection": "서버와 연결이 끊어졌습니다. 재접속을 시도합니다 ...", | ||||
|       "lostConnectionReconnect": "서버와 연결이 끊어졌습니다. __time__ 초 안에 재접속을 시도합니다.", | ||||
|       "lostConnectionTry": "지금 재접속", | ||||
|       "cannotAddSubflowToItself": "서브플로우 자기자신을 추가할 수 없습니다", | ||||
|       "cannotAddCircularReference": "순환참조가 발견되었습니다. 서브플로우를 추가할 수 없습니다", | ||||
|       "unsupportedVersion": "<p>지원하지 않는 Node.js를 사용하고 있습니다</p><p>Node.js LTS 버전을 사용해 주세요</p>", | ||||
|       "failedToAppendNode": "<p>'__module__' 읽어오기 실패</p><p>__error__</p>" | ||||
|     }, | ||||
|     "project": { | ||||
|       "change-branch": "로컬지점으로 '__project__' 변경", | ||||
|       "merge-abort": "Git 병합을 중지했습니다.", | ||||
|       "loaded": "'__project__' 프로젝트를 열었습니다", | ||||
|       "updated": "'__project__'가 변경 되었습니다", | ||||
|       "pull": "'__project__'를 다시 가져왔습니다", | ||||
|       "revert": "'__project__'를 취소했습니다", | ||||
|       "merge-complete": "Git 병합이 완료되었습니다" | ||||
|     }, | ||||
|     "label": { | ||||
|       "manage-project-dep": "프로젝트 의존성 관리", | ||||
|       "setup-cred": "인증정보 설정", | ||||
|       "setup-project": "프로젝트 파일 설정", | ||||
|       "create-default-package": "기본 패키지 파일 생성", | ||||
|       "no-thanks": "괜찮습니다", | ||||
|       "create-default-project": "기본 프로젝트 파일 생성", | ||||
|       "show-merge-conflicts": "병합 충돌 보여주기" | ||||
|     } | ||||
|   }, | ||||
|   "clipboard": { | ||||
|     "clipboard": "클립보드", | ||||
|     "nodes": "노드", | ||||
|     "node": "__count__ 개의 노드", | ||||
|     "node_plural": "__count__ 개의 노드", | ||||
|     "configNode": "__count__ 개의 설정 노드", | ||||
|     "configNode_plural": "__count__ 개의 설정 노드", | ||||
|     "flow": "__count__ 개의 플로우", | ||||
|     "flow_plural": "__count__ 개의 플로우", | ||||
|     "subflow": "__count__ 개의 서브 플로우", | ||||
|     "subflow_plural": "__count__ 개의 서브 플로우", | ||||
|     "pasteNodes": "여기에 노드를 붙여넣기 하세요", | ||||
|     "selectFile": "불러올 파일을 선택하세요", | ||||
|     "importNodes": "노드 불러오기", | ||||
|     "exportNodes": "클립보드에 노드 내보내기", | ||||
|     "download": "다운로드", | ||||
|     "importUnrecognised": "알 수 없는 형식 :", | ||||
|     "importUnrecognised_plural": "알 수 없는 형식 :", | ||||
|     "nodesExported": "클립보드에 노드 내보내기", | ||||
|     "nodesImported": "불러오기 : ", | ||||
|     "nodeCopied": "__count__개의 노드가 복사 되었습니다", | ||||
|     "nodeCopied_plural": "__count__개의 노드가 복사 되었습니다", | ||||
|     "invalidFlow": "정상적지 않은 플로우 : __message__", | ||||
|     "export": { | ||||
|       "selected": "선택된 노드", | ||||
|       "current": "현재 플로우", | ||||
|       "all": "모든 플로우", | ||||
|       "compact": "압축형식", | ||||
|       "formatted": "서식유지", | ||||
|       "copy": "클립보드로 내보내기" | ||||
|     }, | ||||
|     "import": { | ||||
|       "import": "가져올 위치 : ", | ||||
|       "newFlow": "새로운 플로우", | ||||
|       "errors": { | ||||
|         "notArray": "입력이 JSON 배열이 아닙니다", | ||||
|         "itemNotObject": "입력이 올바른 플로우가 아닙니다 - __index__는 노드 오브젝트가 아닙니다", | ||||
|         "missingId": "입력이 올바른 플로우가 아닙니다 - __index__의 'id' 속성이 없습니다", | ||||
|         "missingType": "입력이 올바른 플로우가 아닙니다 - __index__의 'type' 속성이 없습니다" | ||||
|       } | ||||
|     }, | ||||
|     "copyMessagePath": "Path가 복사 되었습니다", | ||||
|     "copyMessageValue": "Value가 복사 되었습니다", | ||||
|     "copyMessageValue_truncated": "Truncated value가 복사 되었습니다" | ||||
|   }, | ||||
|   "deploy": { | ||||
|     "deploy": "배포하기", | ||||
|     "full": "전체", | ||||
|     "fullDesc": "작업공간 내 모든 플로우를 배포합니다", | ||||
|     "modifiedFlows": "변경된 플로우", | ||||
|     "modifiedFlowsDesc": "변경사항이 있는 플로우만 배포합니다", | ||||
|     "modifiedNodes": "변경된 노드", | ||||
|     "modifiedNodesDesc": "변경사항이 있는 노드만 배포합니다", | ||||
|     "restartFlows": "플로우 재시작", | ||||
|     "restartFlowsDesc": "현재 배포된 플로우를 재시작합니다", | ||||
|     "successfulDeploy": "배포가 성공했습니다", | ||||
|     "successfulRestart": "플로우 재시작을 성공했습니다", | ||||
|     "deployFailed": "배포 실패 : __message__", | ||||
|     "unusedConfigNodes": "사용되지 않는 설정노드가 있습니다", | ||||
|     "unusedConfigNodesLink": "여기를 클릭하면 볼 수 있습니다", | ||||
|     "errors": { | ||||
|       "noResponse": "서버의 응답이 없습니다" | ||||
|     }, | ||||
|     "confirm": { | ||||
|       "button": { | ||||
|         "ignore": "무시", | ||||
|         "confirm": "배포 확인", | ||||
|         "review": "변경사항 보기", | ||||
|         "cancel": "취소", | ||||
|         "merge": "병합", | ||||
|         "overwrite": "무시하고 배포하기" | ||||
|       }, | ||||
|       "undeployedChanges": "배포되지 않은 변경사항이 있습니다.\n\n이 페이지를 떠나면 변경사항이 사라집니다", | ||||
|       "improperlyConfigured": "작업공간에 올바르게 구성되지 않은 노드가 있습니다 :", | ||||
|       "unknown": "작업공간에 알려지지 않는 노드타입이 있습니다 :", | ||||
|       "confirm": "배포하시겠습니까?", | ||||
|       "doNotWarn": "이 경고를 무시", | ||||
|       "conflict": "서버가 최신 플로우를 사용중입니다", | ||||
|       "backgroundUpdate": "플로우가 변경되었습니다", | ||||
|       "conflictChecking": "변경사항이 자동으로 병합될 수 있는지 확인", | ||||
|       "conflictAutoMerge": "변경사항에 충돌이 없습니다. 자동병합이 가능합니다", | ||||
|       "conflictManualMerge": "변경사항에 충돌이 있습니다. 배포하기 전에 충돌을 해결하세요", | ||||
|       "plusNMore": "+ __count__ 개 더보기" | ||||
|     } | ||||
|   }, | ||||
|   "eventLog": { | ||||
|     "title": "이벤트 로그", | ||||
|     "view": "로그 보기" | ||||
|   }, | ||||
|   "diff": { | ||||
|     "unresolvedCount": "__count__개의 충돌이 해결되지 않음", | ||||
|     "unresolvedCount_plural": "__count__개의 충돌이 해결되지 않음", | ||||
|     "globalNodes": "Global 노드", | ||||
|     "flowProperties": "플로우 속성", | ||||
|     "type": { | ||||
|       "added": "추가됨", | ||||
|       "changed": "변경됨", | ||||
|       "unchanged": "변경없음", | ||||
|       "deleted": "삭제됨", | ||||
|       "flowDeleted": "플로우 삭제됨", | ||||
|       "flowAdded": "플로우 추가됨", | ||||
|       "movedTo": "__id__로 이동됨", | ||||
|       "movedFrom": "__id__로 부터 이동됨" | ||||
|     }, | ||||
|     "nodeCount": "__count__ 개의 노드", | ||||
|     "nodeCount_plural": "__count__ 개의 노드", | ||||
|     "local": "로컬 변경사항", | ||||
|     "remote": "원격 변경사항", | ||||
|     "reviewChanges": "변경사항 살펴보기", | ||||
|     "noBinaryFileShowed": "바이너리파일 내용을 볼수 없습니다", | ||||
|     "viewCommitDiff": "변경사항 보기", | ||||
|     "compareChanges": "변경사항 비교", | ||||
|     "saveConflict": "충돌 해결내용 저장", | ||||
|     "conflictHeader": "<span>__unresolved__</span> 개 중 <span>__resolved__</span> 충돌이 해결됨", | ||||
|     "commonVersionError": "Common Version의 JSON 형식이 올바르지 않습니다 :", | ||||
|     "oldVersionError": "Old Version의 JSON 형식이 올바르지 않습니다 :", | ||||
|     "newVersionError": "New Version의 JSON 형식이 올바르지 않습니다 :" | ||||
|   }, | ||||
|   "subflow": { | ||||
|     "editSubflow": "플로우 템플릿 수정 : __name__", | ||||
|     "edit": "플로우 템플릿 수정", | ||||
|     "subflowInstances": "서브 플로우 템플릿에 __count__개의 인스턴스가 있습니다", | ||||
|     "subflowInstances_plural": "서브 플로우 템플릿에 __count__개의 인스턴스가 있습니다", | ||||
|     "editSubflowProperties": "속성 수정", | ||||
|     "input": "입력:", | ||||
|     "output": "출력:", | ||||
|     "deleteSubflow": "서브 플로우 삭제", | ||||
|     "info": "상세내역", | ||||
|     "category": "카테고리", | ||||
|     "errors": { | ||||
|       "noNodesSelected": "<strong>서브 플로우를 생성할 수 없습니다</strong> : 노드가 선택되지 않았습니다", | ||||
|       "multipleInputsToSelection": "<strong>서브 플로우를 생성할 수 없습니다</strong> : 복수의 입력이 선택되었습니다" | ||||
|     } | ||||
|   }, | ||||
|   "editor": { | ||||
|     "configEdit": "수정", | ||||
|     "configAdd": "추가", | ||||
|     "configUpdate": "변경", | ||||
|     "configDelete": "삭제", | ||||
|     "nodesUse": "__count__개의 노드가 이 설정을 사용중입니다", | ||||
|     "nodesUse_plural": "__count__개의 노드가 이 설정을 사용중입니다", | ||||
|     "addNewConfig": "__type__의 설정노드 추가", | ||||
|     "editNode": "__type__의 노드 수정", | ||||
|     "editConfig": "__type__의 설정노드 수정", | ||||
|     "addNewType": "__type__의 노드타입 추가 ...", | ||||
|     "nodeProperties": "노드 속성", | ||||
|     "label": "명칭", | ||||
|     "portLabels": "포트 설정", | ||||
|     "labelInputs": "입력", | ||||
|     "labelOutputs": "출력", | ||||
|     "settingIcon": "아이콘", | ||||
|     "noDefaultLabel": "없음", | ||||
|     "defaultLabel": "기본 명칭", | ||||
|     "searchIcons": "아이콘 조회", | ||||
|     "useDefault": "기본설정 사용", | ||||
|     "description": "상세 내역", | ||||
|     "show": "보이기", | ||||
|     "hide": "숨기기", | ||||
|     "errors": { | ||||
|       "scopeChange": "범위를 변경하게 되면 다른 플로우의 노드가 사용이 불가능해 집니다." | ||||
|     } | ||||
|   }, | ||||
|   "keyboard": { | ||||
|     "title": "키보드 단축키", | ||||
|     "keyboard": "키보드", | ||||
|     "filterActions": "필터", | ||||
|     "shortcut": "단축키", | ||||
|     "scope": "범위", | ||||
|     "unassigned": "미할당", | ||||
|     "global": "글로벌", | ||||
|     "workspace": "작업공간", | ||||
|     "selectAll": "모든 노드 선택", | ||||
|     "selectAllConnected": "모든 연결된 노드 선택", | ||||
|     "addRemoveNode": "노드 추가/삭제", | ||||
|     "editSelected": "선택된 노드 수정", | ||||
|     "deleteSelected": "선택된 노드나 링크를 삭제", | ||||
|     "importNode": "노드 불러오기", | ||||
|     "exportNode": "노드 내보내기", | ||||
|     "nudgeNode": "선택된 노드 이동 (1px)", | ||||
|     "moveNode": "선택된 노드 이동 (20px)", | ||||
|     "toggleSidebar": "사이드바 표시/비표시", | ||||
|     "togglePalette": "팔렛트 표시/비표시", | ||||
|     "copyNode": "선택된 노드 복사", | ||||
|     "cutNode": "선택된 노드 잘라내기", | ||||
|     "pasteNode": "노드 붙여넣기", | ||||
|     "undoChange": "마지막 변경 되돌리기", | ||||
|     "searchBox": "검색창 열기", | ||||
|     "managePalette": "팔렛트 관리" | ||||
|   }, | ||||
|   "library": { | ||||
|     "library": "라이브러리", | ||||
|     "openLibrary": "라이브러리 열기...", | ||||
|     "saveToLibrary": "라이브러리로 저장...", | ||||
|     "typeLibrary": "__type__ 라이브러리", | ||||
|     "unnamedType": "이름없는 __type__", | ||||
|     "dialogSaveOverwrite": "__libraryType__이 __libraryName__으로 이미 등록되어있습니다. 덮어쓸까요?", | ||||
|     "invalidFilename": "파일명이 올바르지 않습니다", | ||||
|     "savedNodes": "저장된 노드", | ||||
|     "savedType": "저장된 __type__", | ||||
|     "saveFailed": "저장 실패 : __message__", | ||||
|     "types": { | ||||
|         "examples": "예시" | ||||
|     } | ||||
|   }, | ||||
|   "palette": { | ||||
|     "noInfo": "정보 없음", | ||||
|     "filter": "필터", | ||||
|     "search": "모듈 검색", | ||||
|     "addCategory": "추가 ...", | ||||
|     "label": { | ||||
|       "subflows": "서브 플로우", | ||||
|       "input": "입력", | ||||
|       "output": "출력", | ||||
|       "function": "기능", | ||||
|       "social": "소셜", | ||||
|       "storage": "저장", | ||||
|       "analysis": "분석", | ||||
|       "advanced": "그 외" | ||||
|     }, | ||||
|     "actions": { | ||||
|       "collapse-all": "모든 카테고리 접기", | ||||
|       "expand-all": "모든 카테고리 펼치기" | ||||
|     }, | ||||
|     "event": { | ||||
|       "nodeAdded": "팔렛트에 노드가 추가되었습니다:", | ||||
|       "nodeAdded_plural": "팔렛트에 노드가 추가되었습니다:", | ||||
|       "nodeRemoved": "팔렛트에서 노드가 삭제되었습니다:", | ||||
|       "nodeRemoved_plural": "팔렛트에서 노드가 삭제되었습니다:", | ||||
|       "nodeEnabled": "노드가 활성화 되었습니다:", | ||||
|       "nodeEnabled_plural": "노드가 활성화 되었습니다:", | ||||
|       "nodeDisabled": "노드가 비활성화 되었습니다:", | ||||
|       "nodeDisabled_plural": "노드가 비활성화 되었습니다:", | ||||
|       "nodeUpgraded": "__module__ 노드모듈이 __version__으로 업그레이드 되었습니다" | ||||
|     }, | ||||
|     "editor": { | ||||
|       "title": "팔렛트 관리", | ||||
|       "palette": "팔렛트", | ||||
|       "times": { | ||||
|         "seconds": "몇초 전", | ||||
|         "minutes": "몇분 전", | ||||
|         "minutesV": "__count__분 전", | ||||
|         "hoursV": "__count__시간 전", | ||||
|         "hoursV_plural": "__count__시간 전", | ||||
|         "daysV": "__count__일 전", | ||||
|         "daysV_plural": "__count__일 전", | ||||
|         "weeksV": "__count__주 전", | ||||
|         "weeksV_plural": "__count__주 전", | ||||
|         "monthsV": "__count__달 전", | ||||
|         "monthsV_plural": "__count__달 전", | ||||
|         "yearsV": "__count__년 전", | ||||
|         "yearsV_plural": "__count__년 전", | ||||
|         "yearMonthsV": "__y__년, __count__월 전", | ||||
|         "yearMonthsV_plural": "__y__년, __count__월 전", | ||||
|         "yearsMonthsV": "__y__년, __count__월 전", | ||||
|         "yearsMonthsV_plural": "__y__년, __count__월 전" | ||||
|       }, | ||||
|       "nodeCount": "__label__ 개의 노드", | ||||
|       "nodeCount_plural": "__label__ 개의 노드", | ||||
|       "moduleCount": "__count__ 개의 모듈 사용가능", | ||||
|       "moduleCount_plural": "__count__ 개의 모듈 사용가능", | ||||
|       "inuse": "사용중", | ||||
|       "enableall": "모두 활성화", | ||||
|       "disableall": "모두 비활성화", | ||||
|       "enable": "활성화", | ||||
|       "disable": "비활성화", | ||||
|       "remove": "삭제", | ||||
|       "update": "__version__으로 업데이트", | ||||
|       "updated": "업데이트 됨", | ||||
|       "install": "설치", | ||||
|       "installed": "설치됨", | ||||
|       "conflict": "충돌", | ||||
|       "conflictTip": "<p>노드타입이 이미 설치 되어 있습니다.<br/>/p><p>충돌모듈 : <code>__module__</code></p>", | ||||
|       "loading": "카탈로그 여는중...", | ||||
|       "tab-nodes": "설치된 노드", | ||||
|       "tab-install": "설치가능한 노드", | ||||
|       "sort": "정렬:", | ||||
|       "sortAZ": "a-z", | ||||
|       "sortRecent": "최근", | ||||
|       "more": "+ __count__ 개 더 보기", | ||||
|       "errors": { | ||||
|         "catalogLoadFailed": "<p>노드 카탈로그를 설치하지 못했습니다.</p><p>브라우저 콘솔로그를 참고하세요.</p>", | ||||
|         "installFailed": "<p>설치 실패 : __module__</p><p>__message__</p><p>브라우저 콘솔로그를 참고하세요.</p>", | ||||
|         "removeFailed": "<p>삭제 실패 : __module__</p><p>__message__</p><p>브라우저 콘솔로그를 참고하세요.</p>", | ||||
|         "updateFailed": "<p>업데이트 실패 : __module__</p><p>__message__</p><p>브라우저 콘솔로그를 참고하세요.</p>", | ||||
|         "enableFailed": "<p>활성화 실패 : __module__</p><p>__message__</p><p>브라우저 콘솔로그를 참고하세요.</p>", | ||||
|         "disableFailed": "<p>비활성화 실패 : __module__</p><p>__message__</p><p>브라우저 콘솔로그를 참고하세요.</p>" | ||||
|       }, | ||||
|       "confirm": { | ||||
|         "install": { | ||||
|           "body": "<p>'__module__' 설치중</p><p>설치하기 전 노드 설명서를 읽으세요. 어떤 노드은 의존성이 자동으로 해결되지 않거나, Node-RED의 재시작이 필요할 수 있습니다.</p>", | ||||
|           "title": "노드 설치" | ||||
|         }, | ||||
|         "remove": { | ||||
|           "body": "<p>'__module__' 삭제중</p><p>Node-RED에서 노드를 제거합니다. Node-RED가 재시작되기까지 리소스가 계속 사용될 수도 있습니다.</p>", | ||||
|           "title": "노드 삭제" | ||||
|         }, | ||||
|         "update": { | ||||
|           "body": "<p>'__module__' 업데이트중</p><p>업데이트 반영을 위해 Node-RED를 수동으로 재시작해야 할 경우도 있습니다.</p>", | ||||
|           "title": "노드 변경" | ||||
|         }, | ||||
|         "cannotUpdate": { | ||||
|           "body": "이 노드에 대한 업데이트가 있지만, 팔레트 관리자가 변경할 수 있는 위치에 설치되지 않았습니다.<br/><br/>이 노드를 변경하는 방법은 설명서를 참조하세요" | ||||
|         }, | ||||
|         "button": { | ||||
|           "review": "노드정보 열기", | ||||
|           "install": "설치", | ||||
|           "remove": "삭제", | ||||
|           "update": "업데이트" | ||||
|         } | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   "sidebar": { | ||||
|     "info": { | ||||
|       "name": "노드정보", | ||||
|       "tabName": "이름", | ||||
|       "label": "정보", | ||||
|       "node": "노드", | ||||
|       "type": "타입", | ||||
|       "module": "모듈", | ||||
|       "id": "ID", | ||||
|       "status": "상태", | ||||
|       "enabled": "활성화", | ||||
|       "disabled": "비활성화", | ||||
|       "subflow": "서브 플로우", | ||||
|       "instances": "인스턴스", | ||||
|       "properties": "속성", | ||||
|       "info": "정보", | ||||
|       "desc": "상세 내역", | ||||
|       "blank": "공백", | ||||
|       "null": "null", | ||||
|       "showMore": "더 보기", | ||||
|       "showLess": "간단히", | ||||
|       "flow": "플로우", | ||||
|       "selection": "선택", | ||||
|       "nodes": "__count__ 개의 노드", | ||||
|       "flowDesc": "플로우 상세내역", | ||||
|       "subflowDesc": "서브 플로우 상세내역", | ||||
|       "nodeHelp": "노드 도움말", | ||||
|       "none": "없음", | ||||
|       "arrayItems": "__count__ 개의 항목", | ||||
|       "showTips": "설정에서 도움말을 열 수 있습니다. " | ||||
|     }, | ||||
|     "config": { | ||||
|       "name": "노드 설정", | ||||
|       "label": "설정", | ||||
|       "global": "모든 플로우", | ||||
|       "none": "없음", | ||||
|       "subflows": "보조 플로우", | ||||
|       "flows": "플로우", | ||||
|       "filterAll": "전체", | ||||
|       "filterUnused": "미사용", | ||||
|       "filtered": "__count__ 개 숨김" | ||||
|     }, | ||||
|     "context": { | ||||
|       "name": "Context 데이터", | ||||
|       "label": "context", | ||||
|       "none": "선택 없음", | ||||
|       "refresh": "새로고침", | ||||
|       "empty": "공백", | ||||
|       "node": "노드", | ||||
|       "flow": "플로우", | ||||
|       "global": "Global", | ||||
|       "deleteConfirm": "정말로 이 아이템을 지우시겠습니까?" | ||||
|     }, | ||||
|     "palette": { | ||||
|       "name": "팔레트 관리", | ||||
|       "label": "팔레트" | ||||
|     }, | ||||
|     "project": { | ||||
|       "label": "프로젝트", | ||||
|       "name": "프로젝트", | ||||
|       "description": "상세내역", | ||||
|       "dependencies": "의존성", | ||||
|       "settings": "설정", | ||||
|       "noSummaryAvailable": "요약 없음", | ||||
|       "editDescription": "프로젝트 상세내역 수정", | ||||
|       "editDependencies": "프로젝트 의존성 수정", | ||||
|       "editReadme": "README.md 수정", | ||||
|       "showProjectSettings": "프로젝트 설정 보이기", | ||||
|       "projectSettings": { | ||||
|         "title": "프로젝트 설정", | ||||
|         "edit": "수정", | ||||
|         "none": "없음", | ||||
|         "install": "설치", | ||||
|         "removeFromProject": "프로젝트에서 삭제", | ||||
|         "addToProject": "프로젝트에 추가", | ||||
|         "files": "파일", | ||||
|         "flow": "플로우", | ||||
|         "credentials": "인증정보", | ||||
|         "invalidEncryptionKey": "잘못된 암호화 키", | ||||
|         "encryptionEnabled": "암호화 활성화", | ||||
|         "encryptionDisabled": "암호화 비활성화", | ||||
|         "setTheEncryptionKey": "암호화 키 설정 :", | ||||
|         "resetTheEncryptionKey": "암호화 키 초기화 :", | ||||
|         "changeTheEncryptionKey": "암호화 키 변경:", | ||||
|         "currentKey": "현재 키", | ||||
|         "newKey": "새로운 키", | ||||
|         "credentialsAlert": "모든 인증정보를 삭제합니다", | ||||
|         "versionControl": "버전 관리", | ||||
|         "branches": "브랜치", | ||||
|         "noBranches": "브랜치 없음", | ||||
|         "deleteConfirm": "다시 되돌릴 수 없습니다. '__name__'의 로컬 브랜치를 삭제 히시겠습니까?", | ||||
|         "unmergedConfirm": "'__name__'의 병합되지 않은 수정사항을 잃어버릴 수 있습니다. 그래도 삭제 하시겠습니까?", | ||||
|         "deleteUnmergedBranch": "미병합 브랜치 삭제", | ||||
|         "gitRemotes": "Git 원격", | ||||
|         "addRemote": "원격 추가", | ||||
|         "addRemote2": "원격 추가", | ||||
|         "remoteName": "원격 이름", | ||||
|         "nameRule": "A-Z 0-9 _ -의 문자만 사용이 가능합니다", | ||||
|         "url": "URL", | ||||
|         "urlRule": "https://, ssh:// or file://", | ||||
|         "urlRule2": "URL안에 사용자아이디/비밀번호를 사용하지 마세요", | ||||
|         "noRemotes": "원격 없음", | ||||
|         "deleteRemoteConfrim": "원격 '__name__'를 정말로 삭제하시겠습니까?", | ||||
|         "deleteRemote": "원격 삭제" | ||||
|       }, | ||||
|       "userSettings": { | ||||
|         "committerDetail": "Committer 상세내역", | ||||
|         "committerTip": "시스템 기본값을 사용하려면 비워두세요", | ||||
|         "userName": "사용자명", | ||||
|         "email": "이메일", | ||||
|         "sshKeys": "SSH키", | ||||
|         "sshKeysTip": "원격저장소에 대한 보안연결을 허용합니다", | ||||
|         "add": "키 추가", | ||||
|         "addSshKey": "SSH키 추가", | ||||
|         "addSshKeyTip": "public/private 키쌍을 추가합니다", | ||||
|         "name": "이름", | ||||
|         "nameRule": "A-Z 0-9 _ -의 문자만 사용이 가능합니다", | ||||
|         "passphrase": "암호", | ||||
|         "passphraseShort": "암호가 너무 짧습니다", | ||||
|         "optional": "선택항목", | ||||
|         "cancel": "취소", | ||||
|         "generate": "Key 생성", | ||||
|         "noSshKeys": "SSH키 없음", | ||||
|         "copyPublicKey": "클립보드로 public key 복사", | ||||
|         "delete": "키 삭제", | ||||
|         "gitConfig": "Git 설정", | ||||
|         "deleteConfirm": "다시 되돌릴 수 없습니다. __name__의 SSH키를 삭제하시겠습니까?" | ||||
|       }, | ||||
|       "versionControl": { | ||||
|         "unstagedChanges": "변경사항을 언스테이징", | ||||
|         "stagedChanges": "스테이징된 변경사항", | ||||
|         "unstageChange": "스테이징 되지않은 변경사항", | ||||
|         "stageChange": "변경사항을 스테이징", | ||||
|         "unstageAllChange": "모든 변경사항 언스테이징", | ||||
|         "stageAllChange": "모든 변경사항 스테이징", | ||||
|         "commitChanges": "변경사항 커밋", | ||||
|         "resolveConflicts": "충돌 해결", | ||||
|         "head": "HEAD", | ||||
|         "staged": "스테이징 됨", | ||||
|         "unstaged": "스테이징 안됨", | ||||
|         "local": "로컬", | ||||
|         "remote": "리모트", | ||||
|         "revert": "다시 복원할 수 없습니다. '__file__'을 되돌리시겠습니까?", | ||||
|         "revertChanges": "변경사항 되돌리기", | ||||
|         "localChanges": "로컬 변경사항", | ||||
|         "none": "없음", | ||||
|         "conflictResolve": "모든 충돌이 해결되었습니다. 변경사항을 적용하여 병합을 완료하세요", | ||||
|         "localFiles": "로컬 파일", | ||||
|         "all": "전체", | ||||
|         "unmergedChanges": "병합되지 않은 변경사항", | ||||
|         "abortMerge": "병합 중단", | ||||
|         "commit": "커밋", | ||||
|         "changeToCommit": "커밋 변경사항", | ||||
|         "commitPlaceholder": "커밋 메시지를 입력하세요", | ||||
|         "cancelCapital": "취소", | ||||
|         "commitCapital": "커밋", | ||||
|         "commitHistory": "커밋 이력", | ||||
|         "branch": "브랜치 :", | ||||
|         "moreCommits": "커밋 더보기", | ||||
|         "changeLocalBranch": "로컬 브랜치 변경", | ||||
|         "createBranchPlaceholder": "브렌치 찾기/생성", | ||||
|         "upstream": "업스트림", | ||||
|         "localOverwrite": "브랜치에 반영할 변경사항이 있습니다. 변경사항을 커밋하거나, 변경내역을 취소해야 합니다", | ||||
|         "manageRemoteBranch": "원격 브랜치 관리", | ||||
|         "unableToAccess": "원격저장소에 접근할 수 없습니다", | ||||
|         "retry": "재시도", | ||||
|         "setUpstreamBranch": "업스트림 브랜치로 설정", | ||||
|         "createRemoteBranchPlaceholder": "리모드 브랜치 찾기/생성", | ||||
|         "trackedUpstreamBranch": "생성된 브랜치는 트래킹된 업스트림 브랜치로 설정됩니다", | ||||
|         "selectUpstreamBranch": "브랜치가 생성될 것입니다. 트래킹된 업스트림 브랜치로 설정하세요", | ||||
|         "pushFailed": "리모트에 최신 커밋이 있기 때문에 push할 수 없습니다. 먼저 pull과 병합을 하신 후 push하세요", | ||||
|         "push": "push", | ||||
|         "pull": "pull", | ||||
|         "unablePull": "<p>원격저장소의 변경사항을 가져올 수 없습니다, 당신의 unstaged 로컬 변경사항을 덮어씁니다.</p><p>변경사항을 적용하고 다시 시도하세요</p>", | ||||
|         "showUnstagedChanges": "unstaged 변경사항 보여주기", | ||||
|         "connectionFailed": "원격저장소 연결 불가 : ", | ||||
|         "pullUnrelatedHistory": "<p>원격저장소에 연관없는 커밋 기록이 있습니다.</p><p>모든 변경사항을 로컬 저장소로 가져 오시겠습니까?</p>", | ||||
|         "pullChanges": "Pull 변경사항", | ||||
|         "history": "이력", | ||||
|         "projectHistory": "프로젝트 이력", | ||||
|         "daysAgo": "__count__일 전", | ||||
|         "daysAgo_plural": "__count__일 전", | ||||
|         "hoursAgo": "__count__시간 전", | ||||
|         "hoursAgo_plural": "__count__시간 전", | ||||
|         "minsAgo": "__count__분 전", | ||||
|         "minsAgo_plural": "__count__분 전", | ||||
|         "secondsAgo": "몇초 전", | ||||
|         "notTracking": "당신의 로컬 브랜치는 원격브랜치를 트래킹하고 있지 않습니다", | ||||
|         "statusUnmergedChanged": "당신의 저장소는 병합되지 않은 변경사항을 가지고 있습니다. 충돌을 수정하고 결과를 커밋하세요", | ||||
|         "repositoryUpToDate": "당신의 저장소는 최신상태 입니다", | ||||
|         "commitsAhead": "당신의 저장소가 원격지보다 __count__ 커밋을 앞서 있습니다. 이제 커밋 할 수 있습니다.", | ||||
|         "commitsAhead_plural": "당신의 저장소가 원격지보다  __count__ 커밋을 앞서 있습니다. 지금 커밋할 수 있습니다.", | ||||
|         "commitsBehind": "당신의 저장소가 원격지보다 __count__ 커밋이 늦습니다. 이제 pull 할 수 있습니다.", | ||||
|         "commitsBehind_plural": "당신의 저장소가 원격지보다 __count__ 커밋이 늦습니다. 이제 pull 할 수 있습니다.", | ||||
|         "commitsAheadAndBehind1": "당신의 저장소가 __count__ 커밋이 늦고, ", | ||||
|         "commitsAheadAndBehind1_plural": "당신의 저장소가 __count__ 커밋이 늦고 ", | ||||
|         "commitsAheadAndBehind2": "__count__ 커밋이 원격지보다 앞서 있습니다. ", | ||||
|         "commitsAheadAndBehind2_plural": "__count__ 커밋이 원격지보다 앞서 있습니다.", | ||||
|         "commitsAheadAndBehind3": "push하기전에 리모트 저장소에서 pull을 먼저 수행하세요.", | ||||
|         "commitsAheadAndBehind3_plural": "push하기전에 리모트 저장소에서 pull을 먼저 수행하세요.", | ||||
|         "refreshCommitHistory": "커밋 기록 새로고침", | ||||
|         "refreshChanges": "변경사항 새로고침" | ||||
|       } | ||||
|     } | ||||
|   }, | ||||
|   "typedInput": { | ||||
|     "type": { | ||||
|       "str": "string", | ||||
|       "num": "number", | ||||
|       "re": "regular expression", | ||||
|       "bool": "boolean", | ||||
|       "json": "JSON", | ||||
|       "bin": "buffer", | ||||
|       "date": "timestamp", | ||||
|       "jsonata": "expression", | ||||
|       "env": "env variable" | ||||
|     } | ||||
|   }, | ||||
|   "editableList": { | ||||
|     "add": "추가" | ||||
|   }, | ||||
|   "search": { | ||||
|     "empty": "결과 없음", | ||||
|     "addNode": "노드 추가 ..." | ||||
|   }, | ||||
|   "expressionEditor": { | ||||
|     "functions": "기능", | ||||
|     "functionReference": "기능 참조", | ||||
|     "insert": "삽입", | ||||
|     "title": "JSONata 형식 에디터", | ||||
|     "test": "테스트", | ||||
|     "data": "예제 메세지", | ||||
|     "result": "결과", | ||||
|     "format": "형식", | ||||
|     "compatMode": "호환모드 사용", | ||||
|     "compatModeDesc": "<h3>JSONata호환 모드</h3><p> 입력된 형식은 <code>msg</code> 를 참조하고 있어, 호환모드로 평가합니다. 이 모드는 후에 폐지될 예정이니, <code>msg</code> 를 사용하지 않도록 해 주시길 바랍니다. </p><p> JSONata를 Node-RED에서 처음 지원했을 때에는 <code>msg</code> 오브젝트의 참조가 필요했습니다. 예를 들어 <code>msg.payload</code> 는 payload를 참고하기 위해 사용되었습니다. </p><p> 직접 메시지에 대하여 식을 평가하도록 되었기에, 이 형식은 사용할 수 없게 됩니다. payload를 참조하려면 단순히 <code>payload</code> 로 지정해 주십시오. </p>", | ||||
|     "noMatch": "결과 없음", | ||||
|     "errors": { | ||||
|       "invalid-expr": "유효하지 않은 JSONata 형식 :\n  __message__", | ||||
|       "invalid-msg": "유효하지 않은  예시 JSON 메세지 :\n  __message__", | ||||
|       "context-unsupported": "컨텍스트 기능을 테스트 할 수 없습니다.\n $flowContext 또는 $globalContext", | ||||
|       "eval": "형식 오류 :\n  __message__" | ||||
|     } | ||||
|   }, | ||||
|   "jsEditor": { | ||||
|     "title": "자바스크립트 에디터" | ||||
|   }, | ||||
|   "jsonEditor": { | ||||
|     "title": "JSON 에디터", | ||||
|     "format": "JSON 형식" | ||||
|   }, | ||||
|   "markdownEditor": { | ||||
|     "title": "Markdown 에디터", | ||||
|     "format": "Markdown 형식", | ||||
|     "heading1": "제목 레벨1", | ||||
|     "heading2": "제목 레벨2", | ||||
|     "heading3": "제목 레벨3", | ||||
|     "bold": "강조", | ||||
|     "italic": "이탤릭", | ||||
|     "code": "코드", | ||||
|     "ordered-list": "번호 목차", | ||||
|     "unordered-list": "목차", | ||||
|     "quote": "인용", | ||||
|     "link": "링크", | ||||
|     "horizontal-rule": "나눔줄", | ||||
|     "toggle-preview": "미리보기 전환" | ||||
|   }, | ||||
|   "bufferEditor": { | ||||
|     "title": "Buffer 에디터", | ||||
|     "modeString": "UTF-8 문자열로 처리", | ||||
|     "modeArray": "JSON 배열로 처리", | ||||
|     "modeDesc": "<h3>Buffer 에디터</h3><p>버퍼타입은 byet값의 JSON배열로 저장됩니다. 이 에디터는 입력된 값을 JSON 배열로 구문분석 합니다. 만약 유효한 JSON이 아닌경우 UTF-8 문자열로 처리되어 각 문자코드 번호의 배열로 변환됩니다.</p><p>예를들어 <code>Hello World</code> 라는 값은 다음의 JSON 배열로 변환됩니다.<pre>[72, 101, 108, 108, 111, 32, 87, 111, 114, 108, 100]</pre></p>" | ||||
|   }, | ||||
|   "projects": { | ||||
|     "config-git": "Git client 설정", | ||||
|     "welcome": { | ||||
|       "hello": "안녕하세요. Node-RED에서 프로젝트 기능을 이용할 수 있게 되었습니다.", | ||||
|       "desc0": "플로우 파일을 관리하는 새로운 방법이며, 버전을 관리할 수 도 있습니다.", | ||||
|       "desc1": "무선 프로젝트를 작성하거나 기존의 Git저장소에서 프로젝트를 복제할 수 있습니다.", | ||||
|       "desc2": "이 기능을 건너뛰어도 상관없습니다. 언제든지 프로젝트 메뉴에서 첫번째 프로젝트를 만들 수 있습니다.", | ||||
|       "create": "프로젝트 생성", | ||||
|       "clone": "프로젝트 복제", | ||||
|       "not-right-now": "나중에" | ||||
|     }, | ||||
|     "git-config": { | ||||
|       "setup": "버전관리 클라이언트를 설정합니다", | ||||
|       "desc0": "Node-RED는 오픈소스 Git로 버전관리를 할 수 있습니다. 프로젝트 파일의 변경사항을 추적하고 원격저장소로 push할 수 있습니다.", | ||||
|       "desc1": "당신이 변경사항을 커밋하면 git은 누가 변경사항을 만들었는지 사용자명과 이메일 정보를 기록합니다. 사용자명은 꼭 당신의 실명일 필요는 없습니다.", | ||||
|       "desc2": "당신의 Git 클라이언트는 아래와 같이 이미 설정되었습니다.", | ||||
|       "desc3": "당신은 git config의 설정탭에서 설정을 변경할 수 있습니다.", | ||||
|       "username": "사용자명", | ||||
|       "email": "이메일" | ||||
|     }, | ||||
|     "project-details": { | ||||
|       "create": "프로젝트 생성", | ||||
|       "desc0": "프로젝트는 Git 저장소로 관리되어집니다. 다른 사람과 협업하거나 공유하기 쉬워집니다.", | ||||
|       "desc1": "당신은 여러 개의 프로젝트를 생성할 수 있고 에디터에서 프로젝트를 선택할 수 있습니다.", | ||||
|       "desc2": "시작하려면 프로젝트 이름과 프로젝트의 상세설명이 필요합니다.", | ||||
|       "already-exists": "프로젝트가 이미 존재합니다", | ||||
|       "must-contain": "A-Z 0-9 _ -의 문자만 사용이 가능합니다", | ||||
|       "project-name": "프로젝트명", | ||||
|       "desc": "상세설명", | ||||
|       "opt": "옵션" | ||||
|     }, | ||||
|     "clone-project": { | ||||
|       "clone": "프로젝트 복제", | ||||
|       "desc0": "프로젝트가 있는 저장소를 가지고 있다면, 즉시 복제하여 사용할 수 있습니다.", | ||||
|       "already-exists": "프로젝트가 이미 존재합니다", | ||||
|       "must-contain": "A-Z 0-9 _ -의 문자만 사용이 가능합니다", | ||||
|       "project-name": "프로젝트명", | ||||
|       "no-info-in-url": "URL안에 사용자아이디/비밀번호를 사용하지 마세요", | ||||
|       "git-url": "Git 저장소 URL", | ||||
|       "protocols": "https://, ssh:// 혹은 file://", | ||||
|       "auth-failed": "인증 실패", | ||||
|       "username": "사용자명", | ||||
|       "passwd": "패스워드", | ||||
|       "ssh-key": "SSH키", | ||||
|       "passphrase": "패스워드", | ||||
|       "ssh-key-desc": "저장소를 복제하기 전에 접속을 위해 SSH키를 먼저 추가하세요.", | ||||
|       "ssh-key-add": "ssh키 추가", | ||||
|       "credential-key": "인증 암호화 키", | ||||
|       "cant-get-ssh-key": "에러! 선택한 SSH키 경로를 가져올 수 없습니다", | ||||
|       "already-exists2": "이미 존재합니다", | ||||
|       "git-error": "git 에러", | ||||
|       "connection-failed": "접속 실패", | ||||
|       "not-git-repo": "Git저장소가 아닙니다", | ||||
|       "repo-not-found": "저장소가 없습니다" | ||||
|     }, | ||||
|     "default-files": { | ||||
|       "create": "프로젝트 파일 생성", | ||||
|       "desc0": "프로젝트는 당신의 플로우, README, package.json 파일을 포함합니다.", | ||||
|       "desc1": "Git 저장소에서 관리하고 싶은 다른 파일들을 포함할 수 있습니다.", | ||||
|       "desc2": "당신이 이미 가지고 있는 flow, 자격증명파일이 프로젝트로 복사될 것입니다.", | ||||
|       "flow-file": "플로우 파일", | ||||
|       "credentials-file": "자격증명 파일" | ||||
|     }, | ||||
|     "encryption-config": { | ||||
|       "setup": "자격인증 파일의 암호화 설정", | ||||
|       "desc0": "플로우의 자격인증 파일 암호화를 통해 내용을 안전하게 유지할 수 있습니다.", | ||||
|       "desc1": "자격증명을 공용 Git저장소에 저장하려면 비밀키 구문을 제공하여 암호화 해야 합니다", | ||||
|       "desc2": "당신의 플로우 자격인증 파일은 암호화 되어 있지 않습니다.", | ||||
|       "desc3": "즉, 암호 및 액세스 토큰과 같은 내용을 파일에 액세스 할 수있는 모든 사람이 열람할 수 있습니다.", | ||||
|       "desc4": "자격증명을 공용 Git저장소에 저장하려면 비밀키 구문을 제공하여 암호화 해야 합니다", | ||||
|       "desc5": "당신의 플로우 자격증명파일은 setting파일의 credentialSecret속성으로 암호화되어 있습니다.", | ||||
|       "desc6": "당신의 플로우 자격증명파일은 시스템이 생성된 키에 의해 암호화 되어있습니다. 이 프로젝트용 새로운 비밀키를 지정해 주세요.", | ||||
|       "desc7": "키는 프로젝트파일과는 별개로 보존됩니다. 다른 Node-RED에서 이 프로젝트를 이용하려면 이 프로젝트의 키가 필요합니다.", | ||||
|       "credentials": "자격인증", | ||||
|       "enable": "암호화 활성화", | ||||
|       "disable": "암호화 비활성화", | ||||
|       "disabled": "비활성화됨", | ||||
|       "copy": "기존 키를 복사", | ||||
|       "use-custom": "커스텀키 사용", | ||||
|       "desc8": "자격증명 파일이 암호화되어 있지 않아, 간단히 해당내용이 열람될 수 있습니다.", | ||||
|       "create-project-files": "프로젝트 생성", | ||||
|       "create-project": "프로젝트 생성", | ||||
|       "already-exists": "이미 존재합니다.", | ||||
|       "git-error": "git 에러", | ||||
|       "git-auth-error": "git 인증 에러" | ||||
|     }, | ||||
|     "create-success": { | ||||
|       "success": "당신의 첫번째 프로젝트 생성이 성공하였습니다.", | ||||
|       "desc0": "앞으로 이와 같이 Node-RED를 사용할 수 있습니다.", | ||||
|       "desc1": "사이드바의 '정보'탭은 현재 활성화된 프로젝트를 보여줍니다. 이름 옆에 있는 버틀을 사용하여 프로젝트 설정화면을 불러올 수 있습니다.", | ||||
|       "desc2": "사이드바의 '이력'탭은 프로젝트의 변경된 파일을 확인하고 커밋할 수 있습니다. 커밋의 전체 기록을 보여주고 변경사항을 원격 저장소에 push할 수 있습니다." | ||||
|     }, | ||||
|     "create": { | ||||
|       "projects": "프로젝트", | ||||
|       "already-exists": "프로젝트가 이미 존재합니다", | ||||
|       "must-contain": "A-Z 0-9 _ -의 문자만 사용이 가능합니다", | ||||
|       "no-info-in-url": "URL안에 사용자아이디/비밀번호를 사용하지 마세요", | ||||
|       "open": "프로젝트 열기", | ||||
|       "create": "프로젝트 생성", | ||||
|       "clone": "프로젝트 복제", | ||||
|       "project-name": "프로젝트명", | ||||
|       "desc": "상세내역", | ||||
|       "opt": "옵션", | ||||
|       "flow-file": "플로우 파일", | ||||
|       "credentials": "자격증명", | ||||
|       "enable-encryption": "암호화 활성화", | ||||
|       "disable-encryption": "암호화 비활성화", | ||||
|       "encryption-key": "암호화 키", | ||||
|       "desc0": "자격증명 정보를 안전하게 하는 문구", | ||||
|       "desc1": "자격증명 파일이 암호화되어 있지 않아, 간단히 해당내용이 열람될 수 있습니다.", | ||||
|       "git-url": "Git 저장소 URL", | ||||
|       "protocols": "https://, ssh:// 혹은 file://", | ||||
|       "auth-failed": "인증 실패", | ||||
|       "username": "사용자명", | ||||
|       "password": "패스워드", | ||||
|       "ssh-key": "SSH키", | ||||
|       "passphrase": "패스워드", | ||||
|       "desc2": "저장소를 복제하기 전에 접속을 위해 SSH키를 먼저 추가하세요.", | ||||
|       "add-ssh-key": "ssh키 추가", | ||||
|       "credentials-encryption-key": "자격인증 암호화 키", | ||||
|       "already-exists-2": "이미 존재합니다", | ||||
|       "git-error": "git 에러", | ||||
|       "con-failed": "접속 실패", | ||||
|       "not-git": "git 저장소가 아닙니다", | ||||
|       "no-resource": "저장소아 없습니다", | ||||
|       "cant-get-ssh-key-path": "에러! 선택한 SSH키 경로를 가져올 수 없습니다.", | ||||
|       "unexpected_error": "예기치 않은 에러" | ||||
|     }, | ||||
|     "delete": { | ||||
|       "confirm": "프로젝트를 정말 지우시겠습니까?" | ||||
|     }, | ||||
|     "create-project-list": { | ||||
|       "search": "프로젝트 검색", | ||||
|       "current": "현재" | ||||
|     }, | ||||
|     "require-clean": { | ||||
|       "confirm": "<p>변경사항을 배포하지 않아 내용이 손실될 수 있습니다.</p><p>계속 할까요?</p>" | ||||
|     }, | ||||
|     "send-req": { | ||||
|       "auth-req": "저장소에 대한 인증이 필요합니다.", | ||||
|       "username": "사용자명", | ||||
|       "password": "패스워드", | ||||
|       "passphrase": "패스워드", | ||||
|       "retry": "재시도", | ||||
|       "update-failed": "인증 변경 실패", | ||||
|       "unhandled": "오류 응답 미처리" | ||||
|     }, | ||||
|     "create-branch-list": { | ||||
|       "invalid": "올바르지 않은 브랜치", | ||||
|       "create": "브랜치 생성", | ||||
|       "current": "현재" | ||||
|     }, | ||||
|     "create-default-file-set": { | ||||
|       "no-active": "활성화된 프로젝트 없이 기본 파일을 만들 수 없습니다.", | ||||
|       "no-empty": "비어있지 않은 프로젝트에 기본 파일을 만들 수 없습니다.", | ||||
|       "git-error": "git 에러" | ||||
|     }, | ||||
|     "errors": { | ||||
|       "no-username-email": "당신의 Git 클라이언트에 사용자명/이메일이 설정되지 않았습니다.", | ||||
|       "unexpected": "예기치 않은 에러가 발생했습니다.", | ||||
|       "code": "코드" | ||||
|     } | ||||
|   }, | ||||
|   "editor-tab": { | ||||
|     "properties": "속성", | ||||
|     "description": "상세 내역", | ||||
|     "appearance": "모양" | ||||
|   } | ||||
| } | ||||
							
								
								
									
										23
									
								
								packages/node_modules/@node-red/editor-client/locales/ko/infotips.json
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						| @@ -0,0 +1,23 @@ | ||||
| { | ||||
|     "info": { | ||||
|         "tip0": "{{core:delete-selection}}를 사용하여 선택된 노드나 링크를 삭제할 수 있습니다.", | ||||
|         "tip1": "{{core:search}}를 활용하여 노드를 검색할 수 있습니다.", | ||||
|         "tip2": "{{core:toggle-sidebar}}를 사용하여 사이드바를 표시/비표시 전환 할 수 있습니다.", | ||||
|         "tip3": "{{core:manage-palette}}를 사용하여 노드 팔레트를 관리 할 수 있습니다.", | ||||
|         "tip4": "플로우 안의 설정노드가 사이드바에 표시됩니다. 메뉴 혹은 {{core:show-config-tab}}를 사용하여 엑세스 할 수 있습니다.", | ||||
|         "tip5": "설정에서 이 팁을 활성화/비활성화 할 수 있습니다.", | ||||
|         "tip6": "[left] [up] [down] [right] 키를 사용하여 선택된 노드를 움직일 수 있습니다. [shift]키를 누른 채로 움직이면 이동폭이 늘어납니다.", | ||||
|         "tip7": "노드를 와이어 사이로 드래그 하여 연결할 수도 있습니다.", | ||||
|         "tip8": "{{core:show-export-dialog}}를 사용하여 선택한 노드 또는 현재탭을 내보낼 수 있습니다.", | ||||
|         "tip9": "JSON파일을 에디터로 드래그하거나 {{core:show-import-dialog}}를 사용하여 플로우 가져올 수 있습니다.", | ||||
|         "tip10": "[shift] [click] 하고서 드래그하여 선택한 와이어를 이동할 수 있습니다.", | ||||
|         "tip11": "{{core:show-info-tab}}를 사용하여 정보탭을 표시하거나 {{core:show-debug-tab}}를 사용하여 디버그탭을 표시할 수 있습니다.", | ||||
|         "tip12": "작업공간에서 [ctrl] [click]을 사용하여 빠른추가 대회상자를 열 수 있습니다.", | ||||
|         "tip13": "[ctrl]을 누른 상태로 노드의 포트를 클릭하여 빠르게 연결할 수 있습니다.", | ||||
|         "tip14": "[shift]를 누른 상태로 노드를 클릭하여 연결된 모든 노드를 선택할 수 있습니다.", | ||||
|         "tip15": "[ctrl]을 누른 상태로 노드를 클릭하여 현재 선택영역에 노드를 추가/제거 할 수 있습니다.", | ||||
|         "tip16": "{{core:show-previous-tab}}와 {{core:show-next-tab}}를 사용하여 탭을 전환할 수 있습니다.", | ||||
|         "tip17": "노드 편집 창에서 {{core : confirm-edit-tray}}로 변경 사항을 확인하거나 {{core : cancel-edit-tray}}로 취소 할 수 있습니다.", | ||||
|         "tip18": "{{core : edit-selected-node}}를 누르면 현재 선택 영역의 첫 번째 노드가 편집됩니다." | ||||
|     } | ||||
| } | ||||
							
								
								
									
										222
									
								
								packages/node_modules/@node-red/editor-client/locales/ko/jsonata.json
									
									
									
									
										vendored
									
									
										Executable file
									
								
							
							
						
						| @@ -0,0 +1,222 @@ | ||||
| { | ||||
|     "$string": { | ||||
|         "args": "arg", | ||||
|         "desc": "다음과 같은 규칙을 사용하여 인수 *arg*를 문자열로 변환합니다. \n\n - 문자열은 변경되지 않습니다. \n - 함수는 빈 문자열로 변환됩니다. \n - 무한대와 NaN은 JSON수치로 표현할 수 없기 때문에 오류처리 됩니다. \n - 다른 모든 값은 `JSON.stringify` 함수를 사용하여 JSON 문자열로 변환됩니다." | ||||
|     }, | ||||
|     "$length": { | ||||
|         "args": "str", | ||||
|         "desc": "문자열 `str`의 문자 수를 반환합니다. `str`가 문자열이 아닌 경우 에러를 반환합니다." | ||||
|     }, | ||||
|     "$substring": { | ||||
|         "args": "str, start[, length]", | ||||
|         "desc": "(zero-offset)의 `start`에서 시작하는 첫번째 인수 `str`의 문자열을 반환합니다. 만약 `length`가 지정된 경우, 부분 문자열은 최대 `length`의 크기를 갖습니다. 만약 `start` 인수가 음수이면 `str`의 끝에서부터의 문자수를 나타냅니다." | ||||
|     }, | ||||
|     "$substringBefore": { | ||||
|         "args": "str, chars", | ||||
|         "desc": "`str`에 `chars`문자가 처음으로 나오기 전까지의 부분문자열을 반환합니다. 만약 `chars`가 없으면 `str`을 반환합니다." | ||||
|     }, | ||||
|     "$substringAfter": { | ||||
|         "args": "str, chars", | ||||
|         "desc": "`str`에 `chars`문자가 처음으로 나온 이후의 부분문자열을 반환합니다. 만약 `chars`가 없으면 `str`을 반환합니다." | ||||
|     }, | ||||
|     "$uppercase": { | ||||
|         "args": "str", | ||||
|         "desc": "`str`의 문자를 대문자로 반환합니다." | ||||
|     }, | ||||
|     "$lowercase": { | ||||
|         "args": "str", | ||||
|         "desc": "`str`의 문자를 소문자로 반환합니다." | ||||
|     }, | ||||
|     "$trim": { | ||||
|         "args": "str", | ||||
|         "desc": "다음의 순서대로 `str`의 모든 공백을 자르고 정규화 합니다:\n\n - 모든 탭, 캐리지 리턴 및 줄 바꿈은 공백으로 대체됩니다. \n- 연속된 공백은 하나로 줄입니다.\n- 후행 및 선행 공백은 삭제됩니다.\n\n 만일 `str`이 지정되지 않으면 (예: 이 함수를 인수없이 호출), context값을 `str`의 값으로 사용합니다. `str`이 문자열이 아니면 에러가 발생합니다." | ||||
|     }, | ||||
|     "$contains": { | ||||
|         "args": "str, pattern", | ||||
|         "desc": "`str`이 `pattern`과 일치하면 `true`를, 일치하지 않으면 `false`를 반환합니다. 만약 `str`이 지정되지 않으면 (예: 이 함수를 인수없이 호출), context값을 `str`의 값으로 사용합니다. `pattern` 인수는 문자열이나 정규표현으로 할 수 있습니다." | ||||
|     }, | ||||
|     "$split": { | ||||
|         "args": "str[, separator][, limit]", | ||||
|         "desc": "`str`인수를 분할하여 부분문자열로 배열합니다. `str`이 문자열이 아니면 에러가 발생합니다. 생략가능한 인수 `separator`는 `str`을 분할하는 문자를 문자열 또는 정규표현으로 지정합니다. `separator`를 지정하지 않은 경우, 공백의 문자열로 간주하여 `str`은 단일 문자의 배열로 분리됩니다. `separator`가 문자열이 아니면 에러가 발생합니다. 생략가능한 인수 'limit`는 결과의 배열이 갖는 부분문자열의 최대수를 지정합니다. 이 수를 넘는 부분문자열은 파기됩니다. `limit`가 지정되지 않으면`str`은 결과 배열의 크기의 제한없이 완전히 분리됩니다. `limit`이 음수인 경우 에러가 발생합니다." | ||||
|     }, | ||||
|     "$join": { | ||||
|         "args": "array[, separator]", | ||||
|         "desc": "문자열의 배열을 생략가능한 인수 `separator`로 구분한 하나의 문자열로 연결합니다. 배열 `array`가 문자열이 아닌 요소를 포함하는 경우, 에러가 발생합니다. `separator`를 지정하지 않은 경우, 공백의 문자열로 간주합니다(예: 문자열간의 `separator`없음). `separator`가 문자열이 아닌 경우, 에러가 발생합니다." | ||||
|     }, | ||||
|     "$match": { | ||||
|         "args": "str, pattern [, limit]", | ||||
|         "desc": "`str`문자열에 `pattern`를 적용하여, 오브젝트 배열을 반환합니다. 배열요소의 오브젝트는 `str`중 일치하는 부분의 정보를 보유합니다." | ||||
|     }, | ||||
|     "$replace": { | ||||
|         "args": "str, pattern, replacement [, limit]", | ||||
|         "desc": "`str`문자열에서 `pattern` 패턴을 검색하여, `replacement`로 대체합니다.\n\n임의이ㅡ 인수 `limit`는 대체 횟수의 상한값을 지정합니다." | ||||
|     }, | ||||
|     "$now": { | ||||
|         "args": "", | ||||
|         "desc": "ISO 8601 호환 형식으로 타임 스탬프를 생성하고 이를 문자열로 반환합니다." | ||||
|     }, | ||||
|     "$base64encode": { | ||||
|         "args": "string", | ||||
|         "desc": "ASCII 문자열을 base 64 표현으로 변환합니다. 문자열의 각 문자는 이진 데이터의 바이트로 처리됩니다. 이렇게 하려면 문자열의 모든 문자가 URI로 인코딩 된 문자열을 포함하고, 0x00에서 0xFF 범위에 있어야합니다. 해당 범위를 벗어난 유니 코드 문자는 지원되지 않습니다" | ||||
|     }, | ||||
|     "$base64decode": { | ||||
|         "args": "string", | ||||
|         "desc": "UTF-8코드페이지를 이용하여, Base 64형식의 바이트값을 문자열로 변환합니다." | ||||
|     }, | ||||
|     "$number": { | ||||
|         "args": "arg", | ||||
|         "desc": "`arg`를 다음과 같은 규칙을 사요하여 숫자로 변환합니다. :\n\n - 숫자는 변경되지 않습니다.\n – 올바른 JSON의 숫자는 숫자 그대로 변환됩니다.\n – 그 외의 형식은 에러를 발생합니다." | ||||
|     }, | ||||
|     "$abs": { | ||||
|         "args": "number", | ||||
|         "desc": "`number`의 절대값을 반환합니다." | ||||
|     }, | ||||
|     "$floor": { | ||||
|         "args": "number", | ||||
|         "desc": "`number`를 `number`보다 같거나 작은 정수로 내림하여 반환합니다." | ||||
|     }, | ||||
|     "$ceil": { | ||||
|         "args": "number", | ||||
|         "desc": "`number`를 `number`와 같거나 큰 정수로 올림하여 반환합니다." | ||||
|     }, | ||||
|     "$round": { | ||||
|         "args": "number [, precision]", | ||||
|         "desc": "인수 `number`를 반올림한 값을 반환합니다. 임의의 인수 `precision`에는 반올립에서 사용할 소수점이하의 자릿수를 지정합니다." | ||||
|     }, | ||||
|     "$power": { | ||||
|         "args": "base, exponent", | ||||
|         "desc": "기수 `base`의 값을 지수 `exponent`만큼의 거듭 제곱으로 반환합니다." | ||||
|     }, | ||||
|     "$sqrt": { | ||||
|         "args": "number", | ||||
|         "desc": "인수 `number`의 제곱근을 반환합니다." | ||||
|     }, | ||||
|     "$random": { | ||||
|         "args": "", | ||||
|         "desc": "0이상 1미만의 의사난수를 반환합니다." | ||||
|     }, | ||||
|     "$millis": { | ||||
|         "args": "", | ||||
|         "desc": "Unix Epoch (1970 년 1 월 1 일 UTC)부터 경과된 밀리 초 수를 숫자로 반환합니다. 평가대상식에 포함되는 $millis()의 모든 호출은 모두 같은 값을 반환합니다." | ||||
|     }, | ||||
|     "$sum": { | ||||
|         "args": "array", | ||||
|         "desc": "숫자 배열 `array`의 합계를 반환합니다. `array`에 숫자가 아닌 요소가 있는 경우, 에러가 발생합니다." | ||||
|     }, | ||||
|     "$max": { | ||||
|         "args": "array", | ||||
|         "desc": "숫자 배열 `array`에서 최대값을 반환합니다. `array`에 숫자가 아닌 요소가 있는 경우, 에러가 발생합니다." | ||||
|     }, | ||||
|     "$min": { | ||||
|         "args": "array", | ||||
|         "desc": "숫자 배열 `array`에서 최소값을 반환합니다. `array`에 숫자가 아닌 요소가 있는 경우, 에러가 발생합니다." | ||||
|     }, | ||||
|     "$average": { | ||||
|         "args": "array", | ||||
|         "desc": "숫자 배열 `array`에서 평균값을 반환합니다. `array`에 숫자가 아닌 요소가 있는 경우, 에러가 발생합니다." | ||||
|     }, | ||||
|     "$boolean": { | ||||
|         "args": "arg", | ||||
|         "desc": "`arg` 값을 다음의 규칙에 의해 Boolean으로 변환합니다::\n\n - `Boolean` : 변환하지 않음\n - `string`: 비어있음 : `false`\n - `string`: 비어있지 않음 : `true`\n - `number`: `0` : `false`\n - `number`: 0이 아님 : `true`\n - `null` : `false`\n - `array`: 비어있음 : `false`\n - `array`: `true`로 변환된 요소를 가짐 : `true`\n - `array`: 모든 요소가 `false`로 변환 : `false`\n - `object`: 비어있음 : `false`\n - `object`: 비어있지 않음 : `true`\n - `function` : `false`" | ||||
|     }, | ||||
|     "$not": { | ||||
|         "args": "arg", | ||||
|         "desc": "인수의 부정을 Boolean으로 변환합니다. `arg`는 가장먼저boolean으로 변환됩니다." | ||||
|     }, | ||||
|     "$exists": { | ||||
|         "args": "arg", | ||||
|         "desc": "`arg` 식의 평가값이 존재하는 경우 `true`, 식의 평가결과가 미정의인 경우 (예: 존재하지 않는 참조필드로의 경로)는 `false`를 반환합니다." | ||||
|     }, | ||||
|     "$count": { | ||||
|         "args": "array", | ||||
|         "desc": "`array`의 요소 갯수를 반환합니다." | ||||
|     }, | ||||
|     "$append": { | ||||
|         "args": "array, array", | ||||
|         "desc": "두개의 `array`를 병합합니다." | ||||
|     }, | ||||
|     "$sort": { | ||||
|         "args": "array [, function]", | ||||
|         "desc": "배열 `array`의 모든 값을 순서대로 정렬하여 반환합니다. \n\n 비교함수 `function`을 이용하는 경우, 비교함수는 아래와 같은 두개의 인수를 가져야 합니다. \n\n `function(left,right)` \n\n 비교함수는 left와 right의 두개의 값을 비교하기에, 값을 정렬하는 처리에서 호출됩니다. 만약 요구되는 정렬에서 left값을 right값보다 뒤로 두고싶은 경우에는, 비교함수는 치환을 나타내는 Boolean형의 ``true`를, 그렇지 않은 경우에는 `false`를 반환해야 합니다." | ||||
|     }, | ||||
|     "$reverse": { | ||||
|         "args": "array", | ||||
|         "desc": "`array`에 포함된 모든 값의 순서를 역순으로 변환하여 반환합니다." | ||||
|     }, | ||||
|     "$shuffle": { | ||||
|         "args": "array", | ||||
|         "desc": "`array`에 포함된 모든 값의 순서를 랜덤으로 반환합니다." | ||||
|     }, | ||||
|     "$zip": { | ||||
|         "args": "array, ...", | ||||
|         "desc": "배열 `array1` ... arrayN`의 위치 0, 1, 2…. 의 값으로 구성된 convolved (zipped) 배열을 반환합니다." | ||||
|     }, | ||||
|     "$keys": { | ||||
|         "args": "object", | ||||
|         "desc": "`object` 키를 포함하는 배열을 반환합니다. 인수가 오브젝트의 배열이면 반환되는 배열은 모든 오브젝트에있는 모든 키의 중복되지 않은 목록이 됩니다." | ||||
|     }, | ||||
|     "$lookup": { | ||||
|         "args": "object, key", | ||||
|         "desc": "`object` 내의 `key`가 갖는 값을 반환합니다. 최초의 인수가 객체의 배열 인 경우, 배열 내의 모든 오브젝트를 검색하여, 존재하는 모든 키가 갖는 값을 반환합니다." | ||||
|     }, | ||||
|     "$spread": { | ||||
|         "args": "object", | ||||
|         "desc": "`object`의 키/값 쌍별로 각 요소가 하나인 오브젝트 배열로 분할합니다. 만일 오브젝트 배열인 경우, 배열의 결과는 각 오브젝트에서 얻은 키/값 쌍의 오브젝트를 갖습니다." | ||||
|     }, | ||||
|     "$merge": { | ||||
|         "args": "array<object>", | ||||
|         "desc": "`object`배열을 하나의 `object`로 병합합니다. 병합결과의 오브젝트는 입력배열내의 각 오브젝트의 키/값 쌍을 포함합니다. 입력 오브젝트가 같은 키를 가질경우, 반환 된 `object`에는 배열 마지막의 오브젝트의 키/값이 격납됩니다. 입력 배열이 오브젝트가 아닌 요소를 포함하는 경우, 에러가 발생합니다." | ||||
|     }, | ||||
|     "$sift": { | ||||
|         "args": "object, function", | ||||
|         "desc": "함수 `function`을 충족시키는 `object` 인수 키/값 쌍만 포함하는 오브젝트를 반환합니다. \n\n 함수 `function` 다음과 같은 인수를 가져야 합니다 : \n\n `function(value [, key [, object]])`" | ||||
|     }, | ||||
|     "$each": { | ||||
|         "args": "object, function", | ||||
|         "desc": "`object`의 각 키/값 쌍에, 함수`function`을 적용한 값의 배열을 반환합니다." | ||||
|     }, | ||||
|     "$map": { | ||||
|         "args": "array, function", | ||||
|         "desc": "`array`의 각 값에 `function`을 적용한 결과로 이루어진 배열을 반환합니다. \n\n 함수 `function`은 다음과 같은 인수를 가져야 합니다.  \n\n `function(value[, index[, array]])`" | ||||
|     }, | ||||
|     "$filter": { | ||||
|         "args": "array, function", | ||||
|         "desc": "`array`의 값중, 함수 `function`의 조건을 만족하는 값으로 이루어진 배열을 반환합니다. \n\n 함수 `function`은 다음과 같은 형식을 가져야 합니다.  \n\n `function(value[, index[, array]])`" | ||||
|     }, | ||||
|     "$reduce": { | ||||
|         "args": "array, function [, init]", | ||||
|         "desc": "배열의 각 요소값에 함수 `function`을 연속적으로 적용하여 얻어지는 집계값을 반환합니다. `function`의 적용에는 직전의 `function`의 적용결과와 요소값이 인수로 주어집니다. \n\n 함수 `function`은 인수를 두개 뽑아, 배열의 각 요소 사이에 배치하는 중치연산자처럼 작용해야 합니다. \n\n 임의의 인수 `init`에는 집약시의 초기값을 설정합니다." | ||||
|     }, | ||||
|     "$flowContext": { | ||||
|         "args": "string[, string]", | ||||
|         "desc": "플로우 컨텍스트 속성을 취득합니다." | ||||
|     }, | ||||
|     "$globalContext": { | ||||
|         "args": "string[, string]", | ||||
|         "desc": "플로우의 글로벌 컨텍스트 속성을 취득합니다." | ||||
|     }, | ||||
|     "$pad": { | ||||
|         "args": "string, width [, char]", | ||||
|         "desc": "문자수가 인수 `width`의 절대값이상이 되도록, 필요한 경우 여분의 패딩을 사용하여 `string`의 복사본을 반환합니다. \n\n `width`가 양수인 경우, 오른쪽으로 채워지고, 음수이면 왼쪽으로 채워집니다. \n\n 임의의 `char`인수에는 이 함수에서 사용할 패딩을 지정합니다. 지정하지 않는 경우에는, 기본값으로 공백을 사용합니다." | ||||
|     }, | ||||
|     "$fromMillis": { | ||||
|         "args": "number", | ||||
|         "desc": "Unix Epoch (1970 년 1 월 1 일 UTC) 이후의 밀리 초를 나타내는 숫자를 ISO 8601 형식의 타임 스탬프 문자열로 변환합니다." | ||||
|     }, | ||||
|     "$formatNumber": { | ||||
|         "args": "number, picture [, options]", | ||||
|         "desc": "`number`를 문자열로 변환하고 `picture` 문자열에 지정된 표현으로 서식을 변경합니다. \n\n 이 함수의 동작은 XPath F&O 3.1사양에 정의된 XPath/XQuery함수의 fn:format-number의 동작과 같습니다. 인수의 문자열 picture은 fn:format-number 과 같은 구문으로 수치의 서식을 정의합니다. \n\n 임의의 제3 인수 `option`은 소수점기호와 같은 기본 로케일 고유의 서식설정문자를 덮어쓰는데에 사용됩니다. 이 인수를 지정할 경우, XPath F&O 3.1사양의 수치형식에 기술되어있는 name/value 쌍을 포함하는 오브젝트여야 합니다." | ||||
|     }, | ||||
|     "$formatBase": { | ||||
|         "args": "number [, radix]", | ||||
|         "desc": "`number`를 인수 `radix`에 지정한 값을 기수로하는 문자열로 변환합니다. `radix`가 지정되지 않은 경우, 기수 10이 기본값으로 설정됩니다. `radix`에는 2~36의 값을 설정할 수 있고, 그 외의 값의 경우에는 에러가 발생합니다." | ||||
|     }, | ||||
|     "$toMillis": { | ||||
|         "args": "timestamp", | ||||
|         "desc": "ISO 8601 형식의 `timestamp`를 Unix Epoch (1970 년 1 월 1 일 UTC) 이후의 밀리 초 수로 변환합니다. 문자열이 올바른 형식이 아닌 경우 에러가 발생합니다." | ||||
|     }, | ||||
|     "$env": { | ||||
|         "args": "arg", | ||||
|         "desc": "환경변수를 값으로 반환합니다.\n\n 이 함수는 Node-RED 정의 함수입니다." | ||||
|     } | ||||
| } | ||||
| @@ -50,9 +50,6 @@ | ||||
|             "export": "导出", | ||||
|             "search": "查找流程", | ||||
|             "searchInput": "查找流程", | ||||
|             "clipboard": "剪贴板", | ||||
|             "library": "库", | ||||
|             "examples": "例子", | ||||
|             "subflows": "子流程", | ||||
|             "createSubflow": "新建子流程", | ||||
|             "selectionToSubflow": "将选择部分更改为子流程", | ||||
| @@ -100,8 +97,8 @@ | ||||
|         } | ||||
|     }, | ||||
|     "clipboard": { | ||||
|         "clipboard": "剪贴板", | ||||
|         "nodes": "节点", | ||||
|         "selectNodes": "选择上面的文本并复制到剪贴板", | ||||
|         "pasteNodes": "在这里粘贴节点", | ||||
|         "importNodes": "导入节点", | ||||
|         "exportNodes": "导出节点至剪贴板", | ||||
| @@ -237,6 +234,7 @@ | ||||
|         "managePalette": "管理面板" | ||||
|     }, | ||||
|     "library": { | ||||
|         "library": "库", | ||||
|         "openLibrary": "打开库...", | ||||
|         "saveToLibrary": "保存到库...", | ||||
|         "typeLibrary": "__type__类型库", | ||||
| @@ -247,12 +245,9 @@ | ||||
|         "savedNodes": "保存的节点", | ||||
|         "savedType": "已保存__type__", | ||||
|         "saveFailed": "保存失败: __message__", | ||||
|         "filename": "文件名", | ||||
|         "folder": "文件夹", | ||||
|         "filenamePlaceholder": "文件", | ||||
|         "fullFilenamePlaceholder": "a/b/文件", | ||||
|         "folderPlaceholder": "a/b", | ||||
|         "breadcrumb": "库" | ||||
|         "types": { | ||||
|             "examples": "例子" | ||||
|         } | ||||
|     }, | ||||
|     "palette": { | ||||
|         "noInfo": "无可用信息", | ||||
| @@ -390,8 +385,8 @@ | ||||
|             "none": "无", | ||||
|             "subflows": "子流程", | ||||
|             "flows": "流程", | ||||
|             "filterUnused": "未使用", | ||||
|             "filterAll": "所有", | ||||
|             "filterUnused": "未使用", | ||||
|             "filtered": "__count__ 个隐藏" | ||||
|         }, | ||||
|         "palette": { | ||||
|   | ||||
| @@ -1,6 +1,6 @@ | ||||
| { | ||||
|     "name": "@node-red/editor-client", | ||||
|     "version": "0.20.0-beta.4", | ||||
|     "version": "1.0.3", | ||||
|     "license": "Apache-2.0", | ||||
|     "repository": { | ||||
|         "type": "git", | ||||
|   | ||||
| Before Width: | Height: | Size: 291 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/deploy-flows-o.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="27" height="18" xmlns="http://www.w3.org/2000/svg"><g color="#000"><path fill="#fff" d="M0 5.002h10v5H0zM17 .002h10v5H17z"/><path d="M17 13.002h10v5H17z"/></g><path d="M9.5 7.502h2l4-5h2" fill="none" stroke="#fff" stroke-width="1.5"/></svg> | ||||
| After Width: | Height: | Size: 252 B | 
| Before Width: | Height: | Size: 386 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/deploy-flows.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="32" height="32" xmlns="http://www.w3.org/2000/svg"><path color="#000" fill="#8c101c" d="M0 .002h32v32H0z"/><g color="#000"><path fill="#fff" d="M2 13.002h10v5H2zM19 8.002h10v5H19z"/><path d="M19 21.002h10v5H19z"/></g><path d="M11.5 15.502h2l4-5h2" fill="none" stroke="#fff" stroke-width="1.5"/></svg> | ||||
| After Width: | Height: | Size: 312 B | 
| Before Width: | Height: | Size: 289 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/deploy-full-o.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="27" height="18" xmlns="http://www.w3.org/2000/svg"><g fill="#fff" color="#000"><path d="M0 5h10v5H0zM17 0h10v5H17zM17 13h10v5H17z"/></g><path d="M9.5 7.5h2l4-5h2" fill="none" stroke="#fff" stroke-width="1.5"/></svg> | ||||
| After Width: | Height: | Size: 227 B | 
| Before Width: | Height: | Size: 368 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/deploy-full.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="32" height="32" xmlns="http://www.w3.org/2000/svg"><path color="#000" fill="#8c101c" d="M0 0h32v32H0z"/><g fill="#fff" color="#000"><path d="M2 13h10v5H2zM19 8h10v5H19zM19 21h10v5H19z"/></g><path d="M11.5 15.5h2l4-5h2" fill="none" stroke="#fff" stroke-width="1.5"/></svg> | ||||
| After Width: | Height: | Size: 283 B | 
| Before Width: | Height: | Size: 290 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/deploy-nodes-o.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="27" height="18" xmlns="http://www.w3.org/2000/svg"><path color="#000" d="M0 5.002h10v5H0zM17 13.002h10v5H17z"/><path d="M9.5 7.502h2l4-5h2" fill="none" stroke="#000" stroke-width="1.5"/><path color="#000" fill="#fff" d="M17 .002h10v5H17z"/></svg> | ||||
| After Width: | Height: | Size: 258 B | 
| Before Width: | Height: | Size: 392 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/deploy-nodes.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="32" height="32" xmlns="http://www.w3.org/2000/svg"><path color="#000" fill="#8c101c" d="M0 .002h32v32H0z"/><path color="#000" d="M2 13.002h10v5H2zM19 21.002h10v5H19z"/><path d="M11.5 15.502h2l4-5h2" fill="none" stroke="#000" stroke-width="1.5"/><path color="#000" fill="#fff" d="M19 8.002h10v5H19z"/></svg> | ||||
| After Width: | Height: | Size: 318 B | 
| Before Width: | Height: | Size: 1015 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/deploy-reload.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="32" height="32" xmlns="http://www.w3.org/2000/svg"><g color="#000"><path fill="#8c101c" d="M0 .006h32v32H0z"/><path d="M11.81 25.429a10.02 10.02 0 0 0 4.19.914c5.562 0 10.107-4.545 10.107-10.106S21.562 6.131 16 6.131 5.895 10.676 5.895 16.237h3.368c0-3.74 2.997-6.737 6.738-6.737s6.737 2.996 6.737 6.737-2.996 6.738-6.737 6.738a6.775 6.775 0 0 1-2.533-.486l1.43-3.48-6.947 1.317 2.13 8.485z" fill="#fff" style="isolation:auto;mix-blend-mode:normal;text-decoration-color:#000;text-decoration-line:none;text-decoration-style:solid;text-indent:0;text-transform:none;white-space:normal"/></g></svg> | ||||
| After Width: | Height: | Size: 606 B | 
| Before Width: | Height: | Size: 393 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/icons/arrow-in.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="40" height="60" viewBox="0, 0, 40, 60" xmlns="http://www.w3.org/2000/svg"><path d="M18 5v12H7v26h11v12l14-25z" fill="#fff"/></svg> | ||||
| After Width: | Height: | Size: 143 B | 
| Before Width: | Height: | Size: 386 B | 
| Before Width: | Height: | Size: 386 B | 
| Before Width: | Height: | Size: 1019 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/node-red.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="46.994" height="18.006" xmlns="http://www.w3.org/2000/svg"><g stroke="#d6d6d6"><g fill="#9e3131" stroke-linejoin="round" stroke-width="3.847" transform="matrix(.25848 0 0 .2614 -63.87 -108.483)"><rect x="249.04" y="435.92" width="50.294" height="22.953" ry="6.608"/><rect x="345.63" y="416.93" width="50.294" height="22.953" ry="6.608"/><rect x="376.71" y="459.01" width="50.294" height="22.953" ry="6.608"/></g><path d="M301.04 447.43c24.406.184 7.107-18.84 42.708-19.03M374.82 470.48c-46.966.538-28.989-22.664-73.619-22.944" fill="none" stroke-width="5.771" transform="matrix(.25848 0 0 .2614 -63.87 -108.483)"/></g></svg> | ||||
| After Width: | Height: | Size: 636 B | 
| Before Width: | Height: | Size: 600 B | 
| Before Width: | Height: | Size: 410 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/subflow_tab.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="40" height="40" viewBox="0, 0, 40, 40" xmlns="http://www.w3.org/2000/svg"><path d="M25 16h7c.58 0 1-.42 1-1v-2c0-.58-.42-1-1-1h-7c-.58 0-1 .42-1 1v2c0 .58.42 1 1 1zM8 28h7c.58 0 1-.42 1-1v-2c0-.58-.42-1-1-1H8c-.58 0-1 .42-1 1v2c0 .58.42 1 1 1zm-.416 11C5.624 39 4 37.375 4 35.416V4.582C4 2.622 5.625 1 7.584 1h24.832C34.376 1 36 2.623 36 4.582v30.834C36 37.376 34.375 39 32.416 39zM32 27H19c0 2.19-1.81 4-4 4H7v4.416c0 .35.235.584.584.584h24.832c.35 0 .584-.235.584-.584v-8.417zm1-2v-6h-8c-2.19 0-4-1.81-4-4h-1c-4.333-.002-8.667.004-13 0v6h8c2.19 0 4 1.81 4 4h13zm0-16V4.582c0-.35-.235-.582-.584-.582H7.584C7.234 4 7 4.233 7 4.582v8.417c4.333.002 8.667.001 13 .001h1c0-2.19 1.81-4 4-4z" color="#000" fill="#333"/></svg> | ||||
| After Width: | Height: | Size: 732 B | 
| Before Width: | Height: | Size: 638 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/typedInput/09.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M14.16 27.38l1.555-.144c.132.731.383 1.261.755 1.591.371.33.848.494 1.429.494.497 0 .931-.114 1.303-.341.377-.228.686-.53.926-.908.24-.383.44-.899.602-1.546a8.122 8.122 0 0 0 .233-2.3 3.732 3.732 0 0 1-1.33 1.258 3.605 3.605 0 0 1-1.815.476c-1.09 0-2.013-.395-2.768-1.186s-1.133-1.834-1.133-3.128c0-1.336.393-2.411 1.178-3.226.79-.815 1.78-1.223 2.966-1.223.856 0 1.638.231 2.345.692.713.462 1.253 1.12 1.618 1.978.372.85.557 2.085.557 3.702 0 1.684-.182 3.026-.548 4.027-.365.994-.91 1.752-1.636 2.274-.719.52-1.563.781-2.534.781-1.03 0-1.872-.284-2.525-.853-.654-.576-1.046-1.381-1.178-2.418zm6.624-5.815c0-.928-.249-1.666-.746-2.21-.492-.546-1.085-.819-1.78-.819-.719 0-1.345.294-1.878.881s-.8 1.348-.8 2.283c0 .839.252 1.522.755 2.05.51.52 1.135.781 1.878.781.75 0 1.363-.26 1.843-.782.485-.527.728-1.255.728-2.184zM4.858 10.466c0-1.558.158-2.81.476-3.757.324-.952.8-1.686 1.429-2.201.635-.516 1.432-.773 2.39-.773.708 0 1.328.143 1.861.431.533.282.974.692 1.321 1.231.348.534.62 1.187.818 1.96.198.767.297 1.803.297 3.11 0 1.545-.16 2.794-.477 3.747-.317.947-.794 1.68-1.429 2.202-.629.515-1.426.773-2.39.773-1.27 0-2.268-.456-2.993-1.366-.869-1.097-1.303-2.882-1.303-5.357zm1.662 0c0 2.163.252 3.604.755 4.323.51.713 1.136 1.07 1.879 1.07.743 0 1.366-.36 1.87-1.079.508-.719.763-2.157.763-4.314 0-2.169-.255-3.61-.764-4.323-.503-.713-1.132-1.07-1.887-1.07-.743 0-1.336.315-1.78.944-.557.803-.836 2.286-.836 4.45z" fill="#444"/></svg> | ||||
| After Width: | Height: | Size: 1.5 KiB | 
| Before Width: | Height: | Size: 546 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/typedInput/az.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M13.27 29.15l6.733-8.143h-6.235V19.3h8.8v1.559l-6.69 8.09h6.892v1.707h-9.5zm4.909-10.125zM6.577 12.58q0 .827.604 1.304.605.478 1.432.478 1.007 0 1.95-.467 1.59-.774 1.59-2.534V9.824q-.349.222-.9.37-.552.15-1.082.213l-1.155.148q-1.04.138-1.56.435-.88.498-.88 1.59zM11.2 8.721q.657-.085.88-.551.127-.255.127-.732 0-.975-.7-1.41-.689-.445-1.983-.445-1.495 0-2.12.805-.35.446-.456 1.326H5.167q.053-2.1 1.357-2.916 1.315-.827 3.043-.827 2.004 0 3.255.763 1.24.764 1.24 2.375v6.542q0 .297.117.477.127.18.52.18.127 0 .286-.01.159-.021.34-.053v1.41q-.446.127-.68.16-.233.031-.636.031-.986 0-1.43-.7-.234-.37-.33-1.05-.583.764-1.675 1.326t-2.407.562q-1.58 0-2.587-.954-.996-.965-.996-2.407 0-1.58.986-2.45.986-.869 2.587-1.07zm-1.58-4.75z" fill="#444"/></svg> | ||||
| After Width: | Height: | Size: 846 B | 
| Before Width: | Height: | Size: 638 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/typedInput/bin.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M18.8 33.9c3.328 0 4.776-2.603 4.776-7.066s-1.448-7.066-4.776-7.066-4.776 2.603-4.776 7.066S15.473 33.9 18.8 33.9zm0-1.429c-2.192 0-3.073-1.781-3.073-4.522v-2.23c0-2.741.88-4.523 3.073-4.523s3.073 1.782 3.073 4.522v2.231c0 2.74-.88 4.522-3.073 4.522zm-6.306 1.194v-1.429H8.892V20.002H6.328l-3.621 3.386.959 1.038 3.445-3.21h.137v11.02H3.333v1.429zm11.2-17.7v-1.429h-3.602V2.302h-2.564l-3.621 3.386.959 1.038 3.445-3.21h.137v11.02h-3.915v1.429zM7.5 16.2c3.327 0 4.776-2.603 4.776-7.066S10.828 2.068 7.5 2.068 2.725 4.67 2.725 9.134 4.173 16.2 7.5 16.2zm0-1.429c-2.193 0-3.074-1.781-3.074-4.522V8.02c0-2.741.881-4.523 3.074-4.523s3.073 1.782 3.073 4.522v2.231c0 2.74-.881 4.522-3.073 4.522z" fill="#444"/></svg> | ||||
| After Width: | Height: | Size: 805 B | 
| Before Width: | Height: | Size: 646 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/typedInput/bool.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M9.96 21.98a5 5 0 1 1 6.11-7.917zm3.035-13.973c-5.512 0-10 4.488-10 10s4.488 9.998 10 9.998 10-4.486 10-9.998-4.488-10-10-10zm0 1.816c4.53 0 8.182 3.655 8.182 8.184s-3.652 8.182-8.182 8.182-8.181-3.653-8.181-8.182 3.652-8.184 8.181-8.184z" color="#000" fill="#444"/></svg> | ||||
| After Width: | Height: | Size: 368 B | 
| Before Width: | Height: | Size: 809 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/typedInput/env.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M14.33 27.19q2.916-.136 4.024-2.131.58-1.024.58-2.37 0-2.132-1.569-3.24-.904-.648-3.035-1.228zM8.55 10.736q0 1.688 1.108 2.643 1.125.955 3.018 1.33V6.695q-2.234.085-3.189 1.364-.937 1.279-.937 2.677zm-3.07.205q0-2.592 1.893-4.672 1.91-2.08 5.337-2.115V1.887h1.62V4.12q3.393.239 5.2 2.012 1.825 1.757 1.91 4.655h-2.984q-.119-1.296-.699-2.233-1.074-1.723-3.427-1.808v8.287q3.956 1.108 5.371 2.08 2.302 1.603 2.302 4.74 0 4.536-2.95 6.446-1.637 1.057-4.723 1.398v3.308h-1.62v-3.308q-4.962-.324-6.735-3.513-.972-1.722-.972-4.655h3.018q.136 2.336.733 3.41 1.057 1.927 3.922 2.166v-9.293q-3.683-.699-5.44-2.336Q5.48 13.84 5.48 10.941z" fill="#444"/></svg> | ||||
| After Width: | Height: | Size: 745 B | 
| Before Width: | Height: | Size: 563 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/typedInput/expr.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><g transform="translate(-337.103 -913.25) scale(1.2585)" fill="#444" stroke-width=".795"><circle cx="284.36" cy="733.68" r="1.5" color="#000" style="isolation:auto;mix-blend-mode:normal"/><circle cx="284.33" cy="740.74" r="1.5" color="#000" style="isolation:auto;mix-blend-mode:normal"/><path d="M276.18 727.78l4.396-1.565v18.515c-.711 2.606-2.922 4.394-5.812 5.812l-4.135 1.974-.559-1.192 3.353-1.639c1.459-.724 2.689-1.87 2.869-4.955z" fill-rule="evenodd"/></g></svg> | ||||
| After Width: | Height: | Size: 556 B | 
| Before Width: | Height: | Size: 588 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/typedInput/json.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M15 5.225v-1.92h2.24q.608 0 1.216.288.608.256 1.12.8.48.512.8 1.312.32.768.32 1.792v5.824q0 .832.224 1.536t.608 1.216q.352.48.832.768.48.256.992.256v2.176q-.512 0-.992.256t-.832.736q-.384.48-.608 1.184t-.224 1.568v5.792q0 1.024-.32 1.792-.32.8-.8 1.312-.512.544-1.12.8-.608.288-1.216.288H15v-1.92h1.6q.48 0 .768-.256.288-.224.48-.64.16-.384.224-.896.064-.48.064-.96v-5.824q0-1.216.352-2.016.32-.8.768-1.28.448-.512.928-.736.448-.224.736-.256v-.096q-.288-.064-.736-.32-.48-.256-.928-.768t-.768-1.28q-.352-.8-.352-1.92V7.977q0-.512-.064-.992-.064-.512-.224-.896-.192-.384-.48-.608-.288-.256-.768-.256zm-3.648 0v-1.92h-2.24q-.608 0-1.216.288-.608.256-1.12.8-.48.512-.8 1.312-.32.768-.32 1.792v5.824q0 .832-.224 1.536t-.608 1.216q-.352.48-.832.768-.48.256-.992.256v2.176q.512 0 .992.256t.832.736q.384.48.608 1.184t.224 1.568v5.792q0 1.024.32 1.792.32.8.8 1.312.512.544 1.12.8.608.288 1.216.288h2.24v-1.92h-1.6q-.48 0-.768-.256-.288-.224-.48-.64-.16-.384-.224-.896-.064-.48-.064-.96v-5.824q0-1.216-.352-2.016-.32-.8-.768-1.28-.448-.512-.928-.736-.448-.224-.736-.256v-.096q.288-.064.736-.32.48-.256.928-.768t.768-1.28q.352-.8.352-1.92V7.977q0-.512.064-.992.064-.512.224-.896.192-.384.48-.608.288-.256.768-.256z" fill="#444"/></svg> | ||||
| After Width: | Height: | Size: 1.3 KiB | 
| Before Width: | Height: | Size: 502 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/typedInput/re.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M2 19h5v5H2zm16.099-3.304v-5.659h-2.654v5.66l-5.309-2.004-.901 2.404L14.543 18l-3.255 4.557 2.254 1.553 3.255-4.808 3.455 4.808 2.054-1.553L19 18l5.46-1.903-1.002-2.404z" color="#000" fill="#444444"/></svg> | ||||
| After Width: | Height: | Size: 302 B | 
							
								
								
									
										1
									
								
								packages/node_modules/@node-red/editor-client/src/images/typedInput/target.svg
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1 @@ | ||||
| <svg width="26" height="36" viewBox="0, 0, 26, 36" xmlns="http://www.w3.org/2000/svg"><path d="M11 5v5.77a7.542 7.542 0 0 0-5.234 5.25L1 16c-1.432 1.397-1.232 2.722 0 4l4.75-.078a7.542 7.542 0 0 0 5.22 5.297L11 31c1.316 1.303 2.649 1.363 4 0l.009-5.775A7.542 7.542 0 0 0 20.228 20H25c1.261-1.294 1.404-2.623 0-4l-4.774-.01a7.542 7.542 0 0 0-5.23-5.22L15 5c-1.3-1.273-2.63-1.393-4 0zm2 7.499c3.05 0 5.5 2.45 5.5 5.5s-2.45 5.5-5.5 5.5-5.5-2.45-5.5-5.5 2.45-5.5 5.5-5.5z" color="#000" fill="#444"/></svg> | ||||
| After Width: | Height: | Size: 502 B | 
| @@ -143,7 +143,7 @@ RED.comms = (function() { | ||||
|                     } else { | ||||
|                         var msg = RED._("notification.errors.lostConnectionReconnect",{time: connectCountdown})+' <a href="#">'+ RED._("notification.errors.lostConnectionTry")+'</a>'; | ||||
|                         errornotification.update(msg,{silent:true}); | ||||
|                         $(errornotification).find("a").click(function(e) { | ||||
|                         $(errornotification).find("a").on("click", function(e) { | ||||
|                             e.preventDefault(); | ||||
|                             errornotification.update(RED._("notification.errors.lostConnection"),{silent:true}); | ||||
|                             clearInterval(connectCountdownTimer); | ||||
|   | ||||
| @@ -14,7 +14,8 @@ | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
| RED.history = (function() { | ||||
|     var undo_history = []; | ||||
|     var undoHistory = []; | ||||
|     var redoHistory = []; | ||||
|  | ||||
|     function undoEvent(ev) { | ||||
|         var i; | ||||
| @@ -22,52 +23,81 @@ RED.history = (function() { | ||||
|         var node; | ||||
|         var subflow; | ||||
|         var modifiedTabs = {}; | ||||
|         var inverseEv; | ||||
|         if (ev) { | ||||
|             if (ev.t == 'multi') { | ||||
|                 inverseEv = { | ||||
|                     t: 'multi', | ||||
|                     events: [] | ||||
|                 }; | ||||
|                 len = ev.events.length; | ||||
|                 for (i=len-1;i>=0;i--) { | ||||
|                     undoEvent(ev.events[i]); | ||||
|                     var r = undoEvent(ev.events[i]); | ||||
|                     inverseEv.events.push(r); | ||||
|                 } | ||||
|             } else if (ev.t == 'replace') { | ||||
|                 inverseEv = { | ||||
|                     t: 'replace', | ||||
|                     config: RED.nodes.createCompleteNodeSet(), | ||||
|                     changed: {}, | ||||
|                     rev: RED.nodes.version() | ||||
|                 }; | ||||
|                 RED.nodes.clear(); | ||||
|                 var imported = RED.nodes.import(ev.config); | ||||
|                 imported[0].forEach(function(n) { | ||||
|                     if (ev.changed[n.id]) { | ||||
|                         n.changed = true; | ||||
|                         inverseEv.changed[n.id] = true; | ||||
|                     } | ||||
|                 }) | ||||
|  | ||||
|                 RED.nodes.version(ev.rev); | ||||
|             } else if (ev.t == 'add') { | ||||
|                 inverseEv = { | ||||
|                     t: "delete", | ||||
|                 }; | ||||
|                 if (ev.nodes) { | ||||
|                     inverseEv.nodes = []; | ||||
|                     for (i=0;i<ev.nodes.length;i++) { | ||||
|                         node = RED.nodes.node(ev.nodes[i]); | ||||
|                         if (node.z) { | ||||
|                             modifiedTabs[node.z] = true; | ||||
|                         } | ||||
|                         inverseEv.nodes.push(node); | ||||
|                         RED.nodes.remove(ev.nodes[i]); | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.links) { | ||||
|                     inverseEv.links = []; | ||||
|                     for (i=0;i<ev.links.length;i++) { | ||||
|                         inverseEv.links.push(ev.links[i]); | ||||
|                         RED.nodes.removeLink(ev.links[i]); | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.workspaces) { | ||||
|                     inverseEv.workspaces = []; | ||||
|                     for (i=0;i<ev.workspaces.length;i++) { | ||||
|                         var workspaceOrder = RED.nodes.getWorkspaceOrder(); | ||||
|                         ev.workspaces[i]._index = workspaceOrder.indexOf(ev.workspaces[i].id); | ||||
|                         inverseEv.workspaces.push(ev.workspaces[i]); | ||||
|                         RED.nodes.removeWorkspace(ev.workspaces[i].id); | ||||
|                         RED.workspaces.remove(ev.workspaces[i]); | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.subflows) { | ||||
|                     inverseEv.subflows = []; | ||||
|                     for (i=0;i<ev.subflows.length;i++) { | ||||
|                         inverseEv.subflows.push(ev.subflows[i]); | ||||
|                         RED.nodes.removeSubflow(ev.subflows[i]); | ||||
|                         RED.workspaces.remove(ev.subflows[i]); | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.subflow) { | ||||
|                     inverseEv.subflow = {}; | ||||
|                     if (ev.subflow.instances) { | ||||
|                         inverseEv.subflow.instances = []; | ||||
|                         ev.subflow.instances.forEach(function(n) { | ||||
|                             inverseEv.subflow.instances.push(n); | ||||
|                             var node = RED.nodes.node(n.id); | ||||
|                             if (node) { | ||||
|                                 node.changed = n.changed; | ||||
| @@ -83,21 +113,30 @@ RED.history = (function() { | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.removedLinks) { | ||||
|                     inverseEv.createdLinks = []; | ||||
|                     for (i=0;i<ev.removedLinks.length;i++) { | ||||
|                         inverseEv.createdLinks.push(ev.removedLinks[i]); | ||||
|                         RED.nodes.addLink(ev.removedLinks[i]); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|             } else if (ev.t == "delete") { | ||||
|                 inverseEv = { | ||||
|                     t: "add" | ||||
|                 }; | ||||
|                 if (ev.workspaces) { | ||||
|                     inverseEv.workspaces = []; | ||||
|                     for (i=0;i<ev.workspaces.length;i++) { | ||||
|                         inverseEv.workspaces.push(ev.workspaces[i]); | ||||
|                         RED.nodes.addWorkspace(ev.workspaces[i],ev.workspaces[i]._index); | ||||
|                         RED.workspaces.add(ev.workspaces[i],undefined,ev.workspaces[i]._index); | ||||
|                         delete ev.workspaces[i]._index; | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.subflows) { | ||||
|                     inverseEv.subflows = []; | ||||
|                     for (i=0;i<ev.subflows.length;i++) { | ||||
|                         inverseEv.subflows.push(ev.subflows[i]); | ||||
|                         RED.nodes.addSubflow(ev.subflows[i]); | ||||
|                     } | ||||
|                 } | ||||
| @@ -125,14 +164,23 @@ RED.history = (function() { | ||||
|                         }); | ||||
|                     } | ||||
|                 } | ||||
|                 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 (ev.subflow) { | ||||
|                     inverseEv.subflow = {}; | ||||
|                     if (ev.subflow.hasOwnProperty('instances')) { | ||||
|                         inverseEv.subflow.instances = []; | ||||
|                         ev.subflow.instances.forEach(function(n) { | ||||
|                             inverseEv.subflow.instances.push(n); | ||||
|                             var node = RED.nodes.node(n.id); | ||||
|                             if (node) { | ||||
|                                 node.changed = n.changed; | ||||
|                                 node.dirty = true; | ||||
|                             } | ||||
|                         }); | ||||
|                     } | ||||
|                     if (ev.subflow.hasOwnProperty('status')) { | ||||
|                         subflow = RED.nodes.subflow(ev.subflow.id); | ||||
|                         subflow.status = ev.subflow.status; | ||||
|                     } | ||||
|                 } | ||||
|                 if (subflow) { | ||||
|                     RED.nodes.filterNodes({type:"subflow:"+subflow.id}).forEach(function(n) { | ||||
| @@ -146,14 +194,25 @@ RED.history = (function() { | ||||
|                     }); | ||||
|                 } | ||||
|                 if (ev.nodes) { | ||||
|                     inverseEv.nodes = []; | ||||
|                     for (i=0;i<ev.nodes.length;i++) { | ||||
|                         RED.nodes.add(ev.nodes[i]); | ||||
|                         modifiedTabs[ev.nodes[i].z] = true; | ||||
|                         inverseEv.nodes.push(ev.nodes[i].id); | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.links) { | ||||
|                     inverseEv.links = []; | ||||
|                     for (i=0;i<ev.links.length;i++) { | ||||
|                         RED.nodes.addLink(ev.links[i]); | ||||
|                         inverseEv.links.push(ev.links[i]); | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.createdLinks) { | ||||
|                     inverseEv.removedLinks = []; | ||||
|                     for (i=0;i<ev.createdLinks.length;i++) { | ||||
|                         inverseEv.removedLinks.push(ev.createdLinks[i]); | ||||
|                         RED.nodes.removeLink(ev.createdLinks[i]); | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.changes) { | ||||
| @@ -173,8 +232,14 @@ RED.history = (function() { | ||||
|  | ||||
|                 } | ||||
|             } else if (ev.t == "move") { | ||||
|                 inverseEv = { | ||||
|                     t: 'move', | ||||
|                     nodes: [] | ||||
|                 }; | ||||
|                 for (i=0;i<ev.nodes.length;i++) { | ||||
|                     var n = ev.nodes[i]; | ||||
|                     var rn = {n: n.n, ox: n.n.x, oy: n.n.y, dirty: true, moved: n.moved}; | ||||
|                     inverseEv.nodes.push(rn); | ||||
|                     n.n.x = n.ox; | ||||
|                     n.n.y = n.oy; | ||||
|                     n.n.dirty = true; | ||||
| @@ -182,18 +247,28 @@ RED.history = (function() { | ||||
|                 } | ||||
|                 // A move could have caused a link splice | ||||
|                 if (ev.links) { | ||||
|                     inverseEv.removedLinks = []; | ||||
|                     for (i=0;i<ev.links.length;i++) { | ||||
|                         inverseEv.removedLinks.push(ev.links[i]); | ||||
|                         RED.nodes.removeLink(ev.links[i]); | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.removedLinks) { | ||||
|                     inverseEv.links = []; | ||||
|                     for (i=0;i<ev.removedLinks.length;i++) { | ||||
|                         inverseEv.links.push(ev.removedLinks[i]); | ||||
|                         RED.nodes.addLink(ev.removedLinks[i]); | ||||
|                     } | ||||
|                 } | ||||
|             } else if (ev.t == "edit") { | ||||
|                 inverseEv = { | ||||
|                     t: "edit", | ||||
|                     changes: {} | ||||
|                 }; | ||||
|                 inverseEv.node = ev.node; | ||||
|                 for (i in ev.changes) { | ||||
|                     if (ev.changes.hasOwnProperty(i)) { | ||||
|                         inverseEv.changes[i] = ev.node[i]; | ||||
|                         if (ev.node._def.defaults && ev.node._def.defaults[i] && ev.node._def.defaults[i].type) { | ||||
|                             // This is a config node property | ||||
|                             var currentConfigNode = RED.nodes.node(ev.node[i]); | ||||
| @@ -208,23 +283,34 @@ RED.history = (function() { | ||||
|                         ev.node[i] = ev.changes[i]; | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.node.type === 'tab' && ev.changes.hasOwnProperty('disabled')) { | ||||
|                     $("#red-ui-tab-"+(ev.node.id.replace(".","-"))).toggleClass('red-ui-workspace-disabled',!!ev.node.disabled); | ||||
|                     $("#red-ui-workspace").toggleClass("red-ui-workspace-disabled",!!ev.node.disabled); | ||||
|                 } | ||||
|                 if (ev.subflow) { | ||||
|                     inverseEv.subflow = {}; | ||||
|                     if (ev.subflow.hasOwnProperty('inputCount')) { | ||||
|                         inverseEv.subflow.inputCount = ev.node.in.length; | ||||
|                         if (ev.node.in.length > ev.subflow.inputCount) { | ||||
|                             inverseEv.subflow.inputs = ev.node.in.slice(ev.subflow.inputCount); | ||||
|                             ev.node.in.splice(ev.subflow.inputCount); | ||||
|                         } else if (ev.subflow.inputs.length > 0) { | ||||
|                             ev.node.in = ev.node.in.concat(ev.subflow.inputs); | ||||
|                         } | ||||
|                     } | ||||
|                     if (ev.subflow.hasOwnProperty('outputCount')) { | ||||
|                         inverseEv.subflow.outputCount = ev.node.out.length; | ||||
|                         if (ev.node.out.length > ev.subflow.outputCount) { | ||||
|                             inverseEv.subflow.outputs = ev.node.out.slice(ev.subflow.outputCount); | ||||
|                             ev.node.out.splice(ev.subflow.outputCount); | ||||
|                         } else if (ev.subflow.outputs.length > 0) { | ||||
|                             ev.node.out = ev.node.out.concat(ev.subflow.outputs); | ||||
|                         } | ||||
|                     } | ||||
|                     if (ev.subflow.hasOwnProperty('instances')) { | ||||
|                         inverseEv.subflow.instances = []; | ||||
|                         ev.subflow.instances.forEach(function(n) { | ||||
|                             inverseEv.subflow.instances.push(n); | ||||
|                             var node = RED.nodes.node(n.id); | ||||
|                             if (node) { | ||||
|                                 node.changed = n.changed; | ||||
| @@ -232,6 +318,11 @@ RED.history = (function() { | ||||
|                             } | ||||
|                         }); | ||||
|                     } | ||||
|                     if (ev.subflow.hasOwnProperty('status')) { | ||||
|                         if (ev.subflow.status) { | ||||
|                             delete ev.node.status; | ||||
|                         } | ||||
|                     } | ||||
|                     RED.editor.validateNode(ev.node); | ||||
|                     RED.nodes.filterNodes({type:"subflow:"+ev.node.id}).forEach(function(n) { | ||||
|                         n.inputs = ev.node.in.length; | ||||
| @@ -243,9 +334,11 @@ RED.history = (function() { | ||||
|                     var outputMap; | ||||
|                     if (ev.outputMap) { | ||||
|                         outputMap = {}; | ||||
|                         inverseEv.outputMap = {}; | ||||
|                         for (var port in ev.outputMap) { | ||||
|                             if (ev.outputMap.hasOwnProperty(port) && ev.outputMap[port] !== "-1") { | ||||
|                                 outputMap[ev.outputMap[port]] = port; | ||||
|                                 inverseEv.outputMap[ev.outputMap[port]] = port; | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
| @@ -253,43 +346,112 @@ RED.history = (function() { | ||||
|                     RED.editor.validateNode(ev.node); | ||||
|                 } | ||||
|                 if (ev.links) { | ||||
|                     inverseEv.createdLinks = []; | ||||
|                     for (i=0;i<ev.links.length;i++) { | ||||
|                         RED.nodes.addLink(ev.links[i]); | ||||
|                         inverseEv.createdLinks.push(ev.links[i]); | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.createdLinks) { | ||||
|                     inverseEv.links = []; | ||||
|                     for (i=0;i<ev.createdLinks.length;i++) { | ||||
|                         RED.nodes.removeLink(ev.createdLinks[i]); | ||||
|                         inverseEv.links.push(ev.createdLinks[i]); | ||||
|                     } | ||||
|                 } | ||||
|                 ev.node.dirty = true; | ||||
|                 ev.node.changed = ev.changed; | ||||
|             } else if (ev.t == "createSubflow") { | ||||
|                 inverseEv = { | ||||
|                     t: "deleteSubflow", | ||||
|                     activeWorkspace: ev.activeWorkspace, | ||||
|                     dirty: RED.nodes.dirty() | ||||
|                 }; | ||||
|                 if (ev.nodes) { | ||||
|                     inverseEv.movedNodes = []; | ||||
|                     var z = ev.activeWorkspace; | ||||
|                     RED.nodes.filterNodes({z:ev.subflow.subflow.id}).forEach(function(n) { | ||||
|                         n.x += ev.subflow.offsetX; | ||||
|                         n.y += ev.subflow.offsetY; | ||||
|                         n.z = ev.activeWorkspace; | ||||
|                         n.dirty = true; | ||||
|                         inverseEv.movedNodes.push(n.id); | ||||
|                         RED.nodes.moveNodeToTab(n, z); | ||||
|                     }); | ||||
|                     inverseEv.subflows = []; | ||||
|                     for (i=0;i<ev.nodes.length;i++) { | ||||
|                         inverseEv.subflows.push(RED.nodes.node(ev.nodes[i])); | ||||
|                         RED.nodes.remove(ev.nodes[i]); | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.links) { | ||||
|                     inverseEv.links = []; | ||||
|                     for (i=0;i<ev.links.length;i++) { | ||||
|                         inverseEv.links.push(ev.links[i]); | ||||
|                         RED.nodes.removeLink(ev.links[i]); | ||||
|                     } | ||||
|                 } | ||||
|  | ||||
|                 inverseEv.subflow = ev.subflow; | ||||
|                 RED.nodes.removeSubflow(ev.subflow.subflow); | ||||
|                 RED.workspaces.remove(ev.subflow.subflow); | ||||
|  | ||||
|                 if (ev.removedLinks) { | ||||
|                     inverseEv.createdLinks = []; | ||||
|                     for (i=0;i<ev.removedLinks.length;i++) { | ||||
|                         inverseEv.createdLinks.push(ev.removedLinks[i]); | ||||
|                         RED.nodes.addLink(ev.removedLinks[i]); | ||||
|                     } | ||||
|                 } | ||||
|             } else if (ev.t == "deleteSubflow") { | ||||
|                 inverseEv = { | ||||
|                     t: "createSubflow", | ||||
|                     activeWorkspace: ev.activeWorkspace, | ||||
|                     dirty: RED.nodes.dirty(), | ||||
|                 }; | ||||
|                 if (ev.subflow) { | ||||
|                     RED.nodes.addSubflow(ev.subflow.subflow); | ||||
|                     inverseEv.subflow = ev.subflow; | ||||
|                 } | ||||
|                 if (ev.subflows) { | ||||
|                     inverseEv.nodes = []; | ||||
|                     for (i=0;i<ev.subflows.length;i++) { | ||||
|                         RED.nodes.add(ev.subflows[i]); | ||||
|                         inverseEv.nodes.push(ev.subflows[i].id); | ||||
|                     } | ||||
|                 } | ||||
|                 if (ev.movedNodes) { | ||||
|                     ev.movedNodes.forEach(function(nid) { | ||||
|                         nn = RED.nodes.node(nid); | ||||
|                         nn.x -= ev.subflow.offsetX; | ||||
|                         nn.y -= ev.subflow.offsetY; | ||||
|                         nn.dirty = true; | ||||
|                         RED.nodes.moveNodeToTab(nn, ev.subflow.subflow.id); | ||||
|                     }); | ||||
|                 } | ||||
|                 if (ev.links) { | ||||
|                     inverseEv.links = []; | ||||
|                     for (i=0;i<ev.links.length;i++) { | ||||
|                         inverseEv.links.push(ev.links[i]); | ||||
|                         RED.nodes.addLink(ev.links[i]); | ||||
|                     } | ||||
|                 } | ||||
|                 if  (ev.createdLinks) { | ||||
|                     inverseEv.removedLinks = []; | ||||
|                     for (i=0;i<ev.createdLinks.length;i++) { | ||||
|                         inverseEv.removedLinks.push(ev.createdLinks[i]); | ||||
|                         RED.nodes.removeLink(ev.createdLinks[i]); | ||||
|                     } | ||||
|                 } | ||||
|             } else if (ev.t == "reorder") { | ||||
|                 inverseEv = { | ||||
|                     t: 'reorder', | ||||
|                     order: RED.nodes.getWorkspaceOrder() | ||||
|                 }; | ||||
|                 if (ev.order) { | ||||
|                     RED.workspaces.order(ev.order); | ||||
|                 } | ||||
|             } | ||||
|  | ||||
|             Object.keys(modifiedTabs).forEach(function(id) { | ||||
|                 var subflow = RED.nodes.subflow(id); | ||||
|                 if (subflow) { | ||||
| @@ -303,6 +465,9 @@ RED.history = (function() { | ||||
|             RED.palette.refresh(); | ||||
|             RED.workspaces.refresh(); | ||||
|             RED.sidebar.config.refresh(); | ||||
|             RED.subflow.refresh(); | ||||
|  | ||||
|             return inverseEv; | ||||
|         } | ||||
|  | ||||
|     } | ||||
| @@ -310,28 +475,42 @@ RED.history = (function() { | ||||
|     return { | ||||
|         //TODO: this function is a placeholder until there is a 'save' event that can be listened to | ||||
|         markAllDirty: function() { | ||||
|             for (var i=0;i<undo_history.length;i++) { | ||||
|                 undo_history[i].dirty = true; | ||||
|             for (var i=0;i<undoHistory.length;i++) { | ||||
|                 undoHistory[i].dirty = true; | ||||
|             } | ||||
|         }, | ||||
|         list: function() { | ||||
|             return undo_history | ||||
|             return undoHistory; | ||||
|         }, | ||||
|         depth: function() { | ||||
|             return undo_history.length; | ||||
|             return undoHistory.length; | ||||
|         }, | ||||
|         push: function(ev) { | ||||
|             undo_history.push(ev); | ||||
|             undoHistory.push(ev); | ||||
|             redoHistory = []; | ||||
|         }, | ||||
|         pop: function() { | ||||
|             var ev = undo_history.pop(); | ||||
|             undoEvent(ev); | ||||
|             var ev = undoHistory.pop(); | ||||
|             var rev = undoEvent(ev); | ||||
|             if (rev) { | ||||
|                 redoHistory.push(rev); | ||||
|             } | ||||
|         }, | ||||
|         peek: function() { | ||||
|             return undo_history[undo_history.length-1]; | ||||
|             return undoHistory[undoHistory.length-1]; | ||||
|         }, | ||||
|         clear: function() { | ||||
|             undo_history = []; | ||||
|             undoHistory = []; | ||||
|             redoHistory = []; | ||||
|         }, | ||||
|         redo: function() { | ||||
|             var ev = redoHistory.pop(); | ||||
|             if (ev) { | ||||
|                 var uev = undoEvent(ev); | ||||
|                 if (uev) { | ||||
|                     undoHistory.push(uev); | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -21,7 +21,8 @@ RED.i18n = (function() { | ||||
|     return { | ||||
|         init: function(options, done) { | ||||
|             apiRootUrl = options.apiRootUrl||""; | ||||
|             i18n.init({ | ||||
|             var preferredLanguage = localStorage.getItem("editor-language"); | ||||
|             var opts = { | ||||
|                 resGetPath: apiRootUrl+'locales/__ns__?lng=__lng__', | ||||
|                 dynamicLoad: false, | ||||
|                 load:'current', | ||||
| @@ -32,7 +33,11 @@ RED.i18n = (function() { | ||||
|                 fallbackLng: ['en-US'], | ||||
|                 useCookie: false, | ||||
|                 returnObjectTrees: true | ||||
|             },function() { | ||||
|             }; | ||||
|             if (preferredLanguage) { | ||||
|                 opts.lng = preferredLanguage; | ||||
|             } | ||||
|             i18n.init(opts,function() { | ||||
|                 done(); | ||||
|             }); | ||||
|             RED["_"] = function() { | ||||
| @@ -45,8 +50,21 @@ RED.i18n = (function() { | ||||
|             } | ||||
|  | ||||
|         }, | ||||
|         lang: function() { | ||||
|             // Gets the active message catalog language. This is based on what | ||||
|             // locale the editor is using and what languages are available. | ||||
|             // | ||||
|             var preferredLangs = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage()); | ||||
|             var knownLangs = RED.settings.theme("languages")||["en-US"]; | ||||
|             for (var i=0;i<preferredLangs.length;i++) { | ||||
|                 if (knownLangs.indexOf(preferredLangs[i]) > -1) { | ||||
|                     return preferredLangs[i] | ||||
|                 } | ||||
|             } | ||||
|             return 'end-US' | ||||
|         }, | ||||
|         loadNodeCatalog: function(namespace,done) { | ||||
|             var languageList = i18n.functions.toLanguages(i18n.detectLanguage()); | ||||
|             var languageList = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage()); | ||||
|             var toLoad = languageList.length; | ||||
|             languageList.forEach(function(lang) { | ||||
|                 $.ajax({ | ||||
| @@ -68,7 +86,7 @@ RED.i18n = (function() { | ||||
|         }, | ||||
|  | ||||
|         loadNodeCatalogs: function(done) { | ||||
|             var languageList = i18n.functions.toLanguages(i18n.detectLanguage()); | ||||
|             var languageList = i18n.functions.toLanguages(localStorage.getItem("editor-language")||i18n.detectLanguage()); | ||||
|             var toLoad = languageList.length; | ||||
|  | ||||
|             languageList.forEach(function(lang) { | ||||
|   | ||||
| @@ -1,12 +1,14 @@ | ||||
| { | ||||
|     "*": { | ||||
|         "ctrl-shift-p":"core:manage-palette", | ||||
|         "alt-shift-p":"core:manage-palette", | ||||
|         "ctrl-f": "core:search", | ||||
|         "ctrl-shift-f": "core:list-flows", | ||||
|         "ctrl-=": "core:zoom-in", | ||||
|         "ctrl--": "core:zoom-out", | ||||
|         "ctrl-0": "core:zoom-reset", | ||||
|         "ctrl-enter": "core:confirm-edit-tray", | ||||
|         "ctrl-escape": "core:cancel-edit-tray", | ||||
|         "ctrl-d": "core:deploy-flows", | ||||
|         "ctrl-g i": "core:show-info-tab", | ||||
|         "ctrl-g d": "core:show-debug-tab", | ||||
|         "ctrl-g c": "core:show-config-tab", | ||||
| @@ -16,19 +18,22 @@ | ||||
|         "ctrl-space": "core:toggle-sidebar", | ||||
|         "ctrl-p": "core:toggle-palette", | ||||
|         "ctrl-,": "core:show-user-settings", | ||||
|         "ctrl-alt-l": "core:clear-debug-messages", | ||||
|         "ctrl-alt-r": "core:show-remote-diff", | ||||
|         "ctrl-alt-n": "core:new-project", | ||||
|         "ctrl-alt-o": "core:open-project", | ||||
|         "ctrl-g v": "core:show-version-control-tab", | ||||
|         "ctrl-shift-l": "core:show-event-log" | ||||
|         "ctrl-shift-l": "core:show-event-log", | ||||
|         "ctrl-shift-p":"core:show-action-list" | ||||
|     }, | ||||
|     "sidebar-node-config": { | ||||
|     "red-ui-sidebar-node-config": { | ||||
|         "backspace": "core:delete-config-selection", | ||||
|         "delete": "core:delete-config-selection", | ||||
|         "ctrl-a": "core:select-all-config-nodes", | ||||
|         "ctrl-z": "core:undo" | ||||
|         "ctrl-z": "core:undo", | ||||
|         "ctrl-y": "core:redo" | ||||
|     }, | ||||
|     "workspace": { | ||||
|     "red-ui-workspace": { | ||||
|         "backspace": "core:delete-selection", | ||||
|         "delete": "core:delete-selection", | ||||
|         "enter": "core:edit-selected-node", | ||||
| @@ -36,6 +41,7 @@ | ||||
|         "ctrl-x": "core:cut-selection-to-internal-clipboard", | ||||
|         "ctrl-v": "core:paste-from-internal-clipboard", | ||||
|         "ctrl-z": "core:undo", | ||||
|         "ctrl-y": "core:redo", | ||||
|         "ctrl-a": "core:select-all-nodes", | ||||
|         "shift-?": "core:show-help", | ||||
|         "up": "core:move-selection-up", | ||||
|   | ||||
| @@ -17,6 +17,8 @@ RED.nodes = (function() { | ||||
|  | ||||
|     var node_defs = {}; | ||||
|     var nodes = []; | ||||
|     var nodeTabMap = {}; | ||||
|  | ||||
|     var configNodes = {}; | ||||
|     var links = []; | ||||
|     var defaultWorkspace; | ||||
| @@ -213,6 +215,11 @@ RED.nodes = (function() { | ||||
|                 n.i = nextId+1; | ||||
|             } | ||||
|             nodes.push(n); | ||||
|             if (nodeTabMap[n.z]) { | ||||
|                 nodeTabMap[n.z][n.id] = n; | ||||
|             } else { | ||||
|                 console.warn("Node added to unknown tab/subflow:",n); | ||||
|             } | ||||
|         } | ||||
|         RED.events.emit('nodes:add',n); | ||||
|     } | ||||
| @@ -246,6 +253,9 @@ RED.nodes = (function() { | ||||
|             node = getNode(id); | ||||
|             if (node) { | ||||
|                 nodes.splice(nodes.indexOf(node),1); | ||||
|                 if (nodeTabMap[node.z]) { | ||||
|                     delete nodeTabMap[node.z][node.id]; | ||||
|                 } | ||||
|                 removedLinks = links.filter(function(l) { return (l.source === node) || (l.target === node); }); | ||||
|                 removedLinks.forEach(function(l) {links.splice(links.indexOf(l), 1); }); | ||||
|                 var updatedConfigNode = false; | ||||
| @@ -291,6 +301,17 @@ RED.nodes = (function() { | ||||
|         return {links:removedLinks,nodes:removedNodes}; | ||||
|     } | ||||
|  | ||||
|     function moveNodeToTab(node, z) { | ||||
|         if (nodeTabMap[node.z]) { | ||||
|             delete nodeTabMap[node.z][node.id]; | ||||
|         } | ||||
|         if (!nodeTabMap[z]) { | ||||
|             nodeTabMap[z] = {}; | ||||
|         } | ||||
|         nodeTabMap[z][node.id] = node; | ||||
|         node.z = z; | ||||
|     } | ||||
|  | ||||
|     function removeLink(l) { | ||||
|         var index = links.indexOf(l); | ||||
|         if (index != -1) { | ||||
| @@ -300,6 +321,8 @@ RED.nodes = (function() { | ||||
|  | ||||
|     function addWorkspace(ws,targetIndex) { | ||||
|         workspaces[ws.id] = ws; | ||||
|         nodeTabMap[ws.id] = {}; | ||||
|  | ||||
|         ws._def = RED.nodes.getType('tab'); | ||||
|         if (targetIndex === undefined) { | ||||
|             workspacesOrder.push(ws.id); | ||||
| @@ -312,6 +335,7 @@ RED.nodes = (function() { | ||||
|     } | ||||
|     function removeWorkspace(id) { | ||||
|         delete workspaces[id]; | ||||
|         delete nodeTabMap[id]; | ||||
|         workspacesOrder.splice(workspacesOrder.indexOf(id),1); | ||||
|  | ||||
|         var removedNodes = []; | ||||
| @@ -357,18 +381,33 @@ RED.nodes = (function() { | ||||
|             sf.name = subflowName; | ||||
|         } | ||||
|         subflows[sf.id] = sf; | ||||
|         nodeTabMap[sf.id] = {}; | ||||
|  | ||||
|         RED.nodes.registerType("subflow:"+sf.id, { | ||||
|             defaults:{name:{value:""}}, | ||||
|             icon: function() { return sf.icon||"subflow.png" }, | ||||
|             defaults:{ | ||||
|                 name:{value:""}, | ||||
|                 env:{value:[]} | ||||
|             }, | ||||
|             icon: function() { return sf.icon||"subflow.svg" }, | ||||
|             category: sf.category || "subflows", | ||||
|             inputs: sf.in.length, | ||||
|             outputs: sf.out.length, | ||||
|             color: "#da9", | ||||
|             color: sf.color || "#DDAA99", | ||||
|             label: function() { return this.name||RED.nodes.subflow(sf.id).name }, | ||||
|             labelStyle: function() { return this.name?"node_label_italic":""; }, | ||||
|             labelStyle: function() { return this.name?"red-ui-flow-node-label-italic":""; }, | ||||
|             paletteLabel: function() { return RED.nodes.subflow(sf.id).name }, | ||||
|             inputLabels: function(i) { return sf.inputLabels?sf.inputLabels[i]:null }, | ||||
|             outputLabels: function(i) { return sf.outputLabels?sf.outputLabels[i]:null }, | ||||
|             oneditresize: function(size) { | ||||
|                 // var rows = $(".dialog-form>div:not(.node-input-env-container-row)"); | ||||
|                 var height = size.height; | ||||
|                 // for (var i=0; i<rows.size(); i++) { | ||||
|                 //     height -= $(rows[i]).outerHeight(true); | ||||
|                 // } | ||||
|                 // var editorRow = $("#dialog-form>div.node-input-env-container-row"); | ||||
|                 // height -= (parseInt(editorRow.css("marginTop"))+parseInt(editorRow.css("marginBottom"))); | ||||
|                 $("ol.red-ui-editor-subflow-env-list").editableList('height',height); | ||||
|             }, | ||||
|             set:{ | ||||
|                 module: "node-red" | ||||
|             } | ||||
| @@ -380,6 +419,7 @@ RED.nodes = (function() { | ||||
|     } | ||||
|     function removeSubflow(sf) { | ||||
|         delete subflows[sf.id]; | ||||
|         delete nodeTabMap[sf.id]; | ||||
|         registry.removeNodeType("subflow:"+sf.id); | ||||
|     } | ||||
|  | ||||
| @@ -450,7 +490,9 @@ RED.nodes = (function() { | ||||
|         node.id = n.id; | ||||
|         node.type = n.type; | ||||
|         node.z = n.z; | ||||
|  | ||||
|         if (n.d === true) { | ||||
|             node.d = true; | ||||
|         } | ||||
|         if (node.type == "unknown") { | ||||
|             for (var p in n._orig) { | ||||
|                 if (n._orig.hasOwnProperty(p)) { | ||||
| @@ -535,6 +577,8 @@ RED.nodes = (function() { | ||||
|         node.category = n.category; | ||||
|         node.in = []; | ||||
|         node.out = []; | ||||
|         node.env = n.env; | ||||
|         node.color = n.color; | ||||
|  | ||||
|         n.in.forEach(function(p) { | ||||
|             var nIn = {x:p.x,y:p.y,wires:[]}; | ||||
| @@ -567,10 +611,22 @@ RED.nodes = (function() { | ||||
|             node.outputLabels = n.outputLabels.slice(); | ||||
|         } | ||||
|         if (n.icon) { | ||||
|             if (n.icon !== "node-red/subflow.png") { | ||||
|             if (n.icon !== "node-red/subflow.svg") { | ||||
|                 node.icon = n.icon; | ||||
|             } | ||||
|         } | ||||
|         if (n.status) { | ||||
|             node.status = {x: n.status.x, y: n.status.y, wires:[]}; | ||||
|             links.forEach(function(d) { | ||||
|                 if (d.target === n.status) { | ||||
|                     if (d.source.type != "subflow") { | ||||
|                         node.status.wires.push({id:d.source.id, port:d.sourcePort}) | ||||
|                     } else { | ||||
|                         node.status.wires.push({id:n.id, port:0}) | ||||
|                     } | ||||
|                 } | ||||
|             }); | ||||
|         } | ||||
|  | ||||
|         return node; | ||||
|     } | ||||
| @@ -740,6 +796,20 @@ RED.nodes = (function() { | ||||
|         if (!$.isArray(newNodes)) { | ||||
|             newNodes = [newNodes]; | ||||
|         } | ||||
|  | ||||
|         // Scan for any duplicate nodes and remove them. This is a temporary | ||||
|         // fix to help resolve corrupted flows caused by 0.20.0 where multiple | ||||
|         // copies of the flow would get loaded at the same time. | ||||
|         // If the user hit deploy they would have saved those duplicates. | ||||
|         var seenIds = {}; | ||||
|         newNodes = newNodes.filter(function(n) { | ||||
|             if (seenIds[n.id]) { | ||||
|                 return false; | ||||
|             } | ||||
|             seenIds[n.id] = true; | ||||
|             return true; | ||||
|         }) | ||||
|  | ||||
|         var isInitialLoad = false; | ||||
|         if (!initialLoad) { | ||||
|             isInitialLoad = true; | ||||
| @@ -775,7 +845,7 @@ RED.nodes = (function() { | ||||
|             var m = /^subflow:(.+)$/.exec(newNodes[i].type); | ||||
|             if (m) { | ||||
|                 var subflowId = m[1]; | ||||
|                 var parent = getSubflow(newNodes[i].z || activeWorkspace); | ||||
|                 var parent = getSubflow(activeWorkspace); | ||||
|                 if (parent) { | ||||
|                     var err; | ||||
|                     if (subflowId === parent.id) { | ||||
| @@ -851,6 +921,12 @@ RED.nodes = (function() { | ||||
|                         output.i = i; | ||||
|                         output.id = getID(); | ||||
|                     }); | ||||
|                     if (n.status) { | ||||
|                         n.status.type = "subflow"; | ||||
|                         n.status.direction = "status"; | ||||
|                         n.status.z = n.id; | ||||
|                         n.status.id = getID(); | ||||
|                     } | ||||
|                     new_subflows.push(n); | ||||
|                     addSubflow(n,createNewIds); | ||||
|                 } | ||||
| @@ -921,6 +997,9 @@ RED.nodes = (function() { | ||||
|                         users:[], | ||||
|                         _config:{} | ||||
|                     }; | ||||
|                     if (n.hasOwnProperty('d')) { | ||||
|                         configNode.d = n.d; | ||||
|                     } | ||||
|                     for (d in def.defaults) { | ||||
|                         if (def.defaults.hasOwnProperty(d)) { | ||||
|                             configNode[d] = n[d]; | ||||
| @@ -970,6 +1049,9 @@ RED.nodes = (function() { | ||||
|                     if (n.hasOwnProperty('l')) { | ||||
|                         node.l = n.l; | ||||
|                     } | ||||
|                     if (n.hasOwnProperty('d')) { | ||||
|                         node.d = n.d; | ||||
|                     } | ||||
|                     if (createNewIds) { | ||||
|                         if (subflow_blacklist[n.z]) { | ||||
|                             continue; | ||||
| @@ -1018,6 +1100,7 @@ RED.nodes = (function() { | ||||
|                         node.name = n.name; | ||||
|                         node.outputs = subflow.out.length; | ||||
|                         node.inputs = subflow.in.length; | ||||
|                         node.env = n.env; | ||||
|                     } else { | ||||
|                         if (!node._def) { | ||||
|                             if (node.x && node.y) { | ||||
| @@ -1025,7 +1108,7 @@ RED.nodes = (function() { | ||||
|                                     color:"#fee", | ||||
|                                     defaults: {}, | ||||
|                                     label: "unknown: "+n.type, | ||||
|                                     labelStyle: "node_label_italic", | ||||
|                                     labelStyle: "red-ui-flow-node-label-italic", | ||||
|                                     outputs: n.outputs||n.wires.length, | ||||
|                                     set: registry.getNodeSet("node-red/unknown") | ||||
|                                 } | ||||
| @@ -1111,6 +1194,7 @@ RED.nodes = (function() { | ||||
|         var nodeTypeArrayReferences = { | ||||
|             "catch":"scope", | ||||
|             "status":"scope", | ||||
|             "complete": "scope", | ||||
|             "link in":"links", | ||||
|             "link out":"links" | ||||
|         } | ||||
| @@ -1189,6 +1273,19 @@ RED.nodes = (function() { | ||||
|                 }); | ||||
|                 delete output.wires; | ||||
|             }); | ||||
|             if (n.status) { | ||||
|                 n.status.wires.forEach(function(wire) { | ||||
|                     var link; | ||||
|                     if (subflow_map[wire.id] && subflow_map[wire.id].id == n.id) { | ||||
|                         link = {source:n.in[wire.port], sourcePort:wire.port,target:n.status}; | ||||
|                     } else { | ||||
|                         link = {source:node_map[wire.id]||subflow_map[wire.id], sourcePort:wire.port,target:n.status}; | ||||
|                     } | ||||
|                     addLink(link); | ||||
|                     new_links.push(link); | ||||
|                 }); | ||||
|                 delete n.status.wires; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         RED.workspaces.refresh(); | ||||
| @@ -1198,13 +1295,22 @@ RED.nodes = (function() { | ||||
|     // TODO: supports filter.z|type | ||||
|     function filterNodes(filter) { | ||||
|         var result = []; | ||||
|         var searchSet = nodes; | ||||
|         var doZFilter = false; | ||||
|         if (filter.hasOwnProperty("z")) { | ||||
|             if (Object.hasOwnProperty("values") && nodeTabMap.hasOwnProperty(filter.z) ) { | ||||
|                 searchSet = Object.values(nodeTabMap[filter.z]); | ||||
|             } else { | ||||
|                 doZFilter = true; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         for (var n=0;n<nodes.length;n++) { | ||||
|             var node = nodes[n]; | ||||
|             if (filter.hasOwnProperty("z") && node.z !== filter.z) { | ||||
|         for (var n=0;n<searchSet.length;n++) { | ||||
|             var node = searchSet[n]; | ||||
|             if (filter.hasOwnProperty("type") && node.type !== filter.type) { | ||||
|                 continue; | ||||
|             } | ||||
|             if (filter.hasOwnProperty("type") && node.type !== filter.type) { | ||||
|             if (doZFilter && node.z !== filter.z) { | ||||
|                 continue; | ||||
|             } | ||||
|             result.push(node); | ||||
| @@ -1271,6 +1377,7 @@ RED.nodes = (function() { | ||||
|     function clear() { | ||||
|         nodes = []; | ||||
|         links = []; | ||||
|         nodeTabMap = {}; | ||||
|         configNodes = {}; | ||||
|         workspacesOrder = []; | ||||
|         var subflowIds = Object.keys(subflows); | ||||
| @@ -1380,6 +1487,8 @@ RED.nodes = (function() { | ||||
|         remove: removeNode, | ||||
|         clear: clear, | ||||
|  | ||||
|         moveNodeToTab: moveNodeToTab, | ||||
|  | ||||
|         addLink: addLink, | ||||
|         removeLink: removeLink, | ||||
|  | ||||
|   | ||||
| @@ -28,19 +28,40 @@ var RED = (function() { | ||||
|             var hasDeferred = false; | ||||
|  | ||||
|             var nodeConfigEls = $("<div>"+nodeConfig+"</div>"); | ||||
|             nodeConfigEls.find("script").each(function(i,el) { | ||||
|             var scripts = nodeConfigEls.find("script"); | ||||
|             var scriptCount = scripts.length; | ||||
|             scripts.each(function(i,el) { | ||||
|                 var srcUrl = $(el).attr('src'); | ||||
|                 if (srcUrl && !/^\s*(https?:|\/|\.)/.test(srcUrl)) { | ||||
|                     $(el).remove(); | ||||
|                     var newScript = document.createElement("script"); | ||||
|                     newScript.onload = function() { $("body").append(nodeConfigEls); done() } | ||||
|                     $('body').append(newScript); | ||||
|                     newScript.onload = function() { | ||||
|                         scriptCount--; | ||||
|                         if (scriptCount === 0) { | ||||
|                             $("#red-ui-editor-node-configs").append(nodeConfigEls); | ||||
|                             done() | ||||
|                         } | ||||
|                     } | ||||
|                     if ($(el).attr('type') === "module") { | ||||
|                         newScript.type = "module"; | ||||
|                     } | ||||
|                     $("#red-ui-editor-node-configs").append(newScript); | ||||
|                     newScript.src = RED.settings.apiRootUrl+srcUrl; | ||||
|                     hasDeferred = true; | ||||
|                 } else { | ||||
|                     if (/\/ace.js$/.test(srcUrl) || /\/ext-language_tools.js$/.test(srcUrl)) { | ||||
|                         // Block any attempts to load ace.js from a CDN - this will | ||||
|                         // break the version of ace included in the editor. | ||||
|                         // At the time of commit, the contrib-python nodes did this. | ||||
|                         // This is a crude fix until the python nodes are fixed. | ||||
|                         console.warn("Blocked attempt to load",srcUrl,"by",moduleId) | ||||
|                         $(el).remove(); | ||||
|                     } | ||||
|                     scriptCount--; | ||||
|                 } | ||||
|             }) | ||||
|             if (!hasDeferred) { | ||||
|                 $("body").append(nodeConfigEls); | ||||
|                 $("#red-ui-editor-node-configs").append(nodeConfigEls); | ||||
|                 done(); | ||||
|             } | ||||
|         } catch(err) { | ||||
| @@ -86,9 +107,12 @@ var RED = (function() { | ||||
|     } | ||||
|  | ||||
|     function loadNodes() { | ||||
|         var lang = localStorage.getItem("editor-language")||i18n.detectLanguage(); | ||||
|  | ||||
|         $.ajax({ | ||||
|             headers: { | ||||
|                 "Accept":"text/html" | ||||
|                 "Accept":"text/html", | ||||
|                 "Accept-Language": lang | ||||
|             }, | ||||
|             cache: false, | ||||
|             url: 'nodes', | ||||
| @@ -96,10 +120,10 @@ var RED = (function() { | ||||
|                 var configs = data.trim().split(/(?=<!-- --- \[red-module:\S+\] --- -->)/); | ||||
|                 var stepConfig = function() { | ||||
|                     if (configs.length === 0) { | ||||
|                         $("body").i18n(); | ||||
|                         $("#palette > .palette-spinner").hide(); | ||||
|                         $(".palette-scroll").removeClass("hide"); | ||||
|                         $("#palette-search").removeClass("hide"); | ||||
|                         $("#red-ui-editor").i18n(); | ||||
|                         $("#red-ui-palette > .red-ui-palette-spinner").hide(); | ||||
|                         $(".red-ui-palette-scroll").removeClass("hide"); | ||||
|                         $("#red-ui-palette-search").removeClass("hide"); | ||||
|                         loadFlows(function() { | ||||
|                             if (RED.settings.theme("projects.enabled",false)) { | ||||
|                                 RED.projects.refresh(function(activeProject) { | ||||
| @@ -211,7 +235,7 @@ var RED = (function() { | ||||
|                             } | ||||
|                         ] | ||||
|                     } else if (msg.error === "missing-types") { | ||||
|                         text+="<ul><li>"+msg.types.join("</li><li>")+"</li></ul>"; | ||||
|                         text+="<ul><li>"+msg.types.map(RED.utils.sanitize).join("</li><li>")+"</li></ul>"; | ||||
|                         if (!!RED.projects.getActiveProject()) { | ||||
|                             options.buttons = [ | ||||
|                                 { | ||||
| @@ -239,7 +263,7 @@ var RED = (function() { | ||||
|                             if (RED.user.hasPermission("projects.write")) { | ||||
|                                 options.buttons = [ | ||||
|                                     { | ||||
|                                         text: "Setup credentials", | ||||
|                                         text: RED._("notification.project.setupCredentials"), | ||||
|                                         click: function() { | ||||
|                                             persistentNotifications[notificationId].hideNotification(); | ||||
|                                             RED.projects.showCredentialsPrompt(); | ||||
| @@ -250,7 +274,7 @@ var RED = (function() { | ||||
|                         } else { | ||||
|                             options.buttons = [ | ||||
|                                 { | ||||
|                                     text: "Close", | ||||
|                                     text: RED._("common.label.close"), | ||||
|                                     click: function() { | ||||
|                                         persistentNotifications[notificationId].hideNotification(); | ||||
|                                     } | ||||
| @@ -261,7 +285,7 @@ var RED = (function() { | ||||
|                         if (RED.user.hasPermission("projects.write")) { | ||||
|                             options.buttons = [ | ||||
|                                 { | ||||
|                                     text: "Setup project files", | ||||
|                                     text: RED._("notification.project.setupProjectFiles"), | ||||
|                                     click: function() { | ||||
|                                         persistentNotifications[notificationId].hideNotification(); | ||||
|                                         RED.projects.showFilesPrompt(); | ||||
| @@ -273,10 +297,10 @@ var RED = (function() { | ||||
|                         if (RED.user.hasPermission("projects.write")) { | ||||
|                             options.buttons = [ | ||||
|                                 { | ||||
|                                     text: "Create default package file", | ||||
|                                     text: RED._("notification.project.setupProjectFiles"), | ||||
|                                     click: function() { | ||||
|                                         persistentNotifications[notificationId].hideNotification(); | ||||
|                                         RED.projects.createDefaultPackageFile(); | ||||
|                                         RED.projects.showFilesPrompt(); | ||||
|                                     } | ||||
|                                 } | ||||
|                             ] | ||||
| @@ -285,13 +309,13 @@ var RED = (function() { | ||||
|                         if (RED.user.hasPermission("projects.write")) { | ||||
|                             options.buttons = [ | ||||
|                                 { | ||||
|                                     text: "No thanks", | ||||
|                                     text: RED._("notification.project.no"), | ||||
|                                     click: function() { | ||||
|                                         persistentNotifications[notificationId].hideNotification(); | ||||
|                                     } | ||||
|                                 }, | ||||
|                                 { | ||||
|                                     text: "Create default project files", | ||||
|                                     text: RED._("notification.project.createDefault"), | ||||
|                                     click: function() { | ||||
|                                         persistentNotifications[notificationId].hideNotification(); | ||||
|                                         RED.projects.createDefaultFileSet(); | ||||
| @@ -305,7 +329,7 @@ var RED = (function() { | ||||
|                         if (RED.user.hasPermission("projects.write")) { | ||||
|                             options.buttons = [ | ||||
|                                 { | ||||
|                                     text: "Show merge conflicts", | ||||
|                                     text: RED._("notification.project.mergeConflict"), | ||||
|                                     click: function() { | ||||
|                                         persistentNotifications[notificationId].hideNotification(); | ||||
|                                         RED.sidebar.versionControl.showLocalChanges(); | ||||
| @@ -329,12 +353,11 @@ var RED = (function() { | ||||
|             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()}); | ||||
|                     } | ||||
|                 if (msg.hasOwnProperty("text") && /^[a-zA-Z]/.test(msg.text)) { | ||||
|                     msg.text = node._(msg.text.toString(),{defaultValue:msg.text.toString()}); | ||||
|                 } | ||||
|                 node.status = msg; | ||||
|                 node.dirtyStatus = true; | ||||
|                 node.dirty = true; | ||||
|                 RED.view.redraw(); | ||||
|             } | ||||
| @@ -395,8 +418,6 @@ var RED = (function() { | ||||
|                 RED.notify(RED._("palette.event.nodeUpgraded", {module:msg.module,version:msg.version}),"success"); | ||||
|                 RED.nodes.registry.setModulePendingUpdated(msg.module,msg.version); | ||||
|             } | ||||
|             // Refresh flow library to ensure any examples are updated | ||||
|             RED.library.loadFlowLibrary(); | ||||
|         }); | ||||
|         RED.comms.subscribe("event-log/#", function(topic,payload) { | ||||
|             var id = topic.substring(9); | ||||
| @@ -415,7 +436,7 @@ var RED = (function() { | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     function loadEditor() { | ||||
|     function buildMainMenu() { | ||||
|         var menuOptions = []; | ||||
|         if (RED.settings.theme("projects.enabled",false)) { | ||||
|             menuOptions.push({id:"menu-item-projects-menu",label:RED._("menu.label.projects"),options:[ | ||||
| @@ -424,34 +445,20 @@ var RED = (function() { | ||||
|                 {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-palette",label:RED._("menu.label.palette.show"),toggle:true,onselect:"core:toggle-palette", selected: true}, | ||||
|             {id:"menu-item-sidebar",label:RED._("menu.label.sidebar.show"),toggle:true,onselect:"core:toggle-sidebar", selected: true}, | ||||
|             {id:"menu-item-event-log",label:RED._("eventLog.title"),onselect:"core:show-event-log"}, | ||||
|             {id:"menu-item-action-list",label:RED._("keyboard.actionList"),onselect:"core:show-action-list"}, | ||||
|             null | ||||
|         ]}); | ||||
|         menuOptions.push(null); | ||||
|         menuOptions.push({id:"menu-item-import",label:RED._("menu.label.import"),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"} | ||||
|         ]}); | ||||
|         if (RED.settings.theme("menu.menu-item-import-library", true)) { | ||||
|             menuOptions.push({id: "menu-item-import", label: RED._("menu.label.import"), onselect: "core:show-import-dialog"}); | ||||
|         } | ||||
|         if (RED.settings.theme("menu.menu-item-export-library", true)) { | ||||
|             menuOptions.push({id: "menu-item-export", label: RED._("menu.label.export"), onselect: "core:show-export-dialog"}); | ||||
|         } | ||||
|         menuOptions.push(null); | ||||
|         menuOptions.push({id:"menu-item-search",label:RED._("menu.label.search"),onselect:"core:search"}); | ||||
|         menuOptions.push(null); | ||||
| @@ -474,7 +481,9 @@ var RED = (function() { | ||||
|         menuOptions.push({id:"menu-item-user-settings",label:RED._("menu.label.settings"),onselect:"core:show-user-settings"}); | ||||
|         menuOptions.push(null); | ||||
|  | ||||
|         menuOptions.push({id:"menu-item-keyboard-shortcuts",label:RED._("menu.label.keyboardShortcuts"),onselect:"core:show-help"}); | ||||
|         if (RED.settings.theme("menu.menu-item-keyboard-shortcuts", true)) { | ||||
|             menuOptions.push({id: "menu-item-keyboard-shortcuts", label: RED._("menu.label.keyboardShortcuts"), onselect: "core:show-help"}); | ||||
|         } | ||||
|         menuOptions.push({id:"menu-item-help", | ||||
|             label: RED.settings.theme("menu.menu-item-help.label",RED._("menu.label.help")), | ||||
|             href: RED.settings.theme("menu.menu-item-help.url","http://nodered.org/docs") | ||||
| @@ -482,13 +491,24 @@ var RED = (function() { | ||||
|         menuOptions.push({id:"menu-item-node-red-version", label:"v"+RED.settings.version, onselect: "core:show-about" }); | ||||
|  | ||||
|  | ||||
|         $('<li><a id="red-ui-header-button-sidemenu" class="button" href="#"><i class="fa fa-bars"></i></a></li>').appendTo(".red-ui-header-toolbar") | ||||
|         RED.menu.init({id:"red-ui-header-button-sidemenu",options: menuOptions}); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     function loadEditor() { | ||||
|  | ||||
|         RED.workspaces.init(); | ||||
|         RED.statusBar.init(); | ||||
|         RED.view.init(); | ||||
|         RED.userSettings.init(); | ||||
|         RED.user.init(); | ||||
|         RED.notifications.init(); | ||||
|         RED.library.init(); | ||||
|         RED.keyboard.init(); | ||||
|         RED.palette.init(); | ||||
|         RED.eventLog.init(); | ||||
|  | ||||
|         if (RED.settings.theme('palette.editable') !== false) { | ||||
|             RED.palette.editor.init(); | ||||
|         } else { | ||||
| @@ -504,27 +524,57 @@ var RED = (function() { | ||||
|         } | ||||
|  | ||||
|         RED.subflow.init(); | ||||
|         RED.workspaces.init(); | ||||
|         RED.clipboard.init(); | ||||
|         RED.search.init(); | ||||
|         RED.actionList.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.actions.add("core:show-about", showAbout); | ||||
|         buildMainMenu(); | ||||
|  | ||||
|         RED.nodes.init(); | ||||
|         RED.comms.connect(); | ||||
|  | ||||
|         $("#main-container").show(); | ||||
|         $(".header-toolbar").show(); | ||||
|         $("#red-ui-main-container").show(); | ||||
|         $(".red-ui-header-toolbar").show(); | ||||
|  | ||||
|         RED.actions.add("core:show-about", showAbout); | ||||
|  | ||||
|         loadNodeList(); | ||||
|     } | ||||
|  | ||||
|     function buildEditor(options) { | ||||
|         var header = $('<div id="red-ui-header"></div>').appendTo(options.target); | ||||
|         var logo = $('<span class="red-ui-header-logo"></span>').appendTo(header); | ||||
|         $('<ul class="red-ui-header-toolbar hide"></ul>').appendTo(header); | ||||
|         $('<div id="red-ui-header-shade" class="hide"></div>').appendTo(header); | ||||
|         $('<div id="red-ui-main-container" class="red-ui-sidebar-closed hide">'+ | ||||
|             '<div id="red-ui-workspace"></div>'+ | ||||
|             '<div id="red-ui-editor-stack"></div>'+ | ||||
|             '<div id="red-ui-palette"></div>'+ | ||||
|             '<div id="red-ui-sidebar"></div>'+ | ||||
|             '<div id="red-ui-sidebar-separator"></div>'+ | ||||
|         '</div>').appendTo(options.target); | ||||
|         $('<div id="red-ui-editor-node-configs"></div>').appendTo(options.target); | ||||
|         $('<div id="red-ui-full-shade" class="hide"></div>').appendTo(options.target); | ||||
|         $.getJSON(options.apiRootUrl+"theme", function(theme) { | ||||
|             if (theme.header) { | ||||
|                 if (theme.header.url) { | ||||
|                     logo = $("<a>",{href:theme.header.url}).appendTo(logo); | ||||
|                 } | ||||
|                 if (theme.header.image) { | ||||
|                     $('<img>',{src:theme.header.image}).appendTo(logo); | ||||
|                 } | ||||
|                 if (theme.header.title) { | ||||
|                     $('<span>').html(theme.header.title).appendTo(logo); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     var initialised = false; | ||||
|  | ||||
|     function init(options) { | ||||
| @@ -538,6 +588,10 @@ var RED = (function() { | ||||
|         if (options.apiRootUrl && !/\/$/.test(options.apiRootUrl)) { | ||||
|             options.apiRootUrl = options.apiRootUrl+"/"; | ||||
|         } | ||||
|         options.target = $("#red-ui-editor"); | ||||
|         options.target.addClass("red-ui-editor"); | ||||
|  | ||||
|         buildEditor(options); | ||||
|         RED.i18n.init(options, function() { | ||||
|             RED.settings.init(options, loadEditor); | ||||
|         }) | ||||
|   | ||||
| @@ -37,7 +37,7 @@ RED.settings = (function () { | ||||
|         if (key === "auth-tokens") { | ||||
|             localStorage.setItem(key, JSON.stringify(value)); | ||||
|         } else { | ||||
|             userSettings[key] = value; | ||||
|             RED.utils.setMessageProperty(userSettings,key,value); | ||||
|             saveUserSettings(); | ||||
|         } | ||||
|     }; | ||||
| @@ -46,16 +46,26 @@ RED.settings = (function () { | ||||
|      * If the key is not set in the localStorage it returns <i>undefined</i> | ||||
|      * Else return the JSON parsed value | ||||
|      * @param key | ||||
|      * @param defaultIfUndefined | ||||
|      * @returns {*} | ||||
|      */ | ||||
|     var get = function (key) { | ||||
|     var get = function (key,defaultIfUndefined) { | ||||
|         if (!hasLocalStorage()) { | ||||
|             return undefined; | ||||
|         } | ||||
|         if (key === "auth-tokens") { | ||||
|             return JSON.parse(localStorage.getItem(key)); | ||||
|         } else { | ||||
|             return userSettings[key]; | ||||
|             var v; | ||||
|             try { | ||||
|                 v = RED.utils.getMessageProperty(userSettings,key); | ||||
|                 if (v === undefined) { | ||||
|                     v = defaultIfUndefined; | ||||
|                 } | ||||
|             } catch(err) { | ||||
|                 v = defaultIfUndefined; | ||||
|             } | ||||
|             return v; | ||||
|         } | ||||
|     }; | ||||
|  | ||||
| @@ -131,6 +141,12 @@ RED.settings = (function () { | ||||
|                     RED.settings.remove("auth-tokens"); | ||||
|                 } | ||||
|                 console.log("Node-RED: " + data.version); | ||||
|                 console.groupCollapsed("Versions"); | ||||
|                 console.log("jQuery",$().jquery) | ||||
|                 console.log("jQuery UI",$.ui.version); | ||||
|                 console.log("ACE",ace.version); | ||||
|                 console.log("D3",d3.version); | ||||
|                 console.groupEnd(); | ||||
|                 loadUserSettings(done); | ||||
|             }, | ||||
|             error: function(jqXHR,textStatus,errorThrown) { | ||||
|   | ||||
| @@ -97,14 +97,14 @@ RED.text.bidi = (function() { | ||||
|     } | ||||
|  | ||||
|     /** | ||||
|      * Enforces the text direction for all the spans with style bidiAware under | ||||
|      * Enforces the text direction for all the spans with style red-ui-text-bidi-aware under | ||||
|      * workspace or sidebar div | ||||
|      */ | ||||
|     function enforceTextDirectionOnPage() { | ||||
|         $("#workspace").find('span.bidiAware').each(function() { | ||||
|         $("#red-ui-workspace").find('span.red-ui-text-bidi-aware').each(function() { | ||||
|             $(this).attr("dir", resolveBaseTextDir($(this).html())); | ||||
|         }); | ||||
|         $("#sidebar").find('span.bidiAware').each(function() { | ||||
|         $("#red-ui-sidebar").find('span.red-ui-text-bidi-aware').each(function() { | ||||
|             $(this).attr("dir", resolveBaseTextDir($(this).text())); | ||||
|         }); | ||||
|     } | ||||
|   | ||||
							
								
								
									
										230
									
								
								packages/node_modules/@node-red/editor-client/src/js/ui/actionList.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,230 @@ | ||||
| /** | ||||
|  * Copyright JS Foundation and other contributors, http://js.foundation | ||||
|  * | ||||
|  * Licensed under the Apache License, Version 2.0 (the "License"); | ||||
|  * you may not use this file except in compliance with the License. | ||||
|  * You may obtain a copy of the License at | ||||
|  * | ||||
|  * http://www.apache.org/licenses/LICENSE-2.0 | ||||
|  * | ||||
|  * Unless required by applicable law or agreed to in writing, software | ||||
|  * distributed under the License is distributed on an "AS IS" BASIS, | ||||
|  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | ||||
|  * See the License for the specific language governing permissions and | ||||
|  * limitations under the License. | ||||
|  **/ | ||||
| RED.actionList = (function() { | ||||
|  | ||||
|     var disabled = false; | ||||
|     var dialog = null; | ||||
|     var searchInput; | ||||
|     var searchResults; | ||||
|     var selected = -1; | ||||
|     var visible = false; | ||||
|  | ||||
|     var filterTerm = ""; | ||||
|     var filterTerms = []; | ||||
|     var previousActiveElement; | ||||
|  | ||||
|     function ensureSelectedIsVisible() { | ||||
|         var selectedEntry = searchResults.find("li.selected"); | ||||
|         if (selectedEntry.length === 1) { | ||||
|             var scrollWindow = searchResults.parent(); | ||||
|             var scrollHeight = scrollWindow.height(); | ||||
|             var scrollOffset = scrollWindow.scrollTop(); | ||||
|             var y = selectedEntry.position().top; | ||||
|             var h = selectedEntry.height(); | ||||
|             if (y+h > scrollHeight) { | ||||
|                 scrollWindow.animate({scrollTop: '-='+(scrollHeight-(y+h)-10)},50); | ||||
|             } else if (y<0) { | ||||
|                 scrollWindow.animate({scrollTop: '+='+(y-10)},50); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function createDialog() { | ||||
|         dialog = $("<div>",{id:"red-ui-actionList",class:"red-ui-search"}).appendTo("#red-ui-main-container"); | ||||
|         var searchDiv = $("<div>",{class:"red-ui-search-container"}).appendTo(dialog); | ||||
|         searchInput = $('<input type="text" data-i18n="[placeholder]keyboard.filterActions">').appendTo(searchDiv).searchBox({ | ||||
|             change: function() { | ||||
|                 filterTerm = $(this).val().trim(); | ||||
|                 filterTerms = filterTerm.split(" "); | ||||
|                 searchResults.editableList('filter'); | ||||
|                 searchResults.find("li.selected").removeClass("selected"); | ||||
|                 var children = searchResults.children(":visible"); | ||||
|                 if (children.length) { | ||||
|                     $(children[0]).addClass('selected'); | ||||
|                 } | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         searchInput.on('keydown',function(evt) { | ||||
|             var selectedChild; | ||||
|             if (evt.keyCode === 40) { | ||||
|                 // Down | ||||
|                 selectedChild = searchResults.find("li.selected"); | ||||
|                 if (!selectedChild.length) { | ||||
|                     var children = searchResults.children(":visible"); | ||||
|                     if (children.length) { | ||||
|                         $(children[0]).addClass('selected'); | ||||
|                     } | ||||
|                 } else { | ||||
|                     var nextChild = selectedChild.nextAll(":visible").first(); | ||||
|                     if (nextChild.length) { | ||||
|                         selectedChild.removeClass('selected'); | ||||
|                         nextChild.addClass('selected'); | ||||
|                     } | ||||
|                 } | ||||
|                 ensureSelectedIsVisible(); | ||||
|                 evt.preventDefault(); | ||||
|             } else if (evt.keyCode === 38) { | ||||
|                 // Up | ||||
|                 selectedChild = searchResults.find("li.selected"); | ||||
|                 var nextChild = selectedChild.prevAll(":visible").first(); | ||||
|                 if (nextChild.length) { | ||||
|                     selectedChild.removeClass('selected'); | ||||
|                     nextChild.addClass('selected'); | ||||
|                 } | ||||
|                 ensureSelectedIsVisible(); | ||||
|                 evt.preventDefault(); | ||||
|             } else if (evt.keyCode === 13) { | ||||
|                 // Enter | ||||
|                 selectedChild = searchResults.find("li.selected"); | ||||
|                 selectCommand(searchResults.editableList('getItem',selectedChild)); | ||||
|             } | ||||
|         }); | ||||
|         searchInput.i18n(); | ||||
|  | ||||
|         var searchResultsDiv = $("<div>",{class:"red-ui-search-results-container"}).appendTo(dialog); | ||||
|         searchResults = $('<ol>',{style:"position: absolute;top: 5px;bottom: 5px;left: 5px;right: 5px;"}).appendTo(searchResultsDiv).editableList({ | ||||
|             addButton: false, | ||||
|             addItem: function(container,i,action) { | ||||
|                 if (action.id === undefined) { | ||||
|                     $('<div>',{class:"red-ui-search-empty"}).text(RED._('search.empty')).appendTo(container); | ||||
|                 } else { | ||||
|                     var div = $('<a>',{href:'#',class:"red-ui-search-result"}).appendTo(container); | ||||
|                     var contentDiv = $('<div>',{class:"red-ui-search-result-action"}).appendTo(div); | ||||
|  | ||||
|  | ||||
|                     $('<div>').text(action.label).appendTo(contentDiv); | ||||
|                     // $('<div>',{class:"red-ui-search-result-node-type"}).text(node.type).appendTo(contentDiv); | ||||
|                     // $('<div>',{class:"red-ui-search-result-node-id"}).text(node.id).appendTo(contentDiv); | ||||
|                     if (action.key) { | ||||
|                         $('<div>',{class:"red-ui-search-result-action-key"}).html(RED.keyboard.formatKey(action.key)).appendTo(contentDiv); | ||||
|                     } | ||||
|                     div.on("click", function(evt) { | ||||
|                         evt.preventDefault(); | ||||
|                         selectCommand(action); | ||||
|                     }); | ||||
|                 } | ||||
|             }, | ||||
|             scrollOnAdd: false, | ||||
|             filter: function(item) { | ||||
|                 if (filterTerm !== "") { | ||||
|                     var pos=0; | ||||
|                     for (var i=0;i<filterTerms.length;i++) { | ||||
|                         var j = item._label.indexOf(filterTerms[i],pos); | ||||
|                         if (j > -1) { | ||||
|                             pos = j; | ||||
|                         } else { | ||||
|                             return false; | ||||
|                         } | ||||
|                     } | ||||
|                     return true; | ||||
|                 } | ||||
|                 return true; | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     function selectCommand(command) { | ||||
|         hide(); | ||||
|         if (command) { | ||||
|             RED.actions.invoke(command.id); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function show(v) { | ||||
|         if (disabled) { | ||||
|             return; | ||||
|         } | ||||
|         if (!visible) { | ||||
|             previousActiveElement = document.activeElement; | ||||
|             RED.keyboard.add("*","escape",function(){hide()}); | ||||
|             $("#red-ui-header-shade").show(); | ||||
|             $("#red-ui-editor-shade").show(); | ||||
|             $("#red-ui-palette-shade").show(); | ||||
|             $("#red-ui-sidebar-shade").show(); | ||||
|             $("#red-ui-sidebar-separator").hide(); | ||||
|             if (dialog === null) { | ||||
|                 createDialog(); | ||||
|             } | ||||
|             dialog.slideDown(300); | ||||
|             searchInput.searchBox('value',v) | ||||
|             searchResults.editableList('empty'); | ||||
|             results = []; | ||||
|             var actions = RED.actions.list(); | ||||
|             actions.sort(function(A,B) { | ||||
|                 return A.id.localeCompare(B.id); | ||||
|             }); | ||||
|             actions.forEach(function(action) { | ||||
|                 action.label = action.id.replace(/:/,": ").replace(/-/g," ").replace(/(^| )./g,function() { return arguments[0].toUpperCase()}); | ||||
|                 action._label = action.label.toLowerCase(); | ||||
|                 searchResults.editableList('addItem',action) | ||||
|             }) | ||||
|             RED.events.emit("actionList:open"); | ||||
|             visible = true; | ||||
|         } | ||||
|         searchInput.trigger("focus"); | ||||
|         var children = searchResults.children(":visible"); | ||||
|         if (children.length) { | ||||
|             $(children[0]).addClass('selected'); | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function hide() { | ||||
|         if (visible) { | ||||
|             RED.keyboard.remove("escape"); | ||||
|             visible = false; | ||||
|             $("#red-ui-header-shade").hide(); | ||||
|             $("#red-ui-editor-shade").hide(); | ||||
|             $("#red-ui-palette-shade").hide(); | ||||
|             $("#red-ui-sidebar-shade").hide(); | ||||
|             $("#red-ui-sidebar-separator").show(); | ||||
|             if (dialog !== null) { | ||||
|                 dialog.slideUp(200,function() { | ||||
|                     searchInput.searchBox('value',''); | ||||
|                 }); | ||||
|             } | ||||
|             RED.events.emit("actionList:close"); | ||||
|             if (previousActiveElement) { | ||||
|                 $(previousActiveElement).trigger("focus"); | ||||
|                 previousActiveElement = null; | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function init() { | ||||
|         RED.actions.add("core:show-action-list",show); | ||||
|  | ||||
|         RED.events.on("editor:open",function() { disabled = true; }); | ||||
|         RED.events.on("editor:close",function() { disabled = false; }); | ||||
|         RED.events.on("search:open",function() { disabled = true; }); | ||||
|         RED.events.on("search:close",function() { disabled = false; }); | ||||
|         RED.events.on("type-search:open",function() { disabled = true; }); | ||||
|         RED.events.on("type-search:close",function() { disabled = false; }); | ||||
|  | ||||
|         $("#red-ui-header-shade").on('mousedown',hide); | ||||
|         $("#red-ui-editor-shade").on('mousedown',hide); | ||||
|         $("#red-ui-palette-shade").on('mousedown',hide); | ||||
|         $("#red-ui-sidebar-shade").on('mousedown',hide); | ||||
|     } | ||||
|  | ||||
|     return { | ||||
|         init: init, | ||||
|         show: show, | ||||
|         hide: hide | ||||
|     }; | ||||
|  | ||||
| })(); | ||||
| @@ -24,38 +24,38 @@ RED.clipboard = (function() { | ||||
|     var disabled = false; | ||||
|     var popover; | ||||
|     var currentPopoverError; | ||||
|     var activeTab; | ||||
|     var libraryBrowser; | ||||
|     var examplesBrowser; | ||||
|  | ||||
|     function setupDialogs() { | ||||
|         dialog = $('<div id="clipboard-dialog" class="hide node-red-dialog"><form class="dialog-form form-horizontal"></form></div>') | ||||
|             .appendTo("body") | ||||
|         dialog = $('<div id="red-ui-clipboard-dialog" class="hide"><form class="dialog-form form-horizontal"></form></div>') | ||||
|             .appendTo("#red-ui-editor") | ||||
|             .dialog({ | ||||
|                 modal: true, | ||||
|                 autoOpen: false, | ||||
|                 width: 500, | ||||
|                 width: 700, | ||||
|                 resizable: false, | ||||
|                 classes: { | ||||
|                     "ui-dialog": "red-ui-editor-dialog", | ||||
|                     "ui-dialog-titlebar-close": "hide", | ||||
|                     "ui-widget-overlay": "red-ui-editor-dialog" | ||||
|                 }, | ||||
|                 buttons: [ | ||||
|                     { | ||||
|                         id: "clipboard-dialog-cancel", | ||||
|                         id: "red-ui-clipboard-dialog-cancel", | ||||
|                         text: RED._("common.label.cancel"), | ||||
|                         click: function() { | ||||
|                             $( this ).dialog( "close" ); | ||||
|                         } | ||||
|                     }, | ||||
|                     { | ||||
|                         id: "clipboard-dialog-close", | ||||
|                         class: "primary", | ||||
|                         text: RED._("common.label.close"), | ||||
|                         click: function() { | ||||
|                             $( this ).dialog( "close" ); | ||||
|                         } | ||||
|                     }, | ||||
|                     { | ||||
|                         id: "clipboard-dialog-download", | ||||
|                         id: "red-ui-clipboard-dialog-download", | ||||
|                         class: "primary", | ||||
|                         text: RED._("clipboard.download"), | ||||
|                         click: function() { | ||||
|                             var element = document.createElement('a'); | ||||
|                             element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent($("#clipboard-export").val())); | ||||
|                             element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent($("#red-ui-clipboard-dialog-export-text").val())); | ||||
|                             element.setAttribute('download', "flows.json"); | ||||
|                             element.style.display = 'none'; | ||||
|                             document.body.appendChild(element); | ||||
| @@ -65,30 +65,100 @@ RED.clipboard = (function() { | ||||
|                         } | ||||
|                     }, | ||||
|                     { | ||||
|                         id: "clipboard-dialog-copy", | ||||
|                         id: "red-ui-clipboard-dialog-export", | ||||
|                         class: "primary", | ||||
|                         text: RED._("clipboard.export.copy"), | ||||
|                         click: function() { | ||||
|                             $("#clipboard-export").select(); | ||||
|                             document.execCommand("copy"); | ||||
|                             document.getSelection().removeAllRanges(); | ||||
|                             RED.notify(RED._("clipboard.nodesExported"),{id:"clipboard"}); | ||||
|                             $( this ).dialog( "close" ); | ||||
|                             if (activeTab === "red-ui-clipboard-dialog-export-tab-clipboard") { | ||||
|                                 $("#red-ui-clipboard-dialog-export-text").select(); | ||||
|                                 document.execCommand("copy"); | ||||
|                                 document.getSelection().removeAllRanges(); | ||||
|                                 RED.notify(RED._("clipboard.nodesExported"),{id:"clipboard"}); | ||||
|                                 $( this ).dialog( "close" ); | ||||
|                             } else { | ||||
|                                 var flowToExport = $("#red-ui-clipboard-dialog-export-text").val(); | ||||
|                                 var selectedPath = libraryBrowser.getSelected(); | ||||
|                                 if (!selectedPath.children) { | ||||
|                                     selectedPath = selectedPath.parent; | ||||
|                                 } | ||||
|                                 var filename = $("#red-ui-clipboard-dialog-tab-library-name").val().trim(); | ||||
|                                 var saveFlow = function() { | ||||
|                                     $.ajax({ | ||||
|                                         url:'library/'+selectedPath.library+'/'+selectedPath.type+'/'+selectedPath.path + filename, | ||||
|                                         type: "POST", | ||||
|                                         data: flowToExport, | ||||
|                                         contentType: "application/json; charset=utf-8" | ||||
|                                     }).done(function() { | ||||
|                                         $(dialog).dialog( "close" ); | ||||
|                                         RED.notify(RED._("library.exportedToLibrary"),"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"); | ||||
|                                         } | ||||
|                                     }); | ||||
|                                 } | ||||
|                                 if (selectedPath.children) { | ||||
|                                     var exists = false; | ||||
|                                     selectedPath.children.forEach(function(f) { | ||||
|                                         if (f.label === filename) { | ||||
|                                             exists = true; | ||||
|                                         } | ||||
|                                     }); | ||||
|                                     if (exists) { | ||||
|                                         dialog.dialog("close"); | ||||
|                                         var notification = RED.notify(RED._("clipboard.export.exists",{file:RED.utils.sanitize(filename)}),{ | ||||
|                                             type: "warning", | ||||
|                                             fixed: true, | ||||
|                                             buttons: [{ | ||||
|                                                 text: RED._("common.label.cancel"), | ||||
|                                                 click: function() { | ||||
|                                                     notification.hideNotification() | ||||
|                                                     dialog.dialog( "open" ); | ||||
|                                                 } | ||||
|                                             },{ | ||||
|                                                 text: RED._("clipboard.export.overwrite"), | ||||
|                                                 click: function() { | ||||
|                                                     notification.hideNotification() | ||||
|                                                     saveFlow(); | ||||
|                                                 } | ||||
|                                             }] | ||||
|                                         }); | ||||
|                                     } else { | ||||
|                                         saveFlow(); | ||||
|                                     } | ||||
|                                 } else { | ||||
|                                     saveFlow(); | ||||
|                                 } | ||||
|                             } | ||||
|                         } | ||||
|                     }, | ||||
|                     { | ||||
|                         id: "clipboard-dialog-ok", | ||||
|                         id: "red-ui-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'); | ||||
|                             var addNewFlow = ($("#red-ui-clipboard-dialog-import-opt > a.selected").attr('id') === 'red-ui-clipboard-dialog-import-opt-new'); | ||||
|                             if (activeTab === "red-ui-clipboard-dialog-import-tab-clipboard") { | ||||
|                                 RED.view.importNodes($("#red-ui-clipboard-dialog-import-text").val(),addNewFlow); | ||||
|                             } else { | ||||
|                                 var selectedPath; | ||||
|                                 if (activeTab === "red-ui-clipboard-dialog-import-tab-library") { | ||||
|                                     selectedPath = libraryBrowser.getSelected(); | ||||
|                                 } else { | ||||
|                                     selectedPath = examplesBrowser.getSelected(); | ||||
|                                 } | ||||
|                                 if (selectedPath.path) { | ||||
|                                     $.get('library/'+selectedPath.library+'/'+selectedPath.type+'/'+selectedPath.path, function(data) { | ||||
|                                         RED.view.importNodes(data,addNewFlow); | ||||
|                                     }); | ||||
|                                 } | ||||
|                             } | ||||
|                             $( this ).dialog( "close" ); | ||||
|                         } | ||||
|                     } | ||||
|                 ], | ||||
|                 open: function(e) { | ||||
|                     $(this).parent().find(".ui-dialog-titlebar-close").hide(); | ||||
|                 }, | ||||
|                 close: function(e) { | ||||
|                     if (popover) { | ||||
|                         popover.close(true); | ||||
| @@ -101,152 +171,281 @@ RED.clipboard = (function() { | ||||
|  | ||||
|         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>'+ | ||||
|                 '<label style="width:auto;margin-right: 10px;" data-i18n="common.label.export"></label>'+ | ||||
|                 '<span id="red-ui-clipboard-dialog-export-rng-group" class="button-group">'+ | ||||
|                     '<a id="red-ui-clipboard-dialog-export-rng-selected" class="red-ui-button toggle" href="#" data-i18n="clipboard.export.selected"></a>'+ | ||||
|                     '<a id="red-ui-clipboard-dialog-export-rng-flow" class="red-ui-button toggle" href="#" data-i18n="clipboard.export.current"></a>'+ | ||||
|                     '<a id="red-ui-clipboard-dialog-export-rng-full" class="red-ui-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-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>'; | ||||
|             '<div class="red-ui-clipboard-dialog-box">'+ | ||||
|                 '<div class="red-ui-clipboard-dialog-tabs">'+ | ||||
|                     '<ul id="red-ui-clipboard-dialog-export-tabs"></ul>'+ | ||||
|                 '</div>'+ | ||||
|                 '<div id="red-ui-clipboard-dialog-export-tabs-content" class="red-ui-clipboard-dialog-tabs-content">'+ | ||||
|                     '<div id="red-ui-clipboard-dialog-export-tab-clipboard" class="red-ui-clipboard-dialog-tab-clipboard">'+ | ||||
|                         '<div class="form-row">'+ | ||||
|                             '<textarea readonly id="red-ui-clipboard-dialog-export-text"></textarea>'+ | ||||
|                         '</div>'+ | ||||
|                         '<div class="form-row" style="text-align: right;">'+ | ||||
|                             '<span id="red-ui-clipboard-dialog-export-fmt-group" class="button-group">'+ | ||||
|                                 '<a id="red-ui-clipboard-dialog-export-fmt-mini" class="red-ui-button red-ui-button-small toggle" href="#" data-i18n="clipboard.export.compact"></a>'+ | ||||
|                                 '<a id="red-ui-clipboard-dialog-export-fmt-full" class="red-ui-button red-ui-button-small toggle" href="#" data-i18n="clipboard.export.formatted"></a>'+ | ||||
|                             '</span>'+ | ||||
|                         '</div>'+ | ||||
|                     '</div>'+ | ||||
|                     '<div id="red-ui-clipboard-dialog-export-tab-library" class="red-ui-clipboard-dialog-tab-library">'+ | ||||
|                         '<div id="red-ui-clipboard-dialog-export-tab-library-browser"></div>'+ | ||||
|                         '<div class="form-row">'+ | ||||
|                             '<label data-i18n="clipboard.export.exportAs"></label><input id="red-ui-clipboard-dialog-tab-library-name" type="text">'+ | ||||
|                         '</div>'+ | ||||
|                     '</div>'+ | ||||
|                 '</div>'+ | ||||
|             '</div>' | ||||
|             ; | ||||
|  | ||||
|  | ||||
|         importNodesDialog = | ||||
|             '<div class="form-row"><span data-i18n="clipboard.pasteNodes"></span>'+ | ||||
|                 ' <a class="editor-button" id="import-file-upload-btn"><i class="fa fa-upload"></i> <span data-i18n="clipboard.selectFile"></span></a>'+ | ||||
|                 '<input type="file" id="import-file-upload" accept=".json" style="display:none">'+ | ||||
|             '<div class="red-ui-clipboard-dialog-box" style="margin-bottom: 12px">'+ | ||||
|                 '<div class="red-ui-clipboard-dialog-tabs">'+ | ||||
|                     '<ul id="red-ui-clipboard-dialog-import-tabs"></ul>'+ | ||||
|                 '</div>'+ | ||||
|                 '<div id="red-ui-clipboard-dialog-import-tabs-content" class="red-ui-clipboard-dialog-tabs-content">'+ | ||||
|                     '<div id="red-ui-clipboard-dialog-import-tab-clipboard" class="red-ui-clipboard-dialog-tab-clipboard">'+ | ||||
|                         '<div class="form-row"><span data-i18n="clipboard.pasteNodes"></span>'+ | ||||
|                             ' <a class="red-ui-button" id="red-ui-clipboard-dialog-import-file-upload-btn"><i class="fa fa-upload"></i> <span data-i18n="clipboard.selectFile"></span></a>'+ | ||||
|                             '<input type="file" id="red-ui-clipboard-dialog-import-file-upload" accept=".json" style="display:none">'+ | ||||
|                         '</div>'+ | ||||
|                         '<div class="form-row">'+ | ||||
|                             '<textarea id="red-ui-clipboard-dialog-import-text"></textarea>'+ | ||||
|                         '</div>'+ | ||||
|                     '</div>'+ | ||||
|                     '<div id="red-ui-clipboard-dialog-import-tab-library" class="red-ui-clipboard-dialog-tab-library"></div>'+ | ||||
|                     '<div id="red-ui-clipboard-dialog-import-tab-examples" class="red-ui-clipboard-dialog-tab-library"></div>'+ | ||||
|                 '</div>'+ | ||||
|             '</div>'+ | ||||
|             '<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"></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>'+ | ||||
|                 '<label style="width:auto;margin-right: 10px;" data-i18n="clipboard.import.import"></label>'+ | ||||
|                 '<span id="red-ui-clipboard-dialog-import-opt" class="button-group">'+ | ||||
|                     '<a id="red-ui-clipboard-dialog-import-opt-current" class="red-ui-button toggle selected" href="#" data-i18n="clipboard.export.current"></a>'+ | ||||
|                     '<a id="red-ui-clipboard-dialog-import-opt-new" class="red-ui-button toggle" href="#" data-i18n="clipboard.import.newFlow"></a>'+ | ||||
|                 '</span>'+ | ||||
|             '</div>'; | ||||
|  | ||||
|     } | ||||
|  | ||||
|     var validateImportTimeout; | ||||
|  | ||||
|     function validateImport() { | ||||
|         if (validateImportTimeout) { | ||||
|             clearTimeout(validateImportTimeout); | ||||
|     var validateExportFilenameTimeout | ||||
|     function validateExportFilename() { | ||||
|         if (validateExportFilenameTimeout) { | ||||
|             clearTimeout(validateExportFilenameTimeout); | ||||
|         } | ||||
|         validateImportTimeout = setTimeout(function() { | ||||
|             var importInput = $("#clipboard-import"); | ||||
|             var v = importInput.val().trim(); | ||||
|             if (v === "") { | ||||
|                 popover.close(true); | ||||
|                 currentPopoverError = null; | ||||
|                 importInput.removeClass("input-error"); | ||||
|                 $("#clipboard-dialog-ok").button("disable"); | ||||
|                 return; | ||||
|             } | ||||
|             try { | ||||
|                 if (!/^\[[\s\S]*\]$/m.test(v)) { | ||||
|                     throw new Error(RED._("clipboard.import.errors.notArray")); | ||||
|                 } | ||||
|                 var res = JSON.parse(v); | ||||
|                 for (var i=0;i<res.length;i++) { | ||||
|                     if (typeof res[i] !== "object") { | ||||
|                         throw new Error(RED._("clipboard.import.errors.itemNotObject",{index:i})); | ||||
|                     } | ||||
|                     if (!res[i].hasOwnProperty('id')) { | ||||
|                         throw new Error(RED._("clipboard.import.errors.missingId",{index:i})); | ||||
|                     } | ||||
|                     if (!res[i].hasOwnProperty('type')) { | ||||
|                         throw new Error(RED._("clipboard.import.errors.missingType",{index:i})); | ||||
|                     } | ||||
|                 } | ||||
|                 currentPopoverError = null; | ||||
|                 popover.close(true); | ||||
|                 importInput.removeClass("input-error"); | ||||
|                 importInput.val(v); | ||||
|                 $("#clipboard-dialog-ok").button("enable"); | ||||
|             } catch(err) { | ||||
|                 if (v !== "") { | ||||
|                     importInput.addClass("input-error"); | ||||
|                     var errString = err.toString(); | ||||
|                     if (errString !== currentPopoverError) { | ||||
|                         // Display the error as-is. | ||||
|                         // Error messages are only in English. Each browser has its | ||||
|                         // own set of messages with very little consistency. | ||||
|                         // To provide translated messages this code will either need to: | ||||
|                         // - reduce everything down to 'unexpected token at position x' | ||||
|                         //   which is the least useful, but most consistent message | ||||
|                         // - use a custom/library parser that gives consistent messages | ||||
|                         //   which can be translated. | ||||
|                         var message = $('<div class="clipboard-import-error"></div>').text(errString); | ||||
|                         var errorPos; | ||||
|                         // Chrome error messages | ||||
|                         var m = /at position (\d+)/i.exec(errString); | ||||
|                         if (m) { | ||||
|                             errorPos = parseInt(m[1]); | ||||
|                         } else { | ||||
|                             // Firefox error messages | ||||
|                             m = /at line (\d+) column (\d+)/i.exec(errString); | ||||
|                             if (m) { | ||||
|                                 var line = parseInt(m[1])-1; | ||||
|                                 var col = parseInt(m[2])-1; | ||||
|                                 var lines = v.split("\n"); | ||||
|                                 errorPos = 0; | ||||
|                                 for (var i=0;i<line;i++) { | ||||
|                                     errorPos += lines[i].length+1; | ||||
|                                 } | ||||
|                                 errorPos += col; | ||||
|                             } else { | ||||
|                                 // Safari doesn't provide any position information | ||||
|                                 // IE: tbd | ||||
|                             } | ||||
|                         } | ||||
|  | ||||
|                         if (errorPos !== undefined) { | ||||
|                             v = v.replace(/\n/g,"↵"); | ||||
|                             var index = parseInt(m[1]); | ||||
|                             var parseError = $('<div>').appendTo(message); | ||||
|                             var code = $('<pre>').appendTo(parseError); | ||||
|                             $('<span>').text(v.substring(errorPos-12,errorPos)).appendTo(code) | ||||
|                             $('<span class="error">').text(v.charAt(errorPos)).appendTo(code); | ||||
|                             $('<span>').text(v.substring(errorPos+1,errorPos+12)).appendTo(code); | ||||
|                         } | ||||
|                         popover.close(true).setContent(message).open(); | ||||
|                         currentPopoverError = errString; | ||||
|                     } | ||||
|                 } else { | ||||
|                     currentPopoverError = null; | ||||
|                 } | ||||
|                 $("#clipboard-dialog-ok").button("disable"); | ||||
|         validateExportFilenameTimeout = setTimeout(function() { | ||||
|             var filenameInput = $("#red-ui-clipboard-dialog-tab-library-name"); | ||||
|             var filename = filenameInput.val().trim(); | ||||
|             var valid = filename.length > 0 && !/[\/\\]/.test(filename); | ||||
|             if (valid) { | ||||
|                 filenameInput.removeClass("input-error"); | ||||
|                 $("#red-ui-clipboard-dialog-export").button("enable"); | ||||
|             } else { | ||||
|                 filenameInput.addClass("input-error"); | ||||
|                 $("#red-ui-clipboard-dialog-export").button("disable"); | ||||
|             } | ||||
|         },100); | ||||
|     } | ||||
|  | ||||
|     function importNodes() { | ||||
|     var validateImportTimeout; | ||||
|     function validateImport() { | ||||
|         if (activeTab === "red-ui-clipboard-dialog-import-tab-clipboard") { | ||||
|             if (validateImportTimeout) { | ||||
|                 clearTimeout(validateImportTimeout); | ||||
|             } | ||||
|             validateImportTimeout = setTimeout(function() { | ||||
|                 var importInput = $("#red-ui-clipboard-dialog-import-text"); | ||||
|                 var v = importInput.val().trim(); | ||||
|                 if (v === "") { | ||||
|                     popover.close(true); | ||||
|                     currentPopoverError = null; | ||||
|                     importInput.removeClass("input-error"); | ||||
|                     $("#red-ui-clipboard-dialog-ok").button("disable"); | ||||
|                     return; | ||||
|                 } | ||||
|                 try { | ||||
|                     if (!/^\[[\s\S]*\]$/m.test(v)) { | ||||
|                         throw new Error(RED._("clipboard.import.errors.notArray")); | ||||
|                     } | ||||
|                     var res = JSON.parse(v); | ||||
|                     for (var i=0;i<res.length;i++) { | ||||
|                         if (typeof res[i] !== "object") { | ||||
|                             throw new Error(RED._("clipboard.import.errors.itemNotObject",{index:i})); | ||||
|                         } | ||||
|                         if (!res[i].hasOwnProperty('id')) { | ||||
|                             throw new Error(RED._("clipboard.import.errors.missingId",{index:i})); | ||||
|                         } | ||||
|                         if (!res[i].hasOwnProperty('type')) { | ||||
|                             throw new Error(RED._("clipboard.import.errors.missingType",{index:i})); | ||||
|                         } | ||||
|                     } | ||||
|                     currentPopoverError = null; | ||||
|                     popover.close(true); | ||||
|                     importInput.removeClass("input-error"); | ||||
|                     importInput.val(v); | ||||
|                     $("#red-ui-clipboard-dialog-ok").button("enable"); | ||||
|                 } catch(err) { | ||||
|                     if (v !== "") { | ||||
|                         importInput.addClass("input-error"); | ||||
|                         var errString = err.toString(); | ||||
|                         if (errString !== currentPopoverError) { | ||||
|                             // Display the error as-is. | ||||
|                             // Error messages are only in English. Each browser has its | ||||
|                             // own set of messages with very little consistency. | ||||
|                             // To provide translated messages this code will either need to: | ||||
|                             // - reduce everything down to 'unexpected token at position x' | ||||
|                             //   which is the least useful, but most consistent message | ||||
|                             // - use a custom/library parser that gives consistent messages | ||||
|                             //   which can be translated. | ||||
|                             var message = $('<div class="red-ui-clipboard-import-error"></div>').text(errString); | ||||
|                             var errorPos; | ||||
|                             // Chrome error messages | ||||
|                             var m = /at position (\d+)/i.exec(errString); | ||||
|                             if (m) { | ||||
|                                 errorPos = parseInt(m[1]); | ||||
|                             } else { | ||||
|                                 // Firefox error messages | ||||
|                                 m = /at line (\d+) column (\d+)/i.exec(errString); | ||||
|                                 if (m) { | ||||
|                                     var line = parseInt(m[1])-1; | ||||
|                                     var col = parseInt(m[2])-1; | ||||
|                                     var lines = v.split("\n"); | ||||
|                                     errorPos = 0; | ||||
|                                     for (var i=0;i<line;i++) { | ||||
|                                         errorPos += lines[i].length+1; | ||||
|                                     } | ||||
|                                     errorPos += col; | ||||
|                                 } else { | ||||
|                                     // Safari doesn't provide any position information | ||||
|                                     // IE: tbd | ||||
|                                 } | ||||
|                             } | ||||
|  | ||||
|                             if (errorPos !== undefined) { | ||||
|                                 v = v.replace(/\n/g,"↵"); | ||||
|                                 var index = parseInt(m[1]); | ||||
|                                 var parseError = $('<div>').appendTo(message); | ||||
|                                 var code = $('<pre>').appendTo(parseError); | ||||
|                                 $('<span>').text(v.substring(errorPos-12,errorPos)).appendTo(code) | ||||
|                                 $('<span class="error">').text(v.charAt(errorPos)).appendTo(code); | ||||
|                                 $('<span>').text(v.substring(errorPos+1,errorPos+12)).appendTo(code); | ||||
|                             } | ||||
|                             popover.close(true).setContent(message).open(); | ||||
|                             currentPopoverError = errString; | ||||
|                         } | ||||
|                     } else { | ||||
|                         currentPopoverError = null; | ||||
|                     } | ||||
|                     $("#red-ui-clipboard-dialog-ok").button("disable"); | ||||
|                 } | ||||
|             },100); | ||||
|         } else { | ||||
|             var file = libraryBrowser.getSelected(); | ||||
|             if (file && file.label && !file.children) { | ||||
|                 $("#red-ui-clipboard-dialog-ok").button("enable"); | ||||
|             } else { | ||||
|                 $("#red-ui-clipboard-dialog-ok").button("disable"); | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|     function importNodes(mode) { | ||||
|         if (disabled) { | ||||
|             return; | ||||
|         } | ||||
|         mode = mode || "clipboard"; | ||||
|  | ||||
|         dialogContainer.empty(); | ||||
|         dialogContainer.append($(importNodesDialog)); | ||||
|  | ||||
|         var tabs = RED.tabs.create({ | ||||
|             id: "red-ui-clipboard-dialog-import-tabs", | ||||
|             vertical: true, | ||||
|             onchange: function(tab) { | ||||
|                 $("#red-ui-clipboard-dialog-import-tabs-content").children().hide(); | ||||
|                 $("#" + tab.id).show(); | ||||
|                 activeTab = tab.id; | ||||
|                 if (popover) { | ||||
|                     popover.close(true); | ||||
|                     currentPopoverError = null; | ||||
|                 } | ||||
|                 if (tab.id === "red-ui-clipboard-dialog-import-tab-clipboard") { | ||||
|                     $("#red-ui-clipboard-dialog-import-text").trigger("focus"); | ||||
|                 } else { | ||||
|                     libraryBrowser.focus(); | ||||
|                 } | ||||
|                 validateImport(); | ||||
|             } | ||||
|         }); | ||||
|         tabs.addTab({ | ||||
|             id: "red-ui-clipboard-dialog-import-tab-clipboard", | ||||
|             label: RED._("clipboard.clipboard") | ||||
|         }); | ||||
|         tabs.addTab({ | ||||
|             id: "red-ui-clipboard-dialog-import-tab-library", | ||||
|             label: RED._("library.library") | ||||
|         }); | ||||
|         tabs.addTab({ | ||||
|             id: "red-ui-clipboard-dialog-import-tab-examples", | ||||
|             label: RED._("library.types.examples") | ||||
|         }); | ||||
|  | ||||
|         $("#red-ui-clipboard-dialog-tab-library-name").on("keyup", validateExportFilename); | ||||
|         $("#red-ui-clipboard-dialog-tab-library-name").on('paste',function() { setTimeout(validateExportFilename,10)}); | ||||
|         $("#red-ui-clipboard-dialog-export").button("enable"); | ||||
|  | ||||
|         libraryBrowser = RED.library.createBrowser({ | ||||
|             container: $("#red-ui-clipboard-dialog-import-tab-library"), | ||||
|             onselect: function(file) { | ||||
|                 if (file && file.label && !file.children) { | ||||
|                     $("#red-ui-clipboard-dialog-ok").button("enable"); | ||||
|                 } else { | ||||
|                     $("#red-ui-clipboard-dialog-ok").button("disable"); | ||||
|                 } | ||||
|             }, | ||||
|             onconfirm: function(item) { | ||||
|                 if (item && item.label && !item.children) { | ||||
|                     $("#red-ui-clipboard-dialog-ok").trigger("click"); | ||||
|                 } | ||||
|             } | ||||
|         }) | ||||
|         loadFlowLibrary(libraryBrowser,"local",RED._("library.types.local")); | ||||
|  | ||||
|         examplesBrowser = RED.library.createBrowser({ | ||||
|             container: $("#red-ui-clipboard-dialog-import-tab-examples"), | ||||
|             onselect: function(file) { | ||||
|                 if (file && file.label && !file.children) { | ||||
|                     $("#red-ui-clipboard-dialog-ok").button("enable"); | ||||
|                 } else { | ||||
|                     $("#red-ui-clipboard-dialog-ok").button("disable"); | ||||
|                 } | ||||
|             }, | ||||
|             onconfirm: function(item) { | ||||
|                 if (item && item.label && !item.children) { | ||||
|                     $("#red-ui-clipboard-dialog-ok").trigger("click"); | ||||
|                 } | ||||
|             } | ||||
|         }) | ||||
|         loadFlowLibrary(examplesBrowser,"_examples_",RED._("library.types.examples")); | ||||
|  | ||||
|  | ||||
|         dialogContainer.i18n(); | ||||
|  | ||||
|         $("#clipboard-dialog-ok").show(); | ||||
|         $("#clipboard-dialog-cancel").show(); | ||||
|         $("#clipboard-dialog-close").hide(); | ||||
|         $("#clipboard-dialog-copy").hide(); | ||||
|         $("#clipboard-dialog-download").hide(); | ||||
|         $("#clipboard-dialog-ok").button("disable"); | ||||
|         $("#clipboard-import").keyup(validateImport); | ||||
|         $("#clipboard-import").on('paste',function() { setTimeout(validateImport,10)}); | ||||
|         $("#red-ui-clipboard-dialog-ok").show(); | ||||
|         $("#red-ui-clipboard-dialog-cancel").show(); | ||||
|         $("#red-ui-clipboard-dialog-export").hide(); | ||||
|         $("#red-ui-clipboard-dialog-download").hide(); | ||||
|         $("#red-ui-clipboard-dialog-ok").button("disable"); | ||||
|         $("#red-ui-clipboard-dialog-import-text").on("keyup", validateImport); | ||||
|         $("#red-ui-clipboard-dialog-import-text").on('paste',function() { setTimeout(validateImport,10)}); | ||||
|  | ||||
|         $("#import-tab > a").click(function(evt) { | ||||
|         $("#red-ui-clipboard-dialog-import-opt > a").on("click", function(evt) { | ||||
|             evt.preventDefault(); | ||||
|             if ($(this).hasClass('disabled') || $(this).hasClass('selected')) { | ||||
|                 return; | ||||
| @@ -255,66 +454,122 @@ RED.clipboard = (function() { | ||||
|             $(this).addClass('selected'); | ||||
|         }); | ||||
|  | ||||
|         $("#import-file-upload").change(function() { | ||||
|         $("#red-ui-clipboard-dialog-import-file-upload").on("change", function() { | ||||
|             var fileReader = new FileReader(); | ||||
|             fileReader.onload = function () { | ||||
|                 $("#clipboard-import").val(fileReader.result); | ||||
|                 $("#red-ui-clipboard-dialog-import-text").val(fileReader.result); | ||||
|                 validateImport(); | ||||
|             }; | ||||
|             fileReader.readAsText($(this).prop('files')[0]); | ||||
|         }) | ||||
|         $("#import-file-upload-btn").click(function(evt) { | ||||
|         $("#red-ui-clipboard-dialog-import-file-upload-btn").on("click", function(evt) { | ||||
|             evt.preventDefault(); | ||||
|             $("#import-file-upload").click(); | ||||
|             $("#red-ui-clipboard-dialog-import-file-upload").trigger("click"); | ||||
|         }) | ||||
|  | ||||
|         tabs.activateTab("red-ui-clipboard-dialog-import-tab-"+mode); | ||||
|         if (mode === 'clipboard') { | ||||
|             setTimeout(function() { | ||||
|                 $("#red-ui-clipboard-dialog-import-text").trigger("focus"); | ||||
|             },100) | ||||
|         } | ||||
|  | ||||
|  | ||||
|         dialog.dialog("option","title",RED._("clipboard.importNodes")).dialog("open"); | ||||
|         popover = RED.popover.create({ | ||||
|             target: $("#clipboard-import"), | ||||
|             target: $("#red-ui-clipboard-dialog-import-text"), | ||||
|             trigger: "manual", | ||||
|             direction: "bottom", | ||||
|             content: "" | ||||
|         }); | ||||
|     } | ||||
|  | ||||
|     function exportNodes() { | ||||
|     function exportNodes(mode) { | ||||
|         if (disabled) { | ||||
|             return; | ||||
|         } | ||||
|  | ||||
|         mode = mode || "clipboard"; | ||||
|  | ||||
|         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) { | ||||
|         var tabs = RED.tabs.create({ | ||||
|             id: "red-ui-clipboard-dialog-export-tabs", | ||||
|             vertical: true, | ||||
|             onchange: function(tab) { | ||||
|                 $("#red-ui-clipboard-dialog-export-tabs-content").children().hide(); | ||||
|                 $("#" + tab.id).show(); | ||||
|                 activeTab = tab.id; | ||||
|                 if (tab.id === "red-ui-clipboard-dialog-export-tab-clipboard") { | ||||
|                     $("#red-ui-clipboard-dialog-export").button("option","label", RED._("clipboard.export.copy")) | ||||
|                     $("#red-ui-clipboard-dialog-download").show(); | ||||
|                 } else { | ||||
|                     $("#red-ui-clipboard-dialog-export").button("option","label", RED._("clipboard.export.export")) | ||||
|                     $("#red-ui-clipboard-dialog-download").hide(); | ||||
|                     libraryBrowser.focus(); | ||||
|                 } | ||||
|  | ||||
|             } | ||||
|         }); | ||||
|         tabs.addTab({ | ||||
|             id: "red-ui-clipboard-dialog-export-tab-clipboard", | ||||
|             label: RED._("clipboard.clipboard") | ||||
|         }); | ||||
|         tabs.addTab({ | ||||
|             id: "red-ui-clipboard-dialog-export-tab-library", | ||||
|             label: RED._("library.library") | ||||
|         }); | ||||
|  | ||||
|         $("#red-ui-clipboard-dialog-tab-library-name").on("keyup", validateExportFilename); | ||||
|         $("#red-ui-clipboard-dialog-tab-library-name").on('paste',function() { setTimeout(validateExportFilename,10)}); | ||||
|         $("#red-ui-clipboard-dialog-export").button("enable"); | ||||
|  | ||||
|         libraryBrowser = RED.library.createBrowser({ | ||||
|             container: $("#red-ui-clipboard-dialog-export-tab-library-browser"), | ||||
|             folderTools: true, | ||||
|             onselect: function(file) { | ||||
|                 if (file && file.label && !file.children) { | ||||
|                     $("#red-ui-clipboard-dialog-tab-library-name").val(file.label); | ||||
|                 } | ||||
|             } | ||||
|         }) | ||||
|         loadFlowLibrary(libraryBrowser,"local",RED._("library.types.local")); | ||||
|  | ||||
|         $("#red-ui-clipboard-dialog-tab-library-name").val("flows.json").select(); | ||||
|  | ||||
|         dialogContainer.i18n(); | ||||
|         var format = RED.settings.flowFilePretty ? "red-ui-clipboard-dialog-export-fmt-full" : "red-ui-clipboard-dialog-export-fmt-mini"; | ||||
|  | ||||
|         $("#red-ui-clipboard-dialog-export-fmt-group > a").on("click", function(evt) { | ||||
|             evt.preventDefault(); | ||||
|             if ($(this).hasClass('disabled') || $(this).hasClass('selected')) { | ||||
|                 $("#clipboard-export").focus(); | ||||
|                 $("#red-ui-clipboard-dialog-export-text").trigger("focus"); | ||||
|                 return; | ||||
|             } | ||||
|             $(this).parent().children().removeClass('selected'); | ||||
|             $(this).addClass('selected'); | ||||
|  | ||||
|             var flow = $("#clipboard-export").val(); | ||||
|             var flow = $("#red-ui-clipboard-dialog-export-text").val(); | ||||
|             if (flow.length > 0) { | ||||
|                 var nodes = JSON.parse(flow); | ||||
|  | ||||
|                 format = $(this).attr('id'); | ||||
|                 if (format === 'export-format-full') { | ||||
|                 if (format === 'red-ui-clipboard-dialog-export-fmt-full') { | ||||
|                     flow = JSON.stringify(nodes,null,4); | ||||
|                 } else { | ||||
|                     flow = JSON.stringify(nodes); | ||||
|                 } | ||||
|                 $("#clipboard-export").val(flow); | ||||
|                 $("#clipboard-export").focus(); | ||||
|                 $("#red-ui-clipboard-dialog-export-text").val(flow); | ||||
|                 setTimeout(function() { $("#red-ui-clipboard-dialog-export-text").scrollTop(0); },50); | ||||
|  | ||||
|                 $("#red-ui-clipboard-dialog-export-text").trigger("focus"); | ||||
|             } | ||||
|         }); | ||||
|  | ||||
|         $("#export-range-group > a").click(function(evt) { | ||||
|         $("#red-ui-clipboard-dialog-export-rng-group > a").on("click", function(evt) { | ||||
|             evt.preventDefault(); | ||||
|             if ($(this).hasClass('disabled') || $(this).hasClass('selected')) { | ||||
|                 $("#clipboard-export").focus(); | ||||
|                 return; | ||||
|             } | ||||
|             $(this).parent().children().removeClass('selected'); | ||||
| @@ -322,7 +577,7 @@ RED.clipboard = (function() { | ||||
|             var type = $(this).attr('id'); | ||||
|             var flow = ""; | ||||
|             var nodes = null; | ||||
|             if (type === 'export-range-selected') { | ||||
|             if (type === 'red-ui-clipboard-dialog-export-rng-selected') { | ||||
|                 var selection = RED.workspaces.selection(); | ||||
|                 if (selection.length > 0) { | ||||
|                     nodes = []; | ||||
| @@ -335,77 +590,97 @@ RED.clipboard = (function() { | ||||
|                 } | ||||
|                 // Don't include the subflow meta-port nodes in the exported selection | ||||
|                 nodes = RED.nodes.createExportableNodeSet(nodes.filter(function(n) { return n.type !== 'subflow'})); | ||||
|             } else if (type === 'export-range-flow') { | ||||
|             } else if (type === 'red-ui-clipboard-dialog-export-rng-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') { | ||||
|             } else if (type === 'red-ui-clipboard-dialog-export-rng-full') { | ||||
|                 nodes = RED.nodes.createCompleteNodeSet(false); | ||||
|             } | ||||
|             if (nodes !== null) { | ||||
|                 if (format === "export-format-full") { | ||||
|                 if (format === "red-ui-clipboard-dialog-export-fmt-full") { | ||||
|                     flow = JSON.stringify(nodes,null,4); | ||||
|                 } else { | ||||
|                     flow = JSON.stringify(nodes); | ||||
|                 } | ||||
|             } | ||||
|             if (flow.length > 0) { | ||||
|                 $("#export-copy").removeClass('disabled'); | ||||
|                 $("#red-ui-clipboard-dialog-export").removeClass('disabled'); | ||||
|             } else { | ||||
|                 $("#export-copy").addClass('disabled'); | ||||
|                 $("#red-ui-clipboard-dialog-export").addClass('disabled'); | ||||
|             } | ||||
|             $("#clipboard-export").val(flow); | ||||
|             $("#clipboard-export").focus(); | ||||
|             $("#red-ui-clipboard-dialog-export-text").val(flow); | ||||
|             setTimeout(function() { $("#red-ui-clipboard-dialog-export-text").scrollTop(0); },50); | ||||
|             $("#red-ui-clipboard-dialog-export-text").trigger("focus"); | ||||
|         }) | ||||
|  | ||||
|         $("#clipboard-dialog-ok").hide(); | ||||
|         $("#clipboard-dialog-cancel").hide(); | ||||
|         $("#clipboard-dialog-copy").hide(); | ||||
|         $("#clipboard-dialog-close").hide(); | ||||
|         $("#red-ui-clipboard-dialog-ok").hide(); | ||||
|         $("#red-ui-clipboard-dialog-cancel").hide(); | ||||
|         $("#red-ui-clipboard-dialog-export").hide(); | ||||
|         var selection = RED.workspaces.selection(); | ||||
|         if (selection.length > 0) { | ||||
|             $("#export-range-selected").click(); | ||||
|             $("#red-ui-clipboard-dialog-export-rng-selected").trigger("click"); | ||||
|         } else { | ||||
|             selection = RED.view.selection(); | ||||
|             if (selection.nodes) { | ||||
|                 $("#export-range-selected").click(); | ||||
|                 $("#red-ui-clipboard-dialog-export-rng-selected").trigger("click"); | ||||
|             } else { | ||||
|                 $("#export-range-selected").addClass('disabled').removeClass('selected'); | ||||
|                 $("#export-range-flow").click(); | ||||
|                 $("#red-ui-clipboard-dialog-export-rng-selected").addClass('disabled').removeClass('selected'); | ||||
|                 $("#red-ui-clipboard-dialog-export-rng-flow").trigger("click"); | ||||
|             } | ||||
|         } | ||||
|         if (format === "export-format-full") { | ||||
|             $("#export-format-full").click(); | ||||
|         if (format === "red-ui-clipboard-dialog-export-fmt-full") { | ||||
|             $("#red-ui-clipboard-dialog-export-fmt-full").trigger("click"); | ||||
|         } else { | ||||
|             $("#export-format-mini").click(); | ||||
|             $("#red-ui-clipboard-dialog-export-fmt-mini").trigger("click"); | ||||
|         } | ||||
|         $("#clipboard-export") | ||||
|             .focus(function() { | ||||
|                 var textarea = $(this); | ||||
|                 textarea.select(); | ||||
|                 textarea.mouseup(function() { | ||||
|                     textarea.unbind("mouseup"); | ||||
|                     return false; | ||||
|                 }) | ||||
|             }); | ||||
|         tabs.activateTab("red-ui-clipboard-dialog-export-tab-"+mode); | ||||
|         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(); | ||||
|         } | ||||
|         $("#clipboard-dialog-download").show(); | ||||
|         $("#red-ui-clipboard-dialog-export-text").trigger("focus"); | ||||
|         $("#red-ui-clipboard-dialog-cancel").show(); | ||||
|         $("#red-ui-clipboard-dialog-export").show(); | ||||
|         $("#red-ui-clipboard-dialog-download").show(); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     function loadFlowLibrary(browser,library,label) { | ||||
|         // if (includeExamples) { | ||||
|         //     listing.push({ | ||||
|         //         library: "_examples_", | ||||
|         //         type: "flows", | ||||
|         //         icon: 'fa fa-hdd-o', | ||||
|         //         label: RED._("library.types.examples"), | ||||
|         //         path: "", | ||||
|         //         children: function(done,item) { | ||||
|         //             RED.library.loadLibraryFolder("_examples_","flows","",function(children) { | ||||
|         //                 item.children = children; | ||||
|         //                 done(children); | ||||
|         //             }) | ||||
|         //         } | ||||
|         //     }) | ||||
|         // } | ||||
|         browser.data([{ | ||||
|             library: library, | ||||
|             type: "flows", | ||||
|             icon: 'fa fa-hdd-o', | ||||
|             label: label, | ||||
|             path: "", | ||||
|             expanded: true, | ||||
|             children: function(done, item) { | ||||
|                 RED.library.loadLibraryFolder(library,"flows","",function(children) { | ||||
|                     item.children = children; | ||||
|                     done(children); | ||||
|                 }) | ||||
|             } | ||||
|         }], true); | ||||
|  | ||||
|     } | ||||
|  | ||||
|     function hideDropTarget() { | ||||
|         $("#dropTarget").hide(); | ||||
|         $("#red-ui-drop-target").hide(); | ||||
|         RED.keyboard.remove("escape"); | ||||
|     } | ||||
|     function copyText(value,element,msg) { | ||||
| @@ -435,7 +710,7 @@ RED.clipboard = (function() { | ||||
|         if (truncated) { | ||||
|             msg += "_truncated"; | ||||
|         } | ||||
|         $("#clipboard-hidden").val(value).select(); | ||||
|         $("#red-ui-clipboard-hidden").val(value).select(); | ||||
|         var result =  document.execCommand("copy"); | ||||
|         if (result && element) { | ||||
|             var popover = RED.popover.create({ | ||||
| @@ -455,29 +730,34 @@ RED.clipboard = (function() { | ||||
|         init: function() { | ||||
|             setupDialogs(); | ||||
|  | ||||
|             $('<input type="text" id="clipboard-hidden">').appendTo("body"); | ||||
|             $('<input type="text" id="red-ui-clipboard-hidden" tabIndex="-1">').appendTo("#red-ui-editor"); | ||||
|  | ||||
|             RED.actions.add("core:show-export-dialog",exportNodes); | ||||
|             RED.actions.add("core:show-import-dialog",importNodes); | ||||
|  | ||||
|             RED.actions.add("core:show-library-export-dialog",function() { exportNodes('library') }); | ||||
|             RED.actions.add("core:show-library-import-dialog",function() { importNodes('library') }); | ||||
|  | ||||
|             RED.events.on("editor:open",function() { disabled = true; }); | ||||
|             RED.events.on("editor:close",function() { disabled = false; }); | ||||
|             RED.events.on("search:open",function() { disabled = true; }); | ||||
|             RED.events.on("search:close",function() { disabled = false; }); | ||||
|             RED.events.on("actionList:open",function() { disabled = true; }); | ||||
|             RED.events.on("actionList:close",function() { disabled = false; }); | ||||
|             RED.events.on("type-search:open",function() { disabled = true; }); | ||||
|             RED.events.on("type-search:close",function() { disabled = false; }); | ||||
|  | ||||
|             $('<div id="red-ui-drop-target"><div data-i18n="[append]workspace.dropFlowHere"><i class="fa fa-download"></i><br></div></div>').appendTo('#red-ui-editor'); | ||||
|  | ||||
|             $('#chart').on("dragenter",function(event) { | ||||
|             $('#red-ui-workspace-chart').on("dragenter",function(event) { | ||||
|                 if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 || | ||||
|                      $.inArray("Files",event.originalEvent.dataTransfer.types) != -1) { | ||||
|                     $("#dropTarget").css({display:'table'}); | ||||
|                     $("#red-ui-drop-target").css({display:'table'}); | ||||
|                     RED.keyboard.add("*", "escape" ,hideDropTarget); | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|             $('#dropTarget').on("dragover",function(event) { | ||||
|             $('#red-ui-drop-target').on("dragover",function(event) { | ||||
|                 if ($.inArray("text/plain",event.originalEvent.dataTransfer.types) != -1 || | ||||
|                      $.inArray("Files",event.originalEvent.dataTransfer.types) != -1) { | ||||
|                     event.preventDefault(); | ||||
|   | ||||
| @@ -38,7 +38,7 @@ | ||||
|                 this.options[0].show(); | ||||
|             } | ||||
|  | ||||
|             this.element.change(function() { | ||||
|             this.element.on("change", function() { | ||||
|                 if (this.checked) { | ||||
|                     that.options[0].hide(); | ||||
|                     that.options[1].show(); | ||||
| @@ -53,7 +53,7 @@ | ||||
|                     child.checkboxSet('state',isChecked,false,true); | ||||
|                 }) | ||||
|             }) | ||||
|             this.uiElement.click(function(e) { | ||||
|             this.uiElement.on("click", function(e) { | ||||
|                 e.stopPropagation(); | ||||
|                 // state returns null for a partial state. Clicking on that should | ||||
|                 // result in false. | ||||
|   | ||||
| @@ -32,7 +32,10 @@ | ||||
|  *   - scrollOnAdd : boolean - whether to scroll to newly added items | ||||
|  * methods: | ||||
|  *   - addItem(itemData) | ||||
|  *   - insertItemAt : function(data,index) - add an item at the specified index | ||||
|  *   - removeItem(itemData) | ||||
|  *   - getItemAt(index) | ||||
|  *   - indexOf(itemData) | ||||
|  *   - width(width) | ||||
|  *   - height(height) | ||||
|  *   - items() | ||||
| @@ -75,9 +78,9 @@ | ||||
|                         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>') | ||||
|                 $('<a href="#" class="red-ui-button red-ui-button-small red-ui-editableList-addButton" style="margin-top: 4px;"><i class="fa fa-plus"></i> '+addLabel+'</a>') | ||||
|                     .appendTo(this.topContainer) | ||||
|                     .click(function(evt) { | ||||
|                     .on("click", function(evt) { | ||||
|                         evt.preventDefault(); | ||||
|                         that.addItem({}); | ||||
|                     }); | ||||
| @@ -185,6 +188,11 @@ | ||||
|             } | ||||
|         }, | ||||
|         _destroy: function() { | ||||
|             if (this.topContainer) { | ||||
|                 var tc = this.topContainer; | ||||
|                 delete this.topContainer; | ||||
|                 tc.remove(); | ||||
|             } | ||||
|         }, | ||||
|         _refreshFilter: function() { | ||||
|             var that = this; | ||||
| @@ -230,7 +238,24 @@ | ||||
|             this.uiHeight = desiredHeight; | ||||
|             this._resize(); | ||||
|         }, | ||||
|         addItem: function(data) { | ||||
|         getItemAt: function(index) { | ||||
|             var items = this.items(); | ||||
|             if (index >= 0 && index < items.length) { | ||||
|                 return $(items[index]).data('data'); | ||||
|             } else { | ||||
|                 return; | ||||
|             } | ||||
|         }, | ||||
|         indexOf: function(data) { | ||||
|             var items = this.items(); | ||||
|             for (var i=0;i<items.length;i++) { | ||||
|                 if ($(items[i]).data('data') === data) { | ||||
|                     return i | ||||
|                 } | ||||
|             } | ||||
|             return -1 | ||||
|         }, | ||||
|         insertItemAt: function(data,index) { | ||||
|             var that = this; | ||||
|             data = data || {}; | ||||
|             var li = $('<li>'); | ||||
| @@ -248,7 +273,13 @@ | ||||
|                 }); | ||||
|             } | ||||
|             if (!added) { | ||||
|                 li.appendTo(this.element); | ||||
|                 if (index <= 0) { | ||||
|                     li.prependTo(this.element); | ||||
|                 } else if (index > that.element.children().length-1) { | ||||
|                     li.appendTo(this.element); | ||||
|                 } else { | ||||
|                     li.insertBefore(this.element.children().eq(index)); | ||||
|                 } | ||||
|             } | ||||
|             var row = $('<div/>').addClass("red-ui-editableList-item-content").appendTo(li); | ||||
|             row.data('data',data); | ||||
| @@ -257,10 +288,10 @@ | ||||
|                 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); | ||||
|                 var deleteButton = $('<a/>',{href:"#",class:"red-ui-editableList-item-remove red-ui-button red-ui-button-small"}).appendTo(li); | ||||
|                 $('<i/>',{class:"fa fa-remove"}).appendTo(deleteButton); | ||||
|                 li.addClass("red-ui-editableList-item-removable"); | ||||
|                 deleteButton.click(function(evt) { | ||||
|                 deleteButton.on("click", function(evt) { | ||||
|                     evt.preventDefault(); | ||||
|                     var data = row.data('data'); | ||||
|                     li.addClass("red-ui-editableList-item-deleting") | ||||
| @@ -293,6 +324,9 @@ | ||||
|                 },0); | ||||
|             } | ||||
|         }, | ||||
|         addItem: function(data) { | ||||
|             this.insertItemAt(data,this.element.children().length) | ||||
|         }, | ||||
|         addItems: function(items) { | ||||
|             for (var i=0; i<items.length;i++) { | ||||
|                 this.addItem(items[i]); | ||||
| @@ -312,6 +346,7 @@ | ||||
|         }, | ||||
|         empty: function() { | ||||
|             this.element.empty(); | ||||
|             this.uiContainer.scrollTop(0); | ||||
|         }, | ||||
|         filter: function(filter) { | ||||
|             if (filter !== undefined) { | ||||
| @@ -327,6 +362,22 @@ | ||||
|         }, | ||||
|         length: function() { | ||||
|             return this.element.children().length; | ||||
|         }, | ||||
|         show: function(item) { | ||||
|             var items = this.element.children().filter(function(f) { | ||||
|                 return item === $(this).find(".red-ui-editableList-item-content").data('data'); | ||||
|             }); | ||||
|             if (items.length > 0) { | ||||
|                 this.uiContainer.scrollTop(this.uiContainer.scrollTop()+items.position().top) | ||||
|             } | ||||
|         }, | ||||
|         getItem: function(li) { | ||||
|             var el = li.find(".red-ui-editableList-item-content"); | ||||
|             if (el.length) { | ||||
|                 return el.data('data'); | ||||
|             } else { | ||||
|                 return null; | ||||
|             } | ||||
|         } | ||||
|     }); | ||||
| })(jQuery); | ||||
|   | ||||
| @@ -56,12 +56,12 @@ RED.menu = (function() { | ||||
|         } | ||||
|  | ||||
|         if (opt === null) { | ||||
|             item = $('<li class="divider"></li>'); | ||||
|             item = $('<li class="red-ui-menu-divider"></li>'); | ||||
|         } else { | ||||
|             item = $('<li></li>'); | ||||
|  | ||||
|             if (opt.group) { | ||||
|                 item.addClass("menu-group-"+opt.group); | ||||
|                 item.addClass("red-ui-menu-group-"+opt.group); | ||||
|  | ||||
|             } | ||||
|             var linkContent = '<a '+(opt.id?'id="'+opt.id+'" ':'')+'tabindex="-1" href="#">'; | ||||
| @@ -71,7 +71,7 @@ RED.menu = (function() { | ||||
|  | ||||
|             } | ||||
|             if (opt.icon !== undefined) { | ||||
|                 if (/\.png/.test(opt.icon)) { | ||||
|                 if (/\.(png|svg)/.test(opt.icon)) { | ||||
|                     linkContent += '<img src="'+opt.icon+'"/> '; | ||||
|                 } else { | ||||
|                     linkContent += '<i class="'+(opt.icon?opt.icon:'" style="display: inline-block;"')+'"></i> '; | ||||
| @@ -79,10 +79,10 @@ RED.menu = (function() { | ||||
|             } | ||||
|  | ||||
|             if (opt.sublabel) { | ||||
|                 linkContent += '<span class="menu-label-container"><span class="menu-label">'+opt.label+'</span>'+ | ||||
|                                '<span class="menu-sublabel">'+opt.sublabel+'</span></span>' | ||||
|                 linkContent += '<span class="red-ui-menu-label-container"><span class="red-ui-menu-label">'+opt.label+'</span>'+ | ||||
|                                '<span class="red-ui-menu-sublabel">'+opt.sublabel+'</span></span>' | ||||
|             } else { | ||||
|                 linkContent += '<span class="menu-label">'+opt.label+'</span>' | ||||
|                 linkContent += '<span class="red-ui-menu-label">'+opt.label+'</span>' | ||||
|             } | ||||
|  | ||||
|             linkContent += '</a>'; | ||||
| @@ -92,27 +92,16 @@ RED.menu = (function() { | ||||
|             menuItems[opt.id] = opt; | ||||
|  | ||||
|             if (opt.onselect) { | ||||
|                 link.click(function(e) { | ||||
|                 link.on("click", function(e) { | ||||
|                     e.preventDefault(); | ||||
|                     if ($(this).parent().hasClass("disabled")) { | ||||
|                         return; | ||||
|                     } | ||||
|                     if (opt.toggle) { | ||||
|                         var selected = isSelected(opt.id); | ||||
|                         if (typeof opt.toggle === "string") { | ||||
|                             if (!selected) { | ||||
|                                 for (var m in menuItems) { | ||||
|                                     if (menuItems.hasOwnProperty(m)) { | ||||
|                                         var mi = menuItems[m]; | ||||
|                                         if (mi.id != opt.id && opt.toggle == mi.toggle) { | ||||
|                                             setSelected(mi.id,false); | ||||
|                                         } | ||||
|                                     } | ||||
|                                 } | ||||
|                                 setSelected(opt.id,true); | ||||
|                             } | ||||
|                         if (opt.toggle === true) { | ||||
|                             setSelected(opt.id, !isSelected(opt.id)); | ||||
|                         } else { | ||||
|                             setSelected(opt.id, !selected); | ||||
|                             setSelected(opt.id, true); | ||||
|                         } | ||||
|                     } else { | ||||
|                         triggerAction(opt.id); | ||||
| @@ -125,13 +114,13 @@ RED.menu = (function() { | ||||
|                 link.attr("target","_blank").attr("href",opt.href); | ||||
|             } else if (!opt.options) { | ||||
|                 item.addClass("disabled"); | ||||
|                 link.click(function(event) { | ||||
|                 link.on("click", function(event) { | ||||
|                     event.preventDefault(); | ||||
|                 }); | ||||
|             } | ||||
|             if (opt.options) { | ||||
|                 item.addClass("dropdown-submenu pull-left"); | ||||
|                 var submenu = $('<ul id="'+opt.id+'-submenu" class="dropdown-menu"></ul>').appendTo(item); | ||||
|                 item.addClass("red-ui-menu-dropdown-submenu pull-left"); | ||||
|                 var submenu = $('<ul id="'+opt.id+'-submenu" class="red-ui-menu-dropdown"></ul>').appendTo(item); | ||||
|  | ||||
|                 for (var i=0;i<opt.options.length;i++) { | ||||
|                     var li = createMenuItem(opt.options[i]); | ||||
| @@ -150,13 +139,29 @@ RED.menu = (function() { | ||||
|  | ||||
|     } | ||||
|     function createMenu(options) { | ||||
|         var topMenu = $("<ul/>",{class:"dropdown-menu pull-right"}); | ||||
|         var topMenu = $("<ul/>",{class:"red-ui-menu red-ui-menu-dropdown pull-right"}); | ||||
|  | ||||
|         if (options.id) { | ||||
|             topMenu.attr({id:options.id+"-submenu"}); | ||||
|             var menuParent = $("#"+options.id); | ||||
|             if (menuParent.length === 1) { | ||||
|                 topMenu.insertAfter(menuParent); | ||||
|                 menuParent.on("click", function(evt) { | ||||
|                     evt.stopPropagation(); | ||||
|                     evt.preventDefault(); | ||||
|                     if (topMenu.is(":visible")) { | ||||
|                         $(document).off("click.red-ui-menu"); | ||||
|                         topMenu.hide(); | ||||
|                     } else { | ||||
|                         $(document).on("click.red-ui-menu", function(evt) { | ||||
|                             $(document).off("click.red-ui-menu"); | ||||
|                             activeMenu = null; | ||||
|                             topMenu.hide(); | ||||
|                         }); | ||||
|                         $(".red-ui-menu").hide(); | ||||
|                         topMenu.show(); | ||||
|                     } | ||||
|                 }) | ||||
|             } | ||||
|         } | ||||
|  | ||||
| @@ -193,8 +198,9 @@ RED.menu = (function() { | ||||
|     } | ||||
|  | ||||
|     function setSelected(id,state) { | ||||
|         var alreadySet = false; | ||||
|         if (isSelected(id) == state) { | ||||
|             return; | ||||
|             alreadySet = true; | ||||
|         } | ||||
|         var opt = menuItems[id]; | ||||
|         if (state) { | ||||
| @@ -202,10 +208,26 @@ RED.menu = (function() { | ||||
|         } else { | ||||
|             $("#"+id).removeClass("active"); | ||||
|         } | ||||
|         if (opt && opt.onselect) { | ||||
|             triggerAction(opt.id,state); | ||||
|         if (opt) { | ||||
|             if (opt.toggle && typeof opt.toggle === "string") { | ||||
|                 if (state) { | ||||
|                     for (var m in menuItems) { | ||||
|                         if (menuItems.hasOwnProperty(m)) { | ||||
|                             var mi = menuItems[m]; | ||||
|                             if (mi.id != opt.id && opt.toggle == mi.toggle) { | ||||
|                                 setSelected(mi.id,false); | ||||
|                             } | ||||
|                         } | ||||
|                     } | ||||
|                 } | ||||
|             } | ||||
|             if (!alreadySet && opt.onselect) { | ||||
|                 triggerAction(opt.id,state); | ||||
|             } | ||||
|             if (!opt.local && !alreadySet) { | ||||
|                 RED.settings.set(opt.setting||("menu-"+opt.id), state); | ||||
|             } | ||||
|         } | ||||
|         RED.settings.set(opt.setting||("menu-"+opt.id), state); | ||||
|     } | ||||
|  | ||||
|     function toggleSelected(id) { | ||||
| @@ -222,14 +244,14 @@ RED.menu = (function() { | ||||
|  | ||||
|     function addItem(id,opt) { | ||||
|         var item = createMenuItem(opt); | ||||
|         if (opt.group) { | ||||
|             var groupItems = $("#"+id+"-submenu").children(".menu-group-"+opt.group); | ||||
|         if (opt !== null && opt.group) { | ||||
|             var groupItems = $("#"+id+"-submenu").children(".red-ui-menu-group-"+opt.group); | ||||
|             if (groupItems.length === 0) { | ||||
|                 item.appendTo("#"+id+"-submenu"); | ||||
|             } else { | ||||
|                 for (var i=0;i<groupItems.length;i++) { | ||||
|                     var groupItem = groupItems[i]; | ||||
|                     var label = $(groupItem).find(".menu-label").html(); | ||||
|                     var label = $(groupItem).find(".red-ui-menu-label").html(); | ||||
|                     if (opt.label < label) { | ||||
|                         $(groupItem).before(item); | ||||
|                         break; | ||||
| @@ -263,6 +285,5 @@ RED.menu = (function() { | ||||
|         addItem: addItem, | ||||
|         removeItem: removeItem, | ||||
|         setAction: setAction | ||||
|         //TODO: add an api for replacing a submenu - see library.js:loadFlowLibrary | ||||
|     } | ||||
| })(); | ||||
|   | ||||
| @@ -21,6 +21,7 @@ RED.panels = (function() { | ||||
|         var container = options.container || $("#"+options.id); | ||||
|         var children = container.children(); | ||||
|         if (children.length !== 2) { | ||||
|             console.log(options.id); | ||||
|             throw new Error("Container must have exactly two children"); | ||||
|         } | ||||
|         var vertical = (!options.dir || options.dir === "vertical"); | ||||
| @@ -86,10 +87,10 @@ RED.panels = (function() { | ||||
|             resize: function(size) { | ||||
|                 var panelSizes; | ||||
|                 if (vertical) { | ||||
|                     panelSizes = [$(children[0]).height(),$(children[1]).height()]; | ||||
|                     panelSizes = [$(children[0]).outerHeight(),$(children[1]).outerHeight()]; | ||||
|                     container.height(size); | ||||
|                 } else { | ||||
|                     panelSizes = [$(children[0]).width(),$(children[1]).width()]; | ||||
|                     panelSizes = [$(children[0]).outerWidth(),$(children[1]).outerWidth()]; | ||||
|                     container.width(size); | ||||
|                 } | ||||
|                 if (modifiedSizes) { | ||||
| @@ -105,6 +106,11 @@ RED.panels = (function() { | ||||
|                     } | ||||
|                 } | ||||
|                 if (options.resize) { | ||||
|                     if (vertical) { | ||||
|                         panelSizes = [$(children[0]).height(),$(children[1]).height()]; | ||||
|                     } else { | ||||
|                         panelSizes = [$(children[0]).width(),$(children[1]).width()]; | ||||
|                     } | ||||
|                     options.resize(panelSizes[0],panelSizes[1]); | ||||
|                 } | ||||
|             } | ||||
|   | ||||
| @@ -52,6 +52,11 @@ RED.popover = (function() { | ||||
|  | ||||
|         var openPopup = function(instant) { | ||||
|             if (active) { | ||||
|                 var existingPopover = target.data("red-ui-popover"); | ||||
|                 if (options.tooltip && existingPopover) { | ||||
|                     active = false; | ||||
|                     return; | ||||
|                 } | ||||
|                 div = $('<div class="red-ui-popover"></div>'); | ||||
|                 if (size !== "default") { | ||||
|                     div.addClass("red-ui-popover-size-"+size); | ||||
| @@ -122,7 +127,15 @@ RED.popover = (function() { | ||||
|                     } | ||||
|                 } | ||||
|                 div.addClass('red-ui-popover-'+d).css({top: top, left: left}); | ||||
|  | ||||
|                 if (existingPopover) { | ||||
|                     existingPopover.close(true); | ||||
|                 } | ||||
|                 target.data("red-ui-popover",res) | ||||
|                 if (options.tooltip) { | ||||
|                     div.on("mousedown", function(evt) { | ||||
|                         closePopup(true); | ||||
|                     }); | ||||
|                 } | ||||
|                 if (instant) { | ||||
|                     div.show(); | ||||
|                 } else { | ||||
| @@ -131,7 +144,7 @@ RED.popover = (function() { | ||||
|             } | ||||
|         } | ||||
|         var closePopup = function(instant) { | ||||
|             $(document).off('mousedown.modal-popover-close'); | ||||
|             $(document).off('mousedown.red-ui-popover'); | ||||
|             if (!active) { | ||||
|                 if (div) { | ||||
|                     if (instant) { | ||||
| @@ -142,6 +155,7 @@ RED.popover = (function() { | ||||
|                         }); | ||||
|                     } | ||||
|                     div = null; | ||||
|                     target.removeData("red-ui-popover",res) | ||||
|                 } | ||||
|             } | ||||
|         } | ||||
| @@ -162,7 +176,7 @@ RED.popover = (function() { | ||||
|                 } | ||||
|             }); | ||||
|         } else if (trigger === 'click') { | ||||
|             target.click(function(e) { | ||||
|             target.on("click", function(e) { | ||||
|                 e.preventDefault(); | ||||
|                 e.stopPropagation(); | ||||
|                 active = !active; | ||||
| @@ -185,7 +199,7 @@ RED.popover = (function() { | ||||
|             } | ||||
|  | ||||
|         } else if (trigger === 'modal') { | ||||
|             $(document).on('mousedown.modal-popover-close', function (event) { | ||||
|             $(document).on('mousedown.red-ui-popover', function (event) { | ||||
|                 var target = event.target; | ||||
|                 while (target.nodeName !== 'BODY' && target !== div[0]) { | ||||
|                     target = target.parentElement; | ||||
| @@ -236,6 +250,7 @@ RED.popover = (function() { | ||||
|                 } | ||||
|             } | ||||
|             return RED.popover.create({ | ||||
|                 tooltip: true, | ||||
|                 target:target, | ||||
|                 trigger: "hover", | ||||
|                 size: "small", | ||||
| @@ -243,6 +258,71 @@ RED.popover = (function() { | ||||
|                 content: label, | ||||
|                 delay: { show: 750, hide: 50 } | ||||
|             }); | ||||
|         }, | ||||
|         panel: function(content) { | ||||
|             var panel = $('<div class="red-ui-editor-dialog red-ui-popover-panel"></div>'); | ||||
|             panel.css({ display: "none" }); | ||||
|             panel.appendTo(document.body); | ||||
|             content.appendTo(panel); | ||||
|             var closeCallback; | ||||
|  | ||||
|             function hide() { | ||||
|                 $(document).off("mousedown.red-ui-popover-panel-close"); | ||||
|                 panel.hide(); | ||||
|                 panel.css({ | ||||
|                     height: "auto" | ||||
|                 }); | ||||
|                 panel.remove(); | ||||
|             } | ||||
|             function show(options) { | ||||
|                 var closeCallback = options.onclose; | ||||
|                 var target = options.target; | ||||
|                 var align = options.align || "left"; | ||||
|  | ||||
|                 var pos = target.offset(); | ||||
|                 var targetWidth = target.width(); | ||||
|                 var targetHeight = target.height(); | ||||
|                 var panelHeight = panel.height(); | ||||
|                 var panelWidth = panel.width(); | ||||
|  | ||||
|                 var top = (targetHeight+pos.top); | ||||
|                 if (top+panelHeight > $(window).height()) { | ||||
|                     top -= (top+panelHeight)-$(window).height() + 5; | ||||
|                 } | ||||
|                 if (top < 0) { | ||||
|                     panelHeight.height(panelHeight+top) | ||||
|                     top = 0; | ||||
|                 } | ||||
|                 if (align === "left") { | ||||
|                     panel.css({ | ||||
|                         top: top+"px", | ||||
|                         left: (pos.left)+"px", | ||||
|                     }); | ||||
|                 } else if(align === "right") { | ||||
|                     panel.css({ | ||||
|                         top: top+"px", | ||||
|                         left: (pos.left-panelWidth)+"px", | ||||
|                     }); | ||||
|                 } | ||||
|                 panel.slideDown(100); | ||||
|  | ||||
|                 $(document).on("mousedown.red-ui-popover-panel-close", function(event) { | ||||
|                     if(!$(event.target).closest(panel).length && !$(event.target).closest(".red-ui-editor-dialog").length) { | ||||
|                         if (closeCallback) { | ||||
|                             closeCallback(); | ||||
|                         } | ||||
|                         hide(); | ||||
|                     } | ||||
|                     // if ($(event.target).closest(target).length) { | ||||
|                     //     event.preventDefault(); | ||||
|                     // } | ||||
|                 }) | ||||
|             } | ||||
|             return  { | ||||
|                 container: panel, | ||||
|                 show:show, | ||||
|                 hide:hide | ||||
|             } | ||||
|         } | ||||
|     } | ||||
|  | ||||
|   | ||||
| @@ -15,6 +15,19 @@ | ||||
|  **/ | ||||
| (function($) { | ||||
|  | ||||
| /** | ||||
|  * options: | ||||
|  *   - minimumLength : the minimum length of text before firing a change event | ||||
|  *   - delay : delay, in ms, after a keystroke before firing change event | ||||
|  * | ||||
|  * methods: | ||||
|  *   - value([val]) - gets the current value, or, if `val` is provided, sets the value | ||||
|  *   - count - sets or clears a sub-label on the input. This can be used to provide | ||||
|  *             a feedback on the number of matches, or number of available entries to search | ||||
|  *   - change - trigger a change event | ||||
|  * | ||||
|  */ | ||||
|  | ||||
|     $.widget( "nodered.searchBox", { | ||||
|         _create: function() { | ||||
|             var that = this; | ||||
| @@ -22,6 +35,7 @@ | ||||
|             this.currentTimeout = null; | ||||
|             this.lastSent = ""; | ||||
|             this.element.val(""); | ||||
|             this.element.addClass("red-ui-searchBox-input"); | ||||
|             this.uiContainer = this.element.wrap("<div>").parent(); | ||||
|             this.uiContainer.addClass("red-ui-searchBox-container"); | ||||
|  | ||||
| @@ -31,7 +45,7 @@ | ||||
|                 e.preventDefault(); | ||||
|                 that.element.val(""); | ||||
|                 that._change("",true); | ||||
|                 that.element.focus(); | ||||
|                 that.element.trigger("focus"); | ||||
|             }); | ||||
|  | ||||
|             this.resultCount = $('<span>',{class:"red-ui-searchBox-resultCount hide"}).appendTo(this.uiContainer); | ||||
| @@ -47,7 +61,7 @@ | ||||
|             }); | ||||
|  | ||||
|             this.element.on("focus",function() { | ||||
|                 $("body").one("mousedown",function() { | ||||
|                 $(document).one("mousedown",function() { | ||||
|                     that.element.blur(); | ||||
|                 }); | ||||
|             }); | ||||
| @@ -73,6 +87,7 @@ | ||||
|                         that._trigger("change"); | ||||
|                     },this.options.delay); | ||||
|                 } else { | ||||
|                     this.lastSent = this.element.val(); | ||||
|                     this._trigger("change"); | ||||
|                 } | ||||
|             } | ||||
|   | ||||
| @@ -39,17 +39,17 @@ RED.stack = (function() { | ||||
|             } | ||||
|         } | ||||
|         if (options.fill && options.singleExpanded) { | ||||
|             $(window).resize(resizeStack); | ||||
|             $(window).focus(resizeStack); | ||||
|             $(window).on("resize", resizeStack); | ||||
|             $(window).on("focus", resizeStack); | ||||
|         } | ||||
|         return { | ||||
|             add: function(entry) { | ||||
|                 entries.push(entry); | ||||
|                 entry.container = $('<div class="palette-category">').appendTo(container); | ||||
|                 entry.container = $('<div class="red-ui-palette-category">').appendTo(container); | ||||
|                 if (!visible) { | ||||
|                     entry.container.hide(); | ||||
|                 } | ||||
|                 var header = $('<div class="palette-header"></div>').appendTo(entry.container); | ||||
|                 var header = $('<div class="red-ui-palette-header"></div>').appendTo(entry.container); | ||||
|                 entry.header = header; | ||||
|                 entry.contentWrap = $('<div></div>',{style:"position:relative"}).appendTo(entry.container); | ||||
|                 if (options.fill) { | ||||
| @@ -57,7 +57,7 @@ RED.stack = (function() { | ||||
|                 } | ||||
|                 entry.content = $('<div></div>').appendTo(entry.contentWrap); | ||||
|                 if (entry.collapsible !== false) { | ||||
|                     header.click(function() { | ||||
|                     header.on("click", function() { | ||||
|                         if (options.singleExpanded) { | ||||
|                             if (!entry.isExpanded()) { | ||||
|                                 for (var i=0;i<entries.length;i++) { | ||||
| @@ -82,7 +82,7 @@ RED.stack = (function() { | ||||
|                     var icon = $('<i class="fa fa-angle-down"></i>').appendTo(header); | ||||
|  | ||||
|                     if (entry.expanded) { | ||||
|                         entry.container.addClass("palette-category-expanded"); | ||||
|                         entry.container.addClass("expanded"); | ||||
|                         icon.addClass("expanded"); | ||||
|                     } else { | ||||
|                         entry.contentWrap.hide(); | ||||
| @@ -118,7 +118,7 @@ RED.stack = (function() { | ||||
|                         } | ||||
|  | ||||
|                         icon.addClass("expanded"); | ||||
|                         entry.container.addClass("palette-category-expanded"); | ||||
|                         entry.container.addClass("expanded"); | ||||
|                         entry.contentWrap.slideDown(200); | ||||
|                         return true; | ||||
|                     } | ||||
| @@ -126,13 +126,13 @@ RED.stack = (function() { | ||||
|                 entry.collapse = function() { | ||||
|                     if (entry.isExpanded()) { | ||||
|                         icon.removeClass("expanded"); | ||||
|                         entry.container.removeClass("palette-category-expanded"); | ||||
|                         entry.container.removeClass("expanded"); | ||||
|                         entry.contentWrap.slideUp(200); | ||||
|                         return true; | ||||
|                     } | ||||
|                 }; | ||||
|                 entry.isExpanded = function() { | ||||
|                     return entry.container.hasClass("palette-category-expanded"); | ||||
|                     return entry.container.hasClass("expanded"); | ||||
|                 }; | ||||
|                 if (options.fill && options.singleExpanded) { | ||||
|                     resizeStack(); | ||||
|   | ||||
| @@ -19,6 +19,9 @@ | ||||
| RED.tabs = (function() { | ||||
|  | ||||
|     var defaultTabIcon = "fa fa-lemon-o"; | ||||
|     var dragActive = false; | ||||
|     var dblClickTime; | ||||
|     var dblClickArmed = false; | ||||
|  | ||||
|     function createTabs(options) { | ||||
|         var tabs = {}; | ||||
| @@ -36,8 +39,8 @@ RED.tabs = (function() { | ||||
|         } | ||||
|         if (options.addButton) { | ||||
|             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) { | ||||
|             var addButton = $('<div class="red-ui-tab-button red-ui-tabs-add"><a href="#"><i class="fa fa-plus"></i></a></div>').appendTo(wrapper); | ||||
|             addButton.find('a').on("click", function(evt) { | ||||
|                 evt.preventDefault(); | ||||
|                 if (typeof options.addButton === 'function') { | ||||
|                     options.addButton(); | ||||
| @@ -69,7 +72,25 @@ RED.tabs = (function() { | ||||
|                     RED.actions.invoke(options.addButton,{index:targetIndex}); | ||||
|                 } | ||||
|             }); | ||||
|  | ||||
|         } | ||||
|         if (options.searchButton) { | ||||
|             wrapper.addClass("red-ui-tabs-search"); | ||||
|             var searchButton = $('<div class="red-ui-tab-button red-ui-tabs-search"><a href="#"><i class="fa fa-list-ul"></i></a></div>').appendTo(wrapper); | ||||
|             searchButton.find('a').on("click", function(evt) { | ||||
|                 evt.preventDefault(); | ||||
|                 if (typeof options.searchButton === 'function') { | ||||
|                     options.searchButton() | ||||
|                 } else if (typeof options.searchButton === 'string') { | ||||
|                     RED.actions.invoke(options.searchButton); | ||||
|                 } | ||||
|             }) | ||||
|             if (typeof options.searchButton === 'string') { | ||||
|                 var l = options.searchButton; | ||||
|                 if (options.searchButtonCaption) { | ||||
|                     l = options.searchButtonCaption | ||||
|                 } | ||||
|                 RED.popover.tooltip(searchButton,l,options.searchButton); | ||||
|             } | ||||
|  | ||||
|         } | ||||
|         var scrollLeft; | ||||
| @@ -78,7 +99,7 @@ RED.tabs = (function() { | ||||
|         if (options.scrollable) { | ||||
|             wrapper.addClass("red-ui-tabs-scrollable"); | ||||
|             scrollContainer.addClass("red-ui-tabs-scroll-container"); | ||||
|             scrollContainer.scroll(updateScroll); | ||||
|             scrollContainer.on("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"); | ||||
| @@ -95,7 +116,7 @@ RED.tabs = (function() { | ||||
|             if (options.menu !== false) { | ||||
|                 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) { | ||||
|                 selectButton.on("click", function(evt) { | ||||
|                     evt.stopPropagation(); | ||||
|                     evt.preventDefault(); | ||||
|                     if (!collapsibleMenu) { | ||||
| @@ -118,7 +139,7 @@ RED.tabs = (function() { | ||||
|                             } | ||||
|                         }); | ||||
|                         options = pinnedOptions.concat(options); | ||||
|                         collapsibleMenu = RED.menu.init({id:"debug-message-option-menu",options: options}); | ||||
|                         collapsibleMenu = RED.menu.init({options: options}); | ||||
|                         collapsibleMenu.css({ | ||||
|                             position: "absolute" | ||||
|                         }) | ||||
| @@ -130,10 +151,11 @@ RED.tabs = (function() { | ||||
|                         left: (elementPos.left - collapsibleMenu.width() + selectButton.width())+"px" | ||||
|                     }) | ||||
|                     if (collapsibleMenu.is(":visible")) { | ||||
|                         $(document).off("click.tabmenu"); | ||||
|                         $(document).off("click.red-ui-tabmenu"); | ||||
|                     } else { | ||||
|                         $(document).on("click.tabmenu", function(evt) { | ||||
|                             $(document).off("click.tabmenu"); | ||||
|                         $(".red-ui-menu").hide(); | ||||
|                         $(document).on("click.red-ui-tabmenu", function(evt) { | ||||
|                             $(document).off("click.red-ui-tabmenu"); | ||||
|                             collapsibleMenu.hide(); | ||||
|                         }); | ||||
|                     } | ||||
| @@ -182,12 +204,21 @@ RED.tabs = (function() { | ||||
|         } | ||||
|  | ||||
|         function onTabClick(evt) { | ||||
|             evt.preventDefault(); | ||||
|             if (dragActive) { | ||||
|                 return | ||||
|             } | ||||
|             if (dblClickTime && Date.now()-dblClickTime < 400) { | ||||
|                 dblClickTime = 0; | ||||
|                 dblClickArmed = true; | ||||
|                 return onTabDblClick.call(this,evt); | ||||
|             } | ||||
|             dblClickTime = Date.now(); | ||||
|  | ||||
|             var currentTab = ul.find("li.red-ui-tab.active"); | ||||
|             var thisTab = $(this).parent(); | ||||
|             var fireSelectionChanged = false; | ||||
|             if (options.onselect) { | ||||
|                 if (evt.metaKey) { | ||||
|                 if (evt.metaKey || evt.ctrlKey) { | ||||
|                     if (thisTab.hasClass("selected")) { | ||||
|                         thisTab.removeClass("selected"); | ||||
|                         if (thisTab[0] !== currentTab[0]) { | ||||
| @@ -248,7 +279,6 @@ RED.tabs = (function() { | ||||
|             if (fireSelectionChanged) { | ||||
|                 selectionChanged(); | ||||
|             } | ||||
|             return false; | ||||
|         } | ||||
|  | ||||
|         function updateScroll() { | ||||
| @@ -270,7 +300,6 @@ RED.tabs = (function() { | ||||
|         } | ||||
|         function onTabDblClick(evt) { | ||||
|             evt.preventDefault(); | ||||
|             evt.stopPropagation(); | ||||
|             if (evt.metaKey || evt.shiftKey) { | ||||
|                 return; | ||||
|             } | ||||
| @@ -330,7 +359,7 @@ RED.tabs = (function() { | ||||
|             } | ||||
|             var tabs = ul.find("li.red-ui-tab"); | ||||
|             var width = wrapper.width(); | ||||
|             var tabCount = tabs.size(); | ||||
|             var tabCount = tabs.length; | ||||
|             var tabWidth; | ||||
|  | ||||
|             if (options.collapsible) { | ||||
| @@ -399,7 +428,11 @@ RED.tabs = (function() { | ||||
|  | ||||
|         } | ||||
|  | ||||
|         ul.find("li.red-ui-tab a").on("click",onTabClick).on("dblclick",onTabDblClick); | ||||
|         ul.find("li.red-ui-tab a") | ||||
|             .on("mouseup",onTabClick) | ||||
|             .on("click", function(evt) {evt.preventDefault(); }) | ||||
|             .on("dblclick", function(evt) {evt.stopPropagation(); evt.preventDefault(); }) | ||||
|  | ||||
|         setTimeout(function() { | ||||
|             updateTabWidths(); | ||||
|         },0); | ||||
| @@ -416,7 +449,7 @@ RED.tabs = (function() { | ||||
|             var li = ul.find("a[href='#"+id+"']").parent(); | ||||
|             if (li.hasClass("active")) { | ||||
|                 var tab = li.prev(); | ||||
|                 if (tab.size() === 0) { | ||||
|                 if (tab.length === 0) { | ||||
|                     tab = li.next(); | ||||
|                 } | ||||
|                 activateTab(tab.find("a")); | ||||
| @@ -430,7 +463,10 @@ RED.tabs = (function() { | ||||
|             } | ||||
|             delete tabs[id]; | ||||
|             updateTabWidths(); | ||||
|             collapsibleMenu = null; | ||||
|             if (collapsibleMenu) { | ||||
|                 collapsibleMenu.remove(); | ||||
|                 collapsibleMenu = null; | ||||
|             } | ||||
|         } | ||||
|  | ||||
|         return { | ||||
| @@ -466,7 +502,7 @@ RED.tabs = (function() { | ||||
|                 } else if (tab.iconClass) { | ||||
|                     $('<i>',{class:"red-ui-tab-icon "+tab.iconClass}).appendTo(link); | ||||
|                 } | ||||
|                 var span = $('<span/>',{class:"bidiAware"}).text(tab.label).appendTo(link); | ||||
|                 var span = $('<span/>',{class:"red-ui-text-bidi-aware"}).text(tab.label).appendTo(link); | ||||
|                 span.attr('dir', RED.text.bidi.resolveBaseTextDir(tab.label)); | ||||
|                 if (options.collapsible) { | ||||
|                     li.addClass("red-ui-tab-pinned"); | ||||
| @@ -491,7 +527,7 @@ RED.tabs = (function() { | ||||
|                     } else { | ||||
|                         $('<i>',{class:defaultTabIcon}).appendTo(pinnedLink); | ||||
|                     } | ||||
|                     pinnedLink.click(function(evt) { | ||||
|                     pinnedLink.on("click", function(evt) { | ||||
|                         evt.preventDefault(); | ||||
|                         activateTab(tab.id); | ||||
|                     }); | ||||
| @@ -502,8 +538,9 @@ RED.tabs = (function() { | ||||
|                     RED.popover.tooltip($(pinnedLink), tab.name, tab.action); | ||||
|  | ||||
|                 } | ||||
|                 link.on("click",onTabClick); | ||||
|                 link.on("dblclick",onTabDblClick); | ||||
|                 link.on("mouseup",onTabClick); | ||||
|                 link.on("click", function(evt) { evt.preventDefault(); }) | ||||
|                 link.on("dblclick", function(evt) { evt.stopPropagation(); evt.preventDefault(); }) | ||||
|  | ||||
|  | ||||
|                 if (tab.closeable) { | ||||
| @@ -525,7 +562,7 @@ RED.tabs = (function() { | ||||
|                     options.onadd(tab); | ||||
|                 } | ||||
|                 link.attr("title",tab.label); | ||||
|                 if (ul.find("li.red-ui-tab").size() == 1) { | ||||
|                 if (ul.find("li.red-ui-tab").length == 1) { | ||||
|                     activateTab(link); | ||||
|                 } | ||||
|                 if (options.onreorder) { | ||||
| @@ -538,6 +575,8 @@ RED.tabs = (function() { | ||||
|                         axis:"x", | ||||
|                         distance: 20, | ||||
|                         start: function(event,ui) { | ||||
|                             if (dblClickArmed) { dblClickArmed = false; return false } | ||||
|                             dragActive = true; | ||||
|                             originalTabOrder = []; | ||||
|                             tabElements = []; | ||||
|                             ul.children().each(function(i) { | ||||
| @@ -593,6 +632,7 @@ RED.tabs = (function() { | ||||
|                             } | ||||
|                         }, | ||||
|                         stop: function(event,ui) { | ||||
|                             dragActive = false; | ||||
|                             ul.children().css({position:"relative",left:"",transition:""}); | ||||
|                             if (!li.hasClass('active')) { | ||||
|                                 li.css({zIndex:""}); | ||||
| @@ -608,7 +648,10 @@ RED.tabs = (function() { | ||||
|                 setTimeout(function() { | ||||
|                     updateTabWidths(); | ||||
|                 },10); | ||||
|                 collapsibleMenu = null; | ||||
|                 if (collapsibleMenu) { | ||||
|                     collapsibleMenu.remove(); | ||||
|                     collapsibleMenu = null; | ||||
|                 } | ||||
|             }, | ||||
|             removeTab: removeTab, | ||||
|             activateTab: activateTab, | ||||
| @@ -616,7 +659,7 @@ RED.tabs = (function() { | ||||
|             previousTab: activatePreviousTab, | ||||
|             resize: updateTabWidths, | ||||
|             count: function() { | ||||
|                 return ul.find("li.red-ui-tab").size(); | ||||
|                 return ul.find("li.red-ui-tab").length; | ||||
|             }, | ||||
|             contains: function(id) { | ||||
|                 return ul.find("a[href='#"+id+"']").length > 0; | ||||
| @@ -625,7 +668,7 @@ RED.tabs = (function() { | ||||
|                 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)); | ||||
|                 tab.find("span.red-ui-text-bidi-aware").text(label).attr('dir', RED.text.bidi.resolveBaseTextDir(label)); | ||||
|                 updateTabWidths(); | ||||
|             }, | ||||
|             selection: getSelection, | ||||
|   | ||||
							
								
								
									
										100
									
								
								packages/node_modules/@node-red/editor-client/src/js/ui/common/toggleButton.js
									
									
									
									
										vendored
									
									
										Normal file
									
								
							
							
						
						| @@ -0,0 +1,100 @@ | ||||
| /** | ||||
|  * 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: | ||||
|  *   - invertState   : boolean - if "true" the button will show "enabled" when the | ||||
|  *                             checkbox is not selected and vice versa. | ||||
|  *   - enabledIcon   : string - the icon for "enabled" state, default "fa-check-square-o" | ||||
|  *   - enabledLabel  : string - the label for "enabled" state, default "Enabled" ("editor:workspace.enabled") | ||||
|  *   - disabledIcon  : string - the icon for "disabled" state, default "fa-square-o" | ||||
|  *   - disabledLabel : string - the label for "disabled" state, default "Disabled" ("editor:workspace.disabled") | ||||
|  *   - baseClass     : string - the base css class to apply, default "red-ui-button" (alternative eg "red-ui-sidebar-header-button") | ||||
|  *   - class         : string - additional classes to apply to the button - eg "red-ui-button-small" | ||||
|  * methods: | ||||
|  *   - | ||||
|  */ | ||||
|     $.widget( "nodered.toggleButton", { | ||||
|         _create: function() { | ||||
|             var that = this; | ||||
|  | ||||
|             var invertState = false; | ||||
|             if (this.options.hasOwnProperty("invertState")) { | ||||
|                 invertState = this.options.invertState; | ||||
|             } | ||||
|             var baseClass = this.options.baseClass || "red-ui-button"; | ||||
|             var enabledIcon = this.options.enabledIcon || "fa-check-square-o"; | ||||
|             var disabledIcon = this.options.disabledIcon || "fa-square-o"; | ||||
|             var enabledLabel = this.options.hasOwnProperty('enabledLabel') ? this.options.enabledLabel : RED._("editor:workspace.enabled"); | ||||
|             var disabledLabel = this.options.hasOwnProperty('disabledLabel') ? this.options.disabledLabel : RED._("editor:workspace.disabled"); | ||||
|  | ||||
|             this.element.css("display","none"); | ||||
|             this.element.on("focus", function() { | ||||
|                 that.button.focus(); | ||||
|             }); | ||||
|             this.button = $('<button type="button" class="red-ui-toggleButton '+baseClass+' toggle single"><i class="fa"></i> <span></span></button>'); | ||||
|             if (this.options.class) { | ||||
|                 this.button.addClass(this.options.class) | ||||
|             } | ||||
|             this.element.after(this.button); | ||||
|             this.buttonIcon = this.button.find("i"); | ||||
|             this.buttonLabel = this.button.find("span"); | ||||
|  | ||||
|             // Quick hack to find the maximum width of the button | ||||
|             this.button.addClass("selected"); | ||||
|             this.buttonIcon.addClass(enabledIcon); | ||||
|             this.buttonLabel.text(enabledLabel); | ||||
|             var width = this.button.width(); | ||||
|             this.button.removeClass("selected"); | ||||
|             this.buttonIcon.removeClass(enabledIcon); | ||||
|             that.buttonIcon.addClass(disabledIcon); | ||||
|             that.buttonLabel.text(disabledLabel); | ||||
|             width = Math.max(width,this.button.width()); | ||||
|             this.buttonIcon.removeClass(disabledIcon); | ||||
|  | ||||
|             // Fix the width of the button so it doesn't jump around when toggled | ||||
|             if (width > 0) { | ||||
|                 this.button.width(Math.ceil(width)); | ||||
|             } | ||||
|  | ||||
|             this.button.on("click",function(e) { | ||||
|                 e.stopPropagation(); | ||||
|                 if (that.buttonIcon.hasClass(disabledIcon)) { | ||||
|                     that.element.prop("checked",!invertState); | ||||
|                 } else { | ||||
|                     that.element.prop("checked",invertState); | ||||
|                 } | ||||
|                 that.element.trigger("change"); | ||||
|             }) | ||||
|  | ||||
|             this.element.on("change", function(e) { | ||||
|                 if ($(this).prop("checked") !== invertState) { | ||||
|                     that.button.addClass("selected"); | ||||
|                     that.buttonIcon.addClass(enabledIcon); | ||||
|                     that.buttonIcon.removeClass(disabledIcon); | ||||
|                     that.buttonLabel.text(enabledLabel); | ||||
|                 } else { | ||||
|                     that.button.removeClass("selected"); | ||||
|                     that.buttonIcon.addClass(disabledIcon); | ||||
|                     that.buttonIcon.removeClass(enabledIcon); | ||||
|                     that.buttonLabel.text(disabledLabel); | ||||
|                 } | ||||
|             }) | ||||
|             this.element.trigger("change"); | ||||
|         } | ||||
|     }); | ||||
| })(jQuery); | ||||