Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
df54863e72 | ||
|
|
8f340326b0 | ||
|
|
42975bc8ab | ||
|
|
adb5487cdc | ||
|
|
4aad9ca498 | ||
|
|
972d023e95 | ||
|
|
acabef4652 | ||
|
|
f77651ba05 | ||
|
|
23e349d277 | ||
|
|
37d9a6659a | ||
|
|
8796c46810 | ||
|
|
4960891bd9 | ||
|
|
43482d9e48 | ||
|
|
ee323d97b4 | ||
|
|
d6b447f70a | ||
|
|
203fafdf7c | ||
|
|
62e90723d1 | ||
|
|
77372ccce1 | ||
|
|
fdb4980b68 | ||
|
|
ff4f5e6c04 | ||
|
|
0bb3b67075 | ||
|
|
e16b06b44a | ||
|
|
ac9b23f00f | ||
|
|
f562bdd801 | ||
|
|
0c05942b45 | ||
|
|
9db3c93116 | ||
|
|
ce1f3365bb | ||
|
|
3ce3612047 | ||
|
|
44c9eebc4c | ||
|
|
cf6cc0e59d | ||
|
|
2b1fc8d07f | ||
|
|
e7d7ddd698 | ||
|
|
1d6bfc5dd6 | ||
|
|
0ccdbdcbe9 | ||
|
|
463346b867 | ||
|
|
f293700db3 | ||
|
|
b4e343369a | ||
|
|
da1d94775c | ||
|
|
28582b7e77 | ||
|
|
0f4a97f3a6 | ||
|
|
0f75234ed2 | ||
|
|
bc2556139a | ||
|
|
c1f52a5e5a | ||
|
|
ab24b3262c | ||
|
|
42994efa9d | ||
|
|
44cf82caab | ||
|
|
a44ca39eb8 | ||
|
|
3f70c395e1 | ||
|
|
04383c0302 | ||
|
|
55d022eefc | ||
|
|
7d3917adb7 | ||
|
|
7eeeab8486 | ||
|
|
88a46ef59a | ||
|
|
e4a9dc25ec | ||
|
|
dfb563a330 | ||
|
|
16dbb88ee3 | ||
|
|
626f435edf | ||
|
|
d4dd5d7a61 | ||
|
|
de13b8b9ba | ||
|
|
0aabb0b364 | ||
|
|
3605072650 | ||
|
|
6272aabefb | ||
|
|
bf2446614c | ||
|
|
65b8220fe5 | ||
|
|
d296918fcd | ||
|
|
c9a2d439e5 | ||
|
|
73f36bcf33 | ||
|
|
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 | ||
|
|
dc4a0bb462 | ||
|
|
a0418b460a | ||
|
|
0c093b539a | ||
|
|
1971037049 | ||
|
|
57af4ae70d | ||
|
|
8f553497e4 | ||
|
|
0373da44b3 | ||
|
|
1df060b8f6 | ||
|
|
b249fcbb2e | ||
|
|
ff8a36653a | ||
|
|
1c7a9e4de8 | ||
|
|
f56caa745a | ||
|
|
fc0ee2e41b | ||
|
|
319783b008 | ||
|
|
0c3b92567e | ||
|
|
3513a3bd62 | ||
|
|
a5f6dd6399 | ||
|
|
7ced6318a5 | ||
|
|
61c691a267 | ||
|
|
52f920db12 | ||
|
|
16bb0c81f8 | ||
|
|
7ac9448ddc | ||
|
|
23c1723ae1 | ||
|
|
dfe3a52571 | ||
|
|
7deff0e14f | ||
|
|
49a0451b6f | ||
|
|
bafda03fd9 | ||
|
|
27d05ee828 | ||
|
|
484276b80d | ||
|
|
1c61350988 | ||
|
|
01ef81ca58 | ||
|
|
e1192d1200 | ||
|
|
436134e0e3 | ||
|
|
8f506f1267 | ||
|
|
6d9928ea8f | ||
|
|
ad759f2f9f | ||
|
|
5553277a1e | ||
|
|
f0c9740c13 | ||
|
|
b365599bc8 | ||
|
|
56a530058b | ||
|
|
a1dbeda9ce | ||
|
|
1a049e4499 | ||
|
|
a6b10ebfbb | ||
|
|
8e4eade002 | ||
|
|
059e9524b3 | ||
|
|
f0b46d5508 | ||
|
|
a556953a11 | ||
|
|
d1f44a152c | ||
|
|
3a96f71b91 | ||
|
|
b8ab5e0e8d | ||
|
|
f25e01323e | ||
|
|
4fa0c2da4d | ||
|
|
b09d656636 | ||
|
|
5ff6fc0246 | ||
|
|
fc68354e83 | ||
|
|
22c868b4e6 | ||
|
|
f476143e92 | ||
|
|
855151a8d1 | ||
|
|
b9338a78f4 | ||
|
|
815b32c9b6 | ||
|
|
2714032e77 | ||
|
|
e463f79532 | ||
|
|
4cbc3cb71f | ||
|
|
b793716e85 | ||
|
|
451acb1c30 | ||
|
|
d7c663819c | ||
|
|
63d933a51d | ||
|
|
0afe8abdb8 | ||
|
|
413f91d0c8 | ||
|
|
fbb98e23c3 | ||
|
|
c4ea7457dc | ||
|
|
d0083d37da | ||
|
|
6f18a75e5c | ||
|
|
c89a0eb694 | ||
|
|
6b8939c02e | ||
|
|
86e5356b0f | ||
|
|
c0f748bcb5 | ||
|
|
0acb8f5d69 | ||
|
|
37db870475 | ||
|
|
0d5f33299e | ||
|
|
78f818bbb0 | ||
|
|
edafb6a6d2 | ||
|
|
c0984aa740 | ||
|
|
6253bbdc0b | ||
|
|
74f89ef80d | ||
|
|
254a9abad2 | ||
|
|
83e77f8d82 | ||
|
|
2726643586 | ||
|
|
b8f2a468d8 | ||
|
|
fb771d46dd | ||
|
|
ecd4c7fb02 | ||
|
|
da2be59185 | ||
|
|
93a3fa9c75 | ||
|
|
cf546c71e3 | ||
|
|
2791b7da22 | ||
|
|
48fc442b85 | ||
|
|
2e6b18dfa7 | ||
|
|
7f0da49e0a | ||
|
|
b5124d0f6a | ||
|
|
e70a1f0a60 | ||
|
|
7e8475e64d | ||
|
|
e161ada214 | ||
|
|
409b8559d7 | ||
|
|
d74dc92681 | ||
|
|
5f62d7307f | ||
|
|
3866ed3196 | ||
|
|
b039bad649 | ||
|
|
58a6354010 | ||
|
|
429d9474a9 | ||
|
|
be03d2ae9a | ||
|
|
5db40beb79 | ||
|
|
10f74f5152 | ||
|
|
0580237270 | ||
|
|
8059856c39 | ||
|
|
a3518a3bcf | ||
|
|
7b8d67de63 | ||
|
|
7a5aa469cd | ||
|
|
1e415b38d2 | ||
|
|
ff626fb559 | ||
|
|
ab183acac3 | ||
|
|
d9b967a74d | ||
|
|
4180224fd9 | ||
|
|
aa34da61fe | ||
|
|
058b95f4eb | ||
|
|
4115d62bac | ||
|
|
3d72c82bca | ||
|
|
4bed5059c2 | ||
|
|
ac57df409e | ||
|
|
e242e2b137 | ||
|
|
94cb33a0ce | ||
|
|
a2894bf0cb | ||
|
|
a56d47c768 | ||
|
|
3214800741 | ||
|
|
c11c3f9a88 | ||
|
|
81d120ac50 | ||
|
|
50b25572f1 | ||
|
|
39ac19db20 | ||
|
|
5dbbaae6fd | ||
|
|
423480903f | ||
|
|
f00395a6b6 | ||
|
|
391c0606d1 | ||
|
|
a27aaca918 | ||
|
|
03e5d84e0e | ||
|
|
8f21c86737 | ||
|
|
25dc779a73 | ||
|
|
4396d7cfd5 | ||
|
|
4700ed52da | ||
|
|
115d2c5fe9 | ||
|
|
afd5d1d0c0 | ||
|
|
a647768368 | ||
|
|
a9eddbbe9d | ||
|
|
80b23e5cc1 | ||
|
|
8cb4945617 | ||
|
|
f384e3d066 | ||
|
|
3977f2187a | ||
|
|
4ab1a04814 | ||
|
|
2e17f2b4b9 | ||
|
|
4b3270e82a | ||
|
|
de27be0911 | ||
|
|
34000ad159 | ||
|
|
bbcb236a46 | ||
|
|
d29f0eb5b6 | ||
|
|
b480c82f86 | ||
|
|
3105548c98 | ||
|
|
118635facb | ||
|
|
4746b7c361 | ||
|
|
801d0aacf0 | ||
|
|
82236484bc | ||
|
|
9a7cd8ae69 | ||
|
|
c330a47aac | ||
|
|
9293de541b | ||
|
|
01bd94d2b3 | ||
|
|
5913a4af1b | ||
|
|
72e5cb00b3 | ||
|
|
1d866093f1 | ||
|
|
0252591564 | ||
|
|
9ec1904119 | ||
|
|
f46243d943 | ||
|
|
dbcab96eea | ||
|
|
059191702b | ||
|
|
4f6cc96466 | ||
|
|
b98df8ef87 | ||
|
|
d09e448fbd | ||
|
|
fa00b797ee | ||
|
|
508ce6088e | ||
|
|
4d71848360 | ||
|
|
4ebad9efc1 | ||
|
|
4e8ee8eb86 | ||
|
|
ecc3558987 | ||
|
|
986ab29676 | ||
|
|
4679db6ec4 | ||
|
|
35a7925a21 | ||
|
|
5ab449eb7e | ||
|
|
5ba1d6f880 | ||
|
|
734c56a6b6 | ||
|
|
103d03d4c8 | ||
|
|
55b121e0d3 | ||
|
|
0e1c510948 | ||
|
|
b79ee281ec | ||
|
|
758b829a3c | ||
|
|
adc7846aff | ||
|
|
2e955cff54 | ||
|
|
aeeea2281c | ||
|
|
fa3af68836 | ||
|
|
1abdd5177d | ||
|
|
d62d890183 | ||
|
|
62a8602b2b | ||
|
|
1698b5cafb | ||
|
|
108d01ee35 | ||
|
|
e55b50bc5a | ||
|
|
4649553c5e | ||
|
|
1ea99a5dc8 | ||
|
|
ff8d899266 | ||
|
|
2e6064ce5c | ||
|
|
c7f260d030 | ||
|
|
f7e85ac86c | ||
|
|
5f647fd2ab | ||
|
|
6007fe263e | ||
|
|
26921a9c36 | ||
|
|
94a3c1dc21 | ||
|
|
5f0cb23f52 | ||
|
|
b1910d4300 | ||
|
|
163e4c8060 | ||
|
|
87e848beae | ||
|
|
febc020cd3 | ||
|
|
1733162df8 | ||
|
|
ee118d26b6 | ||
|
|
1dfe406ff9 | ||
|
|
5549c49326 | ||
|
|
754a91dbdc | ||
|
|
e3b90fb579 | ||
|
|
4bfe017b08 | ||
|
|
5e68362352 | ||
|
|
0497d38c1d | ||
|
|
1a1d6da451 | ||
|
|
763dc9c8e0 | ||
|
|
89c68d1987 | ||
|
|
70803f31d4 | ||
|
|
db2497424d | ||
|
|
0d3805d10a | ||
|
|
7b8b132062 | ||
|
|
d171f4088f | ||
|
|
e8e733184e | ||
|
|
e793e71163 | ||
|
|
46e47e3fc9 | ||
|
|
d4b3dc7472 | ||
|
|
df47dcc3f3 | ||
|
|
bfc16fc544 | ||
|
|
991e1baffd | ||
|
|
cd54ced1b2 | ||
|
|
f88c3755e0 | ||
|
|
0592b0c56a | ||
|
|
a0b72d0287 | ||
|
|
7a419c1563 | ||
|
|
ea42a3763f | ||
|
|
0f6a60fa69 | ||
|
|
a58b27e9b0 | ||
|
|
cfdeaf2f5d | ||
|
|
b64cd358ed | ||
|
|
12034ab619 | ||
|
|
ad482d5cfb | ||
|
|
885de88d35 | ||
|
|
223fb78bd8 | ||
|
|
077e78d37c | ||
|
|
e49d3923d0 | ||
|
|
65795a673e | ||
|
|
e39e0c9a85 | ||
|
|
f35b042324 | ||
|
|
9c8d5c2613 | ||
|
|
03bfd9a2b5 | ||
|
|
07aa1fd276 | ||
|
|
5aca681b36 | ||
|
|
94f466102e | ||
|
|
08866ae20b | ||
|
|
f73bdcdfb6 | ||
|
|
6410012384 | ||
|
|
93a24aaef8 | ||
|
|
688a31877b | ||
|
|
e9b9f204a5 | ||
|
|
dfee3a7a7c | ||
|
|
d03e2170dd | ||
|
|
d0cdc33c19 | ||
|
|
b7e1521e0d | ||
|
|
ed12cfe160 | ||
|
|
5578949bf5 | ||
|
|
5603d159b3 | ||
|
|
9e2093d6ae | ||
|
|
b7137e617e | ||
|
|
2c33f71ba7 | ||
|
|
56c2c24638 | ||
|
|
a8453657c9 | ||
|
|
55ff74de95 | ||
|
|
e2f7b1ec05 | ||
|
|
1cd2d28a3b | ||
|
|
c7808c5c03 | ||
|
|
3ed9f07015 | ||
|
|
676d2c46a1 | ||
|
|
b5f1a6b08b | ||
|
|
d9616b6d94 | ||
|
|
4812cb6412 | ||
|
|
9e60a23845 | ||
|
|
6cca39af1b | ||
|
|
7ffbe2ab5e | ||
|
|
28850e5510 | ||
|
|
d62bed1536 | ||
|
|
b19cf01a3a | ||
|
|
39dece1e25 | ||
|
|
61ae62a83a | ||
|
|
775f0d9fe6 | ||
|
|
53a925cf7f | ||
|
|
6bf33a5578 | ||
|
|
7f3c4acf62 | ||
|
|
8481c791d7 | ||
|
|
9dd0fb88d6 | ||
|
|
9b004d75c7 | ||
|
|
86c7fbd717 | ||
|
|
6bd7f40511 | ||
|
|
a82257f0b1 | ||
|
|
ee26f32a20 | ||
|
|
7df3d52635 | ||
|
|
f9ba17177e | ||
|
|
ab4941390b | ||
|
|
11d044ede9 | ||
|
|
3c406d955e | ||
|
|
ea37dd5e1d | ||
|
|
fd7225d861 | ||
|
|
e0bd22e674 | ||
|
|
89332cefc5 | ||
|
|
5172f64b72 | ||
|
|
6cb4b9fe4a | ||
|
|
c978f55c56 | ||
|
|
4a205fcfcb | ||
|
|
2e1e703e35 | ||
|
|
a75c162483 | ||
|
|
f6c0700633 | ||
|
|
dece7ddf13 | ||
|
|
d06bcd9dcc | ||
|
|
ee7d82c006 | ||
|
|
b777f7f2af | ||
|
|
fe87b9928c | ||
|
|
fb36709047 | ||
|
|
73aaccb6dd | ||
|
|
1fe0059402 | ||
|
|
0c12c45080 | ||
|
|
a6c48329ef | ||
|
|
a3cd1b89ff | ||
|
|
7a08f42edb | ||
|
|
e8722b56e3 | ||
|
|
052948f6eb | ||
|
|
cd03395e05 | ||
|
|
61caf18fd4 | ||
|
|
015f4d671d | ||
|
|
c13e828c79 | ||
|
|
7a6abaac44 | ||
|
|
58dffd0a33 | ||
|
|
fe0232a4e8 | ||
|
|
8dff6c2e2a | ||
|
|
3a6e2813a6 | ||
|
|
8005640b77 | ||
|
|
bc929fb7e0 | ||
|
|
019874b6af | ||
|
|
a7977a8fc7 | ||
|
|
62f6cc7198 | ||
|
|
ad331ee122 | ||
|
|
387f0600ce | ||
|
|
0801e33f97 | ||
|
|
f576d2f356 | ||
|
|
051f7b2769 | ||
|
|
1f207c493d | ||
|
|
03f565bf95 | ||
|
|
36e29a405e | ||
|
|
2ec53b27d1 | ||
|
|
152a0b50f2 | ||
|
|
c09758fb91 | ||
|
|
2b2884d996 | ||
|
|
4537971300 | ||
|
|
0b43e8b42a | ||
|
|
bf94161f30 | ||
|
|
573426899a | ||
|
|
3816227837 | ||
|
|
fe5e311673 | ||
|
|
bec0b7ec56 | ||
|
|
9d2a9ee70b | ||
|
|
baf652a569 | ||
|
|
9f340bcecd | ||
|
|
cc0a866166 | ||
|
|
d39b62503f | ||
|
|
e9b9af4616 | ||
|
|
7d88ef7ab2 | ||
|
|
5a49bd6f8c | ||
|
|
a255fc8524 | ||
|
|
d1b5c42d42 | ||
|
|
d957768a39 | ||
|
|
999630aed5 | ||
|
|
cf7efccde5 | ||
|
|
7b82a80fb4 | ||
|
|
cfe500794c | ||
|
|
a2d298f493 | ||
|
|
4687a866f5 | ||
|
|
ff08aff131 | ||
|
|
5510c2a37d | ||
|
|
608a084b94 | ||
|
|
9e47abdaa3 | ||
|
|
4d7bd455c9 | ||
|
|
05a72f7c62 | ||
|
|
4e23429cb8 | ||
|
|
b67d3e91af | ||
|
|
636487502d | ||
|
|
3207f457d4 | ||
|
|
af0cb1d6e7 | ||
|
|
06c16b79e3 | ||
|
|
09617e17d9 | ||
|
|
94f50dd6b6 | ||
|
|
d667554686 | ||
|
|
cbf3bcfe1c | ||
|
|
3d82323eaa | ||
|
|
83cd5e7494 | ||
|
|
e1e5554b88 | ||
|
|
6193a0b64e | ||
|
|
d1c8917cd2 | ||
|
|
7e17db4feb | ||
|
|
c214510087 | ||
|
|
9bac5aa58e | ||
|
|
9dbb10c59b | ||
|
|
d5325cc830 | ||
|
|
1539da75ed | ||
|
|
f786afc4b9 | ||
|
|
37ae4d5302 | ||
|
|
37b0543ed6 | ||
|
|
69fc2cd8f8 | ||
|
|
5e03507eba | ||
|
|
01fea212ec | ||
|
|
81ff3ec5b1 | ||
|
|
393464f2d8 | ||
|
|
17867159ea | ||
|
|
7b064ce448 | ||
|
|
bf403cacf8 | ||
|
|
a08bc8bb81 | ||
|
|
554e01a172 | ||
|
|
ed4260dd38 | ||
|
|
9e56cd5ea3 | ||
|
|
8db8766a48 | ||
|
|
222fca3ad7 | ||
|
|
efc50aec07 | ||
|
|
21aebe845f | ||
|
|
345e2357c8 | ||
|
|
8250cbcf6e | ||
|
|
d0040754ea | ||
|
|
22501749da | ||
|
|
c30bc77eea | ||
|
|
f74bac4f6b | ||
|
|
f54036225d | ||
|
|
f1b680119f | ||
|
|
9ffdb83004 | ||
|
|
7080a0ce7d | ||
|
|
de4f1aa8c4 | ||
|
|
fa6182b979 | ||
|
|
a457e337ac | ||
|
|
ba2c280d56 | ||
|
|
c8ed4947e1 | ||
|
|
5b700a30d9 | ||
|
|
d62f9a716e | ||
|
|
949f22acf0 | ||
|
|
358c411255 | ||
|
|
cfec612704 | ||
|
|
1741808e53 | ||
|
|
fd41e8ba45 | ||
|
|
01285ba10d | ||
|
|
0180196d7e | ||
|
|
167d9d34eb | ||
|
|
ab288f1593 | ||
|
|
5813ad95cf | ||
|
|
6801c960b1 | ||
|
|
76d1148a98 | ||
|
|
f63ed78f5b | ||
|
|
0ef248574c | ||
|
|
415fac8a25 | ||
|
|
6cbb77b591 | ||
|
|
65ea8edea7 | ||
|
|
c87fbfd3f8 | ||
|
|
faad739f97 | ||
|
|
38bcb8a724 | ||
|
|
82237f2e79 | ||
|
|
fd363c69cc | ||
|
|
e7769ce467 | ||
|
|
76273300e7 | ||
|
|
cb6d74d7d9 | ||
|
|
cfe78471aa | ||
|
|
e79e0cfb66 | ||
|
|
a74bc81ff8 | ||
|
|
b10b7a713e | ||
|
|
c9a2120c54 | ||
|
|
4e2d337620 | ||
|
|
ec33cdcb29 | ||
|
|
4cfddf1d8d | ||
|
|
3f9b86d8e7 | ||
|
|
f4fdb94a3f | ||
|
|
02856877a6 | ||
|
|
0a5f9307d2 | ||
|
|
579968143c | ||
|
|
aa454a5542 | ||
|
|
ce563085b5 | ||
|
|
6f99b22dc6 | ||
|
|
b08f228191 | ||
|
|
55252300c6 | ||
|
|
f99934b994 | ||
|
|
cd16fa43a0 | ||
|
|
ae9d82430a | ||
|
|
d75ca0c8f0 | ||
|
|
66a4b1c2df | ||
|
|
6fe39d99ac | ||
|
|
388c249212 | ||
|
|
af583145ed | ||
|
|
9c8b7b324f | ||
|
|
a3f5ef1a54 | ||
|
|
305658da3a | ||
|
|
2b24ebf539 | ||
|
|
13d5015fc3 | ||
|
|
13cf1a687e | ||
|
|
d2f434879c | ||
|
|
c3ffaa7ce2 | ||
|
|
2955c167c2 | ||
|
|
81d1bf6d27 | ||
|
|
46ce345203 | ||
|
|
363e69f01c | ||
|
|
9b0875169b | ||
|
|
e616247254 | ||
|
|
cc5f22df79 | ||
|
|
3448467953 | ||
|
|
74dbb96d85 | ||
|
|
d2cfe76a28 | ||
|
|
045e9db7b8 | ||
|
|
460b1d3a66 | ||
|
|
a463f2a855 | ||
|
|
8b3399b8f6 | ||
|
|
ef59d6dcb9 | ||
|
|
1b429b3f99 | ||
|
|
5098f7dee1 | ||
|
|
c509aaf246 | ||
|
|
d7333dec84 | ||
|
|
9d97494cfc | ||
|
|
acf9e7caea | ||
|
|
f6d000b26a | ||
|
|
ba5b35d0cc | ||
|
|
1eae8222c4 | ||
|
|
9b5a519bc7 | ||
|
|
b8a209249e | ||
|
|
ecc1b69f5c | ||
|
|
6253bc6c14 | ||
|
|
7768a4c1ba | ||
|
|
cd1bc7a695 | ||
|
|
42f45f9a83 | ||
|
|
d081eb0a2e | ||
|
|
504533991b | ||
|
|
44a5976b85 | ||
|
|
ac65b93b43 | ||
|
|
e9d27c521e | ||
|
|
dc86ae21de | ||
|
|
befb0f18b6 | ||
|
|
b796a6cbf4 | ||
|
|
9336a55a50 | ||
|
|
26749442fd | ||
|
|
7223d6e750 | ||
|
|
41a8e79e0e | ||
|
|
ec8a78537f | ||
|
|
4eb7597aa9 | ||
|
|
3d13fa3a26 | ||
|
|
655fe8afd3 | ||
|
|
855c66976e | ||
|
|
185cf163b2 | ||
|
|
45b7365025 | ||
|
|
ed5f64ccd6 | ||
|
|
3fc80e1145 | ||
|
|
05e3fc31b4 | ||
|
|
d5e1c4bfa5 | ||
|
|
a7c3317ed6 | ||
|
|
7db08082bc | ||
|
|
32836d42c9 | ||
|
|
789c4b480a | ||
|
|
abe291837a | ||
|
|
81ac0fdba9 | ||
|
|
d19cc972e0 | ||
|
|
8f6c3550e3 | ||
|
|
40681ccda4 | ||
|
|
4f76e1e1eb | ||
|
|
5cd9f89b21 | ||
|
|
b24685e38d | ||
|
|
5d7aa373fd | ||
|
|
e79b7fad0a | ||
|
|
e05541da88 | ||
|
|
0ccbfcfc9e | ||
|
|
8e6a570d47 | ||
|
|
129a884a4e | ||
|
|
2d278f303a | ||
|
|
dd67bd4b5e | ||
|
|
17239fe052 | ||
|
|
389908be7c | ||
|
|
33cf589c05 | ||
|
|
d961355016 | ||
|
|
9a72cf7ac2 | ||
|
|
53027559cd | ||
|
|
2e5545491b | ||
|
|
f9b0da65f1 | ||
|
|
4c734ee70f | ||
|
|
7173e293ef | ||
|
|
19ff17b3a5 | ||
|
|
d2b84c7773 | ||
|
|
623d6c09c4 | ||
|
|
8ae80138a0 | ||
|
|
cca041e21a | ||
|
|
b333061de7 | ||
|
|
abf4322b6c | ||
|
|
4e1a73fa27 | ||
|
|
214c86cc22 | ||
|
|
e0192f570e | ||
|
|
f5b5ab6331 | ||
|
|
d1c83b28f3 | ||
|
|
aa12b3f162 | ||
|
|
754087b5cf | ||
|
|
e656e36a92 | ||
|
|
0bf138281e | ||
|
|
fe62e12ab4 | ||
|
|
3c64c504c8 |
No files matched your search
@@ -1,12 +1,16 @@
|
||||
FROM ubuntu:rolling
|
||||
FROM quay.io/wekan/ubuntu:groovy-20201125.2
|
||||
LABEL maintainer="sgr"
|
||||
|
||||
# 2020-12-03:
|
||||
# - Above Ubuntu base image copied from Docker Hub ubuntu:groovy-20201125.2
|
||||
# to Quay to avoid Docker Hub rate limits.
|
||||
|
||||
ENV BUILD_DEPS="gnupg gosu bsdtar wget curl bzip2 g++ build-essential python git ca-certificates iproute2"
|
||||
ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ENV \
|
||||
DEBUG=false \
|
||||
NODE_VERSION=v12.18.3 \
|
||||
NODE_VERSION=v12.21.0 \
|
||||
METEOR_RELEASE=1.10.2 \
|
||||
USE_EDGE=false \
|
||||
METEOR_EDGE=1.5-beta.17 \
|
||||
@@ -39,6 +43,7 @@ ENV \
|
||||
TRUSTED_URL="" \
|
||||
WEBHOOKS_ATTRIBUTES="" \
|
||||
OAUTH2_ENABLED=false \
|
||||
OAUTH2_CA_CERT="" \
|
||||
OAUTH2_ADFS_ENABLED=false \
|
||||
OAUTH2_LOGIN_STYLE=redirect \
|
||||
OAUTH2_CLIENT_ID="" \
|
||||
@@ -113,7 +118,22 @@ ENV \
|
||||
CORS_ALLOW_HEADERS="" \
|
||||
CORS_EXPOSE_HEADERS="" \
|
||||
DEFAULT_AUTHENTICATION_METHOD="" \
|
||||
PASSWORD_LOGIN_ENABLED=true
|
||||
PASSWORD_LOGIN_ENABLED=true \
|
||||
CAS_ENABLED=false \
|
||||
CAS_BASE_URL="" \
|
||||
CAS_LOGIN_URL="" \
|
||||
CAS_VALIDATE_URL="" \
|
||||
SAML_ENABLED=false \
|
||||
SAML_PROVIDER="" \
|
||||
SAML_ENTRYPOINT="" \
|
||||
SAML_ISSUER="" \
|
||||
SAML_CERT="" \
|
||||
SAML_IDPSLO_REDIRECTURL="" \
|
||||
SAML_PRIVATE_KEYFILE="" \
|
||||
SAML_PUBLIC_CERTFILE="" \
|
||||
SAML_IDENTIFIER_FORMAT="" \
|
||||
SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE="" \
|
||||
SAML_ATTRIBUTES=""
|
||||
|
||||
# Install OS
|
||||
RUN set -o xtrace \
|
||||
|
||||
@@ -81,7 +81,7 @@ parts:
|
||||
wekan:
|
||||
source: .
|
||||
plugin: nodejs
|
||||
node-engine: 12.18.3
|
||||
node-engine: 12.21.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.18.3
|
||||
node-engine: 12.21.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'
|
||||
@@ -5,6 +5,7 @@
|
||||
tmp/
|
||||
node_modules/
|
||||
npm-debug.log
|
||||
.gitmodules
|
||||
.vscode/
|
||||
.idea/
|
||||
.build/*
|
||||
|
||||
+57
-9
@@ -6,8 +6,8 @@
|
||||
meteor-base@1.4.0
|
||||
|
||||
# Build system
|
||||
ecmascript@0.14.3
|
||||
standard-minifier-css@1.6.0
|
||||
ecmascript@0.15.0
|
||||
standard-minifier-css@1.7.2
|
||||
standard-minifier-js@2.6.0
|
||||
mquandalle:jade
|
||||
coffeescript@2.4.1!
|
||||
@@ -23,7 +23,7 @@ dburles:collection-helpers
|
||||
idmontie:migrations
|
||||
matb33:collection-hooks
|
||||
matteodem:easy-search
|
||||
mongo@1.10.0
|
||||
mongo@1.10.1
|
||||
mquandalle:collection-mutations
|
||||
|
||||
# Account system
|
||||
@@ -52,7 +52,6 @@ mquandalle:autofocus
|
||||
ongoworks:speakingurl
|
||||
raix:handlebar-helpers
|
||||
tap:i18n
|
||||
http@1.4.2
|
||||
|
||||
# UI components
|
||||
blaze
|
||||
@@ -72,17 +71,15 @@ simple:rest-accounts-password
|
||||
useraccounts:core
|
||||
email@2.0.0
|
||||
horka:swipebox
|
||||
dynamic-import@0.5.2
|
||||
staringatlights:fast-render
|
||||
dynamic-import@0.6.0
|
||||
|
||||
accounts-password@1.6.2
|
||||
accounts-password@1.7.0
|
||||
cfs:gridfs
|
||||
rzymek:fullcalendar
|
||||
momentjs:moment@2.22.2
|
||||
browser-policy-framing@1.1.0
|
||||
mquandalle:moment
|
||||
msavin:usercache
|
||||
mdg:meteor-apm-agent@3.2.0-rc.0!
|
||||
# Keep stylus in 1.1.0, because building v2 takes extra 52 minutes.
|
||||
coagmano:stylus@1.1.0!
|
||||
lucasantoniassi:accounts-lockout
|
||||
@@ -95,5 +92,56 @@ konecty:mongo-counter
|
||||
percolate:synced-cron
|
||||
easylogic:summernote
|
||||
cfs:filesystem
|
||||
ostrio:cookies
|
||||
tmeasday:check-npm-versions
|
||||
steffo:meteor-accounts-saml
|
||||
rajit:bootstrap3-datepicker-fi
|
||||
rajit:bootstrap3-datepicker-ar
|
||||
rajit:bootstrap3-datepicker-bg
|
||||
rajit:bootstrap3-datepicker-br
|
||||
rajit:bootstrap3-datepicker-ca
|
||||
rajit:bootstrap3-datepicker-cs
|
||||
rajit:bootstrap3-datepicker-da
|
||||
rajit:bootstrap3-datepicker-de
|
||||
rajit:bootstrap3-datepicker-el
|
||||
rajit:bootstrap3-datepicker-en-gb
|
||||
rajit:bootstrap3-datepicker-eo
|
||||
rajit:bootstrap3-datepicker-es
|
||||
rajit:bootstrap3-datepicker-eu
|
||||
rajit:bootstrap3-datepicker-fa
|
||||
rajit:bootstrap3-datepicker-fr
|
||||
rajit:bootstrap3-datepicker-gl
|
||||
rajit:bootstrap3-datepicker-he
|
||||
rajit:bootstrap3-datepicker-hi
|
||||
rajit:bootstrap3-datepicker-hu
|
||||
rajit:bootstrap3-datepicker-hy
|
||||
rajit:bootstrap3-datepicker-id
|
||||
rajit:bootstrap3-datepicker-it
|
||||
rajit:bootstrap3-datepicker-ja
|
||||
rajit:bootstrap3-datepicker-ka
|
||||
rajit:bootstrap3-datepicker-km
|
||||
rajit:bootstrap3-datepicker-ko
|
||||
rajit:bootstrap3-datepicker-lv
|
||||
rajit:bootstrap3-datepicker-mk
|
||||
rajit:bootstrap3-datepicker-mn
|
||||
rajit:bootstrap3-datepicker-nb
|
||||
rajit:bootstrap3-datepicker-nl
|
||||
rajit:bootstrap3-datepicker-oc
|
||||
rajit:bootstrap3-datepicker-pl
|
||||
rajit:bootstrap3-datepicker-pt-br
|
||||
rajit:bootstrap3-datepicker-pt
|
||||
rajit:bootstrap3-datepicker-ro
|
||||
rajit:bootstrap3-datepicker-ru
|
||||
rajit:bootstrap3-datepicker-sl
|
||||
rajit:bootstrap3-datepicker-sr
|
||||
rajit:bootstrap3-datepicker-sv
|
||||
rajit:bootstrap3-datepicker-sw
|
||||
rajit:bootstrap3-datepicker-ta
|
||||
rajit:bootstrap3-datepicker-th
|
||||
rajit:bootstrap3-datepicker-tr
|
||||
rajit:bootstrap3-datepicker-uk
|
||||
rajit:bootstrap3-datepicker-vi
|
||||
rajit:bootstrap3-datepicker-zh-cn
|
||||
rajit:bootstrap3-datepicker-zh-tw
|
||||
staringatlights:fast-render
|
||||
spacebars
|
||||
jkuester:http
|
||||
+1
-1
@@ -1 +1 @@
|
||||
METEOR@1.11
|
||||
METEOR@2.1
|
||||
+70
-21
@@ -1,7 +1,7 @@
|
||||
3stack:presence@1.1.2
|
||||
accounts-base@1.7.0
|
||||
accounts-base@1.8.0
|
||||
accounts-oauth@1.2.0
|
||||
accounts-password@1.6.2
|
||||
accounts-password@1.7.0
|
||||
aldeed:collection2@2.10.0
|
||||
aldeed:collection2-core@1.2.0
|
||||
aldeed:schema-deny@1.1.0
|
||||
@@ -10,8 +10,8 @@ aldeed:simple-schema@1.5.4
|
||||
allow-deny@1.1.0
|
||||
arillo:flow-router-helpers@0.5.2
|
||||
audit-argument-checks@1.0.7
|
||||
autoupdate@1.6.0
|
||||
babel-compiler@7.5.3
|
||||
autoupdate@1.7.0
|
||||
babel-compiler@7.6.0
|
||||
babel-runtime@1.5.0
|
||||
base64@1.0.12
|
||||
binary-heap@1.0.11
|
||||
@@ -49,15 +49,15 @@ coffeescript-compiler@2.4.1
|
||||
cottz:publish-relations@2.0.8
|
||||
dburles:collection-helpers@1.1.0
|
||||
ddp@1.4.0
|
||||
ddp-client@2.3.3
|
||||
ddp-client@2.4.0
|
||||
ddp-common@1.4.0
|
||||
ddp-rate-limiter@1.0.9
|
||||
ddp-server@2.3.2
|
||||
deps@1.0.12
|
||||
diff-sequence@1.1.1
|
||||
dynamic-import@0.5.2
|
||||
dynamic-import@0.6.0
|
||||
easylogic:summernote@0.8.8
|
||||
ecmascript@0.14.3
|
||||
ecmascript@0.15.0
|
||||
ecmascript-runtime@0.7.0
|
||||
ecmascript-runtime-client@0.11.0
|
||||
ecmascript-runtime-server@0.10.0
|
||||
@@ -72,10 +72,11 @@ horka:swipebox@1.0.2
|
||||
hot-code-push@1.0.4
|
||||
html-tools@1.0.11
|
||||
htmljs@1.0.11
|
||||
http@1.4.2
|
||||
http@1.4.3
|
||||
id-map@1.1.0
|
||||
idmontie:migrations@1.0.3
|
||||
inter-process-messaging@0.1.1
|
||||
jkuester:http@2.0.1
|
||||
jquery@1.11.11
|
||||
kadira:blaze-layout@2.3.0
|
||||
kadira:dochead@1.5.0
|
||||
@@ -87,11 +88,10 @@ lamhieu:unblock@1.0.0
|
||||
launch-screen@1.2.0
|
||||
livedata@1.0.18
|
||||
localstorage@1.2.0
|
||||
logging@1.1.20
|
||||
logging@1.2.0
|
||||
lucasantoniassi:accounts-lockout@1.0.0
|
||||
matb33:collection-hooks@0.9.1
|
||||
matteodem:easy-search@1.6.4
|
||||
mdg:meteor-apm-agent@3.3.0
|
||||
mdg:validation-error@0.5.1
|
||||
meteor@1.9.3
|
||||
meteor-base@1.4.0
|
||||
@@ -104,14 +104,14 @@ meteorspark:util@0.2.0
|
||||
minifier-css@1.5.3
|
||||
minifier-js@2.6.0
|
||||
minifiers@1.1.8-faster-rebuild.0
|
||||
minimongo@1.6.0
|
||||
minimongo@1.6.1
|
||||
mobile-status-bar@1.1.0
|
||||
modern-browsers@0.1.5
|
||||
modules@0.15.0
|
||||
modules@0.16.0
|
||||
modules-runtime@0.12.0
|
||||
momentjs:moment@2.27.0
|
||||
mongo@1.10.0
|
||||
mongo-decimal@0.1.1
|
||||
momentjs:moment@2.29.1
|
||||
mongo@1.10.1
|
||||
mongo-decimal@0.1.2
|
||||
mongo-dev-server@1.1.0
|
||||
mongo-id@1.0.7
|
||||
mongo-livedata@1.0.12
|
||||
@@ -127,12 +127,11 @@ mquandalle:mousetrap-bindglobal@0.0.1
|
||||
msavin:usercache@1.8.0
|
||||
npm-bcrypt@0.9.3
|
||||
npm-mongo@3.8.1
|
||||
oauth@1.3.0
|
||||
oauth@1.3.2
|
||||
oauth2@1.3.0
|
||||
observe-sequence@1.0.16
|
||||
ongoworks:speakingurl@1.1.0
|
||||
ordered-dict@1.1.0
|
||||
ostrio:cookies@2.6.0
|
||||
peerlibrary:assert@0.3.0
|
||||
peerlibrary:base-component@0.16.0
|
||||
peerlibrary:blaze-components@0.15.1
|
||||
@@ -143,11 +142,60 @@ promise@0.11.2
|
||||
raix:eventemitter@0.1.3
|
||||
raix:handlebar-helpers@0.2.5
|
||||
rajit:bootstrap3-datepicker@1.7.1_1
|
||||
rajit:bootstrap3-datepicker-ar@1.7.1
|
||||
rajit:bootstrap3-datepicker-bg@1.7.1
|
||||
rajit:bootstrap3-datepicker-br@1.7.1
|
||||
rajit:bootstrap3-datepicker-ca@1.7.1
|
||||
rajit:bootstrap3-datepicker-cs@1.7.1
|
||||
rajit:bootstrap3-datepicker-da@1.7.1
|
||||
rajit:bootstrap3-datepicker-de@1.7.1
|
||||
rajit:bootstrap3-datepicker-el@1.7.1
|
||||
rajit:bootstrap3-datepicker-en-gb@1.7.1
|
||||
rajit:bootstrap3-datepicker-eo@1.7.1
|
||||
rajit:bootstrap3-datepicker-es@1.7.1
|
||||
rajit:bootstrap3-datepicker-eu@1.7.1
|
||||
rajit:bootstrap3-datepicker-fa@1.7.1
|
||||
rajit:bootstrap3-datepicker-fi@1.7.1
|
||||
rajit:bootstrap3-datepicker-fr@1.7.1
|
||||
rajit:bootstrap3-datepicker-gl@1.7.1
|
||||
rajit:bootstrap3-datepicker-he@1.7.1
|
||||
rajit:bootstrap3-datepicker-hi@1.7.1
|
||||
rajit:bootstrap3-datepicker-hu@1.7.1
|
||||
rajit:bootstrap3-datepicker-hy@1.7.1
|
||||
rajit:bootstrap3-datepicker-id@1.7.1
|
||||
rajit:bootstrap3-datepicker-it@1.7.1
|
||||
rajit:bootstrap3-datepicker-ja@1.7.1
|
||||
rajit:bootstrap3-datepicker-ka@1.7.1
|
||||
rajit:bootstrap3-datepicker-km@1.7.1
|
||||
rajit:bootstrap3-datepicker-ko@1.7.1
|
||||
rajit:bootstrap3-datepicker-lv@1.7.1
|
||||
rajit:bootstrap3-datepicker-mk@1.7.1
|
||||
rajit:bootstrap3-datepicker-mn@1.7.1
|
||||
rajit:bootstrap3-datepicker-nb@1.7.1
|
||||
rajit:bootstrap3-datepicker-nl@1.7.1
|
||||
rajit:bootstrap3-datepicker-oc@1.7.1
|
||||
rajit:bootstrap3-datepicker-pl@1.7.1
|
||||
rajit:bootstrap3-datepicker-pt@1.7.1
|
||||
rajit:bootstrap3-datepicker-pt-br@1.7.1
|
||||
rajit:bootstrap3-datepicker-ro@1.7.1
|
||||
rajit:bootstrap3-datepicker-ru@1.7.1
|
||||
rajit:bootstrap3-datepicker-sl@1.7.1
|
||||
rajit:bootstrap3-datepicker-sr@1.7.1
|
||||
rajit:bootstrap3-datepicker-sv@1.7.1
|
||||
rajit:bootstrap3-datepicker-sw@1.7.1
|
||||
rajit:bootstrap3-datepicker-ta@1.7.1
|
||||
rajit:bootstrap3-datepicker-th@1.7.1
|
||||
rajit:bootstrap3-datepicker-tr@1.7.1
|
||||
rajit:bootstrap3-datepicker-uk@1.7.1
|
||||
rajit:bootstrap3-datepicker-vi@1.7.1
|
||||
rajit:bootstrap3-datepicker-zh-cn@1.7.1
|
||||
rajit:bootstrap3-datepicker-zh-tw@1.7.1
|
||||
random@1.2.0
|
||||
rate-limit@1.0.9
|
||||
react-fast-refresh@0.1.0
|
||||
reactive-dict@1.3.0
|
||||
reactive-var@1.0.11
|
||||
reload@1.3.0
|
||||
reload@1.3.1
|
||||
retry@1.1.0
|
||||
routepolicy@1.1.0
|
||||
rzymek:fullcalendar@3.8.0
|
||||
@@ -166,10 +214,11 @@ softwarerero:accounts-t9n@1.3.11
|
||||
spacebars@1.0.15
|
||||
spacebars-compiler@1.1.3
|
||||
srp@1.1.0
|
||||
standard-minifier-css@1.6.0
|
||||
standard-minifier-css@1.7.2
|
||||
standard-minifier-js@2.6.0
|
||||
staringatlights:fast-render@3.3.0
|
||||
staringatlights:inject-data@2.3.0
|
||||
steffo:meteor-accounts-saml@0.0.18
|
||||
tap:i18n@1.8.2
|
||||
templates:tabs@2.3.0
|
||||
templating@1.3.2
|
||||
@@ -186,8 +235,8 @@ useraccounts:core@1.14.2
|
||||
useraccounts:flow-routing@1.14.2
|
||||
useraccounts:unstyled@1.14.2
|
||||
verron:autosize@3.0.8
|
||||
webapp@1.9.1
|
||||
webapp-hashing@1.0.9
|
||||
webapp@1.10.0
|
||||
webapp-hashing@1.1.0
|
||||
wekan-accounts-cas@0.1.0
|
||||
wekan-accounts-oidc@1.0.10
|
||||
wekan-ldap@0.0.2
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ sudo: required
|
||||
|
||||
env:
|
||||
TRAVIS_DOCKER_COMPOSE_VERSION: 1.24.0
|
||||
TRAVIS_NODE_VERSION: 12.18.3
|
||||
TRAVIS_NODE_VERSION: 12.21.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 = bg_BG:bg, en_GB:en-GB, es_AR:es-AR, es_CL:es-CL, es_PE:es-PE, 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_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
|
||||
|
||||
+1390
-1
File diff suppressed because it is too large.
Load diff
+29
-6
@@ -1,6 +1,10 @@
|
||||
FROM ubuntu:rolling
|
||||
FROM quay.io/wekan/ubuntu:groovy-20210115
|
||||
LABEL maintainer="wekan"
|
||||
|
||||
# 2020-12-03:
|
||||
# - Above Ubuntu base image copied from Docker Hub ubuntu:groovy-20201125.2
|
||||
# to Quay to avoid Docker Hub rate limits.
|
||||
|
||||
# Set the environment variables (defaults where required)
|
||||
# DOES NOT WORK: paxctl fix for alpine linux: https://github.com/wekan/wekan/issues/1303
|
||||
# ENV BUILD_DEPS="paxctl"
|
||||
@@ -8,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.18.3 \
|
||||
NODE_VERSION=v12.21.0 \
|
||||
METEOR_RELEASE=1.10.2 \
|
||||
USE_EDGE=false \
|
||||
METEOR_EDGE=1.5-beta.17 \
|
||||
@@ -41,6 +45,7 @@ ENV BUILD_DEPS="apt-utils libarchive-tools gnupg gosu wget curl bzip2 g++ build-
|
||||
TRUSTED_URL="" \
|
||||
WEBHOOKS_ATTRIBUTES="" \
|
||||
OAUTH2_ENABLED=false \
|
||||
OAUTH2_CA_CERT="" \
|
||||
OAUTH2_ADFS_ENABLED=false \
|
||||
OAUTH2_LOGIN_STYLE=redirect \
|
||||
OAUTH2_CLIENT_ID="" \
|
||||
@@ -115,7 +120,23 @@ ENV BUILD_DEPS="apt-utils libarchive-tools gnupg gosu wget curl bzip2 g++ build-
|
||||
CORS_ALLOW_HEADERS="" \
|
||||
CORS_EXPOSE_HEADERS="" \
|
||||
DEFAULT_AUTHENTICATION_METHOD="" \
|
||||
PASSWORD_LOGIN_ENABLED=true
|
||||
PASSWORD_LOGIN_ENABLED=true \
|
||||
CAS_ENABLED=false \
|
||||
CAS_BASE_URL="" \
|
||||
CAS_LOGIN_URL="" \
|
||||
CAS_VALIDATE_URL="" \
|
||||
SAML_ENABLED=false \
|
||||
SAML_PROVIDER="" \
|
||||
SAML_ENTRYPOINT="" \
|
||||
SAML_ISSUER="" \
|
||||
SAML_CERT="" \
|
||||
SAML_IDPSLO_REDIRECTURL="" \
|
||||
SAML_PRIVATE_KEYFILE="" \
|
||||
SAML_PUBLIC_CERTFILE="" \
|
||||
SAML_IDENTIFIER_FORMAT="" \
|
||||
SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE="" \
|
||||
SAML_ATTRIBUTES="" \
|
||||
ORACLE_OIM_ENABLED=false
|
||||
|
||||
# Copy the app to the image
|
||||
COPY ${SRC_PATH} /home/wekan/app
|
||||
@@ -253,11 +274,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
|
||||
@@ -270,10 +292,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.18.3 \
|
||||
NODE_VERSION=v12.21.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.18.3 \
|
||||
NODE_VERSION=v12.21.0 \
|
||||
NODE_ENV=production \
|
||||
NPM_VERSION=latest \
|
||||
WITH_API=true \
|
||||
|
||||
@@ -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,13 +21,12 @@ 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)
|
||||
|
||||
@@ -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 50 languages.
|
||||
- Wekan has been [translated](https://transifex.com/wekan/wekan) to about 61 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.
|
||||
@@ -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.30.0"
|
||||
appVersion: "v5.07.0"
|
||||
files:
|
||||
userUploads:
|
||||
- README.md
|
||||
|
||||
@@ -0,0 +1,251 @@
|
||||
#! /usr/bin/env python3
|
||||
# -*- coding: utf-8 -*-
|
||||
# vi:ts=4:et
|
||||
|
||||
# Wekan API Python CLI, originally from here, where is more details:
|
||||
# https://github.com/wekan/wekan/wiki/New-card-with-Python3-and-REST-API
|
||||
|
||||
try:
|
||||
# python 3
|
||||
from urllib.parse import urlencode
|
||||
except ImportError:
|
||||
# python 2
|
||||
from urllib import urlencode
|
||||
|
||||
import json
|
||||
import requests
|
||||
import sys
|
||||
|
||||
arguments = len(sys.argv) - 1
|
||||
|
||||
if arguments == 0:
|
||||
print("=== Wekan API Python CLI: Shows IDs for addcard ===")
|
||||
print("AUTHORID is USERID that writes card.")
|
||||
print("If *nix: chmod +x api.py => ./api.py users")
|
||||
print("Syntax:")
|
||||
print(" python3 api.py users # All users")
|
||||
print(" python3 api.py boards USERID # Boards of USERID")
|
||||
print(" python3 api.py board BOARDID # Info of BOARDID")
|
||||
print(" python3 api.py swimlanes BOARDID # Swimlanes of BOARDID")
|
||||
print(" python3 api.py lists BOARDID # Lists of BOARDID")
|
||||
print(" python3 api.py createlist BOARDID LISTTITLE # Create list")
|
||||
print(" python3 api.py addcard AUTHORID BOARDID SWIMLANEID LISTID CARDTITLE CARDDESCRIPTION")
|
||||
print(" python3 api.py listattachments BOARDID # List attachments")
|
||||
# TODO:
|
||||
# print(" python3 api.py attachmentdownload BOARDID ATTACHMENTID # One attachment as file")
|
||||
# print(" python3 api.py attachmentsdownload BOARDID # All attachments as files")
|
||||
exit
|
||||
|
||||
# ------- SETTINGS START -------------
|
||||
|
||||
# Username is your Wekan username or email address.
|
||||
# OIDC/OAuth2 etc uses email address as username.
|
||||
|
||||
username = 'testtest'
|
||||
|
||||
password = 'testtest'
|
||||
|
||||
wekanurl = 'http://localhost:4000/'
|
||||
|
||||
# ------- SETTINGS END -------------
|
||||
|
||||
"""
|
||||
EXAMPLE:
|
||||
|
||||
python3 api.py
|
||||
|
||||
OR:
|
||||
chmod +x api.py
|
||||
./api.py
|
||||
|
||||
=== Wekan API Python CLI: Shows IDs for addcard ===
|
||||
AUTHORID is USERID that writes card.
|
||||
Syntax:
|
||||
python3 api.py users # All users
|
||||
python3 api.py boards USERID # Boards of USERID
|
||||
python3 api.py board BOARDID # Info of BOARDID
|
||||
python3 api.py swimlanes BOARDID # Swimlanes of BOARDID
|
||||
python3 api.py lists BOARDID # Lists of BOARDID
|
||||
python3 api.py createlist BOARDID LISTTITLE # Create list
|
||||
python3 api.py addcard AUTHORID BOARDID SWIMLANEID LISTID CARDTITLE CARDDESCRIPTION
|
||||
python3 api.py listattachments BOARDID # List attachments
|
||||
python3 api.py attachmentjson BOARDID ATTACHMENTID # One attachment as JSON base64
|
||||
python3 api.py attachmentbinary BOARDID ATTACHMENTID # One attachment as binary file
|
||||
|
||||
=== USERS ===
|
||||
|
||||
python3 api.py users
|
||||
|
||||
=> abcd1234
|
||||
|
||||
=== BOARDS ===
|
||||
|
||||
python3 api.py boards abcd1234
|
||||
|
||||
|
||||
=== SWIMLANES ===
|
||||
|
||||
python3 api.py swimlanes dYZ
|
||||
|
||||
[{"_id":"Jiv","title":"Default"}
|
||||
]
|
||||
|
||||
=== LISTS ===
|
||||
|
||||
python3 api.py lists dYZ
|
||||
|
||||
[]
|
||||
|
||||
There is no lists, so create a list:
|
||||
|
||||
=== CREATE LIST ===
|
||||
|
||||
python3 api.py createlist dYZ 'Test'
|
||||
|
||||
{"_id":"7Kp"}
|
||||
|
||||
# python3 api.py addcard AUTHORID BOARDID SWIMLANEID LISTID CARDTITLE CARDDESCRIPTION
|
||||
|
||||
python3 api.py addcard ppg dYZ Jiv 7Kp 'Test card' 'Test description'
|
||||
|
||||
=== LIST ATTACHMENTS WITH DOWNLOAD URLs ====
|
||||
|
||||
python3 api.py listattachments BOARDID
|
||||
|
||||
"""
|
||||
|
||||
# ------- API URL GENERATION START -----------
|
||||
|
||||
loginurl = 'users/login'
|
||||
wekanloginurl = wekanurl + loginurl
|
||||
apiboards = 'api/boards/'
|
||||
apiattachments = 'api/attachments/'
|
||||
apiusers = 'api/users'
|
||||
e = 'export'
|
||||
s = '/'
|
||||
l = 'lists'
|
||||
sw = 'swimlane'
|
||||
sws = 'swimlanes'
|
||||
cs = 'cards'
|
||||
bs = 'boards'
|
||||
atl = 'attachmentslist'
|
||||
at = 'attachment'
|
||||
ats = 'attachments'
|
||||
users = wekanurl + apiusers
|
||||
|
||||
# ------- API URL GENERATION END -----------
|
||||
|
||||
# ------- LOGIN TOKEN START -----------
|
||||
|
||||
data = {"username": username, "password": password}
|
||||
body = requests.post(wekanloginurl, data=data)
|
||||
d = body.json()
|
||||
apikey = d['token']
|
||||
|
||||
# ------- LOGIN TOKEN END -----------
|
||||
|
||||
if arguments == 7:
|
||||
|
||||
if sys.argv[1] == 'addcard':
|
||||
# ------- WRITE TO CARD START -----------
|
||||
authorid = sys.argv[2]
|
||||
boardid = sys.argv[3]
|
||||
swimlaneid = sys.argv[4]
|
||||
listid = sys.argv[5]
|
||||
cardtitle = sys.argv[6]
|
||||
carddescription = sys.argv[7]
|
||||
cardtolist = wekanurl + apiboards + boardid + s + l + s + listid + s + cs
|
||||
# Write to card
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
post_data = {'authorId': '{}'.format(authorid), 'title': '{}'.format(cardtitle), 'description': '{}'.format(carddescription), 'swimlaneId': '{}'.format(swimlaneid)}
|
||||
body = requests.post(cardtolist, data=post_data, headers=headers)
|
||||
print(body.text)
|
||||
# ------- WRITE TO CARD END -----------
|
||||
|
||||
if arguments == 3:
|
||||
|
||||
if sys.argv[1] == 'createlist':
|
||||
|
||||
# ------- CREATE LIST START -----------
|
||||
boardid = sys.argv[2]
|
||||
listtitle = sys.argv[3]
|
||||
list = wekanurl + apiboards + boardid + s + l
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
post_data = {'title': '{}'.format(listtitle)}
|
||||
body = requests.post(list, data=post_data, headers=headers)
|
||||
print("=== CREATE LIST ===\n")
|
||||
print(body.text)
|
||||
# ------- CREATE LIST END -----------
|
||||
|
||||
if arguments == 2:
|
||||
|
||||
# ------- BOARDS LIST START -----------
|
||||
userid = sys.argv[2]
|
||||
boards = users + s + userid + s + bs
|
||||
if sys.argv[1] == 'boards':
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
#post_data = {'userId': '{}'.format(userid)}
|
||||
body = requests.get(boards, headers=headers)
|
||||
print("=== BOARDS ===\n")
|
||||
data2 = body.text.replace('}',"}\n")
|
||||
print(data2)
|
||||
# ------- BOARDS LIST END -----------
|
||||
if sys.argv[1] == 'board':
|
||||
|
||||
# ------- BOARD INFO START -----------
|
||||
boardid = sys.argv[2]
|
||||
board = wekanurl + apiboards + boardid
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
body = requests.get(board, headers=headers)
|
||||
print("=== BOARD ===\n")
|
||||
data2 = body.text.replace('}',"}\n")
|
||||
print(data2)
|
||||
# ------- BOARD INFO END -----------
|
||||
|
||||
if sys.argv[1] == 'swimlanes':
|
||||
boardid = sys.argv[2]
|
||||
swimlanes = wekanurl + apiboards + boardid + s + sws
|
||||
# ------- SWIMLANES OF BOARD START -----------
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
print("=== SWIMLANES ===\n")
|
||||
body = requests.get(swimlanes, headers=headers)
|
||||
data2 = body.text.replace('}',"}\n")
|
||||
print(data2)
|
||||
# ------- SWIMLANES OF BOARD END -----------
|
||||
|
||||
if sys.argv[1] == 'lists':
|
||||
|
||||
# ------- LISTS OF BOARD START -----------
|
||||
boardid = sys.argv[2]
|
||||
attachments = wekanurl + apiboards + boardid
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
print("=== LISTS ===\n")
|
||||
body = requests.get(lists, headers=headers)
|
||||
data2 = body.text.replace('}',"}\n")
|
||||
print(data2)
|
||||
# ------- LISTS OF BOARD END -----------
|
||||
|
||||
if sys.argv[1] == 'listattachments':
|
||||
|
||||
# ------- LISTS OF ATTACHMENTS START -----------
|
||||
boardid = sys.argv[2]
|
||||
listattachments = wekanurl + apiboards + boardid + s + ats
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
print("=== LIST OF ATTACHMENTS ===\n")
|
||||
body = requests.get(listattachments, headers=headers)
|
||||
data2 = body.text.replace('}',"}\n")
|
||||
print(data2)
|
||||
# ------- LISTS OF ATTACHMENTS END -----------
|
||||
|
||||
if arguments == 1:
|
||||
|
||||
if sys.argv[1] == 'users':
|
||||
|
||||
# ------- LIST OF USERS START -----------
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
print(users)
|
||||
print("=== USERS ===\n")
|
||||
body = requests.get(users, headers=headers)
|
||||
data2 = body.text.replace('}',"}\n")
|
||||
print(data2)
|
||||
# ------- LIST OF USERS END -----------
|
||||
@@ -15,11 +15,18 @@ template(name="cardActivities")
|
||||
each activityData in currentCard.activities
|
||||
+activity(activity=activityData card=card mode=mode)
|
||||
|
||||
template(name="editOrDeleteComment")
|
||||
= ' - '
|
||||
a.js-open-inlined-form {{_ "edit"}}
|
||||
= ' - '
|
||||
a.js-delete-comment {{_ "delete"}}
|
||||
|
||||
template(name="activity")
|
||||
.activity
|
||||
+userAvatar(userId=activity.user._id)
|
||||
p.activity-desc
|
||||
+memberName(user=activity.user)
|
||||
span.activity-member
|
||||
+memberName(user=activity.user)
|
||||
|
||||
//- attachment activity -------------------------------------------------
|
||||
if($eq activity.activityType 'deleteAttachment')
|
||||
@@ -75,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
|
||||
|
||||
@@ -96,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
|
||||
|
||||
@@ -118,11 +125,10 @@ template(name="activity")
|
||||
+viewer
|
||||
= activity.comment.text
|
||||
span(title=activity.createdAt).activity-meta {{ moment activity.createdAt }}
|
||||
if ($eq currentUser._id activity.comment.userId)
|
||||
= ' - '
|
||||
a.js-open-inlined-form {{_ "edit"}}
|
||||
= ' - '
|
||||
a.js-delete-comment {{_ "delete"}}
|
||||
if($eq currentUser._id activity.comment.userId)
|
||||
+editOrDeleteComment
|
||||
else if currentUser.isBoardAdmin
|
||||
+editOrDeleteComment
|
||||
|
||||
if($eq activity.activityType 'deleteComment')
|
||||
| {{{_ 'activity-deleteComment' currentData.commentId}}}.
|
||||
@@ -133,10 +139,37 @@ 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
|
||||
|
||||
//- date activity ------------------------------------------------
|
||||
if($eq mode 'card')
|
||||
if($eq activity.activityType 'a-receivedAt')
|
||||
| {{{_ 'activity-receivedDate' (sanitize receivedDate) cardLink}}}.
|
||||
|
||||
if($eq activity.activityType 'a-startAt')
|
||||
| {{{_ 'activity-startDate' (sanitize startDate) cardLink}}}.
|
||||
|
||||
if($eq activity.activityType 'a-dueAt')
|
||||
| {{{_ 'activity-dueDate' (sanitize dueDate) cardLink}}}.
|
||||
|
||||
if($eq activity.activityType 'a-endAt')
|
||||
| {{{_ 'activity-endDate' (sanitize endDate) cardLink}}}.
|
||||
|
||||
if($eq mode 'board')
|
||||
if($eq activity.activityType 'a-receivedAt')
|
||||
| {{{_ 'activity-receivedDate' (sanitize receivedDate) cardLink}}}.
|
||||
|
||||
if($eq activity.activityType 'a-startAt')
|
||||
| {{{_ 'activity-startDate' (sanitize startDate) cardLink}}}.
|
||||
|
||||
if($eq activity.activityType 'a-dueAt')
|
||||
| {{{_ 'activity-dueDate' (sanitize dueDate) cardLink}}}.
|
||||
|
||||
if($eq activity.activityType 'a-endAt')
|
||||
| {{{_ 'activity-endDate' (sanitize endDate) cardLink}}}.
|
||||
|
||||
//- customField activity ------------------------------------------------
|
||||
if($eq mode 'board')
|
||||
if($eq activity.activityType 'createCustomField')
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import sanitizeXss from 'xss';
|
||||
|
||||
const activitiesPerPage = 20;
|
||||
const activitiesPerPage = 500;
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
@@ -81,6 +81,30 @@ BlazeComponent.extendComponent({
|
||||
return createCardLink(this.currentData().activity.card());
|
||||
},
|
||||
|
||||
receivedDate() {
|
||||
const receivedDate = this.currentData().activity.card();
|
||||
if (!receivedDate) return null;
|
||||
return receivedDate.receivedAt;
|
||||
},
|
||||
|
||||
startDate() {
|
||||
const startDate = this.currentData().activity.card();
|
||||
if (!startDate) return null;
|
||||
return startDate.startAt;
|
||||
},
|
||||
|
||||
dueDate() {
|
||||
const dueDate = this.currentData().activity.card();
|
||||
if (!dueDate) return null;
|
||||
return dueDate.dueAt;
|
||||
},
|
||||
|
||||
endDate() {
|
||||
const endDate = this.currentData().activity.card();
|
||||
if (!endDate) return null;
|
||||
return endDate.endAt;
|
||||
},
|
||||
|
||||
lastLabel() {
|
||||
const lastLabelId = this.currentData().activity.labelId;
|
||||
if (!lastLabelId) return null;
|
||||
@@ -219,7 +243,7 @@ function createCardLink(card) {
|
||||
Blaze.toHTML(
|
||||
HTML.A(
|
||||
{
|
||||
href: card.absoluteUrl(),
|
||||
href: card.originRelativeUrl(),
|
||||
class: 'action-card',
|
||||
},
|
||||
sanitizeXss(card.title),
|
||||
@@ -236,7 +260,7 @@ function createBoardLink(board, list) {
|
||||
Blaze.toHTML(
|
||||
HTML.A(
|
||||
{
|
||||
href: board.absoluteUrl(),
|
||||
href: board.originRelativeUrl(),
|
||||
class: 'action-board',
|
||||
},
|
||||
sanitizeXss(text),
|
||||
|
||||
@@ -10,12 +10,16 @@
|
||||
|
||||
.activity
|
||||
margin: 0.5px 0
|
||||
padding: 6px 0;
|
||||
display: flex
|
||||
|
||||
.member
|
||||
width: 24px
|
||||
width: 32px
|
||||
height: @width
|
||||
|
||||
.activity-member
|
||||
font-weight: 700
|
||||
|
||||
.activity-desc
|
||||
word-wrap: break-word
|
||||
overflow: hidden
|
||||
|
||||
@@ -3,11 +3,15 @@ BlazeComponent.extendComponent({
|
||||
this.subscribe('archivedBoards');
|
||||
},
|
||||
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
|
||||
archivedBoards() {
|
||||
return Boards.find(
|
||||
{ archived: true },
|
||||
{
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
sort: { archivedAt: -1, modifiedAt: -1 },
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { Cookies } from 'meteor/ostrio:cookies';
|
||||
const cookies = new Cookies();
|
||||
const subManager = new SubsManager();
|
||||
const { calculateIndex } = Utils;
|
||||
const swimlaneWhileSortingHeight = 150;
|
||||
@@ -197,7 +195,7 @@ BlazeComponent.extendComponent({
|
||||
if (currentUser) {
|
||||
showDesktopDragHandles = (currentUser.profile || {})
|
||||
.showDesktopDragHandles;
|
||||
} else if (cookies.has('showDesktopDragHandles')) {
|
||||
} else if (window.localStorage.getItem('showDesktopDragHandles')) {
|
||||
showDesktopDragHandles = true;
|
||||
} else {
|
||||
showDesktopDragHandles = false;
|
||||
@@ -213,7 +211,12 @@ BlazeComponent.extendComponent({
|
||||
}
|
||||
|
||||
// Disable drag-dropping if the current user is not a board member
|
||||
$swimlanesDom.sortable('option', 'disabled', !userIsMember());
|
||||
//$swimlanesDom.sortable('option', 'disabled', !userIsMember());
|
||||
$swimlanesDom.sortable(
|
||||
'option',
|
||||
'disabled',
|
||||
!Meteor.user().isBoardAdmin(),
|
||||
);
|
||||
});
|
||||
|
||||
function userIsMember() {
|
||||
@@ -237,7 +240,9 @@ BlazeComponent.extendComponent({
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).boardView === 'board-view-swimlanes';
|
||||
} else {
|
||||
return cookies.get('boardView') === 'board-view-swimlanes';
|
||||
return (
|
||||
window.localStorage.getItem('boardView') === 'board-view-swimlanes'
|
||||
);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -246,7 +251,7 @@ BlazeComponent.extendComponent({
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).boardView === 'board-view-lists';
|
||||
} else {
|
||||
return cookies.get('boardView') === 'board-view-lists';
|
||||
return window.localStorage.getItem('boardView') === 'board-view-lists';
|
||||
}
|
||||
},
|
||||
|
||||
@@ -255,7 +260,7 @@ BlazeComponent.extendComponent({
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).boardView === 'board-view-cal';
|
||||
} else {
|
||||
return cookies.get('boardView') === 'board-view-cal';
|
||||
return window.localStorage.getItem('boardView') === 'board-view-cal';
|
||||
}
|
||||
},
|
||||
|
||||
@@ -355,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,
|
||||
@@ -417,7 +422,7 @@ BlazeComponent.extendComponent({
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).boardView === 'board-view-cal';
|
||||
} else {
|
||||
return cookies.get('boardView') === 'board-view-cal';
|
||||
return window.localStorage.getItem('boardView') === 'board-view-cal';
|
||||
}
|
||||
},
|
||||
}).register('calendarView');
|
||||
@@ -15,7 +15,8 @@ setBoardColor(color)
|
||||
.is-selected .minicard
|
||||
border-left: 3px solid color
|
||||
|
||||
button[type=submit].primary, input[type=submit].primary
|
||||
button[type=submit].primary, input[type=submit].primary,
|
||||
.sidebar .sidebar-content .sidebar-btn
|
||||
background-color: darken(color, 20%)
|
||||
|
||||
&.pop-over .pop-over-list li a:not(.disabled):hover,
|
||||
@@ -589,22 +590,25 @@ setBoardClear(color1,color2)
|
||||
position relative
|
||||
|
||||
&#header-quick-access #header-user-bar .header-user-bar-name
|
||||
margin: 5px 3px 0 0;
|
||||
margin: 5px 3px 0 0
|
||||
|
||||
section#notifications-drawer
|
||||
top: 46px;
|
||||
top: 46px
|
||||
box-shadow: 0 4px 20px rgba(0,0,0,.1)
|
||||
max-width: 100%
|
||||
|
||||
section#notifications-drawer .header
|
||||
top: 46px;
|
||||
top: 46px
|
||||
border-radius: 0 3px
|
||||
height: 21px
|
||||
background: #f7f7f7
|
||||
|
||||
.board-canvas
|
||||
background: #f5f5f5
|
||||
|
||||
/* Swimlane */
|
||||
.swimlane
|
||||
background: #f5f5f5
|
||||
background: none
|
||||
|
||||
.swimlane .swimlane-header-wrap .swimlane-header
|
||||
font-family: Poppins
|
||||
@@ -650,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)
|
||||
|
||||
@@ -739,3 +742,283 @@ setBoardClear(color1,color2)
|
||||
|
||||
section#notifications-drawer .header .toggle-read
|
||||
top: 18px
|
||||
|
||||
/*
|
||||
Alternate "Modern Dark" Styling
|
||||
*/
|
||||
.board-color-moderndark
|
||||
setBoardColor(#2a2a2a)
|
||||
|
||||
/* General */
|
||||
body
|
||||
background: #2a2a2a
|
||||
|
||||
.board-wrapper .board-canvas .board-overlay
|
||||
opacity: .6
|
||||
|
||||
/* Forms */
|
||||
button[type=submit].primary, .board-color-modern input[type=submit].primary
|
||||
background-color: #819C5D
|
||||
|
||||
.toggle-switch:checked~.toggle-label
|
||||
background-color: #D2E9B4
|
||||
|
||||
.toggle-label:after, .board-color-modern .toggle-switch:checked~.toggle-label:after
|
||||
background-color: #819C5D !important
|
||||
|
||||
/* Headers */
|
||||
&#header-quick-access, .background-box, #header
|
||||
background-color: #333333
|
||||
|
||||
&#header-quick-access
|
||||
padding: 4px
|
||||
font-size: 14px
|
||||
|
||||
&#header #header-main-bar
|
||||
height: 30px
|
||||
padding-top: 3px
|
||||
padding-bottom: 3px
|
||||
|
||||
&#header
|
||||
box-shadow: 0 6px 6px -6px rgba(0,0,0,0.8)
|
||||
|
||||
&#header-quick-access ul
|
||||
overflow: visible
|
||||
|
||||
&#header-quick-access ul li.current
|
||||
border: 0 !important
|
||||
font-weight: bold
|
||||
|
||||
&#header-quick-access ul li.separator
|
||||
display: none
|
||||
|
||||
&#header-quick-access ul li:nth-child(3)
|
||||
margin-right: 10px
|
||||
|
||||
&#header-quick-access ul li a
|
||||
padding: 5px 10px
|
||||
border-radius: 2px
|
||||
|
||||
&#header-quick-access ul li.current a
|
||||
border-radius: 2px
|
||||
background: rgba(255,255,255,.2)
|
||||
|
||||
&#header #header-main-bar h1
|
||||
font-family: Poppins
|
||||
font-weight: bold
|
||||
line-height: 0.8em
|
||||
padding-top: 10px
|
||||
|
||||
/* Content */
|
||||
.board-canvas
|
||||
background: #2a2a2a
|
||||
padding: 10px 10px 0
|
||||
|
||||
/* Swimlanes */
|
||||
.swimlane .swimlane-header-wrap
|
||||
background-color: #666666
|
||||
color: #cccccc
|
||||
padding: 4px 0
|
||||
margin-bottom: 10px
|
||||
|
||||
.swimlane .swimlane-header-wrap .swimlane-header
|
||||
font-family: Poppins
|
||||
|
||||
.swimlane
|
||||
background: #2a2a2a
|
||||
line-height: 15px
|
||||
max-height: 100%
|
||||
|
||||
/* Lists */
|
||||
.swimlane .list
|
||||
background: #666666
|
||||
border-radius: 0
|
||||
border: 0px solid #666666
|
||||
flex: 0 0 265px;
|
||||
|
||||
.swimlane .list:nth-child(even)
|
||||
background: #5f5f5f
|
||||
|
||||
.list-header
|
||||
background: #333333
|
||||
padding-top: 10px
|
||||
border-bottom: 6px solid #333333
|
||||
|
||||
.list-header .viewer
|
||||
padding-left: 10px
|
||||
|
||||
.list-header .list-header-name
|
||||
line-height: 14px
|
||||
color: #eeeeee
|
||||
|
||||
.list-header .list-header-menu
|
||||
padding-top: 17px
|
||||
|
||||
.list-body
|
||||
scrollbar-width: thin
|
||||
scrollbar-color: #343434 #999999
|
||||
|
||||
.list-body::-webkit-scrollbar
|
||||
width: 10px
|
||||
|
||||
.list-body::-webkit-scrollbar-track
|
||||
background: #343434
|
||||
border-radius: 3px
|
||||
margin: 4px 0
|
||||
|
||||
.list-body::-webkit-scrollbar-thumb
|
||||
background-color: #999999
|
||||
border-radius: 6px
|
||||
border: 3px solid #343434
|
||||
|
||||
.list-body .open-minicard-composer:hover
|
||||
background: none
|
||||
box-shadow: none
|
||||
border-bottom: 0
|
||||
|
||||
.list-body a.open-minicard-composer, .list-body a.open-minicard-composer i, .list .list-composer .open-list-composer i
|
||||
color: #bbbbbb
|
||||
|
||||
.list-body a.open-minicard-composer:hover, .list-body a.open-minicard-composer:hover i, .list .list-composer .open-list-composer:hover i
|
||||
color: #ffffff
|
||||
|
||||
/* Mini Card */
|
||||
.minicard
|
||||
background-color: #444444
|
||||
color: #cccccc
|
||||
border-radius: 2px
|
||||
font-size: 0.9em
|
||||
padding: 10px
|
||||
box-shadow: 0 4px 3px -3px rgba(0,0,0,0.8)
|
||||
border-bottom: 1px solid #666666
|
||||
|
||||
.minicard:hover
|
||||
background-color: #555555 !important
|
||||
|
||||
.minicard .card-label
|
||||
font-size: 11px
|
||||
font-weight: 400
|
||||
padding: 2px 6px 0
|
||||
|
||||
.minicard .badges
|
||||
color: #bbbbbb
|
||||
|
||||
.minicard .date
|
||||
margin-top: 7px
|
||||
font-size: 11px
|
||||
|
||||
.card-date
|
||||
color: #555555
|
||||
|
||||
.card-date.almost-due
|
||||
color: #666666
|
||||
|
||||
.minicard.minicard-composer textarea.minicard-composer-textarea:focus
|
||||
background-color: #eeeeee
|
||||
color: #333333
|
||||
padding: 6px
|
||||
|
||||
.is-selected .minicard
|
||||
background-color: #666666
|
||||
|
||||
/* Card Details */
|
||||
.card-details
|
||||
position: absolute
|
||||
top: 30px
|
||||
left: calc(50% - 384px)
|
||||
width: 768px
|
||||
max-height: calc(100% - 60px)
|
||||
background-color: #454545
|
||||
color: #cccccc
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19)
|
||||
border: 1px solid #111111
|
||||
z-index: 100 !important
|
||||
|
||||
.card-details
|
||||
scrollbar-width: thin
|
||||
scrollbar-color: #343434 #999999
|
||||
|
||||
.card-details::-webkit-scrollbar
|
||||
width: 16px
|
||||
|
||||
.card-details::-webkit-scrollbar-track
|
||||
background: #343434
|
||||
|
||||
.card-details::-webkit-scrollbar-thumb
|
||||
background-color: #999999
|
||||
border-radius: 6px
|
||||
border: 4px solid #343434
|
||||
|
||||
.card-details .card-details-header
|
||||
background: #333333
|
||||
color: #cccccc
|
||||
border-bottom: 2px solid #2d2d2d
|
||||
|
||||
.card-details hr
|
||||
background: #2d2d2d
|
||||
|
||||
.card-details .card-details-item-title
|
||||
color: #ffffff
|
||||
|
||||
.card-details .new-description textarea, .card-details .new-comment textarea
|
||||
background-color: #dddddd
|
||||
color: #111111
|
||||
|
||||
.card-details .checklist
|
||||
background-color: transparent
|
||||
margin-bottom: 10px
|
||||
|
||||
.card-details .checklist-item
|
||||
background-color: rgba(255,255,255,0.1)
|
||||
padding: 2px 8px
|
||||
border-radius: 3px
|
||||
font-size: 13px
|
||||
margin-top: 5px
|
||||
|
||||
.card-details .check-box.materialCheckBox
|
||||
border-color: #ffffff
|
||||
|
||||
.card-details .check-box.materialCheckBox.is-checked
|
||||
border-bottom: 2px solid #819C5D
|
||||
border-right: 2px solid #819C5D
|
||||
border-top: 0
|
||||
border-left: 0
|
||||
|
||||
.card-details .js-add-checklist-item
|
||||
margin-top: 4px
|
||||
|
||||
.checklist-items .add-checklist-item
|
||||
margin-top: .7em
|
||||
|
||||
.card-details .activities .activity .activity-desc .activity-comment
|
||||
background-color: #cccccc
|
||||
color: #222222
|
||||
|
||||
/* Sidebar */
|
||||
.sidebar .sidebar-shadow
|
||||
background-color: #222222
|
||||
box-shadow: -10px 0 5px -10px #444444
|
||||
border-left: 1px solid #333333
|
||||
color: #cccccc
|
||||
|
||||
.activities .activity .activity-desc .activity-comment
|
||||
background-color: #cccccc
|
||||
color: #222222
|
||||
|
||||
/* Pop-Ups for "Modern Dark" */
|
||||
.pop-over.board-color-moderndark
|
||||
background-color: #454545
|
||||
color: #cccccc
|
||||
border: 1px solid #111111
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19)
|
||||
|
||||
.pop-over.board-color-moderndark .header
|
||||
background-color: #333333
|
||||
|
||||
.pop-over.board-color-moderndark .header-title
|
||||
font-family: Poppins
|
||||
font-size: 16px
|
||||
color: #cccccc
|
||||
|
||||
.pop-over.board-color-moderndark .pop-over-list li:hover > a
|
||||
background-color: #819C5D !important
|
||||
@@ -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'() {
|
||||
@@ -53,6 +54,10 @@ Template.boardChangeTitlePopup.events({
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated(){
|
||||
// set sort to default
|
||||
Session.set('sortBy','')
|
||||
},
|
||||
watchLevel() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
return currentBoard && currentBoard.getWatchLevel(Meteor.userId());
|
||||
@@ -110,6 +115,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 +133,9 @@ BlazeComponent.extendComponent({
|
||||
Sidebar.setView();
|
||||
Filter.reset();
|
||||
},
|
||||
'click .js-sort-reset'() {
|
||||
Session.set('sortBy','')
|
||||
},
|
||||
'click .js-open-search-view'() {
|
||||
Sidebar.setView('search');
|
||||
},
|
||||
@@ -160,6 +169,9 @@ Template.boardHeaderBar.helpers({
|
||||
boardView() {
|
||||
return Utils.boardView();
|
||||
},
|
||||
isSortActive(){
|
||||
return Session.get('sortBy') ? true : false;
|
||||
}
|
||||
});
|
||||
|
||||
Template.boardChangeViewPopup.events({
|
||||
@@ -368,3 +380,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');
|
||||
@@ -60,10 +60,10 @@ template(name="boardList")
|
||||
|
||||
template(name="boardListHeaderBar")
|
||||
h1 {{_ title }}
|
||||
.board-header-btns.right
|
||||
a.board-header-btn.js-open-archived-board
|
||||
i.fa.fa-archive
|
||||
span {{_ 'archives'}}
|
||||
a.board-header-btn(href="{{pathFor 'board' id=templatesBoardId slug=templatesBoardSlug}}")
|
||||
i.fa.fa-clone
|
||||
span {{_ 'templates'}}
|
||||
//.board-header-btns.right
|
||||
// a.board-header-btn.js-open-archived-board
|
||||
// i.fa.fa-archive
|
||||
// span {{_ 'archives'}}
|
||||
// a.board-header-btn(href="{{pathFor 'board' id=templatesBoardId slug=templatesBoardSlug}}")
|
||||
// i.fa.fa-clone
|
||||
// span {{_ 'templates'}}
|
||||
@@ -124,9 +124,13 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
'click .js-clone-board'(evt) {
|
||||
Meteor.call(
|
||||
'cloneBoard',
|
||||
'copyBoard',
|
||||
this.currentData()._id,
|
||||
Session.get('fromBoard'),
|
||||
{
|
||||
sort: Boards.find({ archived: false }).count(),
|
||||
type: 'board',
|
||||
title: Boards.findOne(this.currentData()._id).title,
|
||||
},
|
||||
(err, res) => {
|
||||
if (err) {
|
||||
this.setError(err.error);
|
||||
|
||||
@@ -7,7 +7,7 @@ $spaceBetweenTiles = 16px
|
||||
|
||||
li
|
||||
float: left
|
||||
width: 25%
|
||||
width: 20%
|
||||
box-sizing: border-box
|
||||
position: relative
|
||||
|
||||
@@ -33,13 +33,12 @@ $spaceBetweenTiles = 16px
|
||||
overflow: hidden;
|
||||
background-color: #999
|
||||
color: #f6f6f6
|
||||
height: auto
|
||||
min-height: 100px
|
||||
font-size: 16px
|
||||
line-height: 22px
|
||||
border-radius: 3px
|
||||
display: block
|
||||
font-weight: 700
|
||||
min-height: 18px
|
||||
padding: 8px
|
||||
margin: ($spaceBetweenTiles/2)
|
||||
position: relative
|
||||
|
||||
@@ -46,9 +46,10 @@ template(name="attachmentsGalery")
|
||||
| {{_ 'remove-cover'}}
|
||||
else
|
||||
| {{_ 'add-cover'}}
|
||||
a.js-confirm-delete
|
||||
i.fa.fa-close
|
||||
| {{_ 'delete'}}
|
||||
if currentUser.isBoardAdmin
|
||||
a.js-confirm-delete
|
||||
i.fa.fa-close
|
||||
| {{_ 'delete'}}
|
||||
|
||||
if currentUser.isBoardMember
|
||||
unless currentUser.isCommentOnly
|
||||
|
||||
@@ -45,6 +45,12 @@ Template.attachmentsGalery.events({
|
||||
},
|
||||
});
|
||||
|
||||
Template.attachmentsGalery.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
});
|
||||
|
||||
Template.previewAttachedImagePopup.events({
|
||||
'click .js-large-image-clicked'() {
|
||||
Popup.close();
|
||||
|
||||
@@ -52,6 +52,14 @@ template(name="cardCustomField-number")
|
||||
if value
|
||||
= value
|
||||
|
||||
template(name="cardCustomField-checkbox")
|
||||
.js-checklist-item.checklist-item(class="{{#if data.value }}is-checked{{/if}}")
|
||||
if canModifyCard
|
||||
.check-box-container
|
||||
.check-box.materialCheckBox(class="{{#if data.value }}is-checked{{/if}}")
|
||||
else
|
||||
.materialCheckBox(class="{{#if data.value }}is-checked{{/if}}")
|
||||
|
||||
template(name="cardCustomField-currency")
|
||||
if canModifyCard
|
||||
+inlinedForm(classNames="js-card-customfield-currency")
|
||||
|
||||
@@ -80,6 +80,25 @@ CardCustomField.register('cardCustomField');
|
||||
}
|
||||
}.register('cardCustomField-number'));
|
||||
|
||||
// cardCustomField-checkbox
|
||||
(class extends CardCustomField {
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
}
|
||||
|
||||
toggleItem() {
|
||||
this.card.setCustomField(this.customFieldId, !this.data().value);
|
||||
}
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-checklist-item .check-box-container': this.toggleItem,
|
||||
},
|
||||
];
|
||||
}
|
||||
}.register('cardCustomField-checkbox'));
|
||||
|
||||
// cardCustomField-currency
|
||||
(class extends CardCustomField {
|
||||
onCreated() {
|
||||
@@ -102,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);
|
||||
},
|
||||
},
|
||||
|
||||
@@ -8,3 +8,7 @@ template(name="dateBadge")
|
||||
time(datetime="{{showISODate}}")
|
||||
| {{showDate}}
|
||||
|
||||
template(name="dateCustomField")
|
||||
a(title="{{showTitle}}" class="{{classes}}")
|
||||
time(datetime="{{showISODate}}")
|
||||
| {{showDate}}
|
||||
@@ -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();
|
||||
@@ -363,6 +389,33 @@ class CardEndDate extends CardDate {
|
||||
}
|
||||
CardEndDate.register('cardEndDate');
|
||||
|
||||
class CardCustomFieldDate extends CardDate {
|
||||
template() {
|
||||
return 'dateCustomField';
|
||||
}
|
||||
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
const self = this;
|
||||
self.autorun(() => {
|
||||
self.date.set(moment(self.data().value));
|
||||
});
|
||||
}
|
||||
|
||||
classes() {
|
||||
return 'customfield-date';
|
||||
}
|
||||
|
||||
showTitle() {
|
||||
return '';
|
||||
}
|
||||
|
||||
events() {
|
||||
return [];
|
||||
}
|
||||
}
|
||||
CardCustomFieldDate.register('cardCustomFieldDate');
|
||||
|
||||
(class extends CardReceivedDate {
|
||||
showDate() {
|
||||
return this.date.get().format('l');
|
||||
@@ -387,6 +440,12 @@ CardEndDate.register('cardEndDate');
|
||||
}
|
||||
}.register('minicardEndDate'));
|
||||
|
||||
(class extends CardCustomFieldDate {
|
||||
showDate() {
|
||||
return this.date.get().format('l');
|
||||
}
|
||||
}.register('minicardCustomFieldDate'));
|
||||
|
||||
class VoteEndDate extends CardDate {
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
display: block
|
||||
border-radius: 4px
|
||||
padding: 1px 3px
|
||||
|
||||
|
||||
background-color: #dbdbdb
|
||||
&:hover, &.is-active
|
||||
background-color: #b3b3b3
|
||||
|
||||
|
||||
&.current, &.almost-due, &.due, &.long-overdue
|
||||
color: #fff
|
||||
|
||||
@@ -14,17 +14,17 @@
|
||||
background-color: #5ba639
|
||||
&:hover, &.is-active
|
||||
background-color: darken(#5ba639, 10)
|
||||
|
||||
|
||||
&.almost-due
|
||||
background-color: #edc909
|
||||
&:hover, &.is-active
|
||||
background-color: darken(#edc909, 10)
|
||||
|
||||
|
||||
&.due
|
||||
background-color: #fa3f00
|
||||
&:hover, &.is-active
|
||||
background-color: darken(#fa3f00, 10)
|
||||
|
||||
|
||||
&.long-overdue
|
||||
background-color: #fd5d47
|
||||
&:hover, &.is-active
|
||||
@@ -57,3 +57,7 @@
|
||||
-webkit-font-smoothing: antialiased
|
||||
margin-right: 0.3em
|
||||
|
||||
.customfield-date
|
||||
display: block
|
||||
border-radius: 4px
|
||||
padding: 1px 3px
|
||||
@@ -0,0 +1,7 @@
|
||||
|
||||
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")
|
||||
| {{getUnsavedValue 'cardDescription' _id getDescription}}
|
||||
@@ -0,0 +1,33 @@
|
||||
const descriptionFormIsOpen = new ReactiveVar(false);
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onDestroyed() {
|
||||
descriptionFormIsOpen.set(false);
|
||||
},
|
||||
|
||||
descriptionFormIsOpen() {
|
||||
return descriptionFormIsOpen.get();
|
||||
},
|
||||
|
||||
getInput() {
|
||||
return this.$('.js-new-description-input');
|
||||
},
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'submit .js-card-description'(event) {
|
||||
event.preventDefault();
|
||||
const description = this.currentComponent().getValue();
|
||||
this.data().setDescription(description);
|
||||
},
|
||||
// Pressing Ctrl+Enter should submit the form
|
||||
'keydown form textarea'(evt) {
|
||||
if (evt.keyCode === 13 && (evt.metaKey || evt.ctrlKey)) {
|
||||
this.find('button[type=submit]').click();
|
||||
}
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('descriptionForm');
|
||||
@@ -0,0 +1,60 @@
|
||||
@import 'nib'
|
||||
|
||||
.new-description
|
||||
position: relative
|
||||
margin: 0 0 20px 0
|
||||
|
||||
|
||||
&.is-open
|
||||
.helper
|
||||
display: inline-block
|
||||
|
||||
textarea
|
||||
min-height: 100px
|
||||
color: #4d4d4d
|
||||
cursor: auto
|
||||
overflow: hidden
|
||||
word-wrap: break-word
|
||||
|
||||
.too-long
|
||||
margin-top: 8px
|
||||
|
||||
textarea
|
||||
background-color: #fff
|
||||
border: 0
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, .23)
|
||||
color: #8c8c8c
|
||||
height: 36px
|
||||
margin: 4px 4px 6px 0
|
||||
padding: 9px 11px
|
||||
width: 100%
|
||||
|
||||
&:hover,
|
||||
&:is-open
|
||||
background-color: #fff
|
||||
box-shadow: 0 1px 3px rgba(0, 0, 0, .33)
|
||||
border: 0
|
||||
cursor: pointer
|
||||
|
||||
&:is-open
|
||||
cursor: auto
|
||||
|
||||
.description-item
|
||||
background-color: #fff
|
||||
border: 0
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, .23)
|
||||
color: #8c8c8c
|
||||
height: 36px
|
||||
margin: 4px 4px 6px 0
|
||||
width: 92%
|
||||
|
||||
&:hover
|
||||
background: darken(white, 12%)
|
||||
|
||||
&.add-description
|
||||
display: flex
|
||||
margin: 5px
|
||||
|
||||
a
|
||||
display: block
|
||||
margin: auto
|
||||
@@ -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
|
||||
@@ -42,12 +41,12 @@ template(name="cardDetails")
|
||||
else
|
||||
p.warning {{_ 'card-archived'}}
|
||||
|
||||
.card-details-items
|
||||
.card-details-items
|
||||
if currentBoard.allowsLabels
|
||||
.card-details-item.card-details-item-labels
|
||||
h3.card-details-item-title
|
||||
i.fa.fa-tags
|
||||
| {{_ 'labels'}}
|
||||
| {{_ 'labels'}}
|
||||
a(class="{{#if canModifyCard}}js-add-labels{{else}}is-disabled{{/if}}" title="{{_ 'card-labels-title'}}")
|
||||
each labels
|
||||
span.card-label(class="card-label-{{color}}" title=name)
|
||||
@@ -57,7 +56,7 @@ template(name="cardDetails")
|
||||
unless currentUser.isWorker
|
||||
a.card-label.add-label.js-add-labels(title="{{_ 'card-labels-title'}}")
|
||||
i.fa.fa-plus
|
||||
|
||||
|
||||
if currentBoard.allowsReceivedDate
|
||||
hr
|
||||
.card-details-item.card-details-item-received
|
||||
@@ -245,8 +244,7 @@ template(name="cardDetails")
|
||||
| {{_ 'description'}}
|
||||
if currentBoard.allowsDescriptionText
|
||||
+inlinedCardDescription(classNames="card-description js-card-description")
|
||||
+editor(autofocus=true)
|
||||
| {{getUnsavedValue 'cardDescription' _id getDescription}}
|
||||
+descriptionForm
|
||||
.edit-controls.clearfix
|
||||
button.primary(type="submit") {{_ 'save'}}
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
@@ -355,10 +353,11 @@ template(name="cardDetailsActionsPopup")
|
||||
a.js-start-voting
|
||||
i.fa.fa-thumbs-up
|
||||
| {{_ 'card-edit-voting'}}
|
||||
li
|
||||
a.js-custom-fields
|
||||
i.fa.fa-list-alt
|
||||
| {{_ 'card-edit-custom-fields'}}
|
||||
if currentUser.isBoardAdmin
|
||||
li
|
||||
a.js-custom-fields
|
||||
i.fa.fa-list-alt
|
||||
| {{_ 'card-edit-custom-fields'}}
|
||||
//li: a.js-received-date {{_ 'editCardReceivedDatePopup-title'}}
|
||||
//li: a.js-start-date {{_ 'editCardStartDatePopup-title'}}
|
||||
//li: a.js-due-date {{_ 'editCardDueDatePopup-title'}}
|
||||
@@ -381,17 +380,19 @@ template(name="cardDetailsActionsPopup")
|
||||
a.js-move-card-to-bottom
|
||||
i.fa.fa-arrow-down
|
||||
| {{_ 'moveCardToBottom-title'}}
|
||||
unless currentUser.isWorker
|
||||
hr
|
||||
ul.pop-over-list
|
||||
ul.pop-over-list
|
||||
if currentUser.isBoardAdmin
|
||||
li
|
||||
a.js-move-card
|
||||
i.fa.fa-arrow-right
|
||||
| {{_ 'moveCardPopup-title'}}
|
||||
unless currentUser.isWorker
|
||||
li
|
||||
a.js-copy-card
|
||||
i.fa.fa-copy
|
||||
| {{_ 'copyCardPopup-title'}}
|
||||
unless currentUser.isWorker
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li
|
||||
@@ -430,13 +431,14 @@ template(name="copyChecklistToManyCardsPopup")
|
||||
+boardsAndLists
|
||||
|
||||
template(name="boardsAndLists")
|
||||
label {{_ 'boards'}}:
|
||||
select.js-select-boards(autofocus)
|
||||
each boards
|
||||
if $eq _id currentBoard._id
|
||||
option(value="{{_id}}" selected) {{_ 'current'}}
|
||||
else
|
||||
option(value="{{_id}}") {{title}}
|
||||
unless currentUser.isWorker
|
||||
label {{_ 'boards'}}:
|
||||
select.js-select-boards(autofocus)
|
||||
each boards
|
||||
if $eq _id currentBoard._id
|
||||
option(value="{{_id}}" selected) {{_ 'current'}}
|
||||
else
|
||||
option(value="{{_id}}") {{title}}
|
||||
|
||||
label {{_ 'swimlanes'}}:
|
||||
select.js-select-swimlanes
|
||||
@@ -530,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
|
||||
@@ -561,7 +563,8 @@ template(name="cardMorePopup")
|
||||
br
|
||||
| {{_ 'added'}}
|
||||
span.date(title=card.createdAt) {{ moment createdAt 'LLL' }}
|
||||
a.js-delete(title="{{_ 'card-delete-notice'}}") {{_ 'delete'}}
|
||||
if currentUser.isBoardAdmin
|
||||
a.js-delete(title="{{_ 'card-delete-notice'}}") {{_ 'delete'}}
|
||||
|
||||
template(name="setCardColorPopup")
|
||||
form.edit-label
|
||||
@@ -608,7 +611,8 @@ template(name="cardStartVotingPopup")
|
||||
|
||||
button.primary.js-submit {{_ 'save'}}
|
||||
if getVoteQuestion
|
||||
button.js-remove-vote.negate.wide.right {{_ 'delete'}}
|
||||
if currentUser.isBoardAdmin
|
||||
button.js-remove-vote.negate.wide.right {{_ 'delete'}}
|
||||
|
||||
template(name="positiveVoteMembersPopup")
|
||||
ul.pop-over-list.js-card-member-list
|
||||
|
||||
@@ -57,7 +57,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
scrollParentContainer() {
|
||||
const cardPanelWidth = 510;
|
||||
const cardPanelWidth = 600;
|
||||
const parentComponent = this.parentComponent();
|
||||
// TODO sometimes parentComponent is not available, maybe because it's not
|
||||
// yet created?!
|
||||
@@ -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,
|
||||
@@ -250,12 +250,15 @@ BlazeComponent.extendComponent({
|
||||
|
||||
// Disable sorting if the current user is not a board member
|
||||
this.autorun(() => {
|
||||
const disabled = !userIsMember() || Utils.isMiniScreen();
|
||||
const disabled = !userIsMember();
|
||||
if (
|
||||
$checklistsDom.data('uiSortable') ||
|
||||
$checklistsDom.data('sortable')
|
||||
) {
|
||||
$checklistsDom.sortable('option', 'disabled', disabled);
|
||||
if (Utils.isMiniScreenOrShowDesktopDragHandles()) {
|
||||
$checklistsDom.sortable({ handle: '.checklist-handle' });
|
||||
}
|
||||
}
|
||||
if ($subtasksDom.data('uiSortable') || $subtasksDom.data('sortable')) {
|
||||
$subtasksDom.sortable('option', 'disabled', disabled);
|
||||
@@ -288,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();
|
||||
@@ -564,6 +569,10 @@ Template.cardDetailsActionsPopup.helpers({
|
||||
return this.findWatcher(Meteor.userId());
|
||||
},
|
||||
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
@@ -668,7 +677,11 @@ Template.moveCardPopup.events({
|
||||
// instead from a “component” state.
|
||||
const card = Cards.findOne(Session.get('currentCard'));
|
||||
const bSelect = $('.js-select-boards')[0];
|
||||
const boardId = bSelect.options[bSelect.selectedIndex].value;
|
||||
let boardId;
|
||||
// if we are a worker, we won't have a board select so we just use the
|
||||
// current boardId of the card.
|
||||
if (bSelect) boardId = bSelect.options[bSelect.selectedIndex].value;
|
||||
else boardId = card.boardId;
|
||||
const lSelect = $('.js-select-lists')[0];
|
||||
const listId = lSelect.options[lSelect.selectedIndex].value;
|
||||
const slSelect = $('.js-select-swimlanes')[0];
|
||||
|
||||
@@ -41,6 +41,8 @@ template(name="checklistDetail")
|
||||
|
||||
if canModifyCard
|
||||
h2.title.js-open-inlined-form.is-editable
|
||||
if isMiniScreenOrShowDesktopDragHandles
|
||||
span.fa.checklist-handle(class="fa-arrows" title="{{_ 'dragChecklist'}}")
|
||||
+viewer
|
||||
= checklist.title
|
||||
else
|
||||
@@ -100,6 +102,8 @@ template(name='checklistItemDetail')
|
||||
if canModifyCard
|
||||
.check-box-container
|
||||
.check-box.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}")
|
||||
if isMiniScreenOrShowDesktopDragHandles
|
||||
span.fa.checklistitem-handle(class="fa-arrows" title="{{_ 'dragChecklistItem'}}")
|
||||
.item-title.js-open-inlined-form.is-editable(class="{{#if item.isFinished }}is-checked{{/if}}")
|
||||
+viewer
|
||||
= item.title
|
||||
|
||||
@@ -6,7 +6,7 @@ function initSorting(items) {
|
||||
helper: 'clone',
|
||||
items: '.js-checklist-item:not(.placeholder)',
|
||||
connectWith: '.js-checklist-items',
|
||||
appendTo: '.board-canvas',
|
||||
appendTo: 'parent',
|
||||
distance: 7,
|
||||
placeholder: 'checklist-item placeholder',
|
||||
scroll: false,
|
||||
@@ -55,11 +55,12 @@ BlazeComponent.extendComponent({
|
||||
self.autorun(() => {
|
||||
const $itemsDom = $(self.itemsDom);
|
||||
if ($itemsDom.data('uiSortable') || $itemsDom.data('sortable')) {
|
||||
$(self.itemsDom).sortable(
|
||||
'option',
|
||||
'disabled',
|
||||
!userIsMember() || Utils.isMiniScreen(),
|
||||
);
|
||||
$(self.itemsDom).sortable('option', 'disabled', !userIsMember());
|
||||
if (Utils.isMiniScreenOrShowDesktopDragHandles()) {
|
||||
$(self.itemsDom).sortable({
|
||||
handle: 'span.fa.checklistitem-handle',
|
||||
});
|
||||
}
|
||||
}
|
||||
});
|
||||
},
|
||||
@@ -110,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.
|
||||
@@ -222,6 +223,14 @@ Template.checklists.helpers({
|
||||
},
|
||||
});
|
||||
|
||||
Template.addChecklistItemForm.onRendered(() => {
|
||||
autosize($('textarea.js-add-checklist-item'));
|
||||
});
|
||||
|
||||
Template.editChecklistItemForm.onRendered(() => {
|
||||
autosize($('textarea.js-edit-checklist-item'));
|
||||
});
|
||||
|
||||
Template.checklistDeleteDialog.onCreated(() => {
|
||||
const $cardDetails = this.$('.card-details');
|
||||
this.scrollState = {
|
||||
|
||||
@@ -42,6 +42,11 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
|
||||
.js-delete-checklist
|
||||
@extends .delete-text
|
||||
|
||||
span.fa.checklist-handle
|
||||
padding-right: 20px
|
||||
padding-top: 3px
|
||||
float: left
|
||||
|
||||
|
||||
.js-confirm-checklist-delete
|
||||
background-color: darken(white, 3%)
|
||||
@@ -129,7 +134,7 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
|
||||
background-color: darken(white, 8%)
|
||||
|
||||
.check-box-container
|
||||
padding-right: 1px;
|
||||
padding-right: 10px;
|
||||
|
||||
.check-box
|
||||
margin: 0.1em 0 0 0;
|
||||
@@ -139,7 +144,6 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
|
||||
|
||||
.item-title
|
||||
flex: 1
|
||||
margin-left: 10px;
|
||||
&.is-checked
|
||||
color: #8c8c8c
|
||||
font-style: italic
|
||||
@@ -151,6 +155,10 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
|
||||
word-wrap: break-word
|
||||
max-width: 420px
|
||||
|
||||
span.fa.checklistitem-handle
|
||||
padding-top: 2px
|
||||
padding-right: 10px;
|
||||
|
||||
.js-delete-checklist-item
|
||||
margin: 0 0 0.5em 1.33em
|
||||
@extends .delete-text
|
||||
|
||||
@@ -77,6 +77,11 @@ template(name="minicard")
|
||||
if $eq definition.type "currency"
|
||||
+viewer
|
||||
= formattedCurrencyCustomFieldValue(definition)
|
||||
else if $eq definition.type "date"
|
||||
.date
|
||||
+minicardCustomFieldDate
|
||||
else if $eq definition.type "checkbox"
|
||||
.materialCheckBox(class="{{#if value }}is-checked{{/if}}")
|
||||
else
|
||||
+viewer
|
||||
= trueValue
|
||||
@@ -85,7 +90,6 @@ template(name="minicard")
|
||||
.minicard-assignees.js-minicard-assignees
|
||||
each getAssignees
|
||||
+userAvatar(userId=this)
|
||||
hr
|
||||
|
||||
if getMembers
|
||||
.minicard-members.js-minicard-members
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { Cookies } from 'meteor/ostrio:cookies';
|
||||
const cookies = new Cookies();
|
||||
// Template.cards.events({
|
||||
// 'click .member': Popup.open('cardMember')
|
||||
// });
|
||||
@@ -34,10 +32,10 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
{
|
||||
'click .js-toggle-minicard-label-text'() {
|
||||
if (cookies.has('hiddenMinicardLabelText')) {
|
||||
cookies.remove('hiddenMinicardLabelText'); //true
|
||||
if (window.localStorage.getItem('hiddenMinicardLabelText')) {
|
||||
window.localStorage.removeItem('hiddenMinicardLabelText'); //true
|
||||
} else {
|
||||
cookies.set('hiddenMinicardLabelText', 'true'); //true
|
||||
window.localStorage.setItem('hiddenMinicardLabelText', 'true'); //true
|
||||
}
|
||||
},
|
||||
},
|
||||
@@ -50,7 +48,7 @@ Template.minicard.helpers({
|
||||
currentUser = Meteor.user();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).showDesktopDragHandles;
|
||||
} else if (cookies.has('showDesktopDragHandles')) {
|
||||
} else if (window.localStorage.getItem('showDesktopDragHandles')) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -60,7 +58,7 @@ Template.minicard.helpers({
|
||||
currentUser = Meteor.user();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).hiddenMinicardLabelText;
|
||||
} else if (cookies.has('hiddenMinicardLabelText')) {
|
||||
} else if (window.localStorage.getItem('hiddenMinicardLabelText')) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
||||
@@ -165,13 +165,15 @@
|
||||
.minicard-members,
|
||||
.minicard-assignees
|
||||
float: right
|
||||
margin: 2px -8px 12px 0
|
||||
margin-left: 5px
|
||||
margin-bottom: 4px
|
||||
|
||||
.member
|
||||
float: right
|
||||
border-radius: 50%
|
||||
height: 28px
|
||||
width: @height
|
||||
margin-bottom: 4px
|
||||
|
||||
.assignee
|
||||
float: right
|
||||
@@ -180,7 +182,10 @@
|
||||
width: @height
|
||||
|
||||
+ .badges
|
||||
margin-top: 10px
|
||||
margin-top: 5px
|
||||
|
||||
.minicard-assignees
|
||||
border-bottom: 1px solid red
|
||||
|
||||
.minicard-members:empty,
|
||||
.minicard-assignees:empty
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
template(name="resultCard")
|
||||
.result-card-wrapper
|
||||
a.minicard-wrapper.card-title(href=originRelativeUrl)
|
||||
+minicard(this)
|
||||
//= card.title
|
||||
ul.result-card-context-list
|
||||
li.result-card-context(title="{{_ 'board'}}")
|
||||
.result-card-block-wrapper
|
||||
+viewer
|
||||
= getBoard.title
|
||||
if getBoard.archived
|
||||
i.fa.fa-archive
|
||||
li.result-card-context.result-card-context-separator
|
||||
= ' '
|
||||
| {{_ 'context-separator'}}
|
||||
= ' '
|
||||
li.result-card-context(title="{{_ 'swimlane'}}")
|
||||
.result-card-block-wrapper
|
||||
+viewer
|
||||
= getSwimlane.title
|
||||
if getSwimlane.archived
|
||||
i.fa.fa-archive
|
||||
li.result-card-context.result-card-context-separator
|
||||
= ' '
|
||||
| {{_ 'context-separator'}}
|
||||
= ' '
|
||||
li.result-card-context(title="{{_ 'list'}}")
|
||||
.result-card-block-wrapper
|
||||
+viewer
|
||||
= getList.title
|
||||
if getList.archived
|
||||
i.fa.fa-archive
|
||||
@@ -0,0 +1,11 @@
|
||||
Template.resultCard.helpers({
|
||||
userId() {
|
||||
return Meteor.userId();
|
||||
},
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [{}];
|
||||
},
|
||||
}).register('resultCard');
|
||||
@@ -0,0 +1,24 @@
|
||||
.result-card-list-wrapper
|
||||
margin: 1rem
|
||||
border-radius: 5px
|
||||
padding: 1.5rem
|
||||
padding-top: 0.75rem
|
||||
display: inline-block
|
||||
min-width: 250px
|
||||
max-width: 350px
|
||||
|
||||
.result-card-wrapper
|
||||
margin-top: 0
|
||||
margin-bottom: 10px
|
||||
|
||||
.result-card-context
|
||||
display: inline-block
|
||||
|
||||
.result-card-context-separator
|
||||
font-weight: bold
|
||||
|
||||
.result-card-context-list
|
||||
margin-bottom: 0.7rem
|
||||
|
||||
.result-card-block-wrapper
|
||||
display: inline-block
|
||||
@@ -2,10 +2,10 @@ template(name="subtasks")
|
||||
h3.card-details-item-title
|
||||
i.fa.fa-sitemap
|
||||
| {{_ 'subtasks'}}
|
||||
if toggleDeleteDialog.get
|
||||
.board-overlay#card-details-overlay
|
||||
+subtaskDeleteDialog(subtask = subtaskToDelete)
|
||||
|
||||
if currentUser.isBoardAdmin
|
||||
if toggleDeleteDialog.get
|
||||
.board-overlay#card-details-overlay
|
||||
+subtaskDeleteDialog(subtask = subtaskToDelete)
|
||||
|
||||
.card-subtasks-items
|
||||
each subtask in currentCard.subtasks
|
||||
@@ -28,7 +28,8 @@ template(name="subtaskDetail")
|
||||
span
|
||||
a.js-view-subtask(title="{{ subtask.title }}") {{_ "view-it"}}
|
||||
if canModifyCard
|
||||
a.js-delete-subtask.toggle-delete-subtask-dialog {{_ "delete"}}...
|
||||
if currentUser.isBoardAdmin
|
||||
a.js-delete-subtask.toggle-delete-subtask-dialog {{_ "delete"}}...
|
||||
|
||||
if canModifyCard
|
||||
h2.title.js-open-inlined-form.is-editable
|
||||
@@ -68,7 +69,8 @@ template(name="editSubtaskItemForm")
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
span(title=createdAt) {{ moment createdAt }}
|
||||
if canModifyCard
|
||||
a.js-delete-subtask-item {{_ "delete"}}...
|
||||
if currentUser.isBoardAdmin
|
||||
a.js-delete-subtask-item {{_ "delete"}}...
|
||||
|
||||
template(name="subtasksItems")
|
||||
.subtasks-items.js-subtasks-items
|
||||
|
||||
@@ -242,11 +242,11 @@ textarea
|
||||
margin: 3px 4px
|
||||
|
||||
// Material Design checkboxes
|
||||
[type="checkbox"]:not(:checked),
|
||||
[type="checkbox"]:checked
|
||||
position: absolute
|
||||
left: -9999px
|
||||
visibility: hidden
|
||||
[type="checkbox"]:not(:checked),
|
||||
[type="checkbox"]:checked
|
||||
position: absolute
|
||||
left: -9999px
|
||||
visibility: hidden
|
||||
|
||||
.materialCheckBox
|
||||
position: relative
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export function getMembersToMap(data) {
|
||||
export function csvGetMembersToMap(data) {
|
||||
// we will work on the list itself (an ordered array of objects) when a
|
||||
// mapping is done, we add a 'wekan' field to the object representing the
|
||||
// imported member
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import trelloMembersMapper from './trelloMembersMapper';
|
||||
import wekanMembersMapper from './wekanMembersMapper';
|
||||
import csvMembersMapper from './csvMembersMapper';
|
||||
import { trelloGetMembersToMap } from './trelloMembersMapper';
|
||||
import { wekanGetMembersToMap } from './wekanMembersMapper';
|
||||
import { csvGetMembersToMap } from './csvMembersMapper';
|
||||
|
||||
const Papa = require('papaparse');
|
||||
|
||||
@@ -99,13 +99,13 @@ BlazeComponent.extendComponent({
|
||||
let membersToMap;
|
||||
switch (importSource) {
|
||||
case 'trello':
|
||||
membersToMap = trelloMembersMapper.getMembersToMap(dataObject);
|
||||
membersToMap = trelloGetMembersToMap(dataObject);
|
||||
break;
|
||||
case 'wekan':
|
||||
membersToMap = wekanMembersMapper.getMembersToMap(dataObject);
|
||||
membersToMap = wekanGetMembersToMap(dataObject);
|
||||
break;
|
||||
case 'csv':
|
||||
membersToMap = csvMembersMapper.getMembersToMap(dataObject);
|
||||
membersToMap = csvGetMembersToMap(dataObject);
|
||||
break;
|
||||
}
|
||||
return membersToMap;
|
||||
@@ -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
|
||||
@@ -1,4 +1,4 @@
|
||||
export function getMembersToMap(data) {
|
||||
export function trelloGetMembersToMap(data) {
|
||||
// we will work on the list itself (an ordered array of objects) when a
|
||||
// mapping is done, we add a 'wekan' field to the object representing the
|
||||
// imported member
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
export function getMembersToMap(data) {
|
||||
export function wekanGetMembersToMap(data) {
|
||||
// we will work on the list itself (an ordered array of objects) when a
|
||||
// mapping is done, we add a 'wekan' field to the object representing the
|
||||
// imported member
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { Cookies } from 'meteor/ostrio:cookies';
|
||||
const cookies = new Cookies();
|
||||
const { calculateIndex } = Utils;
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
@@ -124,7 +122,7 @@ BlazeComponent.extendComponent({
|
||||
if (currentUser) {
|
||||
showDesktopDragHandles = (currentUser.profile || {})
|
||||
.showDesktopDragHandles;
|
||||
} else if (cookies.has('showDesktopDragHandles')) {
|
||||
} else if (window.localStorage.getItem('showDesktopDragHandles')) {
|
||||
showDesktopDragHandles = true;
|
||||
} else {
|
||||
showDesktopDragHandles = false;
|
||||
@@ -185,7 +183,7 @@ Template.list.helpers({
|
||||
currentUser = Meteor.user();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).showDesktopDragHandles;
|
||||
} else if (cookies.has('showDesktopDragHandles')) {
|
||||
} else if (window.localStorage.getItem('showDesktopDragHandles')) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
|
||||
@@ -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 });
|
||||
},
|
||||
);
|
||||
@@ -675,12 +678,18 @@ BlazeComponent.extendComponent({
|
||||
element.type = 'swimlane';
|
||||
_id = element.copy(this.boardId);
|
||||
} else if (this.isBoardTemplateSearch) {
|
||||
board = Boards.findOne(element.linkedId);
|
||||
board.sort = Boards.find({ archived: false }).count();
|
||||
board.type = 'board';
|
||||
board.title = element.title;
|
||||
delete board.slug;
|
||||
_id = board.copy();
|
||||
Meteor.call(
|
||||
'copyBoard',
|
||||
element.linkedId,
|
||||
{
|
||||
sort: Boards.find({ archived: false }).count(),
|
||||
type: 'board',
|
||||
title: element.title,
|
||||
},
|
||||
(err, data) => {
|
||||
_id = data;
|
||||
},
|
||||
);
|
||||
}
|
||||
Popup.close();
|
||||
},
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
template(name="listHeader")
|
||||
.list-header.js-list-header(
|
||||
class="{{#if limitToShowCardsCount}}list-header-card-count{{/if}}"
|
||||
class="{{#if colorClass}}list-header-{{colorClass}}{{/if}}")
|
||||
class=colorClass)
|
||||
+inlinedForm
|
||||
+editListTitleForm
|
||||
else
|
||||
@@ -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
|
||||
@@ -43,8 +43,9 @@ template(name="listHeader")
|
||||
if canSeeAddCard
|
||||
a.js-add-card.fa.fa-plus.list-header-plus-icon
|
||||
a.fa.fa-navicon.js-open-list-menu
|
||||
if showDesktopDragHandles
|
||||
a.list-header-handle.handle.fa.fa-arrows.js-list-handle
|
||||
if currentUser.isBoardAdmin
|
||||
if showDesktopDragHandles
|
||||
a.list-header-handle.handle.fa.fa-arrows.js-list-handle
|
||||
|
||||
template(name="editListTitleForm")
|
||||
.list-composer
|
||||
@@ -115,8 +116,9 @@ template(name="listMorePopup")
|
||||
input.inline-input(type="text" readonly value="{{ rootUrl }}")
|
||||
| {{_ 'added'}}
|
||||
span.date(title=list.createdAt) {{ moment createdAt 'LLL' }}
|
||||
unless currentUser.isWorker
|
||||
a.js-delete {{_ 'delete'}}
|
||||
//unless currentUser.isWorker
|
||||
// if currentUser.isBoardAdmin
|
||||
// a.js-delete {{_ 'delete'}}
|
||||
|
||||
template(name="listDeletePopup")
|
||||
p {{_ "list-delete-pop"}}
|
||||
@@ -151,7 +153,7 @@ template(name="setListColorPopup")
|
||||
form.edit-label
|
||||
.palette-colors: each colors
|
||||
// note: we use the swimlane palette to have more than just the border
|
||||
span.card-label.palette-color.js-palette-color(class="swimlane-{{color}}")
|
||||
span.card-label.palette-color.js-palette-color(class="card-details-{{color}}")
|
||||
if(isSelected color)
|
||||
i.fa.fa-check
|
||||
button.primary.confirm.js-submit {{_ 'save'}}
|
||||
|
||||
@@ -1,5 +1,3 @@
|
||||
import { Cookies } from 'meteor/ostrio:cookies';
|
||||
const cookies = new Cookies();
|
||||
let listsColors;
|
||||
Meteor.startup(() => {
|
||||
listsColors = Lists.simpleSchema()._schema.color.allowedValues;
|
||||
@@ -74,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() {
|
||||
@@ -106,11 +112,15 @@ BlazeComponent.extendComponent({
|
||||
}).register('listHeader');
|
||||
|
||||
Template.listHeader.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
|
||||
showDesktopDragHandles() {
|
||||
currentUser = Meteor.user();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).showDesktopDragHandles;
|
||||
} else if (cookies.has('showDesktopDragHandles')) {
|
||||
} else if (window.localStorage.getItem('showDesktopDragHandles')) {
|
||||
return true;
|
||||
} else {
|
||||
return false;
|
||||
@@ -119,6 +129,10 @@ Template.listHeader.helpers({
|
||||
});
|
||||
|
||||
Template.listActionPopup.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
|
||||
isWipLimitEnabled() {
|
||||
return Template.currentData().getWipLimit('enabled');
|
||||
},
|
||||
@@ -256,6 +270,12 @@ Template.listMorePopup.events({
|
||||
}),
|
||||
});
|
||||
|
||||
Template.listHeader.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentList = this.currentData();
|
||||
@@ -267,7 +287,11 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
isSelected(color) {
|
||||
return this.currentColor.get() === color;
|
||||
if (this.currentColor.get() === null) {
|
||||
return color === 'white';
|
||||
} else {
|
||||
return this.currentColor.get() === color;
|
||||
}
|
||||
},
|
||||
|
||||
events() {
|
||||
|
||||
@@ -0,0 +1,41 @@
|
||||
template(name="brokenCardsHeaderBar")
|
||||
h1
|
||||
| {{_ '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
|
||||
@@ -0,0 +1,28 @@
|
||||
BlazeComponent.extendComponent({}).register('brokenCardsHeaderBar');
|
||||
|
||||
Template.brokenCards.helpers({
|
||||
userId() {
|
||||
return Meteor.userId();
|
||||
},
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
Meteor.subscribe('setting');
|
||||
Meteor.subscribe('brokenCards');
|
||||
},
|
||||
|
||||
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');
|
||||
@@ -0,0 +1,31 @@
|
||||
.broken-cards-card-wrapper
|
||||
margin-top: 0
|
||||
margin-bottom: 10px
|
||||
border-width: 3px !important
|
||||
border-color: grey !important
|
||||
border-style: solid
|
||||
border-radius: 5px
|
||||
padding: 1.5rem
|
||||
background-color: white
|
||||
|
||||
.broken-cards-wrapper
|
||||
max-width: 500px
|
||||
margin-right: auto
|
||||
margin-left: auto
|
||||
|
||||
.broken-cards-card-title
|
||||
font-weight: bold
|
||||
//padding: 10px
|
||||
|
||||
.broken-cards-context
|
||||
display: inline-block
|
||||
|
||||
.broken-cards-context-separator
|
||||
font-weight: bold
|
||||
|
||||
.broken-cards-context-list
|
||||
//margin-bottom: 0.7rem
|
||||
|
||||
.broken-cards-null
|
||||
color: darkred
|
||||
font-style: italic
|
||||
@@ -0,0 +1,53 @@
|
||||
template(name="dueCardsHeaderBar")
|
||||
if currentUser
|
||||
h1
|
||||
i.fa.fa-calendar
|
||||
| {{_ 'dueCards-title'}}
|
||||
|
||||
.board-header-btns.left
|
||||
a.board-header-btn.js-due-cards-view-change(title="{{_ 'dueCardsViewChange-title'}}")
|
||||
i.fa.fa-caret-down
|
||||
if $eq dueCardsView 'me'
|
||||
i.fa.fa-user
|
||||
| {{_ 'dueCardsViewChange-choice-me'}}
|
||||
if $eq dueCardsView 'all'
|
||||
i.fa.fa-users
|
||||
| {{_ 'dueCardsViewChange-choice-all'}}
|
||||
|
||||
template(name="dueCardsModalTitle")
|
||||
if currentUser
|
||||
h2
|
||||
i.fa.fa-keyboard-o
|
||||
| {{_ 'dueCards-title'}}
|
||||
|
||||
template(name="dueCards")
|
||||
if currentUser
|
||||
if isPageReady.get
|
||||
.wrapper
|
||||
.due-cards-dueat-list-wrapper
|
||||
each card in dueCardsList
|
||||
+resultCard(card)
|
||||
else
|
||||
+spinner
|
||||
|
||||
template(name="dueCardsViewChangePopup")
|
||||
if currentUser
|
||||
ul.pop-over-list
|
||||
li
|
||||
with "dueCardsViewChange-choice-me"
|
||||
a.js-due-cards-view-me
|
||||
i.fa.fa-user.colorful
|
||||
| {{_ 'dueCardsViewChange-choice-me'}}
|
||||
if $eq Utils.dueCardsView "me"
|
||||
i.fa.fa-check
|
||||
hr
|
||||
li
|
||||
with "dueCardsViewChange-choice-all"
|
||||
a.js-due-cards-view-all
|
||||
i.fa.fa-users.colorful
|
||||
| {{_ 'dueCardsViewChange-choice-all'}}
|
||||
span.sub-name
|
||||
+viewer
|
||||
| {{_ 'dueCardsViewChange-choice-all-description' }}
|
||||
if $eq Utils.dueCardsView "all"
|
||||
i.fa.fa-check
|
||||
@@ -0,0 +1,154 @@
|
||||
const subManager = new SubsManager();
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
dueCardsView() {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('sort:', Utils.dueCardsView());
|
||||
return Utils.dueCardsView();
|
||||
},
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-due-cards-view-change': Popup.open('dueCardsViewChange'),
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('dueCardsHeaderBar');
|
||||
|
||||
Template.dueCards.helpers({
|
||||
userId() {
|
||||
return Meteor.userId();
|
||||
},
|
||||
});
|
||||
|
||||
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('dueCardsViewChangePopup');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.isPageReady = new ReactiveVar(false);
|
||||
|
||||
this.autorun(() => {
|
||||
const handle = subManager.subscribe(
|
||||
'dueCards',
|
||||
Utils.dueCardsView() === 'all',
|
||||
);
|
||||
Tracker.nonreactive(() => {
|
||||
Tracker.autorun(() => {
|
||||
this.isPageReady.set(handle.ready());
|
||||
});
|
||||
});
|
||||
});
|
||||
Meteor.subscribe('setting');
|
||||
},
|
||||
|
||||
dueCardsView() {
|
||||
// eslint-disable-next-line no-console
|
||||
//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 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;
|
||||
|
||||
if (x > y) return 1;
|
||||
else if (x < y) return -1;
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('cards:', cards);
|
||||
return cards;
|
||||
},
|
||||
}).register('dueCards');
|
||||
@@ -0,0 +1,4 @@
|
||||
.due-cards-dueat-list-wrapper
|
||||
max-width: 500px
|
||||
margin-right: auto
|
||||
margin-left: auto
|
||||
Executable → Regular
+32
-2
@@ -91,6 +91,7 @@ Template.editor.onRendered(() => {
|
||||
};
|
||||
const editor = '.editor';
|
||||
const selectors = [
|
||||
`.js-new-description-form ${editor}`,
|
||||
`.js-new-comment-form ${editor}`,
|
||||
`.js-edit-comment ${editor}`,
|
||||
].join(','); // only new comment and edit comment
|
||||
@@ -264,6 +265,34 @@ Template.editor.onRendered(() => {
|
||||
|
||||
import sanitizeXss from 'xss';
|
||||
|
||||
// Additional safeAttrValue function to allow for other specific protocols
|
||||
// See https://github.com/leizongmin/js-xss/issues/52#issuecomment-241354114
|
||||
function mySafeAttrValue(tag, name, value, cssFilter) {
|
||||
// only when the tag is 'a' and attribute is 'href'
|
||||
// then use your custom function
|
||||
if (tag === 'a' && name === 'href') {
|
||||
// only filter the value if starts with 'cbthunderlink:' or 'aodroplink'
|
||||
if (
|
||||
/^thunderlink:/gi.test(value) ||
|
||||
/^cbthunderlink:/gi.test(value) ||
|
||||
/^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;
|
||||
} else {
|
||||
// use the default safeAttrValue function to process all non cbthunderlinks
|
||||
return sanitizeXss.safeAttrValue(tag, name, value, cssFilter);
|
||||
}
|
||||
} else {
|
||||
// use the default safeAttrValue function to process it
|
||||
return sanitizeXss.safeAttrValue(tag, name, value, cssFilter);
|
||||
}
|
||||
}
|
||||
|
||||
// XXX I believe we should compute a HTML rendered field on the server that
|
||||
// would handle markdown and user mentions. We can simply have two
|
||||
// fields, one source, and one compiled version (in HTML) and send only the
|
||||
@@ -277,7 +306,8 @@ Blaze.Template.registerHelper(
|
||||
const view = this;
|
||||
let content = Blaze.toHTML(view.templateContentBlock);
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
if (!currentBoard) return HTML.Raw(sanitizeXss(content));
|
||||
if (!currentBoard)
|
||||
return HTML.Raw(sanitizeXss(content, { safeAttrValue: mySafeAttrValue }));
|
||||
const knowedUsers = currentBoard.members.map(member => {
|
||||
const u = Users.findOne(member.userId);
|
||||
if (u) {
|
||||
@@ -321,7 +351,7 @@ Blaze.Template.registerHelper(
|
||||
content = content.replace(fullMention, Blaze.toHTML(link));
|
||||
}
|
||||
|
||||
return HTML.Raw(sanitizeXss(content));
|
||||
return HTML.Raw(sanitizeXss(content, { safeAttrValue: mySafeAttrValue }));
|
||||
}),
|
||||
);
|
||||
|
||||
|
||||
@@ -0,0 +1,96 @@
|
||||
template(name="globalSearchHeaderBar")
|
||||
if currentUser
|
||||
h1
|
||||
i.fa.fa-search
|
||||
| {{_ 'globalSearch-title'}}
|
||||
|
||||
template(name="globalSearchModalTitle")
|
||||
if currentUser
|
||||
h2
|
||||
i.fa.fa-keyboard-o
|
||||
| {{_ 'globalSearch-title'}}
|
||||
|
||||
template(name="globalSearch")
|
||||
if currentUser
|
||||
.wrapper
|
||||
form.global-search-page.js-search-query-form
|
||||
input.global-search-query-input(
|
||||
id="global-search-input"
|
||||
type="text"
|
||||
name="searchQuery"
|
||||
placeholder="{{_ 'search-example'}}"
|
||||
value="{{ query.get }}"
|
||||
autofocus dir="auto"
|
||||
)
|
||||
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
|
||||
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' }}
|
||||
else
|
||||
.global-search-page
|
||||
.global-search-help
|
||||
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' }}
|
||||
.lists-wrapper
|
||||
each name in myLabelNames.get
|
||||
span.card-label.list-title.js-label-name
|
||||
= name
|
||||
.global-search-instructions
|
||||
+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
|
||||
@@ -0,0 +1,743 @@
|
||||
const subManager = new SubsManager();
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-due-cards-view-change': Popup.open('globalSearchViewChange'),
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('globalSearchHeaderBar');
|
||||
|
||||
Template.globalSearch.helpers({
|
||||
userId() {
|
||||
return Meteor.userId();
|
||||
},
|
||||
});
|
||||
|
||||
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({
|
||||
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.myLists = new ReactiveVar([]);
|
||||
this.myLabelNames = new ReactiveVar([]);
|
||||
this.myBoardNames = new ReactiveVar([]);
|
||||
this.results = new ReactiveVar([]);
|
||||
this.hasNextPage = new ReactiveVar(false);
|
||||
this.hasPreviousPage = new ReactiveVar(false);
|
||||
this.queryParams = null;
|
||||
this.parsingErrors = [];
|
||||
this.resultsCount = 0;
|
||||
this.totalHits = 0;
|
||||
this.queryErrors = null;
|
||||
this.colorMap = null;
|
||||
this.resultsPerPage = 25;
|
||||
|
||||
Meteor.call('myLists', (err, data) => {
|
||||
if (!err) {
|
||||
this.myLists.set(data);
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.call('myLabelNames', (err, data) => {
|
||||
if (!err) {
|
||||
this.myLabelNames.set(data);
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.call('myBoardNames', (err, data) => {
|
||||
if (!err) {
|
||||
this.myBoardNames.set(data);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
onRendered() {
|
||||
Meteor.subscribe('setting');
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
//console.log('lang:', TAPi18n.getLanguage());
|
||||
this.colorMap = Boards.colorMap();
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('colorMap:', this.colorMap);
|
||||
|
||||
if (Session.get('globalQuery')) {
|
||||
this.searchAllBoards(Session.get('globalQuery'));
|
||||
}
|
||||
},
|
||||
|
||||
resetSearch() {
|
||||
this.searching.set(false);
|
||||
this.results.set([]);
|
||||
this.hasResults.set(false);
|
||||
this.hasQueryErrors.set(false);
|
||||
this.resultsHeading.set('');
|
||||
this.parsingErrors = [];
|
||||
this.resultsCount = 0;
|
||||
this.totalHits = 0;
|
||||
this.queryErrors = null;
|
||||
},
|
||||
|
||||
getSessionData() {
|
||||
return SessionData.findOne({
|
||||
userId: Meteor.userId(),
|
||||
sessionId: SessionData.getSessionId(),
|
||||
});
|
||||
},
|
||||
|
||||
getResults() {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('getting results');
|
||||
if (this.queryParams) {
|
||||
const sessionData = this.getSessionData();
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('selector:', sessionData.getSelector());
|
||||
// console.log('session data:', sessionData);
|
||||
const projection = sessionData.getProjection();
|
||||
projection.skip = 0;
|
||||
const cards = Cards.find({ _id: { $in: sessionData.cards } }, projection);
|
||||
this.queryErrors = sessionData.errors;
|
||||
if (this.queryErrors.length) {
|
||||
this.hasQueryErrors.set(true);
|
||||
return null;
|
||||
}
|
||||
|
||||
if (cards) {
|
||||
this.totalHits = sessionData.totalHits;
|
||||
this.resultsCount = cards.count();
|
||||
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,
|
||||
);
|
||||
}
|
||||
}
|
||||
this.resultsCount = 0;
|
||||
return null;
|
||||
},
|
||||
|
||||
errorMessages() {
|
||||
if (this.parsingErrors.length) {
|
||||
return this.parsingErrorMessages();
|
||||
}
|
||||
return this.queryErrorMessages();
|
||||
},
|
||||
|
||||
parsingErrorMessages() {
|
||||
const messages = [];
|
||||
|
||||
if (this.parsingErrors.length) {
|
||||
this.parsingErrors.forEach(err => {
|
||||
messages.push(TAPi18n.__(err.tag, err.value));
|
||||
});
|
||||
}
|
||||
|
||||
return messages;
|
||||
},
|
||||
|
||||
queryErrorMessages() {
|
||||
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;
|
||||
},
|
||||
|
||||
searchAllBoards(query) {
|
||||
query = query.trim();
|
||||
// eslint-disable-next-line no-console
|
||||
//console.log('query:', query);
|
||||
|
||||
this.query.set(query);
|
||||
|
||||
this.resetSearch();
|
||||
|
||||
if (!query) {
|
||||
return;
|
||||
}
|
||||
|
||||
this.searching.set(true);
|
||||
|
||||
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': 'boards',
|
||||
'operator-board-abbrev': 'boards',
|
||||
'operator-swimlane': 'swimlanes',
|
||||
'operator-swimlane-abbrev': 'swimlanes',
|
||||
'operator-list': 'lists',
|
||||
'operator-list-abbrev': 'lists',
|
||||
'operator-label': 'labels',
|
||||
'operator-label-abbrev': 'labels',
|
||||
'operator-user': 'users',
|
||||
'operator-user-abbrev': 'users',
|
||||
'operator-member': 'members',
|
||||
'operator-member-abbrev': 'members',
|
||||
'operator-assignee': 'assignees',
|
||||
'operator-assignee-abbrev': 'assignees',
|
||||
'operator-status': 'status',
|
||||
'operator-due': 'dueAt',
|
||||
'operator-created': 'createdAt',
|
||||
'operator-modified': 'modifiedAt',
|
||||
'operator-comment': 'comments',
|
||||
'operator-has': 'has',
|
||||
'operator-sort': 'sort',
|
||||
'operator-limit': 'limit',
|
||||
};
|
||||
|
||||
const predicates = {
|
||||
due: {
|
||||
'predicate-overdue': 'overdue',
|
||||
},
|
||||
durations: {
|
||||
'predicate-week': 'week',
|
||||
'predicate-month': 'month',
|
||||
'predicate-quarter': 'quarter',
|
||||
'predicate-year': 'year',
|
||||
},
|
||||
status: {
|
||||
'predicate-archived': 'archived',
|
||||
'predicate-all': 'all',
|
||||
'predicate-open': 'open',
|
||||
'predicate-ended': 'ended',
|
||||
'predicate-public': 'public',
|
||||
'predicate-private': 'private',
|
||||
},
|
||||
sorts: {
|
||||
'predicate-due': 'dueAt',
|
||||
'predicate-created': 'createdAt',
|
||||
'predicate-modified': 'modifiedAt',
|
||||
},
|
||||
has: {
|
||||
'predicate-description': 'description',
|
||||
'predicate-checklist': 'checklist',
|
||||
'predicate-attachment': 'attachment',
|
||||
'predicate-start': 'startAt',
|
||||
'predicate-end': 'endAt',
|
||||
'predicate-due': 'dueAt',
|
||||
'predicate-assignee': 'assignees',
|
||||
'predicate-member': '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);
|
||||
|
||||
const params = {
|
||||
limit: this.resultsPerPage,
|
||||
boards: [],
|
||||
swimlanes: [],
|
||||
lists: [],
|
||||
users: [],
|
||||
members: [],
|
||||
assignees: [],
|
||||
labels: [],
|
||||
status: [],
|
||||
dueAt: null,
|
||||
createdAt: null,
|
||||
modifiedAt: null,
|
||||
comments: [],
|
||||
has: [],
|
||||
};
|
||||
|
||||
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.toLowerCase();
|
||||
}
|
||||
// eslint-disable-next-line no-prototype-builtins
|
||||
if (operatorMap.hasOwnProperty(op)) {
|
||||
const operator = operatorMap[op];
|
||||
let value = m.groups.value;
|
||||
if (operator === 'labels') {
|
||||
if (value in this.colorMap) {
|
||||
value = this.colorMap[value];
|
||||
// console.log('found color:', value);
|
||||
}
|
||||
} else if (['dueAt', 'createdAt', 'modifiedAt'].includes(operator)) {
|
||||
let 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 'week':
|
||||
let week = moment().week();
|
||||
if (week === 52) {
|
||||
date = moment(1, 'W');
|
||||
date.set('year', date.year() + 1);
|
||||
} else {
|
||||
date = moment(week + 1, 'W');
|
||||
}
|
||||
break;
|
||||
case 'month':
|
||||
let 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 'quarter':
|
||||
let quarter = moment().quarter();
|
||||
if (quarter === 4) {
|
||||
date = moment(1, 'Q');
|
||||
date.set('year', date.year() + 1);
|
||||
} else {
|
||||
date = moment(quarter + 1, 'Q');
|
||||
}
|
||||
break;
|
||||
case 'year':
|
||||
date = moment(moment().year() + 1, 'YYYY');
|
||||
break;
|
||||
}
|
||||
if (date) {
|
||||
value = {
|
||||
operator: '$lt',
|
||||
value: date.format('YYYY-MM-DD'),
|
||||
};
|
||||
}
|
||||
} else if (operator === 'dueAt' && value === 'overdue') {
|
||||
value = {
|
||||
operator: '$lt',
|
||||
value: moment().format('YYYY-MM-DD'),
|
||||
};
|
||||
} else {
|
||||
this.parsingErrors.push({
|
||||
tag: 'operator-number-expected',
|
||||
value: { operator: op, value },
|
||||
});
|
||||
value = null;
|
||||
}
|
||||
} else {
|
||||
if (operator === 'dueAt') {
|
||||
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 === 'sort') {
|
||||
let negated = false;
|
||||
const m = value.match(reNegatedOperator);
|
||||
if (m) {
|
||||
value = m.groups.operator;
|
||||
negated = true;
|
||||
}
|
||||
if (!predicateTranslations.sorts[value]) {
|
||||
this.parsingErrors.push({
|
||||
tag: 'operator-sort-invalid',
|
||||
value,
|
||||
});
|
||||
} else {
|
||||
value = {
|
||||
name: predicateTranslations.sorts[value],
|
||||
order: negated ? 'des' : 'asc',
|
||||
};
|
||||
}
|
||||
} else if (operator === 'status') {
|
||||
if (!predicateTranslations.status[value]) {
|
||||
this.parsingErrors.push({
|
||||
tag: 'operator-status-invalid',
|
||||
value,
|
||||
});
|
||||
} else {
|
||||
value = predicateTranslations.status[value];
|
||||
}
|
||||
} else if (operator === 'has') {
|
||||
let negated = false;
|
||||
const m = value.match(reNegatedOperator);
|
||||
if (m) {
|
||||
value = m.groups.operator;
|
||||
negated = true;
|
||||
}
|
||||
if (!predicateTranslations.has[value]) {
|
||||
this.parsingErrors.push({
|
||||
tag: 'operator-has-invalid',
|
||||
value,
|
||||
});
|
||||
} else {
|
||||
value = {
|
||||
field: predicateTranslations.has[value],
|
||||
exists: !negated,
|
||||
};
|
||||
}
|
||||
} else if (operator === 'limit') {
|
||||
const limit = parseInt(value, 10);
|
||||
if (isNaN(limit) || limit < 1) {
|
||||
this.parsingErrors.push({
|
||||
tag: 'operator-limit-invalid',
|
||||
value,
|
||||
});
|
||||
} else {
|
||||
value = limit;
|
||||
}
|
||||
}
|
||||
if (Array.isArray(params[operator])) {
|
||||
params[operator].push(value);
|
||||
} else {
|
||||
params[operator] = value;
|
||||
}
|
||||
} else {
|
||||
this.parsingErrors.push({
|
||||
tag: 'operator-unknown-error',
|
||||
value: op,
|
||||
});
|
||||
}
|
||||
continue;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
// 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;
|
||||
|
||||
if (this.parsingErrors.length) {
|
||||
this.searching.set(false);
|
||||
this.queryErrors = this.parsingErrorMessages();
|
||||
this.hasResults.set(true);
|
||||
this.hasQueryErrors.set(true);
|
||||
return;
|
||||
}
|
||||
|
||||
this.autorun(() => {
|
||||
const handle = Meteor.subscribe(
|
||||
'globalSearch',
|
||||
SessionData.getSessionId(),
|
||||
params,
|
||||
);
|
||||
Tracker.nonreactive(() => {
|
||||
Tracker.autorun(() => {
|
||||
if (handle.ready()) {
|
||||
this.getResults();
|
||||
this.searching.set(false);
|
||||
this.hasResults.set(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
nextPage() {
|
||||
const sessionData = this.getSessionData();
|
||||
|
||||
this.autorun(() => {
|
||||
const handle = Meteor.subscribe('nextPage', sessionData.sessionId);
|
||||
Tracker.nonreactive(() => {
|
||||
Tracker.autorun(() => {
|
||||
if (handle.ready()) {
|
||||
this.getResults();
|
||||
this.searching.set(false);
|
||||
this.hasResults.set(true);
|
||||
}
|
||||
});
|
||||
});
|
||||
});
|
||||
},
|
||||
|
||||
previousPage() {
|
||||
const sessionData = this.getSessionData();
|
||||
|
||||
this.autorun(() => {
|
||||
const handle = Meteor.subscribe('previousPage', sessionData.sessionId);
|
||||
Tracker.nonreactive(() => {
|
||||
Tracker.autorun(() => {
|
||||
if (handle.ready()) {
|
||||
this.getResults();
|
||||
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: this.resultsStart,
|
||||
end: this.resultsEnd,
|
||||
total: this.totalHits,
|
||||
});
|
||||
},
|
||||
|
||||
getSearchHref() {
|
||||
const baseUrl = window.location.href.replace(/([?#].*$|\s*$)/, '');
|
||||
return `${baseUrl}?q=${encodeURIComponent(this.query.get())}`;
|
||||
},
|
||||
|
||||
searchInstructions() {
|
||||
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'),
|
||||
operator_user_abbrev: TAPi18n.__('operator-user-abbrev'),
|
||||
operator_member: TAPi18n.__('operator-member'),
|
||||
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'),
|
||||
};
|
||||
|
||||
let text = `# ${TAPi18n.__('globalSearch-instructions-heading')}`;
|
||||
text += `\n${TAPi18n.__('globalSearch-instructions-description', tags)}`;
|
||||
text += `\n\n${TAPi18n.__('globalSearch-instructions-operators', tags)}`;
|
||||
|
||||
[
|
||||
'globalSearch-instructions-operator-board',
|
||||
'globalSearch-instructions-operator-list',
|
||||
'globalSearch-instructions-operator-swimlane',
|
||||
'globalSearch-instructions-operator-comment',
|
||||
'globalSearch-instructions-operator-label',
|
||||
'globalSearch-instructions-operator-hash',
|
||||
'globalSearch-instructions-operator-user',
|
||||
'globalSearch-instructions-operator-at',
|
||||
'globalSearch-instructions-operator-member',
|
||||
'globalSearch-instructions-operator-assignee',
|
||||
'globalSearch-instructions-operator-due',
|
||||
'globalSearch-instructions-operator-created',
|
||||
'globalSearch-instructions-operator-modified',
|
||||
'globalSearch-instructions-operator-status',
|
||||
].forEach(instruction => {
|
||||
text += `\n* ${TAPi18n.__(instruction, tags)}`;
|
||||
});
|
||||
|
||||
[
|
||||
'globalSearch-instructions-status-archived',
|
||||
'globalSearch-instructions-status-public',
|
||||
'globalSearch-instructions-status-private',
|
||||
'globalSearch-instructions-status-all',
|
||||
'globalSearch-instructions-status-ended',
|
||||
].forEach(instruction => {
|
||||
text += `\n * ${TAPi18n.__(instruction, tags)}`;
|
||||
});
|
||||
|
||||
[
|
||||
'globalSearch-instructions-operator-has',
|
||||
'globalSearch-instructions-operator-sort',
|
||||
'globalSearch-instructions-operator-limit',
|
||||
].forEach(instruction => {
|
||||
text += `\n* ${TAPi18n.__(instruction, tags)}`;
|
||||
});
|
||||
|
||||
text += `\n## ${TAPi18n.__('heading-notes')}`;
|
||||
[
|
||||
'globalSearch-instructions-notes-1',
|
||||
'globalSearch-instructions-notes-2',
|
||||
'globalSearch-instructions-notes-3',
|
||||
'globalSearch-instructions-notes-3-2',
|
||||
'globalSearch-instructions-notes-4',
|
||||
'globalSearch-instructions-notes-5',
|
||||
].forEach(instruction => {
|
||||
text += `\n* ${TAPi18n.__(instruction, tags)}`;
|
||||
});
|
||||
|
||||
return text;
|
||||
},
|
||||
|
||||
labelColors() {
|
||||
return Boards.simpleSchema()._schema['labels.$.color'].allowedValues.map(
|
||||
color => {
|
||||
return { color, name: TAPi18n.__(`color-${color}`) };
|
||||
},
|
||||
);
|
||||
},
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'submit .js-search-query-form'(evt) {
|
||||
evt.preventDefault();
|
||||
this.searchAllBoards(evt.target.searchQuery.value);
|
||||
},
|
||||
'click .js-next-page'(evt) {
|
||||
evt.preventDefault();
|
||||
this.nextPage();
|
||||
},
|
||||
'click .js-previous-page'(evt) {
|
||||
evt.preventDefault();
|
||||
this.previousPage();
|
||||
},
|
||||
'click .js-label-color'(evt) {
|
||||
evt.preventDefault();
|
||||
const input = document.getElementById('global-search-input');
|
||||
this.query.set(
|
||||
`${input.value} ${TAPi18n.__('operator-label')}:"${
|
||||
evt.currentTarget.textContent
|
||||
}"`,
|
||||
);
|
||||
document.getElementById('global-search-input').focus();
|
||||
},
|
||||
'click .js-board-title'(evt) {
|
||||
evt.preventDefault();
|
||||
const input = document.getElementById('global-search-input');
|
||||
this.query.set(
|
||||
`${input.value} ${TAPi18n.__('operator-board')}:"${
|
||||
evt.currentTarget.textContent
|
||||
}"`,
|
||||
);
|
||||
document.getElementById('global-search-input').focus();
|
||||
},
|
||||
'click .js-list-title'(evt) {
|
||||
evt.preventDefault();
|
||||
const input = document.getElementById('global-search-input');
|
||||
this.query.set(
|
||||
`${input.value} ${TAPi18n.__('operator-list')}:"${
|
||||
evt.currentTarget.textContent
|
||||
}"`,
|
||||
);
|
||||
document.getElementById('global-search-input').focus();
|
||||
},
|
||||
'click .js-label-name'(evt) {
|
||||
evt.preventDefault();
|
||||
const input = document.getElementById('global-search-input');
|
||||
this.query.set(
|
||||
`${input.value} ${TAPi18n.__('operator-label')}:"${
|
||||
evt.currentTarget.textContent
|
||||
}"`,
|
||||
);
|
||||
document.getElementById('global-search-input').focus();
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('globalSearch');
|
||||
@@ -0,0 +1,121 @@
|
||||
.global-search-board-wrapper
|
||||
border-radius: 8px
|
||||
//padding: 0.5rem
|
||||
min-width: 400px
|
||||
border-width: 8px
|
||||
border-color: grey
|
||||
border-style: solid
|
||||
margin-bottom: 2rem
|
||||
margin-right: auto
|
||||
margin-left: auto
|
||||
|
||||
.global-search-board-title
|
||||
font-size: 1.4rem
|
||||
font-weight: bold
|
||||
padding: 0.5rem
|
||||
background-color: grey
|
||||
color: white
|
||||
|
||||
.global-search-swimlane-title
|
||||
font-size: 1.1rem
|
||||
font-weight: bold
|
||||
padding: 0.5rem
|
||||
padding-bottom: 0.4rem
|
||||
margin-top: 0
|
||||
margin-bottom: 0.5rem
|
||||
//border-top: black 1px solid
|
||||
//border-bottom: black 1px solid
|
||||
text-align: center
|
||||
|
||||
.swimlane-default-color
|
||||
background-color: lightgrey
|
||||
|
||||
.global-search-list-title
|
||||
font-weight: bold
|
||||
font-size: 1.1rem
|
||||
//padding-bottom: 0
|
||||
//margin-bottom: 0
|
||||
text-align: center
|
||||
margin-bottom: 0.7rem
|
||||
|
||||
.global-search-list-wrapper
|
||||
margin: 1rem
|
||||
border-radius: 5px
|
||||
padding: 1.5rem
|
||||
padding-top: 0.75rem
|
||||
display: inline-block
|
||||
min-width: 250px
|
||||
max-width: 350px
|
||||
|
||||
.global-search-card-wrapper
|
||||
margin-top: 0
|
||||
margin-bottom: 10px
|
||||
|
||||
.global-search-results-list-wrapper
|
||||
max-width: 500px
|
||||
margin-right: auto
|
||||
margin-left: auto
|
||||
|
||||
.global-search-field-name
|
||||
font-weight: bold
|
||||
|
||||
.global-search-context
|
||||
display: inline-block
|
||||
|
||||
.global-search-context-separator
|
||||
font-weight: bold
|
||||
|
||||
.global-search-context-list
|
||||
margin-bottom: 0.7rem
|
||||
|
||||
.global-search-error-messages
|
||||
color: darkred
|
||||
|
||||
.global-search-page
|
||||
width: 40%
|
||||
min-width: 400px
|
||||
margin-right: auto
|
||||
margin-left: auto
|
||||
line-height: 150%
|
||||
|
||||
.global-search-page h1
|
||||
margin-top: 2rem;
|
||||
|
||||
.global-search-page h2
|
||||
margin-top: 1rem;
|
||||
|
||||
.global-search-query-input
|
||||
width: 90% !important
|
||||
margin-right: auto
|
||||
margin-left: auto
|
||||
|
||||
.global-search-operator
|
||||
font-family: Courier
|
||||
|
||||
.global-search-value
|
||||
font-family: Courier
|
||||
font-style: italic
|
||||
|
||||
code
|
||||
color: black
|
||||
background-color: lightgrey
|
||||
padding: 0.1rem !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,38 +7,59 @@ 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
|
||||
ul
|
||||
li
|
||||
a(href="{{pathFor 'home'}}")
|
||||
span.fa.fa-home
|
||||
| {{_ 'all-boards'}}
|
||||
li.separator -
|
||||
li
|
||||
a(href="{{pathFor 'public'}}")
|
||||
span.fa.fa-globe
|
||||
| {{_ 'public'}}
|
||||
//-
|
||||
On sandstorm, the logo shouldn't be clickable, because we only have one
|
||||
page/document on it, and we don't want to see the home page containing
|
||||
the list of all boards.
|
||||
unless currentSetting.hideLogo
|
||||
if currentSetting.customTopLeftCornerLogoImageUrl
|
||||
if currentSetting.customTopLeftCornerLogoLinkUrl
|
||||
a(href="{{currentSetting.customTopLeftCornerLogoLinkUrl}}")
|
||||
img(src="{{currentSetting.customTopLeftCornerLogoImageUrl}}" height="{{#if currentSetting.customTopLeftCornerLogoHeight}}#{currentSetting.customTopLeftCornerLogoHeight}{{else}}27{{/if}}" width="auto" margin="0" padding="0")
|
||||
unless currentSetting.customTopLeftCornerLogoLinkUrl
|
||||
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="")
|
||||
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'}}
|
||||
|
||||
a#header-new-board-icon.js-create-board
|
||||
i.fa.fa-plus(title="Create a new board")
|
||||
// Next line is used only for spacing at header,
|
||||
// there is no visible clickable icon.
|
||||
#header-new-board-icon
|
||||
// Hide duplicate create board button,
|
||||
// because it did not show board templates correctly.
|
||||
//a#header-new-board-icon.js-create-board
|
||||
// i.fa.fa-plus(title="Create a new board")
|
||||
|
||||
+notifications
|
||||
|
||||
@@ -52,17 +73,6 @@ template(name="header")
|
||||
#header-main-bar(class="{{#if wrappedHeader}}wrapper{{/if}}")
|
||||
+Template.dynamic(template=headerBar)
|
||||
|
||||
//unless hideLogo
|
||||
|
||||
//-
|
||||
On sandstorm, the logo shouldn't be clickable, because we only have one
|
||||
page/document on it, and we don't want to see the home page containing
|
||||
the list of all boards.
|
||||
|
||||
// unless currentSetting.hideLogo
|
||||
// a.wekan-logo(href="{{pathFor 'home'}}" title="{{_ 'header-logo-title'}}")
|
||||
// img(src="{{pathFor '/logo-header.png'}}" alt="")
|
||||
|
||||
if appIsOffline
|
||||
+offlineWarning
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -19,6 +19,27 @@ head
|
||||
|
||||
template(name="userFormsLayout")
|
||||
section.auth-layout
|
||||
if currentSetting.hideLogo
|
||||
h1.at-form-landing-logo
|
||||
br
|
||||
br
|
||||
unless currentSetting.hideLogo
|
||||
h1.at-form-landing-logo
|
||||
if currentSetting.customLoginLogoImageUrl
|
||||
if currentSetting.customLoginLogoLinkUrl
|
||||
a(href="{{currentSetting.customLoginLogoLinkUrl}}")
|
||||
img(src="{{currentSetting.customLoginLogoImageUrl}}" width="300" height="auto")
|
||||
br
|
||||
unless currentSetting.customLoginLogoLinkUrl
|
||||
img(src="{{currentSetting.customLoginLogoImageUrl}}" width="300" height="auto")
|
||||
br
|
||||
unless currentSetting.customLoginLogoImageUrl
|
||||
img(src="{{pathFor '/wekan-logo.svg'}}" alt="" width="300" height="auto")
|
||||
br
|
||||
if currentSetting.textBelowCustomLoginLogo
|
||||
+viewer
|
||||
| {{currentSetting.textBelowCustomLoginLogo}}
|
||||
br
|
||||
section.auth-dialog
|
||||
if isLoading
|
||||
+loader
|
||||
|
||||
@@ -74,6 +74,24 @@ Template.userFormsLayout.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 === '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 === '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 === 'Español de Argentina') {
|
||||
@@ -84,20 +102,12 @@ Template.userFormsLayout.helpers({
|
||||
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 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 === '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 === 'oc') {
|
||||
name = 'Occitan';
|
||||
} else if (lang.name === 'st') {
|
||||
@@ -169,6 +179,19 @@ async function authentication(event, templateInstance) {
|
||||
});
|
||||
});
|
||||
|
||||
case 'saml':
|
||||
return new Promise(resolve => {
|
||||
const provider = Meteor.settings.public.SAML_PROVIDER;
|
||||
Meteor.loginWithSaml(
|
||||
{
|
||||
provider,
|
||||
},
|
||||
function() {
|
||||
resolve(FlowRouter.go('/'));
|
||||
},
|
||||
);
|
||||
});
|
||||
|
||||
case 'cas':
|
||||
return new Promise(resolve => {
|
||||
Meteor.loginWithCas(match, password, function() {
|
||||
|
||||
@@ -276,7 +276,7 @@ kbd
|
||||
padding-bottom: 0
|
||||
|
||||
.wrapper
|
||||
max-width: 1200px
|
||||
width: calc(100% - 20px)
|
||||
margin: 0 auto
|
||||
|
||||
.relative
|
||||
@@ -388,10 +388,12 @@ a
|
||||
ol
|
||||
list-style-type: decimal
|
||||
padding-left: 20px
|
||||
padding-bottom: 10px
|
||||
|
||||
ul
|
||||
list-style-type: initial
|
||||
padding-left: 20px
|
||||
padding-bottom: 10px
|
||||
|
||||
em
|
||||
font-style : italic
|
||||
@@ -447,7 +449,6 @@ a
|
||||
flex-direction: column
|
||||
align-items: center
|
||||
justify-content: center
|
||||
height: 100%
|
||||
|
||||
.auth-dialog
|
||||
margin: 0 !important
|
||||
|
||||
@@ -0,0 +1,73 @@
|
||||
template(name="myCardsHeaderBar")
|
||||
if currentUser
|
||||
h1
|
||||
//a.back-btn(href="{{pathFor 'home'}}")
|
||||
// i.fa.fa-chevron-left
|
||||
i.fa.fa-list
|
||||
| {{_ 'my-cards'}}
|
||||
|
||||
.board-header-btns.left
|
||||
a.board-header-btn.js-toggle-my-cards-choose-sort(title="{{_ 'myCardsSortChange-title'}}")
|
||||
i.fa.fa-caret-down
|
||||
if $eq myCardsSort 'board'
|
||||
i.fa.fa-th-large
|
||||
| {{_ 'myCardsSortChange-choice-board'}}
|
||||
if $eq myCardsSort 'dueAt'
|
||||
i.fa.fa-calendar
|
||||
| {{_ 'myCardsSortChange-choice-dueat'}}
|
||||
|
||||
template(name="myCardsModalTitle")
|
||||
if currentUser
|
||||
h2
|
||||
i.fa.fa-keyboard-o
|
||||
| {{_ 'my-cards'}}
|
||||
|
||||
template(name="myCards")
|
||||
if currentUser
|
||||
if isPageReady.get
|
||||
.wrapper
|
||||
if $eq myCardsSort 'board'
|
||||
each board in myCardsList
|
||||
.my-cards-board-wrapper
|
||||
.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
|
||||
= swimlane.title
|
||||
each list in swimlane.myLists
|
||||
.my-cards-list-wrapper
|
||||
.my-cards-list-title(class=list.colorClass)
|
||||
+viewer
|
||||
= list.title
|
||||
each card in list.myCards
|
||||
.my-cards-card-wrapper
|
||||
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
|
||||
ul.pop-over-list
|
||||
li
|
||||
with "my-cards-sort-board"
|
||||
a.js-my-cards-sort-board
|
||||
i.fa.fa-th-large.colorful
|
||||
| {{_ 'myCardsSortChange-choice-board'}}
|
||||
if $eq Utils.myCardsSort "board"
|
||||
i.fa.fa-check
|
||||
hr
|
||||
li
|
||||
with "my-cards-sort-dueat"
|
||||
a.js-my-cards-sort-dueat
|
||||
i.fa.fa-calendar.colorful
|
||||
| {{_ 'myCardsSortChange-choice-dueat'}}
|
||||
if $eq Utils.myCardsSort "dueAt"
|
||||
i.fa.fa-check
|
||||
@@ -0,0 +1,250 @@
|
||||
const subManager = new SubsManager();
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
myCardsSort() {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('sort:', Utils.myCardsSort());
|
||||
return Utils.myCardsSort();
|
||||
},
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-toggle-my-cards-choose-sort': Popup.open(
|
||||
'myCardsSortChange',
|
||||
),
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('myCardsHeaderBar');
|
||||
|
||||
Template.myCards.helpers({
|
||||
userId() {
|
||||
return Meteor.userId();
|
||||
},
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-my-cards-sort-board'() {
|
||||
Utils.setMyCardsSort('board');
|
||||
Popup.close();
|
||||
},
|
||||
|
||||
'click .js-my-cards-sort-dueat'() {
|
||||
Utils.setMyCardsSort('dueAt');
|
||||
Popup.close();
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('myCardsSortChangePopup');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.isPageReady = new ReactiveVar(false);
|
||||
|
||||
this.autorun(() => {
|
||||
const handle = subManager.subscribe('myCards');
|
||||
Tracker.nonreactive(() => {
|
||||
Tracker.autorun(() => {
|
||||
this.isPageReady.set(handle.ready());
|
||||
});
|
||||
});
|
||||
});
|
||||
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,
|
||||
},
|
||||
},
|
||||
);
|
||||
|
||||
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) {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('new list');
|
||||
list = card.getList();
|
||||
if (list.archived) {
|
||||
list = null;
|
||||
return;
|
||||
}
|
||||
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;
|
||||
}
|
||||
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;
|
||||
}
|
||||
// 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);
|
||||
}
|
||||
|
||||
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) => {
|
||||
return a.sort - b.sort;
|
||||
});
|
||||
});
|
||||
swimlane.myLists.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;
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('boards:', boards);
|
||||
return boards;
|
||||
},
|
||||
|
||||
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 cards = [];
|
||||
cursor.forEach(card => {
|
||||
if (
|
||||
!card.getBoard().archived &&
|
||||
!card.getSwimlane().archived &&
|
||||
!card.getList().archived
|
||||
) {
|
||||
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;
|
||||
|
||||
if (x > y) return 1;
|
||||
else if (x < y) return -1;
|
||||
|
||||
return 0;
|
||||
});
|
||||
|
||||
// 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');
|
||||
@@ -0,0 +1,57 @@
|
||||
.my-cards-board-wrapper
|
||||
border-radius: 0 0 4px 4px;
|
||||
//padding: 0.5rem
|
||||
min-width: 400px
|
||||
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
|
||||
padding: 0.5rem
|
||||
background-color: grey
|
||||
color: white
|
||||
|
||||
.my-cards-swimlane-title
|
||||
font-size: 1.1rem
|
||||
font-weight: bold
|
||||
padding: 0.5rem
|
||||
padding-bottom: 0.4rem
|
||||
margin-top: 0
|
||||
margin-bottom: 0.5rem
|
||||
//border-top: black 1px solid
|
||||
//border-bottom: black 1px solid
|
||||
text-align: center
|
||||
|
||||
.swimlane-default-color
|
||||
background-color: lightgrey
|
||||
|
||||
.my-cards-list-title
|
||||
font-weight: bold
|
||||
font-size: 1.1rem
|
||||
//padding-bottom: 0
|
||||
//margin-bottom: 0
|
||||
text-align: center
|
||||
margin-bottom: 0.7rem
|
||||
|
||||
.my-cards-list-wrapper
|
||||
margin: 1rem
|
||||
border-radius: 5px
|
||||
//padding: 1.5rem
|
||||
//padding-top: 0.75rem
|
||||
display: inline-grid
|
||||
min-width: 250px
|
||||
max-width: 350px
|
||||
|
||||
.my-cards-card-wrapper
|
||||
margin-top: 0
|
||||
margin-bottom: 10px
|
||||
|
||||
.my-cards-dueat-list-wrapper
|
||||
max-width: 500px
|
||||
margin-right: auto
|
||||
margin-left: auto
|
||||
@@ -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
|
||||
@@ -26,6 +26,10 @@ template(name='notificationIcon')
|
||||
i.fa.fa-code.activity-type(title="custom field")
|
||||
else if($in activityType 'addedLabel' 'removedLabel')
|
||||
i.fa.fa-tag.activity-type(title="label")
|
||||
else if($in activityType 'a-startAt' 'a-receivedAt')
|
||||
i.fa.fa-clock-o.activity-type(title="date")
|
||||
else if($in activityType 'a-dueAt' 'a-endAt')
|
||||
i.fa.fa-clock-o.activity-type(title="date")
|
||||
|
||||
else if($in activityType 'createList' 'removeList' 'archivedList')
|
||||
+listNotificationIcon
|
||||
|
||||
@@ -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.
@@ -3,32 +3,32 @@ template(name="cardActions")
|
||||
div.trigger-content
|
||||
div.trigger-dropdown
|
||||
select(id="setdate-action")
|
||||
option(value="setDate") {{{_'r-set'}}}
|
||||
option(value="updateDate") {{{_'r-update'}}}
|
||||
option(value="setDate") {{_'r-set'}}
|
||||
option(value="updateDate") {{_'r-update'}}
|
||||
div.trigger-text
|
||||
| {{{_'r-datefield'}}}
|
||||
| {{_'r-datefield'}}
|
||||
div.trigger-dropdown
|
||||
select(id="setdate-datefield")
|
||||
option(value="startAt") {{{_'r-df-start-at'}}}
|
||||
option(value="dueAt") {{{_'r-df-due-at'}}}
|
||||
option(value="endAt") {{{_'r-df-end-at'}}}
|
||||
option(value="receivedAt") {{{_'r-df-received-at'}}}
|
||||
option(value="startAt") {{_'r-df-start-at'}}
|
||||
option(value="dueAt") {{_'r-df-due-at'}}
|
||||
option(value="endAt") {{_'r-df-end-at'}}
|
||||
option(value="receivedAt") {{_'r-df-received-at'}}
|
||||
div.trigger-text
|
||||
| {{{_'r-to-current-datetime'}}}
|
||||
| {{_'r-to-current-datetime'}}
|
||||
div.trigger-button.js-set-date-action.js-goto-rules
|
||||
i.fa.fa-plus
|
||||
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| {{{_'r-remove-value-from'}}}
|
||||
| {{{_'r-datefield'}}}
|
||||
| {{_'r-remove-value-from'}}
|
||||
| {{_'r-datefield'}}
|
||||
div.trigger-dropdown
|
||||
select(id="setdate-removedatefieldvalue")
|
||||
option(value="startAt") {{{_'r-df-start-at'}}}
|
||||
option(value="dueAt") {{{_'r-df-due-at'}}}
|
||||
option(value="endAt") {{{_'r-df-end-at'}}}
|
||||
option(value="receivedAt") {{{_'r-df-received-at'}}}
|
||||
option(value="startAt") {{_'r-df-start-at'}}
|
||||
option(value="dueAt") {{_'r-df-due-at'}}
|
||||
option(value="endAt") {{_'r-df-end-at'}}
|
||||
option(value="receivedAt") {{_'r-df-received-at'}}
|
||||
div.trigger-button.js-remove-datevalue-action.js-goto-rules
|
||||
i.fa.fa-plus
|
||||
|
||||
@@ -36,10 +36,10 @@ template(name="cardActions")
|
||||
div.trigger-content
|
||||
div.trigger-dropdown
|
||||
select(id="label-action")
|
||||
option(value="add") {{{_'r-add'}}}
|
||||
option(value="remove") {{{_'r-remove'}}}
|
||||
option(value="add") {{_'r-add'}}
|
||||
option(value="remove") {{_'r-remove'}}
|
||||
div.trigger-text
|
||||
| {{{_'r-label'}}}
|
||||
| {{_'r-label'}}
|
||||
div.trigger-dropdown
|
||||
select(id="label-id")
|
||||
each labels
|
||||
@@ -52,26 +52,26 @@ template(name="cardActions")
|
||||
div.trigger-content
|
||||
div.trigger-dropdown
|
||||
select(id="member-action")
|
||||
option(value="add") {{{_'r-add'}}}
|
||||
option(value="remove") {{{_'r-remove'}}}
|
||||
option(value="add") {{_'r-add'}}
|
||||
option(value="remove") {{_'r-remove'}}
|
||||
div.trigger-text
|
||||
| {{{_'r-member'}}}
|
||||
| {{_'r-member'}}
|
||||
div.trigger-dropdown
|
||||
input(id="member-name",type=text,placeholder="{{{_'r-name'}}}")
|
||||
input(id="member-name",type=text,placeholder="{{_'r-name'}}")
|
||||
div.trigger-button.js-add-member-action.js-goto-rules
|
||||
i.fa.fa-plus
|
||||
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| {{{_'r-remove-all'}}}
|
||||
| {{_'r-remove-all'}}
|
||||
div.trigger-button.js-add-removeall-action.js-goto-rules
|
||||
i.fa.fa-plus
|
||||
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| {{{_'r-set-color'}}}
|
||||
| {{_'r-set-color'}}
|
||||
button.trigger-button.trigger-button-color.js-show-color-palette(
|
||||
id="color-action"
|
||||
class="card-details-{{cardColorButton}}")
|
||||
|
||||
@@ -3,12 +3,12 @@ template(name="checklistActions")
|
||||
div.trigger-content
|
||||
div.trigger-dropdown
|
||||
select(id="check-action")
|
||||
option(value="add") {{{_'r-add'}}}
|
||||
option(value="remove") {{{_'r-remove'}}}
|
||||
option(value="add") {{_'r-add'}}
|
||||
option(value="remove") {{_'r-remove'}}
|
||||
div.trigger-text
|
||||
| {{{_'r-checklist'}}}
|
||||
| {{_'r-checklist'}}
|
||||
div.trigger-dropdown
|
||||
input(id="checklist-name",type=text,placeholder="{{{_'r-name'}}}")
|
||||
input(id="checklist-name",type=text,placeholder="{{_'r-name'}}")
|
||||
div.trigger-button.js-add-checklist-action.js-goto-rules
|
||||
i.fa.fa-plus
|
||||
|
||||
@@ -16,12 +16,12 @@ template(name="checklistActions")
|
||||
div.trigger-content
|
||||
div.trigger-dropdown
|
||||
select(id="checkall-action")
|
||||
option(value="check") {{{_'r-check-all'}}}
|
||||
option(value="uncheck") {{{_'r-uncheck-all'}}}
|
||||
option(value="check") {{_'r-check-all'}}
|
||||
option(value="uncheck") {{_'r-uncheck-all'}}
|
||||
div.trigger-text
|
||||
| {{{_'r-items-check'}}}
|
||||
| {{_'r-items-check'}}
|
||||
div.trigger-dropdown
|
||||
input(id="checklist-name2",type=text,placeholder="{{{_'r-name'}}}")
|
||||
input(id="checklist-name2",type=text,placeholder="{{_'r-name'}}")
|
||||
div.trigger-button.js-add-checkall-action.js-goto-rules
|
||||
i.fa.fa-plus
|
||||
|
||||
@@ -30,36 +30,36 @@ template(name="checklistActions")
|
||||
div.trigger-content
|
||||
div.trigger-dropdown
|
||||
select(id="check-item-action")
|
||||
option(value="check") {{{_'r-check'}}}
|
||||
option(value="uncheck") {{{_'r-uncheck'}}}
|
||||
option(value="check") {{_'r-check'}}
|
||||
option(value="uncheck") {{_'r-uncheck'}}
|
||||
div.trigger-text
|
||||
| {{{_'r-item'}}}
|
||||
| {{_'r-item'}}
|
||||
div.trigger-dropdown
|
||||
input(id="checkitem-name",type=text,placeholder="{{{_'r-name'}}}")
|
||||
input(id="checkitem-name",type=text,placeholder="{{_'r-name'}}")
|
||||
div.trigger-text
|
||||
| {{{_'r-of-checklist'}}}
|
||||
| {{_'r-of-checklist'}}
|
||||
div.trigger-dropdown
|
||||
input(id="checklist-name3",type=text,placeholder="{{{_'r-name'}}}")
|
||||
input(id="checklist-name3",type=text,placeholder="{{_'r-name'}}")
|
||||
div.trigger-button.js-add-check-item-action.js-goto-rules
|
||||
i.fa.fa-plus
|
||||
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| {{{_'r-add-checklist'}}}
|
||||
| {{_'r-add-checklist'}}
|
||||
div.trigger-dropdown
|
||||
input(id="checklist-name-3",type=text,placeholder="{{{_'r-name'}}}")
|
||||
input(id="checklist-name-3",type=text,placeholder="{{_'r-name'}}")
|
||||
div.trigger-text
|
||||
| {{{_'r-with-items'}}}
|
||||
| {{_'r-with-items'}}
|
||||
div.trigger-dropdown
|
||||
input(id="checklist-items",type=text,placeholder="{{{_'r-items-list'}}}")
|
||||
input(id="checklist-items",type=text,placeholder="{{_'r-items-list'}}")
|
||||
div.trigger-button.js-add-checklist-items-action.js-goto-rules
|
||||
i.fa.fa-plus
|
||||
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| {{{_'r-checklist-note'}}}
|
||||
| {{_'r-checklist-note'}}
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@ template(name="ruleDetails")
|
||||
.rules
|
||||
h2
|
||||
i.fa.fa-magic
|
||||
| {{{_ 'r-rule-details' }}}
|
||||
| {{_ 'r-rule-details' }}
|
||||
.triggers-content
|
||||
.triggers-body
|
||||
.triggers-main-body
|
||||
@@ -21,4 +21,4 @@ template(name="ruleDetails")
|
||||
div.rules-back
|
||||
button.js-goback
|
||||
i.fa.fa-chevron-left
|
||||
| {{{_ 'back'}}}
|
||||
| {{_ 'back'}}
|
||||
@@ -2,10 +2,12 @@
|
||||
overflow:hidden
|
||||
overflow-y:scroll
|
||||
max-height: 400px
|
||||
padding-right: 5px
|
||||
.rules-lists-item
|
||||
display: block
|
||||
position: relative
|
||||
overflow: auto
|
||||
border-bottom: 1px solid #bfbfbf
|
||||
p
|
||||
display: inline-block
|
||||
float: left
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
template(name="rulesActions")
|
||||
h2
|
||||
i.fa.fa-magic
|
||||
| {{{_ 'r-rule' }}} "#{data.ruleName.get}" - {{{_ 'r-add-action'}}}
|
||||
| {{_ 'r-rule' }} "#{data.ruleName.get}" - {{_ 'r-add-action'}}
|
||||
.triggers-content
|
||||
.triggers-body
|
||||
.triggers-side-menu
|
||||
@@ -26,4 +26,4 @@ template(name="rulesActions")
|
||||
div.rules-back
|
||||
button.js-goback
|
||||
i.fa.fa-chevron-left
|
||||
| {{{_ 'back'}}}
|
||||
| {{_ 'back'}}
|
||||
@@ -2,7 +2,7 @@ template(name="rulesList")
|
||||
.rules
|
||||
h2
|
||||
i.fa.fa-magic
|
||||
| {{{_ 'r-board-rules' }}}
|
||||
| {{_ 'r-board-rules' }}
|
||||
|
||||
ul.rules-list
|
||||
each rules
|
||||
@@ -12,26 +12,26 @@ template(name="rulesList")
|
||||
div.rules-btns-group
|
||||
button.js-goto-details
|
||||
i.fa.fa-eye
|
||||
| {{{_ 'r-view-rule'}}}
|
||||
| {{_ 'r-view-rule'}}
|
||||
if currentUser.isAdmin
|
||||
button.js-delete-rule
|
||||
i.fa.fa-trash-o
|
||||
| {{{_ 'r-delete-rule'}}}
|
||||
| {{_ 'r-delete-rule'}}
|
||||
else if currentUser.isBoardAdmin
|
||||
button.js-delete-rule
|
||||
i.fa.fa-trash-o
|
||||
| {{{_ 'r-delete-rule'}}}
|
||||
| {{_ 'r-delete-rule'}}
|
||||
else
|
||||
li.no-items-message {{{_ 'r-no-rules' }}}
|
||||
li.no-items-message {{_ 'r-no-rules' }}
|
||||
if currentUser.isAdmin
|
||||
div.rules-add
|
||||
button.js-goto-trigger
|
||||
i.fa.fa-plus
|
||||
| {{{_ 'r-add-rule'}}}
|
||||
input(type=text,placeholder="{{{_ 'r-new-rule-name' }}}",id="ruleTitle")
|
||||
| {{_ 'r-add-rule'}}
|
||||
input(type=text,placeholder="{{_ 'r-new-rule-name' }}",id="ruleTitle")
|
||||
else if currentUser.isBoardAdmin
|
||||
div.rules-add
|
||||
button.js-goto-trigger
|
||||
i.fa.fa-plus
|
||||
| {{{_ 'r-add-rule'}}}
|
||||
input(type=text,placeholder="{{{_ 'r-new-rule-name' }}}",id="ruleTitle")
|
||||
| {{_ 'r-add-rule'}}
|
||||
input(type=text,placeholder="{{_ 'r-new-rule-name' }}",id="ruleTitle")
|
||||
@@ -1,7 +1,7 @@
|
||||
template(name="rulesTriggers")
|
||||
h2
|
||||
i.fa.fa-magic
|
||||
| {{{_ 'r-rule' }}} "#{data.ruleName.get}" - {{{_ 'r-add-trigger'}}}
|
||||
| {{_ 'r-rule' }} "#{data.ruleName.get}" - {{_ 'r-add-trigger'}}
|
||||
.triggers-content
|
||||
.triggers-body
|
||||
.triggers-side-menu
|
||||
@@ -22,4 +22,4 @@ template(name="rulesTriggers")
|
||||
div.rules-back
|
||||
button.js-goback
|
||||
i.fa.fa-chevron-left
|
||||
| {{{_ 'back'}}}
|
||||
| {{_ 'back'}}
|
||||
@@ -100,7 +100,7 @@ template(name="boardTriggers")
|
||||
div.trigger-item
|
||||
div.trigger-content
|
||||
div.trigger-text
|
||||
| {{{_'r-board-note'}}}
|
||||
| {{_'r-board-note'}}
|
||||
|
||||
template(name="boardCardTitlePopup")
|
||||
form
|
||||
@@ -109,8 +109,3 @@ template(name="boardCardTitlePopup")
|
||||
input.js-card-filter-name(type="text" value=title autofocus)
|
||||
input.js-card-filter-button.primary.wide(type="submit" value="{{_ 'set-filter'}}")
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
@@ -5,50 +5,199 @@ template(name="people")
|
||||
else
|
||||
.content-title.ext-box
|
||||
.ext-box-left
|
||||
span
|
||||
i.fa.fa-users
|
||||
| {{_ 'people'}}
|
||||
input#searchInput(placeholder="{{_ 'search'}}")
|
||||
button#searchButton
|
||||
i.fa.fa-search
|
||||
| {{_ 'search'}}
|
||||
.ext-box-right
|
||||
span {{_ 'people-number'}} #{peopleNumber}
|
||||
if loading.get
|
||||
+spinner
|
||||
else if orgSetting.get
|
||||
span
|
||||
i.fa.fa-sitemap
|
||||
unless isMiniScreen
|
||||
| {{_ 'organizations'}}
|
||||
input#searchOrgInput(placeholder="{{_ 'search'}}")
|
||||
button#searchOrgButton
|
||||
i.fa.fa-search
|
||||
| {{_ 'search'}}
|
||||
.ext-box-right
|
||||
span {{#unless isMiniScreen}}{{_ 'org-number'}}{{/unless}} #{orgNumber}
|
||||
else if teamSetting.get
|
||||
span
|
||||
i.fa.fa-users
|
||||
unless isMiniScreen
|
||||
| {{_ 'teams'}}
|
||||
input#searchTeamInput(placeholder="{{_ 'search'}}")
|
||||
button#searchTeamButton
|
||||
i.fa.fa-search
|
||||
| {{_ 'search'}}
|
||||
.ext-box-right
|
||||
span {{#unless isMiniScreen}}{{_ 'team-number'}}{{/unless}} #{teamNumber}
|
||||
else if peopleSetting.get
|
||||
span
|
||||
i.fa.fa-user
|
||||
unless isMiniScreen
|
||||
| {{_ 'people'}}
|
||||
input#searchInput(placeholder="{{_ 'search'}}")
|
||||
button#searchButton
|
||||
i.fa.fa-search
|
||||
| {{_ 'search'}}
|
||||
.ext-box-right
|
||||
span {{#unless isMiniScreen}}{{_ 'people-number'}}{{/unless}} #{peopleNumber}
|
||||
.content-body
|
||||
.side-menu
|
||||
ul
|
||||
li.active
|
||||
a.js-setting-menu(data-id="people-setting")
|
||||
a.js-org-menu(data-id="org-setting")
|
||||
i.fa.fa-sitemap
|
||||
| {{_ 'organizations'}}
|
||||
li
|
||||
a.js-team-menu(data-id="team-setting")
|
||||
i.fa.fa-users
|
||||
| {{_ 'teams'}}
|
||||
li
|
||||
a.js-people-menu(data-id="people-setting")
|
||||
i.fa.fa-user
|
||||
| {{_ 'people'}}
|
||||
.main-body
|
||||
if loading.get
|
||||
+spinner
|
||||
else if people.get
|
||||
else if orgSetting.get
|
||||
+orgGeneral
|
||||
else if teamSetting.get
|
||||
+teamGeneral
|
||||
else if peopleSetting.get
|
||||
+peopleGeneral
|
||||
|
||||
|
||||
template(name="orgGeneral")
|
||||
table
|
||||
tbody
|
||||
tr
|
||||
th {{_ 'displayName'}}
|
||||
th {{_ 'description'}}
|
||||
th {{_ 'shortName'}}
|
||||
th {{_ 'website'}}
|
||||
th {{_ 'createdAt'}}
|
||||
th {{_ 'active'}}
|
||||
th
|
||||
+newOrgRow
|
||||
each org in orgList
|
||||
+orgRow(orgId=org._id)
|
||||
|
||||
template(name="teamGeneral")
|
||||
table
|
||||
tbody
|
||||
tr
|
||||
th {{_ 'displayName'}}
|
||||
th {{_ 'description'}}
|
||||
th {{_ 'shortName'}}
|
||||
th {{_ 'website'}}
|
||||
th {{_ 'createdAt'}}
|
||||
th {{_ 'active'}}
|
||||
th
|
||||
+newTeamRow
|
||||
each team in teamList
|
||||
+teamRow(teamId=team._id)
|
||||
|
||||
template(name="peopleGeneral")
|
||||
table
|
||||
tbody
|
||||
tr
|
||||
th {{_ 'username'}}
|
||||
th {{_ 'fullname'}}
|
||||
th {{_ 'initials'}}
|
||||
th {{_ 'admin'}}
|
||||
th {{_ 'email'}}
|
||||
th {{_ 'verified'}}
|
||||
th {{_ 'createdAt'}}
|
||||
th {{_ 'active'}}
|
||||
th {{_ 'authentication-method'}}
|
||||
th {{_ 'import-usernames'}}
|
||||
th
|
||||
+newUserRow
|
||||
each user in peopleList
|
||||
+peopleRow(userId=user._id)
|
||||
|
||||
template(name="newOrgRow")
|
||||
a.new-org
|
||||
i.fa.fa-edit
|
||||
| {{_ 'new'}}
|
||||
|
||||
template(name="newTeamRow")
|
||||
a.new-team
|
||||
i.fa.fa-edit
|
||||
| {{_ 'new'}}
|
||||
|
||||
template(name="newUserRow")
|
||||
a.new-user
|
||||
i.fa.fa-edit
|
||||
| {{_ 'new'}}
|
||||
|
||||
template(name="orgRow")
|
||||
tr
|
||||
if orgData.loginDisabled
|
||||
td <s>{{ orgData.orgDisplayName }}</s>
|
||||
else
|
||||
td {{ orgData.orgDisplayName }}
|
||||
if orgData.loginDisabled
|
||||
td <s>{{ orgData.orgDesc }}</s>
|
||||
else
|
||||
td {{ orgData.orgDesc }}
|
||||
if orgData.loginDisabled
|
||||
td <s>{{ orgData.orgName }}</s>
|
||||
else
|
||||
td {{ orgData.orgName }}
|
||||
if orgData.loginDisabled
|
||||
td <s>{{ orgData.orgWebsite }}</s>
|
||||
else
|
||||
td {{ orgData.orgWebsite }}
|
||||
if orgData.loginDisabled
|
||||
td <s>{{ moment orgData.createdAt 'LLL' }}</s>
|
||||
else
|
||||
td {{ moment orgData.createdAt 'LLL' }}
|
||||
td
|
||||
if orgData.loginDisabled
|
||||
| {{_ 'no'}}
|
||||
else
|
||||
| {{_ 'yes'}}
|
||||
td
|
||||
a.edit-org
|
||||
i.fa.fa-edit
|
||||
| {{_ 'edit'}}
|
||||
a.more-settings-org
|
||||
i.fa.fa-ellipsis-h
|
||||
|
||||
template(name="teamRow")
|
||||
tr
|
||||
if teamData.loginDisabled
|
||||
td <s>{{ teamData.teamDisplayName }}</s>
|
||||
else
|
||||
td {{ teamData.teamDisplayName }}
|
||||
if teamData.loginDisabled
|
||||
td <s>{{ teamData.teamDesc }}</s>
|
||||
else
|
||||
td {{ teamData.teamDesc }}
|
||||
if teamData.loginDisabled
|
||||
td <s>{{ teamData.teamName }}</s>
|
||||
else
|
||||
td {{ teamData.teamName }}
|
||||
if teamData.loginDisabled
|
||||
td <s>{{ teamData.teamWebsite }}</s>
|
||||
else
|
||||
td {{ teamData.teamWebsite }}
|
||||
if orgData.loginDisabled
|
||||
td <s>{{ moment teamData.createdAt 'LLL' }}</s>
|
||||
else
|
||||
td {{ moment teamData.createdAt 'LLL' }}
|
||||
td
|
||||
if teamData.loginDisabled
|
||||
| {{_ 'no'}}
|
||||
else
|
||||
| {{_ 'yes'}}
|
||||
td
|
||||
a.edit-team
|
||||
i.fa.fa-edit
|
||||
| {{_ 'edit'}}
|
||||
a.more-settings-team
|
||||
i.fa.fa-ellipsis-h
|
||||
|
||||
template(name="peopleRow")
|
||||
tr
|
||||
if userData.loginDisabled
|
||||
@@ -59,6 +208,10 @@ template(name="peopleRow")
|
||||
td <s>{{ userData.profile.fullname }}</s>
|
||||
else
|
||||
td {{ userData.profile.fullname }}
|
||||
if userData.loginDisabled
|
||||
td <s>{{ userData.profile.initials }}</s>
|
||||
else
|
||||
td {{ userData.profile.initials }}
|
||||
if userData.loginDisabled
|
||||
td
|
||||
if userData.isAdmin
|
||||
@@ -100,17 +253,72 @@ 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
|
||||
| {{_ 'edit'}}
|
||||
a.more-settings-user
|
||||
i.fa.fa-ellipsis-h
|
||||
|
||||
template(name="editOrgPopup")
|
||||
form
|
||||
label.hide.orgId(type="text" value=org._id)
|
||||
label
|
||||
| {{_ 'displayName'}}
|
||||
input.js-orgDisplayName(type="text" value=org.displayName required)
|
||||
span.error.hide.orgname-taken
|
||||
| {{_ 'error-orgname-taken'}}
|
||||
label
|
||||
| {{_ 'description'}}
|
||||
input.js-orgDesc(type="text" value=org.orgDesc required)
|
||||
label
|
||||
| {{_ 'shortName'}}
|
||||
input.js-orgShortName(type="text" value=org.orgShortName required)
|
||||
label
|
||||
| {{_ 'website'}}
|
||||
input.js-orgWebsite(type="text" value=org.orgWebsite required)
|
||||
label
|
||||
| {{_ 'active'}}
|
||||
select.select-active.js-org-isactive
|
||||
option(value="false") {{_ 'yes'}}
|
||||
option(value="true" selected="{{org.loginDisabled}}") {{_ 'no'}}
|
||||
hr
|
||||
div.buttonsContainer
|
||||
input.primary.wide(type="submit" value="{{_ 'save'}}")
|
||||
|
||||
template(name="editTeamPopup")
|
||||
form
|
||||
label.hide.teamId(type="text" value=team._id)
|
||||
label
|
||||
| {{_ 'displayName'}}
|
||||
input.js-teamDisplayName(type="text" value=team.teamDisplayName required)
|
||||
span.error.hide.teamname-taken
|
||||
| {{_ 'error-teamname-taken'}}
|
||||
label
|
||||
| {{_ 'description'}}
|
||||
input.js-teamDesc(type="text" value=team.teamDesc required)
|
||||
label
|
||||
| {{_ 'shortName'}}
|
||||
input.js-teamShortName(type="text" value=team.teamShortName required)
|
||||
label
|
||||
| {{_ 'website'}}
|
||||
input.js-teamWebsite(type="text" value=team.teamWebsite required)
|
||||
label
|
||||
| {{_ 'active'}}
|
||||
select.select-active.js-team-isactive
|
||||
option(value="false") {{_ 'yes'}}
|
||||
option(value="true" selected="{{team.loginDisabled}}") {{_ 'no'}}
|
||||
hr
|
||||
div.buttonsContainer
|
||||
input.primary.wide(type="submit" value="{{_ 'save'}}")
|
||||
|
||||
template(name="editUserPopup")
|
||||
form
|
||||
label.hide.userId(type="text" value=user._id)
|
||||
label
|
||||
| {{_ 'fullname'}}
|
||||
input.js-profile-fullname(type="text" value=user.profile.fullname)
|
||||
label
|
||||
| {{_ 'username'}}
|
||||
span.error.hide.username-taken
|
||||
@@ -118,7 +326,18 @@ template(name="editUserPopup")
|
||||
if isLdap
|
||||
input.js-profile-username(type="text" value=user.username readonly)
|
||||
else
|
||||
input.js-profile-username(type="text" value=user.username)
|
||||
input.js-profile-username(type="text" value=user.username required)
|
||||
label
|
||||
| {{_ 'fullname'}}
|
||||
input.js-profile-fullname(type="text" value=user.profile.fullname required)
|
||||
label
|
||||
| {{_ 'initials'}}
|
||||
input.js-profile-initials(type="text" value=user.profile.initials required)
|
||||
label
|
||||
| {{_ 'admin'}}
|
||||
select.select-role.js-profile-isadmin
|
||||
option(value="false") {{_ 'no'}}
|
||||
option(value="true" selected="{{user.isAdmin}}") {{_ 'yes'}}
|
||||
label
|
||||
| {{_ 'email'}}
|
||||
span.error.hide.email-taken
|
||||
@@ -126,12 +345,15 @@ template(name="editUserPopup")
|
||||
if isLdap
|
||||
input.js-profile-email(type="email" value="{{user.emails.[0].address}}" readonly)
|
||||
else
|
||||
input.js-profile-email(type="email" value="{{user.emails.[0].address}}")
|
||||
input.js-profile-email(type="email" value="{{user.emails.[0].address}}" required)
|
||||
label
|
||||
| {{_ 'admin'}}
|
||||
select.select-role.js-profile-isadmin
|
||||
| {{_ 'import-usernames'}}
|
||||
input.js-import-usernames(type="text" value=user.importUsernames)
|
||||
label
|
||||
| {{_ 'verified'}}
|
||||
select.select-verified.js-profile-email-verified
|
||||
option(value="false") {{_ 'no'}}
|
||||
option(value="true" selected="{{user.isAdmin}}") {{_ 'yes'}}
|
||||
option(value="true" selected="{{userData.emails.[0].verified}}") {{_ 'yes'}}
|
||||
label
|
||||
| {{_ 'active'}}
|
||||
select.select-active.js-profile-isactive
|
||||
@@ -151,15 +373,61 @@ template(name="editUserPopup")
|
||||
input.js-profile-password(type="password")
|
||||
div.buttonsContainer
|
||||
input.primary.wide(type="submit" value="{{_ 'save'}}")
|
||||
// div
|
||||
// input#deleteButton.primary.wide(type="button" value="{{_ 'delete'}}")
|
||||
|
||||
template(name="newOrgPopup")
|
||||
form
|
||||
//label.hide.userId(type="text" value=user._id)
|
||||
label
|
||||
| {{_ 'displayName'}}
|
||||
input.js-orgDisplayName(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'description'}}
|
||||
input.js-orgDesc(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'shortName'}}
|
||||
input.js-orgName(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'website'}}
|
||||
input.js-orgWebsite(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'active'}}
|
||||
select.select-active.js-org-isactive
|
||||
option(value="false" selected="selected") {{_ 'yes'}}
|
||||
option(value="true") {{_ 'no'}}
|
||||
hr
|
||||
div.buttonsContainer
|
||||
input.primary.wide(type="submit" value="{{_ 'save'}}")
|
||||
|
||||
template(name="newTeamPopup")
|
||||
form
|
||||
//label.hide.teamId(type="text" value=team._id)
|
||||
label
|
||||
| {{_ 'displayName'}}
|
||||
input.js-teamDisplayName(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'description'}}
|
||||
input.js-teamDesc(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'shortName'}}
|
||||
input.js-teamName(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'website'}}
|
||||
input.js-teamWebsite(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'active'}}
|
||||
select.select-active.js-team-isactive
|
||||
option(value="false" selected="selected") {{_ 'yes'}}
|
||||
option(value="true") {{_ 'no'}}
|
||||
hr
|
||||
div.buttonsContainer
|
||||
input.primary.wide(type="submit" value="{{_ 'save'}}")
|
||||
|
||||
template(name="newUserPopup")
|
||||
form
|
||||
//label.hide.userId(type="text" value=user._id)
|
||||
label
|
||||
| {{_ 'fullname'}}
|
||||
input.js-profile-fullname(type="text" value="")
|
||||
input.js-profile-fullname(type="text" value="" required)
|
||||
label
|
||||
| {{_ 'username'}}
|
||||
span.error.hide.username-taken
|
||||
@@ -167,7 +435,10 @@ template(name="newUserPopup")
|
||||
//if isLdap
|
||||
// input.js-profile-username(type="text" value=user.username readonly)
|
||||
//else
|
||||
input.js-profile-username(type="text" value="")
|
||||
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
|
||||
@@ -175,7 +446,10 @@ template(name="newUserPopup")
|
||||
//if isLdap
|
||||
// input.js-profile-email(type="email" value="{{user.emails.[0].address}}" readonly)
|
||||
//else
|
||||
input.js-profile-email(type="email" value="")
|
||||
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
|
||||
@@ -197,6 +471,56 @@ template(name="newUserPopup")
|
||||
hr
|
||||
label
|
||||
| {{_ 'password'}}
|
||||
input.js-profile-password(type="password")
|
||||
input.js-profile-password(type="password" required)
|
||||
div.buttonsContainer
|
||||
input.primary.wide(type="submit" value="{{_ 'save'}}")
|
||||
|
||||
template(name="settingsOrgPopup")
|
||||
ul.pop-over-list
|
||||
li
|
||||
a.impersonate-org
|
||||
i.fa.fa-user
|
||||
| {{_ 'impersonate-org'}}
|
||||
// Delete is not enabled yet, because it does leave empty user avatars
|
||||
// to boards: boards members, card members and assignees have
|
||||
// empty users. See:
|
||||
// - wekan/client/components/settings/peopleBody.jade deleteButton
|
||||
// - wekan/client/components/settings/peopleBody.js deleteButton
|
||||
// - wekan/client/components/sidebar/sidebar.js Popup.afterConfirm('removeMember'
|
||||
// that does now remove member from board, card members and assignees correctly,
|
||||
// but that should be used to remove user from all boards similarly
|
||||
// - wekan/models/users.js Delete is not enabled
|
||||
//li
|
||||
// br
|
||||
// br
|
||||
// hr
|
||||
//li
|
||||
// form
|
||||
// label.hide.userId(type="text" value=user._id)
|
||||
// div.buttonsContainer
|
||||
// input#deleteButton.card-details-red.right.wide(type="button" value="{{_ 'delete'}}")
|
||||
|
||||
template(name="settingsUserPopup")
|
||||
ul.pop-over-list
|
||||
li
|
||||
a.impersonate-user
|
||||
i.fa.fa-user
|
||||
| {{_ 'impersonate-user'}}
|
||||
// Delete is not enabled yet, because it does leave empty user avatars
|
||||
// to boards: boards members, card members and assignees have
|
||||
// empty users. See:
|
||||
// - wekan/client/components/settings/peopleBody.jade deleteButton
|
||||
// - wekan/client/components/settings/peopleBody.js deleteButton
|
||||
// - wekan/client/components/sidebar/sidebar.js Popup.afterConfirm('removeMember'
|
||||
// that does now remove member from board, card members and assignees correctly,
|
||||
// but that should be used to remove user from all boards similarly
|
||||
// - wekan/models/users.js Delete is not enabled
|
||||
//li
|
||||
// br
|
||||
// br
|
||||
// hr
|
||||
//li
|
||||
// form
|
||||
// label.hide.userId(type="text" value=user._id)
|
||||
// div.buttonsContainer
|
||||
// input#deleteButton.card-details-red.right.wide(type="button" value="{{_ 'delete'}}")
|
||||
@@ -1,3 +1,5 @@
|
||||
const orgsPerPage = 25;
|
||||
const teamsPerPage = 25;
|
||||
const usersPerPage = 25;
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
@@ -7,17 +9,45 @@ BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.error = new ReactiveVar('');
|
||||
this.loading = new ReactiveVar(false);
|
||||
this.people = new ReactiveVar(true);
|
||||
this.orgSetting = new ReactiveVar(true);
|
||||
this.teamSetting = new ReactiveVar(true);
|
||||
this.peopleSetting = new ReactiveVar(true);
|
||||
this.findOrgsOptions = new ReactiveVar({});
|
||||
this.findTeamsOptions = new ReactiveVar({});
|
||||
this.findUsersOptions = new ReactiveVar({});
|
||||
this.number = new ReactiveVar(0);
|
||||
this.numberOrgs = new ReactiveVar(0);
|
||||
this.numberTeams = new ReactiveVar(0);
|
||||
this.numberPeople = new ReactiveVar(0);
|
||||
|
||||
this.page = new ReactiveVar(1);
|
||||
this.loadNextPageLocked = false;
|
||||
this.callFirstWith(null, 'resetNextPeak');
|
||||
this.autorun(() => {
|
||||
const limit = this.page.get() * usersPerPage;
|
||||
const limitOrgs = this.page.get() * orgsPerPage;
|
||||
const limitTeams = this.page.get() * teamsPerPage;
|
||||
const limitUsers = this.page.get() * usersPerPage;
|
||||
|
||||
this.subscribe('people', this.findUsersOptions.get(), limit, () => {
|
||||
this.subscribe('org', this.findOrgsOptions.get(), limitOrgs, () => {
|
||||
this.loadNextPageLocked = false;
|
||||
const nextPeakBefore = this.callFirstWith(null, 'getNextPeak');
|
||||
this.calculateNextPeak();
|
||||
const nextPeakAfter = this.callFirstWith(null, 'getNextPeak');
|
||||
if (nextPeakBefore === nextPeakAfter) {
|
||||
this.callFirstWith(null, 'resetNextPeak');
|
||||
}
|
||||
});
|
||||
|
||||
this.subscribe('team', this.findTeamsOptions.get(), limitTeams, () => {
|
||||
this.loadNextPageLocked = false;
|
||||
const nextPeakBefore = this.callFirstWith(null, 'getNextPeak');
|
||||
this.calculateNextPeak();
|
||||
const nextPeakAfter = this.callFirstWith(null, 'getNextPeak');
|
||||
if (nextPeakBefore === nextPeakAfter) {
|
||||
this.callFirstWith(null, 'resetNextPeak');
|
||||
}
|
||||
});
|
||||
|
||||
this.subscribe('people', this.findUsersOptions.get(), limitUsers, () => {
|
||||
this.loadNextPageLocked = false;
|
||||
const nextPeakBefore = this.callFirstWith(null, 'getNextPeak');
|
||||
this.calculateNextPeak();
|
||||
@@ -31,6 +61,22 @@ BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click #searchOrgButton'() {
|
||||
this.filterOrg();
|
||||
},
|
||||
'keydown #searchOrgInput'(event) {
|
||||
if (event.keyCode === 13 && !event.shiftKey) {
|
||||
this.filterOrg();
|
||||
}
|
||||
},
|
||||
'click #searchTeamButton'() {
|
||||
this.filterTeam();
|
||||
},
|
||||
'keydown #searchTeamInput'(event) {
|
||||
if (event.keyCode === 13 && !event.shiftKey) {
|
||||
this.filterTeam();
|
||||
}
|
||||
},
|
||||
'click #searchButton'() {
|
||||
this.filterPeople();
|
||||
},
|
||||
@@ -39,9 +85,18 @@ BlazeComponent.extendComponent({
|
||||
this.filterPeople();
|
||||
}
|
||||
},
|
||||
'click #newOrgButton'() {
|
||||
Popup.open('newOrg');
|
||||
},
|
||||
'click #newTeamButton'() {
|
||||
Popup.open('newTeam');
|
||||
},
|
||||
'click #newUserButton'() {
|
||||
Popup.open('newUser');
|
||||
},
|
||||
'click a.js-org-menu': this.switchMenu,
|
||||
'click a.js-team-menu': this.switchMenu,
|
||||
'click a.js-people-menu': this.switchMenu,
|
||||
},
|
||||
];
|
||||
},
|
||||
@@ -84,18 +139,63 @@ BlazeComponent.extendComponent({
|
||||
setLoading(w) {
|
||||
this.loading.set(w);
|
||||
},
|
||||
orgList() {
|
||||
const orgs = Org.find(this.findOrgsOptions.get(), {
|
||||
fields: { _id: true },
|
||||
});
|
||||
this.numberOrgs.set(orgs.count(false));
|
||||
return orgs;
|
||||
},
|
||||
teamList() {
|
||||
const teams = Team.find(this.findTeamsOptions.get(), {
|
||||
fields: { _id: true },
|
||||
});
|
||||
this.numberTeams.set(team.count(false));
|
||||
return teams;
|
||||
},
|
||||
peopleList() {
|
||||
const users = Users.find(this.findUsersOptions.get(), {
|
||||
fields: { _id: true },
|
||||
});
|
||||
this.number.set(users.count(false));
|
||||
this.numberPeople.set(users.count(false));
|
||||
return users;
|
||||
},
|
||||
orgNumber() {
|
||||
return this.numberOrgs.get();
|
||||
},
|
||||
teamNumber() {
|
||||
return this.numberTeams.get();
|
||||
},
|
||||
peopleNumber() {
|
||||
return this.number.get();
|
||||
return this.numberPeople.get();
|
||||
},
|
||||
switchMenu(event) {
|
||||
const target = $(event.target);
|
||||
if (!target.hasClass('active')) {
|
||||
$('.side-menu li.active').removeClass('active');
|
||||
target.parent().addClass('active');
|
||||
const targetID = target.data('id');
|
||||
this.orgSetting.set('org-setting' === targetID);
|
||||
this.teamSetting.set('team-setting' === targetID);
|
||||
this.peopleSetting.set('people-setting' === targetID);
|
||||
}
|
||||
},
|
||||
}).register('people');
|
||||
|
||||
Template.orgRow.helpers({
|
||||
orgData() {
|
||||
const orgCollection = this.esSearch ? ESSearchResults : Org;
|
||||
return orgCollection.findOne(this.orgId);
|
||||
},
|
||||
});
|
||||
|
||||
Template.teamRow.helpers({
|
||||
teamData() {
|
||||
const teamCollection = this.esSearch ? ESSearchResults : Team;
|
||||
return teamCollection.findOne(this.teamId);
|
||||
},
|
||||
});
|
||||
|
||||
Template.peopleRow.helpers({
|
||||
userData() {
|
||||
const userCollection = this.esSearch ? ESSearchResults : Users;
|
||||
@@ -122,6 +222,24 @@ Template.editUserPopup.onCreated(function() {
|
||||
});
|
||||
});
|
||||
|
||||
Template.editOrgPopup.helpers({
|
||||
org() {
|
||||
return Org.findOne(this.orgId);
|
||||
},
|
||||
errorMessage() {
|
||||
return Template.instance().errorMessage.get();
|
||||
},
|
||||
});
|
||||
|
||||
Template.editTeamPopup.helpers({
|
||||
team() {
|
||||
return Team.findOne(this.teamId);
|
||||
},
|
||||
errorMessage() {
|
||||
return Template.instance().errorMessage.get();
|
||||
},
|
||||
});
|
||||
|
||||
Template.editUserPopup.helpers({
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
@@ -144,6 +262,14 @@ Template.editUserPopup.helpers({
|
||||
},
|
||||
});
|
||||
|
||||
Template.newOrgPopup.onCreated(function() {
|
||||
this.errorMessage = new ReactiveVar('');
|
||||
});
|
||||
|
||||
Template.newTeamPopup.onCreated(function() {
|
||||
this.errorMessage = new ReactiveVar('');
|
||||
});
|
||||
|
||||
Template.newUserPopup.onCreated(function() {
|
||||
this.authenticationMethods = new ReactiveVar([]);
|
||||
this.errorMessage = new ReactiveVar('');
|
||||
@@ -163,28 +289,76 @@ Template.newUserPopup.onCreated(function() {
|
||||
});
|
||||
});
|
||||
|
||||
Template.newUserPopup.helpers({
|
||||
//user() {
|
||||
// return Users.findOne(this.userId);
|
||||
//},
|
||||
authentications() {
|
||||
return Template.instance().authenticationMethods.get();
|
||||
Template.newOrgPopup.helpers({
|
||||
org() {
|
||||
return Org.findOne(this.orgId);
|
||||
},
|
||||
//isSelected(match) {
|
||||
// const userId = Template.instance().data.userId;
|
||||
// const selected = Users.findOne(userId).authenticationMethod;
|
||||
// return selected === match;
|
||||
//},
|
||||
//isLdap() {
|
||||
// const userId = Template.instance().data.userId;
|
||||
// const selected = Users.findOne(userId).authenticationMethod;
|
||||
// return selected === 'ldap';
|
||||
//},
|
||||
errorMessage() {
|
||||
return Template.instance().errorMessage.get();
|
||||
},
|
||||
});
|
||||
|
||||
Template.newTeamPopup.helpers({
|
||||
team() {
|
||||
return Team.findOne(this.teamId);
|
||||
},
|
||||
errorMessage() {
|
||||
return Template.instance().errorMessage.get();
|
||||
},
|
||||
});
|
||||
|
||||
Template.newUserPopup.helpers({
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
},
|
||||
authentications() {
|
||||
return Template.instance().authenticationMethods.get();
|
||||
},
|
||||
isSelected(match) {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
return selected === match;
|
||||
},
|
||||
isLdap() {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
return selected === 'ldap';
|
||||
},
|
||||
errorMessage() {
|
||||
return Template.instance().errorMessage.get();
|
||||
},
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {},
|
||||
org() {
|
||||
return Org.findOne(this.orgId);
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click a.edit-org': Popup.open('editOrg'),
|
||||
'click a.more-settings-org': Popup.open('settingsOrg'),
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('orgRow');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {},
|
||||
team() {
|
||||
return Team.findOne(this.teamId);
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click a.edit-team': Popup.open('editTeam'),
|
||||
'click a.more-settings-team': Popup.open('settingsTeam'),
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('teamRow');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {},
|
||||
user() {
|
||||
@@ -194,11 +368,32 @@ BlazeComponent.extendComponent({
|
||||
return [
|
||||
{
|
||||
'click a.edit-user': Popup.open('editUser'),
|
||||
'click a.more-settings-user': Popup.open('settingsUser'),
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('peopleRow');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click a.new-org': Popup.open('newOrg'),
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('newOrgRow');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click a.new-team': Popup.open('newTeam'),
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('newTeamRow');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [
|
||||
@@ -209,24 +404,121 @@ 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();
|
||||
const user = Users.findOne(this.userId);
|
||||
const fullname = templateInstance.find('.js-profile-fullname').value.trim();
|
||||
const username = templateInstance.find('.js-profile-username').value.trim();
|
||||
const fullname = templateInstance.find('.js-profile-fullname').value.trim();
|
||||
const initials = templateInstance.find('.js-profile-initials').value.trim();
|
||||
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 verified = templateInstance
|
||||
.find('.js-profile-email-verified')
|
||||
.value.trim();
|
||||
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;
|
||||
const isChangeInitials = initials.length > 0;
|
||||
const isChangeEmailVerified = verified !== user.emails[0].verified;
|
||||
|
||||
// If previously email address has not been set, it is undefined,
|
||||
// check for undefined, and allow adding email address.
|
||||
const isChangeEmail =
|
||||
email.toLowerCase() !== user.emails[0].address.toLowerCase();
|
||||
email.toLowerCase() !==
|
||||
(typeof user.emails !== 'undefined'
|
||||
? user.emails[0].address.toLowerCase()
|
||||
: false);
|
||||
|
||||
Users.update(this.userId, {
|
||||
$set: {
|
||||
@@ -234,6 +526,7 @@ Template.editUserPopup.events({
|
||||
isAdmin: isAdmin === 'true',
|
||||
loginDisabled: isActive === 'true',
|
||||
authenticationMethod: authentication,
|
||||
importUsernames: Users.parseImportUsernames(importUsernames),
|
||||
},
|
||||
});
|
||||
|
||||
@@ -241,6 +534,14 @@ Template.editUserPopup.events({
|
||||
Meteor.call('setPassword', password, this.userId);
|
||||
}
|
||||
|
||||
if (isChangeEmailVerified) {
|
||||
Meteor.call('setEmailVerified', email, verified === 'true', this.userId);
|
||||
}
|
||||
|
||||
if (isChangeInitials) {
|
||||
Meteor.call('setInitials', initials, this.userId);
|
||||
}
|
||||
|
||||
if (isChangeUserName && isChangeEmail) {
|
||||
Meteor.call(
|
||||
'setUsernameAndEmail',
|
||||
@@ -296,11 +597,56 @@ Template.editUserPopup.events({
|
||||
});
|
||||
} else Popup.close();
|
||||
},
|
||||
});
|
||||
|
||||
'click #deleteButton': Popup.afterConfirm('userDelete', function() {
|
||||
Users.remove(this.userId);
|
||||
Template.newOrgPopup.events({
|
||||
submit(event, templateInstance) {
|
||||
event.preventDefault();
|
||||
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',
|
||||
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();
|
||||
},
|
||||
});
|
||||
|
||||
Template.newUserPopup.events({
|
||||
@@ -308,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');
|
||||
@@ -343,3 +695,70 @@ Template.newUserPopup.events({
|
||||
Popup.close();
|
||||
},
|
||||
});
|
||||
|
||||
Template.settingsUserPopup.events({
|
||||
'click .impersonate-user'(event) {
|
||||
event.preventDefault();
|
||||
|
||||
Meteor.call('impersonate', this.userId, err => {
|
||||
if (!err) {
|
||||
FlowRouter.go('/');
|
||||
Meteor.connection.setUserId(this.userId);
|
||||
}
|
||||
});
|
||||
},
|
||||
'click #deleteButton'(event) {
|
||||
event.preventDefault();
|
||||
/*
|
||||
// Delete is not enabled yet, because it does leave empty user avatars
|
||||
// to boards: boards members, card members and assignees have
|
||||
// empty users. See:
|
||||
// - wekan/client/components/settings/peopleBody.jade deleteButton
|
||||
// - wekan/client/components/settings/peopleBody.js deleteButton
|
||||
// - wekan/client/components/sidebar/sidebar.js Popup.afterConfirm('removeMember'
|
||||
// that does now remove member from board, card members and assignees correctly,
|
||||
// but that should be used to remove user from all boards similarly
|
||||
// - wekan/models/users.js Delete is not enabled
|
||||
//
|
||||
//console.log('user id: ' + this.userId);
|
||||
//Popup.afterConfirm('userDelete', function(event) {
|
||||
//Boards.find({ members: this.userId }).forEach(board => {
|
||||
// console.log('board id: ' + board._id);
|
||||
//Cards.find({ boardId: board._id, members: this.userId }).forEach(card => {
|
||||
// card.unassignMember(this.userId);
|
||||
//});
|
||||
//Cards.find({ boardId: board._id, members: this.userId }).forEach(card => {
|
||||
// card.unassignMember(this.userId);
|
||||
//});
|
||||
//Cards.find({ boardId: board._id, assignees: this.userId }).forEach(card => {
|
||||
// card.unassignAssignee(this.userId);
|
||||
//});
|
||||
//Boards.findOne({ boardId: board._id }).removeMember(this.userId);
|
||||
//});
|
||||
//Users.remove(this.userId);
|
||||
*/
|
||||
Popup.close();
|
||||
},
|
||||
});
|
||||
|
||||
Template.settingsUserPopup.helpers({
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
},
|
||||
authentications() {
|
||||
return Template.instance().authenticationMethods.get();
|
||||
},
|
||||
isSelected(match) {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
return selected === match;
|
||||
},
|
||||
isLdap() {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
return selected === 'ldap';
|
||||
},
|
||||
errorMessage() {
|
||||
return Template.instance().errorMessage.get();
|
||||
},
|
||||
});
|
||||
@@ -21,7 +21,7 @@ table
|
||||
|
||||
.ext-box-left
|
||||
display: flex;
|
||||
width: 40%
|
||||
width: 100%
|
||||
|
||||
span
|
||||
vertical-align: center;
|
||||
@@ -46,3 +46,6 @@ table
|
||||
|
||||
div
|
||||
margin: auto
|
||||
|
||||
.more-settings-user,.more-settings-team,.more-settings-org
|
||||
margin-left: 10px;
|
||||
@@ -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,39 +82,40 @@ 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'}}
|
||||
@@ -163,13 +166,6 @@ template(name='announcementSettings')
|
||||
|
||||
template(name='layoutSettings')
|
||||
ul#layout-setting.setting-detail
|
||||
//li.layout-form
|
||||
.title {{_ 'hide-logo'}}
|
||||
.form-group.flex
|
||||
input.wekan-form-control#hide-logo(type="radio" name="hideLogo" value="true" checked="{{#if currentSetting.hideLogo}}checked{{/if}}")
|
||||
span {{_ 'yes'}}
|
||||
input.wekan-form-control#hide-logo(type="radio" name="hideLogo" value="false" checked="{{#unless currentSetting.hideLogo}}checked{{/unless}}")
|
||||
span {{_ 'no'}}
|
||||
li.layout-form
|
||||
.title {{_ 'display-authentication-method'}}
|
||||
.form-group.flex
|
||||
@@ -184,10 +180,44 @@ template(name='layoutSettings')
|
||||
.title {{_ 'custom-product-name'}}
|
||||
.form-group
|
||||
input.wekan-form-control#product-name(type="text", placeholder="" value="{{currentSetting.productName}}")
|
||||
li.layout-form
|
||||
.title {{_ 'hide-logo'}}
|
||||
.form-group.flex
|
||||
input.wekan-form-control#hide-logo(type="radio" name="hideLogo" value="true" checked="{{#if currentSetting.hideLogo}}checked{{/if}}")
|
||||
span {{_ 'yes'}}
|
||||
input.wekan-form-control#hide-logo(type="radio" name="hideLogo" value="false" checked="{{#unless currentSetting.hideLogo}}checked{{/unless}}")
|
||||
span {{_ 'no'}}
|
||||
li.layout-form
|
||||
.title {{_ 'custom-login-logo-image-url'}}
|
||||
.form-group
|
||||
input.wekan-form-control#custom-login-logo-image-url(type="text", placeholder="" value="{{currentSetting.customLoginLogoImageUrl}}")
|
||||
li.layout-form
|
||||
.title {{_ 'custom-login-logo-link-url'}}
|
||||
.form-group
|
||||
input.wekan-form-control#custom-login-logo-link-url(type="text", placeholder="" value="{{currentSetting.customLoginLogoLinkUrl}}")
|
||||
li.layout-form
|
||||
.title {{_ 'text-below-custom-login-logo'}}
|
||||
.form-group
|
||||
textarea#text-below-custom-login-logo.wekan-form-control= currentSetting.textBelowCustomLoginLogo
|
||||
li.layout-form
|
||||
.title {{_ 'custom-top-left-corner-logo-image-url'}}
|
||||
.form-group
|
||||
input.wekan-form-control#custom-top-left-corner-logo-image-url(type="text", placeholder="" value="{{currentSetting.customTopLeftCornerLogoImageUrl}}")
|
||||
li.layout-form
|
||||
.title {{_ 'custom-top-left-corner-logo-link-url'}}
|
||||
.form-group
|
||||
input.wekan-form-control#custom-top-left-corner-logo-link-url(type="text", placeholder="" value="{{currentSetting.customTopLeftCornerLogoLinkUrl}}")
|
||||
li.layout-form
|
||||
.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'}}
|
||||
|
||||
|
||||
template(name='selectAuthenticationMethod')
|
||||
select#defaultAuthenticationMethod
|
||||
each authentications
|
||||
|
||||
@@ -167,6 +167,33 @@ BlazeComponent.extendComponent({
|
||||
const productName = $('#product-name')
|
||||
.val()
|
||||
.trim();
|
||||
const customLoginLogoImageUrl = $('#custom-login-logo-image-url')
|
||||
.val()
|
||||
.trim();
|
||||
const customLoginLogoLinkUrl = $('#custom-login-logo-link-url')
|
||||
.val()
|
||||
.trim();
|
||||
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',
|
||||
)
|
||||
.val()
|
||||
.trim();
|
||||
const customTopLeftCornerLogoLinkUrl = $(
|
||||
'#custom-top-left-corner-logo-link-url',
|
||||
)
|
||||
.val()
|
||||
.trim();
|
||||
const customTopLeftCornerLogoHeight = $(
|
||||
'#custom-top-left-corner-logo-height',
|
||||
)
|
||||
.val()
|
||||
.trim();
|
||||
const hideLogoChange = $('input[name=hideLogo]:checked').val() === 'true';
|
||||
const displayAuthenticationMethod =
|
||||
$('input[name=displayAuthenticationMethod]:checked').val() === 'true';
|
||||
@@ -177,8 +204,15 @@ BlazeComponent.extendComponent({
|
||||
$set: {
|
||||
productName,
|
||||
hideLogo: hideLogoChange,
|
||||
customLoginLogoImageUrl,
|
||||
customLoginLogoLinkUrl,
|
||||
textBelowCustomLoginLogo,
|
||||
customTopLeftCornerLogoImageUrl,
|
||||
customTopLeftCornerLogoLinkUrl,
|
||||
customTopLeftCornerLogoHeight,
|
||||
displayAuthenticationMethod,
|
||||
defaultAuthenticationMethod,
|
||||
automaticLinkedUrlSchemes,
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
|
||||
Loaded 100 of 281 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user