Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13979389ca | ||
|
|
350a52935a | ||
|
|
945e57bb43 | ||
|
|
3c374a2891 | ||
|
|
c9074bd8d9 | ||
|
|
bc685c59e0 | ||
|
|
aa53ad38fc | ||
|
|
875442f1ce | ||
|
|
a8c071f04c | ||
|
|
ef6c9c66af | ||
|
|
3df38447e9 | ||
|
|
338aabc02f | ||
|
|
912717ebf9 | ||
|
|
9f1a2ec625 | ||
|
|
93f0a69c53 | ||
|
|
2846522450 | ||
|
|
be8374d100 | ||
|
|
399f63cef6 | ||
|
|
adf8f7b69a | ||
|
|
8e9206bdee | ||
|
|
1946ba150d | ||
|
|
60cb5fb017 | ||
|
|
1892a17855 | ||
|
|
588e051f0f | ||
|
|
1c5857f064 | ||
|
|
1067542b94 | ||
|
|
538e197147 | ||
|
|
36db6c6e2d | ||
|
|
e53b63541e | ||
|
|
d6ca13a61d | ||
|
|
7caf817c81 | ||
|
|
286617e7be | ||
|
|
a423f7883e | ||
|
|
6d949ccdb4 | ||
|
|
0e0ac36788 | ||
|
|
99ab6d13d4 | ||
|
|
dcf7232958 | ||
|
|
a4408b55ed | ||
|
|
06f0ceebd1 | ||
|
|
5fe78a477c | ||
|
|
7ef8de50bd | ||
|
|
6646b8638e | ||
|
|
46840c9373 | ||
|
|
76bd3bfe1d | ||
|
|
2a2ed1eb2c | ||
|
|
a533605608 | ||
|
|
7749c0bd9a | ||
|
|
a37caf459e | ||
|
|
1c0a1e021a | ||
|
|
f483b162ce | ||
|
|
42fad8fb98 | ||
|
|
316acd0366 | ||
|
|
f80ecded0a | ||
|
|
40a5422e75 | ||
|
|
726fd5d60d | ||
|
|
211656e9da | ||
|
|
5eb4eb04c4 | ||
|
|
fb3b47e2bb | ||
|
|
14ac099e87 | ||
|
|
f83ee124d0 | ||
|
|
59ee616304 | ||
|
|
25989b9736 | ||
|
|
fef6433b75 | ||
|
|
ea72ce1fa2 | ||
|
|
26e326a204 | ||
|
|
ebb356cf2d | ||
|
|
d6142e4b75 | ||
|
|
c7b554afd9 | ||
|
|
30c1b5cca8 | ||
|
|
0c58bcf99c | ||
|
|
f3d58339ae | ||
|
|
67c6dd7bee | ||
|
|
f2d52b55c8 | ||
|
|
8c72531e6d | ||
|
|
b2f19ed714 | ||
|
|
e5359dc838 | ||
|
|
6fd3c0fa6b | ||
|
|
981a641bce | ||
|
|
47c70f03a2 | ||
|
|
030359aa0e | ||
|
|
81c9bb6899 | ||
|
|
4d192a0165 | ||
|
|
33a8de7bb5 | ||
|
|
9125ab440d | ||
|
|
1c966ed7b4 | ||
|
|
6a4b03324c | ||
|
|
4a8dcde8ee | ||
|
|
c2139662cd | ||
|
|
c0ecfb87b0 | ||
|
|
7673c77c57 | ||
|
|
66c2140911 | ||
|
|
ea3144492e | ||
|
|
10a9306abd | ||
|
|
76aae41637 | ||
|
|
49071ca5fd | ||
|
|
08e3ca3435 | ||
|
|
6b7b464acc | ||
|
|
767d8e66e7 | ||
|
|
e30edce73e | ||
|
|
f5796faa84 | ||
|
|
b48297df22 | ||
|
|
c262620993 | ||
|
|
41685536d7 | ||
|
|
92052458f5 | ||
|
|
6c3170360b | ||
|
|
cd3a27941c | ||
|
|
8a98f03f1a | ||
|
|
5552c17eba | ||
|
|
92733b24d1 | ||
|
|
806ad78637 | ||
|
|
9e557f6887 | ||
|
|
ad9daba60d | ||
|
|
2c92524cf4 | ||
|
|
06e374f0ff | ||
|
|
48ba81eb3d | ||
|
|
0767f50af8 | ||
|
|
68610e5066 | ||
|
|
ba9e2debe2 | ||
|
|
6c8a5cc580 | ||
|
|
3a7eece244 | ||
|
|
bf27ffb92e | ||
|
|
3fc9c6efe7 | ||
|
|
fe2015735a | ||
|
|
2ab34d3b87 | ||
|
|
79ea4d6d1e | ||
|
|
54f7361767 | ||
|
|
0a7ffe4cb0 | ||
|
|
0e714a90e0 | ||
|
|
5e3a9dc059 | ||
|
|
6e1ef3d94a | ||
|
|
bf48d4371c | ||
|
|
2f2aa7b08a | ||
|
|
20b0422024 | ||
|
|
dcb9fb7465 | ||
|
|
3a287a494b | ||
|
|
0926943670 | ||
|
|
06e26d8d89 | ||
|
|
94953a1c97 | ||
|
|
02e9795816 | ||
|
|
c29cff3822 | ||
|
|
29216599e4 | ||
|
|
3b65113d05 | ||
|
|
a182482cfb | ||
|
|
9022e9949f | ||
|
|
cecf69af02 | ||
|
|
b7dbeba7de | ||
|
|
c6ee58ef88 | ||
|
|
1b3135a79f | ||
|
|
131959e050 | ||
|
|
3f3b4746a9 | ||
|
|
30d154724a | ||
|
|
16130b3f73 | ||
|
|
47427f89b0 | ||
|
|
384d80a647 | ||
|
|
43d11af631 | ||
|
|
9bda4372a5 | ||
|
|
61223503e3 | ||
|
|
4d2ad079dc | ||
|
|
50c071682b | ||
|
|
015ccb7a28 | ||
|
|
b9aed314f3 | ||
|
|
452e2e2408 | ||
|
|
9370c1d472 | ||
|
|
8143dc9196 | ||
|
|
98ba18b052 | ||
|
|
9860f20be3 | ||
|
|
cfbb06ed1f | ||
|
|
e39760eb19 | ||
|
|
b3da55f85c | ||
|
|
bc4b637f06 | ||
|
|
c993c8f47e | ||
|
|
40470bedb3 | ||
|
|
912479baa4 | ||
|
|
cfbf3e320c | ||
|
|
4431ec5a27 | ||
|
|
d7784a8d38 | ||
|
|
2c4ed5f298 | ||
|
|
6a97aeb60c | ||
|
|
c7dc912dd4 | ||
|
|
0ee886692e | ||
|
|
34fef627a1 | ||
|
|
52d36d3780 | ||
|
|
8555c24eb2 | ||
|
|
c41c26e5a1 | ||
|
|
35cc9b3fcc | ||
|
|
dbfd219491 | ||
|
|
0da5f26668 | ||
|
|
8bf40e219a | ||
|
|
8f1f8c0fb9 | ||
|
|
386a65d6c6 | ||
|
|
a73ce72e46 | ||
|
|
d0616d8d67 | ||
|
|
6ad007a5f1 | ||
|
|
95d3e5cdc6 | ||
|
|
08a3506f12 | ||
|
|
520f295733 | ||
|
|
7da5121ddd | ||
|
|
3222625286 | ||
|
|
05d952b864 | ||
|
|
a3837ccbc7 | ||
|
|
ac8199177f | ||
|
|
140a134a11 | ||
|
|
c1b3e5367c | ||
|
|
b637a8e8ea | ||
|
|
999323526c | ||
|
|
2e0168283e | ||
|
|
13039c895a | ||
|
|
4148238af3 | ||
|
|
7a98445370 | ||
|
|
7ef3bba9f7 | ||
|
|
492306453c | ||
|
|
e12353bd7e | ||
|
|
a3622ddc1d | ||
|
|
ac95be9e41 | ||
|
|
4a3fc42d1f | ||
|
|
557f9709ac | ||
|
|
4468c71d98 | ||
|
|
c8491749e0 | ||
|
|
e5123f2d81 | ||
|
|
41664f16a3 | ||
|
|
8c9c0e9316 | ||
|
|
f21bd16cec | ||
|
|
edc5a5b6a2 | ||
|
|
7d4de21be0 | ||
|
|
5babe0358d | ||
|
|
62ef1fe7cc | ||
|
|
4be5727a18 | ||
|
|
e128a5775d | ||
|
|
ba9f9705d4 | ||
|
|
3aae07695c | ||
|
|
4393deb130 | ||
|
|
83ae1d4a19 | ||
|
|
94992fca44 | ||
|
|
a8af5343a7 | ||
|
|
070e8831b4 | ||
|
|
f177e416ee | ||
|
|
ffea7aff99 | ||
|
|
01b16566c8 | ||
|
|
549b15000b | ||
|
|
d05b84dff9 | ||
|
|
c6cad13f1e | ||
|
|
a8d1210655 | ||
|
|
45d33fa2e4 | ||
|
|
81ceb1ca0f | ||
|
|
923d26ad81 | ||
|
|
583f114c68 | ||
|
|
b29ec93c34 | ||
|
|
c7ee585a62 | ||
|
|
a7721b9048 | ||
|
|
184fd3abdd | ||
|
|
5fd2f1ee8a | ||
|
|
23218d3808 | ||
|
|
9b8de53bfe | ||
|
|
9130410f09 | ||
|
|
1f57a3f62e | ||
|
|
6938cec583 | ||
|
|
3c2cc351f4 | ||
|
|
ebeadeef60 | ||
|
|
7d59ae93f9 | ||
|
|
59e15d262f | ||
|
|
712417b379 | ||
|
|
cad55d57d7 | ||
|
|
cca7e59eb2 | ||
|
|
59a358903a | ||
|
|
2eadd3eb8b | ||
|
|
0261bb592e | ||
|
|
7862e280ec | ||
|
|
13fecfae27 | ||
|
|
b7819cad69 | ||
|
|
028fba9996 | ||
|
|
ce94433c46 | ||
|
|
442eefbe6b | ||
|
|
84c3b38052 | ||
|
|
8557d91468 | ||
|
|
949a3a1337 | ||
|
|
24288919e2 | ||
|
|
92c57fc91e | ||
|
|
9d1e7abd07 | ||
|
|
8dfdbe7a16 | ||
|
|
15fbe7ca50 | ||
|
|
9aa8bc8921 | ||
|
|
e90791fdbc | ||
|
|
b869e3efb6 | ||
|
|
7e8073d621 | ||
|
|
c10f7b6134 | ||
|
|
1a71abbc1d | ||
|
|
0a46d06c1f | ||
|
|
23595674cf | ||
|
|
6fead14c11 | ||
|
|
52d54f35a3 | ||
|
|
3c1eff6241 | ||
|
|
fb2972396a | ||
|
|
4d9f76cc68 | ||
|
|
924c579680 | ||
|
|
ca2ea2c13e | ||
|
|
b579dc598b | ||
|
|
04c5f60287 | ||
|
|
123789aff0 | ||
|
|
74b66fdcaf | ||
|
|
3f09b54e04 | ||
|
|
c39403c307 | ||
|
|
13ea7bf3d7 | ||
|
|
dc2835d341 | ||
|
|
94ff2d6a9e | ||
|
|
6479c6a5c5 | ||
|
|
a1ddf8e6d2 | ||
|
|
102b39cd29 | ||
|
|
b7373a27b8 | ||
|
|
fb0b762293 | ||
|
|
5b799b4536 | ||
|
|
8050d7353d | ||
|
|
66b1736bb3 | ||
|
|
f33ea5baf0 | ||
|
|
5959fd1fd0 | ||
|
|
c8ec8d456b | ||
|
|
87b394949e | ||
|
|
d93481d840 | ||
|
|
20fa441cfe | ||
|
|
46281542c5 | ||
|
|
5de6d5954a | ||
|
|
7a3c340d65 | ||
|
|
5e8669be4e | ||
|
|
df40384200 | ||
|
|
515556a784 | ||
|
|
af63259f09 | ||
|
|
bb807d53ba | ||
|
|
38279e2a32 | ||
|
|
3e6b396d09 | ||
|
|
42fc182832 | ||
|
|
3f1bba4f1a | ||
|
|
b008986122 | ||
|
|
26b30c817c | ||
|
|
b1083607d4 | ||
|
|
78f9a3303e | ||
|
|
a5519983fe | ||
|
|
bc0a879ca1 | ||
|
|
4c016169c5 | ||
|
|
46c29a0b97 | ||
|
|
9ab0efe87a | ||
|
|
6638d8215f | ||
|
|
e1a00090ba | ||
|
|
44bfe89ea8 | ||
|
|
b75e16f104 | ||
|
|
695cdfcc4e | ||
|
|
285ef2e36d | ||
|
|
fb3aa6ef4f | ||
|
|
0eb5cd05f5 | ||
|
|
3d1c70b96b | ||
|
|
946c288925 | ||
|
|
04464dcdb3 | ||
|
|
8a4f25527e | ||
|
|
581fd9c9fb | ||
|
|
fbce80a4c8 | ||
|
|
1ee3215cf3 | ||
|
|
95efcbe717 | ||
|
|
594d8a8ba1 | ||
|
|
9933f3a583 | ||
|
|
23bcf88aa2 | ||
|
|
21009f5ffe | ||
|
|
2810520612 | ||
|
|
3e088b4eb1 | ||
|
|
8e98eebe03 | ||
|
|
1f11f8add5 | ||
|
|
7192bc944b | ||
|
|
04aaa6f30c | ||
|
|
4405693b1f | ||
|
|
47380244b8 | ||
|
|
4640effb16 | ||
|
|
01a1eb177e | ||
|
|
0afac8bbff | ||
|
|
0a59e9732e | ||
|
|
ed92db87bc | ||
|
|
e892a6104a | ||
|
|
d489b4bf23 | ||
|
|
8c6df7f20c | ||
|
|
49d0fb2eae | ||
|
|
edf08c8cd4 | ||
|
|
ebe6946233 | ||
|
|
54aad2d067 | ||
|
|
d06d22fd65 | ||
|
|
940fbda494 | ||
|
|
58cd17468c | ||
|
|
977c63eb2f | ||
|
|
b9cbab2577 | ||
|
|
2dafd52610 | ||
|
|
3b95728567 | ||
|
|
825742359e | ||
|
|
56e29dae33 | ||
|
|
4b005b4b39 | ||
|
|
8fb1a45cee | ||
|
|
41c1dde504 | ||
|
|
985ee3df91 | ||
|
|
467835192f | ||
|
|
7a929024f2 | ||
|
|
6698c34dbb | ||
|
|
3fbf9ab98f | ||
|
|
bd747cea24 | ||
|
|
be61e7c10c | ||
|
|
515275583e | ||
|
|
e386c16a7f | ||
|
|
3bba30cc1e | ||
|
|
85f02a1b7c | ||
|
|
528c5f2627 | ||
|
|
780e453cf5 | ||
|
|
f3ebc4a28e | ||
|
|
7df32ff4ac | ||
|
|
985882a4ad | ||
|
|
986bc27001 | ||
|
|
053f944691 | ||
|
|
85080519a1 | ||
|
|
7569cc54ab | ||
|
|
923f5d6bb1 | ||
|
|
c8b82576a3 | ||
|
|
aa8926e61c | ||
|
|
6d6b9c831a | ||
|
|
650ed70f92 | ||
|
|
a3d37e621c | ||
|
|
06799b19b0 | ||
|
|
e6a13d7220 | ||
|
|
45e2827516 | ||
|
|
0b395d03f6 | ||
|
|
2d8ac3bf80 | ||
|
|
301580d61a | ||
|
|
b0a2c590fe | ||
|
|
9bb56d3fc0 | ||
|
|
8162654d6f | ||
|
|
b33a3ef254 | ||
|
|
a89c52cfdb | ||
|
|
06aaf7cb8d | ||
|
|
f929cdae9c | ||
|
|
20eb6338de | ||
|
|
6c76c277c7 | ||
|
|
49ef80ab6c | ||
|
|
8b4193149b | ||
|
|
2b4dd3b5ce | ||
|
|
006560b96d | ||
|
|
32ec95ffa8 | ||
|
|
10c2512d74 | ||
|
|
28e5b0bd5b | ||
|
|
87fc4f936a | ||
|
|
71d3135bd2 | ||
|
|
6052b0d042 | ||
|
|
e83b0ac651 | ||
|
|
30ada60862 | ||
|
|
d136a5206c | ||
|
|
ea908adbf9 | ||
|
|
97d0eada57 | ||
|
|
352546f554 | ||
|
|
b583e67ae8 | ||
|
|
9de7040401 | ||
|
|
8951d0aa57 | ||
|
|
582bc3a4c4 | ||
|
|
5f21823c43 | ||
|
|
11162585ca | ||
|
|
dad5d2a905 | ||
|
|
2d683ea198 | ||
|
|
c082a48e67 | ||
|
|
ba387bcc84 | ||
|
|
c8d1a576b0 | ||
|
|
3e691f8b25 | ||
|
|
f700970cd4 | ||
|
|
2828027cc8 | ||
|
|
4a5d05a19f | ||
|
|
0867f728d1 | ||
|
|
0bd8b298d7 | ||
|
|
6d8cf57868 | ||
|
|
4790d31ff7 | ||
|
|
d7243bba77 | ||
|
|
0225eefa66 | ||
|
|
18240c9d07 | ||
|
|
4b4fcda66d | ||
|
|
97c6b65315 | ||
|
|
8f176421da | ||
|
|
0bd9f309a1 | ||
|
|
6fb9529518 | ||
|
|
e6c59fc9b0 | ||
|
|
a12d465881 | ||
|
|
a921bde6ac | ||
|
|
8fbfd5ad0a | ||
|
|
acaefab0f4 | ||
|
|
952affc6df | ||
|
|
521e840b54 | ||
|
|
752a558b30 | ||
|
|
40c077101a | ||
|
|
f7075f4ccb | ||
|
|
9fc5283856 | ||
|
|
e0d63db1ab | ||
|
|
d519429ea1 | ||
|
|
e4d3ae4c3f | ||
|
|
f7e45273a1 | ||
|
|
f57fc3cd6e | ||
|
|
033b8c5d48 | ||
|
|
ad26e57e78 | ||
|
|
e9e3e14695 | ||
|
|
e127c33bae | ||
|
|
5192f4a326 | ||
|
|
2260f214ed | ||
|
|
2b91557ad2 | ||
|
|
c1f0017867 | ||
|
|
20ea0dba95 | ||
|
|
712dbb8e73 | ||
|
|
f9b760bfc4 | ||
|
|
14d2209587 | ||
|
|
bcd43629cc | ||
|
|
8985799c20 | ||
|
|
3300bbe9e7 | ||
|
|
14bd59a101 | ||
|
|
c0bdde26cf | ||
|
|
01edbb2351 | ||
|
|
cbad4cf594 | ||
|
|
11b61b8fe2 | ||
|
|
1d0da28d9e | ||
|
|
23f6c107c6 | ||
|
|
95f8a05cbd | ||
|
|
167863d957 | ||
|
|
22fc643f25 | ||
|
|
4d9d4a9dfd | ||
|
|
93766fe6ed | ||
|
|
aef6967d4c | ||
|
|
0d4ec25593 | ||
|
|
2b13158fcd | ||
|
|
a1ff7b9673 | ||
|
|
aeb0f1e6d8 | ||
|
|
5034c957ba | ||
|
|
620f932dcd | ||
|
|
5f5c75bb0f | ||
|
|
7184f4c66e | ||
|
|
1d5c2c63b9 | ||
|
|
f660aa13d1 | ||
|
|
47ac33d6c2 | ||
|
|
ce35799506 | ||
|
|
418fe725e5 | ||
|
|
ba7818c51e | ||
|
|
9af03b0416 | ||
|
|
0defe76fe3 | ||
|
|
76ac070f9b | ||
|
|
f0a6fa68ea | ||
|
|
2da7b1d542 | ||
|
|
053e817393 | ||
|
|
f11650ece1 | ||
|
|
aff94a6770 | ||
|
|
0090734cd8 | ||
|
|
af816fe50f | ||
|
|
e7122a9b36 | ||
|
|
1db4161538 | ||
|
|
2295b218e3 | ||
|
|
0053ce2708 | ||
|
|
fb37f48a86 | ||
|
|
974ad26f06 | ||
|
|
5539653492 | ||
|
|
11e8cbf66f | ||
|
|
a45feacd3f | ||
|
|
9aeb5b4f05 | ||
|
|
ed0fa5df5c | ||
|
|
70de2d48be | ||
|
|
c0acc336cc | ||
|
|
c068dfe87b | ||
|
|
21f37db562 | ||
|
|
030faf918e | ||
|
|
8df318bced | ||
|
|
bbf1f3a43f | ||
|
|
f258d8d517 | ||
|
|
0985438df5 | ||
|
|
9d0956511d | ||
|
|
d6b8c76cc7 | ||
|
|
7d69bd5c46 | ||
|
|
cfd283e7e3 | ||
|
|
999c20f3fa | ||
|
|
85f9996b41 | ||
|
|
c4e07d6a53 | ||
|
|
2aba1e3bf9 | ||
|
|
5e5847c5e4 | ||
|
|
224c257c4f | ||
|
|
28a0a97ca4 | ||
|
|
662a4a5f00 | ||
|
|
df152e292d | ||
|
|
d92a97ff1e | ||
|
|
115cb016a0 | ||
|
|
7cda243b42 | ||
|
|
46b573462f | ||
|
|
5b3bd8ff2a | ||
|
|
6faae766a8 | ||
|
|
bf636725e8 | ||
|
|
bafba7aa6a | ||
|
|
e1984831bd | ||
|
|
c826438328 | ||
|
|
e39390ab92 | ||
|
|
120f57894f | ||
|
|
b89a01fddf | ||
|
|
21e4a64dc7 | ||
|
|
4aeab872de | ||
|
|
a0a2c9375e | ||
|
|
d1dd9ba955 | ||
|
|
e48db7d7ea | ||
|
|
239dea793a | ||
|
|
b0ce378629 | ||
|
|
7de50c0f4b | ||
|
|
07926386ea | ||
|
|
f1c962fbbc | ||
|
|
5d79c231ed | ||
|
|
972f0481e5 | ||
|
|
49781aae17 | ||
|
|
51f22f48dc | ||
|
|
a64381153f | ||
|
|
10280966ac | ||
|
|
16ad6bf9fc | ||
|
|
1aa5c23bba | ||
|
|
9216a69c05 | ||
|
|
7b2cff4c5e | ||
|
|
bf42958059 | ||
|
|
1deccf2f4b | ||
|
|
57755ef413 | ||
|
|
c2cf850179 | ||
|
|
67838ae29e | ||
|
|
4d22477477 | ||
|
|
96b5ed1df6 | ||
|
|
b9ec43c0f7 | ||
|
|
8a0899a819 | ||
|
|
e390852a67 | ||
|
|
c4083c23d6 | ||
|
|
bdc751ac24 | ||
|
|
0e23975964 | ||
|
|
ad53414c4d | ||
|
|
23e01130e9 | ||
|
|
f779c35d0e |
No files matched your search
@@ -38,7 +38,7 @@ jobs:
|
||||
# https://github.com/docker/login-action
|
||||
- name: Log into registry ${{ env.REGISTRY }}
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
|
||||
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -48,14 +48,14 @@ jobs:
|
||||
# https://github.com/docker/metadata-action
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@507c2f2dc502c992ad446e3d7a5dfbe311567a96
|
||||
uses: docker/metadata-action@818d4b7b91585d195f67373fd9cb0332e31a7175
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
|
||||
# Build and push Docker image with Buildx (don't push on PR)
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
|
||||
uses: docker/build-push-action@2eb1c1961a95fc15694676618e422e8ba1d63825
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
|
||||
+94
-63
@@ -6,7 +6,7 @@
|
||||
meteor-base@1.5.1
|
||||
|
||||
# Build system
|
||||
ecmascript@0.16.5
|
||||
ecmascript@0.16.7
|
||||
standard-minifier-js@2.8.1
|
||||
mquandalle:jade
|
||||
coffeescript@2.4.1!
|
||||
@@ -21,11 +21,11 @@ cottz:publish-relations
|
||||
dburles:collection-helpers
|
||||
idmontie:migrations
|
||||
easy:search
|
||||
mongo@1.16.4
|
||||
mongo@1.16.6
|
||||
mquandalle:collection-mutations
|
||||
|
||||
# Account system
|
||||
accounts-password@2.3.3
|
||||
accounts-password@2.3.4
|
||||
useraccounts:core
|
||||
useraccounts:flow-routing
|
||||
useraccounts:unstyled
|
||||
@@ -39,37 +39,114 @@ wekan-accounts-oidc
|
||||
|
||||
# Utilities
|
||||
check@1.3.2
|
||||
jquery@1.11.10
|
||||
jquery@3.0.0!
|
||||
random@1.2.1
|
||||
reactive-dict@1.3.1
|
||||
session@1.2.1
|
||||
tracker@1.3.0
|
||||
underscore@1.0.11
|
||||
tracker@1.3.2
|
||||
underscore@1.0.13
|
||||
arillo:flow-router-helpers
|
||||
audit-argument-checks@1.0.7
|
||||
kadira:blaze-layout
|
||||
kadira:dochead
|
||||
mquandalle:autofocus
|
||||
ongoworks:speakingurl
|
||||
raix:handlebar-helpers
|
||||
http@2.0.0! # force new http package
|
||||
|
||||
# Datepicker
|
||||
rajit:bootstrap3-datepicker
|
||||
rajit:bootstrap3-datepicker-de
|
||||
rajit:bootstrap3-datepicker-tr
|
||||
rajit:bootstrap3-datepicker-ja
|
||||
rajit:bootstrap3-datepicker-fr
|
||||
rajit:bootstrap3-datepicker-it
|
||||
rajit:bootstrap3-datepicker-th
|
||||
rajit:bootstrap3-datepicker-nl
|
||||
rajit:bootstrap3-datepicker-es
|
||||
rajit:bootstrap3-datepicker-lv
|
||||
rajit:bootstrap3-datepicker-sv
|
||||
rajit:bootstrap3-datepicker-gl
|
||||
rajit:bootstrap3-datepicker-eu
|
||||
rajit:bootstrap3-datepicker-vi
|
||||
rajit:bootstrap3-datepicker-no
|
||||
rajit:bootstrap3-datepicker-en-gb
|
||||
rajit:bootstrap3-datepicker-ro
|
||||
rajit:bootstrap3-datepicker-rs
|
||||
rajit:bootstrap3-datepicker-ru
|
||||
rajit:bootstrap3-datepicker-bs
|
||||
rajit:bootstrap3-datepicker-mn
|
||||
rajit:bootstrap3-datepicker-id
|
||||
rajit:bootstrap3-datepicker-fa
|
||||
rajit:bootstrap3-datepicker-ko
|
||||
rajit:bootstrap3-datepicker-pt
|
||||
rajit:bootstrap3-datepicker-sl
|
||||
rajit:bootstrap3-datepicker-sq
|
||||
rajit:bootstrap3-datepicker-cy
|
||||
rajit:bootstrap3-datepicker-ka
|
||||
rajit:bootstrap3-datepicker-sr
|
||||
rajit:bootstrap3-datepicker-az
|
||||
rajit:bootstrap3-datepicker-cs
|
||||
rajit:bootstrap3-datepicker-me
|
||||
rajit:bootstrap3-datepicker-ta
|
||||
rajit:bootstrap3-datepicker-eo
|
||||
rajit:bootstrap3-datepicker-oc
|
||||
rajit:bootstrap3-datepicker-he
|
||||
rajit:bootstrap3-datepicker-sw
|
||||
rajit:bootstrap3-datepicker-rs-latin
|
||||
rajit:bootstrap3-datepicker-da
|
||||
rajit:bootstrap3-datepicker-pt-br
|
||||
rajit:bootstrap3-datepicker-br
|
||||
rajit:bootstrap3-datepicker-it-ch
|
||||
rajit:bootstrap3-datepicker-en-za
|
||||
rajit:bootstrap3-datepicker-en-ie
|
||||
rajit:bootstrap3-datepicker-en-ca
|
||||
rajit:bootstrap3-datepicker-uz-latn
|
||||
rajit:bootstrap3-datepicker-ms
|
||||
rajit:bootstrap3-datepicker-uk
|
||||
rajit:bootstrap3-datepicker-hu
|
||||
rajit:bootstrap3-datepicker-fo
|
||||
rajit:bootstrap3-datepicker-kr
|
||||
rajit:bootstrap3-datepicker-hi
|
||||
rajit:bootstrap3-datepicker-km
|
||||
rajit:bootstrap3-datepicker-fi
|
||||
rajit:bootstrap3-datepicker-is
|
||||
rajit:bootstrap3-datepicker-kh
|
||||
rajit:bootstrap3-datepicker-bg
|
||||
rajit:bootstrap3-datepicker-bn
|
||||
rajit:bootstrap3-datepicker-pl
|
||||
rajit:bootstrap3-datepicker-et
|
||||
rajit:bootstrap3-datepicker-ar
|
||||
rajit:bootstrap3-datepicker-ca
|
||||
rajit:bootstrap3-datepicker-kk
|
||||
rajit:bootstrap3-datepicker-sk
|
||||
rajit:bootstrap3-datepicker-el
|
||||
rajit:bootstrap3-datepicker-hy
|
||||
rajit:bootstrap3-datepicker-hr
|
||||
rajit:bootstrap3-datepicker-tg
|
||||
rajit:bootstrap3-datepicker-nb
|
||||
rajit:bootstrap3-datepicker-mk
|
||||
rajit:bootstrap3-datepicker-nl-be
|
||||
rajit:bootstrap3-datepicker-zh-cn
|
||||
rajit:bootstrap3-datepicker-ar-tn
|
||||
rajit:bootstrap3-datepicker-en-au
|
||||
rajit:bootstrap3-datepicker-fr-ch
|
||||
rajit:bootstrap3-datepicker-zh-tw
|
||||
rajit:bootstrap3-datepicker-uz-cyrl
|
||||
rajit:bootstrap3-datepicker-sr-latin
|
||||
rajit:bootstrap3-datepicker-en-nz
|
||||
|
||||
# UI components
|
||||
blaze
|
||||
ostrio:i18n
|
||||
reactive-var@1.0.12
|
||||
fortawesome:fontawesome
|
||||
mousetrap:mousetrap
|
||||
mquandalle:jquery-textcomplete
|
||||
mquandalle:mousetrap-bindglobal
|
||||
peerlibrary:blaze-components
|
||||
templates:tabs
|
||||
meteor-autosize
|
||||
rajit:bootstrap3-datepicker
|
||||
shell-server@0.5.0
|
||||
email@2.2.3
|
||||
horka:swipebox
|
||||
dynamic-import@0.7.2
|
||||
email@2.2.5
|
||||
dynamic-import@0.7.3
|
||||
cfs:gridfs
|
||||
rzymek:fullcalendar
|
||||
msavin:usercache
|
||||
@@ -82,55 +159,6 @@ percolate:synced-cron
|
||||
cfs:filesystem
|
||||
ostrio:cookies
|
||||
ostrio:files@2.3.0
|
||||
rajit:bootstrap3-datepicker-fi
|
||||
rajit:bootstrap3-datepicker-ar
|
||||
rajit:bootstrap3-datepicker-bg
|
||||
rajit:bootstrap3-datepicker-br
|
||||
rajit:bootstrap3-datepicker-ca
|
||||
rajit:bootstrap3-datepicker-cs
|
||||
rajit:bootstrap3-datepicker-da
|
||||
rajit:bootstrap3-datepicker-de
|
||||
rajit:bootstrap3-datepicker-el
|
||||
rajit:bootstrap3-datepicker-en-gb
|
||||
rajit:bootstrap3-datepicker-eo
|
||||
rajit:bootstrap3-datepicker-es
|
||||
rajit:bootstrap3-datepicker-eu
|
||||
rajit:bootstrap3-datepicker-fa
|
||||
rajit:bootstrap3-datepicker-fr
|
||||
rajit:bootstrap3-datepicker-gl
|
||||
rajit:bootstrap3-datepicker-he
|
||||
rajit:bootstrap3-datepicker-hi
|
||||
rajit:bootstrap3-datepicker-hu
|
||||
rajit:bootstrap3-datepicker-hy
|
||||
rajit:bootstrap3-datepicker-id
|
||||
rajit:bootstrap3-datepicker-it
|
||||
rajit:bootstrap3-datepicker-ja
|
||||
rajit:bootstrap3-datepicker-ka
|
||||
rajit:bootstrap3-datepicker-km
|
||||
rajit:bootstrap3-datepicker-ko
|
||||
rajit:bootstrap3-datepicker-lv
|
||||
rajit:bootstrap3-datepicker-mk
|
||||
rajit:bootstrap3-datepicker-mn
|
||||
rajit:bootstrap3-datepicker-nb
|
||||
rajit:bootstrap3-datepicker-nl
|
||||
rajit:bootstrap3-datepicker-oc
|
||||
rajit:bootstrap3-datepicker-pl
|
||||
rajit:bootstrap3-datepicker-pt-br
|
||||
rajit:bootstrap3-datepicker-pt
|
||||
rajit:bootstrap3-datepicker-ro
|
||||
rajit:bootstrap3-datepicker-ru
|
||||
rajit:bootstrap3-datepicker-sl
|
||||
rajit:bootstrap3-datepicker-sr
|
||||
rajit:bootstrap3-datepicker-sv
|
||||
rajit:bootstrap3-datepicker-sw
|
||||
rajit:bootstrap3-datepicker-ta
|
||||
rajit:bootstrap3-datepicker-th
|
||||
rajit:bootstrap3-datepicker-tr
|
||||
rajit:bootstrap3-datepicker-uk
|
||||
rajit:bootstrap3-datepicker-vi
|
||||
rajit:bootstrap3-datepicker-zh-cn
|
||||
rajit:bootstrap3-datepicker-zh-tw
|
||||
easylogic:summernote
|
||||
pascoual:pdfkit
|
||||
lmieulet:meteor-coverage
|
||||
meteortesting:mocha@2.0.3
|
||||
@@ -141,4 +169,7 @@ kadira:flow-router
|
||||
spacebars
|
||||
service-configuration@1.3.1
|
||||
communitypackages:picker
|
||||
minifier-css@1.6.2
|
||||
minifier-css@1.6.4
|
||||
blaze
|
||||
kadira:blaze-layout
|
||||
peerlibrary:blaze-components
|
||||
+1
-1
@@ -1 +1 @@
|
||||
METEOR@2.10.0
|
||||
METEOR@2.12
|
||||
+65
-37
@@ -1,6 +1,6 @@
|
||||
accounts-base@2.2.6
|
||||
accounts-base@2.2.8
|
||||
accounts-oauth@1.4.2
|
||||
accounts-password@2.3.3
|
||||
accounts-password@2.3.4
|
||||
aldeed:collection2@2.10.0
|
||||
aldeed:collection2-core@1.2.0
|
||||
aldeed:schema-deny@1.1.0
|
||||
@@ -10,16 +10,16 @@ allow-deny@1.1.1
|
||||
arillo:flow-router-helpers@0.5.2
|
||||
audit-argument-checks@1.0.7
|
||||
autoupdate@1.8.0
|
||||
babel-compiler@7.10.2
|
||||
babel-compiler@7.10.4
|
||||
babel-runtime@1.5.1
|
||||
base64@1.0.12
|
||||
binary-heap@1.0.11
|
||||
blaze@2.6.1
|
||||
blaze@2.7.1
|
||||
blaze-tools@1.1.3
|
||||
boilerplate-generator@1.7.1
|
||||
caching-compiler@1.2.2
|
||||
caching-html-compiler@1.2.1
|
||||
callback-hook@1.5.0
|
||||
callback-hook@1.5.1
|
||||
cfs:access-point@0.1.49
|
||||
cfs:base-package@0.0.30
|
||||
cfs:collection@0.5.5
|
||||
@@ -39,34 +39,32 @@ cfs:tempstore@0.1.6
|
||||
cfs:upload-http@0.0.20
|
||||
cfs:worker@0.1.5
|
||||
check@1.3.2
|
||||
coffeescript@2.4.1
|
||||
coffeescript@2.7.0
|
||||
coffeescript-compiler@2.4.1
|
||||
communitypackages:picker@1.1.0
|
||||
communitypackages:picker@1.1.1
|
||||
cottz:publish-relations@2.0.8
|
||||
dburles:collection-helpers@1.1.0
|
||||
ddp@1.4.1
|
||||
ddp-client@2.6.1
|
||||
ddp-common@1.4.0
|
||||
ddp-rate-limiter@1.1.1
|
||||
ddp-server@2.6.0
|
||||
ddp-rate-limiter@1.2.0
|
||||
ddp-server@2.6.1
|
||||
deps@1.0.12
|
||||
diff-sequence@1.1.2
|
||||
dynamic-import@0.7.2
|
||||
dynamic-import@0.7.3
|
||||
easy:search@2.2.1
|
||||
easylogic:summernote@0.8.8
|
||||
easysearch:components@2.2.2
|
||||
easysearch:core@2.2.2
|
||||
ecmascript@0.16.5
|
||||
ecmascript-runtime@0.8.0
|
||||
ecmascript@0.16.7
|
||||
ecmascript-runtime@0.8.1
|
||||
ecmascript-runtime-client@0.12.1
|
||||
ecmascript-runtime-server@0.11.0
|
||||
ejson@1.1.3
|
||||
email@2.2.3
|
||||
email@2.2.5
|
||||
es5-shim@4.8.0
|
||||
fetch@0.1.3
|
||||
fortawesome:fontawesome@4.7.0
|
||||
geojson-utils@1.0.11
|
||||
horka:swipebox@1.0.2
|
||||
hot-code-push@1.0.4
|
||||
html-tools@1.1.3
|
||||
htmljs@1.1.1
|
||||
@@ -74,7 +72,7 @@ http@2.0.0
|
||||
id-map@1.1.1
|
||||
idmontie:migrations@1.0.3
|
||||
inter-process-messaging@0.1.1
|
||||
jquery@1.11.11
|
||||
jquery@3.0.0
|
||||
kadira:blaze-layout@2.3.0
|
||||
kadira:dochead@1.5.0
|
||||
kadira:flow-router@2.12.1
|
||||
@@ -82,10 +80,10 @@ konecty:mongo-counter@0.0.5_3
|
||||
livedata@1.0.18
|
||||
lmieulet:meteor-coverage@1.1.4
|
||||
localstorage@1.2.0
|
||||
logging@1.3.1
|
||||
matb33:collection-hooks@1.2.0
|
||||
logging@1.3.2
|
||||
matb33:collection-hooks@1.2.2
|
||||
mdg:validation-error@0.5.1
|
||||
meteor@1.11.0
|
||||
meteor@1.11.2
|
||||
meteor-autosize@5.0.1
|
||||
meteor-base@1.5.1
|
||||
meteorhacks:aggregate@1.3.0
|
||||
@@ -93,17 +91,17 @@ meteorhacks:collection-utils@1.2.0
|
||||
meteorhacks:picker@1.0.3
|
||||
meteorhacks:subs-manager@1.6.4
|
||||
meteortesting:browser-tests@1.4.2
|
||||
meteortesting:mocha@2.0.4
|
||||
meteortesting:mocha@2.1.0
|
||||
meteortesting:mocha-core@8.0.1
|
||||
minifier-css@1.6.2
|
||||
minifier-css@1.6.4
|
||||
minifier-js@2.7.5
|
||||
minifiers@1.1.8-faster-rebuild.0
|
||||
minimongo@1.9.1
|
||||
minimongo@1.9.3
|
||||
modern-browsers@0.1.9
|
||||
modules@0.19.0
|
||||
modules-runtime@0.13.1
|
||||
momentjs:moment@2.29.3
|
||||
mongo@1.16.4
|
||||
mongo@1.16.6
|
||||
mongo-decimal@0.1.3
|
||||
mongo-dev-server@1.1.0
|
||||
mongo-id@1.0.8
|
||||
@@ -116,16 +114,16 @@ mquandalle:jade-compiler@0.4.5
|
||||
mquandalle:jquery-textcomplete@0.8.0_1
|
||||
mquandalle:mousetrap-bindglobal@0.0.1
|
||||
msavin:usercache@1.8.0
|
||||
npm-mongo@4.12.1
|
||||
oauth@2.1.3
|
||||
npm-mongo@4.16.0
|
||||
oauth@2.2.0
|
||||
oauth2@1.3.2
|
||||
observe-sequence@1.0.20
|
||||
observe-sequence@1.0.21
|
||||
ongoworks:speakingurl@1.1.0
|
||||
ordered-dict@1.1.0
|
||||
ostrio:cookies@2.7.2
|
||||
ostrio:cstorage@4.0.1
|
||||
ostrio:files@2.3.2
|
||||
ostrio:i18n@3.2.0
|
||||
ostrio:files@2.3.3
|
||||
ostrio:i18n@3.2.1
|
||||
pascoual:pdfkit@1.0.7
|
||||
peerlibrary:assert@0.3.0
|
||||
peerlibrary:base-component@0.17.1
|
||||
@@ -139,56 +137,87 @@ raix:eventemitter@0.1.3
|
||||
raix:handlebar-helpers@0.2.5
|
||||
rajit:bootstrap3-datepicker@1.7.1_1
|
||||
rajit:bootstrap3-datepicker-ar@1.7.1
|
||||
rajit:bootstrap3-datepicker-ar-tn@1.7.1
|
||||
rajit:bootstrap3-datepicker-az@1.7.1
|
||||
rajit:bootstrap3-datepicker-bg@1.7.1
|
||||
rajit:bootstrap3-datepicker-bn@1.7.1
|
||||
rajit:bootstrap3-datepicker-br@1.7.1
|
||||
rajit:bootstrap3-datepicker-bs@1.7.1
|
||||
rajit:bootstrap3-datepicker-ca@1.7.1
|
||||
rajit:bootstrap3-datepicker-cs@1.7.1
|
||||
rajit:bootstrap3-datepicker-cy@1.7.1
|
||||
rajit:bootstrap3-datepicker-da@1.7.1
|
||||
rajit:bootstrap3-datepicker-de@1.7.1
|
||||
rajit:bootstrap3-datepicker-el@1.7.1
|
||||
rajit:bootstrap3-datepicker-en-au@1.7.1
|
||||
rajit:bootstrap3-datepicker-en-ca@1.7.1
|
||||
rajit:bootstrap3-datepicker-en-gb@1.7.1
|
||||
rajit:bootstrap3-datepicker-en-ie@1.7.1
|
||||
rajit:bootstrap3-datepicker-en-nz@1.7.1
|
||||
rajit:bootstrap3-datepicker-en-za@1.7.1
|
||||
rajit:bootstrap3-datepicker-eo@1.7.1
|
||||
rajit:bootstrap3-datepicker-es@1.7.1
|
||||
rajit:bootstrap3-datepicker-et@1.7.1
|
||||
rajit:bootstrap3-datepicker-eu@1.7.1
|
||||
rajit:bootstrap3-datepicker-fa@1.7.1
|
||||
rajit:bootstrap3-datepicker-fi@1.7.1
|
||||
rajit:bootstrap3-datepicker-fo@1.7.1
|
||||
rajit:bootstrap3-datepicker-fr@1.7.1
|
||||
rajit:bootstrap3-datepicker-fr-ch@1.7.1
|
||||
rajit:bootstrap3-datepicker-gl@1.7.1
|
||||
rajit:bootstrap3-datepicker-he@1.7.1
|
||||
rajit:bootstrap3-datepicker-hi@1.7.1
|
||||
rajit:bootstrap3-datepicker-hr@1.7.1
|
||||
rajit:bootstrap3-datepicker-hu@1.7.1
|
||||
rajit:bootstrap3-datepicker-hy@1.7.1
|
||||
rajit:bootstrap3-datepicker-id@1.7.1
|
||||
rajit:bootstrap3-datepicker-is@1.7.1
|
||||
rajit:bootstrap3-datepicker-it@1.7.1
|
||||
rajit:bootstrap3-datepicker-it-ch@1.7.1
|
||||
rajit:bootstrap3-datepicker-ja@1.7.1
|
||||
rajit:bootstrap3-datepicker-ka@1.7.1
|
||||
rajit:bootstrap3-datepicker-kh@1.7.1
|
||||
rajit:bootstrap3-datepicker-kk@1.7.1
|
||||
rajit:bootstrap3-datepicker-km@1.7.1
|
||||
rajit:bootstrap3-datepicker-ko@1.7.1
|
||||
rajit:bootstrap3-datepicker-kr@1.7.1
|
||||
rajit:bootstrap3-datepicker-lv@1.7.1
|
||||
rajit:bootstrap3-datepicker-me@1.7.1
|
||||
rajit:bootstrap3-datepicker-mk@1.7.1
|
||||
rajit:bootstrap3-datepicker-mn@1.7.1
|
||||
rajit:bootstrap3-datepicker-ms@1.7.1
|
||||
rajit:bootstrap3-datepicker-nb@1.7.1
|
||||
rajit:bootstrap3-datepicker-nl@1.7.1
|
||||
rajit:bootstrap3-datepicker-nl-be@1.7.1
|
||||
rajit:bootstrap3-datepicker-no@1.7.1
|
||||
rajit:bootstrap3-datepicker-oc@1.7.1
|
||||
rajit:bootstrap3-datepicker-pl@1.7.1
|
||||
rajit:bootstrap3-datepicker-pt@1.7.1
|
||||
rajit:bootstrap3-datepicker-pt-br@1.7.1
|
||||
rajit:bootstrap3-datepicker-ro@1.7.1
|
||||
rajit:bootstrap3-datepicker-rs@1.7.1
|
||||
rajit:bootstrap3-datepicker-rs-latin@1.7.1
|
||||
rajit:bootstrap3-datepicker-ru@1.7.1
|
||||
rajit:bootstrap3-datepicker-sk@1.7.1
|
||||
rajit:bootstrap3-datepicker-sl@1.7.1
|
||||
rajit:bootstrap3-datepicker-sq@1.7.1
|
||||
rajit:bootstrap3-datepicker-sr@1.7.1
|
||||
rajit:bootstrap3-datepicker-sr-latin@1.7.1
|
||||
rajit:bootstrap3-datepicker-sv@1.7.1
|
||||
rajit:bootstrap3-datepicker-sw@1.7.1
|
||||
rajit:bootstrap3-datepicker-ta@1.7.1
|
||||
rajit:bootstrap3-datepicker-tg@1.7.1
|
||||
rajit:bootstrap3-datepicker-th@1.7.1
|
||||
rajit:bootstrap3-datepicker-tr@1.7.1
|
||||
rajit:bootstrap3-datepicker-uk@1.7.1
|
||||
rajit:bootstrap3-datepicker-uz-cyrl@1.7.1
|
||||
rajit:bootstrap3-datepicker-uz-latn@1.7.1
|
||||
rajit:bootstrap3-datepicker-vi@1.7.1
|
||||
rajit:bootstrap3-datepicker-zh-cn@1.7.1
|
||||
rajit:bootstrap3-datepicker-zh-tw@1.7.1
|
||||
random@1.2.1
|
||||
rate-limit@1.0.9
|
||||
react-fast-refresh@0.2.5
|
||||
rate-limit@1.1.1
|
||||
react-fast-refresh@0.2.7
|
||||
reactive-dict@1.3.1
|
||||
reactive-var@1.0.12
|
||||
reload@1.3.1
|
||||
@@ -201,11 +230,11 @@ sha@1.0.9
|
||||
shell-server@0.5.0
|
||||
simple:authenticate-user-by-token@1.2.1
|
||||
simple:json-routes@2.3.1
|
||||
simple:rest-accounts-password@1.2.1
|
||||
simple:rest-accounts-password@1.2.2
|
||||
simple:rest-bearer-token-parser@1.1.1
|
||||
simple:rest-json-error-handler@1.1.1
|
||||
socket-stream-client@0.5.0
|
||||
spacebars@1.3.0
|
||||
socket-stream-client@0.5.1
|
||||
spacebars@1.4.1
|
||||
spacebars-compiler@1.3.1
|
||||
standard-minifier-js@2.8.1
|
||||
templates:tabs@2.3.0
|
||||
@@ -213,15 +242,14 @@ templating@1.4.1
|
||||
templating-compiler@1.4.1
|
||||
templating-runtime@1.5.0
|
||||
templating-tools@1.2.2
|
||||
tracker@1.3.0
|
||||
twbs:bootstrap@3.3.6
|
||||
tracker@1.3.2
|
||||
ui@1.0.13
|
||||
underscore@1.0.11
|
||||
underscore@1.0.13
|
||||
url@1.3.2
|
||||
useraccounts:core@1.16.2
|
||||
useraccounts:flow-routing@1.15.0
|
||||
useraccounts:unstyled@1.14.2
|
||||
webapp@1.13.3
|
||||
webapp@1.13.5
|
||||
webapp-hashing@1.1.1
|
||||
wekan-accounts-cas@0.1.0
|
||||
wekan-accounts-lockout@1.0.0
|
||||
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
lang_map = es_AR: es-AR, es_419: es-LA, es_TX: es-TX, he_IL: he-IL, zh_CN: zh-CN, ar_EG: ar-EG, cs_CZ: cs-CZ, fa_IR: fa-IR, ms_MY: ms-MY, nl_NL: nl-NL, de_CH: de-CH, en_IT: en-IT, uz_UZ: uz-UZ, fr_CH: fr-CH, hi_IN: hi-IN, et_EE: et-EE, es_PE: es-PE, es_MX: es-MX, gl_ES: gl-ES, mn_MN: mn, sl_SI: sl, zh_TW: zh-TW, ast_ES: ast-ES, es_CL: es-CL, ja_JP: ja, lv_LV: lv, ro_RO: ro-RO, az_AZ: az-AZ, cy_GB: cy-GB, gu_IN: gu-IN, pl_PL: pl-PL, vep: ve-PP, en_BR: en-BR, en@ysv: en-YS, hu_HU: hu, ko_KR: ko-KR, pt_BR: pt-BR, zh_HK: zh-HK, zu_ZA: zu-ZA, en_MY: en-MY, ja-Hira: ja-HI, fi_FI: fi, vec: ve-CC, vi_VN: vi-VN, fr_FR: fr-FR, id_ID: id, zh_Hans: zh-Hans, en_DE: en-DE, en_GB: en-GB, el_GR: el-GR, uk_UA: uk-UA, az@latin: az-LA, de_AT: de-AT, uz@Latn: uz-LA, vls: vl-SS, ar_DZ: ar-DZ, bg_BG: bg, es_PY: es-PY, fy_NL: fy-NL, uz@Arab: uz-AR, ru_UA: ru-UA, war: wa-RR
|
||||
lang_map = es_AR: es-AR, es_419: es-LA, es_TX: es-TX, he_IL: he-IL, zh_CN: zh-CN, ar_EG: ar-EG, cs_CZ: cs-CZ, fa_IR: fa-IR, ms_MY: ms-MY, nl_NL: nl-NL, de_CH: de-CH, en_IT: en-IT, uz_UZ: uz-UZ, fr_CH: fr-CH, hi_IN: hi-IN, et_EE: et-EE, es_PE: es-PE, es_MX: es-MX, gl_ES: gl-ES, mn_MN: mn, sl_SI: sl, zh_TW: zh-TW, ast_ES: ast-ES, es_CL: es-CL, ja_JP: ja, lv_LV: lv, ro_RO: ro-RO, az_AZ: az-AZ, cy_GB: cy-GB, gu_IN: gu-IN, pl_PL: pl-PL, vep: ve-PP, en_BR: en-BR, en@ysv: en-YS, hu_HU: hu, ko_KR: ko-KR, pt_BR: pt-BR, zh_HK: zh-HK, zu_ZA: zu-ZA, en_MY: en-MY, ja-Hira: ja-HI, fi_FI: fi, vec: ve-CC, vi_VN: vi-VN, fr_FR: fr-FR, id_ID: id, zh_Hans: zh-Hans, en_DE: en-DE, en_GB: en-GB, el_GR: el-GR, uk_UA: uk-UA, az@latin: az-LA, de_AT: de-AT, uz@Latn: uz-LA, vls: vl-SS, ar_DZ: ar-DZ, bg_BG: bg, es_PY: es-PY, fy_NL: fy-NL, uz@Arab: uz-AR, ru_UA: ru-UA, war: wa-RR, zh_CN.GB2312: zh-GB
|
||||
|
||||
[o:wekan:p:wekan:r:application]
|
||||
file_filter = imports/i18n/data/<lang>.i18n.json
|
||||
source_file = imports/i18n/data/en.i18n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
# This is the configuration of the Transifex tool that we use to manage the
|
||||
# translations on Wekan. Documentation at: http://docs.transifex.com/client.
|
||||
#
|
||||
# Push
|
||||
# ====
|
||||
#
|
||||
# It is recommended that contributors use the Transifex web UI to create and
|
||||
# edit translated strings. However in case a contributor has directly jumped
|
||||
# into the code and made its translations in the corresponding i18n.json file
|
||||
# we can push it using
|
||||
#
|
||||
# > tx push -t -l ar
|
||||
#
|
||||
# Where `ar` is the language identifier. In addition, the project maintainer
|
||||
# should push the English source file to Transifex at least before each release
|
||||
# candidate using:
|
||||
#
|
||||
# > tx push -s
|
||||
#
|
||||
# Pull
|
||||
# ====
|
||||
#
|
||||
# The set of accepted language is directly managed in Transifex, the only
|
||||
# restriction we define to bundle a new language in the application, is that its
|
||||
# completion is at least at 75%.
|
||||
#
|
||||
# We use:
|
||||
#
|
||||
# > tx pull
|
||||
#
|
||||
# to download new versions of existing translations, and
|
||||
#
|
||||
# > tx pull -a --minimum-perc=75
|
||||
#
|
||||
# to download new sufficiently advanced translations.
|
||||
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
# tap:i18n requires us to use `-` separator in the language identifiers whereas
|
||||
# Transifex uses a `_` separator, without an option to customize it on one side
|
||||
# or the other, so we need to do a Manual mapping.
|
||||
lang_map = ar_DZ:ar-DZ, ar_EG:ar-EG, az_AZ:az-AZ, az@latin:az-LA, bg_BG:bg, cs_CZ:cs-CZ, cy_GB:cy-GB, de_AT:de-AT, de_CH:de-CH, en_BR:en-BR, en_DE:en-DE, en_IT:en-IT, en_GB:en-GB, en_MY:en-MY, et_EE:et-EE, ast_ES:ast-ES, es_AR:es-AR, en@ysv:en-YS, es_CL:es-CL, es_419:es-LA, es_PE:es-PE, es_MX:es-MX, es_TX:es-TX, es_PY:es-PY, el_GR:el-GR, fa_IR:fa-IR, ja-Hira:ja-HI, ja_JP:ja, fi_FI:fi, fr_FR:fr-FR, fr_CH:fr-CH, fy_NL:fy-NL, gl_ES:gl-ES, gu_IN:gu-IN, he_IL:he-IL, hi_IN:hi-IN, hu_HU:hu, id_ID:id, mn_MN:mn, ms_MY:ms-MY, nl_NL:nl-NL, ko_KR:ko-KR, lv_LV:lv, pl_PL:pl-PL, pt_BR:pt-BR, ro_RO:ro-RO, ru_UA:ru-UA, sl_SI:sl, uk_UA:uk-UA, uz@Arab:uz-AR, uz@Latn:uz-LA, uz_UZ:uz-UZ, vec:ve-CC, vep:ve-PP, vls:vl-SS, war:wa-RR, vi_VN:vi-VN, zh_CN:zh-CN, zh_TW:zh-TW, zh_Hans:zh-Hans, zh_HK:zh-HK, zu_ZA:zu-ZA
|
||||
|
||||
[wekan.application]
|
||||
file_filter = imports/i18n/data/<lang>.i18n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
# We might have a dedicated second resource later to translate the “Welcome
|
||||
# Board” data.
|
||||
#
|
||||
# [wekan.welcomeBoard]
|
||||
# file_filter = private/welcomeBoard/<lang>.json
|
||||
# source_lang = en
|
||||
# type = KEYVALUEJSON
|
||||
+670
-3
@@ -3,13 +3,678 @@
|
||||
Required versions of Node.js, MongoDB etc are listed at https://wekan.github.io
|
||||
Download section.
|
||||
|
||||
Newest WeKan is on platforms: Snap Candidate, Docker, Kubernetes, Source/Bundle. Download section at https://wekan.github.io
|
||||
|
||||
In Progress is:
|
||||
- Getting newest WeKan to all platforms, fixing any migration and upgrade issues
|
||||
- Adding more platforms
|
||||
- Developing all paid features and fixes https://wekan.team/commercial-support/
|
||||
- More info and news at https://github.com/wekan/wekan/issues/4578#issuecomment-1505909376
|
||||
|
||||
Note:
|
||||
- Snap Candidate has newest WeKan with MongoDB 6 https://github.com/wekan/wekan/issues/4824#issuecomment-1425753485
|
||||
- Snap Beta has newest WeKan with MongoDB 5 https://github.com/wekan/wekan/issues/4780#issuecomment-1427625571
|
||||
- Snap Beta has old WeKan with MongoDB 5 https://github.com/wekan/wekan/issues/4780#issuecomment-1427625571
|
||||
- Snap Stable has old WeKan 6.09 with MongoDB 3.2.2
|
||||
|
||||
[How to upgrade WeKan](https://github.com/wekan/wekan/issues/4585)
|
||||
|
||||
# v7.01 2023-07-21 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix for Calendar View Create Card](https://github.com/wekan/wekan/pull/5019).
|
||||
Thanks to DimDz.
|
||||
- [Minicard didn't show the assignee](https://github.com/wekan/wekan/pull/5021).
|
||||
Thanks to mfilser.
|
||||
- [Helm Chart: Add imagePullPolicy to initContainer. Needed for running wekan when restarting while offline](https://github.com/wekan/charts/pull/21).
|
||||
Thanks to jadams.
|
||||
- [Removing Utils.getCurrentSetting() and use ReactiveCache directly](https://github.com/wekan/wekan/pull/5022).
|
||||
Thanks to mfilser.
|
||||
- [Attachment rename and delete works now again for non board admins](https://github.com/wekan/wekan/pull/5023).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v7.00 2023-07-19 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Speed improvements to Board and List loading](https://github.com/wekan/wekan/pull/5014).
|
||||
Thanks to mfilser.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Forked meteor-globals and meteor-reactive-cache to @wekanteam/meteor-globals and @wekanteam/meteor-reactive-cache to update to newest dependencies](https://github.com/wekan/wekan/commit/1c5857f0646658b121d7612b6176ec5e09c68592).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Added missing @babel/runtime](https://github.com/wekan/wekan/commit/60cb5fb0176ecb623d494613aab196f252c16752).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99.9 2023-07-18 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix "PROPAGATE_OIDC_DATA" mechanism if "info.groups" is undefined](https://github.com/wekan/wekan/pull/5011).
|
||||
Thanks to NotTheEvilOne.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99.8 2023-07-13 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix card creation. Now date fields are checked if they are empty](https://github.com/wekan/wekan/pull/5009).
|
||||
Thanks to helioguardabaxo.
|
||||
- [Helm Chart: Changes for Openshift](https://github.com/wekan/charts/pull/20).
|
||||
Thanks to salleman33.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99.7 2023-07-11 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/pull/5008).
|
||||
Thanks to dependabot.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix setting background image](https://github.com/wekan/wekan/pull/5004).
|
||||
Thanks to VidVidex.
|
||||
- [Added missing character](https://github.com/wekan/wekan/commit/4431ec5a2761d56685d2fca1202679b9bdcd9b81).
|
||||
Thanks to xet7.
|
||||
- [Added back datepicker](https://github.com/wekan/wekan/commit/912479baa48354a68bc807737a3db7975a4cb95c).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99.5 2023-07-10 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Reverted bold of minicard title](https://github.com/wekan/wekan/commit/c7dc912dd4403845a123d9202e930c886788db5b).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99.4 2023-07-10 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Disable migration attachment-cardCopy-fix-boardId-etc. Part 3](https://github.com/wekan/wekan/commit/34fef627a1c02700650fa97fb0fd1d3a36d79776).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99.3 2023-07-10 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix migration attachment-cardCopy-fix-boardId-etc. Part 2](https://github.com/wekan/wekan/commit/8555c24eb21134eda9b4d71494676b39d126ef35).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99.2 2023-07-10 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/pull/5001).
|
||||
Thanks to dependabot.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Added back npm packages: fibers and @mapbox/node-pre-gyp](https://github.com/wekan/wekan/commit/8bf40e219a9fa55b8f2ef19dbf6acc58d646b968).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99.1 2023-07-10 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/95d3e5cdc6136a9778bf7c84812a6d62ef6d4044).
|
||||
Thanks to developers of dependencies.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix for migration "attachment-cardCopy-fix-boardId-etc"](https://github.com/wekan/wekan/pull/4999).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99 2023-07-09 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Preview PDF](https://github.com/wekan/wekan/pull/4989).
|
||||
Thanks to VidVidex.
|
||||
- [Preview PDF translations](https://github.com/wekan/wekan/commit/83ae1d4a19925363d8f176553fb10a98a77420be).
|
||||
Thanks xet7.
|
||||
- [Preview PDF to have full width, close at top, and improve viewing at mobile](https://github.com/wekan/wekan/commit/4be5727a18472920ed775b8a2024b9c8ca2fdf0a).
|
||||
Thanks to xet7.
|
||||
- [Show Meteor dependency chain with rebuild-wekan.sh](https://github.com/wekan/wekan/commit/ba9f9705d43189d2491266af1fd4817ff34a3b59).
|
||||
Thanks to xet7.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/92c57fc91ea063914730647d0add8dae77187424).
|
||||
Thanks to developers of dependencies.
|
||||
- Added Snap MONGO_URL to rebuild-wekan.sh dev options.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/7d59ae93f9263c383a1c8c8605490d54b1e09ed7),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/3c2cc351f4bbe82b6870bab0e1891823c359e789).
|
||||
Thanks to xet7.
|
||||
- [MongoDB 6.0.7 at Snap](https://github.com/wekan/wekan/commit/5babe0358deae4b01261ee8655ec0e5a38f0344d).
|
||||
Thanks to MongoDB developers.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [New popup scrolls to top and restore previous position after closing again](https://github.com/wekan/wekan/pull/4979).
|
||||
Thanks to mfilser.
|
||||
- [Copy Checklist dialog now set's the last selected board](https://github.com/wekan/wekan/pull/4980).
|
||||
Thanks to mfilser.
|
||||
- [Copy Checklist only copied the checklist items at the first time, now always](https://github.com/wekan/wekan/pull/4981).
|
||||
Thanks to mfilser.
|
||||
- [Attachment copy changes now the boardId, listId and swimlaneId in the collection data](https://github.com/wekan/wekan/pull/4982).
|
||||
Thanks to mfilser.
|
||||
- [Admin attachment view was missing the column header "S3FileId"](https://github.com/wekan/wekan/pull/4983).
|
||||
Thanks to mfilser.
|
||||
- [Global Search, limit 0 is no limit](https://github.com/wekan/wekan/pull/4984).
|
||||
Thanks to mfilser.
|
||||
- [Admin Report, fixing filesize if not a number](https://github.com/wekan/wekan/pull/4985).
|
||||
Thanks to mfilser.
|
||||
- [Global search, found cards count is now substituted by the translation function itself](https://github.com/wekan/wekan/pull/4986).
|
||||
Thanks to mfilser.
|
||||
- [Utils of canModifyCard and canModifyBoard + move this general functions to Utils class](https://github.com/wekan/wekan/pull/4987).
|
||||
Thanks to mfilser.
|
||||
- Set background color only if it exists.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/45d33fa2e459717064969a1729e016d4004e5435),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/c6cad13f1e86fea44c7c16e1a194c6d7164e824a),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/549b15000b538d6e5013cc978c0f49e753fd903a).
|
||||
Thanks to xet7.
|
||||
- [If there is no Custom Field label at minicard, show value full width](https://github.com/wekan/wekan/commit/ffea7aff99db555d357876e1415f9015154782cc).
|
||||
Thanks to koluka and xet7.
|
||||
- API: Fix /api/boards/{boardId}/attachments endpoint.
|
||||
[Part 1](https://github.com/wekan/wekan/pull/4991),
|
||||
[Part 2](https://github.com/wekan/wekan/pull/4992).
|
||||
Thanks to VidVidex.
|
||||
- [Improved attachment gallery and attachment viewer](https://github.com/wekan/wekan/pull/4995).
|
||||
Thanks to VidVidex.
|
||||
- [Removed horka:swipebox](https://github.com/wekan/wekan/commit/4148238af31ad31b6190221ad69db865f9ed5ccc).
|
||||
Thanks to VidVidex and xet7.
|
||||
- [Bold minicard custom field title](https://github.com/wekan/wekan/pull/4993).
|
||||
Thanks to VidVidex.
|
||||
- [Revert first list width change](https://github.com/wekan/wekan/pull/4993).
|
||||
Thanks to xet7.
|
||||
- [Fixed maximum call stack exceeded by removing bootstrap 3, datepicker and summernote. Updated jquery. Disabled attachments viewer that opens empty when opening card. Fixes all npm audit errors](https://github.com/wekan/wekan/commit/140a134a11d0b262f69e4f343dddddb87c978748).
|
||||
Thanks to xet7.
|
||||
- [Fix attachment viewer not being hidden](https://github.com/wekan/wekan/pull/4997).
|
||||
Thanks to VidVidex.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.98 2023-06-22 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- Add checklist at top.
|
||||
[Part 1](https://github.com/wekan/wekan/pull/4973),
|
||||
[Part 2](https://github.com/wekan/wekan/pull/4974).
|
||||
Thanks to mfilser.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Update rebuild-wekan.sh to use local network IP address](https://github.com/wekan/wekan/commit/6479c6a5c516ade68d50849115367be90d3199a2).
|
||||
Thanks to xet7.
|
||||
- Update GitHub Actions.
|
||||
[Part 1](https://github.com/wekan/wekan/pull/4970),
|
||||
[Part 2](https://github.com/wekan/wekan/pull/4971).
|
||||
Thanks to dependabot.
|
||||
|
||||
and adds the following upcoming translations:
|
||||
|
||||
- [Added translations: Cantonese (China) (yue_CN) and Chinese Traditional (zh-Hant)](https://github.com/wekan/wekan/commit/dc2835d3410fcd7fd376a2be765c63236696605e).
|
||||
Thanks to translators.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Wait until user has logged in before fetching language preference](https://github.com/wekan/wekan/pull/4968).
|
||||
Thanks to simon816.
|
||||
- [Always fetch favicons from / path](https://github.com/wekan/wekan/commit/4d9f76cc68f435b1bbeeb51833dbce931f626b6d).
|
||||
Thanks to nebulade.
|
||||
- [Rounding sort number to next integer](https://github.com/wekan/wekan/pull/4975).
|
||||
Thanks to mfilser.
|
||||
- [Reduce list scroll speed while drag/drop the minicard](https://github.com/wekan/wekan/pull/4976).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.97 2023-06-10 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/d93481d84009922c22a4eaaf49624f7153f737dd).
|
||||
Thanks to developers of dependencies.
|
||||
|
||||
and removes the following features:
|
||||
|
||||
- [Feature: Docker Health Check](https://github.com/wekan/wekan/commit/c8ec8d456b481b10cbf135d5289093a57b2e547f).
|
||||
Thanks to luketainton, mfilser and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.96 2023-06-10 WeKan ® release
|
||||
|
||||
This release fixes the following CRITICAL SECURITY ISSUES:
|
||||
|
||||
- Found and fixed more InvisibleBleed of WeKan.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/4c016169c55e0dc5df9533795ddfec424a053300),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/df40384200d10595a7a9cd582d8534295eec5036).
|
||||
Thanks to xet7.
|
||||
|
||||
and adds the following new features:
|
||||
|
||||
- [Docker Health Check](https://github.com/wekan/wekan/pull/4954).
|
||||
Thanks to luketainton.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix due date filter for next and this week](https://github.com/wekan/wekan/pull/4953).
|
||||
Thanks to helioguardabaxo.
|
||||
- Fixed Rare bug: All Boards page icons random dance. Disabled cards counts and card members at All Boards page.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/b75e16f104390211e3e26c500c0a54687fee329d),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/e1a00090ba0ca192ba30f735a13d1ec5b5aa6bc1),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/9ab0efe87adbc872af287fb8254cccb6dd44aec3).
|
||||
Thanks to xet7.
|
||||
- [Docker build was broken because of wrong curl install](https://github.com/wekan/wekan/pull/4955).
|
||||
Thanks to mfilser.
|
||||
- [Try to fix Docker build by removing empty continuation lines](https://github.com/wekan/wekan/commit/b008986122e258e725379264850d16d06c445db1).
|
||||
Thanks to xet7.
|
||||
- [Clarified required settings for start-wekan.bat and start-wekan.sh](https://github.com/wekan/wekan/commit/3e6b396d0913e6747714a9f87e2161bba0ce525e).
|
||||
Thanks to xet7.
|
||||
- [Fixed drag-drop at Ubuntu Touch Morph Browser and WeKan OpenStore app by changing jquery-ui-touch-punch to newer updated @rwap/jquery-ui-touch-punch](https://github.com/wekan/wekan/commit/af63259f091cb2ade84493a288ea37c53cd37321).
|
||||
Thanks to xet7.
|
||||
- [Try to fix SVG image failed to render](https://github.com/wekan/wekan/commit/7a3c340d657894bf72130b7e51e313e3b020f9cf).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.95 2023-06-07 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Revert smaller swimlane height](https://github.com/wekan/wekan/commit/95efcbe71727ea2be5d2c9a1fa7fd2de76f71ef2).
|
||||
Thanks to kovacs-andras and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.94 2023-06-07 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Added list position when create a new list on board](https://github.com/wekan/wekan/pull/4938).
|
||||
Thanks to helioguardabaxo.
|
||||
- [Added option to show/hide cover attachment on minicard](https://github.com/wekan/wekan/pull/4939).
|
||||
Thanks to helioguardabaxo.
|
||||
- [Count of attachments on minicard. (Badges renamed to Count of attachments)](https://github.com/wekan/wekan/pull/4940).
|
||||
Thanks to helioguardabaxo.
|
||||
- [Renamed Badge to Count of attachments on minicard. Changed icons to Cover image on minicard](https://github.com/wekan/wekan/commit/825742359ef0738b110ed0904853c604bdbd1bac).
|
||||
Thanks to xet7.
|
||||
- [Added conditional to show after list field only if board has at least one list. Now after list shows the last list by default](https://github.com/wekan/wekan/pull/4941).
|
||||
Thanks to helioguardabaxo.
|
||||
- [Changed Add List to be at left. Before it was at right](https://github.com/wekan/wekan/commit/467835192fbcd9d4016674fa2ee406258cc106e7).
|
||||
Thanks to xet7.
|
||||
- [Added icons to swimlane action popup](https://github.com/wekan/wekan/pull/4943).
|
||||
Thanks to helioguardabaxo.
|
||||
- [Added translations to Sort](https://github.com/wekan/wekan/pull/4945).
|
||||
Thanks to DimDz.
|
||||
- Set card attachment as background image.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/8c6df7f20c946163b447227ff2f0d4da681cffb2),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/ed92db87bc0415d3c0bb7f2803d92f8fd7726517),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/01a1eb177e151c3042e1975de771737a6697342f),
|
||||
[Part 4](https://github.com/wekan/wekan/commit/47380244b827a79426ea92d5a96374b72c5b0811).
|
||||
Thanks to xet7.
|
||||
- [Edit the title of a swimlane using API](https://github.com/wekan/wekan/pull/4950).
|
||||
Thanks to DimDz.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- Updated dependencies.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/edf08c8cd44062cbdaa0cc98d10ec045a524cff3),
|
||||
[Part 2](https://github.com/wekan/wekan/pull/4949).
|
||||
Thanks to developers of dependencies.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix 6.93 with brackground image breaks scrolling on lists within swimlanes](https://github.com/wekan/wekan/commit/04aaa6f30cfe59769c9b1c75cf8921fcc99b1977).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.93 2023-05-29 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Layout fixes for modern-dark after shuffling labels and date field on minicard](https://github.com/wekan/wekan/pull/4935).
|
||||
Thanks to jghaanstra.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.92 2023-05-29 WeKan ® release
|
||||
|
||||
This release adds the following improvements:
|
||||
|
||||
- [Moved minicard labels from above minicard title to below minicard title](https://github.com/wekan/wekan/commit/b33a3ef254719dede124921bde40ce8a47c796fc).
|
||||
Thanks to xet7.
|
||||
- [Changed Due Date etc dates to be at top of Minicard](https://github.com/wekan/wekan/commit/a3d37e621c1eeeb9cd586b8fb644eae498df7ac4).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix Docker latest tags at Docker Hub, Quay and GitHub](https://github.com/wekan/wekan/commit/2d8ac3bf8085c913d14fb8a89f84769366073967).
|
||||
Thanks to rikhuijzer and xet7.
|
||||
- [Fixes for Create Card at Calendar](https://github.com/wekan/wekan/pull/4934).
|
||||
Thanks to DimDz.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.91 2023-05-27 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [BoardAdmin and Admin can now set board background image URL](https://github.com/wekan/wekan/commit/49ef80ab6c2dc038941558f68eface5e82a87593).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.90 2023-05-24 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Added Edit Custom Field Value to api.py](https://github.com/wekan/wekan/commit/ea908adbf9b75607c61c0cbc2b23886aa8e95fe7).
|
||||
Thanks to RazvanTinca and xet7.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- Update docker-compose.yml info about Docker images used.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/30ada6086245eb9957385d96132268344ce9513b),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/e83b0ac6519be4163cb6702a4a97d10e7315f5d9).
|
||||
Thanks to xet7.
|
||||
- [Upgrade Snap Candidate to MongoDB 6.0.6](https://github.com/wekan/wekan/commit/87fc4f936a2e37c0b9e3353a7b6f93dbff7fc2b7).
|
||||
Thanks to MongoDB developers.
|
||||
- [Use GitHub Docker Registry. Updated release scripts](https://github.com/wekan/wekan/commit/28e5b0bd5b270b2e2d3de5dad46804ac0d20d898).
|
||||
Thanks to xet7.
|
||||
- [Sync Docker Registries](https://github.com/wekan/wekan/commit/32ec95ffa8b34d5a7d9dff94302520509479c838).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [To get corrent API docs generated, moved new_checklist_item API to correct file where is other checklist item API](https://github.com/wekan/wekan/commit/9de704040172e37769fa28cf571f293dfbd8bbb5).
|
||||
Thanks to xet7.
|
||||
- [Fix sharedDataFolder persisdent provide by k8s has no permission to mkdir and write](https://github.com/wekan/charts/commit/54c11ec8d7d165309632c455003b6e861e43fb4c).
|
||||
Thanks to new2001y.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.89 2023-05-12 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix for the Create Card at Calendar](https://github.com/wekan/wekan/pull/4923).
|
||||
Thanks to DimDz.
|
||||
- [Fixed broken migration migrate-attachments-collectionFS-to-ostrioFiles](https://github.com/wekan/wekan/pull/4926).
|
||||
Thanks to Aman-Maheshwari.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.88 2023-05-11 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Create Card on Calendar View](https://github.com/wekan/wekan/pull/4922).
|
||||
Thanks to DimDz.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [OpenaAPI: Also ignores ThrowStatement](https://github.com/wekan/wekan/pull/4918).
|
||||
Thanks to bentiss.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.87 2023-05-08 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- Added to meteor development options for logging also to ../wekan-log.txt, and showing deprecated API that is Meteor v2.12 new feature.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/9fc52838562c3179775a6b24c23d0385363a0661),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/521e840b54dd896eb192834133c5134a104f1d0b),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/e6c59fc9b0ac53abd7519121d3bff700b1a43c24),
|
||||
[Part 4](https://github.com/wekan/wekan/commit/0bd9f309a10dff200efe6e38c6161deaf93c776d).
|
||||
Thanks to Meteor developers and xet7.
|
||||
- [API: Added User and Admin API for New Checklist Item and Edit Card Custom Field](https://github.com/wekan/wekan/pull/4911).
|
||||
Thanks to DimDz.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/2b91557ad2931b3004a1da1ba0c790ed0e0546d3).
|
||||
Thanks to developers of dependencies.
|
||||
- [Upgraded to Meteor 2.12](https://github.com/wekan/wekan/commit/d519429ea14de3740408fbca3d231a1440562201).
|
||||
Thanks to Meteor developers.
|
||||
- [Updated translations](https://github.com/wekan/wekan/commit/40c077101a94f639b90f607624c4c72e12235711).
|
||||
xet7 fixed all translations of advanced filter description to have correct escaping of slash and backslash,
|
||||
so that bulding bundle of WeKan would not crash to invalid JSON syntax in translations.
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Added X for closing card opened in Global Search](https://github.com/wekan/wekan/pull/4910).
|
||||
Thanks to deniszulic.
|
||||
|
||||
and tried to fix the following bugs:
|
||||
|
||||
- [Tried to fix building WeKan OpenAPI docs using Ubuntu 23.04 amd64 with XFCE desktop, but it did not work, still getting error: Failed to parse the source OpenAPI document](https://github.com/wekan/wekan/commit/97c6b6531502d09cbd6c267212651f3036338a11).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.86 2023-04-26 WeKan ® release
|
||||
|
||||
This release fixes the following CRITICAL SECURITY FIXES:
|
||||
|
||||
- [Security fix to InvisibleBleed in WeKan. Escape HTML comment tags so that HTML comments are visible](https://github.com/wekan/wekan/commit/167863d95711249e69bb3511175d73b34acbbdb3).
|
||||
Thanks to xet7 for fixing.
|
||||
- [Security Fix to AdminBleed in WeKan, so that non-admin can not change to Admin](https://github.com/wekan/wekan/commit/cbad4cf5943d47b916f64b4582f8ca76a9dfd743).
|
||||
Thanks to Christian Pöschl of usd AG Responsible Disclosure Team for reporting and xet7 for fixing.
|
||||
|
||||
and adds the following new features:
|
||||
|
||||
- [Feature: Show plus sign in front of attachments](https://github.com/wekan/wekan/commit/2b13158fcd37ff7163fc3d97b88b6bf920dd7b9c).
|
||||
Thanks to Meeques and xet7.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Upgrade to Meteor 2.12-beta.2](https://github.com/wekan/wekan/commit/4d9d4a9dfdd5bb0fc5997351df8995f72d9ca82c).
|
||||
Thanks to Meteor developers.
|
||||
- [Update Docker Ubuntu base image and Meteor version](https://github.com/wekan/wekan/commit/bcd43629cc4074bc4f9b0b70189645ae91cfe59a).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- Fix Exception in callback of async function: TypeError: this._now is not a function.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/aeb0f1e6d8d9f5d8808128f4049768bea57ca164),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/aef6967d4c90544aa0281d22b6df46b2dd40467f).
|
||||
Thanks to xet7.
|
||||
- [Remove extra debug message and disable some rarely used feature that produces errors](https://github.com/wekan/wekan/commit/c0bdde26cfd2ae6d1aeaf8b5c7ce0eb72ada6dec).
|
||||
Thanks to xet7.
|
||||
- [Revert some migration filename changes](https://github.com/wekan/wekan/commit/3300bbe9e7a6c02c753b0d1f2e8547d1d85cb76c).
|
||||
Thanks to xet7.
|
||||
- [Add back node-gyp related dependencies](https://github.com/wekan/wekan/commit/712dbb8e73df740816eb66257e834bc7e22bd0fb).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.85 2023-04-18 WeKan ® release
|
||||
|
||||
This release adds the following CRITICAL SECURITY FIXES:
|
||||
|
||||
- [Security fix to ReactionBleed in WeKan. It is XSS in feature "Reaction to comment"](https://github.com/wekan/wekan/commit/47ac33d6c234359c31d9b5eae49ed3e793907279).
|
||||
Thanks to Alexander Starikov at Jet Infosystems (https://jetinfosystems.com/) for reporting and fixing.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/fb37f48a86732be40c20c58eb336fa262218d0fe).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Disable file validation temporarily, because it causes data loss of some attachments when upgrading](https://github.com/wekan/wekan/commit/e7122a9b368e25cc155f39e34fff741fcc9f004c).
|
||||
Thanks to xet7.
|
||||
- [Added uploadedAt and copies to be migrated when migrating CollectionFS to ostrio-files](https://github.com/wekan/wekan/commit/0090734cd85435e852d2546d20c5a16a24a1ae66).
|
||||
Thanks to xet7
|
||||
- [Added more descriptive times of attachment migrations and uploads](https://github.com/wekan/wekan/commit/f11650ece1ccd8cd8ff820c1ccb39086129e01d0).
|
||||
Thanks to xet7.
|
||||
- [Fix LDAP Group Filtering does not work](https://github.com/wekan/wekan/commit/2da7b1d5420d7621cafa387db5c63bf1612e3d08).
|
||||
Thanks to emilburggraf, psteinforth, craig-silva, Daniel-H76, benh57, falkheiland and xet7.
|
||||
- [Save files serverside with filename ObjectID, without filename](https://github.com/wekan/wekan/commit/76ac070f9b99388fa9e13bd987b1c93ed1f465c7).
|
||||
Thanks to g-roliveira, iamabrantes, Floaz, koelle25, scott-dunt, mfilser and xet7.
|
||||
- [Fixed count of found cards in Global Search](https://github.com/wekan/wekan/commit/9af03b0416b532f2084d0320b95388f0009fb364).
|
||||
Thanks to xet7.
|
||||
- [Fix Card opens full width by opening at left](https://github.com/wekan/wekan/commit/418fe725e5846620a244b22bce2e0d1194ebf033).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.84 2023-04-11 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Get card drag/drop working for empty swimlane](https://github.com/wekan/wekan/pull/4883).
|
||||
Thanks to mfilser.
|
||||
- [Added 'next week' due date filter](https://github.com/wekan/wekan/pull/4884).
|
||||
Thanks to helioguardabaxo.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.83 2023-04-08 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix open card position by opening card to fullscreen](https://github.com/wekan/wekan/commit/030faf918e64ab5ee359703c038c7c7a3d3154ae).
|
||||
Thanks to SmartPhoneLover, BabyFnord and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.82 2023-04-07 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Added missing docs of Snap avatars max size etc](https://github.com/wekan/wekan/commit/2aba1e3bf98717f403b064f4de3f893bf1b009aa).
|
||||
Thanks to xet7.
|
||||
- [Fix avatar if Meteor.user() is undefined](https://github.com/wekan/wekan/pull/4876).
|
||||
Thanks to mfilser.
|
||||
- [Fix broken add_board_member API and return value for remove_board_member](https://github.com/wekan/wekan/pull/4880).
|
||||
Thanks to gustavengstrom.
|
||||
- [Try to fix card open position and make card resizeable](https://github.com/wekan/wekan/commit/f258d8d51784839d06b34e43ec50951603340037).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.81 2023-03-26 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Helm Chart - fix: broken secretEnv indentation](https://github.com/wekan/charts/pull/18).
|
||||
Fixed in already released WeKan Helm Chart 1.2.7.
|
||||
Thanks to Nightreaver.
|
||||
- [Fix Bug: Cardoptions disappear behind scrollbar in german](https://github.com/wekan/wekan/commit/bf636725e8637200c2121e754297d281f8c38d4e).
|
||||
Thanks to Meeques and xet7.
|
||||
- [Add some info about allowed filesizes and filetypes for attachments and avatars](https://github.com/wekan/wekan/commit/5b3bd8ff2a29e2c1ada4c49de4c50c132b603863).
|
||||
Thanks to Meeques and xet7.
|
||||
- [Disable MongoDB telemetry and free monitoring in WeKan Snap](https://github.com/wekan/wekan/commit/df152e292dadd10a9873c21fff9571b98a06eec6).
|
||||
Thanks to webenefits and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.80 2023-03-23 WeKan ® release
|
||||
|
||||
This release adds the following improvements:
|
||||
|
||||
- [Helm Charts secretEnv: Modify secret and deployment to allow users to provide secretEnv with empty value](https://github.com/wekan/charts/pull/13).
|
||||
Thanks to jehutyy.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Custom Fields, display Grid Button only if more than 1 custom field](https://github.com/wekan/wekan/pull/4864).
|
||||
Thanks to mfilser.
|
||||
- Helm Charts: Add missing data-storage as pvc for WRITABLE_PATH.
|
||||
[Part 1](https://github.com/wekan/charts/issues/14),
|
||||
[Part 2](https://github.com/wekan/charts/pull/15),
|
||||
[Part 3](https://github.com/wekan/charts/pull/16).
|
||||
Thanks to Nightreaver, NotTheEvilOne and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.79 2023-03-22 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Upgraded to Meteor 2.11.0](https://github.com/wekan/wekan/commit/e48db7d7ea7e70dc767576126be35927ced24ee5).
|
||||
Thanks to Meteor developers.
|
||||
- [Use MongoDB 6](https://github.com/wekan/wekan/commit/4aeab872de2c9d0365a4b8872b6b015a36666615).
|
||||
Thanks to to MongoDB.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Avatar upload was broken if no size is configured](https://github.com/wekan/wekan/pull/4857).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.78 2023-02-28 WeKan ® release
|
||||
|
||||
This release fixes the following CRITICAL SECURITY ISSUES:
|
||||
|
||||
- [Try to fix some security issue](https://github.com/wekan/wekan/commit/5d79c231ed3cfc09636ab678b3f62ea9f36160f2).
|
||||
Thanks to Responsible Security Disclousure contributors and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.77 2023-02-27 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- Updated release scripts
|
||||
[Part 1](https://github.com/wekan/wekan/commit/23e01130e907f0068333046dc4b88a471b781ce7),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/ad53414c4d415b93e808ec88cc36af5a4741f681),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/e390852a673be25e00cb397acf4dbdc5a7d2a1f9).
|
||||
Updated release scripts.
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fixed indentation for image size and compression in docker-compose.yml](https://github.com/wekan/wekan/pull/4846).
|
||||
Thanks to Entepotenz.
|
||||
- [Made ☰ menu buttons bigger at minicard and list, they were too hard to click when they were small](https://github.com/wekan/wekan/commit/c2cf850179ad0079d83561675b6dc2c59825cc11).
|
||||
Thanks to mohammadZahedian and xet7.
|
||||
- [Added "Move card to archive" to minicard ☰ menu](https://github.com/wekan/wekan/commit/1deccf2f4b5ba1a72bc76d5ae83858e6c50b36ae).
|
||||
Thanks to mohammadZahedian and xet7.
|
||||
- [Fix attachment migration error about avatarUrl startsWith undefined](https://github.com/wekan/wekan/commit/7b2cff4c5e7bae4971776638b680696596edc7e6).
|
||||
Thanks to xet7.
|
||||
- Try to fix attachment migrations to ostrioFiles, allow existing files to be migrated.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/9216a69c0541325be6941c07d256b07627a8ec73),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/16ad6bf9fc75b39e6e8cedb8a5a98ec963ccf14a).
|
||||
Thanks to xet7.
|
||||
- [MongoDB to 5 for beta Snap. MongoDB 5 does not seem to show some errors that only MongoDB 6 has](https://github.com/wekan/wekan/commit/a64381153fd762b67f2a752b590b2cdd196bcfe5).
|
||||
Thanks to xet7.
|
||||
- [Use MongoDB 5 at docker-compose.yml](https://github.com/wekan/wekan/commit/51f22f48dc916717ed6be9502dc767798692f07b).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.76 2023-02-22 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
@@ -34,7 +699,7 @@ Thanks to above GitHub users for their contributions and translators for their t
|
||||
|
||||
This release fixes the following CRITICAL SECURITY ISSUES:
|
||||
|
||||
- Try to fix some security issues.
|
||||
- Security Fix of Filebleed in WeKan. That is XSS in filename.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/ff993e7c917b5650a790238e95c78001e4f0e039),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/382168a5b428a7124d368c4fcb37e7e140e7ec8b).
|
||||
Thanks to responsible security disclosure contributors and xet7.
|
||||
@@ -52,6 +717,8 @@ and fixes the following bugs:
|
||||
Thanks to garciadavy.
|
||||
- [Swipebox slide background gradient of black to blue, so that back SVG images are visible](https://github.com/wekan/wekan/commit/c3577aa434ac5330d664f17d0771ff9679cced86).
|
||||
Thanks to xet7.
|
||||
- [Fix typo](https://github.com/wekan/wekan/pull/4840).
|
||||
Thanks to robert-scheck.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
@@ -7007,7 +7674,7 @@ This release adds the following new features, thanks to xet7:
|
||||
and adds the following [themes to board background colors](https://github.com/wekan/wekan/commit/c04292e98832e3aa7952e8a7858d47a853f40aad), thanks to xet7:
|
||||
|
||||
- RELAX MODE, so when green background selected, list background is light green.
|
||||
- [DARK MODE](https://github.com/wekan/wekan/issues/1149), when dark backgroud color selected. Please test and send color visibility fixes as pull requests.
|
||||
- [DARK MODE](https://github.com/wekan/wekan/issues/1149), when dark background color selected. Please test and send color visibility fixes as pull requests.
|
||||
- In RELAX MODE and DARK MODE, [hide card fields: received, start, due, end, members, requested, assigned](https://github.com/wekan/wekan/commit/b42ecb7948ad194433dc4460305174965106a751).
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
FROM --platform=linux/amd64 ubuntu:22.10 as wekan
|
||||
FROM --platform=linux/amd64 ubuntu:23.04 as wekan
|
||||
LABEL maintainer="wekan"
|
||||
|
||||
# 2022-09-04:
|
||||
@@ -22,7 +22,7 @@ ARG DEBIAN_FRONTEND=noninteractive
|
||||
ENV BUILD_DEPS="apt-utils libarchive-tools gnupg gosu wget curl bzip2 g++ build-essential git ca-certificates python3" \
|
||||
DEBUG=false \
|
||||
NODE_VERSION=v14.21.3 \
|
||||
METEOR_RELEASE=2.8.1 \
|
||||
METEOR_RELEASE=METEOR@2.12-beta.2 \
|
||||
USE_EDGE=false \
|
||||
METEOR_EDGE=1.5-beta.17 \
|
||||
NPM_VERSION=latest \
|
||||
|
||||
+7
-1
@@ -78,7 +78,13 @@ RUN \
|
||||
chown wekan --recursive /home/wekan/.config && \
|
||||
\
|
||||
# Install Node dependencies
|
||||
npm install -g npm@${NPM_VERSION}
|
||||
npm install -g npm@${NPM_VERSION} && \
|
||||
\
|
||||
# Install Health Check dependencies
|
||||
apk add curl
|
||||
|
||||
HEALTHCHECK --start-period=30s --interval=30s --timeout=10s --retries=3 \
|
||||
CMD curl --fail "http://localhost:$PORT" || exit 1
|
||||
|
||||
EXPOSE $PORT
|
||||
USER wekan
|
||||
|
||||
@@ -16,9 +16,9 @@ Other platforms and compatible software versions at https://wekan.github.io Down
|
||||
- [OSS Insight](https://ossinsight.io/analyze/wekan/wekan)
|
||||
- [CII Best Practices](https://bestpractices.coreinfrastructure.org/projects/4619)
|
||||
|
||||
## [Translate WeKan ® at Transifex](https://transifex.com/wekan/wekan)
|
||||
## [Translate WeKan ® at Transifex](https://app.transifex.com/wekan/)
|
||||
|
||||
Translations to non-English languages are accepted only at [Transifex](https://transifex.com/wekan/wekan) using webbrowser.
|
||||
Translations to non-English languages are accepted only at [Transifex](https://app.transifex.com/wekan/) using webbrowser.
|
||||
New English strings of new features can be added as PRs to master branch file wekan/imports/i18n/data/en.i18n.json .
|
||||
|
||||
## [WeKan ® feature requests and bugs](https://github.com/wekan/wekan/issues)
|
||||
@@ -58,8 +58,8 @@ install Wekan on your own computer or server. In fact we encourage you to do
|
||||
that by providing one-click installation on various platforms.
|
||||
|
||||
- WeKan ® is used in [most countries of the world](https://snapcraft.io/wekan).
|
||||
- WeKan ® largest user has 22k users using WeKan ® in their company.
|
||||
- WeKan ® has been [translated](https://transifex.com/wekan/wekan) to about 105 languages.
|
||||
- WeKan ® largest user has 30k users using WeKan ® in their company.
|
||||
- WeKan ® has been [translated](https://app.transifex.com/wekan/) to about 105 languages.
|
||||
- [Features][features]: WeKan ® has real-time user interface.
|
||||
- [Platforms][platforms]: WeKan ® supports many platforms.
|
||||
WeKan ® is critical part of new platforms Wekan is currently being integrated to.
|
||||
@@ -116,7 +116,7 @@ with [Meteor](https://www.meteor.com).
|
||||
[wekan_issues]: https://github.com/wekan/wekan/issues
|
||||
[docker_image]: https://hub.docker.com/r/wekanteam/wekan/
|
||||
[wekan_wiki]: https://github.com/wekan/wekan/wiki
|
||||
[translate_wekan]: https://www.transifex.com/wekan/wekan/
|
||||
[translate_wekan]: https://app.transifex.com/wekan/
|
||||
[open_source]: https://en.wikipedia.org/wiki/Open-source_software
|
||||
[free_software]: https://en.wikipedia.org/wiki/Free_software
|
||||
[discussions]: https://github.com/wekan/wekan/discussions
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
|
||||
appVersion: "v6.76.0"
|
||||
appVersion: "v7.01.0"
|
||||
files:
|
||||
userUploads:
|
||||
- README.md
|
||||
|
||||
@@ -37,6 +37,7 @@ If *nix: chmod +x api.py => ./api.py users
|
||||
python3 api.py customfields BOARDID # Custom Fields of BOARDID
|
||||
python3 api.py customfield BOARDID CUSTOMFIELDID # Info of CUSTOMFIELDID
|
||||
python3 api.py addcustomfieldtoboard AUTHORID BOARDID NAME TYPE SETTINGS SHOWONCARD AUTOMATICALLYONCARD SHOWLABELONMINICARD SHOWSUMATTOPOFLIST # Add Custom Field to Board
|
||||
python3 api.py editcustomfield BOARDID LISTID CARDID CUSTOMFIELDID NEWCUSTOMFIELDVALUE
|
||||
python3 api.py listattachments BOARDID # List attachments
|
||||
|
||||
Admin API:
|
||||
@@ -217,6 +218,25 @@ if arguments == 6:
|
||||
print(data2)
|
||||
# ------- EDIT CARD END -----------
|
||||
|
||||
if sys.argv[1] == 'editcustomfield':
|
||||
|
||||
# ------- EDIT CUSTOMFIELD START -----------
|
||||
boardid = sys.argv[2]
|
||||
listid = sys.argv[3]
|
||||
cardid = sys.argv[4]
|
||||
customfieldid = sys.argv[5]
|
||||
newcustomfieldvalue = sys.argv[6]
|
||||
edfield = wekanurl + apiboards + boardid + s + l + s + listid + s + cs + s + cardid + s + 'customFields' + s + customfieldid
|
||||
#print(edfield)
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
post_data = {'_id': '{}'.format(customfieldid), 'value': '{}'.format(newcustomfieldvalue)}
|
||||
#print(post_data)
|
||||
body = requests.post(edfield, data=post_data, headers=headers)
|
||||
print("=== EDIT CUSTOMFIELD ===\n")
|
||||
data2 = body.text.replace('}',"}\n")
|
||||
print(data2)
|
||||
# ------- EDIT CUSTOMFIELD END -----------
|
||||
|
||||
if arguments == 4:
|
||||
|
||||
if sys.argv[1] == 'newuser':
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import DOMPurify from 'dompurify';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
@@ -24,7 +25,7 @@ BlazeComponent.extendComponent({
|
||||
searchId = Session.get(`current${capitalizedMode}`);
|
||||
}
|
||||
const limit = this.page.get() * activitiesPerPage;
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
const hideSystem = user ? user.hasHiddenSystemMessages() : false;
|
||||
if (searchId === null) return;
|
||||
|
||||
@@ -65,7 +66,7 @@ Template.activities.helpers({
|
||||
BlazeComponent.extendComponent({
|
||||
checkItem() {
|
||||
const checkItemId = this.currentData().activity.checklistItemId;
|
||||
const checkItem = ChecklistItems.findOne({ _id: checkItemId });
|
||||
const checkItem = ReactiveCache.getChecklistItem(checkItemId);
|
||||
return checkItem && checkItem.title;
|
||||
},
|
||||
|
||||
@@ -145,7 +146,7 @@ BlazeComponent.extendComponent({
|
||||
lastLabel() {
|
||||
const lastLabelId = this.currentData().activity.labelId;
|
||||
if (!lastLabelId) return null;
|
||||
const lastLabel = Boards.findOne(
|
||||
const lastLabel = ReactiveCache.getBoard(
|
||||
this.currentData().activity.boardId,
|
||||
).getLabelById(lastLabelId);
|
||||
if (lastLabel && (lastLabel.name === undefined || lastLabel.name === '')) {
|
||||
@@ -158,7 +159,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
lastCustomField() {
|
||||
const lastCustomField = CustomFields.findOne(
|
||||
const lastCustomField = ReactiveCache.getCustomField(
|
||||
this.currentData().activity.customFieldId,
|
||||
);
|
||||
if (!lastCustomField) return null;
|
||||
@@ -166,7 +167,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
lastCustomFieldValue() {
|
||||
const lastCustomField = CustomFields.findOne(
|
||||
const lastCustomField = ReactiveCache.getCustomField(
|
||||
this.currentData().activity.customFieldId,
|
||||
);
|
||||
if (!lastCustomField) return null;
|
||||
@@ -282,10 +283,10 @@ Template.activity.helpers({
|
||||
|
||||
Template.commentReactions.events({
|
||||
'click .reaction'(event) {
|
||||
if (Meteor.user().isBoardMember()) {
|
||||
if (ReactiveCache.getCurrentUser().isBoardMember()) {
|
||||
const codepoint = event.currentTarget.dataset['codepoint'];
|
||||
const commentId = Template.instance().data.commentId;
|
||||
const cardComment = CardComments.findOne({_id: commentId});
|
||||
const cardComment = ReactiveCache.getCardComment(commentId);
|
||||
cardComment.toggleReaction(codepoint);
|
||||
}
|
||||
},
|
||||
@@ -294,10 +295,10 @@ Template.commentReactions.events({
|
||||
|
||||
Template.addReactionPopup.events({
|
||||
'click .add-comment-reaction'(event) {
|
||||
if (Meteor.user().isBoardMember()) {
|
||||
if (ReactiveCache.getCurrentUser().isBoardMember()) {
|
||||
const codepoint = event.currentTarget.dataset['codepoint'];
|
||||
const commentId = Template.instance().data.commentId;
|
||||
const cardComment = CardComments.findOne({_id: commentId});
|
||||
const cardComment = ReactiveCache.getCardComment(commentId);
|
||||
cardComment.toggleReaction(codepoint);
|
||||
}
|
||||
Popup.back();
|
||||
@@ -325,12 +326,13 @@ Template.addReactionPopup.helpers({
|
||||
|
||||
Template.commentReactions.helpers({
|
||||
isSelected(userIds) {
|
||||
return userIds.includes(Meteor.user()._id);
|
||||
return Meteor.userId() && userIds.includes(Meteor.userId());
|
||||
},
|
||||
userNames(userIds) {
|
||||
return Users.find({_id: {$in: userIds}})
|
||||
.map(user => user.profile.fullname)
|
||||
.join(', ');
|
||||
const ret = ReactiveCache.getUsers({_id: {$in: userIds}})
|
||||
.map(user => user.profile.fullname)
|
||||
.join(', ');
|
||||
return ret;
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
const commentFormIsOpen = new ReactiveVar(false);
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
@@ -24,7 +26,7 @@ BlazeComponent.extendComponent({
|
||||
let boardId = card.boardId;
|
||||
let cardId = card._id;
|
||||
if (card.isLinkedCard()) {
|
||||
boardId = Cards.findOne(card.linkedId).boardId;
|
||||
boardId = ReactiveCache.getCard(card.linkedId).boardId;
|
||||
cardId = card.linkedId;
|
||||
} else if (card.isLinkedBoard()) {
|
||||
boardId = card.linkedId;
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.subscribe('archivedBoards');
|
||||
},
|
||||
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
|
||||
archivedBoards() {
|
||||
return Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{ archived: true },
|
||||
{
|
||||
sort: { archivedAt: -1, modifiedAt: -1 },
|
||||
},
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
|
||||
events() {
|
||||
@@ -25,8 +28,8 @@ BlazeComponent.extendComponent({
|
||||
Meteor.settings &&
|
||||
Meteor.settings.public &&
|
||||
Meteor.settings.public.sandstorm;
|
||||
if (isSandstorm && Session.get('currentBoard')) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
if (isSandstorm && Utils.getCurrentBoardId()) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
currentBoard.archive();
|
||||
}
|
||||
const board = this.currentData();
|
||||
@@ -39,8 +42,8 @@ BlazeComponent.extendComponent({
|
||||
Meteor.settings &&
|
||||
Meteor.settings.public &&
|
||||
Meteor.settings.public.sandstorm;
|
||||
if (isSandstorm && Session.get('currentBoard')) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
if (isSandstorm && Utils.getCurrentBoardId()) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
Boards.remove(currentBoard._id);
|
||||
}
|
||||
Boards.remove(this._id);
|
||||
|
||||
@@ -167,3 +167,58 @@
|
||||
border-color: #2b004d;
|
||||
color: #fff !important;
|
||||
}
|
||||
/* Modal Styles */
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 9999;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.modal-dialog {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 25%; /* Adjust the height to make it smaller */
|
||||
position: relative;
|
||||
margin: 10% auto; /* This margin will help center the modal vertically */
|
||||
max-width: 400px; /* Adjust the max-width to make it smaller */
|
||||
background-color: #fff;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.modal-header {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-bottom: 1px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
.modal-title {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
}
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-top: 4px;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
.close {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
font-size: 25px;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
const subManager = new SubsManager();
|
||||
@@ -43,9 +44,9 @@ BlazeComponent.extendComponent({
|
||||
this.mouseHasEnterCardDetails = false;
|
||||
|
||||
// fix swimlanes sort field if there are null values
|
||||
const currentBoardData = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoardData = Utils.getCurrentBoard();
|
||||
const nullSortSwimlanes = currentBoardData.nullSortSwimlanes();
|
||||
if (nullSortSwimlanes.count() > 0) {
|
||||
if (nullSortSwimlanes.length > 0) {
|
||||
const swimlanes = currentBoardData.swimlanes();
|
||||
let count = 0;
|
||||
swimlanes.forEach(s => {
|
||||
@@ -60,7 +61,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
// fix lists sort field if there are null values
|
||||
const nullSortLists = currentBoardData.nullSortLists();
|
||||
if (nullSortLists.count() > 0) {
|
||||
if (nullSortLists.length > 0) {
|
||||
const lists = currentBoardData.lists();
|
||||
let count = 0;
|
||||
lists.forEach(l => {
|
||||
@@ -204,33 +205,26 @@ BlazeComponent.extendComponent({
|
||||
}
|
||||
|
||||
// Disable drag-dropping if the current user is not a board member
|
||||
//$swimlanesDom.sortable('option', 'disabled', !userIsMember());
|
||||
$swimlanesDom.sortable(
|
||||
'option',
|
||||
'disabled',
|
||||
!Meteor.user() || !Meteor.user().isBoardAdmin(),
|
||||
!ReactiveCache.getCurrentUser()?.isBoardAdmin(),
|
||||
);
|
||||
});
|
||||
|
||||
function userIsMember() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly()
|
||||
);
|
||||
}
|
||||
|
||||
// If there is no data in the board (ie, no lists) we autofocus the list
|
||||
// creation form by clicking on the corresponding element.
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
if (userIsMember() && currentBoard.lists().count() === 0) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
if (Utils.canModifyBoard() && currentBoard.lists().length === 0) {
|
||||
boardComponent.openNewListForm();
|
||||
}
|
||||
|
||||
Utils.setBackgroundImage();
|
||||
},
|
||||
|
||||
notDisplayThisBoard() {
|
||||
let allowPrivateVisibilityOnly = TableVisibilityModeSettings.findOne('tableVisibilityMode-allowPrivateOnly');
|
||||
let currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
let currentBoard = Utils.getCurrentBoard();
|
||||
if (allowPrivateVisibilityOnly !== undefined && allowPrivateVisibilityOnly.booleanValue && currentBoard.permission == 'public') {
|
||||
return true;
|
||||
}
|
||||
@@ -239,7 +233,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
isViewSwimlanes() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).boardView === 'board-view-swimlanes';
|
||||
} else {
|
||||
@@ -250,7 +244,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
isViewLists() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).boardView === 'board-view-lists';
|
||||
} else {
|
||||
@@ -259,7 +253,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
isViewCalendar() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).boardView === 'board-view-cal';
|
||||
} else {
|
||||
@@ -328,6 +322,7 @@ BlazeComponent.extendComponent({
|
||||
id: 'calendar-view',
|
||||
defaultView: 'agendaDay',
|
||||
editable: true,
|
||||
selectable: true,
|
||||
timezone: 'local',
|
||||
weekNumbers: true,
|
||||
header: {
|
||||
@@ -349,7 +344,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
locale: TAPi18n.getLanguage(),
|
||||
events(start, end, timezone, callback) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const events = [];
|
||||
const pushEvent = function (card, title, start, end, extraCls) {
|
||||
start = start || card.startAt;
|
||||
@@ -395,7 +390,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
eventResize(event, delta, revertFunc) {
|
||||
let isOk = false;
|
||||
const card = Cards.findOne(event.id);
|
||||
const card = ReactiveCache.getCard(event.id);
|
||||
|
||||
if (card) {
|
||||
card.setEnd(event.end.toDate());
|
||||
@@ -407,7 +402,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
eventDrop(event, delta, revertFunc) {
|
||||
let isOk = false;
|
||||
const card = Cards.findOne(event.id);
|
||||
const card = ReactiveCache.getCard(event.id);
|
||||
if (card) {
|
||||
// TODO: add a flag for allDay events
|
||||
if (!event.allDay) {
|
||||
@@ -422,10 +417,62 @@ BlazeComponent.extendComponent({
|
||||
revertFunc();
|
||||
}
|
||||
},
|
||||
select: function (startDate) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
const modalElement = document.createElement('div');
|
||||
modalElement.classList.add('modal', 'fade');
|
||||
modalElement.setAttribute('tabindex', '-1');
|
||||
modalElement.setAttribute('role', 'dialog');
|
||||
modalElement.innerHTML = `
|
||||
<div class="modal-dialog justify-content-center align-items-center" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">${TAPi18n.__('r-create-card')}</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body text-center">
|
||||
<input type="text" class="form-control" id="card-title-input" placeholder="">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" id="create-card-button">${TAPi18n.__('add-card')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
const createCardButton = modalElement.querySelector('#create-card-button');
|
||||
createCardButton.addEventListener('click', function () {
|
||||
const myTitle = modalElement.querySelector('#card-title-input').value;
|
||||
if (myTitle) {
|
||||
const firstList = currentBoard.draggableLists()[0];
|
||||
const firstSwimlane = currentBoard.swimlanes()[0];
|
||||
Meteor.call('createCardWithDueDate', currentBoard._id, firstList._id, myTitle, startDate.toDate(), firstSwimlane._id, function(error, result) {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
} else {
|
||||
console.log("Card Created", result);
|
||||
}
|
||||
});
|
||||
closeModal();
|
||||
}
|
||||
});
|
||||
document.body.appendChild(modalElement);
|
||||
const openModal = function() {
|
||||
modalElement.style.display = 'flex';
|
||||
};
|
||||
const closeModal = function() {
|
||||
modalElement.style.display = 'none';
|
||||
};
|
||||
const closeButton = modalElement.querySelector('[data-dismiss="modal"]');
|
||||
closeButton.addEventListener('click', closeModal);
|
||||
openModal();
|
||||
}
|
||||
};
|
||||
},
|
||||
isViewCalendar() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).boardView === 'board-view-cal';
|
||||
} else {
|
||||
|
||||
@@ -1834,19 +1834,20 @@
|
||||
background-color: #4d4d4d !important;
|
||||
}
|
||||
.board-color-moderndark .minicard .minicard-labels {
|
||||
margin-bottom: 4px;
|
||||
margin: 8px 0 4px;
|
||||
}
|
||||
.board-color-moderndark .minicard .card-label {
|
||||
font-size: 11px;
|
||||
font-weight: 400;
|
||||
padding: 1px 6px 0;
|
||||
border-radius: 2px;
|
||||
line-height: 18px;
|
||||
}
|
||||
.board-color-moderndark .minicard .badges {
|
||||
color: #bbb;
|
||||
}
|
||||
.board-color-moderndark .minicard .date {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
font-size: 11px;
|
||||
}
|
||||
.board-color-moderndark .card-date {
|
||||
@@ -1975,7 +1976,7 @@
|
||||
background-color: #ccc;
|
||||
color: #222;
|
||||
}
|
||||
.board-color-moderndark .attachments-galery .attachment-item {
|
||||
.board-color-moderndark .attachments-gallery .attachment-item {
|
||||
color: #222;
|
||||
}
|
||||
.board-color-moderndark .minicard-description {
|
||||
@@ -2147,10 +2148,10 @@
|
||||
.board-color-exodark .sidebar-content {
|
||||
box-shadow: 0 0 7px 0 #00897b;
|
||||
}
|
||||
.board-color-exodark .attachments-galery .attachment-item {
|
||||
.board-color-exodark .attachments-gallery .attachment-item {
|
||||
background: #2b2b2b;
|
||||
}
|
||||
.board-color-exodark .attachments-galery .attachment-item:hover {
|
||||
.board-color-exodark .attachments-gallery .attachment-item:hover {
|
||||
border: 1px solid #00897b;
|
||||
background: #2b2b2b;
|
||||
}
|
||||
|
||||
@@ -39,9 +39,9 @@ template(name="boardHeaderBar")
|
||||
span {{_ watchLevel}}
|
||||
a.board-header-btn(title="{{_ 'sort-cards'}}" class="{{#if isSortActive }}emphasis{{else}} js-sort-cards {{/if}}")
|
||||
i.fa.fa-sort
|
||||
span {{#if isSortActive }}{{_ 'Sort is on'}}{{else}}{{_ 'sort-cards'}}{{/if}}
|
||||
span {{#if isSortActive }}{{_ 'sort-is-on'}}{{else}}{{_ 'sort-cards'}}{{/if}}
|
||||
if isSortActive
|
||||
a.board-header-btn-close.js-sort-reset(title="Remove Sort")
|
||||
a.board-header-btn-close.js-sort-reset(title="{{_ 'remove-sort'}}")
|
||||
i.fa.fa-times-thin
|
||||
|
||||
else
|
||||
@@ -82,9 +82,9 @@ template(name="boardHeaderBar")
|
||||
span {{_ watchLevel}}
|
||||
a.board-header-btn(title="{{_ 'sort-cards'}}" class="{{#if isSortActive }}emphasis{{else}} js-sort-cards {{/if}}")
|
||||
i.fa.fa-sort
|
||||
span {{#if isSortActive }}{{_ 'Sort is on'}}{{else}}{{_ 'sort-cards'}}{{/if}}
|
||||
span {{#if isSortActive }}{{_ 'sort-is-on'}}{{else}}{{_ 'sort-cards'}}{{/if}}
|
||||
if isSortActive
|
||||
a.board-header-btn-close.js-sort-reset(title="Remove Sort")
|
||||
a.board-header-btn-close.js-sort-reset(title="{{_ 'remove-sort'}}")
|
||||
i.fa.fa-times-thin
|
||||
|
||||
else
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
/*
|
||||
@@ -18,14 +19,14 @@ Template.boardMenuPopup.events({
|
||||
'click .js-change-board-color': Popup.open('boardChangeColor'),
|
||||
'click .js-change-language': Popup.open('changeLanguage'),
|
||||
'click .js-archive-board ': Popup.afterConfirm('archiveBoard', function() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
currentBoard.archive();
|
||||
// XXX We should have some kind of notification on top of the page to
|
||||
// confirm that the board was successfully archived.
|
||||
FlowRouter.go('home');
|
||||
}),
|
||||
'click .js-delete-board': Popup.afterConfirm('deleteBoard', function() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
Popup.back();
|
||||
Boards.remove(currentBoard._id);
|
||||
FlowRouter.go('home');
|
||||
@@ -58,24 +59,24 @@ Template.boardChangeTitlePopup.events({
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
watchLevel() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return currentBoard && currentBoard.getWatchLevel(Meteor.userId());
|
||||
},
|
||||
|
||||
isStarred() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
return user && user.hasStarred(boardId);
|
||||
},
|
||||
|
||||
// Only show the star counter if the number of star is greater than 2
|
||||
showStarCounter() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return currentBoard && currentBoard.stars >= 2;
|
||||
},
|
||||
/*
|
||||
showSort() {
|
||||
return Meteor.user().hasSortBy();
|
||||
return ReactiveCache.getCurrentUser().hasSortBy();
|
||||
},
|
||||
directionClass() {
|
||||
return this.currentDirection() === -1 ? DOWNCLS : UPCLS;
|
||||
@@ -85,10 +86,10 @@ BlazeComponent.extendComponent({
|
||||
Meteor.call('setListSortBy', direction + this.currentListSortBy());
|
||||
},
|
||||
currentDirection() {
|
||||
return Meteor.user().getListSortByDirection();
|
||||
return ReactiveCache.getCurrentUser().getListSortByDirection();
|
||||
},
|
||||
currentListSortBy() {
|
||||
return Meteor.user().getListSortBy();
|
||||
return ReactiveCache.getCurrentUser().getListSortBy();
|
||||
},
|
||||
listSortShortDesc() {
|
||||
return `list-label-short-${this.currentListSortBy()}`;
|
||||
@@ -99,7 +100,7 @@ BlazeComponent.extendComponent({
|
||||
{
|
||||
'click .js-edit-board-title': Popup.open('boardChangeTitle'),
|
||||
'click .js-star-board'() {
|
||||
Meteor.user().toggleBoardStar(Session.get('currentBoard'));
|
||||
ReactiveCache.getCurrentUser().toggleBoardStar(Session.get('currentBoard'));
|
||||
},
|
||||
'click .js-open-board-menu': Popup.open('boardMenu'),
|
||||
'click .js-change-visibility': Popup.open('boardChangeVisibility'),
|
||||
@@ -158,13 +159,6 @@ BlazeComponent.extendComponent({
|
||||
}).register('boardHeaderBar');
|
||||
|
||||
Template.boardHeaderBar.helpers({
|
||||
canModifyBoard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly()
|
||||
);
|
||||
},
|
||||
boardView() {
|
||||
return Utils.boardView();
|
||||
},
|
||||
@@ -313,7 +307,7 @@ const CreateBoard = BlazeComponent.extendComponent({
|
||||
onSubmit(event) {
|
||||
super.onSubmit(event);
|
||||
// Immediately star boards crated with the headerbar popup.
|
||||
Meteor.user().toggleBoardStar(this.boardId.get());
|
||||
ReactiveCache.getCurrentUser().toggleBoardStar(this.boardId.get());
|
||||
}
|
||||
}.register('headerBarCreateBoardPopup'));
|
||||
|
||||
@@ -322,12 +316,12 @@ BlazeComponent.extendComponent({
|
||||
return !TableVisibilityModeSettings.findOne('tableVisibilityMode-allowPrivateOnly').booleanValue;
|
||||
},
|
||||
visibilityCheck() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return this.currentData() === currentBoard.permission;
|
||||
},
|
||||
|
||||
selectBoardVisibility() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const visibility = this.currentData();
|
||||
currentBoard.setVisibility(visibility);
|
||||
Popup.back();
|
||||
@@ -344,7 +338,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
watchLevel() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return currentBoard.getWatchLevel(Meteor.userId());
|
||||
},
|
||||
|
||||
@@ -384,7 +378,7 @@ BlazeComponent.extendComponent({
|
||||
allowedSortValues() {
|
||||
const types = [];
|
||||
const pushed = {};
|
||||
Meteor.user()
|
||||
ReactiveCache.getCurrentUser()
|
||||
.getListSortTypes()
|
||||
.forEach(type => {
|
||||
const key = type.replace(/^-/, '');
|
||||
@@ -400,16 +394,16 @@ BlazeComponent.extendComponent({
|
||||
return types;
|
||||
},
|
||||
Direction() {
|
||||
return Meteor.user().getListSortByDirection() === -1
|
||||
return ReactiveCache.getCurrentUser().getListSortByDirection() === -1
|
||||
? this.downClass
|
||||
: this.upClass;
|
||||
},
|
||||
sortby() {
|
||||
return Meteor.user().getListSortBy();
|
||||
return ReactiveCache.getCurrentUser().getListSortBy();
|
||||
},
|
||||
|
||||
setSortBy(type = null) {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
if (type === null) {
|
||||
type = user._getListSortBy();
|
||||
} else {
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
const subManager = new SubsManager();
|
||||
|
||||
Template.boardList.helpers({
|
||||
currentSetting() {
|
||||
return Settings.findOne();
|
||||
},
|
||||
hideCardCounterList() {
|
||||
return Utils.isMiniScreen() && Session.get('currentBoard');
|
||||
/* Bug Board icons random dance https://github.com/wekan/wekan/issues/4214
|
||||
return Utils.isMiniScreen() && Session.get('currentBoard'); */
|
||||
return true;
|
||||
},
|
||||
hideBoardMemberList() {
|
||||
return Utils.isMiniScreen() && Session.get('currentBoard');
|
||||
/* Bug Board icons random dance https://github.com/wekan/wekan/issues/4214
|
||||
return Utils.isMiniScreen() && Session.get('currentBoard'); */
|
||||
return true;
|
||||
},
|
||||
})
|
||||
|
||||
@@ -29,10 +31,10 @@ Template.boardListHeaderBar.helpers({
|
||||
//}
|
||||
},
|
||||
templatesBoardId() {
|
||||
return Meteor.user() && Meteor.user().getTemplatesBoardId();
|
||||
return ReactiveCache.getCurrentUser()?.getTemplatesBoardId();
|
||||
},
|
||||
templatesBoardSlug() {
|
||||
return Meteor.user() && Meteor.user().getTemplatesBoardSlug();
|
||||
return ReactiveCache.getCurrentUser()?.getTemplatesBoardSlug();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -40,7 +42,7 @@ BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
Meteor.subscribe('setting');
|
||||
Meteor.subscribe('tableVisibilityModeSettings');
|
||||
let currUser = Meteor.user();
|
||||
let currUser = ReactiveCache.getCurrentUser();
|
||||
let userLanguage;
|
||||
if (currUser && currUser.profile) {
|
||||
userLanguage = currUser.profile.language
|
||||
@@ -84,7 +86,6 @@ BlazeComponent.extendComponent({
|
||||
// DOM in its initial state. The card move is then handled reactively by
|
||||
// Blaze with the below query.
|
||||
$boards.sortable('cancel');
|
||||
|
||||
board.move(sortIndex.base);
|
||||
},
|
||||
});
|
||||
@@ -99,51 +100,34 @@ BlazeComponent.extendComponent({
|
||||
});
|
||||
},
|
||||
userHasTeams() {
|
||||
if (Meteor.user() != null && Meteor.user().teams && Meteor.user().teams.length > 0)
|
||||
if (ReactiveCache.getCurrentUser()?.teams?.length > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
},
|
||||
teamsDatas() {
|
||||
if (Meteor.user().teams)
|
||||
return Meteor.user().teams.sort((a, b) => a.teamDisplayName.localeCompare(b.teamDisplayName));
|
||||
const teams = ReactiveCache.getCurrentUser()?.teams
|
||||
if (teams)
|
||||
return teams.sort((a, b) => a.teamDisplayName.localeCompare(b.teamDisplayName));
|
||||
else
|
||||
return [];
|
||||
},
|
||||
userHasOrgs() {
|
||||
if (Meteor.user() != null && Meteor.user().orgs && Meteor.user().orgs.length > 0)
|
||||
if (ReactiveCache.getCurrentUser()?.orgs?.length > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
},
|
||||
/*
|
||||
userHasTemplates(){
|
||||
if(Meteor.user() != null && Meteor.user().orgs && Meteor.user().orgs.length > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
},
|
||||
*/
|
||||
orgsDatas() {
|
||||
if (Meteor.user().orgs)
|
||||
return Meteor.user().orgs.sort((a, b) => a.orgDisplayName.localeCompare(b.orgDisplayName));
|
||||
const orgs = ReactiveCache.getCurrentUser()?.orgs;
|
||||
if (orgs)
|
||||
return orgs.sort((a, b) => a.orgDisplayName.localeCompare(b.orgDisplayName));
|
||||
else
|
||||
return [];
|
||||
},
|
||||
userHasOrgsOrTeams() {
|
||||
let boolUserHasOrgs;
|
||||
if (Meteor.user() != null && Meteor.user().orgs && Meteor.user().orgs.length > 0)
|
||||
boolUserHasOrgs = true;
|
||||
else
|
||||
boolUserHasOrgs = false;
|
||||
|
||||
let boolUserHasTeams;
|
||||
if (Meteor.user() != null && Meteor.user().teams && Meteor.user().teams.length > 0)
|
||||
boolUserHasTeams = true;
|
||||
else
|
||||
boolUserHasTeams = false;
|
||||
|
||||
return (boolUserHasOrgs || boolUserHasTeams);
|
||||
const ret = this.userHasOrgs() || this.userHasTeams();
|
||||
return ret;
|
||||
},
|
||||
boards() {
|
||||
let query = {
|
||||
@@ -165,14 +149,7 @@ BlazeComponent.extendComponent({
|
||||
if (allowPrivateVisibilityOnly !== undefined && allowPrivateVisibilityOnly.booleanValue) {
|
||||
query.$and.push({ 'permission': 'private' });
|
||||
}
|
||||
const currUser = Users.findOne(Meteor.userId());
|
||||
|
||||
// const currUser = Users.findOne(Meteor.userId(), {
|
||||
// fields: {
|
||||
// orgs: 1,
|
||||
// teams: 1,
|
||||
// },
|
||||
// });
|
||||
const currUser = ReactiveCache.getCurrentUser();
|
||||
|
||||
let orgIdsUserBelongs = currUser !== undefined && currUser.teams !== 'undefined' ? currUser.orgIdsUserBelongs() : '';
|
||||
if (orgIdsUserBelongs && orgIdsUserBelongs != '') {
|
||||
@@ -204,51 +181,54 @@ BlazeComponent.extendComponent({
|
||||
};
|
||||
}
|
||||
|
||||
return Boards.find(query, {
|
||||
const ret = ReactiveCache.getBoards(query, {
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
});
|
||||
return ret;
|
||||
},
|
||||
boardLists(boardId) {
|
||||
let boardLists = [];
|
||||
const lists = Lists.find({ 'boardId': boardId, 'archived': false },{sort: ['sort','asc']});
|
||||
lists.forEach(list => {
|
||||
let cardCount = Cards.find({ 'boardId': boardId, 'listId': list._id }).count()
|
||||
boardLists.push(`${list.title}: ${cardCount}`);
|
||||
/* Bug Board icons random dance https://github.com/wekan/wekan/issues/4214
|
||||
const lists = ReactiveCache.getLists({ 'boardId': boardId, 'archived': false },{sort: ['sort','asc']});
|
||||
const ret = lists.map(list => {
|
||||
let cardCount = ReactiveCache.getCards({ 'boardId': boardId, 'listId': list._id }).length;
|
||||
return `${list.title}: ${cardCount}`;
|
||||
});
|
||||
return boardLists
|
||||
return ret;
|
||||
*/
|
||||
return [];
|
||||
},
|
||||
|
||||
boardMembers(boardId) {
|
||||
let boardMembers = [];
|
||||
const lists = Boards.findOne({ '_id': boardId })
|
||||
/* Bug Board icons random dance https://github.com/wekan/wekan/issues/4214
|
||||
const lists = ReactiveCache.getBoard(boardId)
|
||||
let members = lists.members
|
||||
members.forEach(member => {
|
||||
boardMembers.push(member.userId);
|
||||
});
|
||||
return boardMembers
|
||||
*/
|
||||
return boardMembers;
|
||||
},
|
||||
|
||||
isStarred() {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
return user && user.hasStarred(this.currentData()._id);
|
||||
},
|
||||
isAdministrable() {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
return user && user.isBoardAdmin(this.currentData()._id);
|
||||
},
|
||||
|
||||
hasOvertimeCards() {
|
||||
subManager.subscribe('board', this.currentData()._id, false);
|
||||
return this.currentData().hasOvertimeCards();
|
||||
},
|
||||
|
||||
hasSpentTimeCards() {
|
||||
subManager.subscribe('board', this.currentData()._id, false);
|
||||
return this.currentData().hasSpentTimeCards();
|
||||
},
|
||||
|
||||
isInvited() {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
return user && user.isInvitedTo(this.currentData()._id);
|
||||
},
|
||||
|
||||
@@ -258,18 +238,18 @@ BlazeComponent.extendComponent({
|
||||
'click .js-add-board': Popup.open('createBoard'),
|
||||
'click .js-star-board'(evt) {
|
||||
const boardId = this.currentData()._id;
|
||||
Meteor.user().toggleBoardStar(boardId);
|
||||
ReactiveCache.getCurrentUser().toggleBoardStar(boardId);
|
||||
evt.preventDefault();
|
||||
},
|
||||
'click .js-clone-board'(evt) {
|
||||
let title = getSlug(Boards.findOne(this.currentData()._id).title) || 'cloned-board';
|
||||
let title = getSlug(ReactiveCache.getBoard(this.currentData()._id).title) || 'cloned-board';
|
||||
Meteor.call(
|
||||
'copyBoard',
|
||||
this.currentData()._id,
|
||||
{
|
||||
sort: Boards.find({ archived: false }).count(),
|
||||
sort: ReactiveCache.getBoards({ archived: false }).length,
|
||||
type: 'board',
|
||||
title: Boards.findOne(this.currentData()._id).title,
|
||||
title: ReactiveCache.getBoard(this.currentData()._id).title,
|
||||
},
|
||||
(err, res) => {
|
||||
if (err) {
|
||||
@@ -343,7 +323,7 @@ BlazeComponent.extendComponent({
|
||||
query.$and[2].$or.push({ 'orgs.orgId': { $in: selectedOrgsValues } });
|
||||
}
|
||||
|
||||
let filteredBoards = Boards.find(query, {}).fetch();
|
||||
let filteredBoards = ReactiveCache.getBoards(query, {});
|
||||
let allBoards = document.getElementsByClassName("js-board");
|
||||
let currBoard;
|
||||
if (filteredBoards.length > 0) {
|
||||
|
||||
@@ -1,90 +1,190 @@
|
||||
.slide {
|
||||
/* swipebox slide background gradient of black to blue, so that back SVG images are visible */
|
||||
background: rgb(2,0,36);
|
||||
background: linear-gradient(90deg, rgba(2,0,36,1) 0%, rgba(9,9,121,1) 14%, rgba(0,212,255,1) 100%);
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
.attachment-upload {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
.attachments-galery {
|
||||
.attachment-gallery {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
}
|
||||
.attachments-galery .attachment-item {
|
||||
width: 31.33%;
|
||||
margin: 10px 1% 0;
|
||||
text-align: center;
|
||||
border-radius: 3px;
|
||||
overflow: auto;
|
||||
background: #ededed;
|
||||
min-height: 120px;
|
||||
.attachment-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-top: 16px;
|
||||
}
|
||||
.attachments-galery .attachment-item:hover {
|
||||
.attachment-item:hover {
|
||||
background: #e0e0e0;
|
||||
}
|
||||
.attachments-galery .attachment-item.add-attachment {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.attachments-galery .attachment-item.add-attachment a {
|
||||
.attachment-thumbnail-container {
|
||||
display: block;
|
||||
margin: auto;
|
||||
width: 150px;
|
||||
min-width: 150px;
|
||||
max-height: 150px;
|
||||
padding-right: 16px;
|
||||
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-thumbnail {
|
||||
height: 80px;
|
||||
.attachment-thumbnail {
|
||||
max-width: 150px;
|
||||
max-height: 150px;
|
||||
min-height: 2em;
|
||||
cursor: pointer;
|
||||
}
|
||||
.attachment-thumbnail-text {
|
||||
min-height: 2em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
font-size: 2em;
|
||||
cursor: pointer;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-thumbnail .attachment-thumbnail-img {
|
||||
max-height: 100%;
|
||||
.attachment-details-container {
|
||||
display: block;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.attachment-details {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-right: 25px; /* Make sure the icons are not to far to the right */
|
||||
}
|
||||
.attachment-actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
.add-attachment {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px dashed #555;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
margin-top: 16px;
|
||||
}
|
||||
.icon {
|
||||
font-size: 1.5em;
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.icon:hover {
|
||||
color: #666;
|
||||
}
|
||||
#viewer-overlay {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
top: 48px; /* height of the navbar */
|
||||
left: 0;
|
||||
z-index: 9999 !important;
|
||||
background: rgba(13,13,13,0.95);
|
||||
}
|
||||
#viewer-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
height: 100%;
|
||||
}
|
||||
#viewer-top-bar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
padding: 16px;
|
||||
}
|
||||
#attachment-name {
|
||||
color: white;
|
||||
font-size: 1.5em;
|
||||
max-width: calc(100% - 50px); /* Make sure the name does not overlap the close button */
|
||||
}
|
||||
#viewer-close {
|
||||
color:white;
|
||||
cursor: pointer;
|
||||
font-size: 4em;
|
||||
top: 0;
|
||||
right: 8px;
|
||||
position: absolute;
|
||||
}
|
||||
.attachment-arrow {
|
||||
font-size: 4em;
|
||||
color:white;
|
||||
cursor: pointer;
|
||||
align-self: center;
|
||||
margin: 0 20px;
|
||||
}
|
||||
#image-viewer {
|
||||
background:
|
||||
repeating-conic-gradient(#808080 0% 25%, transparent 0% 50%)
|
||||
50% / 20px 20px; /* Checkerboard background for transparent images */
|
||||
max-width: 100%;
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-thumbnail .attachment-thumbnail-ext {
|
||||
text-transform: uppercase;
|
||||
font-size: 1.6em;
|
||||
#pdf-viewer {
|
||||
width: 40vw;
|
||||
height: 100vh;
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-details {
|
||||
font-size: 0.75em;
|
||||
margin: 3px;
|
||||
#txt-viewer{
|
||||
background-color: white;
|
||||
width: 40vw;
|
||||
height: 100vh;
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-details .attachment-details-actions a {
|
||||
.pdf-preview-error {
|
||||
margin-top: 20vh;
|
||||
display: block;
|
||||
font-size: 2em;
|
||||
color: white;
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-details .attachment-details-actions a.attachment-details-menu {
|
||||
padding-top: 10px;
|
||||
}
|
||||
.attachment-image-preview {
|
||||
max-width: 100px;
|
||||
display: block;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
|
||||
}
|
||||
.preview-clipboard-image {
|
||||
width: 280px;
|
||||
max-width: 100%;
|
||||
height: 200px;
|
||||
display: block;
|
||||
border: 1px solid #000;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
|
||||
|
||||
@media screen and (max-width: 1600px) {
|
||||
#pdf-viewer {
|
||||
width: 60vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
.attachments-galery .attachment-item {
|
||||
width: 48%;
|
||||
#viewer-container {
|
||||
display: block;
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-thumbnail {
|
||||
height: 130px;
|
||||
.attachment-arrow{
|
||||
position: absolute;
|
||||
bottom: 2.2em;
|
||||
font-size: 1.6em;
|
||||
padding: 16px;
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-details {
|
||||
font-size: 1.1em;
|
||||
#prev-attachment{
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 360px) {
|
||||
.attachments-galery .attachment-item {
|
||||
#next-attachment{
|
||||
right: 0;
|
||||
}
|
||||
#pdf-viewer {
|
||||
width: 100%;
|
||||
height: calc(100vh - 155px); /* Full height - height of top and bottom bars */
|
||||
}
|
||||
#txt-viewer {
|
||||
width: 100%;
|
||||
height: calc(100vh - 155px); /* Full height - height of top and bottom bars */
|
||||
}
|
||||
#audio-viewer {
|
||||
margin-top: 20%;
|
||||
width: 100%;
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-thumbnail {
|
||||
height: 200px;
|
||||
.attachment-thumbnail-container {
|
||||
width: 100px;
|
||||
min-width: 100px;
|
||||
}
|
||||
.attachment-thumbnail {
|
||||
max-width: 100px;
|
||||
}
|
||||
.attachment-details {
|
||||
flex-direction: column;
|
||||
margin-right: 0px;
|
||||
}
|
||||
.attachment-actions {
|
||||
flex-direction: row;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
@@ -30,64 +30,92 @@ template(name="attachmentDeletePopup")
|
||||
p {{_ "attachment-delete-pop"}}
|
||||
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
|
||||
|
||||
template(name="attachmentsGalery")
|
||||
.attachments-galery
|
||||
template(name="attachmentViewer")
|
||||
#viewer-overlay.hidden
|
||||
#viewer-top-bar
|
||||
span#attachment-name
|
||||
a#viewer-close.fa.fa-times-thin
|
||||
|
||||
#viewer-container
|
||||
i.fa.fa-chevron-left.attachment-arrow#prev-attachment
|
||||
#viewer-content
|
||||
img#image-viewer.hidden
|
||||
video#video-viewer.hidden(controls="true")
|
||||
audio#audio-viewer.hidden(controls="true")
|
||||
object#pdf-viewer.hidden(type="application/pdf")
|
||||
span.pdf-preview-error {{_ 'preview-pdf-not-supported' }}
|
||||
object#txt-viewer.hidden(type="text/plain")
|
||||
i.fa.fa-chevron-right.attachment-arrow#next-attachment
|
||||
|
||||
template(name="attachmentGallery")
|
||||
|
||||
.attachment-gallery
|
||||
|
||||
a.attachment-item.add-attachment.js-add-attachment
|
||||
i.fa.fa-plus.icon
|
||||
|
||||
each attachments
|
||||
|
||||
.attachment-item
|
||||
a.attachment-thumbnail.swipebox(href="{{link}}" title="{{sanitize name}}")
|
||||
.attachment-thumbnail-container.open-preview(data-attachment-id="{{_id}}" data-card-id="{{ meta.cardId }}")
|
||||
if link
|
||||
if isImage
|
||||
img.attachment-thumbnail-img(src="{{link}}" title="{{sanitize name}}")
|
||||
if(isImage)
|
||||
img.attachment-thumbnail(src="{{link}}" title="{{sanitize name}}")
|
||||
else if($eq extension 'svg')
|
||||
img.attachment-thumbnail(src="{{link}}" title="{{sanitize name}}" type="image/svg+xml")
|
||||
else if($eq extension 'mp3')
|
||||
video(width="100%" height="100%" title="{{sanitize name}}" controls="true")
|
||||
video.attachment-thumbnail(title="{{sanitize name}}")
|
||||
source(src="{{link}}" type="audio/mpeg")
|
||||
else if($eq extension 'ogg')
|
||||
video(width="100%" height="100%" title="{{sanitize name}}" controls="true")
|
||||
video.attachment-thumbnail(title="{{sanitize name}}")
|
||||
source(src="{{link}}" type="video/ogg")
|
||||
else if($eq extension 'webm')
|
||||
video(width="100%" height="100%" title="{{sanitize name}}" controls="true")
|
||||
video.attachment-thumbnail(title="{{sanitize name}}")
|
||||
source(src="{{link}}" type="video/webm")
|
||||
else if($eq extension 'mp4')
|
||||
video(width="100%" height="100%" title="{{sanitize name}}" controls="true")
|
||||
video.attachment-thumbnail(title="{{sanitize name}}")
|
||||
source(src="{{link}}" type="video/mp4")
|
||||
else
|
||||
span.attachment-thumbnail-ext= extension
|
||||
p.attachment-details
|
||||
= name
|
||||
span.file-size ({{fileSize size}})
|
||||
span.attachment-details-actions
|
||||
a.js-download(href="{{link}}?download=true", download="{{name}}")
|
||||
i.fa.fa-download
|
||||
| {{_ 'download'}}
|
||||
if currentUser.isBoardMember
|
||||
unless currentUser.isCommentOnly
|
||||
unless currentUser.isWorker
|
||||
a.fa.fa-navicon.attachment-details-menu.js-open-attachment-menu(title="{{_ 'attachmentActionsPopup-title'}}")
|
||||
span.attachment-thumbnail-text= extension
|
||||
|
||||
.attachment-details-container
|
||||
.attachment-details
|
||||
div
|
||||
b
|
||||
= name
|
||||
span.file-size ({{fileSize size}})
|
||||
.attachment-actions
|
||||
a.js-download(href="{{link}}?download=true", download="{{name}}")
|
||||
i.fa.fa-download.icon(title="{{_ 'download'}}")
|
||||
if currentUser.isBoardMember
|
||||
unless currentUser.isCommentOnly
|
||||
unless currentUser.isWorker
|
||||
a.js-rename
|
||||
i.fa.fa-pencil-square-o.icon(title="{{_ 'rename'}}")
|
||||
a.js-confirm-delete
|
||||
i.fa.fa-trash.icon(title="{{_ 'delete'}}")
|
||||
a.fa.fa-navicon.icon.js-open-attachment-menu(data-attachment-link="{{link}}" title="{{_ 'attachmentActionsPopup-title'}}")
|
||||
|
||||
if currentUser.isBoardMember
|
||||
unless currentUser.isCommentOnly
|
||||
unless currentUser.isWorker
|
||||
//li.attachment-item.add-attachment
|
||||
a.js-add-attachment(title="{{_ 'add-attachment' }}")
|
||||
i.fa.fa-plus
|
||||
|
||||
template(name="attachmentActionsPopup")
|
||||
ul.pop-over-list
|
||||
li
|
||||
if isImage
|
||||
a(class="{{#if isCover}}js-remove-cover{{else}}js-add-cover{{/if}}")
|
||||
i.fa.fa-thumb-tack
|
||||
i.fa.fa-book
|
||||
i.fa.fa-picture-o
|
||||
if isCover
|
||||
| {{_ 'remove-cover'}}
|
||||
else
|
||||
| {{_ 'add-cover'}}
|
||||
if currentUser.isBoardAdmin
|
||||
a.js-rename
|
||||
i.fa.fa-pencil-square-o
|
||||
| {{_ 'rename'}}
|
||||
a.js-confirm-delete
|
||||
i.fa.fa-close
|
||||
| {{_ 'delete'}}
|
||||
if isImage
|
||||
a(class="{{#if isBackgroundImage}}js-remove-background-image{{else}}js-add-background-image{{/if}}")
|
||||
i.fa.fa-picture-o
|
||||
if isBackgroundImage
|
||||
| {{_ 'remove-background-image'}}
|
||||
else
|
||||
| {{_ 'add-background-image'}}
|
||||
p.attachment-storage
|
||||
| {{versions.original.storage}}
|
||||
|
||||
|
||||
@@ -1,10 +1,28 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { ObjectID } from 'bson';
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
const filesize = require('filesize');
|
||||
const prettyMilliseconds = require('pretty-ms');
|
||||
|
||||
Template.attachmentsGalery.events({
|
||||
// We store current card ID and the ID of currently opened attachment in a
|
||||
// global var. This is used so that we know what's the next attachment to open
|
||||
// when the user clicks on the prev/next button in the attachment viewer.
|
||||
let cardId = null;
|
||||
let openAttachmentId = null;
|
||||
|
||||
|
||||
// Stores link to the attachment for which attachment actions popup was opened
|
||||
attachmentActionsLink = null;
|
||||
|
||||
Template.attachmentGallery.events({
|
||||
'click .open-preview'(event) {
|
||||
|
||||
openAttachmentId = $(event.currentTarget).attr("data-attachment-id");
|
||||
cardId = $(event.currentTarget).attr("data-card-id");
|
||||
|
||||
openAttachmentViewer(openAttachmentId);
|
||||
},
|
||||
'click .js-add-attachment': Popup.open('cardAttachments'),
|
||||
// If we let this event bubble, FlowRouter will handle it and empty the page
|
||||
// content, see #101.
|
||||
@@ -12,11 +30,144 @@ Template.attachmentsGalery.events({
|
||||
event.stopPropagation();
|
||||
},
|
||||
'click .js-open-attachment-menu': Popup.open('attachmentActions'),
|
||||
'mouseover .js-open-attachment-menu'(event) { // For some reason I cannot combine handlers for "click .js-open-attachment-menu" and "mouseover .js-open-attachment-menu" events so this is a quick workaround.
|
||||
attachmentActionsLink = event.currentTarget.getAttribute("data-attachment-link");
|
||||
},
|
||||
'click .js-rename': Popup.open('attachmentRename'),
|
||||
'click .js-confirm-delete': Popup.afterConfirm('attachmentDelete', function() {
|
||||
Attachments.remove(this._id);
|
||||
Popup.back(2);
|
||||
}),
|
||||
});
|
||||
|
||||
Template.attachmentsGalery.helpers({
|
||||
function getNextAttachmentId(currentAttachmentId) {
|
||||
const attachments = ReactiveCache.getAttachments({'meta.cardId': cardId});
|
||||
|
||||
let i = 0;
|
||||
for (; i < attachments.length; i++) {
|
||||
if (attachments[i]._id === currentAttachmentId) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return attachments[(i + 1 + attachments.length) % attachments.length]._id;
|
||||
}
|
||||
|
||||
function getPrevAttachmentId(currentAttachmentId) {
|
||||
const attachments = ReactiveCache.getAttachments({'meta.cardId': cardId});
|
||||
|
||||
let i = 0;
|
||||
for (; i < attachments.length; i++) {
|
||||
if (attachments[i]._id === currentAttachmentId) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return attachments[(i - 1 + attachments.length) % attachments.length]._id;
|
||||
}
|
||||
|
||||
function openAttachmentViewer(attachmentId){
|
||||
|
||||
const attachment = ReactiveCache.getAttachment(attachmentId);
|
||||
|
||||
$("#attachment-name").text(attachment.name);
|
||||
|
||||
// IMPORTANT: if you ever add a new viewer, make sure you also implement
|
||||
// cleanup in the closeAttachmentViewer() function
|
||||
switch(true){
|
||||
case (attachment.isImage):
|
||||
$("#image-viewer").attr("src", attachment.link());
|
||||
$("#image-viewer").removeClass("hidden");
|
||||
break;
|
||||
case (attachment.isPDF):
|
||||
$("#pdf-viewer").attr("data", attachment.link());
|
||||
$("#pdf-viewer").removeClass("hidden");
|
||||
break;
|
||||
case (attachment.isVideo):
|
||||
// We have to create a new <source> DOM element and append it to the video
|
||||
// element, otherwise the video won't load
|
||||
let videoSource = document.createElement('source');
|
||||
videoSource.setAttribute('src', attachment.link());
|
||||
$("#video-viewer").append(videoSource);
|
||||
|
||||
$("#video-viewer").removeClass("hidden");
|
||||
break;
|
||||
case (attachment.isAudio):
|
||||
// We have to create a new <source> DOM element and append it to the audio
|
||||
// element, otherwise the audio won't load
|
||||
let audioSource = document.createElement('source');
|
||||
audioSource.setAttribute('src', attachment.link());
|
||||
$("#audio-viewer").append(audioSource);
|
||||
|
||||
$("#audio-viewer").removeClass("hidden");
|
||||
break;
|
||||
case (attachment.isText):
|
||||
case (attachment.isJSON):
|
||||
$("#txt-viewer").attr("data", attachment.link());
|
||||
$("#txt-viewer").removeClass("hidden");
|
||||
break;
|
||||
}
|
||||
|
||||
$("#viewer-overlay").removeClass("hidden");
|
||||
}
|
||||
|
||||
function closeAttachmentViewer() {
|
||||
$("#viewer-overlay").addClass("hidden");
|
||||
|
||||
// We need to reset the viewers to avoid showing previous attachments
|
||||
$("#image-viewer").attr("src", "");
|
||||
$("#image-viewer").addClass("hidden");
|
||||
|
||||
$("#pdf-viewer").attr("data", "");
|
||||
$("#pdf-viewer").addClass("hidden");
|
||||
|
||||
$("#txt-viewer").attr("data", "");
|
||||
$("#txt-viewer").addClass("hidden");
|
||||
|
||||
$("#video-viewer").get(0).pause(); // Stop playback
|
||||
$("#video-viewer").get(0).currentTime = 0;
|
||||
$("#video-viewer").empty();
|
||||
$("#video-viewer").addClass("hidden");
|
||||
|
||||
$("#audio-viewer").get(0).pause(); // Stop playback
|
||||
$("#audio-viewer").get(0).currentTime = 0;
|
||||
$("#audio-viewer").empty();
|
||||
$("#audio-viewer").addClass("hidden");
|
||||
}
|
||||
|
||||
Template.attachmentViewer.events({
|
||||
'click #viewer-container'(event) {
|
||||
|
||||
// Make sure the click was on #viewer-container and not on any of its children
|
||||
if(event.target !== event.currentTarget) return;
|
||||
|
||||
closeAttachmentViewer();
|
||||
},
|
||||
'click #viewer-content'(event) {
|
||||
|
||||
// Make sure the click was on #viewer-content and not on any of its children
|
||||
if(event.target !== event.currentTarget) return;
|
||||
|
||||
closeAttachmentViewer();
|
||||
},
|
||||
'click #viewer-close'() {
|
||||
closeAttachmentViewer();
|
||||
},
|
||||
'click #next-attachment'(event) {
|
||||
closeAttachmentViewer()
|
||||
const id = getNextAttachmentId(openAttachmentId);
|
||||
openAttachmentId = id;
|
||||
openAttachmentViewer(id);
|
||||
},
|
||||
'click #prev-attachment'(event) {
|
||||
closeAttachmentViewer()
|
||||
const id = getPrevAttachmentId(openAttachmentId);
|
||||
openAttachmentId = id;
|
||||
openAttachmentViewer(id);
|
||||
}
|
||||
});
|
||||
|
||||
Template.attachmentGallery.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
fileSize(size) {
|
||||
const ret = filesize(size);
|
||||
@@ -172,25 +323,40 @@ Template.previewClipboardImagePopup.events({
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
isCover() {
|
||||
const ret = Cards.findOne(this.data().meta.cardId).coverId == this.data()._id;
|
||||
const ret = ReactiveCache.getCard(this.data().meta.cardId).coverId == this.data()._id;
|
||||
return ret;
|
||||
},
|
||||
isBackgroundImage() {
|
||||
//const currentBoard = Utils.getCurrentBoard();
|
||||
//return currentBoard.backgroundImageURL === $(".attachment-thumbnail-img").attr("src");
|
||||
return false;
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-rename': Popup.open('attachmentRename'),
|
||||
'click .js-confirm-delete': Popup.afterConfirm('attachmentDelete', function() {
|
||||
Attachments.remove(this._id);
|
||||
Popup.back(2);
|
||||
}),
|
||||
'click .js-add-cover'() {
|
||||
Cards.findOne(this.data().meta.cardId).setCover(this.data()._id);
|
||||
ReactiveCache.getCard(this.data().meta.cardId).setCover(this.data()._id);
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-remove-cover'() {
|
||||
Cards.findOne(this.data().meta.cardId).unsetCover();
|
||||
ReactiveCache.getCard(this.data().meta.cardId).unsetCover();
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-add-background-image'() {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
currentBoard.setBackgroundImageURL(attachmentActionsLink);
|
||||
Utils.setBackgroundImage(attachmentActionsLink);
|
||||
Popup.back();
|
||||
event.preventDefault();
|
||||
},
|
||||
'click .js-remove-background-image'() {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
currentBoard.setBackgroundImageURL("");
|
||||
Utils.setBackgroundImage("");
|
||||
Popup.back();
|
||||
Utils.reload();
|
||||
event.preventDefault();
|
||||
},
|
||||
'click .js-move-storage-fs'() {
|
||||
Meteor.call('moveAttachmentToStorage', this.data()._id, "fs");
|
||||
Popup.back();
|
||||
|
||||
@@ -37,14 +37,6 @@ const CardCustomField = BlazeComponent.extendComponent({
|
||||
self.card = Utils.getCurrentCard();
|
||||
self.customFieldId = this.data()._id;
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly()
|
||||
);
|
||||
},
|
||||
});
|
||||
CardCustomField.register('cardCustomField');
|
||||
|
||||
|
||||
@@ -2,17 +2,6 @@ import moment from 'moment/min/moment-with-locales';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import { DatePicker } from '/client/lib/datepicker';
|
||||
|
||||
Template.dateBadge.helpers({
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// editCardReceivedDatePopup
|
||||
(class extends DatePicker {
|
||||
onCreated() {
|
||||
|
||||
@@ -84,7 +84,7 @@
|
||||
overflow-x: hidden;
|
||||
background: #f7f7f7;
|
||||
border-radius: bottom 3px;
|
||||
z-index: 20;
|
||||
z-index: 30;
|
||||
animation: flexGrowIn 0.1s;
|
||||
box-shadow: 0 0 7px 0 #b3b3b3;
|
||||
transition: flex-basis 0.1s;
|
||||
@@ -245,6 +245,14 @@
|
||||
padding-top: 10px;
|
||||
}
|
||||
@media screen and (min-width: 801px) {
|
||||
.card-details {
|
||||
top: 97px;
|
||||
left: 0;
|
||||
width: 600px;
|
||||
bottom: 0;
|
||||
position: fixed;
|
||||
resize: both;
|
||||
}
|
||||
.card-details-maximized {
|
||||
padding: 0;
|
||||
flex-shrink: 0;
|
||||
|
||||
@@ -266,12 +266,14 @@ template(name="cardDetails")
|
||||
i.fa.fa-list-alt
|
||||
= definition.name
|
||||
+cardCustomField
|
||||
.material-toggle-switch(title="{{_ 'change'}} {{_ 'custom-fields'}} {{_ 'layout'}}")
|
||||
if customFieldsGrid
|
||||
input.toggle-switch(type="checkbox" id="toggleCustomFieldsGridButton" checked="checked")
|
||||
else
|
||||
input.toggle-switch(type="checkbox" id="toggleCustomFieldsGridButton")
|
||||
label.toggle-label(for="toggleCustomFieldsGridButton")
|
||||
|
||||
if $gt customFieldsWD.length 1
|
||||
.material-toggle-switch(title="{{_ 'change'}} {{_ 'custom-fields'}} {{_ 'layout'}}")
|
||||
if customFieldsGrid
|
||||
input.toggle-switch(type="checkbox" id="toggleCustomFieldsGridButton" checked="checked")
|
||||
else
|
||||
input.toggle-switch(type="checkbox" id="toggleCustomFieldsGridButton")
|
||||
label.toggle-label(for="toggleCustomFieldsGridButton")
|
||||
a.fa.fa-plus.js-custom-fields.card-details-item.custom-fields(title="{{_ 'custom-fields'}}")
|
||||
|
||||
if getVoteQuestion
|
||||
@@ -539,8 +541,8 @@ template(name="cardDetails")
|
||||
+viewer
|
||||
= getDescription
|
||||
|
||||
.card-checklist-attachmentGalerys
|
||||
.card-checklist-attachmentGalery.card-checklists
|
||||
.card-checklist-attachmentGalleries
|
||||
.card-checklist-attachmentGallery.card-checklists
|
||||
if currentBoard.allowsChecklists
|
||||
hr
|
||||
+checklists(cardId = _id)
|
||||
@@ -552,8 +554,16 @@ template(name="cardDetails")
|
||||
h3.card-details-item-title
|
||||
i.fa.fa-paperclip
|
||||
| {{_ 'attachments'}}
|
||||
.card-checklist-attachmentGalery.card-attachmentGalery
|
||||
+attachmentsGalery
|
||||
if Meteor.settings.public.attachmentsUploadMaxSize
|
||||
| {{_ 'max-upload-filesize'}} {{Meteor.settings.public.attachmentsUploadMaxSize}}
|
||||
br
|
||||
if Meteor.settings.public.attachmentsUploadMimeTypes
|
||||
| {{_ 'allowed-upload-filetypes'}} {{Meteor.settings.public.attachmentsUploadMimeTypes}}
|
||||
br
|
||||
| {{_ 'invalid-file'}}
|
||||
.card-checklist-attachmentGallery.card-attachmentGallery
|
||||
+attachmentViewer
|
||||
+attachmentGallery
|
||||
hr
|
||||
|
||||
.card-details-right
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import moment from 'moment/min/moment-with-locales';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import { DatePicker } from '/client/lib/datepicker';
|
||||
@@ -63,25 +64,16 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
hiddenSystemMessages() {
|
||||
return Meteor.user().hasHiddenSystemMessages();
|
||||
return ReactiveCache.getCurrentUser().hasHiddenSystemMessages();
|
||||
},
|
||||
|
||||
customFieldsGrid() {
|
||||
return Meteor.user().hasCustomFieldsGrid();
|
||||
return ReactiveCache.getCurrentUser().hasCustomFieldsGrid();
|
||||
},
|
||||
|
||||
|
||||
cardMaximized() {
|
||||
return !Utils.getPopupCardId() && Meteor.user().hasCardMaximized();
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
return !Utils.getPopupCardId() && ReactiveCache.getCurrentUser().hasCardMaximized();
|
||||
},
|
||||
|
||||
scrollParentContainer() {
|
||||
@@ -152,7 +144,7 @@ BlazeComponent.extendComponent({
|
||||
const card = this.currentData();
|
||||
let result = '#';
|
||||
if (card) {
|
||||
const board = Boards.findOne(card.boardId);
|
||||
const board = ReactiveCache.getBoard(card.boardId);
|
||||
if (board) {
|
||||
result = FlowRouter.path('card', {
|
||||
boardId: card.boardId,
|
||||
@@ -201,15 +193,15 @@ BlazeComponent.extendComponent({
|
||||
cardId: card._id,
|
||||
boardId: card.boardId,
|
||||
listId: card.listId,
|
||||
user: Meteor.user().username,
|
||||
user: ReactiveCache.getCurrentUser().username,
|
||||
url: '',
|
||||
};
|
||||
|
||||
const integrations = Integrations.find({
|
||||
const integrations = ReactiveCache.getIntegrations({
|
||||
boardId: { $in: [card.boardId, Integrations.Const.GLOBAL_WEBHOOK_ID] },
|
||||
enabled: true,
|
||||
activities: { $in: ['CardDetailsRendered', 'all'] },
|
||||
}).fetch();
|
||||
});
|
||||
|
||||
if (integrations.length > 0) {
|
||||
integrations.forEach((integration) => {
|
||||
@@ -296,7 +288,7 @@ BlazeComponent.extendComponent({
|
||||
});
|
||||
|
||||
function userIsMember() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember();
|
||||
return ReactiveCache.getCurrentUser()?.isBoardMember();
|
||||
}
|
||||
|
||||
// Disable sorting if the current user is not a board member
|
||||
@@ -660,15 +652,7 @@ Template.cardDetailsActionsPopup.helpers({
|
||||
},
|
||||
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly()
|
||||
);
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -744,19 +728,8 @@ BlazeComponent.extendComponent({
|
||||
}).register('editCardTitleForm');
|
||||
|
||||
Template.cardMembersPopup.onCreated(function () {
|
||||
let currBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
let currBoard = Utils.getCurrentBoard();
|
||||
let members = currBoard.activeMembers();
|
||||
|
||||
// let query = {
|
||||
// "teams.teamId": { $in: currBoard.teams.map(t => t.teamId) },
|
||||
// };
|
||||
|
||||
// let boardTeamUsers = Users.find(query, {
|
||||
// sort: { sort: 1 },
|
||||
// });
|
||||
|
||||
// members = currBoard.activeMembers2(members, boardTeamUsers);
|
||||
|
||||
this.members = new ReactiveVar(members);
|
||||
});
|
||||
|
||||
@@ -774,24 +747,14 @@ Template.cardMembersPopup.helpers({
|
||||
});
|
||||
|
||||
const filterMembers = (filterTerm) => {
|
||||
let currBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
let currBoard = Utils.getCurrentBoard();
|
||||
let members = currBoard.activeMembers();
|
||||
|
||||
// let query = {
|
||||
// "teams.teamId": { $in: currBoard.teams.map(t => t.teamId) },
|
||||
// };
|
||||
|
||||
// let boardTeamUsers = Users.find(query, {
|
||||
// sort: { sort: 1 },
|
||||
// });
|
||||
|
||||
// members = currBoard.activeMembers2(members, boardTeamUsers);
|
||||
|
||||
if (filterTerm) {
|
||||
members = members
|
||||
.map(member => ({
|
||||
member,
|
||||
user: Users.findOne(member.userId)
|
||||
user: ReactiveCache.getUser(member.userId)
|
||||
}))
|
||||
.filter(({ user }) =>
|
||||
(user.profile.fullname !== undefined && user.profile.fullname.toLowerCase().indexOf(filterTerm.toLowerCase()) !== -1)
|
||||
@@ -830,11 +793,11 @@ Template.editCardAssignerForm.events({
|
||||
/** Move Card Dialog */
|
||||
(class extends DialogWithBoardSwimlaneList {
|
||||
getDialogOptions() {
|
||||
const ret = Meteor.user().getMoveAndCopyDialogOptions();
|
||||
const ret = ReactiveCache.getCurrentUser().getMoveAndCopyDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(boardId, swimlaneId, listId, options) {
|
||||
Meteor.user().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
const minOrder = card.getMinSort(listId, swimlaneId);
|
||||
card.move(boardId, swimlaneId, listId, minOrder - 1);
|
||||
@@ -844,11 +807,11 @@ Template.editCardAssignerForm.events({
|
||||
/** Copy Card Dialog */
|
||||
(class extends DialogWithBoardSwimlaneList {
|
||||
getDialogOptions() {
|
||||
const ret = Meteor.user().getMoveAndCopyDialogOptions();
|
||||
const ret = ReactiveCache.getCurrentUser().getMoveAndCopyDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(boardId, swimlaneId, listId, options) {
|
||||
Meteor.user().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
|
||||
// const textarea = $('#copy-card-title');
|
||||
@@ -871,11 +834,11 @@ Template.editCardAssignerForm.events({
|
||||
/** Convert Checklist-Item to card dialog */
|
||||
(class extends DialogWithBoardSwimlaneList {
|
||||
getDialogOptions() {
|
||||
const ret = Meteor.user().getMoveAndCopyDialogOptions();
|
||||
const ret = ReactiveCache.getCurrentUser().getMoveAndCopyDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(boardId, swimlaneId, listId, options) {
|
||||
Meteor.user().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
|
||||
const textarea = this.$('#copy-card-title');
|
||||
@@ -889,7 +852,7 @@ Template.editCardAssignerForm.events({
|
||||
swimlaneId: swimlaneId,
|
||||
sort: 0,
|
||||
});
|
||||
const card = Cards.findOne(_id);
|
||||
const card = ReactiveCache.getCard(_id);
|
||||
const minOrder = card.getMinSort();
|
||||
card.move(card.boardId, card.swimlaneId, card.listId, minOrder - 1);
|
||||
|
||||
@@ -901,11 +864,11 @@ Template.editCardAssignerForm.events({
|
||||
/** Copy many cards dialog */
|
||||
(class extends DialogWithBoardSwimlaneList {
|
||||
getDialogOptions() {
|
||||
const ret = Meteor.user().getMoveAndCopyDialogOptions();
|
||||
const ret = ReactiveCache.getCurrentUser().getMoveAndCopyDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(boardId, swimlaneId, listId, options) {
|
||||
Meteor.user().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
|
||||
const textarea = this.$('#copy-card-title');
|
||||
@@ -977,27 +940,27 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
boards() {
|
||||
return Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
_id: {
|
||||
$ne: Meteor.user().getTemplatesBoardId(),
|
||||
},
|
||||
_id: { $ne: ReactiveCache.getCurrentUser().getTemplatesBoardId() },
|
||||
},
|
||||
{
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
|
||||
cards() {
|
||||
const currentId = Utils.getCurrentCardId();
|
||||
if (this.parentBoard.get()) {
|
||||
return Cards.find({
|
||||
const ret = ReactiveCache.getCards({
|
||||
boardId: this.parentBoard.get(),
|
||||
_id: { $ne: currentId },
|
||||
});
|
||||
return ret;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
@@ -1021,7 +984,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
setParentCardId(cardId) {
|
||||
if (cardId) {
|
||||
this.parentCard = Cards.findOne(cardId);
|
||||
this.parentCard = ReactiveCache.getCard(cardId);
|
||||
} else {
|
||||
this.parentCard = null;
|
||||
}
|
||||
@@ -1040,7 +1003,7 @@ BlazeComponent.extendComponent({
|
||||
'click .js-delete': Popup.afterConfirm('cardDelete', function () {
|
||||
Popup.close();
|
||||
// verify that there are no linked cards
|
||||
if (Cards.find({ linkedId: this._id }).count() === 0) {
|
||||
if (ReactiveCache.getCards({ linkedId: this._id }).length === 0) {
|
||||
Cards.remove(this._id);
|
||||
} else {
|
||||
// TODO: Maybe later we can list where the linked cards are.
|
||||
@@ -1579,8 +1542,8 @@ EscapeActions.register(
|
||||
() => {
|
||||
// if card description diverges from database due to editing
|
||||
// ask user whether changes should be applied
|
||||
if (Meteor.user()) {
|
||||
if (Meteor.user().profile.rescueCardDescription == true) {
|
||||
if (ReactiveCache.getCurrentUser()) {
|
||||
if (ReactiveCache.getCurrentUser().profile.rescueCardDescription == true) {
|
||||
currentDescription = document.getElementsByClassName("editor js-new-description-input").item(0)
|
||||
if (currentDescription?.value && !(currentDescription.value === Utils.getCurrentCard().getDescription())) {
|
||||
if (confirm(TAPi18n.__('rescue-card-description-dialogue'))) {
|
||||
@@ -1614,19 +1577,8 @@ EscapeActions.register(
|
||||
);
|
||||
|
||||
Template.cardAssigneesPopup.onCreated(function () {
|
||||
let currBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
let currBoard = Utils.getCurrentBoard();
|
||||
let members = currBoard.activeMembers();
|
||||
|
||||
// let query = {
|
||||
// "teams.teamId": { $in: currBoard.teams.map(t => t.teamId) },
|
||||
// };
|
||||
|
||||
// let boardTeamUsers = Users.find(query, {
|
||||
// sort: { sort: 1 },
|
||||
// });
|
||||
|
||||
// members = currBoard.activeMembers2(members, boardTeamUsers);
|
||||
|
||||
this.members = new ReactiveVar(members);
|
||||
});
|
||||
|
||||
@@ -1656,13 +1608,13 @@ Template.cardAssigneesPopup.helpers({
|
||||
},
|
||||
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
});
|
||||
|
||||
Template.cardAssigneePopup.helpers({
|
||||
userData() {
|
||||
return Users.findOne(this.userId, {
|
||||
return ReactiveCache.getUser(this.userId, {
|
||||
fields: {
|
||||
profile: 1,
|
||||
username: 1,
|
||||
@@ -1671,21 +1623,10 @@ Template.cardAssigneePopup.helpers({
|
||||
},
|
||||
|
||||
memberType() {
|
||||
const user = Users.findOne(this.userId);
|
||||
const user = ReactiveCache.getUser(this.userId);
|
||||
return user && user.isBoardAdmin() ? 'admin' : 'normal';
|
||||
},
|
||||
|
||||
/*
|
||||
presenceStatusClassName() {
|
||||
const user = Users.findOne(this.userId);
|
||||
const userPresence = presences.findOne({ userId: this.userId });
|
||||
if (user && user.isInvitedTo(Session.get('currentBoard'))) return 'pending';
|
||||
else if (!userPresence) return 'disconnected';
|
||||
else if (Session.equals('currentBoard', userPresence.state.currentBoardId))
|
||||
return 'active';
|
||||
else return 'idle';
|
||||
},
|
||||
*/
|
||||
isCardAssignee() {
|
||||
const card = Template.parentData();
|
||||
const cardAssignees = card.getAssignees();
|
||||
@@ -1694,13 +1635,13 @@ Template.cardAssigneePopup.helpers({
|
||||
},
|
||||
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
});
|
||||
|
||||
Template.cardAssigneePopup.events({
|
||||
'click .js-remove-assignee'() {
|
||||
Cards.findOne(this.cardId).unassignAssignee(this.userId);
|
||||
ReactiveCache.getCard(this.cardId).unassignAssignee(this.userId);
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-edit-profile': Popup.open('editProfile'),
|
||||
|
||||
@@ -83,13 +83,3 @@ BlazeComponent.extendComponent({
|
||||
];
|
||||
},
|
||||
}).register('cardSpentTime');
|
||||
|
||||
Template.timeBadge.helpers({
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly()
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -164,6 +164,21 @@ textarea.js-edit-checklist-item {
|
||||
color: #222;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
|
||||
}
|
||||
.add-checklist-top {
|
||||
/* more space to checklists title */
|
||||
padding-left: 20px;
|
||||
/* + is easier clickable */
|
||||
padding-right: 20px;
|
||||
}
|
||||
.add-checklist-top.js-open-inlined-form:hover {
|
||||
background: #dbdbdb;
|
||||
color: #222;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,.2);
|
||||
}
|
||||
.card-details-item-title {
|
||||
/* max width for adding checklist at top */
|
||||
width: 100%;
|
||||
}
|
||||
.checklist-details-menu {
|
||||
float: right;
|
||||
padding: 6px 10px 6px 10px;
|
||||
|
||||
@@ -3,6 +3,12 @@ template(name="checklists")
|
||||
h3.card-details-item-title
|
||||
i.fa.fa-check
|
||||
| {{_ 'checklists'}}
|
||||
if canModifyCard
|
||||
+inlinedForm(autoclose=false classNames="js-add-checklist" cardId = cardId position="top")
|
||||
+addChecklistItemForm
|
||||
else
|
||||
a.add-checklist-top.js-open-inlined-form(title="{{_ 'add-checklist'}}")
|
||||
i.fa.fa-plus
|
||||
if currentUser.isBoardMember
|
||||
.material-toggle-switch(title="{{_ 'hide-checked-items'}}")
|
||||
//span.toggle-switch-title
|
||||
@@ -86,6 +92,13 @@ template(name="editChecklistItemForm")
|
||||
| {{_ 'convertChecklistItemToCardPopup-title'}}
|
||||
|
||||
template(name="checklistItems")
|
||||
if checklist.items.length
|
||||
if canModifyCard
|
||||
+inlinedForm(autoclose=false classNames="js-add-checklist-item" checklist = checklist position="top")
|
||||
+addChecklistItemForm(checklist=checklist showNewlineBecomesNewChecklistItem=true)
|
||||
else
|
||||
a.add-checklist-item.js-open-inlined-form(title="{{_ 'add-checklist-item'}}")
|
||||
i.fa.fa-plus
|
||||
.checklist-items.js-checklist-items
|
||||
each item in checklist.items
|
||||
+inlinedForm(classNames="js-edit-checklist-item" item = item checklist = checklist)
|
||||
@@ -140,10 +153,7 @@ template(name="copyAndMoveChecklist")
|
||||
label {{_ 'boards'}}:
|
||||
select.js-select-boards(autofocus)
|
||||
each boards
|
||||
if $eq _id currentBoard._id
|
||||
option(value="{{_id}}" selected) {{_ 'current'}}
|
||||
else
|
||||
option(value="{{_id}}" selected="{{#if isDialogOptionBoardId _id}}selected{{/if}}") {{title}}
|
||||
option(value="{{_id}}" selected="{{#if isDialogOptionBoardId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
label {{_ 'swimlanes'}}:
|
||||
select.js-select-swimlanes
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import Cards from '/models/cards';
|
||||
import Boards from '/models/boards';
|
||||
@@ -54,7 +55,7 @@ BlazeComponent.extendComponent({
|
||||
});
|
||||
|
||||
function userIsMember() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember();
|
||||
return ReactiveCache.getCurrentUser()?.isBoardMember();
|
||||
}
|
||||
|
||||
// Disable sorting if the current user is not a board member
|
||||
@@ -71,15 +72,6 @@ BlazeComponent.extendComponent({
|
||||
});
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
|
||||
/** returns the finished percent of the checklist */
|
||||
finishedPercent() {
|
||||
const ret = this.data().checklist.finishedPercent();
|
||||
@@ -93,20 +85,32 @@ BlazeComponent.extendComponent({
|
||||
const textarea = this.find('textarea.js-add-checklist-item');
|
||||
const title = textarea.value.trim();
|
||||
let cardId = this.currentData().cardId;
|
||||
const card = Cards.findOne(cardId);
|
||||
const card = ReactiveCache.getCard(cardId);
|
||||
//if (card.isLinked()) cardId = card.linkedId;
|
||||
if (card.isLinkedCard()) cardId = card.linkedId;
|
||||
if (card.isLinkedCard()) {
|
||||
cardId = card.linkedId;
|
||||
}
|
||||
|
||||
let sortIndex;
|
||||
let checklistItemIndex;
|
||||
if (this.currentData().position === 'top') {
|
||||
sortIndex = Utils.calculateIndexData(null, card.firstChecklist()).base;
|
||||
checklistItemIndex = 0;
|
||||
} else {
|
||||
sortIndex = Utils.calculateIndexData(card.lastChecklist(), null).base;
|
||||
checklistItemIndex = -1;
|
||||
}
|
||||
|
||||
if (title) {
|
||||
Checklists.insert({
|
||||
cardId,
|
||||
title,
|
||||
sort: card.checklists().count(),
|
||||
sort: sortIndex,
|
||||
});
|
||||
this.closeAllInlinedForms();
|
||||
setTimeout(() => {
|
||||
this.$('.add-checklist-item')
|
||||
.last()
|
||||
.eq(checklistItemIndex)
|
||||
.click();
|
||||
}, 100);
|
||||
}
|
||||
@@ -122,13 +126,22 @@ BlazeComponent.extendComponent({
|
||||
let checklistItems = [title];
|
||||
if (newlineBecomesNewChecklistItem.checked) {
|
||||
checklistItems = title.split('\n').map(_value => _value.trim());
|
||||
if (this.currentData().position === 'top') {
|
||||
checklistItems = checklistItems.reverse();
|
||||
}
|
||||
}
|
||||
for (let checklistItem of checklistItems) {
|
||||
let sortIndex;
|
||||
if (this.currentData().position === 'top') {
|
||||
sortIndex = Utils.calculateIndexData(null, checklist.firstItem()).base;
|
||||
} else {
|
||||
sortIndex = Utils.calculateIndexData(checklist.lastItem(), null).base;
|
||||
}
|
||||
ChecklistItems.insert({
|
||||
title: checklistItem,
|
||||
checklistId: checklist._id,
|
||||
cardId: checklist.cardId,
|
||||
sort: Utils.calculateIndexData(checklist.lastItem()).base,
|
||||
sort: sortIndex,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -137,15 +150,6 @@ BlazeComponent.extendComponent({
|
||||
textarea.focus();
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
|
||||
deleteItem() {
|
||||
const checklist = this.currentData().checklist;
|
||||
const item = this.currentData().item;
|
||||
@@ -229,25 +233,26 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
boards() {
|
||||
return Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
_id: { $ne: Meteor.user().getTemplatesBoardId() },
|
||||
_id: { $ne: ReactiveCache.getCurrentUser().getTemplatesBoardId() },
|
||||
},
|
||||
{
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
|
||||
swimlanes() {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
|
||||
return board.swimlanes();
|
||||
},
|
||||
|
||||
aBoardLists() {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
|
||||
return board.lists();
|
||||
},
|
||||
|
||||
@@ -265,12 +270,12 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.checklists.helpers({
|
||||
checklists() {
|
||||
const card = Cards.findOne(this.cardId);
|
||||
const card = ReactiveCache.getCard(this.cardId);
|
||||
const ret = card.checklists();
|
||||
return ret;
|
||||
},
|
||||
hideCheckedItems() {
|
||||
const currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) return currentUser.hasHideCheckedItems();
|
||||
return false;
|
||||
},
|
||||
@@ -280,14 +285,6 @@ BlazeComponent.extendComponent({
|
||||
onRendered() {
|
||||
autosize(this.$('textarea.js-add-checklist-item'));
|
||||
},
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
@@ -325,14 +322,6 @@ BlazeComponent.extendComponent({
|
||||
onRendered() {
|
||||
autosize(this.$('textarea.js-edit-checklist-item'));
|
||||
},
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
@@ -349,16 +338,8 @@ BlazeComponent.extendComponent({
|
||||
}).register('editChecklistItemForm');
|
||||
|
||||
Template.checklistItemDetail.helpers({
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
hideCheckedItems() {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
if (user) return user.hasHideCheckedItems();
|
||||
return false;
|
||||
},
|
||||
@@ -384,11 +365,11 @@ BlazeComponent.extendComponent({
|
||||
/** Move Checklist Dialog */
|
||||
(class extends DialogWithBoardSwimlaneListCard {
|
||||
getDialogOptions() {
|
||||
const ret = Meteor.user().getMoveChecklistDialogOptions();
|
||||
const ret = ReactiveCache.getCurrentUser().getMoveChecklistDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(cardId, options) {
|
||||
Meteor.user().setMoveChecklistDialogOption(this.currentBoardId, options);
|
||||
ReactiveCache.getCurrentUser().setMoveChecklistDialogOption(this.currentBoardId, options);
|
||||
this.data().checklist.move(cardId);
|
||||
}
|
||||
}).register('moveChecklistPopup');
|
||||
@@ -396,11 +377,11 @@ BlazeComponent.extendComponent({
|
||||
/** Copy Checklist Dialog */
|
||||
(class extends DialogWithBoardSwimlaneListCard {
|
||||
getDialogOptions() {
|
||||
const ret = Meteor.user().getCopyChecklistDialogOptions();
|
||||
const ret = ReactiveCache.getCurrentUser().getCopyChecklistDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(cardId, options) {
|
||||
Meteor.user().setCopyChecklistDialogOption(this.currentBoardId, options);
|
||||
ReactiveCache.getCurrentUser().setCopyChecklistDialogOption(this.currentBoardId, options);
|
||||
this.data().checklist.copy(cardId);
|
||||
}
|
||||
}).register('copyChecklistPopup');
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
let labelColors;
|
||||
Meteor.startup(() => {
|
||||
labelColors = Boards.simpleSchema()._schema['labels.$.color'].allowedValues;
|
||||
@@ -32,7 +34,7 @@ Template.createLabelPopup.helpers({
|
||||
// is not already used in the board (although it's not a problem if two
|
||||
// labels have the same color).
|
||||
defaultColor() {
|
||||
const labels = Boards.findOne(Session.get('currentBoard')).labels;
|
||||
const labels = Utils.getCurrentBoard().labels;
|
||||
const usedColors = _.pluck(labels, 'color');
|
||||
const availableColors = _.difference(labelColors, usedColors);
|
||||
return availableColors.length > 1 ? availableColors[0] : labelColors[0];
|
||||
@@ -117,7 +119,7 @@ Template.createLabelPopup.events({
|
||||
// Create the new label
|
||||
'submit .create-label'(event, templateInstance) {
|
||||
event.preventDefault();
|
||||
const board = Boards.findOne(Session.get('currentBoard'));
|
||||
const board = Utils.getCurrentBoard();
|
||||
const name = templateInstance
|
||||
.$('#labelName')
|
||||
.val()
|
||||
@@ -130,13 +132,13 @@ Template.createLabelPopup.events({
|
||||
|
||||
Template.editLabelPopup.events({
|
||||
'click .js-delete-label': Popup.afterConfirm('deleteLabel', function () {
|
||||
const board = Boards.findOne(Session.get('currentBoard'));
|
||||
const board = Utils.getCurrentBoard();
|
||||
board.removeLabel(this._id);
|
||||
Popup.back(2);
|
||||
}),
|
||||
'submit .edit-label'(event, templateInstance) {
|
||||
event.preventDefault();
|
||||
const board = Boards.findOne(Session.get('currentBoard'));
|
||||
const board = Utils.getCurrentBoard();
|
||||
const name = templateInstance
|
||||
.$('#labelName')
|
||||
.val()
|
||||
@@ -149,6 +151,6 @@ Template.editLabelPopup.events({
|
||||
|
||||
Template.cardLabelsPopup.helpers({
|
||||
isLabelSelected(cardId) {
|
||||
return _.contains(Cards.findOne(cardId).labelIds, this._id);
|
||||
return _.contains(ReactiveCache.getCard(cardId).labelIds, this._id);
|
||||
},
|
||||
});
|
||||
@@ -45,12 +45,12 @@
|
||||
}
|
||||
.minicard-details-menu-with-handle {
|
||||
float: right;
|
||||
font-size: 14px;
|
||||
font-size: 18px;
|
||||
padding-right: 30px;
|
||||
}
|
||||
.minicard-details-menu {
|
||||
float: right;
|
||||
font-size: 14px;
|
||||
font-size: 18px;
|
||||
}
|
||||
@media print {
|
||||
.minicard-details-menu,
|
||||
@@ -120,6 +120,13 @@
|
||||
max-width: 100px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.minicard .minicard-custom-field-item-fullwidth {
|
||||
flex-grow: 1;
|
||||
display: block;
|
||||
word-wrap: break-word;
|
||||
max-width: 100%;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.minicard .handle {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
|
||||
@@ -9,17 +9,27 @@ template(name="minicard")
|
||||
.fa.fa-arrows
|
||||
else
|
||||
a.fa.fa-navicon.minicard-details-menu.js-open-minicard-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}")
|
||||
.dates
|
||||
if getReceived
|
||||
unless getStart
|
||||
unless getDue
|
||||
unless getEnd
|
||||
.date
|
||||
+minicardReceivedDate
|
||||
if getStart
|
||||
.date
|
||||
+minicardStartDate
|
||||
if getDue
|
||||
.date
|
||||
+minicardDueDate
|
||||
if getEnd
|
||||
+minicardEndDate
|
||||
if getSpentTime
|
||||
.date
|
||||
+cardSpentTime
|
||||
if cover
|
||||
.minicard-cover(style="background-image: url('{{cover.link 'original'}}?dummyReloadAfterSessionEstablished={{sess}}');")
|
||||
if labels
|
||||
.minicard-labels(class="{{#if hiddenMinicardLabelText}}minicard-labels-no-text{{/if}}")
|
||||
each labels
|
||||
unless hiddenMinicardLabelText
|
||||
span.js-card-label.card-label(class="card-label-{{color}}" title=name)
|
||||
+viewer
|
||||
= name
|
||||
if hiddenMinicardLabelText
|
||||
.minicard-label(class="card-label-{{color}}" title="{{name}}")
|
||||
if currentBoard.allowsCoverAttachmentOnMinicard
|
||||
.minicard-cover(style="background-image: url('{{cover.link 'original'}}?dummyReloadAfterSessionEstablished={{sess}}');")
|
||||
.minicard-title
|
||||
if $eq 'prefix-with-full-path' currentBoard.presentParentTask
|
||||
.parent-prefix
|
||||
@@ -46,50 +56,60 @@ template(name="minicard")
|
||||
if $eq 'subtext-with-parent' currentBoard.presentParentTask
|
||||
.parent-subtext
|
||||
| {{ parentCardName }}
|
||||
|
||||
.dates
|
||||
if getReceived
|
||||
unless getStart
|
||||
unless getDue
|
||||
unless getEnd
|
||||
.date
|
||||
+minicardReceivedDate
|
||||
if getStart
|
||||
.date
|
||||
+minicardStartDate
|
||||
if getDue
|
||||
.date
|
||||
+minicardDueDate
|
||||
if getEnd
|
||||
+minicardEndDate
|
||||
if getSpentTime
|
||||
.date
|
||||
+cardSpentTime
|
||||
if labels
|
||||
.minicard-labels(class="{{#if hiddenMinicardLabelText}}minicard-labels-no-text{{/if}}")
|
||||
each labels
|
||||
unless hiddenMinicardLabelText
|
||||
span.js-card-label.card-label(class="card-label-{{color}}" title=name)
|
||||
+viewer
|
||||
= name
|
||||
if hiddenMinicardLabelText
|
||||
.minicard-label(class="card-label-{{color}}" title="{{name}}")
|
||||
|
||||
.minicard-custom-fields
|
||||
each customFieldsWD
|
||||
if definition.showOnCard
|
||||
if trueValue
|
||||
.minicard-custom-field
|
||||
// If there is custom field label, show label at left,
|
||||
// and value at right
|
||||
if definition.showLabelOnMiniCard
|
||||
.minicard-custom-field-item
|
||||
+viewer
|
||||
= definition.name
|
||||
.minicard-custom-field-item
|
||||
if $eq definition.type "currency"
|
||||
+viewer
|
||||
= formattedCurrencyCustomFieldValue(definition)
|
||||
else if $eq definition.type "date"
|
||||
.date
|
||||
+minicardCustomFieldDate
|
||||
else if $eq definition.type "checkbox"
|
||||
.materialCheckBox(class="{{#if value }}is-checked{{/if}}")
|
||||
else if $eq definition.type "stringtemplate"
|
||||
+viewer
|
||||
= formattedStringtemplateCustomFieldValue(definition)
|
||||
else
|
||||
+viewer
|
||||
= trueValue
|
||||
.minicard-custom-field-item
|
||||
if $eq definition.type "currency"
|
||||
+viewer
|
||||
= formattedCurrencyCustomFieldValue(definition)
|
||||
else if $eq definition.type "date"
|
||||
.date
|
||||
+minicardCustomFieldDate
|
||||
else if $eq definition.type "checkbox"
|
||||
.materialCheckBox(class="{{#if value }}is-checked{{/if}}")
|
||||
else if $eq definition.type "stringtemplate"
|
||||
+viewer
|
||||
= formattedStringtemplateCustomFieldValue(definition)
|
||||
else
|
||||
+viewer
|
||||
= trueValue
|
||||
else
|
||||
// If there is no custom field label,
|
||||
// show value full width
|
||||
.minicard-custom-field-item-fullwidth
|
||||
if $eq definition.type "currency"
|
||||
+viewer
|
||||
= formattedCurrencyCustomFieldValue(definition)
|
||||
else if $eq definition.type "date"
|
||||
.date
|
||||
+minicardCustomFieldDate
|
||||
else if $eq definition.type "checkbox"
|
||||
.materialCheckBox(class="{{#if value }}is-checked{{/if}}")
|
||||
else if $eq definition.type "stringtemplate"
|
||||
+viewer
|
||||
= formattedStringtemplateCustomFieldValue(definition)
|
||||
else
|
||||
+viewer
|
||||
= trueValue
|
||||
|
||||
if showAssignee
|
||||
if getAssignees
|
||||
@@ -109,11 +129,11 @@ template(name="minicard")
|
||||
|
||||
.badges
|
||||
unless currentUser.isNoComments
|
||||
if comments.count
|
||||
.badge(title="{{_ 'card-comments-title' comments.count }}")
|
||||
if comments.length
|
||||
.badge(title="{{_ 'card-comments-title' comments.length }}")
|
||||
span.badge-icon.fa.fa-comment-o.badge-comment
|
||||
= ' '
|
||||
= comments.count
|
||||
= comments.length
|
||||
//span.badge-comment.badge-text
|
||||
//| {{_ 'comment'}}
|
||||
if getDescription
|
||||
@@ -132,10 +152,11 @@ template(name="minicard")
|
||||
if expiredPoker
|
||||
span.badge-text {{ getPokerEstimation }}
|
||||
if attachments.length
|
||||
.badge
|
||||
span.badge-icon.fa.fa-paperclip
|
||||
span.badge-text= attachments.length
|
||||
if checklists.count
|
||||
if currentBoard.allowsBadgeAttachmentOnMinicard
|
||||
.badge
|
||||
span.badge-icon.fa.fa-paperclip
|
||||
span.badge-text= attachments.length
|
||||
if checklists.length
|
||||
.badge(class="{{#if checklistFinished}}is-finished{{/if}}")
|
||||
span.badge-icon.fa.fa-check-square-o
|
||||
span.badge-text.check-list-text {{checklistFinishedCount}}/{{checklistItemCount}}
|
||||
@@ -145,9 +166,10 @@ template(name="minicard")
|
||||
span.badge-text.check-list-text {{subtasksFinishedCount}}/{{allSubtasksCount}}
|
||||
//{{subtasksFinishedCount}}/{{subtasksCount}} does not work because when a subtaks is archived, the count goes down
|
||||
if currentBoard.allowsCardSortingByNumber
|
||||
.badge
|
||||
span.badge-icon.fa.fa-sort
|
||||
span.badge-text.check-list-sort {{ sort }}
|
||||
if currentBoard.allowsCardSortingByNumberOnMinicard
|
||||
.badge
|
||||
span.badge-icon.fa.fa-sort
|
||||
span.badge-text.check-list-sort {{ sort }}
|
||||
if currentBoard.allowsDescriptionTextOnMinicard
|
||||
if getDescription
|
||||
.minicard-description
|
||||
@@ -172,6 +194,12 @@ template(name="minicardDetailsActionsPopup")
|
||||
i.fa.fa-copy
|
||||
| {{_ 'copyCardPopup-title'}}
|
||||
hr
|
||||
li
|
||||
a.js-archive
|
||||
i.fa.fa-arrow-right
|
||||
i.fa.fa-archive
|
||||
| {{_ 'archive-card'}}
|
||||
hr
|
||||
li
|
||||
a.js-move-card-to-top
|
||||
i.fa.fa-arrow-up
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import { CustomFieldStringTemplate } from '/client/lib/customFields'
|
||||
|
||||
@@ -37,37 +38,45 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
showCreator() {
|
||||
if (this.data().board()) {
|
||||
return (
|
||||
this.data().board.allowsCreator === null ||
|
||||
this.data().board().allowsCreator === undefined ||
|
||||
this.data().board().allowsCreator
|
||||
);
|
||||
// return this.data().board().allowsCreator;
|
||||
// cache "board" to reduce the mini-mongodb access
|
||||
const board = this.data().board();
|
||||
let ret = false;
|
||||
if (board) {
|
||||
ret =
|
||||
board.allowsCreator === null ||
|
||||
board.allowsCreator === undefined ||
|
||||
board.allowsCreator
|
||||
;
|
||||
}
|
||||
return false;
|
||||
return ret;
|
||||
},
|
||||
|
||||
showMembers() {
|
||||
if (this.data().board()) {
|
||||
return (
|
||||
this.data().board.allowsMembers === null ||
|
||||
this.data().board().allowsMembers === undefined ||
|
||||
this.data().board().allowsMembers
|
||||
);
|
||||
// cache "board" to reduce the mini-mongodb access
|
||||
const board = this.data().board();
|
||||
let ret = false;
|
||||
if (board) {
|
||||
ret =
|
||||
board.allowsMembers === null ||
|
||||
board.allowsMembers === undefined ||
|
||||
board.allowsMembers
|
||||
;
|
||||
}
|
||||
return false;
|
||||
return ret;
|
||||
},
|
||||
|
||||
showAssignee() {
|
||||
if (this.data().board()) {
|
||||
return (
|
||||
this.data().board.allowsAssignee === null ||
|
||||
this.data().board().allowsAssignee === undefined ||
|
||||
this.data().board().allowsAssignee
|
||||
);
|
||||
// cache "board" to reduce the mini-mongodb access
|
||||
const board = this.data().board();
|
||||
let ret = false;
|
||||
if (board) {
|
||||
ret =
|
||||
board.allowsAssignee === null ||
|
||||
board.allowsAssignee === undefined ||
|
||||
board.allowsAssignee
|
||||
;
|
||||
}
|
||||
return false;
|
||||
return ret;
|
||||
},
|
||||
|
||||
/** opens the card label popup only if clicked onto a label
|
||||
@@ -105,7 +114,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.minicard.helpers({
|
||||
hiddenMinicardLabelText() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).hiddenMinicardLabelText;
|
||||
} else if (window.localStorage.getItem('hiddenMinicardLabelText')) {
|
||||
@@ -168,4 +177,9 @@ Template.minicardDetailsActionsPopup.events({
|
||||
this.move(this.boardId, this.swimlaneId, this.listId, maxOrder + 1);
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-archive': Popup.afterConfirm('cardArchive', function () {
|
||||
Popup.close();
|
||||
this.archive();
|
||||
Utils.goBoardId(this.boardId);
|
||||
}),
|
||||
});
|
||||
@@ -1,13 +1,4 @@
|
||||
BlazeComponent.extendComponent({
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
}).register('subtaskDetail');
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
addSubtask(event) {
|
||||
@@ -15,19 +6,19 @@ BlazeComponent.extendComponent({
|
||||
const textarea = this.find('textarea.js-add-subtask-item');
|
||||
const title = textarea.value.trim();
|
||||
const cardId = this.currentData().cardId;
|
||||
const card = Cards.findOne(cardId);
|
||||
const card = ReactiveCache.getCard(cardId);
|
||||
const sortIndex = -1;
|
||||
const crtBoard = Boards.findOne(card.boardId);
|
||||
const crtBoard = ReactiveCache.getBoard(card.boardId);
|
||||
const targetBoard = crtBoard.getDefaultSubtasksBoard();
|
||||
const listId = targetBoard.getDefaultSubtasksListId();
|
||||
|
||||
//Get the full swimlane data for the parent task.
|
||||
const parentSwimlane = Swimlanes.findOne({
|
||||
const parentSwimlane = ReactiveCache.getSwimlane({
|
||||
boardId: crtBoard._id,
|
||||
_id: card.swimlaneId,
|
||||
});
|
||||
//find the swimlane of the same name in the target board.
|
||||
const targetSwimlane = Swimlanes.findOne({
|
||||
const targetSwimlane = ReactiveCache.getSwimlane({
|
||||
boardId: targetBoard._id,
|
||||
title: parentSwimlane.title,
|
||||
});
|
||||
@@ -70,15 +61,6 @@ BlazeComponent.extendComponent({
|
||||
textarea.focus();
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
|
||||
deleteSubtask() {
|
||||
const subtask = this.currentData().subtask;
|
||||
if (subtask && subtask._id) {
|
||||
@@ -117,17 +99,6 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
}).register('subtasks');
|
||||
|
||||
Template.subtaskItemDetail.helpers({
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
// ...
|
||||
}).register('subtaskItemDetail');
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
export function csvGetMembersToMap(data) {
|
||||
// we will work on the list itself (an ordered array of objects) when a
|
||||
// mapping is done, we add a 'wekan' field to the object representing the
|
||||
@@ -28,7 +30,7 @@ export function csvGetMembersToMap(data) {
|
||||
username: importedMember,
|
||||
id: importedMember,
|
||||
};
|
||||
const wekanUser = Users.findOne({ username: importedMember.username });
|
||||
const wekanUser = ReactiveCache.getUser({ username: importedMember.username });
|
||||
if (wekanUser) importedMember.wekanId = wekanUser._id;
|
||||
membersToMap.push(importedMember);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { trelloGetMembersToMap } from './trelloMembersMapper';
|
||||
import { wekanGetMembersToMap } from './wekanMembersMapper';
|
||||
import { csvGetMembersToMap } from './csvMembersMapper';
|
||||
@@ -174,9 +175,9 @@ BlazeComponent.extendComponent({
|
||||
this._refreshMembers(
|
||||
this.members().map(member => {
|
||||
if (!member.wekanId) {
|
||||
let user = Users.findOne({ username: member.username });
|
||||
let user = ReactiveCache.getUser({ username: member.username });
|
||||
if (!user) {
|
||||
user = Users.findOne({ importUsernames: member.username });
|
||||
user = ReactiveCache.getUser({ importUsernames: member.username });
|
||||
}
|
||||
if (user) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
export function trelloGetMembersToMap(data) {
|
||||
// we will work on the list itself (an ordered array of objects) when a
|
||||
// mapping is done, we add a 'wekan' field to the object representing the
|
||||
@@ -5,7 +7,7 @@ export function trelloGetMembersToMap(data) {
|
||||
const membersToMap = data.members;
|
||||
// auto-map based on username
|
||||
membersToMap.forEach(importedMember => {
|
||||
const wekanUser = Users.findOne({ username: importedMember.username });
|
||||
const wekanUser = ReactiveCache.getUser({ username: importedMember.username });
|
||||
if (wekanUser) {
|
||||
importedMember.wekanId = wekanUser._id;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
export function wekanGetMembersToMap(data) {
|
||||
// we will work on the list itself (an ordered array of objects) when a
|
||||
// mapping is done, we add a 'wekan' field to the object representing the
|
||||
@@ -15,7 +17,7 @@ export function wekanGetMembersToMap(data) {
|
||||
importedMember.fullName = user.profile.fullname;
|
||||
}
|
||||
importedMember.username = user.username;
|
||||
const wekanUser = Users.findOne({ username: importedMember.username });
|
||||
const wekanUser = ReactiveCache.getUser({ username: importedMember.username });
|
||||
if (wekanUser) {
|
||||
importedMember.wekanId = wekanUser._id;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
/* overflow: auto; - List width and height resizeable */
|
||||
}
|
||||
.list:first-child {
|
||||
min-width: 20px;
|
||||
margin-left: 5px;
|
||||
border-left: none;
|
||||
}
|
||||
@@ -112,6 +113,9 @@
|
||||
color: #4d4d4d;
|
||||
padding-left: 4px;
|
||||
}
|
||||
.js-open-list-menu {
|
||||
font-size: 18px;
|
||||
}
|
||||
.list-body {
|
||||
flex: 1 1 auto;
|
||||
flex-direction: column;
|
||||
@@ -122,6 +126,8 @@
|
||||
.list-body .minicards {
|
||||
flex-grow: 1;
|
||||
flex-shrink: 0;
|
||||
/** get card drag/drop working for empty swimlanes */
|
||||
min-height: 32px;
|
||||
}
|
||||
.list-body .minicards form {
|
||||
margin-bottom: 9px;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
require('/client/lib/jquery-ui.js')
|
||||
|
||||
@@ -23,14 +24,6 @@ BlazeComponent.extendComponent({
|
||||
onRendered() {
|
||||
const boardComponent = this.parentComponent().parentComponent();
|
||||
|
||||
function userIsMember() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly()
|
||||
);
|
||||
}
|
||||
|
||||
const itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)';
|
||||
const $cards = this.$('.js-minicards');
|
||||
|
||||
@@ -60,6 +53,7 @@ BlazeComponent.extendComponent({
|
||||
distance: 7,
|
||||
items: itemsSelector,
|
||||
placeholder: 'minicard-wrapper placeholder',
|
||||
scrollSpeed: 10,
|
||||
start(evt, ui) {
|
||||
ui.helper.css('z-index', 1000);
|
||||
ui.placeholder.height(ui.helper.height());
|
||||
@@ -74,7 +68,7 @@ BlazeComponent.extendComponent({
|
||||
const nCards = MultiSelection.isActive() ? MultiSelection.count() : 1;
|
||||
const sortIndex = calculateIndex(prevCardDom, nextCardDom, nCards);
|
||||
const listId = Blaze.getData(ui.item.parents('.list').get(0))._id;
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const defaultSwimlaneId = currentBoard.getDefaultSwimline()._id;
|
||||
let targetSwimlaneId = null;
|
||||
|
||||
@@ -96,7 +90,7 @@ BlazeComponent.extendComponent({
|
||||
$cards.sortable('cancel');
|
||||
|
||||
if (MultiSelection.isActive()) {
|
||||
Cards.find(MultiSelection.getMongoSelector(), { sort: ['sort'] }).forEach((card, i) => {
|
||||
ReactiveCache.getCards(MultiSelection.getMongoSelector(), { sort: ['sort'] }).forEach((card, i) => {
|
||||
const newSwimlaneId = targetSwimlaneId
|
||||
? targetSwimlaneId
|
||||
: card.swimlaneId || defaultSwimlaneId;
|
||||
@@ -168,9 +162,9 @@ BlazeComponent.extendComponent({
|
||||
'option',
|
||||
'disabled',
|
||||
// Disable drag-dropping when user is not member
|
||||
!userIsMember(),
|
||||
!Utils.canModifyBoard(),
|
||||
// Not disable drag-dropping while in multi-selection mode
|
||||
// MultiSelection.isActive() || !userIsMember(),
|
||||
// MultiSelection.isActive() || !Utils.canModifyBoard(),
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -180,14 +174,13 @@ BlazeComponent.extendComponent({
|
||||
const currentBoardId = Tracker.nonreactive(() => {
|
||||
return Session.get('currentBoard');
|
||||
});
|
||||
Cards.find({ boardId: currentBoardId }).fetch();
|
||||
Tracker.afterFlush(() => {
|
||||
$cards.find(itemsSelector).droppable({
|
||||
hoverClass: 'draggable-hover-card',
|
||||
accept: '.js-member,.js-label',
|
||||
drop(event, ui) {
|
||||
const cardId = Blaze.getData(this)._id;
|
||||
const card = Cards.findOne(cardId);
|
||||
const card = ReactiveCache.getCard(cardId);
|
||||
|
||||
if (ui.draggable.hasClass('js-member')) {
|
||||
const memberId = Blaze.getData(ui.draggable.get(0)).userId;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
template(name="listBody")
|
||||
.list-body
|
||||
.minicards.clearfix.js-minicards(class="{{#if reachedWipLimit}}js-list-full{{/if}}")
|
||||
if cards.count
|
||||
if cards.length
|
||||
+inlinedForm(autoclose=false position="top")
|
||||
+addCardForm(listId=_id position="top")
|
||||
ul.sidebar-list
|
||||
@@ -54,6 +54,7 @@ template(name="addCardForm")
|
||||
.add-controls.clearfix
|
||||
button.primary.confirm(type="submit") {{_ 'add'}}
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
.add-controls.clearfix
|
||||
unless currentBoard.isTemplatesBoard
|
||||
unless currentBoard.isTemplateBoard
|
||||
span.quiet
|
||||
@@ -94,7 +95,7 @@ template(name="linkCardPopup")
|
||||
label {{_ 'cards'}}:
|
||||
select.js-select-cards
|
||||
each cards
|
||||
option(value="{{getId}}") {{getTitle}}
|
||||
option(value="{{getRealId}}") {{getTitle}}
|
||||
|
||||
.edit-controls.clearfix
|
||||
input.primary.confirm.js-done(type="button" value="{{_ 'link'}}")
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import { Spinner } from '/client/lib/spinner';
|
||||
|
||||
@@ -15,10 +16,11 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
customFieldsSum() {
|
||||
return CustomFields.find({
|
||||
const ret = ReactiveCache.getCustomFields({
|
||||
boardIds: { $in: [Session.get('currentBoard')] },
|
||||
showSumAtTopOfList: true,
|
||||
});
|
||||
return ret;
|
||||
},
|
||||
|
||||
openForm(options) {
|
||||
@@ -64,7 +66,7 @@ BlazeComponent.extendComponent({
|
||||
swimlaneId = this.parentComponent()
|
||||
.parentComponent()
|
||||
.data()._id; // Always swimlanes view
|
||||
const swimlane = Swimlanes.findOne(swimlaneId);
|
||||
const swimlane = ReactiveCache.getSwimlane(swimlaneId);
|
||||
// If this is the card templates swimlane, insert a card template
|
||||
if (swimlane.isCardTemplatesSwimlane()) cardType = 'template-card';
|
||||
// If this is the board templates swimlane, insert a board template and a linked card
|
||||
@@ -112,7 +114,7 @@ BlazeComponent.extendComponent({
|
||||
// to appear
|
||||
const cardCount = this.data()
|
||||
.cards(this.idOrNull(swimlaneId))
|
||||
.count();
|
||||
.length;
|
||||
if (this.cardlimit.get() < cardCount) {
|
||||
this.cardlimit.set(this.cardlimit.get() + InfiniteScrollIter);
|
||||
}
|
||||
@@ -200,25 +202,23 @@ BlazeComponent.extendComponent({
|
||||
archived: false,
|
||||
};
|
||||
if (swimlaneId) selector.swimlaneId = swimlaneId;
|
||||
return Cards.find(Filter.mongoSelector(selector), {
|
||||
const ret = ReactiveCache.getCards(Filter.mongoSelector(selector), {
|
||||
// sort: ['sort'],
|
||||
sort: sortBy,
|
||||
limit,
|
||||
});
|
||||
}, true);
|
||||
return ret;
|
||||
},
|
||||
|
||||
showSpinner(swimlaneId) {
|
||||
const list = Template.currentData();
|
||||
return list.cards(swimlaneId).count() > this.cardlimit.get();
|
||||
return list.cards(swimlaneId).length > this.cardlimit.get();
|
||||
},
|
||||
|
||||
canSeeAddCard() {
|
||||
return (
|
||||
!this.reachedWipLimit() &&
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
Utils.canModifyCard()
|
||||
);
|
||||
},
|
||||
|
||||
@@ -227,7 +227,7 @@ BlazeComponent.extendComponent({
|
||||
return (
|
||||
!list.getWipLimit('soft') &&
|
||||
list.getWipLimit('enabled') &&
|
||||
list.getWipLimit('value') <= list.cards().count()
|
||||
list.getWipLimit('value') <= list.cards().length
|
||||
);
|
||||
},
|
||||
|
||||
@@ -269,9 +269,8 @@ BlazeComponent.extendComponent({
|
||||
const currentBoardId = Session.get('currentBoard');
|
||||
arr = [];
|
||||
_.forEach(
|
||||
Boards.findOne(currentBoardId)
|
||||
.customFields()
|
||||
.fetch(),
|
||||
ReactiveCache.getBoard(currentBoardId)
|
||||
.customFields(),
|
||||
function (field) {
|
||||
if (field.automaticallyOnCard || field.alwaysOnCard)
|
||||
arr.push({ _id: field._id, value: null });
|
||||
@@ -288,8 +287,8 @@ BlazeComponent.extendComponent({
|
||||
|
||||
getLabels() {
|
||||
const currentBoardId = Session.get('currentBoard');
|
||||
if (Boards.findOne(currentBoardId).labels) {
|
||||
return Boards.findOne(currentBoardId).labels.filter(label => {
|
||||
if (ReactiveCache.getBoard(currentBoardId).labels) {
|
||||
return ReactiveCache.getBoard(currentBoardId).labels.filter(label => {
|
||||
return this.labels.get().indexOf(label._id) > -1;
|
||||
});
|
||||
}
|
||||
@@ -349,10 +348,10 @@ BlazeComponent.extendComponent({
|
||||
{
|
||||
match: /\B@([\w.-]*)$/,
|
||||
search(term, callback) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
callback(
|
||||
$.map(currentBoard.activeMembers(), member => {
|
||||
const user = Users.findOne(member.userId);
|
||||
const user = ReactiveCache.getUser(member.userId);
|
||||
return user.username.indexOf(term) === 0 ? user : null;
|
||||
}),
|
||||
);
|
||||
@@ -374,7 +373,7 @@ BlazeComponent.extendComponent({
|
||||
{
|
||||
match: /\B#(\w*)$/,
|
||||
search(term, callback) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
callback(
|
||||
$.map(currentBoard.labels, label => {
|
||||
if (label.name == undefined) {
|
||||
@@ -430,10 +429,10 @@ BlazeComponent.extendComponent({
|
||||
this.boardId = Session.get('currentBoard');
|
||||
// In order to get current board info
|
||||
subManager.subscribe('board', this.boardId, false);
|
||||
this.board = Boards.findOne(this.boardId);
|
||||
this.board = ReactiveCache.getBoard(this.boardId);
|
||||
// List where to insert card
|
||||
const list = $(Popup._getTopStack().openerElement).closest('.js-list');
|
||||
this.listId = Blaze.getData(list[0])._id;
|
||||
this.list = $(Popup._getTopStack().openerElement).closest('.js-list');
|
||||
this.listId = Blaze.getData(this.list[0])._id;
|
||||
// Swimlane where to insert card
|
||||
const swimlane = $(Popup._getTopStack().openerElement).closest(
|
||||
'.js-swimlane',
|
||||
@@ -442,11 +441,11 @@ BlazeComponent.extendComponent({
|
||||
if (Utils.boardView() === 'board-view-swimlanes')
|
||||
this.swimlaneId = Blaze.getData(swimlane[0])._id;
|
||||
else if (Utils.boardView() === 'board-view-lists' || !Utils.boardView)
|
||||
this.swimlaneId = Swimlanes.findOne({ boardId: this.boardId })._id;
|
||||
this.swimlaneId = ReactiveCache.getSwimlane({ boardId: this.boardId })._id;
|
||||
},
|
||||
|
||||
boards() {
|
||||
const boards = Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
@@ -457,16 +456,22 @@ BlazeComponent.extendComponent({
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return boards;
|
||||
return ret;
|
||||
},
|
||||
|
||||
swimlanes() {
|
||||
if (!this.selectedBoardId.get()) {
|
||||
return [];
|
||||
}
|
||||
const swimlanes = Swimlanes.find({ boardId: this.selectedBoardId.get() });
|
||||
if (swimlanes.count())
|
||||
this.selectedSwimlaneId.set(swimlanes.fetch()[0]._id);
|
||||
const swimlanes = ReactiveCache.getSwimlanes(
|
||||
{
|
||||
boardId: this.selectedBoardId.get()
|
||||
},
|
||||
{
|
||||
sort: { sort: 1 },
|
||||
});
|
||||
if (swimlanes.length)
|
||||
this.selectedSwimlaneId.set(swimlanes[0]._id);
|
||||
return swimlanes;
|
||||
},
|
||||
|
||||
@@ -474,8 +479,14 @@ BlazeComponent.extendComponent({
|
||||
if (!this.selectedBoardId.get()) {
|
||||
return [];
|
||||
}
|
||||
const lists = Lists.find({ boardId: this.selectedBoardId.get() });
|
||||
if (lists.count()) this.selectedListId.set(lists.fetch()[0]._id);
|
||||
const lists = ReactiveCache.getLists(
|
||||
{
|
||||
boardId: this.selectedBoardId.get()
|
||||
},
|
||||
{
|
||||
sort: { sort: 1 },
|
||||
});
|
||||
if (lists.length) this.selectedListId.set(lists[0]._id);
|
||||
return lists;
|
||||
},
|
||||
|
||||
@@ -483,10 +494,9 @@ BlazeComponent.extendComponent({
|
||||
if (!this.board) {
|
||||
return [];
|
||||
}
|
||||
const ownCardsIds = this.board.cards().map(card => {
|
||||
return card.linkedId || card._id;
|
||||
});
|
||||
return Cards.find({
|
||||
const ownCardsIds = this.board.cards().map(card => card.getRealId());
|
||||
const ret = ReactiveCache.getCards(
|
||||
{
|
||||
boardId: this.selectedBoardId.get(),
|
||||
swimlaneId: this.selectedSwimlaneId.get(),
|
||||
listId: this.selectedListId.get(),
|
||||
@@ -494,7 +504,24 @@ BlazeComponent.extendComponent({
|
||||
linkedId: { $nin: ownCardsIds },
|
||||
_id: { $nin: ownCardsIds },
|
||||
type: { $nin: ['template-card'] },
|
||||
},
|
||||
{
|
||||
sort: { sort: 1 },
|
||||
});
|
||||
return ret;
|
||||
},
|
||||
|
||||
getSortIndex() {
|
||||
const position = this.currentData().position;
|
||||
let ret;
|
||||
if (position === 'top') {
|
||||
const firstCardDom = this.list.find('.js-minicard:first')[0];
|
||||
ret = Utils.calculateIndex(null, firstCardDom).base;
|
||||
} else if (position === 'bottom') {
|
||||
const lastCardDom = this.list.find('.js-minicard:last')[0];
|
||||
ret = Utils.calculateIndex(lastCardDom, null).base;
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
|
||||
events() {
|
||||
@@ -519,16 +546,17 @@ BlazeComponent.extendComponent({
|
||||
Popup.back();
|
||||
return;
|
||||
}
|
||||
const nextCardNumber = this.board.getNextCardNumber();
|
||||
const sortIndex = this.getSortIndex();
|
||||
const _id = Cards.insert({
|
||||
title: $('.js-select-cards option:selected').text(), //dummy
|
||||
listId: this.listId,
|
||||
swimlaneId: this.swimlaneId,
|
||||
boardId: this.boardId,
|
||||
sort: Lists.findOne(this.listId)
|
||||
.cards()
|
||||
.count(),
|
||||
sort: sortIndex,
|
||||
type: 'cardType-linkedCard',
|
||||
linkedId,
|
||||
cardNumber: nextCardNumber,
|
||||
});
|
||||
Filter.addException(_id);
|
||||
Popup.back();
|
||||
@@ -540,21 +568,22 @@ BlazeComponent.extendComponent({
|
||||
const impBoardId = $('.js-select-boards option:selected').val();
|
||||
if (
|
||||
!impBoardId ||
|
||||
Cards.findOne({ linkedId: impBoardId, archived: false })
|
||||
ReactiveCache.getCard({ linkedId: impBoardId, archived: false })
|
||||
) {
|
||||
Popup.back();
|
||||
return;
|
||||
}
|
||||
const nextCardNumber = this.board.getNextCardNumber();
|
||||
const sortIndex = this.getSortIndex();
|
||||
const _id = Cards.insert({
|
||||
title: $('.js-select-boards option:selected').text(), //dummy
|
||||
listId: this.listId,
|
||||
swimlaneId: this.swimlaneId,
|
||||
boardId: this.boardId,
|
||||
sort: Lists.findOne(this.listId)
|
||||
.cards()
|
||||
.count(),
|
||||
sort: sortIndex,
|
||||
type: 'cardType-linkedBoard',
|
||||
linkedId: impBoardId,
|
||||
cardNumber: nextCardNumber,
|
||||
});
|
||||
Filter.addException(_id);
|
||||
Popup.back();
|
||||
@@ -587,36 +616,27 @@ BlazeComponent.extendComponent({
|
||||
this.isListTemplateSearch ||
|
||||
this.isSwimlaneTemplateSearch ||
|
||||
this.isBoardTemplateSearch;
|
||||
let board = {};
|
||||
|
||||
this.board = {};
|
||||
if (this.isTemplateSearch) {
|
||||
//board = Boards.findOne((Meteor.user().profile || {}).templatesBoardId);
|
||||
board._id = (Meteor.user().profile || {}).templatesBoardId;
|
||||
const boardId = (ReactiveCache.getCurrentUser().profile || {}).templatesBoardId;
|
||||
if (boardId) {
|
||||
this.board = ReactiveCache.getBoard(boardId);
|
||||
}
|
||||
} else {
|
||||
// Prefetch first non-current board id
|
||||
board = Boards.find({
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
_id: {
|
||||
$nin: [
|
||||
Session.get('currentBoard'),
|
||||
(Meteor.user().profile || {}).templatesBoardId,
|
||||
],
|
||||
},
|
||||
});
|
||||
this.board = Utils.getCurrentBoard();
|
||||
}
|
||||
if (!board) {
|
||||
if (!this.board) {
|
||||
Popup.back();
|
||||
return;
|
||||
}
|
||||
const boardId = board._id;
|
||||
this.boardId = this.board._id;
|
||||
// Subscribe to this board
|
||||
subManager.subscribe('board', boardId, false);
|
||||
this.selectedBoardId = new ReactiveVar(boardId);
|
||||
subManager.subscribe('board', this.boardId, false);
|
||||
this.selectedBoardId = new ReactiveVar(this.boardId);
|
||||
this.list = $(Popup._getTopStack().openerElement).closest('.js-list');
|
||||
|
||||
if (!this.isBoardTemplateSearch) {
|
||||
this.boardId = Session.get('currentBoard');
|
||||
// In order to get current board info
|
||||
subManager.subscribe('board', this.boardId, false);
|
||||
this.swimlaneId = '';
|
||||
// Swimlane where to insert card
|
||||
const swimlane = $(Popup._getTopStack().openerElement).parents(
|
||||
@@ -624,16 +644,15 @@ BlazeComponent.extendComponent({
|
||||
);
|
||||
if (Utils.boardView() === 'board-view-swimlanes')
|
||||
this.swimlaneId = Blaze.getData(swimlane[0])._id;
|
||||
else this.swimlaneId = Swimlanes.findOne({ boardId: this.boardId })._id;
|
||||
else this.swimlaneId = ReactiveCache.getSwimlane({ boardId: this.boardId })._id;
|
||||
// List where to insert card
|
||||
const list = $(Popup._getTopStack().openerElement).closest('.js-list');
|
||||
this.listId = Blaze.getData(list[0])._id;
|
||||
this.listId = Blaze.getData(this.list[0])._id;
|
||||
}
|
||||
this.term = new ReactiveVar('');
|
||||
},
|
||||
|
||||
boards() {
|
||||
const boards = Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
@@ -644,14 +663,14 @@ BlazeComponent.extendComponent({
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return boards;
|
||||
return ret;
|
||||
},
|
||||
|
||||
results() {
|
||||
if (!this.selectedBoardId) {
|
||||
return [];
|
||||
}
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
|
||||
if (!this.isTemplateSearch || this.isCardTemplateSearch) {
|
||||
return board.searchCards(this.term.get(), false);
|
||||
} else if (this.isListTemplateSearch) {
|
||||
@@ -669,6 +688,19 @@ BlazeComponent.extendComponent({
|
||||
}
|
||||
},
|
||||
|
||||
getSortIndex() {
|
||||
const position = this.data().position;
|
||||
let ret;
|
||||
if (position === 'top') {
|
||||
const firstCardDom = this.list.find('.js-minicard:first')[0];
|
||||
ret = Utils.calculateIndex(null, firstCardDom).base;
|
||||
} else if (position === 'bottom') {
|
||||
const lastCardDom = this.list.find('.js-minicard:last')[0];
|
||||
ret = Utils.calculateIndex(lastCardDom, null).base;
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
@@ -692,9 +724,8 @@ BlazeComponent.extendComponent({
|
||||
if (!this.isTemplateSearch || this.isCardTemplateSearch) {
|
||||
// Card insertion
|
||||
// 1. Common
|
||||
element.sort = Lists.findOne(this.listId)
|
||||
.cards()
|
||||
.count();
|
||||
element.cardNumber = this.board.getNextCardNumber();
|
||||
element.sort = this.getSortIndex();
|
||||
// 1.A From template
|
||||
if (this.isTemplateSearch) {
|
||||
element.type = 'cardType-card';
|
||||
@@ -707,15 +738,15 @@ BlazeComponent.extendComponent({
|
||||
Filter.addException(_id);
|
||||
// List insertion
|
||||
} else if (this.isListTemplateSearch) {
|
||||
element.sort = Swimlanes.findOne(this.swimlaneId)
|
||||
element.sort = ReactiveCache.getSwimlane(this.swimlaneId)
|
||||
.lists()
|
||||
.count();
|
||||
.length;
|
||||
element.type = 'list';
|
||||
_id = element.copy(this.boardId, this.swimlaneId);
|
||||
} else if (this.isSwimlaneTemplateSearch) {
|
||||
element.sort = Boards.findOne(this.boardId)
|
||||
element.sort = ReactiveCache.getBoard(this.boardId)
|
||||
.swimlanes()
|
||||
.count();
|
||||
.length;
|
||||
element.type = 'swimlane';
|
||||
_id = element.copy(this.boardId);
|
||||
} else if (this.isBoardTemplateSearch) {
|
||||
@@ -723,7 +754,7 @@ BlazeComponent.extendComponent({
|
||||
'copyBoard',
|
||||
element.linkedId,
|
||||
{
|
||||
sort: Boards.find({ archived: false }).count(),
|
||||
sort: ReactiveCache.getBoards({ archived: false }).length,
|
||||
type: 'board',
|
||||
title: element.title,
|
||||
},
|
||||
@@ -757,7 +788,7 @@ BlazeComponent.extendComponent({
|
||||
Meteor.settings.public.sandstorm;
|
||||
|
||||
if (isSandstorm) {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
if (user) {
|
||||
if (Utils.boardView() === 'board-view-swimlanes') {
|
||||
this.swimlaneId = this.parentComponent()
|
||||
|
||||
@@ -15,11 +15,11 @@ template(name="listHeader")
|
||||
= title
|
||||
if wipLimit.enabled
|
||||
| (
|
||||
span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.count}}
|
||||
span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.length}}
|
||||
|/#{wipLimit.value})
|
||||
|
||||
if showCardsCountForList cards.count
|
||||
span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.count}}
|
||||
if showCardsCountForList cards.length
|
||||
span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.length}}
|
||||
|
||||
if isMiniScreen
|
||||
if currentList
|
||||
@@ -79,7 +79,7 @@ template(name="listActionPopup")
|
||||
i.fa.fa-paint-brush
|
||||
| {{_ 'set-color-list'}}
|
||||
ul.pop-over-list
|
||||
if cards.count
|
||||
if cards.length
|
||||
li
|
||||
a.js-select-cards
|
||||
i.fa.fa-check-square
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
let listsColors;
|
||||
@@ -12,12 +13,12 @@ BlazeComponent.extendComponent({
|
||||
(!list.getWipLimit('enabled') ||
|
||||
list.getWipLimit('soft') ||
|
||||
!this.reachedWipLimit()) &&
|
||||
!Meteor.user().isWorker()
|
||||
!ReactiveCache.getCurrentUser().isWorker()
|
||||
);
|
||||
},
|
||||
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
starred(check = undefined) {
|
||||
const list = Template.currentData();
|
||||
@@ -47,9 +48,9 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
limitToShowCardsCount() {
|
||||
const currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return Meteor.user().getLimitToShowCardsCount();
|
||||
return currentUser.getLimitToShowCardsCount();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -63,14 +64,15 @@ BlazeComponent.extendComponent({
|
||||
.parentComponent()
|
||||
.data()._id;
|
||||
|
||||
return list.cards(swimlaneId).count();
|
||||
const ret = list.cards(swimlaneId).length;
|
||||
return ret;
|
||||
},
|
||||
|
||||
reachedWipLimit() {
|
||||
const list = Template.currentData();
|
||||
return (
|
||||
list.getWipLimit('enabled') &&
|
||||
list.getWipLimit('value') <= list.cards().count()
|
||||
list.getWipLimit('value') <= list.cards().length
|
||||
);
|
||||
},
|
||||
|
||||
@@ -78,7 +80,7 @@ BlazeComponent.extendComponent({
|
||||
const list = Template.currentData();
|
||||
return (
|
||||
list.getWipLimit('enabled') &&
|
||||
list.getWipLimit('value') < list.cards().count()
|
||||
list.getWipLimit('value') < list.cards().length
|
||||
);
|
||||
},
|
||||
|
||||
@@ -123,13 +125,13 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.listHeader.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
}
|
||||
});
|
||||
|
||||
Template.listActionPopup.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
|
||||
isWipLimitEnabled() {
|
||||
@@ -183,7 +185,7 @@ BlazeComponent.extendComponent({
|
||||
10,
|
||||
);
|
||||
|
||||
if (limit < list.cards().count() && !list.getWipLimit('soft')) {
|
||||
if (limit < list.cards().length && !list.getWipLimit('soft')) {
|
||||
Template.instance()
|
||||
.$('.wip-limit-error')
|
||||
.click();
|
||||
@@ -198,9 +200,9 @@ BlazeComponent.extendComponent({
|
||||
|
||||
if (
|
||||
list.getWipLimit('soft') &&
|
||||
list.getWipLimit('value') < list.cards().count()
|
||||
list.getWipLimit('value') < list.cards().length
|
||||
) {
|
||||
list.setWipLimit(list.cards().count());
|
||||
list.setWipLimit(list.cards().length);
|
||||
}
|
||||
Meteor.call('enableSoftLimit', Template.currentData()._id);
|
||||
},
|
||||
@@ -210,9 +212,9 @@ BlazeComponent.extendComponent({
|
||||
// Prevent user from using previously stored wipLimit.value if it is less than the current number of cards in the list
|
||||
if (
|
||||
!list.getWipLimit('enabled') &&
|
||||
list.getWipLimit('value') < list.cards().count()
|
||||
list.getWipLimit('value') < list.cards().length
|
||||
) {
|
||||
list.setWipLimit(list.cards().count());
|
||||
list.setWipLimit(list.cards().length);
|
||||
}
|
||||
Meteor.call('enableWipLimit', list._id);
|
||||
},
|
||||
@@ -244,17 +246,16 @@ BlazeComponent.extendComponent({
|
||||
Template.listMorePopup.events({
|
||||
'click .js-delete': Popup.afterConfirm('listDelete', function() {
|
||||
Popup.back();
|
||||
// TODO how can we avoid the fetch call?
|
||||
const allCards = this.allCards().fetch();
|
||||
const allCards = this.allCards();
|
||||
const allCardIds = _.pluck(allCards, '_id');
|
||||
// it's okay if the linked cards are on the same list
|
||||
if (
|
||||
Cards.find({
|
||||
ReactiveCache.getCards({
|
||||
$and: [
|
||||
{ listId: { $ne: this._id } },
|
||||
{ linkedId: { $in: allCardIds } },
|
||||
],
|
||||
}).count() === 0
|
||||
}).length === 0
|
||||
) {
|
||||
allCardIds.map(_id => Cards.remove(_id));
|
||||
Lists.remove(this._id);
|
||||
@@ -279,7 +280,7 @@ Template.listMorePopup.events({
|
||||
|
||||
Template.listHeader.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { CardSearchPagedComponent } from '../../lib/cardSearch';
|
||||
import {
|
||||
OPERATOR_HAS,
|
||||
@@ -66,7 +67,7 @@ class DueCardsComponent extends CardSearchPagedComponent {
|
||||
});
|
||||
|
||||
if (Utils.dueCardsView() !== 'all') {
|
||||
queryParams.addPredicate(OPERATOR_USER, Meteor.user().username);
|
||||
queryParams.addPredicate(OPERATOR_USER, ReactiveCache.getCurrentUser().username);
|
||||
}
|
||||
|
||||
this.runGlobalSearch(queryParams);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
const specialHandles = [
|
||||
{userId: 'board_members', username: 'board_members'},
|
||||
{userId: 'card_members', username: 'card_members'}
|
||||
@@ -13,13 +15,13 @@ BlazeComponent.extendComponent({
|
||||
{
|
||||
match: /\B@([\w.-]*)$/,
|
||||
search(term, callback) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
callback(
|
||||
_.union(
|
||||
currentBoard
|
||||
.activeMembers()
|
||||
.map(member => {
|
||||
const user = Users.findOne(member.userId);
|
||||
const user = ReactiveCache.getUser(member.userId);
|
||||
const username = user.username;
|
||||
const fullName = user.profile && user.profile !== undefined && user.profile.fullname ? user.profile.fullname : "";
|
||||
return username.includes(term) || fullName.includes(term) ? user : null;
|
||||
@@ -328,13 +330,13 @@ Blaze.Template.registerHelper(
|
||||
new Template('mentions', function() {
|
||||
const view = this;
|
||||
let content = Blaze.toHTML(view.templateContentBlock);
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
if (!currentBoard)
|
||||
return HTML.Raw(
|
||||
DOMPurify.sanitize(content, { ALLOW_UNKNOWN_PROTOCOLS: true }),
|
||||
);
|
||||
const knowedUsers = _.union(currentBoard.members.map(member => {
|
||||
const u = Users.findOne(member.userId);
|
||||
const u = ReactiveCache.getUser(member.userId);
|
||||
if (u) {
|
||||
member.username = u.username;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
Meteor.subscribe('user-admin');
|
||||
Meteor.subscribe('boards');
|
||||
Meteor.subscribe('setting');
|
||||
@@ -9,7 +11,7 @@ Template.header.onCreated(function(){
|
||||
|
||||
Meteor.subscribe('setting', {
|
||||
onReady() {
|
||||
templateInstance.currentSetting.set(Settings.findOne());
|
||||
templateInstance.currentSetting.set(ReactiveCache.getCurrentSetting());
|
||||
let currSetting = templateInstance.currentSetting.curValue;
|
||||
if(currSetting && currSetting !== undefined && currSetting.customLoginLogoImageUrl !== undefined && document.getElementById("headerIsSettingDatabaseCallDone") != null)
|
||||
document.getElementById("headerIsSettingDatabaseCallDone").style.display = 'none';
|
||||
@@ -24,10 +26,6 @@ Template.header.helpers({
|
||||
return !Session.get('currentBoard');
|
||||
},
|
||||
|
||||
currentSetting() {
|
||||
return Settings.findOne();
|
||||
},
|
||||
|
||||
hideLogo() {
|
||||
return Utils.isMiniScreen() && Session.get('currentBoard');
|
||||
},
|
||||
|
||||
@@ -6,12 +6,12 @@ head
|
||||
where the application is deployed with a path prefix, but it seems to be
|
||||
difficult to do that cleanly with Blaze -- at least without adding extra
|
||||
packages.
|
||||
link(rel="shortcut icon" type="image/x-icon" href="favicon.ico")
|
||||
link(rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png")
|
||||
link(rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png")
|
||||
link(rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png")
|
||||
link(rel="shortcut icon" type="image/x-icon" href="/favicon.ico")
|
||||
link(rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png")
|
||||
link(rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png")
|
||||
link(rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png")
|
||||
link(rel="manifest" crossOrigin="use-credentials" href="/site.webmanifest")
|
||||
link(rel="mask-icon" href="safari-pinned-tab.svg" color="#5bbad5")
|
||||
link(rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5")
|
||||
meta(name="apple-mobile-web-app-title" content="Wekan")
|
||||
meta(name="application-name" content="Wekan")
|
||||
meta(name="msapplication-TileColor" content="#00aba9")
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
BlazeLayout.setRoot('body');
|
||||
@@ -28,7 +29,7 @@ Template.userFormsLayout.onCreated(function () {
|
||||
|
||||
Meteor.subscribe('setting', {
|
||||
onReady() {
|
||||
templateInstance.currentSetting.set(Settings.findOne());
|
||||
templateInstance.currentSetting.set(ReactiveCache.getCurrentSetting());
|
||||
let currSetting = templateInstance.currentSetting.curValue;
|
||||
let oidcBtnElt = $("#at-oidc");
|
||||
if(currSetting && currSetting !== undefined && currSetting.oidcBtnText !== undefined && oidcBtnElt != null && oidcBtnElt != undefined){
|
||||
@@ -50,7 +51,7 @@ Template.userFormsLayout.onCreated(function () {
|
||||
}
|
||||
});
|
||||
|
||||
if (!Meteor.user()?.profile) {
|
||||
if (!ReactiveCache.getCurrentUser()?.profile) {
|
||||
Meteor.call('isOidcRedirectionEnabled', (_, result) => {
|
||||
if (result) {
|
||||
AccountsTemplates.options.socialLoginStyle = 'redirect';
|
||||
@@ -59,7 +60,7 @@ Template.userFormsLayout.onCreated(function () {
|
||||
};
|
||||
Meteor.loginWithOidc(options);
|
||||
}
|
||||
else console.log("oidc redirect not set");
|
||||
//else console.log("oidc redirect not set");
|
||||
});
|
||||
}
|
||||
Meteor.call('isDisableRegistration', (_, result) => {
|
||||
@@ -85,10 +86,6 @@ Template.userFormsLayout.onRendered(() => {
|
||||
});
|
||||
|
||||
Template.userFormsLayout.helpers({
|
||||
currentSetting() {
|
||||
return Template.instance().currentSetting.get();
|
||||
},
|
||||
|
||||
// isSettingDatabaseCallDone(){
|
||||
// return isSettingDatabaseFctCallDone;
|
||||
// },
|
||||
@@ -164,7 +161,7 @@ Template.userFormsLayout.events({
|
||||
},
|
||||
'DOMSubtreeModified #at-oidc'(event) {
|
||||
if (alreadyCheck <= 2) {
|
||||
let currSetting = Settings.findOne();
|
||||
let currSetting = ReactiveCache.getCurrentSetting();
|
||||
let oidcBtnElt = $("#at-oidc");
|
||||
if (currSetting && currSetting !== undefined && currSetting.oidcBtnText !== undefined && oidcBtnElt != null && oidcBtnElt != undefined) {
|
||||
let htmlvalue = "<i class='fa fa-oidc'></i>" + currSetting.oidcBtnText;
|
||||
@@ -185,7 +182,7 @@ Template.userFormsLayout.events({
|
||||
'DOMSubtreeModified .at-form'(event) {
|
||||
if (alreadyCheck <= 2 && !isCheckDone) {
|
||||
if (document.getElementById("at-oidc") != null) {
|
||||
let currSetting = Settings.findOne();
|
||||
let currSetting = ReactiveCache.getCurrentSetting();
|
||||
let oidcBtnElt = $("#at-oidc");
|
||||
if (currSetting && currSetting !== undefined && currSetting.oidcBtnText !== undefined && oidcBtnElt != null && oidcBtnElt != undefined) {
|
||||
let htmlvalue = "<i class='fa fa-oidc'></i>" + currSetting.oidcBtnText;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
Template.notification.events({
|
||||
'click .read-status .materialCheckBox'() {
|
||||
const update = {};
|
||||
@@ -7,22 +9,22 @@ Template.notification.events({
|
||||
Users.update(Meteor.userId(), { $set: update });
|
||||
},
|
||||
'click .remove a'() {
|
||||
Meteor.user().removeNotification(this.activityData._id);
|
||||
ReactiveCache.getCurrentUser().removeNotification(this.activityData._id);
|
||||
},
|
||||
});
|
||||
|
||||
Template.notification.helpers({
|
||||
mode: 'board',
|
||||
isOfActivityType(activityId, type) {
|
||||
const activity = Activities.findOne(activityId);
|
||||
const activity = ReactiveCache.getActivity(activityId);
|
||||
return activity && activity.activityType === type;
|
||||
},
|
||||
activityType(activityId) {
|
||||
const activity = Activities.findOne(activityId);
|
||||
const activity = ReactiveCache.getActivity(activityId);
|
||||
return activity ? activity.activityType : '';
|
||||
},
|
||||
activityUser(activityId) {
|
||||
const activity = Activities.findOne(activityId);
|
||||
const activity = ReactiveCache.getActivity(activityId);
|
||||
return activity && activity.userId;
|
||||
},
|
||||
});
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
// this hides the notifications drawer if anyone clicks off of the panel
|
||||
Template.body.events({
|
||||
click(event) {
|
||||
@@ -12,7 +14,7 @@ Template.body.events({
|
||||
|
||||
Template.notifications.helpers({
|
||||
unreadNotifications() {
|
||||
const notifications = Users.findOne(Meteor.userId()).notifications();
|
||||
const notifications = ReactiveCache.getCurrentUser().notifications();
|
||||
const unreadNotifications = _.filter(notifications, v => !v.read);
|
||||
return unreadNotifications.length;
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { toggleNotificationsDrawer } from './notifications.js';
|
||||
|
||||
Template.notificationsDrawer.onCreated(function() {
|
||||
@@ -14,11 +15,11 @@ Template.notificationsDrawer.onCreated(function() {
|
||||
|
||||
Template.notificationsDrawer.helpers({
|
||||
transformedProfile() {
|
||||
return Users.findOne(Meteor.userId());
|
||||
return ReactiveCache.getCurrentUser();
|
||||
},
|
||||
readNotifications() {
|
||||
const readNotifications = _.filter(
|
||||
Meteor.user().profile.notifications,
|
||||
ReactiveCache.getCurrentUser().profile.notifications,
|
||||
v => !!v.read,
|
||||
);
|
||||
return readNotifications.length;
|
||||
@@ -27,7 +28,7 @@ Template.notificationsDrawer.helpers({
|
||||
|
||||
Template.notificationsDrawer.events({
|
||||
'click .all-read'() {
|
||||
const notifications = Meteor.user().profile.notifications;
|
||||
const notifications = ReactiveCache.getCurrentUser().profile.notifications;
|
||||
for (const index in notifications) {
|
||||
if (notifications.hasOwnProperty(index) && !notifications[index].read) {
|
||||
const update = {};
|
||||
@@ -43,7 +44,7 @@ Template.notificationsDrawer.events({
|
||||
Session.set('showReadNotifications', !Session.get('showReadNotifications'));
|
||||
},
|
||||
'click .remove-read'() {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
for (const notification of user.profile.notifications) {
|
||||
if (notification.read) {
|
||||
user.removeNotification(notification.activity);
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {},
|
||||
|
||||
boards() {
|
||||
const boards = Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
_id: {
|
||||
$ne: Meteor.user().getTemplatesBoardId(),
|
||||
$ne: ReactiveCache.getCurrentUser().getTemplatesBoardId(),
|
||||
},
|
||||
},
|
||||
{
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return boards;
|
||||
return ret;
|
||||
},
|
||||
|
||||
events() {
|
||||
|
||||
@@ -18,7 +18,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
labels() {
|
||||
const labels = Boards.findOne(Session.get('currentBoard')).labels;
|
||||
const labels = Utils.getCurrentBoard().labels;
|
||||
for (let i = 0; i < labels.length; i++) {
|
||||
if (labels[i].name === '' || labels[i].name === undefined) {
|
||||
labels[i].name = labels[i].color.toUpperCase();
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.subscribe('allRules');
|
||||
@@ -7,24 +9,16 @@ BlazeComponent.extendComponent({
|
||||
|
||||
trigger() {
|
||||
const ruleId = this.data().ruleId;
|
||||
const rule = Rules.findOne({
|
||||
_id: ruleId.get(),
|
||||
});
|
||||
const trigger = Triggers.findOne({
|
||||
_id: rule.triggerId,
|
||||
});
|
||||
const rule = ReactiveCache.getRule(ruleId.get());
|
||||
const trigger = ReactiveCache.getTrigger(rule.triggerId);
|
||||
const desc = trigger.description();
|
||||
const upperdesc = desc.charAt(0).toUpperCase() + desc.substr(1);
|
||||
return upperdesc;
|
||||
},
|
||||
action() {
|
||||
const ruleId = this.data().ruleId;
|
||||
const rule = Rules.findOne({
|
||||
_id: ruleId.get(),
|
||||
});
|
||||
const action = Actions.findOne({
|
||||
_id: rule.actionId,
|
||||
});
|
||||
const rule = ReactiveCache.getRule(ruleId.get());
|
||||
const action = ReactiveCache.getAction(rule.actionId);
|
||||
const desc = action.description();
|
||||
const upperdesc = desc.charAt(0).toUpperCase() + desc.substr(1);
|
||||
return upperdesc;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentActions = new ReactiveVar('board');
|
||||
@@ -33,7 +35,8 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
rules() {
|
||||
return Rules.find({});
|
||||
const ret = ReactiveCache.getRules({});
|
||||
return ret;
|
||||
},
|
||||
|
||||
name() {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.subscribe('allRules');
|
||||
@@ -5,9 +7,10 @@ BlazeComponent.extendComponent({
|
||||
|
||||
rules() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
return Rules.find({
|
||||
const ret = ReactiveCache.getRules({
|
||||
boardId,
|
||||
});
|
||||
return ret;
|
||||
},
|
||||
events() {
|
||||
return [{}];
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.rulesCurrentTab = new ReactiveVar('rulesList');
|
||||
@@ -55,7 +57,7 @@ BlazeComponent.extendComponent({
|
||||
let trigger = this.triggerVar.get();
|
||||
trigger.userId = '*';
|
||||
if (username !== undefined) {
|
||||
const userFound = Users.findOne({ username });
|
||||
const userFound = ReactiveCache.getUser({ username });
|
||||
if (userFound !== undefined) {
|
||||
trigger.userId = userFound._id;
|
||||
this.triggerVar.set(trigger);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.showBoardTrigger = new ReactiveVar(true);
|
||||
@@ -31,7 +33,8 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
rules() {
|
||||
return Rules.find({});
|
||||
const ret = ReactiveCache.getRules({});
|
||||
return ret;
|
||||
},
|
||||
|
||||
name() {
|
||||
|
||||
@@ -5,7 +5,7 @@ BlazeComponent.extendComponent({
|
||||
this.subscribe('allRules');
|
||||
},
|
||||
labels() {
|
||||
const labels = Boards.findOne(Session.get('currentBoard')).labels;
|
||||
const labels = Utils.getCurrentBoard().labels;
|
||||
for (let i = 0; i < labels.length; i++) {
|
||||
if (labels[i].name === '' || labels[i].name === undefined) {
|
||||
labels[i].name = labels[i].color;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import { AttachmentStorage } from '/models/attachments';
|
||||
import { CardSearchPagedComponent } from '/client/lib/cardSearch';
|
||||
@@ -115,12 +116,15 @@ class AdminReport extends BlazeComponent {
|
||||
}
|
||||
|
||||
fileSize(size) {
|
||||
const ret = filesize(size);
|
||||
let ret = "";
|
||||
if (_.isNumber(size)) {
|
||||
ret = filesize(size);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
abbreviate(text) {
|
||||
if (text.length > 30) {
|
||||
if (text?.length > 30) {
|
||||
return `${text.substr(0, 29)}...`;
|
||||
}
|
||||
return text;
|
||||
@@ -137,7 +141,7 @@ class AdminReport extends BlazeComponent {
|
||||
results() {
|
||||
const rules = [];
|
||||
|
||||
Rules.find().forEach(rule => {
|
||||
ReactiveCache.getRules().forEach(rule => {
|
||||
rules.push({
|
||||
_id: rule._id,
|
||||
title: rule.title,
|
||||
@@ -158,17 +162,13 @@ class AdminReport extends BlazeComponent {
|
||||
collection = Boards;
|
||||
|
||||
userNames(members) {
|
||||
let text = '';
|
||||
members.forEach(member => {
|
||||
const user = Users.findOne(member.userId);
|
||||
text += text ? ', ' : '';
|
||||
if (user) {
|
||||
text += user.username;
|
||||
} else {
|
||||
text += member.userId
|
||||
}
|
||||
});
|
||||
return text;
|
||||
const ret = (members || [])
|
||||
.map(_member => {
|
||||
const _ret = ReactiveCache.getUser(_member.userId)?.username || _member.userId;
|
||||
return _ret;
|
||||
})
|
||||
.join(", ");
|
||||
return ret;
|
||||
}
|
||||
}.register('boardsReport'));
|
||||
|
||||
@@ -176,13 +176,13 @@ class AdminReport extends BlazeComponent {
|
||||
collection = Cards;
|
||||
|
||||
userNames(userIds) {
|
||||
let text = '';
|
||||
userIds.forEach(userId => {
|
||||
const user = Users.findOne(userId);
|
||||
text += text ? ', ' : '';
|
||||
text += user.username;
|
||||
});
|
||||
return text;
|
||||
const ret = (userIds || [])
|
||||
.map(_userId => {
|
||||
const _ret = ReactiveCache.getUser(_userId)?.username;
|
||||
return _ret;
|
||||
})
|
||||
.join(", ");
|
||||
return ret
|
||||
}
|
||||
}.register('cardsReport'));
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ template(name="moveBoardAttachments")
|
||||
th {{_ 'version-name'}}
|
||||
th {{_ 'size'}}
|
||||
th GridFsFileId
|
||||
th S3FileId
|
||||
th {{_ 'storage'}}
|
||||
th {{_ 'action'}}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import Attachments, { fileStoreStrategyFactory } from '/models/attachments';
|
||||
const filesize = require('filesize');
|
||||
|
||||
@@ -44,7 +45,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
getBoardsWithAttachments() {
|
||||
this.attachments = Attachments.find().get();
|
||||
this.attachments = ReactiveCache.getAttachments();
|
||||
this.attachmentsByBoardId = _.chain(this.attachments)
|
||||
.groupBy(fileObj => fileObj.meta.boardId)
|
||||
.value();
|
||||
@@ -61,14 +62,14 @@ BlazeComponent.extendComponent({
|
||||
return _version;
|
||||
});
|
||||
});
|
||||
const board = Boards.findOne(boardId);
|
||||
const board = ReactiveCache.getBoard(boardId);
|
||||
board.attachments = boardAttachments;
|
||||
return board;
|
||||
})
|
||||
return ret;
|
||||
},
|
||||
getBoardData(boardid) {
|
||||
const ret = Boards.findOne(boardId);
|
||||
const ret = ReactiveCache.getBoard(boardId);
|
||||
return ret;
|
||||
},
|
||||
events() {
|
||||
|
||||
@@ -41,7 +41,10 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
fileSize(size) {
|
||||
const ret = filesize(size);
|
||||
let ret = "";
|
||||
if (_.isNumber(size)) {
|
||||
ret = filesize(size);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
}).register('statistics');
|
||||
@@ -1,7 +1,9 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
Template.invitationCode.onRendered(function() {
|
||||
Meteor.subscribe('setting', {
|
||||
onReady() {
|
||||
const setting = Settings.findOne();
|
||||
const setting = ReactiveCache.getCurrentSetting();
|
||||
|
||||
if (!setting || !setting.disableRegistration) {
|
||||
$('#invitationcode').hide();
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
const orgsPerPage = 25;
|
||||
const teamsPerPage = 25;
|
||||
const usersPerPage = 25;
|
||||
@@ -143,27 +145,27 @@ BlazeComponent.extendComponent({
|
||||
this.loading.set(w);
|
||||
},
|
||||
orgList() {
|
||||
const orgs = Org.find(this.findOrgsOptions.get(), {
|
||||
const orgs = ReactiveCache.getOrgs(this.findOrgsOptions.get(), {
|
||||
sort: { orgDisplayName: 1 },
|
||||
fields: { _id: true },
|
||||
});
|
||||
this.numberOrgs.set(orgs.count(false));
|
||||
this.numberOrgs.set(orgs.length);
|
||||
return orgs;
|
||||
},
|
||||
teamList() {
|
||||
const teams = Team.find(this.findTeamsOptions.get(), {
|
||||
const teams = ReactiveCache.getTeams(this.findTeamsOptions.get(), {
|
||||
sort: { teamDisplayName: 1 },
|
||||
fields: { _id: true },
|
||||
});
|
||||
this.numberTeams.set(teams.count(false));
|
||||
this.numberTeams.set(teams.length);
|
||||
return teams;
|
||||
},
|
||||
peopleList() {
|
||||
const users = Users.find(this.findUsersOptions.get(), {
|
||||
const users = ReactiveCache.getUsers(this.findUsersOptions.get(), {
|
||||
sort: { username: 1 },
|
||||
fields: { _id: true },
|
||||
});
|
||||
this.numberPeople.set(users.count(false));
|
||||
this.numberPeople.set(users.length);
|
||||
return users;
|
||||
},
|
||||
orgNumber() {
|
||||
@@ -190,19 +192,19 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.orgRow.helpers({
|
||||
orgData() {
|
||||
return Org.findOne(this.orgId);
|
||||
return ReactiveCache.getOrg(this.orgId);
|
||||
},
|
||||
});
|
||||
|
||||
Template.teamRow.helpers({
|
||||
teamData() {
|
||||
return Team.findOne(this.teamId);
|
||||
return ReactiveCache.getTeam(this.teamId);
|
||||
},
|
||||
});
|
||||
|
||||
Template.peopleRow.helpers({
|
||||
userData() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -227,7 +229,7 @@ Template.editUserPopup.onCreated(function () {
|
||||
|
||||
Template.editOrgPopup.helpers({
|
||||
org() {
|
||||
return Org.findOne(this.orgId);
|
||||
return ReactiveCache.getOrg(this.orgId);
|
||||
},
|
||||
errorMessage() {
|
||||
return Template.instance().errorMessage.get();
|
||||
@@ -236,7 +238,7 @@ Template.editOrgPopup.helpers({
|
||||
|
||||
Template.editTeamPopup.helpers({
|
||||
team() {
|
||||
return Team.findOne(this.teamId);
|
||||
return ReactiveCache.getTeam(this.teamId);
|
||||
},
|
||||
errorMessage() {
|
||||
return Template.instance().errorMessage.get();
|
||||
@@ -245,25 +247,27 @@ Template.editTeamPopup.helpers({
|
||||
|
||||
Template.editUserPopup.helpers({
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
authentications() {
|
||||
return Template.instance().authenticationMethods.get();
|
||||
},
|
||||
orgsDatas() {
|
||||
return Org.find({}, {sort: { orgDisplayName: 1 }});
|
||||
const ret = ReactiveCache.getOrgs({}, {sort: { orgDisplayName: 1 }});
|
||||
return ret;
|
||||
},
|
||||
teamsDatas() {
|
||||
return Team.find({}, {sort: { teamDisplayName: 1 }});
|
||||
const ret = ReactiveCache.getTeams({}, {sort: { teamDisplayName: 1 }});
|
||||
return ret;
|
||||
},
|
||||
isSelected(match) {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
const selected = ReactiveCache.getUser(userId).authenticationMethod;
|
||||
return selected === match;
|
||||
},
|
||||
isLdap() {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
const selected = ReactiveCache.getUser(userId).authenticationMethod;
|
||||
return selected === 'ldap';
|
||||
},
|
||||
errorMessage() {
|
||||
@@ -300,7 +304,7 @@ Template.newUserPopup.onCreated(function () {
|
||||
|
||||
Template.newOrgPopup.helpers({
|
||||
org() {
|
||||
return Org.findOne(this.orgId);
|
||||
return ReactiveCache.getOrg(this.orgId);
|
||||
},
|
||||
errorMessage() {
|
||||
return Template.instance().errorMessage.get();
|
||||
@@ -309,7 +313,7 @@ Template.newOrgPopup.helpers({
|
||||
|
||||
Template.newTeamPopup.helpers({
|
||||
team() {
|
||||
return Team.findOne(this.teamId);
|
||||
return ReactiveCache.getTeam(this.teamId);
|
||||
},
|
||||
errorMessage() {
|
||||
return Template.instance().errorMessage.get();
|
||||
@@ -318,21 +322,23 @@ Template.newTeamPopup.helpers({
|
||||
|
||||
Template.newUserPopup.helpers({
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
authentications() {
|
||||
return Template.instance().authenticationMethods.get();
|
||||
},
|
||||
orgsDatas() {
|
||||
return Org.find({}, {sort: { orgDisplayName: 1 }});
|
||||
const ret = ReactiveCache.getOrgs({}, {sort: { orgDisplayName: 1 }});
|
||||
return ret;
|
||||
},
|
||||
teamsDatas() {
|
||||
return Team.find({}, {sort: { teamDisplayName: 1 }});
|
||||
const ret = ReactiveCache.getTeams({}, {sort: { teamDisplayName: 1 }});
|
||||
return ret;
|
||||
},
|
||||
isSelected(match) {
|
||||
const userId = Template.instance().data.userId;
|
||||
if(userId){
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
const selected = ReactiveCache.getUser(userId).authenticationMethod;
|
||||
return selected === match;
|
||||
}
|
||||
else{
|
||||
@@ -341,7 +347,7 @@ Template.newUserPopup.helpers({
|
||||
},
|
||||
isLdap() {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
const selected = ReactiveCache.getUser(userId).authenticationMethod;
|
||||
return selected === 'ldap';
|
||||
},
|
||||
errorMessage() {
|
||||
@@ -352,7 +358,7 @@ Template.newUserPopup.helpers({
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {},
|
||||
org() {
|
||||
return Org.findOne(this.orgId);
|
||||
return ReactiveCache.getOrg(this.orgId);
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
@@ -367,7 +373,7 @@ BlazeComponent.extendComponent({
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {},
|
||||
team() {
|
||||
return Team.findOne(this.teamId);
|
||||
return ReactiveCache.getTeam(this.teamId);
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
@@ -382,7 +388,7 @@ BlazeComponent.extendComponent({
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {},
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
@@ -417,7 +423,8 @@ BlazeComponent.extendComponent({
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {},
|
||||
teamsDatas() {
|
||||
return Team.find({}, {sort: { teamDisplayName: 1 }});
|
||||
const ret = ReactiveCache.getTeams({}, {sort: { teamDisplayName: 1 }});
|
||||
return ret;
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
@@ -440,7 +447,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
if(document.getElementById('addAction').checked){
|
||||
for(let i = 0; i < selectedUserChkBoxUserIds.length; i++){
|
||||
currentUser = Users.findOne(selectedUserChkBoxUserIds[i]);
|
||||
currentUser = ReactiveCache.getUser(selectedUserChkBoxUserIds[i]);
|
||||
userTms = currentUser.teams;
|
||||
if(userTms == undefined || userTms.length == 0){
|
||||
userTms = [];
|
||||
@@ -469,7 +476,7 @@ BlazeComponent.extendComponent({
|
||||
}
|
||||
else{
|
||||
for(let i = 0; i < selectedUserChkBoxUserIds.length; i++){
|
||||
currentUser = Users.findOne(selectedUserChkBoxUserIds[i]);
|
||||
currentUser = ReactiveCache.getUser(selectedUserChkBoxUserIds[i]);
|
||||
userTms = currentUser.teams;
|
||||
if(userTms !== undefined || userTms.length > 0)
|
||||
{
|
||||
@@ -562,7 +569,7 @@ BlazeComponent.extendComponent({
|
||||
Template.editOrgPopup.events({
|
||||
submit(event, templateInstance) {
|
||||
event.preventDefault();
|
||||
const org = Org.findOne(this.orgId);
|
||||
const org = ReactiveCache.getOrg(this.orgId);
|
||||
|
||||
const orgDisplayName = templateInstance
|
||||
.find('.js-orgDisplayName')
|
||||
@@ -603,7 +610,7 @@ Template.editOrgPopup.events({
|
||||
Template.editTeamPopup.events({
|
||||
submit(event, templateInstance) {
|
||||
event.preventDefault();
|
||||
const team = Team.findOne(this.teamId);
|
||||
const team = ReactiveCache.getTeam(this.teamId);
|
||||
|
||||
const teamDisplayName = templateInstance
|
||||
.find('.js-teamDisplayName')
|
||||
@@ -647,7 +654,7 @@ Template.editTeamPopup.events({
|
||||
Template.editUserPopup.events({
|
||||
submit(event, templateInstance) {
|
||||
event.preventDefault();
|
||||
const user = Users.findOne(this.userId);
|
||||
const user = ReactiveCache.getUser(this.userId);
|
||||
const username = templateInstance.find('.js-profile-username').value.trim();
|
||||
const fullname = templateInstance.find('.js-profile-fullname').value.trim();
|
||||
const initials = templateInstance.find('.js-profile-initials').value.trim();
|
||||
@@ -1071,7 +1078,7 @@ Template.newUserPopup.events({
|
||||
Template.settingsOrgPopup.events({
|
||||
'click #deleteButton'(event) {
|
||||
event.preventDefault();
|
||||
if(Users.find({"orgs.orgId": this.orgId}).count() > 0)
|
||||
if (ReactiveCache.getUsers({"orgs.orgId": this.orgId}).length > 0)
|
||||
{
|
||||
let orgClassList = document.getElementById("deleteOrgWarningMessage").classList;
|
||||
if(orgClassList.contains('hide'))
|
||||
@@ -1089,7 +1096,7 @@ Template.settingsOrgPopup.events({
|
||||
Template.settingsTeamPopup.events({
|
||||
'click #deleteButton'(event) {
|
||||
event.preventDefault();
|
||||
if(Users.find({"teams.teamId": this.teamId}).count() > 0)
|
||||
if (ReactiveCache.getUsers({"teams.teamId": this.teamId}).length > 0)
|
||||
{
|
||||
let teamClassList = document.getElementById("deleteTeamWarningMessage").classList;
|
||||
if(teamClassList.contains('hide'))
|
||||
@@ -1139,19 +1146,19 @@ Template.settingsUserPopup.events({
|
||||
|
||||
Template.settingsUserPopup.helpers({
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
authentications() {
|
||||
return Template.instance().authenticationMethods.get();
|
||||
},
|
||||
isSelected(match) {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
const selected = ReactiveCache.getUser(userId).authenticationMethod;
|
||||
return selected === match;
|
||||
},
|
||||
isLdap() {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
const selected = ReactiveCache.getUser(userId).authenticationMethod;
|
||||
return selected === 'ldap';
|
||||
},
|
||||
errorMessage() {
|
||||
|
||||
@@ -171,15 +171,15 @@ template(name='announcementSettings')
|
||||
ul#announcement-setting.setting-detail
|
||||
li
|
||||
a.flex.js-toggle-activemessage
|
||||
.materialCheckBox(class="{{#if currentSetting.enabled}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if currentAnnouncements.enabled}}is-checked{{/if}}")
|
||||
|
||||
span {{_ 'admin-announcement-active'}}
|
||||
li
|
||||
.admin-announcement(class="{{#if currentSetting.enabled}}{{else}}hide{{/if}}")
|
||||
.admin-announcement(class="{{#if currentAnnouncements.enabled}}{{else}}hide{{/if}}")
|
||||
ul
|
||||
li
|
||||
.title {{_ 'admin-announcement-title'}}
|
||||
textarea#admin-announcement.wekan-form-control= currentSetting.body
|
||||
textarea#admin-announcement.wekan-form-control= currentAnnouncements.body
|
||||
li
|
||||
button.js-announcement-save.primary {{_ 'save'}}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import { ALLOWED_WAIT_SPINNERS } from '/config/const';
|
||||
|
||||
@@ -42,12 +43,8 @@ BlazeComponent.extendComponent({
|
||||
}
|
||||
},
|
||||
|
||||
currentSetting() {
|
||||
return Settings.findOne();
|
||||
},
|
||||
|
||||
boards() {
|
||||
return Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
@@ -57,19 +54,20 @@ BlazeComponent.extendComponent({
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
toggleForgotPassword() {
|
||||
this.setLoading(true);
|
||||
const forgotPasswordClosed = this.currentSetting().disableForgotPassword;
|
||||
Settings.update(Settings.findOne()._id, {
|
||||
const forgotPasswordClosed = ReactiveCache.getCurrentSetting().disableForgotPassword;
|
||||
Settings.update(ReactiveCache.getCurrentSetting()._id, {
|
||||
$set: { disableForgotPassword: !forgotPasswordClosed },
|
||||
});
|
||||
this.setLoading(false);
|
||||
},
|
||||
toggleRegistration() {
|
||||
this.setLoading(true);
|
||||
const registrationClosed = this.currentSetting().disableRegistration;
|
||||
Settings.update(Settings.findOne()._id, {
|
||||
const registrationClosed = ReactiveCache.getCurrentSetting().disableRegistration;
|
||||
Settings.update(ReactiveCache.getCurrentSetting()._id, {
|
||||
$set: { disableRegistration: !registrationClosed },
|
||||
});
|
||||
this.setLoading(false);
|
||||
@@ -165,7 +163,7 @@ BlazeComponent.extendComponent({
|
||||
.trim();
|
||||
const from = this.checkField('#mail-server-from');
|
||||
const tls = $('#mail-server-tls.is-checked').length > 0;
|
||||
Settings.update(Settings.findOne()._id, {
|
||||
Settings.update(ReactiveCache.getCurrentSetting()._id, {
|
||||
$set: {
|
||||
'mailServer.host': host,
|
||||
'mailServer.port': port,
|
||||
@@ -245,7 +243,7 @@ BlazeComponent.extendComponent({
|
||||
const spinnerName = $('#spinnerName').val();
|
||||
|
||||
try {
|
||||
Settings.update(Settings.findOne()._id, {
|
||||
Settings.update(ReactiveCache.getCurrentSetting()._id, {
|
||||
$set: {
|
||||
productName,
|
||||
hideLogo: hideLogoChange,
|
||||
@@ -416,7 +414,7 @@ BlazeComponent.extendComponent({
|
||||
this.loading.set(w);
|
||||
},
|
||||
|
||||
currentSetting() {
|
||||
currentAnnouncements() {
|
||||
return Announcements.findOne();
|
||||
},
|
||||
|
||||
@@ -431,8 +429,9 @@ BlazeComponent.extendComponent({
|
||||
|
||||
toggleActive() {
|
||||
this.setLoading(true);
|
||||
const isActive = this.currentSetting().enabled;
|
||||
Announcements.update(Announcements.findOne()._id, {
|
||||
const announcements = this.currentAnnouncements();
|
||||
const isActive = announcements.enabled;
|
||||
Announcements.update(announcements._id, {
|
||||
$set: { enabled: !isActive },
|
||||
});
|
||||
this.setLoading(false);
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
box-shadow: -10px 0px 5px -10px #b3b3b3;
|
||||
z-index: 10;
|
||||
}
|
||||
.sidebar-xmark {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 5px;
|
||||
font-size: 25px;
|
||||
}
|
||||
.sidebar .sidebar-content {
|
||||
padding: 12px;
|
||||
margin-bottom: 1.6em;
|
||||
@@ -24,6 +30,7 @@
|
||||
left: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
width: 90%;
|
||||
}
|
||||
.sidebar .sidebar-content .hide-btn {
|
||||
display: none;
|
||||
|
||||
@@ -5,6 +5,7 @@ template(name="sidebar")
|
||||
// title="{{showTongueTitle}}")
|
||||
// i.fa.fa-navicon
|
||||
.sidebar-shadow
|
||||
a.sidebar-xmark.js-close-sidebar ✕
|
||||
.sidebar-content.js-board-sidebar-content
|
||||
//a.hide-btn.js-hide-sidebar
|
||||
// i.fa.fa-navicon
|
||||
@@ -12,7 +13,8 @@ template(name="sidebar")
|
||||
h2
|
||||
a.fa.fa-chevron-left.js-back-home
|
||||
= getViewTitle
|
||||
+Template.dynamic(template=getViewTemplate)
|
||||
if isOpen
|
||||
+Template.dynamic(template=getViewTemplate)
|
||||
|
||||
template(name='homeSidebar')
|
||||
hr
|
||||
@@ -137,6 +139,22 @@ template(name="boardChangeColorPopup")
|
||||
if isSelected
|
||||
i.fa.fa-check
|
||||
|
||||
template(name="boardChangeBackgroundImagePopup")
|
||||
form
|
||||
label
|
||||
| {{_ 'board-background-image-url'}}
|
||||
input.js-board-background-image-url(type="text" value="{{backgroundImageURL}}" autofocus)
|
||||
div.buttonsContainer
|
||||
input.primary.wide(type="submit" value="{{_ 'save'}}")
|
||||
br
|
||||
br
|
||||
br
|
||||
br
|
||||
br
|
||||
hr
|
||||
div
|
||||
button.js-remove-background-image.negate.wide.card-details-red.right {{_ 'unset-color'}}
|
||||
|
||||
template(name="boardInfoOnMyBoardsPopup")
|
||||
form.board-info-on-my-boards
|
||||
h3 {{_ 'show-at-all-boards-page'}}
|
||||
@@ -293,6 +311,25 @@ template(name="boardMinicardSettingsPopup")
|
||||
span
|
||||
i.fa.fa-align-left
|
||||
| {{_ 'description-on-minicard'}}
|
||||
div.check-div
|
||||
a.flex.js-field-has-cover-attachment-on-minicard(class="{{#if allowsCoverAttachmentOnMinicard}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if allowsCoverAttachmentOnMinicard}}is-checked{{/if}}")
|
||||
span
|
||||
i.fa.fa-book
|
||||
i.fa.fa-picture-o
|
||||
| {{_ 'cover-attachment-on-minicard'}}
|
||||
div.check-div
|
||||
a.flex.js-field-has-badge-attachment-on-minicard(class="{{#if allowsBadgeAttachmentOnMinicard}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if allowsBadgeAttachmentOnMinicard}}is-checked{{/if}}")
|
||||
span
|
||||
i.fa.fa-paperclip
|
||||
| {{_ 'badge-attachment-on-minicard'}}
|
||||
div.check-div
|
||||
a.flex.js-field-has-card-sorting-by-number-on-minicard(class="{{#if allowsCardSortingByNumberOnMinicard}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if allowsCardSortingByNumberOnMinicard}}is-checked{{/if}}")
|
||||
span
|
||||
i.fa.fa-sort
|
||||
| {{_ 'card-sorting-by-number-on-minicard'}}
|
||||
|
||||
template(name="boardSubtaskSettingsPopup")
|
||||
form.board-subtask-settings
|
||||
@@ -408,13 +445,18 @@ template(name="boardMenuPopup")
|
||||
a.js-change-board-color
|
||||
i.fa.fa-paint-brush
|
||||
| {{_ 'board-change-color'}}
|
||||
if currentUser.isBoardAdmin
|
||||
unless currentSetting.hideBoardMemberList
|
||||
unless currentSetting.hideCardCounterList
|
||||
li
|
||||
a.js-board-info-on-my-boards(title="{{_ 'board-info-on-my-boards'}}")
|
||||
i.fa.fa-id-card-o
|
||||
| {{_ 'board-info-on-my-boards'}}
|
||||
li
|
||||
a.js-change-background-image
|
||||
i.fa.fa-picture-o
|
||||
| {{_ 'board-change-background-image'}}
|
||||
//Bug Board icons random dance https://github.com/wekan/wekan/issues/4214
|
||||
//if currentUser.isBoardAdmin
|
||||
// unless currentSetting.hideBoardMemberList
|
||||
// unless currentSetting.hideCardCounterList
|
||||
// li
|
||||
// a.js-board-info-on-my-boards(title="{{_ 'board-info-on-my-boards'}}")
|
||||
// i.fa.fa-id-card-o
|
||||
// | {{_ 'board-info-on-my-boards'}}
|
||||
hr
|
||||
ul.pop-over-list
|
||||
if withApi
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
Sidebar = null;
|
||||
@@ -111,7 +112,7 @@ BlazeComponent.extendComponent({
|
||||
'click .js-toggle-sidebar': this.toggle,
|
||||
'click .js-back-home': this.setView,
|
||||
'click .js-toggle-minicard-label-text'() {
|
||||
currentUser = Meteor.user();
|
||||
currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
Meteor.call('toggleMinicardLabelText');
|
||||
} else if (window.localStorage.getItem('hiddenMinicardLabelText')) {
|
||||
@@ -125,6 +126,9 @@ BlazeComponent.extendComponent({
|
||||
'click .js-shortcuts'() {
|
||||
FlowRouter.go('shortcuts');
|
||||
},
|
||||
'click .js-close-sidebar'() {
|
||||
Sidebar.toggle()
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
@@ -134,7 +138,7 @@ Blaze.registerHelper('Sidebar', () => Sidebar);
|
||||
|
||||
Template.homeSidebar.helpers({
|
||||
hiddenMinicardLabelText() {
|
||||
currentUser = Meteor.user();
|
||||
currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).hiddenMinicardLabelText;
|
||||
} else if (window.localStorage.getItem('hiddenMinicardLabelText')) {
|
||||
@@ -146,16 +150,13 @@ Template.homeSidebar.helpers({
|
||||
});
|
||||
|
||||
Template.boardInfoOnMyBoardsPopup.helpers({
|
||||
currentSetting() {
|
||||
return Settings.findOne();
|
||||
},
|
||||
hideCardCounterList() {
|
||||
return Utils.isMiniScreen() && Session.get('currentBoard');
|
||||
},
|
||||
hideBoardMemberList() {
|
||||
return Utils.isMiniScreen() && Session.get('currentBoard');
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
EscapeActions.register(
|
||||
'sidebarView',
|
||||
@@ -169,15 +170,15 @@ EscapeActions.register(
|
||||
|
||||
Template.memberPopup.helpers({
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
memberType() {
|
||||
const type = Users.findOne(this.userId).isBoardAdmin() ? 'admin' : 'normal';
|
||||
const type = ReactiveCache.getUser(this.userId).isBoardAdmin() ? 'admin' : 'normal';
|
||||
if (type === 'normal') {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const commentOnly = currentBoard.hasCommentOnly(this.userId);
|
||||
const noComments = currentBoard.hasNoComments(this.userId);
|
||||
const worker = currentBoard.hasWorker(this.userId);
|
||||
@@ -195,7 +196,7 @@ Template.memberPopup.helpers({
|
||||
}
|
||||
},
|
||||
isInvited() {
|
||||
return Users.findOne(this.userId).isInvitedTo(Session.get('currentBoard'));
|
||||
return ReactiveCache.getUser(this.userId).isInvitedTo(Session.get('currentBoard'));
|
||||
},
|
||||
});
|
||||
|
||||
@@ -215,17 +216,18 @@ Template.boardMenuPopup.events({
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-change-board-color': Popup.open('boardChangeColor'),
|
||||
'click .js-change-background-image': Popup.open('boardChangeBackgroundImage'),
|
||||
'click .js-board-info-on-my-boards': Popup.open('boardInfoOnMyBoards'),
|
||||
'click .js-change-language': Popup.open('changeLanguage'),
|
||||
'click .js-archive-board ': Popup.afterConfirm('archiveBoard', function() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
currentBoard.archive();
|
||||
// XXX We should have some kind of notification on top of the page to
|
||||
// confirm that the board was successfully archived.
|
||||
FlowRouter.go('home');
|
||||
}),
|
||||
'click .js-delete-board': Popup.afterConfirm('deleteBoard', function() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
Popup.back();
|
||||
Boards.remove(currentBoard._id);
|
||||
FlowRouter.go('home');
|
||||
@@ -247,7 +249,7 @@ Template.boardMenuPopup.onCreated(function() {
|
||||
|
||||
Template.boardMenuPopup.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
withApi() {
|
||||
return Template.instance().apiEnabled.get();
|
||||
@@ -277,13 +279,13 @@ Template.memberPopup.events({
|
||||
// This works from removing member from board, card members and assignees.
|
||||
const boardId = Session.get('currentBoard');
|
||||
const memberId = this.userId;
|
||||
Cards.find({ boardId, members: memberId }).forEach(card => {
|
||||
ReactiveCache.getCards({ boardId, members: memberId }).forEach(card => {
|
||||
card.unassignMember(memberId);
|
||||
});
|
||||
Cards.find({ boardId, assignees: memberId }).forEach(card => {
|
||||
ReactiveCache.getCards({ boardId, assignees: memberId }).forEach(card => {
|
||||
card.unassignAssignee(memberId);
|
||||
});
|
||||
Boards.findOne(boardId).removeMember(memberId);
|
||||
ReactiveCache.getBoard(boardId).removeMember(memberId);
|
||||
Popup.back();
|
||||
}),
|
||||
'click .js-leave-member': Popup.afterConfirm('leaveBoard', () => {
|
||||
@@ -297,16 +299,16 @@ Template.memberPopup.events({
|
||||
|
||||
Template.removeMemberPopup.helpers({
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
board() {
|
||||
return Boards.findOne(Session.get('currentBoard'));
|
||||
return Utils.getCurrentBoard();
|
||||
},
|
||||
});
|
||||
|
||||
Template.leaveBoardPopup.helpers({
|
||||
board() {
|
||||
return Boards.findOne(Session.get('currentBoard'));
|
||||
return Utils.getCurrentBoard();
|
||||
},
|
||||
});
|
||||
BlazeComponent.extendComponent({
|
||||
@@ -356,11 +358,11 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.membersWidget.helpers({
|
||||
isInvited() {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
return user && user.isInvitedTo(Session.get('currentBoard'));
|
||||
},
|
||||
isWorker() {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
if (user) {
|
||||
return Meteor.call(Boards.hasWorker(user.memberId));
|
||||
} else {
|
||||
@@ -368,22 +370,22 @@ Template.membersWidget.helpers({
|
||||
}
|
||||
},
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
AtLeastOneOrgWasCreated(){
|
||||
let orgs = Org.find({}, {sort: { createdAt: -1 }});
|
||||
let orgs = ReactiveCache.getOrgs({}, {sort: { createdAt: -1 }});
|
||||
if(orgs === undefined)
|
||||
return false;
|
||||
|
||||
return orgs.count() > 0;
|
||||
return orgs.length > 0;
|
||||
},
|
||||
|
||||
AtLeastOneTeamWasCreated(){
|
||||
let teams = Team.find({}, {sort: { createdAt: -1 }});
|
||||
let teams = ReactiveCache.getTeams({}, {sort: { createdAt: -1 }});
|
||||
if(teams === undefined)
|
||||
return false;
|
||||
|
||||
return teams.count() > 0;
|
||||
return teams.length > 0;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -404,13 +406,13 @@ Template.membersWidget.events({
|
||||
},
|
||||
'click .js-member-invite-accept'() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
Meteor.user().removeInvite(boardId);
|
||||
ReactiveCache.getCurrentUser().removeInvite(boardId);
|
||||
},
|
||||
'click .js-member-invite-decline'() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
Meteor.call('quitBoard', boardId, (err, ret) => {
|
||||
if (!err && ret) {
|
||||
Meteor.user().removeInvite(boardId);
|
||||
ReactiveCache.getCurrentUser().removeInvite(boardId);
|
||||
FlowRouter.go('home');
|
||||
}
|
||||
});
|
||||
@@ -423,7 +425,8 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
integrations() {
|
||||
const boardId = this.boardId();
|
||||
return Integrations.find({ boardId: `${boardId}` }).fetch();
|
||||
const ret = ReactiveCache.getIntegrations({ boardId });
|
||||
return ret;
|
||||
},
|
||||
types() {
|
||||
return Integrations.Const.WEBHOOK_TYPES;
|
||||
@@ -434,7 +437,7 @@ BlazeComponent.extendComponent({
|
||||
for (const k in condition) {
|
||||
if (!condition[k]) delete condition[k];
|
||||
}
|
||||
return Integrations.findOne(condition);
|
||||
return ReactiveCache.getIntegration(condition);
|
||||
},
|
||||
onCreated() {
|
||||
this.disabled = new ReactiveVar(false);
|
||||
@@ -602,7 +605,7 @@ Template.labelsWidget.events({
|
||||
|
||||
Template.labelsWidget.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -616,7 +619,7 @@ function draggableMembersLabelsWidgets() {
|
||||
const currentBoardId = Tracker.nonreactive(() => {
|
||||
return Session.get('currentBoard');
|
||||
});
|
||||
Boards.findOne(currentBoardId, {
|
||||
ReactiveCache.getBoard(currentBoardId, {
|
||||
fields: {
|
||||
members: 1,
|
||||
labels: 1,
|
||||
@@ -637,7 +640,7 @@ function draggableMembersLabelsWidgets() {
|
||||
});
|
||||
|
||||
function userIsMember() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember();
|
||||
return ReactiveCache.getCurrentUser()?.isBoardMember();
|
||||
}
|
||||
|
||||
this.autorun(() => {
|
||||
@@ -656,7 +659,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
isSelected() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return currentBoard.color === this.currentData().toString();
|
||||
},
|
||||
|
||||
@@ -664,7 +667,7 @@ BlazeComponent.extendComponent({
|
||||
return [
|
||||
{
|
||||
'click .js-select-background'(evt) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const newColor = this.currentData().toString();
|
||||
currentBoard.setColor(newColor);
|
||||
evt.preventDefault();
|
||||
@@ -674,9 +677,40 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
}).register('boardChangeColorPopup');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
submit(event) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const backgroundImageURL = this.find('.js-board-background-image-url').value.trim();
|
||||
currentBoard.setBackgroundImageURL(backgroundImageURL);
|
||||
Utils.setBackgroundImage();
|
||||
Popup.back();
|
||||
event.preventDefault();
|
||||
},
|
||||
'click .js-remove-background-image'() {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
currentBoard.setBackgroundImageURL("");
|
||||
Popup.back();
|
||||
Utils.reload();
|
||||
event.preventDefault();
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('boardChangeBackgroundImagePopup');
|
||||
|
||||
Template.boardChangeBackgroundImagePopup.helpers({
|
||||
backgroundImageURL() {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return currentBoard.backgroundImageURL;
|
||||
},
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
this.currentBoard = Utils.getCurrentBoard();
|
||||
},
|
||||
|
||||
allowsCardCounterList() {
|
||||
@@ -729,7 +763,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
this.currentBoard = Utils.getCurrentBoard();
|
||||
},
|
||||
|
||||
allowsSubtasks() {
|
||||
@@ -752,7 +786,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
boards() {
|
||||
return Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
@@ -761,10 +795,11 @@ BlazeComponent.extendComponent({
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
|
||||
lists() {
|
||||
return Lists.find(
|
||||
return ReactiveCache.getLists(
|
||||
{
|
||||
boardId: this.currentBoard._id,
|
||||
archived: false,
|
||||
@@ -776,7 +811,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
hasLists() {
|
||||
return this.lists().count() > 0;
|
||||
return this.lists().length > 0;
|
||||
},
|
||||
|
||||
isListSelected() {
|
||||
@@ -855,7 +890,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
this.currentBoard = Utils.getCurrentBoard();
|
||||
},
|
||||
|
||||
allowsReceivedDate() {
|
||||
@@ -950,7 +985,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
boards() {
|
||||
return Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
@@ -959,10 +994,11 @@ BlazeComponent.extendComponent({
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
|
||||
lists() {
|
||||
return Lists.find(
|
||||
return ReactiveCache.getLists(
|
||||
{
|
||||
boardId: this.currentBoard._id,
|
||||
archived: false,
|
||||
@@ -974,7 +1010,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
hasLists() {
|
||||
return this.lists().count() > 0;
|
||||
return this.lists().length > 0;
|
||||
},
|
||||
|
||||
isListSelected() {
|
||||
@@ -1290,15 +1326,27 @@ BlazeComponent.extendComponent({
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
this.currentBoard = Utils.getCurrentBoard();
|
||||
},
|
||||
|
||||
allowsDescriptionTextOnMinicard() {
|
||||
return this.currentBoard.allowsDescriptionTextOnMinicard;
|
||||
},
|
||||
|
||||
allowsCoverAttachmentOnMinicard() {
|
||||
return this.currentBoard.allowsCoverAttachmentOnMinicard;
|
||||
},
|
||||
|
||||
allowsBadgeAttachmentOnMinicard() {
|
||||
return this.currentBoard.allowsBadgeAttachmentOnMinicard;
|
||||
},
|
||||
|
||||
allowsCardSortingByNumberOnMinicard() {
|
||||
return this.currentBoard.allowsCardSortingByNumberOnMinicard;
|
||||
},
|
||||
|
||||
lists() {
|
||||
return Lists.find(
|
||||
return ReactiveCache.getLists(
|
||||
{
|
||||
boardId: this.currentBoard._id,
|
||||
archived: false,
|
||||
@@ -1310,7 +1358,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
hasLists() {
|
||||
return this.lists().count() > 0;
|
||||
return this.lists().length > 0;
|
||||
},
|
||||
|
||||
isListSelected() {
|
||||
@@ -1338,6 +1386,54 @@ BlazeComponent.extendComponent({
|
||||
this.currentBoard.allowsDescriptionTextOnMinicard,
|
||||
);
|
||||
},
|
||||
'click .js-field-has-cover-attachment-on-minicard'(evt) {
|
||||
evt.preventDefault();
|
||||
this.currentBoard.allowsCoverAttachmentOnMinicard = !this.currentBoard
|
||||
.allowsCoverAttachmentOnMinicard;
|
||||
this.currentBoard.setallowsCoverAttachmentOnMinicard(
|
||||
this.currentBoard.allowsCoverAttachmentOnMinicard,
|
||||
);
|
||||
$(`.js-field-has-cover-attachment-on-minicard ${MCB}`).toggleClass(
|
||||
CKCLS,
|
||||
this.currentBoard.allowsCoverAttachmentOnMinicard,
|
||||
);
|
||||
$('.js-field-has-cover-attachment-on-minicard').toggleClass(
|
||||
CKCLS,
|
||||
this.currentBoard.allowsCoverAttachmentOnMinicard,
|
||||
);
|
||||
},
|
||||
'click .js-field-has-badge-attachment-on-minicard'(evt) {
|
||||
evt.preventDefault();
|
||||
this.currentBoard.allowsBadgeAttachmentOnMinicard = !this.currentBoard
|
||||
.allowsBadgeAttachmentOnMinicard;
|
||||
this.currentBoard.setallowsBadgeAttachmentOnMinicard(
|
||||
this.currentBoard.allowsBadgeAttachmentOnMinicard,
|
||||
);
|
||||
$(`.js-field-has-badge-attachment-on-minicard ${MCB}`).toggleClass(
|
||||
CKCLS,
|
||||
this.currentBoard.allowsBadgeAttachmentOnMinicard,
|
||||
);
|
||||
$('.js-field-has-badge-attachment-on-minicard').toggleClass(
|
||||
CKCLS,
|
||||
this.currentBoard.allowsBadgeAttachmentOnMinicard,
|
||||
);
|
||||
},
|
||||
'click .js-field-has-card-sorting-by-number-on-minicard'(evt) {
|
||||
evt.preventDefault();
|
||||
this.currentBoard.allowsCardSortingByNumberOnMinicard = !this.currentBoard
|
||||
.allowsCardSortingByNumberOnMinicard;
|
||||
this.currentBoard.setallowsCardSortingByNumberOnMinicard(
|
||||
this.currentBoard.allowsCardSortingByNumberOnMinicard,
|
||||
);
|
||||
$(`.js-field-has-card-sorting-by-number-on-minicard ${MCB}`).toggleClass(
|
||||
CKCLS,
|
||||
this.currentBoard.allowsCardSortingByNumberOnMinicard,
|
||||
);
|
||||
$('.js-field-has-card-sorting-by-number-on-minicard').toggleClass(
|
||||
CKCLS,
|
||||
this.currentBoard.allowsCardSortingByNumberOnMinicard,
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
@@ -1356,7 +1452,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
isBoardMember() {
|
||||
const userId = this.currentData().__originalId;
|
||||
const user = Users.findOne(userId);
|
||||
const user = ReactiveCache.getUser(userId);
|
||||
return user && user.isBoardMember();
|
||||
},
|
||||
|
||||
@@ -1396,7 +1492,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
'click .js-select-member'() {
|
||||
const userId = this.currentData().__originalId;
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
if (!currentBoard.hasMember(userId)) {
|
||||
this.inviteUser(userId);
|
||||
}
|
||||
@@ -1452,7 +1548,7 @@ BlazeComponent.extendComponent({
|
||||
this.setError('');
|
||||
},
|
||||
'change #jsBoardOrgs'() {
|
||||
let currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
let currentBoard = Utils.getCurrentBoard();
|
||||
let selectElt = document.getElementById("jsBoardOrgs");
|
||||
let selectedOrgId = selectElt.options[selectElt.selectedIndex].value;
|
||||
let selectedOrgDisplayName = selectElt.options[selectElt.selectedIndex].text;
|
||||
@@ -1484,8 +1580,8 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.addBoardOrgPopup.helpers({
|
||||
orgsDatas() {
|
||||
let orgs = Org.find({}, {sort: { orgDisplayName: 1 }});
|
||||
return orgs;
|
||||
let ret = ReactiveCache.getOrgs({}, {sort: { orgDisplayName: 1 }});
|
||||
return ret;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1526,7 +1622,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
'click #leaveBoardBtn'(){
|
||||
let stringOrgId = document.getElementById('hideOrgId').value;
|
||||
let currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
let currentBoard = Utils.getCurrentBoard();
|
||||
let boardOrganizations = [];
|
||||
if(currentBoard.orgs !== undefined){
|
||||
for(let i = 0; i < currentBoard.orgs.length; i++){
|
||||
@@ -1550,7 +1646,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.removeBoardOrgPopup.helpers({
|
||||
org() {
|
||||
return Org.findOne(this.orgId);
|
||||
return ReactiveCache.getOrg(this.orgId);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1597,7 +1693,7 @@ BlazeComponent.extendComponent({
|
||||
this.setError('');
|
||||
},
|
||||
'change #jsBoardTeams'() {
|
||||
let currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
let currentBoard = Utils.getCurrentBoard();
|
||||
let selectElt = document.getElementById("jsBoardTeams");
|
||||
let selectedTeamId = selectElt.options[selectElt.selectedIndex].value;
|
||||
let selectedTeamDisplayName = selectElt.options[selectElt.selectedIndex].text;
|
||||
@@ -1622,13 +1718,13 @@ BlazeComponent.extendComponent({
|
||||
"teams.teamId": { $in: boardTeams.map(t => t.teamId) },
|
||||
};
|
||||
|
||||
const boardTeamUsers = Users.find(query, {
|
||||
const boardTeamUsers = ReactiveCache.getUsers(query, {
|
||||
sort: { sort: 1 },
|
||||
});
|
||||
|
||||
if(boardTeams !== undefined && boardTeams.length > 0){
|
||||
let index;
|
||||
if(boardTeamUsers && boardTeamUsers.count() > 0){
|
||||
if (boardTeamUsers && boardTeamUsers.length > 0) {
|
||||
boardTeamUsers.forEach((u) => {
|
||||
index = members.findIndex(function(m){ return m.userId == u._id});
|
||||
if(index == -1){
|
||||
@@ -1657,8 +1753,8 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.addBoardTeamPopup.helpers({
|
||||
teamsDatas() {
|
||||
let teams = Team.find({}, {sort: { teamDisplayName: 1 }});
|
||||
return teams;
|
||||
let ret = ReactiveCache.getTeams({}, {sort: { teamDisplayName: 1 }});
|
||||
return ret;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1706,7 +1802,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
'click #leaveBoardTeamBtn'(){
|
||||
let stringTeamId = document.getElementById('hideTeamId').value;
|
||||
let currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
let currentBoard = Utils.getCurrentBoard();
|
||||
let boardTeams = [];
|
||||
if(currentBoard.teams !== undefined){
|
||||
for(let i = 0; i < currentBoard.teams.length; i++){
|
||||
@@ -1721,13 +1817,13 @@ BlazeComponent.extendComponent({
|
||||
"teams.teamId": stringTeamId
|
||||
};
|
||||
|
||||
const boardTeamUsers = Users.find(query, {
|
||||
const boardTeamUsers = ReactiveCache.getUsers(query, {
|
||||
sort: { sort: 1 },
|
||||
});
|
||||
|
||||
if(currentBoard.teams !== undefined && currentBoard.teams.length > 0){
|
||||
let index;
|
||||
if(boardTeamUsers && boardTeamUsers.count() > 0){
|
||||
if (boardTeamUsers && boardTeamUsers.length > 0) {
|
||||
boardTeamUsers.forEach((u) => {
|
||||
index = members.findIndex(function(m){ return m.userId == u._id});
|
||||
if(index !== -1 && (u.isAdmin === undefined || u.isAdmin == false)){
|
||||
@@ -1751,7 +1847,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.removeBoardTeamPopup.helpers({
|
||||
team() {
|
||||
return Team.findOne(this.teamId);
|
||||
return ReactiveCache.getTeam(this.teamId);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1759,7 +1855,7 @@ Template.changePermissionsPopup.events({
|
||||
'click .js-set-admin, click .js-set-normal, click .js-set-no-comments, click .js-set-comment-only, click .js-set-worker'(
|
||||
event,
|
||||
) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const memberId = this.userId;
|
||||
const isAdmin = $(event.currentTarget).hasClass('js-set-admin');
|
||||
const isCommentOnly = $(event.currentTarget).hasClass(
|
||||
@@ -1780,12 +1876,12 @@ Template.changePermissionsPopup.events({
|
||||
|
||||
Template.changePermissionsPopup.helpers({
|
||||
isAdmin() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return currentBoard.hasAdmin(this.userId);
|
||||
},
|
||||
|
||||
isNormal() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return (
|
||||
!currentBoard.hasAdmin(this.userId) &&
|
||||
!currentBoard.hasNoComments(this.userId) &&
|
||||
@@ -1795,7 +1891,7 @@ Template.changePermissionsPopup.helpers({
|
||||
},
|
||||
|
||||
isNoComments() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return (
|
||||
!currentBoard.hasAdmin(this.userId) &&
|
||||
currentBoard.hasNoComments(this.userId)
|
||||
@@ -1803,7 +1899,7 @@ Template.changePermissionsPopup.helpers({
|
||||
},
|
||||
|
||||
isCommentOnly() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return (
|
||||
!currentBoard.hasAdmin(this.userId) &&
|
||||
currentBoard.hasCommentOnly(this.userId)
|
||||
@@ -1811,14 +1907,14 @@ Template.changePermissionsPopup.helpers({
|
||||
},
|
||||
|
||||
isWorker() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return (
|
||||
!currentBoard.hasAdmin(this.userId) && currentBoard.hasWorker(this.userId)
|
||||
);
|
||||
},
|
||||
|
||||
isLastAdmin() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return (
|
||||
currentBoard.hasAdmin(this.userId) && currentBoard.activeAdmins() === 1
|
||||
);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
//archivedRequested = false;
|
||||
@@ -33,7 +34,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
archivedCards() {
|
||||
return Cards.find(
|
||||
const ret = ReactiveCache.getCards(
|
||||
{
|
||||
archived: true,
|
||||
boardId: Session.get('currentBoard'),
|
||||
@@ -42,10 +43,11 @@ BlazeComponent.extendComponent({
|
||||
sort: { archivedAt: -1, modifiedAt: -1 },
|
||||
},
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
|
||||
archivedLists() {
|
||||
return Lists.find(
|
||||
return ReactiveCache.getLists(
|
||||
{
|
||||
archived: true,
|
||||
boardId: Session.get('currentBoard'),
|
||||
@@ -57,7 +59,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
archivedSwimlanes() {
|
||||
return Swimlanes.find(
|
||||
return ReactiveCache.getSwimlanes(
|
||||
{
|
||||
archived: true,
|
||||
boardId: Session.get('currentBoard'),
|
||||
@@ -159,10 +161,10 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.archivesSidebar.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
isWorker() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return (
|
||||
!currentBoard.hasAdmin(this.userId) && currentBoard.hasWorker(this.userId)
|
||||
);
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
customFields() {
|
||||
return CustomFields.find({
|
||||
const ret = ReactiveCache.getCustomFields({
|
||||
boardIds: { $in: [Session.get('currentBoard')] },
|
||||
});
|
||||
return ret;
|
||||
},
|
||||
|
||||
events() {
|
||||
@@ -275,7 +277,7 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({
|
||||
'click .js-delete-custom-field': Popup.afterConfirm(
|
||||
'deleteCustomField',
|
||||
function() {
|
||||
const customField = CustomFields.findOne(this._id);
|
||||
const customField = ReactiveCache.getCustomField(this._id);
|
||||
if (customField.boardIds.length > 1) {
|
||||
CustomFields.update(customField._id, {
|
||||
$pull: {
|
||||
|
||||
@@ -109,13 +109,18 @@ template(name="filterSidebar")
|
||||
| {{_ 'filter-due-tomorrow' }}
|
||||
if Filter.dueAt.isSelected 'tomorrow'
|
||||
i.fa.fa-check
|
||||
li(class="{{#if Filter.dueAt.isSelected 'week'}}active{{/if}}")
|
||||
li(class="{{#if Filter.dueAt.isSelected 'thisweek'}}active{{/if}}")
|
||||
a.name.js-toggle-due-this-week-filter
|
||||
span.sidebar-list-item-description
|
||||
| {{_ 'filter-due-this-week' }}
|
||||
if Filter.dueAt.isSelected 'week'
|
||||
if Filter.dueAt.isSelected 'thisweek'
|
||||
i.fa.fa-check
|
||||
li(class="{{#if Filter.dueAt.isSelected 'nextweek'}}active{{/if}}")
|
||||
a.name.js-toggle-due-next-week-filter
|
||||
span.sidebar-list-item-description
|
||||
| {{_ 'filter-due-next-week' }}
|
||||
if Filter.dueAt.isSelected 'nextweek'
|
||||
i.fa.fa-check
|
||||
|
||||
hr
|
||||
h3
|
||||
i.fa.fa-list-alt
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
const subManager = new SubsManager();
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
@@ -53,6 +55,11 @@ BlazeComponent.extendComponent({
|
||||
Filter.dueAt.thisWeek();
|
||||
Filter.resetExceptions();
|
||||
},
|
||||
'click .js-toggle-due-next-week-filter'(evt) {
|
||||
evt.preventDefault();
|
||||
Filter.dueAt.nextWeek();
|
||||
Filter.resetExceptions();
|
||||
},
|
||||
'click .js-toggle-archive-filter'(evt) {
|
||||
evt.preventDefault();
|
||||
Filter.archive.toggle(this.currentData()._id);
|
||||
@@ -88,7 +95,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
'click .js-filter-to-selection'(evt) {
|
||||
evt.preventDefault();
|
||||
const selectedCards = Cards.find(Filter.mongoSelector()).map(c => {
|
||||
const selectedCards = ReactiveCache.getCards(Filter.mongoSelector()).map(c => {
|
||||
return c._id;
|
||||
});
|
||||
MultiSelection.add(selectedCards);
|
||||
@@ -99,14 +106,14 @@ BlazeComponent.extendComponent({
|
||||
}).register('filterSidebar');
|
||||
|
||||
function mutateSelectedCards(mutationName, ...args) {
|
||||
Cards.find(MultiSelection.getMongoSelector(), {sort: ['sort']}).forEach(card => {
|
||||
ReactiveCache.getCards(MultiSelection.getMongoSelector(), {sort: ['sort']}).forEach(card => {
|
||||
card[mutationName](...args);
|
||||
});
|
||||
}
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
mapSelection(kind, _id) {
|
||||
return Cards.find(MultiSelection.getMongoSelector(), {sort: ['sort']}).map(card => {
|
||||
return ReactiveCache.getCards(MultiSelection.getMongoSelector(), {sort: ['sort']}).map(card => {
|
||||
const methodName = kind === 'label' ? 'hasLabel' : 'isAssigned';
|
||||
return card[methodName](_id);
|
||||
});
|
||||
@@ -166,10 +173,10 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.multiselectionSidebar.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
isCommentOnly() {
|
||||
return Meteor.user().isCommentOnly();
|
||||
return ReactiveCache.getCurrentUser().isCommentOnly();
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -4,12 +4,12 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
cards() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return currentBoard.searchCards(this.term.get());
|
||||
},
|
||||
|
||||
lists() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return currentBoard.searchLists(this.term.get());
|
||||
},
|
||||
|
||||
|
||||
@@ -41,15 +41,24 @@ template(name="editSwimlaneTitleForm")
|
||||
template(name="swimlaneActionPopup")
|
||||
unless currentUser.isCommentOnly
|
||||
ul.pop-over-list
|
||||
li: a.js-set-swimlane-color {{_ 'select-color'}}
|
||||
li: a.js-set-swimlane-color
|
||||
i.fa.fa-paint-brush
|
||||
| {{_ 'select-color'}}
|
||||
unless this.isTemplateContainer
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li: a.js-close-swimlane {{_ 'archive-swimlane'}}
|
||||
li: a.js-close-swimlane
|
||||
i.fa.fa-arrow-right
|
||||
i.fa.fa-archive
|
||||
| {{_ 'archive-swimlane'}}
|
||||
ul.pop-over-list
|
||||
li: a.js-copy-swimlane {{_ 'copy-swimlane'}}
|
||||
li: a.js-copy-swimlane
|
||||
i.fa.fa-copy
|
||||
| {{_ 'copy-swimlane'}}
|
||||
ul.pop-over-list
|
||||
li: a.js-move-swimlane {{_ 'move-swimlane'}}
|
||||
li: a.js-move-swimlane
|
||||
i.fa.fa-arrow-up
|
||||
| {{_ 'move-swimlane'}}
|
||||
|
||||
template(name="swimlaneAddPopup")
|
||||
unless currentUser.isCommentOnly
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
const { calculateIndexData } = Utils;
|
||||
|
||||
let swimlaneColors;
|
||||
@@ -30,7 +31,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.swimlaneFixedHeader.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -47,7 +48,7 @@ Template.swimlaneActionPopup.events({
|
||||
|
||||
Template.swimlaneActionPopup.events({
|
||||
isCommentOnly() {
|
||||
return Meteor.user().isCommentOnly();
|
||||
return ReactiveCache.getCurrentUser().isCommentOnly();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -61,7 +62,7 @@ BlazeComponent.extendComponent({
|
||||
{
|
||||
submit(event) {
|
||||
event.preventDefault();
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const nextSwimlane = currentBoard.nextSwimlane(this.currentSwimlane);
|
||||
const titleInput = this.find('.swimlane-name-input');
|
||||
const title = titleInput.value.trim();
|
||||
|
||||
@@ -7,20 +7,20 @@ template(name="swimlane")
|
||||
if currentListIsInThisSwimlane _id
|
||||
+list(currentList)
|
||||
unless currentList
|
||||
each lists
|
||||
+miniList(this)
|
||||
if currentUser.isBoardMember
|
||||
unless currentUser.isCommentOnly
|
||||
+addListForm
|
||||
each lists
|
||||
+miniList(this)
|
||||
else
|
||||
if currentUser.isBoardMember
|
||||
unless currentUser.isCommentOnly
|
||||
+addListForm
|
||||
each lists
|
||||
if visible this
|
||||
+list(this)
|
||||
if currentCardIsInThisList _id ../_id
|
||||
+cardDetails(currentCard)
|
||||
if currentUser.isBoardMember
|
||||
unless currentUser.isCommentOnly
|
||||
+addListForm
|
||||
|
||||
template(name="listsGroup")
|
||||
.swimlane.list-group.js-lists
|
||||
@@ -51,6 +51,11 @@ template(name="addListForm")
|
||||
+inlinedForm(autoclose=false)
|
||||
input.list-name-input.full-line(type="text" placeholder="{{_ 'add-list'}}"
|
||||
autocomplete="off" autofocus)
|
||||
if currentBoard.getLastList
|
||||
| {{_ 'add-after-list'}}
|
||||
select.list-position-input.full-line
|
||||
each currentBoard.lists
|
||||
option(value="{{_id}}" selected=currentBoard.getLastList.title) {{title}}
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm(type="submit") {{_ 'save'}}
|
||||
.fa.fa-times-thin.js-close-inlined-form
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
const { calculateIndex } = Utils;
|
||||
|
||||
function currentListIsInThisSwimlane(swimlaneId) {
|
||||
const currentList = Lists.findOne(Session.get('currentList'));
|
||||
const currentList = Utils.getCurrentList();
|
||||
return (
|
||||
currentList &&
|
||||
(currentList.swimlaneId === swimlaneId || currentList.swimlaneId === '')
|
||||
@@ -10,7 +11,7 @@ function currentListIsInThisSwimlane(swimlaneId) {
|
||||
|
||||
function currentCardIsInThisList(listId, swimlaneId) {
|
||||
const currentCard = Utils.getCurrentCard();
|
||||
//const currentUser = Meteor.user();
|
||||
//const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (
|
||||
//currentUser &&
|
||||
//currentUser.profile &&
|
||||
@@ -104,15 +105,6 @@ function initSortable(boardComponent, $listsDom) {
|
||||
},
|
||||
});
|
||||
|
||||
//function userIsMember() {
|
||||
// return (
|
||||
// Meteor.user() &&
|
||||
// Meteor.user().isBoardMember() &&
|
||||
// !Meteor.user().isCommentOnly() &&
|
||||
// !Meteor.user().isWorker()
|
||||
// );
|
||||
//}
|
||||
|
||||
boardComponent.autorun(() => {
|
||||
if (Utils.isTouchScreenOrShowDesktopDragHandles()) {
|
||||
$listsDom.sortable({
|
||||
@@ -129,11 +121,7 @@ function initSortable(boardComponent, $listsDom) {
|
||||
$listsDom.sortable(
|
||||
'option',
|
||||
'disabled',
|
||||
// Disable drag-dropping when user is not member/is worker
|
||||
//!userIsMember() || Meteor.user().isWorker(),
|
||||
!Meteor.user() || !Meteor.user().isBoardAdmin(),
|
||||
// Not disable drag-dropping while in multi-selection mode
|
||||
// MultiSelection.isActive() || !userIsMember(),
|
||||
!ReactiveCache.getCurrentUser()?.isBoardAdmin(),
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -182,7 +170,7 @@ BlazeComponent.extendComponent({
|
||||
.parentComponent()
|
||||
.data()._id;
|
||||
const cards = list.cards(swimlaneId);
|
||||
if (cards.count() === 0) {
|
||||
if (cards.length === 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -239,7 +227,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
this.currentBoard = Utils.getCurrentBoard();
|
||||
this.isListTemplatesSwimlane =
|
||||
this.currentBoard.isTemplatesBoard() &&
|
||||
this.currentData().isListTemplatesSwimlane();
|
||||
@@ -257,9 +245,19 @@ BlazeComponent.extendComponent({
|
||||
submit(evt) {
|
||||
evt.preventDefault();
|
||||
const lastList = this.currentBoard.getLastList();
|
||||
const sortIndex = Utils.calculateIndexData(lastList, null).base;
|
||||
const titleInput = this.find('.list-name-input');
|
||||
const title = titleInput.value.trim();
|
||||
let sortIndex = 0
|
||||
if (lastList) {
|
||||
const positionInput = this.find('.list-position-input');
|
||||
const position = positionInput.value.trim();
|
||||
const ret = ReactiveCache.getList({ boardId: Utils.getCurrentBoardId(), _id: position, archived: false })
|
||||
sortIndex = parseInt(JSON.stringify(ret['sort']))
|
||||
sortIndex = sortIndex+1
|
||||
} else {
|
||||
sortIndex = Utils.calculateIndexData(lastList, null).base;
|
||||
}
|
||||
|
||||
if (title) {
|
||||
Lists.insert({
|
||||
title,
|
||||
@@ -284,12 +282,6 @@ BlazeComponent.extendComponent({
|
||||
Template.swimlane.helpers({
|
||||
canSeeAddList() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
/*
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
*/
|
||||
},
|
||||
});
|
||||
|
||||
@@ -314,7 +306,7 @@ BlazeComponent.extendComponent({
|
||||
.parentComponent()
|
||||
.data()._id;
|
||||
const cards = list.cards(swimlaneId);
|
||||
if (cards.count() === 0) {
|
||||
if (cards.length === 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -340,7 +332,7 @@ class MoveSwimlaneComponent extends BlazeComponent {
|
||||
}
|
||||
|
||||
board() {
|
||||
return Boards.findOne(Session.get('currentBoard'));
|
||||
return Utils.getCurrentBoard();
|
||||
}
|
||||
|
||||
toBoardsSelector() {
|
||||
@@ -353,14 +345,14 @@ class MoveSwimlaneComponent extends BlazeComponent {
|
||||
}
|
||||
|
||||
toBoards() {
|
||||
return Boards.find(this.toBoardsSelector(), { sort: { title: 1 } });
|
||||
const ret = ReactiveCache.getBoards(this.toBoardsSelector(), { sort: { title: 1 } });
|
||||
return ret;
|
||||
}
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-done'() {
|
||||
// const swimlane = Swimlanes.findOne(this.currentSwimlane._id);
|
||||
const bSelect = $('.js-select-boards')[0];
|
||||
let boardId;
|
||||
if (bSelect) {
|
||||
|
||||
@@ -102,6 +102,13 @@ template(name="changeAvatarPopup")
|
||||
i.fa.fa-check
|
||||
p.sub-name {{_ 'default-avatar'}}
|
||||
input.hide.js-upload-avatar-input(accept="image/*;capture=camera" type="file")
|
||||
if Meteor.settings.public.avatarsUploadMaxSize
|
||||
| {{_ 'max-avatar-filesize'}} {{Meteor.settings.public.avatarsUploadMaxSize}}
|
||||
br
|
||||
if Meteor.settings.public.avatarsUploadMimeTypes
|
||||
| {{_ 'allowed-avatar-filetypes'}} {{Meteor.settings.public.avatarsUploadMimeTypes}}
|
||||
br
|
||||
| {{_ 'invalid-file'}}
|
||||
button.full.js-upload-avatar
|
||||
i.fa.fa-upload
|
||||
| {{_ 'upload-avatar'}}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import Cards from '/models/cards';
|
||||
import Avatars from '/models/avatars';
|
||||
import Users from '/models/users';
|
||||
@@ -6,7 +7,7 @@ import Team from '/models/team';
|
||||
|
||||
Template.userAvatar.helpers({
|
||||
userData() {
|
||||
return Users.findOne(this.userId, {
|
||||
return ReactiveCache.getUser(this.userId, {
|
||||
fields: {
|
||||
profile: 1,
|
||||
username: 1,
|
||||
@@ -15,13 +16,13 @@ Template.userAvatar.helpers({
|
||||
},
|
||||
|
||||
memberType() {
|
||||
const user = Users.findOne(this.userId);
|
||||
const user = ReactiveCache.getUser(this.userId);
|
||||
return user && user.isBoardAdmin() ? 'admin' : 'normal';
|
||||
},
|
||||
|
||||
/*
|
||||
presenceStatusClassName() {
|
||||
const user = Users.findOne(this.userId);
|
||||
const user = ReactiveCache.getUser(this.userId);
|
||||
const userPresence = presences.findOne({ userId: this.userId });
|
||||
if (user && user.isInvitedTo(Session.get('currentBoard'))) return 'pending';
|
||||
else if (!userPresence) return 'disconnected';
|
||||
@@ -35,12 +36,12 @@ Template.userAvatar.helpers({
|
||||
|
||||
Template.userAvatarInitials.helpers({
|
||||
initials() {
|
||||
const user = Users.findOne(this.userId);
|
||||
const user = ReactiveCache.getUser(this.userId);
|
||||
return user && user.getInitials();
|
||||
},
|
||||
|
||||
viewPortWidth() {
|
||||
const user = Users.findOne(this.userId);
|
||||
const user = ReactiveCache.getUser(this.userId);
|
||||
return ((user && user.getInitials().length) || 1) * 12;
|
||||
},
|
||||
});
|
||||
@@ -88,21 +89,18 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.boardOrgRow.helpers({
|
||||
orgData() {
|
||||
return Org.findOne(this.orgId);
|
||||
},
|
||||
currentUser(){
|
||||
return Meteor.user();
|
||||
return ReactiveCache.getOrg(this.orgId);
|
||||
},
|
||||
});
|
||||
|
||||
Template.boardOrgName.helpers({
|
||||
orgName() {
|
||||
const org = Org.findOne(this.orgId);
|
||||
const org = ReactiveCache.getOrg(this.orgId);
|
||||
return org && org.orgDisplayName;
|
||||
},
|
||||
|
||||
orgViewPortWidth() {
|
||||
const org = Org.findOne(this.orgId);
|
||||
const org = ReactiveCache.getOrg(this.orgId);
|
||||
return ((org && org.orgDisplayName.length) || 1) * 12;
|
||||
},
|
||||
});
|
||||
@@ -150,21 +148,18 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.boardTeamRow.helpers({
|
||||
teamData() {
|
||||
return Team.findOne(this.teamId);
|
||||
},
|
||||
currentUser(){
|
||||
return Meteor.user();
|
||||
return ReactiveCache.getTeam(this.teamId);
|
||||
},
|
||||
});
|
||||
|
||||
Template.boardTeamName.helpers({
|
||||
teamName() {
|
||||
const team = Team.findOne(this.teamId);
|
||||
const team = ReactiveCache.getTeam(this.teamId);
|
||||
return team && team.teamDisplayName;
|
||||
},
|
||||
|
||||
teamViewPortWidth() {
|
||||
const team = Team.findOne(this.teamId);
|
||||
const team = ReactiveCache.getTeam(this.teamId);
|
||||
return ((team && team.teamDisplayName.length) || 1) * 12;
|
||||
},
|
||||
});
|
||||
@@ -177,24 +172,25 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
uploadedAvatars() {
|
||||
return Avatars.find({ userId: Meteor.userId() }).each();
|
||||
const ret = ReactiveCache.getAvatars({ userId: Meteor.userId() }, {}, true).each();
|
||||
return ret;
|
||||
},
|
||||
|
||||
isSelected() {
|
||||
const userProfile = Meteor.user().profile;
|
||||
const userProfile = ReactiveCache.getCurrentUser().profile;
|
||||
const avatarUrl = userProfile && userProfile.avatarUrl;
|
||||
const currentAvatarUrl = `${this.currentData().link()}?auth=false&brokenIsFine=true`;
|
||||
return avatarUrl === currentAvatarUrl;
|
||||
},
|
||||
|
||||
noAvatarUrl() {
|
||||
const userProfile = Meteor.user().profile;
|
||||
const userProfile = ReactiveCache.getCurrentUser().profile;
|
||||
const avatarUrl = userProfile && userProfile.avatarUrl;
|
||||
return !avatarUrl;
|
||||
},
|
||||
|
||||
setAvatar(avatarUrl) {
|
||||
Meteor.user().setAvatarUrl(avatarUrl);
|
||||
ReactiveCache.getCurrentUser().setAvatarUrl(avatarUrl);
|
||||
},
|
||||
|
||||
setError(error) {
|
||||
@@ -248,7 +244,7 @@ Template.cardMembersPopup.helpers({
|
||||
},
|
||||
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -263,13 +259,13 @@ Template.cardMembersPopup.events({
|
||||
|
||||
Template.cardMemberPopup.helpers({
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
});
|
||||
|
||||
Template.cardMemberPopup.events({
|
||||
'click .js-remove-member'() {
|
||||
Cards.findOne(this.cardId).unassignMember(this.userId);
|
||||
ReactiveCache.getCard(this.cardId).unassignMember(this.userId);
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-edit-profile': Popup.open('editProfile'),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
Template.headerUserBar.events({
|
||||
@@ -13,27 +14,27 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.memberMenuPopup.helpers({
|
||||
templatesBoardId() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return Meteor.user().getTemplatesBoardId();
|
||||
return currentUser.getTemplatesBoardId();
|
||||
} else {
|
||||
// No need to getTemplatesBoardId on public board
|
||||
return false;
|
||||
}
|
||||
},
|
||||
templatesBoardSlug() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return Meteor.user().getTemplatesBoardSlug();
|
||||
return currentUser.getTemplatesBoardSlug();
|
||||
} else {
|
||||
// No need to getTemplatesBoardSlug() on public board
|
||||
return false;
|
||||
}
|
||||
},
|
||||
isSameDomainNameSettingValue(){
|
||||
const currSett = Settings.findOne();
|
||||
const currSett = ReactiveCache.getCurrentSetting();
|
||||
if(currSett && currSett != undefined && currSett.disableRegistration && currSett.mailDomainName !== undefined && currSett.mailDomainName != ""){
|
||||
currentUser = Meteor.user();
|
||||
currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
let found = false;
|
||||
for(let i = 0; i < currentUser.emails.length; i++) {
|
||||
@@ -51,7 +52,7 @@ Template.memberMenuPopup.helpers({
|
||||
return false;
|
||||
},
|
||||
isNotOAuth2AuthenticationMethod(){
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return currentUser.authenticationMethod.toLowerCase() != 'oauth2';
|
||||
} else {
|
||||
@@ -140,12 +141,6 @@ Template.invitePeoplePopup.events({
|
||||
},
|
||||
});
|
||||
|
||||
Template.invitePeoplePopup.helpers({
|
||||
currentSetting() {
|
||||
return Settings.findOne();
|
||||
},
|
||||
});
|
||||
|
||||
Template.editProfilePopup.helpers({
|
||||
allowEmailChange() {
|
||||
Meteor.call('AccountSettings.allowEmailChange', (_, result) => {
|
||||
@@ -191,9 +186,9 @@ Template.editProfilePopup.events({
|
||||
'profile.initials': initials,
|
||||
},
|
||||
});
|
||||
isChangeUserName = username !== Meteor.user().username;
|
||||
isChangeUserName = username !== ReactiveCache.getCurrentUser().username;
|
||||
isChangeEmail =
|
||||
email.toLowerCase() !== Meteor.user().emails[0].address.toLowerCase();
|
||||
email.toLowerCase() !== ReactiveCache.getCurrentUser().emails[0].address.toLowerCase();
|
||||
if (isChangeUserName && isChangeEmail) {
|
||||
Meteor.call(
|
||||
'setUsernameAndEmail',
|
||||
@@ -288,7 +283,7 @@ Template.changeLanguagePopup.events({
|
||||
|
||||
Template.changeSettingsPopup.helpers({
|
||||
hiddenSystemMessages() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).hasHiddenSystemMessages;
|
||||
} else if (window.localStorage.getItem('hasHiddenSystemMessages')) {
|
||||
@@ -298,7 +293,7 @@ Template.changeSettingsPopup.helpers({
|
||||
}
|
||||
},
|
||||
rescueCardDescription() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).rescueCardDescription;
|
||||
} else if (window.localStorage.getItem('rescueCardDescription')) {
|
||||
@@ -308,9 +303,9 @@ Template.changeSettingsPopup.helpers({
|
||||
}
|
||||
},
|
||||
showCardsCountAt() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return Meteor.user().getLimitToShowCardsCount();
|
||||
return currentUser.getLimitToShowCardsCount();
|
||||
} else {
|
||||
return window.localStorage.getItem('limitToShowCardsCount');
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { Blaze } from 'meteor/blaze';
|
||||
import { Session } from 'meteor/session';
|
||||
import moment from 'moment/min/moment-with-locales';
|
||||
@@ -13,15 +14,21 @@ Blaze.registerHelper('currentCard', () => {
|
||||
});
|
||||
|
||||
Blaze.registerHelper('currentList', () => {
|
||||
const listId = Session.get('currentList');
|
||||
if (listId) {
|
||||
return Lists.findOne(listId);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
const ret = Utils.getCurrentList();
|
||||
return ret;
|
||||
});
|
||||
|
||||
Blaze.registerHelper('getUser', userId => Users.findOne(userId));
|
||||
Blaze.registerHelper('currentSetting', () => {
|
||||
const ret = ReactiveCache.getCurrentSetting();
|
||||
return ret;
|
||||
});
|
||||
|
||||
Blaze.registerHelper('currentUser', () => {
|
||||
const ret = ReactiveCache.getCurrentUser();
|
||||
return ret;
|
||||
});
|
||||
|
||||
Blaze.registerHelper('getUser', userId => ReactiveCache.getUser(userId));
|
||||
|
||||
Blaze.registerHelper('concat', (...args) => args.slice(0, -1).join(''));
|
||||
|
||||
@@ -42,3 +49,11 @@ Blaze.registerHelper('moment', (...args) => {
|
||||
const [date, format] = args;
|
||||
return moment(date).format(format);
|
||||
});
|
||||
|
||||
Blaze.registerHelper('canModifyCard', () =>
|
||||
Utils.canModifyCard(),
|
||||
);
|
||||
|
||||
Blaze.registerHelper('canModifyBoard', () =>
|
||||
Utils.canModifyBoard(),
|
||||
);
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import Cards from '../../models/cards';
|
||||
import SessionData from '../../models/usersessiondata';
|
||||
@@ -61,8 +62,8 @@ export class CardSearchPagedComponent extends BlazeComponent {
|
||||
}
|
||||
|
||||
getSessionData(sessionId) {
|
||||
return SessionData.findOne({
|
||||
sessionId: sessionId ? sessionId : SessionData.getSessionId(),
|
||||
return ReactiveCache.getSessionData({
|
||||
sessionId: sessionId || SessionData.getSessionId(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -74,7 +75,7 @@ export class CardSearchPagedComponent extends BlazeComponent {
|
||||
console.log('session data:', this.sessionData);
|
||||
const cards = [];
|
||||
this.sessionData.cards.forEach(cardId => {
|
||||
cards.push(Cards.findOne({ _id: cardId }));
|
||||
cards.push(ReactiveCache.getCard(cardId));
|
||||
});
|
||||
this.queryErrors = this.sessionData.errors;
|
||||
if (this.queryErrors.length) {
|
||||
@@ -168,7 +169,7 @@ export class CardSearchPagedComponent extends BlazeComponent {
|
||||
} else if (this.resultsCount === 1) {
|
||||
return TAPi18n.__('one-card-found');
|
||||
} else if (this.resultsCount === this.totalHits) {
|
||||
return TAPi18n.__('n-cards-found', this.resultsCount);
|
||||
return TAPi18n.__('n-cards-found', {sprintf: [this.resultsCount]});
|
||||
}
|
||||
|
||||
return TAPi18n.__('n-n-of-n-cards-found', {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import moment from 'moment/min/moment-with-locales';
|
||||
|
||||
@@ -22,7 +23,7 @@ export class DatePicker extends BlazeComponent {
|
||||
}
|
||||
|
||||
startDayOfWeek() {
|
||||
const currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return currentUser.getStartDayOfWeek();
|
||||
} else {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
export class DialogWithBoardSwimlaneList extends BlazeComponent {
|
||||
/** returns the card dialog options
|
||||
* @return Object with properties { boardId, swimlaneId, listId }
|
||||
@@ -52,26 +54,26 @@ export class DialogWithBoardSwimlaneList extends BlazeComponent {
|
||||
}
|
||||
}
|
||||
this.getBoardData(this.selectedBoardId.get());
|
||||
if (!this.selectedSwimlaneId.get() || !Swimlanes.findOne({_id: this.selectedSwimlaneId.get(), boardId: this.selectedBoardId.get()})) {
|
||||
if (!this.selectedSwimlaneId.get() || !ReactiveCache.getSwimlane({_id: this.selectedSwimlaneId.get(), boardId: this.selectedBoardId.get()})) {
|
||||
this.setFirstSwimlaneId();
|
||||
}
|
||||
if (!this.selectedListId.get() || !Lists.findOne({_id: this.selectedListId.get(), boardId: this.selectedBoardId.get()})) {
|
||||
if (!this.selectedListId.get() || !ReactiveCache.getList({_id: this.selectedListId.get(), boardId: this.selectedBoardId.get()})) {
|
||||
this.setFirstListId();
|
||||
}
|
||||
}
|
||||
/** sets the first swimlane id */
|
||||
setFirstSwimlaneId() {
|
||||
try {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const swimlaneId = board.swimlanes().fetch()[0]._id;
|
||||
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
|
||||
const swimlaneId = board.swimlanes()[0]._id;
|
||||
this.selectedSwimlaneId.set(swimlaneId);
|
||||
} catch (e) {}
|
||||
}
|
||||
/** sets the first list id */
|
||||
setFirstListId() {
|
||||
try {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const listId = board.lists().fetch()[0]._id;
|
||||
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
|
||||
const listId = board.lists()[0]._id;
|
||||
this.selectedListId.set(listId);
|
||||
} catch (e) {}
|
||||
}
|
||||
@@ -105,11 +107,11 @@ export class DialogWithBoardSwimlaneList extends BlazeComponent {
|
||||
|
||||
/** returns all available board */
|
||||
boards() {
|
||||
const ret = Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
_id: { $ne: Meteor.user().getTemplatesBoardId() },
|
||||
_id: { $ne: ReactiveCache.getCurrentUser().getTemplatesBoardId() },
|
||||
},
|
||||
{
|
||||
sort: { sort: 1 },
|
||||
@@ -120,14 +122,14 @@ export class DialogWithBoardSwimlaneList extends BlazeComponent {
|
||||
|
||||
/** returns all available swimlanes of the current board */
|
||||
swimlanes() {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
|
||||
const ret = board.swimlanes();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** returns all available lists of the current board */
|
||||
lists() {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
|
||||
const ret = board.lists();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { DialogWithBoardSwimlaneList } from '/client/lib/dialogWithBoardSwimlaneList';
|
||||
|
||||
export class DialogWithBoardSwimlaneListCard extends DialogWithBoardSwimlaneList {
|
||||
@@ -22,7 +23,7 @@ export class DialogWithBoardSwimlaneListCard extends DialogWithBoardSwimlaneList
|
||||
|
||||
/** returns all available cards of the current list */
|
||||
cards() {
|
||||
const list = Lists.findOne(this.selectedListId.get());
|
||||
const list = ReactiveCache.getList(this.selectedListId.get());
|
||||
let ret = [];
|
||||
if (list) {
|
||||
ret = list.cards(this.selectedSwimlaneId.get());
|
||||
|
||||
+47
-20
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import moment from 'moment/min/moment-with-locales';
|
||||
|
||||
// Filtered view manager
|
||||
@@ -55,7 +56,12 @@ class DateFilter {
|
||||
|
||||
// thisWeek is a convenience method for calling relativeWeek with 1
|
||||
thisWeek() {
|
||||
this.relativeWeek(1);
|
||||
this.relativeWeek(1, 'this')
|
||||
}
|
||||
|
||||
// nextWeek is a convenience method for calling relativeWeek with 1
|
||||
nextWeek() {
|
||||
this.relativeWeek(1, 'next')
|
||||
}
|
||||
|
||||
// relativeDay builds a filter starting from now and including all
|
||||
@@ -83,11 +89,17 @@ class DateFilter {
|
||||
this._updateState('day');
|
||||
}
|
||||
|
||||
// relativeWeek builds a filter starting from today and including all
|
||||
// relativeWeek builds a filter starting from today (for this week)
|
||||
// or 7 days after (for next week) and including all
|
||||
// weeks up to today +/- offset. This considers the user's preferred
|
||||
// start of week day (as defined by Meteor).
|
||||
relativeWeek(offset) {
|
||||
if (this._filterState == 'week') {
|
||||
relativeWeek(offset, week) {
|
||||
if (this._filterState == 'thisweek') {
|
||||
this.reset();
|
||||
return;
|
||||
}
|
||||
|
||||
if (this._filterState == 'nextweek') {
|
||||
this.reset();
|
||||
return;
|
||||
}
|
||||
@@ -96,28 +108,43 @@ class DateFilter {
|
||||
// preferred starting day of the week. This date should be added
|
||||
// to the moment start of week to get the real start of week date.
|
||||
// The default is 1, meaning Monday.
|
||||
const currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
const weekStartDay = currentUser ? currentUser.getStartDayOfWeek() : 1;
|
||||
|
||||
// Moments are mutable so they must be cloned before modification
|
||||
var thisWeekStart = moment()
|
||||
.startOf('day')
|
||||
.startOf('week')
|
||||
.add(weekStartDay, 'days');
|
||||
var thisWeekEnd = thisWeekStart
|
||||
.clone()
|
||||
.add(offset, 'week')
|
||||
.endOf('day');
|
||||
var startDate = thisWeekStart.toDate();
|
||||
var endDate = thisWeekEnd.toDate();
|
||||
if (week === 'this') {
|
||||
// Moments are mutable so they must be cloned before modification
|
||||
var WeekStart = moment()
|
||||
.startOf('day')
|
||||
.startOf('week')
|
||||
.add(weekStartDay, 'days');
|
||||
var WeekEnd = WeekStart
|
||||
.clone()
|
||||
.add(6, 'days')
|
||||
.endOf('day');
|
||||
|
||||
this._updateState('thisweek');
|
||||
} else if (week === 'next') {
|
||||
// Moments are mutable so they must be cloned before modification
|
||||
var WeekStart = moment()
|
||||
.startOf('day')
|
||||
.startOf('week')
|
||||
.add(weekStartDay + 7, 'days');
|
||||
var WeekEnd = WeekStart
|
||||
.clone()
|
||||
.add(6, 'days')
|
||||
.endOf('day');
|
||||
|
||||
this._updateState('nextweek');
|
||||
}
|
||||
|
||||
var startDate = WeekStart.toDate();
|
||||
var endDate = WeekEnd.toDate();
|
||||
|
||||
if (offset >= 0) {
|
||||
this._filter = { $gte: startDate, $lte: endDate };
|
||||
} else {
|
||||
this._filter = { $lte: startDate, $gte: endDate };
|
||||
}
|
||||
|
||||
this._updateState('week');
|
||||
}
|
||||
|
||||
// noDate builds a filter for items where date is not set
|
||||
@@ -345,14 +372,14 @@ class AdvancedFilter {
|
||||
}
|
||||
|
||||
_fieldNameToId(field) {
|
||||
const found = CustomFields.findOne({
|
||||
const found = ReactiveCache.getCustomField({
|
||||
name: field,
|
||||
});
|
||||
return found._id;
|
||||
}
|
||||
|
||||
_fieldValueToId(field, value) {
|
||||
const found = CustomFields.findOne({
|
||||
const found = ReactiveCache.getCustomField({
|
||||
name: field,
|
||||
});
|
||||
if (
|
||||
|
||||
+14
-2
@@ -1,11 +1,23 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
// We save the user language preference in the user profile, and use that to set
|
||||
// the language reactively. If the user is not connected we use the language
|
||||
// information provided by the browser, and default to english.
|
||||
|
||||
Meteor.startup(() => {
|
||||
const currentUser = Meteor.user();
|
||||
Meteor.startup(async () => {
|
||||
let currentUser = ReactiveCache.getCurrentUser();
|
||||
// If we're still logging in, wait (#4967)
|
||||
if (!currentUser && Meteor.loggingIn()) {
|
||||
await new Promise((resolve) => {
|
||||
Tracker.autorun(() => {
|
||||
if (!Meteor.loggingIn()) {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
currentUser = ReactiveCache.getCurrentUser();
|
||||
}
|
||||
// Select first available language
|
||||
const [language] = [
|
||||
// User profile
|
||||
|
||||
Vendored
+1
-1
@@ -17,4 +17,4 @@ require('jquery-ui/ui/widgets/draggable')
|
||||
require('jquery-ui/ui/widgets/droppable')
|
||||
|
||||
// enable touch on mobile
|
||||
require('jquery-ui-touch-punch')
|
||||
require('@rwap/jquery-ui-touch-punch')
|
||||
+13
-15
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
// XXX There is no reason to define these shortcuts globally, they should be
|
||||
// attached to a template (most of them will go in the `board` template).
|
||||
|
||||
@@ -76,14 +78,14 @@ Mousetrap.bind(numbArray, (evt, key) => {
|
||||
return;
|
||||
}
|
||||
const currentBoardId = Session.get('currentBoard');
|
||||
board = Boards.findOne(currentBoardId);
|
||||
board = ReactiveCache.getBoard(currentBoardId);
|
||||
labels = board.labels;
|
||||
if(MultiSelection.isActive())
|
||||
{
|
||||
const cardIds = MultiSelection.getSelectedCardIds();
|
||||
for (const cardId of cardIds)
|
||||
{
|
||||
card = Cards.findOne(cardId);
|
||||
card = ReactiveCache.getCard(cardId);
|
||||
if(num <= board.labels.length)
|
||||
{
|
||||
card.removeLabel(labels[num-1]["_id"]);
|
||||
@@ -100,14 +102,14 @@ Mousetrap.bind(numArray, (evt, key) => {
|
||||
if (currentUserId === null) {
|
||||
return;
|
||||
}
|
||||
board = Boards.findOne(currentBoardId);
|
||||
board = ReactiveCache.getBoard(currentBoardId);
|
||||
labels = board.labels;
|
||||
if(MultiSelection.isActive() && Meteor.user().isBoardMember())
|
||||
if(MultiSelection.isActive() && ReactiveCache.getCurrentUser().isBoardMember())
|
||||
{
|
||||
const cardIds = MultiSelection.getSelectedCardIds();
|
||||
for (const cardId of cardIds)
|
||||
{
|
||||
card = Cards.findOne(cardId);
|
||||
card = ReactiveCache.getCard(cardId);
|
||||
if(num <= board.labels.length)
|
||||
{
|
||||
card.addLabel(labels[num-1]["_id"]);
|
||||
@@ -120,8 +122,8 @@ Mousetrap.bind(numArray, (evt, key) => {
|
||||
if (!cardId) {
|
||||
return;
|
||||
}
|
||||
if (Meteor.user().isBoardMember()) {
|
||||
const card = Cards.findOne(cardId);
|
||||
if (ReactiveCache.getCurrentUser().isBoardMember()) {
|
||||
const card = ReactiveCache.getCard(cardId);
|
||||
if(num <= board.labels.length)
|
||||
{
|
||||
card.toggleLabel(labels[num-1]["_id"]);
|
||||
@@ -140,8 +142,8 @@ Mousetrap.bind('space', evt => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Meteor.user().isBoardMember()) {
|
||||
const card = Cards.findOne(cardId);
|
||||
if (ReactiveCache.getCurrentUser().isBoardMember()) {
|
||||
const card = ReactiveCache.getCard(cardId);
|
||||
card.toggleMember(currentUserId);
|
||||
// We should prevent scrolling in card when spacebar is clicked
|
||||
// This should do it according to Mousetrap docs, but it doesn't
|
||||
@@ -160,12 +162,8 @@ Mousetrap.bind('c', evt => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
) {
|
||||
const card = Cards.findOne(cardId);
|
||||
if (Utils.canModifyBoard()) {
|
||||
const card = ReactiveCache.getCard(cardId);
|
||||
card.archive();
|
||||
// We should prevent scrolling in card when spacebar is clicked
|
||||
// This should do it according to Mousetrap docs, but it doesn't
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
function getCardsBetween(idA, idB) {
|
||||
function pluckId(doc) {
|
||||
return doc._id;
|
||||
}
|
||||
|
||||
function getListsStrictlyBetween(id1, id2) {
|
||||
return Lists.find({
|
||||
return ReactiveCache.getLists({
|
||||
$and: [
|
||||
{ sort: { $gt: Lists.findOne(id1).sort } },
|
||||
{ sort: { $lt: Lists.findOne(id2).sort } },
|
||||
{ sort: { $gt: ReactiveCache.getList(id1).sort } },
|
||||
{ sort: { $lt: ReactiveCache.getList(id2).sort } },
|
||||
],
|
||||
archived: false,
|
||||
}).map(pluckId);
|
||||
}
|
||||
|
||||
const cards = _.sortBy([Cards.findOne(idA), Cards.findOne(idB)], c => {
|
||||
const cards = _.sortBy([ReactiveCache.getCard(idA), ReactiveCache.getCard(idB)], c => {
|
||||
return c.sort;
|
||||
});
|
||||
|
||||
@@ -48,7 +50,7 @@ function getCardsBetween(idA, idB) {
|
||||
};
|
||||
}
|
||||
|
||||
return Cards.find(Filter.mongoSelector(selector)).map(pluckId);
|
||||
return ReactiveCache.getCards(Filter.mongoSelector(selector)).map(pluckId);
|
||||
}
|
||||
|
||||
MultiSelection = {
|
||||
@@ -77,7 +79,7 @@ MultiSelection = {
|
||||
},
|
||||
|
||||
count() {
|
||||
return Cards.find(this.getMongoSelector()).count();
|
||||
return ReactiveCache.getCards(this.getMongoSelector()).length;
|
||||
},
|
||||
|
||||
isEmpty() {
|
||||
|
||||
@@ -76,6 +76,14 @@ window.Popup = new (class {
|
||||
dataContext: (this && this.currentData && this.currentData()) || (options && options.dataContextIfCurrentDataIsUndefined) || this,
|
||||
});
|
||||
|
||||
const $contentWrapper = $('.content-wrapper')
|
||||
if ($contentWrapper.length > 0) {
|
||||
const contentWrapper = $contentWrapper[0];
|
||||
self._getTopStack().scrollTop = contentWrapper.scrollTop;
|
||||
// scroll from e.g. delete comment to the top (where the confirm button is)
|
||||
$contentWrapper.scrollTop(0);
|
||||
}
|
||||
|
||||
// If there are no popup currently opened we use the Blaze API to render
|
||||
// one into the DOM. We use a reactive function as the data parameter that
|
||||
// return the complete along with its top element and depends on our
|
||||
@@ -129,6 +137,21 @@ window.Popup = new (class {
|
||||
/// steps back is greater than the popup stack size, the popup will be closed.
|
||||
back(n = 1) {
|
||||
if (this._stack.length > n) {
|
||||
const $contentWrapper = $('.content-wrapper')
|
||||
if ($contentWrapper.length > 0) {
|
||||
const contentWrapper = $contentWrapper[0];
|
||||
const stack = this._stack[this._stack.length - n];
|
||||
// scrollTopMax and scrollLeftMax only available at Firefox (https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTopMax)
|
||||
const scrollTopMax = contentWrapper.scrollTopMax || contentWrapper.scrollHeight - contentWrapper.clientHeight;
|
||||
if (scrollTopMax && stack.scrollTop > scrollTopMax) {
|
||||
// sometimes scrollTopMax is lower than scrollTop, so i need this dirty hack
|
||||
setTimeout(() => {
|
||||
$contentWrapper.scrollTop(stack.scrollTop);
|
||||
}, 6);
|
||||
}
|
||||
// restore the old popup scroll position
|
||||
$contentWrapper.scrollTop(stack.scrollTop);
|
||||
}
|
||||
_.times(n, () => this._stack.pop());
|
||||
this._dep.changed();
|
||||
} else {
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
Meteor.subscribe('setting');
|
||||
|
||||
import { ALLOWED_WAIT_SPINNERS } from '/config/const';
|
||||
|
||||
export class Spinner extends BlazeComponent {
|
||||
currentSettings() {
|
||||
return Settings.findOne();
|
||||
}
|
||||
|
||||
getSpinnerName() {
|
||||
let ret = 'Bounce';
|
||||
let defaultWaitSpinner = Meteor.settings.public.WAIT_SPINNER;
|
||||
if (defaultWaitSpinner && ALLOWED_WAIT_SPINNERS.includes(defaultWaitSpinner)) {
|
||||
ret = defaultWaitSpinner;
|
||||
}
|
||||
let settings = this.currentSettings();
|
||||
let settings = ReactiveCache.getCurrentSetting();
|
||||
|
||||
if (settings && settings.spinnerName) {
|
||||
ret = settings.spinnerName;
|
||||
|
||||
+102
-50
@@ -1,4 +1,15 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
Utils = {
|
||||
setBackgroundImage(url) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
if (currentBoard.backgroundImageURL !== undefined) {
|
||||
$(".board-wrapper,.board-wrapper .board-canvas").css({"background":"url(" + currentBoard.backgroundImageURL + ")","background-size":"cover"});
|
||||
$(".swimlane,.swimlane .list,.swimlane .list .list-body,.swimlane .list:first-child .list-body").css({"background-color":"transparent"});
|
||||
} else if (currentBoard.color !== undefined) {
|
||||
currentBoard.setColor(currentBoard.color);
|
||||
}
|
||||
},
|
||||
/** returns the current board id
|
||||
* <li> returns the current board id or the board id of the popup card if set
|
||||
*/
|
||||
@@ -22,22 +33,53 @@ Utils = {
|
||||
const ret = Session.get('popupCardId');
|
||||
return ret;
|
||||
},
|
||||
getCurrentListId() {
|
||||
const ret = Session.get('currentList');
|
||||
return ret;
|
||||
},
|
||||
/** returns the current board
|
||||
* <li> returns the current board or the board of the popup card if set
|
||||
*/
|
||||
getCurrentBoard() {
|
||||
const boardId = Utils.getCurrentBoardId();
|
||||
const ret = Boards.findOne(boardId);
|
||||
const ret = ReactiveCache.getBoard(boardId);
|
||||
return ret;
|
||||
},
|
||||
getCurrentCard(ignorePopupCard) {
|
||||
const cardId = Utils.getCurrentCardId(ignorePopupCard);
|
||||
const ret = Cards.findOne(cardId);
|
||||
const ret = ReactiveCache.getCard(cardId);
|
||||
return ret;
|
||||
},
|
||||
getCurrentList() {
|
||||
const listId = this.getCurrentListId();
|
||||
let ret = null;
|
||||
if (listId) {
|
||||
ret = ReactiveCache.getList(listId);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
getPopupCard() {
|
||||
const cardId = Utils.getPopupCardId();
|
||||
const ret = Cards.findOne(cardId);
|
||||
const ret = ReactiveCache.getCard(cardId);
|
||||
return ret;
|
||||
},
|
||||
canModifyCard() {
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
const ret = (
|
||||
currentUser &&
|
||||
currentUser.isBoardMember() &&
|
||||
!currentUser.isCommentOnly() &&
|
||||
!currentUser.isWorker()
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
canModifyBoard() {
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
const ret = (
|
||||
currentUser &&
|
||||
currentUser.isBoardMember() &&
|
||||
!currentUser.isCommentOnly()
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
reload() {
|
||||
@@ -48,9 +90,9 @@ Utils = {
|
||||
window.location.reload();
|
||||
},
|
||||
setBoardView(view) {
|
||||
currentUser = Meteor.user();
|
||||
currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
Meteor.user().setBoardView(view);
|
||||
ReactiveCache.getCurrentUser().setBoardView(view);
|
||||
} else if (view === 'board-view-swimlanes') {
|
||||
window.localStorage.setItem('boardView', 'board-view-swimlanes'); //true
|
||||
Utils.reload();
|
||||
@@ -72,7 +114,7 @@ Utils = {
|
||||
},
|
||||
|
||||
boardView() {
|
||||
currentUser = Meteor.user();
|
||||
currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).boardView;
|
||||
} else if (
|
||||
@@ -116,11 +158,8 @@ Utils = {
|
||||
},
|
||||
|
||||
archivedBoardIds() {
|
||||
const archivedBoards = [];
|
||||
Boards.find({ archived: false }).forEach(board => {
|
||||
archivedBoards.push(board._id);
|
||||
});
|
||||
return archivedBoards;
|
||||
const ret = ReactiveCache.getBoards({ archived: false }).map(board => board._id);
|
||||
return ret;
|
||||
},
|
||||
|
||||
dueCardsView() {
|
||||
@@ -155,7 +194,7 @@ Utils = {
|
||||
|
||||
// XXX We should remove these two methods
|
||||
goBoardId(_id) {
|
||||
const board = Boards.findOne(_id);
|
||||
const board = ReactiveCache.getBoard(_id);
|
||||
return (
|
||||
board &&
|
||||
FlowRouter.go('board', {
|
||||
@@ -166,8 +205,8 @@ Utils = {
|
||||
},
|
||||
|
||||
goCardId(_id) {
|
||||
const card = Cards.findOne(_id);
|
||||
const board = Boards.findOne(card.boardId);
|
||||
const card = ReactiveCache.getCard(_id);
|
||||
const board = ReactiveCache.getBoard(card.boardId);
|
||||
return (
|
||||
board &&
|
||||
FlowRouter.go('card', {
|
||||
@@ -180,7 +219,7 @@ Utils = {
|
||||
getCommonAttachmentMetaFrom(card) {
|
||||
const meta = {};
|
||||
if (card.isLinkedCard()) {
|
||||
meta.boardId = Cards.findOne(card.linkedId).boardId;
|
||||
meta.boardId = ReactiveCache.getCard(card.linkedId).boardId;
|
||||
meta.cardId = card.linkedId;
|
||||
} else {
|
||||
meta.boardId = card.boardId;
|
||||
@@ -288,7 +327,7 @@ Utils = {
|
||||
|
||||
// returns if desktop drag handles are enabled
|
||||
isShowDesktopDragHandles() {
|
||||
//const currentUser = Meteor.user();
|
||||
//const currentUser = ReactiveCache.getCurrentUser();
|
||||
//if (currentUser) {
|
||||
// return (currentUser.profile || {}).showDesktopDragHandles;
|
||||
//} else if (window.localStorage.getItem('showDesktopDragHandles')) {
|
||||
@@ -313,20 +352,51 @@ Utils = {
|
||||
increment = 1;
|
||||
// If we drop the card in the first position
|
||||
} else if (!prevData) {
|
||||
base = nextData.sort - 1;
|
||||
increment = -1;
|
||||
const nextSortIndex = nextData.sort;
|
||||
const ceil = Math.ceil(nextSortIndex - 1);
|
||||
if (ceil < nextSortIndex) {
|
||||
increment = nextSortIndex - ceil;
|
||||
base = nextSortIndex - increment;
|
||||
} else {
|
||||
base = nextData.sort - 1;
|
||||
increment = -1;
|
||||
}
|
||||
// If we drop the card in the last position
|
||||
} else if (!nextData) {
|
||||
base = prevData.sort + 1;
|
||||
increment = 1;
|
||||
const prevSortIndex = prevData.sort;
|
||||
const floor = Math.floor(prevSortIndex + 1);
|
||||
if (floor > prevSortIndex) {
|
||||
increment = prevSortIndex - floor;
|
||||
base = prevSortIndex - increment;
|
||||
} else {
|
||||
base = prevData.sort + 1;
|
||||
increment = 1;
|
||||
}
|
||||
}
|
||||
// In the general case take the average of the previous and next element
|
||||
// sort indexes.
|
||||
else {
|
||||
const prevSortIndex = prevData.sort;
|
||||
const nextSortIndex = nextData.sort;
|
||||
increment = (nextSortIndex - prevSortIndex) / (nItems + 1);
|
||||
base = prevSortIndex + increment;
|
||||
if (nItems == 1 ) {
|
||||
if (prevSortIndex < 0 ) {
|
||||
const ceil = Math.ceil(nextSortIndex - 1);
|
||||
if (ceil < nextSortIndex && ceil > prevSortIndex) {
|
||||
increment = ceil - prevSortIndex;
|
||||
}
|
||||
} else {
|
||||
const floor = Math.floor(nextSortIndex - 1);
|
||||
if (floor < nextSortIndex && floor > prevSortIndex) {
|
||||
increment = floor - prevSortIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!increment) {
|
||||
increment = (nextSortIndex - prevSortIndex) / (nItems + 1);
|
||||
}
|
||||
if (!base) {
|
||||
base = prevSortIndex + increment;
|
||||
}
|
||||
}
|
||||
// XXX Return a generator that yield values instead of a base with a
|
||||
// increment number.
|
||||
@@ -338,34 +408,16 @@ Utils = {
|
||||
|
||||
// Determine the new sort index
|
||||
calculateIndex(prevCardDomElement, nextCardDomElement, nCards = 1) {
|
||||
let base, increment;
|
||||
// If we drop the card to an empty column
|
||||
if (!prevCardDomElement && !nextCardDomElement) {
|
||||
base = 0;
|
||||
increment = 1;
|
||||
// If we drop the card in the first position
|
||||
} else if (!prevCardDomElement) {
|
||||
base = Blaze.getData(nextCardDomElement).sort - 1;
|
||||
increment = -1;
|
||||
// If we drop the card in the last position
|
||||
} else if (!nextCardDomElement) {
|
||||
base = Blaze.getData(prevCardDomElement).sort + 1;
|
||||
increment = 1;
|
||||
let prevData = null;
|
||||
let nextData = null;
|
||||
if (prevCardDomElement) {
|
||||
prevData = Blaze.getData(prevCardDomElement)
|
||||
}
|
||||
// In the general case take the average of the previous and next element
|
||||
// sort indexes.
|
||||
else {
|
||||
const prevSortIndex = Blaze.getData(prevCardDomElement).sort;
|
||||
const nextSortIndex = Blaze.getData(nextCardDomElement).sort;
|
||||
increment = (nextSortIndex - prevSortIndex) / (nCards + 1);
|
||||
base = prevSortIndex + increment;
|
||||
if (nextCardDomElement) {
|
||||
nextData = Blaze.getData(nextCardDomElement);
|
||||
}
|
||||
// XXX Return a generator that yield values instead of a base with a
|
||||
// increment number.
|
||||
return {
|
||||
base,
|
||||
increment,
|
||||
};
|
||||
const ret = Utils.calculateIndexData(prevData, nextData, nCards);
|
||||
return ret;
|
||||
},
|
||||
|
||||
manageCustomUI() {
|
||||
@@ -380,7 +432,7 @@ Utils = {
|
||||
},
|
||||
|
||||
setCustomUI(data) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
if (currentBoard) {
|
||||
DocHead.setTitle(`${currentBoard.title} - ${data.productName}`);
|
||||
} else {
|
||||
@@ -392,7 +444,7 @@ Utils = {
|
||||
window._paq = window._paq || [];
|
||||
window._paq.push(['setDoNotTrack', data.doNotTrack]);
|
||||
if (data.withUserName) {
|
||||
window._paq.push(['setUserId', Meteor.user().username]);
|
||||
window._paq.push(['setUserId', ReactiveCache.getCurrentUser().username]);
|
||||
}
|
||||
window._paq.push(['trackPageView']);
|
||||
window._paq.push(['enableLinkTracking']);
|
||||
|
||||
Loaded 100 of 336 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user