mirror of
https://github.com/wekan/wekan.git
synced 2026-11-06 12:45:03 -05:00
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
13979389ca | ||
|
|
350a52935a | ||
|
|
945e57bb43 | ||
|
|
3c374a2891 | ||
|
|
c9074bd8d9 | ||
|
|
bc685c59e0 | ||
|
|
aa53ad38fc | ||
|
|
875442f1ce | ||
|
|
a8c071f04c | ||
|
|
ef6c9c66af | ||
|
|
3df38447e9 | ||
|
|
338aabc02f | ||
|
|
912717ebf9 | ||
|
|
9f1a2ec625 | ||
|
|
93f0a69c53 | ||
|
|
2846522450 | ||
|
|
be8374d100 | ||
|
|
399f63cef6 | ||
|
|
adf8f7b69a | ||
|
|
8e9206bdee | ||
|
|
1946ba150d | ||
|
|
60cb5fb017 | ||
|
|
1892a17855 | ||
|
|
588e051f0f | ||
|
|
1c5857f064 | ||
|
|
1067542b94 | ||
|
|
538e197147 | ||
|
|
36db6c6e2d | ||
|
|
e53b63541e | ||
|
|
d6ca13a61d | ||
|
|
7caf817c81 | ||
|
|
286617e7be | ||
|
|
a423f7883e | ||
|
|
6d949ccdb4 | ||
|
|
0e0ac36788 | ||
|
|
99ab6d13d4 | ||
|
|
dcf7232958 | ||
|
|
a4408b55ed | ||
|
|
06f0ceebd1 | ||
|
|
5fe78a477c | ||
|
|
7ef8de50bd | ||
|
|
6646b8638e | ||
|
|
46840c9373 | ||
|
|
76bd3bfe1d | ||
|
|
2a2ed1eb2c | ||
|
|
a533605608 | ||
|
|
7749c0bd9a | ||
|
|
a37caf459e | ||
|
|
1c0a1e021a | ||
|
|
f483b162ce | ||
|
|
42fad8fb98 | ||
|
|
316acd0366 | ||
|
|
f80ecded0a | ||
|
|
40a5422e75 | ||
|
|
726fd5d60d | ||
|
|
211656e9da | ||
|
|
5eb4eb04c4 | ||
|
|
fb3b47e2bb | ||
|
|
14ac099e87 | ||
|
|
f83ee124d0 | ||
|
|
59ee616304 | ||
|
|
25989b9736 | ||
|
|
fef6433b75 | ||
|
|
ea72ce1fa2 | ||
|
|
26e326a204 | ||
|
|
ebb356cf2d | ||
|
|
d6142e4b75 | ||
|
|
c7b554afd9 | ||
|
|
30c1b5cca8 | ||
|
|
0c58bcf99c | ||
|
|
f3d58339ae | ||
|
|
67c6dd7bee | ||
|
|
f2d52b55c8 | ||
|
|
8c72531e6d | ||
|
|
b2f19ed714 | ||
|
|
e5359dc838 | ||
|
|
6fd3c0fa6b | ||
|
|
981a641bce | ||
|
|
47c70f03a2 | ||
|
|
030359aa0e | ||
|
|
81c9bb6899 | ||
|
|
4d192a0165 | ||
|
|
33a8de7bb5 | ||
|
|
9125ab440d | ||
|
|
1c966ed7b4 | ||
|
|
6a4b03324c | ||
|
|
4a8dcde8ee | ||
|
|
c2139662cd | ||
|
|
c0ecfb87b0 | ||
|
|
7673c77c57 | ||
|
|
66c2140911 | ||
|
|
ea3144492e | ||
|
|
10a9306abd | ||
|
|
76aae41637 | ||
|
|
49071ca5fd | ||
|
|
08e3ca3435 | ||
|
|
6b7b464acc | ||
|
|
767d8e66e7 | ||
|
|
e30edce73e | ||
|
|
f5796faa84 | ||
|
|
b48297df22 | ||
|
|
c262620993 | ||
|
|
41685536d7 | ||
|
|
92052458f5 | ||
|
|
6c3170360b | ||
|
|
cd3a27941c | ||
|
|
8a98f03f1a | ||
|
|
5552c17eba | ||
|
|
92733b24d1 | ||
|
|
806ad78637 | ||
|
|
9e557f6887 | ||
|
|
ad9daba60d | ||
|
|
2c92524cf4 | ||
|
|
06e374f0ff | ||
|
|
48ba81eb3d | ||
|
|
0767f50af8 | ||
|
|
68610e5066 | ||
|
|
ba9e2debe2 | ||
|
|
6c8a5cc580 | ||
|
|
3a7eece244 | ||
|
|
bf27ffb92e | ||
|
|
3fc9c6efe7 | ||
|
|
fe2015735a | ||
|
|
2ab34d3b87 | ||
|
|
79ea4d6d1e | ||
|
|
54f7361767 | ||
|
|
0a7ffe4cb0 | ||
|
|
0e714a90e0 | ||
|
|
5e3a9dc059 | ||
|
|
6e1ef3d94a | ||
|
|
bf48d4371c | ||
|
|
2f2aa7b08a | ||
|
|
20b0422024 | ||
|
|
dcb9fb7465 | ||
|
|
3a287a494b | ||
|
|
0926943670 | ||
|
|
06e26d8d89 | ||
|
|
94953a1c97 | ||
|
|
02e9795816 | ||
|
|
c29cff3822 | ||
|
|
29216599e4 | ||
|
|
3b65113d05 | ||
|
|
a182482cfb | ||
|
|
9022e9949f | ||
|
|
cecf69af02 | ||
|
|
b7dbeba7de | ||
|
|
c6ee58ef88 | ||
|
|
1b3135a79f | ||
|
|
131959e050 | ||
|
|
3f3b4746a9 | ||
|
|
30d154724a | ||
|
|
16130b3f73 | ||
|
|
47427f89b0 | ||
|
|
384d80a647 | ||
|
|
43d11af631 | ||
|
|
9bda4372a5 | ||
|
|
61223503e3 | ||
|
|
4d2ad079dc | ||
|
|
50c071682b | ||
|
|
015ccb7a28 | ||
|
|
b9aed314f3 | ||
|
|
452e2e2408 | ||
|
|
9370c1d472 | ||
|
|
8143dc9196 | ||
|
|
98ba18b052 | ||
|
|
9860f20be3 | ||
|
|
cfbb06ed1f | ||
|
|
e39760eb19 | ||
|
|
b3da55f85c | ||
|
|
bc4b637f06 | ||
|
|
c993c8f47e | ||
|
|
40470bedb3 | ||
|
|
912479baa4 | ||
|
|
cfbf3e320c | ||
|
|
4431ec5a27 | ||
|
|
d7784a8d38 | ||
|
|
2c4ed5f298 | ||
|
|
6a97aeb60c | ||
|
|
c7dc912dd4 | ||
|
|
0ee886692e | ||
|
|
34fef627a1 | ||
|
|
52d36d3780 | ||
|
|
8555c24eb2 | ||
|
|
c41c26e5a1 | ||
|
|
35cc9b3fcc | ||
|
|
dbfd219491 | ||
|
|
0da5f26668 | ||
|
|
8bf40e219a | ||
|
|
8f1f8c0fb9 | ||
|
|
386a65d6c6 | ||
|
|
a73ce72e46 | ||
|
|
d0616d8d67 | ||
|
|
6ad007a5f1 | ||
|
|
95d3e5cdc6 | ||
|
|
08a3506f12 | ||
|
|
520f295733 | ||
|
|
7da5121ddd | ||
|
|
3222625286 | ||
|
|
05d952b864 | ||
|
|
a3837ccbc7 | ||
|
|
ac8199177f | ||
|
|
140a134a11 | ||
|
|
c1b3e5367c | ||
|
|
b637a8e8ea | ||
|
|
999323526c | ||
|
|
2e0168283e | ||
|
|
13039c895a | ||
|
|
4148238af3 | ||
|
|
7a98445370 | ||
|
|
7ef3bba9f7 | ||
|
|
492306453c | ||
|
|
e12353bd7e | ||
|
|
a3622ddc1d | ||
|
|
ac95be9e41 | ||
|
|
4a3fc42d1f | ||
|
|
557f9709ac | ||
|
|
4468c71d98 | ||
|
|
c8491749e0 | ||
|
|
e5123f2d81 | ||
|
|
41664f16a3 | ||
|
|
8c9c0e9316 | ||
|
|
f21bd16cec | ||
|
|
edc5a5b6a2 | ||
|
|
7d4de21be0 | ||
|
|
5babe0358d | ||
|
|
62ef1fe7cc | ||
|
|
4be5727a18 | ||
|
|
e128a5775d | ||
|
|
ba9f9705d4 | ||
|
|
3aae07695c | ||
|
|
4393deb130 | ||
|
|
83ae1d4a19 | ||
|
|
94992fca44 | ||
|
|
a8af5343a7 | ||
|
|
070e8831b4 | ||
|
|
f177e416ee | ||
|
|
ffea7aff99 | ||
|
|
01b16566c8 | ||
|
|
549b15000b | ||
|
|
d05b84dff9 | ||
|
|
c6cad13f1e | ||
|
|
a8d1210655 | ||
|
|
45d33fa2e4 | ||
|
|
81ceb1ca0f | ||
|
|
923d26ad81 | ||
|
|
583f114c68 | ||
|
|
b29ec93c34 | ||
|
|
c7ee585a62 | ||
|
|
a7721b9048 | ||
|
|
184fd3abdd | ||
|
|
5fd2f1ee8a | ||
|
|
23218d3808 | ||
|
|
9b8de53bfe | ||
|
|
9130410f09 | ||
|
|
1f57a3f62e | ||
|
|
6938cec583 | ||
|
|
3c2cc351f4 | ||
|
|
ebeadeef60 | ||
|
|
7d59ae93f9 | ||
|
|
59e15d262f | ||
|
|
712417b379 | ||
|
|
cad55d57d7 | ||
|
|
cca7e59eb2 | ||
|
|
59a358903a | ||
|
|
2eadd3eb8b | ||
|
|
0261bb592e | ||
|
|
7862e280ec | ||
|
|
13fecfae27 | ||
|
|
b7819cad69 | ||
|
|
028fba9996 | ||
|
|
ce94433c46 | ||
|
|
442eefbe6b | ||
|
|
84c3b38052 | ||
|
|
8557d91468 | ||
|
|
949a3a1337 | ||
|
|
24288919e2 | ||
|
|
92c57fc91e | ||
|
|
9d1e7abd07 | ||
|
|
8dfdbe7a16 | ||
|
|
15fbe7ca50 | ||
|
|
9aa8bc8921 | ||
|
|
e90791fdbc | ||
|
|
b869e3efb6 | ||
|
|
7e8073d621 | ||
|
|
c10f7b6134 | ||
|
|
1a71abbc1d | ||
|
|
0a46d06c1f | ||
|
|
23595674cf | ||
|
|
6fead14c11 | ||
|
|
52d54f35a3 | ||
|
|
3c1eff6241 | ||
|
|
fb2972396a | ||
|
|
4d9f76cc68 | ||
|
|
924c579680 | ||
|
|
ca2ea2c13e | ||
|
|
b579dc598b | ||
|
|
04c5f60287 | ||
|
|
123789aff0 | ||
|
|
74b66fdcaf | ||
|
|
3f09b54e04 | ||
|
|
c39403c307 | ||
|
|
13ea7bf3d7 | ||
|
|
dc2835d341 | ||
|
|
94ff2d6a9e | ||
|
|
6479c6a5c5 | ||
|
|
a1ddf8e6d2 | ||
|
|
102b39cd29 | ||
|
|
b7373a27b8 | ||
|
|
fb0b762293 | ||
|
|
5b799b4536 | ||
|
|
8050d7353d | ||
|
|
66b1736bb3 | ||
|
|
f33ea5baf0 | ||
|
|
5959fd1fd0 | ||
|
|
c8ec8d456b | ||
|
|
87b394949e | ||
|
|
d93481d840 | ||
|
|
20fa441cfe | ||
|
|
46281542c5 | ||
|
|
5de6d5954a | ||
|
|
7a3c340d65 | ||
|
|
5e8669be4e | ||
|
|
df40384200 | ||
|
|
515556a784 | ||
|
|
af63259f09 | ||
|
|
bb807d53ba | ||
|
|
38279e2a32 | ||
|
|
3e6b396d09 | ||
|
|
42fc182832 | ||
|
|
3f1bba4f1a | ||
|
|
b008986122 | ||
|
|
26b30c817c | ||
|
|
b1083607d4 | ||
|
|
78f9a3303e | ||
|
|
a5519983fe | ||
|
|
bc0a879ca1 | ||
|
|
4c016169c5 | ||
|
|
46c29a0b97 | ||
|
|
9ab0efe87a | ||
|
|
6638d8215f | ||
|
|
e1a00090ba | ||
|
|
44bfe89ea8 | ||
|
|
b75e16f104 | ||
|
|
695cdfcc4e | ||
|
|
285ef2e36d | ||
|
|
fb3aa6ef4f | ||
|
|
0eb5cd05f5 | ||
|
|
3d1c70b96b | ||
|
|
946c288925 | ||
|
|
04464dcdb3 | ||
|
|
8a4f25527e | ||
|
|
581fd9c9fb | ||
|
|
fbce80a4c8 | ||
|
|
1ee3215cf3 | ||
|
|
95efcbe717 | ||
|
|
594d8a8ba1 | ||
|
|
9933f3a583 | ||
|
|
23bcf88aa2 | ||
|
|
21009f5ffe | ||
|
|
2810520612 | ||
|
|
3e088b4eb1 | ||
|
|
8e98eebe03 | ||
|
|
1f11f8add5 | ||
|
|
7192bc944b | ||
|
|
04aaa6f30c | ||
|
|
4405693b1f | ||
|
|
47380244b8 | ||
|
|
4640effb16 | ||
|
|
01a1eb177e | ||
|
|
0afac8bbff | ||
|
|
0a59e9732e | ||
|
|
ed92db87bc | ||
|
|
e892a6104a | ||
|
|
d489b4bf23 | ||
|
|
8c6df7f20c | ||
|
|
49d0fb2eae | ||
|
|
edf08c8cd4 | ||
|
|
ebe6946233 | ||
|
|
54aad2d067 | ||
|
|
d06d22fd65 | ||
|
|
940fbda494 | ||
|
|
58cd17468c | ||
|
|
977c63eb2f | ||
|
|
b9cbab2577 | ||
|
|
2dafd52610 | ||
|
|
3b95728567 | ||
|
|
825742359e | ||
|
|
56e29dae33 | ||
|
|
4b005b4b39 | ||
|
|
8fb1a45cee | ||
|
|
41c1dde504 | ||
|
|
985ee3df91 | ||
|
|
467835192f | ||
|
|
7a929024f2 | ||
|
|
6698c34dbb | ||
|
|
3fbf9ab98f | ||
|
|
bd747cea24 | ||
|
|
be61e7c10c | ||
|
|
515275583e | ||
|
|
e386c16a7f | ||
|
|
3bba30cc1e | ||
|
|
85f02a1b7c | ||
|
|
528c5f2627 | ||
|
|
780e453cf5 | ||
|
|
f3ebc4a28e | ||
|
|
7df32ff4ac | ||
|
|
985882a4ad | ||
|
|
986bc27001 | ||
|
|
053f944691 | ||
|
|
85080519a1 | ||
|
|
7569cc54ab | ||
|
|
923f5d6bb1 | ||
|
|
c8b82576a3 | ||
|
|
aa8926e61c | ||
|
|
6d6b9c831a | ||
|
|
650ed70f92 | ||
|
|
a3d37e621c | ||
|
|
06799b19b0 | ||
|
|
e6a13d7220 | ||
|
|
45e2827516 | ||
|
|
0b395d03f6 | ||
|
|
2d8ac3bf80 | ||
|
|
301580d61a | ||
|
|
b0a2c590fe | ||
|
|
9bb56d3fc0 | ||
|
|
8162654d6f | ||
|
|
b33a3ef254 | ||
|
|
a89c52cfdb | ||
|
|
06aaf7cb8d | ||
|
|
f929cdae9c | ||
|
|
20eb6338de | ||
|
|
6c76c277c7 | ||
|
|
49ef80ab6c | ||
|
|
8b4193149b | ||
|
|
2b4dd3b5ce | ||
|
|
006560b96d | ||
|
|
32ec95ffa8 | ||
|
|
10c2512d74 | ||
|
|
28e5b0bd5b | ||
|
|
87fc4f936a | ||
|
|
71d3135bd2 | ||
|
|
6052b0d042 | ||
|
|
e83b0ac651 | ||
|
|
30ada60862 | ||
|
|
d136a5206c | ||
|
|
ea908adbf9 | ||
|
|
97d0eada57 | ||
|
|
352546f554 | ||
|
|
b583e67ae8 | ||
|
|
9de7040401 | ||
|
|
8951d0aa57 | ||
|
|
582bc3a4c4 | ||
|
|
5f21823c43 | ||
|
|
11162585ca | ||
|
|
dad5d2a905 | ||
|
|
2d683ea198 | ||
|
|
c082a48e67 | ||
|
|
ba387bcc84 | ||
|
|
c8d1a576b0 | ||
|
|
3e691f8b25 | ||
|
|
f700970cd4 | ||
|
|
2828027cc8 | ||
|
|
4a5d05a19f | ||
|
|
0867f728d1 | ||
|
|
0bd8b298d7 | ||
|
|
6d8cf57868 | ||
|
|
4790d31ff7 | ||
|
|
d7243bba77 | ||
|
|
0225eefa66 | ||
|
|
18240c9d07 | ||
|
|
4b4fcda66d | ||
|
|
97c6b65315 | ||
|
|
8f176421da | ||
|
|
0bd9f309a1 | ||
|
|
6fb9529518 | ||
|
|
e6c59fc9b0 | ||
|
|
a12d465881 | ||
|
|
a921bde6ac | ||
|
|
8fbfd5ad0a | ||
|
|
acaefab0f4 | ||
|
|
952affc6df | ||
|
|
521e840b54 | ||
|
|
752a558b30 | ||
|
|
40c077101a | ||
|
|
f7075f4ccb | ||
|
|
9fc5283856 | ||
|
|
e0d63db1ab | ||
|
|
d519429ea1 | ||
|
|
e4d3ae4c3f | ||
|
|
f7e45273a1 | ||
|
|
f57fc3cd6e | ||
|
|
033b8c5d48 | ||
|
|
ad26e57e78 | ||
|
|
e9e3e14695 | ||
|
|
e127c33bae | ||
|
|
5192f4a326 | ||
|
|
2260f214ed | ||
|
|
2b91557ad2 | ||
|
|
c1f0017867 |
No files matched your search
@@ -38,7 +38,7 @@ jobs:
|
||||
# https://github.com/docker/login-action
|
||||
- name: Log into registry ${{ env.REGISTRY }}
|
||||
if: github.event_name != 'pull_request'
|
||||
uses: docker/login-action@f4ef78c080cd8ba55a85445d5b36e214a81df20a
|
||||
uses: docker/login-action@465a07811f14bebb1938fbed4728c6a1ff8901fc
|
||||
with:
|
||||
registry: ${{ env.REGISTRY }}
|
||||
username: ${{ github.actor }}
|
||||
@@ -48,14 +48,14 @@ jobs:
|
||||
# https://github.com/docker/metadata-action
|
||||
- name: Extract Docker metadata
|
||||
id: meta
|
||||
uses: docker/metadata-action@c4ee3adeed93b1fa6a762f209fb01608c1a22f1e
|
||||
uses: docker/metadata-action@818d4b7b91585d195f67373fd9cb0332e31a7175
|
||||
with:
|
||||
images: ${{ env.REGISTRY }}/${{ env.IMAGE_NAME }}
|
||||
|
||||
# Build and push Docker image with Buildx (don't push on PR)
|
||||
# https://github.com/docker/build-push-action
|
||||
- name: Build and push Docker image
|
||||
uses: docker/build-push-action@3b5e8027fcad23fda98b2e3ac259d8d67585f671
|
||||
uses: docker/build-push-action@2eb1c1961a95fc15694676618e422e8ba1d63825
|
||||
with:
|
||||
context: .
|
||||
push: ${{ github.event_name != 'pull_request' }}
|
||||
|
||||
+92
-61
@@ -6,7 +6,7 @@
|
||||
meteor-base@1.5.1
|
||||
|
||||
# Build system
|
||||
ecmascript@0.16.7-beta2120.2
|
||||
ecmascript@0.16.7
|
||||
standard-minifier-js@2.8.1
|
||||
mquandalle:jade
|
||||
coffeescript@2.4.1!
|
||||
@@ -21,7 +21,7 @@ cottz:publish-relations
|
||||
dburles:collection-helpers
|
||||
idmontie:migrations
|
||||
easy:search
|
||||
mongo@1.16.6-beta2120.2
|
||||
mongo@1.16.6
|
||||
mquandalle:collection-mutations
|
||||
|
||||
# Account system
|
||||
@@ -43,33 +43,110 @@ jquery@3.0.0!
|
||||
random@1.2.1
|
||||
reactive-dict@1.3.1
|
||||
session@1.2.1
|
||||
tracker@1.3.2-beta2120.2
|
||||
underscore@1.0.13-beta2120.2
|
||||
tracker@1.3.2
|
||||
underscore@1.0.13
|
||||
arillo:flow-router-helpers
|
||||
audit-argument-checks@1.0.7
|
||||
kadira:blaze-layout
|
||||
kadira:dochead
|
||||
mquandalle:autofocus
|
||||
ongoworks:speakingurl
|
||||
raix:handlebar-helpers
|
||||
http@2.0.0! # force new http package
|
||||
|
||||
# Datepicker
|
||||
rajit:bootstrap3-datepicker
|
||||
rajit:bootstrap3-datepicker-de
|
||||
rajit:bootstrap3-datepicker-tr
|
||||
rajit:bootstrap3-datepicker-ja
|
||||
rajit:bootstrap3-datepicker-fr
|
||||
rajit:bootstrap3-datepicker-it
|
||||
rajit:bootstrap3-datepicker-th
|
||||
rajit:bootstrap3-datepicker-nl
|
||||
rajit:bootstrap3-datepicker-es
|
||||
rajit:bootstrap3-datepicker-lv
|
||||
rajit:bootstrap3-datepicker-sv
|
||||
rajit:bootstrap3-datepicker-gl
|
||||
rajit:bootstrap3-datepicker-eu
|
||||
rajit:bootstrap3-datepicker-vi
|
||||
rajit:bootstrap3-datepicker-no
|
||||
rajit:bootstrap3-datepicker-en-gb
|
||||
rajit:bootstrap3-datepicker-ro
|
||||
rajit:bootstrap3-datepicker-rs
|
||||
rajit:bootstrap3-datepicker-ru
|
||||
rajit:bootstrap3-datepicker-bs
|
||||
rajit:bootstrap3-datepicker-mn
|
||||
rajit:bootstrap3-datepicker-id
|
||||
rajit:bootstrap3-datepicker-fa
|
||||
rajit:bootstrap3-datepicker-ko
|
||||
rajit:bootstrap3-datepicker-pt
|
||||
rajit:bootstrap3-datepicker-sl
|
||||
rajit:bootstrap3-datepicker-sq
|
||||
rajit:bootstrap3-datepicker-cy
|
||||
rajit:bootstrap3-datepicker-ka
|
||||
rajit:bootstrap3-datepicker-sr
|
||||
rajit:bootstrap3-datepicker-az
|
||||
rajit:bootstrap3-datepicker-cs
|
||||
rajit:bootstrap3-datepicker-me
|
||||
rajit:bootstrap3-datepicker-ta
|
||||
rajit:bootstrap3-datepicker-eo
|
||||
rajit:bootstrap3-datepicker-oc
|
||||
rajit:bootstrap3-datepicker-he
|
||||
rajit:bootstrap3-datepicker-sw
|
||||
rajit:bootstrap3-datepicker-rs-latin
|
||||
rajit:bootstrap3-datepicker-da
|
||||
rajit:bootstrap3-datepicker-pt-br
|
||||
rajit:bootstrap3-datepicker-br
|
||||
rajit:bootstrap3-datepicker-it-ch
|
||||
rajit:bootstrap3-datepicker-en-za
|
||||
rajit:bootstrap3-datepicker-en-ie
|
||||
rajit:bootstrap3-datepicker-en-ca
|
||||
rajit:bootstrap3-datepicker-uz-latn
|
||||
rajit:bootstrap3-datepicker-ms
|
||||
rajit:bootstrap3-datepicker-uk
|
||||
rajit:bootstrap3-datepicker-hu
|
||||
rajit:bootstrap3-datepicker-fo
|
||||
rajit:bootstrap3-datepicker-kr
|
||||
rajit:bootstrap3-datepicker-hi
|
||||
rajit:bootstrap3-datepicker-km
|
||||
rajit:bootstrap3-datepicker-fi
|
||||
rajit:bootstrap3-datepicker-is
|
||||
rajit:bootstrap3-datepicker-kh
|
||||
rajit:bootstrap3-datepicker-bg
|
||||
rajit:bootstrap3-datepicker-bn
|
||||
rajit:bootstrap3-datepicker-pl
|
||||
rajit:bootstrap3-datepicker-et
|
||||
rajit:bootstrap3-datepicker-ar
|
||||
rajit:bootstrap3-datepicker-ca
|
||||
rajit:bootstrap3-datepicker-kk
|
||||
rajit:bootstrap3-datepicker-sk
|
||||
rajit:bootstrap3-datepicker-el
|
||||
rajit:bootstrap3-datepicker-hy
|
||||
rajit:bootstrap3-datepicker-hr
|
||||
rajit:bootstrap3-datepicker-tg
|
||||
rajit:bootstrap3-datepicker-nb
|
||||
rajit:bootstrap3-datepicker-mk
|
||||
rajit:bootstrap3-datepicker-nl-be
|
||||
rajit:bootstrap3-datepicker-zh-cn
|
||||
rajit:bootstrap3-datepicker-ar-tn
|
||||
rajit:bootstrap3-datepicker-en-au
|
||||
rajit:bootstrap3-datepicker-fr-ch
|
||||
rajit:bootstrap3-datepicker-zh-tw
|
||||
rajit:bootstrap3-datepicker-uz-cyrl
|
||||
rajit:bootstrap3-datepicker-sr-latin
|
||||
rajit:bootstrap3-datepicker-en-nz
|
||||
|
||||
# UI components
|
||||
blaze
|
||||
ostrio:i18n
|
||||
reactive-var@1.0.12
|
||||
fortawesome:fontawesome
|
||||
mousetrap:mousetrap
|
||||
mquandalle:jquery-textcomplete
|
||||
mquandalle:mousetrap-bindglobal
|
||||
peerlibrary:blaze-components
|
||||
templates:tabs
|
||||
meteor-autosize
|
||||
rajit:bootstrap3-datepicker
|
||||
shell-server@0.5.0
|
||||
email@2.2.5-beta2120.2
|
||||
horka:swipebox
|
||||
dynamic-import@0.7.3-beta2120.2
|
||||
email@2.2.5
|
||||
dynamic-import@0.7.3
|
||||
cfs:gridfs
|
||||
rzymek:fullcalendar
|
||||
msavin:usercache
|
||||
@@ -82,55 +159,6 @@ percolate:synced-cron
|
||||
cfs:filesystem
|
||||
ostrio:cookies
|
||||
ostrio:files@2.3.0
|
||||
rajit:bootstrap3-datepicker-fi
|
||||
rajit:bootstrap3-datepicker-ar
|
||||
rajit:bootstrap3-datepicker-bg
|
||||
rajit:bootstrap3-datepicker-br
|
||||
rajit:bootstrap3-datepicker-ca
|
||||
rajit:bootstrap3-datepicker-cs
|
||||
rajit:bootstrap3-datepicker-da
|
||||
rajit:bootstrap3-datepicker-de
|
||||
rajit:bootstrap3-datepicker-el
|
||||
rajit:bootstrap3-datepicker-en-gb
|
||||
rajit:bootstrap3-datepicker-eo
|
||||
rajit:bootstrap3-datepicker-es
|
||||
rajit:bootstrap3-datepicker-eu
|
||||
rajit:bootstrap3-datepicker-fa
|
||||
rajit:bootstrap3-datepicker-fr
|
||||
rajit:bootstrap3-datepicker-gl
|
||||
rajit:bootstrap3-datepicker-he
|
||||
rajit:bootstrap3-datepicker-hi
|
||||
rajit:bootstrap3-datepicker-hu
|
||||
rajit:bootstrap3-datepicker-hy
|
||||
rajit:bootstrap3-datepicker-id
|
||||
rajit:bootstrap3-datepicker-it
|
||||
rajit:bootstrap3-datepicker-ja
|
||||
rajit:bootstrap3-datepicker-ka
|
||||
rajit:bootstrap3-datepicker-km
|
||||
rajit:bootstrap3-datepicker-ko
|
||||
rajit:bootstrap3-datepicker-lv
|
||||
rajit:bootstrap3-datepicker-mk
|
||||
rajit:bootstrap3-datepicker-mn
|
||||
rajit:bootstrap3-datepicker-nb
|
||||
rajit:bootstrap3-datepicker-nl
|
||||
rajit:bootstrap3-datepicker-oc
|
||||
rajit:bootstrap3-datepicker-pl
|
||||
rajit:bootstrap3-datepicker-pt-br
|
||||
rajit:bootstrap3-datepicker-pt
|
||||
rajit:bootstrap3-datepicker-ro
|
||||
rajit:bootstrap3-datepicker-ru
|
||||
rajit:bootstrap3-datepicker-sl
|
||||
rajit:bootstrap3-datepicker-sr
|
||||
rajit:bootstrap3-datepicker-sv
|
||||
rajit:bootstrap3-datepicker-sw
|
||||
rajit:bootstrap3-datepicker-ta
|
||||
rajit:bootstrap3-datepicker-th
|
||||
rajit:bootstrap3-datepicker-tr
|
||||
rajit:bootstrap3-datepicker-uk
|
||||
rajit:bootstrap3-datepicker-vi
|
||||
rajit:bootstrap3-datepicker-zh-cn
|
||||
rajit:bootstrap3-datepicker-zh-tw
|
||||
easylogic:summernote
|
||||
pascoual:pdfkit
|
||||
lmieulet:meteor-coverage
|
||||
meteortesting:mocha@2.0.3
|
||||
@@ -141,4 +169,7 @@ kadira:flow-router
|
||||
spacebars
|
||||
service-configuration@1.3.1
|
||||
communitypackages:picker
|
||||
minifier-css@1.6.4-beta2120.2
|
||||
minifier-css@1.6.4
|
||||
blaze
|
||||
kadira:blaze-layout
|
||||
peerlibrary:blaze-components
|
||||
+1
-1
@@ -1 +1 @@
|
||||
METEOR@2.12-beta.2
|
||||
METEOR@2.12
|
||||
+57
-29
@@ -1,4 +1,4 @@
|
||||
accounts-base@2.2.8-beta2120.2
|
||||
accounts-base@2.2.8
|
||||
accounts-oauth@1.4.2
|
||||
accounts-password@2.3.4
|
||||
aldeed:collection2@2.10.0
|
||||
@@ -10,16 +10,16 @@ allow-deny@1.1.1
|
||||
arillo:flow-router-helpers@0.5.2
|
||||
audit-argument-checks@1.0.7
|
||||
autoupdate@1.8.0
|
||||
babel-compiler@7.10.4-beta2120.2
|
||||
babel-compiler@7.10.4
|
||||
babel-runtime@1.5.1
|
||||
base64@1.0.12
|
||||
binary-heap@1.0.11
|
||||
blaze@2.6.1
|
||||
blaze@2.7.1
|
||||
blaze-tools@1.1.3
|
||||
boilerplate-generator@1.7.1
|
||||
caching-compiler@1.2.2
|
||||
caching-html-compiler@1.2.1
|
||||
callback-hook@1.5.1-beta2120.2
|
||||
callback-hook@1.5.1
|
||||
cfs:access-point@0.1.49
|
||||
cfs:base-package@0.0.30
|
||||
cfs:collection@0.5.5
|
||||
@@ -41,32 +41,30 @@ cfs:worker@0.1.5
|
||||
check@1.3.2
|
||||
coffeescript@2.7.0
|
||||
coffeescript-compiler@2.4.1
|
||||
communitypackages:picker@1.1.0
|
||||
communitypackages:picker@1.1.1
|
||||
cottz:publish-relations@2.0.8
|
||||
dburles:collection-helpers@1.1.0
|
||||
ddp@1.4.1
|
||||
ddp-client@2.6.1
|
||||
ddp-common@1.4.0
|
||||
ddp-rate-limiter@1.2.0-beta2120.2
|
||||
ddp-server@2.6.1-beta2120.2
|
||||
ddp-rate-limiter@1.2.0
|
||||
ddp-server@2.6.1
|
||||
deps@1.0.12
|
||||
diff-sequence@1.1.2
|
||||
dynamic-import@0.7.3-beta2120.2
|
||||
dynamic-import@0.7.3
|
||||
easy:search@2.2.1
|
||||
easylogic:summernote@0.8.8
|
||||
easysearch:components@2.2.2
|
||||
easysearch:core@2.2.2
|
||||
ecmascript@0.16.7-beta2120.2
|
||||
ecmascript-runtime@0.8.1-beta2120.2
|
||||
ecmascript@0.16.7
|
||||
ecmascript-runtime@0.8.1
|
||||
ecmascript-runtime-client@0.12.1
|
||||
ecmascript-runtime-server@0.11.0
|
||||
ejson@1.1.3
|
||||
email@2.2.5-beta2120.2
|
||||
email@2.2.5
|
||||
es5-shim@4.8.0
|
||||
fetch@0.1.3
|
||||
fortawesome:fontawesome@4.7.0
|
||||
geojson-utils@1.0.11
|
||||
horka:swipebox@1.0.2
|
||||
hot-code-push@1.0.4
|
||||
html-tools@1.1.3
|
||||
htmljs@1.1.1
|
||||
@@ -85,7 +83,7 @@ localstorage@1.2.0
|
||||
logging@1.3.2
|
||||
matb33:collection-hooks@1.2.2
|
||||
mdg:validation-error@0.5.1
|
||||
meteor@1.11.2-beta2120.2
|
||||
meteor@1.11.2
|
||||
meteor-autosize@5.0.1
|
||||
meteor-base@1.5.1
|
||||
meteorhacks:aggregate@1.3.0
|
||||
@@ -95,15 +93,15 @@ meteorhacks:subs-manager@1.6.4
|
||||
meteortesting:browser-tests@1.4.2
|
||||
meteortesting:mocha@2.1.0
|
||||
meteortesting:mocha-core@8.0.1
|
||||
minifier-css@1.6.4-beta2120.2
|
||||
minifier-css@1.6.4
|
||||
minifier-js@2.7.5
|
||||
minifiers@1.1.8-faster-rebuild.0
|
||||
minimongo@1.9.3-beta2120.2
|
||||
minimongo@1.9.3
|
||||
modern-browsers@0.1.9
|
||||
modules@0.19.0
|
||||
modules-runtime@0.13.1
|
||||
momentjs:moment@2.29.3
|
||||
mongo@1.16.6-beta2120.2
|
||||
mongo@1.16.6
|
||||
mongo-decimal@0.1.3
|
||||
mongo-dev-server@1.1.0
|
||||
mongo-id@1.0.8
|
||||
@@ -116,15 +114,15 @@ mquandalle:jade-compiler@0.4.5
|
||||
mquandalle:jquery-textcomplete@0.8.0_1
|
||||
mquandalle:mousetrap-bindglobal@0.0.1
|
||||
msavin:usercache@1.8.0
|
||||
npm-mongo@4.16.0-beta2120.2
|
||||
npm-mongo@4.16.0
|
||||
oauth@2.2.0
|
||||
oauth2@1.3.2
|
||||
observe-sequence@1.0.20
|
||||
observe-sequence@1.0.21
|
||||
ongoworks:speakingurl@1.1.0
|
||||
ordered-dict@1.1.0
|
||||
ostrio:cookies@2.7.2
|
||||
ostrio:cstorage@4.0.1
|
||||
ostrio:files@2.3.2
|
||||
ostrio:files@2.3.3
|
||||
ostrio:i18n@3.2.1
|
||||
pascoual:pdfkit@1.0.7
|
||||
peerlibrary:assert@0.3.0
|
||||
@@ -139,56 +137,87 @@ raix:eventemitter@0.1.3
|
||||
raix:handlebar-helpers@0.2.5
|
||||
rajit:bootstrap3-datepicker@1.7.1_1
|
||||
rajit:bootstrap3-datepicker-ar@1.7.1
|
||||
rajit:bootstrap3-datepicker-ar-tn@1.7.1
|
||||
rajit:bootstrap3-datepicker-az@1.7.1
|
||||
rajit:bootstrap3-datepicker-bg@1.7.1
|
||||
rajit:bootstrap3-datepicker-bn@1.7.1
|
||||
rajit:bootstrap3-datepicker-br@1.7.1
|
||||
rajit:bootstrap3-datepicker-bs@1.7.1
|
||||
rajit:bootstrap3-datepicker-ca@1.7.1
|
||||
rajit:bootstrap3-datepicker-cs@1.7.1
|
||||
rajit:bootstrap3-datepicker-cy@1.7.1
|
||||
rajit:bootstrap3-datepicker-da@1.7.1
|
||||
rajit:bootstrap3-datepicker-de@1.7.1
|
||||
rajit:bootstrap3-datepicker-el@1.7.1
|
||||
rajit:bootstrap3-datepicker-en-au@1.7.1
|
||||
rajit:bootstrap3-datepicker-en-ca@1.7.1
|
||||
rajit:bootstrap3-datepicker-en-gb@1.7.1
|
||||
rajit:bootstrap3-datepicker-en-ie@1.7.1
|
||||
rajit:bootstrap3-datepicker-en-nz@1.7.1
|
||||
rajit:bootstrap3-datepicker-en-za@1.7.1
|
||||
rajit:bootstrap3-datepicker-eo@1.7.1
|
||||
rajit:bootstrap3-datepicker-es@1.7.1
|
||||
rajit:bootstrap3-datepicker-et@1.7.1
|
||||
rajit:bootstrap3-datepicker-eu@1.7.1
|
||||
rajit:bootstrap3-datepicker-fa@1.7.1
|
||||
rajit:bootstrap3-datepicker-fi@1.7.1
|
||||
rajit:bootstrap3-datepicker-fo@1.7.1
|
||||
rajit:bootstrap3-datepicker-fr@1.7.1
|
||||
rajit:bootstrap3-datepicker-fr-ch@1.7.1
|
||||
rajit:bootstrap3-datepicker-gl@1.7.1
|
||||
rajit:bootstrap3-datepicker-he@1.7.1
|
||||
rajit:bootstrap3-datepicker-hi@1.7.1
|
||||
rajit:bootstrap3-datepicker-hr@1.7.1
|
||||
rajit:bootstrap3-datepicker-hu@1.7.1
|
||||
rajit:bootstrap3-datepicker-hy@1.7.1
|
||||
rajit:bootstrap3-datepicker-id@1.7.1
|
||||
rajit:bootstrap3-datepicker-is@1.7.1
|
||||
rajit:bootstrap3-datepicker-it@1.7.1
|
||||
rajit:bootstrap3-datepicker-it-ch@1.7.1
|
||||
rajit:bootstrap3-datepicker-ja@1.7.1
|
||||
rajit:bootstrap3-datepicker-ka@1.7.1
|
||||
rajit:bootstrap3-datepicker-kh@1.7.1
|
||||
rajit:bootstrap3-datepicker-kk@1.7.1
|
||||
rajit:bootstrap3-datepicker-km@1.7.1
|
||||
rajit:bootstrap3-datepicker-ko@1.7.1
|
||||
rajit:bootstrap3-datepicker-kr@1.7.1
|
||||
rajit:bootstrap3-datepicker-lv@1.7.1
|
||||
rajit:bootstrap3-datepicker-me@1.7.1
|
||||
rajit:bootstrap3-datepicker-mk@1.7.1
|
||||
rajit:bootstrap3-datepicker-mn@1.7.1
|
||||
rajit:bootstrap3-datepicker-ms@1.7.1
|
||||
rajit:bootstrap3-datepicker-nb@1.7.1
|
||||
rajit:bootstrap3-datepicker-nl@1.7.1
|
||||
rajit:bootstrap3-datepicker-nl-be@1.7.1
|
||||
rajit:bootstrap3-datepicker-no@1.7.1
|
||||
rajit:bootstrap3-datepicker-oc@1.7.1
|
||||
rajit:bootstrap3-datepicker-pl@1.7.1
|
||||
rajit:bootstrap3-datepicker-pt@1.7.1
|
||||
rajit:bootstrap3-datepicker-pt-br@1.7.1
|
||||
rajit:bootstrap3-datepicker-ro@1.7.1
|
||||
rajit:bootstrap3-datepicker-rs@1.7.1
|
||||
rajit:bootstrap3-datepicker-rs-latin@1.7.1
|
||||
rajit:bootstrap3-datepicker-ru@1.7.1
|
||||
rajit:bootstrap3-datepicker-sk@1.7.1
|
||||
rajit:bootstrap3-datepicker-sl@1.7.1
|
||||
rajit:bootstrap3-datepicker-sq@1.7.1
|
||||
rajit:bootstrap3-datepicker-sr@1.7.1
|
||||
rajit:bootstrap3-datepicker-sr-latin@1.7.1
|
||||
rajit:bootstrap3-datepicker-sv@1.7.1
|
||||
rajit:bootstrap3-datepicker-sw@1.7.1
|
||||
rajit:bootstrap3-datepicker-ta@1.7.1
|
||||
rajit:bootstrap3-datepicker-tg@1.7.1
|
||||
rajit:bootstrap3-datepicker-th@1.7.1
|
||||
rajit:bootstrap3-datepicker-tr@1.7.1
|
||||
rajit:bootstrap3-datepicker-uk@1.7.1
|
||||
rajit:bootstrap3-datepicker-uz-cyrl@1.7.1
|
||||
rajit:bootstrap3-datepicker-uz-latn@1.7.1
|
||||
rajit:bootstrap3-datepicker-vi@1.7.1
|
||||
rajit:bootstrap3-datepicker-zh-cn@1.7.1
|
||||
rajit:bootstrap3-datepicker-zh-tw@1.7.1
|
||||
random@1.2.1
|
||||
rate-limit@1.1.1-beta2120.2
|
||||
react-fast-refresh@0.2.7-beta2120.2
|
||||
rate-limit@1.1.1
|
||||
react-fast-refresh@0.2.7
|
||||
reactive-dict@1.3.1
|
||||
reactive-var@1.0.12
|
||||
reload@1.3.1
|
||||
@@ -201,11 +230,11 @@ sha@1.0.9
|
||||
shell-server@0.5.0
|
||||
simple:authenticate-user-by-token@1.2.1
|
||||
simple:json-routes@2.3.1
|
||||
simple:rest-accounts-password@1.2.1
|
||||
simple:rest-accounts-password@1.2.2
|
||||
simple:rest-bearer-token-parser@1.1.1
|
||||
simple:rest-json-error-handler@1.1.1
|
||||
socket-stream-client@0.5.1-beta2120.2
|
||||
spacebars@1.3.0
|
||||
socket-stream-client@0.5.1
|
||||
spacebars@1.4.1
|
||||
spacebars-compiler@1.3.1
|
||||
standard-minifier-js@2.8.1
|
||||
templates:tabs@2.3.0
|
||||
@@ -213,15 +242,14 @@ templating@1.4.1
|
||||
templating-compiler@1.4.1
|
||||
templating-runtime@1.5.0
|
||||
templating-tools@1.2.2
|
||||
tracker@1.3.2-beta2120.2
|
||||
twbs:bootstrap@3.3.6
|
||||
tracker@1.3.2
|
||||
ui@1.0.13
|
||||
underscore@1.0.13-beta2120.2
|
||||
underscore@1.0.13
|
||||
url@1.3.2
|
||||
useraccounts:core@1.16.2
|
||||
useraccounts:flow-routing@1.15.0
|
||||
useraccounts:unstyled@1.14.2
|
||||
webapp@1.13.5-beta2120.2
|
||||
webapp@1.13.5
|
||||
webapp-hashing@1.1.1
|
||||
wekan-accounts-cas@0.1.0
|
||||
wekan-accounts-lockout@1.0.0
|
||||
|
||||
+1
-2
@@ -1,10 +1,9 @@
|
||||
[main]
|
||||
host = https://www.transifex.com
|
||||
lang_map = es_AR: es-AR, es_419: es-LA, es_TX: es-TX, he_IL: he-IL, zh_CN: zh-CN, ar_EG: ar-EG, cs_CZ: cs-CZ, fa_IR: fa-IR, ms_MY: ms-MY, nl_NL: nl-NL, de_CH: de-CH, en_IT: en-IT, uz_UZ: uz-UZ, fr_CH: fr-CH, hi_IN: hi-IN, et_EE: et-EE, es_PE: es-PE, es_MX: es-MX, gl_ES: gl-ES, mn_MN: mn, sl_SI: sl, zh_TW: zh-TW, ast_ES: ast-ES, es_CL: es-CL, ja_JP: ja, lv_LV: lv, ro_RO: ro-RO, az_AZ: az-AZ, cy_GB: cy-GB, gu_IN: gu-IN, pl_PL: pl-PL, vep: ve-PP, en_BR: en-BR, en@ysv: en-YS, hu_HU: hu, ko_KR: ko-KR, pt_BR: pt-BR, zh_HK: zh-HK, zu_ZA: zu-ZA, en_MY: en-MY, ja-Hira: ja-HI, fi_FI: fi, vec: ve-CC, vi_VN: vi-VN, fr_FR: fr-FR, id_ID: id, zh_Hans: zh-Hans, en_DE: en-DE, en_GB: en-GB, el_GR: el-GR, uk_UA: uk-UA, az@latin: az-LA, de_AT: de-AT, uz@Latn: uz-LA, vls: vl-SS, ar_DZ: ar-DZ, bg_BG: bg, es_PY: es-PY, fy_NL: fy-NL, uz@Arab: uz-AR, ru_UA: ru-UA, war: wa-RR
|
||||
lang_map = es_AR: es-AR, es_419: es-LA, es_TX: es-TX, he_IL: he-IL, zh_CN: zh-CN, ar_EG: ar-EG, cs_CZ: cs-CZ, fa_IR: fa-IR, ms_MY: ms-MY, nl_NL: nl-NL, de_CH: de-CH, en_IT: en-IT, uz_UZ: uz-UZ, fr_CH: fr-CH, hi_IN: hi-IN, et_EE: et-EE, es_PE: es-PE, es_MX: es-MX, gl_ES: gl-ES, mn_MN: mn, sl_SI: sl, zh_TW: zh-TW, ast_ES: ast-ES, es_CL: es-CL, ja_JP: ja, lv_LV: lv, ro_RO: ro-RO, az_AZ: az-AZ, cy_GB: cy-GB, gu_IN: gu-IN, pl_PL: pl-PL, vep: ve-PP, en_BR: en-BR, en@ysv: en-YS, hu_HU: hu, ko_KR: ko-KR, pt_BR: pt-BR, zh_HK: zh-HK, zu_ZA: zu-ZA, en_MY: en-MY, ja-Hira: ja-HI, fi_FI: fi, vec: ve-CC, vi_VN: vi-VN, fr_FR: fr-FR, id_ID: id, zh_Hans: zh-Hans, en_DE: en-DE, en_GB: en-GB, el_GR: el-GR, uk_UA: uk-UA, az@latin: az-LA, de_AT: de-AT, uz@Latn: uz-LA, vls: vl-SS, ar_DZ: ar-DZ, bg_BG: bg, es_PY: es-PY, fy_NL: fy-NL, uz@Arab: uz-AR, ru_UA: ru-UA, war: wa-RR, zh_CN.GB2312: zh-GB
|
||||
|
||||
[o:wekan:p:wekan:r:application]
|
||||
file_filter = imports/i18n/data/<lang>.i18n.json
|
||||
source_file = imports/i18n/data/en.i18n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
@@ -1,55 +0,0 @@
|
||||
# This is the configuration of the Transifex tool that we use to manage the
|
||||
# translations on Wekan. Documentation at: http://docs.transifex.com/client.
|
||||
#
|
||||
# Push
|
||||
# ====
|
||||
#
|
||||
# It is recommended that contributors use the Transifex web UI to create and
|
||||
# edit translated strings. However in case a contributor has directly jumped
|
||||
# into the code and made its translations in the corresponding i18n.json file
|
||||
# we can push it using
|
||||
#
|
||||
# > tx push -t -l ar
|
||||
#
|
||||
# Where `ar` is the language identifier. In addition, the project maintainer
|
||||
# should push the English source file to Transifex at least before each release
|
||||
# candidate using:
|
||||
#
|
||||
# > tx push -s
|
||||
#
|
||||
# Pull
|
||||
# ====
|
||||
#
|
||||
# The set of accepted language is directly managed in Transifex, the only
|
||||
# restriction we define to bundle a new language in the application, is that its
|
||||
# completion is at least at 75%.
|
||||
#
|
||||
# We use:
|
||||
#
|
||||
# > tx pull
|
||||
#
|
||||
# to download new versions of existing translations, and
|
||||
#
|
||||
# > tx pull -a --minimum-perc=75
|
||||
#
|
||||
# to download new sufficiently advanced translations.
|
||||
|
||||
[main]
|
||||
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_DZ:ar-DZ, ar_EG:ar-EG, az_AZ:az-AZ, az@latin:az-LA, bg_BG:bg, cs_CZ:cs-CZ, cy_GB:cy-GB, de_AT:de-AT, de_CH:de-CH, en_BR:en-BR, en_DE:en-DE, en_IT:en-IT, en_GB:en-GB, en_MY:en-MY, et_EE:et-EE, ast_ES:ast-ES, es_AR:es-AR, en@ysv:en-YS, 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, ja-Hira:ja-HI, ja_JP:ja, fi_FI:fi, fr_FR:fr-FR, fr_CH:fr-CH, fy_NL:fy-NL, gl_ES:gl-ES, gu_IN:gu-IN, he_IL:he-IL, hi_IN:hi-IN, hu_HU:hu, id_ID:id, mn_MN:mn, ms_MY:ms-MY, nl_NL:nl-NL, ko_KR:ko-KR, lv_LV:lv, pl_PL:pl-PL, pt_BR:pt-BR, ro_RO:ro-RO, ru_UA:ru-UA, sl_SI:sl, uk_UA:uk-UA, uz@Arab:uz-AR, uz@Latn:uz-LA, uz_UZ:uz-UZ, vec:ve-CC, vep:ve-PP, vls:vl-SS, war:wa-RR, vi_VN:vi-VN, zh_CN:zh-CN, zh_TW:zh-TW, zh_Hans:zh-Hans, zh_HK:zh-HK, zu_ZA:zu-ZA
|
||||
|
||||
[wekan.application]
|
||||
file_filter = imports/i18n/data/<lang>.i18n.json
|
||||
source_lang = en
|
||||
type = KEYVALUEJSON
|
||||
|
||||
# We might have a dedicated second resource later to translate the “Welcome
|
||||
# Board” data.
|
||||
#
|
||||
# [wekan.welcomeBoard]
|
||||
# file_filter = private/welcomeBoard/<lang>.json
|
||||
# source_lang = en
|
||||
# type = KEYVALUEJSON
|
||||
+464
-1
@@ -18,6 +18,469 @@ Note:
|
||||
|
||||
[How to upgrade WeKan](https://github.com/wekan/wekan/issues/4585)
|
||||
|
||||
# v7.01 2023-07-21 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix for Calendar View Create Card](https://github.com/wekan/wekan/pull/5019).
|
||||
Thanks to DimDz.
|
||||
- [Minicard didn't show the assignee](https://github.com/wekan/wekan/pull/5021).
|
||||
Thanks to mfilser.
|
||||
- [Helm Chart: Add imagePullPolicy to initContainer. Needed for running wekan when restarting while offline](https://github.com/wekan/charts/pull/21).
|
||||
Thanks to jadams.
|
||||
- [Removing Utils.getCurrentSetting() and use ReactiveCache directly](https://github.com/wekan/wekan/pull/5022).
|
||||
Thanks to mfilser.
|
||||
- [Attachment rename and delete works now again for non board admins](https://github.com/wekan/wekan/pull/5023).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v7.00 2023-07-19 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Speed improvements to Board and List loading](https://github.com/wekan/wekan/pull/5014).
|
||||
Thanks to mfilser.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Forked meteor-globals and meteor-reactive-cache to @wekanteam/meteor-globals and @wekanteam/meteor-reactive-cache to update to newest dependencies](https://github.com/wekan/wekan/commit/1c5857f0646658b121d7612b6176ec5e09c68592).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Added missing @babel/runtime](https://github.com/wekan/wekan/commit/60cb5fb0176ecb623d494613aab196f252c16752).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99.9 2023-07-18 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix "PROPAGATE_OIDC_DATA" mechanism if "info.groups" is undefined](https://github.com/wekan/wekan/pull/5011).
|
||||
Thanks to NotTheEvilOne.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99.8 2023-07-13 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix card creation. Now date fields are checked if they are empty](https://github.com/wekan/wekan/pull/5009).
|
||||
Thanks to helioguardabaxo.
|
||||
- [Helm Chart: Changes for Openshift](https://github.com/wekan/charts/pull/20).
|
||||
Thanks to salleman33.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99.7 2023-07-11 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/pull/5008).
|
||||
Thanks to dependabot.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix setting background image](https://github.com/wekan/wekan/pull/5004).
|
||||
Thanks to VidVidex.
|
||||
- [Added missing character](https://github.com/wekan/wekan/commit/4431ec5a2761d56685d2fca1202679b9bdcd9b81).
|
||||
Thanks to xet7.
|
||||
- [Added back datepicker](https://github.com/wekan/wekan/commit/912479baa48354a68bc807737a3db7975a4cb95c).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99.5 2023-07-10 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Reverted bold of minicard title](https://github.com/wekan/wekan/commit/c7dc912dd4403845a123d9202e930c886788db5b).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99.4 2023-07-10 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Disable migration attachment-cardCopy-fix-boardId-etc. Part 3](https://github.com/wekan/wekan/commit/34fef627a1c02700650fa97fb0fd1d3a36d79776).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99.3 2023-07-10 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix migration attachment-cardCopy-fix-boardId-etc. Part 2](https://github.com/wekan/wekan/commit/8555c24eb21134eda9b4d71494676b39d126ef35).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99.2 2023-07-10 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/pull/5001).
|
||||
Thanks to dependabot.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Added back npm packages: fibers and @mapbox/node-pre-gyp](https://github.com/wekan/wekan/commit/8bf40e219a9fa55b8f2ef19dbf6acc58d646b968).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99.1 2023-07-10 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/95d3e5cdc6136a9778bf7c84812a6d62ef6d4044).
|
||||
Thanks to developers of dependencies.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix for migration "attachment-cardCopy-fix-boardId-etc"](https://github.com/wekan/wekan/pull/4999).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.99 2023-07-09 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Preview PDF](https://github.com/wekan/wekan/pull/4989).
|
||||
Thanks to VidVidex.
|
||||
- [Preview PDF translations](https://github.com/wekan/wekan/commit/83ae1d4a19925363d8f176553fb10a98a77420be).
|
||||
Thanks xet7.
|
||||
- [Preview PDF to have full width, close at top, and improve viewing at mobile](https://github.com/wekan/wekan/commit/4be5727a18472920ed775b8a2024b9c8ca2fdf0a).
|
||||
Thanks to xet7.
|
||||
- [Show Meteor dependency chain with rebuild-wekan.sh](https://github.com/wekan/wekan/commit/ba9f9705d43189d2491266af1fd4817ff34a3b59).
|
||||
Thanks to xet7.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/92c57fc91ea063914730647d0add8dae77187424).
|
||||
Thanks to developers of dependencies.
|
||||
- Added Snap MONGO_URL to rebuild-wekan.sh dev options.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/7d59ae93f9263c383a1c8c8605490d54b1e09ed7),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/3c2cc351f4bbe82b6870bab0e1891823c359e789).
|
||||
Thanks to xet7.
|
||||
- [MongoDB 6.0.7 at Snap](https://github.com/wekan/wekan/commit/5babe0358deae4b01261ee8655ec0e5a38f0344d).
|
||||
Thanks to MongoDB developers.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [New popup scrolls to top and restore previous position after closing again](https://github.com/wekan/wekan/pull/4979).
|
||||
Thanks to mfilser.
|
||||
- [Copy Checklist dialog now set's the last selected board](https://github.com/wekan/wekan/pull/4980).
|
||||
Thanks to mfilser.
|
||||
- [Copy Checklist only copied the checklist items at the first time, now always](https://github.com/wekan/wekan/pull/4981).
|
||||
Thanks to mfilser.
|
||||
- [Attachment copy changes now the boardId, listId and swimlaneId in the collection data](https://github.com/wekan/wekan/pull/4982).
|
||||
Thanks to mfilser.
|
||||
- [Admin attachment view was missing the column header "S3FileId"](https://github.com/wekan/wekan/pull/4983).
|
||||
Thanks to mfilser.
|
||||
- [Global Search, limit 0 is no limit](https://github.com/wekan/wekan/pull/4984).
|
||||
Thanks to mfilser.
|
||||
- [Admin Report, fixing filesize if not a number](https://github.com/wekan/wekan/pull/4985).
|
||||
Thanks to mfilser.
|
||||
- [Global search, found cards count is now substituted by the translation function itself](https://github.com/wekan/wekan/pull/4986).
|
||||
Thanks to mfilser.
|
||||
- [Utils of canModifyCard and canModifyBoard + move this general functions to Utils class](https://github.com/wekan/wekan/pull/4987).
|
||||
Thanks to mfilser.
|
||||
- Set background color only if it exists.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/45d33fa2e459717064969a1729e016d4004e5435),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/c6cad13f1e86fea44c7c16e1a194c6d7164e824a),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/549b15000b538d6e5013cc978c0f49e753fd903a).
|
||||
Thanks to xet7.
|
||||
- [If there is no Custom Field label at minicard, show value full width](https://github.com/wekan/wekan/commit/ffea7aff99db555d357876e1415f9015154782cc).
|
||||
Thanks to koluka and xet7.
|
||||
- API: Fix /api/boards/{boardId}/attachments endpoint.
|
||||
[Part 1](https://github.com/wekan/wekan/pull/4991),
|
||||
[Part 2](https://github.com/wekan/wekan/pull/4992).
|
||||
Thanks to VidVidex.
|
||||
- [Improved attachment gallery and attachment viewer](https://github.com/wekan/wekan/pull/4995).
|
||||
Thanks to VidVidex.
|
||||
- [Removed horka:swipebox](https://github.com/wekan/wekan/commit/4148238af31ad31b6190221ad69db865f9ed5ccc).
|
||||
Thanks to VidVidex and xet7.
|
||||
- [Bold minicard custom field title](https://github.com/wekan/wekan/pull/4993).
|
||||
Thanks to VidVidex.
|
||||
- [Revert first list width change](https://github.com/wekan/wekan/pull/4993).
|
||||
Thanks to xet7.
|
||||
- [Fixed maximum call stack exceeded by removing bootstrap 3, datepicker and summernote. Updated jquery. Disabled attachments viewer that opens empty when opening card. Fixes all npm audit errors](https://github.com/wekan/wekan/commit/140a134a11d0b262f69e4f343dddddb87c978748).
|
||||
Thanks to xet7.
|
||||
- [Fix attachment viewer not being hidden](https://github.com/wekan/wekan/pull/4997).
|
||||
Thanks to VidVidex.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.98 2023-06-22 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- Add checklist at top.
|
||||
[Part 1](https://github.com/wekan/wekan/pull/4973),
|
||||
[Part 2](https://github.com/wekan/wekan/pull/4974).
|
||||
Thanks to mfilser.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Update rebuild-wekan.sh to use local network IP address](https://github.com/wekan/wekan/commit/6479c6a5c516ade68d50849115367be90d3199a2).
|
||||
Thanks to xet7.
|
||||
- Update GitHub Actions.
|
||||
[Part 1](https://github.com/wekan/wekan/pull/4970),
|
||||
[Part 2](https://github.com/wekan/wekan/pull/4971).
|
||||
Thanks to dependabot.
|
||||
|
||||
and adds the following upcoming translations:
|
||||
|
||||
- [Added translations: Cantonese (China) (yue_CN) and Chinese Traditional (zh-Hant)](https://github.com/wekan/wekan/commit/dc2835d3410fcd7fd376a2be765c63236696605e).
|
||||
Thanks to translators.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Wait until user has logged in before fetching language preference](https://github.com/wekan/wekan/pull/4968).
|
||||
Thanks to simon816.
|
||||
- [Always fetch favicons from / path](https://github.com/wekan/wekan/commit/4d9f76cc68f435b1bbeeb51833dbce931f626b6d).
|
||||
Thanks to nebulade.
|
||||
- [Rounding sort number to next integer](https://github.com/wekan/wekan/pull/4975).
|
||||
Thanks to mfilser.
|
||||
- [Reduce list scroll speed while drag/drop the minicard](https://github.com/wekan/wekan/pull/4976).
|
||||
Thanks to mfilser.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.97 2023-06-10 WeKan ® release
|
||||
|
||||
This release adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/d93481d84009922c22a4eaaf49624f7153f737dd).
|
||||
Thanks to developers of dependencies.
|
||||
|
||||
and removes the following features:
|
||||
|
||||
- [Feature: Docker Health Check](https://github.com/wekan/wekan/commit/c8ec8d456b481b10cbf135d5289093a57b2e547f).
|
||||
Thanks to luketainton, mfilser and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.96 2023-06-10 WeKan ® release
|
||||
|
||||
This release fixes the following CRITICAL SECURITY ISSUES:
|
||||
|
||||
- Found and fixed more InvisibleBleed of WeKan.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/4c016169c55e0dc5df9533795ddfec424a053300),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/df40384200d10595a7a9cd582d8534295eec5036).
|
||||
Thanks to xet7.
|
||||
|
||||
and adds the following new features:
|
||||
|
||||
- [Docker Health Check](https://github.com/wekan/wekan/pull/4954).
|
||||
Thanks to luketainton.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix due date filter for next and this week](https://github.com/wekan/wekan/pull/4953).
|
||||
Thanks to helioguardabaxo.
|
||||
- Fixed Rare bug: All Boards page icons random dance. Disabled cards counts and card members at All Boards page.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/b75e16f104390211e3e26c500c0a54687fee329d),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/e1a00090ba0ca192ba30f735a13d1ec5b5aa6bc1),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/9ab0efe87adbc872af287fb8254cccb6dd44aec3).
|
||||
Thanks to xet7.
|
||||
- [Docker build was broken because of wrong curl install](https://github.com/wekan/wekan/pull/4955).
|
||||
Thanks to mfilser.
|
||||
- [Try to fix Docker build by removing empty continuation lines](https://github.com/wekan/wekan/commit/b008986122e258e725379264850d16d06c445db1).
|
||||
Thanks to xet7.
|
||||
- [Clarified required settings for start-wekan.bat and start-wekan.sh](https://github.com/wekan/wekan/commit/3e6b396d0913e6747714a9f87e2161bba0ce525e).
|
||||
Thanks to xet7.
|
||||
- [Fixed drag-drop at Ubuntu Touch Morph Browser and WeKan OpenStore app by changing jquery-ui-touch-punch to newer updated @rwap/jquery-ui-touch-punch](https://github.com/wekan/wekan/commit/af63259f091cb2ade84493a288ea37c53cd37321).
|
||||
Thanks to xet7.
|
||||
- [Try to fix SVG image failed to render](https://github.com/wekan/wekan/commit/7a3c340d657894bf72130b7e51e313e3b020f9cf).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.95 2023-06-07 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Revert smaller swimlane height](https://github.com/wekan/wekan/commit/95efcbe71727ea2be5d2c9a1fa7fd2de76f71ef2).
|
||||
Thanks to kovacs-andras and xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.94 2023-06-07 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Added list position when create a new list on board](https://github.com/wekan/wekan/pull/4938).
|
||||
Thanks to helioguardabaxo.
|
||||
- [Added option to show/hide cover attachment on minicard](https://github.com/wekan/wekan/pull/4939).
|
||||
Thanks to helioguardabaxo.
|
||||
- [Count of attachments on minicard. (Badges renamed to Count of attachments)](https://github.com/wekan/wekan/pull/4940).
|
||||
Thanks to helioguardabaxo.
|
||||
- [Renamed Badge to Count of attachments on minicard. Changed icons to Cover image on minicard](https://github.com/wekan/wekan/commit/825742359ef0738b110ed0904853c604bdbd1bac).
|
||||
Thanks to xet7.
|
||||
- [Added conditional to show after list field only if board has at least one list. Now after list shows the last list by default](https://github.com/wekan/wekan/pull/4941).
|
||||
Thanks to helioguardabaxo.
|
||||
- [Changed Add List to be at left. Before it was at right](https://github.com/wekan/wekan/commit/467835192fbcd9d4016674fa2ee406258cc106e7).
|
||||
Thanks to xet7.
|
||||
- [Added icons to swimlane action popup](https://github.com/wekan/wekan/pull/4943).
|
||||
Thanks to helioguardabaxo.
|
||||
- [Added translations to Sort](https://github.com/wekan/wekan/pull/4945).
|
||||
Thanks to DimDz.
|
||||
- Set card attachment as background image.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/8c6df7f20c946163b447227ff2f0d4da681cffb2),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/ed92db87bc0415d3c0bb7f2803d92f8fd7726517),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/01a1eb177e151c3042e1975de771737a6697342f),
|
||||
[Part 4](https://github.com/wekan/wekan/commit/47380244b827a79426ea92d5a96374b72c5b0811).
|
||||
Thanks to xet7.
|
||||
- [Edit the title of a swimlane using API](https://github.com/wekan/wekan/pull/4950).
|
||||
Thanks to DimDz.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- Updated dependencies.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/edf08c8cd44062cbdaa0cc98d10ec045a524cff3),
|
||||
[Part 2](https://github.com/wekan/wekan/pull/4949).
|
||||
Thanks to developers of dependencies.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix 6.93 with brackground image breaks scrolling on lists within swimlanes](https://github.com/wekan/wekan/commit/04aaa6f30cfe59769c9b1c75cf8921fcc99b1977).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.93 2023-05-29 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Layout fixes for modern-dark after shuffling labels and date field on minicard](https://github.com/wekan/wekan/pull/4935).
|
||||
Thanks to jghaanstra.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.92 2023-05-29 WeKan ® release
|
||||
|
||||
This release adds the following improvements:
|
||||
|
||||
- [Moved minicard labels from above minicard title to below minicard title](https://github.com/wekan/wekan/commit/b33a3ef254719dede124921bde40ce8a47c796fc).
|
||||
Thanks to xet7.
|
||||
- [Changed Due Date etc dates to be at top of Minicard](https://github.com/wekan/wekan/commit/a3d37e621c1eeeb9cd586b8fb644eae498df7ac4).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Fix Docker latest tags at Docker Hub, Quay and GitHub](https://github.com/wekan/wekan/commit/2d8ac3bf8085c913d14fb8a89f84769366073967).
|
||||
Thanks to rikhuijzer and xet7.
|
||||
- [Fixes for Create Card at Calendar](https://github.com/wekan/wekan/pull/4934).
|
||||
Thanks to DimDz.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.91 2023-05-27 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [BoardAdmin and Admin can now set board background image URL](https://github.com/wekan/wekan/commit/49ef80ab6c2dc038941558f68eface5e82a87593).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.90 2023-05-24 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Added Edit Custom Field Value to api.py](https://github.com/wekan/wekan/commit/ea908adbf9b75607c61c0cbc2b23886aa8e95fe7).
|
||||
Thanks to RazvanTinca and xet7.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- Update docker-compose.yml info about Docker images used.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/30ada6086245eb9957385d96132268344ce9513b),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/e83b0ac6519be4163cb6702a4a97d10e7315f5d9).
|
||||
Thanks to xet7.
|
||||
- [Upgrade Snap Candidate to MongoDB 6.0.6](https://github.com/wekan/wekan/commit/87fc4f936a2e37c0b9e3353a7b6f93dbff7fc2b7).
|
||||
Thanks to MongoDB developers.
|
||||
- [Use GitHub Docker Registry. Updated release scripts](https://github.com/wekan/wekan/commit/28e5b0bd5b270b2e2d3de5dad46804ac0d20d898).
|
||||
Thanks to xet7.
|
||||
- [Sync Docker Registries](https://github.com/wekan/wekan/commit/32ec95ffa8b34d5a7d9dff94302520509479c838).
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [To get corrent API docs generated, moved new_checklist_item API to correct file where is other checklist item API](https://github.com/wekan/wekan/commit/9de704040172e37769fa28cf571f293dfbd8bbb5).
|
||||
Thanks to xet7.
|
||||
- [Fix sharedDataFolder persisdent provide by k8s has no permission to mkdir and write](https://github.com/wekan/charts/commit/54c11ec8d7d165309632c455003b6e861e43fb4c).
|
||||
Thanks to new2001y.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.89 2023-05-12 WeKan ® release
|
||||
|
||||
This release fixes the following bugs:
|
||||
|
||||
- [Fix for the Create Card at Calendar](https://github.com/wekan/wekan/pull/4923).
|
||||
Thanks to DimDz.
|
||||
- [Fixed broken migration migrate-attachments-collectionFS-to-ostrioFiles](https://github.com/wekan/wekan/pull/4926).
|
||||
Thanks to Aman-Maheshwari.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.88 2023-05-11 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- [Create Card on Calendar View](https://github.com/wekan/wekan/pull/4922).
|
||||
Thanks to DimDz.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [OpenaAPI: Also ignores ThrowStatement](https://github.com/wekan/wekan/pull/4918).
|
||||
Thanks to bentiss.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.87 2023-05-08 WeKan ® release
|
||||
|
||||
This release adds the following new features:
|
||||
|
||||
- Added to meteor development options for logging also to ../wekan-log.txt, and showing deprecated API that is Meteor v2.12 new feature.
|
||||
[Part 1](https://github.com/wekan/wekan/commit/9fc52838562c3179775a6b24c23d0385363a0661),
|
||||
[Part 2](https://github.com/wekan/wekan/commit/521e840b54dd896eb192834133c5134a104f1d0b),
|
||||
[Part 3](https://github.com/wekan/wekan/commit/e6c59fc9b0ac53abd7519121d3bff700b1a43c24),
|
||||
[Part 4](https://github.com/wekan/wekan/commit/0bd9f309a10dff200efe6e38c6161deaf93c776d).
|
||||
Thanks to Meteor developers and xet7.
|
||||
- [API: Added User and Admin API for New Checklist Item and Edit Card Custom Field](https://github.com/wekan/wekan/pull/4911).
|
||||
Thanks to DimDz.
|
||||
|
||||
and adds the following updates:
|
||||
|
||||
- [Updated dependencies](https://github.com/wekan/wekan/commit/2b91557ad2931b3004a1da1ba0c790ed0e0546d3).
|
||||
Thanks to developers of dependencies.
|
||||
- [Upgraded to Meteor 2.12](https://github.com/wekan/wekan/commit/d519429ea14de3740408fbca3d231a1440562201).
|
||||
Thanks to Meteor developers.
|
||||
- [Updated translations](https://github.com/wekan/wekan/commit/40c077101a94f639b90f607624c4c72e12235711).
|
||||
xet7 fixed all translations of advanced filter description to have correct escaping of slash and backslash,
|
||||
so that bulding bundle of WeKan would not crash to invalid JSON syntax in translations.
|
||||
Thanks to xet7.
|
||||
|
||||
and fixes the following bugs:
|
||||
|
||||
- [Added X for closing card opened in Global Search](https://github.com/wekan/wekan/pull/4910).
|
||||
Thanks to deniszulic.
|
||||
|
||||
and tried to fix the following bugs:
|
||||
|
||||
- [Tried to fix building WeKan OpenAPI docs using Ubuntu 23.04 amd64 with XFCE desktop, but it did not work, still getting error: Failed to parse the source OpenAPI document](https://github.com/wekan/wekan/commit/97c6b6531502d09cbd6c267212651f3036338a11).
|
||||
Thanks to xet7.
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
# v6.86 2023-04-26 WeKan ® release
|
||||
|
||||
This release fixes the following CRITICAL SECURITY FIXES:
|
||||
@@ -7211,7 +7674,7 @@ This release adds the following new features, thanks to xet7:
|
||||
and adds the following [themes to board background colors](https://github.com/wekan/wekan/commit/c04292e98832e3aa7952e8a7858d47a853f40aad), thanks to xet7:
|
||||
|
||||
- RELAX MODE, so when green background selected, list background is light green.
|
||||
- [DARK MODE](https://github.com/wekan/wekan/issues/1149), when dark backgroud color selected. Please test and send color visibility fixes as pull requests.
|
||||
- [DARK MODE](https://github.com/wekan/wekan/issues/1149), when dark background color selected. Please test and send color visibility fixes as pull requests.
|
||||
- In RELAX MODE and DARK MODE, [hide card fields: received, start, due, end, members, requested, assigned](https://github.com/wekan/wekan/commit/b42ecb7948ad194433dc4460305174965106a751).
|
||||
|
||||
Thanks to above GitHub users for their contributions and translators for their translations.
|
||||
|
||||
+7
-1
@@ -78,7 +78,13 @@ RUN \
|
||||
chown wekan --recursive /home/wekan/.config && \
|
||||
\
|
||||
# Install Node dependencies
|
||||
npm install -g npm@${NPM_VERSION}
|
||||
npm install -g npm@${NPM_VERSION} && \
|
||||
\
|
||||
# Install Health Check dependencies
|
||||
apk add curl
|
||||
|
||||
HEALTHCHECK --start-period=30s --interval=30s --timeout=10s --retries=3 \
|
||||
CMD curl --fail "http://localhost:$PORT" || exit 1
|
||||
|
||||
EXPOSE $PORT
|
||||
USER wekan
|
||||
|
||||
+1
-1
@@ -1,5 +1,5 @@
|
||||
appId: wekan-public/apps/77b94f60-dec9-0136-304e-16ff53095928
|
||||
appVersion: "v6.86.0"
|
||||
appVersion: "v7.01.0"
|
||||
files:
|
||||
userUploads:
|
||||
- README.md
|
||||
|
||||
@@ -37,6 +37,7 @@ If *nix: chmod +x api.py => ./api.py users
|
||||
python3 api.py customfields BOARDID # Custom Fields of BOARDID
|
||||
python3 api.py customfield BOARDID CUSTOMFIELDID # Info of CUSTOMFIELDID
|
||||
python3 api.py addcustomfieldtoboard AUTHORID BOARDID NAME TYPE SETTINGS SHOWONCARD AUTOMATICALLYONCARD SHOWLABELONMINICARD SHOWSUMATTOPOFLIST # Add Custom Field to Board
|
||||
python3 api.py editcustomfield BOARDID LISTID CARDID CUSTOMFIELDID NEWCUSTOMFIELDVALUE
|
||||
python3 api.py listattachments BOARDID # List attachments
|
||||
|
||||
Admin API:
|
||||
@@ -217,6 +218,25 @@ if arguments == 6:
|
||||
print(data2)
|
||||
# ------- EDIT CARD END -----------
|
||||
|
||||
if sys.argv[1] == 'editcustomfield':
|
||||
|
||||
# ------- EDIT CUSTOMFIELD START -----------
|
||||
boardid = sys.argv[2]
|
||||
listid = sys.argv[3]
|
||||
cardid = sys.argv[4]
|
||||
customfieldid = sys.argv[5]
|
||||
newcustomfieldvalue = sys.argv[6]
|
||||
edfield = wekanurl + apiboards + boardid + s + l + s + listid + s + cs + s + cardid + s + 'customFields' + s + customfieldid
|
||||
#print(edfield)
|
||||
headers = {'Accept': 'application/json', 'Authorization': 'Bearer {}'.format(apikey)}
|
||||
post_data = {'_id': '{}'.format(customfieldid), 'value': '{}'.format(newcustomfieldvalue)}
|
||||
#print(post_data)
|
||||
body = requests.post(edfield, data=post_data, headers=headers)
|
||||
print("=== EDIT CUSTOMFIELD ===\n")
|
||||
data2 = body.text.replace('}',"}\n")
|
||||
print(data2)
|
||||
# ------- EDIT CUSTOMFIELD END -----------
|
||||
|
||||
if arguments == 4:
|
||||
|
||||
if sys.argv[1] == 'newuser':
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import DOMPurify from 'dompurify';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
@@ -24,7 +25,7 @@ BlazeComponent.extendComponent({
|
||||
searchId = Session.get(`current${capitalizedMode}`);
|
||||
}
|
||||
const limit = this.page.get() * activitiesPerPage;
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
const hideSystem = user ? user.hasHiddenSystemMessages() : false;
|
||||
if (searchId === null) return;
|
||||
|
||||
@@ -65,7 +66,7 @@ Template.activities.helpers({
|
||||
BlazeComponent.extendComponent({
|
||||
checkItem() {
|
||||
const checkItemId = this.currentData().activity.checklistItemId;
|
||||
const checkItem = ChecklistItems.findOne({ _id: checkItemId });
|
||||
const checkItem = ReactiveCache.getChecklistItem(checkItemId);
|
||||
return checkItem && checkItem.title;
|
||||
},
|
||||
|
||||
@@ -145,7 +146,7 @@ BlazeComponent.extendComponent({
|
||||
lastLabel() {
|
||||
const lastLabelId = this.currentData().activity.labelId;
|
||||
if (!lastLabelId) return null;
|
||||
const lastLabel = Boards.findOne(
|
||||
const lastLabel = ReactiveCache.getBoard(
|
||||
this.currentData().activity.boardId,
|
||||
).getLabelById(lastLabelId);
|
||||
if (lastLabel && (lastLabel.name === undefined || lastLabel.name === '')) {
|
||||
@@ -158,7 +159,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
lastCustomField() {
|
||||
const lastCustomField = CustomFields.findOne(
|
||||
const lastCustomField = ReactiveCache.getCustomField(
|
||||
this.currentData().activity.customFieldId,
|
||||
);
|
||||
if (!lastCustomField) return null;
|
||||
@@ -166,7 +167,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
lastCustomFieldValue() {
|
||||
const lastCustomField = CustomFields.findOne(
|
||||
const lastCustomField = ReactiveCache.getCustomField(
|
||||
this.currentData().activity.customFieldId,
|
||||
);
|
||||
if (!lastCustomField) return null;
|
||||
@@ -282,10 +283,10 @@ Template.activity.helpers({
|
||||
|
||||
Template.commentReactions.events({
|
||||
'click .reaction'(event) {
|
||||
if (Meteor.user().isBoardMember()) {
|
||||
if (ReactiveCache.getCurrentUser().isBoardMember()) {
|
||||
const codepoint = event.currentTarget.dataset['codepoint'];
|
||||
const commentId = Template.instance().data.commentId;
|
||||
const cardComment = CardComments.findOne({_id: commentId});
|
||||
const cardComment = ReactiveCache.getCardComment(commentId);
|
||||
cardComment.toggleReaction(codepoint);
|
||||
}
|
||||
},
|
||||
@@ -294,10 +295,10 @@ Template.commentReactions.events({
|
||||
|
||||
Template.addReactionPopup.events({
|
||||
'click .add-comment-reaction'(event) {
|
||||
if (Meteor.user().isBoardMember()) {
|
||||
if (ReactiveCache.getCurrentUser().isBoardMember()) {
|
||||
const codepoint = event.currentTarget.dataset['codepoint'];
|
||||
const commentId = Template.instance().data.commentId;
|
||||
const cardComment = CardComments.findOne({_id: commentId});
|
||||
const cardComment = ReactiveCache.getCardComment(commentId);
|
||||
cardComment.toggleReaction(codepoint);
|
||||
}
|
||||
Popup.back();
|
||||
@@ -325,12 +326,13 @@ Template.addReactionPopup.helpers({
|
||||
|
||||
Template.commentReactions.helpers({
|
||||
isSelected(userIds) {
|
||||
return userIds.includes(Meteor.user()._id);
|
||||
return Meteor.userId() && userIds.includes(Meteor.userId());
|
||||
},
|
||||
userNames(userIds) {
|
||||
return Users.find({_id: {$in: userIds}})
|
||||
.map(user => user.profile.fullname)
|
||||
.join(', ');
|
||||
const ret = ReactiveCache.getUsers({_id: {$in: userIds}})
|
||||
.map(user => user.profile.fullname)
|
||||
.join(', ');
|
||||
return ret;
|
||||
}
|
||||
})
|
||||
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
const commentFormIsOpen = new ReactiveVar(false);
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
@@ -24,7 +26,7 @@ BlazeComponent.extendComponent({
|
||||
let boardId = card.boardId;
|
||||
let cardId = card._id;
|
||||
if (card.isLinkedCard()) {
|
||||
boardId = Cards.findOne(card.linkedId).boardId;
|
||||
boardId = ReactiveCache.getCard(card.linkedId).boardId;
|
||||
cardId = card.linkedId;
|
||||
} else if (card.isLinkedBoard()) {
|
||||
boardId = card.linkedId;
|
||||
|
||||
@@ -1,19 +1,22 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.subscribe('archivedBoards');
|
||||
},
|
||||
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
|
||||
archivedBoards() {
|
||||
return Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{ archived: true },
|
||||
{
|
||||
sort: { archivedAt: -1, modifiedAt: -1 },
|
||||
},
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
|
||||
events() {
|
||||
@@ -25,8 +28,8 @@ BlazeComponent.extendComponent({
|
||||
Meteor.settings &&
|
||||
Meteor.settings.public &&
|
||||
Meteor.settings.public.sandstorm;
|
||||
if (isSandstorm && Session.get('currentBoard')) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
if (isSandstorm && Utils.getCurrentBoardId()) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
currentBoard.archive();
|
||||
}
|
||||
const board = this.currentData();
|
||||
@@ -39,8 +42,8 @@ BlazeComponent.extendComponent({
|
||||
Meteor.settings &&
|
||||
Meteor.settings.public &&
|
||||
Meteor.settings.public.sandstorm;
|
||||
if (isSandstorm && Session.get('currentBoard')) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
if (isSandstorm && Utils.getCurrentBoardId()) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
Boards.remove(currentBoard._id);
|
||||
}
|
||||
Boards.remove(this._id);
|
||||
|
||||
@@ -167,3 +167,58 @@
|
||||
border-color: #2b004d;
|
||||
color: #fff !important;
|
||||
}
|
||||
/* Modal Styles */
|
||||
.modal {
|
||||
display: none;
|
||||
position: fixed;
|
||||
top: 50%;
|
||||
left: 50%;
|
||||
transform: translate(-50%, -50%);
|
||||
z-index: 9999;
|
||||
background-color: rgba(0, 0, 0, 0.5);
|
||||
width: 100%;
|
||||
height: 100%;
|
||||
}
|
||||
.modal-dialog {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
height: 25%; /* Adjust the height to make it smaller */
|
||||
position: relative;
|
||||
margin: 10% auto; /* This margin will help center the modal vertically */
|
||||
max-width: 400px; /* Adjust the max-width to make it smaller */
|
||||
background-color: #fff;
|
||||
border-radius: 5px;
|
||||
box-shadow: 0 0 10px rgba(0, 0, 0, 0.3);
|
||||
}
|
||||
.modal-header {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-bottom: 1px;
|
||||
border-bottom: 1px solid #ccc;
|
||||
}
|
||||
.modal-title {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
margin: 0;
|
||||
font-size: 18px;
|
||||
}
|
||||
.modal-footer {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
padding-top: 4px;
|
||||
border-top: 1px solid #ccc;
|
||||
}
|
||||
.close {
|
||||
display: flex;
|
||||
justify-content: center;
|
||||
align-items: center;
|
||||
position: absolute;
|
||||
top: 5px;
|
||||
right: 5px;
|
||||
font-size: 25px;
|
||||
cursor: pointer;
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
const subManager = new SubsManager();
|
||||
@@ -43,9 +44,9 @@ BlazeComponent.extendComponent({
|
||||
this.mouseHasEnterCardDetails = false;
|
||||
|
||||
// fix swimlanes sort field if there are null values
|
||||
const currentBoardData = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoardData = Utils.getCurrentBoard();
|
||||
const nullSortSwimlanes = currentBoardData.nullSortSwimlanes();
|
||||
if (nullSortSwimlanes.count() > 0) {
|
||||
if (nullSortSwimlanes.length > 0) {
|
||||
const swimlanes = currentBoardData.swimlanes();
|
||||
let count = 0;
|
||||
swimlanes.forEach(s => {
|
||||
@@ -60,7 +61,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
// fix lists sort field if there are null values
|
||||
const nullSortLists = currentBoardData.nullSortLists();
|
||||
if (nullSortLists.count() > 0) {
|
||||
if (nullSortLists.length > 0) {
|
||||
const lists = currentBoardData.lists();
|
||||
let count = 0;
|
||||
lists.forEach(l => {
|
||||
@@ -204,33 +205,26 @@ BlazeComponent.extendComponent({
|
||||
}
|
||||
|
||||
// Disable drag-dropping if the current user is not a board member
|
||||
//$swimlanesDom.sortable('option', 'disabled', !userIsMember());
|
||||
$swimlanesDom.sortable(
|
||||
'option',
|
||||
'disabled',
|
||||
!Meteor.user() || !Meteor.user().isBoardAdmin(),
|
||||
!ReactiveCache.getCurrentUser()?.isBoardAdmin(),
|
||||
);
|
||||
});
|
||||
|
||||
function userIsMember() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly()
|
||||
);
|
||||
}
|
||||
|
||||
// If there is no data in the board (ie, no lists) we autofocus the list
|
||||
// creation form by clicking on the corresponding element.
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
if (userIsMember() && currentBoard.lists().count() === 0) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
if (Utils.canModifyBoard() && currentBoard.lists().length === 0) {
|
||||
boardComponent.openNewListForm();
|
||||
}
|
||||
|
||||
Utils.setBackgroundImage();
|
||||
},
|
||||
|
||||
notDisplayThisBoard() {
|
||||
let allowPrivateVisibilityOnly = TableVisibilityModeSettings.findOne('tableVisibilityMode-allowPrivateOnly');
|
||||
let currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
let currentBoard = Utils.getCurrentBoard();
|
||||
if (allowPrivateVisibilityOnly !== undefined && allowPrivateVisibilityOnly.booleanValue && currentBoard.permission == 'public') {
|
||||
return true;
|
||||
}
|
||||
@@ -239,7 +233,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
isViewSwimlanes() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).boardView === 'board-view-swimlanes';
|
||||
} else {
|
||||
@@ -250,7 +244,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
isViewLists() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).boardView === 'board-view-lists';
|
||||
} else {
|
||||
@@ -259,7 +253,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
isViewCalendar() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).boardView === 'board-view-cal';
|
||||
} else {
|
||||
@@ -328,6 +322,7 @@ BlazeComponent.extendComponent({
|
||||
id: 'calendar-view',
|
||||
defaultView: 'agendaDay',
|
||||
editable: true,
|
||||
selectable: true,
|
||||
timezone: 'local',
|
||||
weekNumbers: true,
|
||||
header: {
|
||||
@@ -349,7 +344,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
locale: TAPi18n.getLanguage(),
|
||||
events(start, end, timezone, callback) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const events = [];
|
||||
const pushEvent = function (card, title, start, end, extraCls) {
|
||||
start = start || card.startAt;
|
||||
@@ -395,7 +390,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
eventResize(event, delta, revertFunc) {
|
||||
let isOk = false;
|
||||
const card = Cards.findOne(event.id);
|
||||
const card = ReactiveCache.getCard(event.id);
|
||||
|
||||
if (card) {
|
||||
card.setEnd(event.end.toDate());
|
||||
@@ -407,7 +402,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
eventDrop(event, delta, revertFunc) {
|
||||
let isOk = false;
|
||||
const card = Cards.findOne(event.id);
|
||||
const card = ReactiveCache.getCard(event.id);
|
||||
if (card) {
|
||||
// TODO: add a flag for allDay events
|
||||
if (!event.allDay) {
|
||||
@@ -422,10 +417,62 @@ BlazeComponent.extendComponent({
|
||||
revertFunc();
|
||||
}
|
||||
},
|
||||
select: function (startDate) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
const modalElement = document.createElement('div');
|
||||
modalElement.classList.add('modal', 'fade');
|
||||
modalElement.setAttribute('tabindex', '-1');
|
||||
modalElement.setAttribute('role', 'dialog');
|
||||
modalElement.innerHTML = `
|
||||
<div class="modal-dialog justify-content-center align-items-center" role="document">
|
||||
<div class="modal-content">
|
||||
<div class="modal-header">
|
||||
<h5 class="modal-title">${TAPi18n.__('r-create-card')}</h5>
|
||||
<button type="button" class="close" data-dismiss="modal" aria-label="Close">
|
||||
<span aria-hidden="true">×</span>
|
||||
</button>
|
||||
</div>
|
||||
<div class="modal-body text-center">
|
||||
<input type="text" class="form-control" id="card-title-input" placeholder="">
|
||||
</div>
|
||||
<div class="modal-footer">
|
||||
<button type="button" class="btn btn-primary" id="create-card-button">${TAPi18n.__('add-card')}</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
`;
|
||||
const createCardButton = modalElement.querySelector('#create-card-button');
|
||||
createCardButton.addEventListener('click', function () {
|
||||
const myTitle = modalElement.querySelector('#card-title-input').value;
|
||||
if (myTitle) {
|
||||
const firstList = currentBoard.draggableLists()[0];
|
||||
const firstSwimlane = currentBoard.swimlanes()[0];
|
||||
Meteor.call('createCardWithDueDate', currentBoard._id, firstList._id, myTitle, startDate.toDate(), firstSwimlane._id, function(error, result) {
|
||||
if (error) {
|
||||
console.log(error);
|
||||
} else {
|
||||
console.log("Card Created", result);
|
||||
}
|
||||
});
|
||||
closeModal();
|
||||
}
|
||||
});
|
||||
document.body.appendChild(modalElement);
|
||||
const openModal = function() {
|
||||
modalElement.style.display = 'flex';
|
||||
};
|
||||
const closeModal = function() {
|
||||
modalElement.style.display = 'none';
|
||||
};
|
||||
const closeButton = modalElement.querySelector('[data-dismiss="modal"]');
|
||||
closeButton.addEventListener('click', closeModal);
|
||||
openModal();
|
||||
}
|
||||
};
|
||||
},
|
||||
isViewCalendar() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).boardView === 'board-view-cal';
|
||||
} else {
|
||||
|
||||
@@ -1834,19 +1834,20 @@
|
||||
background-color: #4d4d4d !important;
|
||||
}
|
||||
.board-color-moderndark .minicard .minicard-labels {
|
||||
margin-bottom: 4px;
|
||||
margin: 8px 0 4px;
|
||||
}
|
||||
.board-color-moderndark .minicard .card-label {
|
||||
font-size: 11px;
|
||||
font-weight: 400;
|
||||
padding: 1px 6px 0;
|
||||
border-radius: 2px;
|
||||
line-height: 18px;
|
||||
}
|
||||
.board-color-moderndark .minicard .badges {
|
||||
color: #bbb;
|
||||
}
|
||||
.board-color-moderndark .minicard .date {
|
||||
margin-top: 10px;
|
||||
margin-bottom: 10px;
|
||||
font-size: 11px;
|
||||
}
|
||||
.board-color-moderndark .card-date {
|
||||
@@ -1975,7 +1976,7 @@
|
||||
background-color: #ccc;
|
||||
color: #222;
|
||||
}
|
||||
.board-color-moderndark .attachments-galery .attachment-item {
|
||||
.board-color-moderndark .attachments-gallery .attachment-item {
|
||||
color: #222;
|
||||
}
|
||||
.board-color-moderndark .minicard-description {
|
||||
@@ -2147,10 +2148,10 @@
|
||||
.board-color-exodark .sidebar-content {
|
||||
box-shadow: 0 0 7px 0 #00897b;
|
||||
}
|
||||
.board-color-exodark .attachments-galery .attachment-item {
|
||||
.board-color-exodark .attachments-gallery .attachment-item {
|
||||
background: #2b2b2b;
|
||||
}
|
||||
.board-color-exodark .attachments-galery .attachment-item:hover {
|
||||
.board-color-exodark .attachments-gallery .attachment-item:hover {
|
||||
border: 1px solid #00897b;
|
||||
background: #2b2b2b;
|
||||
}
|
||||
|
||||
@@ -39,9 +39,9 @@ template(name="boardHeaderBar")
|
||||
span {{_ watchLevel}}
|
||||
a.board-header-btn(title="{{_ 'sort-cards'}}" class="{{#if isSortActive }}emphasis{{else}} js-sort-cards {{/if}}")
|
||||
i.fa.fa-sort
|
||||
span {{#if isSortActive }}{{_ 'Sort is on'}}{{else}}{{_ 'sort-cards'}}{{/if}}
|
||||
span {{#if isSortActive }}{{_ 'sort-is-on'}}{{else}}{{_ 'sort-cards'}}{{/if}}
|
||||
if isSortActive
|
||||
a.board-header-btn-close.js-sort-reset(title="Remove Sort")
|
||||
a.board-header-btn-close.js-sort-reset(title="{{_ 'remove-sort'}}")
|
||||
i.fa.fa-times-thin
|
||||
|
||||
else
|
||||
@@ -82,9 +82,9 @@ template(name="boardHeaderBar")
|
||||
span {{_ watchLevel}}
|
||||
a.board-header-btn(title="{{_ 'sort-cards'}}" class="{{#if isSortActive }}emphasis{{else}} js-sort-cards {{/if}}")
|
||||
i.fa.fa-sort
|
||||
span {{#if isSortActive }}{{_ 'Sort is on'}}{{else}}{{_ 'sort-cards'}}{{/if}}
|
||||
span {{#if isSortActive }}{{_ 'sort-is-on'}}{{else}}{{_ 'sort-cards'}}{{/if}}
|
||||
if isSortActive
|
||||
a.board-header-btn-close.js-sort-reset(title="Remove Sort")
|
||||
a.board-header-btn-close.js-sort-reset(title="{{_ 'remove-sort'}}")
|
||||
i.fa.fa-times-thin
|
||||
|
||||
else
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
/*
|
||||
@@ -18,14 +19,14 @@ Template.boardMenuPopup.events({
|
||||
'click .js-change-board-color': Popup.open('boardChangeColor'),
|
||||
'click .js-change-language': Popup.open('changeLanguage'),
|
||||
'click .js-archive-board ': Popup.afterConfirm('archiveBoard', function() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
currentBoard.archive();
|
||||
// XXX We should have some kind of notification on top of the page to
|
||||
// confirm that the board was successfully archived.
|
||||
FlowRouter.go('home');
|
||||
}),
|
||||
'click .js-delete-board': Popup.afterConfirm('deleteBoard', function() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
Popup.back();
|
||||
Boards.remove(currentBoard._id);
|
||||
FlowRouter.go('home');
|
||||
@@ -58,24 +59,24 @@ Template.boardChangeTitlePopup.events({
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
watchLevel() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return currentBoard && currentBoard.getWatchLevel(Meteor.userId());
|
||||
},
|
||||
|
||||
isStarred() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
return user && user.hasStarred(boardId);
|
||||
},
|
||||
|
||||
// Only show the star counter if the number of star is greater than 2
|
||||
showStarCounter() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return currentBoard && currentBoard.stars >= 2;
|
||||
},
|
||||
/*
|
||||
showSort() {
|
||||
return Meteor.user().hasSortBy();
|
||||
return ReactiveCache.getCurrentUser().hasSortBy();
|
||||
},
|
||||
directionClass() {
|
||||
return this.currentDirection() === -1 ? DOWNCLS : UPCLS;
|
||||
@@ -85,10 +86,10 @@ BlazeComponent.extendComponent({
|
||||
Meteor.call('setListSortBy', direction + this.currentListSortBy());
|
||||
},
|
||||
currentDirection() {
|
||||
return Meteor.user().getListSortByDirection();
|
||||
return ReactiveCache.getCurrentUser().getListSortByDirection();
|
||||
},
|
||||
currentListSortBy() {
|
||||
return Meteor.user().getListSortBy();
|
||||
return ReactiveCache.getCurrentUser().getListSortBy();
|
||||
},
|
||||
listSortShortDesc() {
|
||||
return `list-label-short-${this.currentListSortBy()}`;
|
||||
@@ -99,7 +100,7 @@ BlazeComponent.extendComponent({
|
||||
{
|
||||
'click .js-edit-board-title': Popup.open('boardChangeTitle'),
|
||||
'click .js-star-board'() {
|
||||
Meteor.user().toggleBoardStar(Session.get('currentBoard'));
|
||||
ReactiveCache.getCurrentUser().toggleBoardStar(Session.get('currentBoard'));
|
||||
},
|
||||
'click .js-open-board-menu': Popup.open('boardMenu'),
|
||||
'click .js-change-visibility': Popup.open('boardChangeVisibility'),
|
||||
@@ -158,13 +159,6 @@ BlazeComponent.extendComponent({
|
||||
}).register('boardHeaderBar');
|
||||
|
||||
Template.boardHeaderBar.helpers({
|
||||
canModifyBoard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly()
|
||||
);
|
||||
},
|
||||
boardView() {
|
||||
return Utils.boardView();
|
||||
},
|
||||
@@ -313,7 +307,7 @@ const CreateBoard = BlazeComponent.extendComponent({
|
||||
onSubmit(event) {
|
||||
super.onSubmit(event);
|
||||
// Immediately star boards crated with the headerbar popup.
|
||||
Meteor.user().toggleBoardStar(this.boardId.get());
|
||||
ReactiveCache.getCurrentUser().toggleBoardStar(this.boardId.get());
|
||||
}
|
||||
}.register('headerBarCreateBoardPopup'));
|
||||
|
||||
@@ -322,12 +316,12 @@ BlazeComponent.extendComponent({
|
||||
return !TableVisibilityModeSettings.findOne('tableVisibilityMode-allowPrivateOnly').booleanValue;
|
||||
},
|
||||
visibilityCheck() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return this.currentData() === currentBoard.permission;
|
||||
},
|
||||
|
||||
selectBoardVisibility() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const visibility = this.currentData();
|
||||
currentBoard.setVisibility(visibility);
|
||||
Popup.back();
|
||||
@@ -344,7 +338,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
watchLevel() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return currentBoard.getWatchLevel(Meteor.userId());
|
||||
},
|
||||
|
||||
@@ -384,7 +378,7 @@ BlazeComponent.extendComponent({
|
||||
allowedSortValues() {
|
||||
const types = [];
|
||||
const pushed = {};
|
||||
Meteor.user()
|
||||
ReactiveCache.getCurrentUser()
|
||||
.getListSortTypes()
|
||||
.forEach(type => {
|
||||
const key = type.replace(/^-/, '');
|
||||
@@ -400,16 +394,16 @@ BlazeComponent.extendComponent({
|
||||
return types;
|
||||
},
|
||||
Direction() {
|
||||
return Meteor.user().getListSortByDirection() === -1
|
||||
return ReactiveCache.getCurrentUser().getListSortByDirection() === -1
|
||||
? this.downClass
|
||||
: this.upClass;
|
||||
},
|
||||
sortby() {
|
||||
return Meteor.user().getListSortBy();
|
||||
return ReactiveCache.getCurrentUser().getListSortBy();
|
||||
},
|
||||
|
||||
setSortBy(type = null) {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
if (type === null) {
|
||||
type = user._getListSortBy();
|
||||
} else {
|
||||
|
||||
@@ -1,16 +1,18 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
const subManager = new SubsManager();
|
||||
|
||||
Template.boardList.helpers({
|
||||
currentSetting() {
|
||||
return Settings.findOne();
|
||||
},
|
||||
hideCardCounterList() {
|
||||
return Utils.isMiniScreen() && Session.get('currentBoard');
|
||||
/* Bug Board icons random dance https://github.com/wekan/wekan/issues/4214
|
||||
return Utils.isMiniScreen() && Session.get('currentBoard'); */
|
||||
return true;
|
||||
},
|
||||
hideBoardMemberList() {
|
||||
return Utils.isMiniScreen() && Session.get('currentBoard');
|
||||
/* Bug Board icons random dance https://github.com/wekan/wekan/issues/4214
|
||||
return Utils.isMiniScreen() && Session.get('currentBoard'); */
|
||||
return true;
|
||||
},
|
||||
})
|
||||
|
||||
@@ -29,10 +31,10 @@ Template.boardListHeaderBar.helpers({
|
||||
//}
|
||||
},
|
||||
templatesBoardId() {
|
||||
return Meteor.user() && Meteor.user().getTemplatesBoardId();
|
||||
return ReactiveCache.getCurrentUser()?.getTemplatesBoardId();
|
||||
},
|
||||
templatesBoardSlug() {
|
||||
return Meteor.user() && Meteor.user().getTemplatesBoardSlug();
|
||||
return ReactiveCache.getCurrentUser()?.getTemplatesBoardSlug();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -40,7 +42,7 @@ BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
Meteor.subscribe('setting');
|
||||
Meteor.subscribe('tableVisibilityModeSettings');
|
||||
let currUser = Meteor.user();
|
||||
let currUser = ReactiveCache.getCurrentUser();
|
||||
let userLanguage;
|
||||
if (currUser && currUser.profile) {
|
||||
userLanguage = currUser.profile.language
|
||||
@@ -84,7 +86,6 @@ BlazeComponent.extendComponent({
|
||||
// DOM in its initial state. The card move is then handled reactively by
|
||||
// Blaze with the below query.
|
||||
$boards.sortable('cancel');
|
||||
|
||||
board.move(sortIndex.base);
|
||||
},
|
||||
});
|
||||
@@ -99,51 +100,34 @@ BlazeComponent.extendComponent({
|
||||
});
|
||||
},
|
||||
userHasTeams() {
|
||||
if (Meteor.user() != null && Meteor.user().teams && Meteor.user().teams.length > 0)
|
||||
if (ReactiveCache.getCurrentUser()?.teams?.length > 0)
|
||||
return true;
|
||||
else
|
||||
return false;
|
||||
},
|
||||
teamsDatas() {
|
||||
if (Meteor.user().teams)
|
||||
return Meteor.user().teams.sort((a, b) => a.teamDisplayName.localeCompare(b.teamDisplayName));
|
||||
const teams = ReactiveCache.getCurrentUser()?.teams
|
||||
if (teams)
|
||||
return teams.sort((a, b) => a.teamDisplayName.localeCompare(b.teamDisplayName));
|
||||
else
|
||||
return [];
|
||||
},
|
||||
userHasOrgs() {
|
||||
if (Meteor.user() != null && Meteor.user().orgs && Meteor.user().orgs.length > 0)
|
||||
if (ReactiveCache.getCurrentUser()?.orgs?.length > 0)
|
||||
return true;
|
||||
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.sort((a, b) => a.orgDisplayName.localeCompare(b.orgDisplayName));
|
||||
const orgs = ReactiveCache.getCurrentUser()?.orgs;
|
||||
if (orgs)
|
||||
return orgs.sort((a, b) => a.orgDisplayName.localeCompare(b.orgDisplayName));
|
||||
else
|
||||
return [];
|
||||
},
|
||||
userHasOrgsOrTeams() {
|
||||
let boolUserHasOrgs;
|
||||
if (Meteor.user() != null && Meteor.user().orgs && Meteor.user().orgs.length > 0)
|
||||
boolUserHasOrgs = true;
|
||||
else
|
||||
boolUserHasOrgs = false;
|
||||
|
||||
let boolUserHasTeams;
|
||||
if (Meteor.user() != null && Meteor.user().teams && Meteor.user().teams.length > 0)
|
||||
boolUserHasTeams = true;
|
||||
else
|
||||
boolUserHasTeams = false;
|
||||
|
||||
return (boolUserHasOrgs || boolUserHasTeams);
|
||||
const ret = this.userHasOrgs() || this.userHasTeams();
|
||||
return ret;
|
||||
},
|
||||
boards() {
|
||||
let query = {
|
||||
@@ -165,14 +149,7 @@ BlazeComponent.extendComponent({
|
||||
if (allowPrivateVisibilityOnly !== undefined && allowPrivateVisibilityOnly.booleanValue) {
|
||||
query.$and.push({ 'permission': 'private' });
|
||||
}
|
||||
const currUser = Users.findOne(Meteor.userId());
|
||||
|
||||
// const currUser = Users.findOne(Meteor.userId(), {
|
||||
// fields: {
|
||||
// orgs: 1,
|
||||
// teams: 1,
|
||||
// },
|
||||
// });
|
||||
const currUser = ReactiveCache.getCurrentUser();
|
||||
|
||||
let orgIdsUserBelongs = currUser !== undefined && currUser.teams !== 'undefined' ? currUser.orgIdsUserBelongs() : '';
|
||||
if (orgIdsUserBelongs && orgIdsUserBelongs != '') {
|
||||
@@ -204,51 +181,54 @@ BlazeComponent.extendComponent({
|
||||
};
|
||||
}
|
||||
|
||||
return Boards.find(query, {
|
||||
const ret = ReactiveCache.getBoards(query, {
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
});
|
||||
return ret;
|
||||
},
|
||||
boardLists(boardId) {
|
||||
let boardLists = [];
|
||||
const lists = Lists.find({ 'boardId': boardId, 'archived': false },{sort: ['sort','asc']});
|
||||
lists.forEach(list => {
|
||||
let cardCount = Cards.find({ 'boardId': boardId, 'listId': list._id }).count()
|
||||
boardLists.push(`${list.title}: ${cardCount}`);
|
||||
/* Bug Board icons random dance https://github.com/wekan/wekan/issues/4214
|
||||
const lists = ReactiveCache.getLists({ 'boardId': boardId, 'archived': false },{sort: ['sort','asc']});
|
||||
const ret = lists.map(list => {
|
||||
let cardCount = ReactiveCache.getCards({ 'boardId': boardId, 'listId': list._id }).length;
|
||||
return `${list.title}: ${cardCount}`;
|
||||
});
|
||||
return boardLists
|
||||
return ret;
|
||||
*/
|
||||
return [];
|
||||
},
|
||||
|
||||
boardMembers(boardId) {
|
||||
let boardMembers = [];
|
||||
const lists = Boards.findOne({ '_id': boardId })
|
||||
/* Bug Board icons random dance https://github.com/wekan/wekan/issues/4214
|
||||
const lists = ReactiveCache.getBoard(boardId)
|
||||
let members = lists.members
|
||||
members.forEach(member => {
|
||||
boardMembers.push(member.userId);
|
||||
});
|
||||
return boardMembers
|
||||
*/
|
||||
return boardMembers;
|
||||
},
|
||||
|
||||
isStarred() {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
return user && user.hasStarred(this.currentData()._id);
|
||||
},
|
||||
isAdministrable() {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
return user && user.isBoardAdmin(this.currentData()._id);
|
||||
},
|
||||
|
||||
hasOvertimeCards() {
|
||||
subManager.subscribe('board', this.currentData()._id, false);
|
||||
return this.currentData().hasOvertimeCards();
|
||||
},
|
||||
|
||||
hasSpentTimeCards() {
|
||||
subManager.subscribe('board', this.currentData()._id, false);
|
||||
return this.currentData().hasSpentTimeCards();
|
||||
},
|
||||
|
||||
isInvited() {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
return user && user.isInvitedTo(this.currentData()._id);
|
||||
},
|
||||
|
||||
@@ -258,18 +238,18 @@ BlazeComponent.extendComponent({
|
||||
'click .js-add-board': Popup.open('createBoard'),
|
||||
'click .js-star-board'(evt) {
|
||||
const boardId = this.currentData()._id;
|
||||
Meteor.user().toggleBoardStar(boardId);
|
||||
ReactiveCache.getCurrentUser().toggleBoardStar(boardId);
|
||||
evt.preventDefault();
|
||||
},
|
||||
'click .js-clone-board'(evt) {
|
||||
let title = getSlug(Boards.findOne(this.currentData()._id).title) || 'cloned-board';
|
||||
let title = getSlug(ReactiveCache.getBoard(this.currentData()._id).title) || 'cloned-board';
|
||||
Meteor.call(
|
||||
'copyBoard',
|
||||
this.currentData()._id,
|
||||
{
|
||||
sort: Boards.find({ archived: false }).count(),
|
||||
sort: ReactiveCache.getBoards({ archived: false }).length,
|
||||
type: 'board',
|
||||
title: Boards.findOne(this.currentData()._id).title,
|
||||
title: ReactiveCache.getBoard(this.currentData()._id).title,
|
||||
},
|
||||
(err, res) => {
|
||||
if (err) {
|
||||
@@ -343,7 +323,7 @@ BlazeComponent.extendComponent({
|
||||
query.$and[2].$or.push({ 'orgs.orgId': { $in: selectedOrgsValues } });
|
||||
}
|
||||
|
||||
let filteredBoards = Boards.find(query, {}).fetch();
|
||||
let filteredBoards = ReactiveCache.getBoards(query, {});
|
||||
let allBoards = document.getElementsByClassName("js-board");
|
||||
let currBoard;
|
||||
if (filteredBoards.length > 0) {
|
||||
|
||||
@@ -1,90 +1,190 @@
|
||||
.slide {
|
||||
/* swipebox slide background gradient of black to blue, so that back SVG images are visible */
|
||||
background: rgb(2,0,36);
|
||||
background: linear-gradient(90deg, rgba(2,0,36,1) 0%, rgba(9,9,121,1) 14%, rgba(0,212,255,1) 100%);
|
||||
.hidden {
|
||||
display: none;
|
||||
}
|
||||
.attachment-upload {
|
||||
text-align: center;
|
||||
font-weight: bold;
|
||||
}
|
||||
.attachments-galery {
|
||||
.attachment-gallery {
|
||||
display: flex;
|
||||
flex-wrap: wrap;
|
||||
flex-direction: column;
|
||||
}
|
||||
.attachments-galery .attachment-item {
|
||||
width: 31.33%;
|
||||
margin: 10px 1% 0;
|
||||
text-align: center;
|
||||
border-radius: 3px;
|
||||
overflow: auto;
|
||||
background: #ededed;
|
||||
min-height: 120px;
|
||||
.attachment-item {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
margin-top: 16px;
|
||||
}
|
||||
.attachments-galery .attachment-item:hover {
|
||||
.attachment-item:hover {
|
||||
background: #e0e0e0;
|
||||
}
|
||||
.attachments-galery .attachment-item.add-attachment {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
}
|
||||
.attachments-galery .attachment-item.add-attachment a {
|
||||
.attachment-thumbnail-container {
|
||||
display: block;
|
||||
margin: auto;
|
||||
width: 150px;
|
||||
min-width: 150px;
|
||||
max-height: 150px;
|
||||
padding-right: 16px;
|
||||
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-thumbnail {
|
||||
height: 80px;
|
||||
.attachment-thumbnail {
|
||||
max-width: 150px;
|
||||
max-height: 150px;
|
||||
min-height: 2em;
|
||||
cursor: pointer;
|
||||
}
|
||||
.attachment-thumbnail-text {
|
||||
min-height: 2em;
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
position: relative;
|
||||
font-size: 2em;
|
||||
cursor: pointer;
|
||||
border: 1px solid #ccc;
|
||||
border-radius: 5px;
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-thumbnail .attachment-thumbnail-img {
|
||||
max-height: 100%;
|
||||
.attachment-details-container {
|
||||
display: block;
|
||||
flex-grow: 1;
|
||||
}
|
||||
.attachment-details {
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
margin-right: 25px; /* Make sure the icons are not to far to the right */
|
||||
}
|
||||
.attachment-actions {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
align-items: center;
|
||||
}
|
||||
.add-attachment {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
justify-content: center;
|
||||
border: 1px dashed #555;
|
||||
border-radius: 5px;
|
||||
padding: 10px;
|
||||
cursor: pointer;
|
||||
margin-top: 16px;
|
||||
}
|
||||
.icon {
|
||||
font-size: 1.5em;
|
||||
cursor: pointer;
|
||||
margin-left: 10px;
|
||||
}
|
||||
.icon:hover {
|
||||
color: #666;
|
||||
}
|
||||
#viewer-overlay {
|
||||
width: 100%;
|
||||
height: 100vh;
|
||||
position: fixed;
|
||||
top: 48px; /* height of the navbar */
|
||||
left: 0;
|
||||
z-index: 9999 !important;
|
||||
background: rgba(13,13,13,0.95);
|
||||
}
|
||||
#viewer-container {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
height: 100%;
|
||||
}
|
||||
#viewer-top-bar {
|
||||
display: flex;
|
||||
flex-direction: row;
|
||||
justify-content: space-between;
|
||||
width: 100%;
|
||||
padding: 16px;
|
||||
}
|
||||
#attachment-name {
|
||||
color: white;
|
||||
font-size: 1.5em;
|
||||
max-width: calc(100% - 50px); /* Make sure the name does not overlap the close button */
|
||||
}
|
||||
#viewer-close {
|
||||
color:white;
|
||||
cursor: pointer;
|
||||
font-size: 4em;
|
||||
top: 0;
|
||||
right: 8px;
|
||||
position: absolute;
|
||||
}
|
||||
.attachment-arrow {
|
||||
font-size: 4em;
|
||||
color:white;
|
||||
cursor: pointer;
|
||||
align-self: center;
|
||||
margin: 0 20px;
|
||||
}
|
||||
#image-viewer {
|
||||
background:
|
||||
repeating-conic-gradient(#808080 0% 25%, transparent 0% 50%)
|
||||
50% / 20px 20px; /* Checkerboard background for transparent images */
|
||||
max-width: 100%;
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-thumbnail .attachment-thumbnail-ext {
|
||||
text-transform: uppercase;
|
||||
font-size: 1.6em;
|
||||
#pdf-viewer {
|
||||
width: 40vw;
|
||||
height: 100vh;
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-details {
|
||||
font-size: 0.75em;
|
||||
margin: 3px;
|
||||
#txt-viewer{
|
||||
background-color: white;
|
||||
width: 40vw;
|
||||
height: 100vh;
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-details .attachment-details-actions a {
|
||||
.pdf-preview-error {
|
||||
margin-top: 20vh;
|
||||
display: block;
|
||||
font-size: 2em;
|
||||
color: white;
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-details .attachment-details-actions a.attachment-details-menu {
|
||||
padding-top: 10px;
|
||||
}
|
||||
.attachment-image-preview {
|
||||
max-width: 100px;
|
||||
display: block;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
|
||||
}
|
||||
.preview-clipboard-image {
|
||||
width: 280px;
|
||||
max-width: 100%;
|
||||
height: 200px;
|
||||
display: block;
|
||||
border: 1px solid #000;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
|
||||
|
||||
@media screen and (max-width: 1600px) {
|
||||
#pdf-viewer {
|
||||
width: 60vw;
|
||||
}
|
||||
}
|
||||
|
||||
@media screen and (max-width: 800px) {
|
||||
.attachments-galery .attachment-item {
|
||||
width: 48%;
|
||||
#viewer-container {
|
||||
display: block;
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-thumbnail {
|
||||
height: 130px;
|
||||
.attachment-arrow{
|
||||
position: absolute;
|
||||
bottom: 2.2em;
|
||||
font-size: 1.6em;
|
||||
padding: 16px;
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-details {
|
||||
font-size: 1.1em;
|
||||
#prev-attachment{
|
||||
left: 0;
|
||||
}
|
||||
}
|
||||
@media screen and (max-width: 360px) {
|
||||
.attachments-galery .attachment-item {
|
||||
#next-attachment{
|
||||
right: 0;
|
||||
}
|
||||
#pdf-viewer {
|
||||
width: 100%;
|
||||
height: calc(100vh - 155px); /* Full height - height of top and bottom bars */
|
||||
}
|
||||
#txt-viewer {
|
||||
width: 100%;
|
||||
height: calc(100vh - 155px); /* Full height - height of top and bottom bars */
|
||||
}
|
||||
#audio-viewer {
|
||||
margin-top: 20%;
|
||||
width: 100%;
|
||||
}
|
||||
.attachments-galery .attachment-item .attachment-thumbnail {
|
||||
height: 200px;
|
||||
.attachment-thumbnail-container {
|
||||
width: 100px;
|
||||
min-width: 100px;
|
||||
}
|
||||
.attachment-thumbnail {
|
||||
max-width: 100px;
|
||||
}
|
||||
.attachment-details {
|
||||
flex-direction: column;
|
||||
margin-right: 0px;
|
||||
}
|
||||
.attachment-actions {
|
||||
flex-direction: row;
|
||||
margin-top: 10px;
|
||||
}
|
||||
}
|
||||
@@ -30,63 +30,92 @@ template(name="attachmentDeletePopup")
|
||||
p {{_ "attachment-delete-pop"}}
|
||||
button.js-confirm.negate.full(type="submit") {{_ 'delete'}}
|
||||
|
||||
template(name="attachmentsGalery")
|
||||
.attachments-galery
|
||||
if currentUser.isBoardMember
|
||||
unless currentUser.isCommentOnly
|
||||
unless currentUser.isWorker
|
||||
//li.attachment-item.add-attachment
|
||||
a.js-add-attachment(title="{{_ 'add-attachment' }}")
|
||||
i.fa.fa-plus
|
||||
template(name="attachmentViewer")
|
||||
#viewer-overlay.hidden
|
||||
#viewer-top-bar
|
||||
span#attachment-name
|
||||
a#viewer-close.fa.fa-times-thin
|
||||
|
||||
#viewer-container
|
||||
i.fa.fa-chevron-left.attachment-arrow#prev-attachment
|
||||
#viewer-content
|
||||
img#image-viewer.hidden
|
||||
video#video-viewer.hidden(controls="true")
|
||||
audio#audio-viewer.hidden(controls="true")
|
||||
object#pdf-viewer.hidden(type="application/pdf")
|
||||
span.pdf-preview-error {{_ 'preview-pdf-not-supported' }}
|
||||
object#txt-viewer.hidden(type="text/plain")
|
||||
i.fa.fa-chevron-right.attachment-arrow#next-attachment
|
||||
|
||||
template(name="attachmentGallery")
|
||||
|
||||
.attachment-gallery
|
||||
|
||||
a.attachment-item.add-attachment.js-add-attachment
|
||||
i.fa.fa-plus.icon
|
||||
|
||||
each attachments
|
||||
|
||||
.attachment-item
|
||||
a.attachment-thumbnail.swipebox(href="{{link}}" title="{{sanitize name}}")
|
||||
.attachment-thumbnail-container.open-preview(data-attachment-id="{{_id}}" data-card-id="{{ meta.cardId }}")
|
||||
if link
|
||||
if isImage
|
||||
img.attachment-thumbnail-img(src="{{link}}" title="{{sanitize name}}")
|
||||
if(isImage)
|
||||
img.attachment-thumbnail(src="{{link}}" title="{{sanitize name}}")
|
||||
else if($eq extension 'svg')
|
||||
img.attachment-thumbnail(src="{{link}}" title="{{sanitize name}}" type="image/svg+xml")
|
||||
else if($eq extension 'mp3')
|
||||
video(width="100%" height="100%" title="{{sanitize name}}" controls="true")
|
||||
video.attachment-thumbnail(title="{{sanitize name}}")
|
||||
source(src="{{link}}" type="audio/mpeg")
|
||||
else if($eq extension 'ogg')
|
||||
video(width="100%" height="100%" title="{{sanitize name}}" controls="true")
|
||||
video.attachment-thumbnail(title="{{sanitize name}}")
|
||||
source(src="{{link}}" type="video/ogg")
|
||||
else if($eq extension 'webm')
|
||||
video(width="100%" height="100%" title="{{sanitize name}}" controls="true")
|
||||
video.attachment-thumbnail(title="{{sanitize name}}")
|
||||
source(src="{{link}}" type="video/webm")
|
||||
else if($eq extension 'mp4')
|
||||
video(width="100%" height="100%" title="{{sanitize name}}" controls="true")
|
||||
video.attachment-thumbnail(title="{{sanitize name}}")
|
||||
source(src="{{link}}" type="video/mp4")
|
||||
else
|
||||
span.attachment-thumbnail-ext= extension
|
||||
p.attachment-details
|
||||
= name
|
||||
span.file-size ({{fileSize size}})
|
||||
span.attachment-details-actions
|
||||
a.js-download(href="{{link}}?download=true", download="{{name}}")
|
||||
i.fa.fa-download
|
||||
| {{_ 'download'}}
|
||||
if currentUser.isBoardMember
|
||||
unless currentUser.isCommentOnly
|
||||
unless currentUser.isWorker
|
||||
a.fa.fa-navicon.attachment-details-menu.js-open-attachment-menu(title="{{_ 'attachmentActionsPopup-title'}}")
|
||||
span.attachment-thumbnail-text= extension
|
||||
|
||||
.attachment-details-container
|
||||
.attachment-details
|
||||
div
|
||||
b
|
||||
= name
|
||||
span.file-size ({{fileSize size}})
|
||||
.attachment-actions
|
||||
a.js-download(href="{{link}}?download=true", download="{{name}}")
|
||||
i.fa.fa-download.icon(title="{{_ 'download'}}")
|
||||
if currentUser.isBoardMember
|
||||
unless currentUser.isCommentOnly
|
||||
unless currentUser.isWorker
|
||||
a.js-rename
|
||||
i.fa.fa-pencil-square-o.icon(title="{{_ 'rename'}}")
|
||||
a.js-confirm-delete
|
||||
i.fa.fa-trash.icon(title="{{_ 'delete'}}")
|
||||
a.fa.fa-navicon.icon.js-open-attachment-menu(data-attachment-link="{{link}}" title="{{_ 'attachmentActionsPopup-title'}}")
|
||||
|
||||
|
||||
template(name="attachmentActionsPopup")
|
||||
ul.pop-over-list
|
||||
li
|
||||
if isImage
|
||||
a(class="{{#if isCover}}js-remove-cover{{else}}js-add-cover{{/if}}")
|
||||
i.fa.fa-thumb-tack
|
||||
i.fa.fa-book
|
||||
i.fa.fa-picture-o
|
||||
if isCover
|
||||
| {{_ 'remove-cover'}}
|
||||
else
|
||||
| {{_ 'add-cover'}}
|
||||
if currentUser.isBoardAdmin
|
||||
a.js-rename
|
||||
i.fa.fa-pencil-square-o
|
||||
| {{_ 'rename'}}
|
||||
a.js-confirm-delete
|
||||
i.fa.fa-close
|
||||
| {{_ 'delete'}}
|
||||
if isImage
|
||||
a(class="{{#if isBackgroundImage}}js-remove-background-image{{else}}js-add-background-image{{/if}}")
|
||||
i.fa.fa-picture-o
|
||||
if isBackgroundImage
|
||||
| {{_ 'remove-background-image'}}
|
||||
else
|
||||
| {{_ 'add-background-image'}}
|
||||
p.attachment-storage
|
||||
| {{versions.original.storage}}
|
||||
|
||||
|
||||
@@ -1,10 +1,28 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { ObjectID } from 'bson';
|
||||
import DOMPurify from 'dompurify';
|
||||
|
||||
const filesize = require('filesize');
|
||||
const prettyMilliseconds = require('pretty-ms');
|
||||
|
||||
Template.attachmentsGalery.events({
|
||||
// We store current card ID and the ID of currently opened attachment in a
|
||||
// global var. This is used so that we know what's the next attachment to open
|
||||
// when the user clicks on the prev/next button in the attachment viewer.
|
||||
let cardId = null;
|
||||
let openAttachmentId = null;
|
||||
|
||||
|
||||
// Stores link to the attachment for which attachment actions popup was opened
|
||||
attachmentActionsLink = null;
|
||||
|
||||
Template.attachmentGallery.events({
|
||||
'click .open-preview'(event) {
|
||||
|
||||
openAttachmentId = $(event.currentTarget).attr("data-attachment-id");
|
||||
cardId = $(event.currentTarget).attr("data-card-id");
|
||||
|
||||
openAttachmentViewer(openAttachmentId);
|
||||
},
|
||||
'click .js-add-attachment': Popup.open('cardAttachments'),
|
||||
// If we let this event bubble, FlowRouter will handle it and empty the page
|
||||
// content, see #101.
|
||||
@@ -12,11 +30,144 @@ Template.attachmentsGalery.events({
|
||||
event.stopPropagation();
|
||||
},
|
||||
'click .js-open-attachment-menu': Popup.open('attachmentActions'),
|
||||
'mouseover .js-open-attachment-menu'(event) { // For some reason I cannot combine handlers for "click .js-open-attachment-menu" and "mouseover .js-open-attachment-menu" events so this is a quick workaround.
|
||||
attachmentActionsLink = event.currentTarget.getAttribute("data-attachment-link");
|
||||
},
|
||||
'click .js-rename': Popup.open('attachmentRename'),
|
||||
'click .js-confirm-delete': Popup.afterConfirm('attachmentDelete', function() {
|
||||
Attachments.remove(this._id);
|
||||
Popup.back(2);
|
||||
}),
|
||||
});
|
||||
|
||||
Template.attachmentsGalery.helpers({
|
||||
function getNextAttachmentId(currentAttachmentId) {
|
||||
const attachments = ReactiveCache.getAttachments({'meta.cardId': cardId});
|
||||
|
||||
let i = 0;
|
||||
for (; i < attachments.length; i++) {
|
||||
if (attachments[i]._id === currentAttachmentId) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return attachments[(i + 1 + attachments.length) % attachments.length]._id;
|
||||
}
|
||||
|
||||
function getPrevAttachmentId(currentAttachmentId) {
|
||||
const attachments = ReactiveCache.getAttachments({'meta.cardId': cardId});
|
||||
|
||||
let i = 0;
|
||||
for (; i < attachments.length; i++) {
|
||||
if (attachments[i]._id === currentAttachmentId) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return attachments[(i - 1 + attachments.length) % attachments.length]._id;
|
||||
}
|
||||
|
||||
function openAttachmentViewer(attachmentId){
|
||||
|
||||
const attachment = ReactiveCache.getAttachment(attachmentId);
|
||||
|
||||
$("#attachment-name").text(attachment.name);
|
||||
|
||||
// IMPORTANT: if you ever add a new viewer, make sure you also implement
|
||||
// cleanup in the closeAttachmentViewer() function
|
||||
switch(true){
|
||||
case (attachment.isImage):
|
||||
$("#image-viewer").attr("src", attachment.link());
|
||||
$("#image-viewer").removeClass("hidden");
|
||||
break;
|
||||
case (attachment.isPDF):
|
||||
$("#pdf-viewer").attr("data", attachment.link());
|
||||
$("#pdf-viewer").removeClass("hidden");
|
||||
break;
|
||||
case (attachment.isVideo):
|
||||
// We have to create a new <source> DOM element and append it to the video
|
||||
// element, otherwise the video won't load
|
||||
let videoSource = document.createElement('source');
|
||||
videoSource.setAttribute('src', attachment.link());
|
||||
$("#video-viewer").append(videoSource);
|
||||
|
||||
$("#video-viewer").removeClass("hidden");
|
||||
break;
|
||||
case (attachment.isAudio):
|
||||
// We have to create a new <source> DOM element and append it to the audio
|
||||
// element, otherwise the audio won't load
|
||||
let audioSource = document.createElement('source');
|
||||
audioSource.setAttribute('src', attachment.link());
|
||||
$("#audio-viewer").append(audioSource);
|
||||
|
||||
$("#audio-viewer").removeClass("hidden");
|
||||
break;
|
||||
case (attachment.isText):
|
||||
case (attachment.isJSON):
|
||||
$("#txt-viewer").attr("data", attachment.link());
|
||||
$("#txt-viewer").removeClass("hidden");
|
||||
break;
|
||||
}
|
||||
|
||||
$("#viewer-overlay").removeClass("hidden");
|
||||
}
|
||||
|
||||
function closeAttachmentViewer() {
|
||||
$("#viewer-overlay").addClass("hidden");
|
||||
|
||||
// We need to reset the viewers to avoid showing previous attachments
|
||||
$("#image-viewer").attr("src", "");
|
||||
$("#image-viewer").addClass("hidden");
|
||||
|
||||
$("#pdf-viewer").attr("data", "");
|
||||
$("#pdf-viewer").addClass("hidden");
|
||||
|
||||
$("#txt-viewer").attr("data", "");
|
||||
$("#txt-viewer").addClass("hidden");
|
||||
|
||||
$("#video-viewer").get(0).pause(); // Stop playback
|
||||
$("#video-viewer").get(0).currentTime = 0;
|
||||
$("#video-viewer").empty();
|
||||
$("#video-viewer").addClass("hidden");
|
||||
|
||||
$("#audio-viewer").get(0).pause(); // Stop playback
|
||||
$("#audio-viewer").get(0).currentTime = 0;
|
||||
$("#audio-viewer").empty();
|
||||
$("#audio-viewer").addClass("hidden");
|
||||
}
|
||||
|
||||
Template.attachmentViewer.events({
|
||||
'click #viewer-container'(event) {
|
||||
|
||||
// Make sure the click was on #viewer-container and not on any of its children
|
||||
if(event.target !== event.currentTarget) return;
|
||||
|
||||
closeAttachmentViewer();
|
||||
},
|
||||
'click #viewer-content'(event) {
|
||||
|
||||
// Make sure the click was on #viewer-content and not on any of its children
|
||||
if(event.target !== event.currentTarget) return;
|
||||
|
||||
closeAttachmentViewer();
|
||||
},
|
||||
'click #viewer-close'() {
|
||||
closeAttachmentViewer();
|
||||
},
|
||||
'click #next-attachment'(event) {
|
||||
closeAttachmentViewer()
|
||||
const id = getNextAttachmentId(openAttachmentId);
|
||||
openAttachmentId = id;
|
||||
openAttachmentViewer(id);
|
||||
},
|
||||
'click #prev-attachment'(event) {
|
||||
closeAttachmentViewer()
|
||||
const id = getPrevAttachmentId(openAttachmentId);
|
||||
openAttachmentId = id;
|
||||
openAttachmentViewer(id);
|
||||
}
|
||||
});
|
||||
|
||||
Template.attachmentGallery.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
fileSize(size) {
|
||||
const ret = filesize(size);
|
||||
@@ -172,25 +323,40 @@ Template.previewClipboardImagePopup.events({
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
isCover() {
|
||||
const ret = Cards.findOne(this.data().meta.cardId).coverId == this.data()._id;
|
||||
const ret = ReactiveCache.getCard(this.data().meta.cardId).coverId == this.data()._id;
|
||||
return ret;
|
||||
},
|
||||
isBackgroundImage() {
|
||||
//const currentBoard = Utils.getCurrentBoard();
|
||||
//return currentBoard.backgroundImageURL === $(".attachment-thumbnail-img").attr("src");
|
||||
return false;
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-rename': Popup.open('attachmentRename'),
|
||||
'click .js-confirm-delete': Popup.afterConfirm('attachmentDelete', function() {
|
||||
Attachments.remove(this._id);
|
||||
Popup.back(2);
|
||||
}),
|
||||
'click .js-add-cover'() {
|
||||
Cards.findOne(this.data().meta.cardId).setCover(this.data()._id);
|
||||
ReactiveCache.getCard(this.data().meta.cardId).setCover(this.data()._id);
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-remove-cover'() {
|
||||
Cards.findOne(this.data().meta.cardId).unsetCover();
|
||||
ReactiveCache.getCard(this.data().meta.cardId).unsetCover();
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-add-background-image'() {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
currentBoard.setBackgroundImageURL(attachmentActionsLink);
|
||||
Utils.setBackgroundImage(attachmentActionsLink);
|
||||
Popup.back();
|
||||
event.preventDefault();
|
||||
},
|
||||
'click .js-remove-background-image'() {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
currentBoard.setBackgroundImageURL("");
|
||||
Utils.setBackgroundImage("");
|
||||
Popup.back();
|
||||
Utils.reload();
|
||||
event.preventDefault();
|
||||
},
|
||||
'click .js-move-storage-fs'() {
|
||||
Meteor.call('moveAttachmentToStorage', this.data()._id, "fs");
|
||||
Popup.back();
|
||||
|
||||
@@ -37,14 +37,6 @@ const CardCustomField = BlazeComponent.extendComponent({
|
||||
self.card = Utils.getCurrentCard();
|
||||
self.customFieldId = this.data()._id;
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly()
|
||||
);
|
||||
},
|
||||
});
|
||||
CardCustomField.register('cardCustomField');
|
||||
|
||||
|
||||
@@ -2,17 +2,6 @@ import moment from 'moment/min/moment-with-locales';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import { DatePicker } from '/client/lib/datepicker';
|
||||
|
||||
Template.dateBadge.helpers({
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
// editCardReceivedDatePopup
|
||||
(class extends DatePicker {
|
||||
onCreated() {
|
||||
|
||||
@@ -541,8 +541,8 @@ template(name="cardDetails")
|
||||
+viewer
|
||||
= getDescription
|
||||
|
||||
.card-checklist-attachmentGalerys
|
||||
.card-checklist-attachmentGalery.card-checklists
|
||||
.card-checklist-attachmentGalleries
|
||||
.card-checklist-attachmentGallery.card-checklists
|
||||
if currentBoard.allowsChecklists
|
||||
hr
|
||||
+checklists(cardId = _id)
|
||||
@@ -555,14 +555,15 @@ template(name="cardDetails")
|
||||
i.fa.fa-paperclip
|
||||
| {{_ 'attachments'}}
|
||||
if Meteor.settings.public.attachmentsUploadMaxSize
|
||||
| {{_ 'max-upload-filesize'}} {{Meteor.settings.public.attachmentsUploadMaxSize}}
|
||||
| {{_ 'max-upload-filesize'}} {{Meteor.settings.public.attachmentsUploadMaxSize}}
|
||||
br
|
||||
if Meteor.settings.public.attachmentsUploadMimeTypes
|
||||
| {{_ 'allowed-upload-filetypes'}} {{Meteor.settings.public.attachmentsUploadMimeTypes}}
|
||||
br
|
||||
| {{_ 'invalid-file'}}
|
||||
.card-checklist-attachmentGalery.card-attachmentGalery
|
||||
+attachmentsGalery
|
||||
.card-checklist-attachmentGallery.card-attachmentGallery
|
||||
+attachmentViewer
|
||||
+attachmentGallery
|
||||
hr
|
||||
|
||||
.card-details-right
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import moment from 'moment/min/moment-with-locales';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import { DatePicker } from '/client/lib/datepicker';
|
||||
@@ -63,25 +64,16 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
hiddenSystemMessages() {
|
||||
return Meteor.user().hasHiddenSystemMessages();
|
||||
return ReactiveCache.getCurrentUser().hasHiddenSystemMessages();
|
||||
},
|
||||
|
||||
customFieldsGrid() {
|
||||
return Meteor.user().hasCustomFieldsGrid();
|
||||
return ReactiveCache.getCurrentUser().hasCustomFieldsGrid();
|
||||
},
|
||||
|
||||
|
||||
cardMaximized() {
|
||||
return !Utils.getPopupCardId() && Meteor.user().hasCardMaximized();
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
return !Utils.getPopupCardId() && ReactiveCache.getCurrentUser().hasCardMaximized();
|
||||
},
|
||||
|
||||
scrollParentContainer() {
|
||||
@@ -152,7 +144,7 @@ BlazeComponent.extendComponent({
|
||||
const card = this.currentData();
|
||||
let result = '#';
|
||||
if (card) {
|
||||
const board = Boards.findOne(card.boardId);
|
||||
const board = ReactiveCache.getBoard(card.boardId);
|
||||
if (board) {
|
||||
result = FlowRouter.path('card', {
|
||||
boardId: card.boardId,
|
||||
@@ -201,15 +193,15 @@ BlazeComponent.extendComponent({
|
||||
cardId: card._id,
|
||||
boardId: card.boardId,
|
||||
listId: card.listId,
|
||||
user: Meteor.user().username,
|
||||
user: ReactiveCache.getCurrentUser().username,
|
||||
url: '',
|
||||
};
|
||||
|
||||
const integrations = Integrations.find({
|
||||
const integrations = ReactiveCache.getIntegrations({
|
||||
boardId: { $in: [card.boardId, Integrations.Const.GLOBAL_WEBHOOK_ID] },
|
||||
enabled: true,
|
||||
activities: { $in: ['CardDetailsRendered', 'all'] },
|
||||
}).fetch();
|
||||
});
|
||||
|
||||
if (integrations.length > 0) {
|
||||
integrations.forEach((integration) => {
|
||||
@@ -296,7 +288,7 @@ BlazeComponent.extendComponent({
|
||||
});
|
||||
|
||||
function userIsMember() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember();
|
||||
return ReactiveCache.getCurrentUser()?.isBoardMember();
|
||||
}
|
||||
|
||||
// Disable sorting if the current user is not a board member
|
||||
@@ -660,15 +652,7 @@ Template.cardDetailsActionsPopup.helpers({
|
||||
},
|
||||
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly()
|
||||
);
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -744,19 +728,8 @@ BlazeComponent.extendComponent({
|
||||
}).register('editCardTitleForm');
|
||||
|
||||
Template.cardMembersPopup.onCreated(function () {
|
||||
let currBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
let currBoard = Utils.getCurrentBoard();
|
||||
let members = currBoard.activeMembers();
|
||||
|
||||
// let query = {
|
||||
// "teams.teamId": { $in: currBoard.teams.map(t => t.teamId) },
|
||||
// };
|
||||
|
||||
// let boardTeamUsers = Users.find(query, {
|
||||
// sort: { sort: 1 },
|
||||
// });
|
||||
|
||||
// members = currBoard.activeMembers2(members, boardTeamUsers);
|
||||
|
||||
this.members = new ReactiveVar(members);
|
||||
});
|
||||
|
||||
@@ -774,24 +747,14 @@ Template.cardMembersPopup.helpers({
|
||||
});
|
||||
|
||||
const filterMembers = (filterTerm) => {
|
||||
let currBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
let currBoard = Utils.getCurrentBoard();
|
||||
let members = currBoard.activeMembers();
|
||||
|
||||
// let query = {
|
||||
// "teams.teamId": { $in: currBoard.teams.map(t => t.teamId) },
|
||||
// };
|
||||
|
||||
// let boardTeamUsers = Users.find(query, {
|
||||
// sort: { sort: 1 },
|
||||
// });
|
||||
|
||||
// members = currBoard.activeMembers2(members, boardTeamUsers);
|
||||
|
||||
if (filterTerm) {
|
||||
members = members
|
||||
.map(member => ({
|
||||
member,
|
||||
user: Users.findOne(member.userId)
|
||||
user: ReactiveCache.getUser(member.userId)
|
||||
}))
|
||||
.filter(({ user }) =>
|
||||
(user.profile.fullname !== undefined && user.profile.fullname.toLowerCase().indexOf(filterTerm.toLowerCase()) !== -1)
|
||||
@@ -830,11 +793,11 @@ Template.editCardAssignerForm.events({
|
||||
/** Move Card Dialog */
|
||||
(class extends DialogWithBoardSwimlaneList {
|
||||
getDialogOptions() {
|
||||
const ret = Meteor.user().getMoveAndCopyDialogOptions();
|
||||
const ret = ReactiveCache.getCurrentUser().getMoveAndCopyDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(boardId, swimlaneId, listId, options) {
|
||||
Meteor.user().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
const minOrder = card.getMinSort(listId, swimlaneId);
|
||||
card.move(boardId, swimlaneId, listId, minOrder - 1);
|
||||
@@ -844,11 +807,11 @@ Template.editCardAssignerForm.events({
|
||||
/** Copy Card Dialog */
|
||||
(class extends DialogWithBoardSwimlaneList {
|
||||
getDialogOptions() {
|
||||
const ret = Meteor.user().getMoveAndCopyDialogOptions();
|
||||
const ret = ReactiveCache.getCurrentUser().getMoveAndCopyDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(boardId, swimlaneId, listId, options) {
|
||||
Meteor.user().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
|
||||
// const textarea = $('#copy-card-title');
|
||||
@@ -871,11 +834,11 @@ Template.editCardAssignerForm.events({
|
||||
/** Convert Checklist-Item to card dialog */
|
||||
(class extends DialogWithBoardSwimlaneList {
|
||||
getDialogOptions() {
|
||||
const ret = Meteor.user().getMoveAndCopyDialogOptions();
|
||||
const ret = ReactiveCache.getCurrentUser().getMoveAndCopyDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(boardId, swimlaneId, listId, options) {
|
||||
Meteor.user().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
|
||||
const textarea = this.$('#copy-card-title');
|
||||
@@ -889,7 +852,7 @@ Template.editCardAssignerForm.events({
|
||||
swimlaneId: swimlaneId,
|
||||
sort: 0,
|
||||
});
|
||||
const card = Cards.findOne(_id);
|
||||
const card = ReactiveCache.getCard(_id);
|
||||
const minOrder = card.getMinSort();
|
||||
card.move(card.boardId, card.swimlaneId, card.listId, minOrder - 1);
|
||||
|
||||
@@ -901,11 +864,11 @@ Template.editCardAssignerForm.events({
|
||||
/** Copy many cards dialog */
|
||||
(class extends DialogWithBoardSwimlaneList {
|
||||
getDialogOptions() {
|
||||
const ret = Meteor.user().getMoveAndCopyDialogOptions();
|
||||
const ret = ReactiveCache.getCurrentUser().getMoveAndCopyDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(boardId, swimlaneId, listId, options) {
|
||||
Meteor.user().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
ReactiveCache.getCurrentUser().setMoveAndCopyDialogOption(this.currentBoardId, options);
|
||||
const card = this.data();
|
||||
|
||||
const textarea = this.$('#copy-card-title');
|
||||
@@ -977,27 +940,27 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
boards() {
|
||||
return Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
_id: {
|
||||
$ne: Meteor.user().getTemplatesBoardId(),
|
||||
},
|
||||
_id: { $ne: ReactiveCache.getCurrentUser().getTemplatesBoardId() },
|
||||
},
|
||||
{
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
|
||||
cards() {
|
||||
const currentId = Utils.getCurrentCardId();
|
||||
if (this.parentBoard.get()) {
|
||||
return Cards.find({
|
||||
const ret = ReactiveCache.getCards({
|
||||
boardId: this.parentBoard.get(),
|
||||
_id: { $ne: currentId },
|
||||
});
|
||||
return ret;
|
||||
} else {
|
||||
return [];
|
||||
}
|
||||
@@ -1021,7 +984,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
setParentCardId(cardId) {
|
||||
if (cardId) {
|
||||
this.parentCard = Cards.findOne(cardId);
|
||||
this.parentCard = ReactiveCache.getCard(cardId);
|
||||
} else {
|
||||
this.parentCard = null;
|
||||
}
|
||||
@@ -1040,7 +1003,7 @@ BlazeComponent.extendComponent({
|
||||
'click .js-delete': Popup.afterConfirm('cardDelete', function () {
|
||||
Popup.close();
|
||||
// verify that there are no linked cards
|
||||
if (Cards.find({ linkedId: this._id }).count() === 0) {
|
||||
if (ReactiveCache.getCards({ linkedId: this._id }).length === 0) {
|
||||
Cards.remove(this._id);
|
||||
} else {
|
||||
// TODO: Maybe later we can list where the linked cards are.
|
||||
@@ -1579,8 +1542,8 @@ EscapeActions.register(
|
||||
() => {
|
||||
// if card description diverges from database due to editing
|
||||
// ask user whether changes should be applied
|
||||
if (Meteor.user()) {
|
||||
if (Meteor.user().profile.rescueCardDescription == true) {
|
||||
if (ReactiveCache.getCurrentUser()) {
|
||||
if (ReactiveCache.getCurrentUser().profile.rescueCardDescription == true) {
|
||||
currentDescription = document.getElementsByClassName("editor js-new-description-input").item(0)
|
||||
if (currentDescription?.value && !(currentDescription.value === Utils.getCurrentCard().getDescription())) {
|
||||
if (confirm(TAPi18n.__('rescue-card-description-dialogue'))) {
|
||||
@@ -1614,19 +1577,8 @@ EscapeActions.register(
|
||||
);
|
||||
|
||||
Template.cardAssigneesPopup.onCreated(function () {
|
||||
let currBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
let currBoard = Utils.getCurrentBoard();
|
||||
let members = currBoard.activeMembers();
|
||||
|
||||
// let query = {
|
||||
// "teams.teamId": { $in: currBoard.teams.map(t => t.teamId) },
|
||||
// };
|
||||
|
||||
// let boardTeamUsers = Users.find(query, {
|
||||
// sort: { sort: 1 },
|
||||
// });
|
||||
|
||||
// members = currBoard.activeMembers2(members, boardTeamUsers);
|
||||
|
||||
this.members = new ReactiveVar(members);
|
||||
});
|
||||
|
||||
@@ -1656,13 +1608,13 @@ Template.cardAssigneesPopup.helpers({
|
||||
},
|
||||
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
});
|
||||
|
||||
Template.cardAssigneePopup.helpers({
|
||||
userData() {
|
||||
return Users.findOne(this.userId, {
|
||||
return ReactiveCache.getUser(this.userId, {
|
||||
fields: {
|
||||
profile: 1,
|
||||
username: 1,
|
||||
@@ -1671,21 +1623,10 @@ Template.cardAssigneePopup.helpers({
|
||||
},
|
||||
|
||||
memberType() {
|
||||
const user = Users.findOne(this.userId);
|
||||
const user = ReactiveCache.getUser(this.userId);
|
||||
return user && user.isBoardAdmin() ? 'admin' : 'normal';
|
||||
},
|
||||
|
||||
/*
|
||||
presenceStatusClassName() {
|
||||
const user = Users.findOne(this.userId);
|
||||
const userPresence = presences.findOne({ userId: this.userId });
|
||||
if (user && user.isInvitedTo(Session.get('currentBoard'))) return 'pending';
|
||||
else if (!userPresence) return 'disconnected';
|
||||
else if (Session.equals('currentBoard', userPresence.state.currentBoardId))
|
||||
return 'active';
|
||||
else return 'idle';
|
||||
},
|
||||
*/
|
||||
isCardAssignee() {
|
||||
const card = Template.parentData();
|
||||
const cardAssignees = card.getAssignees();
|
||||
@@ -1694,13 +1635,13 @@ Template.cardAssigneePopup.helpers({
|
||||
},
|
||||
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
});
|
||||
|
||||
Template.cardAssigneePopup.events({
|
||||
'click .js-remove-assignee'() {
|
||||
Cards.findOne(this.cardId).unassignAssignee(this.userId);
|
||||
ReactiveCache.getCard(this.cardId).unassignAssignee(this.userId);
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-edit-profile': Popup.open('editProfile'),
|
||||
|
||||
@@ -83,13 +83,3 @@ BlazeComponent.extendComponent({
|
||||
];
|
||||
},
|
||||
}).register('cardSpentTime');
|
||||
|
||||
Template.timeBadge.helpers({
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly()
|
||||
);
|
||||
},
|
||||
});
|
||||
@@ -164,6 +164,21 @@ textarea.js-edit-checklist-item {
|
||||
color: #222;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,0.2);
|
||||
}
|
||||
.add-checklist-top {
|
||||
/* more space to checklists title */
|
||||
padding-left: 20px;
|
||||
/* + is easier clickable */
|
||||
padding-right: 20px;
|
||||
}
|
||||
.add-checklist-top.js-open-inlined-form:hover {
|
||||
background: #dbdbdb;
|
||||
color: #222;
|
||||
box-shadow: 0 1px 2px rgba(0,0,0,.2);
|
||||
}
|
||||
.card-details-item-title {
|
||||
/* max width for adding checklist at top */
|
||||
width: 100%;
|
||||
}
|
||||
.checklist-details-menu {
|
||||
float: right;
|
||||
padding: 6px 10px 6px 10px;
|
||||
|
||||
@@ -3,6 +3,12 @@ template(name="checklists")
|
||||
h3.card-details-item-title
|
||||
i.fa.fa-check
|
||||
| {{_ 'checklists'}}
|
||||
if canModifyCard
|
||||
+inlinedForm(autoclose=false classNames="js-add-checklist" cardId = cardId position="top")
|
||||
+addChecklistItemForm
|
||||
else
|
||||
a.add-checklist-top.js-open-inlined-form(title="{{_ 'add-checklist'}}")
|
||||
i.fa.fa-plus
|
||||
if currentUser.isBoardMember
|
||||
.material-toggle-switch(title="{{_ 'hide-checked-items'}}")
|
||||
//span.toggle-switch-title
|
||||
@@ -86,6 +92,13 @@ template(name="editChecklistItemForm")
|
||||
| {{_ 'convertChecklistItemToCardPopup-title'}}
|
||||
|
||||
template(name="checklistItems")
|
||||
if checklist.items.length
|
||||
if canModifyCard
|
||||
+inlinedForm(autoclose=false classNames="js-add-checklist-item" checklist = checklist position="top")
|
||||
+addChecklistItemForm(checklist=checklist showNewlineBecomesNewChecklistItem=true)
|
||||
else
|
||||
a.add-checklist-item.js-open-inlined-form(title="{{_ 'add-checklist-item'}}")
|
||||
i.fa.fa-plus
|
||||
.checklist-items.js-checklist-items
|
||||
each item in checklist.items
|
||||
+inlinedForm(classNames="js-edit-checklist-item" item = item checklist = checklist)
|
||||
@@ -140,10 +153,7 @@ template(name="copyAndMoveChecklist")
|
||||
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 isDialogOptionBoardId _id}}selected{{/if}}") {{title}}
|
||||
option(value="{{_id}}" selected="{{#if isDialogOptionBoardId _id}}selected{{/if}}") {{title}}
|
||||
|
||||
label {{_ 'swimlanes'}}:
|
||||
select.js-select-swimlanes
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import Cards from '/models/cards';
|
||||
import Boards from '/models/boards';
|
||||
@@ -54,7 +55,7 @@ BlazeComponent.extendComponent({
|
||||
});
|
||||
|
||||
function userIsMember() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember();
|
||||
return ReactiveCache.getCurrentUser()?.isBoardMember();
|
||||
}
|
||||
|
||||
// Disable sorting if the current user is not a board member
|
||||
@@ -71,15 +72,6 @@ BlazeComponent.extendComponent({
|
||||
});
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
|
||||
/** returns the finished percent of the checklist */
|
||||
finishedPercent() {
|
||||
const ret = this.data().checklist.finishedPercent();
|
||||
@@ -93,20 +85,32 @@ BlazeComponent.extendComponent({
|
||||
const textarea = this.find('textarea.js-add-checklist-item');
|
||||
const title = textarea.value.trim();
|
||||
let cardId = this.currentData().cardId;
|
||||
const card = Cards.findOne(cardId);
|
||||
const card = ReactiveCache.getCard(cardId);
|
||||
//if (card.isLinked()) cardId = card.linkedId;
|
||||
if (card.isLinkedCard()) cardId = card.linkedId;
|
||||
if (card.isLinkedCard()) {
|
||||
cardId = card.linkedId;
|
||||
}
|
||||
|
||||
let sortIndex;
|
||||
let checklistItemIndex;
|
||||
if (this.currentData().position === 'top') {
|
||||
sortIndex = Utils.calculateIndexData(null, card.firstChecklist()).base;
|
||||
checklistItemIndex = 0;
|
||||
} else {
|
||||
sortIndex = Utils.calculateIndexData(card.lastChecklist(), null).base;
|
||||
checklistItemIndex = -1;
|
||||
}
|
||||
|
||||
if (title) {
|
||||
Checklists.insert({
|
||||
cardId,
|
||||
title,
|
||||
sort: card.checklists().count(),
|
||||
sort: sortIndex,
|
||||
});
|
||||
this.closeAllInlinedForms();
|
||||
setTimeout(() => {
|
||||
this.$('.add-checklist-item')
|
||||
.last()
|
||||
.eq(checklistItemIndex)
|
||||
.click();
|
||||
}, 100);
|
||||
}
|
||||
@@ -122,13 +126,22 @@ BlazeComponent.extendComponent({
|
||||
let checklistItems = [title];
|
||||
if (newlineBecomesNewChecklistItem.checked) {
|
||||
checklistItems = title.split('\n').map(_value => _value.trim());
|
||||
if (this.currentData().position === 'top') {
|
||||
checklistItems = checklistItems.reverse();
|
||||
}
|
||||
}
|
||||
for (let checklistItem of checklistItems) {
|
||||
let sortIndex;
|
||||
if (this.currentData().position === 'top') {
|
||||
sortIndex = Utils.calculateIndexData(null, checklist.firstItem()).base;
|
||||
} else {
|
||||
sortIndex = Utils.calculateIndexData(checklist.lastItem(), null).base;
|
||||
}
|
||||
ChecklistItems.insert({
|
||||
title: checklistItem,
|
||||
checklistId: checklist._id,
|
||||
cardId: checklist.cardId,
|
||||
sort: Utils.calculateIndexData(checklist.lastItem()).base,
|
||||
sort: sortIndex,
|
||||
});
|
||||
}
|
||||
}
|
||||
@@ -137,15 +150,6 @@ BlazeComponent.extendComponent({
|
||||
textarea.focus();
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
|
||||
deleteItem() {
|
||||
const checklist = this.currentData().checklist;
|
||||
const item = this.currentData().item;
|
||||
@@ -229,25 +233,26 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
boards() {
|
||||
return Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
_id: { $ne: Meteor.user().getTemplatesBoardId() },
|
||||
_id: { $ne: ReactiveCache.getCurrentUser().getTemplatesBoardId() },
|
||||
},
|
||||
{
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
|
||||
swimlanes() {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
|
||||
return board.swimlanes();
|
||||
},
|
||||
|
||||
aBoardLists() {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
|
||||
return board.lists();
|
||||
},
|
||||
|
||||
@@ -265,12 +270,12 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.checklists.helpers({
|
||||
checklists() {
|
||||
const card = Cards.findOne(this.cardId);
|
||||
const card = ReactiveCache.getCard(this.cardId);
|
||||
const ret = card.checklists();
|
||||
return ret;
|
||||
},
|
||||
hideCheckedItems() {
|
||||
const currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) return currentUser.hasHideCheckedItems();
|
||||
return false;
|
||||
},
|
||||
@@ -280,14 +285,6 @@ 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 [
|
||||
{
|
||||
@@ -325,14 +322,6 @@ 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 [
|
||||
{
|
||||
@@ -349,16 +338,8 @@ BlazeComponent.extendComponent({
|
||||
}).register('editChecklistItemForm');
|
||||
|
||||
Template.checklistItemDetail.helpers({
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
hideCheckedItems() {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
if (user) return user.hasHideCheckedItems();
|
||||
return false;
|
||||
},
|
||||
@@ -384,11 +365,11 @@ BlazeComponent.extendComponent({
|
||||
/** Move Checklist Dialog */
|
||||
(class extends DialogWithBoardSwimlaneListCard {
|
||||
getDialogOptions() {
|
||||
const ret = Meteor.user().getMoveChecklistDialogOptions();
|
||||
const ret = ReactiveCache.getCurrentUser().getMoveChecklistDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(cardId, options) {
|
||||
Meteor.user().setMoveChecklistDialogOption(this.currentBoardId, options);
|
||||
ReactiveCache.getCurrentUser().setMoveChecklistDialogOption(this.currentBoardId, options);
|
||||
this.data().checklist.move(cardId);
|
||||
}
|
||||
}).register('moveChecklistPopup');
|
||||
@@ -396,11 +377,11 @@ BlazeComponent.extendComponent({
|
||||
/** Copy Checklist Dialog */
|
||||
(class extends DialogWithBoardSwimlaneListCard {
|
||||
getDialogOptions() {
|
||||
const ret = Meteor.user().getCopyChecklistDialogOptions();
|
||||
const ret = ReactiveCache.getCurrentUser().getCopyChecklistDialogOptions();
|
||||
return ret;
|
||||
}
|
||||
setDone(cardId, options) {
|
||||
Meteor.user().setCopyChecklistDialogOption(this.currentBoardId, options);
|
||||
ReactiveCache.getCurrentUser().setCopyChecklistDialogOption(this.currentBoardId, options);
|
||||
this.data().checklist.copy(cardId);
|
||||
}
|
||||
}).register('copyChecklistPopup');
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
let labelColors;
|
||||
Meteor.startup(() => {
|
||||
labelColors = Boards.simpleSchema()._schema['labels.$.color'].allowedValues;
|
||||
@@ -32,7 +34,7 @@ Template.createLabelPopup.helpers({
|
||||
// is not already used in the board (although it's not a problem if two
|
||||
// labels have the same color).
|
||||
defaultColor() {
|
||||
const labels = Boards.findOne(Session.get('currentBoard')).labels;
|
||||
const labels = Utils.getCurrentBoard().labels;
|
||||
const usedColors = _.pluck(labels, 'color');
|
||||
const availableColors = _.difference(labelColors, usedColors);
|
||||
return availableColors.length > 1 ? availableColors[0] : labelColors[0];
|
||||
@@ -117,7 +119,7 @@ Template.createLabelPopup.events({
|
||||
// Create the new label
|
||||
'submit .create-label'(event, templateInstance) {
|
||||
event.preventDefault();
|
||||
const board = Boards.findOne(Session.get('currentBoard'));
|
||||
const board = Utils.getCurrentBoard();
|
||||
const name = templateInstance
|
||||
.$('#labelName')
|
||||
.val()
|
||||
@@ -130,13 +132,13 @@ Template.createLabelPopup.events({
|
||||
|
||||
Template.editLabelPopup.events({
|
||||
'click .js-delete-label': Popup.afterConfirm('deleteLabel', function () {
|
||||
const board = Boards.findOne(Session.get('currentBoard'));
|
||||
const board = Utils.getCurrentBoard();
|
||||
board.removeLabel(this._id);
|
||||
Popup.back(2);
|
||||
}),
|
||||
'submit .edit-label'(event, templateInstance) {
|
||||
event.preventDefault();
|
||||
const board = Boards.findOne(Session.get('currentBoard'));
|
||||
const board = Utils.getCurrentBoard();
|
||||
const name = templateInstance
|
||||
.$('#labelName')
|
||||
.val()
|
||||
@@ -149,6 +151,6 @@ Template.editLabelPopup.events({
|
||||
|
||||
Template.cardLabelsPopup.helpers({
|
||||
isLabelSelected(cardId) {
|
||||
return _.contains(Cards.findOne(cardId).labelIds, this._id);
|
||||
return _.contains(ReactiveCache.getCard(cardId).labelIds, this._id);
|
||||
},
|
||||
});
|
||||
@@ -120,6 +120,13 @@
|
||||
max-width: 100px;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.minicard .minicard-custom-field-item-fullwidth {
|
||||
flex-grow: 1;
|
||||
display: block;
|
||||
word-wrap: break-word;
|
||||
max-width: 100%;
|
||||
margin-right: 4px;
|
||||
}
|
||||
.minicard .handle {
|
||||
width: 20px;
|
||||
height: 20px;
|
||||
|
||||
@@ -9,17 +9,27 @@ template(name="minicard")
|
||||
.fa.fa-arrows
|
||||
else
|
||||
a.fa.fa-navicon.minicard-details-menu.js-open-minicard-details-menu(title="{{_ 'cardDetailsActionsPopup-title'}}")
|
||||
.dates
|
||||
if getReceived
|
||||
unless getStart
|
||||
unless getDue
|
||||
unless getEnd
|
||||
.date
|
||||
+minicardReceivedDate
|
||||
if getStart
|
||||
.date
|
||||
+minicardStartDate
|
||||
if getDue
|
||||
.date
|
||||
+minicardDueDate
|
||||
if getEnd
|
||||
+minicardEndDate
|
||||
if getSpentTime
|
||||
.date
|
||||
+cardSpentTime
|
||||
if cover
|
||||
.minicard-cover(style="background-image: url('{{cover.link 'original'}}?dummyReloadAfterSessionEstablished={{sess}}');")
|
||||
if labels
|
||||
.minicard-labels(class="{{#if hiddenMinicardLabelText}}minicard-labels-no-text{{/if}}")
|
||||
each labels
|
||||
unless hiddenMinicardLabelText
|
||||
span.js-card-label.card-label(class="card-label-{{color}}" title=name)
|
||||
+viewer
|
||||
= name
|
||||
if hiddenMinicardLabelText
|
||||
.minicard-label(class="card-label-{{color}}" title="{{name}}")
|
||||
if currentBoard.allowsCoverAttachmentOnMinicard
|
||||
.minicard-cover(style="background-image: url('{{cover.link 'original'}}?dummyReloadAfterSessionEstablished={{sess}}');")
|
||||
.minicard-title
|
||||
if $eq 'prefix-with-full-path' currentBoard.presentParentTask
|
||||
.parent-prefix
|
||||
@@ -46,50 +56,60 @@ template(name="minicard")
|
||||
if $eq 'subtext-with-parent' currentBoard.presentParentTask
|
||||
.parent-subtext
|
||||
| {{ parentCardName }}
|
||||
|
||||
.dates
|
||||
if getReceived
|
||||
unless getStart
|
||||
unless getDue
|
||||
unless getEnd
|
||||
.date
|
||||
+minicardReceivedDate
|
||||
if getStart
|
||||
.date
|
||||
+minicardStartDate
|
||||
if getDue
|
||||
.date
|
||||
+minicardDueDate
|
||||
if getEnd
|
||||
+minicardEndDate
|
||||
if getSpentTime
|
||||
.date
|
||||
+cardSpentTime
|
||||
if labels
|
||||
.minicard-labels(class="{{#if hiddenMinicardLabelText}}minicard-labels-no-text{{/if}}")
|
||||
each labels
|
||||
unless hiddenMinicardLabelText
|
||||
span.js-card-label.card-label(class="card-label-{{color}}" title=name)
|
||||
+viewer
|
||||
= name
|
||||
if hiddenMinicardLabelText
|
||||
.minicard-label(class="card-label-{{color}}" title="{{name}}")
|
||||
|
||||
.minicard-custom-fields
|
||||
each customFieldsWD
|
||||
if definition.showOnCard
|
||||
if trueValue
|
||||
.minicard-custom-field
|
||||
// If there is custom field label, show label at left,
|
||||
// and value at right
|
||||
if definition.showLabelOnMiniCard
|
||||
.minicard-custom-field-item
|
||||
+viewer
|
||||
= definition.name
|
||||
.minicard-custom-field-item
|
||||
if $eq definition.type "currency"
|
||||
+viewer
|
||||
= formattedCurrencyCustomFieldValue(definition)
|
||||
else if $eq definition.type "date"
|
||||
.date
|
||||
+minicardCustomFieldDate
|
||||
else if $eq definition.type "checkbox"
|
||||
.materialCheckBox(class="{{#if value }}is-checked{{/if}}")
|
||||
else if $eq definition.type "stringtemplate"
|
||||
+viewer
|
||||
= formattedStringtemplateCustomFieldValue(definition)
|
||||
else
|
||||
+viewer
|
||||
= trueValue
|
||||
.minicard-custom-field-item
|
||||
if $eq definition.type "currency"
|
||||
+viewer
|
||||
= formattedCurrencyCustomFieldValue(definition)
|
||||
else if $eq definition.type "date"
|
||||
.date
|
||||
+minicardCustomFieldDate
|
||||
else if $eq definition.type "checkbox"
|
||||
.materialCheckBox(class="{{#if value }}is-checked{{/if}}")
|
||||
else if $eq definition.type "stringtemplate"
|
||||
+viewer
|
||||
= formattedStringtemplateCustomFieldValue(definition)
|
||||
else
|
||||
+viewer
|
||||
= trueValue
|
||||
else
|
||||
// If there is no custom field label,
|
||||
// show value full width
|
||||
.minicard-custom-field-item-fullwidth
|
||||
if $eq definition.type "currency"
|
||||
+viewer
|
||||
= formattedCurrencyCustomFieldValue(definition)
|
||||
else if $eq definition.type "date"
|
||||
.date
|
||||
+minicardCustomFieldDate
|
||||
else if $eq definition.type "checkbox"
|
||||
.materialCheckBox(class="{{#if value }}is-checked{{/if}}")
|
||||
else if $eq definition.type "stringtemplate"
|
||||
+viewer
|
||||
= formattedStringtemplateCustomFieldValue(definition)
|
||||
else
|
||||
+viewer
|
||||
= trueValue
|
||||
|
||||
if showAssignee
|
||||
if getAssignees
|
||||
@@ -109,11 +129,11 @@ template(name="minicard")
|
||||
|
||||
.badges
|
||||
unless currentUser.isNoComments
|
||||
if comments.count
|
||||
.badge(title="{{_ 'card-comments-title' comments.count }}")
|
||||
if comments.length
|
||||
.badge(title="{{_ 'card-comments-title' comments.length }}")
|
||||
span.badge-icon.fa.fa-comment-o.badge-comment
|
||||
= ' '
|
||||
= comments.count
|
||||
= comments.length
|
||||
//span.badge-comment.badge-text
|
||||
//| {{_ 'comment'}}
|
||||
if getDescription
|
||||
@@ -132,10 +152,11 @@ template(name="minicard")
|
||||
if expiredPoker
|
||||
span.badge-text {{ getPokerEstimation }}
|
||||
if attachments.length
|
||||
.badge
|
||||
span.badge-icon.fa.fa-paperclip
|
||||
span.badge-text= attachments.length
|
||||
if checklists.count
|
||||
if currentBoard.allowsBadgeAttachmentOnMinicard
|
||||
.badge
|
||||
span.badge-icon.fa.fa-paperclip
|
||||
span.badge-text= attachments.length
|
||||
if checklists.length
|
||||
.badge(class="{{#if checklistFinished}}is-finished{{/if}}")
|
||||
span.badge-icon.fa.fa-check-square-o
|
||||
span.badge-text.check-list-text {{checklistFinishedCount}}/{{checklistItemCount}}
|
||||
@@ -145,9 +166,10 @@ template(name="minicard")
|
||||
span.badge-text.check-list-text {{subtasksFinishedCount}}/{{allSubtasksCount}}
|
||||
//{{subtasksFinishedCount}}/{{subtasksCount}} does not work because when a subtaks is archived, the count goes down
|
||||
if currentBoard.allowsCardSortingByNumber
|
||||
.badge
|
||||
span.badge-icon.fa.fa-sort
|
||||
span.badge-text.check-list-sort {{ sort }}
|
||||
if currentBoard.allowsCardSortingByNumberOnMinicard
|
||||
.badge
|
||||
span.badge-icon.fa.fa-sort
|
||||
span.badge-text.check-list-sort {{ sort }}
|
||||
if currentBoard.allowsDescriptionTextOnMinicard
|
||||
if getDescription
|
||||
.minicard-description
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import { CustomFieldStringTemplate } from '/client/lib/customFields'
|
||||
|
||||
@@ -37,37 +38,45 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
showCreator() {
|
||||
if (this.data().board()) {
|
||||
return (
|
||||
this.data().board.allowsCreator === null ||
|
||||
this.data().board().allowsCreator === undefined ||
|
||||
this.data().board().allowsCreator
|
||||
);
|
||||
// return this.data().board().allowsCreator;
|
||||
// cache "board" to reduce the mini-mongodb access
|
||||
const board = this.data().board();
|
||||
let ret = false;
|
||||
if (board) {
|
||||
ret =
|
||||
board.allowsCreator === null ||
|
||||
board.allowsCreator === undefined ||
|
||||
board.allowsCreator
|
||||
;
|
||||
}
|
||||
return false;
|
||||
return ret;
|
||||
},
|
||||
|
||||
showMembers() {
|
||||
if (this.data().board()) {
|
||||
return (
|
||||
this.data().board.allowsMembers === null ||
|
||||
this.data().board().allowsMembers === undefined ||
|
||||
this.data().board().allowsMembers
|
||||
);
|
||||
// cache "board" to reduce the mini-mongodb access
|
||||
const board = this.data().board();
|
||||
let ret = false;
|
||||
if (board) {
|
||||
ret =
|
||||
board.allowsMembers === null ||
|
||||
board.allowsMembers === undefined ||
|
||||
board.allowsMembers
|
||||
;
|
||||
}
|
||||
return false;
|
||||
return ret;
|
||||
},
|
||||
|
||||
showAssignee() {
|
||||
if (this.data().board()) {
|
||||
return (
|
||||
this.data().board.allowsAssignee === null ||
|
||||
this.data().board().allowsAssignee === undefined ||
|
||||
this.data().board().allowsAssignee
|
||||
);
|
||||
// cache "board" to reduce the mini-mongodb access
|
||||
const board = this.data().board();
|
||||
let ret = false;
|
||||
if (board) {
|
||||
ret =
|
||||
board.allowsAssignee === null ||
|
||||
board.allowsAssignee === undefined ||
|
||||
board.allowsAssignee
|
||||
;
|
||||
}
|
||||
return false;
|
||||
return ret;
|
||||
},
|
||||
|
||||
/** opens the card label popup only if clicked onto a label
|
||||
@@ -105,7 +114,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.minicard.helpers({
|
||||
hiddenMinicardLabelText() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).hiddenMinicardLabelText;
|
||||
} else if (window.localStorage.getItem('hiddenMinicardLabelText')) {
|
||||
|
||||
@@ -1,13 +1,4 @@
|
||||
BlazeComponent.extendComponent({
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
}).register('subtaskDetail');
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
addSubtask(event) {
|
||||
@@ -15,19 +6,19 @@ BlazeComponent.extendComponent({
|
||||
const textarea = this.find('textarea.js-add-subtask-item');
|
||||
const title = textarea.value.trim();
|
||||
const cardId = this.currentData().cardId;
|
||||
const card = Cards.findOne(cardId);
|
||||
const card = ReactiveCache.getCard(cardId);
|
||||
const sortIndex = -1;
|
||||
const crtBoard = Boards.findOne(card.boardId);
|
||||
const crtBoard = ReactiveCache.getBoard(card.boardId);
|
||||
const targetBoard = crtBoard.getDefaultSubtasksBoard();
|
||||
const listId = targetBoard.getDefaultSubtasksListId();
|
||||
|
||||
//Get the full swimlane data for the parent task.
|
||||
const parentSwimlane = Swimlanes.findOne({
|
||||
const parentSwimlane = ReactiveCache.getSwimlane({
|
||||
boardId: crtBoard._id,
|
||||
_id: card.swimlaneId,
|
||||
});
|
||||
//find the swimlane of the same name in the target board.
|
||||
const targetSwimlane = Swimlanes.findOne({
|
||||
const targetSwimlane = ReactiveCache.getSwimlane({
|
||||
boardId: targetBoard._id,
|
||||
title: parentSwimlane.title,
|
||||
});
|
||||
@@ -70,15 +61,6 @@ BlazeComponent.extendComponent({
|
||||
textarea.focus();
|
||||
},
|
||||
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
|
||||
deleteSubtask() {
|
||||
const subtask = this.currentData().subtask;
|
||||
if (subtask && subtask._id) {
|
||||
@@ -117,17 +99,6 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
}).register('subtasks');
|
||||
|
||||
Template.subtaskItemDetail.helpers({
|
||||
canModifyCard() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
);
|
||||
},
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
// ...
|
||||
}).register('subtaskItemDetail');
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
export function csvGetMembersToMap(data) {
|
||||
// we will work on the list itself (an ordered array of objects) when a
|
||||
// mapping is done, we add a 'wekan' field to the object representing the
|
||||
@@ -28,7 +30,7 @@ export function csvGetMembersToMap(data) {
|
||||
username: importedMember,
|
||||
id: importedMember,
|
||||
};
|
||||
const wekanUser = Users.findOne({ username: importedMember.username });
|
||||
const wekanUser = ReactiveCache.getUser({ username: importedMember.username });
|
||||
if (wekanUser) importedMember.wekanId = wekanUser._id;
|
||||
membersToMap.push(importedMember);
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { trelloGetMembersToMap } from './trelloMembersMapper';
|
||||
import { wekanGetMembersToMap } from './wekanMembersMapper';
|
||||
import { csvGetMembersToMap } from './csvMembersMapper';
|
||||
@@ -174,9 +175,9 @@ BlazeComponent.extendComponent({
|
||||
this._refreshMembers(
|
||||
this.members().map(member => {
|
||||
if (!member.wekanId) {
|
||||
let user = Users.findOne({ username: member.username });
|
||||
let user = ReactiveCache.getUser({ username: member.username });
|
||||
if (!user) {
|
||||
user = Users.findOne({ importUsernames: member.username });
|
||||
user = ReactiveCache.getUser({ importUsernames: member.username });
|
||||
}
|
||||
if (user) {
|
||||
// eslint-disable-next-line no-console
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
export function trelloGetMembersToMap(data) {
|
||||
// we will work on the list itself (an ordered array of objects) when a
|
||||
// mapping is done, we add a 'wekan' field to the object representing the
|
||||
@@ -5,7 +7,7 @@ export function trelloGetMembersToMap(data) {
|
||||
const membersToMap = data.members;
|
||||
// auto-map based on username
|
||||
membersToMap.forEach(importedMember => {
|
||||
const wekanUser = Users.findOne({ username: importedMember.username });
|
||||
const wekanUser = ReactiveCache.getUser({ username: importedMember.username });
|
||||
if (wekanUser) {
|
||||
importedMember.wekanId = wekanUser._id;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
export function wekanGetMembersToMap(data) {
|
||||
// we will work on the list itself (an ordered array of objects) when a
|
||||
// mapping is done, we add a 'wekan' field to the object representing the
|
||||
@@ -15,7 +17,7 @@ export function wekanGetMembersToMap(data) {
|
||||
importedMember.fullName = user.profile.fullname;
|
||||
}
|
||||
importedMember.username = user.username;
|
||||
const wekanUser = Users.findOne({ username: importedMember.username });
|
||||
const wekanUser = ReactiveCache.getUser({ username: importedMember.username });
|
||||
if (wekanUser) {
|
||||
importedMember.wekanId = wekanUser._id;
|
||||
}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
/* overflow: auto; - List width and height resizeable */
|
||||
}
|
||||
.list:first-child {
|
||||
min-width: 20px;
|
||||
margin-left: 5px;
|
||||
border-left: none;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
require('/client/lib/jquery-ui.js')
|
||||
|
||||
@@ -23,14 +24,6 @@ BlazeComponent.extendComponent({
|
||||
onRendered() {
|
||||
const boardComponent = this.parentComponent().parentComponent();
|
||||
|
||||
function userIsMember() {
|
||||
return (
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly()
|
||||
);
|
||||
}
|
||||
|
||||
const itemsSelector = '.js-minicard:not(.placeholder, .js-card-composer)';
|
||||
const $cards = this.$('.js-minicards');
|
||||
|
||||
@@ -60,6 +53,7 @@ BlazeComponent.extendComponent({
|
||||
distance: 7,
|
||||
items: itemsSelector,
|
||||
placeholder: 'minicard-wrapper placeholder',
|
||||
scrollSpeed: 10,
|
||||
start(evt, ui) {
|
||||
ui.helper.css('z-index', 1000);
|
||||
ui.placeholder.height(ui.helper.height());
|
||||
@@ -74,7 +68,7 @@ BlazeComponent.extendComponent({
|
||||
const nCards = MultiSelection.isActive() ? MultiSelection.count() : 1;
|
||||
const sortIndex = calculateIndex(prevCardDom, nextCardDom, nCards);
|
||||
const listId = Blaze.getData(ui.item.parents('.list').get(0))._id;
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const defaultSwimlaneId = currentBoard.getDefaultSwimline()._id;
|
||||
let targetSwimlaneId = null;
|
||||
|
||||
@@ -96,7 +90,7 @@ BlazeComponent.extendComponent({
|
||||
$cards.sortable('cancel');
|
||||
|
||||
if (MultiSelection.isActive()) {
|
||||
Cards.find(MultiSelection.getMongoSelector(), { sort: ['sort'] }).forEach((card, i) => {
|
||||
ReactiveCache.getCards(MultiSelection.getMongoSelector(), { sort: ['sort'] }).forEach((card, i) => {
|
||||
const newSwimlaneId = targetSwimlaneId
|
||||
? targetSwimlaneId
|
||||
: card.swimlaneId || defaultSwimlaneId;
|
||||
@@ -168,9 +162,9 @@ BlazeComponent.extendComponent({
|
||||
'option',
|
||||
'disabled',
|
||||
// Disable drag-dropping when user is not member
|
||||
!userIsMember(),
|
||||
!Utils.canModifyBoard(),
|
||||
// Not disable drag-dropping while in multi-selection mode
|
||||
// MultiSelection.isActive() || !userIsMember(),
|
||||
// MultiSelection.isActive() || !Utils.canModifyBoard(),
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -180,14 +174,13 @@ BlazeComponent.extendComponent({
|
||||
const currentBoardId = Tracker.nonreactive(() => {
|
||||
return Session.get('currentBoard');
|
||||
});
|
||||
Cards.find({ boardId: currentBoardId }).fetch();
|
||||
Tracker.afterFlush(() => {
|
||||
$cards.find(itemsSelector).droppable({
|
||||
hoverClass: 'draggable-hover-card',
|
||||
accept: '.js-member,.js-label',
|
||||
drop(event, ui) {
|
||||
const cardId = Blaze.getData(this)._id;
|
||||
const card = Cards.findOne(cardId);
|
||||
const card = ReactiveCache.getCard(cardId);
|
||||
|
||||
if (ui.draggable.hasClass('js-member')) {
|
||||
const memberId = Blaze.getData(ui.draggable.get(0)).userId;
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
template(name="listBody")
|
||||
.list-body
|
||||
.minicards.clearfix.js-minicards(class="{{#if reachedWipLimit}}js-list-full{{/if}}")
|
||||
if cards.count
|
||||
if cards.length
|
||||
+inlinedForm(autoclose=false position="top")
|
||||
+addCardForm(listId=_id position="top")
|
||||
ul.sidebar-list
|
||||
@@ -95,7 +95,7 @@ template(name="linkCardPopup")
|
||||
label {{_ 'cards'}}:
|
||||
select.js-select-cards
|
||||
each cards
|
||||
option(value="{{getId}}") {{getTitle}}
|
||||
option(value="{{getRealId}}") {{getTitle}}
|
||||
|
||||
.edit-controls.clearfix
|
||||
input.primary.confirm.js-done(type="button" value="{{_ 'link'}}")
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import { Spinner } from '/client/lib/spinner';
|
||||
|
||||
@@ -15,10 +16,11 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
customFieldsSum() {
|
||||
return CustomFields.find({
|
||||
const ret = ReactiveCache.getCustomFields({
|
||||
boardIds: { $in: [Session.get('currentBoard')] },
|
||||
showSumAtTopOfList: true,
|
||||
});
|
||||
return ret;
|
||||
},
|
||||
|
||||
openForm(options) {
|
||||
@@ -64,7 +66,7 @@ BlazeComponent.extendComponent({
|
||||
swimlaneId = this.parentComponent()
|
||||
.parentComponent()
|
||||
.data()._id; // Always swimlanes view
|
||||
const swimlane = Swimlanes.findOne(swimlaneId);
|
||||
const swimlane = ReactiveCache.getSwimlane(swimlaneId);
|
||||
// If this is the card templates swimlane, insert a card template
|
||||
if (swimlane.isCardTemplatesSwimlane()) cardType = 'template-card';
|
||||
// If this is the board templates swimlane, insert a board template and a linked card
|
||||
@@ -112,7 +114,7 @@ BlazeComponent.extendComponent({
|
||||
// to appear
|
||||
const cardCount = this.data()
|
||||
.cards(this.idOrNull(swimlaneId))
|
||||
.count();
|
||||
.length;
|
||||
if (this.cardlimit.get() < cardCount) {
|
||||
this.cardlimit.set(this.cardlimit.get() + InfiniteScrollIter);
|
||||
}
|
||||
@@ -200,25 +202,23 @@ BlazeComponent.extendComponent({
|
||||
archived: false,
|
||||
};
|
||||
if (swimlaneId) selector.swimlaneId = swimlaneId;
|
||||
return Cards.find(Filter.mongoSelector(selector), {
|
||||
const ret = ReactiveCache.getCards(Filter.mongoSelector(selector), {
|
||||
// sort: ['sort'],
|
||||
sort: sortBy,
|
||||
limit,
|
||||
});
|
||||
}, true);
|
||||
return ret;
|
||||
},
|
||||
|
||||
showSpinner(swimlaneId) {
|
||||
const list = Template.currentData();
|
||||
return list.cards(swimlaneId).count() > this.cardlimit.get();
|
||||
return list.cards(swimlaneId).length > this.cardlimit.get();
|
||||
},
|
||||
|
||||
canSeeAddCard() {
|
||||
return (
|
||||
!this.reachedWipLimit() &&
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
Utils.canModifyCard()
|
||||
);
|
||||
},
|
||||
|
||||
@@ -227,7 +227,7 @@ BlazeComponent.extendComponent({
|
||||
return (
|
||||
!list.getWipLimit('soft') &&
|
||||
list.getWipLimit('enabled') &&
|
||||
list.getWipLimit('value') <= list.cards().count()
|
||||
list.getWipLimit('value') <= list.cards().length
|
||||
);
|
||||
},
|
||||
|
||||
@@ -269,9 +269,8 @@ BlazeComponent.extendComponent({
|
||||
const currentBoardId = Session.get('currentBoard');
|
||||
arr = [];
|
||||
_.forEach(
|
||||
Boards.findOne(currentBoardId)
|
||||
.customFields()
|
||||
.fetch(),
|
||||
ReactiveCache.getBoard(currentBoardId)
|
||||
.customFields(),
|
||||
function (field) {
|
||||
if (field.automaticallyOnCard || field.alwaysOnCard)
|
||||
arr.push({ _id: field._id, value: null });
|
||||
@@ -288,8 +287,8 @@ BlazeComponent.extendComponent({
|
||||
|
||||
getLabels() {
|
||||
const currentBoardId = Session.get('currentBoard');
|
||||
if (Boards.findOne(currentBoardId).labels) {
|
||||
return Boards.findOne(currentBoardId).labels.filter(label => {
|
||||
if (ReactiveCache.getBoard(currentBoardId).labels) {
|
||||
return ReactiveCache.getBoard(currentBoardId).labels.filter(label => {
|
||||
return this.labels.get().indexOf(label._id) > -1;
|
||||
});
|
||||
}
|
||||
@@ -349,10 +348,10 @@ BlazeComponent.extendComponent({
|
||||
{
|
||||
match: /\B@([\w.-]*)$/,
|
||||
search(term, callback) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
callback(
|
||||
$.map(currentBoard.activeMembers(), member => {
|
||||
const user = Users.findOne(member.userId);
|
||||
const user = ReactiveCache.getUser(member.userId);
|
||||
return user.username.indexOf(term) === 0 ? user : null;
|
||||
}),
|
||||
);
|
||||
@@ -374,7 +373,7 @@ BlazeComponent.extendComponent({
|
||||
{
|
||||
match: /\B#(\w*)$/,
|
||||
search(term, callback) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
callback(
|
||||
$.map(currentBoard.labels, label => {
|
||||
if (label.name == undefined) {
|
||||
@@ -430,10 +429,10 @@ BlazeComponent.extendComponent({
|
||||
this.boardId = Session.get('currentBoard');
|
||||
// In order to get current board info
|
||||
subManager.subscribe('board', this.boardId, false);
|
||||
this.board = Boards.findOne(this.boardId);
|
||||
this.board = ReactiveCache.getBoard(this.boardId);
|
||||
// List where to insert card
|
||||
const list = $(Popup._getTopStack().openerElement).closest('.js-list');
|
||||
this.listId = Blaze.getData(list[0])._id;
|
||||
this.list = $(Popup._getTopStack().openerElement).closest('.js-list');
|
||||
this.listId = Blaze.getData(this.list[0])._id;
|
||||
// Swimlane where to insert card
|
||||
const swimlane = $(Popup._getTopStack().openerElement).closest(
|
||||
'.js-swimlane',
|
||||
@@ -442,11 +441,11 @@ BlazeComponent.extendComponent({
|
||||
if (Utils.boardView() === 'board-view-swimlanes')
|
||||
this.swimlaneId = Blaze.getData(swimlane[0])._id;
|
||||
else if (Utils.boardView() === 'board-view-lists' || !Utils.boardView)
|
||||
this.swimlaneId = Swimlanes.findOne({ boardId: this.boardId })._id;
|
||||
this.swimlaneId = ReactiveCache.getSwimlane({ boardId: this.boardId })._id;
|
||||
},
|
||||
|
||||
boards() {
|
||||
const boards = Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
@@ -457,16 +456,22 @@ BlazeComponent.extendComponent({
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return boards;
|
||||
return ret;
|
||||
},
|
||||
|
||||
swimlanes() {
|
||||
if (!this.selectedBoardId.get()) {
|
||||
return [];
|
||||
}
|
||||
const swimlanes = Swimlanes.find({ boardId: this.selectedBoardId.get() });
|
||||
if (swimlanes.count())
|
||||
this.selectedSwimlaneId.set(swimlanes.fetch()[0]._id);
|
||||
const swimlanes = ReactiveCache.getSwimlanes(
|
||||
{
|
||||
boardId: this.selectedBoardId.get()
|
||||
},
|
||||
{
|
||||
sort: { sort: 1 },
|
||||
});
|
||||
if (swimlanes.length)
|
||||
this.selectedSwimlaneId.set(swimlanes[0]._id);
|
||||
return swimlanes;
|
||||
},
|
||||
|
||||
@@ -474,8 +479,14 @@ BlazeComponent.extendComponent({
|
||||
if (!this.selectedBoardId.get()) {
|
||||
return [];
|
||||
}
|
||||
const lists = Lists.find({ boardId: this.selectedBoardId.get() });
|
||||
if (lists.count()) this.selectedListId.set(lists.fetch()[0]._id);
|
||||
const lists = ReactiveCache.getLists(
|
||||
{
|
||||
boardId: this.selectedBoardId.get()
|
||||
},
|
||||
{
|
||||
sort: { sort: 1 },
|
||||
});
|
||||
if (lists.length) this.selectedListId.set(lists[0]._id);
|
||||
return lists;
|
||||
},
|
||||
|
||||
@@ -483,10 +494,9 @@ BlazeComponent.extendComponent({
|
||||
if (!this.board) {
|
||||
return [];
|
||||
}
|
||||
const ownCardsIds = this.board.cards().map(card => {
|
||||
return card.linkedId || card._id;
|
||||
});
|
||||
return Cards.find({
|
||||
const ownCardsIds = this.board.cards().map(card => card.getRealId());
|
||||
const ret = ReactiveCache.getCards(
|
||||
{
|
||||
boardId: this.selectedBoardId.get(),
|
||||
swimlaneId: this.selectedSwimlaneId.get(),
|
||||
listId: this.selectedListId.get(),
|
||||
@@ -494,7 +504,24 @@ BlazeComponent.extendComponent({
|
||||
linkedId: { $nin: ownCardsIds },
|
||||
_id: { $nin: ownCardsIds },
|
||||
type: { $nin: ['template-card'] },
|
||||
},
|
||||
{
|
||||
sort: { sort: 1 },
|
||||
});
|
||||
return ret;
|
||||
},
|
||||
|
||||
getSortIndex() {
|
||||
const position = this.currentData().position;
|
||||
let ret;
|
||||
if (position === 'top') {
|
||||
const firstCardDom = this.list.find('.js-minicard:first')[0];
|
||||
ret = Utils.calculateIndex(null, firstCardDom).base;
|
||||
} else if (position === 'bottom') {
|
||||
const lastCardDom = this.list.find('.js-minicard:last')[0];
|
||||
ret = Utils.calculateIndex(lastCardDom, null).base;
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
|
||||
events() {
|
||||
@@ -519,16 +546,17 @@ BlazeComponent.extendComponent({
|
||||
Popup.back();
|
||||
return;
|
||||
}
|
||||
const nextCardNumber = this.board.getNextCardNumber();
|
||||
const sortIndex = this.getSortIndex();
|
||||
const _id = Cards.insert({
|
||||
title: $('.js-select-cards option:selected').text(), //dummy
|
||||
listId: this.listId,
|
||||
swimlaneId: this.swimlaneId,
|
||||
boardId: this.boardId,
|
||||
sort: Lists.findOne(this.listId)
|
||||
.cards()
|
||||
.count(),
|
||||
sort: sortIndex,
|
||||
type: 'cardType-linkedCard',
|
||||
linkedId,
|
||||
cardNumber: nextCardNumber,
|
||||
});
|
||||
Filter.addException(_id);
|
||||
Popup.back();
|
||||
@@ -540,21 +568,22 @@ BlazeComponent.extendComponent({
|
||||
const impBoardId = $('.js-select-boards option:selected').val();
|
||||
if (
|
||||
!impBoardId ||
|
||||
Cards.findOne({ linkedId: impBoardId, archived: false })
|
||||
ReactiveCache.getCard({ linkedId: impBoardId, archived: false })
|
||||
) {
|
||||
Popup.back();
|
||||
return;
|
||||
}
|
||||
const nextCardNumber = this.board.getNextCardNumber();
|
||||
const sortIndex = this.getSortIndex();
|
||||
const _id = Cards.insert({
|
||||
title: $('.js-select-boards option:selected').text(), //dummy
|
||||
listId: this.listId,
|
||||
swimlaneId: this.swimlaneId,
|
||||
boardId: this.boardId,
|
||||
sort: Lists.findOne(this.listId)
|
||||
.cards()
|
||||
.count(),
|
||||
sort: sortIndex,
|
||||
type: 'cardType-linkedBoard',
|
||||
linkedId: impBoardId,
|
||||
cardNumber: nextCardNumber,
|
||||
});
|
||||
Filter.addException(_id);
|
||||
Popup.back();
|
||||
@@ -587,36 +616,27 @@ BlazeComponent.extendComponent({
|
||||
this.isListTemplateSearch ||
|
||||
this.isSwimlaneTemplateSearch ||
|
||||
this.isBoardTemplateSearch;
|
||||
let board = {};
|
||||
|
||||
this.board = {};
|
||||
if (this.isTemplateSearch) {
|
||||
//board = Boards.findOne((Meteor.user().profile || {}).templatesBoardId);
|
||||
board._id = (Meteor.user().profile || {}).templatesBoardId;
|
||||
const boardId = (ReactiveCache.getCurrentUser().profile || {}).templatesBoardId;
|
||||
if (boardId) {
|
||||
this.board = ReactiveCache.getBoard(boardId);
|
||||
}
|
||||
} else {
|
||||
// Prefetch first non-current board id
|
||||
board = Boards.find({
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
_id: {
|
||||
$nin: [
|
||||
Session.get('currentBoard'),
|
||||
(Meteor.user().profile || {}).templatesBoardId,
|
||||
],
|
||||
},
|
||||
});
|
||||
this.board = Utils.getCurrentBoard();
|
||||
}
|
||||
if (!board) {
|
||||
if (!this.board) {
|
||||
Popup.back();
|
||||
return;
|
||||
}
|
||||
const boardId = board._id;
|
||||
this.boardId = this.board._id;
|
||||
// Subscribe to this board
|
||||
subManager.subscribe('board', boardId, false);
|
||||
this.selectedBoardId = new ReactiveVar(boardId);
|
||||
subManager.subscribe('board', this.boardId, false);
|
||||
this.selectedBoardId = new ReactiveVar(this.boardId);
|
||||
this.list = $(Popup._getTopStack().openerElement).closest('.js-list');
|
||||
|
||||
if (!this.isBoardTemplateSearch) {
|
||||
this.boardId = Session.get('currentBoard');
|
||||
// In order to get current board info
|
||||
subManager.subscribe('board', this.boardId, false);
|
||||
this.swimlaneId = '';
|
||||
// Swimlane where to insert card
|
||||
const swimlane = $(Popup._getTopStack().openerElement).parents(
|
||||
@@ -624,16 +644,15 @@ BlazeComponent.extendComponent({
|
||||
);
|
||||
if (Utils.boardView() === 'board-view-swimlanes')
|
||||
this.swimlaneId = Blaze.getData(swimlane[0])._id;
|
||||
else this.swimlaneId = Swimlanes.findOne({ boardId: this.boardId })._id;
|
||||
else this.swimlaneId = ReactiveCache.getSwimlane({ boardId: this.boardId })._id;
|
||||
// List where to insert card
|
||||
const list = $(Popup._getTopStack().openerElement).closest('.js-list');
|
||||
this.listId = Blaze.getData(list[0])._id;
|
||||
this.listId = Blaze.getData(this.list[0])._id;
|
||||
}
|
||||
this.term = new ReactiveVar('');
|
||||
},
|
||||
|
||||
boards() {
|
||||
const boards = Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
@@ -644,14 +663,14 @@ BlazeComponent.extendComponent({
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return boards;
|
||||
return ret;
|
||||
},
|
||||
|
||||
results() {
|
||||
if (!this.selectedBoardId) {
|
||||
return [];
|
||||
}
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
|
||||
if (!this.isTemplateSearch || this.isCardTemplateSearch) {
|
||||
return board.searchCards(this.term.get(), false);
|
||||
} else if (this.isListTemplateSearch) {
|
||||
@@ -669,6 +688,19 @@ BlazeComponent.extendComponent({
|
||||
}
|
||||
},
|
||||
|
||||
getSortIndex() {
|
||||
const position = this.data().position;
|
||||
let ret;
|
||||
if (position === 'top') {
|
||||
const firstCardDom = this.list.find('.js-minicard:first')[0];
|
||||
ret = Utils.calculateIndex(null, firstCardDom).base;
|
||||
} else if (position === 'bottom') {
|
||||
const lastCardDom = this.list.find('.js-minicard:last')[0];
|
||||
ret = Utils.calculateIndex(lastCardDom, null).base;
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
@@ -692,9 +724,8 @@ BlazeComponent.extendComponent({
|
||||
if (!this.isTemplateSearch || this.isCardTemplateSearch) {
|
||||
// Card insertion
|
||||
// 1. Common
|
||||
element.sort = Lists.findOne(this.listId)
|
||||
.cards()
|
||||
.count();
|
||||
element.cardNumber = this.board.getNextCardNumber();
|
||||
element.sort = this.getSortIndex();
|
||||
// 1.A From template
|
||||
if (this.isTemplateSearch) {
|
||||
element.type = 'cardType-card';
|
||||
@@ -707,15 +738,15 @@ BlazeComponent.extendComponent({
|
||||
Filter.addException(_id);
|
||||
// List insertion
|
||||
} else if (this.isListTemplateSearch) {
|
||||
element.sort = Swimlanes.findOne(this.swimlaneId)
|
||||
element.sort = ReactiveCache.getSwimlane(this.swimlaneId)
|
||||
.lists()
|
||||
.count();
|
||||
.length;
|
||||
element.type = 'list';
|
||||
_id = element.copy(this.boardId, this.swimlaneId);
|
||||
} else if (this.isSwimlaneTemplateSearch) {
|
||||
element.sort = Boards.findOne(this.boardId)
|
||||
element.sort = ReactiveCache.getBoard(this.boardId)
|
||||
.swimlanes()
|
||||
.count();
|
||||
.length;
|
||||
element.type = 'swimlane';
|
||||
_id = element.copy(this.boardId);
|
||||
} else if (this.isBoardTemplateSearch) {
|
||||
@@ -723,7 +754,7 @@ BlazeComponent.extendComponent({
|
||||
'copyBoard',
|
||||
element.linkedId,
|
||||
{
|
||||
sort: Boards.find({ archived: false }).count(),
|
||||
sort: ReactiveCache.getBoards({ archived: false }).length,
|
||||
type: 'board',
|
||||
title: element.title,
|
||||
},
|
||||
@@ -757,7 +788,7 @@ BlazeComponent.extendComponent({
|
||||
Meteor.settings.public.sandstorm;
|
||||
|
||||
if (isSandstorm) {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
if (user) {
|
||||
if (Utils.boardView() === 'board-view-swimlanes') {
|
||||
this.swimlaneId = this.parentComponent()
|
||||
|
||||
@@ -15,11 +15,11 @@ template(name="listHeader")
|
||||
= title
|
||||
if wipLimit.enabled
|
||||
| (
|
||||
span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.count}}
|
||||
span(class="{{#if exceededWipLimit}}highlight{{/if}}") {{cards.length}}
|
||||
|/#{wipLimit.value})
|
||||
|
||||
if showCardsCountForList cards.count
|
||||
span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.count}}
|
||||
if showCardsCountForList cards.length
|
||||
span.cardCount {{cardsCount}} {{cardsCountForListIsOne cards.length}}
|
||||
|
||||
if isMiniScreen
|
||||
if currentList
|
||||
@@ -79,7 +79,7 @@ template(name="listActionPopup")
|
||||
i.fa.fa-paint-brush
|
||||
| {{_ 'set-color-list'}}
|
||||
ul.pop-over-list
|
||||
if cards.count
|
||||
if cards.length
|
||||
li
|
||||
a.js-select-cards
|
||||
i.fa.fa-check-square
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
let listsColors;
|
||||
@@ -12,12 +13,12 @@ BlazeComponent.extendComponent({
|
||||
(!list.getWipLimit('enabled') ||
|
||||
list.getWipLimit('soft') ||
|
||||
!this.reachedWipLimit()) &&
|
||||
!Meteor.user().isWorker()
|
||||
!ReactiveCache.getCurrentUser().isWorker()
|
||||
);
|
||||
},
|
||||
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
starred(check = undefined) {
|
||||
const list = Template.currentData();
|
||||
@@ -47,9 +48,9 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
limitToShowCardsCount() {
|
||||
const currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return Meteor.user().getLimitToShowCardsCount();
|
||||
return currentUser.getLimitToShowCardsCount();
|
||||
} else {
|
||||
return false;
|
||||
}
|
||||
@@ -63,14 +64,15 @@ BlazeComponent.extendComponent({
|
||||
.parentComponent()
|
||||
.data()._id;
|
||||
|
||||
return list.cards(swimlaneId).count();
|
||||
const ret = list.cards(swimlaneId).length;
|
||||
return ret;
|
||||
},
|
||||
|
||||
reachedWipLimit() {
|
||||
const list = Template.currentData();
|
||||
return (
|
||||
list.getWipLimit('enabled') &&
|
||||
list.getWipLimit('value') <= list.cards().count()
|
||||
list.getWipLimit('value') <= list.cards().length
|
||||
);
|
||||
},
|
||||
|
||||
@@ -78,7 +80,7 @@ BlazeComponent.extendComponent({
|
||||
const list = Template.currentData();
|
||||
return (
|
||||
list.getWipLimit('enabled') &&
|
||||
list.getWipLimit('value') < list.cards().count()
|
||||
list.getWipLimit('value') < list.cards().length
|
||||
);
|
||||
},
|
||||
|
||||
@@ -123,13 +125,13 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.listHeader.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
}
|
||||
});
|
||||
|
||||
Template.listActionPopup.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
|
||||
isWipLimitEnabled() {
|
||||
@@ -183,7 +185,7 @@ BlazeComponent.extendComponent({
|
||||
10,
|
||||
);
|
||||
|
||||
if (limit < list.cards().count() && !list.getWipLimit('soft')) {
|
||||
if (limit < list.cards().length && !list.getWipLimit('soft')) {
|
||||
Template.instance()
|
||||
.$('.wip-limit-error')
|
||||
.click();
|
||||
@@ -198,9 +200,9 @@ BlazeComponent.extendComponent({
|
||||
|
||||
if (
|
||||
list.getWipLimit('soft') &&
|
||||
list.getWipLimit('value') < list.cards().count()
|
||||
list.getWipLimit('value') < list.cards().length
|
||||
) {
|
||||
list.setWipLimit(list.cards().count());
|
||||
list.setWipLimit(list.cards().length);
|
||||
}
|
||||
Meteor.call('enableSoftLimit', Template.currentData()._id);
|
||||
},
|
||||
@@ -210,9 +212,9 @@ BlazeComponent.extendComponent({
|
||||
// Prevent user from using previously stored wipLimit.value if it is less than the current number of cards in the list
|
||||
if (
|
||||
!list.getWipLimit('enabled') &&
|
||||
list.getWipLimit('value') < list.cards().count()
|
||||
list.getWipLimit('value') < list.cards().length
|
||||
) {
|
||||
list.setWipLimit(list.cards().count());
|
||||
list.setWipLimit(list.cards().length);
|
||||
}
|
||||
Meteor.call('enableWipLimit', list._id);
|
||||
},
|
||||
@@ -244,17 +246,16 @@ BlazeComponent.extendComponent({
|
||||
Template.listMorePopup.events({
|
||||
'click .js-delete': Popup.afterConfirm('listDelete', function() {
|
||||
Popup.back();
|
||||
// TODO how can we avoid the fetch call?
|
||||
const allCards = this.allCards().fetch();
|
||||
const allCards = this.allCards();
|
||||
const allCardIds = _.pluck(allCards, '_id');
|
||||
// it's okay if the linked cards are on the same list
|
||||
if (
|
||||
Cards.find({
|
||||
ReactiveCache.getCards({
|
||||
$and: [
|
||||
{ listId: { $ne: this._id } },
|
||||
{ linkedId: { $in: allCardIds } },
|
||||
],
|
||||
}).count() === 0
|
||||
}).length === 0
|
||||
) {
|
||||
allCardIds.map(_id => Cards.remove(_id));
|
||||
Lists.remove(this._id);
|
||||
@@ -279,7 +280,7 @@ Template.listMorePopup.events({
|
||||
|
||||
Template.listHeader.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { CardSearchPagedComponent } from '../../lib/cardSearch';
|
||||
import {
|
||||
OPERATOR_HAS,
|
||||
@@ -66,7 +67,7 @@ class DueCardsComponent extends CardSearchPagedComponent {
|
||||
});
|
||||
|
||||
if (Utils.dueCardsView() !== 'all') {
|
||||
queryParams.addPredicate(OPERATOR_USER, Meteor.user().username);
|
||||
queryParams.addPredicate(OPERATOR_USER, ReactiveCache.getCurrentUser().username);
|
||||
}
|
||||
|
||||
this.runGlobalSearch(queryParams);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
const specialHandles = [
|
||||
{userId: 'board_members', username: 'board_members'},
|
||||
{userId: 'card_members', username: 'card_members'}
|
||||
@@ -13,13 +15,13 @@ BlazeComponent.extendComponent({
|
||||
{
|
||||
match: /\B@([\w.-]*)$/,
|
||||
search(term, callback) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
callback(
|
||||
_.union(
|
||||
currentBoard
|
||||
.activeMembers()
|
||||
.map(member => {
|
||||
const user = Users.findOne(member.userId);
|
||||
const user = ReactiveCache.getUser(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;
|
||||
@@ -328,13 +330,13 @@ Blaze.Template.registerHelper(
|
||||
new Template('mentions', function() {
|
||||
const view = this;
|
||||
let content = Blaze.toHTML(view.templateContentBlock);
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
if (!currentBoard)
|
||||
return HTML.Raw(
|
||||
DOMPurify.sanitize(content, { ALLOW_UNKNOWN_PROTOCOLS: true }),
|
||||
);
|
||||
const knowedUsers = _.union(currentBoard.members.map(member => {
|
||||
const u = Users.findOne(member.userId);
|
||||
const u = ReactiveCache.getUser(member.userId);
|
||||
if (u) {
|
||||
member.username = u.username;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
Meteor.subscribe('user-admin');
|
||||
Meteor.subscribe('boards');
|
||||
Meteor.subscribe('setting');
|
||||
@@ -9,7 +11,7 @@ Template.header.onCreated(function(){
|
||||
|
||||
Meteor.subscribe('setting', {
|
||||
onReady() {
|
||||
templateInstance.currentSetting.set(Settings.findOne());
|
||||
templateInstance.currentSetting.set(ReactiveCache.getCurrentSetting());
|
||||
let currSetting = templateInstance.currentSetting.curValue;
|
||||
if(currSetting && currSetting !== undefined && currSetting.customLoginLogoImageUrl !== undefined && document.getElementById("headerIsSettingDatabaseCallDone") != null)
|
||||
document.getElementById("headerIsSettingDatabaseCallDone").style.display = 'none';
|
||||
@@ -24,10 +26,6 @@ Template.header.helpers({
|
||||
return !Session.get('currentBoard');
|
||||
},
|
||||
|
||||
currentSetting() {
|
||||
return Settings.findOne();
|
||||
},
|
||||
|
||||
hideLogo() {
|
||||
return Utils.isMiniScreen() && Session.get('currentBoard');
|
||||
},
|
||||
|
||||
@@ -6,12 +6,12 @@ head
|
||||
where the application is deployed with a path prefix, but it seems to be
|
||||
difficult to do that cleanly with Blaze -- at least without adding extra
|
||||
packages.
|
||||
link(rel="shortcut icon" type="image/x-icon" href="favicon.ico")
|
||||
link(rel="apple-touch-icon" sizes="180x180" href="apple-touch-icon.png")
|
||||
link(rel="icon" type="image/png" sizes="32x32" href="favicon-32x32.png")
|
||||
link(rel="icon" type="image/png" sizes="16x16" href="favicon-16x16.png")
|
||||
link(rel="shortcut icon" type="image/x-icon" href="/favicon.ico")
|
||||
link(rel="apple-touch-icon" sizes="180x180" href="/apple-touch-icon.png")
|
||||
link(rel="icon" type="image/png" sizes="32x32" href="/favicon-32x32.png")
|
||||
link(rel="icon" type="image/png" sizes="16x16" href="/favicon-16x16.png")
|
||||
link(rel="manifest" crossOrigin="use-credentials" href="/site.webmanifest")
|
||||
link(rel="mask-icon" href="safari-pinned-tab.svg" color="#5bbad5")
|
||||
link(rel="mask-icon" href="/safari-pinned-tab.svg" color="#5bbad5")
|
||||
meta(name="apple-mobile-web-app-title" content="Wekan")
|
||||
meta(name="application-name" content="Wekan")
|
||||
meta(name="msapplication-TileColor" content="#00aba9")
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
BlazeLayout.setRoot('body');
|
||||
@@ -28,7 +29,7 @@ Template.userFormsLayout.onCreated(function () {
|
||||
|
||||
Meteor.subscribe('setting', {
|
||||
onReady() {
|
||||
templateInstance.currentSetting.set(Settings.findOne());
|
||||
templateInstance.currentSetting.set(ReactiveCache.getCurrentSetting());
|
||||
let currSetting = templateInstance.currentSetting.curValue;
|
||||
let oidcBtnElt = $("#at-oidc");
|
||||
if(currSetting && currSetting !== undefined && currSetting.oidcBtnText !== undefined && oidcBtnElt != null && oidcBtnElt != undefined){
|
||||
@@ -50,7 +51,7 @@ Template.userFormsLayout.onCreated(function () {
|
||||
}
|
||||
});
|
||||
|
||||
if (!Meteor.user()?.profile) {
|
||||
if (!ReactiveCache.getCurrentUser()?.profile) {
|
||||
Meteor.call('isOidcRedirectionEnabled', (_, result) => {
|
||||
if (result) {
|
||||
AccountsTemplates.options.socialLoginStyle = 'redirect';
|
||||
@@ -85,10 +86,6 @@ Template.userFormsLayout.onRendered(() => {
|
||||
});
|
||||
|
||||
Template.userFormsLayout.helpers({
|
||||
currentSetting() {
|
||||
return Template.instance().currentSetting.get();
|
||||
},
|
||||
|
||||
// isSettingDatabaseCallDone(){
|
||||
// return isSettingDatabaseFctCallDone;
|
||||
// },
|
||||
@@ -164,7 +161,7 @@ Template.userFormsLayout.events({
|
||||
},
|
||||
'DOMSubtreeModified #at-oidc'(event) {
|
||||
if (alreadyCheck <= 2) {
|
||||
let currSetting = Settings.findOne();
|
||||
let currSetting = ReactiveCache.getCurrentSetting();
|
||||
let oidcBtnElt = $("#at-oidc");
|
||||
if (currSetting && currSetting !== undefined && currSetting.oidcBtnText !== undefined && oidcBtnElt != null && oidcBtnElt != undefined) {
|
||||
let htmlvalue = "<i class='fa fa-oidc'></i>" + currSetting.oidcBtnText;
|
||||
@@ -185,7 +182,7 @@ Template.userFormsLayout.events({
|
||||
'DOMSubtreeModified .at-form'(event) {
|
||||
if (alreadyCheck <= 2 && !isCheckDone) {
|
||||
if (document.getElementById("at-oidc") != null) {
|
||||
let currSetting = Settings.findOne();
|
||||
let currSetting = ReactiveCache.getCurrentSetting();
|
||||
let oidcBtnElt = $("#at-oidc");
|
||||
if (currSetting && currSetting !== undefined && currSetting.oidcBtnText !== undefined && oidcBtnElt != null && oidcBtnElt != undefined) {
|
||||
let htmlvalue = "<i class='fa fa-oidc'></i>" + currSetting.oidcBtnText;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
Template.notification.events({
|
||||
'click .read-status .materialCheckBox'() {
|
||||
const update = {};
|
||||
@@ -7,22 +9,22 @@ Template.notification.events({
|
||||
Users.update(Meteor.userId(), { $set: update });
|
||||
},
|
||||
'click .remove a'() {
|
||||
Meteor.user().removeNotification(this.activityData._id);
|
||||
ReactiveCache.getCurrentUser().removeNotification(this.activityData._id);
|
||||
},
|
||||
});
|
||||
|
||||
Template.notification.helpers({
|
||||
mode: 'board',
|
||||
isOfActivityType(activityId, type) {
|
||||
const activity = Activities.findOne(activityId);
|
||||
const activity = ReactiveCache.getActivity(activityId);
|
||||
return activity && activity.activityType === type;
|
||||
},
|
||||
activityType(activityId) {
|
||||
const activity = Activities.findOne(activityId);
|
||||
const activity = ReactiveCache.getActivity(activityId);
|
||||
return activity ? activity.activityType : '';
|
||||
},
|
||||
activityUser(activityId) {
|
||||
const activity = Activities.findOne(activityId);
|
||||
const activity = ReactiveCache.getActivity(activityId);
|
||||
return activity && activity.userId;
|
||||
},
|
||||
});
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
// this hides the notifications drawer if anyone clicks off of the panel
|
||||
Template.body.events({
|
||||
click(event) {
|
||||
@@ -12,7 +14,7 @@ Template.body.events({
|
||||
|
||||
Template.notifications.helpers({
|
||||
unreadNotifications() {
|
||||
const notifications = Users.findOne(Meteor.userId()).notifications();
|
||||
const notifications = ReactiveCache.getCurrentUser().notifications();
|
||||
const unreadNotifications = _.filter(notifications, v => !v.read);
|
||||
return unreadNotifications.length;
|
||||
},
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { toggleNotificationsDrawer } from './notifications.js';
|
||||
|
||||
Template.notificationsDrawer.onCreated(function() {
|
||||
@@ -14,11 +15,11 @@ Template.notificationsDrawer.onCreated(function() {
|
||||
|
||||
Template.notificationsDrawer.helpers({
|
||||
transformedProfile() {
|
||||
return Users.findOne(Meteor.userId());
|
||||
return ReactiveCache.getCurrentUser();
|
||||
},
|
||||
readNotifications() {
|
||||
const readNotifications = _.filter(
|
||||
Meteor.user().profile.notifications,
|
||||
ReactiveCache.getCurrentUser().profile.notifications,
|
||||
v => !!v.read,
|
||||
);
|
||||
return readNotifications.length;
|
||||
@@ -27,7 +28,7 @@ Template.notificationsDrawer.helpers({
|
||||
|
||||
Template.notificationsDrawer.events({
|
||||
'click .all-read'() {
|
||||
const notifications = Meteor.user().profile.notifications;
|
||||
const notifications = ReactiveCache.getCurrentUser().profile.notifications;
|
||||
for (const index in notifications) {
|
||||
if (notifications.hasOwnProperty(index) && !notifications[index].read) {
|
||||
const update = {};
|
||||
@@ -43,7 +44,7 @@ Template.notificationsDrawer.events({
|
||||
Session.set('showReadNotifications', !Session.get('showReadNotifications'));
|
||||
},
|
||||
'click .remove-read'() {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
for (const notification of user.profile.notifications) {
|
||||
if (notification.read) {
|
||||
user.removeNotification(notification.activity);
|
||||
|
||||
@@ -1,20 +1,22 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {},
|
||||
|
||||
boards() {
|
||||
const boards = Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
_id: {
|
||||
$ne: Meteor.user().getTemplatesBoardId(),
|
||||
$ne: ReactiveCache.getCurrentUser().getTemplatesBoardId(),
|
||||
},
|
||||
},
|
||||
{
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return boards;
|
||||
return ret;
|
||||
},
|
||||
|
||||
events() {
|
||||
|
||||
@@ -18,7 +18,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
labels() {
|
||||
const labels = Boards.findOne(Session.get('currentBoard')).labels;
|
||||
const labels = Utils.getCurrentBoard().labels;
|
||||
for (let i = 0; i < labels.length; i++) {
|
||||
if (labels[i].name === '' || labels[i].name === undefined) {
|
||||
labels[i].name = labels[i].color.toUpperCase();
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.subscribe('allRules');
|
||||
@@ -7,24 +9,16 @@ BlazeComponent.extendComponent({
|
||||
|
||||
trigger() {
|
||||
const ruleId = this.data().ruleId;
|
||||
const rule = Rules.findOne({
|
||||
_id: ruleId.get(),
|
||||
});
|
||||
const trigger = Triggers.findOne({
|
||||
_id: rule.triggerId,
|
||||
});
|
||||
const rule = ReactiveCache.getRule(ruleId.get());
|
||||
const trigger = ReactiveCache.getTrigger(rule.triggerId);
|
||||
const desc = trigger.description();
|
||||
const upperdesc = desc.charAt(0).toUpperCase() + desc.substr(1);
|
||||
return upperdesc;
|
||||
},
|
||||
action() {
|
||||
const ruleId = this.data().ruleId;
|
||||
const rule = Rules.findOne({
|
||||
_id: ruleId.get(),
|
||||
});
|
||||
const action = Actions.findOne({
|
||||
_id: rule.actionId,
|
||||
});
|
||||
const rule = ReactiveCache.getRule(ruleId.get());
|
||||
const action = ReactiveCache.getAction(rule.actionId);
|
||||
const desc = action.description();
|
||||
const upperdesc = desc.charAt(0).toUpperCase() + desc.substr(1);
|
||||
return upperdesc;
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentActions = new ReactiveVar('board');
|
||||
@@ -33,7 +35,8 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
rules() {
|
||||
return Rules.find({});
|
||||
const ret = ReactiveCache.getRules({});
|
||||
return ret;
|
||||
},
|
||||
|
||||
name() {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.subscribe('allRules');
|
||||
@@ -5,9 +7,10 @@ BlazeComponent.extendComponent({
|
||||
|
||||
rules() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
return Rules.find({
|
||||
const ret = ReactiveCache.getRules({
|
||||
boardId,
|
||||
});
|
||||
return ret;
|
||||
},
|
||||
events() {
|
||||
return [{}];
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.rulesCurrentTab = new ReactiveVar('rulesList');
|
||||
@@ -55,7 +57,7 @@ BlazeComponent.extendComponent({
|
||||
let trigger = this.triggerVar.get();
|
||||
trigger.userId = '*';
|
||||
if (username !== undefined) {
|
||||
const userFound = Users.findOne({ username });
|
||||
const userFound = ReactiveCache.getUser({ username });
|
||||
if (userFound !== undefined) {
|
||||
trigger.userId = userFound._id;
|
||||
this.triggerVar.set(trigger);
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.showBoardTrigger = new ReactiveVar(true);
|
||||
@@ -31,7 +33,8 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
rules() {
|
||||
return Rules.find({});
|
||||
const ret = ReactiveCache.getRules({});
|
||||
return ret;
|
||||
},
|
||||
|
||||
name() {
|
||||
|
||||
@@ -5,7 +5,7 @@ BlazeComponent.extendComponent({
|
||||
this.subscribe('allRules');
|
||||
},
|
||||
labels() {
|
||||
const labels = Boards.findOne(Session.get('currentBoard')).labels;
|
||||
const labels = Utils.getCurrentBoard().labels;
|
||||
for (let i = 0; i < labels.length; i++) {
|
||||
if (labels[i].name === '' || labels[i].name === undefined) {
|
||||
labels[i].name = labels[i].color;
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import { AttachmentStorage } from '/models/attachments';
|
||||
import { CardSearchPagedComponent } from '/client/lib/cardSearch';
|
||||
@@ -115,12 +116,15 @@ class AdminReport extends BlazeComponent {
|
||||
}
|
||||
|
||||
fileSize(size) {
|
||||
const ret = filesize(size);
|
||||
let ret = "";
|
||||
if (_.isNumber(size)) {
|
||||
ret = filesize(size);
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
abbreviate(text) {
|
||||
if (text.length > 30) {
|
||||
if (text?.length > 30) {
|
||||
return `${text.substr(0, 29)}...`;
|
||||
}
|
||||
return text;
|
||||
@@ -137,7 +141,7 @@ class AdminReport extends BlazeComponent {
|
||||
results() {
|
||||
const rules = [];
|
||||
|
||||
Rules.find().forEach(rule => {
|
||||
ReactiveCache.getRules().forEach(rule => {
|
||||
rules.push({
|
||||
_id: rule._id,
|
||||
title: rule.title,
|
||||
@@ -158,17 +162,13 @@ class AdminReport extends BlazeComponent {
|
||||
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;
|
||||
const ret = (members || [])
|
||||
.map(_member => {
|
||||
const _ret = ReactiveCache.getUser(_member.userId)?.username || _member.userId;
|
||||
return _ret;
|
||||
})
|
||||
.join(", ");
|
||||
return ret;
|
||||
}
|
||||
}.register('boardsReport'));
|
||||
|
||||
@@ -176,13 +176,13 @@ class AdminReport extends BlazeComponent {
|
||||
collection = Cards;
|
||||
|
||||
userNames(userIds) {
|
||||
let text = '';
|
||||
userIds.forEach(userId => {
|
||||
const user = Users.findOne(userId);
|
||||
text += text ? ', ' : '';
|
||||
text += user.username;
|
||||
});
|
||||
return text;
|
||||
const ret = (userIds || [])
|
||||
.map(_userId => {
|
||||
const _ret = ReactiveCache.getUser(_userId)?.username;
|
||||
return _ret;
|
||||
})
|
||||
.join(", ");
|
||||
return ret
|
||||
}
|
||||
}.register('cardsReport'));
|
||||
|
||||
|
||||
@@ -58,6 +58,7 @@ template(name="moveBoardAttachments")
|
||||
th {{_ 'version-name'}}
|
||||
th {{_ 'size'}}
|
||||
th GridFsFileId
|
||||
th S3FileId
|
||||
th {{_ 'storage'}}
|
||||
th {{_ 'action'}}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import Attachments, { fileStoreStrategyFactory } from '/models/attachments';
|
||||
const filesize = require('filesize');
|
||||
|
||||
@@ -44,7 +45,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
getBoardsWithAttachments() {
|
||||
this.attachments = Attachments.find().get();
|
||||
this.attachments = ReactiveCache.getAttachments();
|
||||
this.attachmentsByBoardId = _.chain(this.attachments)
|
||||
.groupBy(fileObj => fileObj.meta.boardId)
|
||||
.value();
|
||||
@@ -61,14 +62,14 @@ BlazeComponent.extendComponent({
|
||||
return _version;
|
||||
});
|
||||
});
|
||||
const board = Boards.findOne(boardId);
|
||||
const board = ReactiveCache.getBoard(boardId);
|
||||
board.attachments = boardAttachments;
|
||||
return board;
|
||||
})
|
||||
return ret;
|
||||
},
|
||||
getBoardData(boardid) {
|
||||
const ret = Boards.findOne(boardId);
|
||||
const ret = ReactiveCache.getBoard(boardId);
|
||||
return ret;
|
||||
},
|
||||
events() {
|
||||
|
||||
@@ -41,7 +41,10 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
fileSize(size) {
|
||||
const ret = filesize(size);
|
||||
let ret = "";
|
||||
if (_.isNumber(size)) {
|
||||
ret = filesize(size);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
}).register('statistics');
|
||||
@@ -1,7 +1,9 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
Template.invitationCode.onRendered(function() {
|
||||
Meteor.subscribe('setting', {
|
||||
onReady() {
|
||||
const setting = Settings.findOne();
|
||||
const setting = ReactiveCache.getCurrentSetting();
|
||||
|
||||
if (!setting || !setting.disableRegistration) {
|
||||
$('#invitationcode').hide();
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
const orgsPerPage = 25;
|
||||
const teamsPerPage = 25;
|
||||
const usersPerPage = 25;
|
||||
@@ -143,27 +145,27 @@ BlazeComponent.extendComponent({
|
||||
this.loading.set(w);
|
||||
},
|
||||
orgList() {
|
||||
const orgs = Org.find(this.findOrgsOptions.get(), {
|
||||
const orgs = ReactiveCache.getOrgs(this.findOrgsOptions.get(), {
|
||||
sort: { orgDisplayName: 1 },
|
||||
fields: { _id: true },
|
||||
});
|
||||
this.numberOrgs.set(orgs.count(false));
|
||||
this.numberOrgs.set(orgs.length);
|
||||
return orgs;
|
||||
},
|
||||
teamList() {
|
||||
const teams = Team.find(this.findTeamsOptions.get(), {
|
||||
const teams = ReactiveCache.getTeams(this.findTeamsOptions.get(), {
|
||||
sort: { teamDisplayName: 1 },
|
||||
fields: { _id: true },
|
||||
});
|
||||
this.numberTeams.set(teams.count(false));
|
||||
this.numberTeams.set(teams.length);
|
||||
return teams;
|
||||
},
|
||||
peopleList() {
|
||||
const users = Users.find(this.findUsersOptions.get(), {
|
||||
const users = ReactiveCache.getUsers(this.findUsersOptions.get(), {
|
||||
sort: { username: 1 },
|
||||
fields: { _id: true },
|
||||
});
|
||||
this.numberPeople.set(users.count(false));
|
||||
this.numberPeople.set(users.length);
|
||||
return users;
|
||||
},
|
||||
orgNumber() {
|
||||
@@ -190,19 +192,19 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.orgRow.helpers({
|
||||
orgData() {
|
||||
return Org.findOne(this.orgId);
|
||||
return ReactiveCache.getOrg(this.orgId);
|
||||
},
|
||||
});
|
||||
|
||||
Template.teamRow.helpers({
|
||||
teamData() {
|
||||
return Team.findOne(this.teamId);
|
||||
return ReactiveCache.getTeam(this.teamId);
|
||||
},
|
||||
});
|
||||
|
||||
Template.peopleRow.helpers({
|
||||
userData() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -227,7 +229,7 @@ Template.editUserPopup.onCreated(function () {
|
||||
|
||||
Template.editOrgPopup.helpers({
|
||||
org() {
|
||||
return Org.findOne(this.orgId);
|
||||
return ReactiveCache.getOrg(this.orgId);
|
||||
},
|
||||
errorMessage() {
|
||||
return Template.instance().errorMessage.get();
|
||||
@@ -236,7 +238,7 @@ Template.editOrgPopup.helpers({
|
||||
|
||||
Template.editTeamPopup.helpers({
|
||||
team() {
|
||||
return Team.findOne(this.teamId);
|
||||
return ReactiveCache.getTeam(this.teamId);
|
||||
},
|
||||
errorMessage() {
|
||||
return Template.instance().errorMessage.get();
|
||||
@@ -245,25 +247,27 @@ Template.editTeamPopup.helpers({
|
||||
|
||||
Template.editUserPopup.helpers({
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
authentications() {
|
||||
return Template.instance().authenticationMethods.get();
|
||||
},
|
||||
orgsDatas() {
|
||||
return Org.find({}, {sort: { orgDisplayName: 1 }});
|
||||
const ret = ReactiveCache.getOrgs({}, {sort: { orgDisplayName: 1 }});
|
||||
return ret;
|
||||
},
|
||||
teamsDatas() {
|
||||
return Team.find({}, {sort: { teamDisplayName: 1 }});
|
||||
const ret = ReactiveCache.getTeams({}, {sort: { teamDisplayName: 1 }});
|
||||
return ret;
|
||||
},
|
||||
isSelected(match) {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
const selected = ReactiveCache.getUser(userId).authenticationMethod;
|
||||
return selected === match;
|
||||
},
|
||||
isLdap() {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
const selected = ReactiveCache.getUser(userId).authenticationMethod;
|
||||
return selected === 'ldap';
|
||||
},
|
||||
errorMessage() {
|
||||
@@ -300,7 +304,7 @@ Template.newUserPopup.onCreated(function () {
|
||||
|
||||
Template.newOrgPopup.helpers({
|
||||
org() {
|
||||
return Org.findOne(this.orgId);
|
||||
return ReactiveCache.getOrg(this.orgId);
|
||||
},
|
||||
errorMessage() {
|
||||
return Template.instance().errorMessage.get();
|
||||
@@ -309,7 +313,7 @@ Template.newOrgPopup.helpers({
|
||||
|
||||
Template.newTeamPopup.helpers({
|
||||
team() {
|
||||
return Team.findOne(this.teamId);
|
||||
return ReactiveCache.getTeam(this.teamId);
|
||||
},
|
||||
errorMessage() {
|
||||
return Template.instance().errorMessage.get();
|
||||
@@ -318,21 +322,23 @@ Template.newTeamPopup.helpers({
|
||||
|
||||
Template.newUserPopup.helpers({
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
authentications() {
|
||||
return Template.instance().authenticationMethods.get();
|
||||
},
|
||||
orgsDatas() {
|
||||
return Org.find({}, {sort: { orgDisplayName: 1 }});
|
||||
const ret = ReactiveCache.getOrgs({}, {sort: { orgDisplayName: 1 }});
|
||||
return ret;
|
||||
},
|
||||
teamsDatas() {
|
||||
return Team.find({}, {sort: { teamDisplayName: 1 }});
|
||||
const ret = ReactiveCache.getTeams({}, {sort: { teamDisplayName: 1 }});
|
||||
return ret;
|
||||
},
|
||||
isSelected(match) {
|
||||
const userId = Template.instance().data.userId;
|
||||
if(userId){
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
const selected = ReactiveCache.getUser(userId).authenticationMethod;
|
||||
return selected === match;
|
||||
}
|
||||
else{
|
||||
@@ -341,7 +347,7 @@ Template.newUserPopup.helpers({
|
||||
},
|
||||
isLdap() {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
const selected = ReactiveCache.getUser(userId).authenticationMethod;
|
||||
return selected === 'ldap';
|
||||
},
|
||||
errorMessage() {
|
||||
@@ -352,7 +358,7 @@ Template.newUserPopup.helpers({
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {},
|
||||
org() {
|
||||
return Org.findOne(this.orgId);
|
||||
return ReactiveCache.getOrg(this.orgId);
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
@@ -367,7 +373,7 @@ BlazeComponent.extendComponent({
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {},
|
||||
team() {
|
||||
return Team.findOne(this.teamId);
|
||||
return ReactiveCache.getTeam(this.teamId);
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
@@ -382,7 +388,7 @@ BlazeComponent.extendComponent({
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {},
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
@@ -417,7 +423,8 @@ BlazeComponent.extendComponent({
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {},
|
||||
teamsDatas() {
|
||||
return Team.find({}, {sort: { teamDisplayName: 1 }});
|
||||
const ret = ReactiveCache.getTeams({}, {sort: { teamDisplayName: 1 }});
|
||||
return ret;
|
||||
},
|
||||
events() {
|
||||
return [
|
||||
@@ -440,7 +447,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
if(document.getElementById('addAction').checked){
|
||||
for(let i = 0; i < selectedUserChkBoxUserIds.length; i++){
|
||||
currentUser = Users.findOne(selectedUserChkBoxUserIds[i]);
|
||||
currentUser = ReactiveCache.getUser(selectedUserChkBoxUserIds[i]);
|
||||
userTms = currentUser.teams;
|
||||
if(userTms == undefined || userTms.length == 0){
|
||||
userTms = [];
|
||||
@@ -469,7 +476,7 @@ BlazeComponent.extendComponent({
|
||||
}
|
||||
else{
|
||||
for(let i = 0; i < selectedUserChkBoxUserIds.length; i++){
|
||||
currentUser = Users.findOne(selectedUserChkBoxUserIds[i]);
|
||||
currentUser = ReactiveCache.getUser(selectedUserChkBoxUserIds[i]);
|
||||
userTms = currentUser.teams;
|
||||
if(userTms !== undefined || userTms.length > 0)
|
||||
{
|
||||
@@ -562,7 +569,7 @@ BlazeComponent.extendComponent({
|
||||
Template.editOrgPopup.events({
|
||||
submit(event, templateInstance) {
|
||||
event.preventDefault();
|
||||
const org = Org.findOne(this.orgId);
|
||||
const org = ReactiveCache.getOrg(this.orgId);
|
||||
|
||||
const orgDisplayName = templateInstance
|
||||
.find('.js-orgDisplayName')
|
||||
@@ -603,7 +610,7 @@ Template.editOrgPopup.events({
|
||||
Template.editTeamPopup.events({
|
||||
submit(event, templateInstance) {
|
||||
event.preventDefault();
|
||||
const team = Team.findOne(this.teamId);
|
||||
const team = ReactiveCache.getTeam(this.teamId);
|
||||
|
||||
const teamDisplayName = templateInstance
|
||||
.find('.js-teamDisplayName')
|
||||
@@ -647,7 +654,7 @@ Template.editTeamPopup.events({
|
||||
Template.editUserPopup.events({
|
||||
submit(event, templateInstance) {
|
||||
event.preventDefault();
|
||||
const user = Users.findOne(this.userId);
|
||||
const user = ReactiveCache.getUser(this.userId);
|
||||
const username = templateInstance.find('.js-profile-username').value.trim();
|
||||
const fullname = templateInstance.find('.js-profile-fullname').value.trim();
|
||||
const initials = templateInstance.find('.js-profile-initials').value.trim();
|
||||
@@ -1071,7 +1078,7 @@ Template.newUserPopup.events({
|
||||
Template.settingsOrgPopup.events({
|
||||
'click #deleteButton'(event) {
|
||||
event.preventDefault();
|
||||
if(Users.find({"orgs.orgId": this.orgId}).count() > 0)
|
||||
if (ReactiveCache.getUsers({"orgs.orgId": this.orgId}).length > 0)
|
||||
{
|
||||
let orgClassList = document.getElementById("deleteOrgWarningMessage").classList;
|
||||
if(orgClassList.contains('hide'))
|
||||
@@ -1089,7 +1096,7 @@ Template.settingsOrgPopup.events({
|
||||
Template.settingsTeamPopup.events({
|
||||
'click #deleteButton'(event) {
|
||||
event.preventDefault();
|
||||
if(Users.find({"teams.teamId": this.teamId}).count() > 0)
|
||||
if (ReactiveCache.getUsers({"teams.teamId": this.teamId}).length > 0)
|
||||
{
|
||||
let teamClassList = document.getElementById("deleteTeamWarningMessage").classList;
|
||||
if(teamClassList.contains('hide'))
|
||||
@@ -1139,19 +1146,19 @@ Template.settingsUserPopup.events({
|
||||
|
||||
Template.settingsUserPopup.helpers({
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
authentications() {
|
||||
return Template.instance().authenticationMethods.get();
|
||||
},
|
||||
isSelected(match) {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
const selected = ReactiveCache.getUser(userId).authenticationMethod;
|
||||
return selected === match;
|
||||
},
|
||||
isLdap() {
|
||||
const userId = Template.instance().data.userId;
|
||||
const selected = Users.findOne(userId).authenticationMethod;
|
||||
const selected = ReactiveCache.getUser(userId).authenticationMethod;
|
||||
return selected === 'ldap';
|
||||
},
|
||||
errorMessage() {
|
||||
|
||||
@@ -171,15 +171,15 @@ template(name='announcementSettings')
|
||||
ul#announcement-setting.setting-detail
|
||||
li
|
||||
a.flex.js-toggle-activemessage
|
||||
.materialCheckBox(class="{{#if currentSetting.enabled}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if currentAnnouncements.enabled}}is-checked{{/if}}")
|
||||
|
||||
span {{_ 'admin-announcement-active'}}
|
||||
li
|
||||
.admin-announcement(class="{{#if currentSetting.enabled}}{{else}}hide{{/if}}")
|
||||
.admin-announcement(class="{{#if currentAnnouncements.enabled}}{{else}}hide{{/if}}")
|
||||
ul
|
||||
li
|
||||
.title {{_ 'admin-announcement-title'}}
|
||||
textarea#admin-announcement.wekan-form-control= currentSetting.body
|
||||
textarea#admin-announcement.wekan-form-control= currentAnnouncements.body
|
||||
li
|
||||
button.js-announcement-save.primary {{_ 'save'}}
|
||||
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import { ALLOWED_WAIT_SPINNERS } from '/config/const';
|
||||
|
||||
@@ -42,12 +43,8 @@ BlazeComponent.extendComponent({
|
||||
}
|
||||
},
|
||||
|
||||
currentSetting() {
|
||||
return Settings.findOne();
|
||||
},
|
||||
|
||||
boards() {
|
||||
return Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
@@ -57,19 +54,20 @@ BlazeComponent.extendComponent({
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
toggleForgotPassword() {
|
||||
this.setLoading(true);
|
||||
const forgotPasswordClosed = this.currentSetting().disableForgotPassword;
|
||||
Settings.update(Settings.findOne()._id, {
|
||||
const forgotPasswordClosed = ReactiveCache.getCurrentSetting().disableForgotPassword;
|
||||
Settings.update(ReactiveCache.getCurrentSetting()._id, {
|
||||
$set: { disableForgotPassword: !forgotPasswordClosed },
|
||||
});
|
||||
this.setLoading(false);
|
||||
},
|
||||
toggleRegistration() {
|
||||
this.setLoading(true);
|
||||
const registrationClosed = this.currentSetting().disableRegistration;
|
||||
Settings.update(Settings.findOne()._id, {
|
||||
const registrationClosed = ReactiveCache.getCurrentSetting().disableRegistration;
|
||||
Settings.update(ReactiveCache.getCurrentSetting()._id, {
|
||||
$set: { disableRegistration: !registrationClosed },
|
||||
});
|
||||
this.setLoading(false);
|
||||
@@ -165,7 +163,7 @@ BlazeComponent.extendComponent({
|
||||
.trim();
|
||||
const from = this.checkField('#mail-server-from');
|
||||
const tls = $('#mail-server-tls.is-checked').length > 0;
|
||||
Settings.update(Settings.findOne()._id, {
|
||||
Settings.update(ReactiveCache.getCurrentSetting()._id, {
|
||||
$set: {
|
||||
'mailServer.host': host,
|
||||
'mailServer.port': port,
|
||||
@@ -245,7 +243,7 @@ BlazeComponent.extendComponent({
|
||||
const spinnerName = $('#spinnerName').val();
|
||||
|
||||
try {
|
||||
Settings.update(Settings.findOne()._id, {
|
||||
Settings.update(ReactiveCache.getCurrentSetting()._id, {
|
||||
$set: {
|
||||
productName,
|
||||
hideLogo: hideLogoChange,
|
||||
@@ -416,7 +414,7 @@ BlazeComponent.extendComponent({
|
||||
this.loading.set(w);
|
||||
},
|
||||
|
||||
currentSetting() {
|
||||
currentAnnouncements() {
|
||||
return Announcements.findOne();
|
||||
},
|
||||
|
||||
@@ -431,8 +429,9 @@ BlazeComponent.extendComponent({
|
||||
|
||||
toggleActive() {
|
||||
this.setLoading(true);
|
||||
const isActive = this.currentSetting().enabled;
|
||||
Announcements.update(Announcements.findOne()._id, {
|
||||
const announcements = this.currentAnnouncements();
|
||||
const isActive = announcements.enabled;
|
||||
Announcements.update(announcements._id, {
|
||||
$set: { enabled: !isActive },
|
||||
});
|
||||
this.setLoading(false);
|
||||
|
||||
@@ -14,6 +14,12 @@
|
||||
box-shadow: -10px 0px 5px -10px #b3b3b3;
|
||||
z-index: 10;
|
||||
}
|
||||
.sidebar-xmark {
|
||||
position: absolute;
|
||||
right: 10px;
|
||||
top: 5px;
|
||||
font-size: 25px;
|
||||
}
|
||||
.sidebar .sidebar-content {
|
||||
padding: 12px;
|
||||
margin-bottom: 1.6em;
|
||||
@@ -24,6 +30,7 @@
|
||||
left: 0;
|
||||
overflow-x: hidden;
|
||||
overflow-y: auto;
|
||||
width: 90%;
|
||||
}
|
||||
.sidebar .sidebar-content .hide-btn {
|
||||
display: none;
|
||||
|
||||
@@ -5,6 +5,7 @@ template(name="sidebar")
|
||||
// title="{{showTongueTitle}}")
|
||||
// i.fa.fa-navicon
|
||||
.sidebar-shadow
|
||||
a.sidebar-xmark.js-close-sidebar ✕
|
||||
.sidebar-content.js-board-sidebar-content
|
||||
//a.hide-btn.js-hide-sidebar
|
||||
// i.fa.fa-navicon
|
||||
@@ -12,7 +13,8 @@ template(name="sidebar")
|
||||
h2
|
||||
a.fa.fa-chevron-left.js-back-home
|
||||
= getViewTitle
|
||||
+Template.dynamic(template=getViewTemplate)
|
||||
if isOpen
|
||||
+Template.dynamic(template=getViewTemplate)
|
||||
|
||||
template(name='homeSidebar')
|
||||
hr
|
||||
@@ -137,6 +139,22 @@ template(name="boardChangeColorPopup")
|
||||
if isSelected
|
||||
i.fa.fa-check
|
||||
|
||||
template(name="boardChangeBackgroundImagePopup")
|
||||
form
|
||||
label
|
||||
| {{_ 'board-background-image-url'}}
|
||||
input.js-board-background-image-url(type="text" value="{{backgroundImageURL}}" autofocus)
|
||||
div.buttonsContainer
|
||||
input.primary.wide(type="submit" value="{{_ 'save'}}")
|
||||
br
|
||||
br
|
||||
br
|
||||
br
|
||||
br
|
||||
hr
|
||||
div
|
||||
button.js-remove-background-image.negate.wide.card-details-red.right {{_ 'unset-color'}}
|
||||
|
||||
template(name="boardInfoOnMyBoardsPopup")
|
||||
form.board-info-on-my-boards
|
||||
h3 {{_ 'show-at-all-boards-page'}}
|
||||
@@ -293,6 +311,25 @@ template(name="boardMinicardSettingsPopup")
|
||||
span
|
||||
i.fa.fa-align-left
|
||||
| {{_ 'description-on-minicard'}}
|
||||
div.check-div
|
||||
a.flex.js-field-has-cover-attachment-on-minicard(class="{{#if allowsCoverAttachmentOnMinicard}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if allowsCoverAttachmentOnMinicard}}is-checked{{/if}}")
|
||||
span
|
||||
i.fa.fa-book
|
||||
i.fa.fa-picture-o
|
||||
| {{_ 'cover-attachment-on-minicard'}}
|
||||
div.check-div
|
||||
a.flex.js-field-has-badge-attachment-on-minicard(class="{{#if allowsBadgeAttachmentOnMinicard}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if allowsBadgeAttachmentOnMinicard}}is-checked{{/if}}")
|
||||
span
|
||||
i.fa.fa-paperclip
|
||||
| {{_ 'badge-attachment-on-minicard'}}
|
||||
div.check-div
|
||||
a.flex.js-field-has-card-sorting-by-number-on-minicard(class="{{#if allowsCardSortingByNumberOnMinicard}}is-checked{{/if}}")
|
||||
.materialCheckBox(class="{{#if allowsCardSortingByNumberOnMinicard}}is-checked{{/if}}")
|
||||
span
|
||||
i.fa.fa-sort
|
||||
| {{_ 'card-sorting-by-number-on-minicard'}}
|
||||
|
||||
template(name="boardSubtaskSettingsPopup")
|
||||
form.board-subtask-settings
|
||||
@@ -408,13 +445,18 @@ template(name="boardMenuPopup")
|
||||
a.js-change-board-color
|
||||
i.fa.fa-paint-brush
|
||||
| {{_ 'board-change-color'}}
|
||||
if currentUser.isBoardAdmin
|
||||
unless currentSetting.hideBoardMemberList
|
||||
unless currentSetting.hideCardCounterList
|
||||
li
|
||||
a.js-board-info-on-my-boards(title="{{_ 'board-info-on-my-boards'}}")
|
||||
i.fa.fa-id-card-o
|
||||
| {{_ 'board-info-on-my-boards'}}
|
||||
li
|
||||
a.js-change-background-image
|
||||
i.fa.fa-picture-o
|
||||
| {{_ 'board-change-background-image'}}
|
||||
//Bug Board icons random dance https://github.com/wekan/wekan/issues/4214
|
||||
//if currentUser.isBoardAdmin
|
||||
// unless currentSetting.hideBoardMemberList
|
||||
// unless currentSetting.hideCardCounterList
|
||||
// li
|
||||
// a.js-board-info-on-my-boards(title="{{_ 'board-info-on-my-boards'}}")
|
||||
// i.fa.fa-id-card-o
|
||||
// | {{_ 'board-info-on-my-boards'}}
|
||||
hr
|
||||
ul.pop-over-list
|
||||
if withApi
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
Sidebar = null;
|
||||
@@ -111,7 +112,7 @@ BlazeComponent.extendComponent({
|
||||
'click .js-toggle-sidebar': this.toggle,
|
||||
'click .js-back-home': this.setView,
|
||||
'click .js-toggle-minicard-label-text'() {
|
||||
currentUser = Meteor.user();
|
||||
currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
Meteor.call('toggleMinicardLabelText');
|
||||
} else if (window.localStorage.getItem('hiddenMinicardLabelText')) {
|
||||
@@ -125,6 +126,9 @@ BlazeComponent.extendComponent({
|
||||
'click .js-shortcuts'() {
|
||||
FlowRouter.go('shortcuts');
|
||||
},
|
||||
'click .js-close-sidebar'() {
|
||||
Sidebar.toggle()
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
@@ -134,7 +138,7 @@ Blaze.registerHelper('Sidebar', () => Sidebar);
|
||||
|
||||
Template.homeSidebar.helpers({
|
||||
hiddenMinicardLabelText() {
|
||||
currentUser = Meteor.user();
|
||||
currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).hiddenMinicardLabelText;
|
||||
} else if (window.localStorage.getItem('hiddenMinicardLabelText')) {
|
||||
@@ -146,16 +150,13 @@ Template.homeSidebar.helpers({
|
||||
});
|
||||
|
||||
Template.boardInfoOnMyBoardsPopup.helpers({
|
||||
currentSetting() {
|
||||
return Settings.findOne();
|
||||
},
|
||||
hideCardCounterList() {
|
||||
return Utils.isMiniScreen() && Session.get('currentBoard');
|
||||
},
|
||||
hideBoardMemberList() {
|
||||
return Utils.isMiniScreen() && Session.get('currentBoard');
|
||||
},
|
||||
})
|
||||
});
|
||||
|
||||
EscapeActions.register(
|
||||
'sidebarView',
|
||||
@@ -169,15 +170,15 @@ EscapeActions.register(
|
||||
|
||||
Template.memberPopup.helpers({
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
memberType() {
|
||||
const type = Users.findOne(this.userId).isBoardAdmin() ? 'admin' : 'normal';
|
||||
const type = ReactiveCache.getUser(this.userId).isBoardAdmin() ? 'admin' : 'normal';
|
||||
if (type === 'normal') {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const commentOnly = currentBoard.hasCommentOnly(this.userId);
|
||||
const noComments = currentBoard.hasNoComments(this.userId);
|
||||
const worker = currentBoard.hasWorker(this.userId);
|
||||
@@ -195,7 +196,7 @@ Template.memberPopup.helpers({
|
||||
}
|
||||
},
|
||||
isInvited() {
|
||||
return Users.findOne(this.userId).isInvitedTo(Session.get('currentBoard'));
|
||||
return ReactiveCache.getUser(this.userId).isInvitedTo(Session.get('currentBoard'));
|
||||
},
|
||||
});
|
||||
|
||||
@@ -215,17 +216,18 @@ Template.boardMenuPopup.events({
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-change-board-color': Popup.open('boardChangeColor'),
|
||||
'click .js-change-background-image': Popup.open('boardChangeBackgroundImage'),
|
||||
'click .js-board-info-on-my-boards': Popup.open('boardInfoOnMyBoards'),
|
||||
'click .js-change-language': Popup.open('changeLanguage'),
|
||||
'click .js-archive-board ': Popup.afterConfirm('archiveBoard', function() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
currentBoard.archive();
|
||||
// XXX We should have some kind of notification on top of the page to
|
||||
// confirm that the board was successfully archived.
|
||||
FlowRouter.go('home');
|
||||
}),
|
||||
'click .js-delete-board': Popup.afterConfirm('deleteBoard', function() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
Popup.back();
|
||||
Boards.remove(currentBoard._id);
|
||||
FlowRouter.go('home');
|
||||
@@ -247,7 +249,7 @@ Template.boardMenuPopup.onCreated(function() {
|
||||
|
||||
Template.boardMenuPopup.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
withApi() {
|
||||
return Template.instance().apiEnabled.get();
|
||||
@@ -277,13 +279,13 @@ Template.memberPopup.events({
|
||||
// This works from removing member from board, card members and assignees.
|
||||
const boardId = Session.get('currentBoard');
|
||||
const memberId = this.userId;
|
||||
Cards.find({ boardId, members: memberId }).forEach(card => {
|
||||
ReactiveCache.getCards({ boardId, members: memberId }).forEach(card => {
|
||||
card.unassignMember(memberId);
|
||||
});
|
||||
Cards.find({ boardId, assignees: memberId }).forEach(card => {
|
||||
ReactiveCache.getCards({ boardId, assignees: memberId }).forEach(card => {
|
||||
card.unassignAssignee(memberId);
|
||||
});
|
||||
Boards.findOne(boardId).removeMember(memberId);
|
||||
ReactiveCache.getBoard(boardId).removeMember(memberId);
|
||||
Popup.back();
|
||||
}),
|
||||
'click .js-leave-member': Popup.afterConfirm('leaveBoard', () => {
|
||||
@@ -297,16 +299,16 @@ Template.memberPopup.events({
|
||||
|
||||
Template.removeMemberPopup.helpers({
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
board() {
|
||||
return Boards.findOne(Session.get('currentBoard'));
|
||||
return Utils.getCurrentBoard();
|
||||
},
|
||||
});
|
||||
|
||||
Template.leaveBoardPopup.helpers({
|
||||
board() {
|
||||
return Boards.findOne(Session.get('currentBoard'));
|
||||
return Utils.getCurrentBoard();
|
||||
},
|
||||
});
|
||||
BlazeComponent.extendComponent({
|
||||
@@ -356,11 +358,11 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.membersWidget.helpers({
|
||||
isInvited() {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
return user && user.isInvitedTo(Session.get('currentBoard'));
|
||||
},
|
||||
isWorker() {
|
||||
const user = Meteor.user();
|
||||
const user = ReactiveCache.getCurrentUser();
|
||||
if (user) {
|
||||
return Meteor.call(Boards.hasWorker(user.memberId));
|
||||
} else {
|
||||
@@ -368,22 +370,22 @@ Template.membersWidget.helpers({
|
||||
}
|
||||
},
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
AtLeastOneOrgWasCreated(){
|
||||
let orgs = Org.find({}, {sort: { createdAt: -1 }});
|
||||
let orgs = ReactiveCache.getOrgs({}, {sort: { createdAt: -1 }});
|
||||
if(orgs === undefined)
|
||||
return false;
|
||||
|
||||
return orgs.count() > 0;
|
||||
return orgs.length > 0;
|
||||
},
|
||||
|
||||
AtLeastOneTeamWasCreated(){
|
||||
let teams = Team.find({}, {sort: { createdAt: -1 }});
|
||||
let teams = ReactiveCache.getTeams({}, {sort: { createdAt: -1 }});
|
||||
if(teams === undefined)
|
||||
return false;
|
||||
|
||||
return teams.count() > 0;
|
||||
return teams.length > 0;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -404,13 +406,13 @@ Template.membersWidget.events({
|
||||
},
|
||||
'click .js-member-invite-accept'() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
Meteor.user().removeInvite(boardId);
|
||||
ReactiveCache.getCurrentUser().removeInvite(boardId);
|
||||
},
|
||||
'click .js-member-invite-decline'() {
|
||||
const boardId = Session.get('currentBoard');
|
||||
Meteor.call('quitBoard', boardId, (err, ret) => {
|
||||
if (!err && ret) {
|
||||
Meteor.user().removeInvite(boardId);
|
||||
ReactiveCache.getCurrentUser().removeInvite(boardId);
|
||||
FlowRouter.go('home');
|
||||
}
|
||||
});
|
||||
@@ -423,7 +425,8 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
integrations() {
|
||||
const boardId = this.boardId();
|
||||
return Integrations.find({ boardId: `${boardId}` }).fetch();
|
||||
const ret = ReactiveCache.getIntegrations({ boardId });
|
||||
return ret;
|
||||
},
|
||||
types() {
|
||||
return Integrations.Const.WEBHOOK_TYPES;
|
||||
@@ -434,7 +437,7 @@ BlazeComponent.extendComponent({
|
||||
for (const k in condition) {
|
||||
if (!condition[k]) delete condition[k];
|
||||
}
|
||||
return Integrations.findOne(condition);
|
||||
return ReactiveCache.getIntegration(condition);
|
||||
},
|
||||
onCreated() {
|
||||
this.disabled = new ReactiveVar(false);
|
||||
@@ -602,7 +605,7 @@ Template.labelsWidget.events({
|
||||
|
||||
Template.labelsWidget.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -616,7 +619,7 @@ function draggableMembersLabelsWidgets() {
|
||||
const currentBoardId = Tracker.nonreactive(() => {
|
||||
return Session.get('currentBoard');
|
||||
});
|
||||
Boards.findOne(currentBoardId, {
|
||||
ReactiveCache.getBoard(currentBoardId, {
|
||||
fields: {
|
||||
members: 1,
|
||||
labels: 1,
|
||||
@@ -637,7 +640,7 @@ function draggableMembersLabelsWidgets() {
|
||||
});
|
||||
|
||||
function userIsMember() {
|
||||
return Meteor.user() && Meteor.user().isBoardMember();
|
||||
return ReactiveCache.getCurrentUser()?.isBoardMember();
|
||||
}
|
||||
|
||||
this.autorun(() => {
|
||||
@@ -656,7 +659,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
isSelected() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return currentBoard.color === this.currentData().toString();
|
||||
},
|
||||
|
||||
@@ -664,7 +667,7 @@ BlazeComponent.extendComponent({
|
||||
return [
|
||||
{
|
||||
'click .js-select-background'(evt) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const newColor = this.currentData().toString();
|
||||
currentBoard.setColor(newColor);
|
||||
evt.preventDefault();
|
||||
@@ -674,9 +677,40 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
}).register('boardChangeColorPopup');
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
submit(event) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const backgroundImageURL = this.find('.js-board-background-image-url').value.trim();
|
||||
currentBoard.setBackgroundImageURL(backgroundImageURL);
|
||||
Utils.setBackgroundImage();
|
||||
Popup.back();
|
||||
event.preventDefault();
|
||||
},
|
||||
'click .js-remove-background-image'() {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
currentBoard.setBackgroundImageURL("");
|
||||
Popup.back();
|
||||
Utils.reload();
|
||||
event.preventDefault();
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
}).register('boardChangeBackgroundImagePopup');
|
||||
|
||||
Template.boardChangeBackgroundImagePopup.helpers({
|
||||
backgroundImageURL() {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return currentBoard.backgroundImageURL;
|
||||
},
|
||||
});
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
this.currentBoard = Utils.getCurrentBoard();
|
||||
},
|
||||
|
||||
allowsCardCounterList() {
|
||||
@@ -729,7 +763,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
this.currentBoard = Utils.getCurrentBoard();
|
||||
},
|
||||
|
||||
allowsSubtasks() {
|
||||
@@ -752,7 +786,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
boards() {
|
||||
return Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
@@ -761,10 +795,11 @@ BlazeComponent.extendComponent({
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
|
||||
lists() {
|
||||
return Lists.find(
|
||||
return ReactiveCache.getLists(
|
||||
{
|
||||
boardId: this.currentBoard._id,
|
||||
archived: false,
|
||||
@@ -776,7 +811,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
hasLists() {
|
||||
return this.lists().count() > 0;
|
||||
return this.lists().length > 0;
|
||||
},
|
||||
|
||||
isListSelected() {
|
||||
@@ -855,7 +890,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
this.currentBoard = Utils.getCurrentBoard();
|
||||
},
|
||||
|
||||
allowsReceivedDate() {
|
||||
@@ -950,7 +985,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
boards() {
|
||||
return Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
@@ -959,10 +994,11 @@ BlazeComponent.extendComponent({
|
||||
sort: { sort: 1 /* boards default sorting */ },
|
||||
},
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
|
||||
lists() {
|
||||
return Lists.find(
|
||||
return ReactiveCache.getLists(
|
||||
{
|
||||
boardId: this.currentBoard._id,
|
||||
archived: false,
|
||||
@@ -974,7 +1010,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
hasLists() {
|
||||
return this.lists().count() > 0;
|
||||
return this.lists().length > 0;
|
||||
},
|
||||
|
||||
isListSelected() {
|
||||
@@ -1290,15 +1326,27 @@ BlazeComponent.extendComponent({
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
this.currentBoard = Utils.getCurrentBoard();
|
||||
},
|
||||
|
||||
allowsDescriptionTextOnMinicard() {
|
||||
return this.currentBoard.allowsDescriptionTextOnMinicard;
|
||||
},
|
||||
|
||||
allowsCoverAttachmentOnMinicard() {
|
||||
return this.currentBoard.allowsCoverAttachmentOnMinicard;
|
||||
},
|
||||
|
||||
allowsBadgeAttachmentOnMinicard() {
|
||||
return this.currentBoard.allowsBadgeAttachmentOnMinicard;
|
||||
},
|
||||
|
||||
allowsCardSortingByNumberOnMinicard() {
|
||||
return this.currentBoard.allowsCardSortingByNumberOnMinicard;
|
||||
},
|
||||
|
||||
lists() {
|
||||
return Lists.find(
|
||||
return ReactiveCache.getLists(
|
||||
{
|
||||
boardId: this.currentBoard._id,
|
||||
archived: false,
|
||||
@@ -1310,7 +1358,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
hasLists() {
|
||||
return this.lists().count() > 0;
|
||||
return this.lists().length > 0;
|
||||
},
|
||||
|
||||
isListSelected() {
|
||||
@@ -1338,6 +1386,54 @@ BlazeComponent.extendComponent({
|
||||
this.currentBoard.allowsDescriptionTextOnMinicard,
|
||||
);
|
||||
},
|
||||
'click .js-field-has-cover-attachment-on-minicard'(evt) {
|
||||
evt.preventDefault();
|
||||
this.currentBoard.allowsCoverAttachmentOnMinicard = !this.currentBoard
|
||||
.allowsCoverAttachmentOnMinicard;
|
||||
this.currentBoard.setallowsCoverAttachmentOnMinicard(
|
||||
this.currentBoard.allowsCoverAttachmentOnMinicard,
|
||||
);
|
||||
$(`.js-field-has-cover-attachment-on-minicard ${MCB}`).toggleClass(
|
||||
CKCLS,
|
||||
this.currentBoard.allowsCoverAttachmentOnMinicard,
|
||||
);
|
||||
$('.js-field-has-cover-attachment-on-minicard').toggleClass(
|
||||
CKCLS,
|
||||
this.currentBoard.allowsCoverAttachmentOnMinicard,
|
||||
);
|
||||
},
|
||||
'click .js-field-has-badge-attachment-on-minicard'(evt) {
|
||||
evt.preventDefault();
|
||||
this.currentBoard.allowsBadgeAttachmentOnMinicard = !this.currentBoard
|
||||
.allowsBadgeAttachmentOnMinicard;
|
||||
this.currentBoard.setallowsBadgeAttachmentOnMinicard(
|
||||
this.currentBoard.allowsBadgeAttachmentOnMinicard,
|
||||
);
|
||||
$(`.js-field-has-badge-attachment-on-minicard ${MCB}`).toggleClass(
|
||||
CKCLS,
|
||||
this.currentBoard.allowsBadgeAttachmentOnMinicard,
|
||||
);
|
||||
$('.js-field-has-badge-attachment-on-minicard').toggleClass(
|
||||
CKCLS,
|
||||
this.currentBoard.allowsBadgeAttachmentOnMinicard,
|
||||
);
|
||||
},
|
||||
'click .js-field-has-card-sorting-by-number-on-minicard'(evt) {
|
||||
evt.preventDefault();
|
||||
this.currentBoard.allowsCardSortingByNumberOnMinicard = !this.currentBoard
|
||||
.allowsCardSortingByNumberOnMinicard;
|
||||
this.currentBoard.setallowsCardSortingByNumberOnMinicard(
|
||||
this.currentBoard.allowsCardSortingByNumberOnMinicard,
|
||||
);
|
||||
$(`.js-field-has-card-sorting-by-number-on-minicard ${MCB}`).toggleClass(
|
||||
CKCLS,
|
||||
this.currentBoard.allowsCardSortingByNumberOnMinicard,
|
||||
);
|
||||
$('.js-field-has-card-sorting-by-number-on-minicard').toggleClass(
|
||||
CKCLS,
|
||||
this.currentBoard.allowsCardSortingByNumberOnMinicard,
|
||||
);
|
||||
},
|
||||
},
|
||||
];
|
||||
},
|
||||
@@ -1356,7 +1452,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
isBoardMember() {
|
||||
const userId = this.currentData().__originalId;
|
||||
const user = Users.findOne(userId);
|
||||
const user = ReactiveCache.getUser(userId);
|
||||
return user && user.isBoardMember();
|
||||
},
|
||||
|
||||
@@ -1396,7 +1492,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
'click .js-select-member'() {
|
||||
const userId = this.currentData().__originalId;
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
if (!currentBoard.hasMember(userId)) {
|
||||
this.inviteUser(userId);
|
||||
}
|
||||
@@ -1452,7 +1548,7 @@ BlazeComponent.extendComponent({
|
||||
this.setError('');
|
||||
},
|
||||
'change #jsBoardOrgs'() {
|
||||
let currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
let currentBoard = Utils.getCurrentBoard();
|
||||
let selectElt = document.getElementById("jsBoardOrgs");
|
||||
let selectedOrgId = selectElt.options[selectElt.selectedIndex].value;
|
||||
let selectedOrgDisplayName = selectElt.options[selectElt.selectedIndex].text;
|
||||
@@ -1484,8 +1580,8 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.addBoardOrgPopup.helpers({
|
||||
orgsDatas() {
|
||||
let orgs = Org.find({}, {sort: { orgDisplayName: 1 }});
|
||||
return orgs;
|
||||
let ret = ReactiveCache.getOrgs({}, {sort: { orgDisplayName: 1 }});
|
||||
return ret;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1526,7 +1622,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
'click #leaveBoardBtn'(){
|
||||
let stringOrgId = document.getElementById('hideOrgId').value;
|
||||
let currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
let currentBoard = Utils.getCurrentBoard();
|
||||
let boardOrganizations = [];
|
||||
if(currentBoard.orgs !== undefined){
|
||||
for(let i = 0; i < currentBoard.orgs.length; i++){
|
||||
@@ -1550,7 +1646,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.removeBoardOrgPopup.helpers({
|
||||
org() {
|
||||
return Org.findOne(this.orgId);
|
||||
return ReactiveCache.getOrg(this.orgId);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1597,7 +1693,7 @@ BlazeComponent.extendComponent({
|
||||
this.setError('');
|
||||
},
|
||||
'change #jsBoardTeams'() {
|
||||
let currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
let currentBoard = Utils.getCurrentBoard();
|
||||
let selectElt = document.getElementById("jsBoardTeams");
|
||||
let selectedTeamId = selectElt.options[selectElt.selectedIndex].value;
|
||||
let selectedTeamDisplayName = selectElt.options[selectElt.selectedIndex].text;
|
||||
@@ -1622,13 +1718,13 @@ BlazeComponent.extendComponent({
|
||||
"teams.teamId": { $in: boardTeams.map(t => t.teamId) },
|
||||
};
|
||||
|
||||
const boardTeamUsers = Users.find(query, {
|
||||
const boardTeamUsers = ReactiveCache.getUsers(query, {
|
||||
sort: { sort: 1 },
|
||||
});
|
||||
|
||||
if(boardTeams !== undefined && boardTeams.length > 0){
|
||||
let index;
|
||||
if(boardTeamUsers && boardTeamUsers.count() > 0){
|
||||
if (boardTeamUsers && boardTeamUsers.length > 0) {
|
||||
boardTeamUsers.forEach((u) => {
|
||||
index = members.findIndex(function(m){ return m.userId == u._id});
|
||||
if(index == -1){
|
||||
@@ -1657,8 +1753,8 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.addBoardTeamPopup.helpers({
|
||||
teamsDatas() {
|
||||
let teams = Team.find({}, {sort: { teamDisplayName: 1 }});
|
||||
return teams;
|
||||
let ret = ReactiveCache.getTeams({}, {sort: { teamDisplayName: 1 }});
|
||||
return ret;
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1706,7 +1802,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
'click #leaveBoardTeamBtn'(){
|
||||
let stringTeamId = document.getElementById('hideTeamId').value;
|
||||
let currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
let currentBoard = Utils.getCurrentBoard();
|
||||
let boardTeams = [];
|
||||
if(currentBoard.teams !== undefined){
|
||||
for(let i = 0; i < currentBoard.teams.length; i++){
|
||||
@@ -1721,13 +1817,13 @@ BlazeComponent.extendComponent({
|
||||
"teams.teamId": stringTeamId
|
||||
};
|
||||
|
||||
const boardTeamUsers = Users.find(query, {
|
||||
const boardTeamUsers = ReactiveCache.getUsers(query, {
|
||||
sort: { sort: 1 },
|
||||
});
|
||||
|
||||
if(currentBoard.teams !== undefined && currentBoard.teams.length > 0){
|
||||
let index;
|
||||
if(boardTeamUsers && boardTeamUsers.count() > 0){
|
||||
if (boardTeamUsers && boardTeamUsers.length > 0) {
|
||||
boardTeamUsers.forEach((u) => {
|
||||
index = members.findIndex(function(m){ return m.userId == u._id});
|
||||
if(index !== -1 && (u.isAdmin === undefined || u.isAdmin == false)){
|
||||
@@ -1751,7 +1847,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.removeBoardTeamPopup.helpers({
|
||||
team() {
|
||||
return Team.findOne(this.teamId);
|
||||
return ReactiveCache.getTeam(this.teamId);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -1759,7 +1855,7 @@ Template.changePermissionsPopup.events({
|
||||
'click .js-set-admin, click .js-set-normal, click .js-set-no-comments, click .js-set-comment-only, click .js-set-worker'(
|
||||
event,
|
||||
) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const memberId = this.userId;
|
||||
const isAdmin = $(event.currentTarget).hasClass('js-set-admin');
|
||||
const isCommentOnly = $(event.currentTarget).hasClass(
|
||||
@@ -1780,12 +1876,12 @@ Template.changePermissionsPopup.events({
|
||||
|
||||
Template.changePermissionsPopup.helpers({
|
||||
isAdmin() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return currentBoard.hasAdmin(this.userId);
|
||||
},
|
||||
|
||||
isNormal() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return (
|
||||
!currentBoard.hasAdmin(this.userId) &&
|
||||
!currentBoard.hasNoComments(this.userId) &&
|
||||
@@ -1795,7 +1891,7 @@ Template.changePermissionsPopup.helpers({
|
||||
},
|
||||
|
||||
isNoComments() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return (
|
||||
!currentBoard.hasAdmin(this.userId) &&
|
||||
currentBoard.hasNoComments(this.userId)
|
||||
@@ -1803,7 +1899,7 @@ Template.changePermissionsPopup.helpers({
|
||||
},
|
||||
|
||||
isCommentOnly() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return (
|
||||
!currentBoard.hasAdmin(this.userId) &&
|
||||
currentBoard.hasCommentOnly(this.userId)
|
||||
@@ -1811,14 +1907,14 @@ Template.changePermissionsPopup.helpers({
|
||||
},
|
||||
|
||||
isWorker() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return (
|
||||
!currentBoard.hasAdmin(this.userId) && currentBoard.hasWorker(this.userId)
|
||||
);
|
||||
},
|
||||
|
||||
isLastAdmin() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return (
|
||||
currentBoard.hasAdmin(this.userId) && currentBoard.activeAdmins() === 1
|
||||
);
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
//archivedRequested = false;
|
||||
@@ -33,7 +34,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
archivedCards() {
|
||||
return Cards.find(
|
||||
const ret = ReactiveCache.getCards(
|
||||
{
|
||||
archived: true,
|
||||
boardId: Session.get('currentBoard'),
|
||||
@@ -42,10 +43,11 @@ BlazeComponent.extendComponent({
|
||||
sort: { archivedAt: -1, modifiedAt: -1 },
|
||||
},
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
|
||||
archivedLists() {
|
||||
return Lists.find(
|
||||
return ReactiveCache.getLists(
|
||||
{
|
||||
archived: true,
|
||||
boardId: Session.get('currentBoard'),
|
||||
@@ -57,7 +59,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
archivedSwimlanes() {
|
||||
return Swimlanes.find(
|
||||
return ReactiveCache.getSwimlanes(
|
||||
{
|
||||
archived: true,
|
||||
boardId: Session.get('currentBoard'),
|
||||
@@ -159,10 +161,10 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.archivesSidebar.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
isWorker() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return (
|
||||
!currentBoard.hasAdmin(this.userId) && currentBoard.hasWorker(this.userId)
|
||||
);
|
||||
|
||||
@@ -1,10 +1,12 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
customFields() {
|
||||
return CustomFields.find({
|
||||
const ret = ReactiveCache.getCustomFields({
|
||||
boardIds: { $in: [Session.get('currentBoard')] },
|
||||
});
|
||||
return ret;
|
||||
},
|
||||
|
||||
events() {
|
||||
@@ -275,7 +277,7 @@ const CreateCustomFieldPopup = BlazeComponent.extendComponent({
|
||||
'click .js-delete-custom-field': Popup.afterConfirm(
|
||||
'deleteCustomField',
|
||||
function() {
|
||||
const customField = CustomFields.findOne(this._id);
|
||||
const customField = ReactiveCache.getCustomField(this._id);
|
||||
if (customField.boardIds.length > 1) {
|
||||
CustomFields.update(customField._id, {
|
||||
$pull: {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
const subManager = new SubsManager();
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
@@ -93,7 +95,7 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
'click .js-filter-to-selection'(evt) {
|
||||
evt.preventDefault();
|
||||
const selectedCards = Cards.find(Filter.mongoSelector()).map(c => {
|
||||
const selectedCards = ReactiveCache.getCards(Filter.mongoSelector()).map(c => {
|
||||
return c._id;
|
||||
});
|
||||
MultiSelection.add(selectedCards);
|
||||
@@ -104,14 +106,14 @@ BlazeComponent.extendComponent({
|
||||
}).register('filterSidebar');
|
||||
|
||||
function mutateSelectedCards(mutationName, ...args) {
|
||||
Cards.find(MultiSelection.getMongoSelector(), {sort: ['sort']}).forEach(card => {
|
||||
ReactiveCache.getCards(MultiSelection.getMongoSelector(), {sort: ['sort']}).forEach(card => {
|
||||
card[mutationName](...args);
|
||||
});
|
||||
}
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
mapSelection(kind, _id) {
|
||||
return Cards.find(MultiSelection.getMongoSelector(), {sort: ['sort']}).map(card => {
|
||||
return ReactiveCache.getCards(MultiSelection.getMongoSelector(), {sort: ['sort']}).map(card => {
|
||||
const methodName = kind === 'label' ? 'hasLabel' : 'isAssigned';
|
||||
return card[methodName](_id);
|
||||
});
|
||||
@@ -171,10 +173,10 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.multiselectionSidebar.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
isCommentOnly() {
|
||||
return Meteor.user().isCommentOnly();
|
||||
return ReactiveCache.getCurrentUser().isCommentOnly();
|
||||
},
|
||||
});
|
||||
|
||||
|
||||
@@ -4,12 +4,12 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
cards() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return currentBoard.searchCards(this.term.get());
|
||||
},
|
||||
|
||||
lists() {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
return currentBoard.searchLists(this.term.get());
|
||||
},
|
||||
|
||||
|
||||
@@ -41,15 +41,24 @@ template(name="editSwimlaneTitleForm")
|
||||
template(name="swimlaneActionPopup")
|
||||
unless currentUser.isCommentOnly
|
||||
ul.pop-over-list
|
||||
li: a.js-set-swimlane-color {{_ 'select-color'}}
|
||||
li: a.js-set-swimlane-color
|
||||
i.fa.fa-paint-brush
|
||||
| {{_ 'select-color'}}
|
||||
unless this.isTemplateContainer
|
||||
hr
|
||||
ul.pop-over-list
|
||||
li: a.js-close-swimlane {{_ 'archive-swimlane'}}
|
||||
li: a.js-close-swimlane
|
||||
i.fa.fa-arrow-right
|
||||
i.fa.fa-archive
|
||||
| {{_ 'archive-swimlane'}}
|
||||
ul.pop-over-list
|
||||
li: a.js-copy-swimlane {{_ 'copy-swimlane'}}
|
||||
li: a.js-copy-swimlane
|
||||
i.fa.fa-copy
|
||||
| {{_ 'copy-swimlane'}}
|
||||
ul.pop-over-list
|
||||
li: a.js-move-swimlane {{_ 'move-swimlane'}}
|
||||
li: a.js-move-swimlane
|
||||
i.fa.fa-arrow-up
|
||||
| {{_ 'move-swimlane'}}
|
||||
|
||||
template(name="swimlaneAddPopup")
|
||||
unless currentUser.isCommentOnly
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
const { calculateIndexData } = Utils;
|
||||
|
||||
let swimlaneColors;
|
||||
@@ -30,7 +31,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.swimlaneFixedHeader.helpers({
|
||||
isBoardAdmin() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
return ReactiveCache.getCurrentUser().isBoardAdmin();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -47,7 +48,7 @@ Template.swimlaneActionPopup.events({
|
||||
|
||||
Template.swimlaneActionPopup.events({
|
||||
isCommentOnly() {
|
||||
return Meteor.user().isCommentOnly();
|
||||
return ReactiveCache.getCurrentUser().isCommentOnly();
|
||||
},
|
||||
});
|
||||
|
||||
@@ -61,7 +62,7 @@ BlazeComponent.extendComponent({
|
||||
{
|
||||
submit(event) {
|
||||
event.preventDefault();
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
const nextSwimlane = currentBoard.nextSwimlane(this.currentSwimlane);
|
||||
const titleInput = this.find('.swimlane-name-input');
|
||||
const title = titleInput.value.trim();
|
||||
|
||||
@@ -7,20 +7,20 @@ template(name="swimlane")
|
||||
if currentListIsInThisSwimlane _id
|
||||
+list(currentList)
|
||||
unless currentList
|
||||
each lists
|
||||
+miniList(this)
|
||||
if currentUser.isBoardMember
|
||||
unless currentUser.isCommentOnly
|
||||
+addListForm
|
||||
each lists
|
||||
+miniList(this)
|
||||
else
|
||||
if currentUser.isBoardMember
|
||||
unless currentUser.isCommentOnly
|
||||
+addListForm
|
||||
each lists
|
||||
if visible this
|
||||
+list(this)
|
||||
if currentCardIsInThisList _id ../_id
|
||||
+cardDetails(currentCard)
|
||||
if currentUser.isBoardMember
|
||||
unless currentUser.isCommentOnly
|
||||
+addListForm
|
||||
|
||||
template(name="listsGroup")
|
||||
.swimlane.list-group.js-lists
|
||||
@@ -51,6 +51,11 @@ template(name="addListForm")
|
||||
+inlinedForm(autoclose=false)
|
||||
input.list-name-input.full-line(type="text" placeholder="{{_ 'add-list'}}"
|
||||
autocomplete="off" autofocus)
|
||||
if currentBoard.getLastList
|
||||
| {{_ 'add-after-list'}}
|
||||
select.list-position-input.full-line
|
||||
each currentBoard.lists
|
||||
option(value="{{_id}}" selected=currentBoard.getLastList.title) {{title}}
|
||||
.edit-controls.clearfix
|
||||
button.primary.confirm(type="submit") {{_ 'save'}}
|
||||
.fa.fa-times-thin.js-close-inlined-form
|
||||
|
||||
@@ -1,7 +1,8 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
const { calculateIndex } = Utils;
|
||||
|
||||
function currentListIsInThisSwimlane(swimlaneId) {
|
||||
const currentList = Lists.findOne(Session.get('currentList'));
|
||||
const currentList = Utils.getCurrentList();
|
||||
return (
|
||||
currentList &&
|
||||
(currentList.swimlaneId === swimlaneId || currentList.swimlaneId === '')
|
||||
@@ -10,7 +11,7 @@ function currentListIsInThisSwimlane(swimlaneId) {
|
||||
|
||||
function currentCardIsInThisList(listId, swimlaneId) {
|
||||
const currentCard = Utils.getCurrentCard();
|
||||
//const currentUser = Meteor.user();
|
||||
//const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (
|
||||
//currentUser &&
|
||||
//currentUser.profile &&
|
||||
@@ -104,15 +105,6 @@ function initSortable(boardComponent, $listsDom) {
|
||||
},
|
||||
});
|
||||
|
||||
//function userIsMember() {
|
||||
// return (
|
||||
// Meteor.user() &&
|
||||
// Meteor.user().isBoardMember() &&
|
||||
// !Meteor.user().isCommentOnly() &&
|
||||
// !Meteor.user().isWorker()
|
||||
// );
|
||||
//}
|
||||
|
||||
boardComponent.autorun(() => {
|
||||
if (Utils.isTouchScreenOrShowDesktopDragHandles()) {
|
||||
$listsDom.sortable({
|
||||
@@ -129,11 +121,7 @@ function initSortable(boardComponent, $listsDom) {
|
||||
$listsDom.sortable(
|
||||
'option',
|
||||
'disabled',
|
||||
// Disable drag-dropping when user is not member/is worker
|
||||
//!userIsMember() || Meteor.user().isWorker(),
|
||||
!Meteor.user() || !Meteor.user().isBoardAdmin(),
|
||||
// Not disable drag-dropping while in multi-selection mode
|
||||
// MultiSelection.isActive() || !userIsMember(),
|
||||
!ReactiveCache.getCurrentUser()?.isBoardAdmin(),
|
||||
);
|
||||
}
|
||||
});
|
||||
@@ -182,7 +170,7 @@ BlazeComponent.extendComponent({
|
||||
.parentComponent()
|
||||
.data()._id;
|
||||
const cards = list.cards(swimlaneId);
|
||||
if (cards.count() === 0) {
|
||||
if (cards.length === 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -239,7 +227,7 @@ BlazeComponent.extendComponent({
|
||||
|
||||
BlazeComponent.extendComponent({
|
||||
onCreated() {
|
||||
this.currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
this.currentBoard = Utils.getCurrentBoard();
|
||||
this.isListTemplatesSwimlane =
|
||||
this.currentBoard.isTemplatesBoard() &&
|
||||
this.currentData().isListTemplatesSwimlane();
|
||||
@@ -257,9 +245,19 @@ 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();
|
||||
let sortIndex = 0
|
||||
if (lastList) {
|
||||
const positionInput = this.find('.list-position-input');
|
||||
const position = positionInput.value.trim();
|
||||
const ret = ReactiveCache.getList({ boardId: Utils.getCurrentBoardId(), _id: position, archived: false })
|
||||
sortIndex = parseInt(JSON.stringify(ret['sort']))
|
||||
sortIndex = sortIndex+1
|
||||
} else {
|
||||
sortIndex = Utils.calculateIndexData(lastList, null).base;
|
||||
}
|
||||
|
||||
if (title) {
|
||||
Lists.insert({
|
||||
title,
|
||||
@@ -284,12 +282,6 @@ BlazeComponent.extendComponent({
|
||||
Template.swimlane.helpers({
|
||||
canSeeAddList() {
|
||||
return Meteor.user().isBoardAdmin();
|
||||
/*
|
||||
Meteor.user() &&
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
*/
|
||||
},
|
||||
});
|
||||
|
||||
@@ -314,7 +306,7 @@ BlazeComponent.extendComponent({
|
||||
.parentComponent()
|
||||
.data()._id;
|
||||
const cards = list.cards(swimlaneId);
|
||||
if (cards.count() === 0) {
|
||||
if (cards.length === 0) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
@@ -340,7 +332,7 @@ class MoveSwimlaneComponent extends BlazeComponent {
|
||||
}
|
||||
|
||||
board() {
|
||||
return Boards.findOne(Session.get('currentBoard'));
|
||||
return Utils.getCurrentBoard();
|
||||
}
|
||||
|
||||
toBoardsSelector() {
|
||||
@@ -353,14 +345,14 @@ class MoveSwimlaneComponent extends BlazeComponent {
|
||||
}
|
||||
|
||||
toBoards() {
|
||||
return Boards.find(this.toBoardsSelector(), { sort: { title: 1 } });
|
||||
const ret = ReactiveCache.getBoards(this.toBoardsSelector(), { sort: { title: 1 } });
|
||||
return ret;
|
||||
}
|
||||
|
||||
events() {
|
||||
return [
|
||||
{
|
||||
'click .js-done'() {
|
||||
// const swimlane = Swimlanes.findOne(this.currentSwimlane._id);
|
||||
const bSelect = $('.js-select-boards')[0];
|
||||
let boardId;
|
||||
if (bSelect) {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import Cards from '/models/cards';
|
||||
import Avatars from '/models/avatars';
|
||||
import Users from '/models/users';
|
||||
@@ -6,7 +7,7 @@ import Team from '/models/team';
|
||||
|
||||
Template.userAvatar.helpers({
|
||||
userData() {
|
||||
return Users.findOne(this.userId, {
|
||||
return ReactiveCache.getUser(this.userId, {
|
||||
fields: {
|
||||
profile: 1,
|
||||
username: 1,
|
||||
@@ -15,13 +16,13 @@ Template.userAvatar.helpers({
|
||||
},
|
||||
|
||||
memberType() {
|
||||
const user = Users.findOne(this.userId);
|
||||
const user = ReactiveCache.getUser(this.userId);
|
||||
return user && user.isBoardAdmin() ? 'admin' : 'normal';
|
||||
},
|
||||
|
||||
/*
|
||||
presenceStatusClassName() {
|
||||
const user = Users.findOne(this.userId);
|
||||
const user = ReactiveCache.getUser(this.userId);
|
||||
const userPresence = presences.findOne({ userId: this.userId });
|
||||
if (user && user.isInvitedTo(Session.get('currentBoard'))) return 'pending';
|
||||
else if (!userPresence) return 'disconnected';
|
||||
@@ -35,12 +36,12 @@ Template.userAvatar.helpers({
|
||||
|
||||
Template.userAvatarInitials.helpers({
|
||||
initials() {
|
||||
const user = Users.findOne(this.userId);
|
||||
const user = ReactiveCache.getUser(this.userId);
|
||||
return user && user.getInitials();
|
||||
},
|
||||
|
||||
viewPortWidth() {
|
||||
const user = Users.findOne(this.userId);
|
||||
const user = ReactiveCache.getUser(this.userId);
|
||||
return ((user && user.getInitials().length) || 1) * 12;
|
||||
},
|
||||
});
|
||||
@@ -88,21 +89,18 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.boardOrgRow.helpers({
|
||||
orgData() {
|
||||
return Org.findOne(this.orgId);
|
||||
},
|
||||
currentUser(){
|
||||
return Meteor.user();
|
||||
return ReactiveCache.getOrg(this.orgId);
|
||||
},
|
||||
});
|
||||
|
||||
Template.boardOrgName.helpers({
|
||||
orgName() {
|
||||
const org = Org.findOne(this.orgId);
|
||||
const org = ReactiveCache.getOrg(this.orgId);
|
||||
return org && org.orgDisplayName;
|
||||
},
|
||||
|
||||
orgViewPortWidth() {
|
||||
const org = Org.findOne(this.orgId);
|
||||
const org = ReactiveCache.getOrg(this.orgId);
|
||||
return ((org && org.orgDisplayName.length) || 1) * 12;
|
||||
},
|
||||
});
|
||||
@@ -150,21 +148,18 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.boardTeamRow.helpers({
|
||||
teamData() {
|
||||
return Team.findOne(this.teamId);
|
||||
},
|
||||
currentUser(){
|
||||
return Meteor.user();
|
||||
return ReactiveCache.getTeam(this.teamId);
|
||||
},
|
||||
});
|
||||
|
||||
Template.boardTeamName.helpers({
|
||||
teamName() {
|
||||
const team = Team.findOne(this.teamId);
|
||||
const team = ReactiveCache.getTeam(this.teamId);
|
||||
return team && team.teamDisplayName;
|
||||
},
|
||||
|
||||
teamViewPortWidth() {
|
||||
const team = Team.findOne(this.teamId);
|
||||
const team = ReactiveCache.getTeam(this.teamId);
|
||||
return ((team && team.teamDisplayName.length) || 1) * 12;
|
||||
},
|
||||
});
|
||||
@@ -177,24 +172,25 @@ BlazeComponent.extendComponent({
|
||||
},
|
||||
|
||||
uploadedAvatars() {
|
||||
return Avatars.find({ userId: Meteor.userId() }).each();
|
||||
const ret = ReactiveCache.getAvatars({ userId: Meteor.userId() }, {}, true).each();
|
||||
return ret;
|
||||
},
|
||||
|
||||
isSelected() {
|
||||
const userProfile = Meteor.user().profile;
|
||||
const userProfile = ReactiveCache.getCurrentUser().profile;
|
||||
const avatarUrl = userProfile && userProfile.avatarUrl;
|
||||
const currentAvatarUrl = `${this.currentData().link()}?auth=false&brokenIsFine=true`;
|
||||
return avatarUrl === currentAvatarUrl;
|
||||
},
|
||||
|
||||
noAvatarUrl() {
|
||||
const userProfile = Meteor.user().profile;
|
||||
const userProfile = ReactiveCache.getCurrentUser().profile;
|
||||
const avatarUrl = userProfile && userProfile.avatarUrl;
|
||||
return !avatarUrl;
|
||||
},
|
||||
|
||||
setAvatar(avatarUrl) {
|
||||
Meteor.user().setAvatarUrl(avatarUrl);
|
||||
ReactiveCache.getCurrentUser().setAvatarUrl(avatarUrl);
|
||||
},
|
||||
|
||||
setError(error) {
|
||||
@@ -248,7 +244,7 @@ Template.cardMembersPopup.helpers({
|
||||
},
|
||||
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
});
|
||||
|
||||
@@ -263,13 +259,13 @@ Template.cardMembersPopup.events({
|
||||
|
||||
Template.cardMemberPopup.helpers({
|
||||
user() {
|
||||
return Users.findOne(this.userId);
|
||||
return ReactiveCache.getUser(this.userId);
|
||||
},
|
||||
});
|
||||
|
||||
Template.cardMemberPopup.events({
|
||||
'click .js-remove-member'() {
|
||||
Cards.findOne(this.cardId).unassignMember(this.userId);
|
||||
ReactiveCache.getCard(this.cardId).unassignMember(this.userId);
|
||||
Popup.back();
|
||||
},
|
||||
'click .js-edit-profile': Popup.open('editProfile'),
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
Template.headerUserBar.events({
|
||||
@@ -13,27 +14,27 @@ BlazeComponent.extendComponent({
|
||||
|
||||
Template.memberMenuPopup.helpers({
|
||||
templatesBoardId() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return Meteor.user().getTemplatesBoardId();
|
||||
return currentUser.getTemplatesBoardId();
|
||||
} else {
|
||||
// No need to getTemplatesBoardId on public board
|
||||
return false;
|
||||
}
|
||||
},
|
||||
templatesBoardSlug() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return Meteor.user().getTemplatesBoardSlug();
|
||||
return currentUser.getTemplatesBoardSlug();
|
||||
} else {
|
||||
// No need to getTemplatesBoardSlug() on public board
|
||||
return false;
|
||||
}
|
||||
},
|
||||
isSameDomainNameSettingValue(){
|
||||
const currSett = Settings.findOne();
|
||||
const currSett = ReactiveCache.getCurrentSetting();
|
||||
if(currSett && currSett != undefined && currSett.disableRegistration && currSett.mailDomainName !== undefined && currSett.mailDomainName != ""){
|
||||
currentUser = Meteor.user();
|
||||
currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
let found = false;
|
||||
for(let i = 0; i < currentUser.emails.length; i++) {
|
||||
@@ -51,7 +52,7 @@ Template.memberMenuPopup.helpers({
|
||||
return false;
|
||||
},
|
||||
isNotOAuth2AuthenticationMethod(){
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return currentUser.authenticationMethod.toLowerCase() != 'oauth2';
|
||||
} else {
|
||||
@@ -140,12 +141,6 @@ Template.invitePeoplePopup.events({
|
||||
},
|
||||
});
|
||||
|
||||
Template.invitePeoplePopup.helpers({
|
||||
currentSetting() {
|
||||
return Settings.findOne();
|
||||
},
|
||||
});
|
||||
|
||||
Template.editProfilePopup.helpers({
|
||||
allowEmailChange() {
|
||||
Meteor.call('AccountSettings.allowEmailChange', (_, result) => {
|
||||
@@ -191,9 +186,9 @@ Template.editProfilePopup.events({
|
||||
'profile.initials': initials,
|
||||
},
|
||||
});
|
||||
isChangeUserName = username !== Meteor.user().username;
|
||||
isChangeUserName = username !== ReactiveCache.getCurrentUser().username;
|
||||
isChangeEmail =
|
||||
email.toLowerCase() !== Meteor.user().emails[0].address.toLowerCase();
|
||||
email.toLowerCase() !== ReactiveCache.getCurrentUser().emails[0].address.toLowerCase();
|
||||
if (isChangeUserName && isChangeEmail) {
|
||||
Meteor.call(
|
||||
'setUsernameAndEmail',
|
||||
@@ -288,7 +283,7 @@ Template.changeLanguagePopup.events({
|
||||
|
||||
Template.changeSettingsPopup.helpers({
|
||||
hiddenSystemMessages() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).hasHiddenSystemMessages;
|
||||
} else if (window.localStorage.getItem('hasHiddenSystemMessages')) {
|
||||
@@ -298,7 +293,7 @@ Template.changeSettingsPopup.helpers({
|
||||
}
|
||||
},
|
||||
rescueCardDescription() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).rescueCardDescription;
|
||||
} else if (window.localStorage.getItem('rescueCardDescription')) {
|
||||
@@ -308,9 +303,9 @@ Template.changeSettingsPopup.helpers({
|
||||
}
|
||||
},
|
||||
showCardsCountAt() {
|
||||
currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return Meteor.user().getLimitToShowCardsCount();
|
||||
return currentUser.getLimitToShowCardsCount();
|
||||
} else {
|
||||
return window.localStorage.getItem('limitToShowCardsCount');
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { Blaze } from 'meteor/blaze';
|
||||
import { Session } from 'meteor/session';
|
||||
import moment from 'moment/min/moment-with-locales';
|
||||
@@ -13,15 +14,21 @@ Blaze.registerHelper('currentCard', () => {
|
||||
});
|
||||
|
||||
Blaze.registerHelper('currentList', () => {
|
||||
const listId = Session.get('currentList');
|
||||
if (listId) {
|
||||
return Lists.findOne(listId);
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
const ret = Utils.getCurrentList();
|
||||
return ret;
|
||||
});
|
||||
|
||||
Blaze.registerHelper('getUser', userId => Users.findOne(userId));
|
||||
Blaze.registerHelper('currentSetting', () => {
|
||||
const ret = ReactiveCache.getCurrentSetting();
|
||||
return ret;
|
||||
});
|
||||
|
||||
Blaze.registerHelper('currentUser', () => {
|
||||
const ret = ReactiveCache.getCurrentUser();
|
||||
return ret;
|
||||
});
|
||||
|
||||
Blaze.registerHelper('getUser', userId => ReactiveCache.getUser(userId));
|
||||
|
||||
Blaze.registerHelper('concat', (...args) => args.slice(0, -1).join(''));
|
||||
|
||||
@@ -42,3 +49,11 @@ Blaze.registerHelper('moment', (...args) => {
|
||||
const [date, format] = args;
|
||||
return moment(date).format(format);
|
||||
});
|
||||
|
||||
Blaze.registerHelper('canModifyCard', () =>
|
||||
Utils.canModifyCard(),
|
||||
);
|
||||
|
||||
Blaze.registerHelper('canModifyBoard', () =>
|
||||
Utils.canModifyBoard(),
|
||||
);
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import Cards from '../../models/cards';
|
||||
import SessionData from '../../models/usersessiondata';
|
||||
@@ -61,8 +62,8 @@ export class CardSearchPagedComponent extends BlazeComponent {
|
||||
}
|
||||
|
||||
getSessionData(sessionId) {
|
||||
return SessionData.findOne({
|
||||
sessionId: sessionId ? sessionId : SessionData.getSessionId(),
|
||||
return ReactiveCache.getSessionData({
|
||||
sessionId: sessionId || SessionData.getSessionId(),
|
||||
});
|
||||
}
|
||||
|
||||
@@ -74,7 +75,7 @@ export class CardSearchPagedComponent extends BlazeComponent {
|
||||
console.log('session data:', this.sessionData);
|
||||
const cards = [];
|
||||
this.sessionData.cards.forEach(cardId => {
|
||||
cards.push(Cards.findOne({ _id: cardId }));
|
||||
cards.push(ReactiveCache.getCard(cardId));
|
||||
});
|
||||
this.queryErrors = this.sessionData.errors;
|
||||
if (this.queryErrors.length) {
|
||||
@@ -168,7 +169,7 @@ export class CardSearchPagedComponent extends BlazeComponent {
|
||||
} else if (this.resultsCount === 1) {
|
||||
return TAPi18n.__('one-card-found');
|
||||
} else if (this.resultsCount === this.totalHits) {
|
||||
return TAPi18n.__('n-cards-found').replace('%s', this.resultsCount);
|
||||
return TAPi18n.__('n-cards-found', {sprintf: [this.resultsCount]});
|
||||
}
|
||||
|
||||
return TAPi18n.__('n-n-of-n-cards-found', {
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
import moment from 'moment/min/moment-with-locales';
|
||||
|
||||
@@ -22,7 +23,7 @@ export class DatePicker extends BlazeComponent {
|
||||
}
|
||||
|
||||
startDayOfWeek() {
|
||||
const currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return currentUser.getStartDayOfWeek();
|
||||
} else {
|
||||
|
||||
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
export class DialogWithBoardSwimlaneList extends BlazeComponent {
|
||||
/** returns the card dialog options
|
||||
* @return Object with properties { boardId, swimlaneId, listId }
|
||||
@@ -52,26 +54,26 @@ export class DialogWithBoardSwimlaneList extends BlazeComponent {
|
||||
}
|
||||
}
|
||||
this.getBoardData(this.selectedBoardId.get());
|
||||
if (!this.selectedSwimlaneId.get() || !Swimlanes.findOne({_id: this.selectedSwimlaneId.get(), boardId: this.selectedBoardId.get()})) {
|
||||
if (!this.selectedSwimlaneId.get() || !ReactiveCache.getSwimlane({_id: this.selectedSwimlaneId.get(), boardId: this.selectedBoardId.get()})) {
|
||||
this.setFirstSwimlaneId();
|
||||
}
|
||||
if (!this.selectedListId.get() || !Lists.findOne({_id: this.selectedListId.get(), boardId: this.selectedBoardId.get()})) {
|
||||
if (!this.selectedListId.get() || !ReactiveCache.getList({_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;
|
||||
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
|
||||
const swimlaneId = board.swimlanes()[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;
|
||||
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
|
||||
const listId = board.lists()[0]._id;
|
||||
this.selectedListId.set(listId);
|
||||
} catch (e) {}
|
||||
}
|
||||
@@ -105,11 +107,11 @@ export class DialogWithBoardSwimlaneList extends BlazeComponent {
|
||||
|
||||
/** returns all available board */
|
||||
boards() {
|
||||
const ret = Boards.find(
|
||||
const ret = ReactiveCache.getBoards(
|
||||
{
|
||||
archived: false,
|
||||
'members.userId': Meteor.userId(),
|
||||
_id: { $ne: Meteor.user().getTemplatesBoardId() },
|
||||
_id: { $ne: ReactiveCache.getCurrentUser().getTemplatesBoardId() },
|
||||
},
|
||||
{
|
||||
sort: { sort: 1 },
|
||||
@@ -120,14 +122,14 @@ export class DialogWithBoardSwimlaneList extends BlazeComponent {
|
||||
|
||||
/** returns all available swimlanes of the current board */
|
||||
swimlanes() {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
|
||||
const ret = board.swimlanes();
|
||||
return ret;
|
||||
}
|
||||
|
||||
/** returns all available lists of the current board */
|
||||
lists() {
|
||||
const board = Boards.findOne(this.selectedBoardId.get());
|
||||
const board = ReactiveCache.getBoard(this.selectedBoardId.get());
|
||||
const ret = board.lists();
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { DialogWithBoardSwimlaneList } from '/client/lib/dialogWithBoardSwimlaneList';
|
||||
|
||||
export class DialogWithBoardSwimlaneListCard extends DialogWithBoardSwimlaneList {
|
||||
@@ -22,7 +23,7 @@ export class DialogWithBoardSwimlaneListCard extends DialogWithBoardSwimlaneList
|
||||
|
||||
/** returns all available cards of the current list */
|
||||
cards() {
|
||||
const list = Lists.findOne(this.selectedListId.get());
|
||||
const list = ReactiveCache.getList(this.selectedListId.get());
|
||||
let ret = [];
|
||||
if (list) {
|
||||
ret = list.cards(this.selectedSwimlaneId.get());
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import moment from 'moment/min/moment-with-locales';
|
||||
|
||||
// Filtered view manager
|
||||
@@ -107,7 +108,7 @@ class DateFilter {
|
||||
// preferred starting day of the week. This date should be added
|
||||
// to the moment start of week to get the real start of week date.
|
||||
// The default is 1, meaning Monday.
|
||||
const currentUser = Meteor.user();
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
const weekStartDay = currentUser ? currentUser.getStartDayOfWeek() : 1;
|
||||
|
||||
if (week === 'this') {
|
||||
@@ -118,7 +119,7 @@ class DateFilter {
|
||||
.add(weekStartDay, 'days');
|
||||
var WeekEnd = WeekStart
|
||||
.clone()
|
||||
.add(offset, 'week')
|
||||
.add(6, 'days')
|
||||
.endOf('day');
|
||||
|
||||
this._updateState('thisweek');
|
||||
@@ -130,7 +131,7 @@ class DateFilter {
|
||||
.add(weekStartDay + 7, 'days');
|
||||
var WeekEnd = WeekStart
|
||||
.clone()
|
||||
.add(offset, 'week')
|
||||
.add(6, 'days')
|
||||
.endOf('day');
|
||||
|
||||
this._updateState('nextweek');
|
||||
@@ -371,14 +372,14 @@ class AdvancedFilter {
|
||||
}
|
||||
|
||||
_fieldNameToId(field) {
|
||||
const found = CustomFields.findOne({
|
||||
const found = ReactiveCache.getCustomField({
|
||||
name: field,
|
||||
});
|
||||
return found._id;
|
||||
}
|
||||
|
||||
_fieldValueToId(field, value) {
|
||||
const found = CustomFields.findOne({
|
||||
const found = ReactiveCache.getCustomField({
|
||||
name: field,
|
||||
});
|
||||
if (
|
||||
|
||||
+14
-2
@@ -1,11 +1,23 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
import { TAPi18n } from '/imports/i18n';
|
||||
|
||||
// We save the user language preference in the user profile, and use that to set
|
||||
// the language reactively. If the user is not connected we use the language
|
||||
// information provided by the browser, and default to english.
|
||||
|
||||
Meteor.startup(() => {
|
||||
const currentUser = Meteor.user();
|
||||
Meteor.startup(async () => {
|
||||
let currentUser = ReactiveCache.getCurrentUser();
|
||||
// If we're still logging in, wait (#4967)
|
||||
if (!currentUser && Meteor.loggingIn()) {
|
||||
await new Promise((resolve) => {
|
||||
Tracker.autorun(() => {
|
||||
if (!Meteor.loggingIn()) {
|
||||
resolve();
|
||||
}
|
||||
});
|
||||
});
|
||||
currentUser = ReactiveCache.getCurrentUser();
|
||||
}
|
||||
// Select first available language
|
||||
const [language] = [
|
||||
// User profile
|
||||
|
||||
Vendored
+1
-1
@@ -17,4 +17,4 @@ require('jquery-ui/ui/widgets/draggable')
|
||||
require('jquery-ui/ui/widgets/droppable')
|
||||
|
||||
// enable touch on mobile
|
||||
require('jquery-ui-touch-punch')
|
||||
require('@rwap/jquery-ui-touch-punch')
|
||||
+13
-15
@@ -1,3 +1,5 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
// XXX There is no reason to define these shortcuts globally, they should be
|
||||
// attached to a template (most of them will go in the `board` template).
|
||||
|
||||
@@ -76,14 +78,14 @@ Mousetrap.bind(numbArray, (evt, key) => {
|
||||
return;
|
||||
}
|
||||
const currentBoardId = Session.get('currentBoard');
|
||||
board = Boards.findOne(currentBoardId);
|
||||
board = ReactiveCache.getBoard(currentBoardId);
|
||||
labels = board.labels;
|
||||
if(MultiSelection.isActive())
|
||||
{
|
||||
const cardIds = MultiSelection.getSelectedCardIds();
|
||||
for (const cardId of cardIds)
|
||||
{
|
||||
card = Cards.findOne(cardId);
|
||||
card = ReactiveCache.getCard(cardId);
|
||||
if(num <= board.labels.length)
|
||||
{
|
||||
card.removeLabel(labels[num-1]["_id"]);
|
||||
@@ -100,14 +102,14 @@ Mousetrap.bind(numArray, (evt, key) => {
|
||||
if (currentUserId === null) {
|
||||
return;
|
||||
}
|
||||
board = Boards.findOne(currentBoardId);
|
||||
board = ReactiveCache.getBoard(currentBoardId);
|
||||
labels = board.labels;
|
||||
if(MultiSelection.isActive() && Meteor.user().isBoardMember())
|
||||
if(MultiSelection.isActive() && ReactiveCache.getCurrentUser().isBoardMember())
|
||||
{
|
||||
const cardIds = MultiSelection.getSelectedCardIds();
|
||||
for (const cardId of cardIds)
|
||||
{
|
||||
card = Cards.findOne(cardId);
|
||||
card = ReactiveCache.getCard(cardId);
|
||||
if(num <= board.labels.length)
|
||||
{
|
||||
card.addLabel(labels[num-1]["_id"]);
|
||||
@@ -120,8 +122,8 @@ Mousetrap.bind(numArray, (evt, key) => {
|
||||
if (!cardId) {
|
||||
return;
|
||||
}
|
||||
if (Meteor.user().isBoardMember()) {
|
||||
const card = Cards.findOne(cardId);
|
||||
if (ReactiveCache.getCurrentUser().isBoardMember()) {
|
||||
const card = ReactiveCache.getCard(cardId);
|
||||
if(num <= board.labels.length)
|
||||
{
|
||||
card.toggleLabel(labels[num-1]["_id"]);
|
||||
@@ -140,8 +142,8 @@ Mousetrap.bind('space', evt => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (Meteor.user().isBoardMember()) {
|
||||
const card = Cards.findOne(cardId);
|
||||
if (ReactiveCache.getCurrentUser().isBoardMember()) {
|
||||
const card = ReactiveCache.getCard(cardId);
|
||||
card.toggleMember(currentUserId);
|
||||
// We should prevent scrolling in card when spacebar is clicked
|
||||
// This should do it according to Mousetrap docs, but it doesn't
|
||||
@@ -160,12 +162,8 @@ Mousetrap.bind('c', evt => {
|
||||
return;
|
||||
}
|
||||
|
||||
if (
|
||||
Meteor.user().isBoardMember() &&
|
||||
!Meteor.user().isCommentOnly() &&
|
||||
!Meteor.user().isWorker()
|
||||
) {
|
||||
const card = Cards.findOne(cardId);
|
||||
if (Utils.canModifyBoard()) {
|
||||
const card = ReactiveCache.getCard(cardId);
|
||||
card.archive();
|
||||
// We should prevent scrolling in card when spacebar is clicked
|
||||
// This should do it according to Mousetrap docs, but it doesn't
|
||||
|
||||
@@ -1,19 +1,21 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
function getCardsBetween(idA, idB) {
|
||||
function pluckId(doc) {
|
||||
return doc._id;
|
||||
}
|
||||
|
||||
function getListsStrictlyBetween(id1, id2) {
|
||||
return Lists.find({
|
||||
return ReactiveCache.getLists({
|
||||
$and: [
|
||||
{ sort: { $gt: Lists.findOne(id1).sort } },
|
||||
{ sort: { $lt: Lists.findOne(id2).sort } },
|
||||
{ sort: { $gt: ReactiveCache.getList(id1).sort } },
|
||||
{ sort: { $lt: ReactiveCache.getList(id2).sort } },
|
||||
],
|
||||
archived: false,
|
||||
}).map(pluckId);
|
||||
}
|
||||
|
||||
const cards = _.sortBy([Cards.findOne(idA), Cards.findOne(idB)], c => {
|
||||
const cards = _.sortBy([ReactiveCache.getCard(idA), ReactiveCache.getCard(idB)], c => {
|
||||
return c.sort;
|
||||
});
|
||||
|
||||
@@ -48,7 +50,7 @@ function getCardsBetween(idA, idB) {
|
||||
};
|
||||
}
|
||||
|
||||
return Cards.find(Filter.mongoSelector(selector)).map(pluckId);
|
||||
return ReactiveCache.getCards(Filter.mongoSelector(selector)).map(pluckId);
|
||||
}
|
||||
|
||||
MultiSelection = {
|
||||
@@ -77,7 +79,7 @@ MultiSelection = {
|
||||
},
|
||||
|
||||
count() {
|
||||
return Cards.find(this.getMongoSelector()).count();
|
||||
return ReactiveCache.getCards(this.getMongoSelector()).length;
|
||||
},
|
||||
|
||||
isEmpty() {
|
||||
|
||||
@@ -76,6 +76,14 @@ window.Popup = new (class {
|
||||
dataContext: (this && this.currentData && this.currentData()) || (options && options.dataContextIfCurrentDataIsUndefined) || this,
|
||||
});
|
||||
|
||||
const $contentWrapper = $('.content-wrapper')
|
||||
if ($contentWrapper.length > 0) {
|
||||
const contentWrapper = $contentWrapper[0];
|
||||
self._getTopStack().scrollTop = contentWrapper.scrollTop;
|
||||
// scroll from e.g. delete comment to the top (where the confirm button is)
|
||||
$contentWrapper.scrollTop(0);
|
||||
}
|
||||
|
||||
// If there are no popup currently opened we use the Blaze API to render
|
||||
// one into the DOM. We use a reactive function as the data parameter that
|
||||
// return the complete along with its top element and depends on our
|
||||
@@ -129,6 +137,21 @@ window.Popup = new (class {
|
||||
/// steps back is greater than the popup stack size, the popup will be closed.
|
||||
back(n = 1) {
|
||||
if (this._stack.length > n) {
|
||||
const $contentWrapper = $('.content-wrapper')
|
||||
if ($contentWrapper.length > 0) {
|
||||
const contentWrapper = $contentWrapper[0];
|
||||
const stack = this._stack[this._stack.length - n];
|
||||
// scrollTopMax and scrollLeftMax only available at Firefox (https://developer.mozilla.org/en-US/docs/Web/API/Element/scrollTopMax)
|
||||
const scrollTopMax = contentWrapper.scrollTopMax || contentWrapper.scrollHeight - contentWrapper.clientHeight;
|
||||
if (scrollTopMax && stack.scrollTop > scrollTopMax) {
|
||||
// sometimes scrollTopMax is lower than scrollTop, so i need this dirty hack
|
||||
setTimeout(() => {
|
||||
$contentWrapper.scrollTop(stack.scrollTop);
|
||||
}, 6);
|
||||
}
|
||||
// restore the old popup scroll position
|
||||
$contentWrapper.scrollTop(stack.scrollTop);
|
||||
}
|
||||
_.times(n, () => this._stack.pop());
|
||||
this._dep.changed();
|
||||
} else {
|
||||
|
||||
@@ -1,19 +1,17 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
Meteor.subscribe('setting');
|
||||
|
||||
import { ALLOWED_WAIT_SPINNERS } from '/config/const';
|
||||
|
||||
export class Spinner extends BlazeComponent {
|
||||
currentSettings() {
|
||||
return Settings.findOne();
|
||||
}
|
||||
|
||||
getSpinnerName() {
|
||||
let ret = 'Bounce';
|
||||
let defaultWaitSpinner = Meteor.settings.public.WAIT_SPINNER;
|
||||
if (defaultWaitSpinner && ALLOWED_WAIT_SPINNERS.includes(defaultWaitSpinner)) {
|
||||
ret = defaultWaitSpinner;
|
||||
}
|
||||
let settings = this.currentSettings();
|
||||
let settings = ReactiveCache.getCurrentSetting();
|
||||
|
||||
if (settings && settings.spinnerName) {
|
||||
ret = settings.spinnerName;
|
||||
|
||||
+102
-50
@@ -1,4 +1,15 @@
|
||||
import { ReactiveCache } from '/imports/reactiveCache';
|
||||
|
||||
Utils = {
|
||||
setBackgroundImage(url) {
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
if (currentBoard.backgroundImageURL !== undefined) {
|
||||
$(".board-wrapper,.board-wrapper .board-canvas").css({"background":"url(" + currentBoard.backgroundImageURL + ")","background-size":"cover"});
|
||||
$(".swimlane,.swimlane .list,.swimlane .list .list-body,.swimlane .list:first-child .list-body").css({"background-color":"transparent"});
|
||||
} else if (currentBoard.color !== undefined) {
|
||||
currentBoard.setColor(currentBoard.color);
|
||||
}
|
||||
},
|
||||
/** returns the current board id
|
||||
* <li> returns the current board id or the board id of the popup card if set
|
||||
*/
|
||||
@@ -22,22 +33,53 @@ Utils = {
|
||||
const ret = Session.get('popupCardId');
|
||||
return ret;
|
||||
},
|
||||
getCurrentListId() {
|
||||
const ret = Session.get('currentList');
|
||||
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);
|
||||
const ret = ReactiveCache.getBoard(boardId);
|
||||
return ret;
|
||||
},
|
||||
getCurrentCard(ignorePopupCard) {
|
||||
const cardId = Utils.getCurrentCardId(ignorePopupCard);
|
||||
const ret = Cards.findOne(cardId);
|
||||
const ret = ReactiveCache.getCard(cardId);
|
||||
return ret;
|
||||
},
|
||||
getCurrentList() {
|
||||
const listId = this.getCurrentListId();
|
||||
let ret = null;
|
||||
if (listId) {
|
||||
ret = ReactiveCache.getList(listId);
|
||||
}
|
||||
return ret;
|
||||
},
|
||||
getPopupCard() {
|
||||
const cardId = Utils.getPopupCardId();
|
||||
const ret = Cards.findOne(cardId);
|
||||
const ret = ReactiveCache.getCard(cardId);
|
||||
return ret;
|
||||
},
|
||||
canModifyCard() {
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
const ret = (
|
||||
currentUser &&
|
||||
currentUser.isBoardMember() &&
|
||||
!currentUser.isCommentOnly() &&
|
||||
!currentUser.isWorker()
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
canModifyBoard() {
|
||||
const currentUser = ReactiveCache.getCurrentUser();
|
||||
const ret = (
|
||||
currentUser &&
|
||||
currentUser.isBoardMember() &&
|
||||
!currentUser.isCommentOnly()
|
||||
);
|
||||
return ret;
|
||||
},
|
||||
reload() {
|
||||
@@ -48,9 +90,9 @@ Utils = {
|
||||
window.location.reload();
|
||||
},
|
||||
setBoardView(view) {
|
||||
currentUser = Meteor.user();
|
||||
currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
Meteor.user().setBoardView(view);
|
||||
ReactiveCache.getCurrentUser().setBoardView(view);
|
||||
} else if (view === 'board-view-swimlanes') {
|
||||
window.localStorage.setItem('boardView', 'board-view-swimlanes'); //true
|
||||
Utils.reload();
|
||||
@@ -72,7 +114,7 @@ Utils = {
|
||||
},
|
||||
|
||||
boardView() {
|
||||
currentUser = Meteor.user();
|
||||
currentUser = ReactiveCache.getCurrentUser();
|
||||
if (currentUser) {
|
||||
return (currentUser.profile || {}).boardView;
|
||||
} else if (
|
||||
@@ -116,11 +158,8 @@ Utils = {
|
||||
},
|
||||
|
||||
archivedBoardIds() {
|
||||
const archivedBoards = [];
|
||||
Boards.find({ archived: false }).forEach(board => {
|
||||
archivedBoards.push(board._id);
|
||||
});
|
||||
return archivedBoards;
|
||||
const ret = ReactiveCache.getBoards({ archived: false }).map(board => board._id);
|
||||
return ret;
|
||||
},
|
||||
|
||||
dueCardsView() {
|
||||
@@ -155,7 +194,7 @@ Utils = {
|
||||
|
||||
// XXX We should remove these two methods
|
||||
goBoardId(_id) {
|
||||
const board = Boards.findOne(_id);
|
||||
const board = ReactiveCache.getBoard(_id);
|
||||
return (
|
||||
board &&
|
||||
FlowRouter.go('board', {
|
||||
@@ -166,8 +205,8 @@ Utils = {
|
||||
},
|
||||
|
||||
goCardId(_id) {
|
||||
const card = Cards.findOne(_id);
|
||||
const board = Boards.findOne(card.boardId);
|
||||
const card = ReactiveCache.getCard(_id);
|
||||
const board = ReactiveCache.getBoard(card.boardId);
|
||||
return (
|
||||
board &&
|
||||
FlowRouter.go('card', {
|
||||
@@ -180,7 +219,7 @@ Utils = {
|
||||
getCommonAttachmentMetaFrom(card) {
|
||||
const meta = {};
|
||||
if (card.isLinkedCard()) {
|
||||
meta.boardId = Cards.findOne(card.linkedId).boardId;
|
||||
meta.boardId = ReactiveCache.getCard(card.linkedId).boardId;
|
||||
meta.cardId = card.linkedId;
|
||||
} else {
|
||||
meta.boardId = card.boardId;
|
||||
@@ -288,7 +327,7 @@ Utils = {
|
||||
|
||||
// returns if desktop drag handles are enabled
|
||||
isShowDesktopDragHandles() {
|
||||
//const currentUser = Meteor.user();
|
||||
//const currentUser = ReactiveCache.getCurrentUser();
|
||||
//if (currentUser) {
|
||||
// return (currentUser.profile || {}).showDesktopDragHandles;
|
||||
//} else if (window.localStorage.getItem('showDesktopDragHandles')) {
|
||||
@@ -313,20 +352,51 @@ Utils = {
|
||||
increment = 1;
|
||||
// If we drop the card in the first position
|
||||
} else if (!prevData) {
|
||||
base = nextData.sort - 1;
|
||||
increment = -1;
|
||||
const nextSortIndex = nextData.sort;
|
||||
const ceil = Math.ceil(nextSortIndex - 1);
|
||||
if (ceil < nextSortIndex) {
|
||||
increment = nextSortIndex - ceil;
|
||||
base = nextSortIndex - increment;
|
||||
} else {
|
||||
base = nextData.sort - 1;
|
||||
increment = -1;
|
||||
}
|
||||
// If we drop the card in the last position
|
||||
} else if (!nextData) {
|
||||
base = prevData.sort + 1;
|
||||
increment = 1;
|
||||
const prevSortIndex = prevData.sort;
|
||||
const floor = Math.floor(prevSortIndex + 1);
|
||||
if (floor > prevSortIndex) {
|
||||
increment = prevSortIndex - floor;
|
||||
base = prevSortIndex - increment;
|
||||
} else {
|
||||
base = prevData.sort + 1;
|
||||
increment = 1;
|
||||
}
|
||||
}
|
||||
// In the general case take the average of the previous and next element
|
||||
// sort indexes.
|
||||
else {
|
||||
const prevSortIndex = prevData.sort;
|
||||
const nextSortIndex = nextData.sort;
|
||||
increment = (nextSortIndex - prevSortIndex) / (nItems + 1);
|
||||
base = prevSortIndex + increment;
|
||||
if (nItems == 1 ) {
|
||||
if (prevSortIndex < 0 ) {
|
||||
const ceil = Math.ceil(nextSortIndex - 1);
|
||||
if (ceil < nextSortIndex && ceil > prevSortIndex) {
|
||||
increment = ceil - prevSortIndex;
|
||||
}
|
||||
} else {
|
||||
const floor = Math.floor(nextSortIndex - 1);
|
||||
if (floor < nextSortIndex && floor > prevSortIndex) {
|
||||
increment = floor - prevSortIndex;
|
||||
}
|
||||
}
|
||||
}
|
||||
if (!increment) {
|
||||
increment = (nextSortIndex - prevSortIndex) / (nItems + 1);
|
||||
}
|
||||
if (!base) {
|
||||
base = prevSortIndex + increment;
|
||||
}
|
||||
}
|
||||
// XXX Return a generator that yield values instead of a base with a
|
||||
// increment number.
|
||||
@@ -338,34 +408,16 @@ Utils = {
|
||||
|
||||
// Determine the new sort index
|
||||
calculateIndex(prevCardDomElement, nextCardDomElement, nCards = 1) {
|
||||
let base, increment;
|
||||
// If we drop the card to an empty column
|
||||
if (!prevCardDomElement && !nextCardDomElement) {
|
||||
base = 0;
|
||||
increment = 1;
|
||||
// If we drop the card in the first position
|
||||
} else if (!prevCardDomElement) {
|
||||
base = Blaze.getData(nextCardDomElement).sort - 1;
|
||||
increment = -1;
|
||||
// If we drop the card in the last position
|
||||
} else if (!nextCardDomElement) {
|
||||
base = Blaze.getData(prevCardDomElement).sort + 1;
|
||||
increment = 1;
|
||||
let prevData = null;
|
||||
let nextData = null;
|
||||
if (prevCardDomElement) {
|
||||
prevData = Blaze.getData(prevCardDomElement)
|
||||
}
|
||||
// In the general case take the average of the previous and next element
|
||||
// sort indexes.
|
||||
else {
|
||||
const prevSortIndex = Blaze.getData(prevCardDomElement).sort;
|
||||
const nextSortIndex = Blaze.getData(nextCardDomElement).sort;
|
||||
increment = (nextSortIndex - prevSortIndex) / (nCards + 1);
|
||||
base = prevSortIndex + increment;
|
||||
if (nextCardDomElement) {
|
||||
nextData = Blaze.getData(nextCardDomElement);
|
||||
}
|
||||
// XXX Return a generator that yield values instead of a base with a
|
||||
// increment number.
|
||||
return {
|
||||
base,
|
||||
increment,
|
||||
};
|
||||
const ret = Utils.calculateIndexData(prevData, nextData, nCards);
|
||||
return ret;
|
||||
},
|
||||
|
||||
manageCustomUI() {
|
||||
@@ -380,7 +432,7 @@ Utils = {
|
||||
},
|
||||
|
||||
setCustomUI(data) {
|
||||
const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
const currentBoard = Utils.getCurrentBoard();
|
||||
if (currentBoard) {
|
||||
DocHead.setTitle(`${currentBoard.title} - ${data.productName}`);
|
||||
} else {
|
||||
@@ -392,7 +444,7 @@ Utils = {
|
||||
window._paq = window._paq || [];
|
||||
window._paq.push(['setDoNotTrack', data.doNotTrack]);
|
||||
if (data.withUserName) {
|
||||
window._paq.push(['setUserId', Meteor.user().username]);
|
||||
window._paq.push(['setUserId', ReactiveCache.getCurrentUser().username]);
|
||||
}
|
||||
window._paq.push(['trackPageView']);
|
||||
window._paq.push(['enableLinkTracking']);
|
||||
|
||||
@@ -540,12 +540,15 @@ export class Query {
|
||||
}
|
||||
} else if (operator === OPERATOR_LIMIT) {
|
||||
const limit = parseInt(value, 10);
|
||||
if (isNaN(limit) || limit < 1) {
|
||||
if (isNaN(limit) || limit < 0) {
|
||||
this.addError(OPERATOR_LIMIT, {
|
||||
tag: 'operator-limit-invalid',
|
||||
value,
|
||||
});
|
||||
continue;
|
||||
} else if (limit == 0) {
|
||||
// no limit
|
||||
continue;
|
||||
} else {
|
||||
value = limit;
|
||||
}
|
||||
|
||||
+1
-1
@@ -421,7 +421,7 @@ _.each(redirections, (newPath, oldPath) => {
|
||||
//Meteor.isClient && Meteor.startup(() => {
|
||||
// Tracker.autorun(() => {
|
||||
|
||||
// const currentBoard = Boards.findOne(Session.get('currentBoard'));
|
||||
// const currentBoard = Utils.getCurrentBoard();
|
||||
// const titleStack = [appTitle];
|
||||
// if (currentBoard) {
|
||||
// titleStack.push(currentBoard.title);
|
||||
|
||||
+15
-15
@@ -90,14 +90,7 @@ services:
|
||||
|
||||
wekandb:
|
||||
#-------------------------------------------------------------------------------------
|
||||
# ==== MONGODB AND METEOR VERSION ====
|
||||
# a) mongodb latest, like 3.2 - 4.4 or newer https://hub.docker.com/_/mongo?tab=description
|
||||
# 2020-12-03:
|
||||
# - Mongo image copied from Docker Hub mongo:4.4.2-bionic to Quay
|
||||
# to avoid Docker Hub rate limits.
|
||||
# Quay image does work:
|
||||
# image: quay.io/wekan/mongo:4.4.2-bionic
|
||||
# Docker Hub MongoDB image does work:
|
||||
# ==== MONGODB FROM DOCKER HUB ====
|
||||
image: mongo:6
|
||||
#-------------------------------------------------------------------------------------
|
||||
container_name: wekan-db
|
||||
@@ -118,13 +111,20 @@ services:
|
||||
|
||||
wekan:
|
||||
#-------------------------------------------------------------------------------------
|
||||
# ==== MONGODB AND METEOR VERSION ====
|
||||
# a) Quay automatic builds do work work, https://quay.io/wekan/wekan
|
||||
image: quay.io/wekan/wekan
|
||||
# b) Using specific version tag:
|
||||
# image: quay.io/wekan/wekan:v4.52
|
||||
# c) Docker Hub builds do work https://hub.docker.com/r/wekanteam/wekan
|
||||
# image: wekanteam/wekan
|
||||
# ==== WEKAN FROM GITHUB/QUAY/DOCKER HUB ====
|
||||
# All of GitHub, Quay and Docker Hub have latest, but because
|
||||
# latest tag changes when is newest release,
|
||||
# when upgrading would be better to use version tag.
|
||||
# a) Using specific version tag is better:
|
||||
# image: ghcr.io/wekan/wekan:v6.89
|
||||
# image: quay.io/wekan/wekan:v6.89
|
||||
# image: wekanteam/wekan:v6.89
|
||||
# b) GitHub Container registry.
|
||||
image: ghcr.io/wekan/wekan:latest
|
||||
# c) Quay:
|
||||
#image: quay.io/wekan/wekan:latest
|
||||
# d) Docker Hub:
|
||||
#image: wekanteam/wekan:latest
|
||||
#-------------------------------------------------------------------------------------
|
||||
container_name: wekan-app
|
||||
# On CentOS 7 there is seccomp issue with glibc 6,
|
||||
|
||||
+1223
-1203
File diff suppressed because it is too large.
Load diff
File diff suppressed because it is too large.
Load diff
Loaded 100 of 438 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user