mirror of
https://github.com/wekan/wekan.git
synced 2026-11-06 12:45:03 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
5dadb4f0a1 | ||
|
|
1629e6aae6 | ||
|
|
0775e2a3e5 | ||
|
|
454d0b270d | ||
|
|
3076547cee | ||
|
|
4bcddcc98a | ||
|
|
099085b416 | ||
|
|
9bd6879455 | ||
|
|
00efbf00d3 | ||
|
|
5c214c143d | ||
|
|
3418b97faa | ||
|
|
a484101abf | ||
|
|
2f79432e4e | ||
|
|
f71728ae16 | ||
|
|
e7e4296b02 | ||
|
|
b85db43c47 | ||
|
|
db6fc57515 | ||
|
|
6b404da9f8 | ||
|
|
4d31985eb9 | ||
|
|
0e9aa2eeed | ||
|
|
7d73f2bbba | ||
|
|
9ca8d78514 | ||
|
|
11d8096b8d | ||
|
|
a49a918547 | ||
|
|
4ebd113bf0 | ||
|
|
14df71de5b | ||
|
|
9f459a37b8 | ||
|
|
5487c015db | ||
|
|
f46173077b | ||
|
|
c373013134 | ||
|
|
12c5d2324d | ||
|
|
e6dc20f6c7 | ||
|
|
ea658842a2 | ||
|
|
12f0c85546 | ||
|
|
033a5d8186 | ||
|
|
b769a71af3 | ||
|
|
ad35e7b7bd | ||
|
|
a9e56f2b09 | ||
|
|
5f807b80fe | ||
|
|
4d89eb6083 | ||
|
|
bd2739e78d | ||
|
|
265ee9ab83 | ||
|
|
065485168a | ||
|
|
7d609ef0b1 | ||
|
|
dc7b97c178 | ||
|
|
a5b376e6b5 | ||
|
|
993e99330f | ||
|
|
e563212475 | ||
|
|
cc54867976 | ||
|
|
36250f83b9 | ||
|
|
e715106d65 | ||
|
|
f888b5cb23 | ||
|
|
627d7d9456 | ||
|
|
b62dd5782a | ||
|
|
0460a7d9d3 | ||
|
|
45d53dede4 | ||
|
|
ce3c87f767 | ||
|
|
ceed865e30 | ||
|
|
a9bd5c7496 | ||
|
|
e1730c9912 | ||
|
|
8f1754be50 | ||
|
|
4ace1db9b0 | ||
|
|
eff636ddd6 | ||
|
|
9b7bf1ba28 | ||
|
|
7190057d0c | ||
|
|
bb5b723520 | ||
|
|
a2e6f01469 | ||
|
|
12ee7efc5f | ||
|
|
7c7640e63e | ||
|
|
e668fdc500 | ||
|
|
f02478d57c | ||
|
|
8fc117eb53 | ||
|
|
af598b13e8 | ||
|
|
f00f164078 | ||
|
|
70ac18a7e6 | ||
|
|
e461c4a018 | ||
|
|
186364f227 | ||
|
|
72f9d45bbe | ||
|
|
6392e06a36 | ||
|
|
c879e63fc2 | ||
|
|
290a6dfb6e | ||
|
|
94c82d121c | ||
|
|
3e92d6f6a3 | ||
|
|
3a2b50720e | ||
|
|
8f47e65684 | ||
|
|
95ebf3bda8 | ||
|
|
ea95357ae4 | ||
|
|
7501e255dd | ||
|
|
ff13571c71 | ||
|
|
6501173ce4 | ||
|
|
1d13040305 | ||
|
|
af1439b274 | ||
|
|
32af18b33d | ||
|
|
a48e537b2d | ||
|
|
424bc0e7c5 | ||
|
|
e98821fafc | ||
|
|
2d61fcdef4 | ||
|
|
045160c7bb | ||
|
|
f98b03bee5 | ||
|
|
703baf4ce9 | ||
|
|
1bf1ed79e8 | ||
|
|
a7888f0c66 | ||
|
|
7122f59c51 | ||
|
|
839266903a | ||
|
|
a8e3dc06fe | ||
|
|
7e0bc91a44 | ||
|
|
62efb67d06 | ||
|
|
00fd47105d | ||
|
|
1bee24fa68 | ||
|
|
9a539fb414 | ||
|
|
c0828f2d00 | ||
|
|
90c70aef96 | ||
|
|
dfc736b064 | ||
|
|
af53afb9f8 | ||
|
|
df61e471a1 | ||
|
|
3e364c4f35 | ||
|
|
3fb63b518f | ||
|
|
4bf6b457ae | ||
|
|
71c575d4b5 | ||
|
|
8b2c9cc74f | ||
|
|
fc7c70bdc0 | ||
|
|
dd18fd2477 | ||
|
|
2512ea1715 | ||
|
|
d63fa4aa89 | ||
|
|
ec51f7cced | ||
|
|
3eb834c920 | ||
|
|
ba24e4a775 | ||
|
|
bec25720da | ||
|
|
0db7ba5107 | ||
|
|
5e65dfc272 | ||
|
|
9b56f149e1 | ||
|
|
a15ed97ab3 | ||
|
|
d34918b08b | ||
|
|
e16cc34f6d | ||
|
|
87fd4880c9 | ||
|
|
f325fe8436 | ||
|
|
70558d00a7 | ||
|
|
d86eb74eb0 | ||
|
|
6adedfd77f | ||
|
|
e1a7c8abb7 | ||
|
|
8c8fba3c6c | ||
|
|
a176a58a72 | ||
|
|
1db3d9a081 | ||
|
|
8020aa4b81 | ||
|
|
bbef2aff8c | ||
|
|
7e1755c89f | ||
|
|
66a4562c91 | ||
|
|
6ad4e78fa8 | ||
|
|
6a92a95414 | ||
|
|
1fcc0d2ec2 | ||
|
|
e7051c8ecd | ||
|
|
1670ba31e8 | ||
|
|
ac1f540763 | ||
|
|
61dd3180a4 | ||
|
|
930333d546 | ||
|
|
2967d13968 | ||
|
|
56be68fcb7 | ||
|
|
dbb9ddd7d3 | ||
|
|
879ab282e1 | ||
|
|
d9a7950fa4 | ||
|
|
18e34b7f79 | ||
|
|
4abb26f8bc | ||
|
|
cd6b4529be | ||
|
|
6234fdff18 | ||
|
|
d4c3f32383 | ||
|
|
a72d51d901 | ||
|
|
a66257ec21 | ||
|
|
395452b54f | ||
|
|
e40e42103e | ||
|
|
7651c00d57 | ||
|
|
764dbb71f0 | ||
|
|
83ce43ac52 | ||
|
|
e528474fc5 | ||
|
|
73ff4c7966 | ||
|
|
01d8058a3f | ||
|
|
b69f08889a | ||
|
|
edf3573760 | ||
|
|
021def818f | ||
|
|
f519d277a5 | ||
|
|
218ddf03bc | ||
|
|
31c7539eb9 | ||
|
|
eb8d9955d5 | ||
|
|
7bcaf71bf0 | ||
|
|
7afc4638d2 | ||
|
|
c9b7542a9b | ||
|
|
c59c7bd63d | ||
|
|
574116b058 | ||
|
|
dbcc919768 | ||
|
|
bf37737f44 | ||
|
|
187b31caa5 | ||
|
|
f75ab964be | ||
|
|
bff43c3f92 | ||
|
|
fb3099eba9 | ||
|
|
5d1d90c2ff | ||
|
|
4d3c0c60d0 | ||
|
|
99d6f7a765 | ||
|
|
418b9effa7 | ||
|
|
30131ffc20 | ||
|
|
ac85e00e0a | ||
|
|
8b2e2e9b1f | ||
|
|
724f9d43b4 | ||
|
|
2ce136ee0a | ||
|
|
7495c1bf59 | ||
|
|
ef685703cf | ||
|
|
0218f3266b | ||
|
|
6a97dfb4b9 | ||
|
|
75fdc53746 | ||
|
|
ed3c53df35 | ||
|
|
2efa42b853 | ||
|
|
cf151b5632 | ||
|
|
2241c35e55 | ||
|
|
6f7292db5e | ||
|
|
ce587d23fa | ||
|
|
9979193df5 | ||
|
|
bee9dc8b3e | ||
|
|
31bf4072d3 | ||
|
|
fbbd3d5174 | ||
|
|
65b7d3d50d | ||
|
|
4589c3df15 | ||
|
|
a160b662ef | ||
|
|
e176410b54 | ||
|
|
2ac5f0b2d7 | ||
|
|
33f47414bb | ||
|
|
fb27ce027c | ||
|
|
ae180c7b85 | ||
|
|
95ed3a0ab5 | ||
|
|
dbe0b4922f | ||
|
|
e69114319f | ||
|
|
8db78f8dd4 | ||
|
|
f2c31f877c | ||
|
|
a87a591600 | ||
|
|
67687110bb | ||
|
|
db180fa43e | ||
|
|
aff6e361f0 | ||
|
|
a37856c937 | ||
|
|
7f32de3bec | ||
|
|
c46ec4a155 | ||
|
|
0c38700458 | ||
|
|
942065bb29 | ||
|
|
8aa816149f | ||
|
|
27ee16ea1e | ||
|
|
d6b0b0318d | ||
|
|
faf03ae1ce | ||
|
|
dd3c8394e7 | ||
|
|
c10f3e97bf | ||
|
|
ea5b93f97c | ||
|
|
bd08c1a4f1 | ||
|
|
ea17cc8592 | ||
|
|
d535469163 | ||
|
|
349925ad6b | ||
|
|
b876098dc4 | ||
|
|
dc04beb61f | ||
|
|
04d8aee86a | ||
|
|
8064d203f3 | ||
|
|
2fbf411918 | ||
|
|
1e9695a428 | ||
|
|
443b40cff3 | ||
|
|
f144f8c90a | ||
|
|
998d2f5b44 | ||
|
|
c15c10de97 | ||
|
|
142fa1c73d | ||
|
|
23a403644c | ||
|
|
89f4cdb7e5 | ||
|
|
c650dd2088 | ||
|
|
85d51ec403 | ||
|
|
8804ca84ec | ||
|
|
aa0dee1fba | ||
|
|
27d55a49fb | ||
|
|
6ef612d04e | ||
|
|
42610d9642 | ||
|
|
d9c290deda | ||
|
|
49214747cd | ||
|
|
84d0817894 | ||
|
|
94525a4d3d | ||
|
|
4ded5d2f51 | ||
|
|
7f8f3f8f16 | ||
|
|
45d7be19b6 | ||
|
|
8446640060 | ||
|
|
184290ce98 | ||
|
|
39fb0e4911 | ||
|
|
1f65add7b0 | ||
|
|
241c3ed8ae | ||
|
|
ee2fafb6bc | ||
|
|
fee82f7f7a | ||
|
|
c2340c6508 | ||
|
|
5ad9ee1de6 | ||
|
|
ea6551e567 | ||
|
|
6c9a2319ba | ||
|
|
e305bf019f | ||
|
|
505c2da072 | ||
|
|
9085e52446 | ||
|
|
9ac5e44a29 | ||
|
|
3d8e9c8b09 | ||
|
|
5cf352defb | ||
|
|
371dd7db9f | ||
|
|
051de2ea5e | ||
|
|
73408c73af | ||
|
|
7079b65cc1 | ||
|
|
67676c50ad | ||
|
|
e46d10ea4c | ||
|
|
331a64f067 | ||
|
|
7f06218877 | ||
|
|
fc95698953 | ||
|
|
2f69501c14 | ||
|
|
8d2c5a9bbb | ||
|
|
cec05dae47 | ||
|
|
8e6bd81abe | ||
|
|
eb9d44f5f0 | ||
|
|
3a83d48bef | ||
|
|
01cd1c0fdc | ||
|
|
c9ddad5615 | ||
|
|
9eb6a1d6af | ||
|
|
9b22e6da7a | ||
|
|
66488b834b | ||
|
|
8752225409 | ||
|
|
258b31f04a | ||
|
|
6997dbc6a8 | ||
|
|
1c3f42cec1 | ||
|
|
fc6c4f85f0 | ||
|
|
8ad9f2fbea | ||
|
|
ee5ec45c73 | ||
|
|
710c65a8ae | ||
|
|
f094dfb84f | ||
|
|
b84cc037c1 | ||
|
|
7aaa853d1b | ||
|
|
e32225e18f | ||
|
|
d7f903f3cd | ||
|
|
f0ebfb7f58 | ||
|
|
f660dcaa86 | ||
|
|
daa5de7011 | ||
|
|
2827c0e3ed | ||
|
|
00cd8f140c | ||
|
|
8be1d371cd | ||
|
|
2252a855dd | ||
|
|
c1eb175ab8 | ||
|
|
e7174107e9 | ||
|
|
63c838eee9 | ||
|
|
bd336dddec | ||
|
|
673e5b1987 | ||
|
|
d45bbc2269 | ||
|
|
8884d5b7e0 | ||
|
|
a3b99dd02d | ||
|
|
e7138772f0 | ||
|
|
b8a976d4ad | ||
|
|
ba0fb2d985 | ||
|
|
ebc7741fcb | ||
|
|
d1f8c92a99 | ||
|
|
4036abe3c1 | ||
|
|
23a2e90f5f | ||
|
|
5792b21ed1 | ||
|
|
4a4bfef888 | ||
|
|
a2cefc595e | ||
|
|
892828c02e | ||
|
|
9cf8af0416 | ||
|
|
2767c444b2 | ||
|
|
b5ee0649db | ||
|
|
a7b7bfafb5 | ||
|
|
36d8949831 | ||
|
|
5c5c867aca | ||
|
|
383323c4ea | ||
|
|
96465ac664 | ||
|
|
98dedc697c | ||
|
|
f82fbdb8a2 | ||
|
|
5088c12253 | ||
|
|
611af2d523 | ||
|
|
97ef13c222 | ||
|
|
d7adfc779e | ||
|
|
507cfbb377 | ||
|
|
1af75aa579 | ||
|
|
861b98ea37 | ||
|
|
b09be8614b | ||
|
|
8bc047cec3 | ||
|
|
cb7ec54be2 | ||
|
|
6d3b979d67 | ||
|
|
fe01d35fe6 | ||
|
|
f38e3db93c | ||
|
|
b988ef430c | ||
|
|
4a97e70b8d | ||
|
|
f082128d99 | ||
|
|
7577b246da | ||
|
|
9db14a0c3b | ||
|
|
f3d5b887c8 | ||
|
|
7e21589ee1 | ||
|
|
e1e4ea1205 | ||
|
|
54205b7c5d | ||
|
|
e0b5d1c15e | ||
|
|
79b40cd8a9 | ||
|
|
f6830ff4f3 | ||
|
|
765ac045fe | ||
|
|
b9d98f58cf | ||
|
|
e0978000f8 | ||
|
|
bc186958ab | ||
|
|
a190600934 | ||
|
|
65fc2a4fdd | ||
|
|
d41810aca1 | ||
|
|
b75a7a6424 | ||
|
|
bfb3837ee4 | ||
|
|
72fa10761a | ||
|
|
9c1523c916 | ||
|
|
a786262658 | ||
|
|
6245982025 | ||
|
|
c643cdaad3 | ||
|
|
f0cadf858d | ||
|
|
2566286e86 | ||
|
|
8bf3841e6c | ||
|
|
7a959ef1a2 | ||
|
|
5525247f52 | ||
|
|
7444c11c82 | ||
|
|
6d3ecdea55 | ||
|
|
7db1445d09 | ||
|
|
08ee969445 | ||
|
|
4bfa727e9e | ||
|
|
ed53065a09 | ||
|
|
49fdae6e06 | ||
|
|
b78dfc7149 | ||
|
|
0227b38845 | ||
|
|
7d52016d79 | ||
|
|
d9bc5f80a0 | ||
|
|
f1a0e4754f | ||
|
|
496c791629 | ||
|
|
2b7c5cfcb1 | ||
|
|
f647f4580e | ||
|
|
c62c705755 | ||
|
|
57129eff04 | ||
|
|
3c7ca87625 | ||
|
|
126c9ab853 | ||
|
|
c9071a74bc | ||
|
|
292e43466e | ||
|
|
75af42cd8c | ||
|
|
60c831521e | ||
|
|
9e0de569dc | ||
|
|
6dbb8c8c68 | ||
|
|
ac89276ee9 | ||
|
|
7902221a96 | ||
|
|
47540df916 | ||
|
|
dbef7e7cd3 | ||
|
|
4a19790b11 | ||
|
|
533eb41249 | ||
|
|
f09ea42981 | ||
|
|
6290b3b697 | ||
|
|
92b6b0064a | ||
|
|
8662fd59fb | ||
|
|
16bb65f7c7 | ||
|
|
44c3449ab2 | ||
|
|
ed13a3b95f | ||
|
|
32646fb9be | ||
|
|
38eccdb95b | ||
|
|
6944a20ba4 | ||
|
|
2e8323ca6a | ||
|
|
fae4d0be08 | ||
|
|
b58e1c0102 | ||
|
|
f18658c0d2 | ||
|
|
8054f2b002 | ||
|
|
5178aade75 | ||
|
|
6628ae8b5a | ||
|
|
7ca0fa626c | ||
|
|
0ceff124cc | ||
|
|
37faa41d97 | ||
|
|
fc0630715c | ||
|
|
9e75a70212 | ||
|
|
3d61be028a | ||
|
|
f9c179e9df | ||
|
|
2b77a67c03 | ||
|
|
c6fc172055 | ||
|
|
7aafb5e26e | ||
|
|
02b6df320f | ||
|
|
6d719b8a98 | ||
|
|
b1b12b05b5 | ||
|
|
39260bccb3 | ||
|
|
5754a886ab | ||
|
|
624fdea842 | ||
|
|
1975673152 | ||
|
|
1d523c1ede | ||
|
|
407632eed0 | ||
|
|
7518d93feb | ||
|
|
0fb6b6e519 | ||
|
|
fa9641ba7b | ||
|
|
6d855967fe | ||
|
|
17d90684bb | ||
|
|
d6094c3476 | ||
|
|
4eca4eeddc | ||
|
|
b392e515ca | ||
|
|
f25ed7fcfc | ||
|
|
b7928a9538 | ||
|
|
d523a897f6 | ||
|
|
a67e3754ab | ||
|
|
80319b0038 | ||
|
|
becb81f04a | ||
|
|
f50f876cab | ||
|
|
bd7bbd18c5 | ||
|
|
d8218091c6 | ||
|
|
ba3fa2aaea | ||
|
|
0ab86c22af | ||
|
|
0ed029e706 | ||
|
|
c5a7cf56bc | ||
|
|
9f25938b51 | ||
|
|
e0d92c7f64 | ||
|
|
48ecbf5017 | ||
|
|
8fe2e073c5 | ||
|
|
a8c8970192 | ||
|
|
e8e5616832 | ||
|
|
abe5ca752e | ||
|
|
db84c73337 | ||
|
|
a4ac34d8aa | ||
|
|
e47f26a390 | ||
|
|
1eca7c9996 | ||
|
|
25024fbe6b | ||
|
|
1f6d96c873 | ||
|
|
8ec4e1a7d0 | ||
|
|
f4a3363f6f | ||
|
|
4733afe4eb | ||
|
|
72ddd66495 | ||
|
|
a09e961110 | ||
|
|
49c4dd8b14 | ||
|
|
52e45211a2 | ||
|
|
cca51628ef | ||
|
|
506cb696d3 | ||
|
|
a4e02bb8cd | ||
|
|
6d588130dd | ||
|
|
0ce2f9ea43 | ||
|
|
80c4908fcc | ||
|
|
30a29e23d3 | ||
|
|
661e80084c |
No files matched your search
@@ -6,7 +6,7 @@ ENV DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ENV \
|
||||
DEBUG=false \
|
||||
NODE_VERSION=v12.22.7 \
|
||||
NODE_VERSION=v12.22.10 \
|
||||
METEOR_RELEASE=1.10.2 \
|
||||
USE_EDGE=false \
|
||||
METEOR_EDGE=1.5-beta.17 \
|
||||
@@ -22,6 +22,7 @@ ENV \
|
||||
ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURES_BERORE=3 \
|
||||
ACCOUNTS_LOCKOUT_UNKNOWN_USERS_LOCKOUT_PERIOD=60 \
|
||||
ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW=15 \
|
||||
ACCOUNTS_COMMON_LOGIN_EXPIRATION_IN_DAYS=90 \
|
||||
RICHER_CARD_COMMENT_EDITOR=false \
|
||||
CARD_OPENED_WEBHOOK_ENABLED=false \
|
||||
ATTACHMENTS_STORE_PATH="" \
|
||||
@@ -131,7 +132,16 @@ ENV \
|
||||
SAML_IDENTIFIER_FORMAT="" \
|
||||
SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE="" \
|
||||
SAML_ATTRIBUTES="" \
|
||||
DEFAULT_WAIT_SPINNER=""
|
||||
DEFAULT_WAIT_SPINNER="" \
|
||||
NODE_OPTIONS="--max_old_space_size=4096"
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# https://github.com/wekan/wekan/issues/3585#issuecomment-1021522132
|
||||
# Add more Node heap:
|
||||
# NODE_OPTIONS="--max_old_space_size=4096"
|
||||
# Add more stack:
|
||||
# bash -c "ulimit -s 65500; exec node --stack-size=65500 main.js"
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
# Install OS
|
||||
RUN set -o xtrace \
|
||||
@@ -228,7 +238,9 @@ RUN \
|
||||
set -o xtrace && \
|
||||
cd /home/wekan/app_build/bundle/programs/server/ && \
|
||||
chmod u+w package.json npm-shrinkwrap.json && \
|
||||
npm install
|
||||
npm install && \
|
||||
cd node_modules/fibers && \
|
||||
node build.js
|
||||
|
||||
USER root
|
||||
# Cleanup
|
||||
@@ -247,4 +259,14 @@ ENV PORT=3000
|
||||
EXPOSE $PORT
|
||||
WORKDIR /home/wekan/app
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# https://github.com/wekan/wekan/issues/3585#issuecomment-1021522132
|
||||
# Add more Node heap:
|
||||
# NODE_OPTIONS="--max_old_space_size=4096"
|
||||
# Add more stack:
|
||||
# bash -c "ulimit -s 65500; exec node --stack-size=65500 main.js"
|
||||
#---------------------------------------------------------------------
|
||||
#TODO:
|
||||
#CMD ["bash", "-c", "ulimit -s 65500; exec node --stack-size=65500 /build/main.js"]
|
||||
|
||||
CMD ["/home/wekan/.meteor/meteor", "run", "--verbose", "--settings", "settings.json"]
|
||||
@@ -9,4 +9,6 @@ cp -f fix-download-unicode/cfs_access-point.txt .build/bundle/programs/server/pa
|
||||
cd .build/bundle/programs/server
|
||||
rm -rf node_modules
|
||||
/home/wekan/.meteor/meteor npm install
|
||||
cd node_modules/fibers
|
||||
node build.js
|
||||
cd /home/wekan/app
|
||||
@@ -81,7 +81,7 @@ parts:
|
||||
wekan:
|
||||
source: .
|
||||
plugin: nodejs
|
||||
node-engine: 12.22.7
|
||||
node-engine: 12.22.10
|
||||
node-packages:
|
||||
- node-gyp
|
||||
- node-pre-gyp
|
||||
|
||||
@@ -83,7 +83,7 @@ parts:
|
||||
wekan:
|
||||
source: .
|
||||
plugin: nodejs
|
||||
node-engine: 12.22.7
|
||||
node-engine: 12.22.10
|
||||
node-packages:
|
||||
- node-gyp
|
||||
- node-pre-gyp
|
||||
|
||||
+23
-25
@@ -1,37 +1,35 @@
|
||||
## Issue
|
||||
<!--
|
||||
**[PLEASE UPGRADE](https://github.com/wekan/wekan/wiki/Backup)** to the newest WeKan ® before reporting an issue.
|
||||
Please search existing Open and Closed issues, most questions have already been answered.
|
||||
|
||||
**[PLEASE UPGRADE](https://github.com/wekan/wekan/wiki/Backup)** to newest WeKan ® before adding new issue !!
|
||||
- We get too many duplicate reports of already fixed bugs. Newest WeKan ® has newest bugfixes and security fixes.
|
||||
- Please search existing Open and Closed issues, most questions have already been answered many times.
|
||||
If you can not login for any reason: https://github.com/wekan/wekan/wiki/Forgot-Password
|
||||
Email settings, only SMTP MAIL_URL and MAIL_FROM are in use: https://github.com/wekan/wekan/wiki/Troubleshooting-Mail
|
||||
|
||||
If you can not login for any reason:
|
||||
- https://github.com/wekan/wekan/wiki/Forgot-Password
|
||||
|
||||
Email settings, only SMTP MAIL_URL and MAIL_FROM are in use:
|
||||
- https://github.com/wekan/wekan/wiki/Troubleshooting-Mail
|
||||
|
||||
Add these issues to elsewhere:
|
||||
The following types of issues should be reported separately:
|
||||
- SECURITY ISSUES: https://github.com/wekan/wekan/blob/master/SECURITY.md
|
||||
- UCS: https://github.com/wekan/univention/issues
|
||||
-->
|
||||
|
||||
Other Wekan issues can be added here.
|
||||
|
||||
**Server Setup Information**:
|
||||
|
||||
* Note: Please anonymize info, and do not add to this public issue any of your Wekan board URLs, passwords, API tokens etc, do you understand?:
|
||||
### Server Setup Information
|
||||
<!-- Please anonymize info, and do not any of your Wekan board URLs, passwords, API tokens etc to this public issue. -->
|
||||
* Did you test in newest Wekan?:
|
||||
* For new Wekan install, did you configure root-url correctly so Wekan cards open correctly https://github.com/wekan/wekan/wiki/Settings ?
|
||||
* Did you configure root-url correctly so Wekan cards open correctly (see https://github.com/wekan/wekan/wiki/Settings)?
|
||||
* Operating System:
|
||||
* Deployment Method(Snap/Docker/Sandstorm/bundle/source):
|
||||
* Deployment Method (Snap/Docker/Sandstorm/bundle/source):
|
||||
* Http frontend if any (Caddy, Nginx, Apache, see config examples from Wekan GitHub wiki first):
|
||||
* Node.js Version:
|
||||
* MongoDB Version:
|
||||
* Wekan works on newest desktop and mobile webbrowsers that support Javascript. What webbrowser version are you using?
|
||||
* What webbrowser version are you using (Wekan should work on all modern browsers that support Javascript)?
|
||||
|
||||
**Problem description**:
|
||||
- *REQUIRED: Add recorded animated gif about how it works currently, and screenshot mockups how it should work. Use peek to record animgif in Linux https://github.com/phw/peek*
|
||||
- *Explain steps how to reproduce*
|
||||
- *In webbrowser, what does show Right Click / Inspect / Console ? Chrome shows more detailed info than Firefox.*
|
||||
- *If using Snap, what does show command `sudo snap logs wekan.wekan` ? Please anonymize logs.*
|
||||
- *If using Docker, what does show command `sudo docker logs wekan-app` ? Please anonymize logs.*
|
||||
- *If logs are very long, attach them in .zip file*
|
||||
### Problem description
|
||||
<!-- Add a recorded animated gif (e.g. with https://github.com/phw/peek) about how it works currently, and screenshot mockups how it should work. -->
|
||||
#### Reproduction Steps
|
||||
|
||||
#### Logs
|
||||
<!-- Check Right Click>Inspect>Console in you browser - generally Chrome shows more detailed info than Firefox. -->
|
||||
|
||||
<!-- Please anonymize logs.
|
||||
Snap: sudo snap logs wekan.wekan
|
||||
Docker: sudo docker logs wekan-app
|
||||
If logs are very long, attach them in .zip file -->
|
||||
@@ -118,7 +118,7 @@ jobs:
|
||||
.meteor/local/isopacks
|
||||
.meteor/local/bundler-cache/scanner
|
||||
key: v1-meteor_build_cache-${{ github.ref }}-${{ github.sha }}
|
||||
restore-key: |
|
||||
restore-keys: |
|
||||
v1-meteor_build_cache-
|
||||
|
||||
- name: Setup meteor
|
||||
|
||||
@@ -38,3 +38,4 @@ ehthumbs.db
|
||||
# Helm chart
|
||||
# Chart dependencies
|
||||
/helm/wekan/**/*.tgz
|
||||
/helm/wekan/charts
|
||||
@@ -60,7 +60,6 @@ reactive-var@1.0.11
|
||||
fortawesome:fontawesome
|
||||
mousetrap:mousetrap
|
||||
mquandalle:jquery-textcomplete
|
||||
mquandalle:jquery-ui-drag-drop-sort
|
||||
mquandalle:mousetrap-bindglobal
|
||||
peerlibrary:blaze-components@=0.15.1
|
||||
templates:tabs
|
||||
|
||||
+1
-2
@@ -76,6 +76,7 @@ matb33:collection-hooks@0.9.1
|
||||
matteodem:easy-search@1.6.4
|
||||
mdg:validation-error@0.5.1
|
||||
meteor@1.9.3
|
||||
meteor-autosize@5.0.1
|
||||
meteor-base@1.4.0
|
||||
meteor-platform@1.2.6
|
||||
meteorhacks:aggregate@1.3.0
|
||||
@@ -106,7 +107,6 @@ mquandalle:collection-mutations@0.1.0
|
||||
mquandalle:jade@0.4.9
|
||||
mquandalle:jade-compiler@0.4.5
|
||||
mquandalle:jquery-textcomplete@0.8.0_1
|
||||
mquandalle:jquery-ui-drag-drop-sort@0.2.0
|
||||
mquandalle:moment@1.0.1
|
||||
mquandalle:mousetrap-bindglobal@0.0.1
|
||||
msavin:usercache@1.8.0
|
||||
@@ -219,7 +219,6 @@ url@1.3.2
|
||||
useraccounts:core@1.14.2
|
||||
useraccounts:flow-routing@1.14.2
|
||||
useraccounts:unstyled@1.14.2
|
||||
meteor-autosize@5.0.1
|
||||
webapp@1.10.1
|
||||
webapp-hashing@1.1.0
|
||||
wekan-accounts-cas@0.1.0
|
||||
|
||||
+1
-1
@@ -3,7 +3,7 @@ sudo: required
|
||||
|
||||
env:
|
||||
TRAVIS_DOCKER_COMPOSE_VERSION: 1.24.0
|
||||
TRAVIS_NODE_VERSION: 12.22.7
|
||||
TRAVIS_NODE_VERSION: 12.22.10
|
||||
TRAVIS_NPM_VERSION: latest
|
||||
|
||||
before_install:
|
||||
|
||||
+1
-1
@@ -39,7 +39,7 @@ host = https://www.transifex.com
|
||||
# tap:i18n requires us to use `-` separator in the language identifiers whereas
|
||||
# Transifex uses a `_` separator, without an option to customize it on one side
|
||||
# or the other, so we need to do a Manual mapping.
|
||||
lang_map = ar_EG:ar-EG, bg_BG:bg, de_CH:de-CH, en_IT:en-IT, en_GB:en-GB, es_AR:es-AR, es_CL:es-CL, es_419:es-LA, es_PE:es-PE, es_MX:es-MX, es_TX:es-TX, es_PY:es-PY, el_GR:el, fa_IR:fa-IR, fi_FI:fi, fr_CH:fr-CH, hu_HU:hu, id_ID:id, mn_MN:mn, lv_LV:lv, pt_BR:pt-BR, ro_RO:ro, sl_SI:sl, zh_CN:zh-CN, zh_TW:zh-TW, zh_Hans:zh-Hans, zh_HK:zh-HK
|
||||
lang_map = ar_EG:ar-EG, bg_BG:bg, de_AT:de-AT, de_CH:de-CH, en_DE:en-DE, en_IT:en-IT, en_GB:en-GB, et_EE:et-EE, es_AR:es-AR, es_CL:es-CL, es_419:es-LA, es_PE:es-PE, es_MX:es-MX, es_TX:es-TX, es_PY:es-PY, el_GR:el-GR, fa_IR:fa-IR, fi_FI:fi, fr_FR:fr-FR, fr_CH:fr-CH, gl_ES:gl-ES, gu_IN:gu-IN, hi_IN:hi-IN, hu_HU:hu, id_ID:id, mn_MN:mn, ms_MY:ms-MY, lv_LV:lv, pt_BR:pt-BR, ro_RO:ro, ru_UA:ru-UA, sl_SI:sl, uk_UA:uk-UA, zh_CN:zh-CN, zh_TW:zh-TW, zh_Hans:zh-Hans, zh_HK:zh-HK
|
||||
|
||||
[wekan.application]
|
||||
file_filter = i18n/<lang>.i18n.json
|
||||
|
||||
+594
@@ -1,5 +1,599 @@
|
||||
[Mac ChangeLog](https://github.com/wekan/wekan/wiki/Mac)
|
||||
|
||||
# v6.09 2022-02-28 WeKan ® release
|
||||
|
||||
This release tries to fix the following bugs:
|
||||
|
||||
- [Try to fix Admin Panel / Disable Registration and Disable Forgot Password](https://github.com/wekan/wekan/commit/0775e2a3e5c5d98e4d8c1954a15beb0688c73075).
|
||||
Thanks to urmel1960, Ben0it-T and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.08 2022-02-27 WeKan ® release
|
||||
|
||||
This release tries to fix the following bugs:
|
||||
|
||||
- [Try to allow register and login](https://github.com/wekan/wekan/commit/3076547cee3a5fabe8df106ddbbd6ce1e6c91a8b).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.07 2022-02-26 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix Forgot Password to be optional](https://github.com/wekan/wekan/commit/9bd68794555009f5eabad269ed642efa4e3010f1).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.06 2022-02-26 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Feature/shortcuts for label assignment](https://github.com/wekan/wekan/pull/4377).
|
||||
Thanks to Viehlieb.
|
||||
- [Feature/propagate OIDC data](https://github.com/wekan/wekan/pull/4379).
|
||||
Thanks to Viehlieb.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Global search: Card Details popup opens now in normal view even if maximized card is configured](https://github.com/wekan/wekan/pull/4352).
|
||||
Thanks to mfilser.
|
||||
- [Card details, fix header while scrolling](https://github.com/wekan/wekan/pull/4358).
|
||||
Thanks to mfilser.
|
||||
- [Add subscription to announcements, so that system wide announcements are shown to all](https://github.com/wekan/wekan/pull/4375).
|
||||
Thanks to pablo-ng.
|
||||
- [Fixed Disable Self-Registration. Added Disable Forgot Password to same Admin Panel page](https://github.com/wekan/wekan/commit/b85db43c4755cf54e550f664311cd95097d68ae1).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.05 2022-02-07 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Update release scripts to merge latest changes](https://github.com/wekan/wekan/commit/ad35e7b7bd1d6d7568b3a5d692941e03e4623c1a).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix copy move card](https://github.com/wekan/wekan/pull/4345).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.04 2022-02-07 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fixed Copy card to list does not work, by reverting clientside changes of PR 4333](https://github.com/wekan/wekan/commit/a5b376e6b5f9b171c39cd9341b8c2a4346fc3f5e).
|
||||
Thanks to Meeques, PaulITsoft and xet7.
|
||||
- [Fixed Problem with selecting action in rule window](https://github.com/wekan/wekan/commit/dc7b97c1780849b04389696f0dac38e4477e28cf).
|
||||
Thanks to Meeques and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.03 2022-02-07 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated to Node.js v12.22.10](https://github.com/wekan/wekan/commit/cc5486797648b8098e50fa4f68cc4b588f41ab60).
|
||||
Thanks to Node.js developers.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.02 2022-02-06 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/f888b5cb23917c01cef7a84cf23314051ec6bfff).
|
||||
Thanks to developers of dependencies.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.01 2022-02-06 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated to Node.js v14.19.0](https://github.com/wekan/wekan/commit/ceed865e305f41ec027f1ed345b041841c9812c0).
|
||||
Thanks to Node.js developers.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fixed WeKan on Sandstorm](https://github.com/sandstorm-io/meteor-spk/pull/41).
|
||||
Thanks to xet7.
|
||||
- [Fixed building fibers](https://github.com/wekan/wekan/commit/0460a7d9d3219ed7ba5aa5040349b9d56e6a45e0).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.00 2022-02-05 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Adding list select at card details](https://github.com/wekan/wekan/pull/4333).
|
||||
Thanks to mfilser.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated release scripts](https://github.com/wekan/wekan/commit/9b7bf1ba289f0026f0bf957527c86b6f4696686e).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.99 2022-02-04 WeKan ® release
|
||||
|
||||
This release adds the following changes:
|
||||
|
||||
- [Revert rounded corners minicard on moderndark theme](https://github.com/wekan/wekan/pull/4332).
|
||||
Thanks to jghaanstra.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Remove not working options from rebuild-wekan.sh](https://github.com/wekan/wekan/commit/af598b13e8266654ab52425f71840c3628c9835a).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.98 2022-02-03 WeKan ® release
|
||||
|
||||
This release adds the following CRITICAL SECURITY UPDATES:
|
||||
|
||||
- [Updated to Node.js v12.22.10](https://github.com/wekan/wekan/commit/290a6dfb6e104b887f9ee2cc70db84b83fe3be35).
|
||||
Thanks to Node.js developers.
|
||||
|
||||
and adds the following new features:
|
||||
|
||||
- [Make card corners round](https://github.com/wekan/wekan/commit/045160c7bb7c8696a181d9ed4e0b54d0c27b5f59).
|
||||
Thanks to Meeques and xet7.
|
||||
- [Copy checklist](https://github.com/wekan/wekan/pull/4331).
|
||||
Thanks to mfilser.
|
||||
|
||||
and adds the following new translations:
|
||||
|
||||
- Added translation: Galician (Spain).
|
||||
[Part 1](https://github.com/wekan/wekan/commit/c0828f2d00095c68b4533a10ff7ede0a16131093),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/9a539fb414c3ffeae2ea94f863d2bb3bc6e314f1),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/a8e3dc06fe76620d09eddbc7d118a749c85b1c7c).
|
||||
Thanks to translators.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix typo in tests](https://github.com/wekan/wekan/commit/62efb67d06a4aeb3299805911391b6e936901b42).
|
||||
Thanks to xet7.
|
||||
- Try to fix tests by adding puppeteer back.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/7122f59c51775f9b382cdbcf5690eba2ad907ccf),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/1bf1ed79e85e091d79fa70feb46d072c81e55810).
|
||||
Thanks to xet7.
|
||||
- [Removed unnecessary space between checklist title and first checklist item if checklist progress is 0%](https://github.com/wekan/wekan/pull/4329).
|
||||
Thanks to mfilser.
|
||||
- [Lists now moveable when swimlane requires scrolling](https://github.com/wekan/wekan/pull/4330).
|
||||
Thanks to mfilser.
|
||||
- [Add more stack and heap to Node.js at all WeKan platforms](https://github.com/wekan/wekan/commit/ff13571c719ad24e24ea6dc871ced827a7120ac8).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.97 2022-01-23 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix can't add Checklist on cardType-linkedBoard](https://github.com/wekan/wekan/pull/4318).
|
||||
Thanks to Ben0it-T.
|
||||
- [Fix comments for cards that link to a board are not shown](https://github.com/wekan/wekan/pull/4319).
|
||||
Thanks to Ben0it-T.
|
||||
- [Fix Snap OAUTH2_REQUEST_PERMISSIONS of Google/OAuth2/OIDC login](https://github.com/wekan/wekan/commit/4bf6b457ae6bfb6d28127f696344019765d0467d).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.96 2022-01-23 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Move checklist and card popup restore last selected board value](https://github.com/wekan/wekan/pull/4307).
|
||||
Thanks to mfilser.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix Layout "Modern Dark", Card Color, List Header and mouse hover](https://github.com/wekan/wekan/pull/4308).
|
||||
Thanks to mfilser.
|
||||
- [Try to fix OAUTH2_REQUEST_PERMISSIONS by removing quotes](https://github.com/wekan/wekan/commit/5e65dfc272925490b4ad20c49d8d3fd74597beac).
|
||||
Thanks to pcurie and xet7.
|
||||
- [Fix notification drawer always on top](https://github.com/wekan/wekan/commit/bec25720da947e048a63541b4e421bd9bd846c58).
|
||||
Thanks to Azorimor.
|
||||
- [Fix comments not loading on cardType-linkedBoard](https://github.com/wekan/wekan/pull/4315).
|
||||
Thanks to Ben0it-T.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.95 2022-01-18 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Move copy card remembers the last confirmed field values](https://github.com/wekan/wekan/pull/4296).
|
||||
Thanks to mfilser.
|
||||
- [Added "move checklist" and created a "Checklist Action Menu"](https://github.com/wekan/wekan/pull/4297).
|
||||
Thanks to mfilser.
|
||||
- [Add checklist item - each line becomes new item](https://github.com/wekan/wekan/pull/4298).
|
||||
Thanks to mfilser.
|
||||
- [Add progress bar to checklist](https://github.com/wekan/wekan/pull/4299).
|
||||
Thanks to mfilser.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Update ISSUE_TEMPLATE.md: Use comments and rephrase](https://github.com/wekan/wekan/pull/4295).
|
||||
Thanks to xeruf.
|
||||
- [Updated WeKan s390x bundle build script](https://github.com/wekan/wekan/commit/d4c3f323830e4692aac0f1d0faa413302087303b).
|
||||
Thanks to xet7.
|
||||
- [Use different distro for building WeKan releases](https://github.com/wekan/wekan/commit/a176a58a728ffc2bb410b3e8a0036fee25f0b0bd).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Custom Field StringTemplates didn't save the last input value on desktop view after pressing Ctrl+Enter](https://github.com/wekan/wekan/pull/4300).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.94 2022-01-16 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Added copy button to card title](https://github.com/wekan/wekan/pull/4291).
|
||||
Thanks to mfilser.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix Card, List and Comment colors not visible at some themes](https://github.com/wekan/wekan/commit/218ddf03bc109b954d1fe741d1aa533467b51a4d).
|
||||
Thanks to Meeques, Go-rom and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.93 2022-01-14 WeKan ® release
|
||||
|
||||
This release tries to fix the following bugs:
|
||||
|
||||
- Try to fix Sandstorm WeKan package. This did not fix it. Do not try broken experimental Sandstorm WeKan versions yet.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/bff43c3f9252e3133acedb9ccf4fb4f91d1c908d),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/f75ab964be784bf7f6accb3ab0085f623196d811).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.92 2022-01-13 WeKan ® release
|
||||
|
||||
This release adds the following CRITICAL SECURITY UPDATES:
|
||||
|
||||
- [Upgraded markdown-it to 12.3.2](https://github.com/wekan/wekan/commit/724f9d43b47aab3198730801200c0faa53c73e5c).
|
||||
Thanks to markdown-it developers.
|
||||
|
||||
and adds the following new translations:
|
||||
|
||||
- Added translations: Estonian (Estonia) et_EE, Russian (Ukraine) ru_UA, Ukrainian (Ukraine) uk_UA.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/ac85e00e0a99574499786ddf97823dcf2802a47f),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/30131ffc20173d222cb02b283f38a8c0d6a28ccc).
|
||||
Thanks to translators.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fixed OpenAPI docs generating has some swagger error](https://github.com/wekan/wekan/commit/99d6f7a765e2945fb17411f5b8545cd7d6010c5f).
|
||||
Thanks to bentiss.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.91 2022-01-11 WeKan ® release
|
||||
|
||||
This release adds the following CRITICAL SECURITY UPDATES:
|
||||
|
||||
- [Updated to Node.js v12.22.9](https://github.com/wekan/wekan/commit/0218f3266bbab2e044f83a06042ca61afab65bdf).
|
||||
Thanks to Node.js developers.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Added release scripts for starting and stopping services](https://github.com/wekan/wekan/commit/33f47414bbecdc3bca10e807c38562e833997db4).
|
||||
Thanks to xet7.
|
||||
- Updated rebuild-wekan.sh script about installing dependencies.
|
||||
[Part1](https://github.com/wekan/wekan/commit/9979193df5b896efb1a8c0ac9c244972fa08aae1),
|
||||
[Part2](https://github.com/wekan/wekan/commit/6f7292db5e8427fb63305e1e0e41d2337d8d9a60).
|
||||
Thanks to xet7.
|
||||
- In install scripts, use Volta Node and NPM install manager, made with Rust https://volta.sh .
|
||||
Volta uses home directory also with "npm -g install", no sudo needed.
|
||||
xet7 found info about Volta from Miniflare docs.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/2efa42b8537b8a404a0f82d78c5299f098130183),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/ef685703cf8180c3fedef381d3c10aaf405ee8b4).
|
||||
Thanks to Volta developers.
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/75fdc53746710206482b66513b02216dab5a4ad6).
|
||||
Thanks to developers of dependencies.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix user mentions](https://github.com/wekan/wekan/pull/4273).
|
||||
Thanks to Ben0it-T.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.90 2021-12-26 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix Create Board from Template not opening](https://github.com/wekan/wekan/commit/95ed3a0ab56a52a04c13856cf9d1d845659ea1b7).
|
||||
Thanks to Ben0it-T and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.89 2021-12-26 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Edit team/org now update users.teams.teamDisplayName / users.orgs.orgDisplayName](https://github.com/wekan/wekan/pull/4257).
|
||||
Thanks to Ben0it-T.
|
||||
- [Trello api.py: Added for using newest Trello API, to show Trello boards/cards/actions/reactions JSON and download Trello attachments
|
||||
as binary files from S3](https://github.com/wekan/wekan/commit/aff6e361f03f1a7e269edc184884313557c94362).
|
||||
Thanks to xet7.
|
||||
- [Trello api.py: Added additional TODO notes](https://github.com/wekan/wekan/commit/f2c31f877c5a22af4429688fe2620919858ca69f).
|
||||
Thanks to xet7.
|
||||
- [Added Info about Shared Templates In Progress](https://github.com/wekan/wekan/issues/3313#issuecomment-1001187003).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix getLabels exception in template helper](https://github.com/wekan/wekan/pull/4262).
|
||||
Thanks to Ben0it-T.
|
||||
- [Fixed Templates are Missing, Error: Site not Found "/templates" is missing in the URL.
|
||||
Shared Templates part 5: Make visible Create template board checkbox and templates at All Boards page, In Progress](https://github.com/wekan/wekan/commit/7f32de3bec151df9e656013e8e910eb650b8ce80).
|
||||
Thanks to xet7.
|
||||
- [Fixed Duplicate board](https://github.com/wekan/wekan/commit/67687110bb715028dd646d5879c109a095e584d5).
|
||||
Thanks to Ben0it-T and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.88 2021-12-22 WeKan ® release
|
||||
|
||||
This release adds to following CRITICAL SECURITY FIXES:
|
||||
|
||||
- [User now should only see archived cards belonging to boards to which he has permission](https://github.com/wekan/wekan/pull/4252).
|
||||
Thanks to jrsupplee.
|
||||
- [Fix `Boards.userBoards()` method to take into account organizations and teams of the user when determining which boards are accessible](https://github.com/wekan/wekan/pull/4252).
|
||||
Thanks to jrsupplee.
|
||||
|
||||
and adds the following new features:
|
||||
|
||||
- [New `debug` search operator that should help debugging future problems with search](https://github.com/wekan/wekan/pull/4252).
|
||||
Thanks to jrsupplee.
|
||||
- [New `org` and `team` search operators for finding cards belonging to boards with the given organization or team](https://github.com/wekan/wekan/pull/4252).
|
||||
Thanks to jrsupplee.
|
||||
- [New admin report to list boards](https://github.com/wekan/wekan/pull/4252).
|
||||
Thanks to jrsupplee.
|
||||
|
||||
and adds the following accessibility improvements:
|
||||
|
||||
- Made WeKan zoomable by recommendation of Axe browser extension
|
||||
https://github.com/wekan/wekan/issues/459#issuecomment-999098233 by changing meta viewport settings at
|
||||
https://github.com/wekan/wekan/blob/master/client/components/main/layouts.jade#L3 ,
|
||||
in some commit of this WeKan v5.88.
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- Fixed Mermaid Diagram error: Maximum call stack size exceeded.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/23a403644c7db44392d4b0498ee0fc85c504d974),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/998d2f5b445b6bf2bc6cd16beac7231a0cf94fc3),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/443b40cff3cf507887c20639224ac1447acfaf88).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.87 2021-12-19 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Changed Docker base image to ubuntu:rolling](https://github.com/wekan/wekan/commit/8446640060e6e5058d0d186d71831a32a9e606e3).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.86 2021-12-19 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix: BoardAdmin can't edit or delete others comments on cards](https://github.com/wekan/wekan/pull/4248).
|
||||
Thanks to Ben0it-T.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.85 2021-12-17 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated to Node.js v12.22.8](https://github.com/wekan/wekan/commit/5ad9ee1de6446e3b2f3e4a5df207d12de76e1b95).
|
||||
Thanks to Node.js developers.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix mobile card details for Modern Dark theme](https://github.com/wekan/wekan/pull/4240).
|
||||
Thanks to jghaanstra.
|
||||
- [Fixed undefinded added member to board](https://github.com/wekan/wekan/pull/4245).
|
||||
Thanks to Emile840.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.84 2021-12-15 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Kubernetes 1.22 support and basic helm test](https://github.com/wekan/wekan/pull/4208).
|
||||
Thanks to varac.
|
||||
- [Added Helm Chart usage docs](https://github.com/wekan/wekan/pull/4224).
|
||||
Thanks to varac.
|
||||
- [Add full name if exists in `email-invite-subject` for user to invite](https://github.com/wekan/wekan/pull/4226).
|
||||
Thanks to Emile840.
|
||||
- [Sort Organizations, Teams and People](https://github.com/wekan/wekan/pull/4232).
|
||||
Thanks to Emile840.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [List title doesn't overlap with hamburger menu anymore](https://github.com/wekan/wekan/pull/4203).
|
||||
Thanks to mfilser.
|
||||
- [Fix legal notice traduction bug when refreshing sign in page](https://github.com/wekan/wekan/pull/4217).
|
||||
Thanks to Emile840.
|
||||
- [Fix: Clicking to view Lists or Swimlanes Archive adds temporarily many empty Lists to board](https://github.com/wekan/wekan/pull/4221).
|
||||
Thanks to Ben0it-T.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.83 2021-11-30 WeKan ® release
|
||||
|
||||
This release adds to following new improvements:
|
||||
|
||||
- [Changed delete checklist dialog to a popup](https://github.com/wekan/wekan/pull/4200).
|
||||
Thanks to mfilser.
|
||||
- [Dragging minicards scrolls now vertically at the end of the screen](https://github.com/wekan/wekan/pull/4201).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.82 2021-11-29 WeKan ® release
|
||||
|
||||
This release removes the following new features:
|
||||
|
||||
- [Revert change from WeKan v5.81: At Sandstorm, every WeKan user is now WeKan Admin and has Admin Panel](https://github.com/wekan/wekan/commit/ebc7741fcb9ad854234921ed0546255411adeec9).
|
||||
Thanks to ocdtrekkie and xet7.
|
||||
|
||||
and adds the following new features:
|
||||
|
||||
- [List header contains now a button to add the card to the bottom of the list](https://github.com/wekan/wekan/pull/4195).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.81 2021-11-29 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [At Sandstorm, every WeKan user is now WeKan Admin and has WeKan Admin Panel. This could help export, board member permissions, etc](https://github.com/wekan/wekan/commit/23a2e90f5f553c2051978a0b4cd5b0d6d4ee03da).
|
||||
Thanks to PizzaProgram and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.80 2021-11-26 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Show helper at label drag/drop if label popup opened from card details popup](https://github.com/wekan/wekan/pull/4176).
|
||||
Thanks to mfilser.
|
||||
- [Show or hide members and assignee(s) on minicard](https://github.com/wekan/wekan/pull/4179).
|
||||
Thanks to Ben0it-T.
|
||||
- [List adding has now a cancel button](https://github.com/wekan/wekan/pull/4183).
|
||||
Thanks to mfilser.
|
||||
- [CustomFields Currency, autofocus on edit](https://github.com/wekan/wekan/pull/4189).
|
||||
Thanks to mfilser.
|
||||
- [Attachments, show file size in KB in card details](https://github.com/wekan/wekan/pull/4191).
|
||||
Thanks to mfilser.
|
||||
- [Sidebar Member Settings Popup has now a Popup title](https://github.com/wekan/wekan/pull/4190).
|
||||
Thanks to mfilser.
|
||||
- [Add copy text button to most textarea fields](https://github.com/wekan/wekan/pull/4185).
|
||||
Thanks to mfilser.
|
||||
- Copy text button at most textarea fields is now translatable.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/5088c122536e13b44cf2fdbcfabeefd00cee332e),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/96465ac664c526d8749dcad158704b512317e256).
|
||||
Thanks to xet7.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Docker build script to be executeable](https://github.com/wekan/wekan/commit/8054f2b0025c4cb3f6a3ddf71754ae7c707d6ac0).
|
||||
Thanks to xet7.
|
||||
- [Drag drop jquery-ui update + screen and list scroll](https://github.com/wekan/wekan/pull/4181).
|
||||
Thanks to mfilser.
|
||||
- [Settings, add some space between radio buttons](https://github.com/wekan/wekan/pull/4186).
|
||||
Thanks to mfilser.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Default Top Left Corner Logo Image display few seconds before a display of custom Top Left Corner Logo Image](https://github.com/wekan/wekan/issues/4173).
|
||||
Thanks to Emile840.
|
||||
- [App reconnect link wasn't clickable](https://github.com/wekan/wekan/pull/4180).
|
||||
Thanks to mfilser.
|
||||
- [Copy card URL works now again](https://github.com/wekan/wekan/pull/4184).
|
||||
Thanks to mfilser.
|
||||
- [Fix: On mobile infinite scrolling didn't work](https://github.com/wekan/wekan/pull/4187).
|
||||
Thanks to mfilser.
|
||||
- [Custom Field StringTemplates didn't save the last input value on touch devices](https://github.com/wekan/wekan/pull/4188).
|
||||
Thanks to mfilser.
|
||||
- [Move cards to top/bottom ignores the current filter if active](https://github.com/wekan/wekan/pull/4192).
|
||||
Thanks to mfilser.
|
||||
- [Moving many cards with multi selection drag/drop to another list keeps the card order](https://github.com/wekan/wekan/pull/4193).
|
||||
Thanks to mfilser.
|
||||
- [Sidebar multi selection actions keep now the card sorting (cards moving, cards to archive etc)](https://github.com/wekan/wekan/pull/4194).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.79 2021-11-25 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix label width oversize bug](https://github.com/wekan/wekan/pull/4157).
|
||||
Thanks to mfilser.
|
||||
- [Fixed label popup at desktop view (add and remove labels)](https://github.com/wekan/wekan/pull/4170).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.78 2021-11-17 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix: Sandstorm WeKan Admin Panel version info broken](https://github.com/wekan/wekan/commit/02b6df320fc98e18e5a97105a35196bdffec98bb).
|
||||
Thanks to ocdtrekkie and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.77 2021-11-16 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated Docker Ubuntu base image](https://github.com/wekan/wekan/commit/b1b12b05b571f4eebd38e7486dea28dfd97a885d).
|
||||
Thanks to Ubuntu developers.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.76 2021-11-16 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Global search load card details](https://github.com/wekan/wekan/pull/4142).
|
||||
Thanks to mfilser.
|
||||
- [Layout improvement: Adding organisations to the board](https://github.com/wekan/wekan/pull/4143).
|
||||
Thanks to Ben0it-T.
|
||||
- [App reconnect is now possible if the connection was interrupted](https://github.com/wekan/wekan/pull/4147).
|
||||
Thanks to mfilser.
|
||||
- [Boards view has now drag handles at desktop view if drag handles are enabled](https://github.com/wekan/wekan/pull/4149).
|
||||
Thanks to mfilser.
|
||||
- [Account configuration of option loginExpirationInDays is now possible](https://github.com/wekan/wekan/pull/4150).
|
||||
Thanks to mfilser.
|
||||
- [Part 2: Added remaining of Account configuration of option loginExpirationInDays for Snap](https://github.com/wekan/wekan/commit/17d90684bb59fd4159f80b2da224638824151c6f).
|
||||
Thanks to xet7.
|
||||
- [Improve multi selection sidebar opening and closing](https://github.com/wekan/wekan/pull/4153).
|
||||
Thanks to marook.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Added release scripts for building local Docker images and pushing them to Quay.io and Docker Hub](https://github.com/wekan/wekan/commit/49c4dd8b14d9c13a9ae2aa18b37238a05ed41f92).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fixed trim whitespace at multiline editor fields](https://github.com/wekan/wekan/pull/4146).
|
||||
Thanks to mfilser.
|
||||
- [Fixed placeholder was not visible at list view (mobile view)](https://github.com/wekan/wekan/pull/4148).
|
||||
Thanks to mfilser.
|
||||
- [Fix list adding to bottom](https://github.com/wekan/wekan/pull/4152).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.75 2021-11-12 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
+27
-4
@@ -1,4 +1,4 @@
|
||||
FROM quay.io/wekan/ubuntu:impish-20211015
|
||||
FROM ubuntu:rolling
|
||||
LABEL maintainer="wekan"
|
||||
|
||||
# 2021-09-18:
|
||||
@@ -12,7 +12,7 @@ ARG DEBIAN_FRONTEND=noninteractive
|
||||
|
||||
ENV BUILD_DEPS="apt-utils libarchive-tools gnupg gosu wget curl bzip2 g++ build-essential git ca-certificates python3" \
|
||||
DEBUG=false \
|
||||
NODE_VERSION=v12.22.7 \
|
||||
NODE_VERSION=v12.22.10 \
|
||||
METEOR_RELEASE=1.10.2 \
|
||||
USE_EDGE=false \
|
||||
METEOR_EDGE=1.5-beta.17 \
|
||||
@@ -28,6 +28,7 @@ ENV BUILD_DEPS="apt-utils libarchive-tools gnupg gosu wget curl bzip2 g++ build-
|
||||
ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURES_BERORE=3 \
|
||||
ACCOUNTS_LOCKOUT_UNKNOWN_USERS_LOCKOUT_PERIOD=60 \
|
||||
ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW=15 \
|
||||
ACCOUNTS_COMMON_LOGIN_EXPIRATION_IN_DAYS=90 \
|
||||
RICHER_CARD_COMMENT_EDITOR=false \
|
||||
CARD_OPENED_WEBHOOK_ENABLED=false \
|
||||
ATTACHMENTS_STORE_PATH="" \
|
||||
@@ -139,7 +140,16 @@ ENV BUILD_DEPS="apt-utils libarchive-tools gnupg gosu wget curl bzip2 g++ build-
|
||||
SAML_LOCAL_PROFILE_MATCH_ATTRIBUTE="" \
|
||||
SAML_ATTRIBUTES="" \
|
||||
ORACLE_OIM_ENABLED=false \
|
||||
WAIT_SPINNER=""
|
||||
WAIT_SPINNER="" \
|
||||
NODE_OPTIONS="--max_old_space_size=4096"
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# https://github.com/wekan/wekan/issues/3585#issuecomment-1021522132
|
||||
# Add more Node heap:
|
||||
# NODE_OPTIONS="--max_old_space_size=4096"
|
||||
# Add more stack:
|
||||
# bash -c "ulimit -s 65500; exec node --stack-size=65500 main.js"
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
# Copy the app to the image
|
||||
COPY ${SRC_PATH} /home/wekan/app
|
||||
@@ -297,6 +307,9 @@ RUN \
|
||||
cd /home/wekan/app_build/bundle/programs/server/ && \
|
||||
chmod u+w *.json && \
|
||||
gosu wekan:wekan npm install && \
|
||||
cd node_modules/fibers && \
|
||||
node build.js && \
|
||||
cd ../.. && \
|
||||
#gosu wekan:wekan npm install bcrypt && \
|
||||
# Remove legacy webbroser bundle, so that Wekan works also at Android Firefox, iOS Safari, etc.
|
||||
rm -rf /home/wekan/app_build/bundle/programs/web.browser.legacy && \
|
||||
@@ -322,4 +335,14 @@ ENV PORT=8080
|
||||
EXPOSE $PORT
|
||||
USER wekan
|
||||
|
||||
CMD ["node", "/build/main.js"]
|
||||
#---------------------------------------------------------------------
|
||||
# https://github.com/wekan/wekan/issues/3585#issuecomment-1021522132
|
||||
# Add more Node heap:
|
||||
# NODE_OPTIONS="--max_old_space_size=4096"
|
||||
# Add more stack:
|
||||
# bash -c "ulimit -s 65500; exec node --stack-size=65500 main.js"
|
||||
#---------------------------------------------------------------------
|
||||
#
|
||||
# CMD ["node", "/build/main.js"]
|
||||
|
||||
CMD ["bash", "-c", "ulimit -s 65500; exec node --stack-size=65500 /build/main.js"]
|
||||
+24
-4
@@ -4,9 +4,18 @@ FROM amd64/alpine:3.7 AS builder
|
||||
ENV QEMU_VERSION=v4.2.0-6 \
|
||||
QEMU_ARCHITECTURE=aarch64 \
|
||||
NODE_ARCHITECTURE=linux-arm64 \
|
||||
NODE_VERSION=v12.22.7 \
|
||||
NODE_VERSION=v12.22.10 \
|
||||
WEKAN_VERSION=latest \
|
||||
WEKAN_ARCHITECTURE=arm64
|
||||
WEKAN_ARCHITECTURE=arm64 \
|
||||
NODE_OPTIONS="--max_old_space_size=4096"
|
||||
|
||||
#---------------------------------------------------------------------
|
||||
# https://github.com/wekan/wekan/issues/3585#issuecomment-1021522132
|
||||
# Add more Node heap:
|
||||
# NODE_OPTIONS="--max_old_space_size=4096"
|
||||
# Add more stack:
|
||||
# bash -c "ulimit -s 65500; exec node --stack-size=65500 main.js"
|
||||
#---------------------------------------------------------------------
|
||||
|
||||
# Install dependencies
|
||||
RUN apk update && apk add ca-certificates outils-sha1 && \
|
||||
@@ -40,7 +49,7 @@ LABEL maintainer="wekan"
|
||||
# Set the environment variables (defaults where required)
|
||||
ENV QEMU_ARCHITECTURE=aarch64 \
|
||||
NODE_ARCHITECTURE=linux-arm64 \
|
||||
NODE_VERSION=v12.22.7 \
|
||||
NODE_VERSION=v12.22.10 \
|
||||
NODE_ENV=production \
|
||||
NPM_VERSION=latest \
|
||||
WITH_API=true \
|
||||
@@ -74,4 +83,15 @@ RUN \
|
||||
EXPOSE $PORT
|
||||
USER wekan
|
||||
|
||||
CMD ["node", "/home/wekan/bundle/main.js"]
|
||||
#---------------------------------------------------------------------
|
||||
# https://github.com/wekan/wekan/issues/3585#issuecomment-1021522132
|
||||
# Add more Node heap:
|
||||
# NODE_OPTIONS="--max_old_space_size=4096"
|
||||
# Add more stack:
|
||||
# bash -c "ulimit -s 65500; exec node --stack-size=65500 main.js"
|
||||
#---------------------------------------------------------------------
|
||||
#
|
||||
#CMD ["node", "/home/wekan/bundle/main.js"]
|
||||
|
||||
CMD ["bash", "-c", "ulimit -s 65500; exec node --stack-size=65500 /home/wekan/bundle/main.js"]
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
|
||||
appVersion: "v5.75.0"
|
||||
appVersion: "v6.09.0"
|
||||
files:
|
||||
userUploads:
|
||||
- README.md
|
||||
|
||||
@@ -26,6 +26,8 @@ BlazeComponent.extendComponent({
|
||||
if (card.isLinkedCard()) {
|
||||
boardId = Cards.findOne(card.linkedId).boardId;
|
||||
cardId = card.linkedId;
|
||||
} else if (card.isLinkedBoard()) {
|
||||
boardId = card.linkedId;
|
||||
}
|
||||
if (text) {
|
||||
CardComments.insert({
|
||||
|
||||
@@ -31,7 +31,6 @@
|
||||
background-color: #fff
|
||||
border: 0
|
||||
box-shadow: 0 1px 2px rgba(0, 0, 0, .23)
|
||||
color: #8c8c8c
|
||||
height: 36px
|
||||
margin: 4px 4px 6px 0
|
||||
padding: 9px 11px
|
||||
|
||||
@@ -15,9 +15,16 @@ setBoardColor(color)
|
||||
.is-selected .minicard
|
||||
border-left: 3px solid color
|
||||
|
||||
// All minicards rounded corners:
|
||||
.minicard
|
||||
border-radius: 7px
|
||||
padding: 10px 10px 4px 10px
|
||||
box-shadow: 2px 2px 4px 0px rgba(0,0,0,0.15)
|
||||
|
||||
button[type=submit].primary, input[type=submit].primary,
|
||||
.sidebar .sidebar-content .sidebar-btn
|
||||
background-color: darken(color, 20%)
|
||||
border-radius: 7px
|
||||
|
||||
&.pop-over .pop-over-list li a:not(.disabled):hover,
|
||||
.sidebar .sidebar-content .sidebar-btn:hover,
|
||||
@@ -186,9 +193,10 @@ setBoardColor(color)
|
||||
.list >.list-header, .swimlane-header
|
||||
color:rgba(255,255,255,.7)
|
||||
|
||||
/* minicards */
|
||||
/* minicards
|
||||
.minicard
|
||||
background-color:rgba(255,255,255,.4)
|
||||
*/
|
||||
|
||||
.minicard-wrapper.is-selected .minicard,
|
||||
.minicard:hover,
|
||||
@@ -196,9 +204,12 @@ setBoardColor(color)
|
||||
.open-minicard-composer:hover
|
||||
background-color:rgba(255,255,255,.8) !important
|
||||
color:#000
|
||||
border-radius: 7px
|
||||
|
||||
/*
|
||||
.minicard, .minicard .badge
|
||||
color:#fff
|
||||
*/
|
||||
|
||||
.minicard:hover .badge, .minicard-wrapper.is-selected .badge
|
||||
color:#000
|
||||
@@ -214,6 +225,10 @@ setBoardColor(color)
|
||||
.sidebar-content h3, .sidebar-content h2, .sidebar-content
|
||||
color:rgba(255,255,255,.7) !important
|
||||
|
||||
.card-details .activities .activity .activity-desc .activity-comment
|
||||
background-color: #cccccc
|
||||
color: #222222
|
||||
|
||||
.board-color-relax
|
||||
setBoardColor(#27AE61)
|
||||
|
||||
@@ -225,7 +240,7 @@ setBoardColor(color)
|
||||
|
||||
.list-header
|
||||
background-color:#a7e366
|
||||
border-bottom: 6px solid #a7e366
|
||||
// border-bottom: 6px solid #a7e366
|
||||
|
||||
.list-body
|
||||
background-color:#a7e366
|
||||
@@ -450,7 +465,7 @@ setBoardClear(color1,color2)
|
||||
background-color: rgba(255,255,255,0.7)
|
||||
color: rgba(0,0,0,0.8)
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,.2)
|
||||
|
||||
border-radius: 7px
|
||||
.quiet, .quiet a
|
||||
color: rgba(0,0,0,0.4)
|
||||
|
||||
@@ -465,6 +480,7 @@ setBoardClear(color1,color2)
|
||||
|
||||
a:not(.disabled).is-active.fa, a:not(.disabled).is-active i.fa, a:not(.disabled):hover.fa, a:not(.disabled):hover i.fa
|
||||
color: rgba(0,0,0,0.6)
|
||||
border-radius: 7px
|
||||
|
||||
input[type="email"], input[type="password"], input[type="text"]
|
||||
border: 0
|
||||
@@ -541,8 +557,8 @@ setBoardClear(color1,color2)
|
||||
background-color:#dedede
|
||||
|
||||
.list-header
|
||||
background-color: #c9cfc3
|
||||
border-bottom: 6px solid #c9cfc3
|
||||
// background-color: #c9cfc3
|
||||
// border-bottom: 6px solid #c9cfc3
|
||||
|
||||
.swimlane .swimlane-header-wrap
|
||||
background-color: #c2c0ab
|
||||
@@ -645,7 +661,7 @@ setBoardClear(color1,color2)
|
||||
|
||||
.list-header
|
||||
background: none
|
||||
border-bottom-width: 0px
|
||||
// border-bottom-width: 0px
|
||||
|
||||
.list-header .list-header-name
|
||||
font-family: Poppins
|
||||
@@ -758,16 +774,17 @@ setBoardClear(color1,color2)
|
||||
|
||||
/* Forms */
|
||||
button[type=submit].primary, .board-color-modern input[type=submit].primary
|
||||
background-color: #819C5D
|
||||
background-color: #777777
|
||||
border-radius: 7px
|
||||
|
||||
.toggle-switch:checked~.toggle-label
|
||||
background-color: #D2E9B4
|
||||
background-color: #f7f7f7
|
||||
|
||||
.toggle-label:after, .board-color-modern .toggle-switch:checked~.toggle-label:after
|
||||
background-color: #819C5D !important
|
||||
background-color: #777777 !important
|
||||
|
||||
button, input:not([type=file]), select, textarea
|
||||
border-radius: 2px
|
||||
border-radius: 7px
|
||||
|
||||
/* Headers */
|
||||
&#header
|
||||
@@ -854,21 +871,22 @@ setBoardClear(color1,color2)
|
||||
.swimlane .list:first-child
|
||||
margin-left: 0
|
||||
|
||||
.swimlane .list:nth-child(even)
|
||||
background: #5f5f5f
|
||||
.swimlane .list:nth-child(even) .list-header,
|
||||
.swimlane .list:nth-child(even) .list-body
|
||||
background: #6a6a6a
|
||||
|
||||
.swimlane .list:nth-child(odd) .list-header
|
||||
background: #3b3b3b
|
||||
.swimlane .list:nth-child(odd) .list-header,
|
||||
.swimlane .list:nth-child(odd) .list-body
|
||||
background: #555555
|
||||
|
||||
.list-header
|
||||
background: #333333
|
||||
padding: 10px
|
||||
border-bottom: 0
|
||||
|
||||
.list-header .viewer
|
||||
padding-left: 10px
|
||||
|
||||
.list-header .list-header-name
|
||||
.list-header .list-header-name,
|
||||
.minicard
|
||||
line-height: 14px
|
||||
color: #eeeeee
|
||||
|
||||
@@ -876,7 +894,7 @@ setBoardClear(color1,color2)
|
||||
padding: 10px
|
||||
top: 0
|
||||
|
||||
.list-header .list-header-plus-icon
|
||||
.list-header .list-header-plus-top
|
||||
color: #a6a6a6
|
||||
|
||||
.list-body
|
||||
@@ -906,6 +924,7 @@ setBoardClear(color1,color2)
|
||||
|
||||
.list-body a.open-minicard-composer:hover, .list-body a.open-minicard-composer:hover i, .list .list-composer .open-list-composer:hover i
|
||||
color: #ffffff
|
||||
border-radius: 7px
|
||||
|
||||
/* Mini Card */
|
||||
.minicard-wrapper
|
||||
@@ -916,12 +935,13 @@ setBoardClear(color1,color2)
|
||||
color: #cccccc
|
||||
border-radius: 2px
|
||||
font-size: 0.95em
|
||||
padding: 10px
|
||||
box-shadow: 0 4px 3px -3px rgba(0,0,0,0.8)
|
||||
border-bottom: 1px solid #666666
|
||||
padding: 8px
|
||||
|
||||
.minicard:hover
|
||||
background-color: #494949 !important
|
||||
color: #f7f7f7
|
||||
background-color: #4d4d4d !important
|
||||
|
||||
.minicard .minicard-labels
|
||||
margin-bottom: 4px
|
||||
@@ -956,17 +976,24 @@ setBoardClear(color1,color2)
|
||||
|
||||
/* Card Details */
|
||||
.card-details
|
||||
position: absolute
|
||||
top: 30px
|
||||
left: calc(50% - 384px)
|
||||
width: 768px
|
||||
max-height: calc(100% - 60px)
|
||||
background-color: #454545
|
||||
color: #cccccc
|
||||
box-shadow: 0 4px 8px 0 rgba(0, 0, 0, 0.2), 0 6px 20px 0 rgba(0, 0, 0, 0.19)
|
||||
border: 1px solid #111111
|
||||
z-index: 100 !important
|
||||
|
||||
@media screen and (max-width: 800px)
|
||||
.card-details
|
||||
width: 98%
|
||||
|
||||
@media screen and (min-width: 801px)
|
||||
.card-details
|
||||
position: absolute
|
||||
top: 30px
|
||||
left: calc(50% - 384px)
|
||||
width: 768px
|
||||
max-height: calc(100% - 60px)
|
||||
|
||||
.card-details
|
||||
scrollbar-width: thin
|
||||
scrollbar-color: #343434 #999999
|
||||
@@ -1018,8 +1045,8 @@ setBoardClear(color1,color2)
|
||||
border-color: #ffffff
|
||||
|
||||
.card-details .check-box.materialCheckBox.is-checked
|
||||
border-bottom: 2px solid #819C5D
|
||||
border-right: 2px solid #819C5D
|
||||
border-bottom: 2px solid #ffffff
|
||||
border-right: 2px solid #ffffff
|
||||
border-top: 0
|
||||
border-left: 0
|
||||
|
||||
@@ -1059,5 +1086,5 @@ setBoardClear(color1,color2)
|
||||
font-size: 16px
|
||||
color: #cccccc
|
||||
|
||||
.pop-over.board-color-moderndark .pop-over-list li:hover > a
|
||||
background-color: #819C5D !important
|
||||
.pop-over.board-color-moderndark .pop-over-list li > a:hover
|
||||
background-color: rgba(255,255,255,0.2)
|
||||
@@ -235,9 +235,9 @@ template(name="createBoard")
|
||||
= " "
|
||||
| {{{_ 'board-private-info'}}}
|
||||
a.js-change-visibility {{_ 'change'}}.
|
||||
//a.flex.js-toggle-add-template-container
|
||||
// .materialCheckBox#add-template-container
|
||||
// span {{_ 'add-template-container'}}
|
||||
a.flex.js-toggle-add-template-container
|
||||
.materialCheckBox#add-template-container
|
||||
span {{_ 'add-template-container'}}
|
||||
input.primary.wide(type="submit" value="{{_ 'create'}}")
|
||||
span.quiet
|
||||
| {{_ 'or'}}
|
||||
|
||||
@@ -14,6 +14,14 @@ template(name="boardList")
|
||||
option(value="-1") {{_ 'organizations'}} :
|
||||
each orgsDatas
|
||||
option(value="{{orgId}}") {{_ orgDisplayName}}
|
||||
|
||||
//li.AllBoardTemplates
|
||||
// if userHasTemplates
|
||||
// select.js-AllBoardTemplates#jsAllBoardTemplates("multiple")
|
||||
// option(value="-1") {{_ 'templates'}} :
|
||||
// each templatesDatas
|
||||
// option(value="{{templateId}}") {{_ templateDisplayName}}
|
||||
|
||||
li.AllBoardBtns
|
||||
div.AllBoardButtonsContainer
|
||||
if userHasOrgsOrTeams
|
||||
@@ -54,11 +62,11 @@ template(name="boardList")
|
||||
i.fa.js-has-spenttime-cards(
|
||||
class="fa-circle{{#if hasOvertimeCards}} has-overtime-card-active{{else}} no-overtime-card-active{{/if}}"
|
||||
title="{{#if hasOvertimeCards}}{{_ 'has-overtime-cards'}}{{else}}{{_ 'has-spenttime-cards'}}{{/if}}")
|
||||
if isMiniScreen
|
||||
if isMiniScreenOrShowDesktopDragHandles
|
||||
i.fa.board-handle(
|
||||
class="fa-arrows"
|
||||
title="{{_ 'Drag board'}}")
|
||||
unless isMiniScreen
|
||||
else
|
||||
if isSandstorm
|
||||
i.fa.js-clone-board(
|
||||
class="fa-clone"
|
||||
@@ -96,11 +104,11 @@ template(name="boardList")
|
||||
i.fa.js-has-spenttime-cards(
|
||||
class="fa-circle{{#if hasOvertimeCards}} has-overtime-card-active{{else}} no-overtime-card-active{{/if}}"
|
||||
title="{{#if hasOvertimeCards}}{{_ 'has-overtime-cards'}}{{else}}{{_ 'has-spenttime-cards'}}{{/if}}")
|
||||
if isMiniScreen
|
||||
if isMiniScreenOrShowDesktopDragHandles
|
||||
i.fa.board-handle(
|
||||
class="fa-arrows"
|
||||
title="{{_ 'Drag board'}}")
|
||||
unless isMiniScreen
|
||||
else
|
||||
if isSandstorm
|
||||
i.fa.js-clone-board(
|
||||
class="fa-clone"
|
||||
|
||||
@@ -1,5 +1,4 @@
|
||||
const subManager = new SubsManager();
|
||||
const { calculateIndex, enableClickOnTouch } = Utils;
|
||||
|
||||
Template.boardListHeaderBar.events({
|
||||
'click .js-open-archived-board'() {
|
||||
@@ -9,7 +8,11 @@ Template.boardListHeaderBar.events({
|
||||
|
||||
Template.boardListHeaderBar.helpers({
|
||||
title() {
|
||||
//if (FlowRouter.getRouteName() === 'template-container') {
|
||||
// return 'template-container';
|
||||
//} else {
|
||||
return FlowRouter.getRouteName() === 'home' ? 'my-boards' : 'public';
|
||||
//}
|
||||
},
|
||||
templatesBoardId() {
|
||||
return Meteor.user() && Meteor.user().getTemplatesBoardId();
|
||||
@@ -56,7 +59,7 @@ BlazeComponent.extendComponent({
|
||||
// of the previous and the following card -- if any.
|
||||
const prevBoardDom = ui.item.prev('.js-board').get(0);
|
||||
const nextBoardBom = ui.item.next('.js-board').get(0);
|
||||
const sortIndex = calculateIndex(prevBoardDom, nextBoardBom, 1);
|
||||
const sortIndex = Utils.calculateIndex(prevBoardDom, nextBoardBom, 1);
|
||||
|
||||
const boardDomElement = ui.item.get(0);
|
||||
const board = Blaze.getData(boardDomElement);
|
||||
@@ -73,12 +76,9 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
});
|
||||
|
||||
// ugly touch event hotfix
|
||||
enableClickOnTouch(itemsSelector);
|
||||
|
||||
// Disable drag-dropping if the current user is not a board member or is comment only
|
||||
this.autorun(() => {
|
||||
if (Utils.isMiniScreen()) {
|
||||
if (Utils.isMiniScreenOrShowDesktopDragHandles()) {
|
||||
$boards.sortable({
|
||||
handle: '.board-handle',
|
||||
});
|
||||
@@ -93,7 +93,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
teamsDatas() {
|
||||
if(Meteor.user().teams)
|
||||
return Meteor.user().teams;
|
||||
return Meteor.user().teams.sort((a, b) => a.teamDisplayName.localeCompare(b.teamDisplayName));
|
||||
else
|
||||
return [];
|
||||
},
|
||||
@@ -103,9 +103,17 @@ BlazeComponent.extendComponent({
|
||||
else
|
||||
return false;
|
||||
},
|
||||
/*
|
||||
userHasTemplates(){
|
||||
if(Meteor.user() != null && Meteor.user().orgs && Meteor.user().orgs.length > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
},
|
||||
*/
|
||||
orgsDatas() {
|
||||
if(Meteor.user().orgs)
|
||||
return Meteor.user().orgs;
|
||||
return Meteor.user().orgs.sort((a, b) => a.orgDisplayName.localeCompare(b.orgDisplayName));
|
||||
else
|
||||
return [];
|
||||
},
|
||||
@@ -126,12 +134,11 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
boards() {
|
||||
let query = {
|
||||
//archived: false,
|
||||
////type: { $in: ['board','template-container'] },
|
||||
//type: 'board',
|
||||
// { type: 'board' },
|
||||
// { type: { $in: ['board','template-container'] } },
|
||||
$and: [
|
||||
{ archived: false },
|
||||
{ type: 'board' },
|
||||
{ type: { $in: ['board','template-container'] } },
|
||||
{ $or:[] }
|
||||
]
|
||||
};
|
||||
@@ -234,6 +241,7 @@ BlazeComponent.extendComponent({
|
||||
this.setError(err.error);
|
||||
} else {
|
||||
Session.set('fromBoard', null);
|
||||
subManager.subscribe('board', res, false);
|
||||
Utils.goBoardId(res);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -44,6 +44,7 @@ template(name="attachmentsGalery")
|
||||
+spinner
|
||||
p.attachment-details
|
||||
= name
|
||||
span.file-size ({{fileSize size}} KB)
|
||||
span.attachment-details-actions
|
||||
a.js-download(href="{{url download=true}}")
|
||||
i.fa.fa-download
|
||||
|
||||
@@ -49,6 +49,9 @@ Template.attachmentsGalery.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
fileSize(size) {
|
||||
return Math.round(size / 1024);
|
||||
},
|
||||
});
|
||||
|
||||
Template.previewAttachedImagePopup.events({
|
||||
|
||||
@@ -63,7 +63,7 @@ template(name="cardCustomField-checkbox")
|
||||
template(name="cardCustomField-currency")
|
||||
if canModifyCard
|
||||
+inlinedForm(classNames="js-card-customfield-currency")
|
||||
input(type="text" value=data.value)
|
||||
input(type="text" value=data.value autofocus)
|
||||
.edit-controls.clearfix
|
||||
button.primary(type="submit") {{_ 'save'}}
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
|
||||
@@ -271,7 +271,7 @@ CardCustomField.register('cardCustomField');
|
||||
{
|
||||
'submit .js-card-customfield-stringtemplate'(event) {
|
||||
event.preventDefault();
|
||||
const items = this.getItems();
|
||||
const items = this.stringtemplateItems.get();
|
||||
this.card.setCustomField(this.customFieldId, items);
|
||||
},
|
||||
|
||||
@@ -279,9 +279,7 @@ CardCustomField.register('cardCustomField');
|
||||
if (event.keyCode === 13) {
|
||||
event.preventDefault();
|
||||
|
||||
if (event.metaKey || event.ctrlKey) {
|
||||
this.find('button[type=submit]').click();
|
||||
} else if (event.target.value.trim()) {
|
||||
if (event.target.value.trim() || event.metaKey || event.ctrlKey) {
|
||||
const inputLast = this.find('input.last');
|
||||
|
||||
let items = this.getItems();
|
||||
@@ -307,6 +305,9 @@ CardCustomField.register('cardCustomField');
|
||||
|
||||
this.stringtemplateItems.set(items);
|
||||
}
|
||||
if (event.metaKey || event.ctrlKey) {
|
||||
this.find('button[type=submit]').click();
|
||||
}
|
||||
}
|
||||
},
|
||||
|
||||
|
||||
@@ -22,6 +22,7 @@ template(name="cardDetails")
|
||||
title="{{_ 'copy-card-link-to-clipboard'}}"
|
||||
href="{{ originRelativeUrl }}"
|
||||
)
|
||||
span.copied-tooltip {{_ 'copied'}}
|
||||
else
|
||||
unless isPopup
|
||||
a.fa.fa-times-thin.close-card-details.js-close-card-details(title="{{_ 'close-card'}}")
|
||||
@@ -33,6 +34,7 @@ template(name="cardDetails")
|
||||
title="{{_ 'copy-card-link-to-clipboard'}}"
|
||||
href="{{ originRelativeUrl }}"
|
||||
)
|
||||
span.copied-tooltip {{_ 'copied'}}
|
||||
h2.card-details-title.js-card-title(
|
||||
class="{{#if canModifyCard}}js-open-inlined-form is-editable{{/if}}")
|
||||
+viewer
|
||||
@@ -232,6 +234,15 @@ template(name="cardDetails")
|
||||
+viewer
|
||||
= sort
|
||||
|
||||
if currentBoard.allowsShowLists
|
||||
.card-details-item.card-details-show-lists
|
||||
h3.card-details-item-title
|
||||
i.fa.fa-list
|
||||
| {{_ 'list'}}
|
||||
select.js-select-card-details-lists(disabled="{{#unless canModifyCard}}disabled{{/unless}}")
|
||||
each currentBoard.lists
|
||||
option(value="{{_id}}" selected="{{#if isCurrentListId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
//.card-details-items
|
||||
if getSpentTime
|
||||
.card-details-item.card-details-item-spent
|
||||
@@ -574,6 +585,8 @@ template(name="cardDetails")
|
||||
+activities(card=this mode="card")
|
||||
|
||||
template(name="editCardTitleForm")
|
||||
a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}")
|
||||
span.copied-tooltip {{_ 'copied'}}
|
||||
textarea.js-edit-card-title(rows='1' autofocus dir="auto")
|
||||
= getTitle
|
||||
.edit-controls.clearfix
|
||||
@@ -721,17 +734,17 @@ template(name="boardsAndLists")
|
||||
if $eq _id currentBoard._id
|
||||
option(value="{{_id}}" selected) {{_ 'current'}}
|
||||
else
|
||||
option(value="{{_id}}") {{title}}
|
||||
option(value="{{_id}}" selected="{{#if isMoveAndCopyDialogOptionBoardId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
label {{_ 'swimlanes'}}:
|
||||
select.js-select-swimlanes
|
||||
each swimlanes
|
||||
option(value="{{_id}}") {{title}}
|
||||
option(value="{{_id}}" selected="{{#if isMoveAndCopyDialogOptionSwimlaneId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
label {{_ 'lists'}}:
|
||||
select.js-select-lists
|
||||
each aBoardLists
|
||||
option(value="{{_id}}") {{title}}
|
||||
option(value="{{_id}}" selected="{{#if isMoveAndCopyDialogOptionListId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm.js-done {{_ 'done'}}
|
||||
@@ -798,6 +811,7 @@ template(name="cardMorePopup")
|
||||
i.fa.colorful(class="{{#if board.isPublic}}fa-globe{{else}}fa-lock{{/if}}")
|
||||
input.inline-input(type="text" id="cardURL" readonly value="{{ originRelativeUrl }}" autofocus="autofocus")
|
||||
button.js-copy-card-link-to-clipboard(class="btn" id="clipboard") {{_ 'copy-card-link-to-clipboard'}}
|
||||
.copied-tooltip {{_ 'copied'}}
|
||||
span.clearfix
|
||||
br
|
||||
h2 {{_ 'change-card-parent'}}
|
||||
|
||||
@@ -70,7 +70,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
|
||||
cardMaximized() {
|
||||
return Meteor.user().hasCardMaximized();
|
||||
return !Utils.getPopupCardId() && Meteor.user().hasCardMaximized();
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
@@ -168,6 +168,15 @@ BlazeComponent.extendComponent({
|
||||
);
|
||||
},
|
||||
|
||||
/** returns if the list id is the current list id
|
||||
* @param listId list id to check
|
||||
* @return is the list id the current list id ?
|
||||
*/
|
||||
isCurrentListId(listId) {
|
||||
const ret = this.data().listId == listId;
|
||||
return ret;
|
||||
},
|
||||
|
||||
onRendered() {
|
||||
if (Meteor.settings.public.CARD_OPENED_WEBHOOK_ENABLED) {
|
||||
// Send Webhook but not create Activities records ---
|
||||
@@ -325,29 +334,10 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
'click .js-copy-link'(event) {
|
||||
event.preventDefault();
|
||||
const StringToCopyElement = document.getElementById('cardURL_copy');
|
||||
StringToCopyElement.value =
|
||||
window.location.origin + window.location.pathname;
|
||||
StringToCopyElement.select();
|
||||
if (document.execCommand('copy')) {
|
||||
StringToCopyElement.blur();
|
||||
} else {
|
||||
document.getElementById('cardURL_copy').selectionStart = 0;
|
||||
document.getElementById('cardURL_copy').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();
|
||||
}
|
||||
}
|
||||
const promise = Utils.copyTextToClipboard(event.target.href);
|
||||
|
||||
const $tooltip = this.$('.card-details-header .copied-tooltip');
|
||||
Utils.showCopied(promise, $tooltip);
|
||||
},
|
||||
'click .js-open-card-details-menu': Popup.open('cardDetailsActions'),
|
||||
'submit .js-card-description'(event) {
|
||||
@@ -398,6 +388,12 @@ BlazeComponent.extendComponent({
|
||||
card.move(card.boardId, card.swimlaneId, card.listId, sort);
|
||||
}
|
||||
},
|
||||
'change .js-select-card-details-lists'(event) {
|
||||
let card = this.data();
|
||||
const listSelect = this.$('.js-select-card-details-lists')[0];
|
||||
const listId = listSelect.options[listSelect.selectedIndex].value;
|
||||
card.move(card.boardId, card.swimlaneId, listId, card.sort);
|
||||
},
|
||||
'click .js-go-to-linked-card'() {
|
||||
Utils.goCardId(this.data().linkedId);
|
||||
},
|
||||
@@ -546,7 +542,8 @@ Template.cardDetails.helpers({
|
||||
}
|
||||
});
|
||||
Template.cardDetailsPopup.onDestroyed(() => {
|
||||
Session.delete('popupCard');
|
||||
Session.delete('popupCardId');
|
||||
Session.delete('popupCardBoardId');
|
||||
});
|
||||
Template.cardDetailsPopup.helpers({
|
||||
popupCard() {
|
||||
@@ -676,7 +673,7 @@ Template.cardDetailsActionsPopup.events({
|
||||
event.preventDefault();
|
||||
const minOrder = _.min(
|
||||
this.list()
|
||||
.cards(this.swimlaneId)
|
||||
.cardsUnfiltered(this.swimlaneId)
|
||||
.map((c) => c.sort),
|
||||
);
|
||||
this.move(this.boardId, this.swimlaneId, this.listId, minOrder - 1);
|
||||
@@ -686,7 +683,7 @@ Template.cardDetailsActionsPopup.events({
|
||||
event.preventDefault();
|
||||
const maxOrder = _.max(
|
||||
this.list()
|
||||
.cards(this.swimlaneId)
|
||||
.cardsUnfiltered(this.swimlaneId)
|
||||
.map((c) => c.sort),
|
||||
);
|
||||
this.move(this.boardId, this.swimlaneId, this.listId, maxOrder + 1);
|
||||
@@ -707,9 +704,31 @@ Template.cardDetailsActionsPopup.events({
|
||||
},
|
||||
});
|
||||
|
||||
Template.editCardTitleForm.onRendered(function () {
|
||||
autosize(this.$('.js-edit-card-title'));
|
||||
});
|
||||
BlazeComponent.extendComponent({
|
||||
onRendered() {
|
||||
autosize(this.$('textarea.js-edit-card-title'));
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click a.fa.fa-copy'(event) {
|
||||
const $editor = this.$('textarea');
|
||||
const promise = Utils.copyTextToClipboard($editor[0].value);
|
||||
|
||||
const $tooltip = this.$('.copied-tooltip');
|
||||
Utils.showCopied(promise, $tooltip);
|
||||
},
|
||||
'keydown .js-edit-card-title'(event) {
|
||||
// If enter key was pressed, submit the data
|
||||
// Unless the shift key is also being pressed
|
||||
if (event.keyCode === 13 && !event.shiftKey) {
|
||||
$('.js-submit-edit-card-title-form').click();
|
||||
}
|
||||
},
|
||||
}
|
||||
];
|
||||
}
|
||||
}).register('editCardTitleForm');
|
||||
|
||||
Template.cardMembersPopup.onCreated(function () {
|
||||
let currBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
@@ -769,16 +788,6 @@ const filterMembers = (filterTerm) => {
|
||||
return members;
|
||||
}
|
||||
|
||||
Template.editCardTitleForm.events({
|
||||
'keydown .js-edit-card-title'(event) {
|
||||
// If enter key was pressed, submit the data
|
||||
// Unless the shift key is also being pressed
|
||||
if (event.keyCode === 13 && !event.shiftKey) {
|
||||
$('.js-submit-edit-card-title-form').click();
|
||||
}
|
||||
},
|
||||
});
|
||||
|
||||
Template.editCardRequesterForm.onRendered(function () {
|
||||
autosize(this.$('.js-edit-card-requester'));
|
||||
});
|
||||
@@ -807,15 +816,16 @@ Template.editCardAssignerForm.events({
|
||||
|
||||
Template.moveCardPopup.events({
|
||||
'click .js-done'() {
|
||||
// XXX We should *not* get the currentCard from the global state, but
|
||||
// instead from a “component” state.
|
||||
const card = Utils.getCurrentCard();
|
||||
const card = Cards.findOne(this._id);
|
||||
const bSelect = $('.js-select-boards')[0];
|
||||
let boardId;
|
||||
// if we are a worker, we won't have a board select so we just use the
|
||||
// current boardId of the card.
|
||||
if (bSelect) boardId = bSelect.options[bSelect.selectedIndex].value;
|
||||
else boardId = card.boardId;
|
||||
if (bSelect) {
|
||||
boardId = bSelect.options[bSelect.selectedIndex].value;
|
||||
} else {
|
||||
boardId = card.boardId;
|
||||
}
|
||||
const lSelect = $('.js-select-lists')[0];
|
||||
const listId = lSelect.options[lSelect.selectedIndex].value;
|
||||
const slSelect = $('.js-select-swimlanes')[0];
|
||||
@@ -832,8 +842,56 @@ Template.moveCardPopup.events({
|
||||
});
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
subManager.subscribe('board', Session.get('currentBoard'), false);
|
||||
this.selectedBoardId = new ReactiveVar(Session.get('currentBoard'));
|
||||
this.currentBoardId = Utils.getCurrentBoardId();
|
||||
this.selectedBoardId = new ReactiveVar(this.currentBoardId);
|
||||
this.setMoveAndCopyDialogOption(this.currentBoardId);
|
||||
},
|
||||
|
||||
/** set the last confirmed dialog field values
|
||||
* @param boardId the current board id
|
||||
*/
|
||||
setMoveAndCopyDialogOption(boardId) {
|
||||
this.moveAndCopyDialogOption = {
|
||||
'boardId' : "",
|
||||
'swimlaneId' : "",
|
||||
'listId' : "",
|
||||
}
|
||||
|
||||
let currentOptions = Meteor.user().getMoveAndCopyDialogOptions();
|
||||
if (currentOptions && boardId && currentOptions[boardId]) {
|
||||
this.moveAndCopyDialogOption = currentOptions[boardId];
|
||||
if (this.moveAndCopyDialogOption.boardId) {
|
||||
this.selectedBoardId.set(this.moveAndCopyDialogOption.boardId)
|
||||
}
|
||||
}
|
||||
subManager.subscribe('board', this.selectedBoardId.get(), false);
|
||||
},
|
||||
|
||||
/** returns if the board id was the last confirmed one
|
||||
* @param boardId check this board id
|
||||
* @return if the board id was the last confirmed one
|
||||
*/
|
||||
isMoveAndCopyDialogOptionBoardId(boardId) {
|
||||
let ret = this.moveAndCopyDialogOption.boardId == boardId;
|
||||
return ret;
|
||||
},
|
||||
|
||||
/** returns if the swimlane id was the last confirmed one
|
||||
* @param swimlaneId check this swimlane id
|
||||
* @return if the swimlane id was the last confirmed one
|
||||
*/
|
||||
isMoveAndCopyDialogOptionSwimlaneId(swimlaneId) {
|
||||
let ret = this.moveAndCopyDialogOption.swimlaneId == swimlaneId;
|
||||
return ret;
|
||||
},
|
||||
|
||||
/** returns if the list id was the last confirmed one
|
||||
* @param listId check this list id
|
||||
* @return if the list id was the last confirmed one
|
||||
*/
|
||||
isMoveAndCopyDialogOptionListId(listId) {
|
||||
let ret = this.moveAndCopyDialogOption.listId == listId;
|
||||
return ret;
|
||||
},
|
||||
|
||||
boards() {
|
||||
@@ -862,9 +920,27 @@ BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-done'() {
|
||||
const boardSelect = this.$('.js-select-boards')[0];
|
||||
const boardId = boardSelect.options[boardSelect.selectedIndex].value;
|
||||
|
||||
const listSelect = this.$('.js-select-lists')[0];
|
||||
const listId = listSelect.options[listSelect.selectedIndex].value;
|
||||
|
||||
const swimlaneSelect = this.$('.js-select-swimlanes')[0];
|
||||
const swimlaneId = swimlaneSelect.options[swimlaneSelect.selectedIndex].value;
|
||||
|
||||
const options = {
|
||||
'boardId' : boardId,
|
||||
'swimlaneId' : swimlaneId,
|
||||
'listId' : listId,
|
||||
}
|
||||
Meteor.user().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
},
|
||||
'change .js-select-boards'(event) {
|
||||
this.selectedBoardId.set($(event.currentTarget).val());
|
||||
subManager.subscribe('board', this.selectedBoardId.get(), false);
|
||||
const boardId = $(event.currentTarget).val();
|
||||
this.selectedBoardId.set(boardId);
|
||||
subManager.subscribe('board', boardId, false);
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -1088,30 +1164,11 @@ BlazeComponent.extendComponent({
|
||||
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-copy-card-link-to-clipboard'(event) {
|
||||
const promise = Utils.copyTextToClipboard(location.origin + document.getElementById('cardURL').value);
|
||||
|
||||
const $tooltip = this.$('.copied-tooltip');
|
||||
Utils.showCopied(promise, $tooltip);
|
||||
},
|
||||
'click .js-delete': Popup.afterConfirm('cardDelete', function () {
|
||||
Popup.close();
|
||||
|
||||
@@ -76,6 +76,12 @@ avatar-radius = 50%
|
||||
box-shadow: 0 0 0 2px darken(white, 60%) inset
|
||||
|
||||
// Other card details
|
||||
.copied-tooltip
|
||||
display: none
|
||||
padding: 0px 10px;
|
||||
background-color: #000000df;
|
||||
color: #fff;
|
||||
border-radius: 5px;
|
||||
|
||||
.card-details
|
||||
padding: 0
|
||||
@@ -86,7 +92,7 @@ avatar-radius = 50%
|
||||
overflow-x: hidden
|
||||
background: darken(white, 3%)
|
||||
border-radius: bottom 3px
|
||||
z-index: 20 !important
|
||||
z-index: 20
|
||||
animation: flexGrowIn 0.1s
|
||||
box-shadow: 0 0 7px 0 darken(white, 30%)
|
||||
transition: flex-basis 0.1s
|
||||
@@ -104,6 +110,9 @@ avatar-radius = 50%
|
||||
padding: 7px 20px
|
||||
background: darken(white, 7%)
|
||||
border-bottom: 1px solid darken(white, 14%)
|
||||
position: sticky
|
||||
top: 0px
|
||||
z-index: 500
|
||||
|
||||
.card-number {
|
||||
color: darken(white, 30%);
|
||||
@@ -118,7 +127,8 @@ avatar-radius = 50%
|
||||
.card-copy-button,
|
||||
.card-copy-mobile-button,
|
||||
.close-card-details-mobile-web,
|
||||
.card-details-menu-mobile-web
|
||||
.card-details-menu-mobile-web,
|
||||
.copied-tooltip
|
||||
float: right
|
||||
|
||||
.close-card-details,
|
||||
@@ -174,6 +184,9 @@ avatar-radius = 50%
|
||||
margin-top: 5px
|
||||
margin-bottom: 10px
|
||||
|
||||
.copied-tooltip
|
||||
padding: 0px 10px
|
||||
|
||||
.card-details-list
|
||||
font-size: 0.85em
|
||||
margin-bottom: 3px
|
||||
@@ -187,6 +200,10 @@ avatar-radius = 50%
|
||||
border-radius: 3px
|
||||
padding: 0px 5px
|
||||
|
||||
.copied-tooltip
|
||||
margin-right: 10px
|
||||
padding: 10px;
|
||||
|
||||
.card-description textarea
|
||||
min-height: 100px
|
||||
|
||||
@@ -197,13 +214,13 @@ avatar-radius = 50%
|
||||
|
||||
.card-details-item
|
||||
margin-right: 0.5em
|
||||
flex-grow: 1
|
||||
&:last-child
|
||||
margin-right: 0
|
||||
&.card-details-item-labels
|
||||
display: block
|
||||
word-wrap: break-word
|
||||
max-width: 95%
|
||||
flex-grow: 1
|
||||
&.card-details-item-members,
|
||||
&.card-details-item-assignees,
|
||||
&.card-details-item-customfield,
|
||||
@@ -211,7 +228,6 @@ avatar-radius = 50%
|
||||
display: block
|
||||
word-wrap: break-word
|
||||
max-width: 36%
|
||||
flex-grow: 1
|
||||
&.card-details-item-creator,
|
||||
&.card-details-item-received,
|
||||
&.card-details-item-start,
|
||||
@@ -220,7 +236,6 @@ avatar-radius = 50%
|
||||
display: block
|
||||
word-wrap: break-word
|
||||
max-width: 28%
|
||||
flex-grow: 1
|
||||
&.custom-fields
|
||||
padding-left: 10px
|
||||
|
||||
@@ -243,7 +258,7 @@ avatar-radius = 50%
|
||||
overflow-x: scroll
|
||||
background: darken(white, 3%)
|
||||
border-radius: bottom 3px
|
||||
z-index: 1000 !important
|
||||
z-index: 100
|
||||
animation: flexGrowIn 0.1s
|
||||
box-shadow: 0 0 7px 0 darken(white, 30%)
|
||||
transition: flex-basis 0.1s
|
||||
|
||||
@@ -12,18 +12,13 @@ template(name="checklists")
|
||||
input.toggle-switch(type="checkbox" id="toggleHideCheckedItemsButton")
|
||||
label.toggle-label(for="toggleHideCheckedItemsButton")
|
||||
|
||||
if toggleDeleteDialog.get
|
||||
.board-overlay#card-details-overlay
|
||||
+checklistDeleteDialog(checklist = checklistToDelete)
|
||||
|
||||
|
||||
.card-checklist-items
|
||||
each checklist in checklists
|
||||
+checklistDetail(checklist = checklist)
|
||||
|
||||
if canModifyCard
|
||||
+inlinedForm(autoclose=false classNames="js-add-checklist" cardId = cardId)
|
||||
+addChecklistItemForm
|
||||
+addChecklistItemForm(checklist=checklist showNewlineBecomesNewChecklistItem=false)
|
||||
else
|
||||
a.add-checklist.js-open-inlined-form(title="{{_ 'add-checklist'}}")
|
||||
i.fa.fa-plus
|
||||
@@ -36,7 +31,7 @@ template(name="checklistDetail")
|
||||
.checklist-title
|
||||
span
|
||||
if canModifyCard
|
||||
a.js-delete-checklist.toggle-delete-checklist-dialog {{_ "delete"}}...
|
||||
a.fa.fa-navicon.checklist-details-menu.js-open-checklist-details-menu(title="{{_ 'checklistActionsPopup-title'}}")
|
||||
|
||||
if canModifyCard
|
||||
h2.title.js-open-inlined-form.is-editable
|
||||
@@ -48,27 +43,33 @@ template(name="checklistDetail")
|
||||
h2.title
|
||||
+viewer
|
||||
= checklist.title
|
||||
|
||||
if $gt finishedPercent 0
|
||||
.checklist-progress-bar-container
|
||||
.checklist-progress-text {{finishedPercent}}%
|
||||
.checklist-progress-bar
|
||||
.checklist-progress(style="width:{{finishedPercent}}%")
|
||||
+checklistItems(checklist = checklist)
|
||||
|
||||
template(name="checklistDeleteDialog")
|
||||
.js-confirm-checklist-delete
|
||||
p
|
||||
i(class="fa fa-exclamation-triangle" aria-hidden="true")
|
||||
p
|
||||
| {{_ 'confirm-checklist-delete-dialog'}}
|
||||
span {{checklist.title}}
|
||||
| ?
|
||||
.js-checklist-delete-buttons
|
||||
button.confirm-checklist-delete(type="button") {{_ 'delete'}}
|
||||
button.toggle-delete-checklist-dialog(type="button") {{_ 'cancel'}}
|
||||
template(name="checklistDeletePopup")
|
||||
p {{_ 'confirm-checklist-delete-popup'}}
|
||||
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
|
||||
|
||||
template(name="addChecklistItemForm")
|
||||
a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}")
|
||||
span.copied-tooltip {{_ 'copied'}}
|
||||
textarea.js-add-checklist-item(rows='1' autofocus)
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm.js-submit-add-checklist-item-form(type="submit") {{_ 'save'}}
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
if showNewlineBecomesNewChecklistItem
|
||||
.material-toggle-switch(title="{{_ 'newlineBecomesNewChecklistItem'}}")
|
||||
input.toggle-switch(type="checkbox" id="toggleNewlineBecomesNewChecklistItem")
|
||||
label.toggle-label(for="toggleNewlineBecomesNewChecklistItem")
|
||||
|
||||
template(name="editChecklistItemForm")
|
||||
a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}")
|
||||
span.copied-tooltip {{_ 'copied'}}
|
||||
textarea.js-edit-checklist-item(rows='1' autofocus dir="auto")
|
||||
if $eq type 'item'
|
||||
= item.title
|
||||
@@ -93,7 +94,7 @@ template(name="checklistItems")
|
||||
+checklistItemDetail(item = item checklist = checklist)
|
||||
if canModifyCard
|
||||
+inlinedForm(autoclose=false classNames="js-add-checklist-item" checklist = checklist)
|
||||
+addChecklistItemForm
|
||||
+addChecklistItemForm(checklist=checklist showNewlineBecomesNewChecklistItem=true)
|
||||
else
|
||||
a.add-checklist-item.js-open-inlined-form(title="{{_ 'add-checklist-item'}}")
|
||||
i.fa.fa-plus
|
||||
@@ -142,3 +143,50 @@ template(name="boardsSwimlanesAndLists")
|
||||
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm.js-done {{_ 'done'}}
|
||||
|
||||
template(name="checklistActionsPopup")
|
||||
ul.pop-over-list
|
||||
li
|
||||
a.js-delete-checklist.delete-checklist
|
||||
i.fa.fa-trash
|
||||
| {{_ "delete"}} ...
|
||||
a.js-move-checklist.move-checklist
|
||||
i.fa.fa-arrow-right
|
||||
| {{_ "moveChecklist"}} ...
|
||||
a.js-copy-checklist.copy-checklist
|
||||
i.fa.fa-copy
|
||||
| {{_ "copyChecklist"}} ...
|
||||
|
||||
template(name="copyChecklistPopup")
|
||||
+copyAndMoveChecklist
|
||||
|
||||
template(name="moveChecklistPopup")
|
||||
+copyAndMoveChecklist
|
||||
|
||||
template(name="copyAndMoveChecklist")
|
||||
unless currentUser.isWorker
|
||||
label {{_ 'boards'}}:
|
||||
select.js-select-boards(autofocus)
|
||||
each boards
|
||||
if $eq _id currentBoard._id
|
||||
option(value="{{_id}}" selected) {{_ 'current'}}
|
||||
else
|
||||
option(value="{{_id}}" selected="{{#if isChecklistDialogOptionBoardId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
label {{_ 'swimlanes'}}:
|
||||
select.js-select-swimlanes
|
||||
each swimlanes
|
||||
option(value="{{_id}}" selected="{{#if isChecklistDialogOptionSwimlaneId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
label {{_ 'lists'}}:
|
||||
select.js-select-lists
|
||||
each lists
|
||||
option(value="{{_id}}" selected="{{#if isChecklistDialogOptionListId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
label {{_ 'cards'}}:
|
||||
select.js-select-cards
|
||||
each cards
|
||||
option(value="{{_id}}" selected="{{#if isChecklistDialogOptionCardId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm.js-done {{_ 'done'}}
|
||||
@@ -77,6 +77,12 @@ BlazeComponent.extendComponent({
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
|
||||
/** returns the finished percent of the checklist */
|
||||
finishedPercent() {
|
||||
const ret = this.data().checklist.finishedPercent();
|
||||
return ret;
|
||||
},
|
||||
}).register('checklistDetail');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
@@ -86,7 +92,8 @@ BlazeComponent.extendComponent({
|
||||
const title = textarea.value.trim();
|
||||
let cardId = this.currentData().cardId;
|
||||
const card = Cards.findOne(cardId);
|
||||
if (card.isLinked()) cardId = card.linkedId;
|
||||
//if (card.isLinked()) cardId = card.linkedId;
|
||||
if (card.isLinkedCard()) cardId = card.linkedId;
|
||||
|
||||
if (title) {
|
||||
Checklists.insert({
|
||||
@@ -105,16 +112,23 @@ BlazeComponent.extendComponent({
|
||||
addChecklistItem(event) {
|
||||
event.preventDefault();
|
||||
const textarea = this.find('textarea.js-add-checklist-item');
|
||||
const newlineBecomesNewChecklistItem = this.find('input#toggleNewlineBecomesNewChecklistItem');
|
||||
const title = textarea.value.trim();
|
||||
const checklist = this.currentData().checklist;
|
||||
|
||||
if (title) {
|
||||
ChecklistItems.insert({
|
||||
title,
|
||||
checklistId: checklist._id,
|
||||
cardId: checklist.cardId,
|
||||
sort: Utils.calculateIndexData(checklist.lastItem()).base,
|
||||
});
|
||||
let checklistItems = [title];
|
||||
if (newlineBecomesNewChecklistItem.checked) {
|
||||
checklistItems = title.split('\n').map(_value => _value.trim());
|
||||
}
|
||||
for (let checklistItem of checklistItems) {
|
||||
ChecklistItems.insert({
|
||||
title: checklistItem,
|
||||
checklistId: checklist._id,
|
||||
cardId: checklist.cardId,
|
||||
sort: Utils.calculateIndexData(checklist.lastItem()).base,
|
||||
});
|
||||
}
|
||||
}
|
||||
// We keep the form opened, empty it.
|
||||
textarea.value = '';
|
||||
@@ -130,14 +144,6 @@ BlazeComponent.extendComponent({
|
||||
);
|
||||
},
|
||||
|
||||
deleteChecklist() {
|
||||
const checklist = this.currentData().checklist;
|
||||
if (checklist && checklist._id) {
|
||||
Checklists.remove(checklist._id);
|
||||
this.toggleDeleteDialog.set(false);
|
||||
}
|
||||
},
|
||||
|
||||
deleteItem() {
|
||||
const checklist = this.currentData().checklist;
|
||||
const item = this.currentData().item;
|
||||
@@ -163,11 +169,6 @@ BlazeComponent.extendComponent({
|
||||
item.setTitle(title);
|
||||
},
|
||||
|
||||
onCreated() {
|
||||
this.toggleDeleteDialog = new ReactiveVar(false);
|
||||
this.checklistToDelete = null; //Store data context to pass to checklistDeleteDialog template
|
||||
},
|
||||
|
||||
pressKey(event) {
|
||||
//If user press enter key inside a form, submit it
|
||||
//Unless the user is also holding down the 'shift' key
|
||||
@@ -195,12 +196,6 @@ BlazeComponent.extendComponent({
|
||||
|
||||
events() {
|
||||
const events = {
|
||||
'click .toggle-delete-checklist-dialog'(event) {
|
||||
if ($(event.target).hasClass('js-delete-checklist')) {
|
||||
this.checklistToDelete = this.currentData().checklist; //Store data context
|
||||
}
|
||||
this.toggleDeleteDialog.set(!this.toggleDeleteDialog.get());
|
||||
},
|
||||
'click #toggleHideCheckedItemsButton'() {
|
||||
Meteor.call('toggleHideCheckedItems');
|
||||
},
|
||||
@@ -209,13 +204,13 @@ BlazeComponent.extendComponent({
|
||||
return [
|
||||
{
|
||||
...events,
|
||||
'click .js-open-checklist-details-menu': Popup.open('checklistActions'),
|
||||
'submit .js-add-checklist': this.addChecklist,
|
||||
'submit .js-edit-checklist-title': this.editChecklist,
|
||||
'submit .js-add-checklist-item': this.addChecklistItem,
|
||||
'submit .js-edit-checklist-item': this.editChecklistItem,
|
||||
'click .js-convert-checklist-item-to-card': Popup.open('convertChecklistItemToCard'),
|
||||
'click .js-delete-checklist-item': this.deleteItem,
|
||||
'click .confirm-checklist-delete': this.deleteChecklist,
|
||||
'focus .js-add-checklist-item': this.focusChecklistItem,
|
||||
// add and delete checklist / checklist-item
|
||||
'click .js-open-inlined-form': this.closeAllInlinedForms,
|
||||
@@ -279,39 +274,77 @@ Template.checklists.helpers({
|
||||
},
|
||||
});
|
||||
|
||||
Template.addChecklistItemForm.onRendered(() => {
|
||||
autosize($('textarea.js-add-checklist-item'));
|
||||
});
|
||||
BlazeComponent.extendComponent({
|
||||
onRendered() {
|
||||
autosize(this.$('textarea.js-add-checklist-item'));
|
||||
},
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click a.fa.fa-copy'(event) {
|
||||
const $editor = this.$('textarea');
|
||||
const promise = Utils.copyTextToClipboard($editor[0].value);
|
||||
|
||||
Template.editChecklistItemForm.onRendered(() => {
|
||||
autosize($('textarea.js-edit-checklist-item'));
|
||||
});
|
||||
const $tooltip = this.$('.copied-tooltip');
|
||||
Utils.showCopied(promise, $tooltip);
|
||||
},
|
||||
}
|
||||
];
|
||||
}
|
||||
}).register('addChecklistItemForm');
|
||||
|
||||
Template.checklistDeleteDialog.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;
|
||||
});
|
||||
BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-delete-checklist' : Popup.afterConfirm('checklistDelete', function () {
|
||||
Popup.back(2);
|
||||
const checklist = this.checklist;
|
||||
if (checklist && checklist._id) {
|
||||
Checklists.remove(checklist._id);
|
||||
}
|
||||
}),
|
||||
'click .js-move-checklist' : Popup.open('moveChecklist'),
|
||||
'click .js-copy-checklist' : Popup.open('copyChecklist'),
|
||||
}
|
||||
]
|
||||
}
|
||||
}).register('checklistActionsPopup');
|
||||
|
||||
//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);
|
||||
}
|
||||
});
|
||||
});
|
||||
BlazeComponent.extendComponent({
|
||||
onRendered() {
|
||||
autosize(this.$('textarea.js-edit-checklist-item'));
|
||||
},
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click a.fa.fa-copy'(event) {
|
||||
const $editor = this.$('textarea');
|
||||
const promise = Utils.copyTextToClipboard($editor[0].value);
|
||||
|
||||
Template.checklistDeleteDialog.onDestroyed(() => {
|
||||
const $cardDetails = this.$('.card-details');
|
||||
$cardDetails.off('scroll'); //Reactivate scrolling
|
||||
$cardDetails.animate({ scrollTop: this.scrollState.position });
|
||||
});
|
||||
const $tooltip = this.$('.copied-tooltip');
|
||||
Utils.showCopied(promise, $tooltip);
|
||||
},
|
||||
}
|
||||
];
|
||||
}
|
||||
}).register('editChecklistItemForm');
|
||||
|
||||
Template.checklistItemDetail.helpers({
|
||||
canModifyCard() {
|
||||
@@ -345,3 +378,231 @@ BlazeComponent.extendComponent({
|
||||
];
|
||||
},
|
||||
}).register('checklistItemDetail');
|
||||
|
||||
class DialogWithBoardSwimlaneListAndCard extends BlazeComponent {
|
||||
/** returns the checklist dialog options
|
||||
* @return Object with properties { boardId, swimlaneId, listId, cardId }
|
||||
*/
|
||||
getChecklistDialogOptions() {
|
||||
}
|
||||
|
||||
/** checklist is done
|
||||
* @param cardId the selected card id
|
||||
* @param options the selected options (Object with properties { boardId, swimlaneId, listId, cardId })
|
||||
*/
|
||||
setDone(cardId, options) {
|
||||
}
|
||||
|
||||
onCreated() {
|
||||
this.currentBoardId = Utils.getCurrentBoardId();
|
||||
this.selectedBoardId = new ReactiveVar(this.currentBoardId);
|
||||
this.selectedSwimlaneId = new ReactiveVar('');
|
||||
this.selectedListId = new ReactiveVar('');
|
||||
this.setChecklistDialogOption(this.currentBoardId);
|
||||
}
|
||||
|
||||
/** set the last confirmed dialog field values
|
||||
* @param boardId the current board id
|
||||
*/
|
||||
setChecklistDialogOption(boardId) {
|
||||
this.checklistDialogOption = {
|
||||
'boardId' : "",
|
||||
'swimlaneId' : "",
|
||||
'listId' : "",
|
||||
'cardId': "",
|
||||
}
|
||||
|
||||
let currentOptions = this.getChecklistDialogOptions();
|
||||
if (currentOptions && boardId && currentOptions[boardId]) {
|
||||
this.checklistDialogOption = currentOptions[boardId];
|
||||
if (this.checklistDialogOption.boardId &&
|
||||
this.checklistDialogOption.swimlaneId &&
|
||||
this.checklistDialogOption.listId
|
||||
)
|
||||
{
|
||||
this.selectedBoardId.set(this.checklistDialogOption.boardId)
|
||||
this.selectedSwimlaneId.set(this.checklistDialogOption.swimlaneId);
|
||||
this.selectedListId.set(this.checklistDialogOption.listId);
|
||||
}
|
||||
}
|
||||
this.getBoardData(this.selectedBoardId.get());
|
||||
if (!this.selectedSwimlaneId.get() || !Swimlanes.findOne({_id: this.selectedSwimlaneId.get(), boardId: this.selectedBoardId.get()})) {
|
||||
this.setFirstSwimlaneId();
|
||||
}
|
||||
if (!this.selectedListId.get() || !Lists.findOne({_id: this.selectedListId.get(), boardId: this.selectedBoardId.get()})) {
|
||||
this.setFirstListId();
|
||||
}
|
||||
}
|
||||
/** sets the first swimlane id */
|
||||
setFirstSwimlaneId() {
|
||||
try {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const swimlaneId = board.swimlanes().fetch()[0]._id;
|
||||
this.selectedSwimlaneId.set(swimlaneId);
|
||||
} catch (e) {}
|
||||
}
|
||||
/** sets the first list id */
|
||||
setFirstListId() {
|
||||
try {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const listId = board.lists().fetch()[0]._id;
|
||||
this.selectedListId.set(listId);
|
||||
} catch (e) {}
|
||||
}
|
||||
|
||||
/** returns if the board id was the last confirmed one
|
||||
* @param boardId check this board id
|
||||
* @return if the board id was the last confirmed one
|
||||
*/
|
||||
isChecklistDialogOptionBoardId(boardId) {
|
||||
let ret = this.checklistDialogOption.boardId == boardId;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** returns if the swimlane id was the last confirmed one
|
||||
* @param swimlaneId check this swimlane id
|
||||
* @return if the swimlane id was the last confirmed one
|
||||
*/
|
||||
isChecklistDialogOptionSwimlaneId(swimlaneId) {
|
||||
let ret = this.checklistDialogOption.swimlaneId == swimlaneId;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** returns if the list id was the last confirmed one
|
||||
* @param listId check this list id
|
||||
* @return if the list id was the last confirmed one
|
||||
*/
|
||||
isChecklistDialogOptionListId(listId) {
|
||||
let ret = this.checklistDialogOption.listId == listId;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** returns if the card id was the last confirmed one
|
||||
* @param cardId check this card id
|
||||
* @return if the card id was the last confirmed one
|
||||
*/
|
||||
isChecklistDialogOptionCardId(cardId) {
|
||||
let ret = this.checklistDialogOption.cardId == cardId;
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** returns all available board */
|
||||
boards() {
|
||||
const ret = Boards.find(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
_id: { $ne: Meteor.user().getTemplatesBoardId() },
|
||||
},
|
||||
{
|
||||
sort: { sort: 1 },
|
||||
},
|
||||
);
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** returns all available swimlanes of the current board */
|
||||
swimlanes() {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const ret = board.swimlanes();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** returns all available lists of the current board */
|
||||
lists() {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const ret = board.lists();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** returns all available cards of the current list */
|
||||
cards() {
|
||||
const list = Lists.findOne(this.selectedListId.get());
|
||||
const ret = list.cards(this.selectedSwimlaneId.get());
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** get the board data from the server
|
||||
* @param boardId get the board data of this board id
|
||||
*/
|
||||
getBoardData(boardId) {
|
||||
const self = this;
|
||||
Meteor.subscribe('board', boardId, false, {
|
||||
onReady() {
|
||||
const sameBoardId = self.selectedBoardId.get() == boardId;
|
||||
self.selectedBoardId.set(boardId);
|
||||
|
||||
if (!sameBoardId) {
|
||||
// reset swimlane id (for selection in cards())
|
||||
self.setFirstSwimlaneId();
|
||||
|
||||
// reset list id (for selection in cards())
|
||||
self.setFirstListId();
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-done'() {
|
||||
const boardSelect = this.$('.js-select-boards')[0];
|
||||
const boardId = boardSelect.options[boardSelect.selectedIndex].value;
|
||||
|
||||
const listSelect = this.$('.js-select-lists')[0];
|
||||
const listId = listSelect.options[listSelect.selectedIndex].value;
|
||||
|
||||
const swimlaneSelect = this.$('.js-select-swimlanes')[0];
|
||||
const swimlaneId = swimlaneSelect.options[swimlaneSelect.selectedIndex].value;
|
||||
|
||||
const cardSelect = this.$('.js-select-cards')[0];
|
||||
const cardId = cardSelect.options[cardSelect.selectedIndex].value;
|
||||
|
||||
const options = {
|
||||
'boardId' : boardId,
|
||||
'swimlaneId' : swimlaneId,
|
||||
'listId' : listId,
|
||||
'cardId': cardId,
|
||||
}
|
||||
this.setDone(cardId, options);
|
||||
Popup.back(2);
|
||||
},
|
||||
'change .js-select-boards'(event) {
|
||||
const boardId = $(event.currentTarget).val();
|
||||
this.getBoardData(boardId);
|
||||
},
|
||||
'change .js-select-swimlanes'(event) {
|
||||
this.selectedSwimlaneId.set($(event.currentTarget).val());
|
||||
},
|
||||
'change .js-select-lists'(event) {
|
||||
this.selectedListId.set($(event.currentTarget).val());
|
||||
},
|
||||
},
|
||||
];
|
||||
}
|
||||
}
|
||||
|
||||
/** Move Checklist Dialog */
|
||||
(class extends DialogWithBoardSwimlaneListAndCard {
|
||||
getChecklistDialogOptions() {
|
||||
const ret = Meteor.user().getMoveChecklistDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(cardId, options) {
|
||||
Meteor.user().setMoveChecklistDialogOption(this.currentBoardId, options);
|
||||
this.data().checklist.move(cardId);
|
||||
}
|
||||
}).register('moveChecklistPopup');
|
||||
|
||||
/** Copy Checklist Dialog */
|
||||
(class extends DialogWithBoardSwimlaneListAndCard {
|
||||
getChecklistDialogOptions() {
|
||||
const ret = Meteor.user().getCopyChecklistDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(cardId, options) {
|
||||
Meteor.user().setCopyChecklistDialogOption(this.currentBoardId, options);
|
||||
this.data().checklist.copy(cardId);
|
||||
}
|
||||
}).register('copyChecklistPopup');
|
||||
@@ -20,6 +20,25 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
|
||||
display: flex
|
||||
justify-content: space-between
|
||||
|
||||
.checklist-progress-bar-container
|
||||
display: flex
|
||||
flex-direction: row
|
||||
align-items: center
|
||||
|
||||
.checklist-progress-text
|
||||
margin-right: 10px
|
||||
|
||||
.checklist-progress-bar
|
||||
width: 80%
|
||||
height: 10px
|
||||
|
||||
.checklist-progress
|
||||
color: #fff !important
|
||||
background-color: #2196F3 !important
|
||||
padding: 0.01em 16px
|
||||
border-radius: 16px
|
||||
height: 100%
|
||||
|
||||
.checklist-title
|
||||
.checkbox
|
||||
float: left
|
||||
@@ -39,49 +58,11 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
|
||||
&.is-finished
|
||||
color: #3cb500
|
||||
|
||||
.js-delete-checklist
|
||||
@extends .delete-text
|
||||
|
||||
span.fa.checklist-handle
|
||||
padding-right: 20px
|
||||
padding-top: 3px
|
||||
float: left
|
||||
|
||||
|
||||
.js-confirm-checklist-delete
|
||||
background-color: darken(white, 3%)
|
||||
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-checklist-delete-buttons
|
||||
position: relative
|
||||
padding: left 2% right 2%
|
||||
.confirm-checklist-delete
|
||||
margin-left: 12%
|
||||
float: left
|
||||
.toggle-delete-checklist-dialog
|
||||
margin-right: 12%
|
||||
float: right
|
||||
|
||||
#card-details-overlay
|
||||
top: 0
|
||||
bottom: -600px
|
||||
@@ -177,3 +158,11 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
|
||||
background: #dbdbdb
|
||||
color: #222
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,.2)
|
||||
|
||||
.checklist-details-menu
|
||||
float: right
|
||||
padding: 6px 10px 6px 10px
|
||||
|
||||
.edit-controls
|
||||
label.toggle-label
|
||||
margin-left: 2px
|
||||
@@ -48,7 +48,17 @@ BlazeComponent.extendComponent({
|
||||
connectWith: '.edit-labels-pop-over',
|
||||
tolerance: 'pointer',
|
||||
appendTo: '.edit-labels-pop-over',
|
||||
helper: 'clone',
|
||||
helper(element, currentItem) {
|
||||
let ret = currentItem.clone();
|
||||
if (currentItem.closest('.popup-container-depth-0').size() == 0)
|
||||
{ // only set css transform at every sub-popup, not at the main popup
|
||||
const content = currentItem.closest('.content')[0]
|
||||
const offsetLeft = content.offsetLeft;
|
||||
const offsetTop = $('.pop-over > .header').height() * -1;
|
||||
ret.css("transform", `translate(${offsetLeft}px, ${offsetTop}px)`);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
distance: 7,
|
||||
items: itemsSelector,
|
||||
placeholder: 'card-label-wrapper placeholder',
|
||||
@@ -63,7 +73,6 @@ BlazeComponent.extendComponent({
|
||||
card.board().setNewLabelOrder(newLabelOrderOnlyIds);
|
||||
},
|
||||
});
|
||||
Utils.enableClickOnTouch(itemsSelector);
|
||||
|
||||
// Disable drag-dropping if the current user is not a board member or is comment only
|
||||
this.autorun(() => {
|
||||
@@ -78,7 +87,7 @@ BlazeComponent.extendComponent({
|
||||
return [
|
||||
{
|
||||
'click .js-select-label'(event) {
|
||||
const card = Utils.getCurrentCard();
|
||||
const card = this.data();
|
||||
const labelId = this.currentData()._id;
|
||||
card.toggleLabel(labelId);
|
||||
event.preventDefault();
|
||||
|
||||
@@ -146,6 +146,7 @@
|
||||
height: 25px
|
||||
margin: 0px 3% 7px 0px
|
||||
width: 10.5%
|
||||
max-width: 10.5%
|
||||
cursor: pointer
|
||||
|
||||
.edit-labels
|
||||
|
||||
@@ -88,15 +88,17 @@ template(name="minicard")
|
||||
+viewer
|
||||
= trueValue
|
||||
|
||||
if getAssignees
|
||||
.minicard-assignees.js-minicard-assignees
|
||||
each getAssignees
|
||||
+userAvatar(userId=this)
|
||||
if showAssignee
|
||||
if getAssignees
|
||||
.minicard-assignees.js-minicard-assignees
|
||||
each getAssignees
|
||||
+userAvatar(userId=this)
|
||||
|
||||
if getMembers
|
||||
.minicard-members.js-minicard-members
|
||||
each getMembers
|
||||
+userAvatar(userId=this)
|
||||
if showMembers
|
||||
if getMembers
|
||||
.minicard-members.js-minicard-members
|
||||
each getMembers
|
||||
+userAvatar(userId=this)
|
||||
|
||||
if showCreator
|
||||
.minicard-creator
|
||||
|
||||
@@ -49,6 +49,28 @@ BlazeComponent.extendComponent({
|
||||
return false;
|
||||
},
|
||||
|
||||
showMembers() {
|
||||
if (this.data().board()) {
|
||||
return (
|
||||
this.data().board.allowsMembers === null ||
|
||||
this.data().board().allowsMembers === undefined ||
|
||||
this.data().board().allowsMembers
|
||||
);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
showAssignee() {
|
||||
if (this.data().board()) {
|
||||
return (
|
||||
this.data().board.allowsAssignee === null ||
|
||||
this.data().board().allowsAssignee === undefined ||
|
||||
this.data().board().allowsAssignee
|
||||
);
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
/** opens the card label popup only if clicked onto a label
|
||||
* <li> this is necessary to have the data context of the minicard.
|
||||
* if .js-card-label is used at click event, then only the data context of the label itself is available at this.currentData()
|
||||
|
||||
@@ -7,8 +7,16 @@ Template.resultCard.helpers({
|
||||
BlazeComponent.extendComponent({
|
||||
clickOnMiniCard(evt) {
|
||||
evt.preventDefault();
|
||||
Session.set('popupCard', this.currentData()._id);
|
||||
this.cardDetailsPopup(evt);
|
||||
const this_ = this;
|
||||
const cardId = this.currentData()._id;
|
||||
const boardId = this.currentData().boardId;
|
||||
Meteor.subscribe('popupCardData', cardId, {
|
||||
onReady() {
|
||||
Session.set('popupCardId', cardId);
|
||||
Session.set('popupCardBoardId', boardId);
|
||||
this_.cardDetailsPopup(evt);
|
||||
},
|
||||
});
|
||||
},
|
||||
|
||||
cardDetailsPopup(event) {
|
||||
|
||||
@@ -117,7 +117,6 @@ button
|
||||
display: inline-block
|
||||
font-weight: 700
|
||||
line-height: 22px
|
||||
margin: 8px 4px 0 0
|
||||
padding: 7px 20px
|
||||
text-align: center
|
||||
|
||||
@@ -226,20 +225,19 @@ textarea
|
||||
.edit-controls,
|
||||
.add-controls
|
||||
display: flex
|
||||
align-items: baseline
|
||||
margin-top: 0
|
||||
align-items: center
|
||||
margin-top: 0px
|
||||
margin-bottom: 12px
|
||||
|
||||
button[type=submit]
|
||||
input[type=button]
|
||||
float: left
|
||||
height: 32px
|
||||
margin-top: -2px
|
||||
padding-top: 5px
|
||||
padding-bottom: 5px
|
||||
margin-bottom: 0px
|
||||
|
||||
.fa-times-thin
|
||||
font-size: 26px
|
||||
margin: 3px 4px
|
||||
margin: 3px 10px
|
||||
|
||||
// Material Design checkboxes
|
||||
[type="checkbox"]:not(:checked),
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
require('/client/lib/jquery-ui.js')
|
||||
|
||||
const { calculateIndex } = Utils;
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
@@ -93,7 +95,7 @@ BlazeComponent.extendComponent({
|
||||
$cards.sortable('cancel');
|
||||
|
||||
if (MultiSelection.isActive()) {
|
||||
Cards.find(MultiSelection.getMongoSelector()).forEach((card, i) => {
|
||||
Cards.find(MultiSelection.getMongoSelector(), {sort: ['sort']}).forEach((card, i) => {
|
||||
const newSwimlaneId = targetSwimlaneId
|
||||
? targetSwimlaneId
|
||||
: card.swimlaneId || defaultSwimlaneId;
|
||||
@@ -114,6 +116,43 @@ BlazeComponent.extendComponent({
|
||||
}
|
||||
boardComponent.setIsDragging(false);
|
||||
},
|
||||
sort(event, ui) {
|
||||
const $boardCanvas = $('.board-canvas');
|
||||
const boardCanvas = $boardCanvas[0];
|
||||
|
||||
if (event.pageX < 10)
|
||||
{ // scroll to the left
|
||||
boardCanvas.scrollLeft -= 15;
|
||||
ui.helper[0].offsetLeft -= 15;
|
||||
}
|
||||
if (
|
||||
event.pageX > boardCanvas.offsetWidth - 10 &&
|
||||
boardCanvas.scrollLeft < $boardCanvas.data('scrollLeftMax') // don't scroll more than possible
|
||||
)
|
||||
{ // scroll to the right
|
||||
boardCanvas.scrollLeft += 15;
|
||||
}
|
||||
if (
|
||||
event.pageY > boardCanvas.offsetHeight - 10 &&
|
||||
event.pageY + boardCanvas.scrollTop < $boardCanvas.data('scrollTopMax') // don't scroll more than possible
|
||||
)
|
||||
{ // scroll to the bottom
|
||||
boardCanvas.scrollTop += 15;
|
||||
}
|
||||
if (event.pageY < 10)
|
||||
{ // scroll to the top
|
||||
boardCanvas.scrollTop -= 15;
|
||||
}
|
||||
},
|
||||
activate(event, ui) {
|
||||
const $boardCanvas = $('.board-canvas');
|
||||
const boardCanvas = $boardCanvas[0];
|
||||
// scrollTopMax and scrollLeftMax only available at Firefox (https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTopMax)
|
||||
// https://www.it-swarm.com.de/de/javascript/so-erhalten-sie-den-maximalen-dokument-scrolltop-wert/1069126844/
|
||||
$boardCanvas.data('scrollTopMax', boardCanvas.scrollHeight - boardCanvas.clientTop);
|
||||
// https://stackoverflow.com/questions/5138373/how-do-i-get-the-max-value-of-scrollleft/5704386#5704386
|
||||
$boardCanvas.data('scrollLeftMax', boardCanvas.scrollWidth - boardCanvas.clientWidth);
|
||||
},
|
||||
});
|
||||
|
||||
this.autorun(() => {
|
||||
|
||||
@@ -4,7 +4,6 @@
|
||||
box-sizing: border-box
|
||||
display: flex
|
||||
flex-direction: column
|
||||
flex: 0 0 270px
|
||||
position: relative
|
||||
// Even if this background color is the same as the body we can't leave it
|
||||
// transparent, because that won't work during a list drag.
|
||||
@@ -12,6 +11,8 @@
|
||||
border-left: 1px solid darken(white, 20%)
|
||||
padding: 0
|
||||
float: left
|
||||
min-width: 270px
|
||||
max-width: 270px
|
||||
|
||||
&:first-child
|
||||
margin-left: 5px
|
||||
@@ -85,13 +86,9 @@
|
||||
color: #a6a6a6
|
||||
|
||||
.list-header-menu
|
||||
position: absolute
|
||||
padding: 27px 19px
|
||||
margin-top: 1px
|
||||
top: -7px
|
||||
right: 3px
|
||||
float: right
|
||||
|
||||
.list-header-plus-icon
|
||||
.list-header-plus-top
|
||||
color: #a6a6a6
|
||||
margin-right: 15px
|
||||
|
||||
@@ -100,9 +97,10 @@
|
||||
|
||||
.cardCount
|
||||
color: #8c8c8c
|
||||
font-size: 0.8em
|
||||
font-size: 12px
|
||||
font-weight: bold
|
||||
|
||||
.list-header .list-header-plus-icon, .js-open-list-menu, .list-header-menu a
|
||||
.list-header .list-header-plus-top, .js-open-list-menu, .list-header-menu a
|
||||
color #4d4d4d
|
||||
padding-left 4px
|
||||
|
||||
@@ -160,18 +158,6 @@
|
||||
float: left
|
||||
|
||||
@media screen and (max-width: 800px)
|
||||
.list-header-menu
|
||||
position: absolute
|
||||
padding: 27px 19px
|
||||
margin-top: 1px
|
||||
top: -7px
|
||||
margin-right: 7px
|
||||
right: -3px
|
||||
|
||||
.list-header
|
||||
.list-header-name
|
||||
margin-left: 1.4rem
|
||||
|
||||
.mini-list
|
||||
flex: 0 0 60px
|
||||
height: auto
|
||||
@@ -215,7 +201,6 @@
|
||||
display: flex
|
||||
align-items: center
|
||||
.list-header-left-icon
|
||||
display: inline
|
||||
padding: 7px
|
||||
padding-right: 27px
|
||||
margin-top: 1px
|
||||
@@ -238,6 +223,30 @@
|
||||
right: 10px
|
||||
font-size: 24px
|
||||
|
||||
.list-header
|
||||
display: grid
|
||||
grid-template-columns: 30px 5fr 1fr
|
||||
.list-header-left-icon
|
||||
display: grid
|
||||
grid-row: 1/3
|
||||
grid-column: 1
|
||||
.list-header-name
|
||||
grid-row: 1
|
||||
grid-column: 2
|
||||
align-self: end
|
||||
.cardCount
|
||||
grid-row: 2
|
||||
grid-column: 2
|
||||
align-self: start
|
||||
.list-header-menu
|
||||
grid-row: 1/3
|
||||
grid-column: 3
|
||||
.inlined-form
|
||||
grid-row: 1/3
|
||||
grid-column: 1/4
|
||||
.edit-controls
|
||||
align-items: initial
|
||||
|
||||
.link-board-wrapper
|
||||
display: flex
|
||||
align-items: baseline
|
||||
|
||||
@@ -150,7 +150,7 @@ BlazeComponent.extendComponent({
|
||||
// overwriting the event in case the card is already selected.
|
||||
} else if (Utils.isMiniScreen()) {
|
||||
evt.preventDefault();
|
||||
Session.set('popupCard', this.currentData()._id);
|
||||
Session.set('popupCardId', this.currentData()._id);
|
||||
this.cardDetailsPopup(evt);
|
||||
} else if (Session.equals('currentCard', this.currentData()._id)) {
|
||||
evt.stopImmediatePropagation();
|
||||
@@ -277,9 +277,12 @@ BlazeComponent.extendComponent({
|
||||
|
||||
getLabels() {
|
||||
const currentBoardId = Session.get('currentBoard');
|
||||
return Boards.findOne(currentBoardId).labels.filter(label => {
|
||||
return this.labels.get().indexOf(label._id) > -1;
|
||||
});
|
||||
if (Boards.findOne(currentBoardId).labels) {
|
||||
return Boards.findOne(currentBoardId).labels.filter(label => {
|
||||
return this.labels.get().indexOf(label._id) > -1;
|
||||
});
|
||||
}
|
||||
return false;
|
||||
},
|
||||
|
||||
pressKey(evt) {
|
||||
@@ -333,7 +336,7 @@ BlazeComponent.extendComponent({
|
||||
[
|
||||
// User mentions
|
||||
{
|
||||
match: /\B@([\w.]*)$/,
|
||||
match: /\B@([\w.-]*)$/,
|
||||
search(term, callback) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
callback(
|
||||
@@ -344,6 +347,9 @@ BlazeComponent.extendComponent({
|
||||
);
|
||||
},
|
||||
template(user) {
|
||||
if (user.profile && user.profile.fullname) {
|
||||
return (user.username + " (" + user.profile.fullname + ")");
|
||||
}
|
||||
return user.username;
|
||||
},
|
||||
replace(user) {
|
||||
@@ -360,6 +366,9 @@ BlazeComponent.extendComponent({
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
callback(
|
||||
$.map(currentBoard.labels, label => {
|
||||
if (label.name == undefined) {
|
||||
label.name = "";
|
||||
}
|
||||
if (
|
||||
label.name.indexOf(term) > -1 ||
|
||||
label.color.indexOf(term) > -1
|
||||
@@ -569,7 +578,8 @@ BlazeComponent.extendComponent({
|
||||
this.isBoardTemplateSearch;
|
||||
let board = {};
|
||||
if (this.isTemplateSearch) {
|
||||
board = Boards.findOne((Meteor.user().profile || {}).templatesBoardId);
|
||||
//board = Boards.findOne((Meteor.user().profile || {}).templatesBoardId);
|
||||
board._id = (Meteor.user().profile || {}).templatesBoardId;
|
||||
} else {
|
||||
// Prefetch first non-current board id
|
||||
board = Boards.find({
|
||||
@@ -708,6 +718,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
(err, data) => {
|
||||
_id = data;
|
||||
subManager.subscribe('board', _id, false);
|
||||
},
|
||||
);
|
||||
}
|
||||
|
||||
@@ -18,9 +18,9 @@ template(name="listHeader")
|
||||
span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.count}}
|
||||
|/#{wipLimit.value})
|
||||
|
||||
if showCardsCountForList cards.count
|
||||
|
|
||||
span(class="cardCount") {{cardsCount}} {{cardsCountForListIsOne cards.count}}
|
||||
if showCardsCountForList cards.count
|
||||
span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.count}}
|
||||
|
||||
if isMiniScreen
|
||||
if currentList
|
||||
if isWatching
|
||||
@@ -28,7 +28,7 @@ template(name="listHeader")
|
||||
div.list-header-menu
|
||||
unless currentUser.isCommentOnly
|
||||
if canSeeAddCard
|
||||
a.js-add-card.fa.fa-plus.list-header-plus-icon(title="{{_ 'add-card-to-top-of-list'}}")
|
||||
a.js-add-card.fa.fa-plus.list-header-plus-top(title="{{_ 'add-card-to-top-of-list'}}")
|
||||
a.fa.fa-navicon.js-open-list-menu(title="{{_ 'listActionPopup-title'}}")
|
||||
else
|
||||
a.list-header-menu-icon.fa.fa-angle-right.js-select-list
|
||||
@@ -39,9 +39,9 @@ template(name="listHeader")
|
||||
div.list-header-menu
|
||||
unless currentUser.isCommentOnly
|
||||
//if isBoardAdmin
|
||||
// a.fa.js-list-star.list-header-plus-icon(class="fa-star{{#unless starred}}-o{{/unless}}")
|
||||
// a.fa.js-list-star.list-header-plus-top(class="fa-star{{#unless starred}}-o{{/unless}}")
|
||||
if canSeeAddCard
|
||||
a.js-add-card.fa.fa-plus.list-header-plus-icon(title="{{_ 'add-card-to-top-of-list'}}")
|
||||
a.js-add-card.fa.fa-plus.list-header-plus-top(title="{{_ 'add-card-to-top-of-list'}}")
|
||||
a.fa.fa-navicon.js-open-list-menu(title="{{_ 'listActionPopup-title'}}")
|
||||
if currentUser.isBoardAdmin
|
||||
if isShowDesktopDragHandles
|
||||
@@ -55,6 +55,13 @@ template(name="editListTitleForm")
|
||||
a.fa.fa-times-thin.js-close-inlined-form
|
||||
|
||||
template(name="listActionPopup")
|
||||
ul.pop-over-list
|
||||
li
|
||||
a.js-add-card.list-header-plus-bottom
|
||||
i.fa.fa-plus
|
||||
i.fa.fa-arrow-down
|
||||
| {{_ 'add-card-to-bottom-of-list'}}
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li
|
||||
a.js-toggle-watch-list
|
||||
|
||||
@@ -101,7 +101,7 @@ BlazeComponent.extendComponent({
|
||||
this.starred(!this.starred());
|
||||
},
|
||||
'click .js-open-list-menu': Popup.open('listAction'),
|
||||
'click .js-add-card'(event) {
|
||||
'click .js-add-card.list-header-plus-top'(event) {
|
||||
const listDom = $(event.target).parents(
|
||||
`#js-list-${this.currentData()._id}`,
|
||||
)[0];
|
||||
@@ -141,6 +141,14 @@ Template.listActionPopup.helpers({
|
||||
|
||||
Template.listActionPopup.events({
|
||||
'click .js-list-subscribe'() {},
|
||||
'click .js-add-card.list-header-plus-bottom'(event) {
|
||||
const listDom = $(`#js-list-${this._id}`)[0];
|
||||
const listComponent = BlazeComponent.getComponentForElement(listDom);
|
||||
listComponent.openForm({
|
||||
position: 'bottom',
|
||||
});
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-set-color-list': Popup.open('setListColor'),
|
||||
'click .js-select-cards'() {
|
||||
const cardIds = this.allCards().map(card => card._id);
|
||||
|
||||
@@ -1,4 +1,6 @@
|
||||
template(name="editor")
|
||||
a.fa.fa-copy(title="{{_ 'copy-text-to-clipboard'}}")
|
||||
span.copied-tooltip {{_ 'copied'}}
|
||||
textarea.editor(
|
||||
dir="auto"
|
||||
class="{{class}}"
|
||||
|
||||
+288
-266
@@ -4,283 +4,305 @@ const specialHandles = [
|
||||
];
|
||||
const specialHandleNames = specialHandles.map(m => m.username);
|
||||
|
||||
Template.editor.onRendered(() => {
|
||||
const textareaSelector = 'textarea';
|
||||
const mentions = [
|
||||
// User mentions
|
||||
{
|
||||
match: /\B@([\w.]*)$/,
|
||||
search(term, callback) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
callback(
|
||||
_.union(
|
||||
currentBoard
|
||||
.activeMembers()
|
||||
.map(member => {
|
||||
const user = Users.findOne(member.userId);
|
||||
const username = user.username;
|
||||
const fullName = user.profile && user.profile !== undefined ? user.profile.fullname : "";
|
||||
return username.includes(term) || fullName.includes(term) ? fullName + "(" + username + ")" : null;
|
||||
})
|
||||
.filter(Boolean), [...specialHandleNames])
|
||||
);
|
||||
},
|
||||
template(value) {
|
||||
return value;
|
||||
},
|
||||
replace(username) {
|
||||
return `@${username} `;
|
||||
},
|
||||
index: 1,
|
||||
},
|
||||
];
|
||||
const enableTextarea = function() {
|
||||
const $textarea = this.$(textareaSelector);
|
||||
autosize($textarea);
|
||||
$textarea.escapeableTextComplete(mentions);
|
||||
};
|
||||
if (Meteor.settings.public.RICHER_CARD_COMMENT_EDITOR !== false) {
|
||||
const isSmall = Utils.isMiniScreen();
|
||||
const toolbar = isSmall
|
||||
? [
|
||||
['view', ['fullscreen']],
|
||||
['table', ['table']],
|
||||
['font', ['bold', 'underline']],
|
||||
//['fontsize', ['fontsize']],
|
||||
['color', ['color']],
|
||||
]
|
||||
: [
|
||||
['style', ['style']],
|
||||
['font', ['bold', 'underline', 'clear']],
|
||||
['fontsize', ['fontsize']],
|
||||
['fontname', ['fontname']],
|
||||
['color', ['color']],
|
||||
['para', ['ul', 'ol', 'paragraph']],
|
||||
['table', ['table']],
|
||||
//['insert', ['link', 'picture', 'video']], // iframe tag will be sanitized TODO if iframe[class=note-video-clip] can be added into safe list, insert video can be enabled
|
||||
['insert', ['link']], //, 'picture']], // modal popup has issue somehow :(
|
||||
['view', ['fullscreen', 'codeview', 'help']],
|
||||
];
|
||||
const cleanPastedHTML = function(input) {
|
||||
const badTags = [
|
||||
'style',
|
||||
'script',
|
||||
'applet',
|
||||
'embed',
|
||||
'noframes',
|
||||
'noscript',
|
||||
'meta',
|
||||
'link',
|
||||
'button',
|
||||
'form',
|
||||
].join('|');
|
||||
const badPatterns = new RegExp(
|
||||
`(?:${[
|
||||
`<(${badTags})s*[^>][\\s\\S]*?<\\/\\1>`,
|
||||
`<(${badTags})[^>]*?\\/>`,
|
||||
].join('|')})`,
|
||||
'gi',
|
||||
);
|
||||
let output = input;
|
||||
// remove bad Tags
|
||||
output = output.replace(badPatterns, '');
|
||||
// remove attributes ' style="..."'
|
||||
const badAttributes = new RegExp(
|
||||
`(?:${[
|
||||
'on\\S+=([\'"]?).*?\\1',
|
||||
'href=([\'"]?)javascript:.*?\\2',
|
||||
'style=([\'"]?).*?\\3',
|
||||
'target=\\S+',
|
||||
].join('|')})`,
|
||||
'gi',
|
||||
);
|
||||
output = output.replace(badAttributes, '');
|
||||
output = output.replace(/(<a )/gi, '$1target=_ '); // always to new target
|
||||
return output;
|
||||
};
|
||||
const editor = '.editor';
|
||||
const selectors = [
|
||||
`.js-new-description-form ${editor}`,
|
||||
`.js-new-comment-form ${editor}`,
|
||||
`.js-edit-comment ${editor}`,
|
||||
].join(','); // only new comment and edit comment
|
||||
const inputs = $(selectors);
|
||||
if (inputs.length === 0) {
|
||||
// only enable richereditor to new comment or edit comment no others
|
||||
enableTextarea();
|
||||
} else {
|
||||
const placeholder = inputs.attr('placeholder') || '';
|
||||
const mSummernotes = [];
|
||||
const getSummernote = function(input) {
|
||||
const idx = inputs.index(input);
|
||||
if (idx > -1) {
|
||||
return mSummernotes[idx];
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
inputs.each(function(idx, input) {
|
||||
mSummernotes[idx] = $(input).summernote({
|
||||
placeholder,
|
||||
callbacks: {
|
||||
onInit(object) {
|
||||
const originalInput = this;
|
||||
$(originalInput).on('submitted', function() {
|
||||
// when comment is submitted, the original textarea will be set to '', so shall we
|
||||
if (!this.value) {
|
||||
const sn = getSummernote(this);
|
||||
sn && sn.summernote('code', '');
|
||||
}
|
||||
});
|
||||
const jEditor = object && object.editable;
|
||||
const toolbar = object && object.toolbar;
|
||||
if (jEditor !== undefined) {
|
||||
jEditor.escapeableTextComplete(mentions);
|
||||
}
|
||||
if (toolbar !== undefined) {
|
||||
const fBtn = toolbar.find('.btn-fullscreen');
|
||||
fBtn.on('click', function() {
|
||||
const $this = $(this),
|
||||
isActive = $this.hasClass('active');
|
||||
$('.minicards,#header-quick-access').toggle(!isActive); // mini card is still showing when editor is in fullscreen mode, we hide here manually
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onImageUpload(files) {
|
||||
const $summernote = getSummernote(this);
|
||||
if (files && files.length > 0) {
|
||||
const image = files[0];
|
||||
const currentCard = Utils.getCurrentCard();
|
||||
const MAX_IMAGE_PIXEL = Utils.MAX_IMAGE_PIXEL;
|
||||
const COMPRESS_RATIO = Utils.IMAGE_COMPRESS_RATIO;
|
||||
const insertImage = src => {
|
||||
// process all image upload types to the description/comment window
|
||||
const img = document.createElement('img');
|
||||
img.src = src;
|
||||
img.setAttribute('width', '100%');
|
||||
$summernote.summernote('insertNode', img);
|
||||
};
|
||||
const processData = function(fileObj) {
|
||||
Utils.processUploadedAttachment(
|
||||
currentCard,
|
||||
fileObj,
|
||||
attachment => {
|
||||
if (
|
||||
attachment &&
|
||||
attachment._id &&
|
||||
attachment.isImage()
|
||||
) {
|
||||
attachment.one('uploaded', function() {
|
||||
const maxTry = 3;
|
||||
const checkItvl = 500;
|
||||
let retry = 0;
|
||||
const checkUrl = function() {
|
||||
// even though uploaded event fired, attachment.url() is still null somehow //TODO
|
||||
const url = attachment.url();
|
||||
if (url) {
|
||||
insertImage(
|
||||
`${location.protocol}//${location.host}${url}`,
|
||||
);
|
||||
} else {
|
||||
retry++;
|
||||
if (retry < maxTry) {
|
||||
setTimeout(checkUrl, checkItvl);
|
||||
BlazeComponent.extendComponent({
|
||||
onRendered() {
|
||||
const textareaSelector = 'textarea';
|
||||
const mentions = [
|
||||
// User mentions
|
||||
{
|
||||
match: /\B@([\w.-]*)$/,
|
||||
search(term, callback) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
callback(
|
||||
_.union(
|
||||
currentBoard
|
||||
.activeMembers()
|
||||
.map(member => {
|
||||
const user = Users.findOne(member.userId);
|
||||
const username = user.username;
|
||||
const fullName = user.profile && user.profile !== undefined && user.profile.fullname ? user.profile.fullname : "";
|
||||
return username.includes(term) || fullName.includes(term) ? user : null;
|
||||
})
|
||||
.filter(Boolean), [...specialHandles])
|
||||
);
|
||||
},
|
||||
template(user) {
|
||||
if (user.profile && user.profile.fullname) {
|
||||
return (user.profile.fullname + " (" + user.username + ")");
|
||||
}
|
||||
return user.username;
|
||||
},
|
||||
replace(user) {
|
||||
if (user.profile && user.profile.fullname) {
|
||||
return `@${user.username} (${user.profile.fullname}) `;
|
||||
}
|
||||
return `@${user.username} `;
|
||||
},
|
||||
index: 1,
|
||||
},
|
||||
];
|
||||
const enableTextarea = function() {
|
||||
const $textarea = this.$(textareaSelector);
|
||||
autosize($textarea);
|
||||
$textarea.escapeableTextComplete(mentions);
|
||||
};
|
||||
if (Meteor.settings.public.RICHER_CARD_COMMENT_EDITOR !== false) {
|
||||
const isSmall = Utils.isMiniScreen();
|
||||
const toolbar = isSmall
|
||||
? [
|
||||
['view', ['fullscreen']],
|
||||
['table', ['table']],
|
||||
['font', ['bold', 'underline']],
|
||||
//['fontsize', ['fontsize']],
|
||||
['color', ['color']],
|
||||
]
|
||||
: [
|
||||
['style', ['style']],
|
||||
['font', ['bold', 'underline', 'clear']],
|
||||
['fontsize', ['fontsize']],
|
||||
['fontname', ['fontname']],
|
||||
['color', ['color']],
|
||||
['para', ['ul', 'ol', 'paragraph']],
|
||||
['table', ['table']],
|
||||
//['insert', ['link', 'picture', 'video']], // iframe tag will be sanitized TODO if iframe[class=note-video-clip] can be added into safe list, insert video can be enabled
|
||||
['insert', ['link']], //, 'picture']], // modal popup has issue somehow :(
|
||||
['view', ['fullscreen', 'codeview', 'help']],
|
||||
];
|
||||
const cleanPastedHTML = function(input) {
|
||||
const badTags = [
|
||||
'style',
|
||||
'script',
|
||||
'applet',
|
||||
'embed',
|
||||
'noframes',
|
||||
'noscript',
|
||||
'meta',
|
||||
'link',
|
||||
'button',
|
||||
'form',
|
||||
].join('|');
|
||||
const badPatterns = new RegExp(
|
||||
`(?:${[
|
||||
`<(${badTags})s*[^>][\\s\\S]*?<\\/\\1>`,
|
||||
`<(${badTags})[^>]*?\\/>`,
|
||||
].join('|')})`,
|
||||
'gi',
|
||||
);
|
||||
let output = input;
|
||||
// remove bad Tags
|
||||
output = output.replace(badPatterns, '');
|
||||
// remove attributes ' style="..."'
|
||||
const badAttributes = new RegExp(
|
||||
`(?:${[
|
||||
'on\\S+=([\'"]?).*?\\1',
|
||||
'href=([\'"]?)javascript:.*?\\2',
|
||||
'style=([\'"]?).*?\\3',
|
||||
'target=\\S+',
|
||||
].join('|')})`,
|
||||
'gi',
|
||||
);
|
||||
output = output.replace(badAttributes, '');
|
||||
output = output.replace(/(<a )/gi, '$1target=_ '); // always to new target
|
||||
return output;
|
||||
};
|
||||
const editor = '.editor';
|
||||
const selectors = [
|
||||
`.js-new-description-form ${editor}`,
|
||||
`.js-new-comment-form ${editor}`,
|
||||
`.js-edit-comment ${editor}`,
|
||||
].join(','); // only new comment and edit comment
|
||||
const inputs = $(selectors);
|
||||
if (inputs.length === 0) {
|
||||
// only enable richereditor to new comment or edit comment no others
|
||||
enableTextarea();
|
||||
} else {
|
||||
const placeholder = inputs.attr('placeholder') || '';
|
||||
const mSummernotes = [];
|
||||
const getSummernote = function(input) {
|
||||
const idx = inputs.index(input);
|
||||
if (idx > -1) {
|
||||
return mSummernotes[idx];
|
||||
}
|
||||
return undefined;
|
||||
};
|
||||
inputs.each(function(idx, input) {
|
||||
mSummernotes[idx] = $(input).summernote({
|
||||
placeholder,
|
||||
callbacks: {
|
||||
onInit(object) {
|
||||
const originalInput = this;
|
||||
$(originalInput).on('submitted', function() {
|
||||
// when comment is submitted, the original textarea will be set to '', so shall we
|
||||
if (!this.value) {
|
||||
const sn = getSummernote(this);
|
||||
sn && sn.summernote('code', '');
|
||||
}
|
||||
});
|
||||
const jEditor = object && object.editable;
|
||||
const toolbar = object && object.toolbar;
|
||||
if (jEditor !== undefined) {
|
||||
jEditor.escapeableTextComplete(mentions);
|
||||
}
|
||||
if (toolbar !== undefined) {
|
||||
const fBtn = toolbar.find('.btn-fullscreen');
|
||||
fBtn.on('click', function() {
|
||||
const $this = $(this),
|
||||
isActive = $this.hasClass('active');
|
||||
$('.minicards,#header-quick-access').toggle(!isActive); // mini card is still showing when editor is in fullscreen mode, we hide here manually
|
||||
});
|
||||
}
|
||||
},
|
||||
|
||||
onImageUpload(files) {
|
||||
const $summernote = getSummernote(this);
|
||||
if (files && files.length > 0) {
|
||||
const image = files[0];
|
||||
const currentCard = Utils.getCurrentCard();
|
||||
const MAX_IMAGE_PIXEL = Utils.MAX_IMAGE_PIXEL;
|
||||
const COMPRESS_RATIO = Utils.IMAGE_COMPRESS_RATIO;
|
||||
const insertImage = src => {
|
||||
// process all image upload types to the description/comment window
|
||||
const img = document.createElement('img');
|
||||
img.src = src;
|
||||
img.setAttribute('width', '100%');
|
||||
$summernote.summernote('insertNode', img);
|
||||
};
|
||||
const processData = function(fileObj) {
|
||||
Utils.processUploadedAttachment(
|
||||
currentCard,
|
||||
fileObj,
|
||||
attachment => {
|
||||
if (
|
||||
attachment &&
|
||||
attachment._id &&
|
||||
attachment.isImage()
|
||||
) {
|
||||
attachment.one('uploaded', function() {
|
||||
const maxTry = 3;
|
||||
const checkItvl = 500;
|
||||
let retry = 0;
|
||||
const checkUrl = function() {
|
||||
// even though uploaded event fired, attachment.url() is still null somehow //TODO
|
||||
const url = attachment.url();
|
||||
if (url) {
|
||||
insertImage(
|
||||
`${location.protocol}//${location.host}${url}`,
|
||||
);
|
||||
} else {
|
||||
retry++;
|
||||
if (retry < maxTry) {
|
||||
setTimeout(checkUrl, checkItvl);
|
||||
}
|
||||
}
|
||||
};
|
||||
checkUrl();
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
if (MAX_IMAGE_PIXEL) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
const dataurl = e && e.target && e.target.result;
|
||||
if (dataurl !== undefined) {
|
||||
// need to shrink image
|
||||
Utils.shrinkImage({
|
||||
dataurl,
|
||||
maxSize: MAX_IMAGE_PIXEL,
|
||||
ratio: COMPRESS_RATIO,
|
||||
toBlob: true,
|
||||
callback(blob) {
|
||||
if (blob !== false) {
|
||||
blob.name = image.name;
|
||||
processData(blob);
|
||||
}
|
||||
};
|
||||
checkUrl();
|
||||
},
|
||||
});
|
||||
}
|
||||
},
|
||||
);
|
||||
};
|
||||
if (MAX_IMAGE_PIXEL) {
|
||||
const reader = new FileReader();
|
||||
reader.onload = function(e) {
|
||||
const dataurl = e && e.target && e.target.result;
|
||||
if (dataurl !== undefined) {
|
||||
// need to shrink image
|
||||
Utils.shrinkImage({
|
||||
dataurl,
|
||||
maxSize: MAX_IMAGE_PIXEL,
|
||||
ratio: COMPRESS_RATIO,
|
||||
toBlob: true,
|
||||
callback(blob) {
|
||||
if (blob !== false) {
|
||||
blob.name = image.name;
|
||||
processData(blob);
|
||||
}
|
||||
},
|
||||
});
|
||||
}
|
||||
};
|
||||
reader.readAsDataURL(image);
|
||||
} else {
|
||||
processData(image);
|
||||
};
|
||||
reader.readAsDataURL(image);
|
||||
} else {
|
||||
processData(image);
|
||||
}
|
||||
}
|
||||
}
|
||||
},
|
||||
onPaste(e) {
|
||||
var clipboardData = e.clipboardData;
|
||||
var pastedData = clipboardData.getData('Text');
|
||||
},
|
||||
onPaste(e) {
|
||||
var clipboardData = e.clipboardData;
|
||||
var pastedData = clipboardData.getData('Text');
|
||||
|
||||
//if pasted data is an image, exit
|
||||
if (!pastedData.length) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
//if pasted data is an image, exit
|
||||
if (!pastedData.length) {
|
||||
e.preventDefault();
|
||||
return;
|
||||
}
|
||||
|
||||
// clear up unwanted tag info when user pasted in text
|
||||
const thisNote = this;
|
||||
const updatePastedText = function(object) {
|
||||
const someNote = getSummernote(object);
|
||||
// Fix Pasting text into a card is adding a line before and after
|
||||
// (and multiplies by pasting more) by changing paste "p" to "br".
|
||||
// Fixes https://github.com/wekan/wekan/2890 .
|
||||
// == Fix Start ==
|
||||
someNote.execCommand('defaultParagraphSeparator', false, 'br');
|
||||
// == Fix End ==
|
||||
const original = someNote.summernote('code');
|
||||
const cleaned = cleanPastedHTML(original); //this is where to call whatever clean function you want. I have mine in a different file, called CleanPastedHTML.
|
||||
someNote.summernote('code', ''); //clear original
|
||||
someNote.summernote('pasteHTML', cleaned); //this sets the displayed content editor to the cleaned pasted code.
|
||||
};
|
||||
setTimeout(function() {
|
||||
//this kinda sucks, but if you don't do a setTimeout,
|
||||
//the function is called before the text is really pasted.
|
||||
updatePastedText(thisNote);
|
||||
}, 10);
|
||||
// clear up unwanted tag info when user pasted in text
|
||||
const thisNote = this;
|
||||
const updatePastedText = function(object) {
|
||||
const someNote = getSummernote(object);
|
||||
// Fix Pasting text into a card is adding a line before and after
|
||||
// (and multiplies by pasting more) by changing paste "p" to "br".
|
||||
// Fixes https://github.com/wekan/wekan/2890 .
|
||||
// == Fix Start ==
|
||||
someNote.execCommand('defaultParagraphSeparator', false, 'br');
|
||||
// == Fix End ==
|
||||
const original = someNote.summernote('code');
|
||||
const cleaned = cleanPastedHTML(original); //this is where to call whatever clean function you want. I have mine in a different file, called CleanPastedHTML.
|
||||
someNote.summernote('code', ''); //clear original
|
||||
someNote.summernote('pasteHTML', cleaned); //this sets the displayed content editor to the cleaned pasted code.
|
||||
};
|
||||
setTimeout(function() {
|
||||
//this kinda sucks, but if you don't do a setTimeout,
|
||||
//the function is called before the text is really pasted.
|
||||
updatePastedText(thisNote);
|
||||
}, 10);
|
||||
},
|
||||
},
|
||||
},
|
||||
dialogsInBody: true,
|
||||
spellCheck: true,
|
||||
disableGrammar: false,
|
||||
disableDragAndDrop: false,
|
||||
toolbar,
|
||||
popover: {
|
||||
image: [
|
||||
['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']],
|
||||
['float', ['floatLeft', 'floatRight', 'floatNone']],
|
||||
['remove', ['removeMedia']],
|
||||
],
|
||||
link: [['link', ['linkDialogShow', 'unlink']]],
|
||||
table: [
|
||||
['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']],
|
||||
['delete', ['deleteRow', 'deleteCol', 'deleteTable']],
|
||||
],
|
||||
air: [
|
||||
['color', ['color']],
|
||||
['font', ['bold', 'underline', 'clear']],
|
||||
],
|
||||
},
|
||||
height: 200,
|
||||
dialogsInBody: true,
|
||||
spellCheck: true,
|
||||
disableGrammar: false,
|
||||
disableDragAndDrop: false,
|
||||
toolbar,
|
||||
popover: {
|
||||
image: [
|
||||
['imagesize', ['imageSize100', 'imageSize50', 'imageSize25']],
|
||||
['float', ['floatLeft', 'floatRight', 'floatNone']],
|
||||
['remove', ['removeMedia']],
|
||||
],
|
||||
link: [['link', ['linkDialogShow', 'unlink']]],
|
||||
table: [
|
||||
['add', ['addRowDown', 'addRowUp', 'addColLeft', 'addColRight']],
|
||||
['delete', ['deleteRow', 'deleteCol', 'deleteTable']],
|
||||
],
|
||||
air: [
|
||||
['color', ['color']],
|
||||
['font', ['bold', 'underline', 'clear']],
|
||||
],
|
||||
},
|
||||
height: 200,
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
} else {
|
||||
enableTextarea();
|
||||
}
|
||||
} else {
|
||||
enableTextarea();
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click a.fa.fa-copy'(event) {
|
||||
const $editor = this.$('textarea.editor');
|
||||
const promise = Utils.copyTextToClipboard($editor[0].value);
|
||||
|
||||
const $tooltip = this.$('.copied-tooltip');
|
||||
Utils.showCopied(promise, $tooltip);
|
||||
},
|
||||
}
|
||||
]
|
||||
}
|
||||
});
|
||||
}).register('editor');
|
||||
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
@@ -339,7 +361,7 @@ Blaze.Template.registerHelper(
|
||||
}
|
||||
return member;
|
||||
}), [...specialHandles]);
|
||||
const mentionRegex = /\B@([\w.]*)/gi;
|
||||
const mentionRegex = /\B@([\w.-]*)/gi;
|
||||
|
||||
let currentMention;
|
||||
while ((currentMention = mentionRegex.exec(content)) !== null) {
|
||||
|
||||
@@ -0,0 +1,7 @@
|
||||
.new-comment,
|
||||
.inlined-form
|
||||
a.fa.fa-copy
|
||||
float: right
|
||||
position: relative
|
||||
top: 20px
|
||||
right: 6px
|
||||
@@ -42,6 +42,24 @@ template(name="globalSearch")
|
||||
autofocus dir="auto"
|
||||
)
|
||||
a.js-new-search.fa.fa-eraser
|
||||
if debug.get.show
|
||||
h1 Debug
|
||||
if debug.get.showSelector
|
||||
h2 Selector
|
||||
button.js-copy-debug-selector
|
||||
= 'Copy'
|
||||
pre(
|
||||
id="debug-selector"
|
||||
)
|
||||
= sessionData.selector
|
||||
if debug.get.showProjection
|
||||
h2 Projection
|
||||
button.js-copy-debug-projection
|
||||
= 'Copy'
|
||||
pre(
|
||||
id="debug-projection"
|
||||
)
|
||||
= sessionData.projection
|
||||
if searching.get
|
||||
+spinner
|
||||
else if hasResults.get
|
||||
|
||||
@@ -131,6 +131,9 @@ class GlobalSearchComponent extends CardSearchPagedComponent {
|
||||
operator_has: TAPi18n.__('operator-has'),
|
||||
operator_sort: TAPi18n.__('operator-sort'),
|
||||
operator_limit: TAPi18n.__('operator-limit'),
|
||||
operator_debug: TAPi18n.__('operator-debug'),
|
||||
operator_org: TAPi18n.__('operator-org'),
|
||||
operator_team: TAPi18n.__('operator-team'),
|
||||
predicate_overdue: TAPi18n.__('predicate-overdue'),
|
||||
predicate_archived: TAPi18n.__('predicate-archived'),
|
||||
predicate_all: TAPi18n.__('predicate-all'),
|
||||
@@ -151,6 +154,8 @@ class GlobalSearchComponent extends CardSearchPagedComponent {
|
||||
predicate_end: TAPi18n.__('predicate-end'),
|
||||
predicate_assignee: TAPi18n.__('predicate-assignee'),
|
||||
predicate_member: TAPi18n.__('predicate-member'),
|
||||
predicate_selector: TAPi18n.__('predicate-selector'),
|
||||
predicate_projection: TAPi18n.__('predicate-projection'),
|
||||
};
|
||||
|
||||
let text = '';
|
||||
@@ -169,6 +174,8 @@ class GlobalSearchComponent extends CardSearchPagedComponent {
|
||||
['\n- ', 'globalSearch-instructions-operator-member'],
|
||||
['\n- ', 'globalSearch-instructions-operator-assignee'],
|
||||
['\n- ', 'globalSearch-instructions-operator-creator'],
|
||||
['\n- ', 'globalSearch-instructions-operator-org'],
|
||||
['\n- ', 'globalSearch-instructions-operator-team'],
|
||||
['\n- ', 'globalSearch-instructions-operator-due'],
|
||||
['\n- ', 'globalSearch-instructions-operator-created'],
|
||||
['\n- ', 'globalSearch-instructions-operator-modified'],
|
||||
@@ -222,6 +229,30 @@ class GlobalSearchComponent extends CardSearchPagedComponent {
|
||||
);
|
||||
document.getElementById('global-search-input').focus();
|
||||
},
|
||||
'click .js-copy-debug-selector'(evt) {
|
||||
/* Get the text field */
|
||||
const selector = document.getElementById("debug-selector");
|
||||
|
||||
try {
|
||||
navigator.clipboard.writeText(selector.textContent);
|
||||
alert("Selector copied to clipboard");
|
||||
} catch(err) {
|
||||
alert("Error copying text: " + err);
|
||||
}
|
||||
|
||||
},
|
||||
'click .js-copy-debug-projection'(evt) {
|
||||
/* Get the text field */
|
||||
const projection = document.getElementById("debug-projection");
|
||||
|
||||
try {
|
||||
navigator.clipboard.writeText(projection.textContent);
|
||||
alert("Projection copied to clipboard");
|
||||
} catch(err) {
|
||||
alert("Error copying text: " + err);
|
||||
}
|
||||
|
||||
},
|
||||
'click .js-board-title'(evt) {
|
||||
evt.preventDefault();
|
||||
const input = document.getElementById('global-search-input');
|
||||
|
||||
@@ -38,7 +38,8 @@ template(name="header")
|
||||
unless currentSetting.customTopLeftCornerLogoLinkUrl
|
||||
img(src="{{currentSetting.customTopLeftCornerLogoImageUrl}}" height="{{#if currentSetting.customTopLeftCornerLogoHeight}}#{currentSetting.customTopLeftCornerLogoHeight}{{else}}27{{/if}}" width="auto" margin="0" padding="0" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}")
|
||||
unless currentSetting.customTopLeftCornerLogoImageUrl
|
||||
img(src="{{pathFor '/logo-header.png'}}" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}")
|
||||
div#headerIsSettingDatabaseCallDone
|
||||
img(src="{{pathFor '/logo-header.png'}}" alt="{{currentSetting.productName}}" title="{{currentSetting.productName}}")
|
||||
span.allBoards
|
||||
a(href="{{pathFor 'home'}}")
|
||||
span.fa.fa-home
|
||||
@@ -93,3 +94,5 @@ template(name="offlineWarning")
|
||||
p
|
||||
i.fa.fa-warning
|
||||
| {{_ 'app-is-offline'}}
|
||||
|
||||
a.app-try-reconnect {{_ 'app-try-reconnect'}}
|
||||
@@ -1,7 +1,24 @@
|
||||
Meteor.subscribe('user-admin');
|
||||
Meteor.subscribe('boards');
|
||||
Meteor.subscribe('setting');
|
||||
Meteor.subscribe('announcements');
|
||||
Template.header.onCreated(function(){
|
||||
const templateInstance = this;
|
||||
templateInstance.currentSetting = new ReactiveVar();
|
||||
templateInstance.isLoading = new ReactiveVar(false);
|
||||
|
||||
Meteor.subscribe('setting', {
|
||||
onReady() {
|
||||
templateInstance.currentSetting.set(Settings.findOne());
|
||||
let currSetting = templateInstance.currentSetting.curValue;
|
||||
if(currSetting && currSetting !== undefined && currSetting.customLoginLogoImageUrl !== undefined && document.getElementById("headerIsSettingDatabaseCallDone") != null)
|
||||
document.getElementById("headerIsSettingDatabaseCallDone").style.display = 'none';
|
||||
else if(document.getElementById("headerIsSettingDatabaseCallDone") != null)
|
||||
document.getElementById("headerIsSettingDatabaseCallDone").style.display = 'block';
|
||||
return this.stop();
|
||||
},
|
||||
});
|
||||
});
|
||||
Template.header.helpers({
|
||||
wrappedHeader() {
|
||||
return !Session.get('currentBoard');
|
||||
@@ -41,3 +58,10 @@ Template.header.events({
|
||||
Session.set('currentCard', null);
|
||||
},
|
||||
});
|
||||
|
||||
Template.offlineWarning.events({
|
||||
'click a.app-try-reconnect'(event) {
|
||||
event.preventDefault();
|
||||
Meteor.reconnect();
|
||||
},
|
||||
});
|
||||
@@ -99,7 +99,7 @@
|
||||
height: 28px
|
||||
font-size: 12px
|
||||
display: flex
|
||||
z-index: 21
|
||||
z-index: 1000
|
||||
padding: 10px 0px
|
||||
|
||||
.allBoards
|
||||
@@ -250,3 +250,6 @@
|
||||
p
|
||||
margin: 7px
|
||||
padding: 0
|
||||
|
||||
#headerIsSettingDatabaseCallDone
|
||||
display: none;
|
||||
@@ -1,6 +1,6 @@
|
||||
head
|
||||
title
|
||||
meta(name="viewport" content="maximum-scale=1.0,width=device-width,initial-scale=1.0,user-scalable=0")
|
||||
meta(name="viewport" content="width=device-width, initial-scale=1")
|
||||
meta(http-equiv="X-UA-Compatible" content="IE=edge")
|
||||
//- XXX We should use pathFor in the following `href` to support the case
|
||||
where the application is deployed with a path prefix, but it seems to be
|
||||
@@ -48,6 +48,13 @@ template(name="userFormsLayout")
|
||||
+Template.dynamic(template=content)
|
||||
if currentSetting.displayAuthenticationMethod
|
||||
+connectionMethod(authenticationMethod=currentSetting.defaultAuthenticationMethod)
|
||||
if isLegalNoticeLinkExist
|
||||
div#legalNoticeDiv
|
||||
span#legalNoticeSpan {{_ 'acceptance_of_our_legalNotice'}}
|
||||
a#legalNoticeAtLink.at-link(href="{{currentSetting.legalNotice}}", target="_blank", rel="noopener noreferrer")
|
||||
| {{_ 'legalNotice'}}
|
||||
if getLegalNoticeWithWritTraduction
|
||||
div
|
||||
div.at-form-lang
|
||||
select.select-lang.js-userform-set-language
|
||||
each languages
|
||||
|
||||
@@ -53,6 +53,19 @@ Template.userFormsLayout.onCreated(function() {
|
||||
$('.at-pwd-form').hide();
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.call('isDisableRegistration', (_, result) => {
|
||||
if (result) {
|
||||
$('.at-signup-link').hide();
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.call('isDisableForgotPassword', (_, result) => {
|
||||
if (result) {
|
||||
$('.at-pwd-link').hide();
|
||||
}
|
||||
});
|
||||
|
||||
});
|
||||
|
||||
Template.userFormsLayout.onRendered(() => {
|
||||
@@ -77,6 +90,27 @@ Template.userFormsLayout.helpers({
|
||||
// return isSettingDatabaseFctCallDone;
|
||||
// },
|
||||
|
||||
isLegalNoticeLinkExist(){
|
||||
const currSet = Template.instance().currentSetting.get();
|
||||
if(currSet && currSet !== undefined && currSet != null){
|
||||
return currSet.legalNotice !== undefined && currSet.legalNotice.trim() != "";
|
||||
}
|
||||
else
|
||||
return false;
|
||||
},
|
||||
|
||||
getLegalNoticeWithWritTraduction(){
|
||||
let spanLegalNoticeElt = $("#legalNoticeSpan");
|
||||
if(spanLegalNoticeElt != null && spanLegalNoticeElt != undefined){
|
||||
spanLegalNoticeElt.html(TAPi18n.__('acceptance_of_our_legalNotice', {}, T9n.getLanguage() || 'en'));
|
||||
}
|
||||
let atLinkLegalNoticeElt = $("#legalNoticeAtLink");
|
||||
if(atLinkLegalNoticeElt != null && atLinkLegalNoticeElt != undefined){
|
||||
atLinkLegalNoticeElt.html(TAPi18n.__('legalNotice', {}, T9n.getLanguage() || 'en'));
|
||||
}
|
||||
return true;
|
||||
},
|
||||
|
||||
isLoading() {
|
||||
return Template.instance().isLoading.get();
|
||||
},
|
||||
@@ -100,6 +134,12 @@ Template.userFormsLayout.helpers({
|
||||
name = 'مَصرى';
|
||||
} else if (lang.name === 'de-CH') {
|
||||
name = 'Deutsch (Schweiz)';
|
||||
} else if (lang.name === 'de-AT') {
|
||||
name = 'Deutsch (Österreich)';
|
||||
} else if (lang.name === 'en-DE') {
|
||||
name = 'English (Germany)';
|
||||
} else if (lang.name === 'et-EE') {
|
||||
name = 'eesti keel (Eesti)';
|
||||
} else if (lang.name === 'fa-IR') {
|
||||
// fa-IR = Persian (Iran)
|
||||
name = 'فارسی/پارسی (ایران)';
|
||||
@@ -109,14 +149,26 @@ Template.userFormsLayout.helpers({
|
||||
name = 'Français (Canada)';
|
||||
} else if (lang.name === 'fr-CH') {
|
||||
name = 'Français (Schweiz)';
|
||||
} else if (lang.name === 'gu-IN') {
|
||||
// gu-IN = Gurajati (India)
|
||||
name = 'ગુજરાતી';
|
||||
} else if (lang.name === 'hi-IN') {
|
||||
// hi-IN = Hindi (India)
|
||||
name = 'हिंदी (भारत)';
|
||||
} else if (lang.name === 'ig') {
|
||||
name = 'Igbo';
|
||||
} else if (lang.name === 'lv') {
|
||||
name = 'Latviešu';
|
||||
} else if (lang.name === 'latviešu valoda') {
|
||||
name = 'Latviešu';
|
||||
} else if (lang.name === 'ms-MY') {
|
||||
// ms-MY = Malay (Malaysia)
|
||||
name = 'بهاس ملايو';
|
||||
} else if (lang.name === 'en-IT') {
|
||||
name = 'English (Italy)';
|
||||
} else if (lang.name === 'el-GR') {
|
||||
// el-GR = Greek (Greece)
|
||||
name = 'Ελληνικά (Ελλάδα)';
|
||||
} else if (lang.name === 'Español') {
|
||||
name = 'español';
|
||||
} else if (lang.name === 'es_419') {
|
||||
@@ -143,11 +195,18 @@ Template.userFormsLayout.helpers({
|
||||
name = 'español de Perú';
|
||||
} else if (lang.name === 'Español de Puerto Rico') {
|
||||
name = 'español de Puerto Rico';
|
||||
} else if (lang.name === 'gl-ES') {
|
||||
name = 'Galego (España)';
|
||||
} else if (lang.name === 'oc') {
|
||||
name = 'Occitan';
|
||||
} else if (lang.name === 'ru-UA') {
|
||||
name = 'Русский (Украина)';
|
||||
} else if (lang.name === 'st') {
|
||||
name = 'Sãotomense';
|
||||
} else if (lang.name === 'uk-UA') {
|
||||
name = 'українська (Україна)';
|
||||
} else if (lang.name === '繁体中文(台湾)') {
|
||||
// Traditional Chinese (Taiwan)
|
||||
name = '繁體中文(台灣)';
|
||||
}
|
||||
return { tag, name };
|
||||
|
||||
@@ -545,3 +545,8 @@ a
|
||||
|
||||
#isSettingDatabaseCallDone
|
||||
display: none;
|
||||
|
||||
.at-link
|
||||
color: #17683a;
|
||||
text-decoration: underline;
|
||||
text-decoration-color: #17683a;
|
||||
@@ -112,7 +112,7 @@
|
||||
.trigger-item
|
||||
overflow:auto
|
||||
padding:10px
|
||||
height:40px
|
||||
height:100px
|
||||
margin-bottom:5px
|
||||
border-radius: 3px
|
||||
position: relative
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
template(name="adminReports")
|
||||
.setting-content
|
||||
.setting-content.admin-reports-content
|
||||
unless currentUser.isAdmin
|
||||
| {{_ 'error-notAuthorized'}}
|
||||
else
|
||||
@@ -26,6 +26,16 @@ template(name="adminReports")
|
||||
i.fa.fa-magic
|
||||
| {{_ 'rulesReportTitle'}}
|
||||
|
||||
li
|
||||
a.js-report-boards(data-id="report-boards")
|
||||
i.fa.fa-magic
|
||||
| {{_ 'boardsReportTitle'}}
|
||||
|
||||
li
|
||||
a.js-report-cards(data-id="report-cards")
|
||||
i.fa.fa-magic
|
||||
| {{_ 'cardsReportTitle'}}
|
||||
|
||||
.main-body
|
||||
if loading.get
|
||||
+spinner
|
||||
@@ -37,6 +47,10 @@ template(name="adminReports")
|
||||
+orphanedFilesReport
|
||||
else if showRulesReport.get
|
||||
+rulesReport
|
||||
else if showBoardsReport.get
|
||||
+boardsReport
|
||||
else if showCardsReport.get
|
||||
+cardsReport
|
||||
|
||||
|
||||
template(name="brokenCardsReport")
|
||||
@@ -57,7 +71,7 @@ template(name="rulesReport")
|
||||
th actionType
|
||||
th activityType
|
||||
|
||||
each rule in rows
|
||||
each rule in results
|
||||
tr
|
||||
td {{ rule.title }}
|
||||
td {{ rule.boardTitle }}
|
||||
@@ -78,7 +92,7 @@ template(name="filesReport")
|
||||
th MD5 Sum
|
||||
th ID
|
||||
|
||||
each att in attachmentFiles
|
||||
each att in results
|
||||
tr
|
||||
td {{ att.filename }}
|
||||
td.right {{fileSize att.length }}
|
||||
@@ -100,7 +114,7 @@ template(name="orphanedFilesReport")
|
||||
th MD5 Sum
|
||||
th ID
|
||||
|
||||
each att in attachmentFiles
|
||||
each att in results
|
||||
tr
|
||||
td {{ att.filename }}
|
||||
td.right {{fileSize att.length }}
|
||||
@@ -109,3 +123,50 @@ template(name="orphanedFilesReport")
|
||||
td {{ att._id.toHexString }}
|
||||
else
|
||||
div {{_ 'no-results' }}
|
||||
|
||||
template(name="cardsReport")
|
||||
h1 {{_ 'cardsReportTitle'}}
|
||||
if resultsCount
|
||||
table.table
|
||||
tr
|
||||
th Card Title
|
||||
th Board
|
||||
th Swimlane
|
||||
th List
|
||||
th Members
|
||||
th Assignees
|
||||
|
||||
each card in results
|
||||
tr
|
||||
td {{abbreviate card.title }}
|
||||
td {{abbreviate card.board.title }}
|
||||
td {{abbreviate card.swimlane.title }}
|
||||
td {{abbreviate card.list.title }}
|
||||
td {{userNames card.members }}
|
||||
td {{userNames card.assignees }}
|
||||
else
|
||||
div {{_ 'no-results' }}
|
||||
|
||||
template(name="boardsReport")
|
||||
h1 {{_ 'boardsReportTitle'}}
|
||||
if resultsCount
|
||||
table.table
|
||||
tr
|
||||
th Title
|
||||
th Id
|
||||
th Permission
|
||||
th Archived?
|
||||
th Members
|
||||
th Organizations
|
||||
th Teams
|
||||
|
||||
each board in results
|
||||
tr
|
||||
td {{abbreviate board.title }}
|
||||
td {{abbreviate board._id }}
|
||||
td {{ board.permission }}
|
||||
td
|
||||
= yesOrNo(board.archived)
|
||||
td {{userNames board.members }}
|
||||
else
|
||||
div {{_ 'no-results' }}
|
||||
@@ -1,6 +1,8 @@
|
||||
import { AttachmentStorage } from '/models/attachments';
|
||||
import { CardSearchPagedComponent } from '/client/lib/cardSearch';
|
||||
import SessionData from '/models/usersessiondata';
|
||||
import { QueryParams } from '/config/query-classes';
|
||||
import { OPERATOR_LIMIT } from '/config/search-const';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
subscription: null,
|
||||
@@ -8,10 +10,14 @@ BlazeComponent.extendComponent({
|
||||
showBrokenCardsReport: new ReactiveVar(false),
|
||||
showOrphanedFilesReport: new ReactiveVar(false),
|
||||
showRulesReport: new ReactiveVar(false),
|
||||
showCardsReport: new ReactiveVar(false),
|
||||
showBoardsReport: new ReactiveVar(false),
|
||||
sessionId: null,
|
||||
|
||||
onCreated() {
|
||||
this.error = new ReactiveVar('');
|
||||
this.loading = new ReactiveVar(false);
|
||||
this.sessionId = SessionData.getSessionId();
|
||||
},
|
||||
|
||||
events() {
|
||||
@@ -21,6 +27,8 @@ BlazeComponent.extendComponent({
|
||||
'click a.js-report-files': this.switchMenu,
|
||||
'click a.js-report-orphaned-files': this.switchMenu,
|
||||
'click a.js-report-rules': this.switchMenu,
|
||||
'click a.js-report-cards': this.switchMenu,
|
||||
'click a.js-report-boards': this.switchMenu,
|
||||
},
|
||||
];
|
||||
},
|
||||
@@ -32,6 +40,9 @@ BlazeComponent.extendComponent({
|
||||
this.showFilesReport.set(false);
|
||||
this.showBrokenCardsReport.set(false);
|
||||
this.showOrphanedFilesReport.set(false);
|
||||
this.showRulesReport.set(false)
|
||||
this.showBoardsReport.set(false);
|
||||
this.showCardsReport.set(false);
|
||||
if (this.subscription) {
|
||||
this.subscription.stop();
|
||||
}
|
||||
@@ -64,68 +75,79 @@ BlazeComponent.extendComponent({
|
||||
this.showRulesReport.set(true);
|
||||
this.loading.set(false);
|
||||
});
|
||||
} else if ('report-boards' === targetID) {
|
||||
this.subscription = Meteor.subscribe('boardsReport', () => {
|
||||
this.showBoardsReport.set(true);
|
||||
this.loading.set(false);
|
||||
});
|
||||
} else if ('report-cards' === targetID) {
|
||||
const qp = new QueryParams();
|
||||
qp.addPredicate(OPERATOR_LIMIT, 300);
|
||||
this.subscription = Meteor.subscribe(
|
||||
'globalSearch',
|
||||
this.sessionId,
|
||||
qp.getParams(),
|
||||
qp.text,
|
||||
() => {
|
||||
this.showCardsReport.set(true);
|
||||
this.loading.set(false);
|
||||
},
|
||||
);
|
||||
}
|
||||
}
|
||||
},
|
||||
}).register('adminReports');
|
||||
|
||||
Template.filesReport.helpers({
|
||||
attachmentFiles() {
|
||||
class AdminReport extends BlazeComponent {
|
||||
collection;
|
||||
|
||||
results() {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('attachments:', AttachmentStorage.find());
|
||||
// console.log('attachments.count:', AttachmentStorage.find().count());
|
||||
return AttachmentStorage.find();
|
||||
},
|
||||
return this.collection.find();
|
||||
}
|
||||
|
||||
rulesReport() {
|
||||
const rules = [];
|
||||
|
||||
Rules.find().forEach(rule => {
|
||||
rules.push({
|
||||
_id: rule._id,
|
||||
title: rule.title,
|
||||
boardId: rule.boardId,
|
||||
boardTitle: rule.board().title,
|
||||
action: rule.action().fetch(),
|
||||
trigger: rule.trigger().fetch(),
|
||||
});
|
||||
});
|
||||
|
||||
return rules;
|
||||
},
|
||||
yesOrNo(value) {
|
||||
if (value) {
|
||||
return TAPi18n.__('yes');
|
||||
} else {
|
||||
return TAPi18n.__('no');
|
||||
}
|
||||
}
|
||||
|
||||
resultsCount() {
|
||||
return AttachmentStorage.find().count();
|
||||
},
|
||||
return this.collection.find().count();
|
||||
}
|
||||
|
||||
fileSize(size) {
|
||||
return Math.round(size / 1024);
|
||||
},
|
||||
}
|
||||
|
||||
usageCount(key) {
|
||||
return Attachments.find({ 'copies.attachments.key': key }).count();
|
||||
},
|
||||
});
|
||||
}
|
||||
|
||||
Template.orphanedFilesReport.helpers({
|
||||
attachmentFiles() {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('attachments:', AttachmentStorage.find());
|
||||
// console.log('attachments.count:', AttachmentStorage.find().count());
|
||||
return AttachmentStorage.find();
|
||||
},
|
||||
abbreviate(text) {
|
||||
if (text.length > 30) {
|
||||
return `${text.substr(0, 29)}...`;
|
||||
}
|
||||
return text;
|
||||
}
|
||||
}
|
||||
|
||||
resultsCount() {
|
||||
return AttachmentStorage.find().count();
|
||||
},
|
||||
(class extends AdminReport {
|
||||
collection = AttachmentStorage;
|
||||
}.register('filesReport'));
|
||||
|
||||
fileSize(size) {
|
||||
return Math.round(size / 1024);
|
||||
},
|
||||
});
|
||||
(class extends AdminReport {
|
||||
collection = AttachmentStorage;
|
||||
}.register('orphanedFilesReport'));
|
||||
|
||||
Template.rulesReport.helpers({
|
||||
rows() {
|
||||
(class extends AdminReport {
|
||||
collection = Rules;
|
||||
|
||||
results() {
|
||||
const rules = [];
|
||||
|
||||
Rules.find().forEach(rule => {
|
||||
@@ -139,14 +161,43 @@ Template.rulesReport.helpers({
|
||||
});
|
||||
});
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('rows:', rules);
|
||||
return rules;
|
||||
},
|
||||
}
|
||||
}.register('rulesReport'));
|
||||
|
||||
resultsCount() {
|
||||
return Rules.find().count();
|
||||
},
|
||||
});
|
||||
(class extends AdminReport {
|
||||
collection = Boards;
|
||||
|
||||
userNames(members) {
|
||||
let text = '';
|
||||
members.forEach(member => {
|
||||
const user = Users.findOne(member.userId);
|
||||
text += text ? ', ' : '';
|
||||
if (user) {
|
||||
text += user.username;
|
||||
} else {
|
||||
text += member.userId
|
||||
}
|
||||
});
|
||||
return text;
|
||||
}
|
||||
}.register('boardsReport'));
|
||||
|
||||
(class extends AdminReport {
|
||||
collection = Cards;
|
||||
|
||||
userNames(userIds) {
|
||||
let text = '';
|
||||
userIds.forEach(userId => {
|
||||
const user = Users.findOne(userId);
|
||||
text += text ? ', ' : '';
|
||||
text += user.username;
|
||||
});
|
||||
return text;
|
||||
}
|
||||
}.register('cardsReport'));
|
||||
|
||||
class BrokenCardsComponent extends CardSearchPagedComponent {
|
||||
onCreated() {
|
||||
|
||||
@@ -0,0 +1,3 @@
|
||||
.admin-reports-content
|
||||
height: auto !important
|
||||
|
||||
@@ -65,48 +65,49 @@ template(name='statistics')
|
||||
tr
|
||||
th {{_ 'OS_Cpus'}}
|
||||
td {{statistics.os.cpus.length}}
|
||||
tr
|
||||
th {{_ 'Node_heap_total_heap_size'}}
|
||||
td {{bytesToSize statistics.nodeHeapStats.totalHeapSize}}
|
||||
tr
|
||||
th {{_ 'Node_heap_total_heap_size_executable'}}
|
||||
td {{bytesToSize statistics.nodeHeapStats.totalHeapSizeExecutable}}
|
||||
tr
|
||||
th {{_ 'Node_heap_total_physical_size'}}
|
||||
td {{bytesToSize statistics.nodeHeapStats.totalPhysicalSize}}
|
||||
tr
|
||||
th {{_ 'Node_heap_total_available_size'}}
|
||||
td {{bytesToSize statistics.nodeHeapStats.totalAvailableSize}}
|
||||
tr
|
||||
th {{_ 'Node_heap_used_heap_size'}}
|
||||
td {{bytesToSize statistics.nodeHeapStats.usedHeapSize}}
|
||||
tr
|
||||
th {{_ 'Node_heap_heap_size_limit'}}
|
||||
td {{bytesToSize statistics.nodeHeapStats.heapSizeLimit}}
|
||||
tr
|
||||
th {{_ 'Node_heap_malloced_memory'}}
|
||||
td {{bytesToSize statistics.nodeHeapStats.mallocedMemory}}
|
||||
tr
|
||||
th {{_ 'Node_heap_peak_malloced_memory'}}
|
||||
td {{bytesToSize statistics.nodeHeapStats.peakMallocedMemory}}
|
||||
tr
|
||||
th {{_ 'Node_heap_does_zap_garbage'}}
|
||||
td {{statistics.nodeHeapStats.doesZapGarbage}}
|
||||
tr
|
||||
th {{_ 'Node_heap_number_of_native_contexts'}}
|
||||
td {{statistics.nodeHeapStats.numberOfNativeContexts}}
|
||||
tr
|
||||
th {{_ 'Node_heap_number_of_detached_contexts'}}
|
||||
td {{statistics.nodeHeapStats.numberOfDetachedContexts}}
|
||||
tr
|
||||
th {{_ 'Node_memory_usage_rss'}}
|
||||
td {{bytesToSize statistics.nodeMemoryUsage.rss}}
|
||||
tr
|
||||
th {{_ 'Node_memory_usage_heap_total'}}
|
||||
td {{bytesToSize statistics.nodeMemoryUsage.heapTotal}}
|
||||
tr
|
||||
th {{_ 'Node_memory_usage_heap_used'}}
|
||||
td {{bytesToSize statistics.nodeMemoryUsage.heapUsed}}
|
||||
tr
|
||||
th {{_ 'Node_memory_usage_external'}}
|
||||
td {{bytesToSize statistics.nodeMemoryUsage.external}}
|
||||
unless isSandstorm
|
||||
tr
|
||||
th {{_ 'Node_heap_total_heap_size'}}
|
||||
td {{bytesToSize statistics.nodeHeapStats.totalHeapSize}}
|
||||
tr
|
||||
th {{_ 'Node_heap_total_heap_size_executable'}}
|
||||
td {{bytesToSize statistics.nodeHeapStats.totalHeapSizeExecutable}}
|
||||
tr
|
||||
th {{_ 'Node_heap_total_physical_size'}}
|
||||
td {{bytesToSize statistics.nodeHeapStats.totalPhysicalSize}}
|
||||
tr
|
||||
th {{_ 'Node_heap_total_available_size'}}
|
||||
td {{bytesToSize statistics.nodeHeapStats.totalAvailableSize}}
|
||||
tr
|
||||
th {{_ 'Node_heap_used_heap_size'}}
|
||||
td {{bytesToSize statistics.nodeHeapStats.usedHeapSize}}
|
||||
tr
|
||||
th {{_ 'Node_heap_heap_size_limit'}}
|
||||
td {{bytesToSize statistics.nodeHeapStats.heapSizeLimit}}
|
||||
tr
|
||||
th {{_ 'Node_heap_malloced_memory'}}
|
||||
td {{bytesToSize statistics.nodeHeapStats.mallocedMemory}}
|
||||
tr
|
||||
th {{_ 'Node_heap_peak_malloced_memory'}}
|
||||
td {{bytesToSize statistics.nodeHeapStats.peakMallocedMemory}}
|
||||
tr
|
||||
th {{_ 'Node_heap_does_zap_garbage'}}
|
||||
td {{statistics.nodeHeapStats.doesZapGarbage}}
|
||||
tr
|
||||
th {{_ 'Node_heap_number_of_native_contexts'}}
|
||||
td {{statistics.nodeHeapStats.numberOfNativeContexts}}
|
||||
tr
|
||||
th {{_ 'Node_heap_number_of_detached_contexts'}}
|
||||
td {{statistics.nodeHeapStats.numberOfDetachedContexts}}
|
||||
tr
|
||||
th {{_ 'Node_memory_usage_rss'}}
|
||||
td {{bytesToSize statistics.nodeMemoryUsage.rss}}
|
||||
tr
|
||||
th {{_ 'Node_memory_usage_heap_total'}}
|
||||
td {{bytesToSize statistics.nodeMemoryUsage.heapTotal}}
|
||||
tr
|
||||
th {{_ 'Node_memory_usage_heap_used'}}
|
||||
td {{bytesToSize statistics.nodeMemoryUsage.heapUsed}}
|
||||
tr
|
||||
th {{_ 'Node_memory_usage_external'}}
|
||||
td {{bytesToSize statistics.nodeMemoryUsage.external}}
|
||||
@@ -144,6 +144,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
orgList() {
|
||||
const orgs = Org.find(this.findOrgsOptions.get(), {
|
||||
sort: { orgDisplayName: 1 },
|
||||
fields: { _id: true },
|
||||
});
|
||||
this.numberOrgs.set(orgs.count(false));
|
||||
@@ -151,6 +152,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
teamList() {
|
||||
const teams = Team.find(this.findTeamsOptions.get(), {
|
||||
sort: { teamDisplayName: 1 },
|
||||
fields: { _id: true },
|
||||
});
|
||||
this.numberTeams.set(teams.count(false));
|
||||
@@ -158,6 +160,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
peopleList() {
|
||||
const users = Users.find(this.findUsersOptions.get(), {
|
||||
sort: { username: 1 },
|
||||
fields: { _id: true },
|
||||
});
|
||||
this.numberPeople.set(users.count(false));
|
||||
@@ -251,10 +254,10 @@ Template.editUserPopup.helpers({
|
||||
return Template.instance().authenticationMethods.get();
|
||||
},
|
||||
orgsDatas() {
|
||||
return Org.find({}, {sort: { createdAt: -1 }});
|
||||
return Org.find({}, {sort: { orgDisplayName: 1 }});
|
||||
},
|
||||
teamsDatas() {
|
||||
return Team.find({}, {sort: { createdAt: -1 }});
|
||||
return Team.find({}, {sort: { teamDisplayName: 1 }});
|
||||
},
|
||||
isSelected(match) {
|
||||
const userId = Template.instance().data.userId;
|
||||
@@ -324,10 +327,10 @@ Template.newUserPopup.helpers({
|
||||
return Template.instance().authenticationMethods.get();
|
||||
},
|
||||
orgsDatas() {
|
||||
return Org.find({}, {sort: { createdAt: -1 }});
|
||||
return Org.find({}, {sort: { orgDisplayName: 1 }});
|
||||
},
|
||||
teamsDatas() {
|
||||
return Team.find({}, {sort: { createdAt: -1 }});
|
||||
return Team.find({}, {sort: { teamDisplayName: 1 }});
|
||||
},
|
||||
isSelected(match) {
|
||||
const userId = Template.instance().data.userId;
|
||||
@@ -417,7 +420,7 @@ BlazeComponent.extendComponent({
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {},
|
||||
teamsDatas() {
|
||||
return Team.find({}, {sort: { createdAt: -1 }});
|
||||
return Team.find({}, {sort: { teamDisplayName: 1 }});
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
|
||||
@@ -63,6 +63,11 @@ template(name="webhookSettings")
|
||||
|
||||
template(name="general")
|
||||
ul#registration-setting.setting-detail
|
||||
li
|
||||
a.flex.js-toggle-forgot-password
|
||||
.materialCheckBox(class="{{#if currentSetting.disableForgotPassword}}is-checked{{/if}}")
|
||||
|
||||
span {{_ 'disable-forgot-password'}}
|
||||
li
|
||||
a.flex.js-toggle-registration
|
||||
.materialCheckBox(class="{{#if currentSetting.disableRegistration}}is-checked{{/if}}")
|
||||
@@ -188,6 +193,10 @@ template(name='layoutSettings')
|
||||
.title {{_ 'can-invite-if-same-mailDomainName'}}
|
||||
.form-group
|
||||
input.wekan-form-control#mailDomainNamevalue(type="text", placeholder="" value="{{currentSetting.mailDomainName}}")
|
||||
li.layout-form
|
||||
.title {{_ 'custom-legal-notice-link-url'}}
|
||||
.form-group
|
||||
input.wekan-form-control#legalNoticevalue(type="text", placeholder="" value="{{currentSetting.legalNotice}}")
|
||||
li.layout-form
|
||||
.title {{_ 'display-authentication-method'}}
|
||||
.form-group.flex
|
||||
|
||||
@@ -4,6 +4,7 @@ BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.error = new ReactiveVar('');
|
||||
this.loading = new ReactiveVar(false);
|
||||
this.forgotPasswordSetting = new ReactiveVar(true);
|
||||
this.generalSetting = new ReactiveVar(true);
|
||||
this.emailSetting = new ReactiveVar(false);
|
||||
this.accountSetting = new ReactiveVar(false);
|
||||
@@ -56,6 +57,14 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
);
|
||||
},
|
||||
toggleForgotPassword() {
|
||||
this.setLoading(true);
|
||||
const forgotPasswordClosed = this.currentSetting().disableForgotPassword;
|
||||
Settings.update(Settings.findOne()._id, {
|
||||
$set: { disableForgotPassword: !forgotPasswordClosed },
|
||||
});
|
||||
this.setLoading(false);
|
||||
},
|
||||
toggleRegistration() {
|
||||
this.setLoading(true);
|
||||
const registrationClosed = this.currentSetting().disableRegistration;
|
||||
@@ -84,6 +93,7 @@ BlazeComponent.extendComponent({
|
||||
$('.side-menu li.active').removeClass('active');
|
||||
target.parent().addClass('active');
|
||||
const targetID = target.data('id');
|
||||
this.forgotPasswordSetting.set('forgot-password-setting' === targetID);
|
||||
this.generalSetting.set('registration-setting' === targetID);
|
||||
this.emailSetting.set('email-setting' === targetID);
|
||||
this.accountSetting.set('account-setting' === targetID);
|
||||
@@ -210,6 +220,11 @@ BlazeComponent.extendComponent({
|
||||
)
|
||||
.val()
|
||||
.trim();
|
||||
const legalNotice = $(
|
||||
'#legalNoticevalue',
|
||||
)
|
||||
.val()
|
||||
.trim();
|
||||
const hideLogoChange = $('input[name=hideLogo]:checked').val() === 'true';
|
||||
const displayAuthenticationMethod =
|
||||
$('input[name=displayAuthenticationMethod]:checked').val() === 'true';
|
||||
@@ -234,6 +249,7 @@ BlazeComponent.extendComponent({
|
||||
spinnerName,
|
||||
oidcBtnText,
|
||||
mailDomainName,
|
||||
legalNotice,
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
@@ -261,6 +277,7 @@ BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click a.js-toggle-forgot-password': this.toggleForgotPassword,
|
||||
'click a.js-toggle-registration': this.toggleRegistration,
|
||||
'click a.js-toggle-tls': this.toggleTLS,
|
||||
'click a.js-setting-menu': this.switchMenu,
|
||||
|
||||
@@ -88,6 +88,8 @@
|
||||
&.is-checked
|
||||
background #fff
|
||||
|
||||
input[type=radio]
|
||||
margin: 4px
|
||||
|
||||
.option
|
||||
@extends .flex
|
||||
|
||||
@@ -91,7 +91,14 @@ template(name="boardOrgGeneral")
|
||||
table
|
||||
tbody
|
||||
tr
|
||||
th {{_ 'displayName'}}
|
||||
th
|
||||
| {{_ 'add-organizations'}}
|
||||
br
|
||||
i.addOrganizationsLabel
|
||||
| {{_ 'to-create-organizations-contact-admin'}}
|
||||
br
|
||||
i.addOrganizationsLabel
|
||||
| {{_ 'add-organizations-label'}}
|
||||
th
|
||||
if currentUser.isBoardAdmin
|
||||
a.member.orgOrTeamMember.add-member.js-manage-board-addOrg(title="{{_ 'add-members'}}")
|
||||
@@ -106,13 +113,12 @@ template(name="boardTeamGeneral")
|
||||
tbody
|
||||
tr
|
||||
th
|
||||
b
|
||||
| {{_ 'add-teams'}}
|
||||
| {{_ 'add-teams'}}
|
||||
br
|
||||
i.addTeamsLabelcss
|
||||
i.addTeamsLabel
|
||||
| {{_ 'to-create-teams-contact-admin'}}
|
||||
br
|
||||
i.addTeamsLabelcss
|
||||
i.addTeamsLabel
|
||||
| {{_ 'add-teams-label'}}
|
||||
th
|
||||
if currentUser.isBoardAdmin
|
||||
@@ -197,6 +203,12 @@ template(name="boardCardSettingsPopup")
|
||||
span
|
||||
i.fa.fa-sort
|
||||
| {{_ 'card-sorting-by-number'}}
|
||||
div.check-div
|
||||
a.flex.js-field-has-card-show-lists(class="{{#if allowsShowLists}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if allowsShowLists}}is-checked{{/if}}")
|
||||
span
|
||||
i.fa.fa-list
|
||||
| {{_ 'card-show-lists'}}
|
||||
div.check-div
|
||||
a.flex.js-field-has-labels(class="{{#if allowsLabels}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if allowsLabels}}is-checked{{/if}}")
|
||||
@@ -488,12 +500,12 @@ template(name="removeBoardOrgPopup")
|
||||
form
|
||||
input.hide#hideOrgId(type="text" value=org._id)
|
||||
label
|
||||
| {{_ 'leave-board'}} ?
|
||||
| {{_ 'remove-organization-from-board'}}
|
||||
br
|
||||
hr
|
||||
div.buttonsContainer
|
||||
input.primary.wide.leaveBoardBtn#leaveBoardBtn(type="submit" value="{{_ 'leave-board'}}")
|
||||
input.primary.wide.cancelLeaveBoardBtn#cancelLeaveBoardBtn(type="submit" value="{{_ 'Cancel'}}")
|
||||
input.primary.wide.leaveBoardBtn#leaveBoardBtn(type="submit" value="{{_ 'confirm-btn'}}")
|
||||
input.primary.wide.cancelLeaveBoardBtn#cancelLeaveBoardBtn(type="submit" value="{{_ 'cancel'}}")
|
||||
|
||||
template(name="addBoardTeamPopup")
|
||||
select.js-boardTeams#jsBoardTeams
|
||||
|
||||
@@ -827,6 +827,10 @@ BlazeComponent.extendComponent({
|
||||
return this.currentBoard.allowsCardSortingByNumber;
|
||||
},
|
||||
|
||||
allowsShowLists() {
|
||||
return this.currentBoard.allowsShowLists;
|
||||
},
|
||||
|
||||
allowsLabels() {
|
||||
return this.currentBoard.allowsLabels;
|
||||
},
|
||||
@@ -1061,6 +1065,22 @@ BlazeComponent.extendComponent({
|
||||
this.currentBoard.allowsCardSortingByNumber,
|
||||
);
|
||||
},
|
||||
'click .js-field-has-card-show-lists'(evt) {
|
||||
evt.preventDefault();
|
||||
this.currentBoard.allowsShowLists = !this.currentBoard
|
||||
.allowsShowLists;
|
||||
this.currentBoard.setAllowsShowLists(
|
||||
this.currentBoard.allowsShowLists,
|
||||
);
|
||||
$(`.js-field-has-card-show-lists ${MCB}`).toggleClass(
|
||||
CKCLS,
|
||||
this.currentBoard.allowsShowLists,
|
||||
);
|
||||
$('.js-field-has-card-show-lists').toggleClass(
|
||||
CKCLS,
|
||||
this.currentBoard.allowsShowLists,
|
||||
);
|
||||
},
|
||||
'click .js-field-has-labels'(evt) {
|
||||
evt.preventDefault();
|
||||
this.currentBoard.allowsLabels = !this.currentBoard.allowsLabels;
|
||||
@@ -1325,8 +1345,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.addBoardOrgPopup.helpers({
|
||||
orgsDatas() {
|
||||
// return Org.find({}, {sort: { createdAt: -1 }});
|
||||
let orgs = Org.find({}, {sort: { createdAt: -1 }});
|
||||
let orgs = Org.find({}, {sort: { orgDisplayName: 1 }});
|
||||
return orgs;
|
||||
},
|
||||
});
|
||||
@@ -1499,7 +1518,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.addBoardTeamPopup.helpers({
|
||||
teamsDatas() {
|
||||
let teams = Team.find({}, {sort: { createdAt: -1 }});
|
||||
let teams = Team.find({}, {sort: { teamDisplayName: 1 }});
|
||||
return teams;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -225,13 +225,15 @@
|
||||
margin-left: 5% !important
|
||||
background-color: red !important
|
||||
|
||||
.addTeamsLabelcss
|
||||
font-weight: normal;
|
||||
.addTeamsLabel, .addOrganizationsLabel
|
||||
font-weight: normal
|
||||
|
||||
.js-manage-board-removeTeam
|
||||
.js-manage-board-removeTeam:hover, .js-manage-board-removeTeam.is-active,
|
||||
.js-manage-board-removeOrg:hover, .js-manage-board-removeOrg.is-active
|
||||
box-shadow: 0 0 0 2px #e23210 inset !important
|
||||
|
||||
.js-manage-board-addTeam
|
||||
.js-manage-board-addTeam:hover, .js-manage-board-addTeam.is-active,
|
||||
.js-manage-board-addOrg:hover , .js-manage-board-addOrg.is-active
|
||||
box-shadow: 0 0 0 2px #73ea10 inset !important
|
||||
|
||||
.addTeamFaPlus
|
||||
|
||||
@@ -1,4 +1,4 @@
|
||||
archivedRequested = false;
|
||||
//archivedRequested = false;
|
||||
const subManager = new SubsManager();
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
@@ -13,7 +13,7 @@ BlazeComponent.extendComponent({
|
||||
const currentBoardId = Session.get('currentBoard');
|
||||
if (!currentBoardId) return;
|
||||
const handle = subManager.subscribe('board', currentBoardId, true);
|
||||
archivedRequested = true;
|
||||
//archivedRequested = true;
|
||||
Tracker.nonreactive(() => {
|
||||
Tracker.autorun(() => {
|
||||
this.isArchiveReady.set(handle.ready());
|
||||
|
||||
@@ -99,14 +99,14 @@ BlazeComponent.extendComponent({
|
||||
}).register('filterSidebar');
|
||||
|
||||
function mutateSelectedCards(mutationName, ...args) {
|
||||
Cards.find(MultiSelection.getMongoSelector()).forEach(card => {
|
||||
Cards.find(MultiSelection.getMongoSelector(), {sort: ['sort']}).forEach(card => {
|
||||
card[mutationName](...args);
|
||||
});
|
||||
}
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
mapSelection(kind, _id) {
|
||||
return Cards.find(MultiSelection.getMongoSelector()).map(card => {
|
||||
return Cards.find(MultiSelection.getMongoSelector(), {sort: ['sort']}).map(card => {
|
||||
const methodName = kind === 'label' ? 'hasLabel' : 'isAssigned';
|
||||
return card[methodName](_id);
|
||||
});
|
||||
|
||||
@@ -16,7 +16,7 @@ BlazeComponent.extendComponent({
|
||||
clickOnMiniCard(evt) {
|
||||
if (Utils.isMiniScreen()) {
|
||||
evt.preventDefault();
|
||||
Session.set('popupCard', this.currentData()._id);
|
||||
Session.set('popupCardId', this.currentData()._id);
|
||||
this.cardDetailsPopup(evt);
|
||||
}
|
||||
},
|
||||
|
||||
@@ -53,6 +53,7 @@ template(name="addListForm")
|
||||
autocomplete="off" autofocus)
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm(type="submit") {{_ 'save'}}
|
||||
.fa.fa-times-thin.js-close-inlined-form
|
||||
unless currentBoard.isTemplatesBoard
|
||||
unless currentBoard.isTemplateBoard
|
||||
span.quiet
|
||||
|
||||
@@ -54,13 +54,15 @@ function initSortable(boardComponent, $listsDom) {
|
||||
};
|
||||
|
||||
$listsDom.sortable({
|
||||
connectWith: '.board-canvas',
|
||||
tolerance: 'pointer',
|
||||
helper: 'clone',
|
||||
items: '.js-list:not(.js-list-composer)',
|
||||
placeholder: 'list placeholder',
|
||||
placeholder: 'js-list placeholder',
|
||||
distance: 7,
|
||||
start(evt, ui) {
|
||||
ui.placeholder.height(ui.helper.height());
|
||||
ui.placeholder.width(ui.helper.width());
|
||||
EscapeActions.executeUpTo('popup-close');
|
||||
boardComponent.setIsDragging(true);
|
||||
},
|
||||
@@ -148,8 +150,8 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
visible(list) {
|
||||
if (list.archived) {
|
||||
// Show archived list only when filter archive is on or archive is selected
|
||||
if (!(Filter.archive.isSelected() || archivedRequested)) {
|
||||
// Show archived list only when filter archive is on
|
||||
if (!Filter.archive.isSelected()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -237,13 +239,15 @@ BlazeComponent.extendComponent({
|
||||
{
|
||||
submit(evt) {
|
||||
evt.preventDefault();
|
||||
const lastList = this.currentBoard.getLastList();
|
||||
const sortIndex = Utils.calculateIndexData(lastList, null).base;
|
||||
const titleInput = this.find('.list-name-input');
|
||||
const title = titleInput.value.trim();
|
||||
if (title) {
|
||||
Lists.insert({
|
||||
title,
|
||||
boardId: Session.get('currentBoard'),
|
||||
sort: $('.list').length,
|
||||
sort: sortIndex,
|
||||
type: this.isListTemplatesSwimlane ? 'template-list' : 'list',
|
||||
swimlaneId: this.currentBoard.isTemplatesBoard()
|
||||
? this.currentSwimlane._id
|
||||
@@ -278,8 +282,8 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
visible(list) {
|
||||
if (list.archived) {
|
||||
// Show archived list only when filter archive is on or archive is selected
|
||||
if (!(Filter.archive.isSelected() || archivedRequested)) {
|
||||
// Show archived list only when filter archive is on
|
||||
if (!Filter.archive.isSelected()) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -36,6 +36,11 @@
|
||||
// Minimize swimlanes end https://www.w3schools.com/howto/howto_js_accordion.asp
|
||||
*/
|
||||
|
||||
@media screen and (min-width: 801px)
|
||||
.swimlane.ui-sortable
|
||||
// swimlane must have max width, otherwise lists are not sortable if there are too much lists and the swimlane "scrollable"
|
||||
width: max-content
|
||||
|
||||
[class=swimlane]
|
||||
position: sticky
|
||||
left: 0
|
||||
|
||||
@@ -266,25 +266,43 @@ Template.changeLanguagePopup.helpers({
|
||||
} else if (lang.name === 'ar-EG') {
|
||||
// ar-EG = Arabic (Egypt), simply Masri (مَصرى, [ˈmɑsˤɾi], Egyptian, Masr refers to Cairo)
|
||||
name = 'مَصرى';
|
||||
} else if (lang.name === 'de-CH') {
|
||||
name = 'Deutsch (Schweiz)';
|
||||
} else if (lang.name === 'de-AT') {
|
||||
name = 'Deutsch (Österreich)';
|
||||
} else if (lang.name === 'en-DE') {
|
||||
name = 'English (Germany)';
|
||||
} else if (lang.name === 'et-EE') {
|
||||
name = 'eesti keel (Eesti)';
|
||||
} else if (lang.name === 'fa-IR') {
|
||||
// fa-IR = Persian (Iran)
|
||||
name = 'فارسی/پارسی (ایران)';
|
||||
} else if (lang.name === 'de-CH') {
|
||||
name = 'Deutsch (Schweiz)';
|
||||
} else if (lang.name === 'fr-BE') {
|
||||
name = 'Français (Belgique)';
|
||||
} else if (lang.name === 'fr-CA') {
|
||||
name = 'Français (Canada)';
|
||||
} else if (lang.name === 'fr-CH') {
|
||||
name = 'Français (Schweiz)';
|
||||
} else if (lang.name === 'gu-IN') {
|
||||
// gu-IN = Gurajati (India)
|
||||
name = 'ગુજરાતી';
|
||||
} else if (lang.name === 'hi-IN') {
|
||||
// hi-IN = Hindi (India)
|
||||
name = 'हिंदी (भारत)';
|
||||
} else if (lang.name === 'ig') {
|
||||
name = 'Igbo';
|
||||
} else if (lang.name === 'lv') {
|
||||
name = 'Latviešu';
|
||||
} else if (lang.name === 'latviešu valoda') {
|
||||
name = 'Latviešu';
|
||||
} else if (lang.name === 'ms-MY') {
|
||||
// ms-MY = Malay (Malaysia)
|
||||
name = 'بهاس ملايو';
|
||||
} else if (lang.name === 'en-IT') {
|
||||
name = 'English (Italy)';
|
||||
} else if (lang.name === 'el-GR') {
|
||||
// el-GR = Greek (Greece)
|
||||
name = 'Ελληνικά (Ελλάδα)';
|
||||
} else if (lang.name === 'Español') {
|
||||
name = 'español';
|
||||
} else if (lang.name === 'es_419') {
|
||||
@@ -311,11 +329,18 @@ Template.changeLanguagePopup.helpers({
|
||||
name = 'español de Perú';
|
||||
} else if (lang.name === 'Español de Puerto Rico') {
|
||||
name = 'español de Puerto Rico';
|
||||
} else if (lang.name === 'gl-ES') {
|
||||
name = 'Galego (España)';
|
||||
} else if (lang.name === 'oc') {
|
||||
name = 'Occitan';
|
||||
} else if (lang.name === 'ru-UA') {
|
||||
name = 'Русский (Украина)';
|
||||
} else if (lang.name === 'st') {
|
||||
name = 'Sãotomense';
|
||||
} else if (lang.name === 'uk-UA') {
|
||||
name = 'українська (Україна)';
|
||||
} else if (lang.name === '繁体中文(台湾)') {
|
||||
// Traditional Chinese (Taiwan)
|
||||
name = '繁體中文(台灣)';
|
||||
}
|
||||
return { tag, name };
|
||||
|
||||
@@ -1,10 +1,6 @@
|
||||
Blaze.registerHelper('currentBoard', () => {
|
||||
const boardId = Session.get('currentBoard');
|
||||
if (boardId) {
|
||||
return Boards.findOne(boardId);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
const ret = Utils.getCurrentBoard();
|
||||
return ret;
|
||||
});
|
||||
|
||||
Blaze.registerHelper('currentCard', () => {
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
import Cards from '../../models/cards';
|
||||
import SessionData from '../../models/usersessiondata';
|
||||
import {QueryDebug} from "../../config/query-classes";
|
||||
import {OPERATOR_DEBUG} from "../../config/search-const";
|
||||
|
||||
export class CardSearchPagedComponent extends BlazeComponent {
|
||||
onCreated() {
|
||||
@@ -19,6 +21,8 @@ export class CardSearchPagedComponent extends BlazeComponent {
|
||||
this.sessionId = SessionData.getSessionId();
|
||||
this.subscriptionHandle = null;
|
||||
this.serverError = new ReactiveVar(false);
|
||||
this.sessionData = null;
|
||||
this.debug = new ReactiveVar(new QueryDebug());
|
||||
|
||||
const that = this;
|
||||
this.subscriptionCallbacks = {
|
||||
@@ -52,6 +56,7 @@ export class CardSearchPagedComponent extends BlazeComponent {
|
||||
this.resultsCount = 0;
|
||||
this.totalHits = 0;
|
||||
this.queryErrors = null;
|
||||
this.debug.set(new QueryDebug());
|
||||
}
|
||||
|
||||
getSessionData(sessionId) {
|
||||
@@ -63,30 +68,34 @@ export class CardSearchPagedComponent extends BlazeComponent {
|
||||
getResults() {
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('getting results');
|
||||
const sessionData = this.getSessionData();
|
||||
this.sessionData = this.getSessionData();
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('session data:', sessionData);
|
||||
console.log('session data:', this.sessionData);
|
||||
const cards = [];
|
||||
sessionData.cards.forEach(cardId => {
|
||||
this.sessionData.cards.forEach(cardId => {
|
||||
cards.push(Cards.findOne({ _id: cardId }));
|
||||
});
|
||||
this.queryErrors = sessionData.errors;
|
||||
this.queryErrors = this.sessionData.errors;
|
||||
if (this.queryErrors.length) {
|
||||
// console.log('queryErrors:', this.queryErrorMessages());
|
||||
this.hasQueryErrors.set(true);
|
||||
// return null;
|
||||
}
|
||||
this.debug.set(new QueryDebug(this.sessionData.debug));
|
||||
console.log('debug:', this.debug.get().get());
|
||||
console.log('debug.show():', this.debug.get().show());
|
||||
console.log('debug.showSelector():', this.debug.get().showSelector());
|
||||
|
||||
if (cards) {
|
||||
this.totalHits = sessionData.totalHits;
|
||||
this.totalHits = this.sessionData.totalHits;
|
||||
this.resultsCount = cards.length;
|
||||
this.resultsStart = sessionData.lastHit - this.resultsCount + 1;
|
||||
this.resultsEnd = sessionData.lastHit;
|
||||
this.resultsStart = this.sessionData.lastHit - this.resultsCount + 1;
|
||||
this.resultsEnd = this.sessionData.lastHit;
|
||||
this.resultsHeading.set(this.getResultsHeading());
|
||||
this.results.set(cards);
|
||||
this.hasNextPage.set(sessionData.lastHit < sessionData.totalHits);
|
||||
this.hasNextPage.set(this.sessionData.lastHit < this.sessionData.totalHits);
|
||||
this.hasPreviousPage.set(
|
||||
sessionData.lastHit - sessionData.resultsCount > 0,
|
||||
this.sessionData.lastHit - this.sessionData.resultsCount > 0,
|
||||
);
|
||||
return cards;
|
||||
}
|
||||
@@ -113,6 +122,7 @@ export class CardSearchPagedComponent extends BlazeComponent {
|
||||
|
||||
runGlobalSearch(queryParams) {
|
||||
this.searching.set(true);
|
||||
this.debug.set(new QueryDebug());
|
||||
this.stopSubscription();
|
||||
this.subscriptionHandle = this.getSubscription(queryParams);
|
||||
}
|
||||
|
||||
@@ -49,7 +49,8 @@ InlinedForm = BlazeComponent.extendComponent({
|
||||
|
||||
getValue() {
|
||||
const input = this.find('textarea,input[type=text]');
|
||||
return this.isOpen.get() && input && input.value.replaceAll(/\s +$/gm, '');
|
||||
// \s without \n + unicode (https://developer.mozilla.org/de/docs/Web/JavaScript/Guide/Regular_Expressions#special-white-space)
|
||||
return this.isOpen.get() && input && input.value.replaceAll(/[ \f\r\t\v]+$/gm, '');
|
||||
},
|
||||
|
||||
events() {
|
||||
|
||||
Vendored
+20
@@ -0,0 +1,20 @@
|
||||
// https://bugs.jqueryui.com/ticket/15020
|
||||
// required for sortable
|
||||
require('jquery-ui/ui/widget')
|
||||
require('jquery-ui/ui/scroll-parent')
|
||||
require('jquery-ui/ui/data')
|
||||
require('jquery-ui/ui/widgets/mouse')
|
||||
require('jquery-ui/ui/ie')
|
||||
require('jquery-ui/ui/widgets/sortable')
|
||||
|
||||
// required for draggable
|
||||
require('jquery-ui/ui/plugin')
|
||||
require('jquery-ui/ui/safe-active-element')
|
||||
require('jquery-ui/ui/safe-blur')
|
||||
require('jquery-ui/ui/widgets/draggable')
|
||||
|
||||
// everything already required for droppable
|
||||
require('jquery-ui/ui/widgets/droppable')
|
||||
|
||||
// enable touch on mobile
|
||||
require('jquery-ui-touch-punch')
|
||||
+70
-1
@@ -8,7 +8,7 @@ function getHoveredCardId() {
|
||||
}
|
||||
|
||||
function getSelectedCardId() {
|
||||
return Session.get('selectedCard') || getHoveredCardId();
|
||||
return Session.get('currentCard') || Session.get('selectedCard') || getHoveredCardId();
|
||||
}
|
||||
|
||||
Mousetrap.bind('?', () => {
|
||||
@@ -68,6 +68,67 @@ Mousetrap.bind(['down', 'up'], (evt, key) => {
|
||||
}
|
||||
});
|
||||
|
||||
numbArray = _.range(1,10).map(x => 'shift+'+String(x))
|
||||
Mousetrap.bind(numbArray, (evt, key) => {
|
||||
num = parseInt(key.substr(6, key.length));
|
||||
const currentUserId = Meteor.userId();
|
||||
if (currentUserId === null) {
|
||||
return;
|
||||
}
|
||||
const currentBoardId = Session.get('currentBoard');
|
||||
board = Boards.findOne(currentBoardId);
|
||||
labels = board.labels;
|
||||
if(MultiSelection.isActive())
|
||||
{
|
||||
const cardIds = MultiSelection.getSelectedCardIds();
|
||||
for (const cardId of cardIds)
|
||||
{
|
||||
card = Cards.findOne(cardId);
|
||||
if(num <= board.labels.length)
|
||||
{
|
||||
card.removeLabel(labels[num-1]["_id"]);
|
||||
}
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
numArray = _.range(1,10).map(x => String(x))
|
||||
Mousetrap.bind(numArray, (evt, key) => {
|
||||
num = parseInt(key);
|
||||
const currentUserId = Meteor.userId();
|
||||
const currentBoardId = Session.get('currentBoard');
|
||||
if (currentUserId === null) {
|
||||
return;
|
||||
}
|
||||
board = Boards.findOne(currentBoardId);
|
||||
labels = board.labels;
|
||||
if(MultiSelection.isActive() && Meteor.user().isBoardMember())
|
||||
{
|
||||
const cardIds = MultiSelection.getSelectedCardIds();
|
||||
for (const cardId of cardIds)
|
||||
{
|
||||
card = Cards.findOne(cardId);
|
||||
if(num <= board.labels.length)
|
||||
{
|
||||
card.addLabel(labels[num-1]["_id"]);
|
||||
}
|
||||
}
|
||||
return;
|
||||
}
|
||||
|
||||
const cardId = getSelectedCardId();
|
||||
if (!cardId) {
|
||||
return;
|
||||
}
|
||||
if (Meteor.user().isBoardMember()) {
|
||||
const card = Cards.findOne(cardId);
|
||||
if(num <= board.labels.length)
|
||||
{
|
||||
card.toggleLabel(labels[num-1]["_id"]);
|
||||
}
|
||||
}
|
||||
});
|
||||
|
||||
Mousetrap.bind('space', evt => {
|
||||
const cardId = getSelectedCardId();
|
||||
if (!cardId) {
|
||||
@@ -154,5 +215,13 @@ Template.keyboardShortcuts.helpers({
|
||||
keys: ['c'],
|
||||
action: 'archive-card',
|
||||
},
|
||||
{
|
||||
keys: ['number keys 1-9'],
|
||||
action: 'toggle-labels'
|
||||
},
|
||||
{
|
||||
keys: ['shift + number keys 1-9'],
|
||||
action: 'remove-labels-multiselect'
|
||||
},
|
||||
],
|
||||
});
|
||||
@@ -60,6 +60,8 @@ MultiSelection = {
|
||||
|
||||
startRangeCardId: null,
|
||||
|
||||
_sidebarWasOpen: false,
|
||||
|
||||
reset() {
|
||||
this._selectedCards.set([]);
|
||||
},
|
||||
@@ -81,14 +83,21 @@ MultiSelection = {
|
||||
isEmpty() {
|
||||
return this.count() === 0;
|
||||
},
|
||||
getSelectedCardIds(){
|
||||
return this._selectedCards.curValue;
|
||||
},
|
||||
|
||||
activate() {
|
||||
if (!this.isActive()) {
|
||||
this._sidebarWasOpen = Sidebar.isOpen();
|
||||
EscapeActions.executeUpTo('detailsPane');
|
||||
this._isActive.set(true);
|
||||
Tracker.flush();
|
||||
}
|
||||
Sidebar.setView(this.sidebarView);
|
||||
if(Utils.isMiniScreen()) {
|
||||
Sidebar.hide();
|
||||
}
|
||||
},
|
||||
|
||||
disable() {
|
||||
@@ -96,6 +105,9 @@ MultiSelection = {
|
||||
this._isActive.set(false);
|
||||
if (Sidebar && Sidebar.getView() === this.sidebarView) {
|
||||
Sidebar.setView();
|
||||
if(!this._sidebarWasOpen) {
|
||||
Sidebar.hide();
|
||||
}
|
||||
}
|
||||
this.reset();
|
||||
}
|
||||
|
||||
@@ -163,18 +163,6 @@ describe('Utils', function() {
|
||||
it('has no tests yet');
|
||||
});
|
||||
|
||||
describe(Utils.isTouchDevice.name, function() {
|
||||
it('has no tests yet');
|
||||
});
|
||||
|
||||
describe(Utils.calculateTouchDistance.name, function() {
|
||||
it('has no tests yet');
|
||||
});
|
||||
|
||||
describe(Utils.enableClickOnTouch.name, function() {
|
||||
it('has no tests yet');
|
||||
});
|
||||
|
||||
describe(Utils.manageCustomUI.name, function() {
|
||||
it('has no tests yet');
|
||||
});
|
||||
|
||||
+77
-62
@@ -1,4 +1,16 @@
|
||||
Utils = {
|
||||
/** returns the current board id
|
||||
* <li> returns the current board id or the board id of the popup card if set
|
||||
*/
|
||||
getCurrentBoardId() {
|
||||
let popupCardBoardId = Session.get('popupCardBoardId');
|
||||
let currentBoard = Session.get('currentBoard');
|
||||
let ret = currentBoard;
|
||||
if (popupCardBoardId) {
|
||||
ret = popupCardBoardId;
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
getCurrentCardId(ignorePopupCard) {
|
||||
let ret = Session.get('currentCard');
|
||||
if (!ret && !ignorePopupCard) {
|
||||
@@ -7,7 +19,15 @@ Utils = {
|
||||
return ret;
|
||||
},
|
||||
getPopupCardId() {
|
||||
const ret = Session.get('popupCard');
|
||||
const ret = Session.get('popupCardId');
|
||||
return ret;
|
||||
},
|
||||
/** returns the current board
|
||||
* <li> returns the current board or the board of the popup card if set
|
||||
*/
|
||||
getCurrentBoard() {
|
||||
const boardId = Utils.getCurrentBoardId();
|
||||
const ret = Boards.findOne(boardId);
|
||||
return ret;
|
||||
},
|
||||
getCurrentCard(ignorePopupCard) {
|
||||
@@ -344,67 +364,6 @@ Utils = {
|
||||
};
|
||||
},
|
||||
|
||||
// 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);
|
||||
}
|
||||
});
|
||||
},
|
||||
|
||||
manageCustomUI() {
|
||||
Meteor.call('getCustomUI', (err, data) => {
|
||||
if (err && err.error[0] === 'var-not-exist') {
|
||||
@@ -506,6 +465,62 @@ Utils = {
|
||||
}
|
||||
return finalString;
|
||||
},
|
||||
|
||||
fallbackCopyTextToClipboard(text) {
|
||||
var textArea = document.createElement("textarea");
|
||||
textArea.value = text;
|
||||
|
||||
// Avoid scrolling to bottom
|
||||
textArea.style.top = "0";
|
||||
textArea.style.left = "0";
|
||||
textArea.style.position = "fixed";
|
||||
|
||||
document.body.appendChild(textArea);
|
||||
textArea.focus();
|
||||
textArea.select();
|
||||
|
||||
try {
|
||||
document.execCommand('copy');
|
||||
return Promise.resolve(true);
|
||||
} catch (e) {
|
||||
return Promise.reject(false);
|
||||
} finally {
|
||||
document.body.removeChild(textArea);
|
||||
}
|
||||
},
|
||||
|
||||
/** copy the text to the clipboard
|
||||
* @see https://stackoverflow.com/questions/400212/how-do-i-copy-to-the-clipboard-in-javascript/30810322#30810322
|
||||
* @param string copy this text to the clipboard
|
||||
* @return Promise
|
||||
*/
|
||||
copyTextToClipboard(text) {
|
||||
let ret;
|
||||
if (navigator.clipboard) {
|
||||
ret = navigator.clipboard.writeText(text).then(function() {
|
||||
}, function(err) {
|
||||
console.error('Async: Could not copy text: ', err);
|
||||
});
|
||||
} else {
|
||||
ret = Utils.fallbackCopyTextToClipboard(text);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
|
||||
/** show the "copied!" message
|
||||
* @param promise the promise of Utils.copyTextToClipboard
|
||||
* @param $tooltip jQuery tooltip element
|
||||
*/
|
||||
showCopied(promise, $tooltip) {
|
||||
if (promise) {
|
||||
promise.then(() => {
|
||||
$tooltip.show(100);
|
||||
setTimeout(() => $tooltip.hide(100), 1000);
|
||||
}, (err) => {
|
||||
console.error("error: ", err);
|
||||
});
|
||||
}
|
||||
},
|
||||
};
|
||||
|
||||
// A simple tracker dependency that we invalidate every time the window is
|
||||
|
||||
+42
-4
@@ -1,5 +1,32 @@
|
||||
const passwordField = AccountsTemplates.removeField('password');
|
||||
const emailField = AccountsTemplates.removeField('email');
|
||||
let disableRegistration = false;
|
||||
let disableForgotPassword = false;
|
||||
let passwordLoginDisabled = false;
|
||||
|
||||
Meteor.call('isPasswordLoginDisabled', (_, result) => {
|
||||
if (result) {
|
||||
passwordLoginDisabled = true;
|
||||
//console.log('passwordLoginDisabled');
|
||||
//console.log(result);
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.call('isDisableRegistration', (_, result) => {
|
||||
if (result) {
|
||||
disableRegistration = true;
|
||||
//console.log('disableRegistration');
|
||||
//console.log(result);
|
||||
}
|
||||
});
|
||||
|
||||
Meteor.call('isDisableForgotPassword', (_, result) => {
|
||||
if (result) {
|
||||
disableForgotPassword = true;
|
||||
//console.log('disableForgotPassword');
|
||||
//console.log(result);
|
||||
}
|
||||
});
|
||||
|
||||
AccountsTemplates.addFields([
|
||||
{
|
||||
@@ -27,7 +54,8 @@ AccountsTemplates.configure({
|
||||
confirmPassword: true,
|
||||
enablePasswordChange: true,
|
||||
sendVerificationEmail: true,
|
||||
showForgotPasswordLink: true,
|
||||
showForgotPasswordLink: !disableForgotPassword,
|
||||
forbidClientAccountCreation: disableRegistration,
|
||||
onLogoutHook() {
|
||||
const homePage = 'home';
|
||||
if (FlowRouter.getRouteName() === homePage) {
|
||||
@@ -38,11 +66,21 @@ AccountsTemplates.configure({
|
||||
},
|
||||
});
|
||||
|
||||
if (!disableForgotPassword) {
|
||||
[
|
||||
'forgotPwd',
|
||||
'resetPwd',
|
||||
].forEach(routeName => AccountsTemplates.configureRoute(routeName));
|
||||
}
|
||||
|
||||
if (!disableRegistration) {
|
||||
[
|
||||
'signUp',
|
||||
].forEach(routeName => AccountsTemplates.configureRoute(routeName));
|
||||
}
|
||||
|
||||
[
|
||||
'signIn',
|
||||
'signUp',
|
||||
'resetPwd',
|
||||
'forgotPwd',
|
||||
'enrollAccount',
|
||||
].forEach(routeName => AccountsTemplates.configureRoute(routeName));
|
||||
|
||||
|
||||
@@ -49,6 +49,14 @@ export const TYPE_LINKED_BOARD = 'cardType-linkedBoard';
|
||||
export const TYPE_LINKED_CARD = 'cardType-linkedCard';
|
||||
export const TYPE_TEMPLATE_BOARD = 'template-board';
|
||||
export const TYPE_TEMPLATE_CONTAINER = 'template-container';
|
||||
export const TYPE_TEMPLATE_CARD = 'template-card';
|
||||
export const TYPE_TEMPLATE_LIST = 'template-list';
|
||||
export const CARD_TYPES = [
|
||||
TYPE_CARD,
|
||||
TYPE_LINKED_CARD,
|
||||
TYPE_LINKED_BOARD,
|
||||
TYPE_TEMPLATE_CARD
|
||||
];
|
||||
export const ALLOWED_WAIT_SPINNERS = [
|
||||
'Bounce',
|
||||
'Cube',
|
||||
|
||||
+122
-45
@@ -4,6 +4,7 @@ import {
|
||||
OPERATOR_COMMENT,
|
||||
OPERATOR_CREATED_AT,
|
||||
OPERATOR_CREATOR,
|
||||
OPERATOR_DEBUG,
|
||||
OPERATOR_DUE,
|
||||
OPERATOR_HAS,
|
||||
OPERATOR_LABEL,
|
||||
@@ -11,9 +12,11 @@ import {
|
||||
OPERATOR_LIST,
|
||||
OPERATOR_MEMBER,
|
||||
OPERATOR_MODIFIED_AT,
|
||||
OPERATOR_ORG,
|
||||
OPERATOR_SORT,
|
||||
OPERATOR_STATUS,
|
||||
OPERATOR_SWIMLANE,
|
||||
OPERATOR_TEAM,
|
||||
OPERATOR_UNKNOWN,
|
||||
OPERATOR_USER,
|
||||
ORDER_ASCENDING,
|
||||
@@ -34,8 +37,10 @@ import {
|
||||
PREDICATE_OPEN,
|
||||
PREDICATE_OVERDUE,
|
||||
PREDICATE_PRIVATE,
|
||||
PREDICATE_PROJECTION,
|
||||
PREDICATE_PUBLIC,
|
||||
PREDICATE_QUARTER,
|
||||
PREDICATE_SELECTOR,
|
||||
PREDICATE_START_AT,
|
||||
PREDICATE_WEEK,
|
||||
PREDICATE_YEAR,
|
||||
@@ -43,6 +48,46 @@ import {
|
||||
import Boards from '../models/boards';
|
||||
import moment from 'moment';
|
||||
|
||||
export class QueryDebug {
|
||||
predicate = null;
|
||||
|
||||
constructor(predicate) {
|
||||
if (predicate) {
|
||||
this.set(predicate)
|
||||
}
|
||||
}
|
||||
|
||||
get() {
|
||||
return this.predicate;
|
||||
}
|
||||
|
||||
set(predicate) {
|
||||
if ([PREDICATE_ALL, PREDICATE_SELECTOR, PREDICATE_PROJECTION].includes(
|
||||
predicate
|
||||
)) {
|
||||
this.predicate = predicate;
|
||||
} else {
|
||||
this.predicate = null;
|
||||
}
|
||||
}
|
||||
|
||||
show() {
|
||||
return (this.predicate !== null);
|
||||
}
|
||||
|
||||
showAll() {
|
||||
return (this.predicate === PREDICATE_ALL);
|
||||
}
|
||||
|
||||
showSelector() {
|
||||
return (this.predicate === PREDICATE_ALL || this.predicate === PREDICATE_SELECTOR);
|
||||
}
|
||||
|
||||
showProjection() {
|
||||
return (this.predicate === PREDICATE_ALL || this.predicate === PREDICATE_PROJECTION);
|
||||
}
|
||||
}
|
||||
|
||||
export class QueryParams {
|
||||
text = '';
|
||||
|
||||
@@ -71,11 +116,14 @@ export class QueryParams {
|
||||
}
|
||||
|
||||
getPredicate(operator) {
|
||||
if (typeof this.params[operator] === 'object') {
|
||||
return this.params[operator][0];
|
||||
} else {
|
||||
return this.params[operator];
|
||||
if (this.hasOperator(operator)){
|
||||
if (typeof this.params[operator] === 'object') {
|
||||
return this.params[operator][0];
|
||||
} else {
|
||||
return this.params[operator];
|
||||
}
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
getPredicates(operator) {
|
||||
@@ -115,6 +163,8 @@ export class QueryErrors {
|
||||
[OPERATOR_ASSIGNEE, 'user-username-not-found'],
|
||||
[OPERATOR_MEMBER, 'user-username-not-found'],
|
||||
[OPERATOR_CREATOR, 'user-username-not-found'],
|
||||
[OPERATOR_ORG, 'org-name-not-found'],
|
||||
[OPERATOR_TEAM, 'team-name-not-found'],
|
||||
];
|
||||
|
||||
constructor() {
|
||||
@@ -196,6 +246,10 @@ export class Query {
|
||||
return this._errors.errors();
|
||||
}
|
||||
|
||||
addError(operator, error) {
|
||||
this._errors.addError(operator, error)
|
||||
}
|
||||
|
||||
errorMessages() {
|
||||
return this._errors.errorMessages();
|
||||
}
|
||||
@@ -213,6 +267,8 @@ export class Query {
|
||||
}
|
||||
|
||||
buildParams(queryText) {
|
||||
this.queryParams = new QueryParams();
|
||||
|
||||
queryText = queryText.trim();
|
||||
// eslint-disable-next-line no-console
|
||||
//console.log('query:', query);
|
||||
@@ -260,42 +316,51 @@ export class Query {
|
||||
'operator-has': OPERATOR_HAS,
|
||||
'operator-sort': OPERATOR_SORT,
|
||||
'operator-limit': OPERATOR_LIMIT,
|
||||
'operator-debug': OPERATOR_DEBUG,
|
||||
'operator-org': OPERATOR_ORG,
|
||||
'operator-team': OPERATOR_TEAM,
|
||||
};
|
||||
|
||||
const predicates = {
|
||||
due: {
|
||||
'predicate-overdue': PREDICATE_OVERDUE,
|
||||
},
|
||||
durations: {
|
||||
'predicate-week': PREDICATE_WEEK,
|
||||
'predicate-month': PREDICATE_MONTH,
|
||||
'predicate-quarter': PREDICATE_QUARTER,
|
||||
'predicate-year': PREDICATE_YEAR,
|
||||
},
|
||||
status: {
|
||||
'predicate-archived': PREDICATE_ARCHIVED,
|
||||
'predicate-all': PREDICATE_ALL,
|
||||
'predicate-open': PREDICATE_OPEN,
|
||||
'predicate-ended': PREDICATE_ENDED,
|
||||
'predicate-public': PREDICATE_PUBLIC,
|
||||
'predicate-private': PREDICATE_PRIVATE,
|
||||
},
|
||||
sorts: {
|
||||
'predicate-due': PREDICATE_DUE_AT,
|
||||
'predicate-created': PREDICATE_CREATED_AT,
|
||||
'predicate-modified': PREDICATE_MODIFIED_AT,
|
||||
},
|
||||
has: {
|
||||
'predicate-description': PREDICATE_DESCRIPTION,
|
||||
'predicate-checklist': PREDICATE_CHECKLIST,
|
||||
'predicate-attachment': PREDICATE_ATTACHMENT,
|
||||
'predicate-start': PREDICATE_START_AT,
|
||||
'predicate-end': PREDICATE_END_AT,
|
||||
'predicate-due': PREDICATE_DUE_AT,
|
||||
'predicate-assignee': PREDICATE_ASSIGNEES,
|
||||
'predicate-member': PREDICATE_MEMBERS,
|
||||
},
|
||||
};
|
||||
predicates[OPERATOR_DUE] = {
|
||||
'predicate-overdue': PREDICATE_OVERDUE,
|
||||
};
|
||||
predicates[OPERATOR_STATUS] = {
|
||||
'predicate-archived': PREDICATE_ARCHIVED,
|
||||
'predicate-all': PREDICATE_ALL,
|
||||
'predicate-open': PREDICATE_OPEN,
|
||||
'predicate-ended': PREDICATE_ENDED,
|
||||
'predicate-public': PREDICATE_PUBLIC,
|
||||
'predicate-private': PREDICATE_PRIVATE,
|
||||
};
|
||||
predicates[OPERATOR_SORT] = {
|
||||
'predicate-due': PREDICATE_DUE_AT,
|
||||
'predicate-created': PREDICATE_CREATED_AT,
|
||||
'predicate-modified': PREDICATE_MODIFIED_AT,
|
||||
};
|
||||
predicates[OPERATOR_HAS] = {
|
||||
'predicate-description': PREDICATE_DESCRIPTION,
|
||||
'predicate-checklist': PREDICATE_CHECKLIST,
|
||||
'predicate-attachment': PREDICATE_ATTACHMENT,
|
||||
'predicate-start': PREDICATE_START_AT,
|
||||
'predicate-end': PREDICATE_END_AT,
|
||||
'predicate-due': PREDICATE_DUE_AT,
|
||||
'predicate-assignee': PREDICATE_ASSIGNEES,
|
||||
'predicate-member': PREDICATE_MEMBERS,
|
||||
};
|
||||
predicates[OPERATOR_DEBUG] = {
|
||||
'predicate-all': PREDICATE_ALL,
|
||||
'predicate-selector': PREDICATE_SELECTOR,
|
||||
'predicate-projection': PREDICATE_PROJECTION,
|
||||
};
|
||||
|
||||
const predicateTranslations = {};
|
||||
Object.entries(predicates).forEach(([category, catPreds]) => {
|
||||
predicateTranslations[category] = {};
|
||||
@@ -403,7 +468,7 @@ export class Query {
|
||||
value: moment().format('YYYY-MM-DD'),
|
||||
};
|
||||
} else {
|
||||
this.errors.addError(OPERATOR_DUE, {
|
||||
this.addError(OPERATOR_DUE, {
|
||||
tag: 'operator-number-expected',
|
||||
value: { operator: op, value },
|
||||
});
|
||||
@@ -431,27 +496,27 @@ export class Query {
|
||||
value = m.groups.operator;
|
||||
negated = true;
|
||||
}
|
||||
if (!predicateTranslations.sorts[value]) {
|
||||
this.errors.addError(OPERATOR_SORT, {
|
||||
if (!predicateTranslations[OPERATOR_SORT][value]) {
|
||||
this.addError(OPERATOR_SORT, {
|
||||
tag: 'operator-sort-invalid',
|
||||
value,
|
||||
});
|
||||
continue;
|
||||
} else {
|
||||
value = {
|
||||
name: predicateTranslations.sorts[value],
|
||||
name: predicateTranslations[OPERATOR_SORT][value],
|
||||
order: negated ? ORDER_DESCENDING : ORDER_ASCENDING,
|
||||
};
|
||||
}
|
||||
} else if (operator === OPERATOR_STATUS) {
|
||||
if (!predicateTranslations.status[value]) {
|
||||
this.errors.addError(OPERATOR_STATUS, {
|
||||
if (!predicateTranslations[OPERATOR_STATUS][value]) {
|
||||
this.addError(OPERATOR_STATUS, {
|
||||
tag: 'operator-status-invalid',
|
||||
value,
|
||||
});
|
||||
continue;
|
||||
} else {
|
||||
value = predicateTranslations.status[value];
|
||||
value = predicateTranslations[OPERATOR_STATUS][value];
|
||||
}
|
||||
} else if (operator === OPERATOR_HAS) {
|
||||
let negated = false;
|
||||
@@ -460,22 +525,22 @@ export class Query {
|
||||
value = m.groups.operator;
|
||||
negated = true;
|
||||
}
|
||||
if (!predicateTranslations.has[value]) {
|
||||
this.errors.addError(OPERATOR_HAS, {
|
||||
if (!predicateTranslations[OPERATOR_HAS][value]) {
|
||||
this.addError(OPERATOR_HAS, {
|
||||
tag: 'operator-has-invalid',
|
||||
value,
|
||||
});
|
||||
continue;
|
||||
} else {
|
||||
value = {
|
||||
field: predicateTranslations.has[value],
|
||||
field: predicateTranslations[OPERATOR_HAS][value],
|
||||
exists: !negated,
|
||||
};
|
||||
}
|
||||
} else if (operator === OPERATOR_LIMIT) {
|
||||
const limit = parseInt(value, 10);
|
||||
if (isNaN(limit) || limit < 1) {
|
||||
this.errors.addError(OPERATOR_LIMIT, {
|
||||
this.addError(OPERATOR_LIMIT, {
|
||||
tag: 'operator-limit-invalid',
|
||||
value,
|
||||
});
|
||||
@@ -483,11 +548,21 @@ export class Query {
|
||||
} else {
|
||||
value = limit;
|
||||
}
|
||||
} else if (operator === OPERATOR_DEBUG) {
|
||||
if (!predicateTranslations[OPERATOR_DEBUG][value]) {
|
||||
this.addError(OPERATOR_DEBUG, {
|
||||
tag: 'operator-debug-invalid',
|
||||
value,
|
||||
});
|
||||
continue;
|
||||
} else {
|
||||
value = predicateTranslations[OPERATOR_DEBUG][value];
|
||||
}
|
||||
}
|
||||
|
||||
this.queryParams.addPredicate(operator, value);
|
||||
} else {
|
||||
this.errors.addError(OPERATOR_UNKNOWN, {
|
||||
this.addError(OPERATOR_UNKNOWN, {
|
||||
tag: 'operator-unknown-error',
|
||||
value: op,
|
||||
});
|
||||
@@ -509,11 +584,13 @@ export class Query {
|
||||
}
|
||||
}
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
// console.log('text:', text);
|
||||
this.queryParams.text = text;
|
||||
|
||||
// eslint-disable-next-line no-console
|
||||
//console.log('queryParams:', this.queryParams);
|
||||
if (this.queryParams.hasOperator(OPERATOR_DEBUG)) {
|
||||
// eslint-disable-next-line no-console
|
||||
console.log('text:', this.queryParams.text);
|
||||
console.log('queryParams:', this.queryParams);
|
||||
}
|
||||
}
|
||||
}
|
||||
+42
-9
@@ -12,7 +12,8 @@ FlowRouter.route('/', {
|
||||
Session.set('currentBoard', null);
|
||||
Session.set('currentList', null);
|
||||
Session.set('currentCard', null);
|
||||
Session.set('popupCard', null);
|
||||
Session.set('popupCardId', null);
|
||||
Session.set('popupCardBoardId', null);
|
||||
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
@@ -35,7 +36,8 @@ FlowRouter.route('/public', {
|
||||
Session.set('currentBoard', null);
|
||||
Session.set('currentList', null);
|
||||
Session.set('currentCard', null);
|
||||
Session.set('popupCard', null);
|
||||
Session.set('popupCardId', null);
|
||||
Session.set('popupCardBoardId', null);
|
||||
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
@@ -58,7 +60,8 @@ FlowRouter.route('/b/:id/:slug', {
|
||||
const previousBoard = Session.get('currentBoard');
|
||||
Session.set('currentBoard', currentBoard);
|
||||
Session.set('currentCard', null);
|
||||
Session.set('popupCard', null);
|
||||
Session.set('popupCardId', null);
|
||||
Session.set('popupCardBoardId', null);
|
||||
|
||||
// If we close a card, we'll execute again this route action but we don't
|
||||
// want to excape every current actions (filters, etc.)
|
||||
@@ -87,7 +90,8 @@ FlowRouter.route('/b/:boardId/:slug/:cardId', {
|
||||
|
||||
Session.set('currentBoard', params.boardId);
|
||||
Session.set('currentCard', params.cardId);
|
||||
Session.set('popupCard', null);
|
||||
Session.set('popupCardId', null);
|
||||
Session.set('popupCardBoardId', null);
|
||||
|
||||
Utils.manageCustomUI();
|
||||
Utils.manageMatomo();
|
||||
@@ -120,6 +124,30 @@ FlowRouter.route('/shortcuts', {
|
||||
},
|
||||
});
|
||||
|
||||
FlowRouter.route('/b/templates', {
|
||||
name: 'template-container',
|
||||
triggersEnter: [AccountsTemplates.ensureSignedIn],
|
||||
action() {
|
||||
Session.set('currentBoard', null);
|
||||
Session.set('currentList', null);
|
||||
Session.set('currentCard', null);
|
||||
Session.set('popupCardId', null);
|
||||
Session.set('popupCardBoardId', null);
|
||||
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
EscapeActions.executeAll();
|
||||
|
||||
Utils.manageCustomUI();
|
||||
Utils.manageMatomo();
|
||||
|
||||
BlazeLayout.render('defaultLayout', {
|
||||
headerBar: 'boardListHeaderBar',
|
||||
content: 'boardList',
|
||||
});
|
||||
},
|
||||
});
|
||||
|
||||
FlowRouter.route('/my-cards', {
|
||||
name: 'my-cards',
|
||||
triggersEnter: [AccountsTemplates.ensureSignedIn],
|
||||
@@ -216,7 +244,8 @@ FlowRouter.route('/import/:source', {
|
||||
Session.set('currentBoard', null);
|
||||
Session.set('currentList', null);
|
||||
Session.set('currentCard', null);
|
||||
Session.set('popupCard', null);
|
||||
Session.set('popupCardId', null);
|
||||
Session.set('popupCardBoardId', null);
|
||||
Session.set('importSource', params.source);
|
||||
|
||||
Filter.reset();
|
||||
@@ -237,7 +266,8 @@ FlowRouter.route('/setting', {
|
||||
Session.set('currentBoard', null);
|
||||
Session.set('currentList', null);
|
||||
Session.set('currentCard', null);
|
||||
Session.set('popupCard', null);
|
||||
Session.set('popupCardId', null);
|
||||
Session.set('popupCardBoardId', null);
|
||||
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
@@ -261,7 +291,8 @@ FlowRouter.route('/information', {
|
||||
Session.set('currentBoard', null);
|
||||
Session.set('currentList', null);
|
||||
Session.set('currentCard', null);
|
||||
Session.set('popupCard', null);
|
||||
Session.set('popupCardId', null);
|
||||
Session.set('popupCardBoardId', null);
|
||||
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
@@ -284,7 +315,8 @@ FlowRouter.route('/people', {
|
||||
Session.set('currentBoard', null);
|
||||
Session.set('currentList', null);
|
||||
Session.set('currentCard', null);
|
||||
Session.set('popupCard', null);
|
||||
Session.set('popupCardId', null);
|
||||
Session.set('popupCardBoardId', null);
|
||||
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
@@ -307,7 +339,8 @@ FlowRouter.route('/admin-reports', {
|
||||
Session.set('currentBoard', null);
|
||||
Session.set('currentList', null);
|
||||
Session.set('currentCard', null);
|
||||
Session.set('popupCard', null);
|
||||
Session.set('popupCardId', null);
|
||||
Session.set('popupCardBoardId', null);
|
||||
|
||||
Filter.reset();
|
||||
Session.set('sortBy', '');
|
||||
|
||||
@@ -3,6 +3,7 @@ export const OPERATOR_ASSIGNEE = 'assignees';
|
||||
export const OPERATOR_COMMENT = 'comment';
|
||||
export const OPERATOR_CREATED_AT = 'createdAt';
|
||||
export const OPERATOR_CREATOR = 'userId';
|
||||
export const OPERATOR_DEBUG = 'debug';
|
||||
export const OPERATOR_DUE = 'dueAt';
|
||||
export const OPERATOR_BOARD = 'board';
|
||||
export const OPERATOR_HAS = 'has';
|
||||
@@ -11,9 +12,11 @@ export const OPERATOR_LIMIT = 'limit';
|
||||
export const OPERATOR_LIST = 'list';
|
||||
export const OPERATOR_MEMBER = 'members';
|
||||
export const OPERATOR_MODIFIED_AT = 'modifiedAt';
|
||||
export const OPERATOR_ORG = 'org';
|
||||
export const OPERATOR_SORT = 'sort';
|
||||
export const OPERATOR_STATUS = 'status';
|
||||
export const OPERATOR_SWIMLANE = 'swimlane';
|
||||
export const OPERATOR_TEAM = 'team';
|
||||
export const OPERATOR_UNKNOWN = 'unknown';
|
||||
export const OPERATOR_USER = 'user';
|
||||
export const ORDER_ASCENDING = 'asc';
|
||||
@@ -33,9 +36,11 @@ export const PREDICATE_MODIFIED_AT = 'modifiedAt';
|
||||
export const PREDICATE_MONTH = 'month';
|
||||
export const PREDICATE_OPEN = 'open';
|
||||
export const PREDICATE_OVERDUE = 'overdue';
|
||||
export const PREDICATE_PROJECTION = 'projection';
|
||||
export const PREDICATE_PRIVATE = 'private';
|
||||
export const PREDICATE_PUBLIC = 'public';
|
||||
export const PREDICATE_QUARTER = 'quarter';
|
||||
export const PREDICATE_SELECTOR = 'selector';
|
||||
export const PREDICATE_START_AT = 'startAt';
|
||||
export const PREDICATE_SYSTEM = 'system';
|
||||
export const PREDICATE_WEEK = 'week';
|
||||
|
||||
@@ -174,6 +174,12 @@ services:
|
||||
#- MAIL_SERVICE_USER=firstname.lastname@hotmail.com
|
||||
#- MAIL_SERVICE_PASSWORD=SecretPassword
|
||||
#---------------------------------------------------------------
|
||||
# https://github.com/wekan/wekan/issues/3585#issuecomment-1021522132
|
||||
# Add more Node heap, this is done by default at Dockerfile:
|
||||
# - NODE_OPTIONS="--max_old_space_size=4096"
|
||||
# Add more stack, this is done at Dockerfile:
|
||||
# bash -c "ulimit -s 65500; exec node --stack-size=65500 main.js"
|
||||
#---------------------------------------------------------------
|
||||
# ==== OPTIONAL: MONGO OPLOG SETTINGS =====
|
||||
# https://github.com/wekan/wekan-mongodb/issues/2#issuecomment-378343587
|
||||
# We've fixed our CPU usage problem today with an environment
|
||||
@@ -236,6 +242,11 @@ services:
|
||||
#- ACCOUNTS_LOCKOUT_UNKNOWN_USERS_LOCKOUT_PERIOD=60
|
||||
#- ACCOUNTS_LOCKOUT_UNKNOWN_USERS_FAILURE_WINDOW=15
|
||||
#---------------------------------------------------------------
|
||||
# ==== ACCOUNT OPTIONS ====
|
||||
# https://docs.meteor.com/api/accounts-multi.html#AccountsCommon-config
|
||||
# Defaults below. Uncomment to change. wekan/server/accounts-common.js
|
||||
# - ACCOUNTS_COMMON_LOGIN_EXPIRATION_IN_DAYS=90
|
||||
#---------------------------------------------------------------
|
||||
# ==== STORE ATTACHMENT ON SERVER FILESYSTEM INSTEAD OF MONGODB ====
|
||||
# https://github.com/wekan/wekan/pull/2603
|
||||
#- ATTACHMENTS_STORE_PATH = <pathname> # pathname can be relative or fullpath
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
apiVersion: v2
|
||||
appVersion: "5.75"
|
||||
appVersion: "6.09"
|
||||
dependencies:
|
||||
- condition: mongodb.enabled
|
||||
name: mongodb
|
||||
@@ -21,4 +21,4 @@ name: wekan
|
||||
sources:
|
||||
- https://github.com/wekan/wekan
|
||||
type: application
|
||||
version: 1.1.0
|
||||
version: 1.1.1
|
||||
+48
-11
@@ -1,12 +1,38 @@
|
||||
# Helm Chart for Wekan
|
||||
# WeKan ® - Open Source kanban
|
||||
|
||||
## Installing the Chart
|
||||
|
||||
To install the chart with the release name `my-release`:
|
||||
|
||||
```bash
|
||||
helm repo add wekan https://wekan.github.io/charts
|
||||
helm install my-release wekan/wekan
|
||||
```
|
||||
|
||||
These commands deploy Wekan on the Kubernetes cluster in the default configuration.
|
||||
|
||||
Tip: List all releases using `helm list`
|
||||
|
||||
For all available values see `helm show values wekan/wekan`.
|
||||
|
||||
## Uninstalling the Chart
|
||||
|
||||
To uninstall/delete the my-release deployment:
|
||||
|
||||
```bash
|
||||
helm delete my-release
|
||||
```
|
||||
|
||||
The command removes all the Kubernetes components associated with the chart and
|
||||
deletes the release.
|
||||
|
||||
## Features
|
||||
|
||||
o Uses a MongoDB replica set by default - this allows fault-tolerant
|
||||
* Uses a MongoDB replica set by default - this allows fault-tolerant
|
||||
and scalable MongoDB deployment (or just set the replicas to 1 for
|
||||
a single server install)
|
||||
|
||||
o Optional Horizontal Pod Autoscaler (HPA), so that your Wekan pods
|
||||
* Optional Horizontal Pod Autoscaler (HPA), so that your Wekan pods
|
||||
will scale automatically with increased CPU load.
|
||||
|
||||
## The configurable values (values.yaml)
|
||||
@@ -19,7 +45,9 @@ Scaling Wekan:
|
||||
|
||||
replicaCount: 1
|
||||
```
|
||||
**replicaCount** Will set the initial number of replicas for the Wekan pod (and container)
|
||||
|
||||
**replicaCount** will set the initial number of replicas for the Wekan pod
|
||||
(and container)
|
||||
|
||||
```yaml
|
||||
## Configure an horizontal pod autoscaler
|
||||
@@ -34,13 +62,17 @@ autoscaling:
|
||||
##
|
||||
targetCPUUtilizationPercentage: 80
|
||||
```
|
||||
This section (if *enabled* is set to **true**) will enable the Kubernetes Horizontal Pod Autoscaler (HPA).
|
||||
|
||||
**minReplicas:** this is the minimum number of pods to scale down to (We recommend setting this to the same value as **replicaCount**).
|
||||
This section (if *enabled* is set to **true**) will enable the Kubernetes
|
||||
Horizontal Pod Autoscaler (HPA).
|
||||
|
||||
**minReplicas:** this is the minimum number of pods to scale down to
|
||||
(We recommend setting this to the same value as **replicaCount**).
|
||||
|
||||
**maxReplicas:** this is the maximum number of pods to scale up to.
|
||||
|
||||
**targetCPUUtilizationPercentage:** This is the CPU at which the HPA will scale-out the number of Wekan pods.
|
||||
**targetCPUUtilizationPercentage:** This is the CPU at which the HPA will
|
||||
scale-out the number of Wekan pods.
|
||||
|
||||
```yaml
|
||||
mongodb-replicaset:
|
||||
@@ -55,11 +87,16 @@ mongodb-replicaset:
|
||||
|
||||
This section controls the scale of the MongoDB redundant Replica Set.
|
||||
|
||||
**replicas:** This is the number of MongoDB instances to include in the set. You can set this to 1 for a single server - this will still allow you to scale-up later with a helm upgrade.
|
||||
**replicas:** This is the number of MongoDB instances to include in the set.
|
||||
You can set this to 1 for a single server - this will still allow you to
|
||||
scale-up later with a helm upgrade.
|
||||
|
||||
### Install OCP route
|
||||
If you use this chart to deploy Wekan on an OCP cluster, you can create route instead of ingress with following command:
|
||||
|
||||
``` bash
|
||||
$ helm template --set route.enabled=true,ingress.enabled=false values.yaml . | oc apply -f-
|
||||
If you use this chart to deploy Wekan on an OCP cluster, you can create route
|
||||
instead of ingress with following command:
|
||||
|
||||
```bash
|
||||
helm template --set route.enabled=true,ingress.enabled=false values.yaml . | \
|
||||
oc apply -f-
|
||||
```
|
||||
@@ -1 +0,0 @@
|
||||
|
||||
@@ -2,7 +2,8 @@
|
||||
{{- $fullName := include "wekan.fullname" . -}}
|
||||
{{- $servicePort := .Values.service.port -}}
|
||||
{{- $ingressPath := .Values.ingress.path -}}
|
||||
apiVersion: networking.k8s.io/v1beta1
|
||||
{{- $ingressPathType := .Values.ingress.pathtype -}}
|
||||
apiVersion: networking.k8s.io/v1
|
||||
kind: Ingress
|
||||
metadata:
|
||||
name: {{ $fullName }}
|
||||
@@ -27,17 +28,17 @@ spec:
|
||||
secretName: {{ .secretName }}
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
backend:
|
||||
serviceName: {{ $fullName }}
|
||||
servicePort: 8080
|
||||
rules:
|
||||
{{- range .Values.ingress.hosts }}
|
||||
- host: {{ . }}
|
||||
http:
|
||||
paths:
|
||||
- path: {{ $ingressPath }}
|
||||
pathType: {{ $ingressPathType }}
|
||||
backend:
|
||||
serviceName: {{ $fullName }}
|
||||
servicePort: 8080
|
||||
service:
|
||||
name: {{ $fullName }}
|
||||
port:
|
||||
number: 8080
|
||||
{{- end }}
|
||||
{{- end }}
|
||||
@@ -0,0 +1,19 @@
|
||||
apiVersion: v1
|
||||
kind: Pod
|
||||
metadata:
|
||||
name: "{{ template "wekan.fullname" . }}-test-http"
|
||||
labels:
|
||||
app: {{ template "wekan.name" . }}
|
||||
chart: {{ template "wekan.chart" . }}
|
||||
component: wekan
|
||||
release: {{ .Release.Name }}
|
||||
heritage: {{ .Release.Service }}
|
||||
annotations:
|
||||
"helm.sh/hook": test
|
||||
spec:
|
||||
containers:
|
||||
- name: wget
|
||||
image: busybox
|
||||
command: ['wget', '-O', '/dev/stdout']
|
||||
args: ['{{ template "wekan.fullname" . }}:{{ .Values.service.port }}']
|
||||
restartPolicy: Never
|
||||
@@ -14,7 +14,7 @@ serviceAccounts:
|
||||
##
|
||||
image:
|
||||
repository: quay.io/wekan/wekan
|
||||
tag: v5.75
|
||||
tag: v6.09
|
||||
pullPolicy: IfNotPresent
|
||||
|
||||
## Configuration for wekan component
|
||||
@@ -56,6 +56,7 @@ ingress:
|
||||
# kubernetes.io/ingress.class: nginx
|
||||
# kubernetes.io/tls-acme: "true"
|
||||
path: /*
|
||||
pathtype: ImplementationSpecific
|
||||
# This must match 'endpoint', unless your client supports different
|
||||
# hostnames.
|
||||
hosts: [ wekan.local ]
|
||||
|
||||
+36
-2
@@ -96,6 +96,7 @@
|
||||
"add-members": "Add Members",
|
||||
"added": "Added",
|
||||
"addMemberPopup-title": "Members",
|
||||
"memberPopup-title": "Member Settings",
|
||||
"admin": "Admin",
|
||||
"admin-desc": "Can view and edit cards, remove members, and change settings for the board.",
|
||||
"admin-announcement": "Announcement",
|
||||
@@ -106,6 +107,7 @@
|
||||
"and-n-other-card_plural": "And __count__ other cards",
|
||||
"apply": "Apply",
|
||||
"app-is-offline": "Loading, please wait. Refreshing the page will cause data loss. If loading does not work, please check that server has not stopped.",
|
||||
"app-try-reconnect": "Try to reconnect.",
|
||||
"archive": "Move to Archive",
|
||||
"archive-all": "Move All to Archive",
|
||||
"archive-board": "Move Board to Archive",
|
||||
@@ -279,8 +281,10 @@
|
||||
"worker-desc": "Can only move cards, assign itself to card and comment.",
|
||||
"computer": "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?",
|
||||
"confirm-checklist-delete-popup": "Are you sure you want to delete the checklist?",
|
||||
"checklistDeletePopup-title": "Delete Checklist?",
|
||||
"copy-card-link-to-clipboard": "Copy card link to clipboard",
|
||||
"copy-text-to-clipboard": "Copy text to clipboard",
|
||||
"linkCardPopup-title": "Link Card",
|
||||
"searchElementPopup-title": "Search",
|
||||
"copyCardPopup-title": "Copy Card",
|
||||
@@ -567,6 +571,8 @@
|
||||
"has-spenttime-cards": "Has spent time cards",
|
||||
"time": "Time",
|
||||
"title": "Title",
|
||||
"toggle-labels": "Toggle labels 1-9 for card. Multi-Selection adds labels 1-9",
|
||||
"remove-labels-multiselect": "Multi-Selection removes labels 1-9",
|
||||
"tracking": "Tracking",
|
||||
"tracking-info": "You will be notified of any changes to those cards you are involved as creator or member.",
|
||||
"type": "Type",
|
||||
@@ -606,6 +612,7 @@
|
||||
"people": "People",
|
||||
"registration": "Registration",
|
||||
"disable-self-registration": "Disable Self-Registration",
|
||||
"disable-forgot-password": "Disable Forgot Password",
|
||||
"invite": "Invite",
|
||||
"invite-people": "Invite People",
|
||||
"to-boards": "To board(s)",
|
||||
@@ -938,6 +945,8 @@
|
||||
"label-color-not-found": "Label color %s not found.",
|
||||
"user-username-not-found": "Username '%s' not found.",
|
||||
"comment-not-found": "Card with comment containing text '%s' not found.",
|
||||
"org-name-not-found": "Organization '%s' not found.",
|
||||
"team-name-not-found": "Team '%s' not found.",
|
||||
"globalSearch-title": "Search All Boards",
|
||||
"no-cards-found": "No Cards Found",
|
||||
"one-card-found": "One Card Found",
|
||||
@@ -966,6 +975,9 @@
|
||||
"operator-comment": "comment",
|
||||
"operator-has": "has",
|
||||
"operator-limit": "limit",
|
||||
"operator-debug": "debug",
|
||||
"operator-org": "org",
|
||||
"operator-team": "team",
|
||||
"predicate-archived": "archived",
|
||||
"predicate-open": "open",
|
||||
"predicate-ended": "ended",
|
||||
@@ -987,12 +999,15 @@
|
||||
"predicate-member": "member",
|
||||
"predicate-public": "public",
|
||||
"predicate-private": "private",
|
||||
"predicate-selector": "selector",
|
||||
"predicate-projection": "projection",
|
||||
"operator-unknown-error": "%s is not an operator",
|
||||
"operator-number-expected": "operator __operator__ expected a number, got '__value__'",
|
||||
"operator-sort-invalid": "sort of '%s' is invalid",
|
||||
"operator-status-invalid": "'%s' is not a valid status",
|
||||
"operator-has-invalid": "%s is not a valid existence check",
|
||||
"operator-limit-invalid": "%s is not a valid limit. Limit should be a positive integer.",
|
||||
"operator-debug-invalid": "%s is not a valid debug predicate",
|
||||
"next-page": "Next Page",
|
||||
"previous-page": "Previous Page",
|
||||
"heading-notes": "Notes",
|
||||
@@ -1010,6 +1025,8 @@
|
||||
"globalSearch-instructions-operator-member": "`__operator_member__:<username>` - cards where *<username>* is a *member*",
|
||||
"globalSearch-instructions-operator-assignee": "`__operator_assignee__:<username>` - cards where *<username>* is an *assignee*",
|
||||
"globalSearch-instructions-operator-creator": "`__operator_creator__:<username>` - cards where *<username>* is the card's creator",
|
||||
"globalSearch-instructions-operator-org": "`__operator_org__:<display name|short name>` - cards belonging to a board assigned to organization *<name>*",
|
||||
"globalSearch-instructions-operator-team": "`__operator_team__:<display name|short name>` - cards belonging to a board assigned to team *<name>*",
|
||||
"globalSearch-instructions-operator-due": "`__operator_due__:<n>` - cards which are due up to *<n>* days from now. `__operator_due__:__predicate_overdue__ lists all cards past their due date.",
|
||||
"globalSearch-instructions-operator-created": "`__operator_created__:<n>` - cards which were created *<n>* days ago or less",
|
||||
"globalSearch-instructions-operator-modified": "`__operator_modified__:<n>` - cards which were modified *<n>* days ago or less",
|
||||
@@ -1056,6 +1073,8 @@
|
||||
"orphanedFilesReportTitle": "Orphaned Files Report",
|
||||
"reports": "Reports",
|
||||
"rulesReportTitle": "Rules Report",
|
||||
"boardsReportTitle": "Boards Report",
|
||||
"cardsReportTitle": "Cards Report",
|
||||
"copy-swimlane": "Copy Swimlane",
|
||||
"copySwimlanePopup-title": "Copy Swimlane",
|
||||
"display-card-creator": "Display Card Creator",
|
||||
@@ -1113,5 +1132,20 @@
|
||||
"Node_memory_usage_rss": "Node memory usage: resident set size",
|
||||
"Node_memory_usage_heap_total": "Node memory usage: total size of the allocated heap",
|
||||
"Node_memory_usage_heap_used": "Node memory usage: actual memory used",
|
||||
"Node_memory_usage_external": "Node memory usage: external"
|
||||
"Node_memory_usage_external": "Node memory usage: external",
|
||||
"add-organizations": "Add organizations",
|
||||
"add-organizations-label": "Added organizations are displayed below:",
|
||||
"remove-organization-from-board": "Are you sure you want to remove this organization from this board ?",
|
||||
"to-create-organizations-contact-admin": "To create organizations, please contact administrator.",
|
||||
"custom-legal-notice-link-url": "Custom legal notice page URL",
|
||||
"acceptance_of_our_legalNotice": "By continuing, you accept our",
|
||||
"legalNotice": "legal notice",
|
||||
"copied": "Copied!",
|
||||
"checklistActionsPopup-title": "Checklist Actions",
|
||||
"moveChecklist": "Move Checklist",
|
||||
"moveChecklistPopup-title": "Move Checklist",
|
||||
"newlineBecomesNewChecklistItem": "Newline becomes new checklist item",
|
||||
"copyChecklist": "Copy Checklist",
|
||||
"copyChecklistPopup-title": "Copy Checklist",
|
||||
"card-show-lists": "Card Show Lists"
|
||||
}
|
||||
+36
-2
@@ -96,6 +96,7 @@
|
||||
"add-members": "إضافة أعضاء",
|
||||
"added": "أُضيف",
|
||||
"addMemberPopup-title": "الأعضاء",
|
||||
"memberPopup-title": "أفضليات الأعضاء",
|
||||
"admin": "المدير",
|
||||
"admin-desc": "إمكانية مشاهدة و تعديل و حذف أعضاء ، و تعديل إعدادات اللوحة أيضا.",
|
||||
"admin-announcement": "إعلان",
|
||||
@@ -106,6 +107,7 @@
|
||||
"and-n-other-card_plural": "And __count__ other بطاقات",
|
||||
"apply": "طبق",
|
||||
"app-is-offline": "Loading, please wait. Refreshing the page will cause data loss. If loading does not work, please check that server has not stopped.",
|
||||
"app-try-reconnect": "Try to reconnect.",
|
||||
"archive": "نقل الى الارشيف",
|
||||
"archive-all": "نقل الكل الى الارشيف",
|
||||
"archive-board": "نقل اللوح الى الارشيف",
|
||||
@@ -279,8 +281,10 @@
|
||||
"worker-desc": "Can only move cards, assign itself to card and comment.",
|
||||
"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?",
|
||||
"confirm-checklist-delete-popup": "Are you sure you want to delete the checklist?",
|
||||
"checklistDeletePopup-title": "Delete Checklist?",
|
||||
"copy-card-link-to-clipboard": "نسخ رابط البطاقة إلى الحافظة",
|
||||
"copy-text-to-clipboard": "Copy text to clipboard",
|
||||
"linkCardPopup-title": "ربط البطاقة",
|
||||
"searchElementPopup-title": "بحث",
|
||||
"copyCardPopup-title": "نسخ البطاقة",
|
||||
@@ -567,6 +571,8 @@
|
||||
"has-spenttime-cards": "Has spent time cards",
|
||||
"time": "الوقت",
|
||||
"title": "عنوان",
|
||||
"toggle-labels": "Toggle labels 1-9 for card. Multi-Selection adds labels 1-9",
|
||||
"remove-labels-multiselect": "Multi-Selection removes labels 1-9",
|
||||
"tracking": "تتبع",
|
||||
"tracking-info": "You will be notified of any changes to those cards you are involved as creator or member.",
|
||||
"type": "النوع",
|
||||
@@ -606,6 +612,7 @@
|
||||
"people": "الناس",
|
||||
"registration": "تسجيل",
|
||||
"disable-self-registration": "Disable Self-Registration",
|
||||
"disable-forgot-password": "Disable Forgot Password",
|
||||
"invite": "دعوة",
|
||||
"invite-people": "الناس المدعوين",
|
||||
"to-boards": "إلى اللوحات",
|
||||
@@ -938,6 +945,8 @@
|
||||
"label-color-not-found": "Label color %s not found.",
|
||||
"user-username-not-found": "Username '%s' not found.",
|
||||
"comment-not-found": "Card with comment containing text '%s' not found.",
|
||||
"org-name-not-found": "Organization '%s' not found.",
|
||||
"team-name-not-found": "Team '%s' not found.",
|
||||
"globalSearch-title": "Search All Boards",
|
||||
"no-cards-found": "No Cards Found",
|
||||
"one-card-found": "One Card Found",
|
||||
@@ -966,6 +975,9 @@
|
||||
"operator-comment": "comment",
|
||||
"operator-has": "has",
|
||||
"operator-limit": "limit",
|
||||
"operator-debug": "debug",
|
||||
"operator-org": "org",
|
||||
"operator-team": "team",
|
||||
"predicate-archived": "archived",
|
||||
"predicate-open": "open",
|
||||
"predicate-ended": "ended",
|
||||
@@ -987,12 +999,15 @@
|
||||
"predicate-member": "member",
|
||||
"predicate-public": "public",
|
||||
"predicate-private": "private",
|
||||
"predicate-selector": "selector",
|
||||
"predicate-projection": "projection",
|
||||
"operator-unknown-error": "%s is not an operator",
|
||||
"operator-number-expected": "operator __operator__ expected a number, got '__value__'",
|
||||
"operator-sort-invalid": "sort of '%s' is invalid",
|
||||
"operator-status-invalid": "'%s' is not a valid status",
|
||||
"operator-has-invalid": "%s is not a valid existence check",
|
||||
"operator-limit-invalid": "%s is not a valid limit. Limit should be a positive integer.",
|
||||
"operator-debug-invalid": "%s is not a valid debug predicate",
|
||||
"next-page": "Next Page",
|
||||
"previous-page": "Previous Page",
|
||||
"heading-notes": "Notes",
|
||||
@@ -1010,6 +1025,8 @@
|
||||
"globalSearch-instructions-operator-member": "`__operator_member__:<username>` - cards where *<username>* is a *member*",
|
||||
"globalSearch-instructions-operator-assignee": "`__operator_assignee__:<username>` - cards where *<username>* is an *assignee*",
|
||||
"globalSearch-instructions-operator-creator": "`__operator_creator__:<username>` - cards where *<username>* is the card's creator",
|
||||
"globalSearch-instructions-operator-org": "`__operator_org__:<display name|short name>` - cards belonging to a board assigned to organization *<name>*",
|
||||
"globalSearch-instructions-operator-team": "`__operator_team__:<display name|short name>` - cards belonging to a board assigned to team *<name>*",
|
||||
"globalSearch-instructions-operator-due": "`__operator_due__:<n>` - cards which are due up to *<n>* days from now. `__operator_due__:__predicate_overdue__ lists all cards past their due date.",
|
||||
"globalSearch-instructions-operator-created": "`__operator_created__:<n>` - cards which were created *<n>* days ago or less",
|
||||
"globalSearch-instructions-operator-modified": "`__operator_modified__:<n>` - cards which were modified *<n>* days ago or less",
|
||||
@@ -1056,6 +1073,8 @@
|
||||
"orphanedFilesReportTitle": "تقارير الملفات المعزولة",
|
||||
"reports": "تقارير",
|
||||
"rulesReportTitle": "Rules Report",
|
||||
"boardsReportTitle": "Boards Report",
|
||||
"cardsReportTitle": "Cards Report",
|
||||
"copy-swimlane": "Copy Swimlane",
|
||||
"copySwimlanePopup-title": "Copy Swimlane",
|
||||
"display-card-creator": "Display Card Creator",
|
||||
@@ -1113,5 +1132,20 @@
|
||||
"Node_memory_usage_rss": "Node memory usage: resident set size",
|
||||
"Node_memory_usage_heap_total": "Node memory usage: total size of the allocated heap",
|
||||
"Node_memory_usage_heap_used": "Node memory usage: actual memory used",
|
||||
"Node_memory_usage_external": "Node memory usage: external"
|
||||
"Node_memory_usage_external": "Node memory usage: external",
|
||||
"add-organizations": "Add organizations",
|
||||
"add-organizations-label": "Added organizations are displayed below:",
|
||||
"remove-organization-from-board": "Are you sure you want to remove this organization from this board ?",
|
||||
"to-create-organizations-contact-admin": "To create organizations, please contact administrator.",
|
||||
"custom-legal-notice-link-url": "Custom legal notice page URL",
|
||||
"acceptance_of_our_legalNotice": "By continuing, you accept our",
|
||||
"legalNotice": "legal notice",
|
||||
"copied": "Copied!",
|
||||
"checklistActionsPopup-title": "Checklist Actions",
|
||||
"moveChecklist": "Move Checklist",
|
||||
"moveChecklistPopup-title": "Move Checklist",
|
||||
"newlineBecomesNewChecklistItem": "Newline becomes new checklist item",
|
||||
"copyChecklist": "Copy Checklist",
|
||||
"copyChecklistPopup-title": "Copy Checklist",
|
||||
"card-show-lists": "Card Show Lists"
|
||||
}
|
||||
+36
-2
@@ -96,6 +96,7 @@
|
||||
"add-members": "Добави членове",
|
||||
"added": "Добавено",
|
||||
"addMemberPopup-title": "Членове",
|
||||
"memberPopup-title": "Настройки на профила",
|
||||
"admin": "Администратор",
|
||||
"admin-desc": "Can view and edit cards, remove members, and change settings for the board.",
|
||||
"admin-announcement": "Съобщение",
|
||||
@@ -106,6 +107,7 @@
|
||||
"and-n-other-card_plural": "И __count__ други карти",
|
||||
"apply": "Приложи",
|
||||
"app-is-offline": "Loading, please wait. Refreshing the page will cause data loss. If loading does not work, please check that server has not stopped.",
|
||||
"app-try-reconnect": "Try to reconnect.",
|
||||
"archive": "Премести в Архива",
|
||||
"archive-all": "Премести всички в Архива",
|
||||
"archive-board": "Премести Таблото в Архива",
|
||||
@@ -279,8 +281,10 @@
|
||||
"worker-desc": "Може само да премества карти, да ги добавя към себе си и да коментира",
|
||||
"computer": "Компютър",
|
||||
"confirm-subtask-delete-dialog": "Сигурен ли сте, че искате да изтриете подзадачата?",
|
||||
"confirm-checklist-delete-dialog": "Сигурни ли сте, че искате да изтриете този чеклист?",
|
||||
"confirm-checklist-delete-popup": "Are you sure you want to delete the checklist?",
|
||||
"checklistDeletePopup-title": "Delete Checklist?",
|
||||
"copy-card-link-to-clipboard": "Копирай връзката на картата в клипборда",
|
||||
"copy-text-to-clipboard": "Copy text to clipboard",
|
||||
"linkCardPopup-title": "Свържи картата",
|
||||
"searchElementPopup-title": "Търсене",
|
||||
"copyCardPopup-title": "Копирай картата",
|
||||
@@ -567,6 +571,8 @@
|
||||
"has-spenttime-cards": "Има карти с изработено време",
|
||||
"time": "Време",
|
||||
"title": "Заглавие",
|
||||
"toggle-labels": "Toggle labels 1-9 for card. Multi-Selection adds labels 1-9",
|
||||
"remove-labels-multiselect": "Multi-Selection removes labels 1-9",
|
||||
"tracking": "Следене",
|
||||
"tracking-info": "You will be notified of any changes to those cards you are involved as creator or member.",
|
||||
"type": "Тип",
|
||||
@@ -606,6 +612,7 @@
|
||||
"people": "Хора",
|
||||
"registration": "Регистрация",
|
||||
"disable-self-registration": "Disable Self-Registration",
|
||||
"disable-forgot-password": "Disable Forgot Password",
|
||||
"invite": "Покани",
|
||||
"invite-people": "Покани хора",
|
||||
"to-boards": "в табло/а",
|
||||
@@ -938,6 +945,8 @@
|
||||
"label-color-not-found": "Label color %s not found.",
|
||||
"user-username-not-found": "Username '%s' not found.",
|
||||
"comment-not-found": "Card with comment containing text '%s' not found.",
|
||||
"org-name-not-found": "Organization '%s' not found.",
|
||||
"team-name-not-found": "Team '%s' not found.",
|
||||
"globalSearch-title": "Search All Boards",
|
||||
"no-cards-found": "No Cards Found",
|
||||
"one-card-found": "One Card Found",
|
||||
@@ -966,6 +975,9 @@
|
||||
"operator-comment": "коментар",
|
||||
"operator-has": "has",
|
||||
"operator-limit": "limit",
|
||||
"operator-debug": "debug",
|
||||
"operator-org": "org",
|
||||
"operator-team": "team",
|
||||
"predicate-archived": "archived",
|
||||
"predicate-open": "open",
|
||||
"predicate-ended": "ended",
|
||||
@@ -987,12 +999,15 @@
|
||||
"predicate-member": "член",
|
||||
"predicate-public": "public",
|
||||
"predicate-private": "private",
|
||||
"predicate-selector": "selector",
|
||||
"predicate-projection": "projection",
|
||||
"operator-unknown-error": "%s is not an operator",
|
||||
"operator-number-expected": "operator __operator__ expected a number, got '__value__'",
|
||||
"operator-sort-invalid": "sort of '%s' is invalid",
|
||||
"operator-status-invalid": "'%s' is not a valid status",
|
||||
"operator-has-invalid": "%s is not a valid existence check",
|
||||
"operator-limit-invalid": "%s is not a valid limit. Limit should be a positive integer.",
|
||||
"operator-debug-invalid": "%s is not a valid debug predicate",
|
||||
"next-page": "Next Page",
|
||||
"previous-page": "Previous Page",
|
||||
"heading-notes": "Notes",
|
||||
@@ -1010,6 +1025,8 @@
|
||||
"globalSearch-instructions-operator-member": "`__operator_member__:<username>` - cards where *<username>* is a *member*",
|
||||
"globalSearch-instructions-operator-assignee": "`__operator_assignee__:<username>` - cards where *<username>* is an *assignee*",
|
||||
"globalSearch-instructions-operator-creator": "`__operator_creator__:<username>` - cards where *<username>* is the card's creator",
|
||||
"globalSearch-instructions-operator-org": "`__operator_org__:<display name|short name>` - cards belonging to a board assigned to organization *<name>*",
|
||||
"globalSearch-instructions-operator-team": "`__operator_team__:<display name|short name>` - cards belonging to a board assigned to team *<name>*",
|
||||
"globalSearch-instructions-operator-due": "`__operator_due__:<n>` - cards which are due up to *<n>* days from now. `__operator_due__:__predicate_overdue__ lists all cards past their due date.",
|
||||
"globalSearch-instructions-operator-created": "`__operator_created__:<n>` - cards which were created *<n>* days ago or less",
|
||||
"globalSearch-instructions-operator-modified": "`__operator_modified__:<n>` - cards which were modified *<n>* days ago or less",
|
||||
@@ -1056,6 +1073,8 @@
|
||||
"orphanedFilesReportTitle": "Orphaned Files Report",
|
||||
"reports": "Reports",
|
||||
"rulesReportTitle": "Rules Report",
|
||||
"boardsReportTitle": "Boards Report",
|
||||
"cardsReportTitle": "Cards Report",
|
||||
"copy-swimlane": "Copy Swimlane",
|
||||
"copySwimlanePopup-title": "Copy Swimlane",
|
||||
"display-card-creator": "Display Card Creator",
|
||||
@@ -1113,5 +1132,20 @@
|
||||
"Node_memory_usage_rss": "Node memory usage: resident set size",
|
||||
"Node_memory_usage_heap_total": "Node memory usage: total size of the allocated heap",
|
||||
"Node_memory_usage_heap_used": "Node memory usage: actual memory used",
|
||||
"Node_memory_usage_external": "Node memory usage: external"
|
||||
"Node_memory_usage_external": "Node memory usage: external",
|
||||
"add-organizations": "Add organizations",
|
||||
"add-organizations-label": "Added organizations are displayed below:",
|
||||
"remove-organization-from-board": "Are you sure you want to remove this organization from this board ?",
|
||||
"to-create-organizations-contact-admin": "To create organizations, please contact administrator.",
|
||||
"custom-legal-notice-link-url": "Custom legal notice page URL",
|
||||
"acceptance_of_our_legalNotice": "By continuing, you accept our",
|
||||
"legalNotice": "legal notice",
|
||||
"copied": "Copied!",
|
||||
"checklistActionsPopup-title": "Checklist Actions",
|
||||
"moveChecklist": "Move Checklist",
|
||||
"moveChecklistPopup-title": "Move Checklist",
|
||||
"newlineBecomesNewChecklistItem": "Newline becomes new checklist item",
|
||||
"copyChecklist": "Copy Checklist",
|
||||
"copyChecklistPopup-title": "Copy Checklist",
|
||||
"card-show-lists": "Card Show Lists"
|
||||
}
|
||||
+36
-2
@@ -96,6 +96,7 @@
|
||||
"add-members": "Ouzhpenn izili",
|
||||
"added": "Ouzhpennet",
|
||||
"addMemberPopup-title": "Izili",
|
||||
"memberPopup-title": "Member Settings",
|
||||
"admin": "Merour",
|
||||
"admin-desc": "Can view and edit cards, remove members, and change settings for the board.",
|
||||
"admin-announcement": "Announcement",
|
||||
@@ -106,6 +107,7 @@
|
||||
"and-n-other-card_plural": "And __count__ other cards",
|
||||
"apply": "Apply",
|
||||
"app-is-offline": "Loading, please wait. Refreshing the page will cause data loss. If loading does not work, please check that server has not stopped.",
|
||||
"app-try-reconnect": "Try to reconnect.",
|
||||
"archive": "Move to Archive",
|
||||
"archive-all": "Move All to Archive",
|
||||
"archive-board": "Move Board to Archive",
|
||||
@@ -279,8 +281,10 @@
|
||||
"worker-desc": "Can only move cards, assign itself to card and comment.",
|
||||
"computer": "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?",
|
||||
"confirm-checklist-delete-popup": "Are you sure you want to delete the checklist?",
|
||||
"checklistDeletePopup-title": "Delete Checklist?",
|
||||
"copy-card-link-to-clipboard": "Copy card link to clipboard",
|
||||
"copy-text-to-clipboard": "Copy text to clipboard",
|
||||
"linkCardPopup-title": "Link Card",
|
||||
"searchElementPopup-title": "Search",
|
||||
"copyCardPopup-title": "Copy Card",
|
||||
@@ -567,6 +571,8 @@
|
||||
"has-spenttime-cards": "Has spent time cards",
|
||||
"time": "Time",
|
||||
"title": "Title",
|
||||
"toggle-labels": "Toggle labels 1-9 for card. Multi-Selection adds labels 1-9",
|
||||
"remove-labels-multiselect": "Multi-Selection removes labels 1-9",
|
||||
"tracking": "Tracking",
|
||||
"tracking-info": "You will be notified of any changes to those cards you are involved as creator or member.",
|
||||
"type": "Type",
|
||||
@@ -606,6 +612,7 @@
|
||||
"people": "People",
|
||||
"registration": "Registration",
|
||||
"disable-self-registration": "Disable Self-Registration",
|
||||
"disable-forgot-password": "Disable Forgot Password",
|
||||
"invite": "Invite",
|
||||
"invite-people": "Invite People",
|
||||
"to-boards": "To board(s)",
|
||||
@@ -938,6 +945,8 @@
|
||||
"label-color-not-found": "Label color %s not found.",
|
||||
"user-username-not-found": "Username '%s' not found.",
|
||||
"comment-not-found": "Card with comment containing text '%s' not found.",
|
||||
"org-name-not-found": "Organization '%s' not found.",
|
||||
"team-name-not-found": "Team '%s' not found.",
|
||||
"globalSearch-title": "Search All Boards",
|
||||
"no-cards-found": "No Cards Found",
|
||||
"one-card-found": "One Card Found",
|
||||
@@ -966,6 +975,9 @@
|
||||
"operator-comment": "comment",
|
||||
"operator-has": "has",
|
||||
"operator-limit": "limit",
|
||||
"operator-debug": "debug",
|
||||
"operator-org": "org",
|
||||
"operator-team": "team",
|
||||
"predicate-archived": "archived",
|
||||
"predicate-open": "open",
|
||||
"predicate-ended": "ended",
|
||||
@@ -987,12 +999,15 @@
|
||||
"predicate-member": "member",
|
||||
"predicate-public": "public",
|
||||
"predicate-private": "private",
|
||||
"predicate-selector": "selector",
|
||||
"predicate-projection": "projection",
|
||||
"operator-unknown-error": "%s is not an operator",
|
||||
"operator-number-expected": "operator __operator__ expected a number, got '__value__'",
|
||||
"operator-sort-invalid": "sort of '%s' is invalid",
|
||||
"operator-status-invalid": "'%s' is not a valid status",
|
||||
"operator-has-invalid": "%s is not a valid existence check",
|
||||
"operator-limit-invalid": "%s is not a valid limit. Limit should be a positive integer.",
|
||||
"operator-debug-invalid": "%s is not a valid debug predicate",
|
||||
"next-page": "Next Page",
|
||||
"previous-page": "Previous Page",
|
||||
"heading-notes": "Notes",
|
||||
@@ -1010,6 +1025,8 @@
|
||||
"globalSearch-instructions-operator-member": "`__operator_member__:<username>` - cards where *<username>* is a *member*",
|
||||
"globalSearch-instructions-operator-assignee": "`__operator_assignee__:<username>` - cards where *<username>* is an *assignee*",
|
||||
"globalSearch-instructions-operator-creator": "`__operator_creator__:<username>` - cards where *<username>* is the card's creator",
|
||||
"globalSearch-instructions-operator-org": "`__operator_org__:<display name|short name>` - cards belonging to a board assigned to organization *<name>*",
|
||||
"globalSearch-instructions-operator-team": "`__operator_team__:<display name|short name>` - cards belonging to a board assigned to team *<name>*",
|
||||
"globalSearch-instructions-operator-due": "`__operator_due__:<n>` - cards which are due up to *<n>* days from now. `__operator_due__:__predicate_overdue__ lists all cards past their due date.",
|
||||
"globalSearch-instructions-operator-created": "`__operator_created__:<n>` - cards which were created *<n>* days ago or less",
|
||||
"globalSearch-instructions-operator-modified": "`__operator_modified__:<n>` - cards which were modified *<n>* days ago or less",
|
||||
@@ -1056,6 +1073,8 @@
|
||||
"orphanedFilesReportTitle": "Orphaned Files Report",
|
||||
"reports": "Reports",
|
||||
"rulesReportTitle": "Rules Report",
|
||||
"boardsReportTitle": "Boards Report",
|
||||
"cardsReportTitle": "Cards Report",
|
||||
"copy-swimlane": "Copy Swimlane",
|
||||
"copySwimlanePopup-title": "Copy Swimlane",
|
||||
"display-card-creator": "Display Card Creator",
|
||||
@@ -1113,5 +1132,20 @@
|
||||
"Node_memory_usage_rss": "Node memory usage: resident set size",
|
||||
"Node_memory_usage_heap_total": "Node memory usage: total size of the allocated heap",
|
||||
"Node_memory_usage_heap_used": "Node memory usage: actual memory used",
|
||||
"Node_memory_usage_external": "Node memory usage: external"
|
||||
"Node_memory_usage_external": "Node memory usage: external",
|
||||
"add-organizations": "Add organizations",
|
||||
"add-organizations-label": "Added organizations are displayed below:",
|
||||
"remove-organization-from-board": "Are you sure you want to remove this organization from this board ?",
|
||||
"to-create-organizations-contact-admin": "To create organizations, please contact administrator.",
|
||||
"custom-legal-notice-link-url": "Custom legal notice page URL",
|
||||
"acceptance_of_our_legalNotice": "By continuing, you accept our",
|
||||
"legalNotice": "legal notice",
|
||||
"copied": "Copied!",
|
||||
"checklistActionsPopup-title": "Checklist Actions",
|
||||
"moveChecklist": "Move Checklist",
|
||||
"moveChecklistPopup-title": "Move Checklist",
|
||||
"newlineBecomesNewChecklistItem": "Newline becomes new checklist item",
|
||||
"copyChecklist": "Copy Checklist",
|
||||
"copyChecklistPopup-title": "Copy Checklist",
|
||||
"card-show-lists": "Card Show Lists"
|
||||
}
|
||||
+36
-2
@@ -96,6 +96,7 @@
|
||||
"add-members": "Afegeix membres",
|
||||
"added": "Afegit",
|
||||
"addMemberPopup-title": "Membres",
|
||||
"memberPopup-title": "Configura membres",
|
||||
"admin": "Administrador",
|
||||
"admin-desc": "Pots veure i editar fitxes, eliminar usuaris, i canviar la configuració del tauler.",
|
||||
"admin-announcement": "Alertes",
|
||||
@@ -106,6 +107,7 @@
|
||||
"and-n-other-card_plural": "And __count__ other cards",
|
||||
"apply": "Aplica",
|
||||
"app-is-offline": "Carregant. Per favor, espereu. Actualitzar la pàgina pot comportar pèrdua de dades. Si la càrrega no funciona, comproveu que el servidor no s'ha aturat. ",
|
||||
"app-try-reconnect": "Try to reconnect.",
|
||||
"archive": "Moure al arxiu",
|
||||
"archive-all": "Moure tot al arxiu",
|
||||
"archive-board": "Moure Tauler al Arxiu",
|
||||
@@ -279,8 +281,10 @@
|
||||
"worker-desc": "Can only move cards, assign itself to card and comment.",
|
||||
"computer": "Ordinador",
|
||||
"confirm-subtask-delete-dialog": "Esteu segur que voleu eliminar la subtasca?",
|
||||
"confirm-checklist-delete-dialog": "Are you sure you want to delete checklist?",
|
||||
"confirm-checklist-delete-popup": "Are you sure you want to delete the checklist?",
|
||||
"checklistDeletePopup-title": "Delete Checklist?",
|
||||
"copy-card-link-to-clipboard": "Copia l'enllaç de la ftixa al porta-retalls",
|
||||
"copy-text-to-clipboard": "Copy text to clipboard",
|
||||
"linkCardPopup-title": "Link Card",
|
||||
"searchElementPopup-title": "Cerca",
|
||||
"copyCardPopup-title": "Copia la fitxa",
|
||||
@@ -567,6 +571,8 @@
|
||||
"has-spenttime-cards": "Té fitxes amb temps dedicat",
|
||||
"time": "Hora",
|
||||
"title": "Títol",
|
||||
"toggle-labels": "Toggle labels 1-9 for card. Multi-Selection adds labels 1-9",
|
||||
"remove-labels-multiselect": "Multi-Selection removes labels 1-9",
|
||||
"tracking": "En seguiment",
|
||||
"tracking-info": "Seràs notificat per cada canvi a aquelles fitxes de les que n'eres creador o membre",
|
||||
"type": "Tipus",
|
||||
@@ -606,6 +612,7 @@
|
||||
"people": "Persones",
|
||||
"registration": "Registre",
|
||||
"disable-self-registration": "Deshabilita Auto-Registre",
|
||||
"disable-forgot-password": "Disable Forgot Password",
|
||||
"invite": "Convida",
|
||||
"invite-people": "Convida a persones",
|
||||
"to-boards": "Al tauler(s)",
|
||||
@@ -938,6 +945,8 @@
|
||||
"label-color-not-found": "Label color %s not found.",
|
||||
"user-username-not-found": "Username '%s' not found.",
|
||||
"comment-not-found": "Card with comment containing text '%s' not found.",
|
||||
"org-name-not-found": "Organization '%s' not found.",
|
||||
"team-name-not-found": "Team '%s' not found.",
|
||||
"globalSearch-title": "Search All Boards",
|
||||
"no-cards-found": "No Cards Found",
|
||||
"one-card-found": "One Card Found",
|
||||
@@ -966,6 +975,9 @@
|
||||
"operator-comment": "comment",
|
||||
"operator-has": "has",
|
||||
"operator-limit": "limit",
|
||||
"operator-debug": "debug",
|
||||
"operator-org": "org",
|
||||
"operator-team": "team",
|
||||
"predicate-archived": "archived",
|
||||
"predicate-open": "open",
|
||||
"predicate-ended": "ended",
|
||||
@@ -987,12 +999,15 @@
|
||||
"predicate-member": "member",
|
||||
"predicate-public": "public",
|
||||
"predicate-private": "private",
|
||||
"predicate-selector": "selector",
|
||||
"predicate-projection": "projection",
|
||||
"operator-unknown-error": "%s is not an operator",
|
||||
"operator-number-expected": "operator __operator__ expected a number, got '__value__'",
|
||||
"operator-sort-invalid": "sort of '%s' is invalid",
|
||||
"operator-status-invalid": "'%s' is not a valid status",
|
||||
"operator-has-invalid": "%s is not a valid existence check",
|
||||
"operator-limit-invalid": "%s is not a valid limit. Limit should be a positive integer.",
|
||||
"operator-debug-invalid": "%s is not a valid debug predicate",
|
||||
"next-page": "Next Page",
|
||||
"previous-page": "Previous Page",
|
||||
"heading-notes": "Notes",
|
||||
@@ -1010,6 +1025,8 @@
|
||||
"globalSearch-instructions-operator-member": "`__operator_member__:<username>` - cards where *<username>* is a *member*",
|
||||
"globalSearch-instructions-operator-assignee": "`__operator_assignee__:<username>` - cards where *<username>* is an *assignee*",
|
||||
"globalSearch-instructions-operator-creator": "`__operator_creator__:<username>` - cards where *<username>* is the card's creator",
|
||||
"globalSearch-instructions-operator-org": "`__operator_org__:<display name|short name>` - cards belonging to a board assigned to organization *<name>*",
|
||||
"globalSearch-instructions-operator-team": "`__operator_team__:<display name|short name>` - cards belonging to a board assigned to team *<name>*",
|
||||
"globalSearch-instructions-operator-due": "`__operator_due__:<n>` - cards which are due up to *<n>* days from now. `__operator_due__:__predicate_overdue__ lists all cards past their due date.",
|
||||
"globalSearch-instructions-operator-created": "`__operator_created__:<n>` - cards which were created *<n>* days ago or less",
|
||||
"globalSearch-instructions-operator-modified": "`__operator_modified__:<n>` - cards which were modified *<n>* days ago or less",
|
||||
@@ -1056,6 +1073,8 @@
|
||||
"orphanedFilesReportTitle": "Orphaned Files Report",
|
||||
"reports": "Reports",
|
||||
"rulesReportTitle": "Rules Report",
|
||||
"boardsReportTitle": "Boards Report",
|
||||
"cardsReportTitle": "Cards Report",
|
||||
"copy-swimlane": "Copy Swimlane",
|
||||
"copySwimlanePopup-title": "Copy Swimlane",
|
||||
"display-card-creator": "Display Card Creator",
|
||||
@@ -1113,5 +1132,20 @@
|
||||
"Node_memory_usage_rss": "Node memory usage: resident set size",
|
||||
"Node_memory_usage_heap_total": "Node memory usage: total size of the allocated heap",
|
||||
"Node_memory_usage_heap_used": "Node memory usage: actual memory used",
|
||||
"Node_memory_usage_external": "Node memory usage: external"
|
||||
"Node_memory_usage_external": "Node memory usage: external",
|
||||
"add-organizations": "Add organizations",
|
||||
"add-organizations-label": "Added organizations are displayed below:",
|
||||
"remove-organization-from-board": "Are you sure you want to remove this organization from this board ?",
|
||||
"to-create-organizations-contact-admin": "To create organizations, please contact administrator.",
|
||||
"custom-legal-notice-link-url": "Custom legal notice page URL",
|
||||
"acceptance_of_our_legalNotice": "By continuing, you accept our",
|
||||
"legalNotice": "legal notice",
|
||||
"copied": "Copied!",
|
||||
"checklistActionsPopup-title": "Checklist Actions",
|
||||
"moveChecklist": "Move Checklist",
|
||||
"moveChecklistPopup-title": "Move Checklist",
|
||||
"newlineBecomesNewChecklistItem": "Newline becomes new checklist item",
|
||||
"copyChecklist": "Copy Checklist",
|
||||
"copyChecklistPopup-title": "Copy Checklist",
|
||||
"card-show-lists": "Card Show Lists"
|
||||
}
|
||||
+36
-2
@@ -96,6 +96,7 @@
|
||||
"add-members": "Přidat členy",
|
||||
"added": "Přidán",
|
||||
"addMemberPopup-title": "Členové",
|
||||
"memberPopup-title": "Nastavení uživatele",
|
||||
"admin": "Administrátor",
|
||||
"admin-desc": "Může zobrazovat a upravovat karty, mazat členy a měnit nastavení tabla.",
|
||||
"admin-announcement": "Oznámení",
|
||||
@@ -106,6 +107,7 @@
|
||||
"and-n-other-card_plural": "A __count__ dalších karet",
|
||||
"apply": "Použít",
|
||||
"app-is-offline": "Načítá se, prosím čekejte. Obnovení stránky způsobí ztrátu dat. Pokud se načítání nedaří, zkontrolujte prosím server.",
|
||||
"app-try-reconnect": "Try to reconnect.",
|
||||
"archive": "Přesunout do archivu",
|
||||
"archive-all": "Přesunout vše do archivu",
|
||||
"archive-board": "Přesunout tablo do archivu",
|
||||
@@ -279,8 +281,10 @@
|
||||
"worker-desc": "Je možné pouze přesouvat karty, přiřazovat ke kartám a komentovat.",
|
||||
"computer": "Počítač",
|
||||
"confirm-subtask-delete-dialog": "Opravdu chcete smazat tento podúkol?",
|
||||
"confirm-checklist-delete-dialog": "Opravdu chcete smazat tento checklist?",
|
||||
"confirm-checklist-delete-popup": "Are you sure you want to delete the checklist?",
|
||||
"checklistDeletePopup-title": "Delete Checklist?",
|
||||
"copy-card-link-to-clipboard": "Kopírovat adresu karty do mezipaměti",
|
||||
"copy-text-to-clipboard": "Copy text to clipboard",
|
||||
"linkCardPopup-title": "Propojit kartu",
|
||||
"searchElementPopup-title": "Hledat",
|
||||
"copyCardPopup-title": "Kopírovat kartu",
|
||||
@@ -567,6 +571,8 @@
|
||||
"has-spenttime-cards": "Obsahuje karty se stráveným časem",
|
||||
"time": "Čas",
|
||||
"title": "Název",
|
||||
"toggle-labels": "Toggle labels 1-9 for card. Multi-Selection adds labels 1-9",
|
||||
"remove-labels-multiselect": "Multi-Selection removes labels 1-9",
|
||||
"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",
|
||||
@@ -606,6 +612,7 @@
|
||||
"people": "Lidé",
|
||||
"registration": "Registrace",
|
||||
"disable-self-registration": "Vypnout svévolnou registraci",
|
||||
"disable-forgot-password": "Disable Forgot Password",
|
||||
"invite": "Pozvánka",
|
||||
"invite-people": "Pozvat lidi",
|
||||
"to-boards": "Do tabel",
|
||||
@@ -938,6 +945,8 @@
|
||||
"label-color-not-found": "Barva štítku %s nenalezena.",
|
||||
"user-username-not-found": "Uživatelské jméno '%s' nenalezeno.",
|
||||
"comment-not-found": "Karta s komentářem obsahujícím text '%s' nenalezena.",
|
||||
"org-name-not-found": "Organization '%s' not found.",
|
||||
"team-name-not-found": "Team '%s' not found.",
|
||||
"globalSearch-title": "Vyhledat všechna tabla",
|
||||
"no-cards-found": "Žádné karty nebyly nalezeny",
|
||||
"one-card-found": "Nalezena jedna karta",
|
||||
@@ -966,6 +975,9 @@
|
||||
"operator-comment": "komentář",
|
||||
"operator-has": "má",
|
||||
"operator-limit": "limit",
|
||||
"operator-debug": "debug",
|
||||
"operator-org": "org",
|
||||
"operator-team": "team",
|
||||
"predicate-archived": "archivováno",
|
||||
"predicate-open": "otevřít",
|
||||
"predicate-ended": "ukončeno",
|
||||
@@ -987,12 +999,15 @@
|
||||
"predicate-member": "člen",
|
||||
"predicate-public": "veřejný",
|
||||
"predicate-private": "soukromý",
|
||||
"predicate-selector": "selector",
|
||||
"predicate-projection": "projection",
|
||||
"operator-unknown-error": "%s není operátor",
|
||||
"operator-number-expected": "operátor __operator__ očekával číslo, ale dostal '__value__'",
|
||||
"operator-sort-invalid": "pořadí '%s' není platné",
|
||||
"operator-status-invalid": "'%s' není platný stav",
|
||||
"operator-has-invalid": "'%s' není platná kontrola existence",
|
||||
"operator-limit-invalid": "není platný limit. Limit musí být pozitivní číslo.",
|
||||
"operator-debug-invalid": "%s is not a valid debug predicate",
|
||||
"next-page": "Následující stránka",
|
||||
"previous-page": "Předchozí stránka",
|
||||
"heading-notes": "Poznámky",
|
||||
@@ -1010,6 +1025,8 @@
|
||||
"globalSearch-instructions-operator-member": "`__operator_member__:<username>` - karty, kde *<username>* je *member*",
|
||||
"globalSearch-instructions-operator-assignee": "`__operator_assignee__:<username>` - karty, kde *<username>* je *assignee*",
|
||||
"globalSearch-instructions-operator-creator": "`__operator_creator__:<username>` - karty, kde *<username>* je tvůrcem",
|
||||
"globalSearch-instructions-operator-org": "`__operator_org__:<display name|short name>` - cards belonging to a board assigned to organization *<name>*",
|
||||
"globalSearch-instructions-operator-team": "`__operator_team__:<display name|short name>` - cards belonging to a board assigned to team *<name>*",
|
||||
"globalSearch-instructions-operator-due": "`__operator_due__:<n>` - karty, které jsou *<n>* dny před termínem. `__operator_due__:__predicate_overdue__ zobrazí všechny karty po termínu.",
|
||||
"globalSearch-instructions-operator-created": "`__operator_created__:<n>` - karty, které byly vytvořeny před *<n>* nebo méně dny",
|
||||
"globalSearch-instructions-operator-modified": "`__operator_modified__:<n>` - katry, které byly upraveny před *<n>* nebo méně dny ",
|
||||
@@ -1056,6 +1073,8 @@
|
||||
"orphanedFilesReportTitle": "Report osiřelých souborů",
|
||||
"reports": "Reporty",
|
||||
"rulesReportTitle": "Report pravidel",
|
||||
"boardsReportTitle": "Boards Report",
|
||||
"cardsReportTitle": "Cards Report",
|
||||
"copy-swimlane": "Kopírovat dráhu",
|
||||
"copySwimlanePopup-title": "Kopírovat dráhu",
|
||||
"display-card-creator": "Zobrazovat tvůrce karet",
|
||||
@@ -1113,5 +1132,20 @@
|
||||
"Node_memory_usage_rss": "Node memory usage: resident set size",
|
||||
"Node_memory_usage_heap_total": "Node memory usage: total size of the allocated heap",
|
||||
"Node_memory_usage_heap_used": "Node memory usage: actual memory used",
|
||||
"Node_memory_usage_external": "Node memory usage: external"
|
||||
"Node_memory_usage_external": "Node memory usage: external",
|
||||
"add-organizations": "Add organizations",
|
||||
"add-organizations-label": "Added organizations are displayed below:",
|
||||
"remove-organization-from-board": "Are you sure you want to remove this organization from this board ?",
|
||||
"to-create-organizations-contact-admin": "To create organizations, please contact administrator.",
|
||||
"custom-legal-notice-link-url": "Custom legal notice page URL",
|
||||
"acceptance_of_our_legalNotice": "By continuing, you accept our",
|
||||
"legalNotice": "legal notice",
|
||||
"copied": "Copied!",
|
||||
"checklistActionsPopup-title": "Checklist Actions",
|
||||
"moveChecklist": "Move Checklist",
|
||||
"moveChecklistPopup-title": "Move Checklist",
|
||||
"newlineBecomesNewChecklistItem": "Newline becomes new checklist item",
|
||||
"copyChecklist": "Copy Checklist",
|
||||
"copyChecklistPopup-title": "Copy Checklist",
|
||||
"card-show-lists": "Card Show Lists"
|
||||
}
|
||||
+36
-2
@@ -96,6 +96,7 @@
|
||||
"add-members": "Tilføj medlemmer",
|
||||
"added": "Tilføjet",
|
||||
"addMemberPopup-title": "Medlemmer",
|
||||
"memberPopup-title": "Medlemsindstillinger",
|
||||
"admin": "Admin",
|
||||
"admin-desc": "Kan se og redigere kort, fjerne medlemmer og ændre indstillinger for tavlen.",
|
||||
"admin-announcement": "Annoncering",
|
||||
@@ -106,6 +107,7 @@
|
||||
"and-n-other-card_plural": "Samt __count__ andre kort",
|
||||
"apply": "Anvend",
|
||||
"app-is-offline": "Indlæser, vent venligst. Genopfriskes siden er der risiko for tab af data. Fungerer indlæsningen ikke, så tjek venligst om serveren er stoppet. ",
|
||||
"app-try-reconnect": "Try to reconnect.",
|
||||
"archive": "Flyt til arkiv",
|
||||
"archive-all": "Flyt alle til arkiv",
|
||||
"archive-board": "Flyt tavle til arkiv",
|
||||
@@ -279,8 +281,10 @@
|
||||
"worker-desc": "Kan kun flytte kort, tildele sig selv til kort og kommentere.",
|
||||
"computer": "Computer",
|
||||
"confirm-subtask-delete-dialog": "Er du sikker på du vil slette delopgaven?",
|
||||
"confirm-checklist-delete-dialog": "Er du sikker på du vil slette tjeklisten?",
|
||||
"confirm-checklist-delete-popup": "Are you sure you want to delete the checklist?",
|
||||
"checklistDeletePopup-title": "Delete Checklist?",
|
||||
"copy-card-link-to-clipboard": "Kopiér link til kort til udklipsholder ",
|
||||
"copy-text-to-clipboard": "Copy text to clipboard",
|
||||
"linkCardPopup-title": "Sammenkæd kort",
|
||||
"searchElementPopup-title": "Søg",
|
||||
"copyCardPopup-title": "Kopiér kort",
|
||||
@@ -567,6 +571,8 @@
|
||||
"has-spenttime-cards": "Har kort med anvendt tid",
|
||||
"time": "Tid",
|
||||
"title": "Titel",
|
||||
"toggle-labels": "Toggle labels 1-9 for card. Multi-Selection adds labels 1-9",
|
||||
"remove-labels-multiselect": "Multi-Selection removes labels 1-9",
|
||||
"tracking": "Sporing",
|
||||
"tracking-info": "Du vil få notifikation om alle ændringer i kort som du har oprettet eller er medlem af.",
|
||||
"type": "Type",
|
||||
@@ -606,6 +612,7 @@
|
||||
"people": "Personer",
|
||||
"registration": "Tilmelding",
|
||||
"disable-self-registration": "Slå selv-tilmelding fra",
|
||||
"disable-forgot-password": "Disable Forgot Password",
|
||||
"invite": "Invitér",
|
||||
"invite-people": "Invitér personer",
|
||||
"to-boards": "Til tavle(r)",
|
||||
@@ -938,6 +945,8 @@
|
||||
"label-color-not-found": "Label color %s not found.",
|
||||
"user-username-not-found": "Username '%s' not found.",
|
||||
"comment-not-found": "Card with comment containing text '%s' not found.",
|
||||
"org-name-not-found": "Organization '%s' not found.",
|
||||
"team-name-not-found": "Team '%s' not found.",
|
||||
"globalSearch-title": "Search All Boards",
|
||||
"no-cards-found": "No Cards Found",
|
||||
"one-card-found": "One Card Found",
|
||||
@@ -966,6 +975,9 @@
|
||||
"operator-comment": "comment",
|
||||
"operator-has": "has",
|
||||
"operator-limit": "limit",
|
||||
"operator-debug": "debug",
|
||||
"operator-org": "org",
|
||||
"operator-team": "team",
|
||||
"predicate-archived": "archived",
|
||||
"predicate-open": "open",
|
||||
"predicate-ended": "ended",
|
||||
@@ -987,12 +999,15 @@
|
||||
"predicate-member": "medlem",
|
||||
"predicate-public": "public",
|
||||
"predicate-private": "private",
|
||||
"predicate-selector": "selector",
|
||||
"predicate-projection": "projection",
|
||||
"operator-unknown-error": "%s is not an operator",
|
||||
"operator-number-expected": "operator __operator__ expected a number, got '__value__'",
|
||||
"operator-sort-invalid": "sort of '%s' is invalid",
|
||||
"operator-status-invalid": "'%s' is not a valid status",
|
||||
"operator-has-invalid": "%s is not a valid existence check",
|
||||
"operator-limit-invalid": "%s is not a valid limit. Limit should be a positive integer.",
|
||||
"operator-debug-invalid": "%s is not a valid debug predicate",
|
||||
"next-page": "Next Page",
|
||||
"previous-page": "Previous Page",
|
||||
"heading-notes": "Notes",
|
||||
@@ -1010,6 +1025,8 @@
|
||||
"globalSearch-instructions-operator-member": "`__operator_member__:<username>` - cards where *<username>* is a *member*",
|
||||
"globalSearch-instructions-operator-assignee": "`__operator_assignee__:<username>` - cards where *<username>* is an *assignee*",
|
||||
"globalSearch-instructions-operator-creator": "`__operator_creator__:<username>` - cards where *<username>* is the card's creator",
|
||||
"globalSearch-instructions-operator-org": "`__operator_org__:<display name|short name>` - cards belonging to a board assigned to organization *<name>*",
|
||||
"globalSearch-instructions-operator-team": "`__operator_team__:<display name|short name>` - cards belonging to a board assigned to team *<name>*",
|
||||
"globalSearch-instructions-operator-due": "`__operator_due__:<n>` - cards which are due up to *<n>* days from now. `__operator_due__:__predicate_overdue__ lists all cards past their due date.",
|
||||
"globalSearch-instructions-operator-created": "`__operator_created__:<n>` - cards which were created *<n>* days ago or less",
|
||||
"globalSearch-instructions-operator-modified": "`__operator_modified__:<n>` - cards which were modified *<n>* days ago or less",
|
||||
@@ -1056,6 +1073,8 @@
|
||||
"orphanedFilesReportTitle": "Orphaned Files Report",
|
||||
"reports": "Reports",
|
||||
"rulesReportTitle": "Rules Report",
|
||||
"boardsReportTitle": "Boards Report",
|
||||
"cardsReportTitle": "Cards Report",
|
||||
"copy-swimlane": "Copy Swimlane",
|
||||
"copySwimlanePopup-title": "Copy Swimlane",
|
||||
"display-card-creator": "Display Card Creator",
|
||||
@@ -1113,5 +1132,20 @@
|
||||
"Node_memory_usage_rss": "Node memory usage: resident set size",
|
||||
"Node_memory_usage_heap_total": "Node memory usage: total size of the allocated heap",
|
||||
"Node_memory_usage_heap_used": "Node memory usage: actual memory used",
|
||||
"Node_memory_usage_external": "Node memory usage: external"
|
||||
"Node_memory_usage_external": "Node memory usage: external",
|
||||
"add-organizations": "Add organizations",
|
||||
"add-organizations-label": "Added organizations are displayed below:",
|
||||
"remove-organization-from-board": "Are you sure you want to remove this organization from this board ?",
|
||||
"to-create-organizations-contact-admin": "To create organizations, please contact administrator.",
|
||||
"custom-legal-notice-link-url": "Custom legal notice page URL",
|
||||
"acceptance_of_our_legalNotice": "By continuing, you accept our",
|
||||
"legalNotice": "legal notice",
|
||||
"copied": "Copied!",
|
||||
"checklistActionsPopup-title": "Checklist Actions",
|
||||
"moveChecklist": "Move Checklist",
|
||||
"moveChecklistPopup-title": "Move Checklist",
|
||||
"newlineBecomesNewChecklistItem": "Newline becomes new checklist item",
|
||||
"copyChecklist": "Copy Checklist",
|
||||
"copyChecklistPopup-title": "Copy Checklist",
|
||||
"card-show-lists": "Card Show Lists"
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
Loaded 100 of 231 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user