Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4cadc5f4f3 | ||
|
|
8dfb6916c5 | ||
|
|
6066be944a | ||
|
|
e9f8279dbe | ||
|
|
454d3b5bbe | ||
|
|
fe185dd38a | ||
|
|
522b14d96d | ||
|
|
d98b489263 | ||
|
|
47ecc654b8 | ||
|
|
b9a4ae654e | ||
|
|
c40668be3f | ||
|
|
a9d77b975e | ||
|
|
085bf3b6e6 | ||
|
|
91dae9795e | ||
|
|
42081db0d8 | ||
|
|
3af417209c | ||
|
|
b6f60c08e5 | ||
|
|
03d7940829 | ||
|
|
0b263cf582 | ||
|
|
8ef60a06ad | ||
|
|
91eb4b941d | ||
|
|
2171690d22 | ||
|
|
6819303047 | ||
|
|
88e19bd011 | ||
|
|
09b9f690b1 | ||
|
|
7a9c397264 | ||
|
|
c2b7525864 | ||
|
|
e2ecd490ff | ||
|
|
1d3673e9d3 | ||
|
|
5bd85f975c | ||
|
|
89ab99b551 | ||
|
|
01de3f187c | ||
|
|
dcd7925571 | ||
|
|
34b6aa0858 | ||
|
|
73fb62e941 | ||
|
|
55ced412a0 | ||
|
|
04a8d85836 | ||
|
|
392b701956 | ||
|
|
dee098c125 | ||
|
|
56e26a65ae | ||
|
|
69509d597f | ||
|
|
bc7b18abe7 | ||
|
|
4a95cb42cd | ||
|
|
db311f677b | ||
|
|
685fb98e59 | ||
|
|
6dd98285a6 | ||
|
|
e225d29d7a | ||
|
|
eff7d123f2 | ||
|
|
4d62fe83f4 | ||
|
|
a37ca01703 | ||
|
|
ba05f383ca | ||
|
|
4ea4913d72 | ||
|
|
856f3bf864 | ||
|
|
238b0f0725 | ||
|
|
a79a5c7299 | ||
|
|
59580e4b0f | ||
|
|
7e05e02137 | ||
|
|
d4a1611b86 | ||
|
|
77abde7836 | ||
|
|
4c60916191 | ||
|
|
634eec7eb6 | ||
|
|
4ccbbc78cf | ||
|
|
4e1c0fdce8 | ||
|
|
9fa1d846e6 | ||
|
|
969dca292e | ||
|
|
84fde1ecfc | ||
|
|
db9ee59d9f | ||
|
|
20a2ea3e7a | ||
|
|
39b4ada26d | ||
|
|
3ddfe7c1fd | ||
|
|
f7955d5fd7 | ||
|
|
f115afb64e | ||
|
|
3145ec65a3 | ||
|
|
e2f690d0db | ||
|
|
e6c8c04394 | ||
|
|
a7741df5e4 | ||
|
|
912577cab3 | ||
|
|
cec43a63a7 | ||
|
|
10c9fc25a9 | ||
|
|
16665bccf9 | ||
|
|
103cfb936d | ||
|
|
4bb8f3ab27 | ||
|
|
36a4740429 | ||
|
|
ed54c09b48 | ||
|
|
6eb90238b1 | ||
|
|
aad300613d | ||
|
|
a2f8e54b67 | ||
|
|
c9a10efe5c | ||
|
|
7e2f802169 | ||
|
|
9df5a0f530 | ||
|
|
16971ff1d8 | ||
|
|
bef544ddc8 | ||
|
|
2c1f40357d | ||
|
|
ea544caf83 | ||
|
|
be9e98b2a1 | ||
|
|
59a3ac1f37 | ||
|
|
be22ca332b | ||
|
|
983e34ef80 | ||
|
|
c9830bc262 | ||
|
|
fc21c6d1d6 | ||
|
|
960f332dce | ||
|
|
d532a3591f | ||
|
|
03a9f4766a | ||
|
|
96f3e3a958 | ||
|
|
a249ffc805 | ||
|
|
5f53f8cc01 | ||
|
|
ca3f621572 | ||
|
|
a0e1b6f918 | ||
|
|
c76d44b5c7 | ||
|
|
ccc9efb270 | ||
|
|
2ebc34e901 | ||
|
|
04566d3f40 | ||
|
|
1083a92816 | ||
|
|
bb7490a32b | ||
|
|
9e8399612b | ||
|
|
df54863e72 | ||
|
|
8f340326b0 | ||
|
|
42975bc8ab | ||
|
|
adb5487cdc | ||
|
|
4aad9ca498 | ||
|
|
972d023e95 | ||
|
|
acabef4652 | ||
|
|
f77651ba05 | ||
|
|
23e349d277 | ||
|
|
37d9a6659a | ||
|
|
8796c46810 | ||
|
|
0ebb427a00 | ||
|
|
4960891bd9 | ||
|
|
43482d9e48 | ||
|
|
299410f8b4 | ||
|
|
07aa20a3cd | ||
|
|
ee323d97b4 | ||
|
|
d6b447f70a | ||
|
|
06cae36199 | ||
|
|
183404a5f8 | ||
|
|
6def7d6f70 | ||
|
|
097cae1f8c | ||
|
|
ba00311dd4 | ||
|
|
203fafdf7c | ||
|
|
62e90723d1 | ||
|
|
77372ccce1 | ||
|
|
849b608933 | ||
|
|
fdb4980b68 | ||
|
|
ff4f5e6c04 | ||
|
|
0bb3b67075 | ||
|
|
e16b06b44a | ||
|
|
ac9b23f00f | ||
|
|
f562bdd801 | ||
|
|
0c05942b45 | ||
|
|
9db3c93116 | ||
|
|
ce1f3365bb | ||
|
|
4ed5c3e4b8 | ||
|
|
9061180983 | ||
|
|
be970e4cea | ||
|
|
8f978c23b4 | ||
|
|
5f53c71b0c | ||
|
|
58020863a8 | ||
|
|
3ce3612047 | ||
|
|
44c9eebc4c | ||
|
|
cf6cc0e59d | ||
|
|
2b1fc8d07f | ||
|
|
e7d7ddd698 | ||
|
|
1d6bfc5dd6 | ||
|
|
0ccdbdcbe9 | ||
|
|
463346b867 | ||
|
|
f293700db3 | ||
|
|
b4e343369a | ||
|
|
da1d94775c | ||
|
|
28582b7e77 | ||
|
|
0f4a97f3a6 | ||
|
|
0f75234ed2 | ||
|
|
bc2556139a | ||
|
|
c1f52a5e5a | ||
|
|
ab24b3262c | ||
|
|
42994efa9d | ||
|
|
28aebaa06b | ||
|
|
44cf82caab | ||
|
|
a44ca39eb8 | ||
|
|
3f70c395e1 | ||
|
|
04383c0302 | ||
|
|
55d022eefc | ||
|
|
7d3917adb7 | ||
|
|
7eeeab8486 | ||
|
|
88a46ef59a | ||
|
|
e4a9dc25ec | ||
|
|
dfb563a330 | ||
|
|
329256712b | ||
|
|
16dbb88ee3 | ||
|
|
626f435edf | ||
|
|
d4dd5d7a61 | ||
|
|
de13b8b9ba | ||
|
|
0aabb0b364 | ||
|
|
3605072650 | ||
|
|
6272aabefb | ||
|
|
bf2446614c | ||
|
|
65b8220fe5 | ||
|
|
e0b544fc7e | ||
|
|
d296918fcd | ||
|
|
c9a2d439e5 | ||
|
|
73f36bcf33 | ||
|
|
a1bda1169e | ||
|
|
8f5089fd46 | ||
|
|
ae8b17e0fb | ||
|
|
3453690fc2 | ||
|
|
bc1f607c8e | ||
|
|
e0382139b6 | ||
|
|
65d280da8a | ||
|
|
e618070068 | ||
|
|
8181074238 | ||
|
|
b0e4aedd3d | ||
|
|
faa101224a | ||
|
|
eb7fc0fb26 | ||
|
|
a63a61e7fc | ||
|
|
223cc07139 | ||
|
|
62b0d371ee | ||
|
|
884b678bd0 | ||
|
|
2930e9cadb | ||
|
|
6103265488 | ||
|
|
c1f5dfc02e | ||
|
|
8e911a42f5 | ||
|
|
f41c1153d2 | ||
|
|
ff03171f55 | ||
|
|
5fe58dc9ae | ||
|
|
0c1cff52b2 | ||
|
|
8e29a52d71 | ||
|
|
12a0e73587 | ||
|
|
a3229ea965 | ||
|
|
43f40c4085 | ||
|
|
250e79f53c | ||
|
|
c8b2c19010 | ||
|
|
fe1add57f1 | ||
|
|
332f830cc2 | ||
|
|
ccd69dfcf7 | ||
|
|
7e13d09c3c | ||
|
|
71c0c62ee8 | ||
|
|
c599e60e75 | ||
|
|
f2241ba3de | ||
|
|
85fb240b69 | ||
|
|
71725f1b26 | ||
|
|
64d4c3f971 | ||
|
|
4c24b042d0 | ||
|
|
a43736b5c6 | ||
|
|
874c2a6212 | ||
|
|
94492b01cd | ||
|
|
ab6f8397ce | ||
|
|
b105088c28 | ||
|
|
1070805a0f | ||
|
|
799ae886c5 | ||
|
|
1276b23817 | ||
|
|
6ecb5b5c64 | ||
|
|
cbadf5e57c | ||
|
|
3a2deb0039 | ||
|
|
0480c2195c | ||
|
|
fde6a65933 | ||
|
|
6f6249690b | ||
|
|
c23aca78ba | ||
|
|
a195b52d34 | ||
|
|
09a13ef75f | ||
|
|
70e7534933 | ||
|
|
c95edbe25a | ||
|
|
4f9b4059a6 | ||
|
|
9be19bf811 | ||
|
|
0a728f805b | ||
|
|
c7276ee614 | ||
|
|
b419e17cac | ||
|
|
b9405bfb64 | ||
|
|
5d8856a1c7 | ||
|
|
076fd7e83c | ||
|
|
5073c0e9ad | ||
|
|
d95df7245c | ||
|
|
41360ceb71 | ||
|
|
042594ffca | ||
|
|
a8a9ee91bf | ||
|
|
726be664c8 | ||
|
|
c02b71e0e1 | ||
|
|
9cbef4ba4b | ||
|
|
24035329b8 | ||
|
|
457977f954 | ||
|
|
373dc5cadb | ||
|
|
a35cfe660e | ||
|
|
db666eec65 | ||
|
|
5b51a36c62 | ||
|
|
586473aaa7 | ||
|
|
2226ece4b7 | ||
|
|
950e41e8f7 | ||
|
|
49df8f4b43 | ||
|
|
2e9ad941c0 | ||
|
|
dec21f34e9 | ||
|
|
c8605b0cdf | ||
|
|
3d6d191d59 | ||
|
|
8f61278b33 | ||
|
|
5723c0c96f | ||
|
|
2830bdc075 | ||
|
|
37ab621a7e | ||
|
|
f9f286e896 | ||
|
|
e47545aa91 | ||
|
|
799417e0e8 | ||
|
|
cea5f0a30c | ||
|
|
ce61e80261 | ||
|
|
ec23124242 | ||
|
|
678cc56836 | ||
|
|
adf94b5e21 | ||
|
|
d4e40c376a | ||
|
|
3cbf678671 | ||
|
|
c7ec07ed47 | ||
|
|
754d7d099b | ||
|
|
c4cc3f176e | ||
|
|
79a2921e1d | ||
|
|
d64a61bab9 | ||
|
|
0ee78865e1 | ||
|
|
2c29b150c5 | ||
|
|
0801a2fbc4 | ||
|
|
af7ef25c9d | ||
|
|
f852474b56 | ||
|
|
54cfe5984b | ||
|
|
1bc07b1b4a | ||
|
|
b8d52a5aa8 | ||
|
|
af58b1039e | ||
|
|
a124f1dc38 | ||
|
|
fa3e6267fd | ||
|
|
011f86f368 | ||
|
|
0f6edc477e | ||
|
|
bade652c02 | ||
|
|
03ab067d3a | ||
|
|
e3a29ae82f | ||
|
|
3a9ce0f6ce | ||
|
|
d6d40b35a5 | ||
|
|
8baecb5911 | ||
|
|
3bb8fe9076 | ||
|
|
b93d66ce0b | ||
|
|
b71fde7ff3 | ||
|
|
5c7b060f19 | ||
|
|
1f544fff52 | ||
|
|
019520a793 | ||
|
|
29c22efed0 | ||
|
|
650519683c | ||
|
|
bcf5a586c7 | ||
|
|
5d8f5beb2a | ||
|
|
7e58627eaf | ||
|
|
89be0f80b9 | ||
|
|
e8b6b78dfa | ||
|
|
d5ea44a760 | ||
|
|
0638d43cae | ||
|
|
c5d133aaff | ||
|
|
067c2a6fe0 | ||
|
|
9e73a72b8b | ||
|
|
ae23b7611d | ||
|
|
e34a284036 | ||
|
|
116aae0828 | ||
|
|
f33c31aa83 | ||
|
|
c7a742d1de | ||
|
|
d0df3a2915 | ||
|
|
1c494803b0 | ||
|
|
0bd0a70564 | ||
|
|
5cd6470358 | ||
|
|
a7d0576736 | ||
|
|
76e9e2076e | ||
|
|
dcec5b5cb0 | ||
|
|
b4352ada27 | ||
|
|
76047e5351 | ||
|
|
60fedad3fe | ||
|
|
d57eb6a2fc | ||
|
|
c33d39f5d0 | ||
|
|
81aa17f3f0 | ||
|
|
8475201db8 | ||
|
|
40907ef1d8 | ||
|
|
b79fc53265 | ||
|
|
2972351e79 | ||
|
|
c82de08886 | ||
|
|
7806945965 | ||
|
|
9a6a0b0047 | ||
|
|
e0c94e3cbb | ||
|
|
9f328bdee3 | ||
|
|
7a96adf957 | ||
|
|
2111e19d59 | ||
|
|
d93cf08a27 | ||
|
|
a24b64f7ca | ||
|
|
625577f145 | ||
|
|
e13fa0d2d1 | ||
|
|
d470281a5e | ||
|
|
6021438e2e | ||
|
|
737b425aca | ||
|
|
d2a35453ef | ||
|
|
77160a76e8 | ||
|
|
f012a67182 | ||
|
|
2c5e4fad79 | ||
|
|
1486f5f620 | ||
|
|
eb1209cb00 | ||
|
|
bcdaf77a9c | ||
|
|
e8e97838ef | ||
|
|
bec3f309bd | ||
|
|
39bfbbbe0a | ||
|
|
57a98e7a5d | ||
|
|
ea697f2238 | ||
|
|
fd20a9218f | ||
|
|
b47794cbc1 | ||
|
|
c3ce44562e | ||
|
|
4f7803c384 | ||
|
|
6e313d1760 | ||
|
|
0f7a8a25ad | ||
|
|
c692b7847b | ||
|
|
207893fee8 | ||
|
|
9ec3574ff6 | ||
|
|
b0522836e6 | ||
|
|
c62396e389 | ||
|
|
d52e85f298 | ||
|
|
05ebae7329 | ||
|
|
b697bb656e | ||
|
|
4d7de2adce | ||
|
|
8a9528e787 | ||
|
|
6c6cba51fa | ||
|
|
28e23f9d87 | ||
|
|
e31192e97e | ||
|
|
26b7137b5c | ||
|
|
912200a2ec | ||
|
|
c42d0d7423 | ||
|
|
3da66a0fe3 | ||
|
|
41e1f8fbc3 | ||
|
|
130ac3c917 | ||
|
|
3774060d32 | ||
|
|
d8c8856548 | ||
|
|
efec00a550 | ||
|
|
3d3cf1d551 | ||
|
|
c52d17b6fb | ||
|
|
c0b9ef5990 | ||
|
|
e303159b98 | ||
|
|
f274b3c26b | ||
|
|
81fdc9a865 | ||
|
|
f40c9804f8 | ||
|
|
4d13d51038 | ||
|
|
5c4421dc38 | ||
|
|
76ef6a81ab | ||
|
|
a7b43d5b57 | ||
|
|
e4f50d4713 | ||
|
|
1e71237627 | ||
|
|
678c8f6bf6 | ||
|
|
786c27bbec | ||
|
|
710643d8cb | ||
|
|
e595aba189 | ||
|
|
ea67e94c47 | ||
|
|
b2c2067f7d | ||
|
|
4fc2d7b935 | ||
|
|
b1b9dd208b | ||
|
|
ee2f7c077f | ||
|
|
a385d6f4fd | ||
|
|
7031b7a3c7 | ||
|
|
0f0a5fba1f | ||
|
|
1d7af3f011 | ||
|
|
6fd85f97b3 | ||
|
|
a6d17f3813 | ||
|
|
4e830ea416 | ||
|
|
fc5c936272 | ||
|
|
b2af684c4d | ||
|
|
0446999c63 | ||
|
|
6920c39752 | ||
|
|
62ba8ed8d8 | ||
|
|
6eeef96886 | ||
|
|
4acf852650 | ||
|
|
9b3f1562a5 | ||
|
|
49774e46a3 | ||
|
|
ae2447393d | ||
|
|
3435192640 | ||
|
|
6ba4da9711 | ||
|
|
010a1d07d9 | ||
|
|
94d09b0014 | ||
|
|
d6ff442622 | ||
|
|
f7cc1abc8e | ||
|
|
bf7b1789ec | ||
|
|
cf9b482546 | ||
|
|
ad6da9bf37 | ||
|
|
d647884b91 | ||
|
|
5adaaa7f22 | ||
|
|
5b77543ab5 | ||
|
|
0ff215f78f | ||
|
|
ff787bb6ca | ||
|
|
334dfa5cb6 | ||
|
|
a17e628872 | ||
|
|
e87ce4cac5 | ||
|
|
8678e77c65 | ||
|
|
66f99f9ad7 | ||
|
|
b1cdcda8ed | ||
|
|
4c6084ab68 | ||
|
|
fa51ce6fb0 | ||
|
|
5708954268 | ||
|
|
5f23e9caa7 | ||
|
|
37372466cc | ||
|
|
442a7b0fcd | ||
|
|
0adde3e06d | ||
|
|
e0576502d9 | ||
|
|
f8e2fe5794 | ||
|
|
c10f32cc30 | ||
|
|
feb477ca48 | ||
|
|
2d1e4e8a1d | ||
|
|
ef166468e9 | ||
|
|
e58de99d0f | ||
|
|
56c7b7a8f1 | ||
|
|
2df0a54cb8 | ||
|
|
78a1d08a17 | ||
|
|
4effccf96e | ||
|
|
282505cde2 | ||
|
|
d2d4c19196 | ||
|
|
e6d42f21a2 | ||
|
|
71483e8b04 | ||
|
|
54a55a4a23 | ||
|
|
bad4cc12b4 | ||
|
|
6289acd109 | ||
|
|
4e8fc46475 | ||
|
|
4bd3329d07 | ||
|
|
4163841bcf | ||
|
|
7ad1171c5f | ||
|
|
6a32424a08 | ||
|
|
2c30714c6f | ||
|
|
aa22d4e569 | ||
|
|
ac020a401f | ||
|
|
be238ac743 | ||
|
|
f377e66f02 | ||
|
|
6ea79dff51 | ||
|
|
ba336de74b | ||
|
|
b6b3682d06 | ||
|
|
927d15f2d8 | ||
|
|
31f89121fe | ||
|
|
1189b66748 | ||
|
|
a9ceba690e | ||
|
|
f6370782ec | ||
|
|
4c0bd359f9 | ||
|
|
76491515d9 | ||
|
|
2977f7cf47 | ||
|
|
931bff608c | ||
|
|
fea445c902 | ||
|
|
027771b302 | ||
|
|
f2e7296d19 | ||
|
|
20ab2f039b | ||
|
|
158a0807d9 | ||
|
|
814ae5e840 | ||
|
|
37d76e9e06 | ||
|
|
6ba2bb5087 | ||
|
|
4faab518a7 | ||
|
|
e0c6f64788 | ||
|
|
211d27352a | ||
|
|
74ad7b9f8d | ||
|
|
c66a48e530 | ||
|
|
91ef8ca1ae | ||
|
|
9b6288e49c | ||
|
|
9eca4566bf | ||
|
|
907bf4ffdc | ||
|
|
5b194285f5 | ||
|
|
ae1269aa68 | ||
|
|
d1c3c85af8 | ||
|
|
143f259904 | ||
|
|
082b16d422 | ||
|
|
dd163b9923 | ||
|
|
7a5aad9cd8 | ||
|
|
9b813dd6a1 | ||
|
|
66f5f254d0 | ||
|
|
b40d53df84 | ||
|
|
0c54260762 | ||
|
|
5346f89f77 | ||
|
|
7909af6a56 | ||
|
|
ef37cb762d | ||
|
|
3799839539 | ||
|
|
81d496bac7 | ||
|
|
528c0d212a | ||
|
|
3b876b2d20 | ||
|
|
a7bd8d42e8 | ||
|
|
f8f14613f9 | ||
|
|
c9db8e0a26 | ||
|
|
8dd088d727 | ||
|
|
550f7201bb | ||
|
|
e1c14b04ad | ||
|
|
fb690e47e8 | ||
|
|
b537275707 | ||
|
|
545c72fca3 | ||
|
|
39413faff0 | ||
|
|
953cfd6ecd | ||
|
|
36919a25be | ||
|
|
7a66cb46a0 | ||
|
|
3a2926c22e | ||
|
|
591a8cd807 | ||
|
|
4a4c8c2404 | ||
|
|
9d2bb505ae | ||
|
|
2531cf549e | ||
|
|
80c395906b | ||
|
|
da12c84609 | ||
|
|
69c0a3cba3 | ||
|
|
124bce8f80 | ||
|
|
1d37f170fd | ||
|
|
99bdee5b12 | ||
|
|
5476a5984c | ||
|
|
74d93a6adc | ||
|
|
fb9524bba8 | ||
|
|
f56caa745a | ||
|
|
fc0ee2e41b |
No files matched your search
@@ -10,7 +10,7 @@ ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ENV \
|
||||
DEBUG=false \
|
||||
NODE_VERSION=v12.20.1 \
|
||||
NODE_VERSION=v12.22.0 \
|
||||
METEOR_RELEASE=1.10.2 \
|
||||
USE_EDGE=false \
|
||||
METEOR_EDGE=1.5-beta.17 \
|
||||
@@ -19,6 +19,7 @@ ENV \
|
||||
ARCHITECTURE=linux-x64 \
|
||||
SRC_PATH=./ \
|
||||
WITH_API=true \
|
||||
RESULTS_PER_PAGE="" \
|
||||
ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURES_BEFORE=3 \
|
||||
ACCOUNTS_LOCKOUT_KNOWN_USERS_PERIOD=60 \
|
||||
ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURE_WINDOW=15 \
|
||||
|
||||
@@ -81,7 +81,7 @@ parts:
|
||||
wekan:
|
||||
source: .
|
||||
plugin: nodejs
|
||||
node-engine: 12.20.1
|
||||
node-engine: 12.22.0
|
||||
node-packages:
|
||||
- node-gyp
|
||||
- node-pre-gyp
|
||||
|
||||
@@ -5,7 +5,7 @@ echo " with 'sudo dpkg-reconfigure locales' , so that MongoDB works correct
|
||||
echo " You can still use any other locale as your main locale."
|
||||
|
||||
#Below script installs newest node 8.x for Debian/Ubuntu/Mint.
|
||||
#NODE_VERSION=12.18.2
|
||||
#NODE_VERSION=12.21.0
|
||||
#X64NODE="https://nodejs.org/dist/v${NODE_VERSION}/node-v${NODE_VERSION}-linux-x64.tar.gz"
|
||||
|
||||
function pause(){
|
||||
@@ -80,7 +80,7 @@ do
|
||||
curl -0 -L https://npmjs.org/install.sh | sudo sh
|
||||
sudo chown -R $(id -u):$(id -g) $HOME/.npm
|
||||
sudo npm -g install n
|
||||
sudo n 12.18.2
|
||||
sudo n 12.21.0
|
||||
#curl -sL https://deb.nodesource.com/setup_8.x | sudo -E bash -
|
||||
#sudo apt-get install -y nodejs
|
||||
elif [[ "$OSTYPE" == "darwin"* ]]; then
|
||||
|
||||
@@ -83,7 +83,7 @@ parts:
|
||||
wekan:
|
||||
source: .
|
||||
plugin: nodejs
|
||||
node-engine: 12.20.1
|
||||
node-engine: 12.22.0
|
||||
node-packages:
|
||||
- node-gyp
|
||||
- node-pre-gyp
|
||||
|
||||
@@ -1,8 +1,10 @@
|
||||
## Issue
|
||||
|
||||
Email settings:
|
||||
- https://github.com/wekan/wekan/wiki/Troubleshooting-Mail
|
||||
|
||||
Add these issues to elsewhere:
|
||||
- Snap: https://github.com/wekan/wekan-snap/issues
|
||||
- LDAP: https://github.com/wekan/wekan-ldap/issues
|
||||
- SECURITY ISSUES: https://github.com/wekan/wekan/blob/master/SECURITY.md
|
||||
- UCS: https://github.com/wekan/univention/issues
|
||||
|
||||
Other Wekan issues can be added here.
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
on: [push]
|
||||
|
||||
jobs:
|
||||
zap_scan:
|
||||
runs-on: ubuntu-latest
|
||||
name: Scan the webapplication
|
||||
steps:
|
||||
- name: OWASP ZAP Scan
|
||||
runs-on: ubuntu-latest
|
||||
uses: zaproxy/action-baseline@v0.4.0
|
||||
with:
|
||||
target: 'https://boards.wekan.team/sign-in'
|
||||
@@ -31,5 +31,4 @@ Thumbs.db
|
||||
ehthumbs.db
|
||||
.eslintcache
|
||||
.meteor/local
|
||||
.meteor-1.6-snap/.meteor/local
|
||||
.devcontainer/docker-compose.extend.yml
|
||||
+1
-1
@@ -91,7 +91,6 @@ meteorhacks:aggregate@1.3.0
|
||||
wekan-markdown
|
||||
konecty:mongo-counter
|
||||
percolate:synced-cron
|
||||
easylogic:summernote
|
||||
cfs:filesystem
|
||||
tmeasday:check-npm-versions
|
||||
steffo:meteor-accounts-saml
|
||||
@@ -145,3 +144,4 @@ rajit:bootstrap3-datepicker-zh-cn
|
||||
rajit:bootstrap3-datepicker-zh-tw
|
||||
staringatlights:fast-render
|
||||
spacebars
|
||||
easylogic:summernote
|
||||
+1
-1
@@ -1 +1 @@
|
||||
METEOR@2.0
|
||||
METEOR@2.1
|
||||
+1
-1
@@ -3,7 +3,7 @@ sudo: required
|
||||
|
||||
env:
|
||||
TRAVIS_DOCKER_COMPOSE_VERSION: 1.24.0
|
||||
TRAVIS_NODE_VERSION: 12.20.1
|
||||
TRAVIS_NODE_VERSION: 12.22.0
|
||||
TRAVIS_NPM_VERSION: latest
|
||||
|
||||
before_install:
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ 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_EG:ar-EG, bg_BG:bg, en_GB:en-GB, es_AR:es-AR, es_CL:es-CL, es_PE:es-PE, es_MX:es-MX, es_TX:es-TX, es_PY:es-PY, el_GR:el, fi_FI:fi, hu_HU:hu, id_ID:id, mn_MN:mn, no:nb, lv_LV:lv, pt_BR:pt-BR, ro_RO:ro, sl_SI:sl, zh_CN:zh-CN, zh_TW:zh-TW, zh_HK:zh-HK
|
||||
lang_map = ar_EG:ar-EG, bg_BG:bg, en_GB:en-GB, es_AR:es-AR, 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, fa_IR:fa-IR, fi_FI:fi, hu_HU:hu, id_ID:id, mn_MN:mn, no:nb, lv_LV:lv, pt_BR:pt-BR, ro_RO:ro, sl_SI:sl, zh_CN:zh-CN, zh_TW:zh-TW, zh_HK:zh-HK
|
||||
|
||||
[wekan.application]
|
||||
file_filter = i18n/<lang>.i18n.json
|
||||
|
||||
+670
@@ -1,3 +1,673 @@
|
||||
# v5.17 2021-04-01 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix Link dialog closes card when clicking in dialog](https://github.com/wekan/wekan/commit/454d3b5bbeed6cef8ecface7e6094cabfcc4847c).
|
||||
Thanks to ryanMushy.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Added stable tag release script](https://github.com/wekan/wekan/commit/8dfb6916c5180f5d074748840d51dd04f9adb2bb).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.16 2021-04-01 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Added stable tag](https://github.com/wekan/wekan/commit/c40668be3fb9c35d44698f49ab06fec5bcabbe1b).
|
||||
Thanks to rynr and xet7.
|
||||
- [Added back Summernote editor. Removed emoji picker](https://github.com/wekan/wekan/commit/47ecc654b825a875074dfd4826c36e2c5c55f599).
|
||||
Thanks to ryanMushy and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.15 2021-03-31 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fixed card sort reset](https://github.com/wekan/wekan/pull/3686).
|
||||
Thanks to ednamaeG.
|
||||
- [Fix bug in My Cards and Global Search](https://github.com/wekan/wekan/pull/3687).
|
||||
Thanks to jrsupplee.
|
||||
- [Fix bug in Due Cards introduced by last bug fix](https://github.com/wekan/wekan/pull/3688).
|
||||
Thanks to jrsupplee.
|
||||
- [Fixed Bug: Move Swimlane to Archive does not work anymore. Fixed lint in
|
||||
router.js](https://github.com/wekan/wekan/commit/0b263cf582a9649ef72efbd289927105a27583af).
|
||||
Thanks to marcungeschikts and xet7.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- Updated sandstorm release script and added new node update script
|
||||
[Part 1](https://github.com/wekan/wekan/commit/34b6aa0858678da937eacf9a87878bbcb476fd4b),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/01de3f187c90af3ac94215ba7e8c7e780c98768d),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/1d3673e9d320926127b46383321023f149287d6d),
|
||||
[Part 4](https://github.com/wekan/wekan/commit/09b9f690b162ae2797d1996e82c96ed8b8c74221),
|
||||
[Part 5](https://github.com/wekan/wekan/commit/6819303047eab17b03a0c28108fd9a2cfde23d20).
|
||||
Thanks to xet7.
|
||||
- Updated to Node.js v12.22.0
|
||||
[Part 1](https://github.com/wekan/wekan/commit/7a9c3972642601e9d89d5e7a3816643f91448c63),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/c2b7525864048694c39f9cbe8f8c4cd96e36f7aa).
|
||||
Thanks to Node.js developers.
|
||||
- Fixed release website script
|
||||
[Part 1](https://github.com/wekan/wekan/commit/b6f60c08e55c2620fe6724ae2b5da0d9dfc9ec31),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/91dae9795ebd1a98b8ed12c68b78ad90a6983402).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.14 2021-03-29 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Clean-up Global Search, Due Cards, and My Cards. New environment variable `RESULTS_PER_PAGE` for search
|
||||
results](https://github.com/wekan/wekan/pull/3676).
|
||||
Thanks to jrsupplee.
|
||||
- [Added environment variable `RESULTS_PER_PAGE` to all Wekan platforms](https://github.com/wekan/wekan/commit/ba05f383ca29211c5474e06c5ba6673e712afe7a).
|
||||
Thanks to xet7.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated release scripts](https://github.com/wekan/wekan/commit/59580e4b0f711ca55e8cb0d73803a4ff8b56352d).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Require signed-in user for My Cards, Due Cards, and global search](https://github.com/wekan/wekan/pull/3677).
|
||||
Thanks to jrsupplee.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.13 2021-03-28 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fixed Sandstorm Wekan attachments upload](https://github.com/wekan/wekan/commit/d4a1611b86521cd5913277cfa2c86c43958eec7b).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.12 2021-03-28 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix HTTP not defined](https://github.com/wekan/wekan/commit/4c609161915cc46ebfccad3d9e7ffdecdef1f85c).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.11 2021-03-28 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Added emoji picker to card description edit and card comment edit.
|
||||
Removed and disabled Summernote wysiwyg editor, package-lock.json
|
||||
etc](https://github.com/wekan/wekan/commit/84fde1ecfc81e89ed1895cab3bcb328e4f166a87).
|
||||
Thanks to xet7.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated dependencies. Fixed lint](https://github.com/wekan/wekan/commit/4e1c0fdce82e3b4add8c4ffd1832752181573e88).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.10 2021-03-28 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Move swimlane from one board to another](https://github.com/wekan/wekan/pull/3674).
|
||||
Thanks to jrsupplee.
|
||||
- [Added translatable Move Swimlane popup title](https://github.com/wekan/wekan/commit/16665bccf912c5e907739c35f7ef5a376c81740e).
|
||||
Thanks to xet7.
|
||||
- [REST API: Export one attachment](https://github.com/wekan/wekan/pull/3673).
|
||||
Thanks to vagnernascimento.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated package-lock.json](https://github.com/wekan/wekan/commit/3145ec65a3defb8ac8d97aed7e43595f661f7100).
|
||||
Thanks to developers of dependencies.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.09 2021-03-26 Wekan release
|
||||
|
||||
This release adds the following improvements:
|
||||
|
||||
- [Replace edit icon by plus-square on new links](https://github.com/wekan/wekan/pull/3671).
|
||||
Thanks to sim51.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix openapi docs generation](https://github.com/wekan/wekan/pull/3672).
|
||||
Thanks to bentiss.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.08 2021-03-26 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Admin Panel/Settings/Accounts: Hide system messages of all users](https://github.com/wekan/wekan/commit/a249ffc8054189d8e3db9b4c8f082cc7ce7dcb52).
|
||||
Thanks to bbyszio, r4nc0r and xet7.
|
||||
|
||||
and adds the following improvements:
|
||||
|
||||
- [Add Trello attached links to the card description](https://github.com/wekan/wekan/pull/3669).
|
||||
Thanks to jrsupplee.
|
||||
- [Added package-lock.json and updated .gitignore](https://github.com/wekan/wekan/commit/d532a3591f338cec9a3839d43d9a1e9d69f59dc2).
|
||||
Thanks to xet7.
|
||||
|
||||
and adds the following new translations:
|
||||
|
||||
- [Added translation: español de América Latina](https://github.com/wekan/wekan/commit/ccc9efb2703efda4e199a861920b9ec88e634b59).
|
||||
Thanks to translators.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix typos in translations](https://github.com/wekan/wekan/commit/a0e1b6f918dbb252a13db05d6b9e1f832c28654f).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.07 2021-03-19 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fixed sort cards feature](https://github.com/wekan/wekan/pull/3662).
|
||||
Thanks to ednamaeG.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.06 2021-03-18 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fixed Bug: Calendar & parent cards URLs used absolute URLs](https://github.com/wekan/wekan/pull/3648).
|
||||
Thanks to Majed6.
|
||||
- [Fixed Bug: copy to clipboard uses pathname](https://github.com/wekan/wekan/pull/3661).
|
||||
Thanks to Majed6.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.05 2021-03-11 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Change URL scheme recognition for allowing abasurl to link](https://github.com/wekan/wekan/pull/3641).
|
||||
Thanks to tod31 and chrisi51.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.04 2021-03-07 Wekan release
|
||||
|
||||
This release adds the following speed improvements:
|
||||
|
||||
- [Speed improvement: Delete presences older than one week, and add database index to presences
|
||||
serverId](https://github.com/wekan/wekan/commit/9db3c931161adfbeb6fc52d3e4cf621fb9a4955f).
|
||||
Thanks to xet7.
|
||||
|
||||
and adds the following new features:
|
||||
|
||||
- [Added autolinking settings in Admin Panel](https://github.com/wekan/wekan/pull/3633).
|
||||
Thanks to chrisi51.
|
||||
- [Add custom field editing to the REST API](https://github.com/wekan/wekan/pull/3593).
|
||||
Thanks to dudeofawesome.
|
||||
- [Related to custom field editing, Fixed generating API docs and Wekan Custom Fields
|
||||
REST API](https://github.com/wekan/wekan/commit/0bb3b670753c6ba20b0ad63f63d273036f609ee5).
|
||||
Thanks to xet7.
|
||||
|
||||
and adds back the following platforms:
|
||||
|
||||
- [OpenPower Minicloud emergency maintenance has finished, so can now build Wekan for
|
||||
ppc64le](https://github.com/wekan/wekan/commit/ac9b23f00f10b0170b8693e1e997bfb54f807adc).
|
||||
Thanks to OpenPower Minicloud.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Try to fix Snap: Removed fibers multi arch from Snap, because Snap build servers do not build correctly with
|
||||
it](https://github.com/wekan/wekan/commit/a44ca39eb84508441f0f8bdac852745f417f12e7).
|
||||
Thanks to xet7.
|
||||
- [Fix search on labels server error](https://github.com/wekan/wekan/pull/3634).
|
||||
Thanks to jrsupplee.
|
||||
- [Fixed Bug: inconsistent use of relative/absolute URLs](https://github.com/wekan/wekan/pull/3635).
|
||||
Thanks to Majed6.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.03 2021-03-03 Wekan release
|
||||
|
||||
This release adds the following changes:
|
||||
|
||||
- [Hide email settings from Sandstorm Wekan Admin Panel](https://github.com/wekan/wekan/commit/626f435edf75fac68448ba2e14c62acb749f9c9b).
|
||||
Thanks to ocdtrekkie and xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Revert Removed extra imports of Meteor. Hopefully fixes email notifications and rules
|
||||
on old cars not working](https://github.com/wekan/wekan/commit/e4a9dc25ecc230829afea07dbb3915b96115f7f7).
|
||||
Thanks to xet7.
|
||||
- [Fixed Bug: Link at board title can not be edited](https://github.com/wekan/wekan/commit/7d3917adb79be09356d32612585029392bac1e49).
|
||||
Thanks to jonesrussell42, aiac, bbyszio and xet7.
|
||||
|
||||
Thanks to above GitHub and Wekan vanila.io community users for their contributions and translators for their translations.
|
||||
|
||||
# v5.02 2021-03-02 Wekan release
|
||||
|
||||
This release adds the following improvements:
|
||||
|
||||
- [Added sort to edit card REST API](https://github.com/wekan/wekan/pull/3618).
|
||||
Thanks to ChrisMagnuson.
|
||||
- [Add attachmentId to the Webhook data](https://github.com/wekan/wekan/pull/3620).
|
||||
Thanks to n8ores.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix SMTP port lost after upgrade. STMP settings are made only with environment variables on non-Sandstorm platforms.
|
||||
Note: Sending email on Sandstorm Wekan does not work yet](https://github.com/wekan/wekan/commit/65b8220fe53349695a335bdb8b9692f82d4b3329).
|
||||
Thanks to jrsupplee and xet7.
|
||||
- [Removed extra imports of Meteor](https://github.com/wekan/wekan/commit/de13b8b9bafbfb186a037ae20e845846b296ac69).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.01 2021-02-26 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix typo in activities code. Fixes can not edit Custom Field](https://github.com/wekan/wekan/pull/3610).
|
||||
Thanks to n8ores.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.00 2021-02-25 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fixed Unable to remove old Board, reappears](https://github.com/wekan/wekan/commit/332f830cc2e44ab66ca891690b09a425b9fd7e68).
|
||||
Thanks to chirrut2, uusijani, cimm, anicolaides, Philipoo0 and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.99 2021-02-25 Wekan release
|
||||
|
||||
This release fixes the following CRITICAL SECURITY ISSUES:
|
||||
|
||||
- [Fixed SMTP password visible to Admin at Admin Panel by using browser inspect
|
||||
to see behind asterisks](https://github.com/wekan/wekan/commit/71725f1b262b385162b2544f10658a0bc22f6b41).
|
||||
Thanks to Georg Krause and xet7.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Update wekan/releases/up.sh script: Can not build ppc64le version because OpenPower Minicloud
|
||||
is having emergency maintenance](https://github.com/wekan/wekan/commit/a43736b5c6196c65770d8ae17af927406dce2c43).
|
||||
Thanks to xet7.
|
||||
- [Updated to Meteor 2.1](https://github.com/wekan/wekan/commit/f2241ba3de82e393161ee1c456e1a947c6bdb5fc).
|
||||
Thanks to Meteor developers.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.98 2021-02-24 Wekan release
|
||||
|
||||
This release adds the following CRITICAL SECURITY FIXES:
|
||||
|
||||
- [Updated Node.js to v12.21.0](https://github.com/wekan/wekan/commit/fde6a6593379277d601408ec83f6f5a4347afef0).
|
||||
Thanks to Node.js developers.
|
||||
|
||||
and adds the following new features:
|
||||
|
||||
- [Added sort feature for viewing of cards](https://github.com/wekan/wekan/pull/3586).
|
||||
Thanks to ednamaeG.
|
||||
- [Made sort cards feature translatable](https://github.com/wekan/wekan/commit/09a13ef75f478b0fc02ae3cdbfe918367664aa0c).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix development script to escape character](https://github.com/wekan/wekan/commit/2e9ad941c0b63b384ee215548a3f31b4a635b28b).
|
||||
Thanks to xet7.
|
||||
- [Fix bugs with customFields in Webhooks](https://github.com/wekan/wekan/pull/3584).
|
||||
Thanks to n8ores.
|
||||
|
||||
and adds the following improvements:
|
||||
|
||||
- [Global Search Updates](https://github.com/wekan/wekan/pull/3597).
|
||||
Thanks to jrsupplee.
|
||||
- [Updated GitHub issue template links](https://github.com/wekan/wekan/commit/c23aca78babd51857271134aed9247615b87b895).
|
||||
Thanks to atlantsecurity and xet7.
|
||||
- [Admin Panel/People/People/New User: Added Initials](https://github.com/wekan/wekan/commit/3a2deb00399eb213472ef169826bd15ad655e490).
|
||||
Thanks to xet7.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Update release-bundle.sh script: Can not build ppc64le version because OpenPower Minicloud
|
||||
is having emergency maintenance](https://github.com/wekan/wekan/commit/799ae886c5fedad3bafa18a14f8fbbca7ad2c227).
|
||||
Thanks to xet7.
|
||||
- [Update release.sh script: Also build Sandstorm version of Wekan with same
|
||||
script](https://github.com/wekan/wekan/commit/b105088c2858bc04120551a8a8e5a75f187041e5).
|
||||
Thanks to xet7.
|
||||
|
||||
and adds the following new translations:
|
||||
|
||||
- [Added translation: Persian (Iran)](https://github.com/wekan/wekan/commit/0a728f805b336588741ca93f2ecbd1ca31ee53f2).
|
||||
Thanks to translators.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.97 2021-02-24 Wekan release
|
||||
|
||||
Release skipped, because not all required files had new version number updated yet.
|
||||
|
||||
# v4.96 2021-02-13 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Add /api/boards_count endpoint for statistics](https://github.com/wekan/wekan/pull/3556).
|
||||
Thanks to pichouk.
|
||||
- [Added possibility to specify hours in single digits in 24 hour format](https://github.com/wekan/wekan/pull/3557).
|
||||
Thanks to lindhork.
|
||||
- [Added replacement from comma to dot](https://github.com/wekan/wekan/pull/3564).
|
||||
Thanks to lindhork.
|
||||
|
||||
and adds the following improvements:
|
||||
|
||||
- [Checklistitems are now inserted always at the end of the checklist](https://github.com/wekan/wekan/pull/3551).
|
||||
Thanks to mfilser.
|
||||
- [Teams/Organizations: Added more code to Admin Panel for saving and editing. In Progress, does not work yet](https://github.com/wekan/wekan/commit/1bc07b1b4a3e8cd1a177f3f1776ed8e189bc627a).
|
||||
Thanks to xet7.
|
||||
- [Mobile View, list header is now always at top and only lists/cards view have a scroll area](https://github.com/wekan/wekan/pull/3563).
|
||||
Thanks to mfilser.
|
||||
- [Added ChangeLog update script](https://github.com/wekan/wekan/commit/c7ec07ed4748fe9b00f622af7472fd291cf1a3ce).
|
||||
Thanks to xet7.
|
||||
- [Helm: Made SecretEnv a secret and added default mongodb name as Wekan](https://github.com/wekan/wekan/pull/3570).
|
||||
Thanks to meerkampdvv.
|
||||
- [Checklist drag handle now at the left side (same place as for the checklist items)](https://github.com/wekan/wekan/pull/3571).
|
||||
Thanks to mfilser.
|
||||
- [Lists, show also 0 cards at column description](https://github.com/wekan/wekan/pull/3572).
|
||||
Thanks to mfilser.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated Node.js to v12.20.2](https://github.com/wekan/wekan/commit/011f86f368a83c2e70f597c11ec60ec857e0fab0).
|
||||
Thanks to Node.js developers.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Minicard, remove red line below member avatar icon](https://github.com/wekan/wekan/pull/3560).
|
||||
Thanks to mfilser.
|
||||
- [Added padding](https://github.com/wekan/wekan/pull/3559).
|
||||
Thanks to lindhork.
|
||||
- [Changed default behaviour for BIGEVENTS that no activity matches it](https://github.com/wekan/wekan/pull/3561).
|
||||
Thanks to bronger.
|
||||
- [Modern theme: Remove font color when the card has a color](https://github.com/wekan/wekan/pull/3569).
|
||||
Thanks to helioguardabaxo.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.95 2021-02-08 Wekan release
|
||||
|
||||
This release adds back the following features:
|
||||
|
||||
- [Added back Custom Fields sorting, because it now does not prevent loading boards](https://github.com/wekan/wekan/pull/3547).
|
||||
Thanks to mfilser.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/1c494803b091d987e26ccb783432434e7fee15a5).
|
||||
Thanks to xet7.
|
||||
- [Fix typo](https://github.com/wekan/wekan/commit/0bd0a70564d3dda67706deb1bbfbd1d5a96f811f).
|
||||
Thanks to xet7.
|
||||
- Updated release scripts
|
||||
[Part 1](https://github.com/wekan/wekan/commit/d0df3a2915d08b255d7ab92f9bcac195a1e7f442),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/e34a2840366351c0e069515ac2210db3911dbc0f).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.94 2021-02-08 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Settings, "Show cards count" now works at mobile view too](https://github.com/wekan/wekan/pull/3545).
|
||||
Thanks to mfilser.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/b4352ada27545fadc425ca7024532aede3cc1a6f).
|
||||
Thanks to developers of dependencies.
|
||||
- [Update release scripts](https://github.com/wekan/wekan/commit/dcec5b5cb05ac9e0dfae8f360def169f5f9b6fa2).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix bug in adding new users](https://github.com/wekan/wekan/pull/3544).
|
||||
Thanks to jrsupplee.
|
||||
- [Fixed Board does not load, by disabling Custom Fields sorting](https://github.com/wekan/wekan/commit/d57eb6a2fc73c7b25c957ad42b5f7a06f680e1a1).
|
||||
Thanks to marcungeschikts, olivierlambert and xet7.
|
||||
- [Fixed lint](https://github.com/wekan/wekan/commit/60fedad3fe384a2b0652941e57ecaa5fc4b7897a).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# 4.93 2021-02-06 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Add the ability to call get_user operation with username](https://github.com/wekan/wekan/pull/3530).
|
||||
Thanks to magicbelette.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated Ubuntu base image in Dockerfile](https://github.com/wekan/wekan/commit/bcdaf77a9c675530cfa21d038e8abd7c62aef70d).
|
||||
Thanks to Ubuntu and xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Set the language on `TAPi18n` when user selects language](https://github.com/wekan/wekan/pull/3525).
|
||||
Thanks to jrsupplee.
|
||||
- [Fix bug in `uniqueTitle`](https://github.com/wekan/wekan/pull/3526).
|
||||
Thanks to jrsupplee.
|
||||
- [Fixed file permissions in build scripts](https://github.com/wekan/wekan/commit/ea697f2238842893953dee76bed03ffd5b4a107e).
|
||||
Thanks to xet7.
|
||||
- [Red line below the avatar now correctly on FireFox](https://github.com/wekan/wekan/pull/3532).
|
||||
Thanks to mfilser.
|
||||
- [Notifications, enable line wrapping](https://github.com/wekan/wekan/pull/3533).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.92 2021-02-03 Wekan release
|
||||
|
||||
This release adds the following improvements:
|
||||
|
||||
- [Import user mapping improvements](https://github.com/wekan/wekan/pull/3510).
|
||||
Thanks to jrsupplee.
|
||||
- Added Createtoken API.
|
||||
[Part 1](https://github.com/wekan/wekan/pull/3520),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/3774060d32abcfee17dc1c31958d4673794d8619).
|
||||
Thanks to magicbelette and xet7.
|
||||
- Sorted archives.
|
||||
[Part 1](https://github.com/wekan/wekan/pull/3518),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/3da66a0fe30c2b54b63e5d098232b375d899925e).
|
||||
Thanks to bronger, jrsupplee and xet7.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/05ebae7329ba0dd3fe9b04cd63b1f983830cdeee).
|
||||
Thanks to developers of dependencies.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Don't reload page when returning default sort](https://github.com/wekan/wekan/pull/3509).
|
||||
Thanks to jrsupplee.
|
||||
- [Avatar overlaped notifications](https://github.com/wekan/wekan/pull/3516).
|
||||
Thanks to mfilser.
|
||||
- [Hopeful fix for i18n not working in `onRendered()`](https://github.com/wekan/wekan/pull/3519).
|
||||
Thanks to jrsupplee.
|
||||
- [Disable some console.log code, that is only needed while developing](https://github.com/wekan/wekan/commit/f40c9804f848fdb91229c5718ad97495337109ba).
|
||||
Thanks to xet7.
|
||||
- [Try fix removed nonexistent document error](https://github.com/wekan/wekan/commit/f274b3c26be60813829dcf2b0e68a8dd876ff614).
|
||||
Thanks to Brulf, TheMasterFX and xet7.
|
||||
- [Fixed Cards and CustomFields sorted alphabetically](https://github.com/wekan/wekan/pull/3521).
|
||||
Thanks to mfilser.
|
||||
- [Notifications avatar overlaped at mobile view](https://github.com/wekan/wekan/pull/3523).
|
||||
Thanks to mfilser.
|
||||
|
||||
and improves some security related info:
|
||||
|
||||
- [Added badge for CII Best Practices](https://github.com/wekan/wekan/commit/ee2f7c077fe56d6fedb8b75ae3cba6bab56f9363).
|
||||
Thanks to CII and xet7.
|
||||
- [Added PGP public key for sending security vulnerability reports](https://github.com/wekan/wekan/commit/a385d6f4fd76e2bb0f374963848513b9373d6b5a).
|
||||
Thanks to xet7.
|
||||
- [Updated security report email address](https://github.com/wekan/wekan/commit/7031b7a3c77acc0ddeabe436572dd4057001e9f5).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.91 2021-01-29 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Use `new RegExp(...)` to define a regex](https://github.com/wekan/wekan/pull/3505).
|
||||
Thanks to jrsupplee.
|
||||
- [Fixed typos in docker-compose.yml](https://github.com/wekan/wekan/commit/4acf8526509ffe852e6e48e3503560448239d8cd).
|
||||
Thanks to farfoodyou and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.90 2021-01-28 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Create unique board names when importing](https://github.com/wekan/wekan/pull/3499).
|
||||
Thanks to jrsupplee.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Added missing backtick quotes](https://github.com/wekan/wekan/commit/bf7b1789ec16e3c52397318c799ec5a0fc2de3a5).
|
||||
Thanks to xet7.
|
||||
- [Fix some bugs when importing Wekan JSON](https://github.com/wekan/wekan/pull/3500).
|
||||
Thanks to jrsupplee.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.89 2021-01-28 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Try to fix quotes in Global Search](https://github.com/wekan/wekan/commit/0ff215f78f03c81d153dfc0ffa08fac94b542ec2).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.88 2021-01-28 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Additional URL schemes: SolidWorks PDM (conisio:) and abas ERP (abasurl:)](https://github.com/wekan/wekan/pull/3487).
|
||||
Thanks to tod31.
|
||||
|
||||
and adds the following improvements:
|
||||
|
||||
- [Mobile and Desktop have now the same Quick Access view + scrollable](https://github.com/wekan/wekan/pull/3491).
|
||||
Thanks to mfilser.
|
||||
- [Global Search Update](https://github.com/wekan/wekan/pull/3492).
|
||||
Thanks to jrsupplee.
|
||||
- [Added many more fields to Export to Excel, and better formatting. Does not yet have all
|
||||
fields](https://github.com/wekan/wekan/commit/37372466ccd15c7d5d4a55510b349fac0953c425).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Changed method to create initials same as others for new user of oidc](https://github.com/wekan/wekan/pull/3489).
|
||||
Thanks to sato-64bit.
|
||||
- [Removed quotes from docker-compose.yml settings](https://github.com/wekan/wekan/commit/b1cdcda8ed78d48505a8da5180d7aed46a24fd64).
|
||||
Thanks to XL-Reaper, Vinc89 and xet7.
|
||||
- [Repair LDAP_REJECT_UNAUTHORIZED=false CVE-2021-3309](https://github.com/wekan/wekan/pull/3497).
|
||||
Thanks to robert-scheck.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.87 2021-01-26 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Reject by default LDAP connections not authorized via CA trust store](https://github.com/wekan/wekan/pull/3483).
|
||||
Thanks to robert-scheck.
|
||||
- [Handle '\n' line breaks in PEM-encoded SSL/TLS certificates](https://github.com/wekan/wekan/pull/3485).
|
||||
Thanks to robert-scheck.
|
||||
|
||||
and adds the following improvements
|
||||
|
||||
- [Try parallel build of releases, does it work](https://github.com/wekan/wekan/commit/be238ac7439ce38b4403d9a611dec9bb421a856f).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.86 2021-01-25 Wekan release
|
||||
|
||||
This release adds the following improvements:
|
||||
|
||||
- [Added PWA related category, orientation, screenshots, maskable icon and
|
||||
IARC rating ID](https://github.com/wekan/wekan/commit/027771b3021a709d9049015e7d7e6faccf1ad7f3).
|
||||
Thanks to xet7.
|
||||
- [Added PWA related monochrome icon](https://github.com/wekan/wekan/commit/2977f7cf47626b429159cb7b7496919c07ece914).
|
||||
Thanks to xet7.
|
||||
- [Mention Wekan GitHub Discussions at readme](https://github.com/wekan/wekan/commit/4c0bd359f921ae0ea722f78946fcc1168e8b939e).
|
||||
Thanks to xet7.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Use Node 12.20.1 in rebuild-wekan.sh](https://github.com/wekan/wekan/commit/37d76e9e061d31c11fca8e704e9b4c54f17c0023).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Move call to URL search to onRendered](https://github.com/wekan/wekan/pull/3478).
|
||||
Thanks to jrsupplee.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.85 2021-01-23 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Option to add custom field to all cards](https://github.com/wekan/wekan/pulls/3466).
|
||||
Thanks to jrsupplee.
|
||||
- [Added checkbox as an option to custom field create dialog](https://github.com/wekan/wekan/pull/3472).
|
||||
Thanks to jrsupplee.
|
||||
|
||||
and adds the following improvements:
|
||||
|
||||
- [Display My Cards lists using inline-grid](https://github.com/wekan/wekan/pull/3474).
|
||||
Thanks to jrsupplee.
|
||||
- [Added board title link and background color to My Cards](https://github.com/wekan/wekan/pull/3471).
|
||||
Thanks to helioguardabaxo.
|
||||
- [Use simple border at My Cards](https://github.com/wekan/wekan/pull/3475).
|
||||
Thanks to helioguardabaxo.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- Updated dependencies.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/7a66cb46a0ec334f4e95a73322641ba029f770ad),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/953cfd6ecd291196ce2ad1d4a5eac19ca21a20d9).
|
||||
Thanks to developers of dependencies.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [WIP Limit: Limited number of cards highlighting to true overbooking](https://github.com/wekan/wekan/pull/3468).
|
||||
Thanks to bronger.
|
||||
- [Revert table-cell back to inline-block at my-cards-list-wrapper](https://github.com/wekan/wekan/commit/da12c84609674bdf5121ad6b74c97c65b9fc0164).
|
||||
Thanks to jrsupplee and xet7.
|
||||
- [Fix for search operators with uppercase letters](https://github.com/wekan/wekan/pull/3470).
|
||||
Thanks to jrsupplee.
|
||||
- [Boards.copyTitle - escape string used in regex](https://github.com/wekan/wekan/pull/3473).
|
||||
Thanks to jrsupplee.
|
||||
- [Bug fix: import regex escape function](https://github.com/wekan/wekan/pull/3476).
|
||||
Thanks to jrsupplee.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v4.84 2021-01-22 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
+8
-5
@@ -1,4 +1,4 @@
|
||||
FROM quay.io/wekan/ubuntu:groovy-20201125.2
|
||||
FROM quay.io/wekan/ubuntu:groovy-20210115
|
||||
LABEL maintainer="wekan"
|
||||
|
||||
# 2020-12-03:
|
||||
@@ -12,7 +12,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=v12.20.1 \
|
||||
NODE_VERSION=v12.22.0 \
|
||||
METEOR_RELEASE=1.10.2 \
|
||||
USE_EDGE=false \
|
||||
METEOR_EDGE=1.5-beta.17 \
|
||||
@@ -21,6 +21,7 @@ ENV BUILD_DEPS="apt-utils libarchive-tools gnupg gosu wget curl bzip2 g++ build-
|
||||
ARCHITECTURE=linux-x64 \
|
||||
SRC_PATH=./ \
|
||||
WITH_API=true \
|
||||
RESULTS_PER_PAGE="" \
|
||||
ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURES_BEFORE=3 \
|
||||
ACCOUNTS_LOCKOUT_KNOWN_USERS_PERIOD=60 \
|
||||
ACCOUNTS_LOCKOUT_KNOWN_USERS_FAILURE_WINDOW=15 \
|
||||
@@ -274,11 +275,12 @@ RUN \
|
||||
mkdir -p /home/wekan/.npm && \
|
||||
chown wekan --recursive /home/wekan/.npm /home/wekan/.config /home/wekan/.meteor && \
|
||||
#gosu wekan:wekan /home/wekan/.meteor/meteor add standard-minifier-js && \
|
||||
chmod u+w *.json && \
|
||||
gosu wekan:wekan npm install && \
|
||||
gosu wekan:wekan /home/wekan/.meteor/meteor build --directory /home/wekan/app_build && \
|
||||
cp /home/wekan/app/fix-download-unicode/cfs_access-point.txt /home/wekan/app_build/bundle/programs/server/packages/cfs_access-point.js && \
|
||||
#cp /home/wekan/app/fix-download-unicode/cfs_access-point.txt /home/wekan/app_build/bundle/programs/server/packages/cfs_access-point.js && \
|
||||
#rm /home/wekan/app_build/bundle/programs/server/npm/node_modules/meteor/rajit_bootstrap3-datepicker/lib/bootstrap-datepicker/node_modules/phantomjs-prebuilt/lib/phantom/bin/phantomjs && \
|
||||
chown wekan /home/wekan/app_build/bundle/programs/server/packages/cfs_access-point.js && \
|
||||
#chown wekan /home/wekan/app_build/bundle/programs/server/packages/cfs_access-point.js && \
|
||||
#Removed binary version of bcrypt because of security vulnerability that is not fixed yet.
|
||||
#https://github.com/wekan/wekan/commit/4b2010213907c61b0e0482ab55abb06f6a668eac
|
||||
#https://github.com/wekan/wekan/commit/7eeabf14be3c63fae2226e561ef8a0c1390c8d3c
|
||||
@@ -291,10 +293,11 @@ RUN \
|
||||
#find . -name "*phantomjs*" | xargs rm -rf && \
|
||||
#
|
||||
cd /home/wekan/app_build/bundle/programs/server/ && \
|
||||
chmod u+w *.json && \
|
||||
gosu wekan:wekan npm install && \
|
||||
#gosu wekan:wekan npm install bcrypt && \
|
||||
# Remove legacy webbroser bundle, so that Wekan works also at Android Firefox, iOS Safari, etc.
|
||||
rm -rf /home/wekan/app_build/bundle/programs/web.browser.legacy && \
|
||||
rm -rf /home/wekan/app_build/bundle/programs/web.browser.legacy && \
|
||||
mv /home/wekan/app_build/bundle /build && \
|
||||
\
|
||||
# Put back the original tar
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ FROM amd64/alpine:3.7 AS builder
|
||||
ENV QEMU_VERSION=v4.2.0-6 \
|
||||
QEMU_ARCHITECTURE=aarch64 \
|
||||
NODE_ARCHITECTURE=linux-arm64 \
|
||||
NODE_VERSION=v12.20.1 \
|
||||
NODE_VERSION=v12.22.0 \
|
||||
WEKAN_VERSION=3.96 \
|
||||
WEKAN_ARCHITECTURE=arm64
|
||||
|
||||
@@ -40,7 +40,7 @@ LABEL maintainer="wekan"
|
||||
# Set the environment variables (defaults where required)
|
||||
ENV QEMU_ARCHITECTURE=aarch64 \
|
||||
NODE_ARCHITECTURE=linux-arm64 \
|
||||
NODE_VERSION=v12.20.1 \
|
||||
NODE_VERSION=v12.22.0 \
|
||||
NODE_ENV=production \
|
||||
NPM_VERSION=latest \
|
||||
WITH_API=true \
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
[](https://gitpod.io/#https://github.com/wekan/wekan)
|
||||
[](https://gitpod.io/#https://github.com/wekan/wekan)
|
||||
|
||||
# Wekan - Open Source kanban
|
||||
|
||||
@@ -12,6 +12,7 @@
|
||||
[](https://david-dm.org/wekan/wekan)
|
||||
[](https://www.openhub.net/p/wekan)
|
||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fwekan%2Fwekan?ref=badge_shield)
|
||||
[](https://bestpractices.coreinfrastructure.org/projects/4619)
|
||||
|
||||
## [Translate Wekan at Transifex](https://transifex.com/wekan/wekan)
|
||||
|
||||
@@ -20,19 +21,18 @@ New English strings of new features can be added as PRs to edge branch file weka
|
||||
|
||||
## [Wekan feature requests and bugs](https://github.com/wekan/wekan/issues)
|
||||
|
||||
Please add most of your questions as GitHub issue: [Wekan feature requests and bugs](https://github.com/wekan/wekan/issues).
|
||||
Please add most of your questions as GitHub issue: [Wekan Feature Requests and Bugs](https://github.com/wekan/wekan/issues).
|
||||
It's better than at chat where details get lost when chat scrolls up.
|
||||
|
||||
## Chat
|
||||
|
||||
[![Wekan Chat][vanila_badge]][wekan_chat] - Most Wekan community and developers are here. Works on webbrowser
|
||||
and PWA app that can be added as icon on Android and bookmark on iOS, used like native app.
|
||||
[Discussions][discussions] - Wekan Community GitHub Discussions, that are not [Feature Requests and Bugs](https://github.com/wekan/wekan/issues).
|
||||
|
||||
[Wekan IRC FAQ](https://github.com/wekan/wekan/wiki/IRC-FAQ)
|
||||
|
||||
## FAQ
|
||||
|
||||
**NOTE**:
|
||||
**NOTE**:
|
||||
- Please read the [FAQ](https://github.com/wekan/wekan/wiki/FAQ) first
|
||||
- Please don't feed the [trolls](https://github.com/wekan/wekan/wiki/FAQ#why-am-i-called-a-troll) and [spammers](https://github.com/wekan/wekan/wiki/FAQ#why-am-i-called-a-spammer) that are mentioned in the FAQ :)
|
||||
|
||||
@@ -52,7 +52,7 @@ 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 13k users using Wekan in their company.
|
||||
- Wekan has been [translated](https://transifex.com/wekan/wekan) to about 60 languages.
|
||||
- Wekan has been [translated](https://transifex.com/wekan/wekan) to about 62 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.
|
||||
@@ -64,7 +64,7 @@ that by providing one-click installation on various platforms.
|
||||
[More Platforms](https://github.com/wekan/wekan/wiki/Platforms), bundle for RasPi3 ARM and other CPUs where Node.js and MongoDB exists.
|
||||
- 1 GB RAM minimum free for Wekan. Production server should have minimum total 4 GB RAM.
|
||||
For thousands of users, for example with [Docker](https://github.com/wekan/wekan/blob/master/docker-compose.yml): 3 frontend servers,
|
||||
each having 2 CPU and 2 wekan-app containers. One backend wekan-db server with many CPUs.
|
||||
each having 2 CPU and 2 wekan-app containers. One backend wekan-db server with many CPUs.
|
||||
- Enough disk space and alerts about low disk space. If you run out disk space, MongoDB database gets corrupted.
|
||||
- SECURITY: Updating to newest Wekan version very often. Please check you do not have automatic updates of Sandstorm or Snap turned off.
|
||||
Old versions have security issues because of old versions Node.js etc. Only newest Wekan is supported.
|
||||
@@ -114,8 +114,6 @@ with [Meteor](https://www.meteor.com).
|
||||
[translate_wekan]: https://www.transifex.com/wekan/wekan/
|
||||
[open_source]: https://en.wikipedia.org/wiki/Open-source_software
|
||||
[free_software]: https://en.wikipedia.org/wiki/Free_software
|
||||
[vanila_badge]: https://vanila.io/img/join-chat-button2.png
|
||||
[wekan_chat]: https://community.vanila.io/wekan
|
||||
|
||||
[discussions]: https://github.com/wekan/wekan/discussions
|
||||
|
||||
[](https://app.fossa.io/projects/git%2Bgithub.com%2Fwekan%2Fwekan?ref=badge_large)
|
||||
+3
-3
@@ -1,10 +1,10 @@
|
||||
Security is very important to us. If you discover any issue regarding security, please disclose
|
||||
the information responsibly by sending an email to security (at) wekan.team and not by
|
||||
the information responsibly by sending an email to support (at) wekan.team using
|
||||
[this PGP public key](support-at-wekan.team_pgp-publickey.asc) and not by
|
||||
creating a GitHub issue. We will respond swiftly to fix verifiable security issues.
|
||||
|
||||
We thank you with a place at our hall of fame page, that is
|
||||
at https://wekan.github.io/hall-of-fame . Others have just posted public GitHub issue,
|
||||
so they are not at that hall-of-fame page.
|
||||
at https://wekan.github.io/hall-of-fame
|
||||
|
||||
## How should reports be formatted?
|
||||
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
|
||||
appVersion: "v4.84.0"
|
||||
appVersion: "v5.17.0"
|
||||
files:
|
||||
userUploads:
|
||||
- README.md
|
||||
|
||||
@@ -82,7 +82,7 @@ template(name="activity")
|
||||
+viewer
|
||||
= activity.checklist.title
|
||||
else
|
||||
a.activity-checklist(href="{{ activity.card.absoluteUrl }}")
|
||||
a.activity-checklist(href="{{ activity.card.originRelativeUrl }}")
|
||||
+viewer
|
||||
= activity.checklist.title
|
||||
|
||||
@@ -103,7 +103,7 @@ template(name="activity")
|
||||
|
||||
if($eq activity.activityType 'addChecklistItem')
|
||||
| {{{_ 'activity-checklist-item-added' (sanitize activity.checklist.title) cardLink}}}.
|
||||
.activity-checklist(href="{{ activity.card.absoluteUrl }}")
|
||||
.activity-checklist(href="{{ activity.card.originRelativeUrl }}")
|
||||
+viewer
|
||||
= activity.checklistItem.title
|
||||
|
||||
@@ -139,7 +139,7 @@ template(name="activity")
|
||||
//- if we are not in card mode we only display a summary of the comment
|
||||
if($eq activity.activityType 'addComment')
|
||||
| {{{_ 'activity-on' cardLink}}}
|
||||
a.activity-comment(href="{{ activity.card.absoluteUrl }}")
|
||||
a.activity-comment(href="{{ activity.card.originRelativeUrl }}")
|
||||
+viewer
|
||||
= activity.comment.text
|
||||
|
||||
|
||||
@@ -243,7 +243,7 @@ function createCardLink(card) {
|
||||
Blaze.toHTML(
|
||||
HTML.A(
|
||||
{
|
||||
href: card.absoluteUrl(),
|
||||
href: card.originRelativeUrl(),
|
||||
class: 'action-card',
|
||||
},
|
||||
sanitizeXss(card.title),
|
||||
@@ -260,7 +260,7 @@ function createBoardLink(board, list) {
|
||||
Blaze.toHTML(
|
||||
HTML.A(
|
||||
{
|
||||
href: board.absoluteUrl(),
|
||||
href: board.originRelativeUrl(),
|
||||
class: 'action-board',
|
||||
},
|
||||
sanitizeXss(text),
|
||||
|
||||
@@ -11,7 +11,7 @@ BlazeComponent.extendComponent({
|
||||
return Boards.find(
|
||||
{ archived: true },
|
||||
{
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
sort: { archivedAt: -1, modifiedAt: -1 },
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
@@ -360,7 +360,7 @@ BlazeComponent.extendComponent({
|
||||
end: end || card.endAt,
|
||||
allDay:
|
||||
Math.abs(end.getTime() - start.getTime()) / 1000 === 24 * 3600,
|
||||
url: FlowRouter.url('card', {
|
||||
url: FlowRouter.path('card', {
|
||||
boardId: currentBoard._id,
|
||||
slug: currentBoard.slug,
|
||||
cardId: card._id,
|
||||
|
||||
@@ -654,7 +654,6 @@ setBoardClear(color1,color2)
|
||||
|
||||
/* Card changes */
|
||||
.minicard
|
||||
background: #FFF
|
||||
padding: 15px 15px 10px
|
||||
box-shadow: 0 3px 8px rgba(0,0,0,.05)
|
||||
|
||||
|
||||
@@ -1,14 +1,17 @@
|
||||
template(name="boardHeaderBar")
|
||||
h1.header-board-menu
|
||||
with currentBoard
|
||||
a(class="{{#if currentUser.isBoardAdmin}}js-edit-board-title{{else}}is-disabled{{/if}}")
|
||||
+viewer
|
||||
= title
|
||||
+viewer
|
||||
= title
|
||||
|
||||
.board-header-btns.left
|
||||
unless isMiniScreen
|
||||
if currentBoard
|
||||
if currentUser
|
||||
with currentBoard
|
||||
a.board-header-btn(class="{{#if currentUser.isBoardAdmin}}js-edit-board-title{{else}}is-disabled{{/if}}" title="{{_ 'edit'}}" value=title)
|
||||
i.fa.fa-pencil-square-o
|
||||
|
||||
a.board-header-btn.js-star-board(class="{{#if isStarred}}is-active{{/if}}"
|
||||
title="{{#if isStarred}}{{_ 'click-to-unstar'}}{{else}}{{_ 'click-to-star'}}{{/if}} {{_ 'starred-boards-description'}}")
|
||||
i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}")
|
||||
@@ -31,6 +34,12 @@ template(name="boardHeaderBar")
|
||||
if $eq watchLevel "muted"
|
||||
i.fa.fa-bell-slash
|
||||
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}}
|
||||
if isSortActive
|
||||
a.board-header-btn-close.js-sort-reset(title="Remove Sort")
|
||||
i.fa.fa-times-thin
|
||||
|
||||
else
|
||||
a.board-header-btn.js-log-in(
|
||||
@@ -42,6 +51,10 @@ template(name="boardHeaderBar")
|
||||
if currentBoard
|
||||
if isMiniScreen
|
||||
if currentUser
|
||||
with currentBoard
|
||||
a.board-header-btn(class="{{#if currentUser.isBoardAdmin}}js-edit-board-title{{else}}is-disabled{{/if}}" title="{{_ 'edit'}}" value=title)
|
||||
i.fa.fa-pencil-square-o
|
||||
|
||||
a.board-header-btn.js-star-board(class="{{#if isStarred}}is-active{{/if}}"
|
||||
title="{{#if isStarred}}{{_ 'click-to-unstar'}}{{else}}{{_ 'click-to-star'}}{{/if}} {{_ 'starred-boards-description'}}")
|
||||
i.fa(class="fa-star{{#unless isStarred}}-o{{/unless}}")
|
||||
@@ -247,3 +260,19 @@ template(name="boardChangeTitlePopup")
|
||||
template(name="boardCreateRulePopup")
|
||||
p {{_ 'close-board-pop'}}
|
||||
button.js-confirm.negate.full(type="submit") {{_ 'archive'}}
|
||||
|
||||
|
||||
template(name="cardsSortPopup")
|
||||
ul.pop-over-list
|
||||
li
|
||||
a.js-sort-due {{_ 'due-date'}}
|
||||
hr
|
||||
li
|
||||
a.js-sort-title {{_ 'title-alphabetically'}}
|
||||
hr
|
||||
li
|
||||
a.js-sort-created-desc {{_ 'created-at-newest-first'}}
|
||||
hr
|
||||
li
|
||||
a.js-sort-created-asc {{_ 'created-at-oldest-first'}}
|
||||
|
||||
@@ -2,6 +2,7 @@
|
||||
const DOWNCLS = 'fa-sort-down';
|
||||
const UPCLS = 'fa-sort-up';
|
||||
*/
|
||||
const sortCardsBy = new ReactiveVar('');
|
||||
Template.boardMenuPopup.events({
|
||||
'click .js-rename-board': Popup.open('boardChangeTitle'),
|
||||
'click .js-custom-fields'() {
|
||||
@@ -110,6 +111,7 @@ BlazeComponent.extendComponent({
|
||||
'click .js-open-filter-view'() {
|
||||
Sidebar.setView('filter');
|
||||
},
|
||||
'click .js-sort-cards': Popup.open('cardsSort'),
|
||||
/*
|
||||
'click .js-open-sort-view'(evt) {
|
||||
const target = evt.target;
|
||||
@@ -127,6 +129,9 @@ BlazeComponent.extendComponent({
|
||||
Sidebar.setView();
|
||||
Filter.reset();
|
||||
},
|
||||
'click .js-sort-reset'() {
|
||||
Session.set('sortBy', '');
|
||||
},
|
||||
'click .js-open-search-view'() {
|
||||
Sidebar.setView('search');
|
||||
},
|
||||
@@ -160,6 +165,9 @@ Template.boardHeaderBar.helpers({
|
||||
boardView() {
|
||||
return Utils.boardView();
|
||||
},
|
||||
isSortActive() {
|
||||
return Session.get('sortBy') ? true : false;
|
||||
},
|
||||
});
|
||||
|
||||
Template.boardChangeViewPopup.events({
|
||||
@@ -368,3 +376,44 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
}).register('listsortPopup');
|
||||
*/
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-sort-due'() {
|
||||
const sortBy = {
|
||||
dueAt: 1,
|
||||
};
|
||||
Session.set('sortBy', sortBy);
|
||||
sortCardsBy.set(TAPi18n.__('due-date'));
|
||||
Popup.close();
|
||||
},
|
||||
'click .js-sort-title'() {
|
||||
const sortBy = {
|
||||
title: 1,
|
||||
};
|
||||
Session.set('sortBy', sortBy);
|
||||
sortCardsBy.set(TAPi18n.__('title'));
|
||||
Popup.close();
|
||||
},
|
||||
'click .js-sort-created-asc'() {
|
||||
const sortBy = {
|
||||
createdAt: 1,
|
||||
};
|
||||
Session.set('sortBy', sortBy);
|
||||
sortCardsBy.set(TAPi18n.__('date-created-newest-first'));
|
||||
Popup.close();
|
||||
},
|
||||
'click .js-sort-created-desc'() {
|
||||
const sortBy = {
|
||||
createdAt: -1,
|
||||
};
|
||||
Session.set('sortBy', sortBy);
|
||||
sortCardsBy.set(TAPi18n.__('date-created-oldest-first'));
|
||||
Popup.close();
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('cardsSortPopup');
|
||||
@@ -129,7 +129,7 @@ BlazeComponent.extendComponent({
|
||||
{
|
||||
sort: Boards.find({ archived: false }).count(),
|
||||
type: 'board',
|
||||
title: Boards.findOne(this.currentData()._id).copyTitle(),
|
||||
title: Boards.findOne(this.currentData()._id).title,
|
||||
},
|
||||
(err, res) => {
|
||||
if (err) {
|
||||
|
||||
@@ -121,7 +121,8 @@ CardCustomField.register('cardCustomField');
|
||||
{
|
||||
'submit .js-card-customfield-currency'(event) {
|
||||
event.preventDefault();
|
||||
const value = Number(this.find('input').value, 10);
|
||||
// To allow input separated by comma, the comma is replaced by a period.
|
||||
const value = Number(this.find('input').value.replace(/,/i, '.'), 10);
|
||||
this.card.setCustomField(this.customFieldId, value);
|
||||
},
|
||||
},
|
||||
|
||||
@@ -1,3 +1,11 @@
|
||||
// Helper function to replace HH with H for 24 hours format, because H allows also single-digit hours
|
||||
function adjustedTimeFormat() {
|
||||
return moment
|
||||
.localeData()
|
||||
.longDateFormat('LT')
|
||||
.replace(/HH/i, 'H');
|
||||
}
|
||||
|
||||
// Edit received, start, due & end dates
|
||||
BlazeComponent.extendComponent({
|
||||
template() {
|
||||
@@ -59,7 +67,11 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
'keyup .js-time-field'() {
|
||||
// parse for localized time format in strict mode
|
||||
const dateMoment = moment(this.find('#time').value, 'LT', true);
|
||||
const dateMoment = moment(
|
||||
this.find('#time').value,
|
||||
adjustedTimeFormat(),
|
||||
true,
|
||||
);
|
||||
if (dateMoment.isValid()) {
|
||||
this.error.set('');
|
||||
}
|
||||
@@ -71,16 +83,30 @@ BlazeComponent.extendComponent({
|
||||
const time =
|
||||
evt.target.time.value ||
|
||||
moment(new Date().setHours(12, 0, 0)).format('LT');
|
||||
|
||||
const newTime = moment(time, adjustedTimeFormat(), true);
|
||||
const newDate = moment(evt.target.date.value, 'L', true);
|
||||
const dateString = `${evt.target.date.value} ${time}`;
|
||||
const newDate = moment(dateString, 'L LT', true);
|
||||
if (newDate.isValid()) {
|
||||
this._storeDate(newDate.toDate());
|
||||
Popup.close();
|
||||
} else {
|
||||
const newCompleteDate = moment(
|
||||
dateString,
|
||||
'L ' + adjustedTimeFormat(),
|
||||
true,
|
||||
);
|
||||
if (!newTime.isValid()) {
|
||||
this.error.set('invalid-time');
|
||||
evt.target.time.focus();
|
||||
}
|
||||
if (!newDate.isValid()) {
|
||||
this.error.set('invalid-date');
|
||||
evt.target.date.focus();
|
||||
}
|
||||
if (newCompleteDate.isValid()) {
|
||||
this._storeDate(newCompleteDate.toDate());
|
||||
Popup.close();
|
||||
} else {
|
||||
if (!this.error) {
|
||||
this.error.set('invalid');
|
||||
}
|
||||
}
|
||||
},
|
||||
'click .js-delete-date'(evt) {
|
||||
evt.preventDefault();
|
||||
|
||||
@@ -3,5 +3,5 @@ template(name="descriptionForm")
|
||||
.new-description.js-new-description(
|
||||
class="{{#if descriptionFormIsOpen}}is-open{{/if}}")
|
||||
form.js-new-description-form
|
||||
+editor(class="js-new-description-input" data-meteor-emoji-large="true" autofocus="autofocus")
|
||||
+editor(class="js-new-description-input" autofocus="autofocus")
|
||||
| {{getUnsavedValue 'cardDescription' _id getDescription}}
|
||||
@@ -8,11 +8,10 @@ template(name="cardDetails")
|
||||
a.fa.fa-times-thin.close-card-details.js-close-card-details
|
||||
if currentUser.isBoardMember
|
||||
a.fa.fa-navicon.card-details-menu.js-open-card-details-menu
|
||||
input.inline-input(type="text" id="cardURL_copy" value="{{ absoluteUrl }}")
|
||||
input.inline-input(type="text" id="cardURL_copy" value="{{ originRelativeUrl }}")
|
||||
a.fa.fa-link.card-copy-button.js-copy-link(
|
||||
class="fa-link"
|
||||
title="{{_ 'copy-card-link-to-clipboard'}}"
|
||||
value="{{ absoluteUrl }}"
|
||||
)
|
||||
if isMiniScreen
|
||||
a.fa.fa-times-thin.close-card-details-mobile-web.js-close-card-details
|
||||
@@ -533,7 +532,7 @@ template(name="cardMorePopup")
|
||||
span {{_ 'link-card'}}
|
||||
= ' '
|
||||
i.fa.colorful(class="{{#if board.isPublic}}fa-globe{{else}}fa-lock{{/if}}")
|
||||
input.inline-input(type="text" id="cardURL" readonly value="{{ absoluteUrl }}" autofocus="autofocus")
|
||||
input.inline-input(type="text" id="cardURL" readonly value="{{ originRelativeUrl }}" autofocus="autofocus")
|
||||
button.js-copy-card-link-to-clipboard(class="btn" id="clipboard") {{_ 'copy-card-link-to-clipboard'}}
|
||||
span.clearfix
|
||||
br
|
||||
|
||||
@@ -114,7 +114,7 @@ BlazeComponent.extendComponent({
|
||||
if (card) {
|
||||
const board = Boards.findOne(card.boardId);
|
||||
if (board) {
|
||||
result = FlowRouter.url('card', {
|
||||
result = FlowRouter.path('card', {
|
||||
boardId: card.boardId,
|
||||
slug: board.slug,
|
||||
cardId: card._id,
|
||||
@@ -291,6 +291,8 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
'click .js-copy-link'() {
|
||||
StringToCopyElement = document.getElementById('cardURL_copy');
|
||||
StringToCopyElement.value =
|
||||
window.location.origin + window.location.pathname;
|
||||
StringToCopyElement.select();
|
||||
if (document.execCommand('copy')) {
|
||||
StringToCopyElement.blur();
|
||||
|
||||
@@ -111,7 +111,7 @@ BlazeComponent.extendComponent({
|
||||
title,
|
||||
checklistId: checklist._id,
|
||||
cardId: checklist.cardId,
|
||||
sort: checklist.itemCount(),
|
||||
sort: Utils.calculateIndexData(checklist.lastItem()).base,
|
||||
});
|
||||
}
|
||||
// We keep the form opened, empty it.
|
||||
|
||||
@@ -44,8 +44,8 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
|
||||
|
||||
span.fa.checklist-handle
|
||||
padding-right: 20px
|
||||
padding-top: 6px
|
||||
float: right
|
||||
padding-top: 3px
|
||||
float: left
|
||||
|
||||
|
||||
.js-confirm-checklist-delete
|
||||
|
||||
@@ -90,7 +90,6 @@ template(name="minicard")
|
||||
.minicard-assignees.js-minicard-assignees
|
||||
each getAssignees
|
||||
+userAvatar(userId=this)
|
||||
hr(class="assigneehr" title="{{_ 'assignee'}}")
|
||||
|
||||
if getMembers
|
||||
.minicard-members.js-minicard-members
|
||||
|
||||
@@ -166,16 +166,14 @@
|
||||
.minicard-assignees
|
||||
float: right
|
||||
margin-left: 5px
|
||||
|
||||
.assigneehr
|
||||
border-top: 1px solid red
|
||||
margin-bottom: 4px
|
||||
margin-bottom: 4px
|
||||
|
||||
.member
|
||||
float: right
|
||||
border-radius: 50%
|
||||
height: 28px
|
||||
width: @height
|
||||
margin-bottom: 4px
|
||||
|
||||
.assignee
|
||||
float: right
|
||||
@@ -186,6 +184,9 @@
|
||||
+ .badges
|
||||
margin-top: 5px
|
||||
|
||||
.minicard-assignees
|
||||
border-bottom: 1px solid red
|
||||
|
||||
.minicard-members:empty,
|
||||
.minicard-assignees:empty
|
||||
display: none
|
||||
|
||||
@@ -1,23 +1,44 @@
|
||||
template(name="resultCard")
|
||||
.result-card-wrapper
|
||||
a.minicard-wrapper.card-title(href=absoluteUrl)
|
||||
a.minicard-wrapper.card-title(href=originRelativeUrl)
|
||||
+minicard(this)
|
||||
//= card.title
|
||||
ul.result-card-context-list
|
||||
li.result-card-context(title="{{_ 'board'}}")
|
||||
+viewer
|
||||
= getBoard.title
|
||||
.result-card-block-wrapper
|
||||
if boardId
|
||||
+viewer
|
||||
= getBoard.title
|
||||
else
|
||||
.broken-cards-null
|
||||
| NULL
|
||||
if getBoard.archived
|
||||
i.fa.fa-archive
|
||||
li.result-card-context.result-card-context-separator
|
||||
= ' '
|
||||
| {{_ 'context-separator'}}
|
||||
= ' '
|
||||
li.result-card-context(title="{{_ 'swimlane'}}")
|
||||
+viewer
|
||||
= getSwimlane.title
|
||||
.result-card-block-wrapper
|
||||
if swimlaneId
|
||||
+viewer
|
||||
= getSwimlane.title
|
||||
else
|
||||
.broken-cards-null
|
||||
| NULL
|
||||
if getSwimlane.archived
|
||||
i.fa.fa-archive
|
||||
li.result-card-context.result-card-context-separator
|
||||
= ' '
|
||||
| {{_ 'context-separator'}}
|
||||
= ' '
|
||||
li.result-card-context(title="{{_ 'list'}}")
|
||||
+viewer
|
||||
= getList.title
|
||||
.result-card-block-wrapper
|
||||
if listId
|
||||
+viewer
|
||||
= getList.title
|
||||
else
|
||||
.broken-cards-null
|
||||
| NULL
|
||||
if getList.archived
|
||||
i.fa.fa-archive
|
||||
@@ -19,3 +19,6 @@
|
||||
|
||||
.result-card-context-list
|
||||
margin-bottom: 0.7rem
|
||||
|
||||
.result-card-block-wrapper
|
||||
display: inline-block
|
||||
@@ -13,38 +13,43 @@ template(name="import")
|
||||
template(name="importTextarea")
|
||||
form
|
||||
p: label(for='import-textarea') {{_ instruction}} {{_ 'import-board-instruction-about-errors'}}
|
||||
textarea.js-import-json(placeholder="{{_ importPlaceHolder}}" autofocus)
|
||||
textarea.js-import-json(id='import-textarea' placeholder="{{_ importPlaceHolder}}" autofocus)
|
||||
| {{jsonText}}
|
||||
input.primary.wide(type="submit" value="{{_ 'import'}}")
|
||||
|
||||
template(name="importMapMembers")
|
||||
h2 {{_ 'import-map-members'}}
|
||||
.map-members
|
||||
p {{_ 'import-members-map'}}
|
||||
.mapping-list
|
||||
each members
|
||||
a.mapping-item.js-select-member(class="{{#if wekanId}}filled{{/if}}")
|
||||
.profile-source
|
||||
.full-name= fullName
|
||||
.username
|
||||
| ({{username}})
|
||||
.wekan
|
||||
if wekanId
|
||||
+userAvatar(userId=wekanId)
|
||||
else
|
||||
a.member.add-member
|
||||
i.fa.fa-plus
|
||||
//-
|
||||
Due to the way the flewbox layout is working, we need to set some
|
||||
invisible items so that the last row items have a consistent width.
|
||||
See http://jsfiddle.net/Ln4h3c4n/ for an minimal example of the issue.
|
||||
.mapping-item.ghost-item
|
||||
.mapping-item.ghost-item
|
||||
.mapping-item.ghost-item
|
||||
.mapping-item.ghost-item
|
||||
.mapping-item.ghost-item
|
||||
form
|
||||
input.primary.wide(type="submit" value="{{_ 'done'}}")
|
||||
if usersLoaded.get
|
||||
.map-members
|
||||
p {{_ 'import-members-map'}}
|
||||
p.import-members-map-note
|
||||
| {{_ 'import-members-map-note' }}
|
||||
.mapping-list
|
||||
each members
|
||||
a.mapping-item.js-select-member(class="{{#if wekanId}}filled{{/if}}")
|
||||
.profile-source
|
||||
.full-name= fullName
|
||||
.username
|
||||
| ({{username}})
|
||||
.wekan
|
||||
if wekanId
|
||||
+userAvatar(userId=wekanId)
|
||||
else
|
||||
a.member.add-member
|
||||
i.fa.fa-plus
|
||||
//-
|
||||
Due to the way the flewbox layout is working, we need to set some
|
||||
invisible items so that the last row items have a consistent width.
|
||||
See http://jsfiddle.net/Ln4h3c4n/ for an minimal example of the issue.
|
||||
.mapping-item.ghost-item
|
||||
.mapping-item.ghost-item
|
||||
.mapping-item.ghost-item
|
||||
.mapping-item.ghost-item
|
||||
.mapping-item.ghost-item
|
||||
form
|
||||
input.primary.wide(type="submit" value="{{_ 'done'}}")
|
||||
else
|
||||
+spinner
|
||||
|
||||
template(name="importMapMembersAddPopup")
|
||||
.select-member
|
||||
|
||||
@@ -150,14 +150,42 @@ BlazeComponent.extendComponent({
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.usersLoaded = new ReactiveVar(false);
|
||||
|
||||
this.autorun(() => {
|
||||
this.parentComponent()
|
||||
.membersToMap.get()
|
||||
.forEach(({ wekanId }) => {
|
||||
if (wekanId) {
|
||||
this.subscribe('user-miniprofile', wekanId);
|
||||
const handle = this.subscribe(
|
||||
'user-miniprofile',
|
||||
this.members().map(member => {
|
||||
return member.username;
|
||||
}),
|
||||
);
|
||||
Tracker.nonreactive(() => {
|
||||
Tracker.autorun(() => {
|
||||
if (
|
||||
handle.ready() &&
|
||||
!this.usersLoaded.get() &&
|
||||
this.members().length
|
||||
) {
|
||||
this._refreshMembers(
|
||||
this.members().map(member => {
|
||||
if (!member.wekanId) {
|
||||
let user = Users.findOne({ username: member.username });
|
||||
if (!user) {
|
||||
user = Users.findOne({ importUsernames: member.username });
|
||||
}
|
||||
if (user) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('found username:', user.username);
|
||||
member.wekanId = user._id;
|
||||
}
|
||||
}
|
||||
return member;
|
||||
}),
|
||||
);
|
||||
}
|
||||
this.usersLoaded.set(handle.ready());
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
|
||||
Vendored
+4
@@ -47,3 +47,7 @@
|
||||
|
||||
a.show-mapping
|
||||
text-decoration underline
|
||||
|
||||
.import-members-map-note
|
||||
font-size: 90%
|
||||
font-weight: bold
|
||||
@@ -180,7 +180,8 @@
|
||||
border-bottom: 1px solid darken(white, 20%)
|
||||
|
||||
.list
|
||||
display: block
|
||||
display: contents
|
||||
flex-basis: auto
|
||||
width: 100%
|
||||
border-left: 0px
|
||||
&:first-child
|
||||
|
||||
@@ -5,7 +5,7 @@ template(name="listBody")
|
||||
+inlinedForm(autoclose=false position="top")
|
||||
+addCardForm(listId=_id position="top")
|
||||
each (cardsWithLimit (idOrNull ../../_id))
|
||||
a.minicard-wrapper.js-minicard(href=absoluteUrl
|
||||
a.minicard-wrapper.js-minicard(href=originRelativeUrl
|
||||
class="{{#if cardIsSelected}}is-selected{{/if}}"
|
||||
class="{{#if MultiSelection.isSelected _id}}is-checked{{/if}}")
|
||||
if MultiSelection.isActive
|
||||
|
||||
@@ -168,13 +168,16 @@ BlazeComponent.extendComponent({
|
||||
|
||||
cardsWithLimit(swimlaneId) {
|
||||
const limit = this.cardlimit.get();
|
||||
const defaultSort = { sort: 1 };
|
||||
const sortBy = Session.get('sortBy') ? Session.get('sortBy') : defaultSort;
|
||||
const selector = {
|
||||
listId: this.currentData()._id,
|
||||
archived: false,
|
||||
};
|
||||
if (swimlaneId) selector.swimlaneId = swimlaneId;
|
||||
return Cards.find(Filter.mongoSelector(selector), {
|
||||
sort: ['sort'],
|
||||
// sort: ['sort'],
|
||||
sort: sortBy,
|
||||
limit,
|
||||
});
|
||||
},
|
||||
@@ -239,7 +242,7 @@ BlazeComponent.extendComponent({
|
||||
.customFields()
|
||||
.fetch(),
|
||||
function(field) {
|
||||
if (field.automaticallyOnCard)
|
||||
if (field.automaticallyOnCard || field.alwaysOnCard)
|
||||
arr.push({ _id: field._id, value: null });
|
||||
},
|
||||
);
|
||||
|
||||
@@ -15,7 +15,7 @@ template(name="listHeader")
|
||||
= title
|
||||
if wipLimit.enabled
|
||||
| (
|
||||
span(class="{{#if reachedWipLimit}}highlight{{/if}}") {{cards.count}}
|
||||
span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.count}}
|
||||
|/#{wipLimit.value})
|
||||
|
||||
if showCardsCountForList cards.count
|
||||
|
||||
@@ -72,9 +72,17 @@ BlazeComponent.extendComponent({
|
||||
);
|
||||
},
|
||||
|
||||
exceededWipLimit() {
|
||||
const list = Template.currentData();
|
||||
return (
|
||||
list.getWipLimit('enabled') &&
|
||||
list.getWipLimit('value') < list.cards().count()
|
||||
);
|
||||
},
|
||||
|
||||
showCardsCountForList(count) {
|
||||
const limit = this.limitToShowCardsCount();
|
||||
return limit > 0 && count > limit;
|
||||
return limit >= 0 && count >= limit;
|
||||
},
|
||||
|
||||
events() {
|
||||
|
||||
@@ -3,39 +3,15 @@ template(name="brokenCardsHeaderBar")
|
||||
| {{_ 'broken-cards'}}
|
||||
|
||||
template(name="brokenCards")
|
||||
.wrapper
|
||||
.broken-cards-wrapper
|
||||
each card in brokenCardsList
|
||||
.broken-cards-card-wrapper
|
||||
.broken-cards-card-title
|
||||
= card.title
|
||||
ul.broken-cards-context-list
|
||||
li.broken-cards-context(title="{{_ 'board'}}")
|
||||
if card.boardId
|
||||
+viewer
|
||||
= card.getBoard.title
|
||||
else
|
||||
.broken-cards-null
|
||||
| NULL
|
||||
li.broken-cards-context.broken-cards-context-separator
|
||||
= ' '
|
||||
| {{_ 'context-separator'}}
|
||||
= ' '
|
||||
li.broken-cards-context(title="{{_ 'swimlane'}}")
|
||||
if card.swimlaneId
|
||||
+viewer
|
||||
= card.getSwimlane.title
|
||||
else
|
||||
.broken-cards-null
|
||||
| NULL
|
||||
li.broken-cards-context
|
||||
= ' '
|
||||
| {{_ 'context-separator'}}
|
||||
= ' '
|
||||
li.broken-cards-context(title="{{_ 'list'}}")
|
||||
if card.listId
|
||||
+viewer
|
||||
= card.getList.title
|
||||
else
|
||||
.broken-cards-null
|
||||
| NULL
|
||||
if currentUser
|
||||
if searching.get
|
||||
+spinner
|
||||
else if hasResults.get
|
||||
.global-search-results-list-wrapper
|
||||
if hasQueryErrors.get
|
||||
div
|
||||
each msg in errorMessages
|
||||
span.global-search-error-messages
|
||||
= msg
|
||||
else
|
||||
+resultsPaged(this)
|
||||
@@ -1,3 +1,5 @@
|
||||
import { CardSearchPagedComponent } from '../../lib/cardSearch';
|
||||
|
||||
BlazeComponent.extendComponent({}).register('brokenCardsHeaderBar');
|
||||
|
||||
Template.brokenCards.helpers({
|
||||
@@ -6,23 +8,11 @@ Template.brokenCards.helpers({
|
||||
},
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
class BrokenCardsComponent extends CardSearchPagedComponent {
|
||||
onCreated() {
|
||||
Meteor.subscribe('setting');
|
||||
Meteor.subscribe('brokenCards');
|
||||
},
|
||||
super.onCreated();
|
||||
|
||||
brokenCardsList() {
|
||||
const selector = {
|
||||
$or: [
|
||||
{ boardId: { $in: [null, ''] } },
|
||||
{ swimlaneId: { $in: [null, ''] } },
|
||||
{ listId: { $in: [null, ''] } },
|
||||
{ permission: 'public' },
|
||||
{ members: { $elemMatch: { userId: user._id, isActive: true } } },
|
||||
],
|
||||
};
|
||||
|
||||
return Cards.find(selector);
|
||||
},
|
||||
}).register('brokenCards');
|
||||
Meteor.subscribe('brokenCards', this.sessionId);
|
||||
}
|
||||
}
|
||||
BrokenCardsComponent.register('brokenCards');
|
||||
@@ -22,13 +22,17 @@ template(name="dueCardsModalTitle")
|
||||
|
||||
template(name="dueCards")
|
||||
if currentUser
|
||||
if isPageReady.get
|
||||
.wrapper
|
||||
.due-cards-dueat-list-wrapper
|
||||
each card in dueCardsList
|
||||
+resultCard(card)
|
||||
else
|
||||
if searching.get
|
||||
+spinner
|
||||
else if hasResults.get
|
||||
.global-search-results-list-wrapper
|
||||
if hasQueryErrors.get
|
||||
div
|
||||
each msg in errorMessages
|
||||
span.global-search-error-messages
|
||||
= msg
|
||||
else
|
||||
+resultsPaged(this)
|
||||
|
||||
template(name="dueCardsViewChangePopup")
|
||||
if currentUser
|
||||
|
||||
@@ -1,4 +1,14 @@
|
||||
const subManager = new SubsManager();
|
||||
import { CardSearchPagedComponent } from '../../lib/cardSearch';
|
||||
import {
|
||||
OPERATOR_HAS,
|
||||
OPERATOR_SORT,
|
||||
OPERATOR_USER,
|
||||
ORDER_DESCENDING,
|
||||
PREDICATE_DUE_AT,
|
||||
} from '../../../config/search-const';
|
||||
import { QueryParams } from '../../../config/query-classes';
|
||||
|
||||
// const subManager = new SubsManager();
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
dueCardsView() {
|
||||
@@ -40,106 +50,51 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
}).register('dueCardsViewChangePopup');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
class DueCardsComponent extends CardSearchPagedComponent {
|
||||
onCreated() {
|
||||
this.isPageReady = new ReactiveVar(false);
|
||||
super.onCreated();
|
||||
|
||||
this.autorun(() => {
|
||||
const handle = subManager.subscribe(
|
||||
'dueCards',
|
||||
Utils.dueCardsView() === 'all',
|
||||
);
|
||||
Tracker.nonreactive(() => {
|
||||
Tracker.autorun(() => {
|
||||
this.isPageReady.set(handle.ready());
|
||||
});
|
||||
});
|
||||
const queryParams = new QueryParams();
|
||||
queryParams.addPredicate(OPERATOR_HAS, {
|
||||
field: PREDICATE_DUE_AT,
|
||||
exists: true,
|
||||
});
|
||||
Meteor.subscribe('setting');
|
||||
},
|
||||
// queryParams[OPERATOR_LIMIT] = 5;
|
||||
queryParams.addPredicate(OPERATOR_SORT, {
|
||||
name: PREDICATE_DUE_AT,
|
||||
order: ORDER_DESCENDING,
|
||||
});
|
||||
|
||||
if (Utils.dueCardsView() !== 'all') {
|
||||
queryParams.addPredicate(OPERATOR_USER, Meteor.user().username);
|
||||
}
|
||||
|
||||
this.runGlobalSearch(queryParams.getQueryParams());
|
||||
}
|
||||
|
||||
dueCardsView() {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('sort:', Utils.dueCardsView());
|
||||
//console.log('sort:', Utils.dueCardsView());
|
||||
return Utils.dueCardsView();
|
||||
},
|
||||
}
|
||||
|
||||
sortByBoard() {
|
||||
return this.dueCardsView() === 'board';
|
||||
},
|
||||
}
|
||||
|
||||
dueCardsList() {
|
||||
const allUsers = Utils.dueCardsView() === 'all';
|
||||
|
||||
const user = Meteor.user();
|
||||
|
||||
const archivedBoards = [];
|
||||
Boards.find({ archived: true }).forEach(board => {
|
||||
archivedBoards.push(board._id);
|
||||
});
|
||||
|
||||
const permiitedBoards = [];
|
||||
let selector = {
|
||||
archived: false,
|
||||
};
|
||||
// for every user including admin allow her to see cards only from public boards
|
||||
// or those where she is a member
|
||||
//if (!user.isAdmin) {
|
||||
selector.$or = [
|
||||
{ permission: 'public' },
|
||||
{ members: { $elemMatch: { userId: user._id, isActive: true } } },
|
||||
];
|
||||
//}
|
||||
Boards.find(selector).forEach(board => {
|
||||
permiitedBoards.push(board._id);
|
||||
});
|
||||
|
||||
const archivedSwimlanes = [];
|
||||
Swimlanes.find({ archived: true }).forEach(swimlane => {
|
||||
archivedSwimlanes.push(swimlane._id);
|
||||
});
|
||||
|
||||
const archivedLists = [];
|
||||
Lists.find({ archived: true }).forEach(list => {
|
||||
archivedLists.push(list._id);
|
||||
});
|
||||
|
||||
selector = {
|
||||
archived: false,
|
||||
boardId: {
|
||||
$nin: archivedBoards,
|
||||
$in: permiitedBoards,
|
||||
},
|
||||
swimlaneId: { $nin: archivedSwimlanes },
|
||||
listId: { $nin: archivedLists },
|
||||
dueAt: { $ne: null },
|
||||
endAt: null,
|
||||
};
|
||||
|
||||
if (!allUsers) {
|
||||
selector.$or = [{ members: user._id }, { assignees: user._id }];
|
||||
const results = this.getResults();
|
||||
console.log('results:', results);
|
||||
const cards = [];
|
||||
if (results) {
|
||||
results.forEach(card => {
|
||||
cards.push(card);
|
||||
});
|
||||
}
|
||||
|
||||
const cards = [];
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('cards selector:', selector);
|
||||
Cards.find(selector).forEach(card => {
|
||||
cards.push(card);
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log(
|
||||
// 'board:',
|
||||
// card.board(),
|
||||
// 'swimlane:',
|
||||
// card.swimlane(),
|
||||
// 'list:',
|
||||
// card.list(),
|
||||
// );
|
||||
});
|
||||
|
||||
cards.sort((a, b) => {
|
||||
const x = a.dueAt === null ? Date('2100-12-31') : a.dueAt;
|
||||
const y = b.dueAt === null ? Date('2100-12-31') : b.dueAt;
|
||||
const x = a.dueAt === null ? new Date('2100-12-31') : a.dueAt;
|
||||
const y = b.dueAt === null ? new Date('2100-12-31') : b.dueAt;
|
||||
|
||||
if (x > y) return 1;
|
||||
else if (x < y) return -1;
|
||||
@@ -148,7 +103,9 @@ BlazeComponent.extendComponent({
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('cards:', cards);
|
||||
console.log('cards:', cards);
|
||||
return cards;
|
||||
},
|
||||
}).register('dueCards');
|
||||
}
|
||||
}
|
||||
|
||||
DueCardsComponent.register('dueCards');
|
||||
@@ -278,6 +278,8 @@ function mySafeAttrValue(tag, name, value, cssFilter) {
|
||||
/^aodroplink:/gi.test(value) ||
|
||||
/^onenote:/gi.test(value) ||
|
||||
/^file:/gi.test(value) ||
|
||||
/^abasurl:/gi.test(value) ||
|
||||
/^conisio:/gi.test(value) ||
|
||||
/^mailspring:/gi.test(value)
|
||||
) {
|
||||
return value;
|
||||
|
||||
@@ -10,11 +10,29 @@ template(name="globalSearchModalTitle")
|
||||
i.fa.fa-keyboard-o
|
||||
| {{_ 'globalSearch-title'}}
|
||||
|
||||
template(name="resultsPaged")
|
||||
h1
|
||||
= resultsHeading.get
|
||||
a.fa.fa-link(title="{{_ 'link-to-search' }}" href="{{ getSearchHref }}")
|
||||
each card in results.get
|
||||
+resultCard(card)
|
||||
table.global-search-footer
|
||||
tr
|
||||
td.global-search-previous-page
|
||||
if hasPreviousPage.get
|
||||
button.js-previous-page
|
||||
| {{_ 'previous-page' }}
|
||||
td.global-search-next-page(align="right")
|
||||
if hasNextPage.get
|
||||
button.js-next-page
|
||||
| {{_ 'next-page' }}
|
||||
|
||||
template(name="globalSearch")
|
||||
if currentUser
|
||||
.wrapper
|
||||
form.global-search-instructions.js-search-query-form
|
||||
form.global-search-page.js-search-query-form
|
||||
input.global-search-query-input(
|
||||
style="{# if hasResults.get #}display: inline-block;{#/if#}"
|
||||
id="global-search-input"
|
||||
type="text"
|
||||
name="searchQuery"
|
||||
@@ -22,63 +40,47 @@ template(name="globalSearch")
|
||||
value="{{ query.get }}"
|
||||
autofocus dir="auto"
|
||||
)
|
||||
a.js-new-search.fa.fa-eraser
|
||||
if searching.get
|
||||
+spinner
|
||||
else if hasResults.get
|
||||
.global-search-results-list-wrapper
|
||||
if hasQueryErrors.get
|
||||
div
|
||||
ul
|
||||
each msg in errorMessages
|
||||
span.global-search-error-messages
|
||||
| {{_ msg.tag msg.value }}
|
||||
li.global-search-error-messages
|
||||
= msg
|
||||
else
|
||||
h1
|
||||
= resultsHeading.get
|
||||
a.fa.fa-link(title="{{_ 'link-to-search' }}" href="{{ getSearchHref }}")
|
||||
each card in results
|
||||
+resultCard(card)
|
||||
+resultsPaged(this)
|
||||
else if serverError.get
|
||||
.global-search-page
|
||||
.global-search-help
|
||||
h1 {{_ 'server-error' }}
|
||||
+viewer
|
||||
| {{_ 'server-error-troubleshooting' }}
|
||||
else
|
||||
.global-search-instructions
|
||||
h2 {{_ 'boards' }}
|
||||
.lists-wrapper
|
||||
each title in myBoardNames.get
|
||||
span.card-label.list-title.js-board-title
|
||||
= title
|
||||
h2 {{_ 'lists' }}
|
||||
.lists-wrapper
|
||||
each title in myLists.get
|
||||
span.card-label.list-title.js-list-title
|
||||
= title
|
||||
h2 {{_ 'label-colors' }}
|
||||
.palette-colors: each label in labelColors
|
||||
span.card-label.palette-color.js-label-color(class="card-label-{{label.color}}")
|
||||
= label.name
|
||||
if myLabelNames.get.length
|
||||
h2 {{_ 'label-names' }}
|
||||
.global-search-page
|
||||
.global-search-help
|
||||
h2 {{_ 'boards' }}
|
||||
.lists-wrapper
|
||||
each name in myLabelNames.get
|
||||
span.card-label.list-title.js-label-name
|
||||
= name
|
||||
+viewer
|
||||
= searchInstructions
|
||||
|
||||
template(name="globalSearchViewChangePopup")
|
||||
if currentUser
|
||||
ul.pop-over-list
|
||||
li
|
||||
with "globalSearchViewChange-choice-me"
|
||||
a.js-global-search-view-me
|
||||
i.fa.fa-user.colorful
|
||||
| {{_ 'globalSearchViewChange-choice-me'}}
|
||||
if $eq Utils.globalSearchView "me"
|
||||
i.fa.fa-check
|
||||
li
|
||||
with "globalSearchViewChange-choice-all"
|
||||
a.js-global-search-view-all
|
||||
i.fa.fa-users.colorful
|
||||
| {{_ 'globalSearchViewChange-choice-all'}}
|
||||
span.sub-name
|
||||
+viewer
|
||||
| {{_ 'globalSearchViewChange-choice-all-description' }}
|
||||
if $eq Utils.globalSearchView "all"
|
||||
i.fa.fa-check
|
||||
each title in myBoardNames.get
|
||||
span.card-label.list-title.js-board-title
|
||||
= title
|
||||
h2 {{_ 'lists' }}
|
||||
.lists-wrapper
|
||||
each title in myLists.get
|
||||
span.card-label.list-title.js-list-title
|
||||
= title
|
||||
h2 {{_ 'label-colors' }}
|
||||
.palette-colors: each label in labelColors
|
||||
span.card-label.palette-color.js-label-color(class="card-label-{{label.color}}")
|
||||
= label.name
|
||||
if myLabelNames.get.length
|
||||
h2 {{_ 'label-names' }}
|
||||
.lists-wrapper
|
||||
each name in myLabelNames.get
|
||||
span.card-label.list-title.js-label-name
|
||||
= name
|
||||
.global-search-instructions
|
||||
+viewer
|
||||
= searchInstructions
|
||||
@@ -1,4 +1,8 @@
|
||||
const subManager = new SubsManager();
|
||||
import { CardSearchPagedComponent } from '../../lib/cardSearch';
|
||||
import Boards from '../../../models/boards';
|
||||
import { Query, QueryErrors } from '../../../config/query-classes';
|
||||
|
||||
// const subManager = new SubsManager();
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
events() {
|
||||
@@ -16,48 +20,14 @@ Template.globalSearch.helpers({
|
||||
},
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-due-cards-view-me'() {
|
||||
Utils.setDueCardsView('me');
|
||||
Popup.close();
|
||||
},
|
||||
|
||||
'click .js-due-cards-view-all'() {
|
||||
Utils.setDueCardsView('all');
|
||||
Popup.close();
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('globalSearchViewChangePopup');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
class GlobalSearchComponent extends CardSearchPagedComponent {
|
||||
onCreated() {
|
||||
this.searching = new ReactiveVar(false);
|
||||
this.hasResults = new ReactiveVar(false);
|
||||
this.hasQueryErrors = new ReactiveVar(false);
|
||||
this.query = new ReactiveVar('');
|
||||
this.resultsHeading = new ReactiveVar('');
|
||||
this.searchLink = new ReactiveVar(null);
|
||||
super.onCreated();
|
||||
this.myLists = new ReactiveVar([]);
|
||||
this.myLabelNames = new ReactiveVar([]);
|
||||
this.myBoardNames = new ReactiveVar([]);
|
||||
this.parsingErrors = new QueryErrors();
|
||||
this.queryParams = null;
|
||||
this.parsingErrors = [];
|
||||
this.resultsCount = 0;
|
||||
this.totalHits = 0;
|
||||
this.queryErrors = null;
|
||||
this.colorMap = null;
|
||||
// this.colorMap = {};
|
||||
// for (const color of Boards.simpleSchema()._schema['labels.$.color']
|
||||
// .allowedValues) {
|
||||
// this.colorMap[TAPi18n.__(`color-${color}`)] = color;
|
||||
// }
|
||||
// // eslint-disable-next-line no-console
|
||||
// console.log('colorMap:', this.colorMap);
|
||||
|
||||
Meteor.call('myLists', (err, data) => {
|
||||
if (!err) {
|
||||
@@ -76,285 +46,75 @@ BlazeComponent.extendComponent({
|
||||
this.myBoardNames.set(data);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
onRendered() {
|
||||
Meteor.subscribe('setting');
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
//console.log('lang:', TAPi18n.getLanguage());
|
||||
|
||||
if (Session.get('globalQuery')) {
|
||||
this.searchAllBoards(Session.get('globalQuery'));
|
||||
}
|
||||
},
|
||||
}
|
||||
|
||||
resetSearch() {
|
||||
this.searching.set(false);
|
||||
this.hasResults.set(false);
|
||||
this.hasQueryErrors.set(false);
|
||||
this.resultsHeading.set('');
|
||||
this.parsingErrors = [];
|
||||
this.resultsCount = 0;
|
||||
this.totalHits = 0;
|
||||
this.queryErrors = null;
|
||||
},
|
||||
|
||||
results() {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('getting results');
|
||||
if (this.queryParams) {
|
||||
const results = Cards.globalSearch(this.queryParams);
|
||||
this.queryErrors = results.errors;
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('errors:', this.queryErrors);
|
||||
if (this.errorMessages().length) {
|
||||
this.hasQueryErrors.set(true);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (results.cards) {
|
||||
const sessionData = SessionData.findOne({ userId: Meteor.userId() });
|
||||
this.totalHits = sessionData.totalHits;
|
||||
this.resultsCount = results.cards.count();
|
||||
this.resultsHeading.set(this.getResultsHeading());
|
||||
return results.cards;
|
||||
}
|
||||
}
|
||||
this.resultsCount = 0;
|
||||
return [];
|
||||
},
|
||||
super.resetSearch();
|
||||
this.parsingErrors = new QueryErrors();
|
||||
}
|
||||
|
||||
errorMessages() {
|
||||
const messages = [];
|
||||
|
||||
if (this.queryErrors) {
|
||||
this.queryErrors.notFound.boards.forEach(board => {
|
||||
messages.push({ tag: 'board-title-not-found', value: board });
|
||||
});
|
||||
this.queryErrors.notFound.swimlanes.forEach(swim => {
|
||||
messages.push({ tag: 'swimlane-title-not-found', value: swim });
|
||||
});
|
||||
this.queryErrors.notFound.lists.forEach(list => {
|
||||
messages.push({ tag: 'list-title-not-found', value: list });
|
||||
});
|
||||
this.queryErrors.notFound.labels.forEach(label => {
|
||||
const color = Object.entries(this.colorMap)
|
||||
.filter(value => value[1] === label)
|
||||
.map(value => value[0]);
|
||||
if (color.length) {
|
||||
messages.push({
|
||||
tag: 'label-color-not-found',
|
||||
value: color[0],
|
||||
});
|
||||
} else {
|
||||
messages.push({ tag: 'label-not-found', value: label });
|
||||
}
|
||||
});
|
||||
this.queryErrors.notFound.users.forEach(user => {
|
||||
messages.push({ tag: 'user-username-not-found', value: user });
|
||||
});
|
||||
this.queryErrors.notFound.members.forEach(user => {
|
||||
messages.push({ tag: 'user-username-not-found', value: user });
|
||||
});
|
||||
this.queryErrors.notFound.assignees.forEach(user => {
|
||||
messages.push({ tag: 'user-username-not-found', value: user });
|
||||
});
|
||||
if (this.parsingErrors.hasErrors()) {
|
||||
return this.parsingErrors.errorMessages();
|
||||
}
|
||||
return this.queryErrorMessages();
|
||||
}
|
||||
|
||||
if (this.parsingErrors.length) {
|
||||
this.parsingErrors.forEach(err => {
|
||||
messages.push(err);
|
||||
});
|
||||
}
|
||||
parsingErrorMessages() {
|
||||
this.parsingErrors.errorMessages();
|
||||
}
|
||||
|
||||
return messages;
|
||||
},
|
||||
searchAllBoards(queryText) {
|
||||
queryText = queryText.trim();
|
||||
// eslint-disable-next-line no-console
|
||||
//console.log('queryText:', queryText);
|
||||
|
||||
searchAllBoards(query) {
|
||||
query = query.trim();
|
||||
this.query.set(query);
|
||||
this.query.set(queryText);
|
||||
|
||||
this.resetSearch();
|
||||
|
||||
if (!query) {
|
||||
if (!queryText) {
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('query:', query);
|
||||
|
||||
this.searching.set(true);
|
||||
|
||||
if (!this.colorMap) {
|
||||
this.colorMap = {};
|
||||
for (const color of Boards.simpleSchema()._schema['labels.$.color']
|
||||
.allowedValues) {
|
||||
this.colorMap[TAPi18n.__(`color-${color}`)] = color;
|
||||
}
|
||||
}
|
||||
|
||||
const reOperator1 = /^((?<operator>\w+):|(?<abbrev>[#@]))(?<value>\w+)(\s+|$)/;
|
||||
const reOperator2 = /^((?<operator>\w+):|(?<abbrev>[#@]))(?<quote>["']*)(?<value>.*?)\k<quote>(\s+|$)/;
|
||||
const reText = /^(?<text>\S+)(\s+|$)/;
|
||||
const reQuotedText = /^(?<quote>["'])(?<text>\w+)\k<quote>(\s+|$)/;
|
||||
|
||||
const operatorMap = {};
|
||||
operatorMap[TAPi18n.__('operator-board')] = 'boards';
|
||||
operatorMap[TAPi18n.__('operator-board-abbrev')] = 'boards';
|
||||
operatorMap[TAPi18n.__('operator-swimlane')] = 'swimlanes';
|
||||
operatorMap[TAPi18n.__('operator-swimlane-abbrev')] = 'swimlanes';
|
||||
operatorMap[TAPi18n.__('operator-list')] = 'lists';
|
||||
operatorMap[TAPi18n.__('operator-list-abbrev')] = 'lists';
|
||||
operatorMap[TAPi18n.__('operator-label')] = 'labels';
|
||||
operatorMap[TAPi18n.__('operator-label-abbrev')] = 'labels';
|
||||
operatorMap[TAPi18n.__('operator-user')] = 'users';
|
||||
operatorMap[TAPi18n.__('operator-user-abbrev')] = 'users';
|
||||
operatorMap[TAPi18n.__('operator-member')] = 'members';
|
||||
operatorMap[TAPi18n.__('operator-member-abbrev')] = 'members';
|
||||
operatorMap[TAPi18n.__('operator-assignee')] = 'assignees';
|
||||
operatorMap[TAPi18n.__('operator-assignee-abbrev')] = 'assignees';
|
||||
operatorMap[TAPi18n.__('operator-is')] = 'is';
|
||||
operatorMap[TAPi18n.__('operator-due')] = 'dueAt';
|
||||
operatorMap[TAPi18n.__('operator-created')] = 'createdAt';
|
||||
operatorMap[TAPi18n.__('operator-modified')] = 'modifiedAt';
|
||||
const query = new Query();
|
||||
query.buildParams(queryText);
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('operatorMap:', operatorMap);
|
||||
const params = {
|
||||
boards: [],
|
||||
swimlanes: [],
|
||||
lists: [],
|
||||
users: [],
|
||||
members: [],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
is: [],
|
||||
dueAt: null,
|
||||
createdAt: null,
|
||||
modifiedAt: null,
|
||||
};
|
||||
// console.log('params:', query.getParams());
|
||||
|
||||
let text = '';
|
||||
while (query) {
|
||||
m = query.match(reOperator1);
|
||||
if (!m) {
|
||||
m = query.match(reOperator2);
|
||||
if (m) {
|
||||
query = query.replace(reOperator2, '');
|
||||
}
|
||||
} else {
|
||||
query = query.replace(reOperator1, '');
|
||||
}
|
||||
if (m) {
|
||||
let op;
|
||||
if (m.groups.operator) {
|
||||
op = m.groups.operator.toLowerCase();
|
||||
} else {
|
||||
op = m.groups.abbrev;
|
||||
}
|
||||
if (op !== "__proto__") {
|
||||
if (op in operatorMap) {
|
||||
let value = m.groups.value;
|
||||
if (operatorMap[op] === 'labels') {
|
||||
if (value in this.colorMap) {
|
||||
value = this.colorMap[value];
|
||||
}
|
||||
} else if (
|
||||
['dueAt', 'createdAt', 'modifiedAt'].includes(operatorMap[op])
|
||||
) {
|
||||
const days = parseInt(value, 10);
|
||||
if (isNaN(days)) {
|
||||
if (['day', 'week', 'month', 'quarter', 'year'].includes(value)) {
|
||||
value = moment()
|
||||
.subtract(1, value)
|
||||
.format();
|
||||
} else {
|
||||
this.parsingErrors.push({
|
||||
tag: 'operator-number-expected',
|
||||
value: { operator: op, value },
|
||||
});
|
||||
value = null;
|
||||
}
|
||||
} else {
|
||||
value = moment()
|
||||
.subtract(days, 'days')
|
||||
.format();
|
||||
}
|
||||
}
|
||||
if (Array.isArray(params[operatorMap[op]])) {
|
||||
params[operatorMap[op]].push(value);
|
||||
} else {
|
||||
params[operatorMap[op]] = value;
|
||||
}
|
||||
} else {
|
||||
this.parsingErrors.push({
|
||||
tag: 'operator-unknown-error',
|
||||
value: op,
|
||||
});
|
||||
}
|
||||
}
|
||||
continue;
|
||||
}
|
||||
this.queryParams = query.getQueryParams().getParams();
|
||||
|
||||
m = query.match(reQuotedText);
|
||||
if (!m) {
|
||||
m = query.match(reText);
|
||||
if (m) {
|
||||
query = query.replace(reText, '');
|
||||
}
|
||||
} else {
|
||||
query = query.replace(reQuotedText, '');
|
||||
}
|
||||
if (m) {
|
||||
text += (text ? ' ' : '') + m.groups.text;
|
||||
}
|
||||
if (query.hasErrors()) {
|
||||
this.searching.set(false);
|
||||
this.queryErrors = query.errors();
|
||||
this.hasResults.set(true);
|
||||
this.hasQueryErrors.set(true);
|
||||
return;
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('text:', text);
|
||||
params.text = text;
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('params:', params);
|
||||
|
||||
this.queryParams = params;
|
||||
|
||||
this.autorun(() => {
|
||||
const handle = subManager.subscribe('globalSearch', params);
|
||||
Tracker.nonreactive(() => {
|
||||
Tracker.autorun(() => {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('ready:', handle.ready());
|
||||
if (handle.ready()) {
|
||||
this.searching.set(false);
|
||||
this.hasResults.set(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
getResultsHeading() {
|
||||
if (this.resultsCount === 0) {
|
||||
return TAPi18n.__('no-cards-found');
|
||||
} 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-n-of-n-cards-found', {
|
||||
start: 1,
|
||||
end: this.resultsCount,
|
||||
total: this.totalHits,
|
||||
});
|
||||
},
|
||||
|
||||
getSearchHref() {
|
||||
const baseUrl = window.location.href.replace(/([?#].*$|\s*$)/, '');
|
||||
return `${baseUrl}?q=${encodeURIComponent(this.query.get())}`;
|
||||
},
|
||||
this.runGlobalSearch(query.getQueryParams());
|
||||
}
|
||||
|
||||
searchInstructions() {
|
||||
tags = {
|
||||
const tags = {
|
||||
operator_board: TAPi18n.__('operator-board'),
|
||||
operator_list: TAPi18n.__('operator-list'),
|
||||
operator_swimlane: TAPi18n.__('operator-swimlane'),
|
||||
operator_comment: TAPi18n.__('operator-comment'),
|
||||
operator_label: TAPi18n.__('operator-label'),
|
||||
operator_label_abbrev: TAPi18n.__('operator-label-abbrev'),
|
||||
operator_user: TAPi18n.__('operator-user'),
|
||||
@@ -363,54 +123,75 @@ BlazeComponent.extendComponent({
|
||||
operator_member_abbrev: TAPi18n.__('operator-member-abbrev'),
|
||||
operator_assignee: TAPi18n.__('operator-assignee'),
|
||||
operator_assignee_abbrev: TAPi18n.__('operator-assignee-abbrev'),
|
||||
operator_due: TAPi18n.__('operator-due'),
|
||||
operator_created: TAPi18n.__('operator-created'),
|
||||
operator_modified: TAPi18n.__('operator-modified'),
|
||||
operator_status: TAPi18n.__('operator-status'),
|
||||
operator_has: TAPi18n.__('operator-has'),
|
||||
operator_sort: TAPi18n.__('operator-sort'),
|
||||
operator_limit: TAPi18n.__('operator-limit'),
|
||||
predicate_overdue: TAPi18n.__('predicate-overdue'),
|
||||
predicate_archived: TAPi18n.__('predicate-archived'),
|
||||
predicate_all: TAPi18n.__('predicate-all'),
|
||||
predicate_ended: TAPi18n.__('predicate-ended'),
|
||||
predicate_week: TAPi18n.__('predicate-week'),
|
||||
predicate_month: TAPi18n.__('predicate-month'),
|
||||
predicate_quarter: TAPi18n.__('predicate-quarter'),
|
||||
predicate_year: TAPi18n.__('predicate-year'),
|
||||
predicate_attachment: TAPi18n.__('predicate-attachment'),
|
||||
predicate_description: TAPi18n.__('predicate-description'),
|
||||
predicate_checklist: TAPi18n.__('predicate-checklist'),
|
||||
predicate_public: TAPi18n.__('predicate-public'),
|
||||
predicate_private: TAPi18n.__('predicate-private'),
|
||||
predicate_due: TAPi18n.__('predicate-due'),
|
||||
predicate_created: TAPi18n.__('predicate-created'),
|
||||
predicate_modified: TAPi18n.__('predicate-modified'),
|
||||
predicate_start: TAPi18n.__('predicate-start'),
|
||||
predicate_end: TAPi18n.__('predicate-end'),
|
||||
predicate_assignee: TAPi18n.__('predicate-assignee'),
|
||||
predicate_member: TAPi18n.__('predicate-member'),
|
||||
};
|
||||
|
||||
text = `# ${TAPi18n.__('globalSearch-instructions-heading')}`;
|
||||
text += `\n${TAPi18n.__('globalSearch-instructions-description', tags)}`;
|
||||
text += `\n${TAPi18n.__('globalSearch-instructions-operators', tags)}`;
|
||||
text += `\n* ${TAPi18n.__(
|
||||
'globalSearch-instructions-operator-board',
|
||||
tags,
|
||||
)}`;
|
||||
text += `\n* ${TAPi18n.__(
|
||||
'globalSearch-instructions-operator-list',
|
||||
tags,
|
||||
)}`;
|
||||
text += `\n* ${TAPi18n.__(
|
||||
'globalSearch-instructions-operator-swimlane',
|
||||
tags,
|
||||
)}`;
|
||||
text += `\n* ${TAPi18n.__(
|
||||
'globalSearch-instructions-operator-label',
|
||||
tags,
|
||||
)}`;
|
||||
text += `\n* ${TAPi18n.__(
|
||||
'globalSearch-instructions-operator-hash',
|
||||
tags,
|
||||
)}`;
|
||||
text += `\n* ${TAPi18n.__(
|
||||
'globalSearch-instructions-operator-user',
|
||||
tags,
|
||||
)}`;
|
||||
text += `\n* ${TAPi18n.__('globalSearch-instructions-operator-at', tags)}`;
|
||||
text += `\n* ${TAPi18n.__(
|
||||
'globalSearch-instructions-operator-member',
|
||||
tags,
|
||||
)}`;
|
||||
text += `\n* ${TAPi18n.__(
|
||||
'globalSearch-instructions-operator-assignee',
|
||||
tags,
|
||||
)}`;
|
||||
|
||||
text += `\n## ${TAPi18n.__('heading-notes')}`;
|
||||
text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-1', tags)}`;
|
||||
text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-2', tags)}`;
|
||||
text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-3', tags)}`;
|
||||
text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-4', tags)}`;
|
||||
text += `\n* ${TAPi18n.__('globalSearch-instructions-notes-5', tags)}`;
|
||||
let text = '';
|
||||
[
|
||||
['# ', 'globalSearch-instructions-heading'],
|
||||
['\n', 'globalSearch-instructions-description'],
|
||||
['\n\n', 'globalSearch-instructions-operators'],
|
||||
['\n* ', 'globalSearch-instructions-operator-board'],
|
||||
['\n* ', 'globalSearch-instructions-operator-list'],
|
||||
['\n* ', 'globalSearch-instructions-operator-swimlane'],
|
||||
['\n* ', 'globalSearch-instructions-operator-comment'],
|
||||
['\n* ', 'globalSearch-instructions-operator-label'],
|
||||
['\n* ', 'globalSearch-instructions-operator-hash'],
|
||||
['\n* ', 'globalSearch-instructions-operator-user'],
|
||||
['\n* ', 'globalSearch-instructions-operator-at'],
|
||||
['\n* ', 'globalSearch-instructions-operator-member'],
|
||||
['\n* ', 'globalSearch-instructions-operator-assignee'],
|
||||
['\n* ', 'globalSearch-instructions-operator-due'],
|
||||
['\n* ', 'globalSearch-instructions-operator-created'],
|
||||
['\n* ', 'globalSearch-instructions-operator-modified'],
|
||||
['\n* ', 'globalSearch-instructions-operator-status'],
|
||||
['\n * ', 'globalSearch-instructions-status-archived'],
|
||||
['\n * ', 'globalSearch-instructions-status-public'],
|
||||
['\n * ', 'globalSearch-instructions-status-private'],
|
||||
['\n * ', 'globalSearch-instructions-status-all'],
|
||||
['\n * ', 'globalSearch-instructions-status-ended'],
|
||||
['\n* ', 'globalSearch-instructions-operator-has'],
|
||||
['\n* ', 'globalSearch-instructions-operator-sort'],
|
||||
['\n* ', 'globalSearch-instructions-operator-limit'],
|
||||
['\n## ', 'heading-notes'],
|
||||
['\n* ', 'globalSearch-instructions-notes-1'],
|
||||
['\n* ', 'globalSearch-instructions-notes-2'],
|
||||
['\n* ', 'globalSearch-instructions-notes-3'],
|
||||
['\n* ', 'globalSearch-instructions-notes-3-2'],
|
||||
['\n* ', 'globalSearch-instructions-notes-4'],
|
||||
['\n* ', 'globalSearch-instructions-notes-5'],
|
||||
].forEach(([prefix, instruction]) => {
|
||||
text += `${prefix}${TAPi18n.__(instruction, tags)}`;
|
||||
});
|
||||
|
||||
return text;
|
||||
},
|
||||
}
|
||||
|
||||
labelColors() {
|
||||
return Boards.simpleSchema()._schema['labels.$.color'].allowedValues.map(
|
||||
@@ -418,19 +199,21 @@ BlazeComponent.extendComponent({
|
||||
return { color, name: TAPi18n.__(`color-${color}`) };
|
||||
},
|
||||
);
|
||||
},
|
||||
}
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
...super.events()[0],
|
||||
'submit .js-search-query-form'(evt) {
|
||||
evt.preventDefault();
|
||||
this.searchAllBoards(evt.target.searchQuery.value);
|
||||
},
|
||||
'click .js-label-color'(evt) {
|
||||
evt.preventDefault();
|
||||
const input = document.getElementById('global-search-input');
|
||||
this.query.set(
|
||||
`${this.query.get()} ${TAPi18n.__('operator-label')}:"${
|
||||
`${input.value} ${TAPi18n.__('operator-label')}:"${
|
||||
evt.currentTarget.textContent
|
||||
}"`,
|
||||
);
|
||||
@@ -438,8 +221,9 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
'click .js-board-title'(evt) {
|
||||
evt.preventDefault();
|
||||
const input = document.getElementById('global-search-input');
|
||||
this.query.set(
|
||||
`${this.query.get()} ${TAPi18n.__('operator-board')}:"${
|
||||
`${input.value} ${TAPi18n.__('operator-board')}:"${
|
||||
evt.currentTarget.textContent
|
||||
}"`,
|
||||
);
|
||||
@@ -447,8 +231,9 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
'click .js-list-title'(evt) {
|
||||
evt.preventDefault();
|
||||
const input = document.getElementById('global-search-input');
|
||||
this.query.set(
|
||||
`${this.query.get()} ${TAPi18n.__('operator-list')}:"${
|
||||
`${input.value} ${TAPi18n.__('operator-list')}:"${
|
||||
evt.currentTarget.textContent
|
||||
}"`,
|
||||
);
|
||||
@@ -456,14 +241,24 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
'click .js-label-name'(evt) {
|
||||
evt.preventDefault();
|
||||
const input = document.getElementById('global-search-input');
|
||||
this.query.set(
|
||||
`${this.query.get()} ${TAPi18n.__('operator-label')}:"${
|
||||
`${input.value} ${TAPi18n.__('operator-label')}:"${
|
||||
evt.currentTarget.textContent
|
||||
}"`,
|
||||
);
|
||||
document.getElementById('global-search-input').focus();
|
||||
},
|
||||
'click .js-new-search'(evt) {
|
||||
evt.preventDefault();
|
||||
const input = document.getElementById('global-search-input');
|
||||
input.value = '';
|
||||
this.query.set('');
|
||||
this.hasResults.set(false);
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('globalSearch');
|
||||
}
|
||||
}
|
||||
|
||||
GlobalSearchComponent.register('globalSearch');
|
||||
@@ -71,17 +71,17 @@
|
||||
.global-search-error-messages
|
||||
color: darkred
|
||||
|
||||
.global-search-instructions
|
||||
.global-search-page
|
||||
width: 40%
|
||||
min-width: 400px
|
||||
margin-right: auto
|
||||
margin-left: auto
|
||||
line-height: 150%
|
||||
|
||||
.global-search-instructions h1
|
||||
.global-search-page h1
|
||||
margin-top: 2rem;
|
||||
|
||||
.global-search-instructions h2
|
||||
.global-search-page h2
|
||||
margin-top: 1rem;
|
||||
|
||||
.global-search-query-input
|
||||
@@ -100,7 +100,22 @@ code
|
||||
color: black
|
||||
background-color: lightgrey
|
||||
padding: 0.1rem !important
|
||||
font-size: 0.7rem !important
|
||||
font-size: 0.8rem !important
|
||||
|
||||
.list-title
|
||||
background-color: darkgray
|
||||
|
||||
.global-search-footer
|
||||
border: none
|
||||
width: 100%
|
||||
|
||||
.global-search-next-page
|
||||
border: none
|
||||
text-align: right;
|
||||
|
||||
.global-search-previous-page
|
||||
border: none
|
||||
text-align: left;
|
||||
|
||||
.global-search-instructions li
|
||||
margin-bottom: 0.3rem
|
||||
@@ -7,16 +7,21 @@ template(name="header")
|
||||
if currentUser
|
||||
#header-quick-access(class=currentBoard.colorClass)
|
||||
if isMiniScreen
|
||||
ul
|
||||
li
|
||||
a(href="{{pathFor 'home'}}")
|
||||
span.fa.fa-home
|
||||
span
|
||||
a(href="{{pathFor 'home'}}")
|
||||
span.fa.fa-home
|
||||
|
||||
ul.header-quick-access-list
|
||||
if currentList
|
||||
each currentBoard.lists
|
||||
li(class="{{#if $.Session.equals 'currentList' _id}}current{{/if}}")
|
||||
a.js-select-list
|
||||
= title
|
||||
else
|
||||
each currentUser.starredBoards
|
||||
li(class="{{#if $.Session.equals 'currentBoard' _id}}current{{/if}}")
|
||||
a(href="{{pathFor 'board' id=_id slug=slug}}")
|
||||
= title
|
||||
#header-new-board-icon
|
||||
else
|
||||
//-
|
||||
@@ -32,23 +37,21 @@ template(name="header")
|
||||
img(src="{{currentSetting.customTopLeftCornerLogoImageUrl}}" height="{{#if currentSetting.customTopLeftCornerLogoHeight}}#{currentSetting.customTopLeftCornerLogoHeight}{{else}}27{{/if}}" width="auto" margin="0" padding="0")
|
||||
unless currentSetting.customTopLeftCornerLogoImageUrl
|
||||
img(src="{{pathFor '/logo-header.png'}}" alt="")
|
||||
ul
|
||||
li
|
||||
a(href="{{pathFor 'home'}}")
|
||||
span.fa.fa-home
|
||||
| {{_ 'all-boards'}}
|
||||
li.separator -
|
||||
span.allBoards
|
||||
a(href="{{pathFor 'home'}}")
|
||||
span.fa.fa-home
|
||||
| {{_ 'all-boards'}}
|
||||
ul.header-quick-access-list
|
||||
//li
|
||||
// a(href="{{pathFor 'public'}}")
|
||||
// span.fa.fa-globe
|
||||
// | {{_ 'public'}}
|
||||
each currentUser.starredBoards
|
||||
li.separator -
|
||||
li(class="{{#if $.Session.equals 'currentBoard' _id}}current{{/if}}")
|
||||
a(href="{{pathFor 'board' id=_id slug=slug}}")
|
||||
= title
|
||||
else
|
||||
li.current {{_ 'quick-access-description'}}
|
||||
li.current.empty {{_ 'quick-access-description'}}
|
||||
|
||||
// Next line is used only for spacing at header,
|
||||
// there is no visible clickable icon.
|
||||
|
||||
@@ -100,6 +100,10 @@
|
||||
font-size: 12px
|
||||
display: flex
|
||||
z-index: 21
|
||||
padding: 10px 0px
|
||||
|
||||
.allBoards
|
||||
padding: 0 0 0 10px
|
||||
|
||||
#header-user-bar,
|
||||
#header-new-board-icon,
|
||||
@@ -112,21 +116,31 @@
|
||||
a:hover, a.is-active
|
||||
color: white
|
||||
|
||||
ul
|
||||
ul.header-quick-access-list
|
||||
transition: opacity 0.2s
|
||||
margin: 4px 0 0 5px
|
||||
overflow: hidden
|
||||
overflow-x: auto
|
||||
overflow-y: hidden
|
||||
white-space: nowrap
|
||||
padding: 10px
|
||||
margin: -10px
|
||||
|
||||
li
|
||||
display: block
|
||||
float: left
|
||||
display: inline
|
||||
width: auto
|
||||
color: darken(white, 15%)
|
||||
padding: 2px 5px 0
|
||||
padding: 12px 0px
|
||||
margin: -10px 0px
|
||||
|
||||
a
|
||||
padding: 12px 10px
|
||||
margin: -10px 0px
|
||||
|
||||
&.current
|
||||
color: darken(white, 5%)
|
||||
|
||||
&.current.empty
|
||||
padding: 12px 10px 12px 10px
|
||||
|
||||
&:first-child .fa-home,&:nth-child(3) .fa-globe
|
||||
margin-right: 5px
|
||||
|
||||
@@ -186,37 +200,32 @@
|
||||
#header-quick-access
|
||||
transition: background-color 0.4s
|
||||
width: 100%
|
||||
padding: 10px 0px
|
||||
z-index: 30
|
||||
|
||||
ul
|
||||
width: calc(100% - 60px)
|
||||
overflow: ellipsis
|
||||
padding: 10px
|
||||
margin: -10px
|
||||
margin-right: 10px
|
||||
|
||||
li
|
||||
height: 100%
|
||||
padding: 12px 0px
|
||||
margin: -10px 0px
|
||||
|
||||
a
|
||||
height: 100%
|
||||
padding: 12px 10px
|
||||
margin: -10px 0px
|
||||
|
||||
.fa-home
|
||||
span
|
||||
.fa-home
|
||||
font-size: 26px
|
||||
margin-top: -2px
|
||||
margin-right: 10px
|
||||
margin-left: 10px
|
||||
|
||||
#header-new-board-icon
|
||||
display: none
|
||||
|
||||
#header-user-bar
|
||||
position: absolute
|
||||
right: 0px
|
||||
padding: 10px
|
||||
margin: -10px 0 -10px -10px
|
||||
margin: -8px 0 -10px -10px
|
||||
|
||||
.announcement .viewer
|
||||
display: inline-block
|
||||
|
||||
@@ -77,20 +77,45 @@ Template.userFormsLayout.helpers({
|
||||
} else if (lang.name === 'ar-EG') {
|
||||
// ar-EG = Arabic (Egypt), simply Masri (مَصرى, [ˈmɑsˤɾi], Egyptian, Masr refers to Cairo)
|
||||
name = 'مَصرى';
|
||||
} else if (lang.name === 'es-PY') {
|
||||
name = 'Español de Paraguayo';
|
||||
} else if (lang.name === 'fa-IR') {
|
||||
// fa-IR = Persian (Iran)
|
||||
name = 'فارسی/پارسی (ایران)';
|
||||
} else if (lang.name === 'fr-BE') {
|
||||
name = 'Français (Belgique)';
|
||||
} else if (lang.name === 'fr-CA') {
|
||||
name = 'Français (Canada)';
|
||||
} else if (lang.name === 'fr-CA') {
|
||||
name = 'Français (Canada)';
|
||||
} else if (lang.name === 'ig') {
|
||||
name = 'Igbo';
|
||||
} else if (lang.name === 'lv') {
|
||||
name = 'Latviešu';
|
||||
} else if (lang.name === 'latviešu valoda') {
|
||||
name = 'Latviešu';
|
||||
} else if (lang.name === 'Español') {
|
||||
name = 'español';
|
||||
} else if (lang.name === 'es_419') {
|
||||
name = 'español de América Latina';
|
||||
} else if (lang.name === 'es-419') {
|
||||
name = 'español de América Latina';
|
||||
} else if (lang.name === 'Español de América Latina') {
|
||||
name = 'español de América Latina';
|
||||
} else if (lang.name === 'es-LA') {
|
||||
name = 'español de América Latina';
|
||||
} else if (lang.name === 'Español de Argentina') {
|
||||
name = 'español de Argentina';
|
||||
} else if (lang.name === 'Español de Chile') {
|
||||
name = 'español de Chile';
|
||||
} else if (lang.name === 'Español de Colombia') {
|
||||
name = 'español de Colombia';
|
||||
} else if (lang.name === 'Español de México') {
|
||||
name = 'español de México';
|
||||
} else if (lang.name === 'es-PY') {
|
||||
name = 'español de Paraguayo';
|
||||
} else if (lang.name === 'Español de Paraguayo') {
|
||||
name = 'español de Paraguayo';
|
||||
} else if (lang.name === 'Español de Perú') {
|
||||
name = 'español de Perú';
|
||||
} else if (lang.name === 'Español de Puerto Rico') {
|
||||
name = 'español de Puerto Rico';
|
||||
} else if (lang.name === 'oc') {
|
||||
name = 'Occitan';
|
||||
} else if (lang.name === 'st') {
|
||||
|
||||
@@ -24,14 +24,17 @@ template(name="myCardsModalTitle")
|
||||
|
||||
template(name="myCards")
|
||||
if currentUser
|
||||
if isPageReady.get
|
||||
if searching.get
|
||||
+spinner
|
||||
else
|
||||
.wrapper
|
||||
if $eq myCardsSort 'board'
|
||||
each board in myCardsList
|
||||
.my-cards-board-wrapper
|
||||
.my-cards-board-title
|
||||
+viewer
|
||||
= board.title
|
||||
.my-cards-board-title(class=board.colorClass, id="header")
|
||||
a(href=board.originRelativeUrl)
|
||||
+viewer
|
||||
= board.title
|
||||
each swimlane in board.mySwimlanes
|
||||
.my-cards-swimlane-title(class="{{#if swimlane.colorClass}}{{ swimlane.colorClass }}{{else}}swimlane-default-color{{/if}}")
|
||||
+viewer
|
||||
@@ -43,14 +46,12 @@ template(name="myCards")
|
||||
= list.title
|
||||
each card in list.myCards
|
||||
.my-cards-card-wrapper
|
||||
a.minicard-wrapper(href=card.absoluteUrl)
|
||||
a.minicard-wrapper(href=card.originRelativeUrl)
|
||||
+minicard(card)
|
||||
else
|
||||
.my-cards-dueat-list-wrapper
|
||||
each card in myDueCardsList
|
||||
+resultCard(card)
|
||||
else
|
||||
+spinner
|
||||
|
||||
template(name="myCardsSortChangePopup")
|
||||
if currentUser
|
||||
|
||||
+111
-153
@@ -1,4 +1,14 @@
|
||||
const subManager = new SubsManager();
|
||||
import { CardSearchPagedComponent } from '../../lib/cardSearch';
|
||||
import { QueryParams } from '../../../config/query-classes';
|
||||
import {
|
||||
OPERATOR_LIMIT,
|
||||
OPERATOR_SORT,
|
||||
OPERATOR_USER,
|
||||
ORDER_DESCENDING,
|
||||
PREDICATE_DUE_AT,
|
||||
} from '../../../config/search-const';
|
||||
|
||||
// const subManager = new SubsManager();
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
myCardsSort() {
|
||||
@@ -42,182 +52,147 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
}).register('myCardsSortChangePopup');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
class MyCardsComponent extends CardSearchPagedComponent {
|
||||
onCreated() {
|
||||
this.isPageReady = new ReactiveVar(false);
|
||||
super.onCreated();
|
||||
|
||||
this.autorun(() => {
|
||||
const handle = subManager.subscribe('myCards');
|
||||
Tracker.nonreactive(() => {
|
||||
Tracker.autorun(() => {
|
||||
this.isPageReady.set(handle.ready());
|
||||
});
|
||||
});
|
||||
const queryParams = new QueryParams();
|
||||
queryParams.addPredicate(OPERATOR_USER, Meteor.user().username);
|
||||
queryParams.addPredicate(OPERATOR_SORT, {
|
||||
name: PREDICATE_DUE_AT,
|
||||
order: ORDER_DESCENDING,
|
||||
});
|
||||
queryParams.addPredicate(OPERATOR_LIMIT, 100);
|
||||
|
||||
this.runGlobalSearch(queryParams);
|
||||
Meteor.subscribe('setting');
|
||||
},
|
||||
}
|
||||
|
||||
myCardsSort() {
|
||||
// eslint-disable-next-line no-console
|
||||
//console.log('sort:', Utils.myCardsSort());
|
||||
return Utils.myCardsSort();
|
||||
},
|
||||
}
|
||||
|
||||
sortByBoard() {
|
||||
return this.myCardsSort() === 'board';
|
||||
},
|
||||
}
|
||||
|
||||
myCardsList() {
|
||||
const userId = Meteor.userId();
|
||||
const boards = [];
|
||||
let board = null;
|
||||
let swimlane = null;
|
||||
let list = null;
|
||||
|
||||
const cursor = Cards.find(
|
||||
{
|
||||
$or: [{ members: userId }, { assignees: userId }],
|
||||
archived: false,
|
||||
},
|
||||
{
|
||||
sort: {
|
||||
boardId: 1,
|
||||
swimlaneId: 1,
|
||||
listId: 1,
|
||||
sort: 1,
|
||||
},
|
||||
},
|
||||
);
|
||||
const cursor = this.getResults();
|
||||
|
||||
let newBoard = false;
|
||||
let newSwimlane = false;
|
||||
let newList = false;
|
||||
if (cursor) {
|
||||
let newBoard = false;
|
||||
let newSwimlane = false;
|
||||
let newList = false;
|
||||
|
||||
cursor.forEach(card => {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('card:', card.title);
|
||||
if (list === null || card.listId !== list._id) {
|
||||
cursor.forEach(card => {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('new list');
|
||||
list = card.getList();
|
||||
if (list.archived) {
|
||||
list = null;
|
||||
return;
|
||||
// console.log('card:', card.title);
|
||||
if (list === null || card.listId !== list._id) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('new list');
|
||||
list = card.getList();
|
||||
if (list.archived) {
|
||||
list = null;
|
||||
return;
|
||||
}
|
||||
list.myCards = [card];
|
||||
newList = true;
|
||||
}
|
||||
list.myCards = [card];
|
||||
newList = true;
|
||||
}
|
||||
if (swimlane === null || card.swimlaneId !== swimlane._id) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('new swimlane');
|
||||
swimlane = card.getSwimlane();
|
||||
if (swimlane.archived) {
|
||||
swimlane = null;
|
||||
return;
|
||||
if (swimlane === null || card.swimlaneId !== swimlane._id) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('new swimlane');
|
||||
swimlane = card.getSwimlane();
|
||||
if (swimlane.archived) {
|
||||
swimlane = null;
|
||||
return;
|
||||
}
|
||||
swimlane.myLists = [list];
|
||||
newSwimlane = true;
|
||||
}
|
||||
swimlane.myLists = [list];
|
||||
newSwimlane = true;
|
||||
}
|
||||
if (board === null || card.boardId !== board._id) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('new board');
|
||||
board = card.getBoard();
|
||||
if (board.archived) {
|
||||
board = null;
|
||||
return;
|
||||
if (board === null || card.boardId !== board._id) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('new board');
|
||||
board = card.getBoard();
|
||||
if (board.archived) {
|
||||
board = null;
|
||||
return;
|
||||
}
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('board:', b, b._id, b.title);
|
||||
board.mySwimlanes = [swimlane];
|
||||
newBoard = true;
|
||||
}
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('board:', b, b._id, b.title);
|
||||
board.mySwimlanes = [swimlane];
|
||||
newBoard = true;
|
||||
}
|
||||
|
||||
if (newBoard) {
|
||||
boards.push(board);
|
||||
} else if (newSwimlane) {
|
||||
board.mySwimlanes.push(swimlane);
|
||||
} else if (newList) {
|
||||
swimlane.myLists.push(list);
|
||||
} else {
|
||||
list.myCards.push(card);
|
||||
}
|
||||
if (newBoard) {
|
||||
boards.push(board);
|
||||
} else if (newSwimlane) {
|
||||
board.mySwimlanes.push(swimlane);
|
||||
} else if (newList) {
|
||||
swimlane.myLists.push(list);
|
||||
} else {
|
||||
list.myCards.push(card);
|
||||
}
|
||||
|
||||
newBoard = false;
|
||||
newSwimlane = false;
|
||||
newList = false;
|
||||
});
|
||||
newBoard = false;
|
||||
newSwimlane = false;
|
||||
newList = false;
|
||||
});
|
||||
|
||||
// sort the data structure
|
||||
boards.forEach(board => {
|
||||
board.mySwimlanes.forEach(swimlane => {
|
||||
swimlane.myLists.forEach(list => {
|
||||
list.myCards.sort((a, b) => {
|
||||
// sort the data structure
|
||||
boards.forEach(board => {
|
||||
board.mySwimlanes.forEach(swimlane => {
|
||||
swimlane.myLists.forEach(list => {
|
||||
list.myCards.sort((a, b) => {
|
||||
return a.sort - b.sort;
|
||||
});
|
||||
});
|
||||
swimlane.myLists.sort((a, b) => {
|
||||
return a.sort - b.sort;
|
||||
});
|
||||
});
|
||||
swimlane.myLists.sort((a, b) => {
|
||||
board.mySwimlanes.sort((a, b) => {
|
||||
return a.sort - b.sort;
|
||||
});
|
||||
});
|
||||
board.mySwimlanes.sort((a, b) => {
|
||||
return a.sort - b.sort;
|
||||
|
||||
boards.sort((a, b) => {
|
||||
let x = a.sort;
|
||||
let y = b.sort;
|
||||
|
||||
// show the template board last
|
||||
if (a.type === 'template-container') {
|
||||
x = 99999999;
|
||||
} else if (b.type === 'template-container') {
|
||||
y = 99999999;
|
||||
}
|
||||
return x - y;
|
||||
});
|
||||
});
|
||||
|
||||
boards.sort((a, b) => {
|
||||
let x = a.sort;
|
||||
let y = b.sort;
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('boards:', boards);
|
||||
return boards;
|
||||
}
|
||||
|
||||
// show the template board last
|
||||
if (a.type === 'template-container') {
|
||||
x = 99999999;
|
||||
} else if (b.type === 'template-container') {
|
||||
y = 99999999;
|
||||
}
|
||||
return x - y;
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('boards:', boards);
|
||||
return boards;
|
||||
},
|
||||
return [];
|
||||
}
|
||||
|
||||
myDueCardsList() {
|
||||
const userId = Meteor.userId();
|
||||
|
||||
const cursor = Cards.find(
|
||||
{
|
||||
$or: [{ members: userId }, { assignees: userId }],
|
||||
archived: false,
|
||||
},
|
||||
{
|
||||
sort: {
|
||||
dueAt: -1,
|
||||
boardId: 1,
|
||||
swimlaneId: 1,
|
||||
listId: 1,
|
||||
sort: 1,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('cursor:', cursor);
|
||||
|
||||
const cursor = this.getResults();
|
||||
const cards = [];
|
||||
cursor.forEach(card => {
|
||||
if (
|
||||
!card.getBoard().archived &&
|
||||
!card.getSwimlane().archived &&
|
||||
!card.getList().archived
|
||||
) {
|
||||
cards.push(card);
|
||||
}
|
||||
cards.push(card);
|
||||
});
|
||||
|
||||
cards.sort((a, b) => {
|
||||
const x = a.dueAt === null ? Date('2100-12-31') : a.dueAt;
|
||||
const y = b.dueAt === null ? Date('2100-12-31') : b.dueAt;
|
||||
const x = a.dueAt === null ? new Date('2100-12-31') : a.dueAt;
|
||||
const y = b.dueAt === null ? new Date('2100-12-31') : b.dueAt;
|
||||
|
||||
if (x > y) return 1;
|
||||
else if (x < y) return -1;
|
||||
@@ -228,23 +203,6 @@ BlazeComponent.extendComponent({
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('cursor:', cards);
|
||||
return cards;
|
||||
},
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
// 'click .js-my-card'(evt) {
|
||||
// const card = this.currentData().card;
|
||||
// // eslint-disable-next-line no-console
|
||||
// console.log('currentData():', this.currentData());
|
||||
// // eslint-disable-next-line no-console
|
||||
// console.log('card:', card);
|
||||
// if (card) {
|
||||
// Utils.goCardId(card._id);
|
||||
// }
|
||||
// evt.preventDefault();
|
||||
// },
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('myCards');
|
||||
}
|
||||
}
|
||||
MyCardsComponent.register('myCards');
|
||||
@@ -1,14 +1,14 @@
|
||||
.my-cards-board-wrapper
|
||||
border-radius: 8px
|
||||
border-radius: 0 0 4px 4px;
|
||||
//padding: 0.5rem
|
||||
min-width: 400px
|
||||
border-width: 8px
|
||||
border-color: grey
|
||||
border-style: solid
|
||||
margin-bottom: 2rem
|
||||
margin-right: auto
|
||||
margin-left: auto
|
||||
|
||||
border-width: 2px
|
||||
border-style: solid
|
||||
border-color: #a2a2a2
|
||||
|
||||
.my-cards-board-title
|
||||
font-size: 1.4rem
|
||||
font-weight: bold
|
||||
@@ -41,9 +41,9 @@
|
||||
.my-cards-list-wrapper
|
||||
margin: 1rem
|
||||
border-radius: 5px
|
||||
padding: 1.5rem
|
||||
padding-top: 0.75rem
|
||||
display: table-cell
|
||||
//padding: 1.5rem
|
||||
//padding-top: 0.75rem
|
||||
display: inline-grid
|
||||
min-width: 250px
|
||||
max-width: 350px
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
.notification
|
||||
display: flex
|
||||
float: none
|
||||
padding: 12px 8px 8px
|
||||
padding: 15px 8px 8px
|
||||
color: black
|
||||
border-bottom: 1px solid #dbdbdb
|
||||
|
||||
@@ -14,6 +14,7 @@
|
||||
|
||||
.read-status
|
||||
width: 30px
|
||||
padding: 0px 10px 0px 0px
|
||||
|
||||
input
|
||||
width: 24px
|
||||
@@ -28,13 +29,16 @@
|
||||
color: #bbb
|
||||
|
||||
.details
|
||||
width: calc(100% - 30px)
|
||||
|
||||
.activity
|
||||
display: flex
|
||||
a.member
|
||||
margin: 0px 0px 0px 0px
|
||||
padding: 0px
|
||||
|
||||
svg
|
||||
padding: 3px
|
||||
|
||||
.activity-desc
|
||||
width: 100%;
|
||||
margin: 0px 0px 0px 5px
|
||||
|
||||
.activity-comment
|
||||
display: block
|
||||
@@ -55,3 +59,14 @@
|
||||
.remove
|
||||
a:hover
|
||||
color #eb4646 !important
|
||||
|
||||
@media screen and (max-width: 800px)
|
||||
#notifications-drawer
|
||||
.notification
|
||||
height: auto
|
||||
|
||||
.details
|
||||
.activity
|
||||
a.member
|
||||
height: 36px
|
||||
width: 36px
|
||||
@@ -2,7 +2,7 @@ belize = #2980b9
|
||||
|
||||
section#notifications-drawer
|
||||
position: fixed
|
||||
top: 28px
|
||||
top: 48px
|
||||
right: 0
|
||||
width: 400px
|
||||
background-color: #fafafa
|
||||
@@ -17,7 +17,7 @@ section#notifications-drawer
|
||||
|
||||
.header
|
||||
position: fixed
|
||||
top 28px
|
||||
top 48px
|
||||
right 0
|
||||
width calc(400px - 32px)
|
||||
padding: 8px 16px
|
||||
@@ -63,7 +63,7 @@ section#notifications-drawer
|
||||
|
||||
ul.notifications
|
||||
display: block
|
||||
padding: 0px 16px
|
||||
padding: 0px 16px 0px 16px
|
||||
margin: 0
|
||||
height: calc(100vh - 102px)
|
||||
height: calc(100vh - 122px)
|
||||
overflow-y: scroll
|
||||
Vendored
BIN
Binary file not shown.
@@ -74,7 +74,6 @@ template(name="orgGeneral")
|
||||
th {{_ 'description'}}
|
||||
th {{_ 'shortName'}}
|
||||
th {{_ 'website'}}
|
||||
th {{_ 'teams'}}
|
||||
th {{_ 'createdAt'}}
|
||||
th {{_ 'active'}}
|
||||
th
|
||||
@@ -110,6 +109,7 @@ template(name="peopleGeneral")
|
||||
th {{_ 'createdAt'}}
|
||||
th {{_ 'active'}}
|
||||
th {{_ 'authentication-method'}}
|
||||
th {{_ 'import-usernames'}}
|
||||
th
|
||||
+newUserRow
|
||||
each user in peopleList
|
||||
@@ -117,41 +117,37 @@ template(name="peopleGeneral")
|
||||
|
||||
template(name="newOrgRow")
|
||||
a.new-org
|
||||
i.fa.fa-edit
|
||||
i.fa.fa-plus-square
|
||||
| {{_ 'new'}}
|
||||
|
||||
template(name="newTeamRow")
|
||||
a.new-team
|
||||
i.fa.fa-edit
|
||||
i.fa.fa-plus-square
|
||||
| {{_ 'new'}}
|
||||
|
||||
template(name="newUserRow")
|
||||
a.new-user
|
||||
i.fa.fa-edit
|
||||
i.fa.fa-plus-square
|
||||
| {{_ 'new'}}
|
||||
|
||||
template(name="orgRow")
|
||||
tr
|
||||
if orgData.loginDisabled
|
||||
td <s>{{ orgData.displayName }}</s>
|
||||
td <s>{{ orgData.orgDisplayName }}</s>
|
||||
else
|
||||
td {{ orgData.displayName }}
|
||||
td {{ orgData.orgDisplayName }}
|
||||
if orgData.loginDisabled
|
||||
td <s>{{ orgData.orgDesc }}</s>
|
||||
else
|
||||
td {{ orgData.desc }}
|
||||
td {{ orgData.orgDesc }}
|
||||
if orgData.loginDisabled
|
||||
td <s>{{ orgData.name }}</s>
|
||||
td <s>{{ orgData.orgName }}</s>
|
||||
else
|
||||
td {{ orgData.name }}
|
||||
td {{ orgData.orgName }}
|
||||
if orgData.loginDisabled
|
||||
td <s>{{ orgData.website }}</s>
|
||||
td <s>{{ orgData.orgWebsite }}</s>
|
||||
else
|
||||
td {{ orgData.website }}
|
||||
if orgData.loginDisabled
|
||||
td <s>{{ orgData.teams }}</s>
|
||||
else
|
||||
td {{ orgData.teams }}
|
||||
td {{ orgData.orgWebsite }}
|
||||
if orgData.loginDisabled
|
||||
td <s>{{ moment orgData.createdAt 'LLL' }}</s>
|
||||
else
|
||||
@@ -171,21 +167,21 @@ template(name="orgRow")
|
||||
template(name="teamRow")
|
||||
tr
|
||||
if teamData.loginDisabled
|
||||
td <s>{{ teamData.displayName }}</s>
|
||||
td <s>{{ teamData.teamDisplayName }}</s>
|
||||
else
|
||||
td {{ teamData.displayName }}
|
||||
td {{ teamData.teamDisplayName }}
|
||||
if teamData.loginDisabled
|
||||
td <s>{{ teamData.desc }}</s>
|
||||
td <s>{{ teamData.teamDesc }}</s>
|
||||
else
|
||||
td {{ teamData.desc }}
|
||||
td {{ teamData.teamDesc }}
|
||||
if teamData.loginDisabled
|
||||
td <s>{{ teamData.dame }}</s>
|
||||
td <s>{{ teamData.teamName }}</s>
|
||||
else
|
||||
td {{ teamData.name }}
|
||||
td {{ teamData.teamName }}
|
||||
if teamData.loginDisabled
|
||||
td <s>{{ teamData.website }}</s>
|
||||
td <s>{{ teamData.teamWebsite }}</s>
|
||||
else
|
||||
td {{ teamData.website }}
|
||||
td {{ teamData.teamWebsite }}
|
||||
if orgData.loginDisabled
|
||||
td <s>{{ moment teamData.createdAt 'LLL' }}</s>
|
||||
else
|
||||
@@ -257,6 +253,10 @@ template(name="peopleRow")
|
||||
td <s>{{_ userData.authenticationMethod }}</s>
|
||||
else
|
||||
td {{_ userData.authenticationMethod }}
|
||||
if userData.loginDisabled
|
||||
td <s>{{ userData.importUsernamesString }}</s>
|
||||
else
|
||||
td {{ userData.importUsernamesString }}
|
||||
td
|
||||
a.edit-user
|
||||
i.fa.fa-edit
|
||||
@@ -268,19 +268,19 @@ template(name="editOrgPopup")
|
||||
form
|
||||
label.hide.orgId(type="text" value=org._id)
|
||||
label
|
||||
| {{_ 'orgDisplayName'}}
|
||||
| {{_ 'displayName'}}
|
||||
input.js-orgDisplayName(type="text" value=org.displayName required)
|
||||
span.error.hide.orgname-taken
|
||||
| {{_ 'error-orgname-taken'}}
|
||||
label
|
||||
| {{_ 'orgDesc'}}
|
||||
input.js-orgDesc(type="text" value=org.desc required)
|
||||
| {{_ 'description'}}
|
||||
input.js-orgDesc(type="text" value=org.orgDesc required)
|
||||
label
|
||||
| {{_ 'orgName'}}
|
||||
input.js-orgName(type="text" value=org.name required)
|
||||
| {{_ 'shortName'}}
|
||||
input.js-orgShortName(type="text" value=org.orgShortName required)
|
||||
label
|
||||
| {{_ 'orgWebsite'}}
|
||||
input.js-orgWebsite(type="text" value=org.website required)
|
||||
| {{_ 'website'}}
|
||||
input.js-orgWebsite(type="text" value=org.orgWebsite required)
|
||||
label
|
||||
| {{_ 'active'}}
|
||||
select.select-active.js-org-isactive
|
||||
@@ -295,18 +295,18 @@ template(name="editTeamPopup")
|
||||
label.hide.teamId(type="text" value=team._id)
|
||||
label
|
||||
| {{_ 'displayName'}}
|
||||
input.js-teamDisplayName(type="text" value=team.displayName required)
|
||||
input.js-teamDisplayName(type="text" value=team.teamDisplayName required)
|
||||
span.error.hide.teamname-taken
|
||||
| {{_ 'error-teamname-taken'}}
|
||||
label
|
||||
| {{_ 'description'}}
|
||||
input.js-orgDesc(type="text" value=org.desc required)
|
||||
input.js-teamDesc(type="text" value=team.teamDesc required)
|
||||
label
|
||||
| {{_ 'name'}}
|
||||
input.js-orgName(type="text" value=org.name required)
|
||||
| {{_ 'shortName'}}
|
||||
input.js-teamShortName(type="text" value=team.teamShortName required)
|
||||
label
|
||||
| {{_ 'website'}}
|
||||
input.js-orgWebsite(type="text" value=org.website required)
|
||||
input.js-teamWebsite(type="text" value=team.teamWebsite required)
|
||||
label
|
||||
| {{_ 'active'}}
|
||||
select.select-active.js-team-isactive
|
||||
@@ -332,7 +332,7 @@ template(name="editUserPopup")
|
||||
input.js-profile-fullname(type="text" value=user.profile.fullname required)
|
||||
label
|
||||
| {{_ 'initials'}}
|
||||
input.js-profile-initials(type="text" value=user.profile.initials)
|
||||
input.js-profile-initials(type="text" value=user.profile.initials required)
|
||||
label
|
||||
| {{_ 'admin'}}
|
||||
select.select-role.js-profile-isadmin
|
||||
@@ -346,6 +346,9 @@ template(name="editUserPopup")
|
||||
input.js-profile-email(type="email" value="{{user.emails.[0].address}}" readonly)
|
||||
else
|
||||
input.js-profile-email(type="email" value="{{user.emails.[0].address}}" required)
|
||||
label
|
||||
| {{_ 'import-usernames'}}
|
||||
input.js-import-usernames(type="text" value=user.importUsernames)
|
||||
label
|
||||
| {{_ 'verified'}}
|
||||
select.select-verified.js-profile-email-verified
|
||||
@@ -376,22 +379,19 @@ template(name="newOrgPopup")
|
||||
//label.hide.userId(type="text" value=user._id)
|
||||
label
|
||||
| {{_ 'displayName'}}
|
||||
input.js-displayName(type="text" value="" required)
|
||||
input.js-orgDisplayName(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'description'}}
|
||||
input.js-desc(type="text" value="" required)
|
||||
input.js-orgDesc(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'shortName'}}
|
||||
input.js-name(type="text" value="")
|
||||
label
|
||||
| {{_ 'teams'}}
|
||||
input.js-teams(type="text" value="")
|
||||
input.js-orgName(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'website'}}
|
||||
input.js-website(type="text" value="")
|
||||
input.js-orgWebsite(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'active'}}
|
||||
select.select-active.js-profile-isactive
|
||||
select.select-active.js-org-isactive
|
||||
option(value="false" selected="selected") {{_ 'yes'}}
|
||||
option(value="true") {{_ 'no'}}
|
||||
hr
|
||||
@@ -409,13 +409,13 @@ template(name="newTeamPopup")
|
||||
input.js-teamDesc(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'shortName'}}
|
||||
input.js-teamName(type="text" value="")
|
||||
input.js-teamName(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'website'}}
|
||||
input.js-teamWebsite(type="text" value="")
|
||||
input.js-teamWebsite(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'active'}}
|
||||
select.select-active.js-profile-isactive
|
||||
select.select-active.js-team-isactive
|
||||
option(value="false" selected="selected") {{_ 'yes'}}
|
||||
option(value="true") {{_ 'no'}}
|
||||
hr
|
||||
@@ -436,6 +436,9 @@ template(name="newUserPopup")
|
||||
// input.js-profile-username(type="text" value=user.username readonly)
|
||||
//else
|
||||
input.js-profile-username(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'initials'}}
|
||||
input.js-profile-initials(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'email'}}
|
||||
span.error.hide.email-taken
|
||||
@@ -444,6 +447,9 @@ template(name="newUserPopup")
|
||||
// input.js-profile-email(type="email" value="{{user.emails.[0].address}}" readonly)
|
||||
//else
|
||||
input.js-profile-email(type="email" value="" required)
|
||||
label
|
||||
| {{_ 'import-usernames'}}
|
||||
input.js-import-usernames(type="text" value="")
|
||||
label
|
||||
| {{_ 'admin'}}
|
||||
select.select-role.js-profile-isadmin
|
||||
|
||||
@@ -143,7 +143,7 @@ BlazeComponent.extendComponent({
|
||||
const orgs = Org.find(this.findOrgsOptions.get(), {
|
||||
fields: { _id: true },
|
||||
});
|
||||
this.numberOrgs.set(org.count(false));
|
||||
this.numberOrgs.set(orgs.count(false));
|
||||
return orgs;
|
||||
},
|
||||
teamList() {
|
||||
@@ -404,6 +404,88 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
}).register('newUserRow');
|
||||
|
||||
Template.editOrgPopup.events({
|
||||
submit(event, templateInstance) {
|
||||
event.preventDefault();
|
||||
const org = Orgs.findOne(this.orgId);
|
||||
|
||||
const orgDisplayName = templateInstance
|
||||
.find('.js-orgDisplayName')
|
||||
.value.trim();
|
||||
const orgDesc = templateInstance.find('.js-orgDesc').value.trim();
|
||||
const orgShortName = templateInstance.find('.js-orgShortName').value.trim();
|
||||
const orgWebsite = templateInstance.find('.js-orgWebsite').value.trim();
|
||||
const orgIsActive = templateInstance.find('.js-org-isactive').value.trim();
|
||||
|
||||
const isChangeOrgDisplayName = orgDisplayName !== org.orgDisplayName;
|
||||
const isChangeOrgDesc = orgDesc !== org.orgDesc;
|
||||
const isChangeOrgShortName = orgShortName !== org.orgShortName;
|
||||
const isChangeOrgWebsite = orgWebsite !== org.orgWebsite;
|
||||
const isChangeOrgIsActive = orgIsActive !== org.orgIsActive;
|
||||
|
||||
if (isChangeOrgDisplayName) {
|
||||
Meteor.call('setOrgDisplayName', org, orgDisplayName);
|
||||
}
|
||||
|
||||
if (isChangeOrgDesc) {
|
||||
Meteor.call('setOrgDesc', org, orgDesc);
|
||||
}
|
||||
|
||||
if (isChangeOrgShortName) {
|
||||
Meteor.call('setOrgShortName', org, orgShortName);
|
||||
}
|
||||
|
||||
if (isChangeOrgIsActive) {
|
||||
Meteor.call('setOrgIsActive', org, orgIsActive);
|
||||
}
|
||||
|
||||
Popup.close();
|
||||
},
|
||||
});
|
||||
|
||||
Template.editTeamPopup.events({
|
||||
submit(event, templateInstance) {
|
||||
event.preventDefault();
|
||||
const team = Teams.findOne(this.teamId);
|
||||
|
||||
const teamDisplayName = templateInstance
|
||||
.find('.js-teamDisplayName')
|
||||
.value.trim();
|
||||
const teamDesc = templateInstance.find('.js-teamDesc').value.trim();
|
||||
const teamShortName = templateInstance
|
||||
.find('.js-teamShortName')
|
||||
.value.trim();
|
||||
const teamWebsite = templateInstance.find('.js-teamWebsite').value.trim();
|
||||
const teamIsActive = templateInstance
|
||||
.find('.js-team-isactive')
|
||||
.value.trim();
|
||||
|
||||
const isChangeTeamDisplayName = teamDisplayName !== team.teamDisplayName;
|
||||
const isChangeTeamDesc = teamDesc !== team.teamDesc;
|
||||
const isChangeTeamShortName = teamShortName !== team.teamShortName;
|
||||
const isChangeTeamWebsite = teamWebsite !== team.teamWebsite;
|
||||
const isChangeTeamIsActive = teamIsActive !== team.teamIsActive;
|
||||
|
||||
if (isChangeTeamDisplayName) {
|
||||
Meteor.call('setTeamDisplayName', team, teamDisplayName);
|
||||
}
|
||||
|
||||
if (isChangeTeamDesc) {
|
||||
Meteor.call('setTeamDesc', team, teamDesc);
|
||||
}
|
||||
|
||||
if (isChangeTeamShortName) {
|
||||
Meteor.call('setTeamShortName', team, teamShortName);
|
||||
}
|
||||
|
||||
if (isChangeTeamIsActive) {
|
||||
Meteor.call('setTeamIsActive', team, teamIsActive);
|
||||
}
|
||||
|
||||
Popup.close();
|
||||
},
|
||||
});
|
||||
|
||||
Template.editUserPopup.events({
|
||||
submit(event, templateInstance) {
|
||||
event.preventDefault();
|
||||
@@ -421,6 +503,9 @@ Template.editUserPopup.events({
|
||||
const authentication = templateInstance
|
||||
.find('.js-authenticationMethod')
|
||||
.value.trim();
|
||||
const importUsernames = templateInstance
|
||||
.find('.js-import-usernames')
|
||||
.value.trim();
|
||||
|
||||
const isChangePassword = password.length > 0;
|
||||
const isChangeUserName = username !== user.username;
|
||||
@@ -441,6 +526,7 @@ Template.editUserPopup.events({
|
||||
isAdmin: isAdmin === 'true',
|
||||
loginDisabled: isActive === 'true',
|
||||
authenticationMethod: authentication,
|
||||
importUsernames: Users.parseImportUsernames(importUsernames),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -516,39 +602,48 @@ Template.editUserPopup.events({
|
||||
Template.newOrgPopup.events({
|
||||
submit(event, templateInstance) {
|
||||
event.preventDefault();
|
||||
const displayName = templateInstance.find('.js-displayName').value.trim();
|
||||
const desc = templateInstance.find('.js-desc').value.trim();
|
||||
const name = templateInstance.find('.js-name').value.trim();
|
||||
const teams = templateInstance.find('.js-teams').value.trim();
|
||||
const website = templateInstance.find('.js-website').value.trim();
|
||||
const isActive = templateInstance.find('.js-profile-isactive').value.trim();
|
||||
const orgDisplayName = templateInstance
|
||||
.find('.js-orgDisplayName')
|
||||
.value.trim();
|
||||
const orgDesc = templateInstance.find('.js-orgDesc').value.trim();
|
||||
const orgShortName = templateInstance.find('.js-orgShortName').value.trim();
|
||||
const orgWebsite = templateInstance.find('.js-orgWebsite').value.trim();
|
||||
const orgIsActive = templateInstance.find('.js-org-isactive').value.trim();
|
||||
|
||||
Meteor.call(
|
||||
'setCreateOrg',
|
||||
displayName,
|
||||
desc,
|
||||
name,
|
||||
teams,
|
||||
website,
|
||||
isActive,
|
||||
email.toLowerCase(),
|
||||
function(error) {
|
||||
const nameMessageElement = templateInstance.$('.name-taken');
|
||||
if (error) {
|
||||
const errorElement = error.error;
|
||||
if (errorElement === 'name-already-taken') {
|
||||
nameMessageElement.show();
|
||||
emailMessageElement.hide();
|
||||
} else if (errorElement === 'email-already-taken') {
|
||||
usernameMessageElement.hide();
|
||||
emailMessageElement.show();
|
||||
}
|
||||
} else {
|
||||
usernameMessageElement.hide();
|
||||
emailMessageElement.hide();
|
||||
Popup.close();
|
||||
}
|
||||
},
|
||||
orgDisplayName,
|
||||
orgDesc,
|
||||
orgShortName,
|
||||
orgWebsite,
|
||||
orgIsActive,
|
||||
);
|
||||
Popup.close();
|
||||
},
|
||||
});
|
||||
|
||||
Template.newTeamPopup.events({
|
||||
submit(event, templateInstance) {
|
||||
event.preventDefault();
|
||||
const teamDisplayName = templateInstance
|
||||
.find('.js-teamDisplayName')
|
||||
.value.trim();
|
||||
const teamDesc = templateInstance.find('.js-teamDesc').value.trim();
|
||||
const teamShortName = templateInstance
|
||||
.find('.js-teamShortName')
|
||||
.value.trim();
|
||||
const teamWebsite = templateInstance.find('.js-teamWebsite').value.trim();
|
||||
const teamIsActive = templateInstance
|
||||
.find('.js-team-isactive')
|
||||
.value.trim();
|
||||
|
||||
Meteor.call(
|
||||
'setCreateTeam',
|
||||
teamDisplayName,
|
||||
teamDesc,
|
||||
teamShortName,
|
||||
teamWebsite,
|
||||
teamIsActive,
|
||||
);
|
||||
Popup.close();
|
||||
},
|
||||
@@ -559,19 +654,25 @@ Template.newUserPopup.events({
|
||||
event.preventDefault();
|
||||
const fullname = templateInstance.find('.js-profile-fullname').value.trim();
|
||||
const username = templateInstance.find('.js-profile-username').value.trim();
|
||||
const initials = templateInstance.find('.js-profile-initials').value.trim();
|
||||
const password = templateInstance.find('.js-profile-password').value;
|
||||
const isAdmin = templateInstance.find('.js-profile-isadmin').value.trim();
|
||||
const isActive = templateInstance.find('.js-profile-isactive').value.trim();
|
||||
const email = templateInstance.find('.js-profile-email').value.trim();
|
||||
const importUsernames = Users.parseImportUsernames(
|
||||
templateInstance.find('.js-import-usernames').value,
|
||||
);
|
||||
|
||||
Meteor.call(
|
||||
'setCreateUser',
|
||||
fullname,
|
||||
username,
|
||||
initials,
|
||||
password,
|
||||
isAdmin,
|
||||
isActive,
|
||||
email.toLowerCase(),
|
||||
importUsernames,
|
||||
function(error) {
|
||||
const usernameMessageElement = templateInstance.$('.username-taken');
|
||||
const emailMessageElement = templateInstance.$('.email-taken');
|
||||
|
||||
@@ -13,10 +13,11 @@ template(name="setting")
|
||||
a.js-setting-menu(data-id="registration-setting")
|
||||
i.fa.fa-sign-in
|
||||
| {{_ 'registration'}}
|
||||
li
|
||||
a.js-setting-menu(data-id="email-setting")
|
||||
i.fa.fa-envelope
|
||||
| {{_ 'email'}}
|
||||
unless isSandstorm
|
||||
li
|
||||
a.js-setting-menu(data-id="email-setting")
|
||||
i.fa.fa-envelope
|
||||
| {{_ 'email'}}
|
||||
li
|
||||
a.js-setting-menu(data-id="account-setting")
|
||||
i.fa.fa-users
|
||||
@@ -39,7 +40,8 @@ template(name="setting")
|
||||
else if generalSetting.get
|
||||
+general
|
||||
else if emailSetting.get
|
||||
+email
|
||||
unless isSandstorm
|
||||
+email
|
||||
else if accountSetting.get
|
||||
+accountSettings
|
||||
else if announcementSetting.get
|
||||
@@ -80,45 +82,48 @@ template(name="general")
|
||||
|
||||
template(name='email')
|
||||
ul#email-setting.setting-detail
|
||||
li.smtp-form
|
||||
.title {{_ 'smtp-host'}}
|
||||
.description {{_ 'smtp-host-description'}}
|
||||
.form-group
|
||||
input.wekan-form-control#mail-server-host(type="text", placeholder="smtp.domain.com" value="{{currentSetting.mailServer.host}}")
|
||||
li.smtp-form
|
||||
.title {{_ 'smtp-port'}}
|
||||
.description {{_ 'smtp-port-description'}}
|
||||
.form-group
|
||||
input.wekan-form-control#mail-server-port(type="text", placeholder="25" value="{{currentSetting.mailServer.port}}")
|
||||
li.smtp-form
|
||||
.title {{_ 'smtp-username'}}
|
||||
.form-group
|
||||
input.wekan-form-control#mail-server-username(type="text", placeholder="{{_ 'username'}}" value="{{currentSetting.mailServer.username}}")
|
||||
li.smtp-form
|
||||
.title {{_ 'smtp-password'}}
|
||||
.form-group
|
||||
input.wekan-form-control#mail-server-password(type="password", placeholder="{{_ 'password'}}" value="{{currentSetting.mailServer.password}}")
|
||||
li.smtp-form
|
||||
.title {{_ 'smtp-tls'}}
|
||||
.form-group
|
||||
a.flex.js-toggle-tls
|
||||
.materialCheckBox#mail-server-tls(class="{{#if currentSetting.mailServer.enableTLS}}is-checked{{/if}}")
|
||||
|
||||
span {{_ 'smtp-tls-description'}}
|
||||
|
||||
li.smtp-form
|
||||
.title {{_ 'send-from'}}
|
||||
.form-group
|
||||
input.wekan-form-control#mail-server-from(type="email", placeholder="no-reply@domain.com" value="{{currentSetting.mailServer.from}}")
|
||||
|
||||
li
|
||||
button.js-save.primary {{_ 'save'}}
|
||||
//if isSandstorm
|
||||
// li.smtp-form
|
||||
// .title {{_ 'smtp-host'}}
|
||||
// .description {{_ 'smtp-host-description'}}
|
||||
// .form-group
|
||||
// input.wekan-form-control#mail-server-host(type="text", placeholder="smtp.domain.com" value="{{currentSetting.mailServer.host}}")
|
||||
// li.smtp-form
|
||||
// .title {{_ 'smtp-port'}}
|
||||
// .description {{_ 'smtp-port-description'}}
|
||||
// .form-group
|
||||
// input.wekan-form-control#mail-server-port(type="text", placeholder="25" value="{{currentSetting.mailServer.port}}")
|
||||
// li.smtp-form
|
||||
// .title {{_ 'smtp-username'}}
|
||||
// .form-group
|
||||
// input.wekan-form-control#mail-server-username(type="text", placeholder="{{_ 'username'}}" value="{{currentSetting.mailServer.username}}")
|
||||
// li.smtp-form
|
||||
// .title {{_ 'smtp-password'}}
|
||||
// .form-group
|
||||
// input.wekan-form-control#mail-server-password(type="password", placeholder="{{_ 'password'}}" value="")
|
||||
// li.smtp-form
|
||||
// .title {{_ 'smtp-tls'}}
|
||||
// .form-group
|
||||
// a.flex.js-toggle-tls
|
||||
// .materialCheckBox#mail-server-tls(class="{{#if currentSetting.mailServer.enableTLS}}is-checked{{/if}}")
|
||||
//
|
||||
// span {{_ 'smtp-tls-description'}}
|
||||
//
|
||||
// li.smtp-form
|
||||
// .title {{_ 'send-from'}}
|
||||
// .form-group
|
||||
// input.wekan-form-control#mail-server-from(type="email", placeholder="no-reply@domain.com" value="{{currentSetting.mailServer.from}}")
|
||||
//
|
||||
// li
|
||||
// button.js-save.primary {{_ 'save'}}
|
||||
|
||||
li
|
||||
button.js-send-smtp-test-email.primary {{_ 'send-smtp-test'}}
|
||||
|
||||
template(name='accountSettings')
|
||||
ul#account-setting.setting-detail
|
||||
li
|
||||
button.js-all-hide-system-messages.primary {{_ 'hide-system-messages-of-all-users'}}
|
||||
li.accounts-form
|
||||
.title {{_ 'accounts-allowEmailChange'}}
|
||||
.form-group.flex
|
||||
@@ -126,23 +131,18 @@ template(name='accountSettings')
|
||||
span {{_ 'yes'}}
|
||||
input.wekan-form-control#accounts-allowEmailChange(type="radio" name="allowEmailChange" value="false" checked="{{#unless allowEmailChange}}checked{{/unless}}")
|
||||
span {{_ 'no'}}
|
||||
li
|
||||
li.accounts-form
|
||||
.title {{_ 'accounts-allowUserNameChange'}}
|
||||
.form-group.flex
|
||||
input.wekan-form-control#accounts-allowUserNameChange(type="radio" name="allowUserNameChange" value="true" checked="{{#if allowUserNameChange}}checked{{/if}}")
|
||||
span {{_ 'yes'}}
|
||||
input.wekan-form-control#accounts-allowUserNameChange(type="radio" name="allowUserNameChange" value="false" checked="{{#unless allowUserNameChange}}checked{{/unless}}")
|
||||
span {{_ 'no'}}
|
||||
li
|
||||
li.accounts-form
|
||||
.title {{_ 'accounts-allowUserDelete'}}
|
||||
.form-group.flex
|
||||
input.wekan-form-control#accounts-allowUserDelete(type="radio" name="allowUserDelete" value="true" checked="{{#if allowUserDelete}}checked{{/if}}")
|
||||
span {{_ 'yes'}}
|
||||
input.wekan-form-control#accounts-allowUserDelete(type="radio" name="allowUserDelete" value="false" checked="{{#unless allowUserDelete}}checked{{/unless}}")
|
||||
span {{_ 'no'}}
|
||||
li
|
||||
button.js-accounts-save.primary {{_ 'save'}}
|
||||
|
||||
template(name='announcementSettings')
|
||||
@@ -208,6 +208,10 @@ template(name='layoutSettings')
|
||||
.title {{_ 'custom-top-left-corner-logo-height'}}
|
||||
.form-group
|
||||
input.wekan-form-control#custom-top-left-corner-logo-height(type="text", placeholder="" value="{{currentSetting.customTopLeftCornerLogoHeight}}")
|
||||
li.layout-form
|
||||
.title {{_ 'automatic-linked-url-schemes'}}
|
||||
.form-group
|
||||
textarea#automatic-linked-url-schemes.wekan-form-control= currentSetting.automaticLinkedUrlSchemes
|
||||
li
|
||||
button.js-save-layout.primary {{_ 'save'}}
|
||||
|
||||
|
||||
@@ -176,6 +176,9 @@ BlazeComponent.extendComponent({
|
||||
const textBelowCustomLoginLogo = $('#text-below-custom-login-logo')
|
||||
.val()
|
||||
.trim();
|
||||
const automaticLinkedUrlSchemes = $('#automatic-linked-url-schemes')
|
||||
.val()
|
||||
.trim();
|
||||
const customTopLeftCornerLogoImageUrl = $(
|
||||
'#custom-top-left-corner-logo-image-url',
|
||||
)
|
||||
@@ -209,6 +212,7 @@ BlazeComponent.extendComponent({
|
||||
customTopLeftCornerLogoHeight,
|
||||
displayAuthenticationMethod,
|
||||
defaultAuthenticationMethod,
|
||||
automaticLinkedUrlSchemes,
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
@@ -270,7 +274,6 @@ BlazeComponent.extendComponent({
|
||||
$set: { booleanValue: allowUserDelete },
|
||||
});
|
||||
},
|
||||
|
||||
allowEmailChange() {
|
||||
return AccountSettings.findOne('accounts-allowEmailChange').booleanValue;
|
||||
},
|
||||
@@ -280,12 +283,31 @@ BlazeComponent.extendComponent({
|
||||
allowUserDelete() {
|
||||
return AccountSettings.findOne('accounts-allowUserDelete').booleanValue;
|
||||
},
|
||||
allHideSystemMessages() {
|
||||
Meteor.call('setAllUsersHideSystemMessages', (err, ret) => {
|
||||
if (!err && ret) {
|
||||
if (ret === true) {
|
||||
const message = `${TAPi18n.__(
|
||||
'now-system-messages-of-all-users-are-hidden',
|
||||
)}`;
|
||||
alert(message);
|
||||
}
|
||||
} else {
|
||||
const reason = err.reason || '';
|
||||
const message = `${TAPi18n.__(err.error)}\n${reason}`;
|
||||
alert(message);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click button.js-accounts-save': this.saveAccountsChange,
|
||||
},
|
||||
{
|
||||
'click button.js-all-hide-system-messages': this.allHideSystemMessages,
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('accountSettings');
|
||||
|
||||
@@ -14,6 +14,11 @@ template(name="archivesSidebar")
|
||||
if currentUser.isBoardMember
|
||||
unless isWorker
|
||||
p.quiet
|
||||
if this.archivedAt
|
||||
| {{_ 'archived-at' }}
|
||||
|
|
||||
| {{ moment this.archivedAt 'LLL' }}
|
||||
br
|
||||
a.js-restore-card {{_ 'restore'}}
|
||||
if currentUser.isBoardAdmin
|
||||
| -
|
||||
@@ -37,6 +42,11 @@ template(name="archivesSidebar")
|
||||
if currentUser.isBoardMember
|
||||
unless isWorker
|
||||
p.quiet
|
||||
if this.archivedAt
|
||||
| {{_ 'archived-at' }}
|
||||
|
|
||||
| {{ moment this.archivedAt 'LLL' }}
|
||||
br
|
||||
a.js-restore-list {{_ 'restore'}}
|
||||
if currentUser.isBoardAdmin
|
||||
| -
|
||||
@@ -58,6 +68,11 @@ template(name="archivesSidebar")
|
||||
if currentUser.isBoardMember
|
||||
unless isWorker
|
||||
p.quiet
|
||||
if this.archivedAt
|
||||
| {{_ 'archived-at' }}
|
||||
|
|
||||
| {{ moment this.archivedAt 'LLL' }}
|
||||
br
|
||||
a.js-restore-swimlane {{_ 'restore'}}
|
||||
if currentUser.isBoardAdmin
|
||||
| -
|
||||
|
||||
@@ -31,24 +31,39 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
archivedCards() {
|
||||
return Cards.find({
|
||||
archived: true,
|
||||
boardId: Session.get('currentBoard'),
|
||||
});
|
||||
return Cards.find(
|
||||
{
|
||||
archived: true,
|
||||
boardId: Session.get('currentBoard'),
|
||||
},
|
||||
{
|
||||
sort: { archivedAt: -1, modifiedAt: -1 },
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
archivedLists() {
|
||||
return Lists.find({
|
||||
archived: true,
|
||||
boardId: Session.get('currentBoard'),
|
||||
});
|
||||
return Lists.find(
|
||||
{
|
||||
archived: true,
|
||||
boardId: Session.get('currentBoard'),
|
||||
},
|
||||
{
|
||||
sort: { archivedAt: -1, modifiedAt: -1 },
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
archivedSwimlanes() {
|
||||
return Swimlanes.find({
|
||||
archived: true,
|
||||
boardId: Session.get('currentBoard'),
|
||||
});
|
||||
return Swimlanes.find(
|
||||
{
|
||||
archived: true,
|
||||
boardId: Session.get('currentBoard'),
|
||||
},
|
||||
{
|
||||
sort: { archivedAt: -1, modifiedAt: -1 },
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
cardIsInArchivedList() {
|
||||
|
||||
@@ -59,6 +59,10 @@ template(name="createCustomFieldPopup")
|
||||
|
||||
span {{_ 'automatically-field-on-card'}}
|
||||
|
||||
a.flex.js-field-always-on-card(class="{{#if alwaysOnCard}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if alwaysOnCard}}is-checked{{/if}}")
|
||||
span {{_ 'always-field-on-card'}}
|
||||
|
||||
a.flex.js-field-showLabel-on-card(class="{{#if showLabelOnMiniCard}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if showLabelOnMiniCard}}is-checked{{/if}}")
|
||||
|
||||
|
||||
@@ -16,7 +16,7 @@ BlazeComponent.extendComponent({
|
||||
}).register('customFieldsSidebar');
|
||||
|
||||
const CreateCustomFieldPopup = BlazeComponent.extendComponent({
|
||||
_types: ['text', 'number', 'date', 'dropdown', 'currency'],
|
||||
_types: ['text', 'number', 'date', 'dropdown', 'currency', 'checkbox'],
|
||||
|
||||
_currencyList: [
|
||||
{
|
||||
@@ -174,6 +174,14 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({
|
||||
$target.find('.materialCheckBox').toggleClass('is-checked');
|
||||
$target.toggleClass('is-checked');
|
||||
},
|
||||
'click .js-field-always-on-card'(evt) {
|
||||
let $target = $(evt.target);
|
||||
if (!$target.hasClass('js-field-always-on-card')) {
|
||||
$target = $target.parent();
|
||||
}
|
||||
$target.find('.materialCheckBox').toggleClass('is-checked');
|
||||
$target.toggleClass('is-checked');
|
||||
},
|
||||
'click .js-field-showLabel-on-card'(evt) {
|
||||
let $target = $(evt.target);
|
||||
if (!$target.hasClass('js-field-showLabel-on-card')) {
|
||||
@@ -194,6 +202,8 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({
|
||||
this.find('.js-field-showLabel-on-card.is-checked') !== null,
|
||||
automaticallyOnCard:
|
||||
this.find('.js-field-automatically-on-card.is-checked') !== null,
|
||||
alwaysOnCard:
|
||||
this.find('.js-field-always-on-card.is-checked') !== null,
|
||||
};
|
||||
|
||||
// insert or update
|
||||
|
||||
@@ -4,9 +4,9 @@ template(name="searchSidebar")
|
||||
.list-body
|
||||
.minilists.clearfix.js-minilists
|
||||
each (lists)
|
||||
a.minilist-wrapper.js-minilist(href=absoluteUrl)
|
||||
a.minilist-wrapper.js-minilist(href=originRelativeUrl)
|
||||
+minilist(this)
|
||||
.minicards.clearfix.js-minicards
|
||||
each (results)
|
||||
a.minicard-wrapper.js-minicard(href=absoluteUrl)
|
||||
a.minicard-wrapper.js-minicard(href=originRelativeUrl)
|
||||
+minicard(this)
|
||||
@@ -39,6 +39,8 @@ template(name="swimlaneActionPopup")
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li: a.js-close-swimlane {{_ 'archive-swimlane'}}
|
||||
ul.pop-over-list
|
||||
li: a.js-move-swimlane {{_ 'move-swimlane'}}
|
||||
|
||||
template(name="swimlaneAddPopup")
|
||||
unless currentUser.isCommentOnly
|
||||
|
||||
@@ -54,9 +54,10 @@ Template.swimlaneActionPopup.events({
|
||||
this.archive();
|
||||
Popup.close();
|
||||
},
|
||||
'click .js-move-swimlane': Popup.open('moveSwimlane'),
|
||||
});
|
||||
|
||||
Template.swimlaneActionPopup.helpers({
|
||||
Template.swimlaneActionPopup.events({
|
||||
isCommentOnly() {
|
||||
return Meteor.user().isCommentOnly();
|
||||
},
|
||||
|
||||
@@ -61,3 +61,13 @@ template(name="addListForm")
|
||||
a.open-list-composer.js-open-inlined-form
|
||||
i.fa.fa-plus
|
||||
| {{_ 'add-list'}}
|
||||
|
||||
template(name="moveSwimlanePopup")
|
||||
unless currentUser.isWorker
|
||||
label {{_ 'boards'}}:
|
||||
select.js-select-boards(autofocus)
|
||||
each toBoard in toBoards
|
||||
option(value="{{toBoard._id}}") {{toBoard.title}}
|
||||
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm.js-done {{_ 'done'}}
|
||||
@@ -323,3 +323,46 @@ BlazeComponent.extendComponent({
|
||||
initSortable(boardComponent, $listsDom);
|
||||
},
|
||||
}).register('listsGroup');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentSwimlane = this.currentData();
|
||||
},
|
||||
|
||||
board() {
|
||||
return Boards.findOne(Session.get('currentBoard'));
|
||||
},
|
||||
|
||||
toBoards() {
|
||||
const boards = Boards.find(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
type: 'board',
|
||||
_id: { $ne: this.board()._id },
|
||||
},
|
||||
{
|
||||
sort: { title: 1 },
|
||||
},
|
||||
);
|
||||
|
||||
return boards;
|
||||
},
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-done'() {
|
||||
const swimlane = Swimlanes.findOne(this.currentSwimlane._id);
|
||||
const bSelect = $('.js-select-boards')[0];
|
||||
let boardId;
|
||||
if (bSelect) {
|
||||
boardId = bSelect.options[bSelect.selectedIndex].value;
|
||||
Meteor.call('moveSwimlane', this.currentSwimlane._id, boardId);
|
||||
}
|
||||
Popup.close();
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('moveSwimlanePopup');
|
||||
@@ -9,7 +9,6 @@ avatar-radius = 50%
|
||||
float: left
|
||||
height: 30px
|
||||
width: @height
|
||||
margin: 0 4px 4px 0
|
||||
cursor: pointer
|
||||
user-select: none
|
||||
z-index: 1
|
||||
|
||||
@@ -143,7 +143,7 @@ template(name="changeSettingsPopup")
|
||||
label.bold.clear
|
||||
i.fa.fa-sort-numeric-asc
|
||||
| {{_ 'show-cards-minimum-count'}}
|
||||
input#show-cards-count-at.inline-input.left(type="number" value="#{showCardsCountAt}" min="0" max="99" onkeydown="return false")
|
||||
input#show-cards-count-at.inline-input.left(type="number" value="#{showCardsCountAt}" min="-1")
|
||||
label.bold.clear
|
||||
i.fa.fa-calendar
|
||||
| {{_ 'start-day-of-week'}}
|
||||
|
||||
@@ -168,10 +168,32 @@ Template.changeLanguagePopup.helpers({
|
||||
let name = lang.name;
|
||||
if (lang.name === 'br') {
|
||||
name = 'Brezhoneg';
|
||||
} else if (lang.name === 'ar-EG') {
|
||||
// ar-EG = Arabic (Egypt), simply Masri (مَصرى, [ˈmɑsˤɾi], Egyptian, Masr refers to Cairo)
|
||||
name = 'مَصرى';
|
||||
} else if (lang.name === 'fa-IR') {
|
||||
// fa-IR = Persian (Iran)
|
||||
name = 'فارسی/پارسی (ایران)';
|
||||
} else if (lang.name === 'fr-BE') {
|
||||
name = 'Français (Belgique)';
|
||||
} else if (lang.name === 'fr-CA') {
|
||||
name = 'Français (Canada)';
|
||||
} else if (lang.name === 'ig') {
|
||||
name = 'Igbo';
|
||||
} else if (lang.name === 'lv') {
|
||||
name = 'Latviešu';
|
||||
} else if (lang.name === 'latviešu valoda') {
|
||||
name = 'Latviešu';
|
||||
} else if (lang.name === 'Español') {
|
||||
name = 'español';
|
||||
} else if (lang.name === 'es_419') {
|
||||
name = 'español de América Latina';
|
||||
} else if (lang.name === 'es-419') {
|
||||
name = 'español de América Latina';
|
||||
} else if (lang.name === 'Español de América Latina') {
|
||||
name = 'español de América Latina';
|
||||
} else if (lang.name === 'es-LA') {
|
||||
name = 'español de América Latina';
|
||||
} else if (lang.name === 'Español de Argentina') {
|
||||
name = 'español de Argentina';
|
||||
} else if (lang.name === 'Español de Chile') {
|
||||
@@ -182,12 +204,16 @@ Template.changeLanguagePopup.helpers({
|
||||
name = 'español de México';
|
||||
} else if (lang.name === 'es-PY') {
|
||||
name = 'español de Paraguayo';
|
||||
} else if (lang.name === 'Español de Paraguayo') {
|
||||
name = 'español de Paraguayo';
|
||||
} else if (lang.name === 'Español de Perú') {
|
||||
name = 'español de Perú';
|
||||
} else if (lang.name === 'Español de Puerto Rico') {
|
||||
name = 'español de Puerto Rico';
|
||||
} else if (lang.name === 'oc') {
|
||||
name = 'Occitan';
|
||||
} else if (lang.name === 'st') {
|
||||
name = 'Sãotomense';
|
||||
} else if (lang.name === '繁体中文(台湾)') {
|
||||
name = '繁體中文(台灣)';
|
||||
}
|
||||
@@ -213,6 +239,7 @@ Template.changeLanguagePopup.events({
|
||||
'profile.language': this.tag,
|
||||
},
|
||||
});
|
||||
TAPi18n.setLanguage(this.tag);
|
||||
event.preventDefault();
|
||||
},
|
||||
});
|
||||
@@ -270,6 +297,13 @@ Template.changeSettingsPopup.helpers({
|
||||
});
|
||||
|
||||
Template.changeSettingsPopup.events({
|
||||
'keypress/paste #show-cards-count-at'() {
|
||||
let keyCode = event.keyCode;
|
||||
let charCode = String.fromCharCode(keyCode);
|
||||
let regex = new RegExp('[-0-9]');
|
||||
let ret = regex.test(charCode);
|
||||
return ret;
|
||||
},
|
||||
'click .js-toggle-desktop-drag-handles'() {
|
||||
currentUser = Meteor.user();
|
||||
if (currentUser) {
|
||||
@@ -292,7 +326,7 @@ Template.changeSettingsPopup.events({
|
||||
},
|
||||
'click .js-apply-user-settings'(event, templateInstance) {
|
||||
event.preventDefault();
|
||||
const minLimit = parseInt(
|
||||
let minLimit = parseInt(
|
||||
templateInstance.$('#show-cards-count-at').val(),
|
||||
10,
|
||||
);
|
||||
@@ -301,6 +335,9 @@ Template.changeSettingsPopup.events({
|
||||
10,
|
||||
);
|
||||
const currentUser = Meteor.user();
|
||||
if (isNaN(minLimit) || minLimit < -1) {
|
||||
minLimit = -1;
|
||||
}
|
||||
if (!isNaN(minLimit)) {
|
||||
if (currentUser) {
|
||||
Meteor.call('changeLimitToShowCardsCount', minLimit);
|
||||
|
||||
@@ -0,0 +1,183 @@
|
||||
import Cards from '../../models/cards';
|
||||
import SessionData from '../../models/usersessiondata';
|
||||
|
||||
export class CardSearchPagedComponent extends BlazeComponent {
|
||||
onCreated() {
|
||||
this.searching = new ReactiveVar(false);
|
||||
this.hasResults = new ReactiveVar(false);
|
||||
this.hasQueryErrors = new ReactiveVar(false);
|
||||
this.query = new ReactiveVar('');
|
||||
this.resultsHeading = new ReactiveVar('');
|
||||
this.searchLink = new ReactiveVar(null);
|
||||
this.results = new ReactiveVar([]);
|
||||
this.hasNextPage = new ReactiveVar(false);
|
||||
this.hasPreviousPage = new ReactiveVar(false);
|
||||
this.resultsCount = 0;
|
||||
this.totalHits = 0;
|
||||
this.queryErrors = null;
|
||||
this.resultsPerPage = 25;
|
||||
this.sessionId = SessionData.getSessionId();
|
||||
this.subscriptionHandle = null;
|
||||
this.serverError = new ReactiveVar(false);
|
||||
|
||||
const that = this;
|
||||
this.subscriptionCallbacks = {
|
||||
onReady() {
|
||||
that.getResults();
|
||||
that.searching.set(false);
|
||||
that.hasResults.set(true);
|
||||
that.serverError.set(false);
|
||||
},
|
||||
onError(error) {
|
||||
that.searching.set(false);
|
||||
that.hasResults.set(false);
|
||||
that.serverError.set(true);
|
||||
console.log('Error.reason:', error.reason);
|
||||
console.log('Error.message:', error.message);
|
||||
console.log('Error.stack:', error.stack);
|
||||
},
|
||||
};
|
||||
}
|
||||
|
||||
resetSearch() {
|
||||
this.searching.set(false);
|
||||
this.results.set([]);
|
||||
this.hasResults.set(false);
|
||||
this.hasQueryErrors.set(false);
|
||||
this.resultsHeading.set('');
|
||||
this.serverError.set(false);
|
||||
this.resultsCount = 0;
|
||||
this.totalHits = 0;
|
||||
this.queryErrors = null;
|
||||
}
|
||||
|
||||
getSessionData(sessionId) {
|
||||
return SessionData.findOne({
|
||||
sessionId: sessionId ? sessionId : SessionData.getSessionId(),
|
||||
});
|
||||
}
|
||||
|
||||
getResults() {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('getting results');
|
||||
const sessionData = this.getSessionData();
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('selector:', sessionData.getSelector());
|
||||
console.log('session data:', sessionData);
|
||||
const cards = [];
|
||||
sessionData.cards.forEach(cardId => {
|
||||
cards.push(Cards.findOne({ _id: cardId }));
|
||||
});
|
||||
this.queryErrors = sessionData.errors;
|
||||
if (this.queryErrors.length) {
|
||||
// console.log('queryErrors:', this.queryErrorMessages());
|
||||
this.hasQueryErrors.set(true);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (cards) {
|
||||
this.totalHits = sessionData.totalHits;
|
||||
this.resultsCount = cards.length;
|
||||
this.resultsStart = sessionData.lastHit - this.resultsCount + 1;
|
||||
this.resultsEnd = sessionData.lastHit;
|
||||
this.resultsHeading.set(this.getResultsHeading());
|
||||
this.results.set(cards);
|
||||
this.hasNextPage.set(sessionData.lastHit < sessionData.totalHits);
|
||||
this.hasPreviousPage.set(
|
||||
sessionData.lastHit - sessionData.resultsCount > 0,
|
||||
);
|
||||
return cards;
|
||||
}
|
||||
|
||||
this.resultsCount = 0;
|
||||
return null;
|
||||
}
|
||||
|
||||
stopSubscription() {
|
||||
if (this.subscriptionHandle) {
|
||||
this.subscriptionHandle.stop();
|
||||
}
|
||||
}
|
||||
|
||||
runGlobalSearch(queryParams) {
|
||||
this.searching.set(true);
|
||||
this.stopSubscription();
|
||||
this.subscriptionHandle = Meteor.subscribe(
|
||||
'globalSearch',
|
||||
this.sessionId,
|
||||
queryParams.params,
|
||||
queryParams.text,
|
||||
this.subscriptionCallbacks,
|
||||
);
|
||||
}
|
||||
|
||||
queryErrorMessages() {
|
||||
const messages = [];
|
||||
|
||||
this.queryErrors.forEach(err => {
|
||||
let value = err.color ? TAPi18n.__(`color-${err.value}`) : err.value;
|
||||
if (!value) {
|
||||
value = err.value;
|
||||
}
|
||||
messages.push(TAPi18n.__(err.tag, value));
|
||||
});
|
||||
|
||||
return messages;
|
||||
}
|
||||
|
||||
nextPage() {
|
||||
this.searching.set(true);
|
||||
this.stopSubscription();
|
||||
this.subscriptionHandle = Meteor.subscribe(
|
||||
'nextPage',
|
||||
this.sessionId,
|
||||
this.subscriptionCallbacks,
|
||||
);
|
||||
}
|
||||
|
||||
previousPage() {
|
||||
this.searching.set(true);
|
||||
this.stopSubscription();
|
||||
this.subscriptionHandle = Meteor.subscribe(
|
||||
'previousPage',
|
||||
this.sessionId,
|
||||
this.subscriptionCallbacks,
|
||||
);
|
||||
}
|
||||
|
||||
getResultsHeading() {
|
||||
if (this.resultsCount === 0) {
|
||||
return TAPi18n.__('no-cards-found');
|
||||
} 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-n-of-n-cards-found', {
|
||||
start: this.resultsStart,
|
||||
end: this.resultsEnd,
|
||||
total: this.totalHits,
|
||||
});
|
||||
}
|
||||
|
||||
getSearchHref() {
|
||||
const baseUrl = window.location.href.replace(/([?#].*$|\s*$)/, '');
|
||||
return `${baseUrl}?q=${encodeURIComponent(this.query.get())}`;
|
||||
}
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-next-page'(evt) {
|
||||
evt.preventDefault();
|
||||
this.nextPage();
|
||||
},
|
||||
'click .js-previous-page'(evt) {
|
||||
evt.preventDefault();
|
||||
this.previousPage();
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,11 @@
|
||||
// Helper function to replace HH with H for 24 hours format, because H allows also single-digit hours
|
||||
function adjustedTimeFormat() {
|
||||
return moment
|
||||
.localeData()
|
||||
.longDateFormat('LT')
|
||||
.replace(/HH/i, 'H');
|
||||
}
|
||||
|
||||
DatePicker = BlazeComponent.extendComponent({
|
||||
template() {
|
||||
return 'datepicker';
|
||||
@@ -77,7 +85,11 @@ DatePicker = BlazeComponent.extendComponent({
|
||||
},
|
||||
'keyup .js-time-field'() {
|
||||
// parse for localized time format in strict mode
|
||||
const dateMoment = moment(this.find('#time').value, 'LT', true);
|
||||
const dateMoment = moment(
|
||||
this.find('#time').value,
|
||||
adjustedTimeFormat(),
|
||||
true,
|
||||
);
|
||||
if (dateMoment.isValid()) {
|
||||
this.error.set('');
|
||||
}
|
||||
@@ -89,16 +101,30 @@ DatePicker = BlazeComponent.extendComponent({
|
||||
const time =
|
||||
evt.target.time.value ||
|
||||
moment(new Date().setHours(12, 0, 0)).format('LT');
|
||||
|
||||
const newTime = moment(time, adjustedTimeFormat(), true);
|
||||
const newDate = moment(evt.target.date.value, 'L', true);
|
||||
const dateString = `${evt.target.date.value} ${time}`;
|
||||
const newDate = moment(dateString, 'L LT', true);
|
||||
if (newDate.isValid()) {
|
||||
this._storeDate(newDate.toDate());
|
||||
Popup.close();
|
||||
} else {
|
||||
const newCompleteDate = moment(
|
||||
dateString,
|
||||
'L ' + adjustedTimeFormat(),
|
||||
true,
|
||||
);
|
||||
if (!newTime.isValid()) {
|
||||
this.error.set('invalid-time');
|
||||
evt.target.time.focus();
|
||||
}
|
||||
if (!newDate.isValid()) {
|
||||
this.error.set('invalid-date');
|
||||
evt.target.date.focus();
|
||||
}
|
||||
if (newCompleteDate.isValid()) {
|
||||
this._storeDate(newCompleteDate.toDate());
|
||||
Popup.close();
|
||||
} else {
|
||||
if (!this.error) {
|
||||
this.error.set('invalid');
|
||||
}
|
||||
}
|
||||
},
|
||||
'click .js-delete-date'(evt) {
|
||||
evt.preventDefault();
|
||||
|
||||
+17
-17
@@ -4,24 +4,24 @@
|
||||
|
||||
Meteor.startup(() => {
|
||||
TAPi18n.conf.i18n_files_route = Meteor._relativeToSiteRootUrl('/tap-i18n');
|
||||
Tracker.autorun(() => {
|
||||
const currentUser = Meteor.user();
|
||||
let language;
|
||||
if (currentUser) {
|
||||
language = currentUser.profile && currentUser.profile.language;
|
||||
}
|
||||
const currentUser = Meteor.user();
|
||||
let language;
|
||||
if (currentUser) {
|
||||
language = currentUser.profile && currentUser.profile.language;
|
||||
}
|
||||
|
||||
if (!language) {
|
||||
if (navigator.languages) {
|
||||
language = navigator.languages[0];
|
||||
} else {
|
||||
language = navigator.language || navigator.userLanguage;
|
||||
}
|
||||
if (!language) {
|
||||
if (navigator.languages) {
|
||||
language = navigator.languages[0];
|
||||
} else {
|
||||
language = navigator.language || navigator.userLanguage;
|
||||
}
|
||||
}
|
||||
|
||||
if (language) {
|
||||
TAPi18n.setLanguage(language);
|
||||
T9n.setLanguage(language);
|
||||
}
|
||||
});
|
||||
if (language) {
|
||||
TAPi18n.setLanguage(language);
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('language set!');
|
||||
T9n.setLanguage(language);
|
||||
}
|
||||
});
|
||||
+1
-1
@@ -50,5 +50,5 @@ EscapeActions.register(
|
||||
'modalWindow',
|
||||
() => Modal.close(),
|
||||
() => Modal.isOpen(),
|
||||
{ noClickEscapeOn: '.modal-container' },
|
||||
{ noClickEscapeOn: '.modal-container,.model-content' },
|
||||
);
|
||||
@@ -48,8 +48,6 @@ Utils = {
|
||||
let sort = window.localStorage.getItem('myCardsSort');
|
||||
|
||||
if (!sort || !['board', 'dueAt'].includes(sort)) {
|
||||
window.localStorage.setItem('myCardsSort', 'board');
|
||||
location.reload();
|
||||
sort = 'board';
|
||||
}
|
||||
|
||||
@@ -81,8 +79,6 @@ Utils = {
|
||||
let view = window.localStorage.getItem('dueCardsView');
|
||||
|
||||
if (!view || !['me', 'all'].includes(view)) {
|
||||
window.localStorage.setItem('dueCardsView', 'me');
|
||||
location.reload();
|
||||
view = 'me';
|
||||
}
|
||||
|
||||
|
||||
@@ -0,0 +1,506 @@
|
||||
import {
|
||||
OPERATOR_ASSIGNEE,
|
||||
OPERATOR_BOARD,
|
||||
OPERATOR_COMMENT,
|
||||
OPERATOR_CREATED_AT,
|
||||
OPERATOR_DUE,
|
||||
OPERATOR_HAS,
|
||||
OPERATOR_LABEL,
|
||||
OPERATOR_LIMIT,
|
||||
OPERATOR_LIST,
|
||||
OPERATOR_MEMBER,
|
||||
OPERATOR_MODIFIED_AT,
|
||||
OPERATOR_SORT,
|
||||
OPERATOR_STATUS,
|
||||
OPERATOR_SWIMLANE,
|
||||
OPERATOR_UNKNOWN,
|
||||
OPERATOR_USER,
|
||||
ORDER_ASCENDING,
|
||||
ORDER_DESCENDING,
|
||||
PREDICATE_ALL,
|
||||
PREDICATE_ARCHIVED,
|
||||
PREDICATE_ASSIGNEES,
|
||||
PREDICATE_ATTACHMENT,
|
||||
PREDICATE_CHECKLIST,
|
||||
PREDICATE_CREATED_AT,
|
||||
PREDICATE_DESCRIPTION,
|
||||
PREDICATE_DUE_AT,
|
||||
PREDICATE_END_AT,
|
||||
PREDICATE_ENDED,
|
||||
PREDICATE_MEMBERS,
|
||||
PREDICATE_MODIFIED_AT,
|
||||
PREDICATE_MONTH,
|
||||
PREDICATE_OPEN,
|
||||
PREDICATE_OVERDUE,
|
||||
PREDICATE_PRIVATE,
|
||||
PREDICATE_PUBLIC,
|
||||
PREDICATE_QUARTER,
|
||||
PREDICATE_START_AT,
|
||||
PREDICATE_WEEK,
|
||||
PREDICATE_YEAR,
|
||||
} from './search-const';
|
||||
import Boards from '../models/boards';
|
||||
import moment from 'moment';
|
||||
|
||||
export class QueryParams {
|
||||
text = '';
|
||||
|
||||
constructor(params = {}, text = '') {
|
||||
this.params = params;
|
||||
this.text = text;
|
||||
}
|
||||
|
||||
hasOperator(operator) {
|
||||
return (
|
||||
this.params[operator] !== undefined && this.params[operator].length > 0
|
||||
);
|
||||
}
|
||||
|
||||
addPredicate(operator, predicate) {
|
||||
if (!this.hasOperator(operator)) {
|
||||
this.params[operator] = [];
|
||||
}
|
||||
this.params[operator].push(predicate);
|
||||
}
|
||||
|
||||
setPredicate(operator, predicate) {
|
||||
this.params[operator] = predicate;
|
||||
}
|
||||
|
||||
getPredicate(operator) {
|
||||
return this.params[operator][0];
|
||||
}
|
||||
|
||||
getPredicates(operator) {
|
||||
return this.params[operator];
|
||||
}
|
||||
|
||||
getParams() {
|
||||
return this.params;
|
||||
}
|
||||
}
|
||||
|
||||
export class QueryErrors {
|
||||
operatorTagMap = [
|
||||
[OPERATOR_BOARD, 'board-title-not-found'],
|
||||
[OPERATOR_SWIMLANE, 'swimlane-title-not-found'],
|
||||
[
|
||||
OPERATOR_LABEL,
|
||||
label => {
|
||||
if (Boards.labelColors().includes(label)) {
|
||||
return {
|
||||
tag: 'label-color-not-found',
|
||||
value: label,
|
||||
color: true,
|
||||
};
|
||||
} else {
|
||||
return {
|
||||
tag: 'label-not-found',
|
||||
value: label,
|
||||
color: false,
|
||||
};
|
||||
}
|
||||
},
|
||||
],
|
||||
[OPERATOR_LIST, 'list-title-not-found'],
|
||||
[OPERATOR_COMMENT, 'comment-not-found'],
|
||||
[OPERATOR_USER, 'user-username-not-found'],
|
||||
[OPERATOR_ASSIGNEE, 'user-username-not-found'],
|
||||
[OPERATOR_MEMBER, 'user-username-not-found'],
|
||||
];
|
||||
|
||||
constructor() {
|
||||
this._errors = {};
|
||||
|
||||
this.operatorTags = {};
|
||||
this.operatorTagMap.forEach(([operator, tag]) => {
|
||||
this.operatorTags[operator] = tag;
|
||||
});
|
||||
|
||||
this.colorMap = Boards.colorMap();
|
||||
}
|
||||
|
||||
addError(operator, error) {
|
||||
if (!this._errors[operator]) {
|
||||
this._errors[operator] = [];
|
||||
}
|
||||
this._errors[operator].push(error);
|
||||
}
|
||||
|
||||
addNotFound(operator, value) {
|
||||
if (typeof this.operatorTags[operator] === 'function') {
|
||||
this.addError(operator, this.operatorTags[operator](value));
|
||||
} else {
|
||||
this.addError(operator, { tag: this.operatorTags[operator], value });
|
||||
}
|
||||
}
|
||||
|
||||
hasErrors() {
|
||||
return Object.entries(this._errors).length > 0;
|
||||
}
|
||||
|
||||
errors() {
|
||||
const errs = [];
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
Object.entries(this._errors).forEach(([, errors]) => {
|
||||
errors.forEach(err => {
|
||||
errs.push(err);
|
||||
});
|
||||
});
|
||||
return errs;
|
||||
}
|
||||
|
||||
errorMessages() {
|
||||
const messages = [];
|
||||
// eslint-disable-next-line no-unused-vars
|
||||
Object.entries(this._errors).forEach(([, errors]) => {
|
||||
errors.forEach(err => {
|
||||
messages.push(TAPi18n.__(err.tag, err.value));
|
||||
});
|
||||
});
|
||||
return messages;
|
||||
}
|
||||
}
|
||||
|
||||
export class Query {
|
||||
selector = {};
|
||||
projection = {};
|
||||
|
||||
constructor(selector, projection) {
|
||||
this._errors = new QueryErrors();
|
||||
this.queryParams = new QueryParams();
|
||||
this.colorMap = Boards.colorMap();
|
||||
|
||||
if (selector) {
|
||||
this.selector = selector;
|
||||
}
|
||||
|
||||
if (projection) {
|
||||
this.projection = projection;
|
||||
}
|
||||
}
|
||||
|
||||
hasErrors() {
|
||||
return this._errors.hasErrors();
|
||||
}
|
||||
|
||||
errors() {
|
||||
return this._errors.errors();
|
||||
}
|
||||
|
||||
errorMessages() {
|
||||
return this._errors.errorMessages();
|
||||
}
|
||||
|
||||
getQueryParams() {
|
||||
return this.queryParams;
|
||||
}
|
||||
|
||||
addPredicate(operator, predicate) {
|
||||
this.queryParams.addPredicate(operator, predicate);
|
||||
}
|
||||
|
||||
buildParams(queryText) {
|
||||
queryText = queryText.trim();
|
||||
// eslint-disable-next-line no-console
|
||||
//console.log('query:', query);
|
||||
|
||||
if (!queryText) {
|
||||
return;
|
||||
}
|
||||
|
||||
const reOperator1 = new RegExp(
|
||||
'^((?<operator>[\\p{Letter}\\p{Mark}]+):|(?<abbrev>[#@]))(?<value>[\\p{Letter}\\p{Mark}]+)(\\s+|$)',
|
||||
'iu',
|
||||
);
|
||||
const reOperator2 = new RegExp(
|
||||
'^((?<operator>[\\p{Letter}\\p{Mark}]+):|(?<abbrev>[#@]))(?<quote>["\']*)(?<value>.*?)\\k<quote>(\\s+|$)',
|
||||
'iu',
|
||||
);
|
||||
const reText = new RegExp('^(?<text>\\S+)(\\s+|$)', 'u');
|
||||
const reQuotedText = new RegExp(
|
||||
'^(?<quote>["\'])(?<text>.*?)\\k<quote>(\\s+|$)',
|
||||
'u',
|
||||
);
|
||||
const reNegatedOperator = new RegExp('^-(?<operator>.*)$');
|
||||
|
||||
const operators = {
|
||||
'operator-board': OPERATOR_BOARD,
|
||||
'operator-board-abbrev': OPERATOR_BOARD,
|
||||
'operator-swimlane': OPERATOR_SWIMLANE,
|
||||
'operator-swimlane-abbrev': OPERATOR_SWIMLANE,
|
||||
'operator-list': OPERATOR_LIST,
|
||||
'operator-list-abbrev': OPERATOR_LIST,
|
||||
'operator-label': OPERATOR_LABEL,
|
||||
'operator-label-abbrev': OPERATOR_LABEL,
|
||||
'operator-user': OPERATOR_USER,
|
||||
'operator-user-abbrev': OPERATOR_USER,
|
||||
'operator-member': OPERATOR_MEMBER,
|
||||
'operator-member-abbrev': OPERATOR_MEMBER,
|
||||
'operator-assignee': OPERATOR_ASSIGNEE,
|
||||
'operator-assignee-abbrev': OPERATOR_ASSIGNEE,
|
||||
'operator-status': OPERATOR_STATUS,
|
||||
'operator-due': OPERATOR_DUE,
|
||||
'operator-created': OPERATOR_CREATED_AT,
|
||||
'operator-modified': OPERATOR_MODIFIED_AT,
|
||||
'operator-comment': OPERATOR_COMMENT,
|
||||
'operator-has': OPERATOR_HAS,
|
||||
'operator-sort': OPERATOR_SORT,
|
||||
'operator-limit': OPERATOR_LIMIT,
|
||||
};
|
||||
|
||||
const predicates = {
|
||||
due: {
|
||||
'predicate-overdue': PREDICATE_OVERDUE,
|
||||
},
|
||||
durations: {
|
||||
'predicate-week': PREDICATE_WEEK,
|
||||
'predicate-month': PREDICATE_MONTH,
|
||||
'predicate-quarter': PREDICATE_QUARTER,
|
||||
'predicate-year': PREDICATE_YEAR,
|
||||
},
|
||||
status: {
|
||||
'predicate-archived': PREDICATE_ARCHIVED,
|
||||
'predicate-all': PREDICATE_ALL,
|
||||
'predicate-open': PREDICATE_OPEN,
|
||||
'predicate-ended': PREDICATE_ENDED,
|
||||
'predicate-public': PREDICATE_PUBLIC,
|
||||
'predicate-private': PREDICATE_PRIVATE,
|
||||
},
|
||||
sorts: {
|
||||
'predicate-due': PREDICATE_DUE_AT,
|
||||
'predicate-created': PREDICATE_CREATED_AT,
|
||||
'predicate-modified': PREDICATE_MODIFIED_AT,
|
||||
},
|
||||
has: {
|
||||
'predicate-description': PREDICATE_DESCRIPTION,
|
||||
'predicate-checklist': PREDICATE_CHECKLIST,
|
||||
'predicate-attachment': PREDICATE_ATTACHMENT,
|
||||
'predicate-start': PREDICATE_START_AT,
|
||||
'predicate-end': PREDICATE_END_AT,
|
||||
'predicate-due': PREDICATE_DUE_AT,
|
||||
'predicate-assignee': PREDICATE_ASSIGNEES,
|
||||
'predicate-member': PREDICATE_MEMBERS,
|
||||
},
|
||||
};
|
||||
const predicateTranslations = {};
|
||||
Object.entries(predicates).forEach(([category, catPreds]) => {
|
||||
predicateTranslations[category] = {};
|
||||
Object.entries(catPreds).forEach(([tag, value]) => {
|
||||
predicateTranslations[category][TAPi18n.__(tag)] = value;
|
||||
});
|
||||
});
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('predicateTranslations:', predicateTranslations);
|
||||
|
||||
const operatorMap = {};
|
||||
Object.entries(operators).forEach(([key, value]) => {
|
||||
operatorMap[TAPi18n.__(key).toLowerCase()] = value;
|
||||
});
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('operatorMap:', operatorMap);
|
||||
|
||||
let text = '';
|
||||
while (queryText) {
|
||||
let m = queryText.match(reOperator1);
|
||||
if (!m) {
|
||||
m = queryText.match(reOperator2);
|
||||
if (m) {
|
||||
queryText = queryText.replace(reOperator2, '');
|
||||
}
|
||||
} else {
|
||||
queryText = queryText.replace(reOperator1, '');
|
||||
}
|
||||
if (m) {
|
||||
let op;
|
||||
if (m.groups.operator) {
|
||||
op = m.groups.operator.toLowerCase();
|
||||
} else {
|
||||
op = m.groups.abbrev.toLowerCase();
|
||||
}
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
if (operatorMap.hasOwnProperty(op)) {
|
||||
const operator = operatorMap[op];
|
||||
let value = m.groups.value;
|
||||
if (operator === OPERATOR_LABEL) {
|
||||
if (value in this.colorMap) {
|
||||
value = this.colorMap[value];
|
||||
// console.log('found color:', value);
|
||||
}
|
||||
} else if (
|
||||
[OPERATOR_DUE, OPERATOR_CREATED_AT, OPERATOR_MODIFIED_AT].includes(
|
||||
operator,
|
||||
)
|
||||
) {
|
||||
const days = parseInt(value, 10);
|
||||
let duration = null;
|
||||
if (isNaN(days)) {
|
||||
// duration was specified as text
|
||||
if (predicateTranslations.durations[value]) {
|
||||
duration = predicateTranslations.durations[value];
|
||||
let date = null;
|
||||
switch (duration) {
|
||||
case PREDICATE_WEEK:
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
const week = moment().week();
|
||||
if (week === 52) {
|
||||
date = moment(1, 'W');
|
||||
date.set('year', date.year() + 1);
|
||||
} else {
|
||||
date = moment(week + 1, 'W');
|
||||
}
|
||||
break;
|
||||
case PREDICATE_MONTH:
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
const month = moment().month();
|
||||
// .month() is zero indexed
|
||||
if (month === 11) {
|
||||
date = moment(1, 'M');
|
||||
date.set('year', date.year() + 1);
|
||||
} else {
|
||||
date = moment(month + 2, 'M');
|
||||
}
|
||||
break;
|
||||
case PREDICATE_QUARTER:
|
||||
// eslint-disable-next-line no-case-declarations
|
||||
const quarter = moment().quarter();
|
||||
if (quarter === 4) {
|
||||
date = moment(1, 'Q');
|
||||
date.set('year', date.year() + 1);
|
||||
} else {
|
||||
date = moment(quarter + 1, 'Q');
|
||||
}
|
||||
break;
|
||||
case PREDICATE_YEAR:
|
||||
date = moment(moment().year() + 1, 'YYYY');
|
||||
break;
|
||||
}
|
||||
if (date) {
|
||||
value = {
|
||||
operator: '$lt',
|
||||
value: date.format('YYYY-MM-DD'),
|
||||
};
|
||||
}
|
||||
} else if (
|
||||
operator === OPERATOR_DUE &&
|
||||
value === PREDICATE_OVERDUE
|
||||
) {
|
||||
value = {
|
||||
operator: '$lt',
|
||||
value: moment().format('YYYY-MM-DD'),
|
||||
};
|
||||
} else {
|
||||
this.errors.addError(OPERATOR_DUE, {
|
||||
tag: 'operator-number-expected',
|
||||
value: { operator: op, value },
|
||||
});
|
||||
continue;
|
||||
}
|
||||
} else if (operator === OPERATOR_DUE) {
|
||||
value = {
|
||||
operator: '$lt',
|
||||
value: moment(moment().format('YYYY-MM-DD'))
|
||||
.add(days + 1, duration ? duration : 'days')
|
||||
.format(),
|
||||
};
|
||||
} else {
|
||||
value = {
|
||||
operator: '$gte',
|
||||
value: moment(moment().format('YYYY-MM-DD'))
|
||||
.subtract(days, duration ? duration : 'days')
|
||||
.format(),
|
||||
};
|
||||
}
|
||||
} else if (operator === OPERATOR_SORT) {
|
||||
let negated = false;
|
||||
const m = value.match(reNegatedOperator);
|
||||
if (m) {
|
||||
value = m.groups.operator;
|
||||
negated = true;
|
||||
}
|
||||
if (!predicateTranslations.sorts[value]) {
|
||||
this.errors.addError(OPERATOR_SORT, {
|
||||
tag: 'operator-sort-invalid',
|
||||
value,
|
||||
});
|
||||
continue;
|
||||
} else {
|
||||
value = {
|
||||
name: predicateTranslations.sorts[value],
|
||||
order: negated ? ORDER_DESCENDING : ORDER_ASCENDING,
|
||||
};
|
||||
}
|
||||
} else if (operator === OPERATOR_STATUS) {
|
||||
if (!predicateTranslations.status[value]) {
|
||||
this.errors.addError(OPERATOR_STATUS, {
|
||||
tag: 'operator-status-invalid',
|
||||
value,
|
||||
});
|
||||
continue;
|
||||
} else {
|
||||
value = predicateTranslations.status[value];
|
||||
}
|
||||
} else if (operator === OPERATOR_HAS) {
|
||||
let negated = false;
|
||||
const m = value.match(reNegatedOperator);
|
||||
if (m) {
|
||||
value = m.groups.operator;
|
||||
negated = true;
|
||||
}
|
||||
if (!predicateTranslations.has[value]) {
|
||||
this.errors.addError(OPERATOR_HAS, {
|
||||
tag: 'operator-has-invalid',
|
||||
value,
|
||||
});
|
||||
continue;
|
||||
} else {
|
||||
value = {
|
||||
field: predicateTranslations.has[value],
|
||||
exists: !negated,
|
||||
};
|
||||
}
|
||||
} else if (operator === OPERATOR_LIMIT) {
|
||||
const limit = parseInt(value, 10);
|
||||
if (isNaN(limit) || limit < 1) {
|
||||
this.errors.addError(OPERATOR_LIMIT, {
|
||||
tag: 'operator-limit-invalid',
|
||||
value,
|
||||
});
|
||||
continue;
|
||||
} else {
|
||||
value = limit;
|
||||
}
|
||||
}
|
||||
|
||||
this.queryParams.addPredicate(operator, value);
|
||||
} else {
|
||||
this.errors.addError(OPERATOR_UNKNOWN, {
|
||||
tag: 'operator-unknown-error',
|
||||
value: op,
|
||||
});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
m = queryText.match(reQuotedText);
|
||||
if (!m) {
|
||||
m = queryText.match(reText);
|
||||
if (m) {
|
||||
queryText = queryText.replace(reText, '');
|
||||
}
|
||||
} else {
|
||||
queryText = queryText.replace(reQuotedText, '');
|
||||
}
|
||||
if (m) {
|
||||
text += (text ? ' ' : '') + m.groups.text;
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('text:', text);
|
||||
this.queryParams.text = text;
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('queryParams:', this.queryParams);
|
||||
}
|
||||
}
|
||||
@@ -14,6 +14,7 @@ FlowRouter.route('/', {
|
||||
Session.set('currentCard', null);
|
||||
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
EscapeActions.executeAll();
|
||||
|
||||
Utils.manageCustomUI();
|
||||
@@ -35,6 +36,7 @@ FlowRouter.route('/public', {
|
||||
Session.set('currentCard', null);
|
||||
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
EscapeActions.executeAll();
|
||||
|
||||
Utils.manageCustomUI();
|
||||
@@ -59,6 +61,7 @@ FlowRouter.route('/b/:id/:slug', {
|
||||
// want to excape every current actions (filters, etc.)
|
||||
if (previousBoard !== currentBoard) {
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
EscapeActions.executeAll();
|
||||
} else {
|
||||
EscapeActions.executeUpTo('popup-close');
|
||||
@@ -115,8 +118,10 @@ FlowRouter.route('/shortcuts', {
|
||||
|
||||
FlowRouter.route('/my-cards', {
|
||||
name: 'my-cards',
|
||||
triggersEnter: [AccountsTemplates.ensureSignedIn],
|
||||
action() {
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
// EscapeActions.executeAll();
|
||||
EscapeActions.executeUpTo('popup-close');
|
||||
|
||||
@@ -133,8 +138,10 @@ FlowRouter.route('/my-cards', {
|
||||
|
||||
FlowRouter.route('/due-cards', {
|
||||
name: 'due-cards',
|
||||
triggersEnter: [AccountsTemplates.ensureSignedIn],
|
||||
action() {
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
// EscapeActions.executeAll();
|
||||
EscapeActions.executeUpTo('popup-close');
|
||||
|
||||
@@ -151,8 +158,10 @@ FlowRouter.route('/due-cards', {
|
||||
|
||||
FlowRouter.route('/global-search', {
|
||||
name: 'global-search',
|
||||
triggersEnter: [AccountsTemplates.ensureSignedIn],
|
||||
action() {
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
// EscapeActions.executeAll();
|
||||
EscapeActions.executeUpTo('popup-close');
|
||||
|
||||
@@ -179,6 +188,7 @@ FlowRouter.route('/broken-cards', {
|
||||
const brokenCardsTemplate = 'brokenCards';
|
||||
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
// EscapeActions.executeAll();
|
||||
EscapeActions.executeUpTo('popup-close');
|
||||
|
||||
@@ -205,6 +215,7 @@ FlowRouter.route('/import/:source', {
|
||||
Session.set('importSource', params.source);
|
||||
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
EscapeActions.executeAll();
|
||||
BlazeLayout.render('defaultLayout', {
|
||||
headerBar: 'importHeaderBar',
|
||||
@@ -223,6 +234,7 @@ FlowRouter.route('/setting', {
|
||||
Session.set('currentCard', null);
|
||||
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
EscapeActions.executeAll();
|
||||
},
|
||||
],
|
||||
@@ -245,6 +257,7 @@ FlowRouter.route('/information', {
|
||||
Session.set('currentCard', null);
|
||||
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
EscapeActions.executeAll();
|
||||
},
|
||||
],
|
||||
@@ -266,6 +279,7 @@ FlowRouter.route('/people', {
|
||||
Session.set('currentCard', null);
|
||||
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
EscapeActions.executeAll();
|
||||
},
|
||||
],
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
export const DEFAULT_LIMIT = 25;
|
||||
export const OPERATOR_ASSIGNEE = 'assignee';
|
||||
export const OPERATOR_COMMENT = 'comment';
|
||||
export const OPERATOR_CREATED_AT = 'createdAt';
|
||||
export const OPERATOR_DUE = 'dueAt';
|
||||
export const OPERATOR_BOARD = 'board';
|
||||
export const OPERATOR_HAS = 'has';
|
||||
export const OPERATOR_LABEL = 'label';
|
||||
export const OPERATOR_LIMIT = 'limit';
|
||||
export const OPERATOR_LIST = 'list';
|
||||
export const OPERATOR_MEMBER = 'member';
|
||||
export const OPERATOR_MODIFIED_AT = 'modifiedAt';
|
||||
export const OPERATOR_SORT = 'sort';
|
||||
export const OPERATOR_STATUS = 'status';
|
||||
export const OPERATOR_SWIMLANE = 'swimlane';
|
||||
export const OPERATOR_UNKNOWN = 'unknown';
|
||||
export const OPERATOR_USER = 'user';
|
||||
export const ORDER_ASCENDING = 'asc';
|
||||
export const ORDER_DESCENDING = 'des';
|
||||
export const PREDICATE_ALL = 'all';
|
||||
export const PREDICATE_ARCHIVED = 'archived';
|
||||
export const PREDICATE_ASSIGNEES = 'assignees';
|
||||
export const PREDICATE_ATTACHMENT = 'attachment';
|
||||
export const PREDICATE_CHECKLIST = 'checklist';
|
||||
export const PREDICATE_CREATED_AT = 'createdAt';
|
||||
export const PREDICATE_DESCRIPTION = 'description';
|
||||
export const PREDICATE_DUE_AT = 'dueAt';
|
||||
export const PREDICATE_END_AT = 'endAt';
|
||||
export const PREDICATE_ENDED = 'ended';
|
||||
export const PREDICATE_MEMBERS = 'members';
|
||||
export const PREDICATE_MODIFIED_AT = 'modifiedAt';
|
||||
export const PREDICATE_MONTH = 'month';
|
||||
export const PREDICATE_OPEN = 'open';
|
||||
export const PREDICATE_OVERDUE = 'overdue';
|
||||
export const PREDICATE_PRIVATE = 'private';
|
||||
export const PREDICATE_PUBLIC = 'public';
|
||||
export const PREDICATE_QUARTER = 'quarter';
|
||||
export const PREDICATE_START_AT = 'startAt';
|
||||
export const PREDICATE_SYSTEM = 'system';
|
||||
export const PREDICATE_WEEK = 'week';
|
||||
export const PREDICATE_YEAR = 'year';
|
||||
+16
-10
@@ -95,7 +95,10 @@ services:
|
||||
# 2020-12-03:
|
||||
# - Mongo image copied from Docker Hub mongo:4.4.2-bionic to Quay
|
||||
# to avoid Docker Hub rate limits.
|
||||
image: quay.io/wekan/mongo:4.4.2-bionic
|
||||
# Quay image does work:
|
||||
# image: quay.io/wekan/mongo:4.4.2-bionic
|
||||
# Docker Hub MongoDB image does work:
|
||||
image: mongo:4.4
|
||||
#-------------------------------------------------------------------------------------
|
||||
container_name: wekan-db
|
||||
restart: always
|
||||
@@ -114,11 +117,11 @@ services:
|
||||
wekan:
|
||||
#-------------------------------------------------------------------------------------
|
||||
# ==== MONGODB AND METEOR VERSION ====
|
||||
# a) Quay automatic builds do work, https://quay.io/wekan7wekan
|
||||
image: quay.io/wekan/wekan
|
||||
# a) Quay automatic builds do work work, https://quay.io/wekan/wekan
|
||||
image: quay.io/wekan/wekan:stable
|
||||
# b) Using specific version tag:
|
||||
# image: quay.io/wekan/wekan:v4.52
|
||||
# c) Docker Hub builds work https://hub.docker.com/r/wekanteam/wekan
|
||||
# c) Docker Hub builds do work https://hub.docker.com/r/wekanteam/wekan
|
||||
# image: wekanteam/wekan
|
||||
#-------------------------------------------------------------------------------------
|
||||
container_name: wekan-app
|
||||
@@ -206,6 +209,9 @@ services:
|
||||
# There is Feature Request: Logging date and time of all activity with summary reports,
|
||||
# and requesting reason for changing card to other column https://github.com/wekan/wekan/issues/1598
|
||||
#---------------------------------------------------------------
|
||||
# ==== NUMBER OF SEARCH RESULTS PER PAGE BY DEFAULT ====
|
||||
#- RESULTS_PER_PAGE=20
|
||||
#---------------------------------------------------------------
|
||||
# ==== WEKAN API AND EXPORT BOARD ====
|
||||
# Wekan Export Board works when WITH_API=true.
|
||||
# https://github.com/wekan/wekan/wiki/REST-API
|
||||
@@ -306,7 +312,7 @@ services:
|
||||
#- TRUSTED_URL=https://intra.example.com
|
||||
#-----------------------------------------------------------------
|
||||
# ==== OUTGOING WEBHOOKS ====
|
||||
# What to send to Outgoing Webhook, or leave out. Example, that includes all that are default: cardId,listId,oldListId,boardId,comment,user,card,commentId .
|
||||
# What to send to Outgoing Webhook, or leave out. If commented out the default values will be: cardId,listId,oldListId,boardId,comment,user,card,commentId,swimlaneId,customerField,customFieldValue
|
||||
#- WEBHOOKS_ATTRIBUTES=cardId,listId,oldListId,boardId,comment,user,card,commentId
|
||||
#-----------------------------------------------------------------
|
||||
# ==== Debug OIDC OAuth2 etc ====
|
||||
@@ -457,8 +463,8 @@ services:
|
||||
#
|
||||
# The search user DN - You need quotes when you have spaces in parameters
|
||||
# 2 examples:
|
||||
#- LDAP_AUTHENTIFICATION_USERDN="CN=ldap admin,CN=users,DC=domainmatter,DC=lan"
|
||||
#- LDAP_AUTHENTIFICATION_USERDN="CN=wekan_adm,OU=serviceaccounts,OU=admin,OU=prod,DC=mydomain,DC=com"
|
||||
#- LDAP_AUTHENTIFICATION_USERDN=CN=ldap admin,CN=users,DC=domainmatter,DC=lan
|
||||
#- LDAP_AUTHENTIFICATION_USERDN=CN=wekan_adm,OU=serviceaccounts,OU=admin,OU=prod,DC=mydomain,DC=com
|
||||
#
|
||||
# The password for the search user
|
||||
#- LDAP_AUTHENTIFICATION_PASSWORD=pwd
|
||||
@@ -488,10 +494,10 @@ services:
|
||||
#- LDAP_REJECT_UNAUTHORIZED=false
|
||||
#
|
||||
# Option to login to the LDAP server with the user's own username and password, instead of an administrator key. Default: false (use administrator key).
|
||||
#- LDAP_USER_AUTHENTICATION="true"
|
||||
#- LDAP_USER_AUTHENTICATION=true
|
||||
#
|
||||
# Which field is used to find the user for the user authentication. Default: uid.
|
||||
#- LDAP_USER_AUTHENTICATION_FIELD="uid"
|
||||
#- LDAP_USER_AUTHENTICATION_FIELD=uid
|
||||
#
|
||||
# Optional extra LDAP filters. Don't forget the outmost enclosing parentheses if needed
|
||||
#- LDAP_USER_SEARCH_FILTER=
|
||||
@@ -556,7 +562,7 @@ services:
|
||||
#
|
||||
#- LDAP_SYNC_USER_DATA_FIELDMAP={"cn":"name", "mail":"email"}
|
||||
#
|
||||
#- LDAP_SYNC_GROUP_ROLES=''
|
||||
#- LDAP_SYNC_GROUP_ROLES=
|
||||
#
|
||||
# The default domain of the ldap it is used to create email if the field is not map correctly with the LDAP_SYNC_USER_DATA_FIELDMAP
|
||||
# example :
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
name: wekan
|
||||
version: 1.0.2
|
||||
version: 1.0.3
|
||||
apiVersion: v1
|
||||
description: Open Source kanban
|
||||
home: https://wekan.github.io/
|
||||
|
||||
@@ -81,7 +81,7 @@ else use user-provided URL.
|
||||
{{- $release := .Release.Name -}}
|
||||
{{- $replicaSetName := (index .Values "mongodb" "replicaSetName") -}}
|
||||
{{- $mongodbSvcName := include "wekan.mongodb.svcname" . -}}
|
||||
mongodb://{{- range $v := until $count }}{{ $release }}-mongodb-{{ $v }}.{{ $mongodbSvcName }}:27017{{ if ne $v (sub $count 1) }},{{- end -}}{{- end -}}?replicaSet={{ $replicaSetName }}
|
||||
mongodb://{{- range $v := until $count }}{{ $release }}-mongodb-{{ $v }}.{{ $mongodbSvcName }}:27017{{ if ne $v (sub $count 1) }},{{- end -}}{{- end -}}/{{ .Values.dbname }}?replicaSet={{ $replicaSetName }}
|
||||
{{- else -}}
|
||||
{{- index .Values "mongodb" "url" -}}
|
||||
{{- end -}}
|
||||
|
||||
@@ -46,7 +46,10 @@ spec:
|
||||
{{- range $key := .Values.secretEnv }}
|
||||
{{- if .value }}
|
||||
- name: {{ .name }}
|
||||
value: {{ .value | quote }}
|
||||
valueFrom:
|
||||
secretKeyRef:
|
||||
name: {{ template "wekan.fullname" $ }}-secret
|
||||
key: {{ .name }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
livenessProbe:
|
||||
|
||||
@@ -0,0 +1,11 @@
|
||||
{{ if .Values.secretEnv }}
|
||||
apiVersion: v1
|
||||
kind: Secret
|
||||
metadata:
|
||||
name: {{ template "wekan.fullname" $ }}-secret
|
||||
type: Opaque
|
||||
data:
|
||||
{{- range $key := .Values.secretEnv }}
|
||||
{{ $key.name }}: {{ $key.value | b64enc }}
|
||||
{{- end}}
|
||||
{{ end }}
|
||||
@@ -21,6 +21,7 @@ image:
|
||||
##
|
||||
|
||||
replicaCount: 1
|
||||
dbname: wekan
|
||||
|
||||
## Specify additional environmental variables for the Deployment
|
||||
##
|
||||
@@ -32,9 +33,9 @@ env:
|
||||
## Deployment. These can e.g. be provided by a Secret and allow
|
||||
## to store passwords separately
|
||||
##
|
||||
secretEnv:
|
||||
- name: ""
|
||||
value: ""
|
||||
secretEnv: {}
|
||||
# - name: ""
|
||||
# value: ""
|
||||
|
||||
service:
|
||||
type: NodePort
|
||||
|
||||
+990
-924
File diff suppressed because it is too large.
Load diff
+990
-924
File diff suppressed because it is too large.
Load diff
+990
-924
File diff suppressed because it is too large.
Load diff
+990
-924
File diff suppressed because it is too large.
Load diff
+990
-924
File diff suppressed because it is too large.
Load diff
+990
-924
File diff suppressed because it is too large.
Load diff
+990
-924
File diff suppressed because it is too large.
Load diff
+990
-924
File diff suppressed because it is too large.
Load diff
+990
-924
File diff suppressed because it is too large.
Load diff
Loaded 100 of 231 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user