Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 | ||
|
|
65f0cab730 | ||
|
|
b72fae24ca | ||
|
|
228c78c248 | ||
|
|
73fdc7ff79 | ||
|
|
cbf91c1869 | ||
|
|
70777cfce8 | ||
|
|
f74fab64b6 | ||
|
|
12839fd929 | ||
|
|
b903750f45 | ||
|
|
f2d2982a76 | ||
|
|
efb24c2d25 | ||
|
|
5fd7407207 | ||
|
|
0a77266f6e | ||
|
|
936d9fe306 | ||
|
|
810c3c81db | ||
|
|
67f614ffb0 | ||
|
|
7f7ef0a914 | ||
|
|
4acf3738ca | ||
|
|
f370f749b9 | ||
|
|
f518971520 | ||
|
|
c5eca7f3ec | ||
|
|
9868b3b6af | ||
|
|
f9c9f2a453 | ||
|
|
206828b440 | ||
|
|
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.9 \
|
||||
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="" \
|
||||
@@ -236,7 +237,7 @@ RUN \
|
||||
set -o xtrace && \
|
||||
apt-get clean -y && \
|
||||
apt-get autoremove -y && \
|
||||
rm -Rf /tmp* && \
|
||||
rm -Rf /tmp/* && \
|
||||
rm -Rf /home/wekan/app_build && \
|
||||
rm -Rf /var/cache/apt /var/lib/apt/lists && \
|
||||
rm -Rf /var/lib/apt/lists/*
|
||||
|
||||
@@ -13,9 +13,8 @@ services:
|
||||
- 27017
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- wekan-db:/data/db
|
||||
- wekan-db-dump:/dump
|
||||
- ./volumes/wekan-db:/data/db
|
||||
- ./volumes/wekan-db-dump:/dump
|
||||
|
||||
wekan-dev:
|
||||
container_name: wekan-dev-app
|
||||
@@ -38,22 +37,12 @@ services:
|
||||
- wekandb-dev
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- ../client:/home/wekan/app/client
|
||||
- ../models:/home/wekan/app/models
|
||||
- ../config:/home/wekan/app/config
|
||||
- ../i18n:/home/wekan/app/i18n
|
||||
- ../server:/home/wekan/app/server
|
||||
- ../public:/home/wekan/app/public
|
||||
- wekan-tmp:/tmp
|
||||
|
||||
volumes:
|
||||
wekan-dev-db:
|
||||
driver: local
|
||||
wekan-dev-db-dump:
|
||||
driver: local
|
||||
wekan-tmp:
|
||||
driver: local
|
||||
|
||||
networks:
|
||||
wekan-dev-tier:
|
||||
|
||||
@@ -81,7 +81,7 @@ parts:
|
||||
wekan:
|
||||
source: .
|
||||
plugin: nodejs
|
||||
node-engine: 12.22.7
|
||||
node-engine: 12.22.9
|
||||
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.9
|
||||
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 -->
|
||||
@@ -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.9
|
||||
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, 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
|
||||
|
||||
+446
@@ -1,5 +1,451 @@
|
||||
[Mac ChangeLog](https://github.com/wekan/wekan/wiki/Mac)
|
||||
|
||||
# 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:
|
||||
|
||||
- [Card popup close color remove move bottom delete](https://github.com/wekan/wekan/pull/4138).
|
||||
Thanks to mfilser.
|
||||
- [Comment edit has now a cancel button](https://github.com/wekan/wekan/pull/4139).
|
||||
Thanks to mfilser.
|
||||
- [Checklist and items drag drop scrollable mobile view](https://github.com/wekan/wekan/pull/4140).
|
||||
Thanks to mfilser.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated release scripts](https://github.com/wekan/wekan/commit/936d9fe30697e4651cba04d505393e05f8c902c1).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.74 2021-11-11 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Docker fix failed export and timezone](https://github.com/wekan/wekan/pull/4137).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v5.73 2021-11-11 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
+4
-3
@@ -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.9 \
|
||||
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="" \
|
||||
@@ -309,7 +310,7 @@ RUN \
|
||||
apt-get remove --purge -y ${BUILD_DEPS} && \
|
||||
apt-get autoremove -y && \
|
||||
npm uninstall -g api2html &&\
|
||||
rm -R /tmp* && \
|
||||
rm -R /tmp/* && \
|
||||
rm -R /var/lib/apt/lists/* && \
|
||||
rm -R /home/wekan/.meteor && \
|
||||
rm -R /home/wekan/app && \
|
||||
|
||||
+2
-2
@@ -4,7 +4,7 @@ FROM amd64/alpine:3.7 AS builder
|
||||
ENV QEMU_VERSION=v4.2.0-6 \
|
||||
QEMU_ARCHITECTURE=aarch64 \
|
||||
NODE_ARCHITECTURE=linux-arm64 \
|
||||
NODE_VERSION=v12.22.7 \
|
||||
NODE_VERSION=v12.22.9 \
|
||||
WEKAN_VERSION=latest \
|
||||
WEKAN_ARCHITECTURE=arm64
|
||||
|
||||
@@ -40,7 +40,7 @@ LABEL maintainer="wekan"
|
||||
# Set the environment variables (defaults where required)
|
||||
ENV QEMU_ARCHITECTURE=aarch64 \
|
||||
NODE_ARCHITECTURE=linux-arm64 \
|
||||
NODE_VERSION=v12.22.7 \
|
||||
NODE_VERSION=v12.22.9 \
|
||||
NODE_ENV=production \
|
||||
NPM_VERSION=latest \
|
||||
WITH_API=true \
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
|
||||
appVersion: "v5.73.0"
|
||||
appVersion: "v5.97.0"
|
||||
files:
|
||||
userUploads:
|
||||
- README.md
|
||||
|
||||
@@ -140,6 +140,7 @@ template(name="activity")
|
||||
= activity.comment.text
|
||||
.edit-controls
|
||||
button.primary(type="submit") {{_ 'edit'}}
|
||||
.fa.fa-times-thin.js-close-inlined-form
|
||||
else
|
||||
.activity-comment
|
||||
+viewer
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -186,9 +186,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,
|
||||
@@ -197,8 +198,10 @@ setBoardColor(color)
|
||||
background-color:rgba(255,255,255,.8) !important
|
||||
color:#000
|
||||
|
||||
/*
|
||||
.minicard, .minicard .badge
|
||||
color:#fff
|
||||
*/
|
||||
|
||||
.minicard:hover .badge, .minicard-wrapper.is-selected .badge
|
||||
color:#000
|
||||
@@ -214,6 +217,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 +232,7 @@ setBoardColor(color)
|
||||
|
||||
.list-header
|
||||
background-color:#a7e366
|
||||
border-bottom: 6px solid #a7e366
|
||||
// border-bottom: 6px solid #a7e366
|
||||
|
||||
.list-body
|
||||
background-color:#a7e366
|
||||
@@ -541,8 +548,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 +652,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,13 +765,13 @@ setBoardClear(color1,color2)
|
||||
|
||||
/* Forms */
|
||||
button[type=submit].primary, .board-color-modern input[type=submit].primary
|
||||
background-color: #819C5D
|
||||
background-color: #777777
|
||||
|
||||
.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
|
||||
@@ -854,21 +861,22 @@ setBoardClear(color1,color2)
|
||||
.swimlane .list:first-child
|
||||
margin-left: 0
|
||||
|
||||
.swimlane .list:nth-child(even)
|
||||
.swimlane .list:nth-child(even) .list-header,
|
||||
.swimlane .list:nth-child(even) .list-body
|
||||
background: #5f5f5f
|
||||
|
||||
.swimlane .list:nth-child(odd) .list-header
|
||||
.swimlane .list:nth-child(odd) .list-header,
|
||||
.swimlane .list:nth-child(odd) .list-body
|
||||
background: #3b3b3b
|
||||
|
||||
.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 +884,7 @@ setBoardClear(color1,color2)
|
||||
padding: 10px
|
||||
top: 0
|
||||
|
||||
.list-header .list-header-plus-icon
|
||||
.list-header .list-header-plus-top
|
||||
color: #a6a6a6
|
||||
|
||||
.list-body
|
||||
@@ -921,7 +929,8 @@ setBoardClear(color1,color2)
|
||||
border-bottom: 1px solid #666666
|
||||
|
||||
.minicard:hover
|
||||
background-color: #494949 !important
|
||||
color: #f7f7f7
|
||||
background-color: #797979 !important
|
||||
|
||||
.minicard .minicard-labels
|
||||
margin-bottom: 4px
|
||||
@@ -956,17 +965,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 +1034,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 +1075,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
|
||||
@@ -574,6 +576,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 +725,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 +802,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'}}
|
||||
|
||||
@@ -325,29 +325,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) {
|
||||
@@ -546,7 +527,8 @@ Template.cardDetails.helpers({
|
||||
}
|
||||
});
|
||||
Template.cardDetailsPopup.onDestroyed(() => {
|
||||
Session.delete('popupCard');
|
||||
Session.delete('popupCardId');
|
||||
Session.delete('popupCardBoardId');
|
||||
});
|
||||
Template.cardDetailsPopup.helpers({
|
||||
popupCard() {
|
||||
@@ -676,7 +658,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,10 +668,11 @@ 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);
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-archive': Popup.afterConfirm('cardArchive', function () {
|
||||
Popup.close();
|
||||
@@ -706,9 +689,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'));
|
||||
@@ -768,16 +773,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'));
|
||||
});
|
||||
@@ -806,15 +801,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];
|
||||
@@ -831,8 +827,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() {
|
||||
@@ -861,9 +905,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);
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -1011,7 +1073,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
'click .js-remove-color'() {
|
||||
this.currentCard.setColor(null);
|
||||
Popup.back();
|
||||
Popup.close();
|
||||
},
|
||||
},
|
||||
];
|
||||
@@ -1087,33 +1149,14 @@ 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.back();
|
||||
Popup.close();
|
||||
// verify that there are no linked cards
|
||||
if (Cards.find({ linkedId: this._id }).count() === 0) {
|
||||
Cards.remove(this._id);
|
||||
|
||||
@@ -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
|
||||
@@ -118,7 +124,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 +181,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 +197,10 @@ avatar-radius = 50%
|
||||
border-radius: 3px
|
||||
padding: 0px 5px
|
||||
|
||||
.copied-tooltip
|
||||
margin-right: 10px
|
||||
padding: 10px;
|
||||
|
||||
.card-description textarea
|
||||
min-height: 100px
|
||||
|
||||
@@ -243,7 +257,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
|
||||
@@ -287,6 +301,8 @@ input[type="submit"].attachment-add-link-submit
|
||||
padding: 0px 20px 0px 20px
|
||||
margin: 0px
|
||||
transition: none
|
||||
overflow-y: revert
|
||||
overflow-x: revert
|
||||
|
||||
.card-details-canvas
|
||||
width: 100%
|
||||
@@ -314,12 +330,12 @@ input[type="submit"].attachment-add-link-submit
|
||||
& > .content
|
||||
width: calc(100% - 10px)
|
||||
|
||||
& > .content > .card-details-popup
|
||||
overflow-y: auto
|
||||
|
||||
& hr
|
||||
& > .content > .card-details-popup hr
|
||||
margin: 15px 0px
|
||||
|
||||
.card-details-header
|
||||
margin: 0
|
||||
|
||||
card-details-color(background, color...)
|
||||
background: background !important
|
||||
if color
|
||||
|
||||
@@ -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,32 @@ template(name="checklistDetail")
|
||||
h2.title
|
||||
+viewer
|
||||
= checklist.title
|
||||
|
||||
.checklist-progress-bar-container
|
||||
.checklist-progress-text {{#if $gt finishedPercent 0}}{{finishedPercent}}%{{/if}}
|
||||
.checklist-progress-bar
|
||||
.checklist-progress(style="width:{{finishedPercent}}%;{{#if $eq finishedPercent 0}}display:none{{/if}}")
|
||||
+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 +93,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 +142,41 @@ 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"}} ...
|
||||
|
||||
template(name="moveChecklistPopup")
|
||||
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 isMoveChecklistDialogOptionBoardId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
label {{_ 'swimlanes'}}:
|
||||
select.js-select-swimlanes
|
||||
each swimlanes
|
||||
option(value="{{_id}}" selected="{{#if isMoveChecklistDialogOptionSwimlaneId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
label {{_ 'lists'}}:
|
||||
select.js-select-lists
|
||||
each lists
|
||||
option(value="{{_id}}" selected="{{#if isMoveChecklistDialogOptionListId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
label {{_ 'cards'}}:
|
||||
select.js-select-cards
|
||||
each cards
|
||||
option(value="{{_id}}" selected="{{#if isMoveChecklistDialogOptionCardId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm.js-done {{_ 'done'}}
|
||||
@@ -13,7 +13,7 @@ function initSorting(items) {
|
||||
appendTo: 'parent',
|
||||
distance: 7,
|
||||
placeholder: 'checklist-item placeholder',
|
||||
scroll: false,
|
||||
scroll: true,
|
||||
start(evt, ui) {
|
||||
ui.placeholder.height(ui.helper.height());
|
||||
EscapeActions.clickExecute(evt.target, 'inlinedForm');
|
||||
@@ -55,7 +55,7 @@ BlazeComponent.extendComponent({
|
||||
return Meteor.user() && Meteor.user().isBoardMember();
|
||||
}
|
||||
|
||||
// Disable sorting if the current user is not a board member or is a miniscreen
|
||||
// Disable sorting if the current user is not a board member
|
||||
self.autorun(() => {
|
||||
const $itemsDom = $(self.itemsDom);
|
||||
if ($itemsDom.data('uiSortable') || $itemsDom.data('sortable')) {
|
||||
@@ -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
|
||||
@@ -188,18 +189,13 @@ BlazeComponent.extendComponent({
|
||||
}
|
||||
},
|
||||
|
||||
/** closes all inlined forms (checklist and checklist-item input fields) */
|
||||
closeAllInlinedForms() {
|
||||
this.$('.js-close-inlined-form').click();
|
||||
},
|
||||
|
||||
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');
|
||||
},
|
||||
@@ -208,16 +204,16 @@ 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,
|
||||
'click .add-checklist-item.js-open-inlined-form': this.closeAllInlinedForms,
|
||||
'click .add-checklist.js-open-inlined-form': this.closeAllInlinedForms,
|
||||
// add and delete checklist / checklist-item
|
||||
'click .js-open-inlined-form': this.closeAllInlinedForms,
|
||||
keydown: this.pressKey,
|
||||
},
|
||||
];
|
||||
@@ -278,39 +274,76 @@ 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'),
|
||||
}
|
||||
]
|
||||
}
|
||||
}).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() {
|
||||
@@ -344,3 +377,188 @@ BlazeComponent.extendComponent({
|
||||
];
|
||||
},
|
||||
}).register('checklistItemDetail');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentBoardId = Utils.getCurrentBoardId();
|
||||
this.selectedBoardId = new ReactiveVar(this.currentBoardId);
|
||||
this.selectedSwimlaneId = new ReactiveVar('');
|
||||
this.selectedListId = new ReactiveVar('');
|
||||
this.setMoveChecklistDialogOption(this.currentBoardId);
|
||||
},
|
||||
|
||||
/** set the last confirmed dialog field values
|
||||
* @param boardId the current board id
|
||||
*/
|
||||
setMoveChecklistDialogOption(boardId) {
|
||||
this.moveChecklistDialogOption = {
|
||||
'boardId' : "",
|
||||
'swimlaneId' : "",
|
||||
'listId' : "",
|
||||
'cardId': "",
|
||||
}
|
||||
|
||||
let currentOptions = Meteor.user().getMoveChecklistDialogOptions();
|
||||
if (currentOptions && boardId && currentOptions[boardId]) {
|
||||
this.moveChecklistDialogOption = currentOptions[boardId];
|
||||
if (this.moveChecklistDialogOption.boardId &&
|
||||
this.moveChecklistDialogOption.swimlaneId &&
|
||||
this.moveChecklistDialogOption.listId
|
||||
)
|
||||
{
|
||||
this.selectedBoardId.set(this.moveChecklistDialogOption.boardId)
|
||||
this.selectedSwimlaneId.set(this.moveChecklistDialogOption.swimlaneId);
|
||||
this.selectedListId.set(this.moveChecklistDialogOption.listId);
|
||||
}
|
||||
}
|
||||
this.getBoardData(boardId);
|
||||
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
|
||||
*/
|
||||
isMoveChecklistDialogOptionBoardId(boardId) {
|
||||
let ret = this.moveChecklistDialogOption.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
|
||||
*/
|
||||
isMoveChecklistDialogOptionSwimlaneId(swimlaneId) {
|
||||
let ret = this.moveChecklistDialogOption.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
|
||||
*/
|
||||
isMoveChecklistDialogOptionListId(listId) {
|
||||
let ret = this.moveChecklistDialogOption.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
|
||||
*/
|
||||
isMoveChecklistDialogOptionCardId(cardId) {
|
||||
let ret = this.moveChecklistDialogOption.cardId == cardId;
|
||||
return ret;
|
||||
},
|
||||
|
||||
boards() {
|
||||
const ret = Boards.find(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
_id: { $ne: Meteor.user().getTemplatesBoardId() },
|
||||
},
|
||||
{
|
||||
sort: { sort: 1 },
|
||||
},
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
|
||||
swimlanes() {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const ret = board.swimlanes();
|
||||
return ret;
|
||||
},
|
||||
|
||||
lists() {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const ret = board.lists();
|
||||
return ret;
|
||||
},
|
||||
|
||||
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() {
|
||||
self.selectedBoardId.set(boardId);
|
||||
|
||||
// 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,
|
||||
}
|
||||
Meteor.user().setMoveChecklistDialogOption(this.currentBoardId, options);
|
||||
this.data().checklist.move(cardId);
|
||||
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());
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('moveChecklistPopup');
|
||||
@@ -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
|
||||
@@ -167,4 +148,21 @@ textarea.js-add-checklist-item, textarea.js-edit-checklist-item
|
||||
|
||||
.add-checklist-item
|
||||
margin: 0.2em 0 0.5em 1.33em
|
||||
display: inline-block
|
||||
|
||||
.add-checklist-item,.add-checklist
|
||||
&.js-open-inlined-form
|
||||
display: block
|
||||
width: 50%
|
||||
|
||||
&:hover
|
||||
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(() => {
|
||||
|
||||
@@ -85,13 +85,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 +96,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 +157,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 +200,6 @@
|
||||
display: flex
|
||||
align-items: center
|
||||
.list-header-left-icon
|
||||
display: inline
|
||||
padding: 7px
|
||||
padding-right: 27px
|
||||
margin-top: 1px
|
||||
@@ -238,6 +222,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,23 @@
|
||||
Meteor.subscribe('user-admin');
|
||||
Meteor.subscribe('boards');
|
||||
Meteor.subscribe('setting');
|
||||
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 +57,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
|
||||
|
||||
@@ -77,6 +77,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 +121,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 +136,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') {
|
||||
@@ -145,9 +184,14 @@ Template.userFormsLayout.helpers({
|
||||
name = 'español de Puerto Rico';
|
||||
} 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;
|
||||
@@ -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 [
|
||||
|
||||
@@ -188,6 +188,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
|
||||
|
||||
@@ -210,6 +210,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 +239,7 @@ BlazeComponent.extendComponent({
|
||||
spinnerName,
|
||||
oidcBtnText,
|
||||
mailDomainName,
|
||||
legalNotice,
|
||||
},
|
||||
});
|
||||
} catch (e) {
|
||||
|
||||
@@ -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
|
||||
@@ -488,12 +494,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
|
||||
|
||||
@@ -1325,8 +1325,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 +1498,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
|
||||
|
||||
@@ -57,7 +57,7 @@ function initSortable(boardComponent, $listsDom) {
|
||||
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());
|
||||
@@ -148,8 +148,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 +237,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 +280,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;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -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') {
|
||||
@@ -313,9 +331,14 @@ Template.changeLanguagePopup.helpers({
|
||||
name = 'español de Puerto Rico';
|
||||
} 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')
|
||||
@@ -60,6 +60,8 @@ MultiSelection = {
|
||||
|
||||
startRangeCardId: null,
|
||||
|
||||
_sidebarWasOpen: false,
|
||||
|
||||
reset() {
|
||||
this._selectedCards.set([]);
|
||||
},
|
||||
@@ -84,11 +86,15 @@ MultiSelection = {
|
||||
|
||||
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 +102,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
|
||||
|
||||
@@ -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';
|
||||
|
||||
+5
-4
@@ -236,6 +236,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
|
||||
@@ -663,8 +668,6 @@ services:
|
||||
- wekandb
|
||||
volumes:
|
||||
- /etc/localtime:/etc/localtime:ro
|
||||
- /etc/timezone:/etc/timezone:ro
|
||||
- wekan-tmp:/tmp
|
||||
|
||||
#---------------------------------------------------------------------------------
|
||||
# ==== OPTIONAL: SHARE DATABASE TO OFFICE LAN AND REMOTE VPN ====
|
||||
@@ -720,8 +723,6 @@ volumes:
|
||||
driver: local
|
||||
wekan-db-dump:
|
||||
driver: local
|
||||
wekan-tmp:
|
||||
driver: local
|
||||
|
||||
networks:
|
||||
wekan-tier:
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
apiVersion: v2
|
||||
appVersion: "5.73"
|
||||
appVersion: "5.97"
|
||||
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.73
|
||||
tag: v5.97
|
||||
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 ]
|
||||
|
||||
+30
-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",
|
||||
@@ -938,6 +942,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 +972,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 +996,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 +1022,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 +1070,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 +1129,17 @@
|
||||
"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"
|
||||
}
|
||||
+30
-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": "نسخ البطاقة",
|
||||
@@ -938,6 +942,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 +972,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 +996,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 +1022,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 +1070,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 +1129,17 @@
|
||||
"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"
|
||||
}
|
||||
+30
-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": "Копирай картата",
|
||||
@@ -938,6 +942,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 +972,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 +996,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 +1022,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 +1070,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 +1129,17 @@
|
||||
"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"
|
||||
}
|
||||
+30
-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",
|
||||
@@ -938,6 +942,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 +972,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 +996,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 +1022,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 +1070,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 +1129,17 @@
|
||||
"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"
|
||||
}
|
||||
+30
-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",
|
||||
@@ -938,6 +942,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 +972,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 +996,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 +1022,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 +1070,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 +1129,17 @@
|
||||
"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"
|
||||
}
|
||||
+30
-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",
|
||||
@@ -938,6 +942,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 +972,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 +996,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 +1022,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 +1070,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 +1129,17 @@
|
||||
"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"
|
||||
}
|
||||
+30
-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",
|
||||
@@ -938,6 +942,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 +972,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 +996,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 +1022,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 +1070,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 +1129,17 @@
|
||||
"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"
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
+31
-3
@@ -96,6 +96,7 @@
|
||||
"add-members": "Mitglieder hinzufügen",
|
||||
"added": "Hinzugefügt",
|
||||
"addMemberPopup-title": "Mitglieder",
|
||||
"memberPopup-title": "Nutzereinstellungen",
|
||||
"admin": "Admin",
|
||||
"admin-desc": "Kann Karten anzeigen und bearbeiten, Mitglieder entfernen und Boardeinstellungen ändern.",
|
||||
"admin-announcement": "Ankündigung",
|
||||
@@ -106,6 +107,7 @@
|
||||
"and-n-other-card_plural": "und __count__ andere Karten",
|
||||
"apply": "Übernehmen",
|
||||
"app-is-offline": "Laden, bitte warten. Das Aktualisieren der Seite führt zu Datenverlust. Wenn das Laden nicht funktioniert, überprüfen Sie bitte, ob der Server nicht angehalten wurde.",
|
||||
"app-try-reconnect": "Versuch die Verbindung wiederherzustellen.",
|
||||
"archive": "Ins Archiv verschieben",
|
||||
"archive-all": "Alles ins Archiv verschieben",
|
||||
"archive-board": "Board ins Archiv verschieben",
|
||||
@@ -279,8 +281,10 @@
|
||||
"worker-desc": "Kann Karten nur verschieben, sich selbst zuweisen und kommentieren.",
|
||||
"computer": "Computer",
|
||||
"confirm-subtask-delete-dialog": "Wollen Sie die Teilaufgabe wirklich löschen?",
|
||||
"confirm-checklist-delete-dialog": "Wollen Sie die Checkliste wirklich löschen?",
|
||||
"confirm-checklist-delete-popup": "Wollen Sie diese Checkliste wirklich löschen?",
|
||||
"checklistDeletePopup-title": "Checkliste löschen?",
|
||||
"copy-card-link-to-clipboard": "Kopiere Link zur Karte in die Zwischenablage",
|
||||
"copy-text-to-clipboard": "Text in die Zwischenablage kopieren",
|
||||
"linkCardPopup-title": "Karte verknüpfen",
|
||||
"searchElementPopup-title": "Suche",
|
||||
"copyCardPopup-title": "Karte kopieren",
|
||||
@@ -938,6 +942,8 @@
|
||||
"label-color-not-found": "Label-Farbe „%s“ nicht gefunden.",
|
||||
"user-username-not-found": "Nutzername „%s“ nicht gefunden.",
|
||||
"comment-not-found": "Keine Karte gefunden, die „%s“ in einem Kommentar enthält.",
|
||||
"org-name-not-found": "Organisation '%s' nicht gefunden",
|
||||
"team-name-not-found": "Team '%s' nicht gefunden",
|
||||
"globalSearch-title": "Alle Boards durchsuchen",
|
||||
"no-cards-found": "Keine Karten gefunden",
|
||||
"one-card-found": "Eine Karte gefunden",
|
||||
@@ -966,6 +972,9 @@
|
||||
"operator-comment": "kommentieren",
|
||||
"operator-has": "hat",
|
||||
"operator-limit": "Begrenzung",
|
||||
"operator-debug": "debug",
|
||||
"operator-org": "Organisation",
|
||||
"operator-team": "Team",
|
||||
"predicate-archived": "archiviert",
|
||||
"predicate-open": "offen",
|
||||
"predicate-ended": "beendet",
|
||||
@@ -987,12 +996,15 @@
|
||||
"predicate-member": "Mitglied",
|
||||
"predicate-public": "öffentlich",
|
||||
"predicate-private": "privat",
|
||||
"predicate-selector": "Auswahl",
|
||||
"predicate-projection": "Projektion",
|
||||
"operator-unknown-error": "„%s“ ist kein Operator",
|
||||
"operator-number-expected": "Operator „__operator__“ erwartete eine Zahl, bekam aber „__value__“",
|
||||
"operator-sort-invalid": "Sortierung „%s“ ist ungültig",
|
||||
"operator-status-invalid": "„%s“ ist kein gültiger Status",
|
||||
"operator-has-invalid": "%s ist keine gültige Prüfung auf Existenz",
|
||||
"operator-limit-invalid": "%s ist keine gültige Begrenzung. Die Begrenzung sollte eine positive Ganzzahl sein.",
|
||||
"operator-debug-invalid": "%sist kein gültiger Debug-Ausdruck",
|
||||
"next-page": "Nächste Seite",
|
||||
"previous-page": "Vorherige Seite",
|
||||
"heading-notes": "Bemerkungen",
|
||||
@@ -1010,6 +1022,8 @@
|
||||
"globalSearch-instructions-operator-member": "`__operator_member__:<username>` – Karten, von denen *<username>* *Mitglied* ist",
|
||||
"globalSearch-instructions-operator-assignee": "`__operator_assignee__:<username>` – Karten, denen *<username>* *zugewiesen* ist",
|
||||
"globalSearch-instructions-operator-creator": "`__operator_creator__:<username>` – Karten, die von *<username>* angelegt wurden",
|
||||
"globalSearch-instructions-operator-org": "`__operator_org__:<display name|short name>` - Karten gehören zu einem Board, welches der Organisation *<name>* zugewiesen ist.",
|
||||
"globalSearch-instructions-operator-team": "`__operator_team__:<display name|short name>` - Karten gehören zu einem Board, welches dem Team *<name>* zugewiesen ist.",
|
||||
"globalSearch-instructions-operator-due": "`__operator_due__:<n>` – Karten, die spätestens in *<n>* Tagen fällig sind. `__operator_due__:__predicate_overdue__` zeigt alle Karten, für die die Fälligkeit überschritten ist.",
|
||||
"globalSearch-instructions-operator-created": "`__operator_created__:<n>` – Karten, die vor maximal *<n>* Tagen angelegt wurden",
|
||||
"globalSearch-instructions-operator-modified": "`__operator_modified__:<n>` – Karten, die vor maximal *<n>* Tagen geändert wurden",
|
||||
@@ -1056,6 +1070,8 @@
|
||||
"orphanedFilesReportTitle": "Verwaister Datei-Bericht",
|
||||
"reports": "Berichte",
|
||||
"rulesReportTitle": "Regeln-Bericht",
|
||||
"boardsReportTitle": "Board-Bericht",
|
||||
"cardsReportTitle": "Karten-Bericht",
|
||||
"copy-swimlane": "Swimlane kopieren",
|
||||
"copySwimlanePopup-title": "Swimlane kopieren",
|
||||
"display-card-creator": "Zeige Karten-Erstellung",
|
||||
@@ -1098,7 +1114,7 @@
|
||||
"invite-people-success": "Registrierungseinladung erfolgreich versandt",
|
||||
"invite-people-error": "Fehler beim Versand der Registrierungseinladung",
|
||||
"can-invite-if-same-mailDomainName": "Name der Email-Domain",
|
||||
"to-create-teams-contact-admin": "To create teams, please contact the administrator.",
|
||||
"to-create-teams-contact-admin": "Kontaktieren SIe den Administrator um ein Team erstellen zu lassen.",
|
||||
"Node_heap_total_heap_size": "Node heap: total heap size",
|
||||
"Node_heap_total_heap_size_executable": "Node heap: total heap size executable",
|
||||
"Node_heap_total_physical_size": "Node heap: total physical size",
|
||||
@@ -1113,5 +1129,17 @@
|
||||
"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": "Organisation hinzufügen",
|
||||
"add-organizations-label": "Hinzugefügte Organisationen werden nachfolgend angezeigt:",
|
||||
"remove-organization-from-board": "Sind Sie sicher, das Sie diese Organisation von diesem Board entfernen möchten?",
|
||||
"to-create-organizations-contact-admin": "Um Organisationen anzulegen, kontaktieren Sie sich bitte an den Administrator.",
|
||||
"custom-legal-notice-link-url": "URL zu benutzerdefiniertem Impressum",
|
||||
"acceptance_of_our_legalNotice": "Wenn Sie fortfahren, akzeptieren Sie unsere",
|
||||
"legalNotice": "Impressum/Datenschutzerklärung",
|
||||
"copied": "Kopiert!",
|
||||
"checklistActionsPopup-title": "Listenaktionen",
|
||||
"moveChecklist": "Checkliste bewegen",
|
||||
"moveChecklistPopup-title": "Checkliste bewegen",
|
||||
"newlineBecomesNewChecklistItem": "Neue Zeile wird neuer Checklisteneintrag"
|
||||
}
|
||||
+33
-5
@@ -9,7 +9,7 @@
|
||||
"act-removeLabel": "hat Label __label__ von Karte __card__ auf der Liste __list__ in Swimlane __swimlane__ in Board __board__ entfernt",
|
||||
"act-removedLabel": "hat Label __label__ von Karte __card__ auf der Liste __list__ in Swimlane __swimlane__ in Board __board__ entfernt",
|
||||
"act-addChecklist": "hat Checkliste __checklist__ zur Karte __card__ auf der Liste __list__ in Swimlane __swimlane__ in Board __board__ hinzugefügt",
|
||||
"act-addChecklistItem": "hat Checklistenposition __checklistItem__ zu Checkliste __checkList__ auf der Karte __card__ auf der Liste __list__ in Swimlane __swimlane__ in Board __board__ hinzugefügt",
|
||||
"act-addChecklistItem": "hat Checklistenelement __checklistItem__ zu Checkliste __checkList__ auf der Karte __card__ auf der Liste __list__ in Swimlane __swimlane__ in Board __board__ hinzugefügt",
|
||||
"act-removeChecklist": "hat Checkliste __checklist__ von Karte __card__ auf der Liste __list__ in Swimlane __swimlane__ in Board __board__ entfernt",
|
||||
"act-removeChecklistItem": "hat Checklistenposition __checklistItem__ von Checkliste __checkList__ auf der Karte __card__ auf der Liste __list__ in Swimlane __swimlane__ in Board __board__ entfernt",
|
||||
"act-checkedItem": "hat __checklistItem__ der Checkliste __checklist__ der Karte __card__ auf der Liste __list__ in Swimlane __swimlane__ in Board __board__ abgehakt",
|
||||
@@ -96,6 +96,7 @@
|
||||
"add-members": "Mitglieder hinzufügen",
|
||||
"added": "Hinzugefügt",
|
||||
"addMemberPopup-title": "Mitglieder",
|
||||
"memberPopup-title": "Nutzereinstellungen",
|
||||
"admin": "Admin",
|
||||
"admin-desc": "Kann Karten anzeigen und bearbeiten, Mitglieder entfernen und Boardeinstellungen ändern.",
|
||||
"admin-announcement": "Ankündigung",
|
||||
@@ -106,6 +107,7 @@
|
||||
"and-n-other-card_plural": "und __count__ andere Karten",
|
||||
"apply": "Übernehmen",
|
||||
"app-is-offline": "Laden, bitte warten. Das Aktualisieren der Seite führt zu Datenverlust. Wenn das Laden nicht funktioniert, überprüfen Sie bitte, ob der Server nicht angehalten wurde.",
|
||||
"app-try-reconnect": "Versuche die Verbindung wiederherzustellen",
|
||||
"archive": "Ins Archiv verschieben",
|
||||
"archive-all": "Alles ins Archiv verschieben",
|
||||
"archive-board": "Board ins Archiv verschieben",
|
||||
@@ -267,7 +269,7 @@
|
||||
"color-white": "Weiß",
|
||||
"color-yellow": "gelb",
|
||||
"unset-color": "Nicht festgelegt",
|
||||
"comment": "Kommentar",
|
||||
"comment": "Kommentar speichern",
|
||||
"comment-placeholder": "Kommentar schreiben",
|
||||
"comment-only": "Nur Kommentare",
|
||||
"comment-only-desc": "Kann Karten nur kommentieren.",
|
||||
@@ -279,8 +281,10 @@
|
||||
"worker-desc": "Kann Karten nur verschieben, sich selbst zuweisen und kommentieren.",
|
||||
"computer": "Computer",
|
||||
"confirm-subtask-delete-dialog": "Wollen Sie die Teilaufgabe wirklich löschen?",
|
||||
"confirm-checklist-delete-dialog": "Wollen Sie die Checkliste wirklich löschen?",
|
||||
"confirm-checklist-delete-popup": "Wollen Sie diese Checkliste wirklich löschen?",
|
||||
"checklistDeletePopup-title": "Checkliste löschen?",
|
||||
"copy-card-link-to-clipboard": "Kopiere Link zur Karte in die Zwischenablage",
|
||||
"copy-text-to-clipboard": "Text in die Zwischenablage kopieren",
|
||||
"linkCardPopup-title": "Karte verknüpfen",
|
||||
"searchElementPopup-title": "Suche",
|
||||
"copyCardPopup-title": "Karte kopieren",
|
||||
@@ -938,6 +942,8 @@
|
||||
"label-color-not-found": "Label-Farbe „%s“ nicht gefunden.",
|
||||
"user-username-not-found": "Nutzername „%s“ nicht gefunden.",
|
||||
"comment-not-found": "Keine Karte gefunden, die „%s“ in einem Kommentar enthält.",
|
||||
"org-name-not-found": "Organisation '%s' nicht gefunden.",
|
||||
"team-name-not-found": "Team '%s' nicht gefunden.",
|
||||
"globalSearch-title": "Alle Boards durchsuchen",
|
||||
"no-cards-found": "Keine Karten gefunden",
|
||||
"one-card-found": "Eine Karte gefunden",
|
||||
@@ -966,6 +972,9 @@
|
||||
"operator-comment": "Kommentar",
|
||||
"operator-has": "hat",
|
||||
"operator-limit": "Begrenzung",
|
||||
"operator-debug": "Debug",
|
||||
"operator-org": "Organisation",
|
||||
"operator-team": "Team",
|
||||
"predicate-archived": "archiviert",
|
||||
"predicate-open": "offen",
|
||||
"predicate-ended": "beendet",
|
||||
@@ -987,12 +996,15 @@
|
||||
"predicate-member": "Mitglied",
|
||||
"predicate-public": "öffentlich",
|
||||
"predicate-private": "privat",
|
||||
"predicate-selector": "Auswahl",
|
||||
"predicate-projection": "Projektion",
|
||||
"operator-unknown-error": "„%s“ ist kein Operator",
|
||||
"operator-number-expected": "Operator „__operator__“ erwartete eine Zahl, bekam aber „__value__“",
|
||||
"operator-sort-invalid": "Sortierung „%s“ ist ungültig",
|
||||
"operator-status-invalid": "„%s“ ist kein gültiger Status",
|
||||
"operator-has-invalid": "%s ist keine gültige Prüfung auf Existenz",
|
||||
"operator-limit-invalid": "%s ist keine gültige Begrenzung. Die Begrenzung sollte eine positive Ganzzahl sein.",
|
||||
"operator-debug-invalid": "%s ist kein gültiger Debugausdruck",
|
||||
"next-page": "Nächste Seite",
|
||||
"previous-page": "Vorherige Seite",
|
||||
"heading-notes": "Bemerkungen",
|
||||
@@ -1010,6 +1022,8 @@
|
||||
"globalSearch-instructions-operator-member": "`__operator_member__:<username>` – Karten, von denen *<username>* *Mitglied* ist",
|
||||
"globalSearch-instructions-operator-assignee": "`__operator_assignee__:<username>` – Karten, denen *<username>* *zugewiesen* ist",
|
||||
"globalSearch-instructions-operator-creator": "`__operator_creator__:<username>` – Karten, die von *<username>* angelegt wurden",
|
||||
"globalSearch-instructions-operator-org": "`__operator_org__:<display name|short name>` - Karten gehören zu einem Board, dass der Organisation *<name>* zugewiesen ist",
|
||||
"globalSearch-instructions-operator-team": "`__operator_team__:<display name|short name>` - Karten gehören zu einem Board, dass Team *<name>* zugewiesen ist",
|
||||
"globalSearch-instructions-operator-due": "`__operator_due__:<n>` – Karten, die spätestens in *<n>* Tagen fällig sind. `__operator_due__:__predicate_overdue__` zeigt alle Karten, für die die Fälligkeit überschritten ist.",
|
||||
"globalSearch-instructions-operator-created": "`__operator_created__:<n>` – Karten, die vor maximal *<n>* Tagen angelegt wurden",
|
||||
"globalSearch-instructions-operator-modified": "`__operator_modified__:<n>` – Karten, die vor maximal *<n>* Tagen geändert wurden",
|
||||
@@ -1056,6 +1070,8 @@
|
||||
"orphanedFilesReportTitle": "Verwaister Datei-Bericht",
|
||||
"reports": "Berichte",
|
||||
"rulesReportTitle": "Regeln-Bericht",
|
||||
"boardsReportTitle": "Boardbericht",
|
||||
"cardsReportTitle": "Kartenbericht",
|
||||
"copy-swimlane": "Kopiere Swimlane",
|
||||
"copySwimlanePopup-title": "Swimlane kopieren",
|
||||
"display-card-creator": "Karten-Ersteller anzeigen",
|
||||
@@ -1098,7 +1114,7 @@
|
||||
"invite-people-success": "Registrierungseinladung erfolgreich versandt",
|
||||
"invite-people-error": "Fehler beim Versand der Registrierungseinladung",
|
||||
"can-invite-if-same-mailDomainName": "Name der Email-Domain",
|
||||
"to-create-teams-contact-admin": "To create teams, please contact the administrator.",
|
||||
"to-create-teams-contact-admin": "Bitte kontaktieren Sie den Administrator um Teams anlegen zu lassen.",
|
||||
"Node_heap_total_heap_size": "Knoten-Heap: totale Heap-Größe",
|
||||
"Node_heap_total_heap_size_executable": "Knoten-Heap: totale Heap-Größe (Executable)",
|
||||
"Node_heap_total_physical_size": "Knoten-Heap: totale physische Größe",
|
||||
@@ -1113,5 +1129,17 @@
|
||||
"Node_memory_usage_rss": "Knoten-Speicherverbrauch: Resident Set-Größe",
|
||||
"Node_memory_usage_heap_total": "Knoten-Speicherverbrauch: totale Größe des belegten Heaps",
|
||||
"Node_memory_usage_heap_used": "Knoten-Speicherverbrauch: tatsächlicher Speicherverbrauch",
|
||||
"Node_memory_usage_external": "Knoten-Speicherverbrauch: extern"
|
||||
"Node_memory_usage_external": "Knoten-Speicherverbrauch: extern",
|
||||
"add-organizations": "Organisation hinzufügen",
|
||||
"add-organizations-label": "Hinzugefügte Organisationen werden nachfolgend angezeigt:",
|
||||
"remove-organization-from-board": "Sicher, dass du die Organisation von diesem Board entfernen willst?",
|
||||
"to-create-organizations-contact-admin": "Um Organisationen anzulegen, wende dich bitte an den Administrator.",
|
||||
"custom-legal-notice-link-url": "URL zu eigenem Impressum",
|
||||
"acceptance_of_our_legalNotice": "Durch das Einloggen akzeptieren Sie unser",
|
||||
"legalNotice": "Impressum/Datenschutzerklärung",
|
||||
"copied": "Kopiert!",
|
||||
"checklistActionsPopup-title": "Checklistenaktionen",
|
||||
"moveChecklist": "Checkliste verschieben",
|
||||
"moveChecklistPopup-title": "Checkliste verschieben",
|
||||
"newlineBecomesNewChecklistItem": "Neue Zeile wird ein neues Checklistenelement"
|
||||
}
|
||||
@@ -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": "Και __count__ επιπλέον κάρτες",
|
||||
"apply": "Εφαρμογή",
|
||||
"app-is-offline": "Φορτώνει, παρακαλώ περιμένετε. Η ανανέωση της σελίδας θα προκαλέσει απώλεια δεδομένων. Αν η φόρτωση δεν επιτύχει, παρακαλούμε ελέγξτε ότι ο server δεν έχει σταματήσει.",
|
||||
"app-try-reconnect": "Try to reconnect.",
|
||||
"archive": "Μετακίνηση στο Αρχείο",
|
||||
"archive-all": "Μετακίνηση Όλων στο Αρχείο",
|
||||
"archive-board": "Μετακίνηση Πίνακα στο Αρχείο",
|
||||
@@ -156,7 +158,7 @@
|
||||
"card-archived": "Αυτή η κάρτα μετακινήθηκε στο Αρχείο.",
|
||||
"board-archived": "Αυτός ο πίνακας μετακινήθηκε στο Αρχείο.",
|
||||
"card-comments-title": "Αυτή η κάρτα έχει %s σχόλιο.",
|
||||
"card-delete-notice": "Η Διαγραφή είναι μόνιμη. Θα χάσετε όλες τις ενέργειες που σχετίζονται με αυτή την κάρτα. ",
|
||||
"card-delete-notice": "Η Διαγραφή είναι μόνιμη. Θα χάσετε όλες τις ενέργειες που σχετίζονται με αυτή την κάρτα.",
|
||||
"card-delete-pop": "Όλες οι ενέργειες θα αφαιρεθούν από τη ροή δραστηριοτήτων και δε θα μπορείτε να ξανανοίξετε την κάρτα. Δεν υπάρχει δυνατότητα επαναφοράς.",
|
||||
"card-delete-suggest-archive": "Μπορείτε να μετακινήσετε μια κάρτα στο Αρχείο για να την αφαιρέσετε από τον πίνακα και να διατηρήσετε τη δραστηριότητα.",
|
||||
"card-archive-pop": "Card will not be visible at this list after archiving card.",
|
||||
@@ -169,7 +171,7 @@
|
||||
"card-edit-labels": "Επεξεργασία ετικετών",
|
||||
"card-edit-members": "Επεξεργασία μελών",
|
||||
"card-labels-title": "Αλλαγή ετικετών για την κάρτα.",
|
||||
"card-members-title": "Προσθήκη ή διαγραφή μελών του πίνακα από την κάρτα. ",
|
||||
"card-members-title": "Προσθήκη ή διαγραφή μελών του πίνακα από την κάρτα.",
|
||||
"card-start": "Έναρξη",
|
||||
"card-start-on": "Αρχίζει σε",
|
||||
"cardAttachmentsPopup-title": "Συνημμένο Από",
|
||||
@@ -239,7 +241,7 @@
|
||||
"clipboard": "Clipboard ή drag & drop",
|
||||
"close": "Κλείσιμο",
|
||||
"close-board": "Κλείσιμο Πίνακα",
|
||||
"close-board-pop": "Μελλοντικά μπορείτε να επαναφέρετε τον πίνακα κάνοντας κλικ στο κουμπί \"Αρχειοθέτηση\" από την αρχική επικεφαλίδα. ",
|
||||
"close-board-pop": "Μελλοντικά μπορείτε να επαναφέρετε τον πίνακα κάνοντας κλικ στο κουμπί \"Αρχειοθέτηση\" από την αρχική επικεφαλίδα.",
|
||||
"close-card": "Close Card",
|
||||
"color-black": "μαύρο",
|
||||
"color-blue": "μπλε",
|
||||
@@ -279,8 +281,10 @@
|
||||
"worker-desc": "Μπορεί μόνο να μετακινεί κάρτες, να αναθέτει μια κάρτα στον εαυτό του και να σχολιάζει.",
|
||||
"computer": "Υπολογιστής",
|
||||
"confirm-subtask-delete-dialog": "Είστε σίγουροι ότι θέλετε να σβήσετε την υποεργασία;",
|
||||
"confirm-checklist-delete-dialog": "Είστε σίγουρι ότι θέλετε να διαγράψετε τη λίστα ελέγχου - checklist;",
|
||||
"confirm-checklist-delete-popup": "Are you sure you want to delete the checklist?",
|
||||
"checklistDeletePopup-title": "Delete Checklist?",
|
||||
"copy-card-link-to-clipboard": "Αντιγραφή του συνδέσμου της κάρτας στο clipboard",
|
||||
"copy-text-to-clipboard": "Copy text to clipboard",
|
||||
"linkCardPopup-title": "Σύνδεση Κάρτας",
|
||||
"searchElementPopup-title": "Αναζήτηση",
|
||||
"copyCardPopup-title": "Αντιγραφή Κάρτας",
|
||||
@@ -351,8 +355,8 @@
|
||||
"error-board-notAdmin": "Πρέπει να είστε διαχειριστής του πίνακα αυτού για να προβείτε σε αυτό",
|
||||
"error-board-notAMember": "Πρέπει να είστε μέλος του πίνακα αυτού για να προβείτε σε αυτό",
|
||||
"error-json-malformed": "Το κείμενο δεν είναι έγκυρο JSON",
|
||||
"error-json-schema": "Τα JSON δεδομένα σας δεν περιλαμβάνουν την ορθή πληροφορία στην ορθή μορφοποίηση ",
|
||||
"error-csv-schema": "Το CSV(Comma Separated Values)/TSV (Tab Separated Values) σας δεν περιλαμβάνει την ορθή πληροφορία σε ορθή μορφοποίηση ",
|
||||
"error-json-schema": "Τα JSON δεδομένα σας δεν περιλαμβάνουν την ορθή πληροφορία στην ορθή μορφοποίηση",
|
||||
"error-csv-schema": "Το CSV(Comma Separated Values)/TSV (Tab Separated Values) σας δεν περιλαμβάνει την ορθή πληροφορία σε ορθή μορφοποίηση",
|
||||
"error-list-doesNotExist": "Η λίστα δεν υπάρχει",
|
||||
"error-user-doesNotExist": "Ο χρήστης δεν υπάρχει",
|
||||
"error-user-notAllowSelf": "Δε μπορείτε να αυτοπροσκληθείτε",
|
||||
@@ -938,6 +942,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 +972,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 +996,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 +1022,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 +1070,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 +1129,17 @@
|
||||
"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"
|
||||
}
|
||||
File diff suppressed because it is too large.
Load diff
Loaded 100 of 216 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user