mirror of
https://github.com/wekan/wekan.git
synced 2026-11-08 11:25:19 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
eb166737e3 | ||
|
|
a58ee144ac | ||
|
|
54260ca325 | ||
|
|
cb7eebaed0 | ||
|
|
6eeb708e4d | ||
|
|
1c49469b33 | ||
|
|
d18cd59c05 | ||
|
|
960cb27eef | ||
|
|
cdab6076cc | ||
|
|
be9cf34462 | ||
|
|
1e0fdf8abc | ||
|
|
2ef8803dfd | ||
|
|
1d2896886e | ||
|
|
e52351dcbf | ||
|
|
0a001d505d | ||
|
|
55072c529a | ||
|
|
66e22a2c87 | ||
|
|
07b505aa32 | ||
|
|
3c86cf854e | ||
|
|
334c15ff71 | ||
|
|
1aecf8da6b | ||
|
|
9cea76e4ef | ||
|
|
e74fb2f5b0 | ||
|
|
6c0b6ca670 | ||
|
|
9492daf9bc | ||
|
|
f346ce04f5 | ||
|
|
b465500afa | ||
|
|
adf969f6ff | ||
|
|
6462f855c9 | ||
|
|
3721742327 | ||
|
|
910771708a | ||
|
|
7ba361e2c9 | ||
|
|
cc2e0a7c7c | ||
|
|
77efcf7137 | ||
|
|
1298a07838 | ||
|
|
bcbe1aaaf5 | ||
|
|
0c351f4864 | ||
|
|
066237de08 | ||
|
|
ec3902021e | ||
|
|
6928fd71a9 | ||
|
|
035334125b | ||
|
|
70f37c55fd | ||
|
|
670ace6a8d | ||
|
|
ebaccbccca | ||
|
|
652f4e693b | ||
|
|
555d31cca6 | ||
|
|
534b20feda | ||
|
|
24f59b1855 | ||
|
|
c0df1dd4aa | ||
|
|
ba63627ebf | ||
|
|
da636ed17d | ||
|
|
4e12bcc378 | ||
|
|
6cec3b36de | ||
|
|
3e7247891d | ||
|
|
6bb2f311e2 | ||
|
|
0c5fc6d7fd | ||
|
|
8fae676551 | ||
|
|
379f1af89e | ||
|
|
5e128583ac | ||
|
|
23c27f9e07 | ||
|
|
c36509095a | ||
|
|
f85a05e454 | ||
|
|
067e4d15f3 | ||
|
|
65d1330d35 | ||
|
|
39312a075e | ||
|
|
96173ad431 | ||
|
|
c0957ce173 | ||
|
|
fdc168a476 | ||
|
|
3d76b8e1c1 | ||
|
|
1296fce72a | ||
|
|
c34b1a9ec5 | ||
|
|
13db2fd7b2 | ||
|
|
511d1973eb | ||
|
|
dfd26e4843 | ||
|
|
d2c3ecdbcd | ||
|
|
1249bef93e | ||
|
|
71b642a2ba | ||
|
|
f170c116bb | ||
|
|
4ed2f29e30 | ||
|
|
d0731a4bf4 | ||
|
|
d165733242 | ||
|
|
a91f0b5c3b | ||
|
|
cc84bf2de3 | ||
|
|
7e0bc1e33a | ||
|
|
1b94b919fe | ||
|
|
d68ad5af04 | ||
|
|
fcbbb93bb6 | ||
|
|
b3b8d3c086 | ||
|
|
676140f5c8 | ||
|
|
20757efc7e | ||
|
|
4d615057fe | ||
|
|
9bdb5aea87 | ||
|
|
d67c435132 | ||
|
|
18de911a7f | ||
|
|
39b1871e4d | ||
|
|
eecac0e37f | ||
|
|
3e0352c586 | ||
|
|
485f6b5ac2 | ||
|
|
3e715bbcc9 | ||
|
|
b881c3b908 | ||
|
|
9e29d4c815 | ||
|
|
f09d9b63de | ||
|
|
0588c2f605 | ||
|
|
b216c63c13 | ||
|
|
b186561355 | ||
|
|
c9ca79aac8 | ||
|
|
6b4e6d0c63 | ||
|
|
c60ae13b5f | ||
|
|
4e1fedb236 | ||
|
|
3c9aa65ca3 | ||
|
|
365e2e5b4b | ||
|
|
4064429047 | ||
|
|
62dd28d91c | ||
|
|
b3005f828d | ||
|
|
36447ba1c0 | ||
|
|
c694505885 | ||
|
|
807c6ce09e | ||
|
|
9fc3de8502 | ||
|
|
be00465e67 | ||
|
|
5c33a85341 | ||
|
|
e55d7e4f72 | ||
|
|
53c0a52788 | ||
|
|
89b535ac0f | ||
|
|
c2eb300e21 | ||
|
|
eea077e57e | ||
|
|
f725291e14 | ||
|
|
bec1256727 | ||
|
|
9407992312 | ||
|
|
c7e02ad2ee | ||
|
|
ac12aa7ede | ||
|
|
cec5f45459 | ||
|
|
ab73afe17a | ||
|
|
dc4e93ad56 | ||
|
|
2f557ae3a5 | ||
|
|
be25e372a3 | ||
|
|
3f937764cb | ||
|
|
0b9748dff6 | ||
|
|
b9929dc682 | ||
|
|
034981cd3d | ||
|
|
79e464bf90 | ||
|
|
b015b5b724 | ||
|
|
f5515cb95f | ||
|
|
16bbd892aa | ||
|
|
32d9a2c10b | ||
|
|
9967859f42 | ||
|
|
eac0b3e7bb | ||
|
|
8177a1ed0a | ||
|
|
17308dc5f3 | ||
|
|
67301e07e2 | ||
|
|
315db00e83 | ||
|
|
692a1bc369 | ||
|
|
f76d8e47a8 | ||
|
|
6adfcb3513 | ||
|
|
bce2242528 | ||
|
|
f0597ef0c4 | ||
|
|
10aab8a733 | ||
|
|
fb75a487fc | ||
|
|
37306c8d22 | ||
|
|
4ffa8784a2 | ||
|
|
74a01691e3 | ||
|
|
49c415f023 | ||
|
|
b2e175ba8c | ||
|
|
724d26379c | ||
|
|
0a62089df0 | ||
|
|
a93de07fb9 | ||
|
|
64367a01dd | ||
|
|
5644ef66af | ||
|
|
061a13e46e | ||
|
|
dcc7b2970f | ||
|
|
d509b2608f | ||
|
|
193af893ee | ||
|
|
acd105e61b | ||
|
|
a300b73d56 | ||
|
|
5168fb7717 | ||
|
|
945ffeda34 | ||
|
|
66adc397bf | ||
|
|
82a6b4245c | ||
|
|
ae5ea46d7f | ||
|
|
b5022529ac | ||
|
|
49c471d816 | ||
|
|
445aa89e4f | ||
|
|
787941857d | ||
|
|
6a2b494713 | ||
|
|
04d7c47f4c | ||
|
|
9c94ea58b4 | ||
|
|
9f65696fcc | ||
|
|
95b21943ee | ||
|
|
d1400f48c3 | ||
|
|
53d545eeef | ||
|
|
afeb2de412 | ||
|
|
83d6ef7301 | ||
|
|
d2e93c4927 | ||
|
|
fd67bb8e67 | ||
|
|
da6c2b5503 | ||
|
|
57d43f916f | ||
|
|
10a6dbd080 | ||
|
|
0498671cd4 | ||
|
|
b2eeff9697 | ||
|
|
a8146e61f3 | ||
|
|
6a23f73d94 | ||
|
|
b9bcb8f979 | ||
|
|
0416fbdcc4 | ||
|
|
064d125a1c | ||
|
|
1cc8452752 | ||
|
|
5bfb6c6411 | ||
|
|
a48f560a85 | ||
|
|
92bb646977 | ||
|
|
43c38f87a5 | ||
|
|
01c12d7abc | ||
|
|
63e3f6907a | ||
|
|
2e62524d5e | ||
|
|
ec59af3777 | ||
|
|
aa080a7506 | ||
|
|
397dda11ce | ||
|
|
6173a73381 | ||
|
|
dafe1e39a5 | ||
|
|
b77be874e0 | ||
|
|
aca4bffac8 | ||
|
|
2bb80956dd | ||
|
|
e5148b4571 | ||
|
|
6204edd76e | ||
|
|
4eed23afe0 | ||
|
|
2b02e09b07 | ||
|
|
c708877dde | ||
|
|
e2ae5d6b8e | ||
|
|
a798713919 | ||
|
|
19402f5850 | ||
|
|
2beb91ba5d | ||
|
|
1c35f05224 | ||
|
|
758ec48e5c | ||
|
|
f8d5c91659 | ||
|
|
a8f41f7994 | ||
|
|
bf5596b201 | ||
|
|
b0f410f82d | ||
|
|
df54f15ecb | ||
|
|
6a0e4c9b21 | ||
|
|
c0ddecb2ee | ||
|
|
1a7796f2ca | ||
|
|
7119896a3c | ||
|
|
1b32509496 | ||
|
|
a0d2df0647 | ||
|
|
d8c62cf242 | ||
|
|
980fd4f61e | ||
|
|
0dd82fedaf | ||
|
|
058f7e430b | ||
|
|
9487406fc3 | ||
|
|
bf35b09998 | ||
|
|
d50e78c787 | ||
|
|
5dd43fa147 | ||
|
|
5f345e851a | ||
|
|
687c7923e7 | ||
|
|
90707aaab3 | ||
|
|
d5870472fb | ||
|
|
efb083aabf | ||
|
|
5c77407061 | ||
|
|
9c204d9bbe | ||
|
|
616dade81c | ||
|
|
43d86d7d5d | ||
|
|
dea9df2a3b | ||
|
|
6c7eab4456 | ||
|
|
35a3b0b62e | ||
|
|
7683f98b7b | ||
|
|
09dbcf3bea | ||
|
|
369da1e09d | ||
|
|
94a1446a08 | ||
|
|
884cd0e6b8 | ||
|
|
5e17b01077 | ||
|
|
644b235bbb | ||
|
|
3d3096104e | ||
|
|
a41190cdf0 | ||
|
|
1189259a55 | ||
|
|
9a053164ac | ||
|
|
c31602da42 | ||
|
|
074a1218fd | ||
|
|
5d573a7aa1 | ||
|
|
c26a31f498 | ||
|
|
4b65c5cc33 | ||
|
|
af8bf1af2e | ||
|
|
aaae3150c4 | ||
|
|
5220111822 | ||
|
|
62e5e5db49 | ||
|
|
eb6373a879 | ||
|
|
a4ca6dce25 | ||
|
|
5986f64d72 | ||
|
|
b1b9170afe | ||
|
|
13e5ccb56e | ||
|
|
8d24fc4bcf | ||
|
|
cc63a575ab | ||
|
|
a02c51cc3b | ||
|
|
ca6cadbe6d | ||
|
|
cc753cf4e4 | ||
|
|
7e4fddd932 | ||
|
|
06423164fb | ||
|
|
515c9be051 | ||
|
|
243797d2e9 | ||
|
|
c997786e64 | ||
|
|
dd324aa581 | ||
|
|
177c00e974 | ||
|
|
067aef9de9 | ||
|
|
02f14d967f | ||
|
|
122a61b333 | ||
|
|
49a89b80cf | ||
|
|
ee81775dc8 | ||
|
|
05869792ad | ||
|
|
2ac7660f29 | ||
|
|
abf7890941 | ||
|
|
e139e140f4 | ||
|
|
1f7db171d9 | ||
|
|
bf06c715fe | ||
|
|
44e20023cc | ||
|
|
e03ee1bd2f | ||
|
|
aea5ed7848 | ||
|
|
bbdb6a90b2 | ||
|
|
f4eac833ed | ||
|
|
8fbbc104f7 | ||
|
|
6ba4574c67 | ||
|
|
928d88cfe1 | ||
|
|
4f5086c5cd | ||
|
|
fe69ab9030 | ||
|
|
08a1927c0c | ||
|
|
f02d5e64f0 | ||
|
|
5bca2f802b | ||
|
|
3eba6ef285 | ||
|
|
5f81b73a49 | ||
|
|
ad54a8a484 | ||
|
|
5adce79842 | ||
|
|
9fceb212d9 | ||
|
|
e044769d85 | ||
|
|
a86a8eff2d | ||
|
|
7b9aaddb5b | ||
|
|
541dc67a02 | ||
|
|
db5ff4e1e2 | ||
|
|
d0611e1bff | ||
|
|
523ebea4dd | ||
|
|
bccfa320a9 | ||
|
|
72d0db7a59 | ||
|
|
ed0ef5b7d3 | ||
|
|
5619eef620 | ||
|
|
ae2e42e1b4 | ||
|
|
864ad3827d | ||
|
|
9cb8aab3ba | ||
|
|
374e986579 | ||
|
|
3c4549fe64 | ||
|
|
0394a78ece | ||
|
|
19d239f4cf | ||
|
|
d23ac2b385 | ||
|
|
ae5d2b7908 | ||
|
|
766b58d91b | ||
|
|
663a4040f9 | ||
|
|
18467dfe40 | ||
|
|
2a165dccd4 | ||
|
|
d501e5832a | ||
|
|
b198a3ed99 | ||
|
|
226d25ca94 | ||
|
|
b7d508e8c4 | ||
|
|
439d7c3dbc | ||
|
|
bac490d2f3 | ||
|
|
3a4a075dba | ||
|
|
c0ffd6c20f | ||
|
|
94a52080cf | ||
|
|
c9f70cf382 | ||
|
|
04745f0c2f | ||
|
|
aead18eb58 | ||
|
|
a0c02f4a50 | ||
|
|
50f170b75d | ||
|
|
989b026b33 | ||
|
|
4ac6a507cd | ||
|
|
cd36194477 | ||
|
|
6ab1cbb341 | ||
|
|
5a023e4315 | ||
|
|
adb7f5b2ca | ||
|
|
fd465fbb60 | ||
|
|
879a84184f | ||
|
|
f89de026c4 | ||
|
|
5f20e56721 | ||
|
|
d59583915c | ||
|
|
b627ced605 | ||
|
|
c3037b155f | ||
|
|
c3e839c885 | ||
|
|
b0444ae338 | ||
|
|
43dde4a10f | ||
|
|
97922c90cb | ||
|
|
c372ea02f7 | ||
|
|
daa95c582e | ||
|
|
aa2a15bf1b | ||
|
|
f629a7b3f7 | ||
|
|
03921a969a | ||
|
|
b7d51456eb | ||
|
|
6a587299b8 | ||
|
|
f5aa1b795b | ||
|
|
2efc5ab4e9 | ||
|
|
fde26c2183 | ||
|
|
8ad8f17731 | ||
|
|
e9d56b0804 | ||
|
|
43a967b274 | ||
|
|
c1ecaf3959 | ||
|
|
0b5ecd24f9 | ||
|
|
9a55f38d90 | ||
|
|
09c8f29de8 | ||
|
|
620bbb3394 | ||
|
|
77ae6c17e7 | ||
|
|
b8bbdcc4c5 | ||
|
|
18e936fd28 | ||
|
|
c94edb6bb0 | ||
|
|
615f66c820 | ||
|
|
484d495259 | ||
|
|
bec0c4b4d0 | ||
|
|
dfbcca2a2d | ||
|
|
4526845fd1 | ||
|
|
73c6c07c47 | ||
|
|
896a149fb9 | ||
|
|
0034d2d3be | ||
|
|
880dcab0b1 | ||
|
|
98eb4453c5 | ||
|
|
3e686e4379 | ||
|
|
8509dad58f | ||
|
|
0f53220122 | ||
|
|
1214af04a9 | ||
|
|
8c0d61c4a5 | ||
|
|
ba2012af43 | ||
|
|
b5e6e6ee10 | ||
|
|
61ee6cf09f | ||
|
|
04925f7347 | ||
|
|
37817fcaf8 | ||
|
|
8a7ad0df54 | ||
|
|
a433f7d9fe | ||
|
|
991e74bfc2 | ||
|
|
c46817f23a | ||
|
|
94bd63c8a7 | ||
|
|
3e8b2620a1 | ||
|
|
ce8c78eb34 | ||
|
|
85e02010d4 | ||
|
|
a912960a58 | ||
|
|
aeec9f6ef8 | ||
|
|
718adc6c47 | ||
|
|
454aa05987 | ||
|
|
23726136bd | ||
|
|
fa82efe7d2 | ||
|
|
011fad6701 | ||
|
|
fcf262cc98 | ||
|
|
c5f0e87dd0 | ||
|
|
6a154ee9b0 | ||
|
|
558539e21b | ||
|
|
571f55f904 | ||
|
|
259614b647 | ||
|
|
8ec60879dc | ||
|
|
edd2e9db3c | ||
|
|
67454d0491 | ||
|
|
9e14733478 | ||
|
|
848d8ac95d | ||
|
|
93e7c8aecf | ||
|
|
a98ae8dc71 | ||
|
|
193ff20c23 | ||
|
|
92a85a991b | ||
|
|
38af71d9c9 | ||
|
|
246267276a | ||
|
|
ea19176d3c | ||
|
|
f28889de59 | ||
|
|
aa7199af2d | ||
|
|
fba0a52e4a | ||
|
|
6d7bdad140 | ||
|
|
aef871833b | ||
|
|
dda49d2f07 | ||
|
|
199ea3d6f9 | ||
|
|
6478dd7da8 | ||
|
|
53bd527947 | ||
|
|
2156e45869 | ||
|
|
72a66c1d5b | ||
|
|
1ced919dfb | ||
|
|
d948e78d1e | ||
|
|
bd5fd77655 | ||
|
|
45cf2843a6 | ||
|
|
ca51ace22d | ||
|
|
93a7040c77 | ||
|
|
d4df405862 | ||
|
|
dc687848e6 | ||
|
|
85187817a7 | ||
|
|
5f5a1b780e | ||
|
|
e31741cd7b | ||
|
|
d5bfa468f7 | ||
|
|
9990f9856b | ||
|
|
b3bb03fed4 | ||
|
|
1332a57890 | ||
|
|
123d9659c1 | ||
|
|
90d55777f7 | ||
|
|
ec4e1b6eff | ||
|
|
c72b769f82 | ||
|
|
8471f389eb | ||
|
|
23e6b4ec0a | ||
|
|
8f364281d2 | ||
|
|
1f17cee39b | ||
|
|
4787a1186b | ||
|
|
3c4b09157e | ||
|
|
87ee0ca646 | ||
|
|
de59758471 | ||
|
|
ea109cfdd7 | ||
|
|
9035989abf | ||
|
|
aa6076e087 | ||
|
|
78b9436f38 | ||
|
|
3ce3fa74b3 | ||
|
|
d6eff2a074 | ||
|
|
ccf1e8bc3c | ||
|
|
6d75fe4d86 | ||
|
|
82a01edc54 | ||
|
|
9ff2340cdb | ||
|
|
b727204716 | ||
|
|
5b4f2f55aa | ||
|
|
60119153de | ||
|
|
2b2d596da6 | ||
|
|
63c1ef9f9e | ||
|
|
0cc183682e | ||
|
|
4d193f5650 | ||
|
|
73c4806864 | ||
|
|
b0cf60a3d9 | ||
|
|
3ca3d063a7 | ||
|
|
01741750f8 | ||
|
|
4377381fd3 | ||
|
|
9cf1b62cd6 | ||
|
|
5ded2e5121 | ||
|
|
7eeabf14be | ||
|
|
be507e567a | ||
|
|
1117d1c2ae | ||
|
|
9eaac52b73 | ||
|
|
4b20102139 | ||
|
|
edae64b1c7 | ||
|
|
9242bdb10b | ||
|
|
171d0c8629 | ||
|
|
a69997d31e | ||
|
|
31e4400c66 | ||
|
|
3bcd578fcb | ||
|
|
4c5daf5d85 | ||
|
|
5b4d75a976 | ||
|
|
05020241aa | ||
|
|
b9c63a8c8f | ||
|
|
f75f686271 | ||
|
|
505fc71665 | ||
|
|
529594ef55 | ||
|
|
3d1f004e90 | ||
|
|
0195044ba1 | ||
|
|
e8c24aeaf9 | ||
|
|
ad8f227880 | ||
|
|
ddfcb235cc | ||
|
|
c4d83c6e66 | ||
|
|
90b589d993 | ||
|
|
94fc172366 | ||
|
|
d4cc337577 | ||
|
|
25695bdef2 | ||
|
|
af496839f5 | ||
|
|
a8feb8ed32 | ||
|
|
9c09d926e3 | ||
|
|
cba480d3ae | ||
|
|
dbfdba75f9 | ||
|
|
d46afc12be | ||
|
|
531cea489e | ||
|
|
9e4758ec9e | ||
|
|
e8206f2983 | ||
|
|
e5c6da5a39 | ||
|
|
2119a6568b | ||
|
|
dd7c9997a9 | ||
|
|
256ca129f0 | ||
|
|
6d9ac3ae48 | ||
|
|
59046d448f | ||
|
|
d9e291635a | ||
|
|
b8158fadfc | ||
|
|
1133b7a04a | ||
|
|
43fe9ef34a | ||
|
|
f910b66ef2 | ||
|
|
bfac626fa4 | ||
|
|
ecbb8ef071 | ||
|
|
1c0c5bde0f | ||
|
|
c3044a6b8b | ||
|
|
778a29855f | ||
|
|
eb859dac3a | ||
|
|
9ac1164440 | ||
|
|
39974c9532 | ||
|
|
4ff8989e8f | ||
|
|
2bf13a50c4 | ||
|
|
382b14ea27 | ||
|
|
17fcfd3697 | ||
|
|
811ccf0f10 | ||
|
|
422424d21c | ||
|
|
0bdc7efc8b | ||
|
|
32058e8018 | ||
|
|
ba12b53e49 | ||
|
|
b9ead144fb | ||
|
|
1d58e40133 | ||
|
|
cd749bc385 | ||
|
|
01cd2df369 | ||
|
|
1854f5c061 | ||
|
|
b00bd04baa | ||
|
|
8b32cf42cb | ||
|
|
3075791a93 | ||
|
|
38ab2b766d | ||
|
|
410e5aa28d | ||
|
|
82f7541131 | ||
|
|
106b135eba | ||
|
|
7dfec58128 | ||
|
|
977bce9eb2 | ||
|
|
bc0aef3332 | ||
|
|
8101d7ade8 | ||
|
|
f6d19d2833 | ||
|
|
c431af27c2 | ||
|
|
973a0d93ae | ||
|
|
cbdb7b4f64 | ||
|
|
9c5bcd7321 | ||
|
|
8f0c3b45c0 | ||
|
|
78317ef792 | ||
|
|
1ab4f5b913 | ||
|
|
04f09b6042 | ||
|
|
f48e2fbd14 | ||
|
|
27f9e9e104 | ||
|
|
9a509778d3 | ||
|
|
12b08b9915 | ||
|
|
bd8a8ab90e | ||
|
|
642507fb42 | ||
|
|
4600e4e237 | ||
|
|
c2e6f67689 | ||
|
|
9dec10bad3 | ||
|
|
3e390503fc | ||
|
|
a7f8614f04 | ||
|
|
0be7a5d783 | ||
|
|
41b938ea69 | ||
|
|
12a374bec7 | ||
|
|
8dd1566316 | ||
|
|
50f751e0a9 | ||
|
|
1984a6b1c8 | ||
|
|
1d904adc61 | ||
|
|
22882a0603 | ||
|
|
9b465bc98b | ||
|
|
ef99e6a6b1 | ||
|
|
61b240d126 | ||
|
|
1f3b5604c0 | ||
|
|
3bf4f3ef40 | ||
|
|
838578657d | ||
|
|
d6cfac0122 | ||
|
|
c1d2e27c09 | ||
|
|
b43779e408 | ||
|
|
f9df38d333 | ||
|
|
80088174fc | ||
|
|
0dfc62c025 | ||
|
|
7186b947b2 | ||
|
|
98df01060d | ||
|
|
9184bf3946 | ||
|
|
9518a5c11e | ||
|
|
9a766c0f74 | ||
|
|
c0c7b269a7 | ||
|
|
5dafea405d | ||
|
|
77a5f8f339 | ||
|
|
be97efb791 | ||
|
|
7e34dd0c2b | ||
|
|
0ecbb73419 | ||
|
|
f3aa524b77 | ||
|
|
792f187d06 | ||
|
|
4c18df757f | ||
|
|
9d47d3e397 | ||
|
|
0b9328a1be | ||
|
|
fc033c30e6 | ||
|
|
da180472c1 | ||
|
|
cdc2b920ee | ||
|
|
16d75f549d | ||
|
|
c43508cacb | ||
|
|
6b2d022a93 | ||
|
|
1cb8a6e7fe | ||
|
|
5e109de8d5 | ||
|
|
c4b5145db4 | ||
|
|
e5638e5e5a | ||
|
|
7e49ab5fea | ||
|
|
682eab74d9 | ||
|
|
9edbc349b9 | ||
|
|
c751f05962 | ||
|
|
2fa1b3122d | ||
|
|
c48c18c4e9 | ||
|
|
2da157dbb0 | ||
|
|
daeb06f7b7 | ||
|
|
dcd5af0a76 | ||
|
|
e576e0f9cf | ||
|
|
83e7e4fb27 | ||
|
|
01804daf24 | ||
|
|
d77e54fff6 | ||
|
|
0aa78d9847 | ||
|
|
e5c1351e82 | ||
|
|
f6656a4791 | ||
|
|
d2354827da | ||
|
|
814164e53e | ||
|
|
bde9cc7cea | ||
|
|
7b0cf760e9 | ||
|
|
6a16063f7d | ||
|
|
130aa1161e | ||
|
|
eaebe8b893 | ||
|
|
c4b898633e | ||
|
|
88fca396d4 | ||
|
|
cfa3c4bfcb | ||
|
|
bf7520c430 | ||
|
|
166324df01 | ||
|
|
539c1ab87a | ||
|
|
e5cb190693 | ||
|
|
359d0b376f | ||
|
|
a6cf57e988 | ||
|
|
1124f4120c | ||
|
|
6ee6dbade5 | ||
|
|
f219e2151f | ||
|
|
c5b7f30d65 | ||
|
|
e3f1fbc967 | ||
|
|
e6df7d81cf | ||
|
|
24ad97cddb | ||
|
|
b70252468a | ||
|
|
f9941c0f9c | ||
|
|
26c8505d9e | ||
|
|
e7e558e865 | ||
|
|
6167d447fd | ||
|
|
30b17ff6c9 | ||
|
|
df91d1e632 | ||
|
|
1f42aac19f | ||
|
|
212440862b | ||
|
|
21e68f3e54 | ||
|
|
116bc38136 | ||
|
|
e721dba1e2 | ||
|
|
3b6ec34bf5 | ||
|
|
be61904a1e | ||
|
|
170acf6948 | ||
|
|
d69f8f4cda | ||
|
|
db80e73804 | ||
|
|
25668eb7c4 | ||
|
|
11177196e3 | ||
|
|
6d21ffe660 | ||
|
|
ce79645455 | ||
|
|
7b91b341fe | ||
|
|
6856f4d95f | ||
|
|
075ea1c43d | ||
|
|
b7247f8d52 | ||
|
|
87d2cee02a | ||
|
|
fa758a73bd | ||
|
|
4191ede176 | ||
|
|
ded98d73d7 | ||
|
|
bbfacc06e3 | ||
|
|
e45b8ea48c | ||
|
|
179ff7a124 | ||
|
|
fc4d7a0bde | ||
|
|
5415a7c4b9 | ||
|
|
84fd00c566 | ||
|
|
f41589ba82 | ||
|
|
ce65963217 | ||
|
|
1e0fcfd20d | ||
|
|
8d5cbf1e6c | ||
|
|
7cc930f6b9 | ||
|
|
e9bb7e0041 | ||
|
|
61538ab577 | ||
|
|
bca4f0b842 | ||
|
|
0723a204e8 | ||
|
|
2cd1fbf9d9 | ||
|
|
29c3d939a7 | ||
|
|
02e8749540 | ||
|
|
e402200b87 | ||
|
|
ea289c7810 | ||
|
|
f3058133b3 | ||
|
|
e26a4824cf | ||
|
|
e5995477b8 | ||
|
|
c12e003fd3 | ||
|
|
8e11d278d3 | ||
|
|
de13705289 | ||
|
|
09bc8ac44c | ||
|
|
eae4bb2d37 | ||
|
|
31584e849c | ||
|
|
b735817901 | ||
|
|
4dbe6feb8c | ||
|
|
9eef5112dc | ||
|
|
4861da52a0 | ||
|
|
aede4dd9c5 | ||
|
|
4505e6edc9 | ||
|
|
85e86136e9 | ||
|
|
9b961edb36 | ||
|
|
82fc4d011f | ||
|
|
bfe03ac89f | ||
|
|
db74c86e55 | ||
|
|
b7ee0173ec | ||
|
|
ce177117a0 | ||
|
|
b05f3595f0 | ||
|
|
3e927b4e58 | ||
|
|
1c8a00943c | ||
|
|
f00797de5c | ||
|
|
c115046a7c | ||
|
|
8051f6affa | ||
|
|
973b416885 | ||
|
|
b501d35b55 | ||
|
|
8fc4011bf8 | ||
|
|
7b94b04701 | ||
|
|
217ae207b9 | ||
|
|
4f1eaa6b82 | ||
|
|
49c7a6c223 | ||
|
|
0e883675fc | ||
|
|
5a6be37d52 | ||
|
|
c295e47f76 | ||
|
|
9711945e48 | ||
|
|
fb87e4b1f2 | ||
|
|
a320a71467 | ||
|
|
bda6ee26d7 | ||
|
|
40d438a517 | ||
|
|
5d2dd66450 | ||
|
|
f9539aa2a8 | ||
|
|
66e56849a4 | ||
|
|
75512043e8 | ||
|
|
3631cd5026 | ||
|
|
09c59ff562 | ||
|
|
e3d1fbc7f4 | ||
|
|
05f1d197f5 | ||
|
|
485ccf4007 | ||
|
|
fe79a3e763 | ||
|
|
30a4494af2 | ||
|
|
add5d22c4e | ||
|
|
08af6a0cf1 | ||
|
|
38a8d82735 | ||
|
|
42a4ca3678 | ||
|
|
66c20df5ba | ||
|
|
4505495762 | ||
|
|
679e50af64 | ||
|
|
2e8f8924dd | ||
|
|
568a1a11fd | ||
|
|
5e88cb24cb | ||
|
|
023b41b205 | ||
|
|
cca4a3e372 | ||
|
|
caca2e34fc | ||
|
|
07217d0e51 | ||
|
|
75b3d51b39 | ||
|
|
80941e57d3 | ||
|
|
3d0bac1f49 | ||
|
|
10f24a8a8a | ||
|
|
578bdf9e67 | ||
|
|
a7855f3f58 | ||
|
|
ac19904ee8 | ||
|
|
ec1630f8dd | ||
|
|
a7f88d24a1 | ||
|
|
90f3f7ba16 | ||
|
|
5e5a5ed9be | ||
|
|
3eb6f97291 | ||
|
|
06e64d24a8 | ||
|
|
243af32fc7 | ||
|
|
ca89442f3a | ||
|
|
153960742c | ||
|
|
bf7de463f1 | ||
|
|
fa0fd5f21f | ||
|
|
83848dbee2 | ||
|
|
cb099d1093 | ||
|
|
89a8a6f5e3 | ||
|
|
22923d08af | ||
|
|
57ccfcde63 | ||
|
|
75693d16e2 | ||
|
|
454523dd47 | ||
|
|
bb37d8fa96 | ||
|
|
f470323ee7 | ||
|
|
c62a2ee11f | ||
|
|
5b0f7f8aef | ||
|
|
0495e61c28 | ||
|
|
c1c3421006 | ||
|
|
dfc5537107 | ||
|
|
3ce90e9766 | ||
|
|
5b98f139d1 | ||
|
|
293718d90c | ||
|
|
4b53b0c90a | ||
|
|
862239019a | ||
|
|
98103bb2f7 | ||
|
|
e5b003f5ab | ||
|
|
9a1b1a5bed | ||
|
|
983649a6cb | ||
|
|
990af4e5c2 | ||
|
|
660b578ab3 | ||
|
|
f7a9bafe4c | ||
|
|
ac7d44f8a8 | ||
|
|
ed8471be9b | ||
|
|
65beb89944 | ||
|
|
594daa9cf8 | ||
|
|
663d8e3c34 | ||
|
|
128a356b92 | ||
|
|
ebb48f3ee8 | ||
|
|
2092b429db | ||
|
|
58e5e9b308 | ||
|
|
4a2b30d08b | ||
|
|
338fb5304d | ||
|
|
0cee496270 | ||
|
|
9e62584b26 | ||
|
|
5849ffbb53 | ||
|
|
a58bffbb3e | ||
|
|
a8ae6adbc2 | ||
|
|
946dcf0b0a | ||
|
|
1ca9e96f35 | ||
|
|
b475127c53 | ||
|
|
2c1dadf712 | ||
|
|
bbca361aeb | ||
|
|
f96e21f462 | ||
|
|
1be8e5625f | ||
|
|
9084158aec | ||
|
|
6fc89a04de | ||
|
|
d454fa7dd7 | ||
|
|
b6d3e79548 | ||
|
|
4994f66e9c | ||
|
|
a23d93391b | ||
|
|
a033c35a34 | ||
|
|
91bab1c274 | ||
|
|
48cd551a69 | ||
|
|
daf1a67dc2 | ||
|
|
8d2839f0c3 | ||
|
|
284fac043b | ||
|
|
bd239351fd | ||
|
|
37c94622e4 | ||
|
|
c4fa9010f3 | ||
|
|
e44c46bcd2 | ||
|
|
843381a36c | ||
|
|
59ba2111e8 | ||
|
|
1efa66b58c | ||
|
|
dc8c9053c2 | ||
|
|
0a16147470 | ||
|
|
373e9782dc | ||
|
|
951a0db380 | ||
|
|
c0d33d97f2 | ||
|
|
57cf86a79f | ||
|
|
5bdb392258 | ||
|
|
a48630ffcf | ||
|
|
fe1941008c | ||
|
|
190aa36a51 | ||
|
|
468f4de0cf | ||
|
|
93215be2cf | ||
|
|
ab2884cae0 | ||
|
|
5f374b2fd2 | ||
|
|
636e1657f6 | ||
|
|
2001c01b4d | ||
|
|
a9166d877f | ||
|
|
435501fb8e | ||
|
|
fd47e10e52 | ||
|
|
e3bd1c4d23 | ||
|
|
f7b72a1a80 | ||
|
|
31f25bcddb | ||
|
|
1ec5e90706 | ||
|
|
20d6ea85d4 | ||
|
|
7498dba32c | ||
|
|
d374cd2f81 | ||
|
|
ffbd3ccc2a | ||
|
|
ad1a181f6d | ||
|
|
fcd83ea7bd | ||
|
|
07fc296762 | ||
|
|
62fca18fea | ||
|
|
af82a80b2b | ||
|
|
9966c19f94 | ||
|
|
ff320f7b3a | ||
|
|
9c9694bcd1 | ||
|
|
fcd7097aba | ||
|
|
19089e8930 | ||
|
|
f7920da0cf | ||
|
|
d7ea73ff82 | ||
|
|
e077c85d00 | ||
|
|
3665a9131c | ||
|
|
f7fe44fcdf | ||
|
|
a533caa944 | ||
|
|
1ef663531b | ||
|
|
26f66f3cf0 | ||
|
|
2e449e9e78 | ||
|
|
e30f6515c6 | ||
|
|
11e9811f82 | ||
|
|
df5be82840 | ||
|
|
599c83e0da | ||
|
|
c0dbb79ac9 | ||
|
|
0375c551f3 | ||
|
|
ee0f42eeb1 | ||
|
|
becdcbd5a7 | ||
|
|
7f4b382d2f | ||
|
|
96d81768bc | ||
|
|
cd012954e9 | ||
|
|
3b202c284a | ||
|
|
8da1dd524d | ||
|
|
cfaeb43f1f | ||
|
|
25e0c38ad8 | ||
|
|
756fbd0f4c | ||
|
|
d3bdc8edbc | ||
|
|
55a53e2655 | ||
|
|
ffc825e348 | ||
|
|
11b8e12ede | ||
|
|
69aeee536d | ||
|
|
ab6a7c2dd6 | ||
|
|
0a5af2b719 | ||
|
|
ecd77c8704 | ||
|
|
c5019e620a | ||
|
|
257ed56db3 | ||
|
|
9db64a95b6 | ||
|
|
c5a707a7f5 | ||
|
|
842c8b83d2 | ||
|
|
9705118ca2 | ||
|
|
326b4c5350 | ||
|
|
f3ed6ee6f6 | ||
|
|
60c6f4f5af | ||
|
|
3c1cd85f6f | ||
|
|
bb9d5cb694 | ||
|
|
669c2f3861 | ||
|
|
6a93a93d0b | ||
|
|
c3fe70e094 | ||
|
|
b2d3138220 | ||
|
|
405514fd6b | ||
|
|
efa2d99bf4 | ||
|
|
8d816cdb0f | ||
|
|
918bd0befd | ||
|
|
bf2a08555b | ||
|
|
cf97123512 | ||
|
|
6aca70f0d1 | ||
|
|
963e319345 | ||
|
|
b21021501c | ||
|
|
638e2d87eb | ||
|
|
d94393c764 | ||
|
|
faa95a0f8c | ||
|
|
047e22571e | ||
|
|
ed95542b67 | ||
|
|
9c283112ed | ||
|
|
fbfe6590b7 | ||
|
|
2824873511 | ||
|
|
dc9ac5b58a | ||
|
|
ee69eb03d4 | ||
|
|
c040603786 | ||
|
|
275bb0b131 | ||
|
|
8b16955cc2 | ||
|
|
3753337d60 | ||
|
|
caad952bc1 | ||
|
|
6ff89b43b6 | ||
|
|
733b14dcd8 | ||
|
|
d87191f17e | ||
|
|
afd87e3caa | ||
|
|
ade3c02122 |
No files matched your search
+9
-2
@@ -100,7 +100,9 @@
|
||||
"Attachments": true,
|
||||
"Boards": true,
|
||||
"CardComments": true,
|
||||
"DatePicker" : true,
|
||||
"Cards": true,
|
||||
"CustomFields": true,
|
||||
"Lists": true,
|
||||
"UnsavedEditCollection": true,
|
||||
"Users": true,
|
||||
@@ -119,7 +121,8 @@
|
||||
"allowIsBoardAdmin": true,
|
||||
"allowIsBoardMember": true,
|
||||
"allowIsBoardMemberByCard": true,
|
||||
"allowIsBoardMemberNonComment": true,
|
||||
"allowIsBoardMemberCommentOnly": true,
|
||||
"allowIsBoardMemberNoComments": true,
|
||||
"Emoji": true,
|
||||
"Checklists": true,
|
||||
"Settings": true,
|
||||
@@ -129,6 +132,10 @@
|
||||
"Integrations": true,
|
||||
"HTTP": true,
|
||||
"AccountSettings": true,
|
||||
"Announcements": true
|
||||
"Announcements": true,
|
||||
"Swimlanes": true,
|
||||
"ChecklistItems": true,
|
||||
"Subtasks": true,
|
||||
"Npm": true
|
||||
}
|
||||
}
|
||||
@@ -1,16 +1,18 @@
|
||||
## Issue
|
||||
**Impacted version**: xxxx
|
||||
|
||||
**Server Setup Information**:
|
||||
|
||||
* Did you test in newest Wekan?:
|
||||
* Wekan version:
|
||||
* If this is about old version of Wekan, what upgrade problem you have?:
|
||||
* Operating System:
|
||||
* Deployment Method(tar/sandstorm/snap/docker/etc /http frontend (nginx, httpd, ...)):
|
||||
* Deployment Method(snap/docker/sandstorm/mongodb bundle/source):
|
||||
* Http frontend if any (Caddy, Nginx, Apache, see config examples from Wekan GitHub wiki first):
|
||||
* Node Version:
|
||||
* MongoDB Version:
|
||||
* ROOT_URL environment variable (Is there a subfolder?):
|
||||
* ROOT_URL environment variable http(s)://(subdomain).example.com(/suburl):
|
||||
|
||||
**Problem description**:
|
||||
- *be as explicit as you can*
|
||||
- *describe the problem and its symptoms*
|
||||
- *explain how to reproduce*
|
||||
- *attach whatever information that can help understanding the context (screen capture, log files)*
|
||||
- *REQUIRED: Add recorded animated gif about how it works currently, and screenshot mockups how it should work*
|
||||
- *Explain steps how to reproduce*
|
||||
- *Attach log files in .zip file)*
|
||||
@@ -14,3 +14,5 @@ package-lock.json
|
||||
**/stage
|
||||
**/prime
|
||||
**/*.snap
|
||||
snap/.snapcraft/
|
||||
.idea
|
||||
+8
-2
@@ -31,6 +31,7 @@ kenton:accounts-sandstorm
|
||||
service-configuration@1.0.11
|
||||
useraccounts:unstyled
|
||||
useraccounts:flow-routing
|
||||
salleman:accounts-oidc
|
||||
|
||||
# Utilities
|
||||
check@1.2.5
|
||||
@@ -49,7 +50,6 @@ kadira:dochead
|
||||
meteorhacks:picker
|
||||
meteorhacks:subs-manager
|
||||
mquandalle:autofocus
|
||||
mquandalle:moment
|
||||
ongoworks:speakingurl
|
||||
raix:handlebar-helpers
|
||||
tap:i18n
|
||||
@@ -77,8 +77,14 @@ email@1.2.3
|
||||
horka:swipebox
|
||||
dynamic-import@0.2.0
|
||||
staringatlights:fast-render
|
||||
staringatlights:flow-router
|
||||
|
||||
mixmax:smart-disconnect
|
||||
accounts-password@1.5.0
|
||||
cfs:gridfs
|
||||
eluck:accounts-lockout
|
||||
rzymek:fullcalendar
|
||||
momentjs:moment@2.22.2
|
||||
atoy40:accounts-cas
|
||||
browser-policy-framing
|
||||
mquandalle:moment
|
||||
msavin:usercache
|
||||
+12
-1
@@ -1,5 +1,6 @@
|
||||
3stack:presence@1.1.2
|
||||
accounts-base@1.4.0
|
||||
accounts-oauth@1.1.15
|
||||
accounts-password@1.5.0
|
||||
aldeed:collection2@2.10.0
|
||||
aldeed:collection2-core@1.2.0
|
||||
@@ -9,6 +10,7 @@ aldeed:simple-schema@1.5.3
|
||||
alethes:pages@1.8.6
|
||||
allow-deny@1.1.0
|
||||
arillo:flow-router-helpers@0.5.2
|
||||
atoy40:accounts-cas@0.0.2
|
||||
audit-argument-checks@1.0.7
|
||||
autoupdate@1.3.12
|
||||
babel-compiler@6.24.7
|
||||
@@ -18,6 +20,8 @@ binary-heap@1.0.10
|
||||
blaze@2.3.2
|
||||
blaze-tools@1.0.10
|
||||
boilerplate-generator@1.3.1
|
||||
browser-policy-common@1.0.11
|
||||
browser-policy-framing@1.1.0
|
||||
caching-compiler@1.1.9
|
||||
caching-html-compiler@1.1.2
|
||||
callback-hook@1.0.10
|
||||
@@ -57,6 +61,7 @@ ecmascript-runtime@0.5.0
|
||||
ecmascript-runtime-client@0.5.0
|
||||
ecmascript-runtime-server@0.5.0
|
||||
ejson@1.1.0
|
||||
eluck:accounts-lockout@0.9.0
|
||||
email@1.2.3
|
||||
es5-shim@4.6.15
|
||||
fastclick@1.0.13
|
||||
@@ -98,6 +103,7 @@ mixmax:smart-disconnect@0.0.4
|
||||
mobile-status-bar@1.0.14
|
||||
modules@0.11.0
|
||||
modules-runtime@0.9.1
|
||||
momentjs:moment@2.22.2
|
||||
mongo@1.3.1
|
||||
mongo-dev-server@1.1.0
|
||||
mongo-id@1.0.6
|
||||
@@ -112,8 +118,11 @@ mquandalle:jquery-ui-drag-drop-sort@0.2.0
|
||||
mquandalle:moment@1.0.1
|
||||
mquandalle:mousetrap-bindglobal@0.0.1
|
||||
mquandalle:perfect-scrollbar@0.6.5_2
|
||||
msavin:usercache@1.0.0
|
||||
npm-bcrypt@0.9.3
|
||||
npm-mongo@2.2.33
|
||||
oauth@1.2.1
|
||||
oauth2@1.2.0
|
||||
observe-sequence@1.0.16
|
||||
ongoworks:speakingurl@1.1.0
|
||||
ordered-dict@1.0.9
|
||||
@@ -134,6 +143,9 @@ reactive-var@1.0.11
|
||||
reload@1.1.11
|
||||
retry@1.0.9
|
||||
routepolicy@1.0.12
|
||||
rzymek:fullcalendar@3.8.0
|
||||
salleman:accounts-oidc@1.0.9
|
||||
salleman:oidc@1.0.9
|
||||
service-configuration@1.0.11
|
||||
session@1.1.7
|
||||
sha@1.0.9
|
||||
@@ -150,7 +162,6 @@ srp@1.0.10
|
||||
standard-minifier-css@1.3.5
|
||||
standard-minifier-js@2.2.3
|
||||
staringatlights:fast-render@2.16.5
|
||||
staringatlights:flow-router@2.12.2
|
||||
staringatlights:inject-data@2.0.5
|
||||
stylus@2.513.13
|
||||
tap:i18n@1.8.2
|
||||
|
||||
+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 = en_GB:en-GB, es_AR:es-AR, el_GR:el, fa_IR:fa, fi_FI:fi, hu_HU:hu, id_ID:id, mn_MN:mn, no:nb, lv_LV:lv, pt_BR:pt-BR, ro_RO:ro, zh_CN:zh-CN, zh_TW:zh-TW
|
||||
lang_map = bg_BG:bg, en_GB:en-GB, es_AR:es-AR, 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, zh_CN:zh-CN, zh_TW:zh-TW
|
||||
|
||||
[wekan.application]
|
||||
file_filter = i18n/<lang>.i18n.json
|
||||
|
||||
+825
@@ -1,8 +1,833 @@
|
||||
# v1.44 2018-09-09 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- REST API: [Add startAt/dueAt/endAt etc](https://github.com/wekan/wekan/commit/1e0fdf8abc10130ea3c50b13ae97396223ce7fa9).
|
||||
Docs at https://github.com/wekan/wekan/wiki/REST-API-Cards
|
||||
- [Fix cards export and add customFields export](https://github.com/wekan/wekan/pull/1886).
|
||||
|
||||
Thanks to GitHub users ymeramees and xet7 for their contributions.
|
||||
|
||||
# v1.43 2018-09-06 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix "No Comments" permission on Wekan and Trello import](https://github.com/wekan/wekan/commit/0a001d505d81961e6bd6715d885fffee0adb702d).
|
||||
|
||||
Thanks to GitHub user xet7 for contributions.
|
||||
|
||||
# v1.42 2018-09-06 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- REST API: [Create board options to be modifiable](https://github.com/wekan/wekan/commit/9cea76e4efaacaebcb2e9f0690dfeb4ef6d62527),
|
||||
like permissions, public/private board - now private by default,
|
||||
and board background color.
|
||||
Docs at https://github.com/wekan/wekan/wiki/REST-API-Boards
|
||||
- [Add swimlaneId in activity. Create default swimlaneId in API](https://github.com/wekan/wekan/pull/1876).
|
||||
|
||||
Thanks to GitHub users andresmanelli and xet7 for their contributions.
|
||||
|
||||
# v1.41 2018-09-05 Wekan release
|
||||
|
||||
This release tries to fix the following bugs:
|
||||
|
||||
- [Try to fix Wekan Sandstorm API](https://github.com/wekan/wekan/issues/1279#issuecomment-418440401).
|
||||
|
||||
Thanks to GitHub users ocdtrekkie and xet7 for their contributions.
|
||||
|
||||
# v1.40 2018-09-04 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Add permission "No comments"](https://github.com/wekan/wekan/commit/77efcf71376d3da6c19ad1a4910567263e83c0ca).
|
||||
It is like normal user, but [does not show comments and activities](https://github.com/wekan/wekan/issues/1861).
|
||||
|
||||
Thanks to GitHub user xet7 for contributions.
|
||||
|
||||
# v1.39 2018-08-29 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Only allow ifCanModify users to add dates on cards](https://github.com/wekan/wekan/pull/1867).
|
||||
|
||||
Thanks to GitHub user rjevnikar for contributions.
|
||||
|
||||
# v1.38 2018-08-29 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- Add [msavin:userCache](https://github.com/msavin/userCache) to speedup Wekan.
|
||||
See [meteor forums post](https://forums.meteor.com/t/introducing-a-new-approach-to-meteor-user-this-simple-trick-can-save-you-millions-of-database-requests/45336/7).
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix Delete Board](https://github.com/wekan/wekan/commit/534b20fedac9162d2d316bd74eff743d636f2b3d).
|
||||
|
||||
Thanks to GitHub users msavin, rjevnikar and xet7 for their contributions.
|
||||
|
||||
# v1.37 2018-08-28 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Add Missing Index on cards.parentId since Swimlane integration
|
||||
to speedup Wekan](https://github.com/wekan/wekan/issues/1863);
|
||||
- [Update OpenShift template to add Route and parameterize](https://github.com/wekan/wekan/pull/1865);
|
||||
- [Fix typos in Wekan snap help](https://github.com/wekan/wekan/commit/0c5fc6d7fd899a6bc67a446ab43e53290d8571e4).
|
||||
|
||||
Thanks to GitHub users Clement87, InfoSec812 and xet7 for their contributions.
|
||||
|
||||
# v1.36 2018-08-25 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [OAuth2 Login on Standalone Wekan](https://github.com/wekan/wekan/wiki/OAuth2). For example, Rocket.Chat can provide OAuth2 login to Wekan.
|
||||
Also, if you have Rocket.Chat using LDAP/SAML/Google/etc for logging into Rocket.Chat, then same users can login to Wekan when
|
||||
Rocket.Chat is providing OAuth2 login to Wekan.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Move labels back to original place at minicard](https://github.com/wekan/wekan/issues/1842);
|
||||
- [Fix typos in security documentation](https://github.com/wekan/wekan/pull/1857).
|
||||
|
||||
Thanks to GitHub users hever, salleman33, tlevine and xet7 for their contributions.
|
||||
|
||||
# v1.35 2018-08-23 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
Add Caddy plugins:
|
||||
- [http.filter](https://caddyserver.com/docs/http.filter)
|
||||
for changing Wekan UI on the fly, for example custom logo,
|
||||
or changing to all different CSS file to have custom theme;
|
||||
- [http.ipfilter](https://caddyserver.com/docs/http.ipfilter)
|
||||
to block requests by ip address;
|
||||
- [http.realip](https://caddyserver.com/docs/http.realip)
|
||||
for showing real X-Forwarded-For IP to behind proxy;
|
||||
- Turn off Caddy telemetry.
|
||||
|
||||
Add configuring webhooks:
|
||||
- [Make the attributes that the webhook sends configurable](https://github.com/wekan/wekan/pull/1852).
|
||||
|
||||
Thanks to Caddy contributors, and Github users omarsy and xet7 for their contributions.
|
||||
|
||||
# v1.34 2018-08-22 Wekan release
|
||||
|
||||
This release add the following new features:
|
||||
|
||||
- [Add Favicon for pinned tab on Safari browser](https://github.com/wekan/wekan/issues/1795).
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Restored SMTP settings at Admin Panel, and disabled showing password](https://github.com/wekan/wekan/issues/1790);
|
||||
- [Move color labels on minicard to bottom of minicard](https://github.com/wekan/wekan/issues/1842);
|
||||
- [Fix and improve linked cards](https://github.com/wekan/wekan/pull/1849);
|
||||
- [Allow Sandstorm to serve Wekan HTTP API](https://github.com/wekan/wekan/pull/1851);
|
||||
|
||||
Thanks to GitHub users andresmanelli, ocdtrekkie, therampagerado, woodyart and xet7 for their contributions.
|
||||
|
||||
# v1.33 2018-08-16 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Change default value of label ids](https://github.com/wekan/wekan/pull/1837).
|
||||
|
||||
Thanks to GitHub user omarsy for contributions.
|
||||
|
||||
# v1.32 2018-08-16 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Content Policy: Allow inline scripts, otherwise there is errors in browser/inspect/console](https://github.com/wekan/wekan/commit/807c6ce09e4b5d49049d343d73bbca24fa84d527);
|
||||
- [Use only framing policy, not all of content policy](https://github.com/wekan/wekan/commit/b3005f828dbf69bdf174d4bcd7654310fa9e0968);
|
||||
- [Set default matomo settings to disabled](https://github.com/wekan/wekan/commit/807c6ce09e4b5d49049d343d73bbca24fa84d527);
|
||||
- Fix [hidden](https://github.com/wekan/wekan/commit/be00465e67931f2a5655ed47f6e075ed1c589f54)
|
||||
[system](https://github.com/wekan/wekan/commit/9fc3de8502919f9aeb18c9f8ea3b0678b66ce176) [messages](https://github.com/wekan/wekan/issues/1830);
|
||||
- Fix [Requested By](https://github.com/wekan/wekan/commit/e55d7e4f72a4b425c4aca5ba04a7be1fc642649b) and
|
||||
[Assigned By](https://github.com/wekan/wekan/commit/5c33a8534186920be642be8e2ac17743a54f16db) [fields](https://github.com/wekan/wekan/issues/1830);
|
||||
- [Fix Date and Time Formats are only US in every language](https://github.com/wekan/wekan/commit/b3005f828dbf69bdf174d4bcd7654310fa9e0968).
|
||||
|
||||
Thanks to GitHub users andresmanelli and xet7 for their contributions.
|
||||
|
||||
# v1.31 2018-08-14 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Export of Board does not work on Docker](https://github.com/wekan/wekan/issues/1820).
|
||||
|
||||
Thanks to GitHub user xet7 for contributions.
|
||||
|
||||
# v1.30 2018-08-14 Wekan release
|
||||
|
||||
This release add the following new features:
|
||||
|
||||
- [When Content Policy is enabled, allow one URL to have iframe that embeds Wekan](https://github.com/wekan/wekan/commit/b9929dc68297539a94d21950995e26e06745a263);
|
||||
- [Add option to turn off Content Policy](https://github.com/wekan/wekan/commit/b9929dc68297539a94d21950995e26e06745a263);
|
||||
- [Allow always in Wekan markdown `<img src="any-image-url-here">`](https://github.com/wekan/wekan/commit/b9929dc68297539a94d21950995e26e06745a263).
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix Import from Trello error 400](https://github.com/wekan/wekan/commit/2f557ae3a558c654cc6f3befff22f5ee4ea6c3d9).
|
||||
|
||||
Thanks to GitHub user xet7 for contributions.
|
||||
|
||||
# v1.29 2018-08-12 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Revert Fix lint errors, that caused breakage](https://github.com/wekan/wekan/commit/b015b5b7240f5fb5a715843dce5d35907345eb4a).
|
||||
|
||||
Thanks to GitHub user xet7 for contributions.
|
||||
|
||||
# v1.28 2018-08-12 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix lint errors](https://github.com/wekan/wekan/commit/f5515cb95fc93882e5e1098d6043267b9260b9d7).
|
||||
|
||||
Thanks to GitHub user xet7 for contributions.
|
||||
|
||||
# v1.27 2018-08-12 Wekan release
|
||||
|
||||
This release add the following new features:
|
||||
|
||||
- [Linked Cards and Linked Boards](https://github.com/wekan/wekan/pull/1592).
|
||||
|
||||
Thanks to GitHub user andresmanelli for contributions.
|
||||
|
||||
# v1.26 2018-08-09 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Set WITH_API=true setting on Sandstorm, and so that export works](https://github.com/wekan/wekan/commit/a300b73d56750a1a5645767d375be60839314e84);
|
||||
- [Set Matomo blank settings on Sandstorm](https://github.com/wekan/wekan/commit/acd105e61b9dca5a78354047bbc23b0a01e71d8c).
|
||||
|
||||
Thanks to GitHub user xet7 for contributions.
|
||||
|
||||
# v1.25 2018-08-09 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix showing only the cards of the current board in calendar view](https://github.com/wekan/wekan/pull/1822).
|
||||
|
||||
Thanks to GitHub user Yanonix for contributions.
|
||||
|
||||
# v1.24 2018-08-09 Wekan release
|
||||
|
||||
This release add the following new features:
|
||||
|
||||
- [Update node to v8.12.0 prerelease build](https://github.com/wekan/wekan/commit/04d7c47f4ca990311079be8dd6dc383448ee342f).
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Enable Wekan API by default, so that Export Board to JSON works](https://github.com/wekan/wekan/commit/b2eeff96977592deaeb23a8171fc3b13f8c6c5dc);
|
||||
- [Fix the flagging of dates](https://github.com/wekan/wekan/pull/1814);
|
||||
- [Use new WITH_API and Matomo env variables at Dockerfile](https://github.com/wekan/wekan/issues/1820);
|
||||
- For OpenShift compliance, [change](https://github.com/wekan/wekan/commit/53d545eeef7e796bd910f7cce666686ca05de544)
|
||||
[run user](https://github.com/wekan/wekan/pull/1816)
|
||||
and [Docker internal port to 8080](https://github.com/wekan/wekan/commit/95b21943ee7a9fa5a27efe5276307febc2fbad94).
|
||||
|
||||
Thanks to GitHub users rjevnikar, tdemaret, xadagaras and xet7 for their contributions.
|
||||
|
||||
# v1.23 2018-07-30 Wekan release
|
||||
|
||||
This release tries to fix the following bugs:
|
||||
|
||||
- Checking for [existing](https://github.com/wekan/wekan/commit/a48f560a85860451914dbaad8cae6ff5120a0c38)
|
||||
[directories](https://github.com/wekan/wekan/commit/5bfb6c6411c928bfffa7ed6fe829f030e3ea57da) when
|
||||
building snap etc, trying to [get snap to build somehow](https://github.com/wekan/wekan-snap/issues/58).
|
||||
This is just a test, does it build this time correctly.
|
||||
|
||||
Thanks to GitHub user xet7 for contributions.
|
||||
|
||||
# v1.22 2018-07-30 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Backup script now uses mongodump from snap to
|
||||
do backups](https://github.com/wekan/wekan/wiki/Backup);
|
||||
- [Integration of Matomo](https://github.com/wekan/wekan/pull/1806);
|
||||
- [Enable/Disable API with env var](https://github.com/wekan/wekan/pull/1799).
|
||||
|
||||
Thanks to GitHub user Akuket and xet7 for their contributions.
|
||||
|
||||
# v1.21 2018-07-18 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Add logo from Wekan website to login logo](https://github.com/wekan/wekan/commit/4eed23afe06d5fab8d45ba3decc7c1d3b85efbd8).
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Allow to resend invites](https://github.com/wekan/wekan/pull/1785).
|
||||
|
||||
Thanks to GitHub users Akuket and xet7 for their contributions.
|
||||
|
||||
# v1.20 2018-07-18 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Remove SMTP settings from Admin Panel, because they are set in environment
|
||||
variable settings like source/snap/docker already, and password was
|
||||
exposed in plain text](https://github.com/wekan/wekan/issues/1783);
|
||||
- [Added info how to limit snap to root
|
||||
user](https://github.com/wekan/wekan-snap/wiki/Limit-snap-to-root-user-only);
|
||||
- [Add scrolling to long cards](https://github.com/wekan/wekan/pull/1782).
|
||||
|
||||
Thanks to GitHub users jnso, LyR33x and xet7 for their contributions.
|
||||
|
||||
# v1.19 2018-07-16 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Build from source on macOS](https://github.com/wekan/wekan/wiki/Mac);
|
||||
- [Wekan integration with OpenShift](https://github.com/wekan/wekan/pull/1765);
|
||||
- [Snap Caddy: set -agree flag for Let's Encrypt](https://github.com/wekan/wekan-snap/issues/54).
|
||||
|
||||
and fixes the following mobile bugs:
|
||||
|
||||
- [Fix missing utility function](https://github.com/wekan/wekan/commit/5c774070617357c25c7bb35b43f4b122eb4b3e34);
|
||||
- [Avoid default behavior](https://github.com/wekan/wekan/commit/9c204d9bbe4845bc3e352e839615dfb782a753f4);
|
||||
- [Hotfix more sortable elements](https://github.com/wekan/wekan/commit/616dade81c25b10fc409aee1bcc9a93ddbfee81b);
|
||||
- [Hotfix for mobile device](https://github.com/wekan/wekan/commit/43d86d7d5d3f3b34b0500f6d5d3afe7bd86b0060).
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix invitation code](https://github.com/wekan/wekan/pull/1777).
|
||||
|
||||
Thanks to GitHub users adyachok, Akuket, halunk3, Haocen and xet7 for their contributions.
|
||||
|
||||
# v1.18 2018-07-06 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- Fix [Title is required](https://github.com/wekan/wekan/issues/1576)
|
||||
by [setting Checklist title during migration](https://github.com/wekan/wekan/issues/1753).
|
||||
|
||||
Thanks to GitHub users centigrade-kdk and xet7 for their contributions.
|
||||
|
||||
# v1.17 2018-07-06 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Made Subtask Settings visible at Board menu at Sandstorm](https://github.com/wekan/wekan/commit/884cd0e6b888edc9752cbed80e7ac75e2ce232de).
|
||||
|
||||
Thanks to GitHub user xet7 for contributions.
|
||||
|
||||
# v1.16 2018-07-06 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- Fix: [Boards.forEach is not function](https://github.com/wekan/wekan/commit/a41190cdf024df65ad1c9931b3065c6ababeaf25).
|
||||
|
||||
Thanks to GitHub user xet7 for contributions.
|
||||
|
||||
# v1.15 2018-07-06 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- Fix [Title is required](https://github.com/wekan/wekan/issues/1576)
|
||||
by making [Checklist title optional](https://github.com/wekan/wekan/issues/1753).
|
||||
|
||||
Thanks to GitHub users centigrade-kdk and xet7 for their contributions.
|
||||
|
||||
# v1.14 2018-07-06 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- Fix [Checklists.forEach is not a function](https://github.com/wekan/wekan/issues/1753).
|
||||
|
||||
Thanks to GitHub user xet7 for contributions.
|
||||
|
||||
# v1.13 2018-07-06 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- Added snapcraft.yml new node version changes, that were missing from v1.12.
|
||||
|
||||
Thanks to GitHub user xet7 for contibutions.
|
||||
|
||||
# v1.12 2018-07-06 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Nested tasks](https://github.com/wekan/wekan/pull/1723);
|
||||
- [Calendar improvements](https://github.com/wekan/wekan/pull/1752);
|
||||
- [SSO CAS](https://github.com/wekan/wekan/pull/1742).
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix warning about missing space in jade file](https://github.com/wekan/wekan/commit/067aef9de948ef0cb6037d52602100b00d214706);
|
||||
- Revert [Fix vertical align of user avatar initials](https://github.com/wekan/wekan/pull/1714), so that [initials are again
|
||||
visible](https://github.com/wekan/wekan/commit/122a61b3333fb77c0f08bbdc6fe0d3c2f6db97df);
|
||||
- Fix lint warning: [EditCardDate is assigned a value but never used
|
||||
no-unused-vars](https://github.com/wekan/wekan/commit/dd324aa581bed7ea31f20968c6b596f373e7054f);
|
||||
- Fix [Minimize board sidebar actually just moves it over](https://github.com/wekan/wekan/issues/1589).
|
||||
|
||||
Thanks to GitHub users dagomar, ppoulard, pravdomil, TNick and xet7 for their contributions.
|
||||
|
||||
# v1.11 2018-06-30 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
* [Remove card shadow](https://github.com/wekan/wekan/pull/1726), Wekan users now prefer not to have it;
|
||||
* [Revert](https://github.com/wekan/wekan/commit/928d88cfe1da4187797519c929cd2fdd9ffe9c2e) previous
|
||||
[Less margin-bottom after minicard](https://github.com/wekan/wekan/pull/1713).
|
||||
|
||||
Thanks to GitHub users pravdomil and xet7 for their contributions.
|
||||
|
||||
# v1.10 2018-06-28 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
* Fix migration error "TypeError: Checklists.foreach" at [Snap](https://github.com/wekan/wekan-snap/issues/51),
|
||||
[Docker](https://github.com/wekan/wekan/issues/1736) etc.
|
||||
|
||||
Thanks to GitHub users Jubi94, kestrelhawk and xet7 for their contributions.
|
||||
|
||||
# v1.09 2018-06-28 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
* [Calendar](https://github.com/wekan/wekan/pull/1728). Click Lists / Swimlanes / Calendar.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
* To fix ["title is required"](https://github.com/wekan/wekan/issues/1576) fix only
|
||||
[add-checklist-items and revert all other migration changes](https://github.com/wekan/wekan/issues/1734);
|
||||
* [Restore invitation code logic](https://github.com/wekan/wekan/pull/1732). Please test and add comment
|
||||
to those invitation code issues that this fixes.
|
||||
|
||||
Thanks to GitHub users TNick and xet7 for their contributions.
|
||||
|
||||
# v1.08 2018-06-27 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
* [Add more card inner shadow](https://github.com/wekan/wekan/commit/6a587299b80a49fce0789628ff65885b5ed2c837);
|
||||
* [Less margin-bottom after minicard](https://github.com/wekan/wekan/pull/1713);
|
||||
* Updated newest node fork binary from Sandstorm to Wekan, see https://releases.wekan.team/node.txt
|
||||
* Add Georgian language.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
* [Fix typo in English translation](https://github.com/wekan/wekan/pull/1710);
|
||||
* [Fix vertical align of user avatar initials](https://github.com/wekan/wekan/pull/1714);
|
||||
* [Submit inline form on click outside](https://github.com/wekan/wekan/pull/1717), fixes
|
||||
["You have an unsaved description" doesn't go away after saving](https://github.com/wekan/wekan/issues/1287);
|
||||
* [Fix "Error: title is required" by removing find() from all of migrations](https://github.com/wekan/wekan/commit/97922c90cb42be6c6615639bb164173748982f56).
|
||||
|
||||
Thanks to GitHub users pravdomil, xet7 and zypA13510 for their contributions.
|
||||
|
||||
# v1.07 2018-06-14 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
* [Regex for Advanced filter. It aims to solve search in bigger text fields, and using wildcards.
|
||||
A change to translations was made for adding info about regex and escaping characters
|
||||
with \\](https://github.com/wekan/wekan/pull/1702).
|
||||
|
||||
Thanks to GitHub users feuerball11 and xet7 for their contributions.
|
||||
|
||||
# v1.06 2018-06-14 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
* [Fix CardDetail of Mobile View](https://github.com/wekan/wekan/pull/1701).
|
||||
|
||||
Thanks to GitHub users feuerball11 and xet7 for their contributions.
|
||||
|
||||
# v1.05 2018-06-14 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
* [Markdown support in Custom Fields, and view on minicard](https://github.com/wekan/wekan/pull/1699);
|
||||
* [Fixes to Advanced Filter, you are now able to filter for Dropdown and Numbers,
|
||||
also Dropdown are now correctly displayed on minicard](https://github.com/wekan/wekan/pull/1699).
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
* [Fix data colour changes on cards](https://github.com/wekan/wekan/pull/1698);
|
||||
* [Fix for migration error "title is required" and breaking of Standalone and
|
||||
Sandstorm Wekan](https://github.com/wekan/wekan/commit/8d5cbf1e6c2b6d467fe1c0708cd794fd11b98a2e#commitcomment-29362180);
|
||||
* [Fix Issue with custom fields shown on card](https://github.com/wekan/wekan/issues/1659);
|
||||
* [Fix showing public board in list mode](https://github.com/wekan/wekan/issues/1623);
|
||||
* [Fix for not able to remove Custom Field "Show on Card"](https://github.com/wekan/wekan/pull/1699);
|
||||
* [Fix minicardReceivedDate typo in 1.04 regression: Socket connection error and boards
|
||||
not loading](https://github.com/wekan/wekan/issues/1694).
|
||||
|
||||
Thanks to GitHub users feuerball11, Fran-KTA, oec, rjevnikar and xet7 for their contributions.
|
||||
|
||||
# v1.04 2018-06-12 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
* [Add Khmer language](https://github.com/wekan/wekan/commit/2156e458690d0dc34a761a48fd7fa3b54af79031);
|
||||
* [Change label text colour to black for specific label colours for better
|
||||
visibility](https://github.com/wekan/wekan/pull/1689).
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
* [SECURITY FIX: Do not publish all of people collection. This bug has probably been present
|
||||
since addition of Admin Panel](https://github.com/wekan/wekan/commit/dda49d2f07f9c50d5d57acfd5c7eee6492f93b33);
|
||||
* [Modify card covers/mini-cards so that: 1) received date is shown unless there is a start date
|
||||
2) due date is shown, unless there is an end date](https://github.com/wekan/wekan/pull/1685).
|
||||
|
||||
Thanks to GitHub users rjevnikar and xet7 for their contributions.
|
||||
Thanks to Adrian Genaid for security fix, he's now added to [Hall of Fame](https://wekan.github.io/hall-of-fame/).
|
||||
Thanks to translators.
|
||||
|
||||
# v1.03 2018-06-08 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
* [Update to newest Sandstorm fork of Node.js that includes performance
|
||||
etc fixes](https://github.com/wekan/wekan/commit/90d55777f7298d243ed0de03c934cea239a31272);
|
||||
* [Additional label colors. Assigned By and Requested By text fields
|
||||
on card. Delete board from Recycle Bin](https://github.com/wekan/wekan/pull/1679).
|
||||
|
||||
and possibly fixes the following bugs, please test:
|
||||
|
||||
* [Try to fix: Missing board-view-lists Field after DB updated to
|
||||
Wekan 1.02](https://github.com/wekan/wekan/issues/1675).
|
||||
|
||||
Thanks to GitHub users JamesLavin, rjevnikar and xet7 for their contributions.
|
||||
|
||||
# v1.02 2018-05-26 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
* [Remove binary version of bcrypt](https://github.com/wekan/wekan/commit/4b2010213907c61b0e0482ab55abb06f6a668eac)
|
||||
because of [vulnerability](https://nodesecurity.io/advisories/612) that has [issue that is not fixed
|
||||
yet](https://github.com/kelektiv/node.bcrypt.js/issues/604)
|
||||
and [not yet merged pull request](https://github.com/kelektiv/node.bcrypt.js/pull/606).
|
||||
This may cause some slowdown;
|
||||
* [Snap: Filtering out swap file created at build time, adding stage package](https://github.com/wekan/wekan/pull/1660);
|
||||
* [Fix Received Date and End Date on Cards](https://github.com/wekan/wekan/issues/1654).
|
||||
|
||||
Thanks to GitHub users kubiko, xadagaras and xet7 for their contributions.
|
||||
|
||||
# v1.01 2018-05-23 Wekan release
|
||||
|
||||
This release possibly fixes the following bugs, please test:
|
||||
|
||||
* [Possible quickfix for all customFields Import errors, please test](https://github.com/wekan/wekan/pull/1653).
|
||||
|
||||
Thanks to GitHub users feuerball11 and xet7 for their contributions.
|
||||
|
||||
# v1.00 2018-05-21 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
* [Typo in English translation: brakets to brackets](https://github.com/wekan/wekan/issues/1647).
|
||||
|
||||
Thanks to GitHub user yarons for contributions.
|
||||
|
||||
# v0.99 2018-05-21 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
* [Advanced Filter for Custom Fields](https://github.com/wekan/wekan/pull/1646).
|
||||
|
||||
Thanks to GitHub users feuerball11 and xet7 for their contributions.
|
||||
|
||||
# v0.98 2018-05-19 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
* [Filtering by Custom Field](https://github.com/wekan/wekan/pull/1645);
|
||||
* Update to NPM 6.0.1 and MongoDB 3.2.20.
|
||||
|
||||
Thanks to GitHub users feuerball11 and xet7 for their contributions.
|
||||
|
||||
# v0.97 2018-05-19 Wekan release
|
||||
|
||||
Updated translations.
|
||||
|
||||
# v0.96 2018-05-19 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
* [Custom Fields](https://github.com/wekan/wekan/issues/807). Note: Import/Export is not implemented yet.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
* [Fix: checklistItems broken after upgrade](https://github.com/wekan/wekan/issues/1636).
|
||||
|
||||
Thanks to GitHub users feuerball11, franksiler, papoola and xet7 for their contributions.
|
||||
|
||||
# v0.95 2018-05-08 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
* [REST API Edit Card Labels](https://github.com/wekan/wekan/pull/1626);
|
||||
* [Add a new API route to create a new label in a given board](https://github.com/wekan/wekan/pull/1630);
|
||||
* [Admin Panel: Option to block username change](https://github.com/wekan/wekan/pull/1627).
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
* [Error: title is required](https://github.com/wekan/wekan/issues/1576).
|
||||
|
||||
Thanks to GitHub users Shahar-Y, thiagofernando and ThisNeko for their contributions.
|
||||
|
||||
# v0.94 2018-05-03 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
* [REST API POST /cards: allow setting card members](https://github.com/wekan/wekan/pull/1622).
|
||||
|
||||
Thanks to GitHub user couscous3 for contributions.
|
||||
|
||||
# v0.93 2018-05-02 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
* [Checklist items lineheight to 18px, and positioning
|
||||
improvements](https://github.com/wekan/wekan/issues/1619).
|
||||
|
||||
Thanks to GitHub user lichtamberg for contributions.
|
||||
|
||||
# v0.92 2018-05-01 Wekan release
|
||||
|
||||
This release tries to fix the following bugs, please test:
|
||||
|
||||
* [Users who register with an invitation code can't see lists/cards](https://github.com/wekan/wekan/issues/1610).
|
||||
|
||||
Thanks to GitHub user andresmanelli for contributions.
|
||||
|
||||
# v0.91 2018-05-01 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix Wekan Import / Export lists not being sortable](https://github.com/wekan/wekan/commit/539c1ab87a098a7ddfd23cdbd663441bd609b73d).
|
||||
|
||||
Thanks to GitHub user zebby76 for contributions.
|
||||
|
||||
# v0.90 2018-05-01 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Remove space from between checklist items, so longer checklists can be seen
|
||||
at once](https://github.com/wekan/wekan/commit/1124f4120cd77622c0a6313e228e1a00690ff566).
|
||||
|
||||
Thanks to GitHub user xet7 for contributions.
|
||||
|
||||
# v0.89 2018-04-29 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix Wekan import / Export for ChecklistItems](https://github.com/wekan/wekan/pull/1613).
|
||||
|
||||
Thanks to GitHub user zebby76 for contributions.
|
||||
|
||||
# v0.88 2018-04-27 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix Trello import of ChecklistItems](https://github.com/wekan/wekan/pull/1611).
|
||||
|
||||
Thanks to GitHub user zebby76 for contributions.
|
||||
|
||||
# v0.87 2018-04-27 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Sandstorm: Copy Card, Move Card and Copy Checklist Template to Many Cards - No longer works in
|
||||
menu](https://github.com/wekan/wekan/commit/db80e738048e2729917c5e8fc18cf8ee44df7992);
|
||||
- [Snap: Use override-build instead of old deprecated
|
||||
prepare/build/install](https://github.com/wekan/wekan/commit/075ea1c43d827099e0030c750a4c156bd3340fed);
|
||||
- [Removed not-used plugins part of Caddy download
|
||||
URL](https://github.com/wekan/wekan/commit/7b91b341fe9c0cde42f91bf14d228820653c883d).
|
||||
|
||||
Thanks to GitHub users kyrofa and xet7 for their contributions.
|
||||
|
||||
# v0.86 2018-04-20 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- Updated translations: German and Turkish;
|
||||
- Updated Caddy to newest version for Snap.
|
||||
|
||||
Thanks to translators and Caddy developers.
|
||||
|
||||
# v0.85 2018-04-18 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix Switch List/swimlane view only working with admin privileges](https://github.com/wekan/wekan/issues/1567);
|
||||
- [Fix Wekan logo positioning](https://github.com/wekan/wekan/issues/1378);
|
||||
- [Tried to fix, but fix did not work: Fix checklists items migration error "title is required"](https://github.com/wekan/wekan/issues/1576);
|
||||
- [Removed paxctl alpine fix #1303 , because it did not work anymore, so Docker container
|
||||
did not build correctly](https://github.com/wekan/wekan/commit/ce659632174ba25ca9b5e85b053fde02fd9c3928);
|
||||
- [Use curl to download 100% CPU fibers fixed node in snap, and remove paxctl from
|
||||
snap package](https://github.com/wekan/wekan/commit/179ff7a12457be1592f04e1bdc15a5bb4fe9d398).
|
||||
|
||||
Thanks to GitHub users andresmanelli, iwkse and xet7 for their contributions.
|
||||
|
||||
# v0.84 2018-04-16 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Add Checklist Items REST API](https://github.com/wekan/wekan/commit/9eef5112dc1c1c30590d19fbfd2f615714112a3f).
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix Node Fibers 100% CPU issue](https://github.com/wekan/wekan/commit/e26a4824cfb119a15767c4827190a6b9ab65b904);
|
||||
- [Plus button on a Swimlane row, always add an element on the first row](https://github.com/wekan/wekan/issues/1577);
|
||||
- [Fix Checklist REST API](https://github.com/wekan/wekan/commit/9eef5112dc1c1c30590d19fbfd2f615714112a3f);
|
||||
- [Fix Disabling "show cards count" not possible, now zero means disable](https://github.com/wekan/wekan/issues/1570);
|
||||
- [Fix Checklist not copied when copied a card and Copy Checklist Template to Many Cards](https://github.com/wekan/wekan/issues/1565);
|
||||
- [Fix Filter cards hides checklist items](https://github.com/wekan/wekan/issues/1561).
|
||||
|
||||
Thanks to GitHub users andresmanelli, kentonv and xet7 for their contributions.
|
||||
|
||||
# v0.83 2018-04-12 Wekan release
|
||||
|
||||
- Updated translations: Czech and French.
|
||||
|
||||
Thanks to translators!
|
||||
|
||||
# v0.82 2018-04-11 Wekan release
|
||||
|
||||
- [Restore original font and font sizes. Admin panel people and version texts
|
||||
to darker](https://github.com/wekan/wekan/commit/db74c86e555f45a5aaaef84d2f3d4128cec77782).
|
||||
|
||||
Thanks to GitHub users apn3a and xet7 for their contributions.
|
||||
|
||||
# v0.81 2018-04-10 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Removed checkbox from checklist name to have more of material design look](https://github.com/wekan/wekan/issues/1568);
|
||||
- [Renamed Archives to Recycle Bin](https://github.com/wekan/wekan/issues/1429);
|
||||
- [Separate translations for cards in Recycle Bin and cards count](https://github.com/wekan/wekan/commit/49c7a6c223061b9c1769143fea32fecc7d0f3c3e);
|
||||
- [Use lighter and smaller font sizes](https://github.com/wekan/wekan/commit/7b94b0470198bc22b6a52db6661f35076f7c6388);
|
||||
- [Board title as markdown in board view](https://github.com/wekan/wekan/commit/7b94b0470198bc22b6a52db6661f35076f7c6388).
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Removed forcing "cards" translations to lowercase in count of cards](https://github.com/wekan/wekan/issues/1571).
|
||||
|
||||
Thanks to GitHub users BruceZCQ, Chartman123, quantazelle and xet7 for their contributions.
|
||||
|
||||
# v0.80 2018-04-04 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Changed icon of checklist name to unchecked](https://github.com/wekan/wekan/pull/1559/commits/f9539aa2a8d806e5a158d1c32f74788d051d40cb);
|
||||
- [Added meteor packages](https://github.com/wekan/wekan/commit/40d438a517f0d807894e04873358aecf44fa7c4d)
|
||||
for security: [browser-policy](https://atmospherejs.com/meteor/browser-policy) and
|
||||
[eluck:accounts-lockout](https://atmospherejs.com/eluck/accounts-lockout).
|
||||
|
||||
Thanks to GitHub users quantazelle and xet7 for their contributions.
|
||||
|
||||
# v0.79 2018-03-31 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Checklist items sort fix, and checklist sort capability](https://github.com/wekan/wekan/pull/1543);
|
||||
- [Add Received Date and End Date. Between them is already existing Start and Due Date](https://github.com/wekan/wekan/pull/1550).
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix drag in lists view](https://github.com/wekan/wekan/pull/1559/commits/679e50af6449a680f958256570e8b9f1944a3a92);
|
||||
- [Set fixed width for swimlane header](https://github.com/wekan/wekan/pull/1559/commits/2e8f8924dd0d985ae4634450cfbef04e88e5d954).
|
||||
|
||||
Thanks to GitHub users andresmanelli, rjevnikar and xet7 for their contributions.
|
||||
|
||||
# v0.78 2018-03-17 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Allow swimlanes reordering](https://github.com/wekan/wekan/commit/37c94622e476f50bf2387bc8b140454d66200e78);
|
||||
- [Import missing card fields: isOvertime, startAt and spentTime](https://github.com/wekan/wekan/commit/b475127c53031fa498da139a7d16f3e54d43b90d);
|
||||
- [Lists view is the default view when creating boards](https://github.com/wekan/wekan/commit/1ca9e96f35389c0eec2290e8e1207801ee25f907);
|
||||
- [Enabled import at Sandtorm. Keep there big DANGER warning about data loss bug.](https://github.com/wekan/wekan/commit/22923d08af4f1a63ded1d92fe6918436b598592b);
|
||||
- [Add language: Armenian](https://github.com/wekan/wekan/commit/75693d16e2a0f3d201c1036ab06e6d40eb1c0adc).
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix lint errors related to sandstorm](https://github.com/wekan/wekan/commit/0a16147470246c8f49bb918f5ddc7bb2e54fba14);
|
||||
- [Add Swimlanes to globals](https://github.com/wekan/wekan/commit/373e9782dcf87a9c1169b5d1f8175ce14e4898c9);
|
||||
- [Fix lint errors related to trello creator](https://github.com/wekan/wekan/commit/951a0db380d60f3d948ae38d50b85a54983a51de);
|
||||
- [Fix lint errors related to language names](https://github.com/wekan/wekan/commit/c0d33d97f2c8d4e9371a03d4ad3022df3ed64d3d);
|
||||
- [Avoid swimlane title overlap](https://github.com/wekan/wekan/commit/c4fa9010f34966b633c7bf7e46ad49fc101127c9);
|
||||
- [Fix scrollbar inside list and outer scroll](https://github.com/wekan/wekan/commit/a033c35a3411902b9bf8f62a40cd68f641e573d3);
|
||||
- [Remove list max-height 350px](https://github.com/wekan/wekan/commit/b6d3e79548d1e88c93fa2965a936595176a95565);
|
||||
- [Snap: Adding network hooks for configure hook to fix security denials](https://github.com/wekan/wekan/commit/9084158aece8a642dc49bf7ecc2196bf9d1af63e);
|
||||
- [Snap: Fixing problem when mongodb was not started at install/refresh](https://github.com/wekan/wekan/commit/1be8e5625fd20797910009a8221ca706fd52ab11);
|
||||
- [Fix Add Card Button dissapearing when dragging](https://github.com/wekan/wekan/commit/58e5e9b308113e5a8af5166328a68a0aafcc2558);
|
||||
- [Fix Scrollbar near top of screen when using internet explorer on Win7](https://github.com/wekan/wekan/commit/128a356b9222fa0ed824b477c2d0e1e6a0368021);
|
||||
- [Fix scroll when dragging elements. Remove scrollbars from swimlanes.](https://github.com/wekan/wekan/commit/ed8471be9b79243b016a275e5b11a6912717fbb9);
|
||||
- [Partial fix for scroll bar inside cardDetails](https://github.com/wekan/wekan/commit/ac7d44f8a8d809cd94ed5ef3640473f34c72403b);
|
||||
- [Fix swimlane header rotation on Google Chrome. After this change both Firefox 58 and Google Chrome 64
|
||||
have properly rotated swimlane header.](https://github.com/wekan/wekan/commit/9a1b1a5bedbe44827de109731a3c3b1a07790d3e);
|
||||
- [Fix card copy and move with swimlanes](https://github.com/wekan/wekan/commit/4b53b0c90a57593c0fe2d808d2298e85f488bfa9).
|
||||
- [Fix scroll board when opening cardDetails](https://github.com/wekan/wekan/commit/454523dd4744b2bccb6805dad59abd664fdacb31);
|
||||
- [Fix swimlane info not displayed in activities](https://github.com/wekan/wekan/commit/bb37d8fa964c0d03721a664387e74300fde09eef);
|
||||
- [Fix sandstorm default swimlane creation](https://github.com/wekan/wekan/commit/f470323ee746c4e79f07d166d511867408194eb6);
|
||||
- [Extend lists to bottom of frame in lists view](https://github.com/wekan/wekan/commit/c62a2ee11febf7f98456c97dc3973509b4bfe119);
|
||||
- [Fix drag and drop issues when re-enter board](https://github.com/wekan/wekan/commit/5b0f7f8aef115b202aaff6bc25bb514426dc2009).
|
||||
|
||||
Thanks to GitHub users andresmanelli, GhassenRjab, kubiko, lumatijev, lunatic4ever and xet7 for their contributions.
|
||||
|
||||
# v0.77 2018-02-23 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Search from card titles and descriptions on this board](https://github.com/wekan/wekan/pull/1503).
|
||||
- Add Bulgarian language.
|
||||
|
||||
and adds the following [Snap updates](https://github.com/wekan/wekan/pull/1495):
|
||||
|
||||
- Cleanup of snap helper scripts
|
||||
- Cleanup and snapctl settings handling
|
||||
- Fix for snap store auto review refusal
|
||||
- Adding support for automatic restart of services when setting(s) are changed.
|
||||
No need to call systemctl restart anymore
|
||||
- Fixing snap set functionality
|
||||
- Adding optional caddy service support (by default caddy service is disabled),
|
||||
it can be enabled by calling: snap set wekan caddy-enabled=true
|
||||
- [Service life cycle improvements](https://github.com/wekan/wekan/pull/1495)
|
||||
- [Wekan help text changes and tweaks](https://github.com/wekan/wekan/pull/1495).
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix: card-shadow no longer covered the page if you scroll down](https://github.com/wekan/wekan/pull/1496).
|
||||
|
||||
Thanks to GitHub users GhassenRjab, kubiko and stefano-pogliani for their contributions.
|
||||
|
||||
# v0.76 2018-02-21 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Add swimlaneId to POST /api/boards/:boardId/lists/:listId/cards route](https://github.com/wekan/wekan/commit/ee0f42eeb1b10107bd8fc38cdefbdbc4f3fde108);
|
||||
- [Added path to capnp.js to make Wekan work on Sandstorm](https://github.com/wekan/wekan/commit/11e9811f82858a3d98036e142b0da69d867adebc).
|
||||
|
||||
Known bugs:
|
||||
|
||||
- [Disabled Import temporarily on Sandstorm because of data loss bug](https://github.com/wekan/wekan/commit/e30f6515c623de7a48f25e0b2fc75313ae5d187c);
|
||||
- [Swimlane not visible at Sandstorm](https://github.com/wekan/wekan/issues/1494).
|
||||
|
||||
Thanks to GitHub users couscous3 and xet7 for their contributions.
|
||||
|
||||
# v0.75 2018-02-16 Wekan release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Checklist templates](https://github.com/wekan/wekan/pull/1470);
|
||||
- Added [Finnish language changelog](https://github.com/wekan/wekan/tree/devel/meta/t9n-changelog)
|
||||
and [more Finnish traslations](https://github.com/wekan/wekan/blob/devel/sandstorm-pkgdef.capnp)
|
||||
to Sandstorm.
|
||||
|
||||
Thanks to GitHub users erikturk and xet7 for their contributions.
|
||||
|
||||
# v0.74 2018-02-13 Wekan release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Remove Emoji support, so MAC addresses etc show correctly](https://github.com/wekan/wekan/commit/056843d66c361594d5d4478cfe86e2e405333b91).
|
||||
NOTE: You can still add Unicode Emojis, this only removes broken autoconversion to Emojis.
|
||||
|
||||
Thanks to GitHub user xet7 for contributions.
|
||||
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
To get started, [please sign the Contributor License Agreement](https://www.clahub.com/agreements/wekan/wekan).
|
||||
|
||||
[Then, please read documentation at wiki](https://github.com/wekan/wekan/wiki).
|
||||
|
||||
@@ -1,5 +0,0 @@
|
||||
# Contributing
|
||||
|
||||
Please see wiki for all documentation:
|
||||
|
||||
<https://github.com/wekan/wekan/wiki>
|
||||
+83
-38
@@ -1,5 +1,5 @@
|
||||
FROM debian:buster-slim
|
||||
MAINTAINER wekan
|
||||
LABEL maintainer="wekan"
|
||||
|
||||
# Declare Arguments
|
||||
ARG NODE_VERSION
|
||||
@@ -10,18 +10,47 @@ ARG NPM_VERSION
|
||||
ARG FIBERS_VERSION
|
||||
ARG ARCHITECTURE
|
||||
ARG SRC_PATH
|
||||
ARG WITH_API
|
||||
ARG MATOMO_ADDRESS
|
||||
ARG MATOMO_SITE_ID
|
||||
ARG MATOMO_DO_NOT_TRACK
|
||||
ARG MATOMO_WITH_USERNAME
|
||||
ARG BROWSER_POLICY_ENABLED
|
||||
ARG TRUSTED_URL
|
||||
ARG WEBHOOKS_ATTRIBUTES
|
||||
ARG OAUTH2_CLIENT_ID
|
||||
ARG OAUTH2_SECRET
|
||||
ARG OAUTH2_SERVER_URL
|
||||
ARG OAUTH2_AUTH_ENDPOINT
|
||||
ARG OAUTH2_USERINFO_ENDPOINT
|
||||
ARG OAUTH2_TOKEN_ENDPOINT
|
||||
|
||||
# Set the environment variables (defaults where required)
|
||||
# paxctl fix for alpine linux: https://github.com/wekan/wekan/issues/1303
|
||||
ENV BUILD_DEPS="apt-utils gnupg gosu wget curl bzip2 build-essential python git ca-certificates gcc-7 paxctl"
|
||||
ENV NODE_VERSION ${NODE_VERSION:-v8.9.3}
|
||||
ENV METEOR_RELEASE ${METEOR_RELEASE:-1.6.0.1}
|
||||
ENV USE_EDGE ${USE_EDGE:-false}
|
||||
ENV METEOR_EDGE ${METEOR_EDGE:-1.5-beta.17}
|
||||
ENV NPM_VERSION ${NPM_VERSION:-5.5.1}
|
||||
ENV FIBERS_VERSION ${FIBERS_VERSION:-2.0.0}
|
||||
ENV ARCHITECTURE ${ARCHITECTURE:-linux-x64}
|
||||
ENV SRC_PATH ${SRC_PATH:-./}
|
||||
# DOES NOT WORK: paxctl fix for alpine linux: https://github.com/wekan/wekan/issues/1303
|
||||
# ENV BUILD_DEPS="paxctl"
|
||||
ENV BUILD_DEPS="apt-utils gnupg gosu wget curl bzip2 build-essential python git ca-certificates gcc-7" \
|
||||
NODE_VERSION=v8.12.0 \
|
||||
METEOR_RELEASE=1.6.0.1 \
|
||||
USE_EDGE=false \
|
||||
METEOR_EDGE=1.5-beta.17 \
|
||||
NPM_VERSION=latest \
|
||||
FIBERS_VERSION=2.0.0 \
|
||||
ARCHITECTURE=linux-x64 \
|
||||
SRC_PATH=./ \
|
||||
WITH_API=true \
|
||||
MATOMO_ADDRESS="" \
|
||||
MATOMO_SITE_ID="" \
|
||||
MATOMO_DO_NOT_TRACK=true \
|
||||
MATOMO_WITH_USERNAME=false \
|
||||
BROWSER_POLICY_ENABLED=true \
|
||||
TRUSTED_URL="" \
|
||||
WEBHOOKS_ATTRIBUTES="" \
|
||||
OAUTH2_CLIENT_ID="" \
|
||||
OAUTH2_SECRET="" \
|
||||
OAUTH2_SERVER_URL="" \
|
||||
OAUTH2_AUTH_ENDPOINT="" \
|
||||
OAUTH2_USERINFO_ENDPOINT="" \
|
||||
OAUTH2_TOKEN_ENDPOINT=""
|
||||
|
||||
# Copy the app to the image
|
||||
COPY ${SRC_PATH} /home/wekan/app
|
||||
@@ -34,34 +63,46 @@ RUN \
|
||||
apt-get update -y && apt-get install -y --no-install-recommends ${BUILD_DEPS} && \
|
||||
\
|
||||
# Download nodejs
|
||||
wget https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-${ARCHITECTURE}.tar.gz && \
|
||||
wget https://nodejs.org/dist/${NODE_VERSION}/SHASUMS256.txt.asc && \
|
||||
#wget https://nodejs.org/dist/${NODE_VERSION}/node-${NODE_VERSION}-${ARCHITECTURE}.tar.gz && \
|
||||
#wget https://nodejs.org/dist/${NODE_VERSION}/SHASUMS256.txt.asc && \
|
||||
#---------------------------------------------------------------------------------------------
|
||||
# Node Fibers 100% CPU usage issue:
|
||||
# https://github.com/wekan/wekan-mongodb/issues/2#issuecomment-381453161
|
||||
# https://github.com/meteor/meteor/issues/9796#issuecomment-381676326
|
||||
# https://github.com/sandstorm-io/sandstorm/blob/0f1fec013fe7208ed0fd97eb88b31b77e3c61f42/shell/server/00-startup.js#L99-L129
|
||||
# Also see beginning of wekan/server/authentication.js
|
||||
# import Fiber from "fibers";
|
||||
# Fiber.poolSize = 1e9;
|
||||
# Download node version 8.12.0 prerelease that has fix included,
|
||||
# Description at https://releases.wekan.team/node.txt
|
||||
wget https://releases.wekan.team/node-${NODE_VERSION}-${ARCHITECTURE}.tar.gz && \
|
||||
echo "1ed54adb8497ad8967075a0b5d03dd5d0a502be43d4a4d84e5af489c613d7795 node-v8.12.0-linux-x64.tar.gz" >> SHASUMS256.txt.asc && \
|
||||
\
|
||||
# Verify nodejs authenticity
|
||||
grep ${NODE_VERSION}-${ARCHITECTURE}.tar.gz SHASUMS256.txt.asc | shasum -a 256 -c - && \
|
||||
export GNUPGHOME="$(mktemp -d)" && \
|
||||
\
|
||||
#export GNUPGHOME="$(mktemp -d)" && \
|
||||
#\
|
||||
# Try other key servers if ha.pool.sks-keyservers.net is unreachable
|
||||
# Code from https://github.com/chorrell/docker-node/commit/2b673e17547c34f17f24553db02beefbac98d23c
|
||||
# gpg keys listed at https://github.com/nodejs/node#release-team
|
||||
# and keys listed here from previous version of this Dockerfile
|
||||
for key in \
|
||||
9554F04D7259F04124DE6B476D5A82AC7E37093B \
|
||||
94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
|
||||
FD3A5288F042B6850C66B31F09FE44734EB7990E \
|
||||
71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
|
||||
DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
|
||||
C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
|
||||
B9AE9905FFD7803F25714661B63B535A4C206CA9 \
|
||||
; do \
|
||||
gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key" || \
|
||||
gpg --keyserver pgp.mit.edu --recv-keys "$key" || \
|
||||
gpg --keyserver keyserver.pgp.com --recv-keys "$key" ; \
|
||||
done && \
|
||||
gpg --verify SHASUMS256.txt.asc && \
|
||||
#for key in \
|
||||
#9554F04D7259F04124DE6B476D5A82AC7E37093B \
|
||||
#94AE36675C464D64BAFA68DD7434390BDBE9B9C5 \
|
||||
#FD3A5288F042B6850C66B31F09FE44734EB7990E \
|
||||
#71DCFD284A79C3B38668286BC97EC7A07EDE3FC1 \
|
||||
#DD8F2338BAE7501E3DD5AC78C273792F7D83545D \
|
||||
#C4F0DFFF4E8C1A8236409D08E73BC641CC11F4C8 \
|
||||
#B9AE9905FFD7803F25714661B63B535A4C206CA9 \
|
||||
#; do \
|
||||
#gpg --keyserver ha.pool.sks-keyservers.net --recv-keys "$key" || \
|
||||
#gpg --keyserver pgp.mit.edu --recv-keys "$key" || \
|
||||
#gpg --keyserver keyserver.pgp.com --recv-keys "$key" ; \
|
||||
#done && \
|
||||
#gpg --verify SHASUMS256.txt.asc && \
|
||||
# Ignore socket files then delete files then delete directories
|
||||
find "$GNUPGHOME" -type f | xargs rm -f && \
|
||||
find "$GNUPGHOME" -type d | xargs rm -fR && \
|
||||
#find "$GNUPGHOME" -type f | xargs rm -f && \
|
||||
#find "$GNUPGHOME" -type d | xargs rm -fR && \
|
||||
rm -f SHASUMS256.txt.asc && \
|
||||
\
|
||||
# Install Node
|
||||
@@ -71,8 +112,8 @@ RUN \
|
||||
ln -s /opt/nodejs/bin/node /usr/bin/node && \
|
||||
ln -s /opt/nodejs/bin/npm /usr/bin/npm && \
|
||||
\
|
||||
# paxctl fix for alpine linux: https://github.com/wekan/wekan/issues/1303
|
||||
paxctl -mC `which node` && \
|
||||
#DOES NOT WORK: paxctl fix for alpine linux: https://github.com/wekan/wekan/issues/1303
|
||||
#paxctl -mC `which node` && \
|
||||
\
|
||||
# Install Node dependencies
|
||||
npm install -g npm@${NPM_VERSION} && \
|
||||
@@ -111,12 +152,15 @@ RUN \
|
||||
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 && \
|
||||
chown wekan:wekan /home/wekan/app_build/bundle/programs/server/packages/cfs_access-point.js && \
|
||||
cd /home/wekan/app_build/bundle/programs/server/npm/node_modules/meteor/npm-bcrypt && \
|
||||
gosu wekan:wekan rm -rf node_modules/bcrypt && \
|
||||
gosu wekan:wekan npm install bcrypt && \
|
||||
#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
|
||||
#cd /home/wekan/app_build/bundle/programs/server/npm/node_modules/meteor/npm-bcrypt && \
|
||||
#gosu wekan:wekan rm -rf node_modules/bcrypt && \
|
||||
#gosu wekan:wekan npm install bcrypt && \
|
||||
cd /home/wekan/app_build/bundle/programs/server/ && \
|
||||
gosu wekan:wekan npm install && \
|
||||
gosu wekan:wekan npm install bcrypt && \
|
||||
#gosu wekan:wekan npm install bcrypt && \
|
||||
mv /home/wekan/app_build/bundle /build && \
|
||||
\
|
||||
# Cleanup
|
||||
@@ -128,7 +172,8 @@ RUN \
|
||||
rm -R /home/wekan/app_build && \
|
||||
rm /home/wekan/install_meteor.sh
|
||||
|
||||
ENV PORT=80
|
||||
ENV PORT=8080
|
||||
EXPOSE $PORT
|
||||
USER wekan
|
||||
|
||||
CMD ["node", "/build/main.js"]
|
||||
@@ -1,18 +1,19 @@
|
||||
# Wekan
|
||||
|
||||
[](https://transifex.com/wekan/wekan)
|
||||
|
||||
[![Wekan Vanila Chat][vanila_badge]][vanila_chat]
|
||||
[](http://webchat.freenode.net?channels=%23wekan&uio=d4)
|
||||
|
||||
[](https://github.com/wekan/wekan/graphs/contributors)
|
||||
[](https://quay.io/repository/wekan/wekan)
|
||||
|
||||
<!--
|
||||
[](https://hub.docker.com/r/wekanteam/wekan)
|
||||
[](https://hub.docker.com/r/wekanteam/wekan)
|
||||
[![Wekan Build Status][travis_badge]][travis_status]
|
||||
-->
|
||||
|
||||
Freenode IRC #wekan
|
||||
|
||||
[![Wekan chat][vanila_badge]][vanila_chat]
|
||||
|
||||
[Translate Wekan at Transifex][translate_wekan]
|
||||
|
||||
[Open Hub analysis of Wekan code](https://www.openhub.net/p/wekan)
|
||||
[](https://www.codacy.com/app/xet7/wekan?utm_source=github.com&utm_medium=referral&utm_content=wekan/wekan&utm_campaign=Badge_Grade)
|
||||
[](https://codeclimate.com/github/wekan/wekan)
|
||||
[](https://david-dm.org/wekan/wekan)
|
||||
[](https://www.openhub.net/p/wekan)
|
||||
|
||||
Please read [FAQ](https://github.com/wekan/wekan/wiki/FAQ).
|
||||
Please don't feed the trolls and spammers that are mentioned in the FAQ :)
|
||||
|
||||
+129
@@ -0,0 +1,129 @@
|
||||
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
|
||||
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.
|
||||
|
||||
## How should reports be formatted?
|
||||
|
||||
```
|
||||
Name: %name
|
||||
Twitter: %twitter
|
||||
Bug type: %bugtype
|
||||
Domain: %domain
|
||||
Severity: %severity
|
||||
URL: %url
|
||||
PoC: %poc
|
||||
CVSS (optional): %cvss
|
||||
CWSS (optional): %cwss
|
||||
```
|
||||
|
||||
## Who can participate in the program
|
||||
|
||||
Anyone who reports a unique security issue in scope and does not disclose it to
|
||||
a third party before we have patched and updated may be upon their approval
|
||||
added to the Wekan Hall of Fame.
|
||||
|
||||
## Which domains are in scope?
|
||||
|
||||
No public domains, because all those are donated to Wekan Open Source project,
|
||||
and we don't have any permissions to do security scans on those donated servers
|
||||
|
||||
Please don't perform research that could impact other users. Secondly, please keep
|
||||
the reports short and succinct. If we fail to understand the logics of your bug, we will tell you.
|
||||
|
||||
You can [Install Wekan](https://github.com/wekan/wekan/releases) to your own computer
|
||||
and scan it's vulnerabilities there.
|
||||
|
||||
## About Wekan versions
|
||||
|
||||
There are only 2 versions of Wekan: Standalone Wekan, and Sandstorm Wekan.
|
||||
|
||||
### Standalone Wekan Security
|
||||
|
||||
Standalone Wekan includes all non-Sandstorm platforms. Some Standalone Wekan platforms
|
||||
like Snap and Docker have their own specific sandboxing etc features.
|
||||
|
||||
Standalone Wekan by default does not load any files from Internet, like fonts, CSS, etc.
|
||||
This also means all Standalone Wekan functionality works in offline local networks.
|
||||
Wekan is used by companies that have [thousands of users](https://github.com/wekan/wekan/wiki/AWS) and at healthcare.
|
||||
|
||||
Wekan uses xss package for input fields like cards, as you can see from
|
||||
[package.json](https://github.com/wekan/wekan/blob/devel/package.json). Other used versions can be seen from
|
||||
[Meteor versions file](https://github.com/wekan/wekan/blob/devel/.meteor/versions).
|
||||
Forms can include markdown links, html, image tags etc like you see at https://wekan.github.io .
|
||||
It's possible to add attachments to cards, and markdown/html links to files.
|
||||
|
||||
Wekan attachments are not accessible without logging in. Import from Trello works by copying
|
||||
Trello export JSON to Wekan Trello import page, and in Trello JSON file there is direct links to all publicly
|
||||
accessible Trello attachment files, that Standalone Wekan downloads directly to Wekan MongoDB database in
|
||||
[CollectionFS](https://github.com/wekan/wekan/pull/875) format. When Wekan board is exported in
|
||||
Wekan JSON format, all board attachments are included in Wekan JSON file as base64 encoded text.
|
||||
That Wekan JSON format file can be imported to Sandstorm Wekan with all the attachments, when we get
|
||||
latest Wekan version working on Sandstorm, only couple of bugs are left before that. In Sandstorm it's not
|
||||
possible yet to import from Trello with attachments, because Wekan does not implement Sandstorm-compatible
|
||||
access to outside of Wekan grain.
|
||||
|
||||
Standalone Wekan only has password auth currently, there is work in progress to add
|
||||
[oauth2](https://github.com/wekan/wekan/pull/1578), [Openid](https://github.com/wekan/wekan/issues/538),
|
||||
[LDAP](https://github.com/wekan/wekan/issues/119) etc. If you need more login security for Standalone Wekan now,
|
||||
it's possible add additional [Google Auth proxybouncer](https://github.com/wekan/wekan/wiki/Let's-Encrypt-and-Google-Auth) in front of password auth, and then use Google Authenticator for Google Auth. Standalone Wekan does have [brute force protection with eluck:accounts-lockout and browser-policy clickjacking protection](https://github.com/wekan/wekan/blob/devel/CHANGELOG.md#v080-2018-04-04-wekan-release). You can also optionally use some [WAF](https://en.wikipedia.org/wiki/Web_application_firewall)
|
||||
like for example [AWS WAF](https://aws.amazon.com/waf/).
|
||||
|
||||
[All Wekan Platforms](https://github.com/wekan/wekan/wiki/Platforms)
|
||||
|
||||
### Sandstorm Wekan Security
|
||||
|
||||
On Sandstorm platform using environment variable Standalone Wekan features like Admin Panel etc are
|
||||
turned off, because Sandstorm platform provides SSO for all apps running on Sandstorm.
|
||||
|
||||
[Sandstorm](https://sandstorm.io) is separate Open Source platform that has been
|
||||
[security audited](https://sandstorm.io/news/2017-03-02-security-review) and found bugs fixed.
|
||||
Sandstorm also has passwordless login, LDAP, SAML, Google etc auth options already.
|
||||
At Sandstorm code is read-only and signed by app maintainers, only grain content can be modified.
|
||||
Wekan at Sandstorm runs in sandboxed grain, it does not have access elsewhere without user-visible
|
||||
PowerBox request or opening randomly-generated API key URL.
|
||||
Also read [Sandstorm Security Practices](https://docs.sandstorm.io/en/latest/using/security-practices/) and
|
||||
[Sandstorm Security non-events](https://docs.sandstorm.io/en/latest/using/security-non-events/).
|
||||
For Sandstorm specific security issues you can contact [kentonv](https://github.com/kentonv) by email.
|
||||
|
||||
## What Wekan bugs are eligible?
|
||||
|
||||
Any typical web security bugs. If any of the previously mentioned is somehow problematic and
|
||||
a security issue, we'd like to know about it, and also how to fix it:
|
||||
|
||||
- Cross-site Scripting
|
||||
- Open redirect
|
||||
- Cross-site request forgery
|
||||
- File inclusion
|
||||
- Authentication bypass
|
||||
- Server-side code execution
|
||||
|
||||
## What Wekan bugs are NOT eligible?
|
||||
|
||||
Typical already known or "no impact" bugs such as:
|
||||
|
||||
- Brute force password guessign. Currently there is
|
||||
[brute force protection with eluck:accounts-lockout](https://github.com/wekan/wekan/blob/devel/CHANGELOG.md#v080-2018-04-04-wekan-release).
|
||||
- Security issues related to that Wekan uses Meteor 1.6.0.1 related packages, and upgrading to newer
|
||||
Meteor 1.6.1 is complicated process that requires lots of changes to many dependency packages.
|
||||
Upgrading [has been tried many times, spending a lot of time](https://github.com/meteor/meteor/issues/9609)
|
||||
but there still is issues. Helping with package upgrades is very welcome.
|
||||
- [Wekan API old tokens not replaced correctly](https://github.com/wekan/wekan/issues/1437)
|
||||
- Missing Cookie flags on non-session cookies or 3rd party cookies
|
||||
- Logout CSRF
|
||||
- Social engineering
|
||||
- Denial of service
|
||||
- SSL BEAST/CRIME/etc. Wekan does not have SSL built-in, it uses Caddy/Nginx/Apache etc at front.
|
||||
Integrated Caddy support is updated often.
|
||||
- Email spoofing, SPF, DMARC & DKIM. Wekan does not include email server.
|
||||
|
||||
Wekan is Open Source with MIT license, and free to use also for commercial use.
|
||||
We welcome all fixes to improve security by email to security (at) wekan.team .
|
||||
|
||||
## Bonus Points
|
||||
|
||||
If your Responsible Security Disclosure includes code for fixing security issue,
|
||||
you get bonus points, as seen on [Hall of Fame](https://wekan.github.io/hall-of-fame).
|
||||
@@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "Wekan",
|
||||
"description": "The open-source Trello-like kanban",
|
||||
"description": "The open-source kanban",
|
||||
"repository": "https://github.com/wekan/wekan",
|
||||
"logo": "https://raw.githubusercontent.com/wekan/wekan/master/meta/icons/wekan-150.png",
|
||||
"keywords": ["productivity", "tool", "team", "kanban"],
|
||||
|
||||
@@ -53,6 +53,9 @@ template(name="boardActivities")
|
||||
if($eq activityType 'createCard')
|
||||
| {{{_ 'activity-added' cardLink boardLabel}}}.
|
||||
|
||||
if($eq activityType 'createCustomField')
|
||||
| {{_ 'activity-customfield-created' customField}}.
|
||||
|
||||
if($eq activityType 'createList')
|
||||
| {{_ 'activity-added' list.title boardLabel}}.
|
||||
|
||||
|
||||
@@ -8,16 +8,24 @@ BlazeComponent.extendComponent({
|
||||
const sidebar = this.parentComponent(); // XXX for some reason not working
|
||||
sidebar.callFirstWith(null, 'resetNextPeak');
|
||||
this.autorun(() => {
|
||||
const mode = this.data().mode;
|
||||
let mode = this.data().mode;
|
||||
const capitalizedMode = Utils.capitalize(mode);
|
||||
const id = Session.get(`current${capitalizedMode}`);
|
||||
let thisId, searchId;
|
||||
if (mode === 'linkedcard' || mode === 'linkedboard') {
|
||||
thisId = Session.get('currentCard');
|
||||
searchId = Cards.findOne({_id: thisId}).linkedId;
|
||||
mode = mode.replace('linked', '');
|
||||
} else {
|
||||
thisId = Session.get(`current${capitalizedMode}`);
|
||||
searchId = thisId;
|
||||
}
|
||||
const limit = this.page.get() * activitiesPerPage;
|
||||
const user = Meteor.user();
|
||||
const hideSystem = user ? user.hasHiddenSystemMessages() : false;
|
||||
if (id === null)
|
||||
if (searchId === null)
|
||||
return;
|
||||
|
||||
this.subscribe('activities', mode, id, limit, hideSystem, () => {
|
||||
this.subscribe('activities', mode, searchId, limit, hideSystem, () => {
|
||||
this.loadNextPageLocked = false;
|
||||
|
||||
// If the sibear peak hasn't increased, that mean that there are no more
|
||||
@@ -91,6 +99,11 @@ BlazeComponent.extendComponent({
|
||||
}, attachment.name()));
|
||||
},
|
||||
|
||||
customField() {
|
||||
const customField = this.currentData().customField();
|
||||
return customField.name;
|
||||
},
|
||||
|
||||
events() {
|
||||
return [{
|
||||
// XXX We should use Popup.afterConfirmation here
|
||||
|
||||
@@ -21,11 +21,18 @@ BlazeComponent.extendComponent({
|
||||
'submit .js-new-comment-form'(evt) {
|
||||
const input = this.getInput();
|
||||
const text = input.val().trim();
|
||||
const card = this.currentData();
|
||||
let boardId = card.boardId;
|
||||
let cardId = card._id;
|
||||
if (card.isLinkedCard()) {
|
||||
boardId = Cards.findOne(card.linkedId).boardId;
|
||||
cardId = card.linkedId;
|
||||
}
|
||||
if (text) {
|
||||
CardComments.insert({
|
||||
text,
|
||||
boardId: this.currentData().boardId,
|
||||
cardId: this.currentData()._id,
|
||||
boardId,
|
||||
cardId,
|
||||
});
|
||||
resetCommentInput(input);
|
||||
Tracker.flush();
|
||||
|
||||
@@ -6,9 +6,17 @@ template(name="archivedBoards")
|
||||
ul.archived-lists
|
||||
each archivedBoards
|
||||
li.archived-lists-item
|
||||
button.js-restore-board
|
||||
i.fa.fa-undo
|
||||
| {{_ 'restore-board'}}
|
||||
= title
|
||||
div.board-header-btns
|
||||
button.board-header-btn.js-delete-board
|
||||
i.fa.fa-trash-o
|
||||
| {{_ 'delete-board'}}
|
||||
button.board-header-btn.js-restore-board
|
||||
i.fa.fa-undo
|
||||
| {{_ 'restore-board'}}
|
||||
= title
|
||||
else
|
||||
li.no-items-message {{_ 'no-archived-boards'}}
|
||||
|
||||
template(name="boardDeletePopup")
|
||||
p {{_ 'delete-board-confirm-popup'}}
|
||||
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
|
||||
@@ -29,6 +29,17 @@ BlazeComponent.extendComponent({
|
||||
board.restore();
|
||||
Utils.goBoardId(board._id);
|
||||
},
|
||||
'click .js-delete-board': Popup.afterConfirm('boardDelete', function() {
|
||||
Popup.close();
|
||||
const isSandstorm = Meteor.settings && Meteor.settings.public &&
|
||||
Meteor.settings.public.sandstorm;
|
||||
if (isSandstorm && Session.get('currentBoard')) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
Boards.remove(currentBoard._id);
|
||||
}
|
||||
Boards.remove(this._id);
|
||||
FlowRouter.go('home');
|
||||
}),
|
||||
}];
|
||||
},
|
||||
}).register('archivedBoards');
|
||||
@@ -14,7 +14,7 @@ template(name="board")
|
||||
template(name="boardBody")
|
||||
.board-wrapper(class=currentBoard.colorClass)
|
||||
+sidebar
|
||||
.board-canvas(
|
||||
.board-canvas.js-swimlanes.js-perfect-scrollbar(
|
||||
class="{{#if Sidebar.isOpen}}is-sibling-sidebar-open{{/if}}"
|
||||
class="{{#if MultiSelection.isActive}}is-multiselection-active{{/if}}"
|
||||
class="{{#if draggingActive.get}}is-dragging-active{{/if}}")
|
||||
@@ -25,3 +25,11 @@ template(name="boardBody")
|
||||
+swimlane(this)
|
||||
if isViewLists
|
||||
+listsGroup
|
||||
if isViewCalendar
|
||||
+calendarView
|
||||
|
||||
template(name="calendarView")
|
||||
.calendar-view.swimlane
|
||||
if currentCard
|
||||
+cardDetails(currentCard)
|
||||
+fullcalendar(calendarOptions)
|
||||
@@ -1,9 +1,8 @@
|
||||
const subManager = new SubsManager();
|
||||
const { calculateIndex, enableClickOnTouch } = Utils;
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.draggingActive = new ReactiveVar(false);
|
||||
this.showOverlay = new ReactiveVar(false);
|
||||
this.isBoardReady = new ReactiveVar(false);
|
||||
|
||||
// The pattern we use to manually handle data loading is described here:
|
||||
@@ -21,44 +20,102 @@ BlazeComponent.extendComponent({
|
||||
});
|
||||
});
|
||||
});
|
||||
|
||||
this._isDragging = false;
|
||||
this._lastDragPositionX = 0;
|
||||
|
||||
// Used to set the overlay
|
||||
this.mouseHasEnterCardDetails = false;
|
||||
},
|
||||
|
||||
// XXX Flow components allow us to avoid creating these two setter methods by
|
||||
// exposing a public API to modify the component state. We need to investigate
|
||||
// best practices here.
|
||||
setIsDragging(bool) {
|
||||
this.draggingActive.set(bool);
|
||||
},
|
||||
|
||||
scrollLeft(position = 0) {
|
||||
const lists = this.$('.js-lists');
|
||||
lists && lists.animate({
|
||||
scrollLeft: position,
|
||||
});
|
||||
},
|
||||
|
||||
onlyShowCurrentCard() {
|
||||
return Utils.isMiniScreen() && Session.get('currentCard');
|
||||
},
|
||||
|
||||
}).register('board');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.showOverlay = new ReactiveVar(false);
|
||||
this.draggingActive = new ReactiveVar(false);
|
||||
this._isDragging = false;
|
||||
// Used to set the overlay
|
||||
this.mouseHasEnterCardDetails = false;
|
||||
},
|
||||
onRendered() {
|
||||
const boardComponent = this;
|
||||
const $swimlanesDom = boardComponent.$('.js-swimlanes');
|
||||
|
||||
$swimlanesDom.sortable({
|
||||
tolerance: 'pointer',
|
||||
appendTo: '.board-canvas',
|
||||
helper: 'clone',
|
||||
handle: '.js-swimlane-header',
|
||||
items: '.js-swimlane:not(.placeholder)',
|
||||
placeholder: 'swimlane placeholder',
|
||||
distance: 7,
|
||||
start(evt, ui) {
|
||||
ui.placeholder.height(ui.helper.height());
|
||||
EscapeActions.executeUpTo('popup-close');
|
||||
boardComponent.setIsDragging(true);
|
||||
},
|
||||
stop(evt, ui) {
|
||||
// To attribute the new index number, we need to get the DOM element
|
||||
// of the previous and the following card -- if any.
|
||||
const prevSwimlaneDom = ui.item.prev('.js-swimlane').get(0);
|
||||
const nextSwimlaneDom = ui.item.next('.js-swimlane').get(0);
|
||||
const sortIndex = calculateIndex(prevSwimlaneDom, nextSwimlaneDom, 1);
|
||||
|
||||
$swimlanesDom.sortable('cancel');
|
||||
const swimlaneDomElement = ui.item.get(0);
|
||||
const swimlane = Blaze.getData(swimlaneDomElement);
|
||||
|
||||
Swimlanes.update(swimlane._id, {
|
||||
$set: {
|
||||
sort: sortIndex.base,
|
||||
},
|
||||
});
|
||||
|
||||
boardComponent.setIsDragging(false);
|
||||
},
|
||||
});
|
||||
|
||||
// ugly touch event hotfix
|
||||
enableClickOnTouch('.js-swimlane:not(.placeholder)');
|
||||
|
||||
function userIsMember() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
|
||||
}
|
||||
|
||||
// If there is no data in the board (ie, no lists) we autofocus the list
|
||||
// creation form by clicking on the corresponding element.
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
if (userIsMember() && currentBoard.lists().count() === 0) {
|
||||
boardComponent.openNewListForm();
|
||||
}
|
||||
},
|
||||
|
||||
isViewSwimlanes() {
|
||||
const currentBoardId = Session.get('currentBoard');
|
||||
const board = Boards.findOne(currentBoardId);
|
||||
return (board.view === 'board-view-swimlanes');
|
||||
const currentUser = Meteor.user();
|
||||
if (!currentUser) return false;
|
||||
return (currentUser.profile.boardView === 'board-view-swimlanes');
|
||||
},
|
||||
|
||||
isViewLists() {
|
||||
const currentBoardId = Session.get('currentBoard');
|
||||
const board = Boards.findOne(currentBoardId);
|
||||
return (board.view === 'board-view-lists');
|
||||
const currentUser = Meteor.user();
|
||||
if (!currentUser) return true;
|
||||
return (currentUser.profile.boardView === 'board-view-lists');
|
||||
},
|
||||
|
||||
isViewCalendar() {
|
||||
const currentUser = Meteor.user();
|
||||
if (!currentUser) return true;
|
||||
return (currentUser.profile.boardView === 'board-view-cal');
|
||||
},
|
||||
|
||||
openNewListForm() {
|
||||
if (this.isViewSwimlanes()) {
|
||||
this.childComponents('swimlane')[0]
|
||||
.childComponents('addListAndSwimlaneForm')[0].open();
|
||||
} else if (this.isViewLists()) {
|
||||
this.childComponents('listsGroup')[0]
|
||||
.childComponents('addListForm')[0].open();
|
||||
}
|
||||
},
|
||||
events() {
|
||||
return [{
|
||||
// XXX The board-overlay div should probably be moved to the parent
|
||||
@@ -75,4 +132,98 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
}];
|
||||
},
|
||||
}).register('board');
|
||||
|
||||
// XXX Flow components allow us to avoid creating these two setter methods by
|
||||
// exposing a public API to modify the component state. We need to investigate
|
||||
// best practices here.
|
||||
setIsDragging(bool) {
|
||||
this.draggingActive.set(bool);
|
||||
},
|
||||
|
||||
scrollLeft(position = 0) {
|
||||
const swimlanes = this.$('.js-swimlanes');
|
||||
swimlanes && swimlanes.animate({
|
||||
scrollLeft: position,
|
||||
});
|
||||
},
|
||||
|
||||
}).register('boardBody');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onRendered() {
|
||||
this.autorun(function(){
|
||||
$('#calendar-view').fullCalendar('refetchEvents');
|
||||
});
|
||||
},
|
||||
calendarOptions() {
|
||||
return {
|
||||
id: 'calendar-view',
|
||||
defaultView: 'agendaDay',
|
||||
editable: true,
|
||||
timezone: 'local',
|
||||
header: {
|
||||
left: 'title today prev,next',
|
||||
center: 'agendaDay,listDay,timelineDay agendaWeek,listWeek,timelineWeek month,timelineMonth timelineYear',
|
||||
right: '',
|
||||
},
|
||||
// height: 'parent', nope, doesn't work as the parent might be small
|
||||
height: 'auto',
|
||||
/* TODO: lists as resources: https://fullcalendar.io/docs/vertical-resource-view */
|
||||
navLinks: true,
|
||||
nowIndicator: true,
|
||||
businessHours: {
|
||||
// days of week. an array of zero-based day of week integers (0=Sunday)
|
||||
dow: [ 1, 2, 3, 4, 5 ], // Monday - Friday
|
||||
start: '8:00',
|
||||
end: '18:00',
|
||||
},
|
||||
locale: TAPi18n.getLanguage(),
|
||||
events(start, end, timezone, callback) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const events = [];
|
||||
currentBoard.cardsInInterval(start.toDate(), end.toDate()).forEach(function(card){
|
||||
events.push({
|
||||
id: card._id,
|
||||
title: card.title,
|
||||
start: card.startAt,
|
||||
end: card.endAt,
|
||||
allDay: Math.abs(card.endAt.getTime() - card.startAt.getTime()) / 1000 === 24*3600,
|
||||
url: FlowRouter.url('card', {
|
||||
boardId: currentBoard._id,
|
||||
slug: currentBoard.slug,
|
||||
cardId: card._id,
|
||||
}),
|
||||
});
|
||||
});
|
||||
callback(events);
|
||||
},
|
||||
eventResize(event, delta, revertFunc) {
|
||||
let isOk = false;
|
||||
const card = Cards.findOne(event.id);
|
||||
|
||||
if (card) {
|
||||
card.setEnd(event.end.toDate());
|
||||
isOk = true;
|
||||
}
|
||||
if (!isOk) {
|
||||
revertFunc();
|
||||
}
|
||||
},
|
||||
eventDrop(event, delta, revertFunc) {
|
||||
let isOk = false;
|
||||
const card = Cards.findOne(event.id);
|
||||
if (card) {
|
||||
// TODO: add a flag for allDay events
|
||||
if (!event.allDay) {
|
||||
card.setStart(event.start.toDate());
|
||||
card.setEnd(event.end.toDate());
|
||||
isOk = true;
|
||||
}
|
||||
}
|
||||
if (!isOk) {
|
||||
revertFunc();
|
||||
}
|
||||
},
|
||||
};
|
||||
},
|
||||
}).register('calendarView');
|
||||
@@ -1,8 +1,11 @@
|
||||
@import 'nib'
|
||||
|
||||
position()
|
||||
if arguments[0] == cover
|
||||
position: absolute
|
||||
if arguments[0] == cover || arguments[0] == fixed-cover
|
||||
if arguments[0] == cover
|
||||
position: absolute
|
||||
else
|
||||
position: fixed
|
||||
left: 0
|
||||
right: 0
|
||||
top: 0
|
||||
@@ -12,25 +15,19 @@ position()
|
||||
|
||||
.board-wrapper
|
||||
position: cover
|
||||
overflow-x: hidden
|
||||
overflow-y: hidden
|
||||
|
||||
.board-canvas
|
||||
position: cover
|
||||
transition: margin .1s
|
||||
overflow-y: auto
|
||||
|
||||
&.is-sibling-sidebar-open
|
||||
margin-right: 248px
|
||||
|
||||
.swimlane
|
||||
border-bottom: 1px solid #CCC
|
||||
display: flex
|
||||
flex-direction: row
|
||||
margin: 0 0 10px
|
||||
padding: 0 40px 5px 0
|
||||
overflow-x: auto
|
||||
overflow-y: hidden
|
||||
|
||||
.board-overlay
|
||||
position: cover
|
||||
position: fixed-cover
|
||||
top: -100px
|
||||
right: -400px
|
||||
background: black
|
||||
|
||||
@@ -2,7 +2,8 @@ template(name="boardHeaderBar")
|
||||
h1.header-board-menu
|
||||
with currentBoard
|
||||
a(class="{{#if currentUser.isBoardAdmin}}js-edit-board-title{{else}}is-disabled{{/if}}")
|
||||
= title
|
||||
+viewer
|
||||
= title
|
||||
|
||||
.board-header-btns.left
|
||||
unless isMiniScreen
|
||||
@@ -71,7 +72,7 @@ template(name="boardHeaderBar")
|
||||
title="{{_ 'log-in'}}")
|
||||
i.fa.fa-sign-in
|
||||
span {{_ 'log-in'}}
|
||||
|
||||
|
||||
if isSandstorm
|
||||
if currentUser
|
||||
a.board-header-btn.js-open-archived-board
|
||||
@@ -87,10 +88,14 @@ template(name="boardHeaderBar")
|
||||
a.board-header-btn-close.js-filter-reset(title="{{_ 'filter-clear'}}")
|
||||
i.fa.fa-times-thin
|
||||
|
||||
a.board-header-btn.js-open-search-view(title="{{_ 'search'}}")
|
||||
i.fa.fa-search
|
||||
span {{_ 'search'}}
|
||||
|
||||
a.board-header-btn.js-toggle-board-view(
|
||||
title="{{_ 'board-view'}}")
|
||||
i.fa.fa-th-large
|
||||
span {{_ currentBoard.view}}
|
||||
span {{_ currentUser.profile.boardView}}
|
||||
|
||||
if canModifyBoard
|
||||
a.board-header-btn.js-multiselection-activate(
|
||||
@@ -108,6 +113,7 @@ template(name="boardHeaderBar")
|
||||
|
||||
template(name="boardMenuPopup")
|
||||
ul.pop-over-list
|
||||
li: a.js-custom-fields {{_ 'custom-fields'}}
|
||||
li: a.js-open-archives {{_ 'archived-items'}}
|
||||
if currentUser.isBoardAdmin
|
||||
li: a.js-change-board-color {{_ 'board-change-color'}}
|
||||
@@ -124,11 +130,18 @@ template(name="boardMenuPopup")
|
||||
li: a(href="{{exportUrl}}", download="{{exportFilename}}") {{_ 'export-board'}}
|
||||
li: a.js-archive-board {{_ 'archive-board'}}
|
||||
li: a.js-outgoing-webhooks {{_ 'outgoing-webhooks'}}
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li: a.js-subtask-settings {{_ 'subtask-settings'}}
|
||||
|
||||
if isSandstorm
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li: a(href="{{exportUrl}}", download="{{exportFilename}}") {{_ 'export-board'}}
|
||||
li: a.js-import-board {{_ 'import-board-c'}}
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li: a.js-subtask-settings {{_ 'subtask-settings'}}
|
||||
|
||||
template(name="boardVisibilityList")
|
||||
ul.pop-over-list
|
||||
@@ -187,6 +200,56 @@ template(name="boardChangeColorPopup")
|
||||
if isSelected
|
||||
i.fa.fa-check
|
||||
|
||||
template(name="boardSubtaskSettingsPopup")
|
||||
form.board-subtask-settings
|
||||
h3 {{_ 'show-parent-in-minicard'}}
|
||||
a#prefix-with-full-path.flex.js-field-show-parent-in-minicard(class="{{#if $eq presentParentTask 'prefix-with-full-path'}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if $eq presentParentTask 'prefix-with-full-path'}}is-checked{{/if}}")
|
||||
span {{_ 'prefix-with-full-path'}}
|
||||
a#prefix-with-parent.flex.js-field-show-parent-in-minicard(class="{{#if $eq presentParentTask 'prefix-with-parent'}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if $eq presentParentTask 'prefix-with-parent'}}is-checked{{/if}}")
|
||||
span {{_ 'prefix-with-parent'}}
|
||||
a#subtext-with-full-path.flex.js-field-show-parent-in-minicard(class="{{#if $eq presentParentTask 'subtext-with-full-path'}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if $eq presentParentTask 'subtext-with-full-path'}}is-checked{{/if}}")
|
||||
span {{_ 'subtext-with-full-path'}}
|
||||
a#subtext-with-parent.flex.js-field-show-parent-in-minicard(class="{{#if $eq presentParentTask 'subtext-with-parent'}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if $eq presentParentTask 'subtext-with-parent'}}is-checked{{/if}}")
|
||||
span {{_ 'subtext-with-parent'}}
|
||||
a#no-parent.flex.js-field-show-parent-in-minicard(class="{{#if $eq presentParentTask 'no-parent'}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if $eq presentParentTask 'no-parent'}}is-checked{{/if}}")
|
||||
span {{_ 'no-parent'}}
|
||||
div
|
||||
hr
|
||||
|
||||
div.check-div
|
||||
a.flex.js-field-has-subtasks(class="{{#if allowsSubtasks}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if allowsSubtasks}}is-checked{{/if}}")
|
||||
span {{_ 'show-subtasks-field'}}
|
||||
|
||||
label
|
||||
| {{_ 'deposit-subtasks-board'}}
|
||||
select.js-field-deposit-board(disabled="{{#unless allowsSubtasks}}disabled{{/unless}}")
|
||||
each boards
|
||||
if isBoardSelected
|
||||
option(value=_id selected="selected") {{title}}
|
||||
else
|
||||
option(value=_id) {{title}}
|
||||
if isNullBoardSelected
|
||||
option(value='null' selected="selected") {{_ 'custom-field-dropdown-none'}}
|
||||
else
|
||||
option(value='null') {{_ 'custom-field-dropdown-none'}}
|
||||
div
|
||||
hr
|
||||
|
||||
label
|
||||
| {{_ 'deposit-subtasks-list'}}
|
||||
select.js-field-deposit-list(disabled="{{#unless hasLists}}disabled{{/unless}}")
|
||||
each lists
|
||||
if isListSelected
|
||||
option(value=_id selected="selected") {{title}}
|
||||
else
|
||||
option(value=_id) {{title}}
|
||||
|
||||
template(name="createBoard")
|
||||
form
|
||||
label
|
||||
|
||||
@@ -1,5 +1,9 @@
|
||||
Template.boardMenuPopup.events({
|
||||
'click .js-rename-board': Popup.open('boardChangeTitle'),
|
||||
'click .js-custom-fields'() {
|
||||
Sidebar.setView('customFields');
|
||||
Popup.close();
|
||||
},
|
||||
'click .js-open-archives'() {
|
||||
Sidebar.setView('archives');
|
||||
Popup.close();
|
||||
@@ -13,8 +17,15 @@ Template.boardMenuPopup.events({
|
||||
// confirm that the board was successfully archived.
|
||||
FlowRouter.go('home');
|
||||
}),
|
||||
'click .js-delete-board': Popup.afterConfirm('deleteBoard', function() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
Popup.close();
|
||||
Boards.remove(currentBoard._id);
|
||||
FlowRouter.go('home');
|
||||
}),
|
||||
'click .js-outgoing-webhooks': Popup.open('outgoingWebhooks'),
|
||||
'click .js-import-board': Popup.open('chooseBoardSource'),
|
||||
'click .js-subtask-settings': Popup.open('boardSubtaskSettings'),
|
||||
});
|
||||
|
||||
Template.boardMenuPopup.helpers({
|
||||
@@ -77,19 +88,13 @@ BlazeComponent.extendComponent({
|
||||
Modal.open('archivedBoards');
|
||||
},
|
||||
'click .js-toggle-board-view'() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
if (currentBoard.view === 'board-view-swimlanes') {
|
||||
Boards.update(currentBoard._id, {
|
||||
$set: {
|
||||
view: 'board-view-lists',
|
||||
},
|
||||
});
|
||||
} else if (currentBoard.view === 'board-view-lists') {
|
||||
Boards.update(currentBoard._id, {
|
||||
$set: {
|
||||
view: 'board-view-swimlanes',
|
||||
},
|
||||
});
|
||||
const currentUser = Meteor.user();
|
||||
if (currentUser.profile.boardView === 'board-view-swimlanes') {
|
||||
currentUser.setBoardView('board-view-cal');
|
||||
} else if (currentUser.profile.boardView === 'board-view-lists') {
|
||||
currentUser.setBoardView('board-view-swimlanes');
|
||||
} else if (currentUser.profile.boardView === 'board-view-cal') {
|
||||
currentUser.setBoardView('board-view-lists');
|
||||
}
|
||||
},
|
||||
'click .js-open-filter-view'() {
|
||||
@@ -100,6 +105,9 @@ BlazeComponent.extendComponent({
|
||||
Sidebar.setView();
|
||||
Filter.reset();
|
||||
},
|
||||
'click .js-open-search-view'() {
|
||||
Sidebar.setView('search');
|
||||
},
|
||||
'click .js-multiselection-activate'() {
|
||||
const currentCard = Session.get('currentCard');
|
||||
MultiSelection.activate();
|
||||
@@ -146,6 +154,102 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
}).register('boardChangeColorPopup');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
},
|
||||
|
||||
allowsSubtasks() {
|
||||
return this.currentBoard.allowsSubtasks;
|
||||
},
|
||||
|
||||
isBoardSelected() {
|
||||
return this.currentBoard.subtasksDefaultBoardId === this.currentData()._id;
|
||||
},
|
||||
|
||||
isNullBoardSelected() {
|
||||
return (this.currentBoard.subtasksDefaultBoardId === null) || (this.currentBoard.subtasksDefaultBoardId === undefined);
|
||||
},
|
||||
|
||||
boards() {
|
||||
return Boards.find({
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
}, {
|
||||
sort: ['title'],
|
||||
});
|
||||
},
|
||||
|
||||
lists() {
|
||||
return Lists.find({
|
||||
boardId: this.currentBoard._id,
|
||||
archived: false,
|
||||
}, {
|
||||
sort: ['title'],
|
||||
});
|
||||
},
|
||||
|
||||
hasLists() {
|
||||
return this.lists().count() > 0;
|
||||
},
|
||||
|
||||
isListSelected() {
|
||||
return this.currentBoard.subtasksDefaultBoardId === this.currentData()._id;
|
||||
},
|
||||
|
||||
presentParentTask() {
|
||||
let result = this.currentBoard.presentParentTask;
|
||||
if ((result === null) || (result === undefined)) {
|
||||
result = 'no-parent';
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'click .js-field-has-subtasks'(evt) {
|
||||
evt.preventDefault();
|
||||
this.currentBoard.allowsSubtasks = !this.currentBoard.allowsSubtasks;
|
||||
this.currentBoard.setAllowsSubtasks(this.currentBoard.allowsSubtasks);
|
||||
$('.js-field-has-subtasks .materialCheckBox').toggleClass('is-checked', this.currentBoard.allowsSubtasks);
|
||||
$('.js-field-has-subtasks').toggleClass('is-checked', this.currentBoard.allowsSubtasks);
|
||||
$('.js-field-deposit-board').prop('disabled', !this.currentBoard.allowsSubtasks);
|
||||
},
|
||||
'change .js-field-deposit-board'(evt) {
|
||||
let value = evt.target.value;
|
||||
if (value === 'null') {
|
||||
value = null;
|
||||
}
|
||||
this.currentBoard.setSubtasksDefaultBoardId(value);
|
||||
evt.preventDefault();
|
||||
},
|
||||
'change .js-field-deposit-list'(evt) {
|
||||
this.currentBoard.setSubtasksDefaultListId(evt.target.value);
|
||||
evt.preventDefault();
|
||||
},
|
||||
'click .js-field-show-parent-in-minicard'(evt) {
|
||||
const value = evt.target.id || $(evt.target).parent()[0].id || $(evt.target).parent()[0].parent()[0].id;
|
||||
const options = [
|
||||
'prefix-with-full-path',
|
||||
'prefix-with-parent',
|
||||
'subtext-with-full-path',
|
||||
'subtext-with-parent',
|
||||
'no-parent'];
|
||||
options.forEach(function(element) {
|
||||
if (element !== value) {
|
||||
$(`#${element} .materialCheckBox`).toggleClass('is-checked', false);
|
||||
$(`#${element}`).toggleClass('is-checked', false);
|
||||
}
|
||||
});
|
||||
$(`#${value} .materialCheckBox`).toggleClass('is-checked', true);
|
||||
$(`#${value}`).toggleClass('is-checked', true);
|
||||
this.currentBoard.setPresentParentTask(value);
|
||||
evt.preventDefault();
|
||||
},
|
||||
}];
|
||||
},
|
||||
}).register('boardSubtaskSettingsPopup');
|
||||
|
||||
const CreateBoard = BlazeComponent.extendComponent({
|
||||
template() {
|
||||
return 'createBoard';
|
||||
|
||||
@@ -1,3 +1,22 @@
|
||||
.integration-form
|
||||
padding: 5px
|
||||
border-bottom: 1px solid #ccc
|
||||
|
||||
.flex
|
||||
display: -webkit-box
|
||||
display: -moz-box
|
||||
display: -webkit-flex
|
||||
display: -moz-flex
|
||||
display: -ms-flexbox
|
||||
display: flex
|
||||
|
||||
.option
|
||||
@extends .flex
|
||||
-webkit-border-radius: 3px;
|
||||
border-radius: 3px;
|
||||
background: #fff;
|
||||
text-decoration: none;
|
||||
-webkit-box-shadow: 0 1px 2px rgba(0,0,0,0.2);
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
|
||||
margin-top: 5px;
|
||||
padding: 5px;
|
||||
@@ -44,9 +44,9 @@ $spaceBetweenTiles = 16px
|
||||
line-height: 22px
|
||||
|
||||
.board-list-item-desc
|
||||
color: rgba(255, 255, 255, .5)
|
||||
color: #fff
|
||||
display: block
|
||||
font-size: 10px
|
||||
font-size: 14px
|
||||
font-weight: 400
|
||||
line-height: 18px
|
||||
|
||||
|
||||
@@ -57,8 +57,13 @@ Template.cardAttachmentsPopup.events({
|
||||
const card = this;
|
||||
FS.Utility.eachFile(evt, (f) => {
|
||||
const file = new FS.File(f);
|
||||
file.boardId = card.boardId;
|
||||
file.cardId = card._id;
|
||||
if (card.isLinkedCard()) {
|
||||
file.boardId = Cards.findOne(card.linkedId).boardId;
|
||||
file.cardId = card.linkedId;
|
||||
} else {
|
||||
file.boardId = card.boardId;
|
||||
file.cardId = card._id;
|
||||
}
|
||||
file.userId = Meteor.userId();
|
||||
|
||||
const attachment = Attachments.insert(file);
|
||||
|
||||
@@ -0,0 +1,76 @@
|
||||
template(name="cardCustomFieldsPopup")
|
||||
ul.pop-over-list
|
||||
each board.customFields
|
||||
li.item(class="")
|
||||
a.name.js-select-field(href="#")
|
||||
span.full-name
|
||||
= name
|
||||
if hasCustomField
|
||||
i.fa.fa-check
|
||||
hr
|
||||
a.quiet-button.full.js-settings
|
||||
i.fa.fa-cog
|
||||
span {{_ 'settings'}}
|
||||
|
||||
template(name="cardCustomField")
|
||||
+Template.dynamic(template=getTemplate)
|
||||
|
||||
template(name="cardCustomField-text")
|
||||
if canModifyCard
|
||||
+inlinedForm(classNames="js-card-customfield-text")
|
||||
+editor(autofocus=true)
|
||||
= value
|
||||
.edit-controls.clearfix
|
||||
button.primary(type="submit") {{_ 'save'}}
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
else
|
||||
a.js-open-inlined-form
|
||||
if value
|
||||
+viewer
|
||||
= value
|
||||
else
|
||||
| {{_ 'edit'}}
|
||||
|
||||
template(name="cardCustomField-number")
|
||||
if canModifyCard
|
||||
+inlinedForm(classNames="js-card-customfield-number")
|
||||
input(type="number" value=data.value)
|
||||
.edit-controls.clearfix
|
||||
button.primary(type="submit") {{_ 'save'}}
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
else
|
||||
a.js-open-inlined-form
|
||||
if value
|
||||
= value
|
||||
else
|
||||
| {{_ 'edit'}}
|
||||
|
||||
template(name="cardCustomField-date")
|
||||
if canModifyCard
|
||||
a.js-edit-date(title="{{showTitle}}" class="{{classes}}")
|
||||
if value
|
||||
div.card-date
|
||||
time(datetime="{{showISODate}}")
|
||||
| {{showDate}}
|
||||
else
|
||||
| {{_ 'edit'}}
|
||||
|
||||
template(name="cardCustomField-dropdown")
|
||||
if canModifyCard
|
||||
+inlinedForm(classNames="js-card-customfield-dropdown")
|
||||
select.inline
|
||||
each items
|
||||
if($eq data.value this._id)
|
||||
option(value=_id selected="selected") {{name}}
|
||||
else
|
||||
option(value=_id) {{name}}
|
||||
.edit-controls.clearfix
|
||||
button.primary(type="submit") {{_ 'save'}}
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
else
|
||||
a.js-open-inlined-form
|
||||
if value
|
||||
+viewer
|
||||
= selectedItem
|
||||
else
|
||||
| {{_ 'edit'}}
|
||||
@@ -0,0 +1,179 @@
|
||||
Template.cardCustomFieldsPopup.helpers({
|
||||
hasCustomField() {
|
||||
const card = Cards.findOne(Session.get('currentCard'));
|
||||
const customFieldId = this._id;
|
||||
return card.customFieldIndex(customFieldId) > -1;
|
||||
},
|
||||
});
|
||||
|
||||
Template.cardCustomFieldsPopup.events({
|
||||
'click .js-select-field'(evt) {
|
||||
const card = Cards.findOne(Session.get('currentCard'));
|
||||
const customFieldId = this._id;
|
||||
card.toggleCustomField(customFieldId);
|
||||
evt.preventDefault();
|
||||
},
|
||||
'click .js-settings'(evt) {
|
||||
EscapeActions.executeUpTo('detailsPane');
|
||||
Sidebar.setView('customFields');
|
||||
evt.preventDefault();
|
||||
},
|
||||
});
|
||||
|
||||
// cardCustomField
|
||||
const CardCustomField = BlazeComponent.extendComponent({
|
||||
|
||||
getTemplate() {
|
||||
return `cardCustomField-${this.data().definition.type}`;
|
||||
},
|
||||
|
||||
onCreated() {
|
||||
const self = this;
|
||||
self.card = Cards.findOne(Session.get('currentCard'));
|
||||
self.customFieldId = this.data()._id;
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
|
||||
},
|
||||
});
|
||||
CardCustomField.register('cardCustomField');
|
||||
|
||||
// cardCustomField-text
|
||||
(class extends CardCustomField {
|
||||
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
}
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'submit .js-card-customfield-text'(evt) {
|
||||
evt.preventDefault();
|
||||
const value = this.currentComponent().getValue();
|
||||
this.card.setCustomField(this.customFieldId, value);
|
||||
},
|
||||
}];
|
||||
}
|
||||
|
||||
}).register('cardCustomField-text');
|
||||
|
||||
// cardCustomField-number
|
||||
(class extends CardCustomField {
|
||||
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
}
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'submit .js-card-customfield-number'(evt) {
|
||||
evt.preventDefault();
|
||||
const value = parseInt(this.find('input').value, 10);
|
||||
this.card.setCustomField(this.customFieldId, value);
|
||||
},
|
||||
}];
|
||||
}
|
||||
|
||||
}).register('cardCustomField-number');
|
||||
|
||||
// cardCustomField-date
|
||||
(class extends CardCustomField {
|
||||
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
const self = this;
|
||||
self.date = ReactiveVar();
|
||||
self.now = ReactiveVar(moment());
|
||||
window.setInterval(() => {
|
||||
self.now.set(moment());
|
||||
}, 60000);
|
||||
|
||||
self.autorun(() => {
|
||||
self.date.set(moment(self.data().value));
|
||||
});
|
||||
}
|
||||
|
||||
showDate() {
|
||||
// this will start working once mquandalle:moment
|
||||
// is updated to at least moment.js 2.10.5
|
||||
// until then, the date is displayed in the "L" format
|
||||
return this.date.get().calendar(null, {
|
||||
sameElse: 'llll',
|
||||
});
|
||||
}
|
||||
|
||||
showISODate() {
|
||||
return this.date.get().toISOString();
|
||||
}
|
||||
|
||||
classes() {
|
||||
if (this.date.get().isBefore(this.now.get(), 'minute') &&
|
||||
this.now.get().isBefore(this.data().value)) {
|
||||
return 'current';
|
||||
}
|
||||
return '';
|
||||
}
|
||||
|
||||
showTitle() {
|
||||
return `${TAPi18n.__('card-start-on')} ${this.date.get().format('LLLL')}`;
|
||||
}
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'click .js-edit-date': Popup.open('cardCustomField-date'),
|
||||
}];
|
||||
}
|
||||
|
||||
}).register('cardCustomField-date');
|
||||
|
||||
// cardCustomField-datePopup
|
||||
(class extends DatePicker {
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
const self = this;
|
||||
self.card = Cards.findOne(Session.get('currentCard'));
|
||||
self.customFieldId = this.data()._id;
|
||||
this.data().value && this.date.set(moment(this.data().value));
|
||||
}
|
||||
|
||||
_storeDate(date) {
|
||||
this.card.setCustomField(this.customFieldId, date);
|
||||
}
|
||||
|
||||
_deleteDate() {
|
||||
this.card.setCustomField(this.customFieldId, '');
|
||||
}
|
||||
}).register('cardCustomField-datePopup');
|
||||
|
||||
// cardCustomField-dropdown
|
||||
(class extends CardCustomField {
|
||||
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
this._items = this.data().definition.settings.dropdownItems;
|
||||
this.items = this._items.slice(0);
|
||||
this.items.unshift({
|
||||
_id: '',
|
||||
name: TAPi18n.__('custom-field-dropdown-none'),
|
||||
});
|
||||
}
|
||||
|
||||
selectedItem() {
|
||||
const selected = this._items.find((item) => {
|
||||
return item._id === this.data().value;
|
||||
});
|
||||
return (selected) ? selected.name : TAPi18n.__('custom-field-dropdown-unknown');
|
||||
}
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'submit .js-card-customfield-dropdown'(evt) {
|
||||
evt.preventDefault();
|
||||
const value = this.find('select').value;
|
||||
this.card.setCustomField(this.customFieldId, value);
|
||||
},
|
||||
}];
|
||||
}
|
||||
|
||||
}).register('cardCustomField-dropdown');
|
||||
@@ -1,19 +1,3 @@
|
||||
template(name="editCardDate")
|
||||
.edit-card-date
|
||||
form.edit-date
|
||||
.fields
|
||||
.left
|
||||
label(for="date") {{_ 'date'}}
|
||||
input.js-date-field#date(type="text" name="date" value=showDate placeholder=dateFormat autofocus)
|
||||
.right
|
||||
label(for="time") {{_ 'time'}}
|
||||
input.js-time-field#time(type="text" name="time" value=showTime placeholder=timeFormat)
|
||||
.js-datepicker
|
||||
if error.get
|
||||
.warning {{_ error.get}}
|
||||
button.primary.wide.left.js-submit-date(type="submit") {{_ 'save'}}
|
||||
button.js-delete-date.negate.wide.right.js-delete-date {{_ 'delete'}}
|
||||
|
||||
template(name="dateBadge")
|
||||
if canModifyCard
|
||||
a.js-edit-date.card-date(title="{{showTitle}}" class="{{classes}}")
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
// Edit start & due dates
|
||||
const EditCardDate = BlazeComponent.extendComponent({
|
||||
// Edit received, start, due & end dates
|
||||
BlazeComponent.extendComponent({
|
||||
template() {
|
||||
return 'editCardDate';
|
||||
},
|
||||
@@ -92,11 +92,35 @@ Template.dateBadge.helpers({
|
||||
},
|
||||
});
|
||||
|
||||
// editCardStartDatePopup
|
||||
(class extends EditCardDate {
|
||||
// editCardReceivedDatePopup
|
||||
(class extends DatePicker {
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
this.data().startAt && this.date.set(moment(this.data().startAt));
|
||||
this.data().getReceived() && this.date.set(moment(this.data().getReceived()));
|
||||
}
|
||||
|
||||
_storeDate(date) {
|
||||
this.card.setReceived(date);
|
||||
}
|
||||
|
||||
_deleteDate() {
|
||||
this.card.setReceived(null);
|
||||
}
|
||||
}).register('editCardReceivedDatePopup');
|
||||
|
||||
|
||||
// editCardStartDatePopup
|
||||
(class extends DatePicker {
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
this.data().getStart() && this.date.set(moment(this.data().getStart()));
|
||||
}
|
||||
|
||||
onRendered() {
|
||||
super.onRendered();
|
||||
if (moment.isDate(this.card.getReceived())) {
|
||||
this.$('.js-datepicker').datepicker('setStartDate', this.card.getReceived());
|
||||
}
|
||||
}
|
||||
|
||||
_storeDate(date) {
|
||||
@@ -104,21 +128,21 @@ Template.dateBadge.helpers({
|
||||
}
|
||||
|
||||
_deleteDate() {
|
||||
this.card.unsetStart();
|
||||
this.card.setStart(null);
|
||||
}
|
||||
}).register('editCardStartDatePopup');
|
||||
|
||||
// editCardDueDatePopup
|
||||
(class extends EditCardDate {
|
||||
(class extends DatePicker {
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
this.data().dueAt && this.date.set(moment(this.data().dueAt));
|
||||
this.data().getDue() && this.date.set(moment(this.data().getDue()));
|
||||
}
|
||||
|
||||
onRendered() {
|
||||
super.onRendered();
|
||||
if (moment.isDate(this.card.startAt)) {
|
||||
this.$('.js-datepicker').datepicker('setStartDate', this.card.startAt);
|
||||
if (moment.isDate(this.card.getStart())) {
|
||||
this.$('.js-datepicker').datepicker('setStartDate', this.card.getStart());
|
||||
}
|
||||
}
|
||||
|
||||
@@ -127,12 +151,35 @@ Template.dateBadge.helpers({
|
||||
}
|
||||
|
||||
_deleteDate() {
|
||||
this.card.unsetDue();
|
||||
this.card.setDue(null);
|
||||
}
|
||||
}).register('editCardDueDatePopup');
|
||||
|
||||
// editCardEndDatePopup
|
||||
(class extends DatePicker {
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
this.data().getEnd() && this.date.set(moment(this.data().getEnd()));
|
||||
}
|
||||
|
||||
// Display start & due dates
|
||||
onRendered() {
|
||||
super.onRendered();
|
||||
if (moment.isDate(this.card.getStart())) {
|
||||
this.$('.js-datepicker').datepicker('setStartDate', this.card.getStart());
|
||||
}
|
||||
}
|
||||
|
||||
_storeDate(date) {
|
||||
this.card.setEnd(date);
|
||||
}
|
||||
|
||||
_deleteDate() {
|
||||
this.card.setEnd(null);
|
||||
}
|
||||
}).register('editCardEndDatePopup');
|
||||
|
||||
|
||||
// Display received, start, due & end dates
|
||||
const CardDate = BlazeComponent.extendComponent({
|
||||
template() {
|
||||
return 'dateBadge';
|
||||
@@ -161,21 +208,66 @@ const CardDate = BlazeComponent.extendComponent({
|
||||
},
|
||||
});
|
||||
|
||||
class CardReceivedDate extends CardDate {
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
const self = this;
|
||||
self.autorun(() => {
|
||||
self.date.set(moment(self.data().getReceived()));
|
||||
});
|
||||
}
|
||||
|
||||
classes() {
|
||||
let classes = 'received-date ';
|
||||
const dueAt = this.data().getDue();
|
||||
const endAt = this.data().getEnd();
|
||||
const startAt = this.data().getStart();
|
||||
const theDate = this.date.get();
|
||||
// if dueAt, endAt and startAt exist & are > receivedAt, receivedAt doesn't need to be flagged
|
||||
if (((startAt) && (theDate.isAfter(dueAt))) ||
|
||||
((endAt) && (theDate.isAfter(endAt))) ||
|
||||
((dueAt) && (theDate.isAfter(dueAt))))
|
||||
classes += 'long-overdue';
|
||||
else
|
||||
classes += 'current';
|
||||
return classes;
|
||||
}
|
||||
|
||||
showTitle() {
|
||||
return `${TAPi18n.__('card-received-on')} ${this.date.get().format('LLLL')}`;
|
||||
}
|
||||
|
||||
events() {
|
||||
return super.events().concat({
|
||||
'click .js-edit-date': Popup.open('editCardReceivedDate'),
|
||||
});
|
||||
}
|
||||
}
|
||||
CardReceivedDate.register('cardReceivedDate');
|
||||
|
||||
class CardStartDate extends CardDate {
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
const self = this;
|
||||
self.autorun(() => {
|
||||
self.date.set(moment(self.data().startAt));
|
||||
self.date.set(moment(self.data().getStart()));
|
||||
});
|
||||
}
|
||||
|
||||
classes() {
|
||||
let classes = 'start-date' + ' ';
|
||||
if (this.date.get().isBefore(this.now.get(), 'minute') &&
|
||||
this.now.get().isBefore(this.data().dueAt)) {
|
||||
const dueAt = this.data().getDue();
|
||||
const endAt = this.data().getEnd();
|
||||
const theDate = this.date.get();
|
||||
const now = this.now.get();
|
||||
// if dueAt or endAt exist & are > startAt, startAt doesn't need to be flagged
|
||||
if (((endAt) && (theDate.isAfter(endAt))) ||
|
||||
((dueAt) && (theDate.isAfter(dueAt))))
|
||||
classes += 'long-overdue';
|
||||
else if (theDate.isBefore(now, 'minute'))
|
||||
classes += 'almost-due';
|
||||
else
|
||||
classes += 'current';
|
||||
}
|
||||
return classes;
|
||||
}
|
||||
|
||||
@@ -196,17 +288,26 @@ class CardDueDate extends CardDate {
|
||||
super.onCreated();
|
||||
const self = this;
|
||||
self.autorun(() => {
|
||||
self.date.set(moment(self.data().dueAt));
|
||||
self.date.set(moment(self.data().getDue()));
|
||||
});
|
||||
}
|
||||
|
||||
classes() {
|
||||
let classes = 'due-date' + ' ';
|
||||
if (this.now.get().diff(this.date.get(), 'days') >= 2)
|
||||
const endAt = this.data().getEnd();
|
||||
const theDate = this.date.get();
|
||||
const now = this.now.get();
|
||||
// if the due date is after the end date, green - done early
|
||||
if ((endAt) && (theDate.isAfter(endAt)))
|
||||
classes += 'current';
|
||||
// if there is an end date, don't need to flag the due date
|
||||
else if (endAt)
|
||||
classes += '';
|
||||
else if (now.diff(theDate, 'days') >= 2)
|
||||
classes += 'long-overdue';
|
||||
else if (this.now.get().diff(this.date.get(), 'minute') >= 0)
|
||||
else if (now.diff(theDate, 'minute') >= 0)
|
||||
classes += 'due';
|
||||
else if (this.now.get().diff(this.date.get(), 'days') >= -1)
|
||||
else if (now.diff(theDate, 'days') >= -1)
|
||||
classes += 'almost-due';
|
||||
return classes;
|
||||
}
|
||||
@@ -223,6 +324,46 @@ class CardDueDate extends CardDate {
|
||||
}
|
||||
CardDueDate.register('cardDueDate');
|
||||
|
||||
class CardEndDate extends CardDate {
|
||||
onCreated() {
|
||||
super.onCreated();
|
||||
const self = this;
|
||||
self.autorun(() => {
|
||||
self.date.set(moment(self.data().getEnd()));
|
||||
});
|
||||
}
|
||||
|
||||
classes() {
|
||||
let classes = 'end-date' + ' ';
|
||||
const dueAt = this.data().getDue();
|
||||
const theDate = this.date.get();
|
||||
if (theDate.diff(dueAt, 'days') >= 2)
|
||||
classes += 'long-overdue';
|
||||
else if (theDate.diff(dueAt, 'days') >= 0)
|
||||
classes += 'due';
|
||||
else if (theDate.diff(dueAt, 'days') >= -2)
|
||||
classes += 'almost-due';
|
||||
return classes;
|
||||
}
|
||||
|
||||
showTitle() {
|
||||
return `${TAPi18n.__('card-end-on')} ${this.date.get().format('LLLL')}`;
|
||||
}
|
||||
|
||||
events() {
|
||||
return super.events().concat({
|
||||
'click .js-edit-date': Popup.open('editCardEndDate'),
|
||||
});
|
||||
}
|
||||
}
|
||||
CardEndDate.register('cardEndDate');
|
||||
|
||||
(class extends CardReceivedDate {
|
||||
showDate() {
|
||||
return this.date.get().format('l');
|
||||
}
|
||||
}).register('minicardReceivedDate');
|
||||
|
||||
(class extends CardStartDate {
|
||||
showDate() {
|
||||
return this.date.get().format('l');
|
||||
@@ -234,3 +375,9 @@ CardDueDate.register('cardDueDate');
|
||||
return this.date.get().format('l');
|
||||
}
|
||||
}).register('minicardDueDate');
|
||||
|
||||
(class extends CardEndDate {
|
||||
showDate() {
|
||||
return this.date.get().format('l');
|
||||
}
|
||||
}).register('minicardEndDate');
|
||||
@@ -1,22 +1,3 @@
|
||||
.edit-card-date
|
||||
.fields
|
||||
.left
|
||||
width: 56%
|
||||
.right
|
||||
width: 38%
|
||||
.datepicker
|
||||
width: 100%
|
||||
table
|
||||
width: 100%
|
||||
border: none
|
||||
border-spacing: 0
|
||||
border-collapse: collapse
|
||||
thead
|
||||
background: none
|
||||
td, th
|
||||
box-sizing: border-box
|
||||
|
||||
|
||||
.card-date
|
||||
display: block
|
||||
border-radius: 4px
|
||||
@@ -49,12 +30,22 @@
|
||||
&:hover, &.is-active
|
||||
background-color: darken(#fd5d47, 7)
|
||||
|
||||
&.end-date
|
||||
time
|
||||
&::before
|
||||
content: "\f253" // symbol: fa-hourglass-end
|
||||
|
||||
&.due-date
|
||||
time
|
||||
&::before
|
||||
content: "\f090" // symbol: fa-sign-in
|
||||
|
||||
&.start-date
|
||||
time
|
||||
&::before
|
||||
content: "\f251" // symbol: fa-hourglass-start
|
||||
|
||||
&.received-date
|
||||
time
|
||||
&::before
|
||||
content: "\f08b" // symbol: fa-sign-out
|
||||
|
||||
@@ -10,17 +10,63 @@ template(name="cardDetails")
|
||||
h2.card-details-title.js-card-title(
|
||||
class="{{#if canModifyCard}}js-open-inlined-form is-editable{{/if}}")
|
||||
+viewer
|
||||
= title
|
||||
= getTitle
|
||||
if isWatching
|
||||
i.fa.fa-eye.card-details-watch
|
||||
.card-details-path
|
||||
each parentList
|
||||
| >
|
||||
a.js-parent-card(href=linkForCard) {{title}}
|
||||
// else
|
||||
{{_ 'top-level-card'}}
|
||||
if isLinkedCard
|
||||
h3.linked-card-location
|
||||
+viewer
|
||||
| {{getBoardTitle}} > {{getTitle}}
|
||||
|
||||
if archived
|
||||
p.warning {{_ 'card-archived'}}
|
||||
if getArchived
|
||||
if isLinkedBoard
|
||||
p.warning {{_ 'board-archived'}}
|
||||
else
|
||||
p.warning {{_ 'card-archived'}}
|
||||
|
||||
.card-details-items
|
||||
.card-details-item.card-details-item-received
|
||||
h3.card-details-item-title {{_ 'card-received'}}
|
||||
if getReceived
|
||||
+cardReceivedDate
|
||||
else
|
||||
if canModifyCard
|
||||
a.js-received-date {{_ 'add'}}
|
||||
|
||||
.card-details-item.card-details-item-start
|
||||
h3.card-details-item-title {{_ 'card-start'}}
|
||||
if getStart
|
||||
+cardStartDate
|
||||
else
|
||||
if canModifyCard
|
||||
a.js-start-date {{_ 'add'}}
|
||||
|
||||
.card-details-item.card-details-item-due
|
||||
h3.card-details-item-title {{_ 'card-due'}}
|
||||
if getDue
|
||||
+cardDueDate
|
||||
else
|
||||
if canModifyCard
|
||||
a.js-due-date {{_ 'add'}}
|
||||
|
||||
.card-details-item.card-details-item-end
|
||||
h3.card-details-item-title {{_ 'card-end'}}
|
||||
if getEnd
|
||||
+cardEndDate
|
||||
else
|
||||
if canModifyCard
|
||||
a.js-end-date {{_ 'add'}}
|
||||
|
||||
.card-details-items
|
||||
.card-details-item.card-details-item-members
|
||||
h3.card-details-item-title {{_ 'members'}}
|
||||
each members
|
||||
each getMembers
|
||||
+userAvatar(userId=this cardId=../_id)
|
||||
| {{! XXX Hack to hide syntaxic coloration /// }}
|
||||
if canModifyCard
|
||||
@@ -36,20 +82,17 @@ template(name="cardDetails")
|
||||
a.card-label.add-label.js-add-labels(title="{{_ 'card-labels-title'}}")
|
||||
i.fa.fa-plus
|
||||
|
||||
if startAt
|
||||
.card-details-item.card-details-item-start
|
||||
h3.card-details-item-title {{_ 'card-start'}}
|
||||
+cardStartDate
|
||||
|
||||
if dueAt
|
||||
.card-details-item.card-details-item-due
|
||||
h3.card-details-item-title {{_ 'card-due'}}
|
||||
+cardDueDate
|
||||
.card-details-items
|
||||
each customFieldsWD
|
||||
.card-details-item.card-details-item-customfield
|
||||
h3.card-details-item-title
|
||||
= definition.name
|
||||
+cardCustomField
|
||||
|
||||
.card-details-items
|
||||
if spentTime
|
||||
if getSpentTime
|
||||
.card-details-item.card-details-item-spent
|
||||
if isOvertime
|
||||
if getIsOvertime
|
||||
h3.card-details-item-title {{_ 'overtime-hours'}}
|
||||
else
|
||||
h3.card-details-item-title {{_ 'spent-time-hours'}}
|
||||
@@ -60,15 +103,15 @@ template(name="cardDetails")
|
||||
h3.card-details-item-title {{_ 'description'}}
|
||||
+inlinedCardDescription(classNames="card-description js-card-description")
|
||||
+editor(autofocus=true)
|
||||
| {{getUnsavedValue 'cardDescription' _id description}}
|
||||
| {{getUnsavedValue 'cardDescription' _id getDescription}}
|
||||
.edit-controls.clearfix
|
||||
button.primary(type="submit") {{_ 'save'}}
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
else
|
||||
a.js-open-inlined-form
|
||||
if description
|
||||
if getDescription
|
||||
+viewer
|
||||
= description
|
||||
= getDescription
|
||||
else
|
||||
| {{_ 'edit'}}
|
||||
if (hasUnsavedValue 'cardDescription' _id)
|
||||
@@ -77,44 +120,101 @@ template(name="cardDetails")
|
||||
a.js-open-inlined-form {{_ 'view-it'}}
|
||||
= ' - '
|
||||
a.js-close-inlined-form {{_ 'discard'}}
|
||||
else if description
|
||||
else if getDescription
|
||||
h3.card-details-item-title {{_ 'description'}}
|
||||
+viewer
|
||||
= description
|
||||
= getDescription
|
||||
|
||||
.card-details-items
|
||||
.card-details-item.card-details-item-name
|
||||
h3.card-details-item-title {{_ 'requested-by'}}
|
||||
if canModifyCard
|
||||
+inlinedForm(classNames="js-card-details-requester")
|
||||
+editCardRequesterForm
|
||||
else
|
||||
a.js-open-inlined-form
|
||||
if getRequestedBy
|
||||
+viewer
|
||||
= getRequestedBy
|
||||
else
|
||||
| {{_ 'add'}}
|
||||
else if getRequestedBy
|
||||
+viewer
|
||||
= getRequestedBy
|
||||
|
||||
.card-details-item.card-details-item-name
|
||||
h3.card-details-item-title {{_ 'assigned-by'}}
|
||||
if canModifyCard
|
||||
+inlinedForm(classNames="js-card-details-assigner")
|
||||
+editCardAssignerForm
|
||||
else
|
||||
a.js-open-inlined-form
|
||||
if getAssignedBy
|
||||
+viewer
|
||||
= getAssignedBy
|
||||
else
|
||||
| {{_ 'add'}}
|
||||
else if getRequestedBy
|
||||
+viewer
|
||||
= getAssignedBy
|
||||
|
||||
hr
|
||||
+checklists(cardId = _id)
|
||||
|
||||
if currentBoard.allowsSubtasks
|
||||
hr
|
||||
+subtasks(cardId = _id)
|
||||
|
||||
hr
|
||||
h2
|
||||
h3
|
||||
i.fa.fa-paperclip
|
||||
| {{_ 'attachments'}}
|
||||
|
||||
+attachmentsGalery
|
||||
|
||||
hr
|
||||
.activity-title
|
||||
h2 {{ _ 'activity'}}
|
||||
if currentUser.isBoardMember
|
||||
.material-toggle-switch
|
||||
span.toggle-switch-title {{_ 'hide-system-messages'}}
|
||||
if hiddenSystemMessages
|
||||
input.toggle-switch(type="checkbox" id="toggleButton" checked="checked")
|
||||
else
|
||||
input.toggle-switch(type="checkbox" id="toggleButton")
|
||||
label.toggle-label(for="toggleButton")
|
||||
unless currentUser.isNoComments
|
||||
.activity-title
|
||||
h3 {{ _ 'activity'}}
|
||||
if currentUser.isBoardMember
|
||||
.material-toggle-switch
|
||||
span.toggle-switch-title {{_ 'hide-system-messages'}}
|
||||
if hiddenSystemMessages
|
||||
input.toggle-switch(type="checkbox" id="toggleButton" checked="checked")
|
||||
else
|
||||
input.toggle-switch(type="checkbox" id="toggleButton")
|
||||
label.toggle-label(for="toggleButton")
|
||||
if currentUser.isBoardMember
|
||||
+commentForm
|
||||
if isLoaded.get
|
||||
+activities(card=this mode="card")
|
||||
unless currentUser.isNoComments
|
||||
+commentForm
|
||||
unless currentUser.isNoComments
|
||||
if isLoaded.get
|
||||
if isLinkedCard
|
||||
+activities(card=this mode="linkedcard")
|
||||
else if isLinkedBoard
|
||||
+activities(card=this mode="linkedboard")
|
||||
else
|
||||
+activities(card=this mode="card")
|
||||
|
||||
template(name="editCardTitleForm")
|
||||
textarea.js-edit-card-title(rows='1' autofocus)
|
||||
= title
|
||||
= getTitle
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm.js-submit-edit-card-title-form(type="submit") {{_ 'save'}}
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
|
||||
template(name="editCardRequesterForm")
|
||||
input.js-edit-card-requester(type='text' autofocus value=getRequestedBy)
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm.js-submit-edit-card-requester-form(type="submit") {{_ 'save'}}
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
|
||||
template(name="editCardAssignerForm")
|
||||
input.js-edit-card-assigner(type='text' autofocus value=getAssignedBy)
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm.js-submit-edit-card-assigner-form(type="submit") {{_ 'save'}}
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
|
||||
template(name="cardDetailsActionsPopup")
|
||||
ul.pop-over-list
|
||||
li: a.js-toggle-watch-card {{#if isWatching}}{{_ 'unwatch'}}{{else}}{{_ 'watch'}}{{/if}}
|
||||
@@ -124,8 +224,11 @@ template(name="cardDetailsActionsPopup")
|
||||
li: a.js-members {{_ 'card-edit-members'}}
|
||||
li: a.js-labels {{_ 'card-edit-labels'}}
|
||||
li: a.js-attachments {{_ 'card-edit-attachments'}}
|
||||
li: a.js-custom-fields {{_ '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'}}
|
||||
li: a.js-end-date {{_ 'editCardEndDatePopup-title'}}
|
||||
li: a.js-spent-time {{_ 'editCardSpentTimePopup-title'}}
|
||||
hr
|
||||
ul.pop-over-list
|
||||
@@ -135,26 +238,28 @@ template(name="cardDetailsActionsPopup")
|
||||
ul.pop-over-list
|
||||
li: a.js-move-card {{_ 'moveCardPopup-title'}}
|
||||
li: a.js-copy-card {{_ 'copyCardPopup-title'}}
|
||||
li: a.js-copy-checklist-cards {{_ 'copyChecklistToManyCardsPopup-title'}}
|
||||
unless archived
|
||||
li: a.js-archive {{_ 'archive-card'}}
|
||||
li: a.js-more {{_ 'cardMorePopup-title'}}
|
||||
|
||||
template(name="moveCardPopup")
|
||||
if isSandstorm
|
||||
+boardLists
|
||||
else
|
||||
+boardsAndLists
|
||||
+boardsAndLists
|
||||
|
||||
template(name="copyCardPopup")
|
||||
label(for='copy-card-title') {{_ 'title'}}:
|
||||
textarea#copy-card-title.minicard-composer-textarea.js-card-title(autofocus)
|
||||
= title
|
||||
if isSandstorm
|
||||
+boardLists
|
||||
else
|
||||
+boardsAndLists
|
||||
= getTitle
|
||||
+boardsAndLists
|
||||
|
||||
template(name="copyChecklistToManyCardsPopup")
|
||||
label(for='copy-checklist-cards-title') {{_ 'copyChecklistToManyCardsPopup-instructions'}}:
|
||||
textarea#copy-card-title.minicard-composer-textarea.js-card-title(autofocus)
|
||||
| {{_ 'copyChecklistToManyCardsPopup-format'}}
|
||||
+boardsAndLists
|
||||
|
||||
template(name="boardsAndLists")
|
||||
label {{_ 'boards'}}:
|
||||
select.js-select-boards
|
||||
each boards
|
||||
if $eq _id currentBoard._id
|
||||
@@ -162,14 +267,18 @@ template(name="boardsAndLists")
|
||||
else
|
||||
option(value="{{_id}}") {{title}}
|
||||
|
||||
label {{_ 'swimlanes'}}:
|
||||
select.js-select-swimlanes
|
||||
each swimlanes
|
||||
option(value="{{_id}}") {{title}}
|
||||
|
||||
label {{_ 'lists'}}:
|
||||
ul.pop-over-list
|
||||
select.js-select-lists
|
||||
each aBoardLists
|
||||
li
|
||||
if $eq ../_id _id
|
||||
a.disabled {{title}} ({{_ 'current'}})
|
||||
else
|
||||
a.js-select-list= title
|
||||
option(value="{{_id}}") {{title}}
|
||||
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm.js-done {{_ 'done'}}
|
||||
|
||||
template(name="cardMembersPopup")
|
||||
ul.pop-over-list.js-card-member-list
|
||||
@@ -193,10 +302,37 @@ template(name="cardMorePopup")
|
||||
button.js-copy-card-link-to-clipboard(class="btn") {{_ 'copy-card-link-to-clipboard'}}
|
||||
span.clearfix
|
||||
br
|
||||
h2 {{_ 'change-card-parent'}}
|
||||
label {{_ 'source-board'}}:
|
||||
select.js-field-parent-board
|
||||
each boards
|
||||
if isParentBoard
|
||||
option(value="{{_id}}" selected) {{title}}
|
||||
else
|
||||
option(value="{{_id}}") {{title}}
|
||||
if isTopLevel
|
||||
option(value="none" selected) {{_ 'custom-field-dropdown-none'}}
|
||||
else
|
||||
option(value="none") {{_ 'custom-field-dropdown-none'}}
|
||||
|
||||
label {{_ 'parent-card'}}:
|
||||
select.js-field-parent-card
|
||||
if isTopLevel
|
||||
option(value="none" selected) {{_ 'custom-field-dropdown-none'}}
|
||||
else
|
||||
each cards
|
||||
if isParentCard
|
||||
option(value="{{_id}}" selected) {{title}}
|
||||
else
|
||||
option(value="{{_id}}") {{title}}
|
||||
option(value="none") {{_ 'custom-field-dropdown-none'}}
|
||||
br
|
||||
| {{_ 'added'}}
|
||||
span.date(title=card.createdAt) {{ moment createdAt 'LLL' }}
|
||||
a.js-delete(title="{{_ 'card-delete-notice'}}") {{_ 'delete'}}
|
||||
|
||||
|
||||
|
||||
template(name="cardDeletePopup")
|
||||
p {{_ "card-delete-pop"}}
|
||||
unless archived
|
||||
|
||||
@@ -1,4 +1,5 @@
|
||||
const subManager = new SubsManager();
|
||||
const { calculateIndexData, enableClickOnTouch } = Utils;
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
mixins() {
|
||||
@@ -19,9 +20,14 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
onCreated() {
|
||||
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
this.isLoaded = new ReactiveVar(false);
|
||||
this.parentComponent().parentComponent().showOverlay.set(true);
|
||||
this.parentComponent().parentComponent().mouseHasEnterCardDetails = false;
|
||||
const boardBody = this.parentComponent().parentComponent();
|
||||
//in Miniview parent is Board, not BoardBody.
|
||||
if (boardBody !== null) {
|
||||
boardBody.showOverlay.set(true);
|
||||
boardBody.mouseHasEnterCardDetails = false;
|
||||
}
|
||||
this.calculateNextPeak();
|
||||
|
||||
Meteor.subscribe('unsaved-edits');
|
||||
@@ -43,9 +49,10 @@ BlazeComponent.extendComponent({
|
||||
scrollParentContainer() {
|
||||
const cardPanelWidth = 510;
|
||||
const bodyBoardComponent = this.parentComponent().parentComponent();
|
||||
|
||||
const $cardContainer = bodyBoardComponent.$('.js-lists');
|
||||
//On Mobile View Parent is Board, Not Board Body. I cant see how this funciton should work then.
|
||||
if (bodyBoardComponent === null) return;
|
||||
const $cardView = this.$(this.firstNode());
|
||||
const $cardContainer = bodyBoardComponent.$('.js-swimlanes');
|
||||
const cardContainerScroll = $cardContainer.scrollLeft();
|
||||
const cardContainerWidth = $cardContainer.width();
|
||||
|
||||
@@ -64,12 +71,128 @@ BlazeComponent.extendComponent({
|
||||
}
|
||||
},
|
||||
|
||||
presentParentTask() {
|
||||
let result = this.currentBoard.presentParentTask;
|
||||
if ((result === null) || (result === undefined)) {
|
||||
result = 'no-parent';
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
linkForCard() {
|
||||
const card = this.currentData();
|
||||
let result = '#';
|
||||
if (card) {
|
||||
const board = Boards.findOne(card.boardId);
|
||||
if (board) {
|
||||
result = FlowRouter.url('card', {
|
||||
boardId: card.boardId,
|
||||
slug: board.slug,
|
||||
cardId: card._id,
|
||||
});
|
||||
}
|
||||
}
|
||||
return result;
|
||||
},
|
||||
|
||||
onRendered() {
|
||||
if (!Utils.isMiniScreen()) this.scrollParentContainer();
|
||||
const $checklistsDom = this.$('.card-checklist-items');
|
||||
|
||||
$checklistsDom.sortable({
|
||||
tolerance: 'pointer',
|
||||
helper: 'clone',
|
||||
handle: '.checklist-title',
|
||||
items: '.js-checklist',
|
||||
placeholder: 'checklist placeholder',
|
||||
distance: 7,
|
||||
start(evt, ui) {
|
||||
ui.placeholder.height(ui.helper.height());
|
||||
EscapeActions.executeUpTo('popup-close');
|
||||
},
|
||||
stop(evt, ui) {
|
||||
let prevChecklist = ui.item.prev('.js-checklist').get(0);
|
||||
if (prevChecklist) {
|
||||
prevChecklist = Blaze.getData(prevChecklist).checklist;
|
||||
}
|
||||
let nextChecklist = ui.item.next('.js-checklist').get(0);
|
||||
if (nextChecklist) {
|
||||
nextChecklist = Blaze.getData(nextChecklist).checklist;
|
||||
}
|
||||
const sortIndex = calculateIndexData(prevChecklist, nextChecklist, 1);
|
||||
|
||||
$checklistsDom.sortable('cancel');
|
||||
const checklist = Blaze.getData(ui.item.get(0)).checklist;
|
||||
|
||||
Checklists.update(checklist._id, {
|
||||
$set: {
|
||||
sort: sortIndex.base,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// ugly touch event hotfix
|
||||
enableClickOnTouch('.card-checklist-items .js-checklist');
|
||||
|
||||
const $subtasksDom = this.$('.card-subtasks-items');
|
||||
|
||||
$subtasksDom.sortable({
|
||||
tolerance: 'pointer',
|
||||
helper: 'clone',
|
||||
handle: '.subtask-title',
|
||||
items: '.js-subtasks',
|
||||
placeholder: 'subtasks placeholder',
|
||||
distance: 7,
|
||||
start(evt, ui) {
|
||||
ui.placeholder.height(ui.helper.height());
|
||||
EscapeActions.executeUpTo('popup-close');
|
||||
},
|
||||
stop(evt, ui) {
|
||||
let prevChecklist = ui.item.prev('.js-subtasks').get(0);
|
||||
if (prevChecklist) {
|
||||
prevChecklist = Blaze.getData(prevChecklist).subtask;
|
||||
}
|
||||
let nextChecklist = ui.item.next('.js-subtasks').get(0);
|
||||
if (nextChecklist) {
|
||||
nextChecklist = Blaze.getData(nextChecklist).subtask;
|
||||
}
|
||||
const sortIndex = calculateIndexData(prevChecklist, nextChecklist, 1);
|
||||
|
||||
$subtasksDom.sortable('cancel');
|
||||
const subtask = Blaze.getData(ui.item.get(0)).subtask;
|
||||
|
||||
Subtasks.update(subtask._id, {
|
||||
$set: {
|
||||
subtaskSort: sortIndex.base,
|
||||
},
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
// ugly touch event hotfix
|
||||
enableClickOnTouch('.card-subtasks-items .js-subtasks');
|
||||
|
||||
function userIsMember() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember();
|
||||
}
|
||||
|
||||
// Disable sorting if the current user is not a board member
|
||||
this.autorun(() => {
|
||||
if ($checklistsDom.data('sortable')) {
|
||||
$checklistsDom.sortable('option', 'disabled', !userIsMember());
|
||||
}
|
||||
if ($subtasksDom.data('sortable')) {
|
||||
$subtasksDom.sortable('option', 'disabled', !userIsMember());
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
onDestroyed() {
|
||||
this.parentComponent().parentComponent().showOverlay.set(false);
|
||||
const parentComponent = this.parentComponent().parentComponent();
|
||||
//on mobile view parent is Board, not board body.
|
||||
if (parentComponent === null) return;
|
||||
parentComponent.showOverlay.set(false);
|
||||
},
|
||||
|
||||
events() {
|
||||
@@ -100,12 +223,33 @@ BlazeComponent.extendComponent({
|
||||
this.data().setTitle(title);
|
||||
}
|
||||
},
|
||||
'submit .js-card-details-assigner'(evt) {
|
||||
evt.preventDefault();
|
||||
const assigner = this.currentComponent().getValue().trim();
|
||||
if (assigner) {
|
||||
this.data().setAssignedBy(assigner);
|
||||
}
|
||||
},
|
||||
'submit .js-card-details-requester'(evt) {
|
||||
evt.preventDefault();
|
||||
const requester = this.currentComponent().getValue().trim();
|
||||
if (requester) {
|
||||
this.data().setRequestedBy(requester);
|
||||
}
|
||||
},
|
||||
'click .js-member': Popup.open('cardMember'),
|
||||
'click .js-add-members': Popup.open('cardMembers'),
|
||||
'click .js-add-labels': Popup.open('cardLabels'),
|
||||
'click .js-received-date': Popup.open('editCardReceivedDate'),
|
||||
'click .js-start-date': Popup.open('editCardStartDate'),
|
||||
'click .js-due-date': Popup.open('editCardDueDate'),
|
||||
'click .js-end-date': Popup.open('editCardEndDate'),
|
||||
'mouseenter .js-card-details' () {
|
||||
this.parentComponent().parentComponent().showOverlay.set(true);
|
||||
this.parentComponent().parentComponent().mouseHasEnterCardDetails = true;
|
||||
const parentComponent = this.parentComponent().parentComponent();
|
||||
//on mobile view parent is Board, not BoardBody.
|
||||
if (parentComponent === null) return;
|
||||
parentComponent.showOverlay.set(true);
|
||||
parentComponent.mouseHasEnterCardDetails = true;
|
||||
},
|
||||
'click #toggleButton'() {
|
||||
Meteor.call('toggleSystemMessages');
|
||||
@@ -130,7 +274,7 @@ BlazeComponent.extendComponent({
|
||||
close(isReset = false) {
|
||||
if (this.isOpen.get() && !isReset) {
|
||||
const draft = this.getValue().trim();
|
||||
if (draft !== Cards.findOne(Session.get('currentCard')).description) {
|
||||
if (draft !== Cards.findOne(Session.get('currentCard')).getDescription()) {
|
||||
UnsavedEdits.set(this._getUnsavedEditKey(), this.getValue());
|
||||
}
|
||||
}
|
||||
@@ -165,11 +309,15 @@ Template.cardDetailsActionsPopup.events({
|
||||
'click .js-members': Popup.open('cardMembers'),
|
||||
'click .js-labels': Popup.open('cardLabels'),
|
||||
'click .js-attachments': Popup.open('cardAttachments'),
|
||||
'click .js-custom-fields': Popup.open('cardCustomFields'),
|
||||
'click .js-received-date': Popup.open('editCardReceivedDate'),
|
||||
'click .js-start-date': Popup.open('editCardStartDate'),
|
||||
'click .js-due-date': Popup.open('editCardDueDate'),
|
||||
'click .js-end-date': Popup.open('editCardEndDate'),
|
||||
'click .js-spent-time': Popup.open('editCardSpentTime'),
|
||||
'click .js-move-card': Popup.open('moveCard'),
|
||||
'click .js-copy-card': Popup.open('copyCard'),
|
||||
'click .js-copy-checklist-cards': Popup.open('copyChecklistToManyCards'),
|
||||
'click .js-move-card-to-top' (evt) {
|
||||
evt.preventDefault();
|
||||
const minOrder = _.min(this.list().cards(this.swimlaneId).map((c) => c.sort));
|
||||
@@ -209,20 +357,49 @@ Template.editCardTitleForm.events({
|
||||
},
|
||||
});
|
||||
|
||||
Template.editCardRequesterForm.onRendered(function() {
|
||||
autosize(this.$('.js-edit-card-requester'));
|
||||
});
|
||||
|
||||
Template.editCardRequesterForm.events({
|
||||
'keydown .js-edit-card-requester'(evt) {
|
||||
// If enter key was pressed, submit the data
|
||||
if (evt.keyCode === 13) {
|
||||
$('.js-submit-edit-card-requester-form').click();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.editCardAssignerForm.onRendered(function() {
|
||||
autosize(this.$('.js-edit-card-assigner'));
|
||||
});
|
||||
|
||||
Template.editCardAssignerForm.events({
|
||||
'keydown .js-edit-card-assigner'(evt) {
|
||||
// If enter key was pressed, submit the data
|
||||
if (evt.keyCode === 13) {
|
||||
$('.js-submit-edit-card-assigner-form').click();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.moveCardPopup.events({
|
||||
'click .js-select-list' () {
|
||||
'click .js-done' () {
|
||||
// XXX We should *not* get the currentCard from the global state, but
|
||||
// instead from a “component” state.
|
||||
const card = Cards.findOne(Session.get('currentCard'));
|
||||
const newListId = this._id;
|
||||
const lSelect = $('.js-select-lists')[0];
|
||||
const newListId = lSelect.options[lSelect.selectedIndex].value;
|
||||
const slSelect = $('.js-select-swimlanes')[0];
|
||||
card.swimlaneId = slSelect.options[slSelect.selectedIndex].value;
|
||||
card.move(card.swimlaneId, newListId, 0);
|
||||
Popup.close();
|
||||
},
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.selectedBoard = new ReactiveVar(Session.get('currentBoard'));
|
||||
subManager.subscribe('board', Session.get('currentBoard'));
|
||||
this.selectedBoardId = new ReactiveVar(Session.get('currentBoard'));
|
||||
},
|
||||
|
||||
boards() {
|
||||
@@ -235,32 +412,56 @@ BlazeComponent.extendComponent({
|
||||
return boards;
|
||||
},
|
||||
|
||||
swimlanes() {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
return board.swimlanes();
|
||||
},
|
||||
|
||||
aBoardLists() {
|
||||
subManager.subscribe('board', this.selectedBoard.get());
|
||||
const board = Boards.findOne(this.selectedBoard.get());
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
return board.lists();
|
||||
},
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'change .js-select-boards'(evt) {
|
||||
this.selectedBoard.set($(evt.currentTarget).val());
|
||||
this.selectedBoardId.set($(evt.currentTarget).val());
|
||||
subManager.subscribe('board', this.selectedBoardId.get());
|
||||
},
|
||||
}];
|
||||
},
|
||||
}).register('boardsAndLists');
|
||||
|
||||
|
||||
function cloneCheckList(_id, checklist) {
|
||||
'use strict';
|
||||
const checklistId = checklist._id;
|
||||
checklist.cardId = _id;
|
||||
checklist._id = null;
|
||||
const newChecklistId = Checklists.insert(checklist);
|
||||
ChecklistItems.find({checklistId}).forEach(function(item) {
|
||||
item._id = null;
|
||||
item.checklistId = newChecklistId;
|
||||
item.cardId = _id;
|
||||
ChecklistItems.insert(item);
|
||||
});
|
||||
}
|
||||
|
||||
Template.copyCardPopup.events({
|
||||
'click .js-select-list' (evt) {
|
||||
'click .js-done'() {
|
||||
const card = Cards.findOne(Session.get('currentCard'));
|
||||
const oldId = card._id;
|
||||
card._id = null;
|
||||
card.listId = this._id;
|
||||
const list = Lists.findOne(card.listId);
|
||||
card.boardId = list.boardId;
|
||||
const textarea = $(evt.currentTarget).parents('.content').find('textarea');
|
||||
const lSelect = $('.js-select-lists')[0];
|
||||
card.listId = lSelect.options[lSelect.selectedIndex].value;
|
||||
const slSelect = $('.js-select-swimlanes')[0];
|
||||
card.swimlaneId = slSelect.options[slSelect.selectedIndex].value;
|
||||
const bSelect = $('.js-select-boards')[0];
|
||||
card.boardId = bSelect.options[bSelect.selectedIndex].value;
|
||||
const textarea = $('#copy-card-title');
|
||||
const title = textarea.val().trim();
|
||||
// insert new card to the bottom of new list
|
||||
card.sort = Lists.findOne(this._id).cards().count();
|
||||
card.sort = Lists.findOne(card.listId).cards().count();
|
||||
|
||||
if (title) {
|
||||
card.title = title;
|
||||
@@ -274,12 +475,18 @@ Template.copyCardPopup.events({
|
||||
|
||||
// copy checklists
|
||||
let cursor = Checklists.find({cardId: oldId});
|
||||
cursor.forEach(function() {
|
||||
cloneCheckList(_id, arguments[0]);
|
||||
});
|
||||
|
||||
// copy subtasks
|
||||
cursor = Cards.find({parentId: oldId});
|
||||
cursor.forEach(function() {
|
||||
'use strict';
|
||||
const checklist = arguments[0];
|
||||
checklist.cardId = _id;
|
||||
checklist._id = null;
|
||||
Checklists.insert(checklist);
|
||||
const subtask = arguments[0];
|
||||
subtask.parentId = _id;
|
||||
subtask._id = null;
|
||||
/* const newSubtaskId = */ Cards.insert(subtask);
|
||||
});
|
||||
|
||||
// copy card comments
|
||||
@@ -296,36 +503,181 @@ Template.copyCardPopup.events({
|
||||
},
|
||||
});
|
||||
|
||||
Template.cardMorePopup.events({
|
||||
'click .js-copy-card-link-to-clipboard' () {
|
||||
// Clipboard code from:
|
||||
// https://stackoverflow.com/questions/6300213/copy-selected-text-to-the-clipboard-without-using-flash-must-be-cross-browser
|
||||
const StringToCopyElement = document.getElementById('cardURL');
|
||||
StringToCopyElement.select();
|
||||
if (document.execCommand('copy')) {
|
||||
StringToCopyElement.blur();
|
||||
} else {
|
||||
document.getElementById('cardURL').selectionStart = 0;
|
||||
document.getElementById('cardURL').selectionEnd = 999;
|
||||
document.execCommand('copy');
|
||||
if (window.getSelection) {
|
||||
if (window.getSelection().empty) { // Chrome
|
||||
window.getSelection().empty();
|
||||
} else if (window.getSelection().removeAllRanges) { // Firefox
|
||||
window.getSelection().removeAllRanges();
|
||||
}
|
||||
} else if (document.selection) { // IE?
|
||||
document.selection.empty();
|
||||
Template.copyChecklistToManyCardsPopup.events({
|
||||
'click .js-done' () {
|
||||
const card = Cards.findOne(Session.get('currentCard'));
|
||||
const oldId = card._id;
|
||||
card._id = null;
|
||||
const lSelect = $('.js-select-lists')[0];
|
||||
card.listId = lSelect.options[lSelect.selectedIndex].value;
|
||||
const slSelect = $('.js-select-swimlanes')[0];
|
||||
card.swimlaneId = slSelect.options[slSelect.selectedIndex].value;
|
||||
const bSelect = $('.js-select-boards')[0];
|
||||
card.boardId = bSelect.options[bSelect.selectedIndex].value;
|
||||
const textarea = $('#copy-card-title');
|
||||
const titleEntry = textarea.val().trim();
|
||||
// insert new card to the bottom of new list
|
||||
card.sort = Lists.findOne(card.listId).cards().count();
|
||||
|
||||
if (titleEntry) {
|
||||
const titleList = JSON.parse(titleEntry);
|
||||
for (let i = 0; i < titleList.length; i++){
|
||||
const obj = titleList[i];
|
||||
card.title = obj.title;
|
||||
card.description = obj.description;
|
||||
card.coverId = '';
|
||||
const _id = Cards.insert(card);
|
||||
// In case the filter is active we need to add the newly inserted card in
|
||||
// the list of exceptions -- cards that are not filtered. Otherwise the
|
||||
// card will disappear instantly.
|
||||
// See https://github.com/wekan/wekan/issues/80
|
||||
Filter.addException(_id);
|
||||
|
||||
// copy checklists
|
||||
let cursor = Checklists.find({cardId: oldId});
|
||||
cursor.forEach(function() {
|
||||
cloneCheckList(_id, arguments[0]);
|
||||
});
|
||||
|
||||
// copy subtasks
|
||||
cursor = Cards.find({parentId: oldId});
|
||||
cursor.forEach(function() {
|
||||
'use strict';
|
||||
const subtask = arguments[0];
|
||||
subtask.parentId = _id;
|
||||
subtask._id = null;
|
||||
/* const newSubtaskId = */ Cards.insert(subtask);
|
||||
});
|
||||
|
||||
// copy card comments
|
||||
cursor = CardComments.find({cardId: oldId});
|
||||
cursor.forEach(function () {
|
||||
'use strict';
|
||||
const comment = arguments[0];
|
||||
comment.cardId = _id;
|
||||
comment._id = null;
|
||||
CardComments.insert(comment);
|
||||
});
|
||||
}
|
||||
Popup.close();
|
||||
}
|
||||
},
|
||||
'click .js-delete': Popup.afterConfirm('cardDelete', function () {
|
||||
Popup.close();
|
||||
Cards.remove(this._id);
|
||||
Utils.goBoardId(this.boardId);
|
||||
}),
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentCard = this.currentData();
|
||||
this.parentCard = this.currentCard.parentCard();
|
||||
if (this.parentCard) {
|
||||
this.parentBoard = this.parentCard.board();
|
||||
} else {
|
||||
this.parentBoard = null;
|
||||
}
|
||||
},
|
||||
|
||||
boards() {
|
||||
const boards = Boards.find({
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
}, {
|
||||
sort: ['title'],
|
||||
});
|
||||
return boards;
|
||||
},
|
||||
|
||||
cards() {
|
||||
if (this.parentBoard) {
|
||||
return this.parentBoard.cards();
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
},
|
||||
|
||||
isParentBoard() {
|
||||
const board = this.currentData();
|
||||
if (this.parentBoard) {
|
||||
return board._id === this.parentBoard;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
isParentCard() {
|
||||
const card = this.currentData();
|
||||
if (this.parentCard) {
|
||||
return card._id === this.parentCard;
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
setParentCardId(cardId) {
|
||||
if (cardId === 'null') {
|
||||
cardId = null;
|
||||
this.parentCard = null;
|
||||
} else {
|
||||
this.parentCard = Cards.findOne(cardId);
|
||||
}
|
||||
this.currentCard.setParentId(cardId);
|
||||
},
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'click .js-copy-card-link-to-clipboard' () {
|
||||
// Clipboard code from:
|
||||
// https://stackoverflow.com/questions/6300213/copy-selected-text-to-the-clipboard-without-using-flash-must-be-cross-browser
|
||||
const StringToCopyElement = document.getElementById('cardURL');
|
||||
StringToCopyElement.select();
|
||||
if (document.execCommand('copy')) {
|
||||
StringToCopyElement.blur();
|
||||
} else {
|
||||
document.getElementById('cardURL').selectionStart = 0;
|
||||
document.getElementById('cardURL').selectionEnd = 999;
|
||||
document.execCommand('copy');
|
||||
if (window.getSelection) {
|
||||
if (window.getSelection().empty) { // Chrome
|
||||
window.getSelection().empty();
|
||||
} else if (window.getSelection().removeAllRanges) { // Firefox
|
||||
window.getSelection().removeAllRanges();
|
||||
}
|
||||
} else if (document.selection) { // IE?
|
||||
document.selection.empty();
|
||||
}
|
||||
}
|
||||
},
|
||||
'click .js-delete': Popup.afterConfirm('cardDelete', function () {
|
||||
Popup.close();
|
||||
Cards.remove(this._id);
|
||||
Utils.goBoardId(this.boardId);
|
||||
}),
|
||||
'change .js-field-parent-board'(evt) {
|
||||
const selection = $(evt.currentTarget).val();
|
||||
const list = $('.js-field-parent-card');
|
||||
list.empty();
|
||||
if (selection === 'none') {
|
||||
this.parentBoard = null;
|
||||
list.prop('disabled', true);
|
||||
} else {
|
||||
this.parentBoard = Boards.findOne(selection);
|
||||
this.parentBoard.cards().forEach(function(card) {
|
||||
list.append(
|
||||
$('<option></option>').val(card._id).html(card.title)
|
||||
);
|
||||
});
|
||||
list.prop('disabled', false);
|
||||
}
|
||||
list.append(
|
||||
`<option value='none' selected='selected'>${TAPi18n.__('custom-field-dropdown-none')}</option>`
|
||||
);
|
||||
this.setParentCardId('null');
|
||||
},
|
||||
'change .js-field-parent-card'(evt) {
|
||||
const selection = $(evt.currentTarget).val();
|
||||
this.setParentCardId(selection);
|
||||
},
|
||||
}];
|
||||
},
|
||||
}).register('cardMorePopup');
|
||||
|
||||
|
||||
// Close the card details pane by pressing escape
|
||||
EscapeActions.register('detailsPane',
|
||||
() => {
|
||||
|
||||
@@ -2,11 +2,11 @@
|
||||
|
||||
.card-details
|
||||
padding: 0 20px
|
||||
height: 100%
|
||||
flex-shrink: 0
|
||||
flex-basis: 470px
|
||||
will-change: flex-basis
|
||||
overflow: hidden
|
||||
overflow-y: scroll
|
||||
overflow-x: hidden
|
||||
background: darken(white, 3%)
|
||||
border-radius: bottom 3px
|
||||
z-index: 20 !important
|
||||
@@ -47,6 +47,12 @@
|
||||
margin: 7px 0 0
|
||||
padding: 0
|
||||
|
||||
.linked-card-location
|
||||
font-style: italic
|
||||
font-size: 1em
|
||||
margin-bottom: 0
|
||||
& p
|
||||
margin-bottom: 0
|
||||
|
||||
form.inlined-form
|
||||
margin-top: 5px
|
||||
@@ -70,6 +76,7 @@
|
||||
|
||||
.card-details-items
|
||||
display: flex
|
||||
flex-wrap: wrap
|
||||
margin: 15px 0
|
||||
|
||||
.card-details-item
|
||||
@@ -78,14 +85,18 @@
|
||||
margin-right: 0
|
||||
&.card-details-item-labels,
|
||||
&.card-details-item-members,
|
||||
&.card-details-item-received,
|
||||
&.card-details-item-start,
|
||||
&.card-details-item-due
|
||||
width: 50%
|
||||
flex-shrink: 1
|
||||
&.card-details-item-due,
|
||||
&.card-details-item-end,
|
||||
&.card-details-item-customfield,
|
||||
&.card-details-item-name
|
||||
max-width: 50%
|
||||
flex-grow: 1
|
||||
|
||||
.card-details-item-title
|
||||
font-size: 14px
|
||||
color: darken(white, 45%)
|
||||
font-size: 16px
|
||||
color: #000
|
||||
|
||||
.card-label
|
||||
padding-top: 5px
|
||||
|
||||
@@ -3,10 +3,10 @@ template(name="editCardSpentTime")
|
||||
form.edit-time
|
||||
.fields
|
||||
label(for="time") {{_ 'time'}}
|
||||
input.js-time-field#time(type="number" step="0.01" name="time" value="{{card.spentTime}}" placeholder=timeFormat autofocus)
|
||||
input.js-time-field#time(type="number" step="0.01" name="time" value="{{card.getSpentTime}}" placeholder=timeFormat autofocus)
|
||||
label(for="overtime") {{_ 'overtime'}}
|
||||
a.js-toggle-overtime
|
||||
.materialCheckBox#overtime(class="{{#if card.isOvertime}}is-checked{{/if}}" name="overtime")
|
||||
.materialCheckBox#overtime(class="{{#if getIsOvertime}}is-checked{{/if}}" name="overtime")
|
||||
|
||||
if error.get
|
||||
.warning {{_ error.get}}
|
||||
@@ -15,8 +15,8 @@ template(name="editCardSpentTime")
|
||||
|
||||
template(name="timeBadge")
|
||||
if canModifyCard
|
||||
a.js-edit-time.card-time(title="{{showTitle}}" class="{{#if isOvertime}}card-label-red{{else}}card-label-green{{/if}}")
|
||||
a.js-edit-time.card-time(title="{{showTitle}}" class="{{#if getIsOvertime}}card-label-red{{else}}card-label-green{{/if}}")
|
||||
| {{showTime}}
|
||||
else
|
||||
a.card-time(title="{{showTitle}}" class="{{#if isOvertime}}card-label-red{{else}}card-label-green{{/if}}")
|
||||
a.card-time(title="{{showTitle}}" class="{{#if getIsOvertime}}card-label-red{{else}}card-label-green{{/if}}")
|
||||
| {{showTime}}
|
||||
@@ -7,17 +7,17 @@ BlazeComponent.extendComponent({
|
||||
this.card = this.data();
|
||||
},
|
||||
toggleOvertime() {
|
||||
this.card.isOvertime = !this.card.isOvertime;
|
||||
this.card.setIsOvertime(!this.card.getIsOvertime());
|
||||
$('#overtime .materialCheckBox').toggleClass('is-checked');
|
||||
|
||||
$('#overtime').toggleClass('is-checked');
|
||||
},
|
||||
storeTime(spentTime, isOvertime) {
|
||||
this.card.setSpentTime(spentTime);
|
||||
this.card.setOvertime(isOvertime);
|
||||
this.card.setIsOvertime(isOvertime);
|
||||
},
|
||||
deleteTime() {
|
||||
this.card.unsetSpentTime();
|
||||
this.card.setSpentTime(null);
|
||||
},
|
||||
events() {
|
||||
return [{
|
||||
@@ -26,7 +26,7 @@ BlazeComponent.extendComponent({
|
||||
evt.preventDefault();
|
||||
|
||||
const spentTime = parseFloat(evt.target.time.value);
|
||||
const isOvertime = this.card.isOvertime;
|
||||
const isOvertime = this.card.getIsOvertime();
|
||||
|
||||
if (spentTime >= 0) {
|
||||
this.storeTime(spentTime, isOvertime);
|
||||
@@ -55,17 +55,14 @@ BlazeComponent.extendComponent({
|
||||
self.time = ReactiveVar();
|
||||
},
|
||||
showTitle() {
|
||||
if (this.data().isOvertime) {
|
||||
return `${TAPi18n.__('overtime')} ${this.data().spentTime} ${TAPi18n.__('hours')}`;
|
||||
if (this.data().getIsOvertime()) {
|
||||
return `${TAPi18n.__('overtime')} ${this.data().getSpentTime()} ${TAPi18n.__('hours')}`;
|
||||
} else {
|
||||
return `${TAPi18n.__('card-spent')} ${this.data().spentTime} ${TAPi18n.__('hours')}`;
|
||||
return `${TAPi18n.__('card-spent')} ${this.data().getSpentTime()} ${TAPi18n.__('hours')}`;
|
||||
}
|
||||
},
|
||||
showTime() {
|
||||
return this.data().spentTime;
|
||||
},
|
||||
isOvertime() {
|
||||
return this.data().isOvertime;
|
||||
return this.data().getSpentTime();
|
||||
},
|
||||
events() {
|
||||
return [{
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
template(name="checklists")
|
||||
h2 {{_ 'checklists'}}
|
||||
h3 {{_ 'checklists'}}
|
||||
if toggleDeleteDialog.get
|
||||
.board-overlay#card-details-overlay
|
||||
+checklistDeleteDialog(checklist = checklistToDelete)
|
||||
@@ -18,24 +18,24 @@ template(name="checklists")
|
||||
| {{_ 'add-checklist'}}...
|
||||
|
||||
template(name="checklistDetail")
|
||||
+inlinedForm(classNames="js-edit-checklist-title" checklist = checklist)
|
||||
+editChecklistItemForm(checklist = checklist)
|
||||
else
|
||||
.checklist-title
|
||||
.checkbox.fa.fa-check-square-o
|
||||
if canModifyCard
|
||||
a.js-delete-checklist.toggle-delete-checklist-dialog {{_ "delete"}}...
|
||||
.js-checklist.checklist
|
||||
+inlinedForm(classNames="js-edit-checklist-title" checklist = checklist)
|
||||
+editChecklistItemForm(checklist = checklist)
|
||||
else
|
||||
.checklist-title
|
||||
span
|
||||
if canModifyCard
|
||||
a.js-delete-checklist.toggle-delete-checklist-dialog {{_ "delete"}}...
|
||||
|
||||
span.checklist-stat(class="{{#if checklist.isFinished}}is-finished{{/if}}") {{checklist.finishedCount}}/{{checklist.itemCount}}
|
||||
if canModifyCard
|
||||
h2.title.js-open-inlined-form.is-editable
|
||||
+viewer
|
||||
= checklist.title
|
||||
else
|
||||
h2.title
|
||||
+viewer
|
||||
if canModifyCard
|
||||
h2.title.js-open-inlined-form.is-editable
|
||||
+viewer
|
||||
= checklist.title
|
||||
+checklistItems(checklist = checklist)
|
||||
else
|
||||
h2.title
|
||||
+viewer
|
||||
= checklist.title
|
||||
+checklistItems(checklist = checklist)
|
||||
|
||||
template(name="checklistDeleteDialog")
|
||||
.js-confirm-checklist-delete
|
||||
@@ -70,11 +70,11 @@ template(name="editChecklistItemForm")
|
||||
|
||||
template(name="checklistItems")
|
||||
.checklist-items.js-checklist-items
|
||||
each item in checklist.getItemsSorted
|
||||
each item in checklist.items
|
||||
+inlinedForm(classNames="js-edit-checklist-item" item = item checklist = checklist)
|
||||
+editChecklistItemForm(type = 'item' item = item checklist = checklist)
|
||||
else
|
||||
+itemDetail(item = item checklist = checklist)
|
||||
+checklistItemDetail(item = item checklist = checklist)
|
||||
if canModifyCard
|
||||
+inlinedForm(autoclose=false classNames="js-add-checklist-item" checklist = checklist)
|
||||
+addChecklistItemForm
|
||||
@@ -83,8 +83,8 @@ template(name="checklistItems")
|
||||
i.fa.fa-plus
|
||||
| {{_ 'add-checklist-item'}}...
|
||||
|
||||
template(name='itemDetail')
|
||||
.item.js-checklist-item
|
||||
template(name='checklistItemDetail')
|
||||
.js-checklist-item.checklist-item
|
||||
if canModifyCard
|
||||
.check-box.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}")
|
||||
.item-title.js-open-inlined-form.is-editable(class="{{#if item.isFinished }}is-checked{{/if}}")
|
||||
|
||||
@@ -1,11 +1,14 @@
|
||||
const { calculateIndexData, enableClickOnTouch } = Utils;
|
||||
|
||||
function initSorting(items) {
|
||||
items.sortable({
|
||||
tolerance: 'pointer',
|
||||
helper: 'clone',
|
||||
items: '.js-checklist-item:not(.placeholder)',
|
||||
axis: 'y',
|
||||
connectWith: '.js-checklist-items',
|
||||
appendTo: '.board-canvas',
|
||||
distance: 7,
|
||||
placeholder: 'placeholder',
|
||||
placeholder: 'checklist-item placeholder',
|
||||
scroll: false,
|
||||
start(evt, ui) {
|
||||
ui.placeholder.height(ui.helper.height());
|
||||
@@ -13,57 +16,57 @@ function initSorting(items) {
|
||||
},
|
||||
stop(evt, ui) {
|
||||
const parent = ui.item.parents('.js-checklist-items');
|
||||
const orderedItems = [];
|
||||
parent.find('.js-checklist-item').each(function(i, item) {
|
||||
const checklistItem = Blaze.getData(item).item;
|
||||
orderedItems.push(checklistItem._id);
|
||||
});
|
||||
items.sortable('cancel');
|
||||
const formerParent = ui.item.parents('.js-checklist-items');
|
||||
const checklist = Blaze.getData(parent.get(0)).checklist;
|
||||
const oldChecklist = Blaze.getData(formerParent.get(0)).checklist;
|
||||
if (oldChecklist._id !== checklist._id) {
|
||||
const currentItem = Blaze.getData(ui.item.get(0)).item;
|
||||
for (let i = 0; i < orderedItems.length; i++) {
|
||||
const itemId = orderedItems[i];
|
||||
if (itemId !== currentItem._id) continue;
|
||||
const newItem = {
|
||||
_id: checklist.getNewItemId(),
|
||||
title: currentItem.title,
|
||||
sort: i,
|
||||
isFinished: currentItem.isFinished,
|
||||
};
|
||||
checklist.addFullItem(newItem);
|
||||
orderedItems[i] = currentItem._id;
|
||||
oldChecklist.removeItem(itemId);
|
||||
}
|
||||
} else {
|
||||
checklist.sortItems(orderedItems);
|
||||
const checklistId = Blaze.getData(parent.get(0)).checklist._id;
|
||||
let prevItem = ui.item.prev('.js-checklist-item').get(0);
|
||||
if (prevItem) {
|
||||
prevItem = Blaze.getData(prevItem).item;
|
||||
}
|
||||
let nextItem = ui.item.next('.js-checklist-item').get(0);
|
||||
if (nextItem) {
|
||||
nextItem = Blaze.getData(nextItem).item;
|
||||
}
|
||||
const nItems = 1;
|
||||
const sortIndex = calculateIndexData(prevItem, nextItem, nItems);
|
||||
const checklistDomElement = ui.item.get(0);
|
||||
const checklistData = Blaze.getData(checklistDomElement);
|
||||
const checklistItem = checklistData.item;
|
||||
|
||||
items.sortable('cancel');
|
||||
|
||||
checklistItem.move(checklistId, sortIndex.base);
|
||||
},
|
||||
});
|
||||
|
||||
// ugly touch event hotfix
|
||||
enableClickOnTouch('.js-checklist-item:not(.placeholder)');
|
||||
}
|
||||
|
||||
Template.checklists.onRendered(function () {
|
||||
const self = BlazeComponent.getComponentForElement(this.firstNode);
|
||||
self.itemsDom = this.$('.card-checklist-items');
|
||||
initSorting(self.itemsDom);
|
||||
self.itemsDom.mousedown(function(evt) {
|
||||
evt.stopPropagation();
|
||||
});
|
||||
BlazeComponent.extendComponent({
|
||||
onRendered() {
|
||||
const self = this;
|
||||
self.itemsDom = this.$('.js-checklist-items');
|
||||
initSorting(self.itemsDom);
|
||||
self.itemsDom.mousedown(function(evt) {
|
||||
evt.stopPropagation();
|
||||
});
|
||||
|
||||
function userIsMember() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember();
|
||||
}
|
||||
|
||||
// Disable sorting if the current user is not a board member
|
||||
self.autorun(() => {
|
||||
const $itemsDom = $(self.itemsDom);
|
||||
if ($itemsDom.data('sortable')) {
|
||||
$(self.itemsDom).sortable('option', 'disabled', !userIsMember());
|
||||
function userIsMember() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember();
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
// Disable sorting if the current user is not a board member
|
||||
self.autorun(() => {
|
||||
const $itemsDom = $(self.itemsDom);
|
||||
if ($itemsDom.data('sortable')) {
|
||||
$(self.itemsDom).sortable('option', 'disabled', !userIsMember());
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
|
||||
},
|
||||
}).register('checklistDetail');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
|
||||
@@ -71,8 +74,10 @@ BlazeComponent.extendComponent({
|
||||
event.preventDefault();
|
||||
const textarea = this.find('textarea.js-add-checklist-item');
|
||||
const title = textarea.value.trim();
|
||||
const cardId = this.currentData().cardId;
|
||||
let cardId = this.currentData().cardId;
|
||||
const card = Cards.findOne(cardId);
|
||||
if (card.isLinked())
|
||||
cardId = card.linkedId;
|
||||
|
||||
if (title) {
|
||||
Checklists.insert({
|
||||
@@ -95,7 +100,12 @@ BlazeComponent.extendComponent({
|
||||
const checklist = this.currentData().checklist;
|
||||
|
||||
if (title) {
|
||||
checklist.addItem(title);
|
||||
ChecklistItems.insert({
|
||||
title,
|
||||
checklistId: checklist._id,
|
||||
cardId: checklist.cardId,
|
||||
sort: checklist.itemCount(),
|
||||
});
|
||||
}
|
||||
// We keep the form opened, empty it.
|
||||
textarea.value = '';
|
||||
@@ -118,7 +128,7 @@ BlazeComponent.extendComponent({
|
||||
const checklist = this.currentData().checklist;
|
||||
const item = this.currentData().item;
|
||||
if (checklist && item && item._id) {
|
||||
checklist.removeItem(item._id);
|
||||
ChecklistItems.remove(item._id);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -135,9 +145,8 @@ BlazeComponent.extendComponent({
|
||||
|
||||
const textarea = this.find('textarea.js-edit-checklist-item');
|
||||
const title = textarea.value.trim();
|
||||
const itemId = this.currentData().item._id;
|
||||
const checklist = this.currentData().checklist;
|
||||
checklist.editItem(itemId, title);
|
||||
const item = this.currentData().item;
|
||||
item.setTitle(title);
|
||||
},
|
||||
|
||||
onCreated() {
|
||||
@@ -200,7 +209,7 @@ Template.checklistDeleteDialog.onDestroyed(() => {
|
||||
$cardDetails.animate( { scrollTop: this.scrollState.position });
|
||||
});
|
||||
|
||||
Template.itemDetail.helpers({
|
||||
Template.checklistItemDetail.helpers({
|
||||
canModifyCard() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
|
||||
},
|
||||
@@ -211,12 +220,12 @@ BlazeComponent.extendComponent({
|
||||
const checklist = this.currentData().checklist;
|
||||
const item = this.currentData().item;
|
||||
if (checklist && item && item._id) {
|
||||
checklist.toggleItem(item._id);
|
||||
item.toggleItem();
|
||||
}
|
||||
},
|
||||
events() {
|
||||
return [{
|
||||
'click .item .check-box': this.toggleItem,
|
||||
'click .js-checklist-item .check-box': this.toggleItem,
|
||||
}];
|
||||
},
|
||||
}).register('itemDetail');
|
||||
}).register('checklistItemDetail');
|
||||
@@ -26,7 +26,7 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
|
||||
|
||||
.title
|
||||
font-size: 18px
|
||||
line-height: 30px
|
||||
line-height: 25px
|
||||
|
||||
.checklist-stat
|
||||
margin: 0 0.5em
|
||||
@@ -78,34 +78,62 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
|
||||
bottom: -600px
|
||||
right: 0
|
||||
|
||||
.checklist-items
|
||||
.checklist
|
||||
background: darken(white, 3%)
|
||||
|
||||
&.placeholder
|
||||
background: darken(white, 20%)
|
||||
border-radius: 2px
|
||||
|
||||
&.ui-sortable-helper
|
||||
box-shadow: -2px 2px 8px rgba(0, 0, 0, .3),
|
||||
0 0 1px rgba(0, 0, 0, .5)
|
||||
transform: rotate(4deg)
|
||||
cursor: grabbing
|
||||
|
||||
|
||||
.checklist-item
|
||||
margin: 0 0 0 0.1em
|
||||
line-height: 18px
|
||||
font-size: 1.1em
|
||||
margin-top: 3px
|
||||
display: flex
|
||||
background: darken(white, 3%)
|
||||
|
||||
&.placeholder
|
||||
background: darken(white, 20%)
|
||||
border-radius: 2px
|
||||
|
||||
&.ui-sortable-helper
|
||||
box-shadow: -2px 2px 8px rgba(0, 0, 0, .3),
|
||||
0 0 1px rgba(0, 0, 0, .5)
|
||||
transform: rotate(4deg)
|
||||
cursor: grabbing
|
||||
|
||||
&:hover
|
||||
background-color: darken(white, 8%)
|
||||
|
||||
.check-box
|
||||
margin: 0.1em 0 0 0;
|
||||
&.is-checked
|
||||
border-bottom: 2px solid #3cb500
|
||||
border-right: 2px solid #3cb500
|
||||
|
||||
.item-title
|
||||
flex: 1
|
||||
padding-left: 10px;
|
||||
&.is-checked
|
||||
color: #8c8c8c
|
||||
font-style: italic
|
||||
& .viewer
|
||||
p
|
||||
margin-bottom: 2px
|
||||
|
||||
.js-delete-checklist-item
|
||||
margin: 0 0 0.5em 1.33em
|
||||
@extends .delete-text
|
||||
padding: 12px 0 0 0
|
||||
|
||||
.item
|
||||
line-height: 25px
|
||||
font-size: 1.1em
|
||||
margin-top: 3px
|
||||
display: flex
|
||||
&:hover
|
||||
background-color: darken(white, 8%)
|
||||
|
||||
.check-box
|
||||
margin-top: 5px
|
||||
&.is-checked
|
||||
border-bottom: 2px solid #3cb500
|
||||
border-right: 2px solid #3cb500
|
||||
|
||||
.item-title
|
||||
flex: 1
|
||||
padding-left: 10px;
|
||||
&.is-checked
|
||||
color: #8c8c8c
|
||||
font-style: italic
|
||||
|
||||
.js-delete-checklist-item
|
||||
@extends .delete-text
|
||||
padding: 12px 0 0 0
|
||||
|
||||
.add-checklist-item
|
||||
padding-top: 0.5em
|
||||
display: inline-block
|
||||
.add-checklist-item
|
||||
margin: 0.2em 0 0.5em 1.33em
|
||||
display: inline-block
|
||||
@@ -3,7 +3,7 @@
|
||||
// XXX Use .board-widget-labels as a flexbox container
|
||||
.card-label
|
||||
border-radius: 4px
|
||||
color: white
|
||||
color: white //Default white text, in select cases, changed to black to improve contrast between label colour and text
|
||||
display: inline-block
|
||||
font-weight: 700
|
||||
font-size: 13px
|
||||
@@ -48,9 +48,11 @@
|
||||
|
||||
.card-label-yellow
|
||||
background-color: #fad900
|
||||
color: #000000 //Black text for better visibility
|
||||
|
||||
.card-label-orange
|
||||
background-color: #ff9f19
|
||||
color: #000000 //Black text for better visibility
|
||||
|
||||
.card-label-red
|
||||
background-color: #eb4646
|
||||
@@ -63,6 +65,7 @@
|
||||
|
||||
.card-label-pink
|
||||
background-color: #ff78cb
|
||||
color: #000000 //Black text for better visibility
|
||||
|
||||
.card-label-sky
|
||||
background-color: #00c2e0
|
||||
@@ -72,6 +75,55 @@
|
||||
|
||||
.card-label-lime
|
||||
background-color: #51e898
|
||||
color: #000000 //Black text for better visibility
|
||||
|
||||
.card-label-silver
|
||||
background-color: #c0c0c0
|
||||
color: #000000 //Black text for better visibility
|
||||
|
||||
.card-label-peachpuff
|
||||
background-color: #ffdab9
|
||||
color: #000000 //Black text for better visibility
|
||||
|
||||
.card-label-crimson
|
||||
background-color: #dc143c
|
||||
|
||||
.card-label-plum
|
||||
background-color: #dda0dd
|
||||
color: #000000 //Black text for better visibility
|
||||
|
||||
.card-label-darkgreen
|
||||
background-color: #006400
|
||||
|
||||
.card-label-slateblue
|
||||
background-color: #6a5acd
|
||||
|
||||
.card-label-magenta
|
||||
background-color: #ff00ff
|
||||
|
||||
.card-label-gold
|
||||
background-color: #ffd700
|
||||
color: #000000 //Black text for better visibility
|
||||
|
||||
.card-label-navy
|
||||
background-color: #000080
|
||||
|
||||
.card-label-gray
|
||||
background-color: #808080
|
||||
|
||||
.card-label-saddlebrown
|
||||
background-color: #8b4513
|
||||
|
||||
.card-label-paleturquoise
|
||||
background-color: #afeeee
|
||||
color: #000000 //Black text for better visibility
|
||||
|
||||
.card-label-mistyrose
|
||||
background-color: #ffe4e1
|
||||
color: #000000 //Black text for better visibility
|
||||
|
||||
.card-label-indigo
|
||||
background-color: #4b0082
|
||||
|
||||
.edit-label,
|
||||
.create-label
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
template(name="minicard")
|
||||
.minicard
|
||||
.minicard(
|
||||
class="{{#if isLinkedCard}}linked-card{{/if}}"
|
||||
class="{{#if isLinkedBoard}}linked-board{{/if}}")
|
||||
if cover
|
||||
.minicard-cover(style="background-image: url('{{cover.url}}');")
|
||||
if labels
|
||||
@@ -7,30 +9,69 @@ template(name="minicard")
|
||||
each labels
|
||||
.minicard-label(class="card-label-{{color}}" title="{{name}}")
|
||||
.minicard-title
|
||||
if $eq 'prefix-with-full-path' currentBoard.presentParentTask
|
||||
.parent-prefix
|
||||
| {{ parentString ' > ' }}
|
||||
if $eq 'prefix-with-parent' currentBoard.presentParentTask
|
||||
.parent-prefix
|
||||
| {{ parentCardName }}
|
||||
if isLinkedBoard
|
||||
a.js-linked-link
|
||||
span.linked-icon.fa.fa-folder
|
||||
else if isLinkedCard
|
||||
a.js-linked-link
|
||||
span.linked-icon.fa.fa-id-card
|
||||
if getArchived
|
||||
span.linked-icon.linked-archived.fa.fa-archive
|
||||
+viewer
|
||||
= title
|
||||
= getTitle
|
||||
if $eq 'subtext-with-full-path' currentBoard.presentParentTask
|
||||
.parent-subtext
|
||||
| {{ parentString ' > ' }}
|
||||
if $eq 'subtext-with-parent' currentBoard.presentParentTask
|
||||
.parent-subtext
|
||||
| {{ parentCardName }}
|
||||
|
||||
.dates
|
||||
if startAt
|
||||
if getReceived
|
||||
unless getStart
|
||||
unless getDue
|
||||
unless getEnd
|
||||
.date
|
||||
+minicardReceivedDate
|
||||
if getStart
|
||||
.date
|
||||
+minicardStartDate
|
||||
if dueAt
|
||||
if getDue
|
||||
.date
|
||||
+minicardDueDate
|
||||
if spentTime
|
||||
if getSpentTime
|
||||
.date
|
||||
+cardSpentTime
|
||||
|
||||
if members
|
||||
.minicard-custom-fields
|
||||
each customFieldsWD
|
||||
if definition.showOnCard
|
||||
.minicard-custom-field
|
||||
.minicard-custom-field-item
|
||||
= definition.name
|
||||
.minicard-custom-field-item
|
||||
+viewer
|
||||
= trueValue
|
||||
|
||||
if getMembers
|
||||
.minicard-members.js-minicard-members
|
||||
each members
|
||||
each getMembers
|
||||
+userAvatar(userId=this)
|
||||
|
||||
.badges
|
||||
if comments.count
|
||||
.badge(title="{{_ 'card-comments-title' comments.count }}")
|
||||
span.badge-icon.fa.fa-comment-o.badge-comment
|
||||
span.badge-text= comments.count
|
||||
if description
|
||||
.badge.badge-state-image-only(title=description)
|
||||
unless currentUser.isNoComments
|
||||
if comments.count
|
||||
.badge(title="{{_ 'card-comments-title' comments.count }}")
|
||||
span.badge-icon.fa.fa-comment-o.badge-comment
|
||||
span.badge-text= comments.count
|
||||
if getDescription
|
||||
.badge.badge-state-image-only(title=getDescription)
|
||||
span.badge-icon.fa.fa-align-left
|
||||
if attachments.count
|
||||
.badge
|
||||
|
||||
@@ -6,4 +6,15 @@ BlazeComponent.extendComponent({
|
||||
template() {
|
||||
return 'minicard';
|
||||
},
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'click .js-linked-link' () {
|
||||
if (this.data().isLinkedCard())
|
||||
Utils.goCardId(this.data().linkedId);
|
||||
else if (this.data().isLinkedBoard())
|
||||
Utils.goBoardId(this.data().linkedId);
|
||||
},
|
||||
}];
|
||||
},
|
||||
}).register('minicard');
|
||||
@@ -9,7 +9,7 @@
|
||||
|
||||
&.placeholder
|
||||
background: darken(white, 20%)
|
||||
border-radius: 2px
|
||||
border-radius: 9px
|
||||
|
||||
&.ui-sortable-helper
|
||||
cursor: grabbing
|
||||
@@ -44,6 +44,16 @@
|
||||
transition: transform 0.2s,
|
||||
border-radius 0.2s
|
||||
|
||||
&.linked-board
|
||||
&.linked-card
|
||||
.linked-icon
|
||||
display: inline-block
|
||||
margin-right: 11px
|
||||
vertical-align: baseline
|
||||
font-size: 0.9em
|
||||
.linked-archived
|
||||
color: #937760
|
||||
|
||||
.is-selected &
|
||||
transform: translateX(11px)
|
||||
border-bottom-right-radius: 0
|
||||
@@ -77,9 +87,18 @@
|
||||
height: @width
|
||||
border-radius: 2px
|
||||
margin-left: 3px
|
||||
.minicard-custom-fields
|
||||
display:block;
|
||||
.minicard-custom-field
|
||||
display:flex;
|
||||
.minicard-custom-field-item
|
||||
max-width:50%;
|
||||
flex-grow:1;
|
||||
.minicard-title
|
||||
p:last-child
|
||||
margin-bottom: 0
|
||||
.viewer
|
||||
display: inline-block
|
||||
.dates
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
@@ -155,6 +174,13 @@
|
||||
margin-bottom: 20px
|
||||
overflow-y: auto
|
||||
|
||||
.parent-prefix
|
||||
color: darken(white, 30%)
|
||||
font-size: 0.9em
|
||||
.parent-subtext
|
||||
color: darken(white, 30%)
|
||||
font-size: 0.9em
|
||||
|
||||
@media screen and (max-width: 800px)
|
||||
.minicard
|
||||
.is-selected &
|
||||
|
||||
@@ -0,0 +1,97 @@
|
||||
template(name="subtasks")
|
||||
h3 {{_ 'subtasks'}}
|
||||
if toggleDeleteDialog.get
|
||||
.board-overlay#card-details-overlay
|
||||
+subtaskDeleteDialog(subtask = subtaskToDelete)
|
||||
|
||||
|
||||
.card-subtasks-items
|
||||
each subtask in currentCard.subtasks
|
||||
+subtaskDetail(subtask = subtask)
|
||||
|
||||
if canModifyCard
|
||||
+inlinedForm(autoclose=false classNames="js-add-subtask" cardId = cardId)
|
||||
+addSubtaskItemForm
|
||||
else
|
||||
a.js-open-inlined-form
|
||||
i.fa.fa-plus
|
||||
| {{_ 'add-subtask'}}...
|
||||
|
||||
template(name="subtaskDetail")
|
||||
.js-subtasks.subtask
|
||||
+inlinedForm(classNames="js-edit-subtask-title" subtask = subtask)
|
||||
+editSubtaskItemForm(subtask = subtask)
|
||||
else
|
||||
.subtask-title
|
||||
span
|
||||
a.js-view-subtask(title="{{ subtask.title }}") {{_ "view-it"}}
|
||||
if canModifyCard
|
||||
a.js-delete-subtask.toggle-delete-subtask-dialog {{_ "delete"}}...
|
||||
|
||||
if canModifyCard
|
||||
h2.title.js-open-inlined-form.is-editable
|
||||
+viewer
|
||||
= subtask.title
|
||||
else
|
||||
h2.title
|
||||
+viewer
|
||||
= subtask.title
|
||||
|
||||
template(name="subtaskDeleteDialog")
|
||||
.js-confirm-subtask-delete
|
||||
p
|
||||
i(class="fa fa-exclamation-triangle" aria-hidden="true")
|
||||
p
|
||||
| {{_ 'confirm-subtask-delete-dialog'}}
|
||||
span {{subtask.title}}
|
||||
| ?
|
||||
.js-subtask-delete-buttons
|
||||
button.confirm-subtask-delete(type="button") {{_ 'delete'}}
|
||||
button.toggle-delete-subtask-dialog(type="button") {{_ 'cancel'}}
|
||||
|
||||
template(name="addSubtaskItemForm")
|
||||
textarea.js-add-subtask-item(rows='1' autofocus)
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm.js-submit-add-subtask-item-form(type="submit") {{_ 'save'}}
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
|
||||
template(name="editSubtaskItemForm")
|
||||
textarea.js-edit-subtask-item(rows='1' autofocus)
|
||||
if $eq type 'item'
|
||||
= item.title
|
||||
else
|
||||
= subtask.title
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm.js-submit-edit-subtask-item-form(type="submit") {{_ 'save'}}
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
span(title=createdAt) {{ moment createdAt }}
|
||||
if canModifyCard
|
||||
a.js-delete-subtask-item {{_ "delete"}}...
|
||||
|
||||
template(name="subtasksItems")
|
||||
.subtasks-items.js-subtasks-items
|
||||
each item in subtasks.items
|
||||
+inlinedForm(classNames="js-edit-subtask-item" item = item subtasks = subtasks)
|
||||
+editSubtaskItemForm(type = 'item' item = item subtasks = subtasks)
|
||||
else
|
||||
+subtaskItemDetail(item = item subtasks = subtasks)
|
||||
if canModifyCard
|
||||
+inlinedForm(autoclose=false classNames="js-add-subtask-item" subtasks = subtasks)
|
||||
+addSubtaskItemForm
|
||||
else
|
||||
a.add-subtask-item.js-open-inlined-form
|
||||
i.fa.fa-plus
|
||||
| {{_ 'add-subtask-item'}}...
|
||||
|
||||
template(name='subtaskItemDetail')
|
||||
.js-subtasks-item.subtasks-item
|
||||
if canModifyCard
|
||||
.check-box.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}")
|
||||
.item-title.js-open-inlined-form.is-editable(class="{{#if item.isFinished }}is-checked{{/if}}")
|
||||
+viewer
|
||||
= item.title
|
||||
else
|
||||
.materialCheckBox(class="{{#if item.isFinished }}is-checked{{/if}}")
|
||||
.item-title(class="{{#if item.isFinished }}is-checked{{/if}}")
|
||||
+viewer
|
||||
= item.title
|
||||
@@ -0,0 +1,146 @@
|
||||
BlazeComponent.extendComponent({
|
||||
canModifyCard() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
|
||||
},
|
||||
}).register('subtaskDetail');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
|
||||
addSubtask(event) {
|
||||
event.preventDefault();
|
||||
const textarea = this.find('textarea.js-add-subtask-item');
|
||||
const title = textarea.value.trim();
|
||||
const cardId = this.currentData().cardId;
|
||||
const card = Cards.findOne(cardId);
|
||||
const sortIndex = -1;
|
||||
const crtBoard = Boards.findOne(card.boardId);
|
||||
const targetBoard = crtBoard.getDefaultSubtasksBoard();
|
||||
const listId = targetBoard.getDefaultSubtasksListId();
|
||||
const swimlaneId = targetBoard.getDefaultSwimline()._id;
|
||||
|
||||
if (title) {
|
||||
const _id = Cards.insert({
|
||||
title,
|
||||
parentId: cardId,
|
||||
members: [],
|
||||
labelIds: [],
|
||||
customFields: [],
|
||||
listId,
|
||||
boardId: targetBoard._id,
|
||||
sort: sortIndex,
|
||||
swimlaneId,
|
||||
type: 'cardType-card',
|
||||
});
|
||||
|
||||
// In case the filter is active we need to add the newly inserted card in
|
||||
// the list of exceptions -- cards that are not filtered. Otherwise the
|
||||
// card will disappear instantly.
|
||||
// See https://github.com/wekan/wekan/issues/80
|
||||
Filter.addException(_id);
|
||||
|
||||
|
||||
setTimeout(() => {
|
||||
this.$('.add-subtask-item').last().click();
|
||||
}, 100);
|
||||
}
|
||||
textarea.value = '';
|
||||
textarea.focus();
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
|
||||
},
|
||||
|
||||
deleteSubtask() {
|
||||
const subtask = this.currentData().subtask;
|
||||
if (subtask && subtask._id) {
|
||||
subtask.archive();
|
||||
this.toggleDeleteDialog.set(false);
|
||||
}
|
||||
},
|
||||
|
||||
editSubtask(event) {
|
||||
event.preventDefault();
|
||||
const textarea = this.find('textarea.js-edit-subtask-item');
|
||||
const title = textarea.value.trim();
|
||||
const subtask = this.currentData().subtask;
|
||||
subtask.setTitle(title);
|
||||
},
|
||||
|
||||
onCreated() {
|
||||
this.toggleDeleteDialog = new ReactiveVar(false);
|
||||
this.subtaskToDelete = null; //Store data context to pass to subtaskDeleteDialog template
|
||||
},
|
||||
|
||||
pressKey(event) {
|
||||
//If user press enter key inside a form, submit it
|
||||
//Unless the user is also holding down the 'shift' key
|
||||
if (event.keyCode === 13 && !event.shiftKey) {
|
||||
event.preventDefault();
|
||||
const $form = $(event.currentTarget).closest('form');
|
||||
$form.find('button[type=submit]').click();
|
||||
}
|
||||
},
|
||||
|
||||
events() {
|
||||
const events = {
|
||||
'click .toggle-delete-subtask-dialog'(event) {
|
||||
if($(event.target).hasClass('js-delete-subtask')){
|
||||
this.subtaskToDelete = this.currentData().subtask; //Store data context
|
||||
}
|
||||
this.toggleDeleteDialog.set(!this.toggleDeleteDialog.get());
|
||||
},
|
||||
'click .js-view-subtask'(event) {
|
||||
if($(event.target).hasClass('js-view-subtask')){
|
||||
const subtask = this.currentData().subtask;
|
||||
const board = subtask.board();
|
||||
FlowRouter.go('card', {
|
||||
boardId: board._id,
|
||||
slug: board.slug,
|
||||
cardId: subtask._id,
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
return [{
|
||||
...events,
|
||||
'submit .js-add-subtask': this.addSubtask,
|
||||
'submit .js-edit-subtask-title': this.editSubtask,
|
||||
'click .confirm-subtask-delete': this.deleteSubtask,
|
||||
keydown: this.pressKey,
|
||||
}];
|
||||
},
|
||||
}).register('subtasks');
|
||||
|
||||
Template.subtaskDeleteDialog.onCreated(() => {
|
||||
const $cardDetails = this.$('.card-details');
|
||||
this.scrollState = { position: $cardDetails.scrollTop(), //save current scroll position
|
||||
top: false, //required for smooth scroll animation
|
||||
};
|
||||
//Callback's purpose is to only prevent scrolling after animation is complete
|
||||
$cardDetails.animate({ scrollTop: 0 }, 500, () => { this.scrollState.top = true; });
|
||||
|
||||
//Prevent scrolling while dialog is open
|
||||
$cardDetails.on('scroll', () => {
|
||||
if(this.scrollState.top) { //If it's already in position, keep it there. Otherwise let animation scroll
|
||||
$cardDetails.scrollTop(0);
|
||||
}
|
||||
});
|
||||
});
|
||||
|
||||
Template.subtaskDeleteDialog.onDestroyed(() => {
|
||||
const $cardDetails = this.$('.card-details');
|
||||
$cardDetails.off('scroll'); //Reactivate scrolling
|
||||
$cardDetails.animate( { scrollTop: this.scrollState.position });
|
||||
});
|
||||
|
||||
Template.subtaskItemDetail.helpers({
|
||||
canModifyCard() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
|
||||
},
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
// ...
|
||||
}).register('subtaskItemDetail');
|
||||
@@ -0,0 +1,142 @@
|
||||
.js-add-subtask
|
||||
color: #8c8c8c
|
||||
|
||||
textarea.js-add-subtask-item, textarea.js-edit-subtask-item
|
||||
overflow: hidden
|
||||
word-wrap: break-word
|
||||
resize: none
|
||||
height: 34px
|
||||
|
||||
.delete-text
|
||||
color: #8c8c8c
|
||||
text-decoration: underline
|
||||
word-wrap: break-word
|
||||
float: right
|
||||
padding-top: 6px
|
||||
&:hover
|
||||
color: inherit
|
||||
|
||||
.subtask-title
|
||||
.checkbox
|
||||
float: left
|
||||
width: 30px
|
||||
height 30px
|
||||
font-size: 18px
|
||||
line-height: 30px
|
||||
|
||||
.title
|
||||
font-size: 18px
|
||||
line-height: 25px
|
||||
|
||||
.subtasks-stat
|
||||
margin: 0 0.5em
|
||||
float: right
|
||||
padding-top: 6px
|
||||
&.is-finished
|
||||
color: #3cb500
|
||||
|
||||
.js-delete-subtask
|
||||
@extends .delete-text
|
||||
margin: 0 0.5em
|
||||
|
||||
.js-view-subtask
|
||||
@extends .delete-text
|
||||
|
||||
.js-confirm-subtask-delete
|
||||
background-color: darken(white, 3%)
|
||||
position: absolute
|
||||
float: left;
|
||||
width: 60%
|
||||
margin-top: 0
|
||||
margin-left: 13%
|
||||
padding-bottom: 2%
|
||||
padding-left: 3%
|
||||
padding-right: 3%
|
||||
z-index: 17
|
||||
border-radius: 3px
|
||||
|
||||
p
|
||||
position: relative
|
||||
margin-top: 3%
|
||||
width: 100%
|
||||
text-align: center
|
||||
span
|
||||
font-weight: bold
|
||||
|
||||
i
|
||||
font-size: 2em
|
||||
|
||||
.js-subtask-delete-buttons
|
||||
position: relative
|
||||
padding: left 2% right 2%
|
||||
.confirm-subtask-delete
|
||||
margin-left: 12%
|
||||
float: left
|
||||
.toggle-delete-subtask-dialog
|
||||
margin-right: 12%
|
||||
float: right
|
||||
|
||||
#card-details-overlay
|
||||
top: 0
|
||||
bottom: -600px
|
||||
right: 0
|
||||
|
||||
.subtasks
|
||||
background: darken(white, 3%)
|
||||
|
||||
&.placeholder
|
||||
background: darken(white, 20%)
|
||||
border-radius: 2px
|
||||
|
||||
&.ui-sortable-helper
|
||||
box-shadow: -2px 2px 8px rgba(0, 0, 0, .3),
|
||||
0 0 1px rgba(0, 0, 0, .5)
|
||||
transform: rotate(4deg)
|
||||
cursor: grabbing
|
||||
|
||||
|
||||
.subtasks-item
|
||||
margin: 0 0 0 0.1em
|
||||
line-height: 18px
|
||||
font-size: 1.1em
|
||||
margin-top: 3px
|
||||
display: flex
|
||||
background: darken(white, 3%)
|
||||
|
||||
&.placeholder
|
||||
background: darken(white, 20%)
|
||||
border-radius: 2px
|
||||
|
||||
&.ui-sortable-helper
|
||||
box-shadow: -2px 2px 8px rgba(0, 0, 0, .3),
|
||||
0 0 1px rgba(0, 0, 0, .5)
|
||||
transform: rotate(4deg)
|
||||
cursor: grabbing
|
||||
|
||||
&:hover
|
||||
background-color: darken(white, 8%)
|
||||
|
||||
.check-box
|
||||
margin: 0.1em 0 0 0;
|
||||
&.is-checked
|
||||
border-bottom: 2px solid #3cb500
|
||||
border-right: 2px solid #3cb500
|
||||
|
||||
.item-title
|
||||
flex: 1
|
||||
padding-left: 10px;
|
||||
&.is-checked
|
||||
color: #8c8c8c
|
||||
font-style: italic
|
||||
& .viewer
|
||||
p
|
||||
margin-bottom: 2px
|
||||
|
||||
.js-delete-subtask-item
|
||||
margin: 0 0 0.5em 1.33em
|
||||
@extends .delete-text
|
||||
padding: 12px 0 0 0
|
||||
|
||||
.add-subtask-item
|
||||
margin: 0.2em 0 0.5em 1.33em
|
||||
display: inline-block
|
||||
@@ -0,0 +1,15 @@
|
||||
template(name="datepicker")
|
||||
.datepicker-container
|
||||
form.edit-date
|
||||
.fields
|
||||
.left
|
||||
label(for="date") {{_ 'date'}}
|
||||
input.js-date-field#date(type="text" name="date" value=showDate placeholder=dateFormat autofocus)
|
||||
.right
|
||||
label(for="time") {{_ 'time'}}
|
||||
input.js-time-field#time(type="text" name="time" value=showTime placeholder=timeFormat)
|
||||
.js-datepicker
|
||||
if error.get
|
||||
.warning {{_ error.get}}
|
||||
button.primary.wide.left.js-submit-date(type="submit") {{_ 'save'}}
|
||||
button.js-delete-date.negate.wide.right.js-delete-date {{_ 'delete'}}
|
||||
@@ -0,0 +1,17 @@
|
||||
.datepicker-container
|
||||
.fields
|
||||
.left
|
||||
width: 56%
|
||||
.right
|
||||
width: 38%
|
||||
.datepicker
|
||||
width: 100%
|
||||
table
|
||||
width: 100%
|
||||
border: none
|
||||
border-spacing: 0
|
||||
border-collapse: collapse
|
||||
thead
|
||||
background: none
|
||||
td, th
|
||||
box-sizing: border-box
|
||||
@@ -85,6 +85,9 @@ select
|
||||
width: 256px
|
||||
margin-bottom: 8px
|
||||
|
||||
&.inline
|
||||
width: 100%
|
||||
|
||||
option[disabled]
|
||||
color: #8c8c8c
|
||||
|
||||
@@ -222,9 +225,12 @@ textarea
|
||||
|
||||
.edit-controls,
|
||||
.add-controls
|
||||
display: flex
|
||||
align-items: baseline
|
||||
margin-top: 0
|
||||
|
||||
button[type=submit]
|
||||
input[type=button]
|
||||
float: left
|
||||
height: 32px
|
||||
margin-top: -2px
|
||||
|
||||
@@ -16,6 +16,7 @@ template(name="importTextarea")
|
||||
textarea.js-import-json(placeholder="{{_ 'import-json-placeholder'}}" autofocus)
|
||||
| {{jsonText}}
|
||||
if isSandstorm
|
||||
h1.warning DANGER !!! THIS DESTROYS YOUR IMPORTED DATA, CAUSES BOARD NOT FOUND ERROR WHEN YOU OPEN THIS GRAIN AGAIN https://github.com/wekan/wekan/issues/1430
|
||||
p.warning {{_ 'import-sandstorm-warning'}}
|
||||
input.primary.wide(type="submit" value="{{_ 'import'}}")
|
||||
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
const { calculateIndex } = Utils;
|
||||
const { calculateIndex, enableClickOnTouch } = Utils;
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
// Proxy
|
||||
@@ -19,12 +19,17 @@ BlazeComponent.extendComponent({
|
||||
// comment below provides further details.
|
||||
onRendered() {
|
||||
const boardComponent = this.parentComponent().parentComponent();
|
||||
|
||||
function userIsMember() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
|
||||
}
|
||||
|
||||
const itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)';
|
||||
const $cards = this.$('.js-minicards');
|
||||
$cards.sortable({
|
||||
connectWith: '.js-minicards:not(.js-list-full)',
|
||||
tolerance: 'pointer',
|
||||
appendTo: 'body',
|
||||
appendTo: '.board-canvas',
|
||||
helper(evt, item) {
|
||||
const helper = item.clone();
|
||||
if (MultiSelection.isActive()) {
|
||||
@@ -40,7 +45,6 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
distance: 7,
|
||||
items: itemsSelector,
|
||||
scroll: false,
|
||||
placeholder: 'minicard-wrapper placeholder',
|
||||
start(evt, ui) {
|
||||
ui.placeholder.height(ui.helper.height());
|
||||
@@ -79,9 +83,8 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
});
|
||||
|
||||
function userIsMember() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
|
||||
}
|
||||
// ugly touch event hotfix
|
||||
enableClickOnTouch(itemsSelector);
|
||||
|
||||
// Disable drag-dropping if the current user is not a board member or is comment only
|
||||
this.autorun(() => {
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
// transparent, because that won't work during a list drag.
|
||||
background: darken(white, 13%)
|
||||
border-left: 1px solid darken(white, 20%)
|
||||
border-bottom: 1px solid #CCC
|
||||
padding: 0
|
||||
float: left
|
||||
|
||||
@@ -86,7 +87,7 @@
|
||||
color: #ce1414
|
||||
|
||||
.list-body
|
||||
flex: 1
|
||||
flex: 1 1 auto
|
||||
flex-direction: column
|
||||
display: flex
|
||||
overflow-y: auto
|
||||
@@ -186,3 +187,14 @@
|
||||
padding: 7px
|
||||
top: -@padding
|
||||
right: 17px
|
||||
|
||||
.link-board-wrapper
|
||||
display: flex
|
||||
align-items: baseline
|
||||
|
||||
.js-link-board
|
||||
margin-left: 15px
|
||||
|
||||
.search-card-results
|
||||
max-height: 250px
|
||||
overflow: hidden
|
||||
@@ -34,8 +34,60 @@ template(name="addCardForm")
|
||||
|
||||
.add-controls.clearfix
|
||||
button.primary.confirm(type="submit") {{_ 'add'}}
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
span.quiet
|
||||
| {{_ 'or'}}
|
||||
a.js-link {{_ 'link'}}
|
||||
span.quiet
|
||||
|
|
||||
| /
|
||||
a.js-search {{_ 'search'}}
|
||||
|
||||
template(name="autocompleteLabelLine")
|
||||
.minicard-label(class="card-label-{{colorName}}" title=labelName)
|
||||
span(class="{{#if hasNoName}}quiet{{/if}}")= labelName
|
||||
|
||||
template(name="linkCardPopup")
|
||||
label {{_ 'boards'}}:
|
||||
.link-board-wrapper
|
||||
select.js-select-boards
|
||||
each boards
|
||||
if $eq _id currentBoard._id
|
||||
option(value="{{_id}}" selected) {{_ 'current'}}
|
||||
else
|
||||
option(value="{{_id}}") {{title}}
|
||||
input.primary.confirm.js-link-board(type="button" value="{{_ 'link'}}")
|
||||
|
||||
label {{_ 'swimlanes'}}:
|
||||
select.js-select-swimlanes
|
||||
each swimlanes
|
||||
option(value="{{_id}}") {{title}}
|
||||
|
||||
label {{_ 'lists'}}:
|
||||
select.js-select-lists
|
||||
each lists
|
||||
option(value="{{_id}}") {{title}}
|
||||
|
||||
label {{_ 'cards'}}:
|
||||
select.js-select-cards
|
||||
each cards
|
||||
option(value="{{getId}}") {{getTitle}}
|
||||
|
||||
.edit-controls.clearfix
|
||||
input.primary.confirm.js-done(type="button" value="{{_ 'link'}}")
|
||||
|
||||
template(name="searchCardPopup")
|
||||
label {{_ 'boards'}}:
|
||||
.link-board-wrapper
|
||||
select.js-select-boards
|
||||
each boards
|
||||
if $eq _id currentBoard._id
|
||||
option(value="{{_id}}" selected) {{_ 'current'}}
|
||||
else
|
||||
option(value="{{_id}}") {{title}}
|
||||
form.js-search-term-form
|
||||
input(type="text" name="searchTerm" placeholder="{{_ 'search-example'}}" autofocus)
|
||||
.list-body.js-perfect-scrollbar.search-card-results
|
||||
.minicards.clearfix.js-minicards
|
||||
each results
|
||||
a.minicard-wrapper.js-minicard
|
||||
+minicard(this)
|
||||
@@ -1,3 +1,5 @@
|
||||
const subManager = new SubsManager();
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
mixins() {
|
||||
return [Mixins.PerfectScrollbar];
|
||||
@@ -35,24 +37,27 @@ BlazeComponent.extendComponent({
|
||||
|
||||
const members = formComponent.members.get();
|
||||
const labelIds = formComponent.labels.get();
|
||||
const customFields = formComponent.customFields.get();
|
||||
|
||||
const boardId = this.data().board()._id;
|
||||
const board = Boards.findOne(boardId);
|
||||
const boardId = this.data().board();
|
||||
let swimlaneId = '';
|
||||
if (board.view === 'board-view-swimlanes')
|
||||
const boardView = Meteor.user().profile.boardView;
|
||||
if (boardView === 'board-view-swimlanes')
|
||||
swimlaneId = this.parentComponent().parentComponent().data()._id;
|
||||
else
|
||||
swimlaneId = Swimlanes.findOne({boardId})._id;
|
||||
else if ((boardView === 'board-view-lists') || (boardView === 'board-view-cal'))
|
||||
swimlaneId = boardId.getDefaultSwimline()._id;
|
||||
|
||||
if (title) {
|
||||
const _id = Cards.insert({
|
||||
title,
|
||||
members,
|
||||
labelIds,
|
||||
customFields,
|
||||
listId: this.data()._id,
|
||||
boardId: this.data().board()._id,
|
||||
boardId: boardId._id,
|
||||
sort: sortIndex,
|
||||
swimlaneId,
|
||||
type: 'cardType-card',
|
||||
});
|
||||
// In case the filter is active we need to add the newly inserted card in
|
||||
// the list of exceptions -- cards that are not filtered. Otherwise the
|
||||
@@ -106,8 +111,8 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
idOrNull(swimlaneId) {
|
||||
const board = Boards.findOne(Session.get('currentBoard'));
|
||||
if (board.view === 'board-view-swimlanes')
|
||||
const currentUser = Meteor.user();
|
||||
if (currentUser.profile.boardView === 'board-view-swimlanes')
|
||||
return swimlaneId;
|
||||
return undefined;
|
||||
},
|
||||
@@ -146,11 +151,13 @@ BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.labels = new ReactiveVar([]);
|
||||
this.members = new ReactiveVar([]);
|
||||
this.customFields = new ReactiveVar([]);
|
||||
},
|
||||
|
||||
reset() {
|
||||
this.labels.set([]);
|
||||
this.members.set([]);
|
||||
this.customFields.set([]);
|
||||
},
|
||||
|
||||
getLabels() {
|
||||
@@ -193,6 +200,8 @@ BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [{
|
||||
keydown: this.pressKey,
|
||||
'click .js-link': Popup.open('linkCard'),
|
||||
'click .js-search': Popup.open('searchCard'),
|
||||
}];
|
||||
},
|
||||
|
||||
@@ -264,3 +273,200 @@ BlazeComponent.extendComponent({
|
||||
});
|
||||
},
|
||||
}).register('addCardForm');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
// Prefetch first non-current board id
|
||||
const boardId = Boards.findOne({
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
_id: {$ne: Session.get('currentBoard')},
|
||||
}, {
|
||||
sort: ['title'],
|
||||
})._id;
|
||||
// Subscribe to this board
|
||||
subManager.subscribe('board', boardId);
|
||||
this.selectedBoardId = new ReactiveVar(boardId);
|
||||
this.selectedSwimlaneId = new ReactiveVar('');
|
||||
this.selectedListId = new ReactiveVar('');
|
||||
|
||||
this.boardId = Session.get('currentBoard');
|
||||
// In order to get current board info
|
||||
subManager.subscribe('board', this.boardId);
|
||||
this.board = Boards.findOne(this.boardId);
|
||||
// List where to insert card
|
||||
const list = $(Popup._getTopStack().openerElement).closest('.js-list');
|
||||
this.listId = Blaze.getData(list[0])._id;
|
||||
// Swimlane where to insert card
|
||||
const swimlane = $(Popup._getTopStack().openerElement).closest('.js-swimlane');
|
||||
this.swimlaneId = '';
|
||||
const boardView = Meteor.user().profile.boardView;
|
||||
if (boardView === 'board-view-swimlanes')
|
||||
this.swimlaneId = Blaze.getData(swimlane[0])._id;
|
||||
else if (boardView === 'board-view-lists')
|
||||
this.swimlaneId = Swimlanes.findOne({boardId: this.boardId})._id;
|
||||
},
|
||||
|
||||
boards() {
|
||||
const boards = Boards.find({
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
_id: {$ne: Session.get('currentBoard')},
|
||||
}, {
|
||||
sort: ['title'],
|
||||
});
|
||||
return boards;
|
||||
},
|
||||
|
||||
swimlanes() {
|
||||
const swimlanes = Swimlanes.find({boardId: this.selectedBoardId.get()});
|
||||
if (swimlanes.count())
|
||||
this.selectedSwimlaneId.set(swimlanes.fetch()[0]._id);
|
||||
return swimlanes;
|
||||
},
|
||||
|
||||
lists() {
|
||||
const lists = Lists.find({boardId: this.selectedBoardId.get()});
|
||||
if (lists.count())
|
||||
this.selectedListId.set(lists.fetch()[0]._id);
|
||||
return lists;
|
||||
},
|
||||
|
||||
cards() {
|
||||
const ownCardsIds = this.board.cards().map((card) => { return card.linkedId || card._id; });
|
||||
return Cards.find({
|
||||
boardId: this.selectedBoardId.get(),
|
||||
swimlaneId: this.selectedSwimlaneId.get(),
|
||||
listId: this.selectedListId.get(),
|
||||
archived: false,
|
||||
linkedId: {$nin: ownCardsIds},
|
||||
_id: {$nin: ownCardsIds},
|
||||
});
|
||||
},
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'change .js-select-boards'(evt) {
|
||||
subManager.subscribe('board', $(evt.currentTarget).val());
|
||||
this.selectedBoardId.set($(evt.currentTarget).val());
|
||||
},
|
||||
'change .js-select-swimlanes'(evt) {
|
||||
this.selectedSwimlaneId.set($(evt.currentTarget).val());
|
||||
},
|
||||
'change .js-select-lists'(evt) {
|
||||
this.selectedListId.set($(evt.currentTarget).val());
|
||||
},
|
||||
'click .js-done' (evt) {
|
||||
// LINK CARD
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
const _id = Cards.insert({
|
||||
title: $('.js-select-cards option:selected').text(), //dummy
|
||||
listId: this.listId,
|
||||
swimlaneId: this.swimlaneId,
|
||||
boardId: this.boardId,
|
||||
sort: Lists.findOne(this.listId).cards().count(),
|
||||
type: 'cardType-linkedCard',
|
||||
linkedId: $('.js-select-cards option:selected').val(),
|
||||
});
|
||||
Filter.addException(_id);
|
||||
Popup.close();
|
||||
},
|
||||
'click .js-link-board' (evt) {
|
||||
//LINK BOARD
|
||||
evt.stopPropagation();
|
||||
evt.preventDefault();
|
||||
const impBoardId = $('.js-select-boards option:selected').val();
|
||||
const _id = Cards.insert({
|
||||
title: $('.js-select-boards option:selected').text(), //dummy
|
||||
listId: this.listId,
|
||||
swimlaneId: this.swimlaneId,
|
||||
boardId: this.boardId,
|
||||
sort: Lists.findOne(this.listId).cards().count(),
|
||||
type: 'cardType-linkedBoard',
|
||||
linkedId: impBoardId,
|
||||
});
|
||||
Filter.addException(_id);
|
||||
Popup.close();
|
||||
},
|
||||
}];
|
||||
},
|
||||
}).register('linkCardPopup');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
mixins() {
|
||||
return [Mixins.PerfectScrollbar];
|
||||
},
|
||||
|
||||
onCreated() {
|
||||
// Prefetch first non-current board id
|
||||
const boardId = Boards.findOne({
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
_id: {$ne: Session.get('currentBoard')},
|
||||
})._id;
|
||||
// Subscribe to this board
|
||||
subManager.subscribe('board', boardId);
|
||||
this.selectedBoardId = new ReactiveVar(boardId);
|
||||
|
||||
this.boardId = Session.get('currentBoard');
|
||||
// In order to get current board info
|
||||
subManager.subscribe('board', this.boardId);
|
||||
const board = Boards.findOne(this.boardId);
|
||||
// List where to insert card
|
||||
const list = $(Popup._getTopStack().openerElement).closest('.js-list');
|
||||
this.listId = Blaze.getData(list[0])._id;
|
||||
// Swimlane where to insert card
|
||||
const swimlane = $(Popup._getTopStack().openerElement).closest('.js-swimlane');
|
||||
this.swimlaneId = '';
|
||||
if (board.view === 'board-view-swimlanes')
|
||||
this.swimlaneId = Blaze.getData(swimlane[0])._id;
|
||||
else
|
||||
this.swimlaneId = Swimlanes.findOne({boardId: this.boardId})._id;
|
||||
this.term = new ReactiveVar('');
|
||||
},
|
||||
|
||||
boards() {
|
||||
const boards = Boards.find({
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
_id: {$ne: Session.get('currentBoard')},
|
||||
}, {
|
||||
sort: ['title'],
|
||||
});
|
||||
return boards;
|
||||
},
|
||||
|
||||
results() {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
return board.searchCards(this.term.get(), false);
|
||||
},
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'change .js-select-boards'(evt) {
|
||||
subManager.subscribe('board', $(evt.currentTarget).val());
|
||||
this.selectedBoardId.set($(evt.currentTarget).val());
|
||||
},
|
||||
'submit .js-search-term-form'(evt) {
|
||||
evt.preventDefault();
|
||||
this.term.set(evt.target.searchTerm.value);
|
||||
},
|
||||
'click .js-minicard'(evt) {
|
||||
// LINK CARD
|
||||
const card = Blaze.getData(evt.currentTarget);
|
||||
const _id = Cards.insert({
|
||||
title: card.title, //dummy
|
||||
listId: this.listId,
|
||||
swimlaneId: this.swimlaneId,
|
||||
boardId: this.boardId,
|
||||
sort: Lists.findOne(this.listId).cards().count(),
|
||||
type: 'cardType-linkedCard',
|
||||
linkedId: card.linkedId || card._id,
|
||||
});
|
||||
Filter.addException(_id);
|
||||
Popup.close();
|
||||
},
|
||||
}];
|
||||
},
|
||||
}).register('searchCardPopup');
|
||||
@@ -16,8 +16,8 @@ template(name="listHeader")
|
||||
|
||||
if showCardsCountForList cards.count
|
||||
= cards.count
|
||||
span.lowercase
|
||||
| {{_ 'cards'}}
|
||||
span
|
||||
| {{_ 'cards-count'}}
|
||||
if isMiniScreen
|
||||
if currentList
|
||||
if isWatching
|
||||
|
||||
@@ -28,14 +28,15 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
showCardsCountForList(count) {
|
||||
return count > this.limitToShowCardsCount();
|
||||
const limit = this.limitToShowCardsCount();
|
||||
return limit > 0 && count > limit;
|
||||
},
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'click .js-open-list-menu': Popup.open('listAction'),
|
||||
'click .js-add-card' () {
|
||||
const listDom = document.getElementById(`js-list-${this.currentData()._id}`);
|
||||
'click .js-add-card' (evt) {
|
||||
const listDom = $(evt.target).parents(`#js-list-${this.currentData()._id}`)[0];
|
||||
const listComponent = BlazeComponent.getComponentForElement(listDom);
|
||||
listComponent.openForm({
|
||||
position: 'top',
|
||||
|
||||
@@ -1,13 +0,0 @@
|
||||
BlazeComponent.extendComponent({
|
||||
currentCardIsInThisList(listId, swimlaneId) {
|
||||
const currentCard = Cards.findOne(Session.get('currentCard'));
|
||||
const currentBoardId = Session.get('currentBoard');
|
||||
const board = Boards.findOne(currentBoardId);
|
||||
if (board.view === 'board-view-lists')
|
||||
return currentCard && currentCard.listId === listId;
|
||||
else if (board.view === 'board-view-swimlanes')
|
||||
return currentCard && currentCard.listId === listId && currentCard.swimlaneId === swimlaneId;
|
||||
else
|
||||
return false;
|
||||
},
|
||||
}).register('listsGroup');
|
||||
@@ -4,6 +4,7 @@
|
||||
color: white
|
||||
transition: background-color 0.4s
|
||||
background: #2980B9
|
||||
z-index: 17
|
||||
|
||||
#header-main-bar
|
||||
height: 40px
|
||||
@@ -28,13 +29,12 @@
|
||||
font-size: 0.9em
|
||||
margin-right: 10px
|
||||
|
||||
|
||||
.wekan-logo
|
||||
display: block
|
||||
margin: 3px auto 0
|
||||
margin: 3px auto auto
|
||||
width: 97px
|
||||
opacity: 0.6
|
||||
transition: opacity 0.15s
|
||||
float: right
|
||||
|
||||
&:hover
|
||||
opacity: 0.9
|
||||
@@ -99,6 +99,7 @@
|
||||
height: 28px
|
||||
font-size: 12px
|
||||
display: flex
|
||||
z-index: 17
|
||||
|
||||
#header-user-bar,
|
||||
#header-new-board-icon,
|
||||
@@ -217,7 +218,7 @@
|
||||
position: absolute
|
||||
right: 0px
|
||||
padding: 10px
|
||||
margin: -10px
|
||||
margin: -10px 0 -10px -10px
|
||||
|
||||
.announcement,
|
||||
.offline-warning
|
||||
|
||||
@@ -9,6 +9,7 @@ head
|
||||
packages.
|
||||
link(rel="shortcut icon" href="/wekan-favicon.png")
|
||||
link(rel="apple-touch-icon" href="/wekan-favicon.png")
|
||||
link(rel="mask-icon" href="/wekan-150.svg")
|
||||
link(rel="manifest" href="/wekan-manifest.json")
|
||||
|
||||
template(name="userFormsLayout")
|
||||
@@ -17,6 +18,9 @@ template(name="userFormsLayout")
|
||||
img(src="{{pathFor '/wekan-logo.png'}}" alt="Wekan")
|
||||
section.auth-dialog
|
||||
+Template.dynamic(template=content)
|
||||
if isCas
|
||||
.at-form
|
||||
button#cas(class='at-btn submit' type='submit') {{casSignInLabel}}
|
||||
div.at-form-lang
|
||||
select.select-lang.js-userform-set-language
|
||||
each languages
|
||||
|
||||
@@ -17,10 +17,14 @@ Template.userFormsLayout.onRendered(() => {
|
||||
Template.userFormsLayout.helpers({
|
||||
languages() {
|
||||
return _.map(TAPi18n.getLanguages(), (lang, code) => {
|
||||
return {
|
||||
tag: code,
|
||||
name: lang.name === 'br' ? 'Brezhoneg' : lang.name === 'ig' ? 'Igbo' : lang.name,
|
||||
};
|
||||
const tag = code;
|
||||
let name = lang.name;
|
||||
if (lang.name === 'br') {
|
||||
name = 'Brezhoneg';
|
||||
} else if (lang.name === 'ig') {
|
||||
name = 'Igbo';
|
||||
}
|
||||
return { tag, name };
|
||||
}).sort(function(a, b) {
|
||||
if (a.name === b.name) {
|
||||
return 0;
|
||||
@@ -35,6 +39,16 @@ Template.userFormsLayout.helpers({
|
||||
const curLang = T9n.getLanguage() || 'en';
|
||||
return t9nTag === curLang;
|
||||
},
|
||||
|
||||
isCas() {
|
||||
return Meteor.settings.public &&
|
||||
Meteor.settings.public.cas &&
|
||||
Meteor.settings.public.cas.loginUrl;
|
||||
},
|
||||
|
||||
casSignInLabel() {
|
||||
return TAPi18n.__('casSignIn', {}, T9n.getLanguage() || 'en');
|
||||
},
|
||||
});
|
||||
|
||||
Template.userFormsLayout.events({
|
||||
@@ -43,6 +57,13 @@ Template.userFormsLayout.events({
|
||||
T9n.setLanguage(i18nTagToT9n(i18nTag));
|
||||
evt.preventDefault();
|
||||
},
|
||||
'click button#cas'() {
|
||||
Meteor.loginWithCas(function() {
|
||||
if (FlowRouter.getRouteName() === 'atSignIn') {
|
||||
FlowRouter.go('/');
|
||||
}
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
Template.defaultLayout.events({
|
||||
|
||||
@@ -33,6 +33,9 @@ $popupWidth = 300px
|
||||
textarea
|
||||
height: 72px
|
||||
|
||||
form a span
|
||||
padding: 0 0.5rem
|
||||
|
||||
.header
|
||||
height: 36px
|
||||
position: relative
|
||||
|
||||
@@ -1,12 +1,16 @@
|
||||
const { isTouchDevice } = Utils;
|
||||
|
||||
Mixins.PerfectScrollbar = BlazeComponent.extendComponent({
|
||||
onRendered() {
|
||||
const component = this.mixinParent();
|
||||
const domElement = component.find('.js-perfect-scrollbar');
|
||||
Ps.initialize(domElement);
|
||||
if (!isTouchDevice()) {
|
||||
const component = this.mixinParent();
|
||||
const domElement = component.find('.js-perfect-scrollbar');
|
||||
Ps.initialize(domElement);
|
||||
|
||||
// XXX We should create an event map to be consistent with other components
|
||||
// but since BlazeComponent doesn't merge Mixins events transparently I
|
||||
// prefered to use a jQuery event (which is what an event map ends up doing)
|
||||
component.$(domElement).on('mouseenter', () => Ps.update(domElement));
|
||||
// XXX We should create an event map to be consistent with other components
|
||||
// but since BlazeComponent doesn't merge Mixins events transparently I
|
||||
// prefered to use a jQuery event (which is what an event map ends up doing)
|
||||
component.$(domElement).on('mouseenter', () => Ps.update(domElement));
|
||||
}
|
||||
},
|
||||
});
|
||||
@@ -1,6 +1,13 @@
|
||||
Template.invitationCode.onRendered(() => {
|
||||
const setting = Settings.findOne();
|
||||
if (setting || setting.disableRegistration) {
|
||||
$('#invitationcode').hide();
|
||||
}
|
||||
Template.invitationCode.onRendered(function() {
|
||||
Meteor.subscribe('setting', {
|
||||
onReady() {
|
||||
const setting = Settings.findOne();
|
||||
|
||||
if (!setting || !setting.disableRegistration) {
|
||||
$('#invitationcode').hide();
|
||||
}
|
||||
|
||||
return this.stop();
|
||||
},
|
||||
});
|
||||
});
|
||||
@@ -2,9 +2,9 @@
|
||||
overflow: scroll;
|
||||
|
||||
table
|
||||
font-family: arial, sans-serif;
|
||||
border-collapse: collapse;
|
||||
width: 100%;
|
||||
color: #000;
|
||||
|
||||
td, th
|
||||
border: 1px solid #d2d0d0;
|
||||
|
||||
@@ -72,7 +72,7 @@ template(name='email')
|
||||
li.smtp-form
|
||||
.title {{_ 'smtp-password'}}
|
||||
.form-group
|
||||
input.form-control#mail-server-password(type="text", placeholder="{{_ 'password'}}" value="{{currentSetting.mailServer.password}}")
|
||||
input.form-control#mail-server-password(type="text", placeholder="{{_ 'password'}}" value="")
|
||||
li.smtp-form
|
||||
.title {{_ 'smtp-tls'}}
|
||||
.form-group
|
||||
@@ -94,13 +94,21 @@ template(name='email')
|
||||
|
||||
template(name='accountSettings')
|
||||
ul#account-setting.setting-detail
|
||||
li.smtp-form
|
||||
li.accounts-form
|
||||
.title {{_ 'accounts-allowEmailChange'}}
|
||||
.form-group.flex
|
||||
input.form-control#accounts-allowEmailChange(type="radio" name="allowEmailChange" value="true" checked="{{#if allowEmailChange}}checked{{/if}}")
|
||||
span {{_ 'yes'}}
|
||||
input.form-control#accounts-allowEmailChange(type="radio" name="allowEmailChange" value="false" checked="{{#unless allowEmailChange}}checked{{/unless}}")
|
||||
span {{_ 'no'}}
|
||||
li
|
||||
li.accounts-form
|
||||
.title {{_ 'accounts-allowUserNameChange'}}
|
||||
.form-group.flex
|
||||
input.form-control#accounts-allowUserNameChange(type="radio" name="allowUserNameChange" value="true" checked="{{#if allowUserNameChange}}checked{{/if}}")
|
||||
span {{_ 'yes'}}
|
||||
input.form-control#accounts-allowUserNameChange(type="radio" name="allowUserNameChange" value="false" checked="{{#unless allowUserNameChange}}checked{{/unless}}")
|
||||
span {{_ 'no'}}
|
||||
li
|
||||
button.js-accounts-save.primary {{_ 'save'}}
|
||||
|
||||
|
||||
@@ -23,7 +23,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
checkField(selector) {
|
||||
const value = $(selector).val();
|
||||
if(!value || value.trim() === ''){
|
||||
if (!value || value.trim() === '') {
|
||||
$(selector).parents('li.smtp-form').addClass('has-error');
|
||||
throw Error('blank field');
|
||||
} else {
|
||||
@@ -31,7 +31,7 @@ BlazeComponent.extendComponent({
|
||||
}
|
||||
},
|
||||
|
||||
currentSetting(){
|
||||
currentSetting() {
|
||||
return Settings.findOne();
|
||||
},
|
||||
|
||||
@@ -44,23 +44,23 @@ BlazeComponent.extendComponent({
|
||||
sort: ['title'],
|
||||
});
|
||||
},
|
||||
toggleRegistration(){
|
||||
toggleRegistration() {
|
||||
this.setLoading(true);
|
||||
const registrationClosed = this.currentSetting().disableRegistration;
|
||||
Settings.update(Settings.findOne()._id, {$set:{disableRegistration: !registrationClosed}});
|
||||
Settings.update(Settings.findOne()._id, {$set: {disableRegistration: !registrationClosed}});
|
||||
this.setLoading(false);
|
||||
if(registrationClosed){
|
||||
if (registrationClosed) {
|
||||
$('.invite-people').slideUp();
|
||||
}else{
|
||||
} else {
|
||||
$('.invite-people').slideDown();
|
||||
}
|
||||
},
|
||||
toggleTLS(){
|
||||
toggleTLS() {
|
||||
$('#mail-server-tls').toggleClass('is-checked');
|
||||
},
|
||||
switchMenu(event){
|
||||
switchMenu(event) {
|
||||
const target = $(event.target);
|
||||
if(!target.hasClass('active')){
|
||||
if (!target.hasClass('active')) {
|
||||
$('.side-menu li.active').removeClass('active');
|
||||
target.parent().addClass('active');
|
||||
const targetID = target.data('id');
|
||||
@@ -71,9 +71,9 @@ BlazeComponent.extendComponent({
|
||||
}
|
||||
},
|
||||
|
||||
checkBoard(event){
|
||||
checkBoard(event) {
|
||||
let target = $(event.target);
|
||||
if(!target.hasClass('js-toggle-board-choose')){
|
||||
if (!target.hasClass('js-toggle-board-choose')) {
|
||||
target = target.parent();
|
||||
}
|
||||
const checkboxId = target.attr('id');
|
||||
@@ -81,7 +81,7 @@ BlazeComponent.extendComponent({
|
||||
$(`#${checkboxId}`).toggleClass('is-checked');
|
||||
},
|
||||
|
||||
inviteThroughEmail(){
|
||||
inviteThroughEmail() {
|
||||
const emails = $('#email-to-invite').val().trim().split('\n').join(',').split(',');
|
||||
const boardsToInvite = [];
|
||||
$('.js-toggle-board-choose .materialCheckBox.is-checked').each(function () {
|
||||
@@ -104,19 +104,23 @@ BlazeComponent.extendComponent({
|
||||
}
|
||||
},
|
||||
|
||||
saveMailServerInfo(){
|
||||
saveMailServerInfo() {
|
||||
this.setLoading(true);
|
||||
$('li').removeClass('has-error');
|
||||
|
||||
try{
|
||||
try {
|
||||
const host = this.checkField('#mail-server-host');
|
||||
const port = this.checkField('#mail-server-port');
|
||||
const username = $('#mail-server-username').val().trim();
|
||||
const password = $('#mail-server-password').val().trim();
|
||||
const from = this.checkField('#mail-server-from');
|
||||
const tls = $('#mail-server-tls.is-checked').length > 0;
|
||||
Settings.update(Settings.findOne()._id, {$set:{'mailServer.host':host, 'mailServer.port': port, 'mailServer.username': username,
|
||||
'mailServer.password': password, 'mailServer.enableTLS': tls, 'mailServer.from': from}});
|
||||
Settings.update(Settings.findOne()._id, {
|
||||
$set: {
|
||||
'mailServer.host': host, 'mailServer.port': port, 'mailServer.username': username,
|
||||
'mailServer.password': password, 'mailServer.enableTLS': tls, 'mailServer.from': from,
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
return;
|
||||
} finally {
|
||||
@@ -136,11 +140,12 @@ BlazeComponent.extendComponent({
|
||||
const message = `${TAPi18n.__(err.error)}\n${reason}`;
|
||||
console.log(message, err);
|
||||
alert(message);
|
||||
} /* eslint-enable no-console */
|
||||
}
|
||||
/* eslint-enable no-console */
|
||||
});
|
||||
},
|
||||
|
||||
events(){
|
||||
events() {
|
||||
return [{
|
||||
'click a.js-toggle-registration': this.toggleRegistration,
|
||||
'click a.js-toggle-tls': this.toggleTLS,
|
||||
@@ -154,20 +159,28 @@ BlazeComponent.extendComponent({
|
||||
}).register('setting');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
saveAllowEmailChange() {
|
||||
|
||||
saveAccountsChange() {
|
||||
const allowEmailChange = ($('input[name=allowEmailChange]:checked').val() === 'true');
|
||||
const allowUserNameChange = ($('input[name=allowUserNameChange]:checked').val() === 'true');
|
||||
AccountSettings.update('accounts-allowEmailChange', {
|
||||
$set: { 'booleanValue': allowEmailChange },
|
||||
$set: {'booleanValue': allowEmailChange},
|
||||
});
|
||||
AccountSettings.update('accounts-allowUserNameChange', {
|
||||
$set: {'booleanValue': allowUserNameChange},
|
||||
});
|
||||
},
|
||||
|
||||
allowEmailChange() {
|
||||
return AccountSettings.findOne('accounts-allowEmailChange').booleanValue;
|
||||
},
|
||||
allowUserNameChange() {
|
||||
return AccountSettings.findOne('accounts-allowUserNameChange').booleanValue;
|
||||
},
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'click button.js-accounts-save': this.saveAllowEmailChange,
|
||||
'click button.js-accounts-save': this.saveAccountsChange,
|
||||
}];
|
||||
},
|
||||
}).register('accountSettings');
|
||||
@@ -181,27 +194,27 @@ BlazeComponent.extendComponent({
|
||||
this.loading.set(w);
|
||||
},
|
||||
|
||||
currentSetting(){
|
||||
currentSetting() {
|
||||
return Announcements.findOne();
|
||||
},
|
||||
|
||||
saveMessage() {
|
||||
const message = $('#admin-announcement').val().trim();
|
||||
Announcements.update(Announcements.findOne()._id, {
|
||||
$set: { 'body': message },
|
||||
$set: {'body': message},
|
||||
});
|
||||
},
|
||||
|
||||
toggleActive(){
|
||||
toggleActive() {
|
||||
this.setLoading(true);
|
||||
const isActive = this.currentSetting().enabled;
|
||||
Announcements.update(Announcements.findOne()._id, {
|
||||
$set:{ 'enabled': !isActive},
|
||||
$set: {'enabled': !isActive},
|
||||
});
|
||||
this.setLoading(false);
|
||||
if(isActive){
|
||||
if (isActive) {
|
||||
$('.admin-announcement').slideUp();
|
||||
}else{
|
||||
} else {
|
||||
$('.admin-announcement').slideDown();
|
||||
}
|
||||
},
|
||||
|
||||
@@ -22,4 +22,4 @@
|
||||
+ span
|
||||
display: inline-block
|
||||
margin-top: 1px
|
||||
margin-right: 10px
|
||||
margin-right: 10px
|
||||
@@ -23,10 +23,11 @@ template(name='homeSidebar')
|
||||
hr
|
||||
+labelsWidget
|
||||
hr
|
||||
h3
|
||||
i.fa.fa-comments-o
|
||||
| {{_ 'activities'}}
|
||||
+activities(mode="board")
|
||||
unless currentUser.isNoComments
|
||||
h3
|
||||
i.fa.fa-comments-o
|
||||
| {{_ 'activities'}}
|
||||
+activities(mode="board")
|
||||
|
||||
template(name="membersWidget")
|
||||
.board-widget.board-widget-members
|
||||
@@ -145,6 +146,12 @@ template(name="changePermissionsPopup")
|
||||
if isNormal
|
||||
i.fa.fa-check
|
||||
span.sub-name {{_ 'normal-desc'}}
|
||||
li
|
||||
a(class="{{#if isLastAdmin}}disabled{{else}}js-set-no-comments{{/if}}")
|
||||
| {{_ 'no-comments'}}
|
||||
if isNoComments
|
||||
i.fa.fa-check
|
||||
span.sub-name {{_ 'no-comments-desc'}}
|
||||
li
|
||||
a(class="{{#if isLastAdmin}}disabled{{else}}js-set-comment-only{{/if}}")
|
||||
| {{_ 'comment-only'}}
|
||||
|
||||
@@ -4,7 +4,9 @@ const defaultView = 'home';
|
||||
|
||||
const viewTitles = {
|
||||
filter: 'filter-cards',
|
||||
search: 'search-cards',
|
||||
multiselection: 'multi-selection',
|
||||
customFields: 'custom-fields',
|
||||
archives: 'archives',
|
||||
};
|
||||
|
||||
@@ -124,8 +126,11 @@ Template.memberPopup.helpers({
|
||||
if(type === 'normal'){
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const commentOnly = currentBoard.hasCommentOnly(this.userId);
|
||||
const noComments = currentBoard.hasNoComments(this.userId);
|
||||
if(commentOnly){
|
||||
return TAPi18n.__('comment-only').toLowerCase();
|
||||
} else if(noComments) {
|
||||
return TAPi18n.__('no-comments').toLowerCase();
|
||||
} else {
|
||||
return TAPi18n.__(type).toLowerCase();
|
||||
}
|
||||
@@ -155,7 +160,7 @@ Template.memberPopup.events({
|
||||
}),
|
||||
'click .js-leave-member': Popup.afterConfirm('leaveBoard', () => {
|
||||
const boardId = Session.get('currentBoard');
|
||||
Meteor.call('quitBoard', boardId, (err, ret) => {
|
||||
Meteor.call('quitBoard', boardId, () => {
|
||||
Popup.close();
|
||||
FlowRouter.go('home');
|
||||
});
|
||||
@@ -322,12 +327,13 @@ BlazeComponent.extendComponent({
|
||||
}).register('addMemberPopup');
|
||||
|
||||
Template.changePermissionsPopup.events({
|
||||
'click .js-set-admin, click .js-set-normal, click .js-set-comment-only'(event) {
|
||||
'click .js-set-admin, click .js-set-normal, click .js-set-no-comments, click .js-set-comment-only'(event) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const memberId = this.userId;
|
||||
const isAdmin = $(event.currentTarget).hasClass('js-set-admin');
|
||||
const isCommentOnly = $(event.currentTarget).hasClass('js-set-comment-only');
|
||||
currentBoard.setMemberPermission(memberId, isAdmin, isCommentOnly);
|
||||
const isNoComments = $(event.currentTarget).hasClass('js-set-no-comments');
|
||||
currentBoard.setMemberPermission(memberId, isAdmin, isNoComments, isCommentOnly);
|
||||
Popup.back(1);
|
||||
},
|
||||
});
|
||||
@@ -340,7 +346,12 @@ Template.changePermissionsPopup.helpers({
|
||||
|
||||
isNormal() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
return !currentBoard.hasAdmin(this.userId) && !currentBoard.hasCommentOnly(this.userId);
|
||||
return !currentBoard.hasAdmin(this.userId) && !currentBoard.hasNoComments(this.userId) && !currentBoard.hasCommentOnly(this.userId);
|
||||
},
|
||||
|
||||
isNoComments() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
return !currentBoard.hasAdmin(this.userId) && currentBoard.hasNoComments(this.userId);
|
||||
},
|
||||
|
||||
isCommentOnly() {
|
||||
|
||||
@@ -45,28 +45,45 @@
|
||||
display: flex
|
||||
flex-direction: column
|
||||
|
||||
li > a
|
||||
display: flex
|
||||
height: 30px
|
||||
margin: 0
|
||||
padding: 4px
|
||||
border-radius: 3px
|
||||
align-items: center
|
||||
li
|
||||
& > a
|
||||
display: flex
|
||||
height: 30px
|
||||
margin: 0
|
||||
padding: 4px
|
||||
border-radius: 3px
|
||||
align-items: center
|
||||
|
||||
&:hover
|
||||
&, i, .quiet
|
||||
color white
|
||||
&:hover
|
||||
&, i, .quiet
|
||||
color white
|
||||
|
||||
.member, .card-label
|
||||
margin-right: 7px
|
||||
margin-top: 5px
|
||||
.member, .card-label
|
||||
margin-right: 7px
|
||||
margin-top: 5px
|
||||
|
||||
.sidebar-list-item-description
|
||||
flex: 1
|
||||
overflow: ellipsis
|
||||
.minicard-edit-button
|
||||
float: right
|
||||
padding: 8px
|
||||
border-radius: 3px
|
||||
|
||||
.fa.fa-check
|
||||
margin: 0 4px
|
||||
.sidebar-list-item-description
|
||||
flex: 1
|
||||
overflow: ellipsis
|
||||
|
||||
.fa.fa-check
|
||||
margin: 0 4px
|
||||
|
||||
.minicard
|
||||
padding: 6px 8px 4px
|
||||
|
||||
.minicard-edit-button
|
||||
float: right
|
||||
padding: 4px
|
||||
border-radius: 3px
|
||||
|
||||
&:hover
|
||||
background: #dbdbdb
|
||||
|
||||
.sidebar-btn
|
||||
display: block
|
||||
|
||||
@@ -0,0 +1,52 @@
|
||||
template(name="customFieldsSidebar")
|
||||
ul.sidebar-list
|
||||
each customFields
|
||||
li
|
||||
div.minicard-wrapper.js-minicard
|
||||
div.minicard
|
||||
a.fa.fa-pencil.js-edit-custom-field.minicard-edit-button
|
||||
div.minicard-title
|
||||
| {{ name }} ({{ type }})
|
||||
|
||||
if currentUser.isBoardMember
|
||||
hr
|
||||
a.sidebar-btn.js-open-create-custom-field
|
||||
i.fa.fa-plus
|
||||
span {{_ 'createCustomField'}}
|
||||
|
||||
template(name="createCustomFieldPopup")
|
||||
form
|
||||
label
|
||||
| {{_ 'name'}}
|
||||
unless _id
|
||||
input.js-field-name(type="text" autofocus)
|
||||
else
|
||||
input.js-field-name(type="text" value=name)
|
||||
|
||||
label
|
||||
| {{_ 'type'}}
|
||||
select.js-field-type(disabled="{{#if _id}}disabled{{/if}}")
|
||||
each types
|
||||
if selected
|
||||
option(value=value selected="selected") {{name}}
|
||||
else
|
||||
option(value=value) {{name}}
|
||||
div.js-field-settings.js-field-settings-dropdown(class="{{#if isTypeNotSelected 'dropdown'}}hide{{/if}}")
|
||||
label
|
||||
| {{_ 'custom-field-dropdown-options'}}
|
||||
each dropdownItems.get
|
||||
input.js-dropdown-item(type="text" value=name placeholder="")
|
||||
input.js-dropdown-item.last(type="text" value="" placeholder="{{_ 'custom-field-dropdown-options-placeholder'}}")
|
||||
a.flex.js-field-show-on-card(class="{{#if showOnCard}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if showOnCard}}is-checked{{/if}}")
|
||||
|
||||
span {{_ 'show-field-on-card'}}
|
||||
button.primary.wide.left(type="button")
|
||||
| {{_ 'save'}}
|
||||
if _id
|
||||
button.negate.wide.right.js-delete-custom-field(type="button")
|
||||
| {{_ 'delete'}}
|
||||
|
||||
template(name="deleteCustomFieldPopup")
|
||||
p {{_ "custom-field-delete-pop"}}
|
||||
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
|
||||
@@ -0,0 +1,131 @@
|
||||
BlazeComponent.extendComponent({
|
||||
|
||||
customFields() {
|
||||
return CustomFields.find({
|
||||
boardId: Session.get('currentBoard'),
|
||||
});
|
||||
},
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'click .js-open-create-custom-field': Popup.open('createCustomField'),
|
||||
'click .js-edit-custom-field': Popup.open('editCustomField'),
|
||||
}];
|
||||
},
|
||||
|
||||
}).register('customFieldsSidebar');
|
||||
|
||||
const CreateCustomFieldPopup = BlazeComponent.extendComponent({
|
||||
|
||||
_types: ['text', 'number', 'date', 'dropdown'],
|
||||
|
||||
onCreated() {
|
||||
this.type = new ReactiveVar((this.data().type) ? this.data().type : this._types[0]);
|
||||
this.dropdownItems = new ReactiveVar((this.data().settings && this.data().settings.dropdownItems) ? this.data().settings.dropdownItems : []);
|
||||
},
|
||||
|
||||
types() {
|
||||
const currentType = this.data().type;
|
||||
return this._types.
|
||||
map((type) => {return {
|
||||
value: type,
|
||||
name: TAPi18n.__(`custom-field-${type}`),
|
||||
selected: type === currentType,
|
||||
};});
|
||||
},
|
||||
|
||||
isTypeNotSelected(type) {
|
||||
return this.type.get() !== type;
|
||||
},
|
||||
|
||||
getDropdownItems() {
|
||||
const items = this.dropdownItems.get();
|
||||
Array.from(this.findAll('.js-field-settings-dropdown input')).forEach((el, index) => {
|
||||
//console.log('each item!', index, el.value);
|
||||
if (!items[index]) items[index] = {
|
||||
_id: Random.id(6),
|
||||
};
|
||||
items[index].name = el.value.trim();
|
||||
});
|
||||
return items;
|
||||
},
|
||||
|
||||
getSettings() {
|
||||
const settings = {};
|
||||
switch (this.type.get()) {
|
||||
case 'dropdown': {
|
||||
const dropdownItems = this.getDropdownItems().filter((item) => !!item.name.trim());
|
||||
settings.dropdownItems = dropdownItems;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return settings;
|
||||
},
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'change .js-field-type'(evt) {
|
||||
const value = evt.target.value;
|
||||
this.type.set(value);
|
||||
},
|
||||
'keydown .js-dropdown-item.last'(evt) {
|
||||
if (evt.target.value.trim() && evt.keyCode === 13) {
|
||||
const items = this.getDropdownItems();
|
||||
this.dropdownItems.set(items);
|
||||
evt.target.value = '';
|
||||
}
|
||||
},
|
||||
'click .js-field-show-on-card'(evt) {
|
||||
let $target = $(evt.target);
|
||||
if(!$target.hasClass('js-field-show-on-card')){
|
||||
$target = $target.parent();
|
||||
}
|
||||
$target.find('.materialCheckBox').toggleClass('is-checked');
|
||||
$target.toggleClass('is-checked');
|
||||
},
|
||||
'click .primary'(evt) {
|
||||
evt.preventDefault();
|
||||
|
||||
const data = {
|
||||
boardId: Session.get('currentBoard'),
|
||||
name: this.find('.js-field-name').value.trim(),
|
||||
type: this.type.get(),
|
||||
settings: this.getSettings(),
|
||||
showOnCard: this.find('.js-field-show-on-card.is-checked') !== null,
|
||||
};
|
||||
|
||||
// insert or update
|
||||
if (!this.data()._id) {
|
||||
CustomFields.insert(data);
|
||||
} else {
|
||||
CustomFields.update(this.data()._id, {$set: data});
|
||||
}
|
||||
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-delete-custom-field': Popup.afterConfirm('deleteCustomField', function() {
|
||||
const customFieldId = this._id;
|
||||
CustomFields.remove(customFieldId);
|
||||
Popup.close();
|
||||
}),
|
||||
}];
|
||||
},
|
||||
|
||||
});
|
||||
CreateCustomFieldPopup.register('createCustomFieldPopup');
|
||||
|
||||
(class extends CreateCustomFieldPopup {
|
||||
|
||||
template() {
|
||||
return 'createCustomFieldPopup';
|
||||
}
|
||||
|
||||
}).register('editCustomFieldPopup');
|
||||
|
||||
/*Template.deleteCustomFieldPopup.events({
|
||||
'submit'(evt) {
|
||||
const customFieldId = this._id;
|
||||
CustomFields.remove(customFieldId);
|
||||
Popup.close();
|
||||
}
|
||||
});*/
|
||||
@@ -40,6 +40,25 @@ template(name="filterSidebar")
|
||||
| (<span class="username">{{ username }}</span>)
|
||||
if Filter.members.isSelected _id
|
||||
i.fa.fa-check
|
||||
hr
|
||||
ul.sidebar-list
|
||||
li(class="{{#if Filter.customFields.isSelected undefined}}active{{/if}}")
|
||||
a.name.js-toggle-custom-fields-filter
|
||||
span.sidebar-list-item-description
|
||||
| {{_ 'filter-no-custom-fields'}}
|
||||
if Filter.customFields.isSelected undefined
|
||||
i.fa.fa-check
|
||||
each currentBoard.customFields
|
||||
li(class="{{#if Filter.customFields.isSelected _id}}active{{/if}}")
|
||||
a.name.js-toggle-custom-fields-filter
|
||||
span.sidebar-list-item-description
|
||||
| {{ name }}
|
||||
if Filter.customFields.isSelected _id
|
||||
i.fa.fa-check
|
||||
hr
|
||||
span {{_ 'advanced-filter-label'}}
|
||||
input.js-field-advanced-filter(type="text")
|
||||
span {{_ 'advanced-filter-description'}}
|
||||
if Filter.isActive
|
||||
hr
|
||||
a.sidebar-btn.js-clear-all
|
||||
|
||||
@@ -11,6 +11,16 @@ BlazeComponent.extendComponent({
|
||||
Filter.members.toggle(this.currentData()._id);
|
||||
Filter.resetExceptions();
|
||||
},
|
||||
'click .js-toggle-custom-fields-filter'(evt) {
|
||||
evt.preventDefault();
|
||||
Filter.customFields.toggle(this.currentData()._id);
|
||||
Filter.resetExceptions();
|
||||
},
|
||||
'change .js-field-advanced-filter'(evt) {
|
||||
evt.preventDefault();
|
||||
Filter.advanced.set(this.find('.js-field-advanced-filter').value.trim());
|
||||
Filter.resetExceptions();
|
||||
},
|
||||
'click .js-clear-all'(evt) {
|
||||
evt.preventDefault();
|
||||
Filter.reset();
|
||||
|
||||
@@ -0,0 +1,8 @@
|
||||
template(name="searchSidebar")
|
||||
form.js-search-term-form
|
||||
input(type="text" name="searchTerm" placeholder="{{_ 'search-example'}}" autofocus)
|
||||
.list-body.js-perfect-scrollbar
|
||||
.minicards.clearfix.js-minicards
|
||||
each (results)
|
||||
a.minicard-wrapper.js-minicard(href=absoluteUrl)
|
||||
+minicard(this)
|
||||
@@ -0,0 +1,19 @@
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.term = new ReactiveVar('');
|
||||
},
|
||||
|
||||
results() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
return currentBoard.searchCards(this.term.get());
|
||||
},
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'submit .js-search-term-form'(evt) {
|
||||
evt.preventDefault();
|
||||
this.term.set(evt.target.searchTerm.value);
|
||||
},
|
||||
}];
|
||||
},
|
||||
}).register('searchSidebar');
|
||||
@@ -0,0 +1,2 @@
|
||||
input
|
||||
max-width: 100%
|
||||
@@ -1,5 +1,5 @@
|
||||
template(name="swimlaneHeader")
|
||||
.swimlane-header-wrap
|
||||
.swimlane-header-wrap.js-swimlane-header
|
||||
+inlinedForm
|
||||
+editSwimlaneTitleForm
|
||||
else
|
||||
@@ -9,7 +9,7 @@ template(name="swimlaneHeader")
|
||||
.swimlane-header-menu
|
||||
unless currentUser.isCommentOnly
|
||||
a.fa.fa-navicon.js-open-swimlane-menu
|
||||
|
||||
|
||||
template(name="editSwimlaneTitleForm")
|
||||
.list-composer
|
||||
input.list-name-input.full-line(type="text" value=title autofocus)
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
template(name="swimlane")
|
||||
.swimlane.js-lists
|
||||
.swimlane.js-lists.js-swimlane
|
||||
+swimlaneHeader
|
||||
if isMiniScreen
|
||||
if currentList
|
||||
@@ -18,7 +18,7 @@ template(name="swimlane")
|
||||
+addListAndSwimlaneForm
|
||||
|
||||
template(name="listsGroup")
|
||||
.swimlane.js-lists
|
||||
.swimlane.list-group.js-lists
|
||||
if isMiniScreen
|
||||
if currentList
|
||||
+list(currentList)
|
||||
@@ -36,7 +36,7 @@ template(name="listsGroup")
|
||||
+addListForm
|
||||
|
||||
template(name="addListAndSwimlaneForm")
|
||||
.list.js-list.list-composer.js-list-composer
|
||||
.list.list-composer.js-list-composer
|
||||
.list-header
|
||||
+inlinedForm(autoclose=false)
|
||||
input.list-name-input.full-line(type="text" placeholder="{{_ 'add-list'}}"
|
||||
@@ -61,7 +61,7 @@ template(name="addListAndSwimlaneForm")
|
||||
| {{_ 'add-swimlane'}}
|
||||
|
||||
template(name="addListForm")
|
||||
.list.js-list.list-composer.js-list-composer
|
||||
.list.list-composer.js-list-composer
|
||||
.list-header
|
||||
+inlinedForm(autoclose=false)
|
||||
input.list-name-input.full-line(type="text" placeholder="{{_ 'add-list'}}"
|
||||
|
||||
@@ -1,4 +1,100 @@
|
||||
const { calculateIndex, enableClickOnTouch } = Utils;
|
||||
|
||||
function currentCardIsInThisList(listId, swimlaneId) {
|
||||
const currentCard = Cards.findOne(Session.get('currentCard'));
|
||||
const currentUser = Meteor.user();
|
||||
if (currentUser.profile.boardView === 'board-view-lists')
|
||||
return currentCard && currentCard.listId === listId;
|
||||
else if (currentUser.profile.boardView === 'board-view-swimlanes')
|
||||
return currentCard && currentCard.listId === listId && currentCard.swimlaneId === swimlaneId;
|
||||
else if (currentUser.profile.boardView === 'board-view-cal')
|
||||
return currentCard;
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
function initSortable(boardComponent, $listsDom) {
|
||||
// We want to animate the card details window closing. We rely on CSS
|
||||
// transition for the actual animation.
|
||||
$listsDom._uihooks = {
|
||||
removeElement(node) {
|
||||
const removeNode = _.once(() => {
|
||||
node.parentNode.removeChild(node);
|
||||
});
|
||||
if ($(node).hasClass('js-card-details')) {
|
||||
$(node).css({
|
||||
flexBasis: 0,
|
||||
padding: 0,
|
||||
});
|
||||
$listsDom.one(CSSEvents.transitionend, removeNode);
|
||||
} else {
|
||||
removeNode();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
$listsDom.sortable({
|
||||
tolerance: 'pointer',
|
||||
helper: 'clone',
|
||||
handle: '.js-list-header',
|
||||
items: '.js-list:not(.js-list-composer)',
|
||||
placeholder: 'list placeholder',
|
||||
distance: 7,
|
||||
start(evt, ui) {
|
||||
ui.placeholder.height(ui.helper.height());
|
||||
EscapeActions.executeUpTo('popup-close');
|
||||
boardComponent.setIsDragging(true);
|
||||
},
|
||||
stop(evt, ui) {
|
||||
// To attribute the new index number, we need to get the DOM element
|
||||
// of the previous and the following card -- if any.
|
||||
const prevListDom = ui.item.prev('.js-list').get(0);
|
||||
const nextListDom = ui.item.next('.js-list').get(0);
|
||||
const sortIndex = calculateIndex(prevListDom, nextListDom, 1);
|
||||
|
||||
$listsDom.sortable('cancel');
|
||||
const listDomElement = ui.item.get(0);
|
||||
const list = Blaze.getData(listDomElement);
|
||||
|
||||
Lists.update(list._id, {
|
||||
$set: {
|
||||
sort: sortIndex.base,
|
||||
},
|
||||
});
|
||||
|
||||
boardComponent.setIsDragging(false);
|
||||
},
|
||||
});
|
||||
|
||||
// ugly touch event hotfix
|
||||
enableClickOnTouch('.js-list:not(.js-list-composer)');
|
||||
|
||||
function userIsMember() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
|
||||
}
|
||||
|
||||
// Disable drag-dropping while in multi-selection mode, or if the current user
|
||||
// is not a board member
|
||||
boardComponent.autorun(() => {
|
||||
const $listDom = $listsDom;
|
||||
if ($listDom.data('sortable')) {
|
||||
$listsDom.sortable('option', 'disabled',
|
||||
MultiSelection.isActive() || !userIsMember());
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onRendered() {
|
||||
const boardComponent = this.parentComponent();
|
||||
const $listsDom = this.$('.js-lists');
|
||||
|
||||
if (!Session.get('currentCard')) {
|
||||
boardComponent.scrollLeft();
|
||||
}
|
||||
|
||||
initSortable(boardComponent, $listsDom);
|
||||
},
|
||||
onCreated() {
|
||||
this.draggingActive = new ReactiveVar(false);
|
||||
|
||||
@@ -6,38 +102,12 @@ BlazeComponent.extendComponent({
|
||||
this._lastDragPositionX = 0;
|
||||
},
|
||||
|
||||
openNewListForm() {
|
||||
this.childComponents('addListForm')[0].open();
|
||||
},
|
||||
|
||||
id() {
|
||||
return this._id;
|
||||
},
|
||||
|
||||
// XXX Flow components allow us to avoid creating these two setter methods by
|
||||
// exposing a public API to modify the component state. We need to investigate
|
||||
// best practices here.
|
||||
setIsDragging(bool) {
|
||||
this.draggingActive.set(bool);
|
||||
},
|
||||
|
||||
scrollLeft(position = 0) {
|
||||
const lists = this.$('.js-lists');
|
||||
lists && lists.animate({
|
||||
scrollLeft: position,
|
||||
});
|
||||
},
|
||||
|
||||
currentCardIsInThisList(listId, swimlaneId) {
|
||||
const currentCard = Cards.findOne(Session.get('currentCard'));
|
||||
const currentBoardId = Session.get('currentBoard');
|
||||
const board = Boards.findOne(currentBoardId);
|
||||
if (board.view === 'board-view-lists')
|
||||
return currentCard && currentCard.listId === listId;
|
||||
else if (board.view === 'board-view-swimlanes')
|
||||
return currentCard && currentCard.listId === listId && currentCard.swimlaneId === swimlaneId;
|
||||
else
|
||||
return false;
|
||||
return currentCardIsInThisList(listId, swimlaneId);
|
||||
},
|
||||
|
||||
events() {
|
||||
@@ -78,81 +148,6 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
}).register('swimlane');
|
||||
|
||||
Template.swimlane.onRendered(function() {
|
||||
const self = BlazeComponent.getComponentForElement(this.firstNode);
|
||||
|
||||
self.listsDom = this.find('.js-lists');
|
||||
|
||||
if (!Session.get('currentCard')) {
|
||||
self.scrollLeft();
|
||||
}
|
||||
|
||||
// We want to animate the card details window closing. We rely on CSS
|
||||
// transition for the actual animation.
|
||||
self.listsDom._uihooks = {
|
||||
removeElement(node) {
|
||||
const removeNode = _.once(() => {
|
||||
node.parentNode.removeChild(node);
|
||||
});
|
||||
if ($(node).hasClass('js-card-details')) {
|
||||
$(node).css({
|
||||
flexBasis: 0,
|
||||
padding: 0,
|
||||
});
|
||||
$(self.listsDom).one(CSSEvents.transitionend, removeNode);
|
||||
} else {
|
||||
removeNode();
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
$(self.listsDom).sortable({
|
||||
tolerance: 'pointer',
|
||||
helper: 'clone',
|
||||
handle: '.js-list-header',
|
||||
items: '.js-list:not(.js-list-composer)',
|
||||
placeholder: 'list placeholder',
|
||||
distance: 7,
|
||||
start(evt, ui) {
|
||||
ui.placeholder.height(ui.helper.height());
|
||||
Popup.close();
|
||||
},
|
||||
stop() {
|
||||
$(self.listsDom).find('.js-list:not(.js-list-composer)').each(
|
||||
(i, list) => {
|
||||
const data = Blaze.getData(list);
|
||||
Lists.update(data._id, {
|
||||
$set: {
|
||||
sort: i,
|
||||
},
|
||||
});
|
||||
}
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
function userIsMember() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember();
|
||||
}
|
||||
|
||||
// Disable drag-dropping while in multi-selection mode, or if the current user
|
||||
// is not a board member
|
||||
self.autorun(() => {
|
||||
const $listDom = $(self.listsDom);
|
||||
if ($listDom.data('sortable')) {
|
||||
$(self.listsDom).sortable('option', 'disabled',
|
||||
MultiSelection.isActive() || !userIsMember());
|
||||
}
|
||||
});
|
||||
|
||||
// If there is no data in the board (ie, no lists) we autofocus the list
|
||||
// creation form by clicking on the corresponding element.
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
if (userIsMember() && currentBoard.lists().count() === 0) {
|
||||
self.openNewListForm();
|
||||
}
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
// Proxy
|
||||
open() {
|
||||
@@ -227,3 +222,19 @@ Template.swimlane.helpers({
|
||||
return Meteor.user() && Meteor.user().isBoardMember() && !Meteor.user().isCommentOnly();
|
||||
},
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
currentCardIsInThisList(listId, swimlaneId) {
|
||||
return currentCardIsInThisList(listId, swimlaneId);
|
||||
},
|
||||
onRendered() {
|
||||
const boardComponent = this.parentComponent();
|
||||
const $listsDom = this.$('.js-lists');
|
||||
|
||||
if (!Session.get('currentCard')) {
|
||||
boardComponent.scrollLeft();
|
||||
}
|
||||
|
||||
initSortable(boardComponent, $listsDom);
|
||||
},
|
||||
}).register('listsGroup');
|
||||
@@ -1,24 +1,54 @@
|
||||
@import 'nib'
|
||||
|
||||
.swimlane-header-wrap
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex: 0 0 50px;
|
||||
.swimlane
|
||||
// Even if this background color is the same as the body we can't leave it
|
||||
// transparent, because that won't work during a swimlane drag.
|
||||
background: darken(white, 13%)
|
||||
display: flex
|
||||
flex-direction: row
|
||||
overflow: 0;
|
||||
max-height: 100%
|
||||
|
||||
.swimlane-header
|
||||
writing-mode: sideways-lr;
|
||||
font-size: 14px;
|
||||
line-height: 50px;
|
||||
margin: 0;
|
||||
font-weight: bold;
|
||||
min-height: 9px;
|
||||
min-width: 30px;
|
||||
overflow: hidden;
|
||||
-o-text-overflow: ellipsis;
|
||||
text-overflow: ellipsis;
|
||||
word-wrap: break-word;
|
||||
text-align: center;
|
||||
&.placeholder
|
||||
background-color: rgba(0, 0, 0, .2)
|
||||
border-color: transparent
|
||||
box-shadow: none
|
||||
height: 100px
|
||||
|
||||
.swimlane-header-menu
|
||||
position: absolute
|
||||
padding: 20px 20px
|
||||
&.ui-sortable-helper
|
||||
box-shadow: -2px 2px 8px rgba(0, 0, 0, .3),
|
||||
0 0 1px rgba(0, 0, 0, .5)
|
||||
transform: rotate(2deg)
|
||||
cursor: grabbing
|
||||
|
||||
.swimlane-header.ui-sortable-handle
|
||||
cursor: grabbing
|
||||
|
||||
.swimlane-header-wrap
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
flex: 0 0 50px;
|
||||
padding-bottom: 30px;
|
||||
border-bottom: 1px solid #CCC
|
||||
|
||||
.swimlane-header
|
||||
writing-mode: vertical-rl;
|
||||
transform: rotate(180deg);
|
||||
font-size: 14px;
|
||||
line-height: 50px;
|
||||
margin-top: 50px;
|
||||
font-weight: bold;
|
||||
min-height: 9px;
|
||||
width: 50px;
|
||||
overflow: hidden;
|
||||
-o-text-overflow: ellipsis;
|
||||
text-overflow: ellipsis;
|
||||
word-wrap: break-word;
|
||||
text-align: center;
|
||||
|
||||
.swimlane-header-menu
|
||||
position: absolute
|
||||
padding: 20px 20px
|
||||
|
||||
.list-group
|
||||
height: 100%
|
||||
@@ -1,7 +1,7 @@
|
||||
template(name="userAvatar")
|
||||
a.member.js-member(title="{{userData.profile.fullname}} ({{userData.username}})")
|
||||
if userData.profile.avatarUrl
|
||||
img.avatar.avatar-image(src=userData.profile.avatarUrl)
|
||||
img.avatar.avatar-image(src="{{userData.profile.avatarUrl}}")
|
||||
else
|
||||
+userAvatarInitials(userId=userData._id)
|
||||
|
||||
|
||||
@@ -134,8 +134,9 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.cardMembersPopup.helpers({
|
||||
isCardMember() {
|
||||
const cardId = Template.parentData()._id;
|
||||
const cardMembers = Cards.findOne(cardId).members || [];
|
||||
const card = Template.parentData();
|
||||
const cardMembers = card.getMembers();
|
||||
|
||||
return _.contains(cardMembers, this.userId);
|
||||
},
|
||||
|
||||
|
||||
@@ -33,7 +33,10 @@ template(name="editProfilePopup")
|
||||
| {{_ 'username'}}
|
||||
span.error.hide.username-taken
|
||||
| {{_ 'error-username-taken'}}
|
||||
input.js-profile-username(type="text" value=username)
|
||||
if allowUserNameChange
|
||||
input.js-profile-username(type="text" value=username)
|
||||
else
|
||||
input.js-profile-username(type="text" value=username readonly)
|
||||
label
|
||||
| {{_ 'initials'}}
|
||||
input.js-profile-initials(type="text" value=profile.initials)
|
||||
@@ -86,5 +89,5 @@ template(name="changeSettingsPopup")
|
||||
li
|
||||
label.bold
|
||||
| {{_ 'show-cards-minimum-count'}}
|
||||
input#show-cards-count-at.inline-input.left(type="number" value="#{showCardsCountAt}" min="1" max="99" onkeydown="return false")
|
||||
input#show-cards-count-at.inline-input.left(type="number" value="#{showCardsCountAt}" min="0" max="99" onkeydown="return false")
|
||||
input.js-apply-show-cards-at.left(type="submit" value="{{_ 'apply'}}")
|
||||
@@ -24,6 +24,9 @@ Template.editProfilePopup.helpers({
|
||||
allowEmailChange() {
|
||||
return AccountSettings.findOne('accounts-allowEmailChange').booleanValue;
|
||||
},
|
||||
allowUserNameChange() {
|
||||
return AccountSettings.findOne('accounts-allowUserNameChange').booleanValue;
|
||||
},
|
||||
});
|
||||
|
||||
Template.editProfilePopup.events({
|
||||
@@ -114,10 +117,16 @@ Template.changePasswordPopup.onRendered(function () {
|
||||
Template.changeLanguagePopup.helpers({
|
||||
languages() {
|
||||
return _.map(TAPi18n.getLanguages(), (lang, code) => {
|
||||
return {
|
||||
tag: code,
|
||||
name: lang.name === 'br' ? 'Brezhoneg' : lang.name === 'ig' ? 'Igbo' : lang.name,
|
||||
};
|
||||
// Same code in /client/components/main/layouts.js
|
||||
// TODO : Make code reusable
|
||||
const tag = code;
|
||||
let name = lang.name;
|
||||
if (lang.name === 'br') {
|
||||
name = 'Brezhoneg';
|
||||
} else if (lang.name === 'ig') {
|
||||
name = 'Igbo';
|
||||
}
|
||||
return { tag, name };
|
||||
}).sort(function (a, b) {
|
||||
if (a.name === b.name) {
|
||||
return 0;
|
||||
|
||||
@@ -0,0 +1,86 @@
|
||||
DatePicker = BlazeComponent.extendComponent({
|
||||
template() {
|
||||
return 'datepicker';
|
||||
},
|
||||
|
||||
onCreated() {
|
||||
this.error = new ReactiveVar('');
|
||||
this.card = this.data();
|
||||
this.date = new ReactiveVar(moment.invalid());
|
||||
},
|
||||
|
||||
onRendered() {
|
||||
const $picker = this.$('.js-datepicker').datepicker({
|
||||
todayHighlight: true,
|
||||
todayBtn: 'linked',
|
||||
language: TAPi18n.getLanguage(),
|
||||
}).on('changeDate', function(evt) {
|
||||
this.find('#date').value = moment(evt.date).format('L');
|
||||
this.error.set('');
|
||||
this.find('#time').focus();
|
||||
}.bind(this));
|
||||
|
||||
if (this.date.get().isValid()) {
|
||||
$picker.datepicker('update', this.date.get().toDate());
|
||||
}
|
||||
},
|
||||
|
||||
showDate() {
|
||||
if (this.date.get().isValid())
|
||||
return this.date.get().format('L');
|
||||
return '';
|
||||
},
|
||||
showTime() {
|
||||
if (this.date.get().isValid())
|
||||
return this.date.get().format('LT');
|
||||
return '';
|
||||
},
|
||||
dateFormat() {
|
||||
return moment.localeData().longDateFormat('L');
|
||||
},
|
||||
timeFormat() {
|
||||
return moment.localeData().longDateFormat('LT');
|
||||
},
|
||||
|
||||
events() {
|
||||
return [{
|
||||
'keyup .js-date-field'() {
|
||||
// parse for localized date format in strict mode
|
||||
const dateMoment = moment(this.find('#date').value, 'L', true);
|
||||
if (dateMoment.isValid()) {
|
||||
this.error.set('');
|
||||
this.$('.js-datepicker').datepicker('update', dateMoment.toDate());
|
||||
}
|
||||
},
|
||||
'keyup .js-time-field'() {
|
||||
// parse for localized time format in strict mode
|
||||
const dateMoment = moment(this.find('#time').value, 'LT', true);
|
||||
if (dateMoment.isValid()) {
|
||||
this.error.set('');
|
||||
}
|
||||
},
|
||||
'submit .edit-date'(evt) {
|
||||
evt.preventDefault();
|
||||
|
||||
// if no time was given, init with 12:00
|
||||
const time = evt.target.time.value || moment(new Date().setHours(12, 0, 0)).format('LT');
|
||||
|
||||
const dateString = `${evt.target.date.value} ${time}`;
|
||||
const newDate = moment(dateString, 'L LT', true);
|
||||
if (newDate.isValid()) {
|
||||
this._storeDate(newDate.toDate());
|
||||
Popup.close();
|
||||
}
|
||||
else {
|
||||
this.error.set('invalid-date');
|
||||
evt.target.date.focus();
|
||||
}
|
||||
},
|
||||
'click .js-delete-date'(evt) {
|
||||
evt.preventDefault();
|
||||
this._deleteDate();
|
||||
Popup.close();
|
||||
},
|
||||
}];
|
||||
},
|
||||
});
|
||||
+412
-13
@@ -3,17 +3,19 @@
|
||||
// RangeFilter, dateFilter, etc.). We then define a global `Filter` object whose
|
||||
// goal is to filter complete documents by using the local filters for each
|
||||
// fields.
|
||||
|
||||
function showFilterSidebar() {
|
||||
Sidebar.setView('filter');
|
||||
}
|
||||
|
||||
// Use a "set" filter for a field that is a set of documents uniquely
|
||||
// identified. For instance `{ labels: ['labelA', 'labelC', 'labelD'] }`.
|
||||
// use "subField" for searching inside object Fields.
|
||||
// For instance '{ 'customFields._id': ['field1','field2']} (subField would be: _id)
|
||||
class SetFilter {
|
||||
constructor() {
|
||||
constructor(subField = '') {
|
||||
this._dep = new Tracker.Dependency();
|
||||
this._selectedElements = [];
|
||||
this.subField = subField;
|
||||
}
|
||||
|
||||
isSelected(val) {
|
||||
@@ -61,7 +63,9 @@ class SetFilter {
|
||||
|
||||
_getMongoSelector() {
|
||||
this._dep.depend();
|
||||
return { $in: this._selectedElements };
|
||||
return {
|
||||
$in: this._selectedElements,
|
||||
};
|
||||
}
|
||||
|
||||
_getEmptySelector() {
|
||||
@@ -72,10 +76,385 @@ class SetFilter {
|
||||
includeEmpty = true;
|
||||
}
|
||||
});
|
||||
return includeEmpty ? { $eq: [] } : null;
|
||||
return includeEmpty ? {
|
||||
$eq: [],
|
||||
} : null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Advanced filter forms a MongoSelector from a users String.
|
||||
// Build by: Ignatz 19.05.2018 (github feuerball11)
|
||||
class AdvancedFilter {
|
||||
constructor() {
|
||||
this._dep = new Tracker.Dependency();
|
||||
this._filter = '';
|
||||
this._lastValide = {};
|
||||
}
|
||||
|
||||
set(str) {
|
||||
this._filter = str;
|
||||
this._dep.changed();
|
||||
}
|
||||
|
||||
reset() {
|
||||
this._filter = '';
|
||||
this._lastValide = {};
|
||||
this._dep.changed();
|
||||
}
|
||||
|
||||
_isActive() {
|
||||
this._dep.depend();
|
||||
return this._filter !== '';
|
||||
}
|
||||
|
||||
_filterToCommands() {
|
||||
const commands = [];
|
||||
let current = '';
|
||||
let string = false;
|
||||
let regex = false;
|
||||
let wasString = false;
|
||||
let ignore = false;
|
||||
for (let i = 0; i < this._filter.length; i++) {
|
||||
const char = this._filter.charAt(i);
|
||||
if (ignore) {
|
||||
ignore = false;
|
||||
current += char;
|
||||
continue;
|
||||
}
|
||||
if (char === '/') {
|
||||
string = !string;
|
||||
if (string) regex = true;
|
||||
current += char;
|
||||
continue;
|
||||
}
|
||||
if (char === '\'') {
|
||||
string = !string;
|
||||
if (string) wasString = true;
|
||||
continue;
|
||||
}
|
||||
if (char === '\\' && !string) {
|
||||
ignore = true;
|
||||
continue;
|
||||
}
|
||||
if (char === ' ' && !string) {
|
||||
commands.push({
|
||||
'cmd': current,
|
||||
'string': wasString,
|
||||
regex,
|
||||
});
|
||||
wasString = false;
|
||||
current = '';
|
||||
continue;
|
||||
}
|
||||
current += char;
|
||||
}
|
||||
if (current !== '') {
|
||||
commands.push({
|
||||
'cmd': current,
|
||||
'string': wasString,
|
||||
regex,
|
||||
});
|
||||
}
|
||||
return commands;
|
||||
}
|
||||
|
||||
_fieldNameToId(field) {
|
||||
const found = CustomFields.findOne({
|
||||
'name': field,
|
||||
});
|
||||
return found._id;
|
||||
}
|
||||
|
||||
_fieldValueToId(field, value) {
|
||||
const found = CustomFields.findOne({
|
||||
'name': field,
|
||||
});
|
||||
if (found.settings.dropdownItems && found.settings.dropdownItems.length > 0) {
|
||||
for (let i = 0; i < found.settings.dropdownItems.length; i++) {
|
||||
if (found.settings.dropdownItems[i].name === value) {
|
||||
return found.settings.dropdownItems[i]._id;
|
||||
}
|
||||
}
|
||||
}
|
||||
return value;
|
||||
}
|
||||
|
||||
_arrayToSelector(commands) {
|
||||
try {
|
||||
//let changed = false;
|
||||
this._processSubCommands(commands);
|
||||
} catch (e) {
|
||||
return this._lastValide;
|
||||
}
|
||||
this._lastValide = {
|
||||
$or: commands,
|
||||
};
|
||||
return {
|
||||
$or: commands,
|
||||
};
|
||||
}
|
||||
|
||||
_processSubCommands(commands) {
|
||||
const subcommands = [];
|
||||
let level = 0;
|
||||
let start = -1;
|
||||
for (let i = 0; i < commands.length; i++) {
|
||||
if (commands[i].cmd) {
|
||||
switch (commands[i].cmd) {
|
||||
case '(':
|
||||
{
|
||||
level++;
|
||||
if (start === -1) start = i;
|
||||
continue;
|
||||
}
|
||||
case ')':
|
||||
{
|
||||
level--;
|
||||
commands.splice(i, 1);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
default:
|
||||
{
|
||||
if (level > 0) {
|
||||
subcommands.push(commands[i]);
|
||||
commands.splice(i, 1);
|
||||
i--;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (start !== -1) {
|
||||
this._processSubCommands(subcommands);
|
||||
if (subcommands.length === 1)
|
||||
commands.splice(start, 0, subcommands[0]);
|
||||
else
|
||||
commands.splice(start, 0, subcommands);
|
||||
}
|
||||
this._processConditions(commands);
|
||||
this._processLogicalOperators(commands);
|
||||
}
|
||||
|
||||
_processConditions(commands) {
|
||||
for (let i = 0; i < commands.length; i++) {
|
||||
if (!commands[i].string && commands[i].cmd) {
|
||||
switch (commands[i].cmd) {
|
||||
case '=':
|
||||
case '==':
|
||||
case '===':
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
if (commands[i + 1].regex) {
|
||||
const match = str.match(new RegExp('^/(.*?)/([gimy]*)$'));
|
||||
let regex = null;
|
||||
if (match.length > 2)
|
||||
regex = new RegExp(match[1], match[2]);
|
||||
else
|
||||
regex = new RegExp(match[1]);
|
||||
commands[i] = {
|
||||
'customFields._id': this._fieldNameToId(field),
|
||||
'customFields.value': regex,
|
||||
};
|
||||
} else {
|
||||
commands[i] = {
|
||||
'customFields._id': this._fieldNameToId(field),
|
||||
'customFields.value': {
|
||||
$in: [this._fieldValueToId(field, str), parseInt(str, 10)],
|
||||
},
|
||||
};
|
||||
}
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
case '!=':
|
||||
case '!==':
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
if (commands[i + 1].regex) {
|
||||
const match = str.match(new RegExp('^/(.*?)/([gimy]*)$'));
|
||||
let regex = null;
|
||||
if (match.length > 2)
|
||||
regex = new RegExp(match[1], match[2]);
|
||||
else
|
||||
regex = new RegExp(match[1]);
|
||||
commands[i] = {
|
||||
'customFields._id': this._fieldNameToId(field),
|
||||
'customFields.value': {
|
||||
$not: regex,
|
||||
},
|
||||
};
|
||||
} else {
|
||||
commands[i] = {
|
||||
'customFields._id': this._fieldNameToId(field),
|
||||
'customFields.value': {
|
||||
$not: {
|
||||
$in: [this._fieldValueToId(field, str), parseInt(str, 10)],
|
||||
},
|
||||
},
|
||||
};
|
||||
}
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
case '>':
|
||||
case 'gt':
|
||||
case 'Gt':
|
||||
case 'GT':
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
commands[i] = {
|
||||
'customFields._id': this._fieldNameToId(field),
|
||||
'customFields.value': {
|
||||
$gt: parseInt(str, 10),
|
||||
},
|
||||
};
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
case '>=':
|
||||
case '>==':
|
||||
case 'gte':
|
||||
case 'Gte':
|
||||
case 'GTE':
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
commands[i] = {
|
||||
'customFields._id': this._fieldNameToId(field),
|
||||
'customFields.value': {
|
||||
$gte: parseInt(str, 10),
|
||||
},
|
||||
};
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
case '<':
|
||||
case 'lt':
|
||||
case 'Lt':
|
||||
case 'LT':
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
commands[i] = {
|
||||
'customFields._id': this._fieldNameToId(field),
|
||||
'customFields.value': {
|
||||
$lt: parseInt(str, 10),
|
||||
},
|
||||
};
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
case '<=':
|
||||
case '<==':
|
||||
case 'lte':
|
||||
case 'Lte':
|
||||
case 'LTE':
|
||||
{
|
||||
const field = commands[i - 1].cmd;
|
||||
const str = commands[i + 1].cmd;
|
||||
commands[i] = {
|
||||
'customFields._id': this._fieldNameToId(field),
|
||||
'customFields.value': {
|
||||
$lte: parseInt(str, 10),
|
||||
},
|
||||
};
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_processLogicalOperators(commands) {
|
||||
for (let i = 0; i < commands.length; i++) {
|
||||
if (!commands[i].string && commands[i].cmd) {
|
||||
switch (commands[i].cmd) {
|
||||
case 'or':
|
||||
case 'Or':
|
||||
case 'OR':
|
||||
case '|':
|
||||
case '||':
|
||||
{
|
||||
const op1 = commands[i - 1];
|
||||
const op2 = commands[i + 1];
|
||||
commands[i] = {
|
||||
$or: [op1, op2],
|
||||
};
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
case 'and':
|
||||
case 'And':
|
||||
case 'AND':
|
||||
case '&':
|
||||
case '&&':
|
||||
{
|
||||
const op1 = commands[i - 1];
|
||||
const op2 = commands[i + 1];
|
||||
commands[i] = {
|
||||
$and: [op1, op2],
|
||||
};
|
||||
commands.splice(i - 1, 1);
|
||||
commands.splice(i, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
case 'not':
|
||||
case 'Not':
|
||||
case 'NOT':
|
||||
case '!':
|
||||
{
|
||||
const op1 = commands[i + 1];
|
||||
commands[i] = {
|
||||
$not: op1,
|
||||
};
|
||||
commands.splice(i + 1, 1);
|
||||
//changed = true;
|
||||
i--;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
_getMongoSelector() {
|
||||
this._dep.depend();
|
||||
const commands = this._filterToCommands();
|
||||
return this._arrayToSelector(commands);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// The global Filter object.
|
||||
// XXX It would be possible to re-write this object more elegantly, and removing
|
||||
// the need to provide a list of `_fields`. We also should move methods into the
|
||||
@@ -86,8 +465,10 @@ Filter = {
|
||||
// before changing the schema.
|
||||
labelIds: new SetFilter(),
|
||||
members: new SetFilter(),
|
||||
customFields: new SetFilter('_id'),
|
||||
advanced: new AdvancedFilter(),
|
||||
|
||||
_fields: ['labelIds', 'members'],
|
||||
_fields: ['labelIds', 'members', 'customFields'],
|
||||
|
||||
// We don't filter cards that have been added after the last filter change. To
|
||||
// implement this we keep the id of these cards in this `_exceptions` fields
|
||||
@@ -98,7 +479,7 @@ Filter = {
|
||||
isActive() {
|
||||
return _.any(this._fields, (fieldName) => {
|
||||
return this[fieldName]._isActive();
|
||||
});
|
||||
}) || this.advanced._isActive();
|
||||
},
|
||||
|
||||
_getMongoSelector() {
|
||||
@@ -111,7 +492,11 @@ Filter = {
|
||||
this._fields.forEach((fieldName) => {
|
||||
const filter = this[fieldName];
|
||||
if (filter._isActive()) {
|
||||
filterSelector[fieldName] = filter._getMongoSelector();
|
||||
if (filter.subField !== '') {
|
||||
filterSelector[`${fieldName}.${filter.subField}`] = filter._getMongoSelector();
|
||||
} else {
|
||||
filterSelector[fieldName] = filter._getMongoSelector();
|
||||
}
|
||||
emptySelector[fieldName] = filter._getEmptySelector();
|
||||
if (emptySelector[fieldName] !== null) {
|
||||
includeEmptySelectors = true;
|
||||
@@ -119,13 +504,24 @@ Filter = {
|
||||
}
|
||||
});
|
||||
|
||||
const exceptionsSelector = {_id: {$in: this._exceptions}};
|
||||
const exceptionsSelector = {
|
||||
_id: {
|
||||
$in: this._exceptions,
|
||||
},
|
||||
};
|
||||
this._exceptionsDep.depend();
|
||||
|
||||
if (includeEmptySelectors)
|
||||
return {$or: [filterSelector, exceptionsSelector, emptySelector]};
|
||||
else
|
||||
return {$or: [filterSelector, exceptionsSelector]};
|
||||
const selectors = [exceptionsSelector];
|
||||
|
||||
if (_.any(this._fields, (fieldName) => {
|
||||
return this[fieldName]._isActive();
|
||||
})) selectors.push(filterSelector);
|
||||
if (includeEmptySelectors) selectors.push(emptySelector);
|
||||
if (this.advanced._isActive()) selectors.push(this.advanced._getMongoSelector());
|
||||
|
||||
return {
|
||||
$or: selectors,
|
||||
};
|
||||
},
|
||||
|
||||
mongoSelector(additionalSelector) {
|
||||
@@ -133,7 +529,9 @@ Filter = {
|
||||
if (_.isUndefined(additionalSelector))
|
||||
return filterSelector;
|
||||
else
|
||||
return {$and: [filterSelector, additionalSelector]};
|
||||
return {
|
||||
$and: [filterSelector, additionalSelector],
|
||||
};
|
||||
},
|
||||
|
||||
reset() {
|
||||
@@ -141,6 +539,7 @@ Filter = {
|
||||
const filter = this[fieldName];
|
||||
filter.reset();
|
||||
});
|
||||
this.advanced.reset();
|
||||
this.resetExceptions();
|
||||
},
|
||||
|
||||
|
||||
@@ -75,6 +75,16 @@ InlinedForm = BlazeComponent.extendComponent({
|
||||
EscapeActions.register('inlinedForm',
|
||||
() => { currentlyOpenedForm.get().close(); },
|
||||
() => { return currentlyOpenedForm.get() !== null; }, {
|
||||
noClickEscapeOn: '.js-inlined-form',
|
||||
enabledOnClick: false,
|
||||
}
|
||||
);
|
||||
|
||||
// submit on click outside
|
||||
document.addEventListener('click', function(evt) {
|
||||
const openedForm = currentlyOpenedForm.get();
|
||||
const isClickOutside = $(evt.target).closest('.js-inlined-form').length === 0;
|
||||
if (openedForm && isClickOutside) {
|
||||
$('.js-inlined-form button[type=submit]').click();
|
||||
openedForm.close();
|
||||
}
|
||||
}, true);
|
||||
@@ -33,6 +33,37 @@ Utils = {
|
||||
return $(window).width() <= 800;
|
||||
},
|
||||
|
||||
calculateIndexData(prevData, nextData, nItems = 1) {
|
||||
let base, increment;
|
||||
// If we drop the card to an empty column
|
||||
if (!prevData && !nextData) {
|
||||
base = 0;
|
||||
increment = 1;
|
||||
// If we drop the card in the first position
|
||||
} else if (!prevData) {
|
||||
base = nextData.sort - 1;
|
||||
increment = -1;
|
||||
// If we drop the card in the last position
|
||||
} else if (!nextData) {
|
||||
base = prevData.sort + 1;
|
||||
increment = 1;
|
||||
}
|
||||
// In the general case take the average of the previous and next element
|
||||
// sort indexes.
|
||||
else {
|
||||
const prevSortIndex = prevData.sort;
|
||||
const nextSortIndex = nextData.sort;
|
||||
increment = (nextSortIndex - prevSortIndex) / (nItems + 1);
|
||||
base = prevSortIndex + increment;
|
||||
}
|
||||
// XXX Return a generator that yield values instead of a base with a
|
||||
// increment number.
|
||||
return {
|
||||
base,
|
||||
increment,
|
||||
};
|
||||
},
|
||||
|
||||
// Determine the new sort index
|
||||
calculateIndex(prevCardDomElement, nextCardDomElement, nCards = 1) {
|
||||
let base, increment;
|
||||
@@ -64,6 +95,100 @@ Utils = {
|
||||
increment,
|
||||
};
|
||||
},
|
||||
|
||||
// Detect touch device
|
||||
isTouchDevice() {
|
||||
const isTouchable = (() => {
|
||||
const prefixes = ' -webkit- -moz- -o- -ms- '.split(' ');
|
||||
const mq = function(query) {
|
||||
return window.matchMedia(query).matches;
|
||||
};
|
||||
|
||||
if (('ontouchstart' in window) || window.DocumentTouch && document instanceof window.DocumentTouch) {
|
||||
return true;
|
||||
}
|
||||
|
||||
// include the 'heartz' as a way to have a non matching MQ to help terminate the join
|
||||
// https://git.io/vznFH
|
||||
const query = ['(', prefixes.join('touch-enabled),('), 'heartz', ')'].join('');
|
||||
return mq(query);
|
||||
})();
|
||||
Utils.isTouchDevice = () => isTouchable;
|
||||
return isTouchable;
|
||||
},
|
||||
|
||||
calculateTouchDistance(touchA, touchB) {
|
||||
return Math.sqrt(
|
||||
Math.pow(touchA.screenX - touchB.screenX, 2) +
|
||||
Math.pow(touchA.screenY - touchB.screenY, 2)
|
||||
);
|
||||
},
|
||||
|
||||
enableClickOnTouch(selector) {
|
||||
let touchStart = null;
|
||||
let lastTouch = null;
|
||||
|
||||
$(document).on('touchstart', selector, function(e) {
|
||||
touchStart = e.originalEvent.touches[0];
|
||||
});
|
||||
$(document).on('touchmove', selector, function(e) {
|
||||
const touches = e.originalEvent.touches;
|
||||
lastTouch = touches[touches.length - 1];
|
||||
});
|
||||
$(document).on('touchend', selector, function(e) {
|
||||
if (touchStart && lastTouch && Utils.calculateTouchDistance(touchStart, lastTouch) <= 20) {
|
||||
e.preventDefault();
|
||||
const clickEvent = document.createEvent('MouseEvents');
|
||||
clickEvent.initEvent('click', true, true);
|
||||
e.target.dispatchEvent(clickEvent);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
setMatomo(data){
|
||||
window._paq = window._paq || [];
|
||||
window._paq.push(['setDoNotTrack', data.doNotTrack]);
|
||||
if (data.withUserName){
|
||||
window._paq.push(['setUserId', Meteor.user().username]);
|
||||
}
|
||||
window._paq.push(['trackPageView']);
|
||||
window._paq.push(['enableLinkTracking']);
|
||||
|
||||
(function() {
|
||||
window._paq.push(['setTrackerUrl', `${data.address}piwik.php`]);
|
||||
window._paq.push(['setSiteId', data.siteId]);
|
||||
|
||||
const script = document.createElement('script');
|
||||
Object.assign(script, {
|
||||
id: 'scriptMatomo',
|
||||
type: 'text/javascript',
|
||||
async: 'true',
|
||||
defer: 'true',
|
||||
src: `${data.address}piwik.js`,
|
||||
});
|
||||
|
||||
const s = document.getElementsByTagName('script')[0];
|
||||
s.parentNode.insertBefore(script, s);
|
||||
})();
|
||||
|
||||
Session.set('matomo', true);
|
||||
},
|
||||
|
||||
manageMatomo() {
|
||||
const matomo = Session.get('matomo');
|
||||
if (matomo === undefined){
|
||||
Meteor.call('getMatomoConf', (err, data) => {
|
||||
if (err && err.error[0] === 'var-not-exist'){
|
||||
Session.set('matomo', false); // siteId || address server not defined
|
||||
}
|
||||
if (!err){
|
||||
Utils.setMatomo(data);
|
||||
}
|
||||
});
|
||||
} else if (matomo) {
|
||||
window._paq.push(['trackPageView']);
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// A simple tracker dependency that we invalidate every time the window is
|
||||
|
||||
@@ -0,0 +1,4 @@
|
||||
module.exports.models = {
|
||||
connection: 'mongodb',
|
||||
migrate: 'safe',
|
||||
};
|
||||
@@ -14,6 +14,8 @@ FlowRouter.route('/', {
|
||||
Filter.reset();
|
||||
EscapeActions.executeAll();
|
||||
|
||||
Utils.manageMatomo();
|
||||
|
||||
BlazeLayout.render('defaultLayout', {
|
||||
headerBar: 'boardListHeaderBar',
|
||||
content: 'boardList',
|
||||
@@ -38,6 +40,8 @@ FlowRouter.route('/b/:id/:slug', {
|
||||
EscapeActions.executeUpTo('popup-close');
|
||||
}
|
||||
|
||||
Utils.manageMatomo();
|
||||
|
||||
BlazeLayout.render('defaultLayout', {
|
||||
headerBar: 'boardHeaderBar',
|
||||
content: 'board',
|
||||
@@ -53,6 +57,8 @@ FlowRouter.route('/b/:boardId/:slug/:cardId', {
|
||||
Session.set('currentBoard', params.boardId);
|
||||
Session.set('currentCard', params.cardId);
|
||||
|
||||
Utils.manageMatomo();
|
||||
|
||||
BlazeLayout.render('defaultLayout', {
|
||||
headerBar: 'boardHeaderBar',
|
||||
content: 'board',
|
||||
|
||||
+48
-3
@@ -3,7 +3,7 @@ version: '2'
|
||||
services:
|
||||
|
||||
wekandb:
|
||||
image: mongo:3.2.18
|
||||
image: mongo:3.2.20
|
||||
container_name: wekan-db
|
||||
restart: always
|
||||
command: mongod --smallfiles --oplogSize 128
|
||||
@@ -16,7 +16,7 @@ services:
|
||||
- wekan-db-dump:/dump
|
||||
|
||||
wekan:
|
||||
image: wekanteam/wekan:latest
|
||||
image: quay.io/wekan/wekan
|
||||
container_name: wekan-app
|
||||
restart: always
|
||||
networks:
|
||||
@@ -33,10 +33,55 @@ services:
|
||||
- METEOR_EDGE=${METEOR_EDGE}
|
||||
- USE_EDGE=${USE_EDGE}
|
||||
ports:
|
||||
- 80:80
|
||||
# Docker outsideport:insideport
|
||||
- 80:8080
|
||||
environment:
|
||||
- MONGO_URL=mongodb://wekandb:27017/wekan
|
||||
- ROOT_URL=http://localhost
|
||||
# Wekan Export Board works when WITH_API='true'.
|
||||
# If you disable Wekan API with 'false', Export Board does not work.
|
||||
- WITH_API=true
|
||||
# Optional: Integration with Matomo https://matomo.org that is installed to your server
|
||||
# The address of the server where Matomo is hosted.
|
||||
# example: - MATOMO_ADDRESS=https://example.com/matomo
|
||||
- MATOMO_ADDRESS=''
|
||||
# The value of the site ID given in Matomo server for Wekan
|
||||
# example: - MATOMO_SITE_ID=12345
|
||||
- MATOMO_SITE_ID=''
|
||||
# The option do not track which enables users to not be tracked by matomo
|
||||
# example: - MATOMO_DO_NOT_TRACK=false
|
||||
- MATOMO_DO_NOT_TRACK=true
|
||||
# The option that allows matomo to retrieve the username:
|
||||
# example: MATOMO_WITH_USERNAME=true
|
||||
- MATOMO_WITH_USERNAME=false
|
||||
# Enable browser policy and allow one trusted URL that can have iframe that has Wekan embedded inside.
|
||||
# Setting this to false is not recommended, it also disables all other browser policy protections
|
||||
# and allows all iframing etc. See wekan/server/policy.js
|
||||
- BROWSER_POLICY_ENABLED=true
|
||||
# When browser policy is enabled, HTML code at this Trusted URL can have iframe that embeds Wekan inside.
|
||||
- TRUSTED_URL=''
|
||||
# What to send to Outgoing Webhook, or leave out. Example, that includes all that are default: cardId,listId,oldListId,boardId,comment,user,card,commentId .
|
||||
# example: WEBHOOKS_ATTRIBUTES=cardId,listId,oldListId,boardId,comment,user,card,commentId
|
||||
- WEBHOOKS_ATTRIBUTES=''
|
||||
# OAuth2 docs: https://github.com/wekan/wekan/wiki/OAuth2
|
||||
# OAuth2 Client ID, for example from Rocket.Chat. Example: abcde12345
|
||||
# example: OAUTH2_CLIENT_ID=abcde12345
|
||||
- OAUTH2_CLIENT_ID=''
|
||||
# OAuth2 Secret, for example from Rocket.Chat: Example: 54321abcde
|
||||
# example: OAUTH2_SECRET=54321abcde
|
||||
- OAUTH2_SECRET=''
|
||||
# OAuth2 Server URL, for example Rocket.Chat. Example: https://chat.example.com
|
||||
# example: OAUTH2_SERVER_URL=https://chat.example.com
|
||||
- OAUTH2_SERVER_URL=''
|
||||
# OAuth2 Authorization Endpoint. Example: /oauth/authorize
|
||||
# example: OAUTH2_AUTH_ENDPOINT=/oauth/authorize
|
||||
- OAUTH2_AUTH_ENDPOINT=''
|
||||
# OAuth2 Userinfo Endpoint. Example: /oauth/userinfo
|
||||
# example: OAUTH2_USERINFO_ENDPOINT=/oauth/userinfo
|
||||
- OAUTH2_USERINFO_ENDPOINT=''
|
||||
# OAuth2 Token Endpoint. Example: /oauth/token
|
||||
# example: OAUTH2_TOKEN_ENDPOINT=/oauth/token
|
||||
- OAUTH2_TOKEN_ENDPOINT=''
|
||||
depends_on:
|
||||
- wekandb
|
||||
|
||||
|
||||
+106
-29
@@ -2,17 +2,19 @@
|
||||
"accept": "اقبلboard",
|
||||
"act-activity-notify": "[Wekan] اشعار عن نشاط",
|
||||
"act-addAttachment": "ربط __attachment__ الى __card__",
|
||||
"act-addSubtask": "added subtask __checklist__ to __card__",
|
||||
"act-addChecklist": "added checklist __checklist__ to __card__",
|
||||
"act-addChecklistItem": "added __checklistItem__ to checklist __checklist__ on __card__",
|
||||
"act-addComment": "علق على __comment__ : __card__",
|
||||
"act-createBoard": "احدث __board__",
|
||||
"act-createCard": "اضاف __card__ الى __list__",
|
||||
"act-createCustomField": "created custom field __customField__",
|
||||
"act-createList": "اضاف __list__ الى __board__",
|
||||
"act-addBoardMember": "اضاف __member__ الى __board__",
|
||||
"act-archivedBoard": "قام بأرشفة __board__",
|
||||
"act-archivedCard": "قام بأرشفة __card__",
|
||||
"act-archivedList": "قام بأرشفة __list__",
|
||||
"act-archivedSwimlane": "archived __swimlane__",
|
||||
"act-archivedBoard": "__board__ moved to Recycle Bin",
|
||||
"act-archivedCard": "__card__ moved to Recycle Bin",
|
||||
"act-archivedList": "__list__ moved to Recycle Bin",
|
||||
"act-archivedSwimlane": "__swimlane__ moved to Recycle Bin",
|
||||
"act-importBoard": "إستورد __board__",
|
||||
"act-importCard": "إستورد __card__",
|
||||
"act-importList": "إستورد __list__",
|
||||
@@ -27,9 +29,10 @@
|
||||
"activities": "الأنشطة",
|
||||
"activity": "النشاط",
|
||||
"activity-added": "تمت إضافة %s ل %s",
|
||||
"activity-archived": "إلى الأرشيف %s",
|
||||
"activity-archived": "%s moved to Recycle Bin",
|
||||
"activity-attached": "إرفاق %s ل %s",
|
||||
"activity-created": "أنشأ %s",
|
||||
"activity-customfield-created": "created custom field %s",
|
||||
"activity-excluded": "استبعاد %s عن %s",
|
||||
"activity-imported": "imported %s into %s from %s",
|
||||
"activity-imported-board": "imported %s from %s",
|
||||
@@ -39,6 +42,7 @@
|
||||
"activity-removed": "حذف %s إلى %s",
|
||||
"activity-sent": "إرسال %s إلى %s",
|
||||
"activity-unjoined": "غادر %s",
|
||||
"activity-subtask-added": "added subtask to %s",
|
||||
"activity-checklist-added": "أضاف قائمة تحقق إلى %s",
|
||||
"activity-checklist-item-added": "added checklist item to '%s' in %s",
|
||||
"add": "أضف",
|
||||
@@ -46,6 +50,7 @@
|
||||
"add-board": "إضافة لوحة",
|
||||
"add-card": "إضافة بطاقة",
|
||||
"add-swimlane": "Add Swimlane",
|
||||
"add-subtask": "Add Subtask",
|
||||
"add-checklist": "إضافة قائمة تدقيق",
|
||||
"add-checklist-item": "إضافة عنصر إلى قائمة التحقق",
|
||||
"add-cover": "إضافة غلاف",
|
||||
@@ -64,19 +69,19 @@
|
||||
"and-n-other-card_plural": "And __count__ other بطاقات",
|
||||
"apply": "طبق",
|
||||
"app-is-offline": "يتمّ تحميل ويكان، يرجى الانتظار. سيؤدي تحديث الصفحة إلى فقدان البيانات. إذا لم يتم تحميل ويكان، يرجى التحقق من أن خادم ويكان لم يتوقف. ",
|
||||
"archive": "أرشيف",
|
||||
"archive-all": "أرشيف الكل",
|
||||
"archive-board": "أرشيف اللوحة",
|
||||
"archive-card": "أرشيف البطاقة",
|
||||
"archive-list": "قائمة الأرشيفات",
|
||||
"archive-swimlane": "Archive Swimlane",
|
||||
"archive-selection": "أرشف المُحدّد",
|
||||
"archiveBoardPopup-title": "أرشيف اللوحة ؟",
|
||||
"archived-items": "عناصر مؤرشفة",
|
||||
"archived-boards": "لوحات مؤرشفة",
|
||||
"archive": "Move to Recycle Bin",
|
||||
"archive-all": "Move All to Recycle Bin",
|
||||
"archive-board": "Move Board to Recycle Bin",
|
||||
"archive-card": "Move Card to Recycle Bin",
|
||||
"archive-list": "Move List to Recycle Bin",
|
||||
"archive-swimlane": "Move Swimlane to Recycle Bin",
|
||||
"archive-selection": "Move selection to Recycle Bin",
|
||||
"archiveBoardPopup-title": "Move Board to Recycle Bin?",
|
||||
"archived-items": "Recycle Bin",
|
||||
"archived-boards": "Boards in Recycle Bin",
|
||||
"restore-board": "استعادة اللوحة",
|
||||
"no-archived-boards": "لا توجد لوحات مؤرشفة.",
|
||||
"archives": "أرشيفات",
|
||||
"no-archived-boards": "No Boards in Recycle Bin.",
|
||||
"archives": "Recycle Bin",
|
||||
"assign-member": "تعيين عضو",
|
||||
"attached": "أُرفق)",
|
||||
"attachment": "مرفق",
|
||||
@@ -98,19 +103,22 @@
|
||||
"boardMenuPopup-title": "قائمة اللوحة",
|
||||
"boards": "لوحات",
|
||||
"board-view": "Board View",
|
||||
"board-view-cal": "Calendar",
|
||||
"board-view-swimlanes": "Swimlanes",
|
||||
"board-view-lists": "القائمات",
|
||||
"bucket-example": "مثل « todo list » على سبيل المثال",
|
||||
"cancel": "إلغاء",
|
||||
"card-archived": "هذه البطاقة أُرشفت.",
|
||||
"card-archived": "This card is moved to Recycle Bin.",
|
||||
"board-archived": "This board is moved to Recycle Bin.",
|
||||
"card-comments-title": "%s تعليقات لهذه البطاقة",
|
||||
"card-delete-notice": "هذا حذف أبديّ . سوف تفقد كل الإجراءات المنوطة بهذه البطاقة",
|
||||
"card-delete-pop": "سيتم إزالة جميع الإجراءات من تبعات النشاط، وأنك لن تكون قادرا على إعادة فتح البطاقة. لا يوجد التراجع.",
|
||||
"card-delete-suggest-archive": "يمكنك أرشفة بطاقة لحذفها من اللوحة والمحافظة على النشاط.",
|
||||
"card-delete-suggest-archive": "You can move a card to Recycle Bin to remove it from the board and preserve the activity.",
|
||||
"card-due": "مستحق",
|
||||
"card-due-on": "مستحق في",
|
||||
"card-spent": "Spent Time",
|
||||
"card-edit-attachments": "تعديل المرفقات",
|
||||
"card-edit-custom-fields": "Edit custom fields",
|
||||
"card-edit-labels": "تعديل العلامات",
|
||||
"card-edit-members": "تعديل الأعضاء",
|
||||
"card-labels-title": "تعديل علامات البطاقة.",
|
||||
@@ -118,12 +126,19 @@
|
||||
"card-start": "بداية",
|
||||
"card-start-on": "يبدأ في",
|
||||
"cardAttachmentsPopup-title": "إرفاق من",
|
||||
"cardCustomField-datePopup-title": "Change date",
|
||||
"cardCustomFieldsPopup-title": "Edit custom fields",
|
||||
"cardDeletePopup-title": "حذف البطاقة ?",
|
||||
"cardDetailsActionsPopup-title": "إجراءات على البطاقة",
|
||||
"cardLabelsPopup-title": "علامات",
|
||||
"cardMembersPopup-title": "أعضاء",
|
||||
"cardMorePopup-title": "المزيد",
|
||||
"cards": "بطاقات",
|
||||
"cards-count": "بطاقات",
|
||||
"casSignIn": "Sign In with CAS",
|
||||
"cardType-card": "Card",
|
||||
"cardType-linkedCard": "Linked Card",
|
||||
"cardType-linkedBoard": "Linked Board",
|
||||
"change": "Change",
|
||||
"change-avatar": "تعديل الصورة الشخصية",
|
||||
"change-password": "تغيير كلمة المرور",
|
||||
@@ -134,13 +149,14 @@
|
||||
"changePasswordPopup-title": "تغيير كلمة المرور",
|
||||
"changePermissionsPopup-title": "تعديل الصلاحيات",
|
||||
"changeSettingsPopup-title": "تغيير الاعدادات",
|
||||
"subtasks": "Subtasks",
|
||||
"checklists": "قوائم التّدقيق",
|
||||
"click-to-star": "اضغط لإضافة اللوحة للمفضلة.",
|
||||
"click-to-unstar": "اضغط لحذف اللوحة من المفضلة.",
|
||||
"clipboard": "Clipboard or drag & drop",
|
||||
"close": "غلق",
|
||||
"close-board": "غلق اللوحة",
|
||||
"close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
|
||||
"close-board-pop": "You will be able to restore the board by clicking the “Recycle Bin” button from the home header.",
|
||||
"color-black": "black",
|
||||
"color-blue": "blue",
|
||||
"color-green": "green",
|
||||
@@ -155,19 +171,41 @@
|
||||
"comment-placeholder": "أكتب تعليق",
|
||||
"comment-only": "التعليق فقط",
|
||||
"comment-only-desc": "يمكن التعليق على بطاقات فقط.",
|
||||
"no-comments": "No comments",
|
||||
"no-comments-desc": "Can not see comments and activities.",
|
||||
"computer": "حاسوب",
|
||||
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist",
|
||||
"confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?",
|
||||
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?",
|
||||
"copy-card-link-to-clipboard": "نسخ رابط البطاقة إلى الحافظة",
|
||||
"linkCardPopup-title": "Link Card",
|
||||
"searchCardPopup-title": "Search Card",
|
||||
"copyCardPopup-title": "نسخ البطاقة",
|
||||
"copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards",
|
||||
"copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format",
|
||||
"copyChecklistToManyCardsPopup-format": "[ {\"title\": \"First card title\", \"description\":\"First card description\"}, {\"title\":\"Second card title\",\"description\":\"Second card description\"},{\"title\":\"Last card title\",\"description\":\"Last card description\"} ]",
|
||||
"create": "إنشاء",
|
||||
"createBoardPopup-title": "إنشاء لوحة",
|
||||
"chooseBoardSourcePopup-title": "استيراد لوحة",
|
||||
"createLabelPopup-title": "إنشاء علامة",
|
||||
"createCustomField": "Create Field",
|
||||
"createCustomFieldPopup-title": "Create Field",
|
||||
"current": "الحالي",
|
||||
"custom-field-delete-pop": "There is no undo. This will remove this custom field from all cards and destroy its history.",
|
||||
"custom-field-checkbox": "Checkbox",
|
||||
"custom-field-date": "تاريخ",
|
||||
"custom-field-dropdown": "Dropdown List",
|
||||
"custom-field-dropdown-none": "(none)",
|
||||
"custom-field-dropdown-options": "List Options",
|
||||
"custom-field-dropdown-options-placeholder": "Press enter to add more options",
|
||||
"custom-field-dropdown-unknown": "(unknown)",
|
||||
"custom-field-number": "Number",
|
||||
"custom-field-text": "Text",
|
||||
"custom-fields": "Custom Fields",
|
||||
"date": "تاريخ",
|
||||
"decline": "Decline",
|
||||
"default-avatar": "صورة شخصية افتراضية",
|
||||
"delete": "حذف",
|
||||
"deleteCustomFieldPopup-title": "Delete Custom Field?",
|
||||
"deleteLabelPopup-title": "حذف العلامة ?",
|
||||
"description": "وصف",
|
||||
"disambiguateMultiLabelPopup-title": "تحديد الإجراء على العلامة",
|
||||
@@ -182,6 +220,7 @@
|
||||
"soft-wip-limit": "Soft WIP Limit",
|
||||
"editCardStartDatePopup-title": "تغيير تاريخ البدء",
|
||||
"editCardDueDatePopup-title": "تغيير تاريخ الاستحقاق",
|
||||
"editCustomFieldPopup-title": "Edit Field",
|
||||
"editCardSpentTimePopup-title": "Change spent time",
|
||||
"editLabelPopup-title": "تعديل العلامة",
|
||||
"editNotificationPopup-title": "تصحيح الإشعار",
|
||||
@@ -218,15 +257,19 @@
|
||||
"filter-clear": "مسح التصفية",
|
||||
"filter-no-label": "لا يوجد ملصق",
|
||||
"filter-no-member": "ليس هناك أي عضو",
|
||||
"filter-no-custom-fields": "No Custom Fields",
|
||||
"filter-on": "التصفية تشتغل",
|
||||
"filter-on-desc": "أنت بصدد تصفية بطاقات هذه اللوحة. اضغط هنا لتعديل التصفية.",
|
||||
"filter-to-selection": "تصفية بالتحديد",
|
||||
"advanced-filter-label": "Advanced Filter",
|
||||
"advanced-filter-description": "Advanced Filter allows to write a string containing following operators: == != <= >= && || ( ) A space is used as a separator between the Operators. You can filter for all Custom Fields by typing their names and values. For Example: Field1 == Value1. Note: If fields or values contains spaces, you need to encapsulate them into single quotes. For Example: 'Field 1' == 'Value 1'. For single control characters (' \\/) to be skipped, you can use \\. For example: Field1 == I\\'m. Also you can combine multiple conditions. For Example: F1 == V1 || F1 == V2. Normally all operators are interpreted from left to right. You can change the order by placing brackets. For Example: F1 == V1 && ( F2 == V2 || F2 == V3 ). Also you can search text fields using regex: F1 == /Tes.*/i",
|
||||
"fullname": "الإسم الكامل",
|
||||
"header-logo-title": "الرجوع إلى صفحة اللوحات",
|
||||
"hide-system-messages": "إخفاء رسائل النظام",
|
||||
"headerBarCreateBoardPopup-title": "إنشاء لوحة",
|
||||
"home": "الرئيسية",
|
||||
"import": "Import",
|
||||
"link": "Link",
|
||||
"import-board": "استيراد لوحة",
|
||||
"import-board-c": "استيراد لوحة",
|
||||
"import-board-title-trello": "Import board from Trello",
|
||||
@@ -260,8 +303,8 @@
|
||||
"leave-board-pop": "Are you sure you want to leave __boardTitle__? You will be removed from all cards on this board.",
|
||||
"leaveBoardPopup-title": "مغادرة اللوحة ؟",
|
||||
"link-card": "ربط هذه البطاقة",
|
||||
"list-archive-cards": "أرضفت بطاقات هذه القائمة",
|
||||
"list-archive-cards-pop": "سيقتضي هذا أرشفة جميع بطاقات هذه القائمة. لمشاهدة أرشيف البطاقات أو إعادتها إلى اللوحة، اضغط على -القائمة- ثم - أرشيف العناصر-",
|
||||
"list-archive-cards": "Move all cards in this list to Recycle Bin",
|
||||
"list-archive-cards-pop": "This will remove all the cards in this list from the board. To view cards in Recycle Bin and bring them back to the board, click “Menu” > “Recycle Bin”.",
|
||||
"list-move-cards": "نقل بطاقات هذه القائمة",
|
||||
"list-select-cards": "تحديد بطاقات هذه القائمة",
|
||||
"listActionPopup-title": "قائمة الإجراءات",
|
||||
@@ -270,7 +313,7 @@
|
||||
"listMorePopup-title": "المزيد",
|
||||
"link-list": "رابط إلى هذه القائمة",
|
||||
"list-delete-pop": "All actions will be removed from the activity feed and you won't be able to recover the list. There is no undo.",
|
||||
"list-delete-suggest-archive": "يمكنك أرشفة قائمة لحذفها من اللوحة والمحافظة على النشاط.",
|
||||
"list-delete-suggest-archive": "You can move a list to Recycle Bin to remove it from the board and preserve the activity.",
|
||||
"lists": "القائمات",
|
||||
"swimlanes": "Swimlanes",
|
||||
"log-out": "تسجيل الخروج",
|
||||
@@ -290,9 +333,9 @@
|
||||
"muted-info": "You will never be notified of any changes in this board",
|
||||
"my-boards": "لوحاتي",
|
||||
"name": "اسم",
|
||||
"no-archived-cards": "لا توجد بطاقات مؤرشفة.",
|
||||
"no-archived-lists": "لا توجد قوائم مؤرشفة.",
|
||||
"no-archived-swimlanes": "No archived swimlanes.",
|
||||
"no-archived-cards": "No cards in Recycle Bin.",
|
||||
"no-archived-lists": "No lists in Recycle Bin.",
|
||||
"no-archived-swimlanes": "No swimlanes in Recycle Bin.",
|
||||
"no-results": "لا توجد نتائج",
|
||||
"normal": "عادي",
|
||||
"normal-desc": "يمكن مشاهدة و تعديل البطاقات. لا يمكن تغيير إعدادات الضبط.",
|
||||
@@ -328,6 +371,8 @@
|
||||
"restore": "استعادة",
|
||||
"save": "حفظ",
|
||||
"search": "بحث",
|
||||
"search-cards": "Search from card titles and descriptions on this board",
|
||||
"search-example": "Text to search for?",
|
||||
"select-color": "اختيار اللون",
|
||||
"set-wip-limit-value": "Set a limit for the maximum number of tasks in this list",
|
||||
"setWipLimitPopup-title": "Set WIP Limit",
|
||||
@@ -360,6 +405,7 @@
|
||||
"title": "عنوان",
|
||||
"tracking": "تتبع",
|
||||
"tracking-info": "You will be notified of any changes to those cards you are involved as creator or member.",
|
||||
"type": "Type",
|
||||
"unassign-member": "إلغاء تعيين العضو",
|
||||
"unsaved-description": "لديك وصف غير محفوظ",
|
||||
"unwatch": "غير مُشاهد",
|
||||
@@ -368,7 +414,7 @@
|
||||
"uploaded-avatar": "تم رفع الصورة الشخصية",
|
||||
"username": "اسم المستخدم",
|
||||
"view-it": "شاهدها",
|
||||
"warn-list-archived": "انتبه : هذه البطاقة في أرشيف القائمات",
|
||||
"warn-list-archived": "warning: this card is in an list at Recycle Bin",
|
||||
"watch": "مُشاهد",
|
||||
"watching": "مشاهدة",
|
||||
"watching-info": "You will be notified of any change in this board",
|
||||
@@ -424,11 +470,42 @@
|
||||
"hours": "الساعات",
|
||||
"minutes": "الدقائق",
|
||||
"seconds": "الثواني",
|
||||
"show-field-on-card": "Show this field on card",
|
||||
"yes": "نعم",
|
||||
"no": "لا",
|
||||
"accounts": "الحسابات",
|
||||
"accounts-allowEmailChange": "السماح بتغيير البريد الإلكتروني",
|
||||
"accounts-allowUserNameChange": "Allow Username Change",
|
||||
"createdAt": "Created at",
|
||||
"verified": "Verified",
|
||||
"active": "Active"
|
||||
"active": "Active",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
"card-end-on": "Ends on",
|
||||
"editCardReceivedDatePopup-title": "Change received date",
|
||||
"editCardEndDatePopup-title": "Change end date",
|
||||
"assigned-by": "Assigned By",
|
||||
"requested-by": "Requested By",
|
||||
"board-delete-notice": "Deleting is permanent. You will lose all lists, cards and actions associated with this board.",
|
||||
"delete-board-confirm-popup": "All lists, cards, labels, and activities will be deleted and you won't be able to recover the board contents. There is no undo.",
|
||||
"boardDeletePopup-title": "Delete Board?",
|
||||
"delete-board": "Delete Board",
|
||||
"default-subtasks-board": "Subtasks for __board__ board",
|
||||
"default": "Default",
|
||||
"queue": "Queue",
|
||||
"subtask-settings": "Subtasks Settings",
|
||||
"boardSubtaskSettingsPopup-title": "Board Subtasks Settings",
|
||||
"show-subtasks-field": "Cards can have subtasks",
|
||||
"deposit-subtasks-board": "Deposit subtasks to this board:",
|
||||
"deposit-subtasks-list": "Landing list for subtasks deposited here:",
|
||||
"show-parent-in-minicard": "Show parent in minicard:",
|
||||
"prefix-with-full-path": "Prefix with full path",
|
||||
"prefix-with-parent": "Prefix with parent",
|
||||
"subtext-with-full-path": "Subtext with full path",
|
||||
"subtext-with-parent": "Subtext with parent",
|
||||
"change-card-parent": "Change card's parent",
|
||||
"parent-card": "Parent card",
|
||||
"source-board": "Source board",
|
||||
"no-parent": "Don't show parent"
|
||||
}
|
||||
@@ -0,0 +1,511 @@
|
||||
{
|
||||
"accept": "Accept",
|
||||
"act-activity-notify": "[Wekan] Известия за дейности",
|
||||
"act-addAttachment": "прикачи __attachment__ към __card__",
|
||||
"act-addSubtask": "added subtask __checklist__ to __card__",
|
||||
"act-addChecklist": "добави списък със задачи __checklist__ към __card__",
|
||||
"act-addChecklistItem": "добави __checklistItem__ към списък със задачи __checklist__ в __card__",
|
||||
"act-addComment": "Коментира в __card__: __comment__",
|
||||
"act-createBoard": "създаде __board__",
|
||||
"act-createCard": "добави __card__ към __list__",
|
||||
"act-createCustomField": "създаде собствено поле __customField__",
|
||||
"act-createList": "добави __list__ към __board__",
|
||||
"act-addBoardMember": "добави __member__ към __board__",
|
||||
"act-archivedBoard": "__board__ беше преместен в Кошчето",
|
||||
"act-archivedCard": "__card__ беше преместена в Кошчето",
|
||||
"act-archivedList": "__list__ беше преместен в Кошчето",
|
||||
"act-archivedSwimlane": "__swimlane__ беше преместен в Кошчето",
|
||||
"act-importBoard": "импортира __board__",
|
||||
"act-importCard": "импортира __card__",
|
||||
"act-importList": "импортира __list__",
|
||||
"act-joinMember": "добави __member__ към __card__",
|
||||
"act-moveCard": "премести __card__ от __oldList__ в __list__",
|
||||
"act-removeBoardMember": "премахна __member__ от __board__",
|
||||
"act-restoredCard": "възстанови __card__ в __board__",
|
||||
"act-unjoinMember": "премахна __member__ от __card__",
|
||||
"act-withBoardTitle": "[Wekan] __board__",
|
||||
"act-withCardTitle": "[__board__] __card__",
|
||||
"actions": "Actions",
|
||||
"activities": "Действия",
|
||||
"activity": "Дейности",
|
||||
"activity-added": "добави %s към %s",
|
||||
"activity-archived": "премести %s в Кошчето",
|
||||
"activity-attached": "прикачи %s към %s",
|
||||
"activity-created": "създаде %s",
|
||||
"activity-customfield-created": "създаде собствено поле %s",
|
||||
"activity-excluded": "изключи %s от %s",
|
||||
"activity-imported": "импортира %s в/във %s от %s",
|
||||
"activity-imported-board": "импортира %s от %s",
|
||||
"activity-joined": "се присъедини към %s",
|
||||
"activity-moved": "премести %s от %s в/във %s",
|
||||
"activity-on": "на %s",
|
||||
"activity-removed": "премахна %s от %s",
|
||||
"activity-sent": "изпрати %s до %s",
|
||||
"activity-unjoined": "вече не е част от %s",
|
||||
"activity-subtask-added": "added subtask to %s",
|
||||
"activity-checklist-added": "добави списък със задачи към %s",
|
||||
"activity-checklist-item-added": "добави точка към '%s' в/във %s",
|
||||
"add": "Добави",
|
||||
"add-attachment": "Добави прикачен файл",
|
||||
"add-board": "Добави Табло",
|
||||
"add-card": "Добави карта",
|
||||
"add-swimlane": "Добави коридор",
|
||||
"add-subtask": "Add Subtask",
|
||||
"add-checklist": "Добави списък със задачи",
|
||||
"add-checklist-item": "Добави точка към списъка със задачи",
|
||||
"add-cover": "Добави корица",
|
||||
"add-label": "Добави етикет",
|
||||
"add-list": "Добави списък",
|
||||
"add-members": "Добави членове",
|
||||
"added": "Добавено",
|
||||
"addMemberPopup-title": "Членове",
|
||||
"admin": "Администратор",
|
||||
"admin-desc": "Can view and edit cards, remove members, and change settings for the board.",
|
||||
"admin-announcement": "Съобщение",
|
||||
"admin-announcement-active": "Active System-Wide Announcement",
|
||||
"admin-announcement-title": "Съобщение от администратора",
|
||||
"all-boards": "Всички табла",
|
||||
"and-n-other-card": "И __count__ друга карта",
|
||||
"and-n-other-card_plural": "И __count__ други карти",
|
||||
"apply": "Приложи",
|
||||
"app-is-offline": "Wekan зарежда, моля изчакайте! Презареждането на страницата може да доведе до загуба на данни. Ако Wekan не се зареди, моля проверете дали сървъра му работи.",
|
||||
"archive": "Премести в Кошчето",
|
||||
"archive-all": "Премести всички в Кошчето",
|
||||
"archive-board": "Премести Таблото в Кошчето",
|
||||
"archive-card": "Премести Картата в Кошчето",
|
||||
"archive-list": "Премести Списъка в Кошчето",
|
||||
"archive-swimlane": "Премести Коридора в Кошчето",
|
||||
"archive-selection": "Премести избраните в Кошчето",
|
||||
"archiveBoardPopup-title": "Сигурни ли сте, че искате да преместите Таблото в Кошчето?",
|
||||
"archived-items": "Кошче",
|
||||
"archived-boards": "Табла в Кошчето",
|
||||
"restore-board": "Възстанови Таблото",
|
||||
"no-archived-boards": "Няма Табла в Кошчето.",
|
||||
"archives": "Кошче",
|
||||
"assign-member": "Възложи на член от екипа",
|
||||
"attached": "прикачен",
|
||||
"attachment": "Прикаченн файл",
|
||||
"attachment-delete-pop": "Изтриването на прикачен файл е завинаги. Няма как да бъде възстановен.",
|
||||
"attachmentDeletePopup-title": "Желаете ли да изтриете прикачения файл?",
|
||||
"attachments": "Прикачени файлове",
|
||||
"auto-watch": "Автоматично наблюдаване на таблата, когато са създадени",
|
||||
"avatar-too-big": "Аватарът е прекалено голям (максимум 70KB)",
|
||||
"back": "Назад",
|
||||
"board-change-color": "Промени цвета",
|
||||
"board-nb-stars": "%s звезди",
|
||||
"board-not-found": "Таблото не е намерено",
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
"board-public-info": "This board will be <strong>public</strong>.",
|
||||
"boardChangeColorPopup-title": "Change Board Background",
|
||||
"boardChangeTitlePopup-title": "Промени името на Таблото",
|
||||
"boardChangeVisibilityPopup-title": "Change Visibility",
|
||||
"boardChangeWatchPopup-title": "Промени наблюдаването",
|
||||
"boardMenuPopup-title": "Меню на Таблото",
|
||||
"boards": "Табла",
|
||||
"board-view": "Board View",
|
||||
"board-view-cal": "Calendar",
|
||||
"board-view-swimlanes": "Коридори",
|
||||
"board-view-lists": "Списъци",
|
||||
"bucket-example": "Like “Bucket List” for example",
|
||||
"cancel": "Cancel",
|
||||
"card-archived": "Картата е преместена в Кошчето.",
|
||||
"board-archived": "This board is moved to Recycle Bin.",
|
||||
"card-comments-title": "Тази карта има %s коментар.",
|
||||
"card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.",
|
||||
"card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.",
|
||||
"card-delete-suggest-archive": "You can move a card to Recycle Bin to remove it from the board and preserve the activity.",
|
||||
"card-due": "Готова за",
|
||||
"card-due-on": "Готова за",
|
||||
"card-spent": "Изработено време",
|
||||
"card-edit-attachments": "Промени прикачените файлове",
|
||||
"card-edit-custom-fields": "Промени собствените полета",
|
||||
"card-edit-labels": "Промени етикетите",
|
||||
"card-edit-members": "Промени членовете",
|
||||
"card-labels-title": "Промени етикетите за картата.",
|
||||
"card-members-title": "Добави или премахни членове на Таблото от тази карта.",
|
||||
"card-start": "Начало",
|
||||
"card-start-on": "Започва на",
|
||||
"cardAttachmentsPopup-title": "Прикачи от",
|
||||
"cardCustomField-datePopup-title": "Промени датата",
|
||||
"cardCustomFieldsPopup-title": "Промени собствените полета",
|
||||
"cardDeletePopup-title": "Желаете да изтриете картата?",
|
||||
"cardDetailsActionsPopup-title": "Опции",
|
||||
"cardLabelsPopup-title": "Етикети",
|
||||
"cardMembersPopup-title": "Членове",
|
||||
"cardMorePopup-title": "Още",
|
||||
"cards": "Карти",
|
||||
"cards-count": "Карти",
|
||||
"casSignIn": "Sign In with CAS",
|
||||
"cardType-card": "Card",
|
||||
"cardType-linkedCard": "Linked Card",
|
||||
"cardType-linkedBoard": "Linked Board",
|
||||
"change": "Промени",
|
||||
"change-avatar": "Промени аватара",
|
||||
"change-password": "Промени паролата",
|
||||
"change-permissions": "Change permissions",
|
||||
"change-settings": "Промени настройките",
|
||||
"changeAvatarPopup-title": "Промени аватара",
|
||||
"changeLanguagePopup-title": "Промени езика",
|
||||
"changePasswordPopup-title": "Промени паролата",
|
||||
"changePermissionsPopup-title": "Change Permissions",
|
||||
"changeSettingsPopup-title": "Промяна на настройките",
|
||||
"subtasks": "Subtasks",
|
||||
"checklists": "Списъци със задачи",
|
||||
"click-to-star": "Click to star this board.",
|
||||
"click-to-unstar": "Натиснете, за да премахнете това табло от любими.",
|
||||
"clipboard": "Клипборда или с драг & дроп",
|
||||
"close": "Затвори",
|
||||
"close-board": "Затвори Таблото",
|
||||
"close-board-pop": "You will be able to restore the board by clicking the “Recycle Bin” button from the home header.",
|
||||
"color-black": "черно",
|
||||
"color-blue": "синьо",
|
||||
"color-green": "зелено",
|
||||
"color-lime": "лайм",
|
||||
"color-orange": "оранжево",
|
||||
"color-pink": "розово",
|
||||
"color-purple": "пурпурно",
|
||||
"color-red": "червено",
|
||||
"color-sky": "светло синьо",
|
||||
"color-yellow": "жълто",
|
||||
"comment": "Коментирай",
|
||||
"comment-placeholder": "Напиши коментар",
|
||||
"comment-only": "Само коментар",
|
||||
"comment-only-desc": "Може да коментира само в карти.",
|
||||
"no-comments": "No comments",
|
||||
"no-comments-desc": "Can not see comments and activities.",
|
||||
"computer": "Компютър",
|
||||
"confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?",
|
||||
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?",
|
||||
"copy-card-link-to-clipboard": "Копирай връзката на картата в клипборда",
|
||||
"linkCardPopup-title": "Link Card",
|
||||
"searchCardPopup-title": "Search Card",
|
||||
"copyCardPopup-title": "Копирай картата",
|
||||
"copyChecklistToManyCardsPopup-title": "Копирай чеклисти в други карти",
|
||||
"copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format",
|
||||
"copyChecklistToManyCardsPopup-format": "[ {\"title\": \"First card title\", \"description\":\"First card description\"}, {\"title\":\"Second card title\",\"description\":\"Second card description\"},{\"title\":\"Last card title\",\"description\":\"Last card description\"} ]",
|
||||
"create": "Create",
|
||||
"createBoardPopup-title": "Create Board",
|
||||
"chooseBoardSourcePopup-title": "Import board",
|
||||
"createLabelPopup-title": "Create Label",
|
||||
"createCustomField": "Create Field",
|
||||
"createCustomFieldPopup-title": "Create Field",
|
||||
"current": "current",
|
||||
"custom-field-delete-pop": "There is no undo. This will remove this custom field from all cards and destroy its history.",
|
||||
"custom-field-checkbox": "Чекбокс",
|
||||
"custom-field-date": "Дата",
|
||||
"custom-field-dropdown": "Падащо меню",
|
||||
"custom-field-dropdown-none": "(none)",
|
||||
"custom-field-dropdown-options": "List Options",
|
||||
"custom-field-dropdown-options-placeholder": "Press enter to add more options",
|
||||
"custom-field-dropdown-unknown": "(unknown)",
|
||||
"custom-field-number": "Номер",
|
||||
"custom-field-text": "Текст",
|
||||
"custom-fields": "Собствени полета",
|
||||
"date": "Дата",
|
||||
"decline": "Отказ",
|
||||
"default-avatar": "Основен аватар",
|
||||
"delete": "Изтрий",
|
||||
"deleteCustomFieldPopup-title": "Изтриване на Собственото поле?",
|
||||
"deleteLabelPopup-title": "Желаете да изтриете етикета?",
|
||||
"description": "Описание",
|
||||
"disambiguateMultiLabelPopup-title": "Disambiguate Label Action",
|
||||
"disambiguateMultiMemberPopup-title": "Disambiguate Member Action",
|
||||
"discard": "Отказ",
|
||||
"done": "Готово",
|
||||
"download": "Сваляне",
|
||||
"edit": "Промени",
|
||||
"edit-avatar": "Промени аватара",
|
||||
"edit-profile": "Промяна на профила",
|
||||
"edit-wip-limit": "Промени WIP лимита",
|
||||
"soft-wip-limit": "\"Мек\" WIP лимит",
|
||||
"editCardStartDatePopup-title": "Промени началната дата",
|
||||
"editCardDueDatePopup-title": "Промени датата за готовност",
|
||||
"editCustomFieldPopup-title": "Промени Полето",
|
||||
"editCardSpentTimePopup-title": "Промени изработеното време",
|
||||
"editLabelPopup-title": "Промяна на Етикета",
|
||||
"editNotificationPopup-title": "Промени известията",
|
||||
"editProfilePopup-title": "Промяна на профила",
|
||||
"email": "Имейл",
|
||||
"email-enrollAccount-subject": "Ваш профил беше създаден на __siteName__",
|
||||
"email-enrollAccount-text": "Hello __user__,\n\nTo start using the service, simply click the link below.\n\n__url__\n\nThanks.",
|
||||
"email-fail": "Неуспешно изпращане на имейла",
|
||||
"email-fail-text": "Възникна грешка при изпращането на имейла",
|
||||
"email-invalid": "Невалиден имейл",
|
||||
"email-invite": "Покани чрез имейл",
|
||||
"email-invite-subject": "__inviter__ sent you an invitation",
|
||||
"email-invite-text": "Dear __user__,\n\n__inviter__ invites you to join board \"__board__\" for collaborations.\n\nPlease follow the link below:\n\n__url__\n\nThanks.",
|
||||
"email-resetPassword-subject": "Reset your password on __siteName__",
|
||||
"email-resetPassword-text": "Hello __user__,\n\nTo reset your password, simply click the link below.\n\n__url__\n\nThanks.",
|
||||
"email-sent": "Имейлът е изпратен",
|
||||
"email-verifyEmail-subject": "Verify your email address on __siteName__",
|
||||
"email-verifyEmail-text": "Hello __user__,\n\nTo verify your account email, simply click the link below.\n\n__url__\n\nThanks.",
|
||||
"enable-wip-limit": "Включи WIP лимита",
|
||||
"error-board-doesNotExist": "This board does not exist",
|
||||
"error-board-notAdmin": "You need to be admin of this board to do that",
|
||||
"error-board-notAMember": "You need to be a member of this board to do that",
|
||||
"error-json-malformed": "Your text is not valid JSON",
|
||||
"error-json-schema": "Your JSON data does not include the proper information in the correct format",
|
||||
"error-list-doesNotExist": "This list does not exist",
|
||||
"error-user-doesNotExist": "This user does not exist",
|
||||
"error-user-notAllowSelf": "You can not invite yourself",
|
||||
"error-user-notCreated": "This user is not created",
|
||||
"error-username-taken": "This username is already taken",
|
||||
"error-email-taken": "Имейлът е вече зает",
|
||||
"export-board": "Export board",
|
||||
"filter": "Филтър",
|
||||
"filter-cards": "Филтрирай картите",
|
||||
"filter-clear": "Премахване на филтрите",
|
||||
"filter-no-label": "без етикет",
|
||||
"filter-no-member": "без член",
|
||||
"filter-no-custom-fields": "Няма Собствени полета",
|
||||
"filter-on": "Има приложени филтри",
|
||||
"filter-on-desc": "В момента филтрирате картите в това табло. Моля, натиснете тук, за да промените филтъра.",
|
||||
"filter-to-selection": "Филтрирай избраните",
|
||||
"advanced-filter-label": "Advanced Filter",
|
||||
"advanced-filter-description": "Advanced Filter allows to write a string containing following operators: == != <= >= && || ( ) A space is used as a separator between the Operators. You can filter for all Custom Fields by typing their names and values. For Example: Field1 == Value1. Note: If fields or values contains spaces, you need to encapsulate them into single quotes. For Example: 'Field 1' == 'Value 1'. For single control characters (' \\/) to be skipped, you can use \\. For example: Field1 == I\\'m. Also you can combine multiple conditions. For Example: F1 == V1 || F1 == V2. Normally all operators are interpreted from left to right. You can change the order by placing brackets. For Example: F1 == V1 && ( F2 == V2 || F2 == V3 ). Also you can search text fields using regex: F1 == /Tes.*/i",
|
||||
"fullname": "Име",
|
||||
"header-logo-title": "Go back to your boards page.",
|
||||
"hide-system-messages": "Скриване на системните съобщения",
|
||||
"headerBarCreateBoardPopup-title": "Create Board",
|
||||
"home": "Начало",
|
||||
"import": "Import",
|
||||
"link": "Link",
|
||||
"import-board": "import board",
|
||||
"import-board-c": "Import board",
|
||||
"import-board-title-trello": "Import board from Trello",
|
||||
"import-board-title-wekan": "Import board from Wekan",
|
||||
"import-sandstorm-warning": "Imported board will delete all existing data on board and replace it with imported board.",
|
||||
"from-trello": "From Trello",
|
||||
"from-wekan": "From Wekan",
|
||||
"import-board-instruction-trello": "In your Trello board, go to 'Menu', then 'More', 'Print and Export', 'Export JSON', and copy the resulting text.",
|
||||
"import-board-instruction-wekan": "In your Wekan board, go to 'Menu', then 'Export board', and copy the text in the downloaded file.",
|
||||
"import-json-placeholder": "Paste your valid JSON data here",
|
||||
"import-map-members": "Map members",
|
||||
"import-members-map": "Your imported board has some members. Please map the members you want to import to Wekan users",
|
||||
"import-show-user-mapping": "Review members mapping",
|
||||
"import-user-select": "Pick the Wekan user you want to use as this member",
|
||||
"importMapMembersAddPopup-title": "Избери Wekan член",
|
||||
"info": "Версия",
|
||||
"initials": "Инициали",
|
||||
"invalid-date": "Невалидна дата",
|
||||
"invalid-time": "Невалиден час",
|
||||
"invalid-user": "Невалиден потребител",
|
||||
"joined": "присъедини ",
|
||||
"just-invited": "You are just invited to this board",
|
||||
"keyboard-shortcuts": "Keyboard shortcuts",
|
||||
"label-create": "Създай етикет",
|
||||
"label-default": "%s label (default)",
|
||||
"label-delete-pop": "There is no undo. This will remove this label from all cards and destroy its history.",
|
||||
"labels": "Етикети",
|
||||
"language": "Език",
|
||||
"last-admin-desc": "You can’t change roles because there must be at least one admin.",
|
||||
"leave-board": "Leave Board",
|
||||
"leave-board-pop": "Are you sure you want to leave __boardTitle__? You will be removed from all cards on this board.",
|
||||
"leaveBoardPopup-title": "Leave Board ?",
|
||||
"link-card": "Връзка към тази карта",
|
||||
"list-archive-cards": "Премести всички карти от този списък в Кошчето",
|
||||
"list-archive-cards-pop": "This will remove all the cards in this list from the board. To view cards in Recycle Bin and bring them back to the board, click “Menu” > “Recycle Bin”.",
|
||||
"list-move-cards": "Премести всички карти в този списък",
|
||||
"list-select-cards": "Избери всички карти в този списък",
|
||||
"listActionPopup-title": "List Actions",
|
||||
"swimlaneActionPopup-title": "Swimlane Actions",
|
||||
"listImportCardPopup-title": "Импорт на карта от Trello",
|
||||
"listMorePopup-title": "Още",
|
||||
"link-list": "Връзка към този списък",
|
||||
"list-delete-pop": "All actions will be removed from the activity feed and you won't be able to recover the list. There is no undo.",
|
||||
"list-delete-suggest-archive": "Можете да преместите списък в Кошчето, за да го премахнете от Таблото и запазите активността.",
|
||||
"lists": "Списъци",
|
||||
"swimlanes": "Коридори",
|
||||
"log-out": "Изход",
|
||||
"log-in": "Вход",
|
||||
"loginPopup-title": "Вход",
|
||||
"memberMenuPopup-title": "Настройки на профила",
|
||||
"members": "Членове",
|
||||
"menu": "Меню",
|
||||
"move-selection": "Move selection",
|
||||
"moveCardPopup-title": "Премести картата",
|
||||
"moveCardToBottom-title": "Премести в края",
|
||||
"moveCardToTop-title": "Премести в началото",
|
||||
"moveSelectionPopup-title": "Move selection",
|
||||
"multi-selection": "Множествен избор",
|
||||
"multi-selection-on": "Множественият избор е приложен",
|
||||
"muted": "Muted",
|
||||
"muted-info": "You will never be notified of any changes in this board",
|
||||
"my-boards": "Моите табла",
|
||||
"name": "Име",
|
||||
"no-archived-cards": "Няма карти в Кошчето.",
|
||||
"no-archived-lists": "Няма списъци в Кошчето.",
|
||||
"no-archived-swimlanes": "Няма коридори в Кошчето.",
|
||||
"no-results": "No results",
|
||||
"normal": "Normal",
|
||||
"normal-desc": "Can view and edit cards. Can't change settings.",
|
||||
"not-accepted-yet": "Invitation not accepted yet",
|
||||
"notify-participate": "Получавате информация за всички карти, в които сте отбелязани или сте създали",
|
||||
"notify-watch": "Получавате информация за всички табла, списъци и карти, които наблюдавате",
|
||||
"optional": "optional",
|
||||
"or": "or",
|
||||
"page-maybe-private": "This page may be private. You may be able to view it by <a href='%s'>logging in</a>.",
|
||||
"page-not-found": "Page not found.",
|
||||
"password": "Парола",
|
||||
"paste-or-dragdrop": "to paste, or drag & drop image file to it (image only)",
|
||||
"participating": "Participating",
|
||||
"preview": "Preview",
|
||||
"previewAttachedImagePopup-title": "Preview",
|
||||
"previewClipboardImagePopup-title": "Preview",
|
||||
"private": "Private",
|
||||
"private-desc": "This board is private. Only people added to the board can view and edit it.",
|
||||
"profile": "Профил",
|
||||
"public": "Public",
|
||||
"public-desc": "This board is public. It's visible to anyone with the link and will show up in search engines like Google. Only people added to the board can edit.",
|
||||
"quick-access-description": "Star a board to add a shortcut in this bar.",
|
||||
"remove-cover": "Remove Cover",
|
||||
"remove-from-board": "Remove from Board",
|
||||
"remove-label": "Remove Label",
|
||||
"listDeletePopup-title": "Желаете да изтриете списъка?",
|
||||
"remove-member": "Премахни член",
|
||||
"remove-member-from-card": "Премахни от картата",
|
||||
"remove-member-pop": "Remove __name__ (__username__) from __boardTitle__? The member will be removed from all cards on this board. They will receive a notification.",
|
||||
"removeMemberPopup-title": "Remove Member?",
|
||||
"rename": "Rename",
|
||||
"rename-board": "Промени името на Таблото",
|
||||
"restore": "Възстанови",
|
||||
"save": "Запази",
|
||||
"search": "Търсене",
|
||||
"search-cards": "Search from card titles and descriptions on this board",
|
||||
"search-example": "Text to search for?",
|
||||
"select-color": "Избери цвят",
|
||||
"set-wip-limit-value": "Set a limit for the maximum number of tasks in this list",
|
||||
"setWipLimitPopup-title": "Въведи WIP лимит",
|
||||
"shortcut-assign-self": "Добави себе си към тази карта",
|
||||
"shortcut-autocomplete-emoji": "Autocomplete emoji",
|
||||
"shortcut-autocomplete-members": "Autocomplete members",
|
||||
"shortcut-clear-filters": "Изчистване на всички филтри",
|
||||
"shortcut-close-dialog": "Close Dialog",
|
||||
"shortcut-filter-my-cards": "Филтрирай моите карти",
|
||||
"shortcut-show-shortcuts": "Bring up this shortcuts list",
|
||||
"shortcut-toggle-filterbar": "Отвори/затвори сайдбара с филтри",
|
||||
"shortcut-toggle-sidebar": "Toggle Board Sidebar",
|
||||
"show-cards-minimum-count": "Покажи бройката на картите, ако списъка съдържа повече от",
|
||||
"sidebar-open": "Open Sidebar",
|
||||
"sidebar-close": "Close Sidebar",
|
||||
"signupPopup-title": "Create an Account",
|
||||
"star-board-title": "Click to star this board. It will show up at top of your boards list.",
|
||||
"starred-boards": "Любими табла",
|
||||
"starred-boards-description": "Любимите табла се показват в началото на списъка Ви.",
|
||||
"subscribe": "Subscribe",
|
||||
"team": "Team",
|
||||
"this-board": "this board",
|
||||
"this-card": "картата",
|
||||
"spent-time-hours": "Изработено време (часа)",
|
||||
"overtime-hours": "Оувъртайм (часа)",
|
||||
"overtime": "Оувъртайм",
|
||||
"has-overtime-cards": "Има карти с оувъртайм",
|
||||
"has-spenttime-cards": "Има карти с изработено време",
|
||||
"time": "Време",
|
||||
"title": "Title",
|
||||
"tracking": "Следене",
|
||||
"tracking-info": "You will be notified of any changes to those cards you are involved as creator or member.",
|
||||
"type": "Type",
|
||||
"unassign-member": "Unassign member",
|
||||
"unsaved-description": "You have an unsaved description.",
|
||||
"unwatch": "Спри наблюдаването",
|
||||
"upload": "Upload",
|
||||
"upload-avatar": "Качване на аватар",
|
||||
"uploaded-avatar": "Качихте аватар",
|
||||
"username": "Потребителско име",
|
||||
"view-it": "View it",
|
||||
"warn-list-archived": "внимание: тази карта е в списък, който е в Кошчето",
|
||||
"watch": "Наблюдавай",
|
||||
"watching": "Наблюдава",
|
||||
"watching-info": "You will be notified of any change in this board",
|
||||
"welcome-board": "Welcome Board",
|
||||
"welcome-swimlane": "Milestone 1",
|
||||
"welcome-list1": "Basics",
|
||||
"welcome-list2": "Advanced",
|
||||
"what-to-do": "What do you want to do?",
|
||||
"wipLimitErrorPopup-title": "Невалиден WIP лимит",
|
||||
"wipLimitErrorPopup-dialog-pt1": "The number of tasks in this list is higher than the WIP limit you've defined.",
|
||||
"wipLimitErrorPopup-dialog-pt2": "Моля, преместете някои от задачите от този списък или въведете по-висок WIP лимит.",
|
||||
"admin-panel": "Администраторски панел",
|
||||
"settings": "Настройки",
|
||||
"people": "Хора",
|
||||
"registration": "Регистрация",
|
||||
"disable-self-registration": "Disable Self-Registration",
|
||||
"invite": "Покани",
|
||||
"invite-people": "Покани хора",
|
||||
"to-boards": "To board(s)",
|
||||
"email-addresses": "Имейл адреси",
|
||||
"smtp-host-description": "Адресът на SMTP сървъра, който обслужва Вашите имейли.",
|
||||
"smtp-port-description": "Портът, който Вашият SMTP сървър използва за изходящи имейли.",
|
||||
"smtp-tls-description": "Разреши TLS поддръжка за SMTP сървъра",
|
||||
"smtp-host": "SMTP хост",
|
||||
"smtp-port": "SMTP порт",
|
||||
"smtp-username": "Потребителско име",
|
||||
"smtp-password": "Парола",
|
||||
"smtp-tls": "TLS поддръжка",
|
||||
"send-from": "От",
|
||||
"send-smtp-test": "Изпрати тестов имейл на себе си",
|
||||
"invitation-code": "Invitation Code",
|
||||
"email-invite-register-subject": "__inviter__ sent you an invitation",
|
||||
"email-invite-register-text": "Dear __user__,\n\n__inviter__ invites you to Wekan for collaborations.\n\nPlease follow the link below:\n__url__\n\nAnd your invitation code is: __icode__\n\nThanks.",
|
||||
"email-smtp-test-subject": "SMTP тестов имейл, изпратен от Wekan",
|
||||
"email-smtp-test-text": "Успешно изпратихте имейл",
|
||||
"error-invitation-code-not-exist": "Invitation code doesn't exist",
|
||||
"error-notAuthorized": "You are not authorized to view this page.",
|
||||
"outgoing-webhooks": "Outgoing Webhooks",
|
||||
"outgoingWebhooksPopup-title": "Outgoing Webhooks",
|
||||
"new-outgoing-webhook": "New Outgoing Webhook",
|
||||
"no-name": "(Unknown)",
|
||||
"Wekan_version": "Версия на Wekan",
|
||||
"Node_version": "Версия на Node",
|
||||
"OS_Arch": "Архитектура на ОС",
|
||||
"OS_Cpus": "Брой CPU ядра",
|
||||
"OS_Freemem": "Свободна памет",
|
||||
"OS_Loadavg": "ОС средно натоварване",
|
||||
"OS_Platform": "ОС платформа",
|
||||
"OS_Release": "ОС Версия",
|
||||
"OS_Totalmem": "ОС Общо памет",
|
||||
"OS_Type": "Тип ОС",
|
||||
"OS_Uptime": "OS Ъптайм",
|
||||
"hours": "часа",
|
||||
"minutes": "минути",
|
||||
"seconds": "секунди",
|
||||
"show-field-on-card": "Покажи това поле в картата",
|
||||
"yes": "Да",
|
||||
"no": "Не",
|
||||
"accounts": "Профили",
|
||||
"accounts-allowEmailChange": "Разреши промяна на имейла",
|
||||
"accounts-allowUserNameChange": "Allow Username Change",
|
||||
"createdAt": "Създаден на",
|
||||
"verified": "Потвърден",
|
||||
"active": "Активен",
|
||||
"card-received": "Получена",
|
||||
"card-received-on": "Получена на",
|
||||
"card-end": "Завършена",
|
||||
"card-end-on": "Завършена на",
|
||||
"editCardReceivedDatePopup-title": "Промени датата на получаване",
|
||||
"editCardEndDatePopup-title": "Промени датата на завършване",
|
||||
"assigned-by": "Assigned By",
|
||||
"requested-by": "Requested By",
|
||||
"board-delete-notice": "Deleting is permanent. You will lose all lists, cards and actions associated with this board.",
|
||||
"delete-board-confirm-popup": "All lists, cards, labels, and activities will be deleted and you won't be able to recover the board contents. There is no undo.",
|
||||
"boardDeletePopup-title": "Delete Board?",
|
||||
"delete-board": "Delete Board",
|
||||
"default-subtasks-board": "Subtasks for __board__ board",
|
||||
"default": "Default",
|
||||
"queue": "Queue",
|
||||
"subtask-settings": "Subtasks Settings",
|
||||
"boardSubtaskSettingsPopup-title": "Board Subtasks Settings",
|
||||
"show-subtasks-field": "Cards can have subtasks",
|
||||
"deposit-subtasks-board": "Deposit subtasks to this board:",
|
||||
"deposit-subtasks-list": "Landing list for subtasks deposited here:",
|
||||
"show-parent-in-minicard": "Show parent in minicard:",
|
||||
"prefix-with-full-path": "Prefix with full path",
|
||||
"prefix-with-parent": "Prefix with parent",
|
||||
"subtext-with-full-path": "Subtext with full path",
|
||||
"subtext-with-parent": "Subtext with parent",
|
||||
"change-card-parent": "Change card's parent",
|
||||
"parent-card": "Parent card",
|
||||
"source-board": "Source board",
|
||||
"no-parent": "Don't show parent"
|
||||
}
|
||||
+106
-29
@@ -2,17 +2,19 @@
|
||||
"accept": "Asantiñ",
|
||||
"act-activity-notify": "[Wekan] Activity Notification",
|
||||
"act-addAttachment": "attached __attachment__ to __card__",
|
||||
"act-addSubtask": "added subtask __checklist__ to __card__",
|
||||
"act-addChecklist": "added checklist __checklist__ to __card__",
|
||||
"act-addChecklistItem": "added __checklistItem__ to checklist __checklist__ on __card__",
|
||||
"act-addComment": "commented on __card__: __comment__",
|
||||
"act-createBoard": "created __board__",
|
||||
"act-createCard": "added __card__ to __list__",
|
||||
"act-createCustomField": "created custom field __customField__",
|
||||
"act-createList": "added __list__ to __board__",
|
||||
"act-addBoardMember": "added __member__ to __board__",
|
||||
"act-archivedBoard": "archived __board__",
|
||||
"act-archivedCard": "archived __card__",
|
||||
"act-archivedList": "archived __list__",
|
||||
"act-archivedSwimlane": "archived __swimlane__",
|
||||
"act-archivedBoard": "__board__ moved to Recycle Bin",
|
||||
"act-archivedCard": "__card__ moved to Recycle Bin",
|
||||
"act-archivedList": "__list__ moved to Recycle Bin",
|
||||
"act-archivedSwimlane": "__swimlane__ moved to Recycle Bin",
|
||||
"act-importBoard": "imported __board__",
|
||||
"act-importCard": "imported __card__",
|
||||
"act-importList": "imported __list__",
|
||||
@@ -27,9 +29,10 @@
|
||||
"activities": "Oberiantizoù",
|
||||
"activity": "Oberiantiz",
|
||||
"activity-added": "%s ouzhpennet da %s",
|
||||
"activity-archived": "%s diellaouet",
|
||||
"activity-archived": "%s moved to Recycle Bin",
|
||||
"activity-attached": "%s liammet ouzh %s",
|
||||
"activity-created": "%s krouet",
|
||||
"activity-customfield-created": "created custom field %s",
|
||||
"activity-excluded": "excluded %s from %s",
|
||||
"activity-imported": "%s enporzhiet eus %s da %s",
|
||||
"activity-imported-board": "%s enporzhiet da %s",
|
||||
@@ -39,6 +42,7 @@
|
||||
"activity-removed": "removed %s from %s",
|
||||
"activity-sent": "sent %s to %s",
|
||||
"activity-unjoined": "unjoined %s",
|
||||
"activity-subtask-added": "added subtask to %s",
|
||||
"activity-checklist-added": "added checklist to %s",
|
||||
"activity-checklist-item-added": "added checklist item to '%s' in %s",
|
||||
"add": "Ouzhpenn",
|
||||
@@ -46,6 +50,7 @@
|
||||
"add-board": "Add Board",
|
||||
"add-card": "Add Card",
|
||||
"add-swimlane": "Add Swimlane",
|
||||
"add-subtask": "Add Subtask",
|
||||
"add-checklist": "Add Checklist",
|
||||
"add-checklist-item": "Add an item to checklist",
|
||||
"add-cover": "Ouzphenn ur golo",
|
||||
@@ -64,19 +69,19 @@
|
||||
"and-n-other-card_plural": "And __count__ other cards",
|
||||
"apply": "Apply",
|
||||
"app-is-offline": "Wekan is loading, please wait. Refreshing the page will cause data loss. If Wekan does not load, please check that Wekan server has not stopped.",
|
||||
"archive": "Archive",
|
||||
"archive-all": "Archive All",
|
||||
"archive-board": "Archive Board",
|
||||
"archive-card": "Archive Card",
|
||||
"archive-list": "Archive List",
|
||||
"archive-swimlane": "Archive Swimlane",
|
||||
"archive-selection": "Archive selection",
|
||||
"archiveBoardPopup-title": "Archive Board?",
|
||||
"archived-items": "Archived Items",
|
||||
"archived-boards": "Archived Boards",
|
||||
"archive": "Move to Recycle Bin",
|
||||
"archive-all": "Move All to Recycle Bin",
|
||||
"archive-board": "Move Board to Recycle Bin",
|
||||
"archive-card": "Move Card to Recycle Bin",
|
||||
"archive-list": "Move List to Recycle Bin",
|
||||
"archive-swimlane": "Move Swimlane to Recycle Bin",
|
||||
"archive-selection": "Move selection to Recycle Bin",
|
||||
"archiveBoardPopup-title": "Move Board to Recycle Bin?",
|
||||
"archived-items": "Recycle Bin",
|
||||
"archived-boards": "Boards in Recycle Bin",
|
||||
"restore-board": "Restore Board",
|
||||
"no-archived-boards": "No Archived Boards.",
|
||||
"archives": "Archives",
|
||||
"no-archived-boards": "No Boards in Recycle Bin.",
|
||||
"archives": "Recycle Bin",
|
||||
"assign-member": "Assign member",
|
||||
"attached": "attached",
|
||||
"attachment": "Attachment",
|
||||
@@ -98,19 +103,22 @@
|
||||
"boardMenuPopup-title": "Board Menu",
|
||||
"boards": "Boards",
|
||||
"board-view": "Board View",
|
||||
"board-view-cal": "Calendar",
|
||||
"board-view-swimlanes": "Swimlanes",
|
||||
"board-view-lists": "Lists",
|
||||
"bucket-example": "Like “Bucket List” for example",
|
||||
"cancel": "Cancel",
|
||||
"card-archived": "This card is archived.",
|
||||
"card-archived": "This card is moved to Recycle Bin.",
|
||||
"board-archived": "This board is moved to Recycle Bin.",
|
||||
"card-comments-title": "This card has %s comment.",
|
||||
"card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.",
|
||||
"card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.",
|
||||
"card-delete-suggest-archive": "You can archive a card to remove it from the board and preserve the activity.",
|
||||
"card-delete-suggest-archive": "You can move a card to Recycle Bin to remove it from the board and preserve the activity.",
|
||||
"card-due": "Due",
|
||||
"card-due-on": "Due on",
|
||||
"card-spent": "Spent Time",
|
||||
"card-edit-attachments": "Edit attachments",
|
||||
"card-edit-custom-fields": "Edit custom fields",
|
||||
"card-edit-labels": "Edit labels",
|
||||
"card-edit-members": "Edit members",
|
||||
"card-labels-title": "Change the labels for the card.",
|
||||
@@ -118,12 +126,19 @@
|
||||
"card-start": "Start",
|
||||
"card-start-on": "Starts on",
|
||||
"cardAttachmentsPopup-title": "Attach From",
|
||||
"cardCustomField-datePopup-title": "Change date",
|
||||
"cardCustomFieldsPopup-title": "Edit custom fields",
|
||||
"cardDeletePopup-title": "Diverkañ ar gartenn ?",
|
||||
"cardDetailsActionsPopup-title": "Card Actions",
|
||||
"cardLabelsPopup-title": "Labels",
|
||||
"cardMembersPopup-title": "Izili",
|
||||
"cardMorePopup-title": "Muioc’h",
|
||||
"cards": "Kartennoù",
|
||||
"cards-count": "Kartennoù",
|
||||
"casSignIn": "Sign In with CAS",
|
||||
"cardType-card": "Card",
|
||||
"cardType-linkedCard": "Linked Card",
|
||||
"cardType-linkedBoard": "Linked Board",
|
||||
"change": "Change",
|
||||
"change-avatar": "Change Avatar",
|
||||
"change-password": "Kemmañ ger-tremen",
|
||||
@@ -134,13 +149,14 @@
|
||||
"changePasswordPopup-title": "Kemmañ ger-tremen",
|
||||
"changePermissionsPopup-title": "Change Permissions",
|
||||
"changeSettingsPopup-title": "Change Settings",
|
||||
"subtasks": "Subtasks",
|
||||
"checklists": "Checklists",
|
||||
"click-to-star": "Click to star this board.",
|
||||
"click-to-unstar": "Click to unstar this board.",
|
||||
"clipboard": "Clipboard or drag & drop",
|
||||
"close": "Close",
|
||||
"close-board": "Close Board",
|
||||
"close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
|
||||
"close-board-pop": "You will be able to restore the board by clicking the “Recycle Bin” button from the home header.",
|
||||
"color-black": "du",
|
||||
"color-blue": "glas",
|
||||
"color-green": "gwer",
|
||||
@@ -155,19 +171,41 @@
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"no-comments": "No comments",
|
||||
"no-comments-desc": "Can not see comments and activities.",
|
||||
"computer": "Computer",
|
||||
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist",
|
||||
"confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?",
|
||||
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?",
|
||||
"copy-card-link-to-clipboard": "Copy card link to clipboard",
|
||||
"linkCardPopup-title": "Link Card",
|
||||
"searchCardPopup-title": "Search Card",
|
||||
"copyCardPopup-title": "Copy Card",
|
||||
"copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards",
|
||||
"copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format",
|
||||
"copyChecklistToManyCardsPopup-format": "[ {\"title\": \"First card title\", \"description\":\"First card description\"}, {\"title\":\"Second card title\",\"description\":\"Second card description\"},{\"title\":\"Last card title\",\"description\":\"Last card description\"} ]",
|
||||
"create": "Krouiñ",
|
||||
"createBoardPopup-title": "Create Board",
|
||||
"chooseBoardSourcePopup-title": "Import board",
|
||||
"createLabelPopup-title": "Create Label",
|
||||
"createCustomField": "Create Field",
|
||||
"createCustomFieldPopup-title": "Create Field",
|
||||
"current": "current",
|
||||
"custom-field-delete-pop": "There is no undo. This will remove this custom field from all cards and destroy its history.",
|
||||
"custom-field-checkbox": "Checkbox",
|
||||
"custom-field-date": "Date",
|
||||
"custom-field-dropdown": "Dropdown List",
|
||||
"custom-field-dropdown-none": "(none)",
|
||||
"custom-field-dropdown-options": "List Options",
|
||||
"custom-field-dropdown-options-placeholder": "Press enter to add more options",
|
||||
"custom-field-dropdown-unknown": "(unknown)",
|
||||
"custom-field-number": "Number",
|
||||
"custom-field-text": "Text",
|
||||
"custom-fields": "Custom Fields",
|
||||
"date": "Date",
|
||||
"decline": "Decline",
|
||||
"default-avatar": "Default avatar",
|
||||
"delete": "Diverkañ",
|
||||
"deleteCustomFieldPopup-title": "Delete Custom Field?",
|
||||
"deleteLabelPopup-title": "Delete Label?",
|
||||
"description": "Description",
|
||||
"disambiguateMultiLabelPopup-title": "Disambiguate Label Action",
|
||||
@@ -182,6 +220,7 @@
|
||||
"soft-wip-limit": "Soft WIP Limit",
|
||||
"editCardStartDatePopup-title": "Change start date",
|
||||
"editCardDueDatePopup-title": "Change due date",
|
||||
"editCustomFieldPopup-title": "Edit Field",
|
||||
"editCardSpentTimePopup-title": "Change spent time",
|
||||
"editLabelPopup-title": "Change Label",
|
||||
"editNotificationPopup-title": "Edit Notification",
|
||||
@@ -218,15 +257,19 @@
|
||||
"filter-clear": "Clear filter",
|
||||
"filter-no-label": "No label",
|
||||
"filter-no-member": "No member",
|
||||
"filter-no-custom-fields": "No Custom Fields",
|
||||
"filter-on": "Filter is on",
|
||||
"filter-on-desc": "You are filtering cards on this board. Click here to edit filter.",
|
||||
"filter-to-selection": "Filter to selection",
|
||||
"advanced-filter-label": "Advanced Filter",
|
||||
"advanced-filter-description": "Advanced Filter allows to write a string containing following operators: == != <= >= && || ( ) A space is used as a separator between the Operators. You can filter for all Custom Fields by typing their names and values. For Example: Field1 == Value1. Note: If fields or values contains spaces, you need to encapsulate them into single quotes. For Example: 'Field 1' == 'Value 1'. For single control characters (' \\/) to be skipped, you can use \\. For example: Field1 == I\\'m. Also you can combine multiple conditions. For Example: F1 == V1 || F1 == V2. Normally all operators are interpreted from left to right. You can change the order by placing brackets. For Example: F1 == V1 && ( F2 == V2 || F2 == V3 ). Also you can search text fields using regex: F1 == /Tes.*/i",
|
||||
"fullname": "Full Name",
|
||||
"header-logo-title": "Go back to your boards page.",
|
||||
"hide-system-messages": "Hide system messages",
|
||||
"headerBarCreateBoardPopup-title": "Create Board",
|
||||
"home": "Home",
|
||||
"import": "Import",
|
||||
"link": "Link",
|
||||
"import-board": "import board",
|
||||
"import-board-c": "Import board",
|
||||
"import-board-title-trello": "Import board from Trello",
|
||||
@@ -260,8 +303,8 @@
|
||||
"leave-board-pop": "Are you sure you want to leave __boardTitle__? You will be removed from all cards on this board.",
|
||||
"leaveBoardPopup-title": "Leave Board ?",
|
||||
"link-card": "Link to this card",
|
||||
"list-archive-cards": "Archive all cards in this list",
|
||||
"list-archive-cards-pop": "This will remove all the cards in this list from the board. To view archived cards and bring them back to the board, click “Menu” > “Archived Items”.",
|
||||
"list-archive-cards": "Move all cards in this list to Recycle Bin",
|
||||
"list-archive-cards-pop": "This will remove all the cards in this list from the board. To view cards in Recycle Bin and bring them back to the board, click “Menu” > “Recycle Bin”.",
|
||||
"list-move-cards": "Move all cards in this list",
|
||||
"list-select-cards": "Select all cards in this list",
|
||||
"listActionPopup-title": "List Actions",
|
||||
@@ -270,7 +313,7 @@
|
||||
"listMorePopup-title": "Muioc’h",
|
||||
"link-list": "Link to this list",
|
||||
"list-delete-pop": "All actions will be removed from the activity feed and you won't be able to recover the list. There is no undo.",
|
||||
"list-delete-suggest-archive": "You can archive a list to remove it from the board and preserve the activity.",
|
||||
"list-delete-suggest-archive": "You can move a list to Recycle Bin to remove it from the board and preserve the activity.",
|
||||
"lists": "Lists",
|
||||
"swimlanes": "Swimlanes",
|
||||
"log-out": "Log Out",
|
||||
@@ -290,9 +333,9 @@
|
||||
"muted-info": "You will never be notified of any changes in this board",
|
||||
"my-boards": "My Boards",
|
||||
"name": "Name",
|
||||
"no-archived-cards": "No archived cards.",
|
||||
"no-archived-lists": "No archived lists.",
|
||||
"no-archived-swimlanes": "No archived swimlanes.",
|
||||
"no-archived-cards": "No cards in Recycle Bin.",
|
||||
"no-archived-lists": "No lists in Recycle Bin.",
|
||||
"no-archived-swimlanes": "No swimlanes in Recycle Bin.",
|
||||
"no-results": "No results",
|
||||
"normal": "Normal",
|
||||
"normal-desc": "Can view and edit cards. Can't change settings.",
|
||||
@@ -328,6 +371,8 @@
|
||||
"restore": "Restore",
|
||||
"save": "Save",
|
||||
"search": "Search",
|
||||
"search-cards": "Search from card titles and descriptions on this board",
|
||||
"search-example": "Text to search for?",
|
||||
"select-color": "Select Color",
|
||||
"set-wip-limit-value": "Set a limit for the maximum number of tasks in this list",
|
||||
"setWipLimitPopup-title": "Set WIP Limit",
|
||||
@@ -360,6 +405,7 @@
|
||||
"title": "Title",
|
||||
"tracking": "Tracking",
|
||||
"tracking-info": "You will be notified of any changes to those cards you are involved as creator or member.",
|
||||
"type": "Type",
|
||||
"unassign-member": "Unassign member",
|
||||
"unsaved-description": "You have an unsaved description.",
|
||||
"unwatch": "Unwatch",
|
||||
@@ -368,7 +414,7 @@
|
||||
"uploaded-avatar": "Uploaded an avatar",
|
||||
"username": "Username",
|
||||
"view-it": "View it",
|
||||
"warn-list-archived": "warning: this card is in an archived list",
|
||||
"warn-list-archived": "warning: this card is in an list at Recycle Bin",
|
||||
"watch": "Watch",
|
||||
"watching": "Watching",
|
||||
"watching-info": "You will be notified of any change in this board",
|
||||
@@ -424,11 +470,42 @@
|
||||
"hours": "hours",
|
||||
"minutes": "minutes",
|
||||
"seconds": "seconds",
|
||||
"show-field-on-card": "Show this field on card",
|
||||
"yes": "Yes",
|
||||
"no": "No",
|
||||
"accounts": "Accounts",
|
||||
"accounts-allowEmailChange": "Allow Email Change",
|
||||
"accounts-allowUserNameChange": "Allow Username Change",
|
||||
"createdAt": "Created at",
|
||||
"verified": "Verified",
|
||||
"active": "Active"
|
||||
"active": "Active",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
"card-end-on": "Ends on",
|
||||
"editCardReceivedDatePopup-title": "Change received date",
|
||||
"editCardEndDatePopup-title": "Change end date",
|
||||
"assigned-by": "Assigned By",
|
||||
"requested-by": "Requested By",
|
||||
"board-delete-notice": "Deleting is permanent. You will lose all lists, cards and actions associated with this board.",
|
||||
"delete-board-confirm-popup": "All lists, cards, labels, and activities will be deleted and you won't be able to recover the board contents. There is no undo.",
|
||||
"boardDeletePopup-title": "Delete Board?",
|
||||
"delete-board": "Delete Board",
|
||||
"default-subtasks-board": "Subtasks for __board__ board",
|
||||
"default": "Default",
|
||||
"queue": "Queue",
|
||||
"subtask-settings": "Subtasks Settings",
|
||||
"boardSubtaskSettingsPopup-title": "Board Subtasks Settings",
|
||||
"show-subtasks-field": "Cards can have subtasks",
|
||||
"deposit-subtasks-board": "Deposit subtasks to this board:",
|
||||
"deposit-subtasks-list": "Landing list for subtasks deposited here:",
|
||||
"show-parent-in-minicard": "Show parent in minicard:",
|
||||
"prefix-with-full-path": "Prefix with full path",
|
||||
"prefix-with-parent": "Prefix with parent",
|
||||
"subtext-with-full-path": "Subtext with full path",
|
||||
"subtext-with-parent": "Subtext with parent",
|
||||
"change-card-parent": "Change card's parent",
|
||||
"parent-card": "Parent card",
|
||||
"source-board": "Source board",
|
||||
"no-parent": "Don't show parent"
|
||||
}
|
||||
+141
-64
@@ -2,17 +2,19 @@
|
||||
"accept": "Accepta",
|
||||
"act-activity-notify": "[Wekan] Notificació d'activitat",
|
||||
"act-addAttachment": "adjuntat __attachment__ a __card__",
|
||||
"act-addSubtask": "added subtask __checklist__ to __card__",
|
||||
"act-addChecklist": "afegida la checklist _checklist__ a __card__",
|
||||
"act-addChecklistItem": "afegit __checklistItem__ a la checklist __checklist__ on __card__",
|
||||
"act-addComment": "comentat a __card__: __comment__",
|
||||
"act-createBoard": "creat __board__",
|
||||
"act-createCard": "afegit/da __card__ a __list__",
|
||||
"act-createCustomField": "created custom field __customField__",
|
||||
"act-createList": "afegit/da __list__ a __board__",
|
||||
"act-addBoardMember": "afegit/da __member__ a __board__",
|
||||
"act-archivedBoard": "__board__ arxivat",
|
||||
"act-archivedCard": "__card__ arxivat/da",
|
||||
"act-archivedList": "__list__ arxivat/da",
|
||||
"act-archivedSwimlane": "archived __swimlane__",
|
||||
"act-archivedBoard": "__board__ moved to Recycle Bin",
|
||||
"act-archivedCard": "__card__ moved to Recycle Bin",
|
||||
"act-archivedList": "__list__ moved to Recycle Bin",
|
||||
"act-archivedSwimlane": "__swimlane__ moved to Recycle Bin",
|
||||
"act-importBoard": "__board__ importat",
|
||||
"act-importCard": "__card__ importat",
|
||||
"act-importList": "__list__ importat",
|
||||
@@ -27,9 +29,10 @@
|
||||
"activities": "Activitats",
|
||||
"activity": "Activitat",
|
||||
"activity-added": "ha afegit %s a %s",
|
||||
"activity-archived": "ha arxivat %s",
|
||||
"activity-archived": "%s moved to Recycle Bin",
|
||||
"activity-attached": "ha adjuntat %s a %s",
|
||||
"activity-created": "ha creat %s",
|
||||
"activity-customfield-created": "created custom field %s",
|
||||
"activity-excluded": "ha exclòs %s de %s",
|
||||
"activity-imported": "importat %s dins %s des de %s",
|
||||
"activity-imported-board": "importat %s des de %s",
|
||||
@@ -39,13 +42,15 @@
|
||||
"activity-removed": "ha eliminat %s de %s",
|
||||
"activity-sent": "ha enviat %s %s",
|
||||
"activity-unjoined": "desassignat %s",
|
||||
"activity-subtask-added": "added subtask to %s",
|
||||
"activity-checklist-added": "Checklist afegida a %s",
|
||||
"activity-checklist-item-added": "\nafegit checklist item de'%s' a %s",
|
||||
"activity-checklist-item-added": "afegida entrada de checklist de '%s' a %s",
|
||||
"add": "Afegeix",
|
||||
"add-attachment": "Afegeix adjunt",
|
||||
"add-board": "Afegeix Tauler",
|
||||
"add-card": "Afegeix fitxa",
|
||||
"add-swimlane": "Add Swimlane",
|
||||
"add-swimlane": "Afegix Carril de Natació",
|
||||
"add-subtask": "Add Subtask",
|
||||
"add-checklist": "Afegeix checklist",
|
||||
"add-checklist-item": "Afegeix un ítem",
|
||||
"add-cover": "Afegeix coberta",
|
||||
@@ -56,27 +61,27 @@
|
||||
"addMemberPopup-title": "Membres",
|
||||
"admin": "Administrador",
|
||||
"admin-desc": "Pots veure i editar fitxes, eliminar membres, i canviar la configuració del tauler",
|
||||
"admin-announcement": "Announcement",
|
||||
"admin-announcement-active": "Active System-Wide Announcement",
|
||||
"admin-announcement-title": "Announcement from Administrator",
|
||||
"admin-announcement": "Bàndol",
|
||||
"admin-announcement-active": "Activar bàndol del Sistema",
|
||||
"admin-announcement-title": "Bàndol de l'administració",
|
||||
"all-boards": "Tots els taulers",
|
||||
"and-n-other-card": "And __count__ other card",
|
||||
"and-n-other-card_plural": "And __count__ other cards",
|
||||
"apply": "Aplica",
|
||||
"app-is-offline": "Wekan s'està carregant, esperau si us plau. Refrescar la pàgina causarà la pérdua de les dades. Si Wekan no carrega, verificau que el servei de Wekan no estigui aturat",
|
||||
"archive": "Desa",
|
||||
"archive-all": "Desa Tot",
|
||||
"archive-board": "Arxiva tauler",
|
||||
"archive-card": "Arxiva fitxa",
|
||||
"archive-list": "Arxiva llista",
|
||||
"archive-swimlane": "Archive Swimlane",
|
||||
"archive-selection": "Arxiva selecció",
|
||||
"archiveBoardPopup-title": "Arxivar el tauler?",
|
||||
"archived-items": "Elements arxivats",
|
||||
"archived-boards": "Taulers Arxivats",
|
||||
"archive": "Move to Recycle Bin",
|
||||
"archive-all": "Move All to Recycle Bin",
|
||||
"archive-board": "Move Board to Recycle Bin",
|
||||
"archive-card": "Move Card to Recycle Bin",
|
||||
"archive-list": "Move List to Recycle Bin",
|
||||
"archive-swimlane": "Move Swimlane to Recycle Bin",
|
||||
"archive-selection": "Move selection to Recycle Bin",
|
||||
"archiveBoardPopup-title": "Move Board to Recycle Bin?",
|
||||
"archived-items": "Recycle Bin",
|
||||
"archived-boards": "Boards in Recycle Bin",
|
||||
"restore-board": "Restaura Tauler",
|
||||
"no-archived-boards": "Taulers no arxivats",
|
||||
"archives": "Arxivats",
|
||||
"no-archived-boards": "No Boards in Recycle Bin.",
|
||||
"archives": "Recycle Bin",
|
||||
"assign-member": "Assignar membre",
|
||||
"attached": "adjuntat",
|
||||
"attachment": "Adjunt",
|
||||
@@ -97,20 +102,23 @@
|
||||
"boardChangeWatchPopup-title": "Canvia seguiment",
|
||||
"boardMenuPopup-title": "Menú del tauler",
|
||||
"boards": "Taulers",
|
||||
"board-view": "Board View",
|
||||
"board-view-swimlanes": "Swimlanes",
|
||||
"board-view": "Visió del tauler",
|
||||
"board-view-cal": "Calendar",
|
||||
"board-view-swimlanes": "Carrils de Natació",
|
||||
"board-view-lists": "Llistes",
|
||||
"bucket-example": "Igual que “Bucket List”, per exemple",
|
||||
"cancel": "Cancel·la",
|
||||
"card-archived": "Aquesta fitxa està arxivada.",
|
||||
"card-archived": "This card is moved to Recycle Bin.",
|
||||
"board-archived": "This board is moved to Recycle Bin.",
|
||||
"card-comments-title": "Aquesta fitxa té %s comentaris.",
|
||||
"card-delete-notice": "L'esborrat és permanent. Perdreu totes les accions associades a aquesta fitxa.",
|
||||
"card-delete-pop": "Totes les accions s'eliminaran de l'activitat i no podreu tornar a obrir la fitxa. No es pot desfer.",
|
||||
"card-delete-suggest-archive": "Podeu arxivar una fitxa per extreure-la del tauler i preservar l'activitat.",
|
||||
"card-delete-suggest-archive": "You can move a card to Recycle Bin to remove it from the board and preserve the activity.",
|
||||
"card-due": "Finalitza",
|
||||
"card-due-on": "Finalitza a",
|
||||
"card-spent": "Spent Time",
|
||||
"card-spent": "Temps Dedicat",
|
||||
"card-edit-attachments": "Edita arxius adjunts",
|
||||
"card-edit-custom-fields": "Edit custom fields",
|
||||
"card-edit-labels": "Edita etiquetes",
|
||||
"card-edit-members": "Edita membres",
|
||||
"card-labels-title": "Canvia les etiquetes de la fitxa",
|
||||
@@ -118,12 +126,19 @@
|
||||
"card-start": "Comença",
|
||||
"card-start-on": "Comença a",
|
||||
"cardAttachmentsPopup-title": "Adjunta des de",
|
||||
"cardCustomField-datePopup-title": "Change date",
|
||||
"cardCustomFieldsPopup-title": "Edit custom fields",
|
||||
"cardDeletePopup-title": "Esborrar fitxa?",
|
||||
"cardDetailsActionsPopup-title": "Accions de fitxes",
|
||||
"cardLabelsPopup-title": "Etiquetes",
|
||||
"cardMembersPopup-title": "Membres",
|
||||
"cardMorePopup-title": "Més",
|
||||
"cards": "Fitxes",
|
||||
"cards-count": "Fitxes",
|
||||
"casSignIn": "Sign In with CAS",
|
||||
"cardType-card": "Card",
|
||||
"cardType-linkedCard": "Linked Card",
|
||||
"cardType-linkedBoard": "Linked Board",
|
||||
"change": "Canvia",
|
||||
"change-avatar": "Canvia Avatar",
|
||||
"change-password": "Canvia la clau",
|
||||
@@ -134,13 +149,14 @@
|
||||
"changePasswordPopup-title": "Canvia la contrasenya",
|
||||
"changePermissionsPopup-title": "Canvia permisos",
|
||||
"changeSettingsPopup-title": "Canvia configuració",
|
||||
"subtasks": "Subtasks",
|
||||
"checklists": "Checklists",
|
||||
"click-to-star": "Fes clic per destacar aquest tauler.",
|
||||
"click-to-unstar": "Fes clic per deixar de destacar aquest tauler.",
|
||||
"clipboard": "Portaretalls o estirar i amollar",
|
||||
"close": "Tanca",
|
||||
"close-board": "Tanca tauler",
|
||||
"close-board-pop": "Podràs restaurar el tauler, seleccionant \"Arxivats\" de la finistra principal",
|
||||
"close-board-pop": "You will be able to restore the board by clicking the “Recycle Bin” button from the home header.",
|
||||
"color-black": "negre",
|
||||
"color-blue": "blau",
|
||||
"color-green": "verd",
|
||||
@@ -155,19 +171,41 @@
|
||||
"comment-placeholder": "Escriu un comentari",
|
||||
"comment-only": "Només comentaris",
|
||||
"comment-only-desc": "Només pots fer comentaris a les fitxes",
|
||||
"no-comments": "No comments",
|
||||
"no-comments-desc": "Can not see comments and activities.",
|
||||
"computer": "Ordinador",
|
||||
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist",
|
||||
"confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?",
|
||||
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?",
|
||||
"copy-card-link-to-clipboard": "Copia l'enllaç de la ftixa al porta-retalls",
|
||||
"linkCardPopup-title": "Link Card",
|
||||
"searchCardPopup-title": "Search Card",
|
||||
"copyCardPopup-title": "Copia la fitxa",
|
||||
"copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards",
|
||||
"copyChecklistToManyCardsPopup-instructions": "Títols de fitxa i Descripcions de destí en aquest format JSON",
|
||||
"copyChecklistToManyCardsPopup-format": "[ {\"title\": \"Títol de la primera fitxa\", \"description\":\"Descripció de la primera fitxa\"}, {\"title\":\"Títol de la segona fitxa\",\"description\":\"Descripció de la segona fitxa\"},{\"title\":\"Títol de l'última fitxa\",\"description\":\"Descripció de l'última fitxa\"} ]",
|
||||
"create": "Crea",
|
||||
"createBoardPopup-title": "Crea tauler",
|
||||
"chooseBoardSourcePopup-title": "Importa Tauler",
|
||||
"createLabelPopup-title": "Crea etiqueta",
|
||||
"createCustomField": "Create Field",
|
||||
"createCustomFieldPopup-title": "Create Field",
|
||||
"current": "Actual",
|
||||
"custom-field-delete-pop": "There is no undo. This will remove this custom field from all cards and destroy its history.",
|
||||
"custom-field-checkbox": "Checkbox",
|
||||
"custom-field-date": "Data",
|
||||
"custom-field-dropdown": "Dropdown List",
|
||||
"custom-field-dropdown-none": "(none)",
|
||||
"custom-field-dropdown-options": "List Options",
|
||||
"custom-field-dropdown-options-placeholder": "Press enter to add more options",
|
||||
"custom-field-dropdown-unknown": "(unknown)",
|
||||
"custom-field-number": "Number",
|
||||
"custom-field-text": "Text",
|
||||
"custom-fields": "Custom Fields",
|
||||
"date": "Data",
|
||||
"decline": "Declina",
|
||||
"default-avatar": "Avatar per defecte",
|
||||
"delete": "Esborra",
|
||||
"deleteCustomFieldPopup-title": "Delete Custom Field?",
|
||||
"deleteLabelPopup-title": "Esborra etiqueta",
|
||||
"description": "Descripció",
|
||||
"disambiguateMultiLabelPopup-title": "Desfe l'ambigüitat en les etiquetes",
|
||||
@@ -178,11 +216,12 @@
|
||||
"edit": "Edita",
|
||||
"edit-avatar": "Canvia Avatar",
|
||||
"edit-profile": "Edita el teu Perfil",
|
||||
"edit-wip-limit": "Edit WIP Limit",
|
||||
"edit-wip-limit": "Edita el Límit de Treball en Progrès",
|
||||
"soft-wip-limit": "Soft WIP Limit",
|
||||
"editCardStartDatePopup-title": "Canvia data d'inici",
|
||||
"editCardDueDatePopup-title": "Canvia data de finalització",
|
||||
"editCardSpentTimePopup-title": "Change spent time",
|
||||
"editCustomFieldPopup-title": "Edit Field",
|
||||
"editCardSpentTimePopup-title": "Canvia temps dedicat",
|
||||
"editLabelPopup-title": "Canvia etiqueta",
|
||||
"editNotificationPopup-title": "Edita la notificació",
|
||||
"editProfilePopup-title": "Edita teu Perfil",
|
||||
@@ -190,7 +229,7 @@
|
||||
"email-enrollAccount-subject": "An account created for you on __siteName__",
|
||||
"email-enrollAccount-text": "Hola __user__,\n\nPer començar a utilitzar el servei, segueix l'enllaç següent.\n\n__url__\n\nGràcies.",
|
||||
"email-fail": "Error enviant el correu",
|
||||
"email-fail-text": "Error trying to send email",
|
||||
"email-fail-text": "Error en intentar enviar e-mail",
|
||||
"email-invalid": "Adreça de correu invàlida",
|
||||
"email-invite": "Convida mitjançant correu electrònic",
|
||||
"email-invite-subject": "__inviter__ t'ha convidat",
|
||||
@@ -200,7 +239,7 @@
|
||||
"email-sent": "Correu enviat",
|
||||
"email-verifyEmail-subject": "Verify your email address on __siteName__",
|
||||
"email-verifyEmail-text": "Hola __user__, \n\n per verificar el teu correu, segueix l'enllaç següent.\n\n __url__\n\n Gràcies.",
|
||||
"enable-wip-limit": "Enable WIP Limit",
|
||||
"enable-wip-limit": "Activa e Límit de Treball en Progrès",
|
||||
"error-board-doesNotExist": "Aquest tauler no existeix",
|
||||
"error-board-notAdmin": "Necessites ser administrador d'aquest tauler per dur a lloc aquest acció",
|
||||
"error-board-notAMember": "Necessites ser membre d'aquest tauler per dur a terme aquesta acció",
|
||||
@@ -211,22 +250,26 @@
|
||||
"error-user-notAllowSelf": "No et pots convidar a tu mateix",
|
||||
"error-user-notCreated": "L'usuari no s'ha creat",
|
||||
"error-username-taken": "Aquest usuari ja existeix",
|
||||
"error-email-taken": "Email has already been taken",
|
||||
"error-email-taken": "L'adreça de correu electrònic ja és en ús",
|
||||
"export-board": "Exporta tauler",
|
||||
"filter": "Filtre",
|
||||
"filter-cards": "Fitxes de filtre",
|
||||
"filter-clear": "Elimina filtre",
|
||||
"filter-no-label": "Sense etiqueta",
|
||||
"filter-no-member": "Sense membres",
|
||||
"filter-no-custom-fields": "No Custom Fields",
|
||||
"filter-on": "Filtra per",
|
||||
"filter-on-desc": "Estau filtrant fitxes en aquest tauler. Feu clic aquí per editar el filtre.",
|
||||
"filter-to-selection": "Filtra selecció",
|
||||
"advanced-filter-label": "Advanced Filter",
|
||||
"advanced-filter-description": "Advanced Filter allows to write a string containing following operators: == != <= >= && || ( ) A space is used as a separator between the Operators. You can filter for all Custom Fields by typing their names and values. For Example: Field1 == Value1. Note: If fields or values contains spaces, you need to encapsulate them into single quotes. For Example: 'Field 1' == 'Value 1'. For single control characters (' \\/) to be skipped, you can use \\. For example: Field1 == I\\'m. Also you can combine multiple conditions. For Example: F1 == V1 || F1 == V2. Normally all operators are interpreted from left to right. You can change the order by placing brackets. For Example: F1 == V1 && ( F2 == V2 || F2 == V3 ). Also you can search text fields using regex: F1 == /Tes.*/i",
|
||||
"fullname": "Nom complet",
|
||||
"header-logo-title": "Torna a la teva pàgina de taulers",
|
||||
"hide-system-messages": "Oculta missatges del sistema",
|
||||
"headerBarCreateBoardPopup-title": "Crea tauler",
|
||||
"home": "Inici",
|
||||
"import": "importa",
|
||||
"link": "Link",
|
||||
"import-board": "Importa tauler",
|
||||
"import-board-c": "Importa tauler",
|
||||
"import-board-title-trello": "Importa tauler des de Trello",
|
||||
@@ -246,7 +289,7 @@
|
||||
"initials": "Inicials",
|
||||
"invalid-date": "Data invàlida",
|
||||
"invalid-time": "Temps Invàlid",
|
||||
"invalid-user": "Invalid user",
|
||||
"invalid-user": "Usuari invàlid",
|
||||
"joined": "s'ha unit",
|
||||
"just-invited": "Has estat convidat a aquest tauler",
|
||||
"keyboard-shortcuts": "Dreceres de teclat",
|
||||
@@ -257,22 +300,22 @@
|
||||
"language": "Idioma",
|
||||
"last-admin-desc": "No podeu canviar rols perquè ha d'haver-hi almenys un administrador.",
|
||||
"leave-board": "Abandona tauler",
|
||||
"leave-board-pop": "Are you sure you want to leave __boardTitle__? You will be removed from all cards on this board.",
|
||||
"leaveBoardPopup-title": "Leave Board ?",
|
||||
"leave-board-pop": "De debò voleu abandonar __boardTitle__? Se us eliminarà de totes les fitxes d'aquest tauler.",
|
||||
"leaveBoardPopup-title": "Abandonar Tauler?",
|
||||
"link-card": "Enllaç a aquesta fitxa",
|
||||
"list-archive-cards": "Arxiva totes les fitxes d'aquesta llista",
|
||||
"list-archive-cards-pop": "Això eliminarà totes les fitxes d'aquesta llista del tauler. Per veure les fitxes arxivades i recuperar-les en el tauler, feu clic a \" Menú \"/ \" Articles Arxivat \".",
|
||||
"list-archive-cards": "Move all cards in this list to Recycle Bin",
|
||||
"list-archive-cards-pop": "This will remove all the cards in this list from the board. To view cards in Recycle Bin and bring them back to the board, click “Menu” > “Recycle Bin”.",
|
||||
"list-move-cards": "Mou totes les fitxes d'aquesta llista",
|
||||
"list-select-cards": "Selecciona totes les fitxes d'aquesta llista",
|
||||
"listActionPopup-title": "Accions de la llista",
|
||||
"swimlaneActionPopup-title": "Swimlane Actions",
|
||||
"swimlaneActionPopup-title": "Accions de Carril de Natació",
|
||||
"listImportCardPopup-title": "importa una fitxa de Trello",
|
||||
"listMorePopup-title": "Més",
|
||||
"link-list": "Enllaça a aquesta llista",
|
||||
"list-delete-pop": "Totes les accions seran esborrades de la llista d'activitats i no serà possible recuperar la llista",
|
||||
"list-delete-suggest-archive": "Pots arxivar una llista per eliminar-la del tauler i preservar la seva activitat",
|
||||
"list-delete-suggest-archive": "You can move a list to Recycle Bin to remove it from the board and preserve the activity.",
|
||||
"lists": "Llistes",
|
||||
"swimlanes": "Swimlanes",
|
||||
"swimlanes": "Carrils de Natació",
|
||||
"log-out": "Finalitza la sessió",
|
||||
"log-in": "Ingresa",
|
||||
"loginPopup-title": "Inicia sessió",
|
||||
@@ -290,9 +333,9 @@
|
||||
"muted-info": "No seràs notificat dels canvis en aquest tauler",
|
||||
"my-boards": "Els meus taulers",
|
||||
"name": "Nom",
|
||||
"no-archived-cards": "No hi ha fitxes arxivades.",
|
||||
"no-archived-lists": "No hi ha llistes arxivades.",
|
||||
"no-archived-swimlanes": "No archived swimlanes.",
|
||||
"no-archived-cards": "No cards in Recycle Bin.",
|
||||
"no-archived-lists": "No lists in Recycle Bin.",
|
||||
"no-archived-swimlanes": "No swimlanes in Recycle Bin.",
|
||||
"no-results": "Sense resultats",
|
||||
"normal": "Normal",
|
||||
"normal-desc": "Podeu veure i editar fitxes. No podeu canviar la configuració.",
|
||||
@@ -328,9 +371,11 @@
|
||||
"restore": "Restaura",
|
||||
"save": "Desa",
|
||||
"search": "Cerca",
|
||||
"search-cards": "Cerca títols de fitxa i descripcions en aquest tauler",
|
||||
"search-example": "Text que cercar?",
|
||||
"select-color": "Selecciona color",
|
||||
"set-wip-limit-value": "Set a limit for the maximum number of tasks in this list",
|
||||
"setWipLimitPopup-title": "Set WIP Limit",
|
||||
"set-wip-limit-value": "Limita el màxim nombre de tasques en aquesta llista",
|
||||
"setWipLimitPopup-title": "Configura el Límit de Treball en Progrès",
|
||||
"shortcut-assign-self": "Assigna't la ftixa actual",
|
||||
"shortcut-autocomplete-emoji": "Autocompleta emoji",
|
||||
"shortcut-autocomplete-members": "Autocompleta membres",
|
||||
@@ -351,15 +396,16 @@
|
||||
"team": "Equip",
|
||||
"this-board": "aquest tauler",
|
||||
"this-card": "aquesta fitxa",
|
||||
"spent-time-hours": "Spent time (hours)",
|
||||
"overtime-hours": "Overtime (hours)",
|
||||
"overtime": "Overtime",
|
||||
"has-overtime-cards": "Has overtime cards",
|
||||
"has-spenttime-cards": "Has spent time cards",
|
||||
"spent-time-hours": "Temps dedicat (hores)",
|
||||
"overtime-hours": "Temps de més (hores)",
|
||||
"overtime": "Temps de més",
|
||||
"has-overtime-cards": "Té fitxes amb temps de més",
|
||||
"has-spenttime-cards": "Té fitxes amb temps dedicat",
|
||||
"time": "Hora",
|
||||
"title": "Títol",
|
||||
"tracking": "En seguiment",
|
||||
"tracking-info": "Seràs notificat per cada canvi a aquelles fitxes de les que n'eres creador o membre",
|
||||
"type": "Type",
|
||||
"unassign-member": "Desassignar membre",
|
||||
"unsaved-description": "Tens una descripció sense desar.",
|
||||
"unwatch": "Suprimeix observació",
|
||||
@@ -368,18 +414,18 @@
|
||||
"uploaded-avatar": "Avatar actualitzat",
|
||||
"username": "Nom d'Usuari",
|
||||
"view-it": "Vist",
|
||||
"warn-list-archived": "Avís: aquesta fitxa està en una llista arxivada",
|
||||
"warn-list-archived": "warning: this card is in an list at Recycle Bin",
|
||||
"watch": "Observa",
|
||||
"watching": "En observació",
|
||||
"watching-info": "Seràs notificat de cada canvi en aquest tauler",
|
||||
"welcome-board": "Tauler de benvinguda",
|
||||
"welcome-swimlane": "Milestone 1",
|
||||
"welcome-swimlane": "Objectiu 1",
|
||||
"welcome-list1": "Bàsics",
|
||||
"welcome-list2": "Avançades",
|
||||
"what-to-do": "Què vols fer?",
|
||||
"wipLimitErrorPopup-title": "Invalid WIP Limit",
|
||||
"wipLimitErrorPopup-dialog-pt1": "The number of tasks in this list is higher than the WIP limit you've defined.",
|
||||
"wipLimitErrorPopup-dialog-pt2": "Please move some tasks out of this list, or set a higher WIP limit.",
|
||||
"wipLimitErrorPopup-title": "Límit de Treball en Progrès invàlid",
|
||||
"wipLimitErrorPopup-dialog-pt1": "El nombre de tasques en esta llista és superior al límit de Treball en Progrès que heu definit.",
|
||||
"wipLimitErrorPopup-dialog-pt2": "Si us plau mogui algunes taques fora d'aquesta llista, o configuri un límit de Treball en Progrès superior.",
|
||||
"admin-panel": "Tauler d'administració",
|
||||
"settings": "Configuració",
|
||||
"people": "Persones",
|
||||
@@ -398,17 +444,17 @@
|
||||
"smtp-password": "Contrasenya",
|
||||
"smtp-tls": "Suport TLS",
|
||||
"send-from": "De",
|
||||
"send-smtp-test": "Send a test email to yourself",
|
||||
"send-smtp-test": "Envia't un correu electrònic de prova",
|
||||
"invitation-code": "Codi d'invitació",
|
||||
"email-invite-register-subject": "__inviter__ t'ha convidat",
|
||||
"email-invite-register-text": " __user__,\n\n __inviter__ us ha convidat a col·laborar a Wekan.\n\n Clicau l'enllaç següent per acceptar l'invitació:\n __url__\n\n El vostre codi d'invitació és: __icode__\n\n Gràcies",
|
||||
"email-smtp-test-subject": "SMTP Test Email From Wekan",
|
||||
"email-smtp-test-text": "You have successfully sent an email",
|
||||
"email-smtp-test-subject": "Correu de Prova SMTP de Wekan",
|
||||
"email-smtp-test-text": "Has enviat un missatge satisfactòriament",
|
||||
"error-invitation-code-not-exist": "El codi d'invitació no existeix",
|
||||
"error-notAuthorized": "No estau autoritzats per veure aquesta pàgina",
|
||||
"outgoing-webhooks": "Outgoing Webhooks",
|
||||
"outgoingWebhooksPopup-title": "Outgoing Webhooks",
|
||||
"new-outgoing-webhook": "New Outgoing Webhook",
|
||||
"outgoing-webhooks": "Webhooks sortints",
|
||||
"outgoingWebhooksPopup-title": "Webhooks sortints",
|
||||
"new-outgoing-webhook": "Nou Webook sortint",
|
||||
"no-name": "Importa tauler des de Wekan",
|
||||
"Wekan_version": "Versió Wekan",
|
||||
"Node_version": "Versió Node",
|
||||
@@ -424,11 +470,42 @@
|
||||
"hours": "hores",
|
||||
"minutes": "minuts",
|
||||
"seconds": "segons",
|
||||
"show-field-on-card": "Show this field on card",
|
||||
"yes": "Si",
|
||||
"no": "No",
|
||||
"accounts": "Comptes",
|
||||
"accounts-allowEmailChange": "Permet modificar correu electrònic",
|
||||
"accounts-allowUserNameChange": "Allow Username Change",
|
||||
"createdAt": "Creat ",
|
||||
"verified": "Verificat",
|
||||
"active": "Actiu"
|
||||
"active": "Actiu",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
"card-end-on": "Ends on",
|
||||
"editCardReceivedDatePopup-title": "Change received date",
|
||||
"editCardEndDatePopup-title": "Change end date",
|
||||
"assigned-by": "Assigned By",
|
||||
"requested-by": "Requested By",
|
||||
"board-delete-notice": "Deleting is permanent. You will lose all lists, cards and actions associated with this board.",
|
||||
"delete-board-confirm-popup": "All lists, cards, labels, and activities will be deleted and you won't be able to recover the board contents. There is no undo.",
|
||||
"boardDeletePopup-title": "Delete Board?",
|
||||
"delete-board": "Delete Board",
|
||||
"default-subtasks-board": "Subtasks for __board__ board",
|
||||
"default": "Default",
|
||||
"queue": "Queue",
|
||||
"subtask-settings": "Subtasks Settings",
|
||||
"boardSubtaskSettingsPopup-title": "Board Subtasks Settings",
|
||||
"show-subtasks-field": "Cards can have subtasks",
|
||||
"deposit-subtasks-board": "Deposit subtasks to this board:",
|
||||
"deposit-subtasks-list": "Landing list for subtasks deposited here:",
|
||||
"show-parent-in-minicard": "Show parent in minicard:",
|
||||
"prefix-with-full-path": "Prefix with full path",
|
||||
"prefix-with-parent": "Prefix with parent",
|
||||
"subtext-with-full-path": "Subtext with full path",
|
||||
"subtext-with-parent": "Subtext with parent",
|
||||
"change-card-parent": "Change card's parent",
|
||||
"parent-card": "Parent card",
|
||||
"source-board": "Source board",
|
||||
"no-parent": "Don't show parent"
|
||||
}
|
||||
+203
-126
@@ -2,17 +2,19 @@
|
||||
"accept": "Přijmout",
|
||||
"act-activity-notify": "[Wekan] Notifikace aktivit",
|
||||
"act-addAttachment": "přiložen __attachment__ do __card__",
|
||||
"act-addChecklist": "added checklist __checklist__ to __card__",
|
||||
"act-addChecklistItem": "added __checklistItem__ to checklist __checklist__ on __card__",
|
||||
"act-addSubtask": "added subtask __checklist__ to __card__",
|
||||
"act-addChecklist": "přidán checklist __checklist__ do __card__",
|
||||
"act-addChecklistItem": "přidán __checklistItem__ do checklistu __checklist__ v __card__",
|
||||
"act-addComment": "komentář k __card__: __comment__",
|
||||
"act-createBoard": "přidání __board__",
|
||||
"act-createCard": "přidání __card__ do __list__",
|
||||
"act-createCustomField": "vytvořeno vlastní pole __customField__",
|
||||
"act-createList": "přidání __list__ do __board__",
|
||||
"act-addBoardMember": "přidání __member__ do __board__",
|
||||
"act-archivedBoard": "archivace __board__",
|
||||
"act-archivedCard": "archivace __card__",
|
||||
"act-archivedList": "archivace __list__",
|
||||
"act-archivedSwimlane": "archived __swimlane__",
|
||||
"act-archivedBoard": "__board__ bylo přesunuto do koše",
|
||||
"act-archivedCard": "__card__ bylo přesunuto do koše",
|
||||
"act-archivedList": "__list__ bylo přesunuto do koše",
|
||||
"act-archivedSwimlane": "__swimlane__ bylo přesunuto do koše",
|
||||
"act-importBoard": "import __board__",
|
||||
"act-importCard": "import __card__",
|
||||
"act-importList": "import __list__",
|
||||
@@ -27,9 +29,10 @@
|
||||
"activities": "Aktivity",
|
||||
"activity": "Aktivita",
|
||||
"activity-added": "%s přidáno k %s",
|
||||
"activity-archived": "%s archivováno",
|
||||
"activity-archived": "%s bylo přesunuto do koše",
|
||||
"activity-attached": "přiloženo %s k %s",
|
||||
"activity-created": "%s vytvořeno",
|
||||
"activity-customfield-created": "vytvořeno vlastní pole %s",
|
||||
"activity-excluded": "%s vyjmuto z %s",
|
||||
"activity-imported": "importován %s do %s z %s",
|
||||
"activity-imported-board": "importován %s z %s",
|
||||
@@ -39,13 +42,15 @@
|
||||
"activity-removed": "odstraněn %s z %s",
|
||||
"activity-sent": "%s posláno na %s",
|
||||
"activity-unjoined": "odpojen %s",
|
||||
"activity-subtask-added": "added subtask to %s",
|
||||
"activity-checklist-added": "přidán checklist do %s",
|
||||
"activity-checklist-item-added": "přidána položka checklist do '%s' v %s",
|
||||
"add": "Přidat",
|
||||
"add-attachment": "Přidat přílohu",
|
||||
"add-board": "Přidat tablo",
|
||||
"add-card": "Přidat kartu",
|
||||
"add-swimlane": "Add Swimlane",
|
||||
"add-swimlane": "Přidat Swimlane",
|
||||
"add-subtask": "Add Subtask",
|
||||
"add-checklist": "Přidat zaškrtávací seznam",
|
||||
"add-checklist-item": "Přidat položku do zaškrtávacího seznamu",
|
||||
"add-cover": "Přidat obal",
|
||||
@@ -56,27 +61,27 @@
|
||||
"addMemberPopup-title": "Členové",
|
||||
"admin": "Administrátor",
|
||||
"admin-desc": "Může zobrazovat a upravovat karty, mazat členy a měnit nastavení tabla.",
|
||||
"admin-announcement": "Announcement",
|
||||
"admin-announcement-active": "Active System-Wide Announcement",
|
||||
"admin-announcement-title": "Announcement from Administrator",
|
||||
"admin-announcement": "Oznámení",
|
||||
"admin-announcement-active": "Aktivní oznámení v celém systému",
|
||||
"admin-announcement-title": "Oznámení od administrátora",
|
||||
"all-boards": "Všechna tabla",
|
||||
"and-n-other-card": "A __count__ další karta(y)",
|
||||
"and-n-other-card_plural": "A __count__ dalších karet",
|
||||
"apply": "Použít",
|
||||
"app-is-offline": "Wekan is loading, please wait. Refreshing the page will cause data loss. If Wekan does not load, please check that Wekan server has not stopped.",
|
||||
"archive": "Archiv",
|
||||
"archive-all": "Archivovat vše",
|
||||
"archive-board": "Archivovat tablo",
|
||||
"archive-card": "Archivovat kartu",
|
||||
"archive-list": "Archive List",
|
||||
"archive-swimlane": "Archive Swimlane",
|
||||
"archive-selection": "Archivovat výběr",
|
||||
"archiveBoardPopup-title": "Archivovat tablo?",
|
||||
"archived-items": "Archivované položky",
|
||||
"archived-boards": "Archivaná tabla",
|
||||
"app-is-offline": "Wekan se načítá, prosím čekejte. Obnovení stránky způsobí ztrátu dat. Pokud se Wekan nenačte, zkontrolujte prosím, jestli se server s Wekanem nezastavil.",
|
||||
"archive": "Přesunout do koše",
|
||||
"archive-all": "Přesunout všechno do koše",
|
||||
"archive-board": "Přesunout tablo do koše",
|
||||
"archive-card": "Přesunout kartu do koše",
|
||||
"archive-list": "Přesunout seznam do koše",
|
||||
"archive-swimlane": "Přesunout swimlane do koše",
|
||||
"archive-selection": "Přesunout výběr do koše",
|
||||
"archiveBoardPopup-title": "Chcete přesunout tablo do koše?",
|
||||
"archived-items": "Koš",
|
||||
"archived-boards": "Tabla v koši",
|
||||
"restore-board": "Obnovit tablo",
|
||||
"no-archived-boards": "Žádná archivovaná tabla",
|
||||
"archives": "Archivy",
|
||||
"no-archived-boards": "Žádná tabla v koši",
|
||||
"archives": "Koš",
|
||||
"assign-member": "Přiřadit člena",
|
||||
"attached": "přiloženo",
|
||||
"attachment": "Příloha",
|
||||
@@ -94,23 +99,26 @@
|
||||
"boardChangeColorPopup-title": "Změnit pozadí tabla",
|
||||
"boardChangeTitlePopup-title": "Přejmenovat tablo",
|
||||
"boardChangeVisibilityPopup-title": "Upravit viditelnost",
|
||||
"boardChangeWatchPopup-title": "Change Watch",
|
||||
"boardChangeWatchPopup-title": "Změnit sledování",
|
||||
"boardMenuPopup-title": "Menu tabla",
|
||||
"boards": "Tabla",
|
||||
"board-view": "Board View",
|
||||
"board-view": "Náhled tabla",
|
||||
"board-view-cal": "Calendar",
|
||||
"board-view-swimlanes": "Swimlanes",
|
||||
"board-view-lists": "Seznamy",
|
||||
"bucket-example": "Například \"Než mě odvedou\"",
|
||||
"cancel": "Zrušit",
|
||||
"card-archived": "Tato karta je archivována.",
|
||||
"card-archived": "Karta byla přesunuta do koše.",
|
||||
"board-archived": "This board is moved to Recycle Bin.",
|
||||
"card-comments-title": "Tato karta má %s komentářů.",
|
||||
"card-delete-notice": "Smazání je trvalé. Přijdete o všechny akce asociované s touto kartou.",
|
||||
"card-delete-pop": "Všechny akce budou odstraněny z kanálu aktivity a nebude možné kartu znovu otevřít. Toto nelze vrátit zpět.",
|
||||
"card-delete-suggest-archive": "Kartu můžete archivovat a tím ji odstranit z tabla a přitom zachovat aktivity.",
|
||||
"card-delete-suggest-archive": "Kartu můžete přesunout do koše a tím ji odstranit z tabla a přitom zachovat aktivity.",
|
||||
"card-due": "Termín",
|
||||
"card-due-on": "Do",
|
||||
"card-spent": "Spent Time",
|
||||
"card-spent": "Strávený čas",
|
||||
"card-edit-attachments": "Upravit přílohy",
|
||||
"card-edit-custom-fields": "Upravit vlastní pole",
|
||||
"card-edit-labels": "Upravit štítky",
|
||||
"card-edit-members": "Upravit členy",
|
||||
"card-labels-title": "Změnit štítky karty.",
|
||||
@@ -118,12 +126,19 @@
|
||||
"card-start": "Start",
|
||||
"card-start-on": "Začít dne",
|
||||
"cardAttachmentsPopup-title": "Přiložit formulář",
|
||||
"cardCustomField-datePopup-title": "Změnit datum",
|
||||
"cardCustomFieldsPopup-title": "Upravit vlastní pole",
|
||||
"cardDeletePopup-title": "Smazat kartu?",
|
||||
"cardDetailsActionsPopup-title": "Akce karty",
|
||||
"cardLabelsPopup-title": "Štítky",
|
||||
"cardMembersPopup-title": "Členové",
|
||||
"cardMorePopup-title": "Více",
|
||||
"cards": "Karty",
|
||||
"cards-count": "Karty",
|
||||
"casSignIn": "Sign In with CAS",
|
||||
"cardType-card": "Card",
|
||||
"cardType-linkedCard": "Linked Card",
|
||||
"cardType-linkedBoard": "Linked Board",
|
||||
"change": "Změnit",
|
||||
"change-avatar": "Změnit avatar",
|
||||
"change-password": "Změnit heslo",
|
||||
@@ -134,13 +149,14 @@
|
||||
"changePasswordPopup-title": "Změnit heslo",
|
||||
"changePermissionsPopup-title": "Změnit oprávnění",
|
||||
"changeSettingsPopup-title": "Změnit nastavení",
|
||||
"subtasks": "Subtasks",
|
||||
"checklists": "Checklisty",
|
||||
"click-to-star": "Kliknutím přidat hvězdičku tomuto tablu.",
|
||||
"click-to-unstar": "Kliknutím odebrat hvězdičku tomuto tablu.",
|
||||
"clipboard": "Schránka nebo potáhnout a pustit",
|
||||
"close": "Zavřít",
|
||||
"close-board": "Zavřít tablo",
|
||||
"close-board-pop": "Budete moci obnovit tablo kliknutím na tlačítko \"Archivy\" v hlavním menu.",
|
||||
"close-board-pop": "Kliknutím na tlačítko \"Recyklovat\" budete moci obnovit tablo z koše.",
|
||||
"color-black": "černá",
|
||||
"color-blue": "modrá",
|
||||
"color-green": "zelená",
|
||||
@@ -153,21 +169,43 @@
|
||||
"color-yellow": "žlutá",
|
||||
"comment": "Komentář",
|
||||
"comment-placeholder": "Text komentáře",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"comment-only": "Pouze komentáře",
|
||||
"comment-only-desc": "Může přidávat komentáře pouze do karet.",
|
||||
"no-comments": "No comments",
|
||||
"no-comments-desc": "Can not see comments and activities.",
|
||||
"computer": "Počítač",
|
||||
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist",
|
||||
"confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?",
|
||||
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?",
|
||||
"copy-card-link-to-clipboard": "Kopírovat adresu karty do mezipaměti",
|
||||
"linkCardPopup-title": "Link Card",
|
||||
"searchCardPopup-title": "Search Card",
|
||||
"copyCardPopup-title": "Kopírovat kartu",
|
||||
"copyChecklistToManyCardsPopup-title": "Kopírovat checklist do více karet",
|
||||
"copyChecklistToManyCardsPopup-instructions": "Názvy a popisy cílové karty v tomto formátu JSON",
|
||||
"copyChecklistToManyCardsPopup-format": "[ {\"title\": \"Nadpis první karty\", \"description\":\"Popis druhé karty\"}, {\"title\":\"Nadpis druhé karty\",\"description\":\"Popis druhé karty\"},{\"title\":\"Nadpis poslední kary\",\"description\":\"Popis poslední karty\"} ]",
|
||||
"create": "Vytvořit",
|
||||
"createBoardPopup-title": "Vytvořit tablo",
|
||||
"chooseBoardSourcePopup-title": "Importovat tablo",
|
||||
"createLabelPopup-title": "Vytvořit štítek",
|
||||
"createCustomField": "Vytvořit pole",
|
||||
"createCustomFieldPopup-title": "Vytvořit pole",
|
||||
"current": "Aktuální",
|
||||
"date": "Date",
|
||||
"custom-field-delete-pop": "Nelze vrátit zpět. Toto odebere toto vlastní pole ze všech karet a zničí jeho historii.",
|
||||
"custom-field-checkbox": "Checkbox",
|
||||
"custom-field-date": "Datum",
|
||||
"custom-field-dropdown": "Rozbalovací seznam",
|
||||
"custom-field-dropdown-none": "(prázdné)",
|
||||
"custom-field-dropdown-options": "Seznam možností",
|
||||
"custom-field-dropdown-options-placeholder": "Stiskněte enter pro přidání více možností",
|
||||
"custom-field-dropdown-unknown": "(neznámé)",
|
||||
"custom-field-number": "Číslo",
|
||||
"custom-field-text": "Text",
|
||||
"custom-fields": "Vlastní pole",
|
||||
"date": "Datum",
|
||||
"decline": "Zamítnout",
|
||||
"default-avatar": "Výchozí avatar",
|
||||
"delete": "Smazat",
|
||||
"deleteCustomFieldPopup-title": "Smazat vlastní pole",
|
||||
"deleteLabelPopup-title": "Smazat štítek?",
|
||||
"description": "Popis",
|
||||
"disambiguateMultiLabelPopup-title": "Dvojznačný štítek akce",
|
||||
@@ -178,11 +216,12 @@
|
||||
"edit": "Upravit",
|
||||
"edit-avatar": "Změnit avatar",
|
||||
"edit-profile": "Upravit profil",
|
||||
"edit-wip-limit": "Edit WIP Limit",
|
||||
"soft-wip-limit": "Soft WIP Limit",
|
||||
"edit-wip-limit": "Upravit WIP Limit",
|
||||
"soft-wip-limit": "Mírný WIP limit",
|
||||
"editCardStartDatePopup-title": "Změnit datum startu úkolu",
|
||||
"editCardDueDatePopup-title": "Změnit datum dokončení úkolu",
|
||||
"editCardSpentTimePopup-title": "Change spent time",
|
||||
"editCustomFieldPopup-title": "Upravit pole",
|
||||
"editCardSpentTimePopup-title": "Změnit strávený čas",
|
||||
"editLabelPopup-title": "Změnit štítek",
|
||||
"editNotificationPopup-title": "Změnit notifikace",
|
||||
"editProfilePopup-title": "Upravit profil",
|
||||
@@ -190,7 +229,7 @@
|
||||
"email-enrollAccount-subject": "Byl vytvořen účet na __siteName__",
|
||||
"email-enrollAccount-text": "Ahoj __user__,\n\nMůžeš začít používat službu kliknutím na odkaz níže.\n\n__url__\n\nDěkujeme.",
|
||||
"email-fail": "Odeslání emailu selhalo",
|
||||
"email-fail-text": "Error trying to send email",
|
||||
"email-fail-text": "Chyba při pokusu o odeslání emailu",
|
||||
"email-invalid": "Neplatný email",
|
||||
"email-invite": "Pozvat pomocí emailu",
|
||||
"email-invite-subject": "__inviter__ odeslal pozvánku",
|
||||
@@ -200,7 +239,7 @@
|
||||
"email-sent": "Email byl odeslán",
|
||||
"email-verifyEmail-subject": "Ověř svou emailovou adresu na",
|
||||
"email-verifyEmail-text": "Ahoj __user__,\n\nPro ověření emailové adresy klikni na odkaz níže.\n\n__url__\n\nDěkujeme.",
|
||||
"enable-wip-limit": "Enable WIP Limit",
|
||||
"enable-wip-limit": "Povolit WIP Limit",
|
||||
"error-board-doesNotExist": "Toto tablo neexistuje",
|
||||
"error-board-notAdmin": "K provedení změny musíš být administrátor tohoto tabla",
|
||||
"error-board-notAMember": "K provedení změny musíš být členem tohoto tabla",
|
||||
@@ -210,43 +249,47 @@
|
||||
"error-user-doesNotExist": "Tento uživatel neexistuje",
|
||||
"error-user-notAllowSelf": "Nemůžeš pozvat sám sebe",
|
||||
"error-user-notCreated": "Tento uživatel není vytvořen",
|
||||
"error-username-taken": "This username is already taken",
|
||||
"error-email-taken": "Email has already been taken",
|
||||
"error-username-taken": "Toto uživatelské jméno již existuje",
|
||||
"error-email-taken": "Tento email byl již použit",
|
||||
"export-board": "Exportovat tablo",
|
||||
"filter": "Filtr",
|
||||
"filter-cards": "Filtrovat karty",
|
||||
"filter-clear": "Vyčistit filtr",
|
||||
"filter-no-label": "No label",
|
||||
"filter-no-member": "No member",
|
||||
"filter-no-label": "Žádný štítek",
|
||||
"filter-no-member": "Žádný člen",
|
||||
"filter-no-custom-fields": "Žádné vlastní pole",
|
||||
"filter-on": "Filtr je zapnut",
|
||||
"filter-on-desc": "Filtrujete karty tohoto tabla. Pro úpravu filtru klikni sem.",
|
||||
"filter-to-selection": "Filtrovat výběr",
|
||||
"advanced-filter-label": "Pokročilý filtr",
|
||||
"advanced-filter-description": "Advanced Filter allows to write a string containing following operators: == != <= >= && || ( ) A space is used as a separator between the Operators. You can filter for all Custom Fields by typing their names and values. For Example: Field1 == Value1. Note: If fields or values contains spaces, you need to encapsulate them into single quotes. For Example: 'Field 1' == 'Value 1'. For single control characters (' \\/) to be skipped, you can use \\. For example: Field1 == I\\'m. Also you can combine multiple conditions. For Example: F1 == V1 || F1 == V2. Normally all operators are interpreted from left to right. You can change the order by placing brackets. For Example: F1 == V1 && ( F2 == V2 || F2 == V3 ). Also you can search text fields using regex: F1 == /Tes.*/i",
|
||||
"fullname": "Celé jméno",
|
||||
"header-logo-title": "Jit zpět na stránku s tably.",
|
||||
"hide-system-messages": "Hide system messages",
|
||||
"hide-system-messages": "Skrýt systémové zprávy",
|
||||
"headerBarCreateBoardPopup-title": "Vytvořit tablo",
|
||||
"home": "Domů",
|
||||
"import": "Import",
|
||||
"import-board": "import board",
|
||||
"link": "Link",
|
||||
"import-board": "Importovat tablo",
|
||||
"import-board-c": "Importovat tablo",
|
||||
"import-board-title-trello": "Import board from Trello",
|
||||
"import-board-title-wekan": "Import board from Wekan",
|
||||
"import-sandstorm-warning": "Imported board will delete all existing data on board and replace it with imported board.",
|
||||
"from-trello": "From Trello",
|
||||
"from-wekan": "From Wekan",
|
||||
"import-board-title-wekan": "Importovat tablo z Wekanu",
|
||||
"import-sandstorm-warning": "Importované tablo spaže všechny existující data v tablu a nahradí je importovaným tablem.",
|
||||
"from-trello": "Z Trella",
|
||||
"from-wekan": "Z Wekanu",
|
||||
"import-board-instruction-trello": "Na svém Trello tablu, otevři 'Menu', pak 'More', 'Print and Export', 'Export JSON', a zkopíruj výsledný text",
|
||||
"import-board-instruction-wekan": "In your Wekan board, go to 'Menu', then 'Export board', and copy the text in the downloaded file.",
|
||||
"import-board-instruction-wekan": "Ve vašem Wekan tablu jděte do 'Menu', klikněte na 'Exportovat tablo' a zkopírujte text ze staženého souboru.",
|
||||
"import-json-placeholder": "Sem vlož validní JSON data",
|
||||
"import-map-members": "Map members",
|
||||
"import-map-members": "Mapovat členy",
|
||||
"import-members-map": "Toto importované tablo obsahuje několik členů. Namapuj členy z importu na uživatelské účty Wekan.",
|
||||
"import-show-user-mapping": "Zkontrolovat namapování členů",
|
||||
"import-user-select": "Vyber uživatele Wekan, kterého chceš použít pro tohoto člena",
|
||||
"importMapMembersAddPopup-title": "Select Wekan member",
|
||||
"info": "Version",
|
||||
"importMapMembersAddPopup-title": "Vybrat Wekan uživatele",
|
||||
"info": "Verze",
|
||||
"initials": "Iniciály",
|
||||
"invalid-date": "Invalid date",
|
||||
"invalid-time": "Invalid time",
|
||||
"invalid-user": "Invalid user",
|
||||
"invalid-date": "Neplatné datum",
|
||||
"invalid-time": "Neplatný čas",
|
||||
"invalid-user": "Neplatný uživatel",
|
||||
"joined": "spojeno",
|
||||
"just-invited": "Právě jsi byl pozván(a) do tohoto tabla",
|
||||
"keyboard-shortcuts": "Klávesové zkratky",
|
||||
@@ -257,20 +300,20 @@
|
||||
"language": "Jazyk",
|
||||
"last-admin-desc": "Nelze změnit role, protože musí existovat alespoň jeden administrátor.",
|
||||
"leave-board": "Opustit tablo",
|
||||
"leave-board-pop": "Are you sure you want to leave __boardTitle__? You will be removed from all cards on this board.",
|
||||
"leaveBoardPopup-title": "Leave Board ?",
|
||||
"leave-board-pop": "Opravdu chcete opustit tablo __boardTitle__? Odstraníte se tím i ze všech karet v tomto tablu.",
|
||||
"leaveBoardPopup-title": "Opustit tablo?",
|
||||
"link-card": "Odkázat na tuto kartu",
|
||||
"list-archive-cards": "Archivovat všechny karty na tomto seznamu",
|
||||
"list-archive-cards-pop": "Toto odstraní z tabla všechny karty z tohoto seznamu. Pro zobrazení archivovaných karet a jejich opětovné obnovení, klikni v \"Menu\" > \"Archivované položky\".",
|
||||
"list-archive-cards": "Přesunout všechny karty v tomto seznamu do koše",
|
||||
"list-archive-cards-pop": "Toto odstraní z tabla všechny karty z tohoto seznamu. Pro zobrazení karet v koši a jejich opětovné obnovení, klikni v \"Menu\" > \"Archivované položky\".",
|
||||
"list-move-cards": "Přesunout všechny karty v tomto seznamu",
|
||||
"list-select-cards": "Vybrat všechny karty v tomto seznamu",
|
||||
"listActionPopup-title": "Vypsat akce",
|
||||
"swimlaneActionPopup-title": "Swimlane Actions",
|
||||
"swimlaneActionPopup-title": "Akce swimlane",
|
||||
"listImportCardPopup-title": "Importovat Trello kartu",
|
||||
"listMorePopup-title": "Více",
|
||||
"link-list": "Link to this list",
|
||||
"list-delete-pop": "All actions will be removed from the activity feed and you won't be able to recover the list. There is no undo.",
|
||||
"list-delete-suggest-archive": "You can archive a list to remove it from the board and preserve the activity.",
|
||||
"link-list": "Odkaz na tento seznam",
|
||||
"list-delete-pop": "Všechny akce budou odstraněny z kanálu aktivity a nebude možné kartu obnovit. Toto nelze vrátit zpět.",
|
||||
"list-delete-suggest-archive": "Kartu můžete přesunout do koše a tím ji odstranit z tabla a přitom zachovat aktivity.",
|
||||
"lists": "Seznamy",
|
||||
"swimlanes": "Swimlanes",
|
||||
"log-out": "Odhlásit",
|
||||
@@ -281,31 +324,31 @@
|
||||
"menu": "Menu",
|
||||
"move-selection": "Přesunout výběr",
|
||||
"moveCardPopup-title": "Přesunout kartu",
|
||||
"moveCardToBottom-title": "Move to Bottom",
|
||||
"moveCardToTop-title": "Move to Top",
|
||||
"moveCardToBottom-title": "Přesunout dolu",
|
||||
"moveCardToTop-title": "Přesunout nahoru",
|
||||
"moveSelectionPopup-title": "Přesunout výběr",
|
||||
"multi-selection": "Multi-výběr",
|
||||
"multi-selection-on": "Multi-výběr je zapnut",
|
||||
"muted": "Muted",
|
||||
"muted-info": "You will never be notified of any changes in this board",
|
||||
"muted": "Umlčeno",
|
||||
"muted-info": "Nikdy nedostanete oznámení o změně v tomto tablu.",
|
||||
"my-boards": "Moje tabla",
|
||||
"name": "Jméno",
|
||||
"no-archived-cards": "Žádné archivované karty.",
|
||||
"no-archived-lists": "Žádné archivované seznamy.",
|
||||
"no-archived-swimlanes": "No archived swimlanes.",
|
||||
"no-archived-cards": "Žádné karty v koši",
|
||||
"no-archived-lists": "Žádné seznamy v koši",
|
||||
"no-archived-swimlanes": "Žádné swimlane v koši",
|
||||
"no-results": "Žádné výsledky",
|
||||
"normal": "Normální",
|
||||
"normal-desc": "Může zobrazovat a upravovat karty. Nemůže měnit nastavení.",
|
||||
"not-accepted-yet": "Pozvánka ještě nebyla přijmuta",
|
||||
"notify-participate": "Receive updates to any cards you participate as creater or member",
|
||||
"notify-watch": "Receive updates to any boards, lists, or cards you’re watching",
|
||||
"notify-participate": "Dostane aktualizace do všech karet, ve kterých se účastní jako tvůrce nebo člen",
|
||||
"notify-watch": "Dostane aktualitace to všech tabel, seznamů nebo karet, které sledujete",
|
||||
"optional": "volitelný",
|
||||
"or": "nebo",
|
||||
"page-maybe-private": "Tato stránka může být soukromá. Můžete ji zobrazit po <a href='%s'>přihlášení</a>.",
|
||||
"page-not-found": "Stránka nenalezena.",
|
||||
"password": "Heslo",
|
||||
"paste-or-dragdrop": "vložit, nebo přetáhnout a pustit soubor obrázku (pouze obrázek)",
|
||||
"participating": "Participating",
|
||||
"participating": "Zúčastnění",
|
||||
"preview": "Náhled",
|
||||
"previewAttachedImagePopup-title": "Náhled",
|
||||
"previewClipboardImagePopup-title": "Náhled",
|
||||
@@ -317,8 +360,8 @@
|
||||
"quick-access-description": "Pro přidání odkazu do této lišty označ tablo hvězdičkou.",
|
||||
"remove-cover": "Odstranit obal",
|
||||
"remove-from-board": "Odstranit z tabla",
|
||||
"remove-label": "Remove Label",
|
||||
"listDeletePopup-title": "Delete List ?",
|
||||
"remove-label": "Odstranit štítek",
|
||||
"listDeletePopup-title": "Smazat seznam?",
|
||||
"remove-member": "Odebrat uživatele",
|
||||
"remove-member-from-card": "Odstranit z karty",
|
||||
"remove-member-pop": "Odstranit __name__ (__username__) z __boardTitle__? Uživatel bude odebrán ze všech karet na tomto tablu. Na tuto skutečnost bude upozorněn.",
|
||||
@@ -328,11 +371,13 @@
|
||||
"restore": "Obnovit",
|
||||
"save": "Uložit",
|
||||
"search": "Hledat",
|
||||
"select-color": "Select Color",
|
||||
"set-wip-limit-value": "Set a limit for the maximum number of tasks in this list",
|
||||
"setWipLimitPopup-title": "Set WIP Limit",
|
||||
"search-cards": "Hledat nadpisy a popisy karet v tomto tablu",
|
||||
"search-example": "Hledaný text",
|
||||
"select-color": "Vybrat barvu",
|
||||
"set-wip-limit-value": "Nastaví limit pro maximální počet úkolů v seznamu.",
|
||||
"setWipLimitPopup-title": "Nastavit WIP Limit",
|
||||
"shortcut-assign-self": "Přiřadit sebe k aktuální kartě",
|
||||
"shortcut-autocomplete-emoji": "Autocomplete emoji",
|
||||
"shortcut-autocomplete-emoji": "Automatické dokončování emoji",
|
||||
"shortcut-autocomplete-members": "Automatický výběr uživatel",
|
||||
"shortcut-clear-filters": "Vyčistit všechny filtry",
|
||||
"shortcut-close-dialog": "Zavřít dialog",
|
||||
@@ -340,9 +385,9 @@
|
||||
"shortcut-show-shortcuts": "Otevřít tento seznam odkazů",
|
||||
"shortcut-toggle-filterbar": "Přepnout lištu filtrování",
|
||||
"shortcut-toggle-sidebar": "Přepnout lištu tabla",
|
||||
"show-cards-minimum-count": "Show cards count if list contains more than",
|
||||
"sidebar-open": "Open Sidebar",
|
||||
"sidebar-close": "Close Sidebar",
|
||||
"show-cards-minimum-count": "Zobrazit počet karet pokud seznam obsahuje více než ",
|
||||
"sidebar-open": "Otevřít boční panel",
|
||||
"sidebar-close": "Zavřít boční panel",
|
||||
"signupPopup-title": "Vytvořit účet",
|
||||
"star-board-title": "Kliknutím přidat tablu hvězdičku. Poté bude zobrazeno navrchu seznamu.",
|
||||
"starred-boards": "Tabla s hvězdičkou",
|
||||
@@ -351,64 +396,65 @@
|
||||
"team": "Tým",
|
||||
"this-board": "toto tablo",
|
||||
"this-card": "tuto kartu",
|
||||
"spent-time-hours": "Spent time (hours)",
|
||||
"overtime-hours": "Overtime (hours)",
|
||||
"overtime": "Overtime",
|
||||
"has-overtime-cards": "Has overtime cards",
|
||||
"has-spenttime-cards": "Has spent time cards",
|
||||
"time": "Time",
|
||||
"spent-time-hours": "Strávený čas (hodiny)",
|
||||
"overtime-hours": "Přesčas (hodiny)",
|
||||
"overtime": "Přesčas",
|
||||
"has-overtime-cards": "Obsahuje karty s přesčasy",
|
||||
"has-spenttime-cards": "Obsahuje karty se stráveným časem",
|
||||
"time": "Čas",
|
||||
"title": "Název",
|
||||
"tracking": "Tracking",
|
||||
"tracking-info": "You will be notified of any changes to those cards you are involved as creator or member.",
|
||||
"tracking": "Pozorující",
|
||||
"tracking-info": "Budete informováni o všech změnách v kartách, u kterých jste tvůrce nebo člen.",
|
||||
"type": "Typ",
|
||||
"unassign-member": "Vyřadit člena",
|
||||
"unsaved-description": "Popis neni uložen.",
|
||||
"unwatch": "Unwatch",
|
||||
"unwatch": "Přestat sledovat",
|
||||
"upload": "Nahrát",
|
||||
"upload-avatar": "Nahrát avatar",
|
||||
"uploaded-avatar": "Avatar nahrán",
|
||||
"username": "Uživatelské jméno",
|
||||
"view-it": "Zobrazit",
|
||||
"warn-list-archived": "varování: tato karta je v archivovaném seznamu",
|
||||
"watch": "Watch",
|
||||
"watching": "Watching",
|
||||
"watching-info": "You will be notified of any change in this board",
|
||||
"welcome-board": "Welcome Board",
|
||||
"welcome-swimlane": "Milestone 1",
|
||||
"welcome-list1": "Basics",
|
||||
"welcome-list2": "Advanced",
|
||||
"warn-list-archived": "varování: tuto kartu obsahuje seznam v koši",
|
||||
"watch": "Sledovat",
|
||||
"watching": "Sledující",
|
||||
"watching-info": "Bude vám oznámena každá změna v tomto tablu",
|
||||
"welcome-board": "Uvítací tablo",
|
||||
"welcome-swimlane": "Milník 1",
|
||||
"welcome-list1": "Základní",
|
||||
"welcome-list2": "Pokročilé",
|
||||
"what-to-do": "Co chcete dělat?",
|
||||
"wipLimitErrorPopup-title": "Invalid WIP Limit",
|
||||
"wipLimitErrorPopup-dialog-pt1": "The number of tasks in this list is higher than the WIP limit you've defined.",
|
||||
"wipLimitErrorPopup-dialog-pt2": "Please move some tasks out of this list, or set a higher WIP limit.",
|
||||
"admin-panel": "Admin Panel",
|
||||
"wipLimitErrorPopup-title": "Neplatný WIP Limit",
|
||||
"wipLimitErrorPopup-dialog-pt1": "Počet úkolů v tomto seznamu je vyšší než definovaný WIP limit.",
|
||||
"wipLimitErrorPopup-dialog-pt2": "Přesuňte prosím některé úkoly mimo tento seznam, nebo nastavte vyšší WIP limit.",
|
||||
"admin-panel": "Administrátorský panel",
|
||||
"settings": "Nastavení",
|
||||
"people": "Lidé",
|
||||
"registration": "Registrace",
|
||||
"disable-self-registration": "Disable Self-Registration",
|
||||
"disable-self-registration": "Vypnout svévolnou registraci",
|
||||
"invite": "Pozvánka",
|
||||
"invite-people": "Invite People",
|
||||
"to-boards": "To board(s)",
|
||||
"invite-people": "Pozvat lidi",
|
||||
"to-boards": "Do tabel",
|
||||
"email-addresses": "Emailové adresy",
|
||||
"smtp-host-description": "The address of the SMTP server that handles your emails.",
|
||||
"smtp-port-description": "The port your SMTP server uses for outgoing emails.",
|
||||
"smtp-tls-description": "Enable TLS support for SMTP server",
|
||||
"smtp-host-description": "Adresa SMTP serveru, který zpracovává vaše emaily.",
|
||||
"smtp-port-description": "Port, který používá Váš SMTP server pro odchozí emaily.",
|
||||
"smtp-tls-description": "Zapnout TLS podporu pro SMTP server",
|
||||
"smtp-host": "SMTP Host",
|
||||
"smtp-port": "SMTP Port",
|
||||
"smtp-username": "Uživatelské jméno",
|
||||
"smtp-password": "Heslo",
|
||||
"smtp-tls": "TLS support",
|
||||
"smtp-tls": "podpora TLS",
|
||||
"send-from": "Od",
|
||||
"send-smtp-test": "Send a test email to yourself",
|
||||
"invitation-code": "Invitation Code",
|
||||
"send-smtp-test": "Poslat si zkušební email.",
|
||||
"invitation-code": "Kód pozvánky",
|
||||
"email-invite-register-subject": "__inviter__ odeslal pozvánku",
|
||||
"email-invite-register-text": "Dear __user__,\n\n__inviter__ invites you to Wekan for collaborations.\n\nPlease follow the link below:\n__url__\n\nAnd your invitation code is: __icode__\n\nThanks.",
|
||||
"email-smtp-test-subject": "SMTP Test Email From Wekan",
|
||||
"email-smtp-test-text": "You have successfully sent an email",
|
||||
"error-invitation-code-not-exist": "Invitation code doesn't exist",
|
||||
"email-invite-register-text": "Ahoj __user__,\n\n__inviter__ tě přizval ke spolupráci ve Wekanu.\n\nNásleduj prosím odkaz níže:\n\n__url__\n\nKód Tvé pozvánky je: __icode__\n\nDěkujeme.",
|
||||
"email-smtp-test-subject": "SMTP Testovací email z Wekanu",
|
||||
"email-smtp-test-text": "Email byl úspěšně odeslán",
|
||||
"error-invitation-code-not-exist": "Kód pozvánky neexistuje.",
|
||||
"error-notAuthorized": "Nejste autorizován k prohlížení této stránky.",
|
||||
"outgoing-webhooks": "Outgoing Webhooks",
|
||||
"outgoingWebhooksPopup-title": "Outgoing Webhooks",
|
||||
"new-outgoing-webhook": "New Outgoing Webhook",
|
||||
"outgoing-webhooks": "Odchozí Webhooky",
|
||||
"outgoingWebhooksPopup-title": "Odchozí Webhooky",
|
||||
"new-outgoing-webhook": "Nové odchozí Webhooky",
|
||||
"no-name": "(Neznámé)",
|
||||
"Wekan_version": "Wekan verze",
|
||||
"Node_version": "Node verze",
|
||||
@@ -416,19 +462,50 @@
|
||||
"OS_Cpus": "OS Počet CPU",
|
||||
"OS_Freemem": "OS Volná paměť",
|
||||
"OS_Loadavg": "OS Průměrná zátěž systém",
|
||||
"OS_Platform": "OS Platform",
|
||||
"OS_Release": "OS Release",
|
||||
"OS_Platform": "Platforma OS",
|
||||
"OS_Release": "Verze OS",
|
||||
"OS_Totalmem": "OS Celková paměť",
|
||||
"OS_Type": "OS Type",
|
||||
"OS_Type": "Typ OS",
|
||||
"OS_Uptime": "OS Doba běhu systému",
|
||||
"hours": "hodin",
|
||||
"minutes": "minut",
|
||||
"seconds": "sekund",
|
||||
"show-field-on-card": "Ukázat toto pole na kartě",
|
||||
"yes": "Ano",
|
||||
"no": "Ne",
|
||||
"accounts": "Účty",
|
||||
"accounts-allowEmailChange": "Povolit změnu Emailu",
|
||||
"createdAt": "Created at",
|
||||
"verified": "Verified",
|
||||
"active": "Active"
|
||||
"accounts-allowUserNameChange": "Povolit změnu uživatelského jména",
|
||||
"createdAt": "Vytvořeno v",
|
||||
"verified": "Ověřen",
|
||||
"active": "Aktivní",
|
||||
"card-received": "Přijato",
|
||||
"card-received-on": "Přijaté v",
|
||||
"card-end": "Konec",
|
||||
"card-end-on": "Končí v",
|
||||
"editCardReceivedDatePopup-title": "Změnit datum přijetí",
|
||||
"editCardEndDatePopup-title": "Změnit datum konce",
|
||||
"assigned-by": "Assigned By",
|
||||
"requested-by": "Requested By",
|
||||
"board-delete-notice": "Deleting is permanent. You will lose all lists, cards and actions associated with this board.",
|
||||
"delete-board-confirm-popup": "All lists, cards, labels, and activities will be deleted and you won't be able to recover the board contents. There is no undo.",
|
||||
"boardDeletePopup-title": "Smazat tablo?",
|
||||
"delete-board": "Smazat tablo",
|
||||
"default-subtasks-board": "Subtasks for __board__ board",
|
||||
"default": "Default",
|
||||
"queue": "Queue",
|
||||
"subtask-settings": "Subtasks Settings",
|
||||
"boardSubtaskSettingsPopup-title": "Board Subtasks Settings",
|
||||
"show-subtasks-field": "Cards can have subtasks",
|
||||
"deposit-subtasks-board": "Deposit subtasks to this board:",
|
||||
"deposit-subtasks-list": "Landing list for subtasks deposited here:",
|
||||
"show-parent-in-minicard": "Show parent in minicard:",
|
||||
"prefix-with-full-path": "Prefix with full path",
|
||||
"prefix-with-parent": "Prefix with parent",
|
||||
"subtext-with-full-path": "Subtext with full path",
|
||||
"subtext-with-parent": "Subtext with parent",
|
||||
"change-card-parent": "Change card's parent",
|
||||
"parent-card": "Parent card",
|
||||
"source-board": "Source board",
|
||||
"no-parent": "Don't show parent"
|
||||
}
|
||||
+127
-50
@@ -2,17 +2,19 @@
|
||||
"accept": "Akzeptieren",
|
||||
"act-activity-notify": "[Wekan] Aktivitätsbenachrichtigung",
|
||||
"act-addAttachment": "hat __attachment__ an __card__ angehängt",
|
||||
"act-addChecklist": "hat die Checklist __checklist__ zu __card__ hinzugefügt",
|
||||
"act-addSubtask": "hat die Teilaufgabe __checklist__ zu __card__ hinzugefügt",
|
||||
"act-addChecklist": "hat die Checkliste __checklist__ zu __card__ hinzugefügt",
|
||||
"act-addChecklistItem": "hat __checklistItem__ zur Checkliste __checklist__ in __card__ hinzugefügt",
|
||||
"act-addComment": "hat __card__ kommentiert: __comment__",
|
||||
"act-createBoard": "hat __board__ erstellt",
|
||||
"act-createCard": "hat __card__ zu __list__ hinzugefügt",
|
||||
"act-createCustomField": "benutzerdefiniertes Feld __customField__ angelegt",
|
||||
"act-createList": "hat __list__ zu __board__ hinzugefügt",
|
||||
"act-addBoardMember": "hat __member__ zu __board__ hinzugefügt",
|
||||
"act-archivedBoard": "hat __board__ archiviert",
|
||||
"act-archivedCard": "hat __card__ archiviert",
|
||||
"act-archivedList": "hat __list__ archiviert",
|
||||
"act-archivedSwimlane": "__swimlane__ wurde archiviert",
|
||||
"act-archivedBoard": "__board__ in den Papierkorb verschoben",
|
||||
"act-archivedCard": "__card__ in den Papierkorb verschoben",
|
||||
"act-archivedList": "__list__ in den Papierkorb verschoben",
|
||||
"act-archivedSwimlane": "__swimlane__ in den Papierkorb verschoben",
|
||||
"act-importBoard": "hat __board__ importiert",
|
||||
"act-importCard": "hat __card__ importiert",
|
||||
"act-importList": "hat __list__ importiert",
|
||||
@@ -27,9 +29,10 @@
|
||||
"activities": "Aktivitäten",
|
||||
"activity": "Aktivität",
|
||||
"activity-added": "hat %s zu %s hinzugefügt",
|
||||
"activity-archived": "hat %s archiviert",
|
||||
"activity-archived": "hat %s in den Papierkorb verschoben",
|
||||
"activity-attached": "hat %s an %s angehängt",
|
||||
"activity-created": "hat %s erstellt",
|
||||
"activity-customfield-created": "hat das benutzerdefinierte Feld %s erstellt",
|
||||
"activity-excluded": "hat %s von %s ausgeschlossen",
|
||||
"activity-imported": "hat %s in %s von %s importiert",
|
||||
"activity-imported-board": "hat %s von %s importiert",
|
||||
@@ -39,15 +42,17 @@
|
||||
"activity-removed": "hat %s von %s entfernt",
|
||||
"activity-sent": "hat %s an %s gesendet",
|
||||
"activity-unjoined": "hat %s verlassen",
|
||||
"activity-subtask-added": "Teilaufgabe zu %s hinzugefügt",
|
||||
"activity-checklist-added": "hat eine Checkliste zu %s hinzugefügt",
|
||||
"activity-checklist-item-added": "hat einen Punkt zur Checkliste '%s' in %s hinzugefügt",
|
||||
"activity-checklist-item-added": "hat eine Checklistenposition zu '%s' in %s hinzugefügt",
|
||||
"add": "Hinzufügen",
|
||||
"add-attachment": "Datei anhängen",
|
||||
"add-board": "neues Board",
|
||||
"add-card": "Karte hinzufügen",
|
||||
"add-swimlane": "Swimlane hinzufügen",
|
||||
"add-subtask": "Teilaufgabe hinzufügen",
|
||||
"add-checklist": "Checkliste hinzufügen",
|
||||
"add-checklist-item": "Punkt zu einer Checkliste hinzufügen",
|
||||
"add-checklist-item": "Position zu einer Checkliste hinzufügen",
|
||||
"add-cover": "Cover hinzufügen",
|
||||
"add-label": "Label hinzufügen",
|
||||
"add-list": "Liste hinzufügen",
|
||||
@@ -55,32 +60,32 @@
|
||||
"added": "Hinzugefügt",
|
||||
"addMemberPopup-title": "Mitglieder",
|
||||
"admin": "Admin",
|
||||
"admin-desc": "Kann Karten anschauen und bearbeiten, Mitglieder entfernen und Boardeinstellungen ändern.",
|
||||
"admin-desc": "Kann Karten anzeigen und bearbeiten, Mitglieder entfernen und Boardeinstellungen ändern.",
|
||||
"admin-announcement": "Ankündigung",
|
||||
"admin-announcement-active": "Aktive, systemweite Ankündigungen",
|
||||
"admin-announcement-active": "Aktive systemweite Ankündigungen",
|
||||
"admin-announcement-title": "Ankündigung des Administrators",
|
||||
"all-boards": "Alle Boards",
|
||||
"and-n-other-card": "und eine andere Karte",
|
||||
"and-n-other-card_plural": "und __count__ andere Karten",
|
||||
"apply": "Übernehmen",
|
||||
"app-is-offline": "Wekan lädt gerade, bitte warten Sie. Wenn Sie die Seite neu laden, gehen nicht übertragene Änderungen verloren. Sollte Wekan nicht geladen werden, überprüfen Sie bitte, ob der Server noch läuft.",
|
||||
"archive": "Archiv",
|
||||
"archive-all": "Alles archivieren",
|
||||
"archive-board": "Board archivieren",
|
||||
"archive-card": "Karte archivieren",
|
||||
"archive-list": "Liste archivieren",
|
||||
"archive-swimlane": "Swimlane archivieren",
|
||||
"archive-selection": "Auswahl archivieren",
|
||||
"archiveBoardPopup-title": "Board archivieren?",
|
||||
"archived-items": "Archivierte Einträge",
|
||||
"archived-boards": "Achivierte Boards",
|
||||
"archive": "In den Papierkorb verschieben",
|
||||
"archive-all": "Alles in den Papierkorb verschieben",
|
||||
"archive-board": "Board in den Papierkorb verschieben",
|
||||
"archive-card": "Karte in den Papierkorb verschieben",
|
||||
"archive-list": "Liste in den Papierkorb verschieben",
|
||||
"archive-swimlane": "Swimlane in den Papierkorb verschieben",
|
||||
"archive-selection": "Auswahl in den Papierkorb verschieben",
|
||||
"archiveBoardPopup-title": "Board in den Papierkorb verschieben?",
|
||||
"archived-items": "Papierkorb",
|
||||
"archived-boards": "Boards im Papierkorb",
|
||||
"restore-board": "Board wiederherstellen",
|
||||
"no-archived-boards": "Keine archivierten Boards",
|
||||
"archives": "Archive",
|
||||
"no-archived-boards": "Keine Boards im Papierkorb.",
|
||||
"archives": "Papierkorb",
|
||||
"assign-member": "Mitglied zuweisen",
|
||||
"attached": "angehängt",
|
||||
"attachment": "Anhang",
|
||||
"attachment-delete-pop": "Das Löschen eines Anhangs kann nicht wieder rückgängig gemacht werden.",
|
||||
"attachment-delete-pop": "Das Löschen eines Anhangs kann nicht rückgängig gemacht werden.",
|
||||
"attachmentDeletePopup-title": "Anhang löschen?",
|
||||
"attachments": "Anhänge",
|
||||
"auto-watch": "Neue Boards nach Erstellung automatisch beobachten",
|
||||
@@ -98,19 +103,22 @@
|
||||
"boardMenuPopup-title": "Boardmenü",
|
||||
"boards": "Boards",
|
||||
"board-view": "Boardansicht",
|
||||
"board-view-cal": "Kalender",
|
||||
"board-view-swimlanes": "Swimlanes",
|
||||
"board-view-lists": "Listen",
|
||||
"bucket-example": "z.B. \"Löffelliste\"",
|
||||
"cancel": "Abbrechen",
|
||||
"card-archived": "Diese Karte wurde archiviert.",
|
||||
"card-archived": "Diese Karte wurde in den Papierkorb verschoben",
|
||||
"board-archived": "Dieses Board wurde in den Papierkorb verschoben.",
|
||||
"card-comments-title": "Diese Karte hat %s Kommentar(e).",
|
||||
"card-delete-notice": "Löschen ist unwiderruflich. Alle Aktionen die dieser Karte zugeordnet sind werden ebenfalls gelöscht.",
|
||||
"card-delete-pop": "Alle Aktionen werden vom Aktivitätsfeed entfernt und die Karte kann nicht mehr geöffnet werden. Das Löschen kann nicht widerrufen werden!",
|
||||
"card-delete-suggest-archive": "Sie können eine Karte archivieren, um sie vom Board zu entfernen und die Aktivitäten zu behalten.",
|
||||
"card-due": "Ende",
|
||||
"card-due-on": "Ende am",
|
||||
"card-delete-notice": "Löschen kann nicht rückgängig gemacht werden. Alle Aktionen, die dieser Karte zugeordnet sind, werden ebenfalls gelöscht.",
|
||||
"card-delete-pop": "Alle Aktionen werden aus dem Aktivitätsfeed entfernt und die Karte kann nicht wiedereröffnet werden. Die Aktion kann nicht rückgängig gemacht werden.",
|
||||
"card-delete-suggest-archive": "Sie können eine Karte in den Papierkorb verschieben, um sie vom Board zu entfernen und die Aktivitäten zu behalten.",
|
||||
"card-due": "Fällig",
|
||||
"card-due-on": "Fällig am",
|
||||
"card-spent": "Aufgewendete Zeit",
|
||||
"card-edit-attachments": "Anhänge ändern",
|
||||
"card-edit-custom-fields": "Benutzerdefinierte Felder editieren",
|
||||
"card-edit-labels": "Labels ändern",
|
||||
"card-edit-members": "Mitglieder ändern",
|
||||
"card-labels-title": "Labels für diese Karte ändern.",
|
||||
@@ -118,12 +126,19 @@
|
||||
"card-start": "Start",
|
||||
"card-start-on": "Start am",
|
||||
"cardAttachmentsPopup-title": "Anhängen von",
|
||||
"cardCustomField-datePopup-title": "Datum ändern",
|
||||
"cardCustomFieldsPopup-title": "Benutzerdefinierte Felder editieren",
|
||||
"cardDeletePopup-title": "Karte löschen?",
|
||||
"cardDetailsActionsPopup-title": "Kartenaktionen",
|
||||
"cardLabelsPopup-title": "Labels",
|
||||
"cardMembersPopup-title": "Mitglieder",
|
||||
"cardMorePopup-title": "Mehr",
|
||||
"cards": "Karten",
|
||||
"cards-count": "Karten",
|
||||
"casSignIn": "Mit CAS anmelden",
|
||||
"cardType-card": "Karte",
|
||||
"cardType-linkedCard": "Verknüpfte Karte",
|
||||
"cardType-linkedBoard": "Verknüpftes Board",
|
||||
"change": "Ändern",
|
||||
"change-avatar": "Profilbild ändern",
|
||||
"change-password": "Passwort ändern",
|
||||
@@ -134,13 +149,14 @@
|
||||
"changePasswordPopup-title": "Passwort ändern",
|
||||
"changePermissionsPopup-title": "Berechtigungen ändern",
|
||||
"changeSettingsPopup-title": "Einstellungen ändern",
|
||||
"subtasks": "Teilaufgaben",
|
||||
"checklists": "Checklisten",
|
||||
"click-to-star": "Klicken Sie, um das Board mit einem Stern zu markieren.",
|
||||
"click-to-unstar": "Klicken Sie, um den Stern vom Board zu entfernen.",
|
||||
"clipboard": "Zwischenablage oder Drag & Drop",
|
||||
"close": "Schließen",
|
||||
"close-board": "Board schließen",
|
||||
"close-board-pop": "Sie können das Board wiederherstellen, indem Sie den \"Archiv\"-Button in der Kopfzeile der Startseite anklicken.",
|
||||
"close-board-pop": "Sie können das Board wiederherstellen, indem Sie die Schaltfläche \"Papierkorb\" in der Kopfzeile der Startseite anklicken.",
|
||||
"color-black": "schwarz",
|
||||
"color-blue": "blau",
|
||||
"color-green": "grün",
|
||||
@@ -153,21 +169,43 @@
|
||||
"color-yellow": "gelb",
|
||||
"comment": "Kommentar",
|
||||
"comment-placeholder": "Kommentar schreiben",
|
||||
"comment-only": "Nur kommentierbar",
|
||||
"comment-only-desc": "Kann Karten nur Kommentieren",
|
||||
"comment-only": "Nur Kommentare",
|
||||
"comment-only-desc": "Kann Karten nur kommentieren.",
|
||||
"no-comments": "Keine Kommentare",
|
||||
"no-comments-desc": "Kann keine Kommentare und Aktivitäten sehen.",
|
||||
"computer": "Computer",
|
||||
"confirm-checklist-delete-dialog": "Sind Sie sicher, dass Sie die Checkliste löschen möchten?",
|
||||
"confirm-subtask-delete-dialog": "Wollen Sie die Teilaufgabe wirklich löschen?",
|
||||
"confirm-checklist-delete-dialog": "Wollen Sie die Checkliste wirklich löschen?",
|
||||
"copy-card-link-to-clipboard": "Kopiere Link zur Karte in die Zwischenablage",
|
||||
"linkCardPopup-title": "Karte verknüpfen",
|
||||
"searchCardPopup-title": "Karte suchen",
|
||||
"copyCardPopup-title": "Karte kopieren",
|
||||
"copyChecklistToManyCardsPopup-title": "Checklistenvorlage in mehrere Karten kopieren",
|
||||
"copyChecklistToManyCardsPopup-instructions": "Titel und Beschreibungen der Zielkarten im folgenden JSON-Format",
|
||||
"copyChecklistToManyCardsPopup-format": "[ {\"title\": \"Titel der ersten Karte\", \"description\":\"Beschreibung der ersten Karte\"}, {\"title\":\"Titel der zweiten Karte\",\"description\":\"Beschreibung der zweiten Karte\"},{\"title\":\"Titel der letzten Karte\",\"description\":\"Beschreibung der letzten Karte\"} ]",
|
||||
"create": "Erstellen",
|
||||
"createBoardPopup-title": "Board erstellen",
|
||||
"chooseBoardSourcePopup-title": "Board importieren",
|
||||
"createLabelPopup-title": "Label erstellen",
|
||||
"createCustomField": "Feld erstellen",
|
||||
"createCustomFieldPopup-title": "Feld erstellen",
|
||||
"current": "aktuell",
|
||||
"custom-field-delete-pop": "Dies wird das Feld aus allen Karten entfernen und den dazugehörigen Verlauf löschen. Die Aktion kann nicht rückgängig gemacht werden.",
|
||||
"custom-field-checkbox": "Kontrollkästchen",
|
||||
"custom-field-date": "Datum",
|
||||
"custom-field-dropdown": "Dropdownliste",
|
||||
"custom-field-dropdown-none": "(keiner)",
|
||||
"custom-field-dropdown-options": "Listenoptionen",
|
||||
"custom-field-dropdown-options-placeholder": "Drücken Sie die Eingabetaste, um weitere Optionen hinzuzufügen",
|
||||
"custom-field-dropdown-unknown": "(unbekannt)",
|
||||
"custom-field-number": "Zahl",
|
||||
"custom-field-text": "Text",
|
||||
"custom-fields": "Benutzerdefinierte Felder",
|
||||
"date": "Datum",
|
||||
"decline": "Ablehnen",
|
||||
"default-avatar": "Standard Profilbild",
|
||||
"delete": "Löschen",
|
||||
"deleteCustomFieldPopup-title": "Benutzerdefiniertes Feld löschen?",
|
||||
"deleteLabelPopup-title": "Label löschen?",
|
||||
"description": "Beschreibung",
|
||||
"disambiguateMultiLabelPopup-title": "Labels vereinheitlichen",
|
||||
@@ -181,7 +219,8 @@
|
||||
"edit-wip-limit": "WIP-Limit bearbeiten",
|
||||
"soft-wip-limit": "Soft WIP-Limit",
|
||||
"editCardStartDatePopup-title": "Startdatum ändern",
|
||||
"editCardDueDatePopup-title": "Enddatum ändern",
|
||||
"editCardDueDatePopup-title": "Fälligkeitsdatum ändern",
|
||||
"editCustomFieldPopup-title": "Feld bearbeiten",
|
||||
"editCardSpentTimePopup-title": "Aufgewendete Zeit ändern",
|
||||
"editLabelPopup-title": "Label ändern",
|
||||
"editNotificationPopup-title": "Benachrichtigung ändern",
|
||||
@@ -218,15 +257,19 @@
|
||||
"filter-clear": "Filter entfernen",
|
||||
"filter-no-label": "Kein Label",
|
||||
"filter-no-member": "Kein Mitglied",
|
||||
"filter-no-custom-fields": "Keine benutzerdefinierten Felder",
|
||||
"filter-on": "Filter ist aktiv",
|
||||
"filter-on-desc": "Sie filtern die Karten in diesem Board. Klicken Sie, um den Filter zu bearbeiten.",
|
||||
"filter-to-selection": "Ergebnisse auswählen",
|
||||
"advanced-filter-label": "Erweiterter Filter",
|
||||
"advanced-filter-description": "Der erweiterte Filter erlaubt die Eingabe von Zeichenfolgen, die folgende Operatoren enthalten: == != <= >= && || ( ). Ein Leerzeichen wird als Trennzeichen zwischen den Operatoren verwendet. Sie können nach allen benutzerdefinierten Feldern filtern, indem Sie deren Namen und Werte eingeben. Zum Beispiel: Feld1 == Wert1. Hinweis: Wenn Felder oder Werte Leerzeichen enthalten, müssen Sie sie in einfache Anführungszeichen setzen. Zum Beispiel: 'Feld 1' == 'Wert 1'. Um einzelne Steuerzeichen (' \\/) zu überspringen, können Sie \\ verwenden. Zum Beispiel: Feld1 == Ich bin\\'s. Sie können außerdem mehrere Bedingungen kombinieren. Zum Beispiel: F1 == W1 || F1 == W2. Normalerweise werden alle Operatoren von links nach rechts interpretiert. Sie können die Reihenfolge ändern, indem Sie Klammern setzen. Zum Beispiel: F1 == W1 && ( F2 == W2 || F2 == W3 ). Sie können Textfelder auch mithilfe regulärer Ausdrücke durchsuchen: F1 == /Tes.*/i",
|
||||
"fullname": "Vollständiger Name",
|
||||
"header-logo-title": "Zurück zur Board Seite.",
|
||||
"hide-system-messages": "Systemmeldungen ausblenden",
|
||||
"headerBarCreateBoardPopup-title": "Board erstellen",
|
||||
"home": "Home",
|
||||
"import": "Importieren",
|
||||
"link": "Verknüpfung",
|
||||
"import-board": "Board importieren",
|
||||
"import-board-c": "Board importieren",
|
||||
"import-board-title-trello": "Board von Trello importieren",
|
||||
@@ -252,7 +295,7 @@
|
||||
"keyboard-shortcuts": "Tastaturkürzel",
|
||||
"label-create": "Label erstellen",
|
||||
"label-default": "%s Label (Standard)",
|
||||
"label-delete-pop": "Diese Aktion ist unwiderruflich. Das Label wird von allen Karten entfernt und seine Historie wird gelöscht.",
|
||||
"label-delete-pop": "Aktion kann nicht rückgängig gemacht werden. Das Label wird von allen Karten entfernt und seine Historie gelöscht.",
|
||||
"labels": "Labels",
|
||||
"language": "Sprache",
|
||||
"last-admin-desc": "Sie können keine Rollen ändern, weil es mindestens einen Administrator geben muss.",
|
||||
@@ -260,8 +303,8 @@
|
||||
"leave-board-pop": "Sind Sie sicher, dass Sie __boardTitle__ verlassen möchten? Sie werden von allen Karten in diesem Board entfernt.",
|
||||
"leaveBoardPopup-title": "Board verlassen?",
|
||||
"link-card": "Link zu dieser Karte",
|
||||
"list-archive-cards": "Alle Karten in dieser Liste archivieren",
|
||||
"list-archive-cards-pop": "Alle Karten von dieser Liste werden vom Board entfernt. Um archivierte Karten anzuzeigen und wiederherzustellen, klicken Sie auf \"Menü\" > \"Archivierte Einträge\".",
|
||||
"list-archive-cards": "Alle Karten dieser Liste in den Papierkorb verschieben",
|
||||
"list-archive-cards-pop": "Alle Karten dieser Liste werden vom Board entfernt. Um Karten im Papierkorb anzuzeigen und wiederherzustellen, klicken Sie auf \"Menü\" > \"Papierkorb\".",
|
||||
"list-move-cards": "Alle Karten in dieser Liste verschieben",
|
||||
"list-select-cards": "Alle Karten in dieser Liste auswählen",
|
||||
"listActionPopup-title": "Listenaktionen",
|
||||
@@ -269,8 +312,8 @@
|
||||
"listImportCardPopup-title": "Eine Trello-Karte importieren",
|
||||
"listMorePopup-title": "Mehr",
|
||||
"link-list": "Link zu dieser Liste",
|
||||
"list-delete-pop": "Alle Aktionen werden aus dem Verlauf gelöscht. Die Liste kann nicht wiederhergestellt werden.",
|
||||
"list-delete-suggest-archive": "Listen können archiviert werden, um sie aus dem Board zu entfernen und den Verlauf zu erhalten.",
|
||||
"list-delete-pop": "Alle Aktionen werden aus dem Verlauf gelöscht und die Liste kann nicht wiederhergestellt werden.",
|
||||
"list-delete-suggest-archive": "Listen können in den Papierkorb verschoben werden, um sie aus dem Board zu entfernen und die Aktivitäten zu behalten.",
|
||||
"lists": "Listen",
|
||||
"swimlanes": "Swimlanes",
|
||||
"log-out": "Ausloggen",
|
||||
@@ -290,12 +333,12 @@
|
||||
"muted-info": "Sie werden nicht über Änderungen auf diesem Board benachrichtigt",
|
||||
"my-boards": "Meine Boards",
|
||||
"name": "Name",
|
||||
"no-archived-cards": "Keine archivierten Karten.",
|
||||
"no-archived-lists": "Keine archivierten Listen.",
|
||||
"no-archived-swimlanes": "Keine archivierten Swimlanes",
|
||||
"no-archived-cards": "Keine Karten im Papierkorb.",
|
||||
"no-archived-lists": "Keine Listen im Papierkorb.",
|
||||
"no-archived-swimlanes": "Keine Swimlanes im Papierkorb.",
|
||||
"no-results": "Keine Ergebnisse",
|
||||
"normal": "Normal",
|
||||
"normal-desc": "Kann Karten anschauen und bearbeiten, aber keine Einstellungen ändern.",
|
||||
"normal-desc": "Kann Karten anzeigen und bearbeiten, aber keine Einstellungen ändern.",
|
||||
"not-accepted-yet": "Die Einladung wurde noch nicht angenommen",
|
||||
"notify-participate": "Benachrichtigungen zu allen Karten erhalten, an denen Sie teilnehmen",
|
||||
"notify-watch": "Benachrichtigungen über alle Boards, Listen oder Karten erhalten, die Sie beobachten",
|
||||
@@ -328,6 +371,8 @@
|
||||
"restore": "Wiederherstellen",
|
||||
"save": "Speichern",
|
||||
"search": "Suchen",
|
||||
"search-cards": "Suche nach Kartentiteln und Beschreibungen auf diesem Board",
|
||||
"search-example": "Suchbegriff",
|
||||
"select-color": "Farbe auswählen",
|
||||
"set-wip-limit-value": "Setzen Sie ein Limit für die maximale Anzahl von Aufgaben in dieser Liste",
|
||||
"setWipLimitPopup-title": "WIP-Limit setzen",
|
||||
@@ -349,17 +394,18 @@
|
||||
"starred-boards-description": "Markierte Boards erscheinen oben in ihrer Boardliste.",
|
||||
"subscribe": "Abonnieren",
|
||||
"team": "Team",
|
||||
"this-board": "dieses Board",
|
||||
"this-board": "diesem Board",
|
||||
"this-card": "diese Karte",
|
||||
"spent-time-hours": "Aufgewendete Zeit (Stunden)",
|
||||
"overtime-hours": "Überzeit (Stunden)",
|
||||
"overtime": "Überzeit",
|
||||
"has-overtime-cards": "Hat Karten mit Überzeit",
|
||||
"overtime-hours": "Mehrarbeit (Stunden)",
|
||||
"overtime": "Mehrarbeit",
|
||||
"has-overtime-cards": "Hat Karten mit Mehrarbeit",
|
||||
"has-spenttime-cards": "Hat Karten mit aufgewendeten Zeiten",
|
||||
"time": "Zeit",
|
||||
"title": "Titel",
|
||||
"tracking": "Folgen",
|
||||
"tracking-info": "Sie werden über alle Änderungen an Karten benachrichtigt, an denen Sie als Ersteller oder Mitglied beteiligt sind.",
|
||||
"type": "Typ",
|
||||
"unassign-member": "Mitglied entfernen",
|
||||
"unsaved-description": "Sie haben eine nicht gespeicherte Änderung.",
|
||||
"unwatch": "Beobachtung entfernen",
|
||||
@@ -368,7 +414,7 @@
|
||||
"uploaded-avatar": "Profilbild hochgeladen",
|
||||
"username": "Benutzername",
|
||||
"view-it": "Ansehen",
|
||||
"warn-list-archived": "Warnung: Diese Karte befindet sich in einer archivierten Liste",
|
||||
"warn-list-archived": "Warnung: Diese Karte befindet sich in einer Liste im Papierkorb!",
|
||||
"watch": "Beobachten",
|
||||
"watching": "Beobachten",
|
||||
"watching-info": "Sie werden über alle Änderungen in diesem Board benachrichtigt",
|
||||
@@ -424,11 +470,42 @@
|
||||
"hours": "Stunden",
|
||||
"minutes": "Minuten",
|
||||
"seconds": "Sekunden",
|
||||
"show-field-on-card": "Zeige dieses Feld auf der Karte",
|
||||
"yes": "Ja",
|
||||
"no": "Nein",
|
||||
"accounts": "Konten",
|
||||
"accounts-allowEmailChange": "E-Mail ändern zulassen",
|
||||
"accounts-allowEmailChange": "Ändern der E-Mailadresse erlauben",
|
||||
"accounts-allowUserNameChange": "Ändern des Benutzernamens erlauben",
|
||||
"createdAt": "Erstellt am",
|
||||
"verified": "Geprüft",
|
||||
"active": "Aktiv"
|
||||
"active": "Aktiv",
|
||||
"card-received": "Empfangen",
|
||||
"card-received-on": "Empfangen am",
|
||||
"card-end": "Ende",
|
||||
"card-end-on": "Endet am",
|
||||
"editCardReceivedDatePopup-title": "Empfangsdatum ändern",
|
||||
"editCardEndDatePopup-title": "Enddatum ändern",
|
||||
"assigned-by": "Zugewiesen von",
|
||||
"requested-by": "Angefordert von",
|
||||
"board-delete-notice": "Löschen kann nicht rückgängig gemacht werden. Sie werden alle Listen, Karten und Aktionen, die mit diesem Board verbunden sind, verlieren.",
|
||||
"delete-board-confirm-popup": "Alle Listen, Karten, Labels und Akivitäten werden gelöscht und Sie können die Inhalte des Boards nicht wiederherstellen! Die Aktion kann nicht rückgängig gemacht werden.",
|
||||
"boardDeletePopup-title": "Board löschen?",
|
||||
"delete-board": "Board löschen",
|
||||
"default-subtasks-board": "Teilaufgabe für __board__ Board",
|
||||
"default": "Standard",
|
||||
"queue": "Warteschlange",
|
||||
"subtask-settings": "Einstellungen für Teilaufgaben",
|
||||
"boardSubtaskSettingsPopup-title": "Boardeinstellungen für Teilaufgaben",
|
||||
"show-subtasks-field": "Karten können Teilaufgaben haben",
|
||||
"deposit-subtasks-board": "Teilaufgaben in diesem Board ablegen:",
|
||||
"deposit-subtasks-list": "Zielliste für hier abgelegte Teilaufgaben:",
|
||||
"show-parent-in-minicard": "Übergeordnetes Element auf Minikarte anzeigen:",
|
||||
"prefix-with-full-path": "Vollständiger Pfad über Titel",
|
||||
"prefix-with-parent": "Über Titel",
|
||||
"subtext-with-full-path": "Vollständiger Pfad unter Titel",
|
||||
"subtext-with-parent": "Unter Titel",
|
||||
"change-card-parent": "Übergeordnete Karte ändern",
|
||||
"parent-card": "Übergeordnete Karte",
|
||||
"source-board": "Quellboard",
|
||||
"no-parent": "Nicht anzeigen"
|
||||
}
|
||||
+106
-29
@@ -2,17 +2,19 @@
|
||||
"accept": "Accept",
|
||||
"act-activity-notify": "[Wekan] Activity Notification",
|
||||
"act-addAttachment": "attached __attachment__ to __card__",
|
||||
"act-addSubtask": "added subtask __checklist__ to __card__",
|
||||
"act-addChecklist": "added checklist __checklist__ to __card__",
|
||||
"act-addChecklistItem": "added __checklistItem__ to checklist __checklist__ on __card__",
|
||||
"act-addComment": "commented on __card__: __comment__",
|
||||
"act-createBoard": "created __board__",
|
||||
"act-createCard": "added __card__ to __list__",
|
||||
"act-createCustomField": "created custom field __customField__",
|
||||
"act-createList": "added __list__ to __board__",
|
||||
"act-addBoardMember": "added __member__ to __board__",
|
||||
"act-archivedBoard": "archived __board__",
|
||||
"act-archivedCard": "archived __card__",
|
||||
"act-archivedList": "archived __list__",
|
||||
"act-archivedSwimlane": "archived __swimlane__",
|
||||
"act-archivedBoard": "__board__ moved to Recycle Bin",
|
||||
"act-archivedCard": "__card__ moved to Recycle Bin",
|
||||
"act-archivedList": "__list__ moved to Recycle Bin",
|
||||
"act-archivedSwimlane": "__swimlane__ moved to Recycle Bin",
|
||||
"act-importBoard": "imported __board__",
|
||||
"act-importCard": "imported __card__",
|
||||
"act-importList": "imported __list__",
|
||||
@@ -27,9 +29,10 @@
|
||||
"activities": "Activities",
|
||||
"activity": "Activity",
|
||||
"activity-added": "added %s to %s",
|
||||
"activity-archived": "archived %s",
|
||||
"activity-archived": "%s moved to Recycle Bin",
|
||||
"activity-attached": "attached %s to %s",
|
||||
"activity-created": "created %s",
|
||||
"activity-customfield-created": "created custom field %s",
|
||||
"activity-excluded": "excluded %s from %s",
|
||||
"activity-imported": "imported %s into %s from %s",
|
||||
"activity-imported-board": "imported %s from %s",
|
||||
@@ -39,6 +42,7 @@
|
||||
"activity-removed": "removed %s from %s",
|
||||
"activity-sent": "sent %s to %s",
|
||||
"activity-unjoined": "unjoined %s",
|
||||
"activity-subtask-added": "added subtask to %s",
|
||||
"activity-checklist-added": "added checklist to %s",
|
||||
"activity-checklist-item-added": "added checklist item to '%s' in %s",
|
||||
"add": "Προσθήκη",
|
||||
@@ -46,6 +50,7 @@
|
||||
"add-board": "Add Board",
|
||||
"add-card": "Προσθήκη Κάρτας",
|
||||
"add-swimlane": "Add Swimlane",
|
||||
"add-subtask": "Add Subtask",
|
||||
"add-checklist": "Add Checklist",
|
||||
"add-checklist-item": "Add an item to checklist",
|
||||
"add-cover": "Add Cover",
|
||||
@@ -64,19 +69,19 @@
|
||||
"and-n-other-card_plural": "And __count__ other cards",
|
||||
"apply": "Εφαρμογή",
|
||||
"app-is-offline": "Wekan is loading, please wait. Refreshing the page will cause data loss. If Wekan does not load, please check that Wekan server has not stopped.",
|
||||
"archive": "Archive",
|
||||
"archive-all": "Archive All",
|
||||
"archive-board": "Archive Board",
|
||||
"archive-card": "Archive Card",
|
||||
"archive-list": "Archive List",
|
||||
"archive-swimlane": "Archive Swimlane",
|
||||
"archive-selection": "Archive selection",
|
||||
"archiveBoardPopup-title": "Archive Board?",
|
||||
"archived-items": "Archived Items",
|
||||
"archived-boards": "Archived Boards",
|
||||
"archive": "Move to Recycle Bin",
|
||||
"archive-all": "Move All to Recycle Bin",
|
||||
"archive-board": "Move Board to Recycle Bin",
|
||||
"archive-card": "Move Card to Recycle Bin",
|
||||
"archive-list": "Move List to Recycle Bin",
|
||||
"archive-swimlane": "Move Swimlane to Recycle Bin",
|
||||
"archive-selection": "Move selection to Recycle Bin",
|
||||
"archiveBoardPopup-title": "Move Board to Recycle Bin?",
|
||||
"archived-items": "Recycle Bin",
|
||||
"archived-boards": "Boards in Recycle Bin",
|
||||
"restore-board": "Restore Board",
|
||||
"no-archived-boards": "No Archived Boards.",
|
||||
"archives": "Archives",
|
||||
"no-archived-boards": "No Boards in Recycle Bin.",
|
||||
"archives": "Recycle Bin",
|
||||
"assign-member": "Assign member",
|
||||
"attached": "attached",
|
||||
"attachment": "Attachment",
|
||||
@@ -98,19 +103,22 @@
|
||||
"boardMenuPopup-title": "Board Menu",
|
||||
"boards": "Boards",
|
||||
"board-view": "Board View",
|
||||
"board-view-cal": "Calendar",
|
||||
"board-view-swimlanes": "Swimlanes",
|
||||
"board-view-lists": "Λίστες",
|
||||
"bucket-example": "Like “Bucket List” for example",
|
||||
"cancel": "Ακύρωση",
|
||||
"card-archived": "This card is archived.",
|
||||
"card-archived": "This card is moved to Recycle Bin.",
|
||||
"board-archived": "This board is moved to Recycle Bin.",
|
||||
"card-comments-title": "This card has %s comment.",
|
||||
"card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.",
|
||||
"card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.",
|
||||
"card-delete-suggest-archive": "You can archive a card to remove it from the board and preserve the activity.",
|
||||
"card-delete-suggest-archive": "You can move a card to Recycle Bin to remove it from the board and preserve the activity.",
|
||||
"card-due": "Έως",
|
||||
"card-due-on": "Έως τις",
|
||||
"card-spent": "Spent Time",
|
||||
"card-edit-attachments": "Edit attachments",
|
||||
"card-edit-custom-fields": "Edit custom fields",
|
||||
"card-edit-labels": "Edit labels",
|
||||
"card-edit-members": "Edit members",
|
||||
"card-labels-title": "Change the labels for the card.",
|
||||
@@ -118,12 +126,19 @@
|
||||
"card-start": "Start",
|
||||
"card-start-on": "Starts on",
|
||||
"cardAttachmentsPopup-title": "Attach From",
|
||||
"cardCustomField-datePopup-title": "Change date",
|
||||
"cardCustomFieldsPopup-title": "Edit custom fields",
|
||||
"cardDeletePopup-title": "Διαγραφή Κάρτας;",
|
||||
"cardDetailsActionsPopup-title": "Card Actions",
|
||||
"cardLabelsPopup-title": "Ετικέτες",
|
||||
"cardMembersPopup-title": "Μέλοι",
|
||||
"cardMorePopup-title": "Περισσότερα",
|
||||
"cards": "Κάρτες",
|
||||
"cards-count": "Κάρτες",
|
||||
"casSignIn": "Sign In with CAS",
|
||||
"cardType-card": "Card",
|
||||
"cardType-linkedCard": "Linked Card",
|
||||
"cardType-linkedBoard": "Linked Board",
|
||||
"change": "Αλλαγή",
|
||||
"change-avatar": "Change Avatar",
|
||||
"change-password": "Αλλαγή Κωδικού",
|
||||
@@ -134,13 +149,14 @@
|
||||
"changePasswordPopup-title": "Αλλαγή Κωδικού",
|
||||
"changePermissionsPopup-title": "Change Permissions",
|
||||
"changeSettingsPopup-title": "Αλλαγή Ρυθμίσεων",
|
||||
"subtasks": "Subtasks",
|
||||
"checklists": "Checklists",
|
||||
"click-to-star": "Click to star this board.",
|
||||
"click-to-unstar": "Click to unstar this board.",
|
||||
"clipboard": "Clipboard or drag & drop",
|
||||
"close": "Κλείσιμο",
|
||||
"close-board": "Close Board",
|
||||
"close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
|
||||
"close-board-pop": "You will be able to restore the board by clicking the “Recycle Bin” button from the home header.",
|
||||
"color-black": "μαύρο",
|
||||
"color-blue": "μπλε",
|
||||
"color-green": "πράσινο",
|
||||
@@ -155,19 +171,41 @@
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"no-comments": "No comments",
|
||||
"no-comments-desc": "Can not see comments and activities.",
|
||||
"computer": "Υπολογιστής",
|
||||
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist",
|
||||
"confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?",
|
||||
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?",
|
||||
"copy-card-link-to-clipboard": "Copy card link to clipboard",
|
||||
"linkCardPopup-title": "Link Card",
|
||||
"searchCardPopup-title": "Search Card",
|
||||
"copyCardPopup-title": "Copy Card",
|
||||
"copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards",
|
||||
"copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format",
|
||||
"copyChecklistToManyCardsPopup-format": "[ {\"title\": \"First card title\", \"description\":\"First card description\"}, {\"title\":\"Second card title\",\"description\":\"Second card description\"},{\"title\":\"Last card title\",\"description\":\"Last card description\"} ]",
|
||||
"create": "Δημιουργία",
|
||||
"createBoardPopup-title": "Create Board",
|
||||
"chooseBoardSourcePopup-title": "Import board",
|
||||
"createLabelPopup-title": "Create Label",
|
||||
"createCustomField": "Create Field",
|
||||
"createCustomFieldPopup-title": "Create Field",
|
||||
"current": "current",
|
||||
"custom-field-delete-pop": "There is no undo. This will remove this custom field from all cards and destroy its history.",
|
||||
"custom-field-checkbox": "Checkbox",
|
||||
"custom-field-date": "Ημερομηνία",
|
||||
"custom-field-dropdown": "Dropdown List",
|
||||
"custom-field-dropdown-none": "(none)",
|
||||
"custom-field-dropdown-options": "List Options",
|
||||
"custom-field-dropdown-options-placeholder": "Press enter to add more options",
|
||||
"custom-field-dropdown-unknown": "(unknown)",
|
||||
"custom-field-number": "Number",
|
||||
"custom-field-text": "Text",
|
||||
"custom-fields": "Custom Fields",
|
||||
"date": "Ημερομηνία",
|
||||
"decline": "Decline",
|
||||
"default-avatar": "Default avatar",
|
||||
"delete": "Διαγραφή",
|
||||
"deleteCustomFieldPopup-title": "Delete Custom Field?",
|
||||
"deleteLabelPopup-title": "Delete Label?",
|
||||
"description": "Description",
|
||||
"disambiguateMultiLabelPopup-title": "Disambiguate Label Action",
|
||||
@@ -182,6 +220,7 @@
|
||||
"soft-wip-limit": "Soft WIP Limit",
|
||||
"editCardStartDatePopup-title": "Change start date",
|
||||
"editCardDueDatePopup-title": "Change due date",
|
||||
"editCustomFieldPopup-title": "Edit Field",
|
||||
"editCardSpentTimePopup-title": "Change spent time",
|
||||
"editLabelPopup-title": "Change Label",
|
||||
"editNotificationPopup-title": "Edit Notification",
|
||||
@@ -218,15 +257,19 @@
|
||||
"filter-clear": "Clear filter",
|
||||
"filter-no-label": "No label",
|
||||
"filter-no-member": "Κανένα μέλος",
|
||||
"filter-no-custom-fields": "No Custom Fields",
|
||||
"filter-on": "Filter is on",
|
||||
"filter-on-desc": "You are filtering cards on this board. Click here to edit filter.",
|
||||
"filter-to-selection": "Filter to selection",
|
||||
"advanced-filter-label": "Advanced Filter",
|
||||
"advanced-filter-description": "Advanced Filter allows to write a string containing following operators: == != <= >= && || ( ) A space is used as a separator between the Operators. You can filter for all Custom Fields by typing their names and values. For Example: Field1 == Value1. Note: If fields or values contains spaces, you need to encapsulate them into single quotes. For Example: 'Field 1' == 'Value 1'. For single control characters (' \\/) to be skipped, you can use \\. For example: Field1 == I\\'m. Also you can combine multiple conditions. For Example: F1 == V1 || F1 == V2. Normally all operators are interpreted from left to right. You can change the order by placing brackets. For Example: F1 == V1 && ( F2 == V2 || F2 == V3 ). Also you can search text fields using regex: F1 == /Tes.*/i",
|
||||
"fullname": "Πλήρες Όνομα",
|
||||
"header-logo-title": "Go back to your boards page.",
|
||||
"hide-system-messages": "Hide system messages",
|
||||
"headerBarCreateBoardPopup-title": "Create Board",
|
||||
"home": "Home",
|
||||
"import": "Εισαγωγή",
|
||||
"link": "Link",
|
||||
"import-board": "import board",
|
||||
"import-board-c": "Import board",
|
||||
"import-board-title-trello": "Import board from Trello",
|
||||
@@ -260,8 +303,8 @@
|
||||
"leave-board-pop": "Are you sure you want to leave __boardTitle__? You will be removed from all cards on this board.",
|
||||
"leaveBoardPopup-title": "Leave Board ?",
|
||||
"link-card": "Link to this card",
|
||||
"list-archive-cards": "Archive all cards in this list",
|
||||
"list-archive-cards-pop": "This will remove all the cards in this list from the board. To view archived cards and bring them back to the board, click “Menu” > “Archived Items”.",
|
||||
"list-archive-cards": "Move all cards in this list to Recycle Bin",
|
||||
"list-archive-cards-pop": "This will remove all the cards in this list from the board. To view cards in Recycle Bin and bring them back to the board, click “Menu” > “Recycle Bin”.",
|
||||
"list-move-cards": "Move all cards in this list",
|
||||
"list-select-cards": "Select all cards in this list",
|
||||
"listActionPopup-title": "List Actions",
|
||||
@@ -270,7 +313,7 @@
|
||||
"listMorePopup-title": "Περισσότερα",
|
||||
"link-list": "Link to this list",
|
||||
"list-delete-pop": "All actions will be removed from the activity feed and you won't be able to recover the list. There is no undo.",
|
||||
"list-delete-suggest-archive": "You can archive a list to remove it from the board and preserve the activity.",
|
||||
"list-delete-suggest-archive": "You can move a list to Recycle Bin to remove it from the board and preserve the activity.",
|
||||
"lists": "Λίστες",
|
||||
"swimlanes": "Swimlanes",
|
||||
"log-out": "Αποσύνδεση",
|
||||
@@ -290,9 +333,9 @@
|
||||
"muted-info": "You will never be notified of any changes in this board",
|
||||
"my-boards": "My Boards",
|
||||
"name": "Όνομα",
|
||||
"no-archived-cards": "No archived cards.",
|
||||
"no-archived-lists": "No archived lists.",
|
||||
"no-archived-swimlanes": "No archived swimlanes.",
|
||||
"no-archived-cards": "No cards in Recycle Bin.",
|
||||
"no-archived-lists": "No lists in Recycle Bin.",
|
||||
"no-archived-swimlanes": "No swimlanes in Recycle Bin.",
|
||||
"no-results": "Κανένα αποτέλεσμα",
|
||||
"normal": "Normal",
|
||||
"normal-desc": "Can view and edit cards. Can't change settings.",
|
||||
@@ -328,6 +371,8 @@
|
||||
"restore": "Restore",
|
||||
"save": "Αποθήκευση",
|
||||
"search": "Αναζήτηση",
|
||||
"search-cards": "Search from card titles and descriptions on this board",
|
||||
"search-example": "Text to search for?",
|
||||
"select-color": "Επιλέξτε Χρώμα",
|
||||
"set-wip-limit-value": "Set a limit for the maximum number of tasks in this list",
|
||||
"setWipLimitPopup-title": "Set WIP Limit",
|
||||
@@ -360,6 +405,7 @@
|
||||
"title": "Τίτλος",
|
||||
"tracking": "Tracking",
|
||||
"tracking-info": "You will be notified of any changes to those cards you are involved as creator or member.",
|
||||
"type": "Type",
|
||||
"unassign-member": "Unassign member",
|
||||
"unsaved-description": "You have an unsaved description.",
|
||||
"unwatch": "Unwatch",
|
||||
@@ -368,7 +414,7 @@
|
||||
"uploaded-avatar": "Uploaded an avatar",
|
||||
"username": "Όνομα Χρήστη",
|
||||
"view-it": "View it",
|
||||
"warn-list-archived": "warning: this card is in an archived list",
|
||||
"warn-list-archived": "warning: this card is in an list at Recycle Bin",
|
||||
"watch": "Watch",
|
||||
"watching": "Watching",
|
||||
"watching-info": "You will be notified of any change in this board",
|
||||
@@ -424,11 +470,42 @@
|
||||
"hours": "ώρες",
|
||||
"minutes": "λεπτά",
|
||||
"seconds": "δευτερόλεπτα",
|
||||
"show-field-on-card": "Show this field on card",
|
||||
"yes": "Ναι",
|
||||
"no": "Όχι",
|
||||
"accounts": "Λογαριασμοί",
|
||||
"accounts-allowEmailChange": "Allow Email Change",
|
||||
"accounts-allowUserNameChange": "Allow Username Change",
|
||||
"createdAt": "Created at",
|
||||
"verified": "Verified",
|
||||
"active": "Active"
|
||||
"active": "Active",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
"card-end-on": "Ends on",
|
||||
"editCardReceivedDatePopup-title": "Change received date",
|
||||
"editCardEndDatePopup-title": "Change end date",
|
||||
"assigned-by": "Assigned By",
|
||||
"requested-by": "Requested By",
|
||||
"board-delete-notice": "Deleting is permanent. You will lose all lists, cards and actions associated with this board.",
|
||||
"delete-board-confirm-popup": "All lists, cards, labels, and activities will be deleted and you won't be able to recover the board contents. There is no undo.",
|
||||
"boardDeletePopup-title": "Delete Board?",
|
||||
"delete-board": "Delete Board",
|
||||
"default-subtasks-board": "Subtasks for __board__ board",
|
||||
"default": "Default",
|
||||
"queue": "Queue",
|
||||
"subtask-settings": "Subtasks Settings",
|
||||
"boardSubtaskSettingsPopup-title": "Board Subtasks Settings",
|
||||
"show-subtasks-field": "Cards can have subtasks",
|
||||
"deposit-subtasks-board": "Deposit subtasks to this board:",
|
||||
"deposit-subtasks-list": "Landing list for subtasks deposited here:",
|
||||
"show-parent-in-minicard": "Show parent in minicard:",
|
||||
"prefix-with-full-path": "Prefix with full path",
|
||||
"prefix-with-parent": "Prefix with parent",
|
||||
"subtext-with-full-path": "Subtext with full path",
|
||||
"subtext-with-parent": "Subtext with parent",
|
||||
"change-card-parent": "Change card's parent",
|
||||
"parent-card": "Parent card",
|
||||
"source-board": "Source board",
|
||||
"no-parent": "Don't show parent"
|
||||
}
|
||||
+108
-31
@@ -2,17 +2,19 @@
|
||||
"accept": "Accept",
|
||||
"act-activity-notify": "[Wekan] Activity Notification",
|
||||
"act-addAttachment": "attached _ attachment _ to _ card _",
|
||||
"act-addSubtask": "added subtask __checklist__ to __card__",
|
||||
"act-addChecklist": "added checklist __checklist__ to __card__",
|
||||
"act-addChecklistItem": "added __checklistItem__ to checklist __checklist__ on __card__",
|
||||
"act-addComment": "commented on __card__: __comment__",
|
||||
"act-createBoard": "created __board__",
|
||||
"act-createCard": "added __card__ to __list__",
|
||||
"act-createCustomField": "created custom field __customField__",
|
||||
"act-createList": "added __list__ to __board__",
|
||||
"act-addBoardMember": "added __member__ to __board__",
|
||||
"act-archivedBoard": "archived __board__",
|
||||
"act-archivedCard": "archived __card__",
|
||||
"act-archivedList": "archived __list__",
|
||||
"act-archivedSwimlane": "archived __swimlane__",
|
||||
"act-archivedBoard": "__board__ moved to Recycle Bin",
|
||||
"act-archivedCard": "__card__ moved to Recycle Bin",
|
||||
"act-archivedList": "__list__ moved to Recycle Bin",
|
||||
"act-archivedSwimlane": "__swimlane__ moved to Recycle Bin",
|
||||
"act-importBoard": "imported __board__",
|
||||
"act-importCard": "imported __card__",
|
||||
"act-importList": "imported __list__",
|
||||
@@ -27,9 +29,10 @@
|
||||
"activities": "Activities",
|
||||
"activity": "Activity",
|
||||
"activity-added": "added %s to %s",
|
||||
"activity-archived": "archived %s",
|
||||
"activity-archived": "%s moved to Recycle Bin",
|
||||
"activity-attached": "attached %s to %s",
|
||||
"activity-created": "created %s",
|
||||
"activity-customfield-created": "created custom field %s",
|
||||
"activity-excluded": "excluded %s from %s",
|
||||
"activity-imported": "imported %s into %s from %s",
|
||||
"activity-imported-board": "imported %s from %s",
|
||||
@@ -39,6 +42,7 @@
|
||||
"activity-removed": "removed %s from %s",
|
||||
"activity-sent": "sent %s to %s",
|
||||
"activity-unjoined": "unjoined %s",
|
||||
"activity-subtask-added": "added subtask to %s",
|
||||
"activity-checklist-added": "added checklist to %s",
|
||||
"activity-checklist-item-added": "added checklist item to '%s' in %s",
|
||||
"add": "Add",
|
||||
@@ -46,6 +50,7 @@
|
||||
"add-board": "Add Board",
|
||||
"add-card": "Add Card",
|
||||
"add-swimlane": "Add Swimlane",
|
||||
"add-subtask": "Add Subtask",
|
||||
"add-checklist": "Add Checklist",
|
||||
"add-checklist-item": "Add an item to checklist",
|
||||
"add-cover": "Add Cover",
|
||||
@@ -64,19 +69,19 @@
|
||||
"and-n-other-card_plural": "And __count__ other cards",
|
||||
"apply": "Apply",
|
||||
"app-is-offline": "Wekan is loading, please wait. Refreshing the page will cause data loss. If Wekan does not load, please check that Wekan server has not stopped.",
|
||||
"archive": "Archive",
|
||||
"archive-all": "Archive All",
|
||||
"archive-board": "Archive Board",
|
||||
"archive-card": "Archive Card",
|
||||
"archive-list": "Archive List",
|
||||
"archive-swimlane": "Archive Swimlane",
|
||||
"archive-selection": "Archive selection",
|
||||
"archiveBoardPopup-title": "Archive Board?",
|
||||
"archived-items": "Archived Items",
|
||||
"archived-boards": "Archived Boards",
|
||||
"archive": "Move to Recycle Bin",
|
||||
"archive-all": "Move All to Recycle Bin",
|
||||
"archive-board": "Move Board to Recycle Bin",
|
||||
"archive-card": "Move Card to Recycle Bin",
|
||||
"archive-list": "Move List to Recycle Bin",
|
||||
"archive-swimlane": "Move Swimlane to Recycle Bin",
|
||||
"archive-selection": "Move selection to Recycle Bin",
|
||||
"archiveBoardPopup-title": "Move Board to Recycle Bin?",
|
||||
"archived-items": "Recycle Bin",
|
||||
"archived-boards": "Boards in Recycle Bin",
|
||||
"restore-board": "Restore Board",
|
||||
"no-archived-boards": "No Archived Boards.",
|
||||
"archives": "Archives",
|
||||
"no-archived-boards": "No Boards in Recycle Bin.",
|
||||
"archives": "Recycle Bin",
|
||||
"assign-member": "Assign member",
|
||||
"attached": "attached",
|
||||
"attachment": "Attachment",
|
||||
@@ -86,7 +91,7 @@
|
||||
"auto-watch": "Automatically watch boards when they are created",
|
||||
"avatar-too-big": "The avatar is too large (70KB max)",
|
||||
"back": "Back",
|
||||
"board-change-color": "Change color",
|
||||
"board-change-color": "Change colour",
|
||||
"board-nb-stars": "%s stars",
|
||||
"board-not-found": "Board not found",
|
||||
"board-private-info": "This board will be <strong>private</strong>.",
|
||||
@@ -98,19 +103,22 @@
|
||||
"boardMenuPopup-title": "Board Menu",
|
||||
"boards": "Boards",
|
||||
"board-view": "Board View",
|
||||
"board-view-cal": "Calendar",
|
||||
"board-view-swimlanes": "Swimlanes",
|
||||
"board-view-lists": "Lists",
|
||||
"bucket-example": "Like “Bucket List” for example",
|
||||
"cancel": "Cancel",
|
||||
"card-archived": "This card is archived.",
|
||||
"card-archived": "This card is moved to Recycle Bin.",
|
||||
"board-archived": "This board is moved to Recycle Bin.",
|
||||
"card-comments-title": "This card has %s comment.",
|
||||
"card-delete-notice": "Deleting is permanent. You will lose all actions associated with this card.",
|
||||
"card-delete-pop": "All actions will be removed from the activity feed and you won't be able to re-open the card. There is no undo.",
|
||||
"card-delete-suggest-archive": "You can archive a card to remove it from the board and preserve the activity.",
|
||||
"card-delete-suggest-archive": "You can move a card to Recycle Bin to remove it from the board and preserve the activity.",
|
||||
"card-due": "Due",
|
||||
"card-due-on": "Due on",
|
||||
"card-spent": "Spent Time",
|
||||
"card-edit-attachments": "Edit attachments",
|
||||
"card-edit-custom-fields": "Edit custom fields",
|
||||
"card-edit-labels": "Edit labels",
|
||||
"card-edit-members": "Edit members",
|
||||
"card-labels-title": "Change the labels for the card.",
|
||||
@@ -118,12 +126,19 @@
|
||||
"card-start": "Start",
|
||||
"card-start-on": "Starts on",
|
||||
"cardAttachmentsPopup-title": "Attach From",
|
||||
"cardCustomField-datePopup-title": "Change date",
|
||||
"cardCustomFieldsPopup-title": "Edit custom fields",
|
||||
"cardDeletePopup-title": "Delete Card?",
|
||||
"cardDetailsActionsPopup-title": "Card Actions",
|
||||
"cardLabelsPopup-title": "Labels",
|
||||
"cardMembersPopup-title": "Members",
|
||||
"cardMorePopup-title": "More",
|
||||
"cards": "Cards",
|
||||
"cards-count": "Cards",
|
||||
"casSignIn": "Sign In with CAS",
|
||||
"cardType-card": "Card",
|
||||
"cardType-linkedCard": "Linked Card",
|
||||
"cardType-linkedBoard": "Linked Board",
|
||||
"change": "Change",
|
||||
"change-avatar": "Change Avatar",
|
||||
"change-password": "Change Password",
|
||||
@@ -134,13 +149,14 @@
|
||||
"changePasswordPopup-title": "Change Password",
|
||||
"changePermissionsPopup-title": "Change Permissions",
|
||||
"changeSettingsPopup-title": "Change Settings",
|
||||
"subtasks": "Subtasks",
|
||||
"checklists": "Checklists",
|
||||
"click-to-star": "Click to star this board.",
|
||||
"click-to-unstar": "Click to unstar this board.",
|
||||
"clipboard": "Clipboard or drag & drop",
|
||||
"close": "Close",
|
||||
"close-board": "Close Board",
|
||||
"close-board-pop": "You will be able to restore the board by clicking the “Archives” button from the home header.",
|
||||
"close-board-pop": "You will be able to restore the board by clicking the “Recycle Bin” button from the home header.",
|
||||
"color-black": "black",
|
||||
"color-blue": "blue",
|
||||
"color-green": "green",
|
||||
@@ -155,19 +171,41 @@
|
||||
"comment-placeholder": "Write Comment",
|
||||
"comment-only": "Comment only",
|
||||
"comment-only-desc": "Can comment on cards only.",
|
||||
"no-comments": "No comments",
|
||||
"no-comments-desc": "Can not see comments and activities.",
|
||||
"computer": "Computer",
|
||||
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist",
|
||||
"confirm-subtask-delete-dialog": "Are you sure you want to delete subtask?",
|
||||
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?",
|
||||
"copy-card-link-to-clipboard": "Copy card link to clipboard",
|
||||
"linkCardPopup-title": "Link Card",
|
||||
"searchCardPopup-title": "Search Card",
|
||||
"copyCardPopup-title": "Copy Card",
|
||||
"copyChecklistToManyCardsPopup-title": "Copy Checklist Template to Many Cards",
|
||||
"copyChecklistToManyCardsPopup-instructions": "Destination Card Titles and Descriptions in this JSON format",
|
||||
"copyChecklistToManyCardsPopup-format": "[ {\"title\": \"First card title\", \"description\":\"First card description\"}, {\"title\":\"Second card title\",\"description\":\"Second card description\"},{\"title\":\"Last card title\",\"description\":\"Last card description\"} ]",
|
||||
"create": "Create",
|
||||
"createBoardPopup-title": "Create Board",
|
||||
"chooseBoardSourcePopup-title": "Import board",
|
||||
"createLabelPopup-title": "Create Label",
|
||||
"createCustomField": "Create Field",
|
||||
"createCustomFieldPopup-title": "Create Field",
|
||||
"current": "current",
|
||||
"custom-field-delete-pop": "There is no undo. This will remove this custom field from all cards and destroy its history.",
|
||||
"custom-field-checkbox": "Checkbox",
|
||||
"custom-field-date": "Date",
|
||||
"custom-field-dropdown": "Dropdown List",
|
||||
"custom-field-dropdown-none": "(none)",
|
||||
"custom-field-dropdown-options": "List Options",
|
||||
"custom-field-dropdown-options-placeholder": "Press enter to add more options",
|
||||
"custom-field-dropdown-unknown": "(unknown)",
|
||||
"custom-field-number": "Number",
|
||||
"custom-field-text": "Text",
|
||||
"custom-fields": "Custom Fields",
|
||||
"date": "Date",
|
||||
"decline": "Decline",
|
||||
"default-avatar": "Default avatar",
|
||||
"delete": "Delete",
|
||||
"deleteCustomFieldPopup-title": "Delete Custom Field?",
|
||||
"deleteLabelPopup-title": "Delete Label?",
|
||||
"description": "Description",
|
||||
"disambiguateMultiLabelPopup-title": "Disambiguate Label Action",
|
||||
@@ -182,6 +220,7 @@
|
||||
"soft-wip-limit": "Soft WIP Limit",
|
||||
"editCardStartDatePopup-title": "Change start date",
|
||||
"editCardDueDatePopup-title": "Change due date",
|
||||
"editCustomFieldPopup-title": "Edit Field",
|
||||
"editCardSpentTimePopup-title": "Change spent time",
|
||||
"editLabelPopup-title": "Change Label",
|
||||
"editNotificationPopup-title": "Edit Notification",
|
||||
@@ -218,15 +257,19 @@
|
||||
"filter-clear": "Clear filter",
|
||||
"filter-no-label": "No label",
|
||||
"filter-no-member": "No member",
|
||||
"filter-no-custom-fields": "No Custom Fields",
|
||||
"filter-on": "Filter is on",
|
||||
"filter-on-desc": "You are filtering cards on this board. Click here to edit filter.",
|
||||
"filter-to-selection": "Filter to selection",
|
||||
"advanced-filter-label": "Advanced Filter",
|
||||
"advanced-filter-description": "Advanced Filter allows to write a string containing following operators: == != <= >= && || ( ) A space is used as a separator between the Operators. You can filter for all Custom Fields by typing their names and values. For Example: Field1 == Value1. Note: If fields or values contains spaces, you need to encapsulate them into single quotes. For Example: 'Field 1' == 'Value 1'. For single control characters (' \\/) to be skipped, you can use \\. For example: Field1 == I\\'m. Also you can combine multiple conditions. For Example: F1 == V1 || F1 == V2. Normally all operators are interpreted from left to right. You can change the order by placing brackets. For Example: F1 == V1 && ( F2 == V2 || F2 == V3 ). Also you can search text fields using regex: F1 == /Tes.*/i",
|
||||
"fullname": "Full Name",
|
||||
"header-logo-title": "Go back to your boards page.",
|
||||
"hide-system-messages": "Hide system messages",
|
||||
"headerBarCreateBoardPopup-title": "Create Board",
|
||||
"home": "Home",
|
||||
"import": "Import",
|
||||
"link": "Link",
|
||||
"import-board": "import board",
|
||||
"import-board-c": "Import board",
|
||||
"import-board-title-trello": "Import board from Trello",
|
||||
@@ -260,8 +303,8 @@
|
||||
"leave-board-pop": "Are you sure you want to leave __boardTitle__? You will be removed from all cards on this board.",
|
||||
"leaveBoardPopup-title": "Leave Board ?",
|
||||
"link-card": "Link to this card",
|
||||
"list-archive-cards": "Archive all cards in this list",
|
||||
"list-archive-cards-pop": "This will remove all the cards in this list from the board. To view archived cards and bring them back to the board, click “Menu” > “Archived Items”.",
|
||||
"list-archive-cards": "Move all cards in this list to Recycle Bin",
|
||||
"list-archive-cards-pop": "This will remove all the cards in this list from the board. To view cards in Recycle Bin and bring them back to the board, click “Menu” > “Recycle Bin”.",
|
||||
"list-move-cards": "Move all cards in this list",
|
||||
"list-select-cards": "Select all cards in this list",
|
||||
"listActionPopup-title": "List Actions",
|
||||
@@ -270,7 +313,7 @@
|
||||
"listMorePopup-title": "More",
|
||||
"link-list": "Link to this list",
|
||||
"list-delete-pop": "All actions will be removed from the activity feed and you won't be able to recover the list. There is no undo.",
|
||||
"list-delete-suggest-archive": "You can archive a list to remove it from the board and preserve the activity.",
|
||||
"list-delete-suggest-archive": "You can move a list to Recycle Bin to remove it from the board and preserve its activity.",
|
||||
"lists": "Lists",
|
||||
"swimlanes": "Swimlanes",
|
||||
"log-out": "Log Out",
|
||||
@@ -290,9 +333,9 @@
|
||||
"muted-info": "You will never be notified of any changes in this board",
|
||||
"my-boards": "My Boards",
|
||||
"name": "Name",
|
||||
"no-archived-cards": "No archived cards.",
|
||||
"no-archived-lists": "No archived lists.",
|
||||
"no-archived-swimlanes": "No archived swimlanes.",
|
||||
"no-archived-cards": "No cards in Recycle Bin.",
|
||||
"no-archived-lists": "No lists in Recycle Bin.",
|
||||
"no-archived-swimlanes": "No swimlanes in Recycle Bin.",
|
||||
"no-results": "No results",
|
||||
"normal": "Normal",
|
||||
"normal-desc": "Can view and edit cards. Can't change settings.",
|
||||
@@ -328,7 +371,9 @@
|
||||
"restore": "Restore",
|
||||
"save": "Save",
|
||||
"search": "Search",
|
||||
"select-color": "Select Color",
|
||||
"search-cards": "Search from card titles and descriptions on this board",
|
||||
"search-example": "Text to search for?",
|
||||
"select-color": "Select Colour",
|
||||
"set-wip-limit-value": "Set a limit for the maximum number of tasks in this list",
|
||||
"setWipLimitPopup-title": "Set WIP Limit",
|
||||
"shortcut-assign-self": "Assign yourself to current card",
|
||||
@@ -360,6 +405,7 @@
|
||||
"title": "Title",
|
||||
"tracking": "Tracking",
|
||||
"tracking-info": "You will be notified of any changes to those cards you are involved as creator or member.",
|
||||
"type": "Type",
|
||||
"unassign-member": "Unassign member",
|
||||
"unsaved-description": "You have an unsaved description.",
|
||||
"unwatch": "Unwatch",
|
||||
@@ -368,7 +414,7 @@
|
||||
"uploaded-avatar": "Uploaded an avatar",
|
||||
"username": "Username",
|
||||
"view-it": "View it",
|
||||
"warn-list-archived": "warning: this card is in an archived list",
|
||||
"warn-list-archived": "warning: this card is in a list in the Recycle Bin",
|
||||
"watch": "Watch",
|
||||
"watching": "Watching",
|
||||
"watching-info": "You will be notified of any changes in this board",
|
||||
@@ -424,11 +470,42 @@
|
||||
"hours": "hours",
|
||||
"minutes": "minutes",
|
||||
"seconds": "seconds",
|
||||
"show-field-on-card": "Show this field on card",
|
||||
"yes": "Yes",
|
||||
"no": "No",
|
||||
"accounts": "Accounts",
|
||||
"accounts-allowEmailChange": "Allow Email Change",
|
||||
"accounts-allowUserNameChange": "Allow Username Change",
|
||||
"createdAt": "Created at",
|
||||
"verified": "Verified",
|
||||
"active": "Active"
|
||||
"active": "Active",
|
||||
"card-received": "Received",
|
||||
"card-received-on": "Received on",
|
||||
"card-end": "End",
|
||||
"card-end-on": "Ends on",
|
||||
"editCardReceivedDatePopup-title": "Change received date",
|
||||
"editCardEndDatePopup-title": "Change end date",
|
||||
"assigned-by": "Assigned By",
|
||||
"requested-by": "Requested By",
|
||||
"board-delete-notice": "Deleting is permanent. You will lose all lists, cards and actions associated with this board.",
|
||||
"delete-board-confirm-popup": "All lists, cards, labels, and activities will be deleted and you won't be able to recover the board contents. There is no undo.",
|
||||
"boardDeletePopup-title": "Delete Board?",
|
||||
"delete-board": "Delete Board",
|
||||
"default-subtasks-board": "Subtasks for __board__ board",
|
||||
"default": "Default",
|
||||
"queue": "Queue",
|
||||
"subtask-settings": "Subtasks Settings",
|
||||
"boardSubtaskSettingsPopup-title": "Board Subtasks Settings",
|
||||
"show-subtasks-field": "Cards can have subtasks",
|
||||
"deposit-subtasks-board": "Deposit subtasks to this board:",
|
||||
"deposit-subtasks-list": "Landing list for subtasks deposited here:",
|
||||
"show-parent-in-minicard": "Show parent in minicard:",
|
||||
"prefix-with-full-path": "Prefix with full path",
|
||||
"prefix-with-parent": "Prefix with parent",
|
||||
"subtext-with-full-path": "Subtext with full path",
|
||||
"subtext-with-parent": "Subtext with parent",
|
||||
"change-card-parent": "Change card's parent",
|
||||
"parent-card": "Parent card",
|
||||
"source-board": "Source board",
|
||||
"no-parent": "Don't show parent"
|
||||
}
|
||||
Loaded 100 of 189 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user