Compare commits
314
Commits
0.15.1
..
56c3365656
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
56c3365656
|
||
|
|
e7b2c64798
|
||
|
|
7cb6b63eb9
|
||
|
|
d6d88f5f60
|
||
|
|
2c208c4381
|
||
|
|
39bc6c4945
|
||
|
|
b94e3b745f
|
||
|
|
6f337aeee1
|
||
|
|
5d48060834
|
||
|
|
c842c203e2
|
||
|
|
5bcfc8db75
|
||
|
|
27b4dde755
|
||
|
|
91ab199769
|
||
|
|
e75be49be4
|
||
|
|
505fb8cb08
|
||
|
|
e5c9265588
|
||
|
|
02003ec80e
|
||
|
|
133470b6f2
|
||
|
|
4a6230c439
|
||
|
|
fdc7d80bbf
|
||
|
|
352551e168
|
||
|
|
7aec050419
|
||
|
|
4289034436 | ||
|
|
8f8858f100
|
||
|
|
d98fb0d5b2
|
||
|
|
5014bf5bc5
|
||
|
|
0708cabc75
|
||
|
|
4fcb26cf93
|
||
|
|
269def20d1
|
||
|
|
b8de9e0e42
|
||
|
|
7b2b598588
|
||
|
|
e0b61486b0
|
||
|
|
3f86f7412f
|
||
|
|
6454d960de
|
||
|
|
37154c188b
|
||
|
|
8da7578a0a
|
||
|
|
2a64094006 | ||
|
|
e9ce9644ff | ||
|
|
52439aa5bc
|
||
|
|
ccf865687b
|
||
|
|
cac34db1fd
|
||
|
|
faf3893180
|
||
|
|
c33dfcfddd
|
||
|
|
019e14ab1f
|
||
|
|
b5790196c6
|
||
|
|
94a64ca690
|
||
|
|
a6ce04c903 | ||
|
|
165c154233 | ||
|
|
318547db46
|
||
|
|
e60c09e19c
|
||
|
|
4834d1484c
|
||
|
|
4b6342727e
|
||
|
|
cb5fa52cd9
|
||
|
|
947d01cf7f
|
||
|
|
3563394fb3
|
||
|
|
269d7a7def
|
||
|
|
e95f2333b0
|
||
|
|
950217e0a3
|
||
|
|
5e65fb3301
|
||
|
|
2a294cde04
|
||
|
|
e95420d79c
|
||
|
|
cffbd17dc7
|
||
|
|
00de8c3d75
|
||
|
|
1f4711d07a
|
||
|
|
30e3396897
|
||
|
|
5291e049a1
|
||
|
|
08fbb504c9
|
||
|
|
e9ca1d3e5d
|
||
|
|
eb80406fdb
|
||
|
|
9fe53b0b9c
|
||
|
|
9ae5e62e5d
|
||
|
|
1613ae7de6
|
||
|
|
ed1caa7be7 | ||
|
|
d88f3a5a27 | ||
|
|
c98eb49ae3
|
||
|
|
6d9d8a4724
|
||
|
|
7d8c68a455
|
||
|
|
8f33640bec
|
||
|
|
f89023e24a
|
||
|
|
f5d14f2e18
|
||
|
|
9811ede3b2
|
||
|
|
b2e51fea48
|
||
|
|
2a915620c9
|
||
|
|
526688935f
|
||
|
|
c7dcf7c66d
|
||
|
|
06411dc147
|
||
|
|
195d182cc9
|
||
|
|
17217dae76
|
||
|
|
f105cc0a41
|
||
|
|
2f62c7ae89
|
||
|
|
f6c1fea17c
|
||
|
|
178dc93319
|
||
|
|
8ffe8eff06
|
||
|
|
bd4952ee57
|
||
|
|
4b171fd04f
|
||
|
|
2c198cfde8
|
||
|
|
7c6d39b5fa
|
||
|
|
9c13b2f9e9
|
||
|
|
1ec9556aa6
|
||
|
|
adec38b50b
|
||
|
|
a35af6f020
|
||
|
|
e74ff5e885
|
||
|
|
c87561f63b
|
||
|
|
c681570134
|
||
|
|
53b945c72f
|
||
|
|
f6985daec7
|
||
|
|
5662c3b6da
|
||
|
|
9def0b27c9
|
||
|
|
52a02c82d2
|
||
|
|
c241961d0a
|
||
|
|
8f50555a06
|
||
|
|
b35375c929
|
||
|
|
bf1e715261
|
||
|
|
0240e1dca2
|
||
|
|
7cec2a00c5
|
||
|
|
239f79fecb
|
||
|
|
0265a59b82
|
||
|
|
57dce34fc5
|
||
|
|
d8110580e9
|
||
|
|
03b7ada5ef
|
||
|
|
1df505ea00
|
||
|
|
3e8dac3203
|
||
|
|
95707a71a9
|
||
|
|
fc2c2907c4
|
||
|
|
ebdd1c2c0c
|
||
|
|
13254b24dd
|
||
|
|
e17eb64031
|
||
|
|
a0727a0291
|
||
|
|
f7f7926829
|
||
|
|
9b7dca341b
|
||
|
|
da3300562a
|
||
|
|
e2ddb5a14c
|
||
|
|
fb9645aed6
|
||
|
|
a4ebc7e126
|
||
|
|
fd5db7d68a
|
||
|
|
e7eddb4f08
|
||
|
|
94155845f0
|
||
|
|
3abf608b15
|
||
|
|
d31fe2363b
|
||
|
|
11a56f87e8
|
||
|
|
19793cdcd4
|
||
|
|
9363773fa1
|
||
|
|
c7990882cf
|
||
|
|
d4ab76ea1b
|
||
|
|
2c992a0e63
|
||
|
|
88f96acc3c
|
||
|
|
245db06173
|
||
|
|
49c2cd5c4b
|
||
|
|
64db553185
|
||
|
|
a06a19ce9c
|
||
|
|
592ddc1541
|
||
|
|
cb5f2b73d0
|
||
|
|
2304b12c1c
|
||
|
|
38d3e1912c
|
||
|
|
fbc14fd7b4
|
||
|
|
0283df22c8
|
||
|
|
845737ee8e
|
||
|
|
6993511c67
|
||
|
|
9111ad147c
|
||
|
|
333214aa8f
|
||
|
|
c0cde02fec
|
||
|
|
070a20a2e5
|
||
|
|
c5e8409079
|
||
|
|
67eff0eda9
|
||
|
|
3de7b632e0
|
||
|
|
842248e4c4
|
||
|
|
c5d7ec25b5
|
||
|
|
a9a965d698
|
||
|
|
dc866dd540
|
||
|
|
89252619b1
|
||
|
|
2699b06d7c
|
||
|
|
fd0d45f721
|
||
|
|
5ecf838dd2
|
||
|
|
45a7a90cb8
|
||
|
|
cac851f2b1
|
||
|
|
238082b657
|
||
|
|
aecbabe522
|
||
|
|
a9cdac4f74
|
||
|
|
a59dbbe50e
|
||
|
|
9bec95ede8
|
||
|
|
70307a9e82
|
||
|
|
ef077b4e6a
|
||
|
|
dcabed4e93
|
||
|
|
1af047f66e
|
||
|
|
ee91748b3c
|
||
|
|
e5241d619b
|
||
|
|
d79608edbb
|
||
|
|
4cbd26580e
|
||
|
|
fe62ad5539
|
||
|
|
eb13f038a1
|
||
|
|
9505c2b030 | ||
|
|
008835c24f | ||
|
|
7083b3d8d2 | ||
|
|
754931b2f6 | ||
|
|
2dc8ffba32 | ||
|
|
d0fe6a2e85 | ||
|
|
85705b6e68 | ||
|
|
3ea7a015a9 | ||
|
|
44329413ed | ||
|
|
46db68ab22 | ||
|
|
dc9d7f22a2 | ||
|
|
f917018fd9 | ||
|
|
7b420c430d | ||
|
|
00359d25c1 | ||
|
|
d8a3063735 | ||
|
|
6491af19e3
|
||
|
|
61328d20ed | ||
|
|
0a6d92a1f3
|
||
|
|
3a576d1073
|
||
|
|
b30b98b521
|
||
|
|
43d82a2af0
|
||
|
|
6a4495b813 | ||
|
|
e8a0ad6647
|
||
|
|
92b89cc4d8
|
||
|
|
268b1b1d98
|
||
|
|
75bc89ca30
|
||
|
|
0625937068 | ||
|
|
32a9074963
|
||
|
|
b869b5fd2a
|
||
|
|
3a3e2f7157 | ||
|
|
bea57aa03a | ||
|
|
30991d5364 | ||
|
|
5cc8b0811c | ||
|
|
2c73b9862d | ||
|
|
732b2f061e | ||
|
|
3680533eef | ||
|
|
1307d72c9d | ||
|
|
405dfa0c34 | ||
|
|
5c2d154ad1 | ||
|
|
f2bf8d9bac | ||
|
|
f9cfd6bd06
|
||
|
|
287f63fa52
|
||
|
|
5fe47634e8
|
||
|
|
a6590910cf | ||
|
|
ad454c386c | ||
|
|
0b2c296de0
|
||
|
|
0e85940cba
|
||
|
|
8d479c32f8 | ||
|
|
549785cf7d | ||
|
|
aafc4c8d62
|
||
|
|
47dedbdc73
|
||
|
|
6fe134afc8
|
||
|
|
63a50f92e7
|
||
|
|
ca6da15ef7
|
||
|
|
8dfa19fa0f
|
||
|
|
0feee0ae2f
|
||
|
|
2a6a39916a | ||
|
|
f0a2b2859f
|
||
|
|
32ddb66fc8
|
||
|
|
df63c2388d
|
||
|
|
757655ea63
|
||
|
|
329c1cc037 | ||
|
|
da6dd55d13 | ||
|
|
0e5490f1c8 | ||
|
|
b82d638de1 | ||
|
|
224034dcc6 | ||
|
|
026d3d41c1 | ||
|
|
fd1a06b359 | ||
|
|
452d010183
|
||
|
|
eb1c17e3ac
|
||
|
|
a101873eb0
|
||
|
|
3d2acb692a
|
||
|
|
0900c2691e
|
||
|
|
1337676e08
|
||
|
|
2e075eafab | ||
|
|
14d64b6070 | ||
|
|
81b8fbf4e3 | ||
|
|
24d074752f | ||
|
|
08047a9307 | ||
|
|
1b0cd5b90b | ||
|
|
65e8998894 | ||
|
|
449948050b | ||
|
|
cf97281592 | ||
|
|
75684efa1a | ||
|
|
2c4f27a943 | ||
|
|
53b7dec7cd | ||
|
|
e0cbfb000b
|
||
|
|
3a66f4c862 | ||
|
|
85ceaa464f
|
||
|
|
976755338b
|
||
|
|
1c980059cf
|
||
|
|
2d8c4c1698
|
||
|
|
19a333d7bd
|
||
|
|
96c55db63d
|
||
|
|
fecb07ee37
|
||
|
|
e10c6480a5
|
||
|
|
f3cc07c009
|
||
|
|
068076dd47
|
||
|
|
02158605be
|
||
|
|
674e6a90ec
|
||
|
|
f679330466
|
||
|
|
93fc7c2e83
|
||
|
|
f299617c60
|
||
|
|
28cbc5b98c
|
||
|
|
c28f1ee0bc
|
||
|
|
cff112d705
|
||
|
|
9fc4ad63c4 | ||
|
|
97054a71c1 | ||
|
|
2391668a25
|
||
|
|
717d33547c | ||
|
|
997be32679 | ||
|
|
134f00c40e
|
||
|
|
47c898bdfd
|
||
|
|
e752ee12d1 | ||
|
|
cc4515ff66
|
||
|
|
f190292171 | ||
|
|
b246f2b349
|
||
|
|
76b69d851a | ||
|
|
224f586368 | ||
|
|
9add6c8ff1 | ||
|
|
7a63d4eed1 | ||
|
|
e54a4807f7 | ||
|
|
cee04c1d6f | ||
|
|
cbec78589d |
No files matched your search
+2
-1
@@ -1 +1,2 @@
|
|||||||
public/env.sample.js
|
public/env.sample.js
|
||||||
|
.pnpm-store
|
||||||
+29
-12
@@ -19,6 +19,13 @@ get:
|
|||||||
path: odit-git-bot
|
path: odit-git-bot
|
||||||
name: sshkey
|
name: sshkey
|
||||||
|
|
||||||
|
---
|
||||||
|
kind: secret
|
||||||
|
name: npm_url
|
||||||
|
get:
|
||||||
|
path: odit-npm-cache
|
||||||
|
name: url
|
||||||
|
|
||||||
---
|
---
|
||||||
kind: pipeline
|
kind: pipeline
|
||||||
type: kubernetes
|
type: kubernetes
|
||||||
@@ -27,10 +34,14 @@ name: build:dev
|
|||||||
steps:
|
steps:
|
||||||
- name: run full license export
|
- name: run full license export
|
||||||
depends_on: ["clone"]
|
depends_on: ["clone"]
|
||||||
image: registry.odit.services/hub/library/node:alpine
|
image: registry.odit.services/hub/library/node:19.7.0-alpine3.16
|
||||||
commands:
|
commands:
|
||||||
- yarn
|
- npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@8
|
||||||
- yarn licenses:export
|
- pnpm i
|
||||||
|
- pnpm licenses:export
|
||||||
|
environment:
|
||||||
|
NPM_REGISTRY_URL:
|
||||||
|
from_secret: npm_url
|
||||||
- name: push new licenses file to repo
|
- name: push new licenses file to repo
|
||||||
depends_on: ["run full license export"]
|
depends_on: ["run full license export"]
|
||||||
image: appleboy/drone-git-push
|
image: appleboy/drone-git-push
|
||||||
@@ -43,18 +54,21 @@ steps:
|
|||||||
ssh_key:
|
ssh_key:
|
||||||
from_secret: git_ssh
|
from_secret: git_ssh
|
||||||
- name: build dev
|
- name: build dev
|
||||||
image: plugins/docker
|
depends_on: ["clone"]
|
||||||
depends_on: [clone]
|
image: registry.odit.services/library/drone-kaniko
|
||||||
settings:
|
settings:
|
||||||
username:
|
username:
|
||||||
from_secret: docker_username
|
from_secret: docker_username
|
||||||
password:
|
password:
|
||||||
from_secret: docker_password
|
from_secret: docker_password
|
||||||
repo: registry.odit.services/lfk/frontend
|
build_args:
|
||||||
|
- NPM_REGISTRY_URL:
|
||||||
|
from_secret: npm_url
|
||||||
|
repo: lfk/frontend
|
||||||
tags:
|
tags:
|
||||||
- dev
|
- dev
|
||||||
|
cache: true
|
||||||
registry: registry.odit.services
|
registry: registry.odit.services
|
||||||
mtu: 1000
|
|
||||||
trigger:
|
trigger:
|
||||||
branch:
|
branch:
|
||||||
- dev
|
- dev
|
||||||
@@ -67,18 +81,21 @@ type: kubernetes
|
|||||||
name: build:tags
|
name: build:tags
|
||||||
steps:
|
steps:
|
||||||
- name: build $DRONE_TAG
|
- name: build $DRONE_TAG
|
||||||
image: plugins/docker
|
depends_on: ["clone"]
|
||||||
depends_on: [clone]
|
image: registry.odit.services/library/drone-kaniko
|
||||||
settings:
|
settings:
|
||||||
username:
|
username:
|
||||||
from_secret: docker_username
|
from_secret: docker_username
|
||||||
password:
|
password:
|
||||||
from_secret: docker_password
|
from_secret: docker_password
|
||||||
repo: registry.odit.services/lfk/frontend
|
build_args:
|
||||||
|
- NPM_REGISTRY_URL:
|
||||||
|
from_secret: npm_url
|
||||||
|
repo: lfk/frontend
|
||||||
tags:
|
tags:
|
||||||
- '${DRONE_TAG}'
|
- "${DRONE_TAG}"
|
||||||
|
cache: true
|
||||||
registry: registry.odit.services
|
registry: registry.odit.services
|
||||||
mtu: 1000
|
|
||||||
trigger:
|
trigger:
|
||||||
event:
|
event:
|
||||||
- tag
|
- tag
|
||||||
+1
-5
@@ -1,10 +1,6 @@
|
|||||||
node_modules
|
node_modules
|
||||||
package-lock.json
|
|
||||||
yarn.lock
|
|
||||||
*.map
|
*.map
|
||||||
public/env.js
|
public/env.js
|
||||||
public/index.html
|
public/index.html
|
||||||
/dist
|
/dist
|
||||||
.yarn
|
.pnpm-store
|
||||||
.pnp.js
|
|
||||||
.yarnrc.yml
|
|
||||||
+427
-1
@@ -2,8 +2,434 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
|
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
|
||||||
|
|
||||||
|
#### [1.3.4](https://git.odit.services/lfk/frontend/compare/1.3.3...1.3.4)
|
||||||
|
|
||||||
|
- Smaller sponsoring page size [`7cb6b63`](https://git.odit.services/lfk/frontend/commit/7cb6b63eb9596da4ee84369b220c3e680c607032)
|
||||||
|
|
||||||
|
#### [1.3.3](https://git.odit.services/lfk/frontend/compare/1.3.2...1.3.3)
|
||||||
|
|
||||||
|
> 19 April 2023
|
||||||
|
|
||||||
|
- 🚀RELEASE v1.3.3 [`d6d88f5`](https://git.odit.services/lfk/frontend/commit/d6d88f5f60716ca496a17f09b835b23223ec495d)
|
||||||
|
- bumped lfk-client-js [`2c208c4`](https://git.odit.services/lfk/frontend/commit/2c208c438185892270a0ebd37deb6a7c9ac08fc0)
|
||||||
|
|
||||||
|
#### [1.3.2](https://git.odit.services/lfk/frontend/compare/1.3.1...1.3.2)
|
||||||
|
|
||||||
|
> 19 April 2023
|
||||||
|
|
||||||
|
- 🚀RELEASE v1.3.2 [`39bc6c4`](https://git.odit.services/lfk/frontend/commit/39bc6c49450964510f996369d014f92c569188ae)
|
||||||
|
- fix(donors): Shortened texts [`b94e3b7`](https://git.odit.services/lfk/frontend/commit/b94e3b745f2febbe91e16a7a26f96b47d347ab92)
|
||||||
|
- feat(donations): Resolve donations via donor [`6f337ae`](https://git.odit.services/lfk/frontend/commit/6f337aeee16267d1e67e3d3855b63b6f2e57979f)
|
||||||
|
- fix(donors): Removed debug infos [`5d48060`](https://git.odit.services/lfk/frontend/commit/5d48060834717b2244172a0914e2690f8fe634d9)
|
||||||
|
|
||||||
|
#### [1.3.1](https://git.odit.services/lfk/frontend/compare/1.3.0...1.3.1)
|
||||||
|
|
||||||
|
> 19 April 2023
|
||||||
|
|
||||||
|
- feat(donations): Donation table filtering [`91ab199`](https://git.odit.services/lfk/frontend/commit/91ab199769c9f4f8051c74ad43a701db321f3995)
|
||||||
|
- feat(donors): Added name and address filtering [`27b4dde`](https://git.odit.services/lfk/frontend/commit/27b4dde7551995c9d7e8ca33a9bd97d429a35801)
|
||||||
|
- 🚀RELEASE v1.3.1 [`c842c20`](https://git.odit.services/lfk/frontend/commit/c842c203e2fbf0a201297d475db9047c0691bd52)
|
||||||
|
- More filtering [`5bcfc8d`](https://git.odit.services/lfk/frontend/commit/5bcfc8db752fce96e9f523d14cefff1a4f675661)
|
||||||
|
|
||||||
|
#### [1.3.0](https://git.odit.services/lfk/frontend/compare/1.2.0...1.3.0)
|
||||||
|
|
||||||
|
> 19 April 2023
|
||||||
|
|
||||||
|
- feat(donations): Implemented donation deletion via confirm modal [`505fb8c`](https://git.odit.services/lfk/frontend/commit/505fb8cb08b81a7dcb08561bdda0f6464f140d3e)
|
||||||
|
- 🚀RELEASE v1.3.0 [`e75be49`](https://git.odit.services/lfk/frontend/commit/e75be49be42c3d5581e2204bfa064bfa3778c1b6)
|
||||||
|
- feat(donationsoverview): Switched donations overview to datatable [`133470b`](https://git.odit.services/lfk/frontend/commit/133470b6f2a63ec087f27c98ef260648a8672e5f)
|
||||||
|
- feat(donations): Implemented add donation payment via datatable refresh [`e5c9265`](https://git.odit.services/lfk/frontend/commit/e5c92655886ad9a6fcd7565fadd7955c477c3595)
|
||||||
|
- feat(donations): Donations reactive create and load into datatable [`02003ec`](https://git.odit.services/lfk/frontend/commit/02003ec80efc16aabd126710a6eeac18df43f841)
|
||||||
|
- feat(DonationsOverview): i18n loading text [`8f8858f`](https://git.odit.services/lfk/frontend/commit/8f8858f10071ddf9988d0ec0e3c4a891db24a102)
|
||||||
|
- new license file version [CI SKIP] [`4289034`](https://git.odit.services/lfk/frontend/commit/4289034436869750205a946247e7ab5f9892fe98)
|
||||||
|
|
||||||
|
#### [1.2.0](https://git.odit.services/lfk/frontend/compare/1.1.0...1.2.0)
|
||||||
|
|
||||||
|
> 19 April 2023
|
||||||
|
|
||||||
|
- feat(donoroverview): Added datatable formatters [`d98fb0d`](https://git.odit.services/lfk/frontend/commit/d98fb0d5b288c987a45ccbf2bb026ccaab539a71)
|
||||||
|
- 🚀RELEASE v1.2.0 [`fdc7d80`](https://git.odit.services/lfk/frontend/commit/fdc7d80bbf9bd698128e9ec4f91fa813499777a9)
|
||||||
|
- feat(donors): Load donors paginated [`5014bf5`](https://git.odit.services/lfk/frontend/commit/5014bf5bc5873cfe4ae04d71b4aff12b257dd2e3)
|
||||||
|
- feat(donorsoverview): Dynamicly add newly generated donors [`352551e`](https://git.odit.services/lfk/frontend/commit/352551e168b5dced5e7353e82655908d82d28af0)
|
||||||
|
- feat(donorsoverview): Implemented delete confirmation with datatable [`7aec050`](https://git.odit.services/lfk/frontend/commit/7aec050419f6f1bf853c3e1bc655b01725ed3b65)
|
||||||
|
|
||||||
|
#### [1.1.0](https://git.odit.services/lfk/frontend/compare/1.0.0...1.1.0)
|
||||||
|
|
||||||
|
> 19 April 2023
|
||||||
|
|
||||||
|
- 🚀RELEASE v1.1.0 [`0708cab`](https://git.odit.services/lfk/frontend/commit/0708cabc75e63a876e54a0b343318f8d934ae319)
|
||||||
|
- feat(dashboar): Added total donors to overview [`e0b6148`](https://git.odit.services/lfk/frontend/commit/e0b61486b089aa1e611ef3569b1521fc331ec0e4)
|
||||||
|
- feat(dashboard): Updated stats icons [`4fcb26c`](https://git.odit.services/lfk/frontend/commit/4fcb26cf9371e27e5d7e474b3558ef354e9114c0)
|
||||||
|
- feat(dashboard): Added average sponsoring [`269def2`](https://git.odit.services/lfk/frontend/commit/269def20d114ededaba3153bbd50ec2ddd70e1c6)
|
||||||
|
- feat(dashboard): Added total donations [`7b2b598`](https://git.odit.services/lfk/frontend/commit/7b2b59858839b98370af6fb1e6028ba0a1639186)
|
||||||
|
- feat(dashboard): Added average distance [`b8de9e0`](https://git.odit.services/lfk/frontend/commit/b8de9e0e427b3a8b56e6354ad7168ae12c7cce85)
|
||||||
|
- Lockfile [`3f86f74`](https://git.odit.services/lfk/frontend/commit/3f86f7412ffc4bc27328ad1f7d3c3118546e7e29)
|
||||||
|
- Bumped client [`6454d96`](https://git.odit.services/lfk/frontend/commit/6454d960de3f9f5ea86679f157b3b7e7cffde74d)
|
||||||
|
- new license file version [CI SKIP] [`2a64094`](https://git.odit.services/lfk/frontend/commit/2a640940062765a470387103a72ed14a2411d97b)
|
||||||
|
|
||||||
|
### [1.0.0](https://git.odit.services/lfk/frontend/compare/0.19.0...1.0.0)
|
||||||
|
|
||||||
|
> 19 April 2023
|
||||||
|
|
||||||
|
- 🚀RELEASE v1.0.0 [`8da7578`](https://git.odit.services/lfk/frontend/commit/8da7578a0a46a3e97d8c870e29399f6e8821c9fa)
|
||||||
|
- Merge pull request 'feature/175-request_pagination' (#176) from feature/175-request_pagination into dev [`e9ce964`](https://git.odit.services/lfk/frontend/commit/e9ce9644ff03f981cec6e9ad56aa5fdf0ff71ef4)
|
||||||
|
- Donation paginated loading [`ccf8656`](https://git.odit.services/lfk/frontend/commit/ccf865687b34016931a702c0a9b98a0a18e2b03a)
|
||||||
|
- Paginated scan loading [`cac34db`](https://git.odit.services/lfk/frontend/commit/cac34db1fd3bf5dc7c7be64b3a76ca4c8c77938d)
|
||||||
|
- Implemented Async loading of cards via pagination (500 cards per request) [`c33dfcf`](https://git.odit.services/lfk/frontend/commit/c33dfcfddddfed0902f3fa9b1d8a1d3e1560262f)
|
||||||
|
- Paginated runner loading (1000 per page) [`faf3893`](https://git.odit.services/lfk/frontend/commit/faf3893180bb735bea6f1ea58c896686b89949fe)
|
||||||
|
- Allways set loaded to true [`52439aa`](https://git.odit.services/lfk/frontend/commit/52439aa5bc8cfb1d78d5dfce55b1a0df640ad8f5)
|
||||||
|
- Bumped lfk client [`019e14a`](https://git.odit.services/lfk/frontend/commit/019e14ab1f99906f13d36c7148d0f4b7894072f2)
|
||||||
|
- new license file version [CI SKIP] [`a6ce04c`](https://git.odit.services/lfk/frontend/commit/a6ce04c90386f16abf235cc7b2f95aeea5011c7d)
|
||||||
|
|
||||||
|
#### [0.19.0](https://git.odit.services/lfk/frontend/compare/0.18.4...0.19.0)
|
||||||
|
|
||||||
|
> 17 April 2023
|
||||||
|
|
||||||
|
- 🚀RELEASE v0.19.0 [`94a64ca`](https://git.odit.services/lfk/frontend/commit/94a64ca69078c7fe2935eeb5f955fab95a79cb85)
|
||||||
|
- Merge pull request 'feature/173-scanstation_configcodes' (#174) from feature/173-scanstation_configcodes into dev [`165c154`](https://git.odit.services/lfk/frontend/commit/165c1542338c58f2abf42fef2e7b84b40d1e2d9c)
|
||||||
|
- I18n [`e60c09e`](https://git.odit.services/lfk/frontend/commit/e60c09e19c9cc20338906e84f4db4e009d926360)
|
||||||
|
- Implemented config code generation [`4b63427`](https://git.odit.services/lfk/frontend/commit/4b6342727ee0ea38597750d8c99edc301f1ccc2d)
|
||||||
|
- Styling [`4834d14`](https://git.odit.services/lfk/frontend/commit/4834d1484c3fb6ecd4a1b56aa9fbb8125c641a62)
|
||||||
|
- Adjusted size on smaller devices [`318547d`](https://git.odit.services/lfk/frontend/commit/318547db46045e41de64d5688368e85cd6fb8035)
|
||||||
|
- Lockfile [`947d01c`](https://git.odit.services/lfk/frontend/commit/947d01cf7fc7fe2ee88c56e017b0d663f1f3b4f9)
|
||||||
|
- Barcode placeholder [`cb5fa52`](https://git.odit.services/lfk/frontend/commit/cb5fa52cd9a97490b50fb0c02c26615b49650c08)
|
||||||
|
- Added bwip-js for barcode generation [`3563394`](https://git.odit.services/lfk/frontend/commit/3563394fb33d661890327e2ae08c400830b37844)
|
||||||
|
|
||||||
|
#### [0.18.4](https://git.odit.services/lfk/frontend/compare/0.18.3...0.18.4)
|
||||||
|
|
||||||
|
> 15 April 2023
|
||||||
|
|
||||||
|
- 🚀RELEASE v0.18.4 [`269d7a7`](https://git.odit.services/lfk/frontend/commit/269d7a7defdde059ef2bb5103262cf734e9babe9)
|
||||||
|
- Hide address2 in orgs by default [`e95f233`](https://git.odit.services/lfk/frontend/commit/e95f2333b0b958ed00c0e097b43aac2e70ad0d38)
|
||||||
|
|
||||||
|
#### [0.18.3](https://git.odit.services/lfk/frontend/compare/0.18.2...0.18.3)
|
||||||
|
|
||||||
|
> 15 April 2023
|
||||||
|
|
||||||
|
- 🚀RELEASE v0.18.3 [`950217e`](https://git.odit.services/lfk/frontend/commit/950217e0a350f9999b879475edf41f2f11c48179)
|
||||||
|
- Dont show adress 2 in runner overview [`5e65fb3`](https://git.odit.services/lfk/frontend/commit/5e65fb33013c3dad38e7ad6740b017ae206f278f)
|
||||||
|
|
||||||
|
#### [0.18.2](https://git.odit.services/lfk/frontend/compare/0.18.1...0.18.2)
|
||||||
|
|
||||||
|
> 15 April 2023
|
||||||
|
|
||||||
|
- 🚀RELEASE v0.18.2 [`2a294cd`](https://git.odit.services/lfk/frontend/commit/2a294cde040044bbebfb9c8b34b6c91b27772741)
|
||||||
|
- Added timestamps to scanoverview [`cffbd17`](https://git.odit.services/lfk/frontend/commit/cffbd17dc77054048cc9b14891f960f9a3fd18cb)
|
||||||
|
- Push in releaseit [`e95420d`](https://git.odit.services/lfk/frontend/commit/e95420d79c3227c0ca0cf0c0b599970c2b7d690e)
|
||||||
|
|
||||||
|
#### [0.18.1](https://git.odit.services/lfk/frontend/compare/0.18.0...0.18.1)
|
||||||
|
|
||||||
|
> 15 April 2023
|
||||||
|
|
||||||
|
- 🚀RELEASE v0.18.1 [`00de8c3`](https://git.odit.services/lfk/frontend/commit/00de8c3d75e90cd4614f42111f5f45bedde64130)
|
||||||
|
- Missing scanstation translations [`30e3396`](https://git.odit.services/lfk/frontend/commit/30e33968978bf33cedb31bcbf63fac273e1664f5)
|
||||||
|
- fix: button onclick a11y [`9fe53b0`](https://git.odit.services/lfk/frontend/commit/9fe53b0b9c71e8a6b4aa3f317327ffe729df0834)
|
||||||
|
- fix(ConfirmStatsClientDeletion): ScanStationService -> StatsClientService [`5291e04`](https://git.odit.services/lfk/frontend/commit/5291e049a1d2e880fbe277095da91b70d4812c3f)
|
||||||
|
- fix(ConfirmScanStationDeletion): donorControllerRemove -> scanStationControllerRemove [`08fbb50`](https://git.odit.services/lfk/frontend/commit/08fbb504c958415ce75e1e426296f870f0f1358d)
|
||||||
|
|
||||||
|
#### [0.18.0](https://git.odit.services/lfk/frontend/compare/0.17.3...0.18.0)
|
||||||
|
|
||||||
|
> 12 April 2023
|
||||||
|
|
||||||
|
- Moved filter function to typed version [`#171`](https://git.odit.services/lfk/frontend/issues/171)
|
||||||
|
- ScansOverview: migrate to datatable [`#168`](https://git.odit.services/lfk/frontend/issues/168)
|
||||||
|
- 🚀RELEASE v0.18.0 [`eb80406`](https://git.odit.services/lfk/frontend/commit/eb80406fdb8abf3f76bca742095e8f1f03480a56)
|
||||||
|
- wip: ScansOverview -> new datatable [`c87561f`](https://git.odit.services/lfk/frontend/commit/c87561f63b90ab951daf91d9b8b54ba96a94cc7f)
|
||||||
|
- Basic card table replace [`5662c3b`](https://git.odit.services/lfk/frontend/commit/5662c3b6da67c00c94254bf39f8820e531fc93ef)
|
||||||
|
- RunnersOverview: table responsiveness [`bf1e715`](https://git.odit.services/lfk/frontend/commit/bf1e715261c0076fd8543dd1187c516209a73b16)
|
||||||
|
- Basic card delete modal [`8ffe8ef`](https://git.odit.services/lfk/frontend/commit/8ffe8eff0623767809cdc49ea15cf2d30b609285)
|
||||||
|
- wip: delete scans [`f105cc0`](https://git.odit.services/lfk/frontend/commit/f105cc0a41972261610d03015ecd5ee492dab8e2)
|
||||||
|
- Added delete runner modal [`fd5db7d`](https://git.odit.services/lfk/frontend/commit/fd5db7d68ab4b32f7bb14bd0275a447b749e1fd8)
|
||||||
|
- Extracted table bottom [`8f50555`](https://git.odit.services/lfk/frontend/commit/8f50555a06a35d0b11ac1d9201851d00d915c4b8)
|
||||||
|
- fix: formatting [`9def0b2`](https://git.odit.services/lfk/frontend/commit/9def0b27c9958c5c75466f56c17b6dc4d44d2b50)
|
||||||
|
- fix(CardsOverview): table scroll + checkbox posititioning [`9c13b2f`](https://git.odit.services/lfk/frontend/commit/9c13b2f9e938ad36cb74c66a8f91a5b872c8c2d1)
|
||||||
|
- Extracted table header [`c241961`](https://git.odit.services/lfk/frontend/commit/c241961d0ab0d6b8c3bf0453c1a21d84027ed62f)
|
||||||
|
- drop legacy dependencies [`c98eb49`](https://git.odit.services/lfk/frontend/commit/c98eb49ae31d1d28de79c7a9c945ade50828f07f)
|
||||||
|
- scan delete working [`c7dcf7c`](https://git.odit.services/lfk/frontend/commit/c7dcf7c66d7141117e08462ad05f6f441565d012)
|
||||||
|
- Add Card appends current cards [`195d182`](https://git.odit.services/lfk/frontend/commit/195d182cc977b4ac9f342f09a9ea69d461892a95)
|
||||||
|
- Moved data loading to onmount [`a35af6f`](https://git.odit.services/lfk/frontend/commit/a35af6f02055115d60d040baaf22dabbeda38498)
|
||||||
|
- Add runners reactivity [`06411dc`](https://git.odit.services/lfk/frontend/commit/06411dc14747fc9803da009a29688789c31dfc42)
|
||||||
|
- quick cleanup [`ebdd1c2`](https://git.odit.services/lfk/frontend/commit/ebdd1c2c0c2191c60dfacd0c4be989748628ca63)
|
||||||
|
- Extracted deletion into function of overview [`a0727a0`](https://git.odit.services/lfk/frontend/commit/a0727a02913708de06be8bf1b9f8cbae5489f080)
|
||||||
|
- Moved update card logic to overview [`53b945c`](https://git.odit.services/lfk/frontend/commit/53b945c72fa5b30f03eff8bb83f8f25d85d79b07)
|
||||||
|
- wip:ScanValid badge [`bd4952e`](https://git.odit.services/lfk/frontend/commit/bd4952ee575b4cd8caea3608b14d8c51b37a55eb)
|
||||||
|
- yeeted extra table styling [`52a02c8`](https://git.odit.services/lfk/frontend/commit/52a02c82d2bdabdf3e632910aa415c1ffb97fd7f)
|
||||||
|
- Added custom runner filter [`7c6d39b`](https://git.odit.services/lfk/frontend/commit/7c6d39b5fa60d1b834c9fb74dd26dfc2225161d6)
|
||||||
|
- Scan reactive add [`f5d14f2`](https://git.odit.services/lfk/frontend/commit/f5d14f2e1810462cba99b2482320746f0750d4a1)
|
||||||
|
- Moved code around [`239f79f`](https://git.odit.services/lfk/frontend/commit/239f79fecba732c807f4296cf524be15c1ccff1e)
|
||||||
|
- Scan deletion [`7d8c68a`](https://git.odit.services/lfk/frontend/commit/7d8c68a4550407e8c871545e7a0c5f622a1e3b9c)
|
||||||
|
- Added status filter function [`f6c1fea`](https://git.odit.services/lfk/frontend/commit/f6c1fea17ce64d890ac810d9dff058dd589c2989)
|
||||||
|
- Added delete toast [`e2ddb5a`](https://git.odit.services/lfk/frontend/commit/e2ddb5a14cc8b450c00129709bf5b933a47866dd)
|
||||||
|
- Fixed killing of the dom [`2f62c7a`](https://git.odit.services/lfk/frontend/commit/2f62c7ae89b7dda3bc0efd4d56e677898a3f197f)
|
||||||
|
- Cards details modal [`f6985da`](https://git.odit.services/lfk/frontend/commit/f6985daec71e4d922acd8a9b2673fd41317b075f)
|
||||||
|
- Reload table data on delete [`3e8dac3`](https://git.odit.services/lfk/frontend/commit/3e8dac3203f56723a3dad4a35887d60fc03d4ae3)
|
||||||
|
- Added middle-name [`d811058`](https://git.odit.services/lfk/frontend/commit/d8110580e9a33cfb0c6e9cbdce630262d5b5d4c1)
|
||||||
|
- Fixed id sorting [`7cec2a0`](https://git.odit.services/lfk/frontend/commit/7cec2a00c513678cae8643ef3905d566a538bde0)
|
||||||
|
- Import add to datatable [`2a91562`](https://git.odit.services/lfk/frontend/commit/2a915620c9adcb481be53e3c919bd5f14a5108ee)
|
||||||
|
- Scans deletion [`6d9d8a4`](https://git.odit.services/lfk/frontend/commit/6d9d8a4724135df98ed1bec74b0cc20a8bdbda53)
|
||||||
|
- fix(DeleteRunnerModal): ESC key [`1df505e`](https://git.odit.services/lfk/frontend/commit/1df505ea00968f65e7aff85baa80f8935fd2eb7b)
|
||||||
|
- Versionbuilder [`1613ae7`](https://git.odit.services/lfk/frontend/commit/1613ae7de6e84aa5f9df6774a8e820fcf515b14a)
|
||||||
|
- Fixed edit dispatch [`c681570`](https://git.odit.services/lfk/frontend/commit/c68157013431eeb1150e37fea87da02d5f7b032e)
|
||||||
|
- ScansOverview: use CardRunner link [`4b171fd`](https://git.odit.services/lfk/frontend/commit/4b171fd04f4fc895f9919294858e546686504c65)
|
||||||
|
- Added custom filter to scan overview [`2c198cf`](https://git.odit.services/lfk/frontend/commit/2c198cfde89363142c1c958e6961b7823196e04e)
|
||||||
|
- Disable sort for actions [`fc2c290`](https://git.odit.services/lfk/frontend/commit/fc2c2907c43e5b1fa192b571cf93b2f2e492158f)
|
||||||
|
- Delete modal logic [`da33005`](https://git.odit.services/lfk/frontend/commit/da3300562a25cf39945a94f873ec27f0d5fb9dc0)
|
||||||
|
- Module [`9ae5e62`](https://git.odit.services/lfk/frontend/commit/9ae5e62e5d84097082bc29fe20b329f6e614f6ed)
|
||||||
|
- new license file version [CI SKIP] [`ed1caa7`](https://git.odit.services/lfk/frontend/commit/ed1caa7be7673ef08f9c0074101f3cfb52963ab7)
|
||||||
|
- Merge pull request 'experiment/tanstack' (#172) from experiment/tanstack into dev [`d88f3a5`](https://git.odit.services/lfk/frontend/commit/d88f3a5a2737921536c5eb109734abafd7609e51)
|
||||||
|
- Removed pnpm store [`eb13f03`](https://git.odit.services/lfk/frontend/commit/eb13f038a1990ed2966552ab1d36df4a76e5a99a)
|
||||||
|
- dependency update, drop focusTrap, first tanstack experiment in RunnersOverview [`9bec95e`](https://git.odit.services/lfk/frontend/commit/9bec95ede80908e45ad0f18a66dbb45784f7e33e)
|
||||||
|
- Added translations [`dcabed4`](https://git.odit.services/lfk/frontend/commit/dcabed4e93134a1f04305c47536f1cc93b0cfb31)
|
||||||
|
- new license file version [CI SKIP] [`d0fe6a2`](https://git.odit.services/lfk/frontend/commit/d0fe6a2e8513638c4d8e2b3dafd48b91490eab3b)
|
||||||
|
- Bumped pnpm to 8 [`ee91748`](https://git.odit.services/lfk/frontend/commit/ee91748b3c7c2fb4f196d76121713ac42465b9dd)
|
||||||
|
- drop old datatables [`cb5f2b7`](https://git.odit.services/lfk/frontend/commit/cb5f2b73d0a5f71875f48d381382919f9bee364e)
|
||||||
|
- wip: pagination [`a59dbbe`](https://git.odit.services/lfk/frontend/commit/a59dbbe50ede47e0dada906d10887cc6b1ae3264)
|
||||||
|
- Added sort [`842248e`](https://git.odit.services/lfk/frontend/commit/842248e4c43bb94a0e73981d2d848e0723687932)
|
||||||
|
- cleanup headers [`5ecf838`](https://git.odit.services/lfk/frontend/commit/5ecf838dd231269c3c4f0d1e3376ff157457b04a)
|
||||||
|
- Moved filter function to shared [`2304b12`](https://git.odit.services/lfk/frontend/commit/2304b12c1cca6a64573223906ab0561ba9050ec5)
|
||||||
|
- Group filters [`0283df2`](https://git.odit.services/lfk/frontend/commit/0283df22c84740dd978e09120985215b65d7a12a)
|
||||||
|
- feat(RunnersOverview): row selection [`6993511`](https://git.odit.services/lfk/frontend/commit/6993511c67cc81303a1eece7fc2a4218dc818afc)
|
||||||
|
- Basic details and delete buttons [`9363773`](https://git.odit.services/lfk/frontend/commit/9363773fa1910975d48746572fe166363986c6ab)
|
||||||
|
- Added delete cards button [`70307a9`](https://git.odit.services/lfk/frontend/commit/70307a9e8272f22801c6765c947f8576cc1d1102)
|
||||||
|
- ScansOverview: add ThFilterTrack [`008835c`](https://git.odit.services/lfk/frontend/commit/008835c24f833aebbecc53921b0901a76f25bf06)
|
||||||
|
- Yeeted old datatable references [`8925261`](https://git.odit.services/lfk/frontend/commit/89252619b1f6d478c287178bfffc573cf574a8fa)
|
||||||
|
- Added filter [`a9cdac4`](https://git.odit.services/lfk/frontend/commit/a9cdac4f74a80afe3d0ce677ed5256201b75b29b)
|
||||||
|
- Moved sort onclick to header only [`3de7b63`](https://git.odit.services/lfk/frontend/commit/3de7b632e058e9ca9ab951de9e86cc2a40eceb68)
|
||||||
|
- Switched drone to pnpm cache [`d79608e`](https://git.odit.services/lfk/frontend/commit/d79608edbb7ca68b0a26f6c021a141373308081f)
|
||||||
|
- pagination size [`45a7a90`](https://git.odit.services/lfk/frontend/commit/45a7a90cb8ee933d064c5891b3532cb1ece38d38)
|
||||||
|
- RunnersOverview: add filter keyboard support [`9415584`](https://git.odit.services/lfk/frontend/commit/94155845f020679e8765d198b5ab4735e1d1142c)
|
||||||
|
- RunnersOverview: pass selectedRunners to actions [`d4ab76e`](https://git.odit.services/lfk/frontend/commit/d4ab76ea1be1789aaa53ca57d33b2356c6804ffd)
|
||||||
|
- fix pagination next prev [`cac851f`](https://git.odit.services/lfk/frontend/commit/cac851f2b19dafa01b08d1da612e34cbe3eb4133)
|
||||||
|
- Moved docker to pnpm with cache [`4cbd265`](https://git.odit.services/lfk/frontend/commit/4cbd26580e51b854fdfd369056f24a30b04100a1)
|
||||||
|
- fix: TracksOverview [`c799088`](https://git.odit.services/lfk/frontend/commit/c7990882cfa4ac6c3a2ffa696dcbf3b62790c1fe)
|
||||||
|
- Table header i18n [`070a20a`](https://git.odit.services/lfk/frontend/commit/070a20a2e599e9f00b1bd0e944f9d68d08dc1cba)
|
||||||
|
- default to 50 rows pagination [`dc866dd`](https://git.odit.services/lfk/frontend/commit/dc866dd5403ae681193c5e325b1f6d4068f80b61)
|
||||||
|
- improved tablefilters/groupFilter [`3abf608`](https://git.odit.services/lfk/frontend/commit/3abf608b15fcfc2cf65b705d28d394917e7ac333)
|
||||||
|
- Updated group name conversion [`9111ad1`](https://git.odit.services/lfk/frontend/commit/9111ad147c7537036de834f80db6e557d8d6f0d9)
|
||||||
|
- show certificate, runnercard, sponsoring contract section [`49c2cd5`](https://git.odit.services/lfk/frontend/commit/49c2cd5c4b32e1b75fe0dae48c1b470608936704)
|
||||||
|
- add basic table styling [`c5e8409`](https://git.odit.services/lfk/frontend/commit/c5e84090795636c7a80d6cabe46168e436d40f50)
|
||||||
|
- Cards deleted migrations [`ef077b4`](https://git.odit.services/lfk/frontend/commit/ef077b4e6ad722e6d1c9efd5060165f649fd94c9)
|
||||||
|
- ignore pnpm store from now on [`fe62ad5`](https://git.odit.services/lfk/frontend/commit/fe62ad5539bc94b242c30c2952bf4c115cc9abfd)
|
||||||
|
- ammendme [`d31fe23`](https://git.odit.services/lfk/frontend/commit/d31fe2363b0f167b937f7d67908e75c709b324d8)
|
||||||
|
- updated default table row count [`245db06`](https://git.odit.services/lfk/frontend/commit/245db0617306bab23993caf00dc5ba0405e95625)
|
||||||
|
- fix: checkbox styling [`64db553`](https://git.odit.services/lfk/frontend/commit/64db5531858b2275d27c53a347da6c0416a278e8)
|
||||||
|
- Added distance conversion [`333214a`](https://git.odit.services/lfk/frontend/commit/333214aa8f945975ee2dcbd1cfa285e5e75c9d02)
|
||||||
|
- Added filterfunctions [`a9a965d`](https://git.odit.services/lfk/frontend/commit/a9a965d6981b07b02e3f752e65e1e5c4e9df7147)
|
||||||
|
- card/ThFilterRunner: text align left [`7083b3d`](https://git.odit.services/lfk/frontend/commit/7083b3d8d2c81fa4ab14f21d379befbb2dab5b6c)
|
||||||
|
- import [`0240e1d`](https://git.odit.services/lfk/frontend/commit/0240e1dca2e162b8c79f294f5c651b4a38455235)
|
||||||
|
- fix: table sort button + search style [`57dce34`](https://git.odit.services/lfk/frontend/commit/57dce34fc5b04c297c5341db24ec47c2f1d39595)
|
||||||
|
- No longer switching pnpm store path [`e5241d6`](https://git.odit.services/lfk/frontend/commit/e5241d619beda90d271485b6c09142b1e7b9b5f1)
|
||||||
|
- Reactivated generate cards modal [`8f33640`](https://git.odit.services/lfk/frontend/commit/8f33640bec8f79987b1319fb0765535fe493d496)
|
||||||
|
- Always load bulk created cards [`f89023e`](https://git.odit.services/lfk/frontend/commit/f89023e24ab30c90a8cacf2e9590d1dfa1a743d5)
|
||||||
|
- ScansOverview: fallback for manual scans [`1ec9556`](https://git.odit.services/lfk/frontend/commit/1ec9556aa64b996d0bdd9cd3ee50a767a154f5f6)
|
||||||
|
- fix min-w th [`b35375c`](https://git.odit.services/lfk/frontend/commit/b35375c929ad8d525b2761c321ecef0399917828)
|
||||||
|
- Close modal on delete and import toastify [`03b7ada`](https://git.odit.services/lfk/frontend/commit/03b7ada5ef3cbf64f178d3d0d88c448d76a42885)
|
||||||
|
- Fixed styling [`13254b2`](https://git.odit.services/lfk/frontend/commit/13254b24dd75ca3eb47fd53d5368f047545e8420)
|
||||||
|
- Implemented table buttons [`11a56f8`](https://git.odit.services/lfk/frontend/commit/11a56f87e89866bd9b2f7029ef683fd139d60aa4)
|
||||||
|
- RunnersOverview: disable debug log [`2c992a0`](https://git.odit.services/lfk/frontend/commit/2c992a0e63fa72055d28785fe7f5c21fd26f1fea)
|
||||||
|
- RunnersOverview: TopActionSection: add margin top [`88f96ac`](https://git.odit.services/lfk/frontend/commit/88f96acc3c31c748d3da29b4564dd681a89208b9)
|
||||||
|
- Unused filter function value [`38d3e19`](https://git.odit.services/lfk/frontend/commit/38d3e1912cd6d5362db236c34e0c602b52060b73)
|
||||||
|
- Make the linter happy [`fbc14fd`](https://git.odit.services/lfk/frontend/commit/fbc14fd7b47009bf64a8824e7b60373eea031e3f)
|
||||||
|
- Dsable column filter for distance [`67eff0e`](https://git.odit.services/lfk/frontend/commit/67eff0eda9b7d49d1abe784247afdbfbd7a76b00)
|
||||||
|
- getPaginationRowModel [`238082b`](https://git.odit.services/lfk/frontend/commit/238082b657998f513111e832556926decbe84e21)
|
||||||
|
- -> onkeyup [`aecbabe`](https://git.odit.services/lfk/frontend/commit/aecbabe52221c0ab8d94a42dc8ac42f4f397fde8)
|
||||||
|
- removed unused import [`9811ede`](https://git.odit.services/lfk/frontend/commit/9811ede3b23a488a49962a43dae5abad60f93341)
|
||||||
|
- drop redundant button role [`e7eddb4`](https://git.odit.services/lfk/frontend/commit/e7eddb4f08632cc803b8752e3561319fab538843)
|
||||||
|
- Filter id as equals [`2699b06`](https://git.odit.services/lfk/frontend/commit/2699b06d7c42608b1b3ce2037908a78143038441)
|
||||||
|
- debug table [`fd0d45f`](https://git.odit.services/lfk/frontend/commit/fd0d45f721396787ad35fca2a7fd0f26d98b23e9)
|
||||||
|
- add TODO for ScansOverview status filter [`9505c2b`](https://git.odit.services/lfk/frontend/commit/9505c2b03005f4e667082cb4527fea863dbbf7fc)
|
||||||
|
|
||||||
|
#### [0.17.3](https://git.odit.services/lfk/frontend/compare/0.17.2...0.17.3)
|
||||||
|
|
||||||
|
> 15 March 2023
|
||||||
|
|
||||||
|
- dependency fixes [`3ea7a01`](https://git.odit.services/lfk/frontend/commit/3ea7a015a9beba3c2e4d3eb966f24ff6d4ac786e)
|
||||||
|
- 🚀RELEASE v0.17.3 [`85705b6`](https://git.odit.services/lfk/frontend/commit/85705b6e684d0c41d3dc770cef7bffb199101576)
|
||||||
|
- set pnpm to @7 [`4432941`](https://git.odit.services/lfk/frontend/commit/44329413ed2ca23f74e86db041b2c25b2b1c2a2b)
|
||||||
|
|
||||||
|
#### [0.17.2](https://git.odit.services/lfk/frontend/compare/0.17.1...0.17.2)
|
||||||
|
|
||||||
|
> 15 March 2023
|
||||||
|
|
||||||
|
- new license file version [CI SKIP] [`00359d2`](https://git.odit.services/lfk/frontend/commit/00359d25c1bd3efdd6365bf284b3c07634049399)
|
||||||
|
- 🚀RELEASE v0.17.2 [`46db68a`](https://git.odit.services/lfk/frontend/commit/46db68ab229dc740dfff8835ef916f2c2e629b27)
|
||||||
|
- improved ThFilterGroup style [`f917018`](https://git.odit.services/lfk/frontend/commit/f917018fd92a8a5b034f735ac8b6e41995044317)
|
||||||
|
|
||||||
|
#### [0.17.1](https://git.odit.services/lfk/frontend/compare/0.17.0...0.17.1)
|
||||||
|
|
||||||
|
> 15 March 2023
|
||||||
|
|
||||||
|
- Revert "package dependency fixes, bumps, lockfile update" [`d8a3063`](https://git.odit.services/lfk/frontend/commit/d8a30637351e164599e07a6473d9a1d2b08d245d)
|
||||||
|
- 🚀RELEASE v0.17.1 [`7b420c4`](https://git.odit.services/lfk/frontend/commit/7b420c430d27bf0fc85a4297780164a593fc1be3)
|
||||||
|
|
||||||
|
#### [0.17.0](https://git.odit.services/lfk/frontend/compare/0.16.5...0.17.0)
|
||||||
|
|
||||||
|
> 15 March 2023
|
||||||
|
|
||||||
|
- new license file version [CI SKIP] [`61328d2`](https://git.odit.services/lfk/frontend/commit/61328d20ed2cfd1df7d3c32767f9c64154879d6d)
|
||||||
|
- wip: pnpm + node version [`732b2f0`](https://git.odit.services/lfk/frontend/commit/732b2f061e465bd08cf34c58d8cd6b021ba25dce)
|
||||||
|
- package dependency fixes, bumps, lockfile update [`2c73b98`](https://git.odit.services/lfk/frontend/commit/2c73b9862d401dac15021eed3f7847d46132a8ed)
|
||||||
|
- Fixed runners not showing up [`75bc89c`](https://git.odit.services/lfk/frontend/commit/75bc89ca3020c48f490c7602374616bd9461e78f)
|
||||||
|
- add ThFilterRunner [`3a3e2f7`](https://git.odit.services/lfk/frontend/commit/3a3e2f71575d3a0e39a5e13b05cff932b8683ac9)
|
||||||
|
- fix styling for table filters th border [`bea57aa`](https://git.odit.services/lfk/frontend/commit/bea57aa03acaaaa4b1860b30228dd5d1298317f8)
|
||||||
|
- You can now create cards from runners by searching via #runnerid [`e8a0ad6`](https://git.odit.services/lfk/frontend/commit/e8a0ad6647ab39252865f62b755f27c34ac2d243)
|
||||||
|
- remodelled for early return [`b869b5f`](https://git.odit.services/lfk/frontend/commit/b869b5fd2a01955fb21f936fa38eb5a9648e7de3)
|
||||||
|
- 🚀RELEASE v0.17.0 [`6491af1`](https://git.odit.services/lfk/frontend/commit/6491af19e375cbeba7ddd94e463b4dfe308a70a8)
|
||||||
|
- Wow this api is fun [`32a9074`](https://git.odit.services/lfk/frontend/commit/32a9074963cce3328f14b1f981ddd5ee49df0008)
|
||||||
|
- Fixed double space in label [`92b89cc`](https://git.odit.services/lfk/frontend/commit/92b89cc4d88c9d5625c2ddf7c81c98494f7f5271)
|
||||||
|
- UsersOverview: drop pfp [`30991d5`](https://git.odit.services/lfk/frontend/commit/30991d5364a09d517b2115a7e9ea3fbf1fe2e57d)
|
||||||
|
- Switched license generation to cache registry and pnpm [`0a6d92a`](https://git.odit.services/lfk/frontend/commit/0a6d92a1f3c5562f11562c433b3a04e3eaae3da4)
|
||||||
|
- Pinned pnpm in dockerfile, thx @philipp [`3a576d1`](https://git.odit.services/lfk/frontend/commit/3a576d1073ee503b68100e01054a1756bab62805)
|
||||||
|
- Pinned ci node version [`b30b98b`](https://git.odit.services/lfk/frontend/commit/b30b98b521eda2bc7fc055097546f716e90d92ef)
|
||||||
|
- Fixed pnpm being called without being installed [`43d82a2`](https://git.odit.services/lfk/frontend/commit/43d82a2af04af49c2169f78a0d0f27ef7e4d7558)
|
||||||
|
- Merge pull request 'bugfix/162-create_card_modal' (#163) from bugfix/162-create_card_modal into dev [`6a4495b`](https://git.odit.services/lfk/frontend/commit/6a4495b8131a31cd48a608c2275e80494d0a0fb4)
|
||||||
|
- Removed unused log [`268b1b1`](https://git.odit.services/lfk/frontend/commit/268b1b1d9830de196d1d95345d7a2467bbf19eb6)
|
||||||
|
- Merge pull request 'filter by runner full names + "#<ID>"' (#160) from feature/159-cardsoverview-filter-for-runner-full-names-and-id into dev [`0625937`](https://git.odit.services/lfk/frontend/commit/0625937068f0786078ffd29b9c8bb54949350b6c)
|
||||||
|
- UsersOverview: change profilepic scaling [`5cc8b08`](https://git.odit.services/lfk/frontend/commit/5cc8b0811cf290f97a4399b23c5ea4d961a5a91c)
|
||||||
|
|
||||||
|
#### [0.16.5](https://git.odit.services/lfk/frontend/compare/0.16.4...0.16.5)
|
||||||
|
|
||||||
|
> 14 March 2023
|
||||||
|
|
||||||
|
- 🚀RELEASE v0.16.5 [`3680533`](https://git.odit.services/lfk/frontend/commit/3680533eefef042fc77246dd3d374aafe10c428f)
|
||||||
|
- new license file version [CI SKIP] [`405dfa0`](https://git.odit.services/lfk/frontend/commit/405dfa0c34ba87fc450c22e0e9974f92c4cdeffe)
|
||||||
|
|
||||||
|
#### [0.16.4](https://git.odit.services/lfk/frontend/compare/0.16.3...0.16.4)
|
||||||
|
|
||||||
|
> 14 March 2023
|
||||||
|
|
||||||
|
- fix: OrgDetail: clicking on address will toggle selfservice [`#158`](https://git.odit.services/lfk/frontend/issues/158)
|
||||||
|
- 🚀RELEASE v0.16.4 [`5c2d154`](https://git.odit.services/lfk/frontend/commit/5c2d154ad180ce7916605871c63e2f5ac4428250)
|
||||||
|
|
||||||
|
#### [0.16.3](https://git.odit.services/lfk/frontend/compare/0.16.2...0.16.3)
|
||||||
|
|
||||||
|
> 23 February 2023
|
||||||
|
|
||||||
|
- 🚀RELEASE v0.16.3 [`f9cfd6b`](https://git.odit.services/lfk/frontend/commit/f9cfd6bd063b01a584774854d8fb5eab96f99528)
|
||||||
|
- Bumped vite build targets [`5fe4763`](https://git.odit.services/lfk/frontend/commit/5fe47634e8980e77b65c05f213c475cf49273609)
|
||||||
|
- new license file version [CI SKIP] [`a659091`](https://git.odit.services/lfk/frontend/commit/a6590910cfdc5e91fba91c1bc9237e407ef15fd2)
|
||||||
|
- Merge pull request 'feature/156-pdf_names' (#157) from feature/156-pdf_names into dev [`ad454c3`](https://git.odit.services/lfk/frontend/commit/ad454c386cbf11abc59d41d269d1a0ef7442c9ed)
|
||||||
|
- Added ids for generated pdfs [`0b2c296`](https://git.odit.services/lfk/frontend/commit/0b2c296de069a4ef302c5535de01bc18236675bc)
|
||||||
|
|
||||||
|
#### [0.16.2](https://git.odit.services/lfk/frontend/compare/0.16.1...0.16.2)
|
||||||
|
|
||||||
|
> 23 February 2023
|
||||||
|
|
||||||
|
- Fixed scanmodal [`#154`](https://git.odit.services/lfk/frontend/issues/154)
|
||||||
|
- 🚀RELEASE v0.16.2 [`0e85940`](https://git.odit.services/lfk/frontend/commit/0e85940cba292cbccd1ec038aa24f4a719382c19)
|
||||||
|
- Merge pull request 'feature/147-cardoverview_performance' (#153) from feature/147-cardoverview_performance into dev [`8d479c3`](https://git.odit.services/lfk/frontend/commit/8d479c32f82938904aee6a10deb80fea85487e4b)
|
||||||
|
- Merge pull request 'Fixed scanmodal' (#155) from bugfix/154-scan_select_runner_by_id into dev [`549785c`](https://git.odit.services/lfk/frontend/commit/549785cf7d1c9edc1be37dc745b97096232a08ca)
|
||||||
|
- i18n [`ca6da15`](https://git.odit.services/lfk/frontend/commit/ca6da15ef761184a55b18d56f749f660a32cbb83)
|
||||||
|
- Bsic datatable conversion [`757655e`](https://git.odit.services/lfk/frontend/commit/757655ea63b3667bc4612ae1595eb52910b61137)
|
||||||
|
- 1st datatable try with @vincjo/datatables [`81b8fbf`](https://git.odit.services/lfk/frontend/commit/81b8fbf4e341e6f2998a6e9e2053972c5c225021)
|
||||||
|
- Dasboard Cards redesign [`eb1c17e`](https://git.odit.services/lfk/frontend/commit/eb1c17e3ac7e8f5e7310a90421fc9db3ed15c497)
|
||||||
|
- set .phone to null if empty [`da6dd55`](https://git.odit.services/lfk/frontend/commit/da6dd55d139a672fa50204eabdca67d9740614a0)
|
||||||
|
- add group filtering to table [`14d64b6`](https://git.odit.services/lfk/frontend/commit/14d64b6070d98e6368da5709e9ff8221e8a621c7)
|
||||||
|
- formatting [`24d0747`](https://git.odit.services/lfk/frontend/commit/24d074752f1c5dc1a14b075ac14b448d7e129376)
|
||||||
|
- RunnersOverview loading fix [`2e075ea`](https://git.odit.services/lfk/frontend/commit/2e075eafab5c4d78fd9aa9d66834b477b2685bfc)
|
||||||
|
- Added old formatting for runner and status [`df63c23`](https://git.odit.services/lfk/frontend/commit/df63c2388da359dec9ed9968bc9f970be7092a45)
|
||||||
|
- Added custom status filter [`f0a2b28`](https://git.odit.services/lfk/frontend/commit/f0a2b2859fa18426a454b7d9d6dd22dfdfe7ce27)
|
||||||
|
- Basic checkbox fix [`1337676`](https://git.odit.services/lfk/frontend/commit/1337676e0894c46da0b6dcb7553e5ea8f88d0c14)
|
||||||
|
- Fixed all filter [`8dfa19f`](https://git.odit.services/lfk/frontend/commit/8dfa19fa0f9897c61342ece956df88731c7aa861)
|
||||||
|
- improved runner search [`1b0cd5b`](https://git.odit.services/lfk/frontend/commit/1b0cd5b90bcceb92627c6b7cdcdd7792ed81b50f)
|
||||||
|
- set table-layout:fixed + display when loaded [`65e8998`](https://git.odit.services/lfk/frontend/commit/65e89988943807c1606a8b6aea49564b13d52537)
|
||||||
|
- Trigger edit modal [`32ddb66`](https://git.odit.services/lfk/frontend/commit/32ddb66fc8d8cd689f1104759812f4cee4b7a613)
|
||||||
|
- cleaned up table search [`08047a9`](https://git.odit.services/lfk/frontend/commit/08047a93073c32f5dd7a8e958400ae8a5b7f4035)
|
||||||
|
- Fixed edit update bug [`0feee0a`](https://git.odit.services/lfk/frontend/commit/0feee0ae2fb6d8dba0b6fd72cedc0712dc749511)
|
||||||
|
- fix: z-index on action buttons [`224034d`](https://git.odit.services/lfk/frontend/commit/224034dcc6263d3b0a8ea20045e435142d8ed2af)
|
||||||
|
- rename: ThFilterGroup -> ThFilterStatus [`2a6a399`](https://git.odit.services/lfk/frontend/commit/2a6a39916a03c0466e63354e9f5ad7924cb59b6b)
|
||||||
|
- new license file version [CI SKIP] [`0e5490f`](https://git.odit.services/lfk/frontend/commit/0e5490f1c84217a5a6d5c8745c4667b32ca65e1a)
|
||||||
|
- new license file version [CI SKIP] [`026d3d4`](https://git.odit.services/lfk/frontend/commit/026d3d41c1b976a4dc7c733576a6a9e8d4b13b78)
|
||||||
|
- Updated breakpoints [`452d010`](https://git.odit.services/lfk/frontend/commit/452d0101838d72bff7d588a953faae028e2ff819)
|
||||||
|
- Tailwind bump [`a101873`](https://git.odit.services/lfk/frontend/commit/a101873eb0946b284a11a5081642711f5087da14)
|
||||||
|
- Fixed checkbox show [`0900c26`](https://git.odit.services/lfk/frontend/commit/0900c2691e4cfe5046e8ae186c8ac8884c90abd6)
|
||||||
|
- Removed unused console log [`aafc4c8`](https://git.odit.services/lfk/frontend/commit/aafc4c8d62a7a0a493c8bd60149f90c842534bdd)
|
||||||
|
- i18n import [`6fe134a`](https://git.odit.services/lfk/frontend/commit/6fe134afc8bfef4e7470b7e53b9312b172a7322b)
|
||||||
|
- Merge pull request 'fix: RunnerDetail: set .phone to null if empty' (#152) from bugfix/151-runnerdetail--cannot-unset-phone-number into dev [`329c1cc`](https://git.odit.services/lfk/frontend/commit/329c1cc037a43c818ba3b6c72581d29586d76232)
|
||||||
|
- Merge pull request 'feature/146-runner-table-performance-data-table' (#150) from feature/146-runner-table-performance-data-table into dev [`b82d638`](https://git.odit.services/lfk/frontend/commit/b82d638de1aa1f72aada212cf3e4147d808b4fcf)
|
||||||
|
- Merge pull request 'feature/148-dashboard_statscards' (#149) from feature/148-dashboard_statscards into dev [`fd1a06b`](https://git.odit.services/lfk/frontend/commit/fd1a06b3595b3713ad474e623c74105125602d46)
|
||||||
|
- Fixed top checkbox state [`3d2acb6`](https://git.odit.services/lfk/frontend/commit/3d2acb692a28c116790248679e238fb562b24ac5)
|
||||||
|
|
||||||
|
#### [0.16.1](https://git.odit.services/lfk/frontend/compare/0.16.0...0.16.1)
|
||||||
|
|
||||||
|
> 15 February 2023
|
||||||
|
|
||||||
|
- fix: donor detail: sponsorings: unset middlename will show as "null" [`#145`](https://git.odit.services/lfk/frontend/issues/145)
|
||||||
|
- 🚀RELEASE v0.16.1 [`4499480`](https://git.odit.services/lfk/frontend/commit/449948050b8673d43a8dfbb225c3198e4bbb3c7b)
|
||||||
|
|
||||||
|
#### [0.16.0](https://git.odit.services/lfk/frontend/compare/0.15.6...0.16.0)
|
||||||
|
|
||||||
|
> 3 February 2023
|
||||||
|
|
||||||
|
- First page for statsclients [`f299617`](https://git.odit.services/lfk/frontend/commit/f299617c600d2bba7b4405c7c3acae9fd93aefa8)
|
||||||
|
- 🚀RELEASE v0.16.0 [`75684ef`](https://git.odit.services/lfk/frontend/commit/75684efa1ae0edb4b4d414757c5acf2a77c572e5)
|
||||||
|
- Basic statsclient detail [`0215860`](https://git.odit.services/lfk/frontend/commit/02158605be824e5ac21a6284731138190988c794)
|
||||||
|
- Updated Add modal [`f679330`](https://git.odit.services/lfk/frontend/commit/f679330466205e6480cd7f2b7c2b4fdc41c51525)
|
||||||
|
- Switched drone to kaniko [`1c98005`](https://git.odit.services/lfk/frontend/commit/1c980059cff5c87c452428b53513507c2339451f)
|
||||||
|
- Re-added copy modal [`fecb07e`](https://git.odit.services/lfk/frontend/commit/fecb07ee373dcaaeaea69fdf8d4c6ee2c257c89c)
|
||||||
|
- Added Statsclients to sidebar [`068076d`](https://git.odit.services/lfk/frontend/commit/068076dd47373c673a25e730cb8a57c686682810)
|
||||||
|
- Fixed imports and naming [`f3cc07c`](https://git.odit.services/lfk/frontend/commit/f3cc07c009ed0a34e61f1aad47a1a31778145439)
|
||||||
|
- new license file version [CI SKIP] [`2c4f27a`](https://git.odit.services/lfk/frontend/commit/2c4f27a943bb35be6728bb49bd5c2263cba78165)
|
||||||
|
- Merge pull request 'feature/143-beamershow_clients' (#144) from feature/143-beamershow_clients into dev [`53b7dec`](https://git.odit.services/lfk/frontend/commit/53b7dec7cd516c908d45591b855f4be09371f9b1)
|
||||||
|
- Updated deletion modal [`93fc7c2`](https://git.odit.services/lfk/frontend/commit/93fc7c2e83f78dd88f15d9246127bb9e69f1a8ee)
|
||||||
|
- Updated mounted variables [`674e6a9`](https://git.odit.services/lfk/frontend/commit/674e6a90ec23dde9377bea64c14a50e41ffa450d)
|
||||||
|
- Removed Key after creation [`e10c648`](https://git.odit.services/lfk/frontend/commit/e10c6480a504338b21e30fdf2577e5b6c3b635db)
|
||||||
|
- Updated docker base images [`9767553`](https://git.odit.services/lfk/frontend/commit/976755338b8621064f9a73147aa600af1f77cd51)
|
||||||
|
- Added translation [`96c55db`](https://git.odit.services/lfk/frontend/commit/96c55db63dbfed92b78ff0e7bdab7a8cce4d76e9)
|
||||||
|
- Pinned versions [`cff112d`](https://git.odit.services/lfk/frontend/commit/cff112d705a74a135286943298f3f344341325ac)
|
||||||
|
- Tailwind bump [`e0cbfb0`](https://git.odit.services/lfk/frontend/commit/e0cbfb000bee59a71e06bd58a9c7ef6a0fc7091d)
|
||||||
|
- Added missing translation [`19a333d`](https://git.odit.services/lfk/frontend/commit/19a333d7bda525fbcb3c68f3cbf85a4f925a9707)
|
||||||
|
- Bumped apiclient [`c28f1ee`](https://git.odit.services/lfk/frontend/commit/c28f1ee0bc4456595c21858f38e52ed6f16871c5)
|
||||||
|
- new license file version [CI SKIP] [`3a66f4c`](https://git.odit.services/lfk/frontend/commit/3a66f4c862db9f35c223cc7007b0560fef4e1d63)
|
||||||
|
- Bumped apiclient [`28cbc5b`](https://git.odit.services/lfk/frontend/commit/28cbc5b98ca09657100e1740b83aa2617243b26b)
|
||||||
|
- Ignore pnpm lock [`2d8c4c1`](https://git.odit.services/lfk/frontend/commit/2d8c4c1698a1675f618e85e678012f310f87c6ee)
|
||||||
|
|
||||||
|
#### [0.15.6](https://git.odit.services/lfk/frontend/compare/0.15.5...0.15.6)
|
||||||
|
|
||||||
|
> 19 July 2021
|
||||||
|
|
||||||
|
- 🚀RELEASE v0.15.6 [`9fc4ad6`](https://git.odit.services/lfk/frontend/commit/9fc4ad63c4f77b46d645e83c94b51747b91247b8)
|
||||||
|
- Fixed donations getting reduced to the first one on certificates [`2391668`](https://git.odit.services/lfk/frontend/commit/2391668a25a1e11a1409df572d77ad1635070fbc)
|
||||||
|
- new license file version [CI SKIP] [`97054a7`](https://git.odit.services/lfk/frontend/commit/97054a71c1ab8a045762a55148124965c6994373)
|
||||||
|
|
||||||
|
#### [0.15.5](https://git.odit.services/lfk/frontend/compare/0.15.4...0.15.5)
|
||||||
|
|
||||||
|
> 5 July 2021
|
||||||
|
|
||||||
|
- 🚀RELEASE v0.15.5 [`717d335`](https://git.odit.services/lfk/frontend/commit/717d33547c3378424dd720005da9952f8a753f1a)
|
||||||
|
- Merge pull request 'Fixed kilometer conversion' (#142) from bugfix/141-runner_kilometers into dev [`997be32`](https://git.odit.services/lfk/frontend/commit/997be32679dc38c9fb0e92b6ce011057b854d99d)
|
||||||
|
- Fixed kilometer conversion [`134f00c`](https://git.odit.services/lfk/frontend/commit/134f00c40e0c8252e7604a73151e8d6685b2c61d)
|
||||||
|
- new license file version [CI SKIP] [`e752ee1`](https://git.odit.services/lfk/frontend/commit/e752ee12d17a4423f4364f7766eafbe7d4cef2d1)
|
||||||
|
|
||||||
|
#### [0.15.4](https://git.odit.services/lfk/frontend/compare/0.15.3...0.15.4)
|
||||||
|
|
||||||
|
> 5 July 2021
|
||||||
|
|
||||||
|
- Merge pull request 'fix total donation sum in dashboard' (#140) from bugfix/139-total-donation-sum-is-wrong into dev [`#139`](https://git.odit.services/lfk/frontend/issues/139)
|
||||||
|
- 🚀RELEASE v0.15.4 [`cc4515f`](https://git.odit.services/lfk/frontend/commit/cc4515ff66b1c1de3747d0ee6cc465574accedb7)
|
||||||
|
- divide by 100 + toFixes(2) [`b246f2b`](https://git.odit.services/lfk/frontend/commit/b246f2b349b06d1adea318dfad58f97fb1a249bb)
|
||||||
|
|
||||||
|
#### [0.15.3](https://git.odit.services/lfk/frontend/compare/0.15.2...0.15.3)
|
||||||
|
|
||||||
|
> 16 April 2021
|
||||||
|
|
||||||
|
- 🚀RELEASE v0.15.3 [`76b69d8`](https://git.odit.services/lfk/frontend/commit/76b69d851aa590ecf8caac135b72962a72e83635)
|
||||||
|
- Small bugfix (null got displayed) 🛠 [`224f586`](https://git.odit.services/lfk/frontend/commit/224f5863683ae2543a4a435510ed2c558dc5d307)
|
||||||
|
|
||||||
|
#### [0.15.2](https://git.odit.services/lfk/frontend/compare/0.15.1...0.15.2)
|
||||||
|
|
||||||
|
> 16 April 2021
|
||||||
|
|
||||||
|
- 🚀RELEASE v0.15.2 [`9add6c8`](https://git.odit.services/lfk/frontend/commit/9add6c8ff1fbeed91fe97a7cf262921b716f4e3c)
|
||||||
|
- Footer - noopener link [`cee04c1`](https://git.odit.services/lfk/frontend/commit/cee04c1d6fb6005cefe77fb95855ab6fe2cc448f)
|
||||||
|
- Hotfix: Team change recognition 🐞 [`cbec785`](https://git.odit.services/lfk/frontend/commit/cbec78589d2fa21f12ce87e71bff2b49c3a7d345)
|
||||||
|
- NGINX cache assets [`e54a480`](https://git.odit.services/lfk/frontend/commit/e54a4807f70bc333396885f81d3dcc7ae6c115d9)
|
||||||
|
|
||||||
#### [0.15.1](https://git.odit.services/lfk/frontend/compare/0.15.0...0.15.1)
|
#### [0.15.1](https://git.odit.services/lfk/frontend/compare/0.15.0...0.15.1)
|
||||||
|
|
||||||
|
> 16 April 2021
|
||||||
|
|
||||||
|
- 🚀RELEASE v0.15.1 [`a85db7c`](https://git.odit.services/lfk/frontend/commit/a85db7cb3f89881794e37a66ecd822f8ad5873f1)
|
||||||
- Merge pull request '🐞🐳 fix Dockerfile' (#138) from bugfix/136-opacity_reactivity into dev [`2bd3779`](https://git.odit.services/lfk/frontend/commit/2bd3779839de16a89b91a3da93033e2a2b742ab7)
|
- Merge pull request '🐞🐳 fix Dockerfile' (#138) from bugfix/136-opacity_reactivity into dev [`2bd3779`](https://git.odit.services/lfk/frontend/commit/2bd3779839de16a89b91a3da93033e2a2b742ab7)
|
||||||
- 🚚 move to tailwind [`07ac041`](https://git.odit.services/lfk/frontend/commit/07ac041d69b3b1810e5db538b53fe62084490f7a)
|
- 🚚 move to tailwind [`07ac041`](https://git.odit.services/lfk/frontend/commit/07ac041d69b3b1810e5db538b53fe62084490f7a)
|
||||||
- 🐞🐳 fix Dockerfile [`303e33c`](https://git.odit.services/lfk/frontend/commit/303e33cafb4a1be01e4c4b43f46ff0c651cb4620)
|
- 🐞🐳 fix Dockerfile [`303e33c`](https://git.odit.services/lfk/frontend/commit/303e33cafb4a1be01e4c4b43f46ff0c651cb4620)
|
||||||
@@ -1143,7 +1569,7 @@ All notable changes to this project will be documented in this file. Dates are d
|
|||||||
- init [`32357ec`](https://git.odit.services/lfk/frontend/commit/32357ece0a7195ea1135c9c3e4c6c84323f95b4d)
|
- init [`32357ec`](https://git.odit.services/lfk/frontend/commit/32357ece0a7195ea1135c9c3e4c6c84323f95b4d)
|
||||||
- tmp [`1b7173c`](https://git.odit.services/lfk/frontend/commit/1b7173cda9134ee8058a00bdc030defa80d46bfc)
|
- tmp [`1b7173c`](https://git.odit.services/lfk/frontend/commit/1b7173cda9134ee8058a00bdc030defa80d46bfc)
|
||||||
- Login - move to env.js import [`8ef0b21`](https://git.odit.services/lfk/frontend/commit/8ef0b21819309752c573d0485f6514152fb684e6)
|
- Login - move to env.js import [`8ef0b21`](https://git.odit.services/lfk/frontend/commit/8ef0b21819309752c573d0485f6514152fb684e6)
|
||||||
- initial commit [`4bb3bae`](https://git.odit.services/lfk/frontend/commit/4bb3bae4e6fc89c35a8a2b36b7cd6e6d47958eae)
|
- initial commit [`4bb3bae`](https://git.odit.services/lfk/frontend/commit/4bb3bae4e6fc89c35a8a2b36b7cd6e6d47958eae)
|
||||||
- Initial license export [`4c96b9a`](https://git.odit.services/lfk/frontend/commit/4c96b9a3e04dbb7c021c71aa8828a29248509fbe)
|
- Initial license export [`4c96b9a`](https://git.odit.services/lfk/frontend/commit/4c96b9a3e04dbb7c021c71aa8828a29248509fbe)
|
||||||
- 🚚 move to tinro svelte router [`a50ea15`](https://git.odit.services/lfk/frontend/commit/a50ea15b38023b867a9f7757e973184cbcdd2457)
|
- 🚚 move to tinro svelte router [`a50ea15`](https://git.odit.services/lfk/frontend/commit/a50ea15b38023b867a9f7757e973184cbcdd2457)
|
||||||
- new Dashboard [`7270ce9`](https://git.odit.services/lfk/frontend/commit/7270ce9d32869abd4f6ac65ab7c2c87363633cbe)
|
- new Dashboard [`7270ce9`](https://git.odit.services/lfk/frontend/commit/7270ce9d32869abd4f6ac65ab7c2c87363633cbe)
|
||||||
|
|||||||
+10
-7
@@ -1,12 +1,15 @@
|
|||||||
FROM registry.odit.services/hub/library/node:15.14.0-alpine3.13
|
FROM registry.odit.services/hub/library/node:19.7.0-alpine3.16 as build
|
||||||
|
ARG NPM_REGISTRY_URL=https://registry.npmjs.org
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY package.json ./
|
|
||||||
RUN yarn
|
COPY package.json pnpm-lock.yaml *.config.js *.config.cjs index.html ./
|
||||||
COPY package.json *.config.js postcss.config.cjs index.html ./
|
RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@8 && pnpm i
|
||||||
|
|
||||||
COPY src ./src
|
COPY src ./src
|
||||||
COPY public ./public
|
COPY public ./public
|
||||||
RUN yarn build
|
RUN pnpm build
|
||||||
|
|
||||||
# final image
|
# final image
|
||||||
FROM registry.odit.services/hub/fholzer/nginx-brotli:v1.19.1
|
FROM registry.odit.services/library/nginx-brotli:3.15 as final
|
||||||
COPY --from=0 /app/dist /usr/share/nginx/html
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
COPY ./nginx.conf /etc/nginx/nginx.conf
|
COPY ./nginx.conf /etc/nginx/nginx.conf
|
||||||
+1
-1
@@ -13,7 +13,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<span style="display: none;visibility: hidden;" id="buildinfo">RELEASE_INFO-0.15.1-RELEASE_INFO</span>
|
<span style="display: none;visibility: hidden;" id="buildinfo">RELEASE_INFO-1.3.4-RELEASE_INFO</span>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<script src="/env.js"></script>
|
<script src="/env.js"></script>
|
||||||
<script type="module" src="/src/main.js"></script>
|
<script type="module" src="/src/main.js"></script>
|
||||||
|
|||||||
@@ -6,6 +6,11 @@ http {
|
|||||||
server {
|
server {
|
||||||
error_page 404 /index.html;
|
error_page 404 /index.html;
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
|
location /assets {
|
||||||
|
expires 1y;
|
||||||
|
log_not_found off;
|
||||||
|
access_log off;
|
||||||
|
}
|
||||||
location = /index.html {
|
location = /index.html {
|
||||||
add_header Cache-Control 'no-store';
|
add_header Cache-Control 'no-store';
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,4 +1,4 @@
|
|||||||
const fs = require('fs');
|
import fs from 'fs'
|
||||||
// get all language files
|
// get all language files
|
||||||
const files = fs.readdirSync('./src/locales/');
|
const files = fs.readdirSync('./src/locales/');
|
||||||
files.forEach((f) => {
|
files.forEach((f) => {
|
||||||
|
|||||||
+62
-56
@@ -1,56 +1,62 @@
|
|||||||
{
|
{
|
||||||
"name": "@odit/lfk-frontend",
|
"name": "@odit/lfk-frontend",
|
||||||
"version": "0.15.1",
|
"version": "1.3.4",
|
||||||
"scripts": {
|
"type": "module",
|
||||||
"i18n-order": "node order.js",
|
"scripts": {
|
||||||
"dev": "vite",
|
"i18n-order": "node order.js",
|
||||||
"build": "vite build",
|
"dev": "vite",
|
||||||
"release": "release-it",
|
"build": "vite build",
|
||||||
"licenses:export": "license-exporter --json -o public"
|
"release": "release-it",
|
||||||
},
|
"licenses:export": "license-exporter --json -o public"
|
||||||
"license": "CC-BY-NC-SA-4.0",
|
},
|
||||||
"devDependencies": {
|
"license": "CC-BY-NC-SA-4.0",
|
||||||
"@odit/lfk-client-js": "0.11.0",
|
"devDependencies": {
|
||||||
"@odit/license-exporter": "0.0.11",
|
"@odit/license-exporter": "0.0.12",
|
||||||
"@sveltejs/vite-plugin-svelte": "1.0.0-next.6",
|
"@sveltejs/vite-plugin-svelte": "2.0.4",
|
||||||
"@types/html-minifier": "4.0.0",
|
"auto-changelog": "2.4.0",
|
||||||
"auto-changelog": "2.2.1",
|
"autoprefixer": "10.4.14",
|
||||||
"autoprefixer": "^10.2.5",
|
"postcss": "8.4.21",
|
||||||
"check-password-strength": "2.0.2",
|
"release-it": "15.10.1",
|
||||||
"csvtojson": "2.0.10",
|
"svelte-select": "3.17.0",
|
||||||
"gridjs": "3.4.0",
|
"tailwindcss": "3.3.1",
|
||||||
"html-minifier": "4.0.0",
|
"vite": "4.2.1"
|
||||||
"localforage": "1.9.0",
|
},
|
||||||
"marked": "2.0.3",
|
"release-it": {
|
||||||
"postcss": "^8.2.10",
|
"git": {
|
||||||
"release-it": "14.6.1",
|
"commit": true,
|
||||||
"svelte": "3.37.0",
|
"requireCleanWorkingDir": false,
|
||||||
"svelte-focus-trap": "1.2.0",
|
"commitMessage": "🚀RELEASE v${version}",
|
||||||
"svelte-i18n": "3.3.9",
|
"push": true,
|
||||||
"svelte-preprocess": "^4.7.0",
|
"tag": true,
|
||||||
"svelte-select": "3.17.0",
|
"tagName": null,
|
||||||
"tailwindcss": "^2.1.1",
|
"tagAnnotation": "v${version}"
|
||||||
"tinro": "0.6.1",
|
},
|
||||||
"toastify-js": "1.10.0",
|
"npm": {
|
||||||
"validator": "13.5.2",
|
"publish": false
|
||||||
"vite": "2.1.5",
|
},
|
||||||
"xlsx": "0.16.9"
|
"hooks": {
|
||||||
},
|
"after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md && node versionbuilder.js && git add index.html && node order.js && git add src/locales"
|
||||||
"release-it": {
|
}
|
||||||
"git": {
|
},
|
||||||
"commit": true,
|
"dependencies": {
|
||||||
"requireCleanWorkingDir": false,
|
"@odit/lfk-client-js": "1.1.1",
|
||||||
"commitMessage": "🚀RELEASE v${version}",
|
"@paralleldrive/cuid2": "^2.2.0",
|
||||||
"push": false,
|
"@tanstack/svelte-table": "^8.8.5",
|
||||||
"tag": true,
|
"bwip-js": "^3.4.0",
|
||||||
"tagName": null,
|
"check-password-strength": "2.0.7",
|
||||||
"tagAnnotation": "v${version}"
|
"csvtojson": "2.0.10",
|
||||||
},
|
"gridjs": "3.4.0",
|
||||||
"npm": {
|
"localforage": "1.10.0",
|
||||||
"publish": false
|
"marked": "2.0.3",
|
||||||
},
|
"svelte": "3.58.0",
|
||||||
"hooks": {
|
"svelte-french-toast": "1.0.4-beta.0",
|
||||||
"after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md && node versionbuilder.js && git add index.html && node order.js && git add src/locales"
|
"svelte-i18n": "3.6.0",
|
||||||
}
|
"tinro": "0.6.12",
|
||||||
}
|
"toastify-js": "1.12.0",
|
||||||
}
|
"validator": "13.9.0",
|
||||||
|
"xlsx": "0.18.5"
|
||||||
|
},
|
||||||
|
"volta": {
|
||||||
|
"node": "19.7.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
Generated
+3970
File diff suppressed because it is too large.
Load diff
@@ -1 +1 @@
|
|||||||
[{"author":"ODIT.Services","repo":{"type":"git","url":"git+https://git.odit.services/lfk/lfk-client-js"},"description":"A lib to interact with https://git.odit.services/lfk/backend. Use this version for native JS applications.","name":"@odit/lfk-client-js","license":"CC-BY-NC-SA-4.0","version":"0.11.0","licensetext":"Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Creative\r\nCommons Corporation (\"Creative Commons\") is not a law firm and does not provide\r\nlegal services or legal advice. Distribution of Creative Commons public licenses\r\ndoes not create a lawyer-client or other relationship. Creative Commons makes\r\nits licenses and related information available on an \"as-is\" basis. Creative\r\nCommons gives no warranties regarding its licenses, any material licensed\r\nunder their terms and conditions, or any related information. Creative Commons\r\ndisclaims all liability for damages resulting from their use to the fullest\r\nextent possible.\r\n\r\nUsing Creative Commons Public Licenses\r\n\r\nCreative Commons public licenses provide a standard set of terms and conditions\r\nthat creators and other rights holders may use to share original works of\r\nauthorship and other material subject to copyright and certain other rights\r\nspecified in the public license below. The following considerations are for\r\ninformational purposes only, are not exhaustive, and do not form part of our\r\nlicenses.\r\n\r\nConsiderations for licensors: Our public licenses are intended for use by\r\nthose authorized to give the public permission to use material in ways otherwise\r\nrestricted by copyright and certain other rights. Our licenses are irrevocable.\r\nLicensors should read and understand the terms and conditions of the license\r\nthey choose before applying it. Licensors should also secure all rights necessary\r\nbefore applying our licenses so that the public can reuse the material as\r\nexpected. Licensors should clearly mark any material not subject to the license.\r\nThis includes other CC-licensed material, or material used under an exception\r\nor limitation to copyright. More considerations for licensors : wiki.creativecommons.org/Considerations_for_licensors\r\n\r\nConsiderations for the public: By using one of our public licenses, a licensor\r\ngrants the public permission to use the licensed material under specified\r\nterms and conditions. If the licensor's permission is not necessary for any\r\nreason–for example, because of any applicable exception or limitation to copyright–then\r\nthat use is not regulated by the license. Our licenses grant only permissions\r\nunder copyright and certain other rights that a licensor has authority to\r\ngrant. Use of the licensed material may still be restricted for other reasons,\r\nincluding because others have copyright or other rights in the material. A\r\nlicensor may make special requests, such as asking that all changes be marked\r\nor described. Although not required by our licenses, you are encouraged to\r\nrespect those requests where reasonable. More considerations for the public\r\n: wiki.creativecommons.org/Considerations_for_licensees\r\n\r\nCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public\r\nLicense\r\n\r\nBy exercising the Licensed Rights (defined below), You accept and agree to\r\nbe bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-ShareAlike\r\n4.0 International Public License (\"Public License\"). To the extent this Public\r\nLicense may be interpreted as a contract, You are granted the Licensed Rights\r\nin consideration of Your acceptance of these terms and conditions, and the\r\nLicensor grants You such rights in consideration of benefits the Licensor\r\nreceives from making the Licensed Material available under these terms and\r\nconditions.\r\n\r\nSection 1 – Definitions.\r\n\r\na. Adapted Material means material subject to Copyright and Similar Rights\r\nthat is derived from or based upon the Licensed Material and in which the\r\nLicensed Material is translated, altered, arranged, transformed, or otherwise\r\nmodified in a manner requiring permission under the Copyright and Similar\r\nRights held by the Licensor. For purposes of this Public License, where the\r\nLicensed Material is a musical work, performance, or sound recording, Adapted\r\nMaterial is always produced where the Licensed Material is synched in timed\r\nrelation with a moving image.\r\n\r\nb. Adapter's License means the license You apply to Your Copyright and Similar\r\nRights in Your contributions to Adapted Material in accordance with the terms\r\nand conditions of this Public License.\r\n\r\nc. BY-NC-SA Compatible License means a license listed at creativecommons.org/compatiblelicenses,\r\napproved by Creative Commons as essentially the equivalent of this Public\r\nLicense.\r\n\r\nd. Copyright and Similar Rights means copyright and/or similar rights closely\r\nrelated to coLine truncated
|
[{"author":"ODIT.Services","repo":{"type":"git","url":"git+https://git.odit.services/lfk/lfk-client-js"},"description":"A lib to interact with https://git.odit.services/lfk/backend. Use this version for native JS applications.","name":"@odit/lfk-client-js","license":"CC-BY-NC-SA-4.0","version":"1.1.0","licensetext":"Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Creative\r\nCommons Corporation (\"Creative Commons\") is not a law firm and does not provide\r\nlegal services or legal advice. Distribution of Creative Commons public licenses\r\ndoes not create a lawyer-client or other relationship. Creative Commons makes\r\nits licenses and related information available on an \"as-is\" basis. Creative\r\nCommons gives no warranties regarding its licenses, any material licensed\r\nunder their terms and conditions, or any related information. Creative Commons\r\ndisclaims all liability for damages resulting from their use to the fullest\r\nextent possible.\r\n\r\nUsing Creative Commons Public Licenses\r\n\r\nCreative Commons public licenses provide a standard set of terms and conditions\r\nthat creators and other rights holders may use to share original works of\r\nauthorship and other material subject to copyright and certain other rights\r\nspecified in the public license below. The following considerations are for\r\ninformational purposes only, are not exhaustive, and do not form part of our\r\nlicenses.\r\n\r\nConsiderations for licensors: Our public licenses are intended for use by\r\nthose authorized to give the public permission to use material in ways otherwise\r\nrestricted by copyright and certain other rights. Our licenses are irrevocable.\r\nLicensors should read and understand the terms and conditions of the license\r\nthey choose before applying it. Licensors should also secure all rights necessary\r\nbefore applying our licenses so that the public can reuse the material as\r\nexpected. Licensors should clearly mark any material not subject to the license.\r\nThis includes other CC-licensed material, or material used under an exception\r\nor limitation to copyright. More considerations for licensors : wiki.creativecommons.org/Considerations_for_licensors\r\n\r\nConsiderations for the public: By using one of our public licenses, a licensor\r\ngrants the public permission to use the licensed material under specified\r\nterms and conditions. If the licensor's permission is not necessary for any\r\nreason–for example, because of any applicable exception or limitation to copyright–then\r\nthat use is not regulated by the license. Our licenses grant only permissions\r\nunder copyright and certain other rights that a licensor has authority to\r\ngrant. Use of the licensed material may still be restricted for other reasons,\r\nincluding because others have copyright or other rights in the material. A\r\nlicensor may make special requests, such as asking that all changes be marked\r\nor described. Although not required by our licenses, you are encouraged to\r\nrespect those requests where reasonable. More considerations for the public\r\n: wiki.creativecommons.org/Considerations_for_licensees\r\n\r\nCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public\r\nLicense\r\n\r\nBy exercising the Licensed Rights (defined below), You accept and agree to\r\nbe bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-ShareAlike\r\n4.0 International Public License (\"Public License\"). To the extent this Public\r\nLicense may be interpreted as a contract, You are granted the Licensed Rights\r\nin consideration of Your acceptance of these terms and conditions, and the\r\nLicensor grants You such rights in consideration of benefits the Licensor\r\nreceives from making the Licensed Material available under these terms and\r\nconditions.\r\n\r\nSection 1 – Definitions.\r\n\r\na. Adapted Material means material subject to Copyright and Similar Rights\r\nthat is derived from or based upon the Licensed Material and in which the\r\nLicensed Material is translated, altered, arranged, transformed, or otherwise\r\nmodified in a manner requiring permission under the Copyright and Similar\r\nRights held by the Licensor. For purposes of this Public License, where the\r\nLicensed Material is a musical work, performance, or sound recording, Adapted\r\nMaterial is always produced where the Licensed Material is synched in timed\r\nrelation with a moving image.\r\n\r\nb. Adapter's License means the license You apply to Your Copyright and Similar\r\nRights in Your contributions to Adapted Material in accordance with the terms\r\nand conditions of this Public License.\r\n\r\nc. BY-NC-SA Compatible License means a license listed at creativecommons.org/compatiblelicenses,\r\napproved by Creative Commons as essentially the equivalent of this Public\r\nLicense.\r\n\r\nd. Copyright and Similar Rights means copyright and/or similar rights closely\r\nrelated to copLine truncated
|
||||||
@@ -72,6 +72,8 @@
|
|||||||
import Scans from "./components/scans/Scans.svelte";
|
import Scans from "./components/scans/Scans.svelte";
|
||||||
import ScanDetail from "./components/scans/ScanDetail.svelte";
|
import ScanDetail from "./components/scans/ScanDetail.svelte";
|
||||||
import Cards from "./components/cards/Cards.svelte";
|
import Cards from "./components/cards/Cards.svelte";
|
||||||
|
import StatsClients from "./components/statsclients/StatsClients.svelte";
|
||||||
|
import StatsClientDetail from "./components/statsclients/StatsClientDetail.svelte";
|
||||||
store.init();
|
store.init();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -206,6 +208,14 @@
|
|||||||
<ScanStationDetail {params} />
|
<ScanStationDetail {params} />
|
||||||
</Route>
|
</Route>
|
||||||
</Route>
|
</Route>
|
||||||
|
<Route path="/statsclients/*">
|
||||||
|
<Route path="/">
|
||||||
|
<StatsClients />
|
||||||
|
</Route>
|
||||||
|
<Route path="/:clientid" let:params>
|
||||||
|
<StatsClientDetail {params} />
|
||||||
|
</Route>
|
||||||
|
</Route>
|
||||||
<Route path="/about">
|
<Route path="/about">
|
||||||
<About />
|
<About />
|
||||||
</Route>
|
</Route>
|
||||||
|
|||||||
@@ -1,14 +1,16 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import { RunnerCardService } from "@odit/lfk-client-js";
|
import { RunnerCardService } from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
export let bulk_modal_open;
|
export let bulk_modal_open;
|
||||||
export let current_cards;
|
|
||||||
function focus(el) {
|
function focus(el) {
|
||||||
el.focus();
|
el.focus();
|
||||||
}
|
}
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
$: card_count = 0;
|
$: card_count = 0;
|
||||||
$: is_card_count_valid = card_count > 0;
|
$: is_card_count_valid = card_count > 0;
|
||||||
$: processed_last_submit = true;
|
$: processed_last_submit = true;
|
||||||
@@ -34,7 +36,7 @@
|
|||||||
text: $_("creating-blanco-cards"),
|
text: $_("creating-blanco-cards"),
|
||||||
duration: -1,
|
duration: -1,
|
||||||
}).showToast();
|
}).showToast();
|
||||||
RunnerCardService.runnerCardControllerPostBlancoBulk(card_count, false)
|
RunnerCardService.runnerCardControllerPostBlancoBulk(card_count, true)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
bulk_modal_open = false;
|
bulk_modal_open = false;
|
||||||
//
|
//
|
||||||
@@ -43,6 +45,7 @@
|
|||||||
duration: 500,
|
duration: 500,
|
||||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
|
dispatch("created", {cards: result})
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
//
|
//
|
||||||
@@ -71,11 +74,11 @@
|
|||||||
duration: 500,
|
duration: 500,
|
||||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
current_cards = current_cards.concat(result);
|
|
||||||
const toast = Toastify({
|
const toast = Toastify({
|
||||||
text: $_("generating-pdf"),
|
text: $_("generating-pdf"),
|
||||||
duration: -1,
|
duration: -1,
|
||||||
}).showToast();
|
}).showToast();
|
||||||
|
dispatch("created", {cards: result})
|
||||||
fetch(
|
fetch(
|
||||||
`${config.baseurl_documentserver}/cards?&download=true&key=${config.documentserver_key}`,
|
`${config.baseurl_documentserver}/cards?&download=true&key=${config.documentserver_key}`,
|
||||||
{
|
{
|
||||||
@@ -133,7 +136,7 @@
|
|||||||
{#if bulk_modal_open}
|
{#if bulk_modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={() => {
|
on:click_outside={() => {
|
||||||
bulk_modal_open = false;
|
bulk_modal_open = false;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import {
|
import {
|
||||||
RunnerCardService,
|
RunnerCardService,
|
||||||
RunnerService,
|
RunnerService,
|
||||||
@@ -9,24 +9,40 @@
|
|||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
import Select from "svelte-select";
|
import Select from "svelte-select";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
export let modal_open;
|
export let modal_open;
|
||||||
export let current_cards;
|
|
||||||
const getRunnerLabel = (option) =>
|
const dispatch = createEventDispatcher();
|
||||||
option.firstname + " " + (option.middlename || "") + " " + option.lastname;
|
const getRunnerLabel = (option) => {
|
||||||
const filterRunners = (label, filterText, option) =>
|
if (option.middlename) {
|
||||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
return option.firstname + " " + option.middlename + " " + option.lastname;
|
||||||
option.value.toString().startsWith(filterText.toLowerCase());
|
}
|
||||||
|
return option.firstname + " " + option.lastname;
|
||||||
|
};
|
||||||
|
|
||||||
|
const filterRunners = (label, filterText, option) => {
|
||||||
|
if (filterText.startsWith("#")) {
|
||||||
|
return option.value.id == parseInt(filterText.replace("#", ""));
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
|
option.value.toString().startsWith(filterText.toLowerCase())
|
||||||
|
);
|
||||||
|
};
|
||||||
function focus(el) {
|
function focus(el) {
|
||||||
el.focus();
|
el.focus();
|
||||||
}
|
}
|
||||||
$: runner = 0;
|
$: runner = 0;
|
||||||
$: runners = [];
|
|
||||||
$: enabled = true;
|
$: enabled = true;
|
||||||
$: processed_last_submit = true;
|
$: processed_last_submit = true;
|
||||||
|
|
||||||
|
let loading = true;
|
||||||
|
let runners = [];
|
||||||
RunnerService.runnerControllerGetAll().then((val) => {
|
RunnerService.runnerControllerGetAll().then((val) => {
|
||||||
runners = val.map((r) => {
|
runners = val.map((r) => {
|
||||||
return { label: getRunnerLabel(r), value: r };
|
return { label: getRunnerLabel(r), value: r };
|
||||||
});
|
});
|
||||||
|
loading = false;
|
||||||
});
|
});
|
||||||
$: createbtnenabled = true;
|
$: createbtnenabled = true;
|
||||||
(() => {
|
(() => {
|
||||||
@@ -64,8 +80,7 @@
|
|||||||
duration: 500,
|
duration: 500,
|
||||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
current_cards.push(result);
|
dispatch("created", { cards: [result] });
|
||||||
current_cards = current_cards;
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
//
|
//
|
||||||
@@ -82,65 +97,81 @@
|
|||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={() => {
|
on:click_outside={() => {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
||||||
|
>
|
||||||
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
<div
|
<div
|
||||||
class="absolute inset-0 bg-gray-500 opacity-75"
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
data-id="modal_backdrop" />
|
data-id="modal_backdrop"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
aria-hidden="true">​</span>
|
aria-hidden="true">​</span
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
aria-labelledby="modal-headline">
|
aria-labelledby="modal-headline"
|
||||||
|
>
|
||||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
<div class="sm:flex sm:items-start">
|
<div class="sm:flex sm:items-start">
|
||||||
<div
|
<div
|
||||||
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
||||||
|
>
|
||||||
<svg
|
<svg
|
||||||
class="h-6 w-6 text-blue-600"
|
class="h-6 w-6 text-blue-600"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
height="24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
d="M22 10v10a1 1 0 01-1 1H3a1 1 0 01-1-1V10h20zm0-2H2V4a1 1 0 011-1h18a1 1 0 011 1v4zm-7 8v2h4v-2h-4z" /></svg>
|
d="M22 10v10a1 1 0 01-1 1H3a1 1 0 01-1-1V10h20zm0-2H2V4a1 1 0 011-1h18a1 1 0 011 1v4zm-7 8v2h4v-2h-4z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
{$_('create-a-new-card')}
|
{$_("create-a-new-card")}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="mt-2 mb-6">
|
<div class="mt-2 mb-6">
|
||||||
<p class="text-sm text-gray-500">
|
<p class="text-sm text-gray-500">
|
||||||
{$_('you-can-provide-a-runner-but-you-dont-have-to')}
|
{$_("you-can-provide-a-runner-but-you-dont-have-to")}
|
||||||
{$_('if-you-want-to-create-multiple-blanco-cards-try-the-add-bulk-button')}
|
{$_(
|
||||||
|
"if-you-want-to-create-multiple-blanco-cards-try-the-add-bulk-button"
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-6 gap-6">
|
<div class="grid grid-cols-6 gap-6">
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
<label
|
<label
|
||||||
for="donor"
|
for="donor"
|
||||||
class="block text-sm font-medium text-gray-700">{$_('runner')}</label>
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>{$_("runner")}</label
|
||||||
|
>
|
||||||
<Select
|
<Select
|
||||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
itemFilter={(label, filterText, option) => filterRunners(label, filterText, option)}
|
itemFilter={(label, filterText, option) =>
|
||||||
|
filterRunners(label, filterText, option)}
|
||||||
items={runners}
|
items={runners}
|
||||||
showChevron={true}
|
bind:loading
|
||||||
placeholder={$_('search-for-runner-by-name-or-id')}
|
showChevron={!loading}
|
||||||
noOptionsMessage={$_('no-runners-found')}
|
placeholder={$_("search-for-runner-by-name-or-id")}
|
||||||
on:select={(selectedValue) => (runner = selectedValue.detail.value.id)}
|
noOptionsMessage={$_("no-runners-found")}
|
||||||
on:clear={() => (runner = null)} />
|
on:select={(selectedValue) =>
|
||||||
|
(runner = selectedValue.detail.value.id)}
|
||||||
|
on:clear={() => (runner = null)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -152,16 +183,18 @@
|
|||||||
class:opacity-50={!createbtnenabled}
|
class:opacity-50={!createbtnenabled}
|
||||||
on:click={submit}
|
on:click={submit}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
{$_('create')}
|
>
|
||||||
|
{$_("create")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
|
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
{$_('cancel')}
|
>
|
||||||
|
{$_("cancel")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,26 +1,34 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import { RunnerCardService, RunnerService } from "@odit/lfk-client-js";
|
import { RunnerCardService, RunnerService } from "@odit/lfk-client-js";
|
||||||
import Select from "svelte-select";
|
import Select from "svelte-select";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
export let edit_modal_open;
|
export let edit_modal_open;
|
||||||
export let current_cards;
|
|
||||||
export let runner = {};
|
export let runner = {};
|
||||||
export let editable = {};
|
export let editable = {};
|
||||||
export let original_data = {};
|
export let original_data = {};
|
||||||
const getRunnerLabel = (option) =>
|
const getRunnerLabel = (option) =>
|
||||||
option.firstname + " " + (option.middlename || "") + " " + option.lastname;
|
option.firstname + " " + (option.middlename || "") + " " + option.lastname;
|
||||||
const filterRunners = (label, filterText, option) =>
|
const filterRunners = (label, filterText, option) => {
|
||||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
if (filterText.startsWith("#")) {
|
||||||
option.value.toString().startsWith(filterText.toLowerCase());
|
return option.value.id == parseInt(filterText.replace("#",""))
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
|
option.value.toString().startsWith(filterText.toLowerCase())
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
function focus(el) {
|
function focus(el) {
|
||||||
el.focus();
|
el.focus();
|
||||||
}
|
}
|
||||||
$: runners = [];
|
$: runners = [];
|
||||||
$: enabled = true;
|
$: enabled = true;
|
||||||
$: processed_last_submit = true;
|
$: processed_last_submit = true;
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
RunnerService.runnerControllerGetAll().then((val) => {
|
RunnerService.runnerControllerGetAll().then((val) => {
|
||||||
runners = val.map((r) => {
|
runners = val.map((r) => {
|
||||||
return { label: getRunnerLabel(r), value: r };
|
return { label: getRunnerLabel(r), value: r };
|
||||||
@@ -63,8 +71,7 @@
|
|||||||
duration: 500,
|
duration: 500,
|
||||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
current_cards[current_cards.findIndex((c) => c.id === id)] = result;
|
dispatch('dataUpdated', {card: result});
|
||||||
current_cards = current_cards;
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
//
|
//
|
||||||
@@ -81,7 +88,7 @@
|
|||||||
{#if edit_modal_open}
|
{#if edit_modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={() => {
|
on:click_outside={() => {
|
||||||
edit_modal_open = false;
|
edit_modal_open = false;
|
||||||
|
|||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
export let runner;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if !runner}
|
||||||
|
{$_("non-blanko")}
|
||||||
|
{:else}
|
||||||
|
<a href={`/runners/${runner.id}`}>
|
||||||
|
{#if runner.middlename}
|
||||||
|
{runner.firstname} {runner.middlename} {runner.lastname}
|
||||||
|
{:else}
|
||||||
|
{runner.firstname} {runner.lastname}
|
||||||
|
{/if}
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
export let enabled = false;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if enabled}
|
||||||
|
<span
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"
|
||||||
|
>{$_("enabled")}</span
|
||||||
|
>
|
||||||
|
{:else}
|
||||||
|
<span
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800"
|
||||||
|
>{$_("disabled")}</span
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
@@ -7,34 +7,48 @@
|
|||||||
$: current_cards = [];
|
$: current_cards = [];
|
||||||
export let modal_open = false;
|
export let modal_open = false;
|
||||||
export let bulk_modal_open = false;
|
export let bulk_modal_open = false;
|
||||||
|
let addCards;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_('cards')}
|
{$_("cards")}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('CARD:CREATE')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:CREATE")}
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
modal_open = true;
|
modal_open = true;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
{$_('add-card')}
|
>
|
||||||
|
{$_("add-card")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
bulk_modal_open = true;
|
bulk_modal_open = true;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
{$_('create-bulk-cards')}
|
>
|
||||||
|
{$_("create-bulk-cards")}
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
<CardsOverview bind:current_cards />
|
<CardsOverview bind:current_cards bind:addCards />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('CARD:CREATE')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:CREATE")}
|
||||||
<AddCardModal bind:current_cards bind:modal_open />
|
<AddCardModal
|
||||||
<AddCardBulkModal bind:current_cards bind:bulk_modal_open />
|
bind:modal_open
|
||||||
|
on:created={(event) => {
|
||||||
|
console.log(event)
|
||||||
|
addCards(event.detail.cards);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<AddCardBulkModal
|
||||||
|
bind:bulk_modal_open
|
||||||
|
on:created={(event) => {
|
||||||
|
addCards(event.detail.cards);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -2,280 +2,313 @@
|
|||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { RunnerCardService } from "@odit/lfk-client-js";
|
import { RunnerCardService } from "@odit/lfk-client-js";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import Toastify from "toastify-js";
|
import toast from "svelte-french-toast";
|
||||||
import CardsEmptyState from "./CardsEmptyState.svelte";
|
import CardsEmptyState from "./CardsEmptyState.svelte";
|
||||||
import CardDetailModal from "./CardDetailModal.svelte";
|
import CardDetailModal from "./CardDetailModal.svelte";
|
||||||
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
||||||
|
import InputElement from "../shared/InputElement.svelte";
|
||||||
|
import {
|
||||||
|
createSvelteTable,
|
||||||
|
flexRender,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
renderComponent,
|
||||||
|
} from "@tanstack/svelte-table";
|
||||||
|
import { writable } from "svelte/store";
|
||||||
|
import TableBottom from "../shared/TableBottom.svelte";
|
||||||
|
import TableActions from "../shared/TableActions.svelte";
|
||||||
|
import TableHeader from "../shared/TableHeader.svelte";
|
||||||
|
import CardStatus from "./CardStatus.svelte";
|
||||||
|
import CardRunner from "./CardRunner.svelte";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import { runnerFilter, statusFilter } from "../shared/tablefilters";
|
||||||
|
import DeleteCardModal from "./DeleteCardModal.svelte";
|
||||||
|
|
||||||
export let edit_modal_open = false;
|
export let edit_modal_open = false;
|
||||||
export let runner = {};
|
export let runner = {};
|
||||||
export let editable = {};
|
export let editable = {};
|
||||||
export let original_data = {};
|
export let original_data = {};
|
||||||
export let current_cards = [];
|
export let current_cards = [];
|
||||||
$: filtered_cards = current_cards.filter(function (c) {
|
export const addCards = (cards) => {
|
||||||
if (
|
console.log(cards);
|
||||||
c.code.toLowerCase().includes(searchvalue_lowercase) ||
|
current_cards = current_cards.concat(...cards);
|
||||||
c.runner?.firstname.toLowerCase().includes(searchvalue_lowercase) ||
|
options.update((options) => ({
|
||||||
c.runner?.middlename.toLowerCase().includes(searchvalue_lowercase) ||
|
...options,
|
||||||
c.runner?.lastname.toLowerCase().includes(searchvalue_lowercase) ||
|
data: current_cards,
|
||||||
should_display_based_on_id(c.id)
|
}));
|
||||||
) {
|
};
|
||||||
return true;
|
|
||||||
}
|
$: dataLoaded = false;
|
||||||
|
$: selected =
|
||||||
|
$table?.getSelectedRowModel().rows.map((row) => row.index) || [];
|
||||||
|
$: selectedCards =
|
||||||
|
$table?.getSelectedRowModel().rows.map((row) => row.original) || [];
|
||||||
|
$: active_delete = undefined;
|
||||||
|
$: cards_show = generate_cards.length > 0;
|
||||||
|
$: generate_cards = [];
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
accessorKey: "code",
|
||||||
|
header: () => $_("code"),
|
||||||
|
filterFn: `includesString`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "runner",
|
||||||
|
header: () => $_("runner"),
|
||||||
|
cell: (info) => {
|
||||||
|
return renderComponent(CardRunner, { runner: info.getValue() });
|
||||||
|
},
|
||||||
|
filterFn: `runner`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "enabled",
|
||||||
|
cell: (info) => {
|
||||||
|
return renderComponent(CardStatus, { enabled: info.getValue() });
|
||||||
|
},
|
||||||
|
header: () => $_("status"),
|
||||||
|
filterFn: `status`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "actions",
|
||||||
|
header: () => $_("action"),
|
||||||
|
cell: (info) => {
|
||||||
|
return renderComponent(TableActions, {
|
||||||
|
detailsAction: () => {
|
||||||
|
open_edit_modal(
|
||||||
|
current_cards[
|
||||||
|
current_cards.findIndex((r) => r.id == info.row.original.id)
|
||||||
|
]
|
||||||
|
);
|
||||||
|
},
|
||||||
|
deleteAction: () => {
|
||||||
|
active_delete =
|
||||||
|
current_cards[
|
||||||
|
current_cards.findIndex((r) => r.id == info.row.original.id)
|
||||||
|
];
|
||||||
|
},
|
||||||
|
deleteEnabled:
|
||||||
|
store.state.jwtinfo.userdetails.permissions.includes("CARD:DELETE"),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
enableSorting: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
const options = writable({
|
||||||
|
data: [],
|
||||||
|
columns: columns,
|
||||||
|
initialState: {
|
||||||
|
pagination: {
|
||||||
|
pageSize: 50,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
filterFns: {
|
||||||
|
runner: runnerFilter,
|
||||||
|
status: statusFilter,
|
||||||
|
},
|
||||||
|
enableRowSelection: true,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
});
|
});
|
||||||
$: searchvalue = "";
|
|
||||||
$: searchvalue_lowercase = searchvalue.toLowerCase();
|
const table = createSvelteTable(options);
|
||||||
$: active_deletes = [];
|
|
||||||
$: cards_show = current_cards.some((r) => r.is_selected === true);
|
|
||||||
$: generate_cards = current_cards.filter((r) => r.is_selected === true);
|
|
||||||
const cards_promise = RunnerCardService.runnerCardControllerGetAll().then(
|
|
||||||
(val) => {
|
|
||||||
current_cards = val;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
function should_display_based_on_id(id) {
|
|
||||||
if (searchvalue.toString().slice(-1) === "*") {
|
|
||||||
return id.toString().startsWith(searchvalue.replace("*", ""));
|
|
||||||
}
|
|
||||||
return id.toString() === searchvalue;
|
|
||||||
}
|
|
||||||
const getRunnerLabel = (option) =>
|
|
||||||
option?.firstname + " " + (option?.middlename || "") + " " + (option?.lastname || "{$_('non-blanko')}");
|
|
||||||
function open_edit_modal(card) {
|
function open_edit_modal(card) {
|
||||||
if(card.runner?.id){
|
const getRunnerLabel = (option) =>
|
||||||
|
option.firstname +
|
||||||
|
" " +
|
||||||
|
(option.middlename || "") +
|
||||||
|
" " +
|
||||||
|
option.lastname;
|
||||||
|
if (card.runner?.id) {
|
||||||
runner = Object.assign(
|
runner = Object.assign(
|
||||||
{ runner },
|
{ runner },
|
||||||
{ label: getRunnerLabel(card.runner), value: card.runner }
|
{ label: getRunnerLabel(card.runner), value: card.runner }
|
||||||
);
|
);
|
||||||
card.runner = card.runner.id;
|
card.runner = card.runner.id;
|
||||||
}
|
} else {
|
||||||
else{
|
card.runner = null;
|
||||||
card.runner=null;
|
runner = null;
|
||||||
runner = null
|
|
||||||
}
|
}
|
||||||
editable = Object.assign(editable, card);
|
editable = Object.assign(editable, card);
|
||||||
original_data = Object.assign(original_data, card);
|
original_data = Object.assign(original_data, card);
|
||||||
edit_modal_open = true;
|
edit_modal_open = true;
|
||||||
}
|
}
|
||||||
// -----------------
|
|
||||||
let scrollTop = 0;
|
async function deleteCard(delete_card_id) {
|
||||||
$: rendered = filtered_cards;
|
await RunnerCardService.runnerCardControllerRemove(delete_card_id, true);
|
||||||
let innerHeight = 0;
|
current_cards = current_cards.filter((r) => r.id !== delete_card_id);
|
||||||
let ele;
|
options.update((options) => ({
|
||||||
$: updateSlice(scrollTop);
|
...options,
|
||||||
$: innerHeight = `${filtered_cards.length * 25}px`;
|
data: current_cards,
|
||||||
$: if (ele) updateSlice();
|
}));
|
||||||
function updateSlice() {
|
toast.success($_("card-deleted"));
|
||||||
const height = ele ? parseInt(ele.clientHeight) : 100;
|
|
||||||
const init = scrollTop / 25;
|
|
||||||
const end = Math.ceil((scrollTop + height) / 25);
|
|
||||||
rendered = filtered_cards.slice(init, end + 15);
|
|
||||||
}
|
|
||||||
function updateScroll($event) {
|
|
||||||
scrollTop = $event.target.scrollTop;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
toast.loading("Karten werden geladen...");
|
||||||
|
let page = 0;
|
||||||
|
while (page >= 0) {
|
||||||
|
const cards = await RunnerCardService.runnerCardControllerGetAll(
|
||||||
|
page,
|
||||||
|
500
|
||||||
|
);
|
||||||
|
if (cards.length == 0) {
|
||||||
|
page = -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_cards = current_cards.concat(...cards);
|
||||||
|
options.update((options) => ({
|
||||||
|
...options,
|
||||||
|
data: current_cards,
|
||||||
|
}));
|
||||||
|
|
||||||
|
dataLoaded = true;
|
||||||
|
page++;
|
||||||
|
}
|
||||||
|
toast.dismiss();
|
||||||
|
toast.success("All cards loaded");
|
||||||
|
console.log("All cards loaded");
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<style>
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:UPDATE")}
|
||||||
table tbody {
|
|
||||||
display: block;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
table thead, table tbody tr {
|
|
||||||
display: table;
|
|
||||||
width: 100%;
|
|
||||||
table-layout: fixed;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('CARD:UPDATE')}
|
|
||||||
<CardDetailModal
|
<CardDetailModal
|
||||||
bind:current_cards
|
|
||||||
bind:edit_modal_open
|
bind:edit_modal_open
|
||||||
bind:runner
|
bind:runner
|
||||||
bind:editable
|
bind:editable
|
||||||
bind:original_data />
|
bind:original_data
|
||||||
|
on:dataUpdated={(event) => {
|
||||||
|
current_cards[
|
||||||
|
current_cards.findIndex((c) => c.id === event.detail.card.id)
|
||||||
|
] = event.detail.card;
|
||||||
|
current_cards = current_cards;
|
||||||
|
options.update((options) => ({
|
||||||
|
...options,
|
||||||
|
data: current_cards,
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('CARD:GET')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:GET")}
|
||||||
{#await cards_promise}
|
<DeleteCardModal
|
||||||
|
delete_card={active_delete}
|
||||||
|
modal_open={active_delete != undefined}
|
||||||
|
on:delete={(event) => {
|
||||||
|
deleteCard(event.detail.id);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{#if !dataLoaded}
|
||||||
<div
|
<div
|
||||||
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
||||||
role="alert">
|
role="alert"
|
||||||
<p class="font-bold">{$_('loading-cards')}</p>
|
>
|
||||||
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
<p class="font-bold">{$_("loading-cards")}</p>
|
||||||
|
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
||||||
</div>
|
</div>
|
||||||
{:then}
|
{:else if current_cards.length === 0}
|
||||||
{#if current_cards.length === 0}
|
<CardsEmptyState />
|
||||||
<CardsEmptyState />
|
{:else}
|
||||||
{:else}
|
<div class="h-12 mt-1">
|
||||||
<input
|
{#if selected.length > 0}
|
||||||
type="search"
|
<button
|
||||||
bind:value={searchvalue}
|
type="button"
|
||||||
placeholder={$_('datatable.search')}
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm inline-flex"
|
||||||
aria-label={$_('datatable.search')}
|
id="options-menu"
|
||||||
class="gridjs-input gridjs-search-input mb-4" />
|
on:click={async () => {
|
||||||
<div class="h-12">
|
const prom = [];
|
||||||
<GenerateRunnerCards
|
for (const card of selectedCards) {
|
||||||
bind:cards_show
|
prom.push(
|
||||||
bind:generate_cards />
|
await RunnerCardService.runnerCardControllerRemove(
|
||||||
</div>
|
card.id,
|
||||||
<div
|
true
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
)
|
||||||
<table class="divide-y divide-gray-200 w-full">
|
);
|
||||||
<thead class="bg-gray-50">
|
}
|
||||||
<tr>
|
await Promise.all(prom);
|
||||||
<th
|
for (const card of selectedCards) {
|
||||||
scope="col"
|
current_cards = current_cards.filter((r) => r.id !== card.id);
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
}
|
||||||
<span
|
options.update((options) => ({
|
||||||
on:click={() => {
|
...options,
|
||||||
const newstate = !current_cards.some((r) => r.is_selected === true);
|
data: current_cards,
|
||||||
current_cards = current_cards.map((r) => {
|
}));
|
||||||
r.is_selected = newstate;
|
$table.resetRowSelection();
|
||||||
return r;
|
}}
|
||||||
});
|
>
|
||||||
}}
|
{$_("delete-cards")}
|
||||||
class="underline cursor-pointer select-none">{#if current_cards.some((r) => r.is_selected === true)}
|
<svg
|
||||||
{$_('deselect-all')}
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
{:else}{$_('select-all')}{/if}
|
fill="none"
|
||||||
</span>
|
viewBox="0 0 24 24"
|
||||||
</th>
|
stroke-width="1.5"
|
||||||
<th
|
stroke="currentColor"
|
||||||
scope="col"
|
class="w-5 h-5"
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('code')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('runner')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('status')}
|
|
||||||
</th>
|
|
||||||
<th scope="col" class="relative px-6 py-3">
|
|
||||||
<span class="sr-only">{$_('action')}</span>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody class="divide-y divide-gray-200 virtual-wrapper"
|
|
||||||
on:scroll={updateScroll}
|
|
||||||
style="height: 70vh; width:100%"
|
|
||||||
bind:this={ele}
|
|
||||||
>
|
>
|
||||||
{#each filtered_cards as card, index}
|
<path
|
||||||
{#if card.code
|
stroke-linecap="round"
|
||||||
.toLowerCase()
|
stroke-linejoin="round"
|
||||||
.includes(
|
d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"
|
||||||
searchvalue.toLowerCase()
|
/>
|
||||||
) || card.runner?.firstname
|
</svg>
|
||||||
.toLowerCase()
|
</button>
|
||||||
.includes(
|
{/if}
|
||||||
searchvalue.toLowerCase()
|
<GenerateRunnerCards
|
||||||
) || card.runner?.middlename
|
cards_show={selected.length > 0}
|
||||||
.toLowerCase()
|
bind:generate_cards={selectedCards}
|
||||||
.includes(
|
/>
|
||||||
searchvalue.toLowerCase()
|
|
||||||
) || card.runner?.lastname
|
|
||||||
.toLowerCase()
|
|
||||||
.includes(
|
|
||||||
searchvalue.toLowerCase()
|
|
||||||
) || should_display_based_on_id(card.id)}
|
|
||||||
<tr data-rowid="card_{card.id}">
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<input
|
|
||||||
bind:checked={card.is_selected}
|
|
||||||
type="checkbox"
|
|
||||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" />
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<div class="flex items-center">{card.code}</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<div class="flex items-center">
|
|
||||||
{#if card.runner}
|
|
||||||
<a
|
|
||||||
href="../runners/{card.runner.id}"
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{card.runner.firstname}
|
|
||||||
{card.runner.middlename || ''}
|
|
||||||
{card.runner.lastname}</a>
|
|
||||||
{:else}{$_('non-blanko')}{/if}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<div class="flex items-center">
|
|
||||||
{#if card.enabled}
|
|
||||||
<span
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">{$_('enabled')}</span>
|
|
||||||
{:else}
|
|
||||||
<span
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">{$_('disabled')}</span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
{#if active_deletes[card.id] === true}
|
|
||||||
<td
|
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[card.id] = false;
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">{$_('cancel-delete')}</button>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
RunnerCardService.runnerCardControllerRemove(card.id, false).then(
|
|
||||||
(resp) => {
|
|
||||||
current_cards = current_cards.filter(
|
|
||||||
(obj) => obj.id !== card.id
|
|
||||||
);
|
|
||||||
Toastify({
|
|
||||||
text: $_('card-deleted'),
|
|
||||||
duration: 500,
|
|
||||||
backgroundColor:
|
|
||||||
'linear-gradient(to right, #00b09b, #96c93d)',
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('confirm-delete')}</button>
|
|
||||||
</td>
|
|
||||||
{:else}
|
|
||||||
<td
|
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
open_edit_modal(card);
|
|
||||||
}}
|
|
||||||
class="text-indigo-600 hover:text-indigo-900">{$_('details')}</button>
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('CARD:DELETE')}
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[card.id] = true;
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
{/if}
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{:catch error}
|
|
||||||
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
|
|
||||||
<span class="inline-block align-middle mr-8">
|
|
||||||
<b class="capitalize">{$_('general_promise_error')}</b>
|
|
||||||
{error}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
{/await}
|
<div class="overflow-x-auto">
|
||||||
|
<table class="w-full">
|
||||||
|
<thead>
|
||||||
|
{#each $table.getHeaderGroups() as headerGroup}
|
||||||
|
<tr class="select-none">
|
||||||
|
<th class="inset-y-0 left-0 px-4 py-2 text-left w-px">
|
||||||
|
<InputElement
|
||||||
|
type="checkbox"
|
||||||
|
checked={$table.getIsAllRowsSelected()}
|
||||||
|
indeterminate={$table.getIsSomeRowsSelected()}
|
||||||
|
on:change={() => $table.toggleAllRowsSelected()}
|
||||||
|
/>
|
||||||
|
</th>
|
||||||
|
{#each headerGroup.headers as header}
|
||||||
|
<TableHeader {header} />
|
||||||
|
{/each}
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#each $table.getRowModel().rows as row}
|
||||||
|
<tr>
|
||||||
|
<td class="inset-y-0 left-0 px-4 py-2 text-center w-px">
|
||||||
|
<InputElement
|
||||||
|
type="checkbox"
|
||||||
|
checked={row.getIsSelected()}
|
||||||
|
on:change={() => row.toggleSelected()}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
{#each row.getVisibleCells() as cell}
|
||||||
|
<td>
|
||||||
|
<svelte:component
|
||||||
|
this={flexRender(
|
||||||
|
cell.column.columnDef.cell,
|
||||||
|
cell.getContext()
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
{/each}
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<TableBottom {table} {selected} />
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
@@ -0,0 +1,128 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import { clickOutside } from "../base/outsideclick";
|
||||||
|
import { createEventDispatcher, onMount } from "svelte";
|
||||||
|
export let modal_open;
|
||||||
|
export let delete_card = {
|
||||||
|
id: 0,
|
||||||
|
code: "",
|
||||||
|
runner: {
|
||||||
|
firstname: "",
|
||||||
|
lastname: "",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
onMount(() => {
|
||||||
|
document.onkeydown = (e) => {
|
||||||
|
e = e || window.event;
|
||||||
|
if (e.key === "Escape") {
|
||||||
|
modal_open = false;
|
||||||
|
}
|
||||||
|
if (e.keyCode === 13) {
|
||||||
|
if (createbtnenabled === true) {
|
||||||
|
createbtnenabled = false;
|
||||||
|
submit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
async function submit() {
|
||||||
|
dispatch("delete", { id: delete_card.id });
|
||||||
|
modal_open = false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if modal_open}
|
||||||
|
<div
|
||||||
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
|
use:clickOutside
|
||||||
|
on:click_outside={() => {
|
||||||
|
modal_open = false;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
||||||
|
>
|
||||||
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
|
data-id="modal_backdrop"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
|
aria-hidden="true">​</span
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby="modal-headline"
|
||||||
|
>
|
||||||
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
|
<div class="sm:flex sm:items-start">
|
||||||
|
<div
|
||||||
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="h-6 w-6 text-blue-600"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M22 10v10a1 1 0 01-1 1H3a1 1 0 01-1-1V10h20zm0-2H2V4a1 1 0 011-1h18a1 1 0 011 1v4zm-7 8v2h4v-2h-4z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
{$_("confirm-delete")}
|
||||||
|
</h3>
|
||||||
|
<div class="mt-2 mb-6">
|
||||||
|
<p class="text-sm text-gray-500">
|
||||||
|
{$_("please-confirm-the-deletion-of-card")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="w-full">
|
||||||
|
{$_("card")} #{delete_card.code}<br />
|
||||||
|
<span class="inline-block">
|
||||||
|
{$_("runner")}:
|
||||||
|
{#if delete_card.runner}
|
||||||
|
<span class="inline-block"
|
||||||
|
>{delete_card.runner.firstname}
|
||||||
|
{delete_card.runner.lastname}</span
|
||||||
|
>
|
||||||
|
{:else}
|
||||||
|
{$_("non-blanko")}
|
||||||
|
{/if}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||||
|
<button
|
||||||
|
on:click={submit}
|
||||||
|
type="button"
|
||||||
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>
|
||||||
|
{$_("delete")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
modal_open = false;
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>
|
||||||
|
{$_("cancel")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
<script>
|
||||||
|
export let handler;
|
||||||
|
let filterValue = "";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<th>
|
||||||
|
<input
|
||||||
|
on:input={() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const v = filterValue.toLowerCase();
|
||||||
|
handler.filter(v, (c) => {
|
||||||
|
// if (v === "") {
|
||||||
|
// return c;
|
||||||
|
// }
|
||||||
|
|
||||||
|
if (!c.runner && v === "blanko") {
|
||||||
|
return "blanko";
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v.startsWith("#")) {
|
||||||
|
return `#${c.runner?.id}`;
|
||||||
|
}
|
||||||
|
if (c.runner) {
|
||||||
|
let runnerName = `${c.runner.firstname} ${c.runner.lastname}`;
|
||||||
|
if (c.runner.middlename) {
|
||||||
|
runnerName = `${c.runner.firstname} ${c.runner.middlename} ${c.runner.lastname}`;
|
||||||
|
}
|
||||||
|
runnerName = runnerName.toLowerCase();
|
||||||
|
return runnerName;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
}, 150);
|
||||||
|
}}
|
||||||
|
bind:value={filterValue}
|
||||||
|
type="text"
|
||||||
|
name="runnerfilter"
|
||||||
|
id="runnerfilter"
|
||||||
|
/>
|
||||||
|
</th>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
th {
|
||||||
|
border-bottom: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
margin: -1px 0 0 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 24px;
|
||||||
|
border: none;
|
||||||
|
text-align: left;
|
||||||
|
background: inherit;
|
||||||
|
outline: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,45 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
export let handler;
|
||||||
|
let selected = "all";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<th>
|
||||||
|
<select
|
||||||
|
on:input={() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (`${selected}`.trim()) {
|
||||||
|
if (selected === "all") {
|
||||||
|
handler.filter("", "enabled");
|
||||||
|
} else {
|
||||||
|
handler.filter(selected, "enabled");
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}, 50);
|
||||||
|
}}
|
||||||
|
bind:value={selected}
|
||||||
|
name="statusfilter"
|
||||||
|
id="statusfilter"
|
||||||
|
>
|
||||||
|
<option value="all">{$_("all")}</option>
|
||||||
|
<option value="true">{$_("enabled")}</option>
|
||||||
|
<option value="false">{$_("disabled")}</option>
|
||||||
|
</select>
|
||||||
|
</th>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
th {
|
||||||
|
border-bottom: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
select {
|
||||||
|
margin: -1px 0 0 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 24px;
|
||||||
|
border: none;
|
||||||
|
text-align: left;
|
||||||
|
background: inherit;
|
||||||
|
outline: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import {
|
import {
|
||||||
GroupContactService,
|
GroupContactService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
@@ -145,7 +145,7 @@
|
|||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={() => {
|
on:click_outside={() => {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
bind:value={searchvalue}
|
bind:value={searchvalue}
|
||||||
placeholder={$_('datatable.search')}
|
placeholder={$_('datatable.search')}
|
||||||
aria-label={$_('datatable.search')}
|
aria-label={$_('datatable.search')}
|
||||||
class="gridjs-input gridjs-search-input mb-4" />
|
class="mb-4" />
|
||||||
<div
|
<div
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
||||||
<table class="divide-y divide-gray-200 w-full">
|
<table class="divide-y divide-gray-200 w-full">
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
import { router } from "tinro";
|
import { router } from "tinro";
|
||||||
import NoComponentLoaded from "../base/NoComponentLoaded.svelte";
|
import NoComponentLoaded from "../base/NoComponentLoaded.svelte";
|
||||||
import { AuthService } from "@odit/lfk-client-js";
|
import { AuthService } from "@odit/lfk-client-js";
|
||||||
|
import { Toaster } from 'svelte-french-toast';
|
||||||
$: navOpen = false;
|
$: navOpen = false;
|
||||||
function logout() {
|
function logout() {
|
||||||
localForage.clear();
|
localForage.clear();
|
||||||
@@ -256,6 +257,26 @@
|
|||||||
<span>{$_('scanstations')}</span>
|
<span>{$_('scanstations')}</span>
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes('STATSCLIENT:GET')}
|
||||||
|
<a
|
||||||
|
class:bg-gray-100={$router.path === '/statsclients/'}
|
||||||
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
||||||
|
href="/statsclients/">
|
||||||
|
<svg
|
||||||
|
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
||||||
|
fill="currentColor"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"><path
|
||||||
|
fill="none"
|
||||||
|
d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z" /></svg>
|
||||||
|
<span>{$_('statsclients')}</span>
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
<a
|
<a
|
||||||
class:bg-gray-100={$router.path === '/settings/'}
|
class:bg-gray-100={$router.path === '/settings/'}
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
||||||
@@ -325,6 +346,7 @@
|
|||||||
d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4A1 1 0 013 5zm0 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z"
|
d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4A1 1 0 013 5zm0 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z"
|
||||||
clip-rule="evenodd" /></svg></button>
|
clip-rule="evenodd" /></svg></button>
|
||||||
</header>
|
</header>
|
||||||
|
<Toaster position="top-right" />
|
||||||
<slot>
|
<slot>
|
||||||
<NoComponentLoaded />
|
<NoComponentLoaded />
|
||||||
</slot>
|
</slot>
|
||||||
|
|||||||
@@ -1,22 +1,224 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import StatCards from "./StatCards.svelte";
|
import { StatsService } from "@odit/lfk-client-js";
|
||||||
|
import StatCards from "./StatCard.svelte";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
|
import StatCard from "./StatCard.svelte";
|
||||||
let navOpen = false;
|
let navOpen = false;
|
||||||
|
const stats_promise = StatsService.statsControllerGet();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div
|
<div
|
||||||
class="p-5 overflow-x-hidden"
|
class="p-5 overflow-x-hidden"
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
navOpen = false;
|
navOpen = false;
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
<h1 class="text-3xl leading-tight">
|
<h1 class="text-3xl leading-tight">
|
||||||
<span class="font-extrabold">{$_('dashboard-title')}</span>
|
<span class="font-extrabold">{$_("dashboard-title")}</span>
|
||||||
<span>
|
<span>
|
||||||
-
|
-
|
||||||
{$_('dashboard-greeting')},
|
{$_("dashboard-greeting")},
|
||||||
<span
|
<span class="text-blue-500"
|
||||||
class="text-blue-500">{store.state.jwtinfo.userdetails.firstname} {store.state.jwtinfo.userdetails.lastname}</span></span>
|
>{store.state.jwtinfo.userdetails.firstname}
|
||||||
|
{store.state.jwtinfo.userdetails.lastname}</span
|
||||||
|
></span
|
||||||
|
>
|
||||||
</h1>
|
</h1>
|
||||||
<StatCards />
|
<h1>{$_("general-stats")}</h1>
|
||||||
|
{#await stats_promise}
|
||||||
|
<div
|
||||||
|
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
||||||
|
role="alert"
|
||||||
|
>
|
||||||
|
<p class="font-bold">{$_("stats-are-being-loaded")}</p>
|
||||||
|
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
||||||
|
</div>
|
||||||
|
{:then stats}
|
||||||
|
<div
|
||||||
|
class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 2xl:grid-cols-6 gap-4"
|
||||||
|
>
|
||||||
|
<StatCard
|
||||||
|
title={$_("runners")}
|
||||||
|
value={stats.total_runners}
|
||||||
|
href="/runners/"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
height="24"
|
||||||
|
width="24"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
><path d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path
|
||||||
|
d="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1 2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9 0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5.1-.8.1l-5.2 2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</StatCard>
|
||||||
|
<StatCard
|
||||||
|
title={$_("total-scans")}
|
||||||
|
value={stats.total_scans}
|
||||||
|
href="/scans/"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
fill="currentColor"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M2 4h2v16H2V4zm4 0h1v16H6V4zm2 0h2v16H8V4zm3 0h2v16h-2V4zm3 0h2v16h-2V4zm3 0h1v16h-1V4zm2 0h3v16h-3V4z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</StatCard>
|
||||||
|
<StatCard
|
||||||
|
title={$_("total-donors")}
|
||||||
|
value={stats.total_donors}
|
||||||
|
href="/donors/"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
d="M9.33 11.5h2.17A4.5 4.5 0 0 1 16 16H8.999L9 17h8v-1a5.578 5.578 0 0 0-.886-3H19a5 5 0 0 1 4.516 2.851C21.151 18.972 17.322 21 13 21c-2.761 0-5.1-.59-7-1.625L6 10.071A6.967 6.967 0 0 1 9.33 11.5zM5 19a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v9zM18 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6zm-7-3a3 3 0 1 1 0 6 3 3 0 0 1 0-6z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</StatCard>
|
||||||
|
<StatCard
|
||||||
|
title={$_("total-donation-count")}
|
||||||
|
value={stats.total_donations}
|
||||||
|
href="/donations/"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</StatCard>
|
||||||
|
<StatCard
|
||||||
|
title={$_("average-donation")}
|
||||||
|
value={`${(stats.average_donation / 100).toFixed(2)} €`}
|
||||||
|
href="/donations/"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</StatCard>
|
||||||
|
<StatCard
|
||||||
|
title={$_("total-donations")}
|
||||||
|
value={`${(stats.total_donation / 100).toFixed(2)} €`}
|
||||||
|
href="/donations/"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="24"
|
||||||
|
fill="currentColor"
|
||||||
|
width="24"
|
||||||
|
><path d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path
|
||||||
|
d="M15 18.5A6.48 6.48 0 019.24 15H15v-2H8.58c-.05-.33-.08-.66-.08-1s.03-.67.08-1H15V9H9.24A6.491 6.491 0 0115 5.5c1.61 0 3.09.59 4.23 1.57L21 5.3A8.955 8.955 0 0015 3c-3.92 0-7.24 2.51-8.48 6H3v2h3.06a8.262 8.262 0 000 2H3v2h3.52c1.24 3.49 4.56 6 8.48 6 2.31 0 4.41-.87 6-2.3l-1.78-1.77c-1.13.98-2.6 1.57-4.22 1.57z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</StatCard>
|
||||||
|
<StatCard
|
||||||
|
title={$_("total-distance")}
|
||||||
|
value={`${stats.total_distance / 1000} km`}
|
||||||
|
href="#"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="24"
|
||||||
|
width="24"
|
||||||
|
><path d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path
|
||||||
|
d="M21 6H3c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H3V8h2v4h2V8h2v4h2V8h2v4h2V8h2v4h2V8h2v8z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</StatCard>
|
||||||
|
<StatCard
|
||||||
|
title={$_("average-distance")}
|
||||||
|
value={`${(stats.average_distance / 1000).toFixed(2)} km`}
|
||||||
|
href="#"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
height="24"
|
||||||
|
width="24"
|
||||||
|
><path d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path
|
||||||
|
d="M21 6H3c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H3V8h2v4h2V8h2v4h2V8h2v4h2V8h2v4h2V8h2v8z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</StatCard>
|
||||||
|
<StatCard
|
||||||
|
title={$_("count_teams")}
|
||||||
|
value={stats.total_teams}
|
||||||
|
href="/teams/"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
stroke="currentColor"
|
||||||
|
fill="none"
|
||||||
|
stroke-width="2"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
size="24"
|
||||||
|
class="stroke-current text-grey-500"
|
||||||
|
height="24"
|
||||||
|
width="24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
|
||||||
|
<circle cx="9" cy="7" r="4" />
|
||||||
|
<path d="M23 21v-2a4 4 0 0 0-3-3.87" />
|
||||||
|
<path d="M16 3.13a4 4 0 0 1 0 7.75" /></svg
|
||||||
|
>
|
||||||
|
</StatCard>
|
||||||
|
<StatCard
|
||||||
|
title={$_("count_organizations")}
|
||||||
|
value={stats.total_orgs}
|
||||||
|
href="/orgs/"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
height="24"
|
||||||
|
fill="currentColor"
|
||||||
|
width="24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
d="M17 11V3H7v4H3v14h8v-4h2v4h8V11h-4zM7 19H5v-2h2v2zm0-4H5v-2h2v2zm0-4H5V9h2v2zm4 4H9v-2h2v2zm0-4H9V9h2v2zm0-4H9V5h2v2zm4 8h-2v-2h2v2zm0-4h-2V9h2v2zm0-4h-2V5h2v2zm4 12h-2v-2h2v2zm0-4h-2v-2h2v2z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</StatCard>
|
||||||
|
</div>
|
||||||
|
{:catch error}
|
||||||
|
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
|
||||||
|
<span class="inline-block align-middle mr-8">
|
||||||
|
<b class="capitalize">{$_("general_promise_error")}</b>
|
||||||
|
{error}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{/await}
|
||||||
</div>
|
</div>
|
||||||
@@ -0,0 +1,22 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
|
||||||
|
export let href = "#"
|
||||||
|
export let title = "";
|
||||||
|
export let value = "";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<a href={href}>
|
||||||
|
<div
|
||||||
|
class="p-4 rounded-lg bg-white border border-grey-100">
|
||||||
|
<div class="flex flex-row items-center justify-between">
|
||||||
|
<div class="flex flex-col">
|
||||||
|
<div class="text-xs uppercase font-light text-grey-500">
|
||||||
|
{title}
|
||||||
|
</div>
|
||||||
|
<div class="text-xl font-bold">{value}</div>
|
||||||
|
</div>
|
||||||
|
<slot></slot>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</a>
|
||||||
@@ -1,165 +0,0 @@
|
|||||||
<script>
|
|
||||||
import { StatsService } from "@odit/lfk-client-js";
|
|
||||||
import { _ } from "svelte-i18n";
|
|
||||||
const stats_promise = StatsService.statsControllerGet();
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<!-- -->
|
|
||||||
<h1>{$_('general-stats')}</h1>
|
|
||||||
{#await stats_promise}
|
|
||||||
<div
|
|
||||||
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
|
||||||
role="alert">
|
|
||||||
<p class="font-bold">{$_('stats-are-being-loaded')}</p>
|
|
||||||
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
|
||||||
</div>
|
|
||||||
{:then stats}
|
|
||||||
<div
|
|
||||||
class="flex flex-col lg:flex-row w-full lg:space-x-2 space-y-2 lg:space-y-0 mb-2 lg:mb-4">
|
|
||||||
<a href="/runners/" class="w-full lg:w-1/4">
|
|
||||||
<div
|
|
||||||
class="widget w-full p-4 rounded-lg bg-white border border-grey-100">
|
|
||||||
<div class="flex flex-row items-center justify-between">
|
|
||||||
<div class="flex flex-col">
|
|
||||||
<div class="text-xs uppercase font-light text-grey-500">
|
|
||||||
{$_('runners')}
|
|
||||||
</div>
|
|
||||||
<div class="text-xl font-bold">{stats.total_runners}</div>
|
|
||||||
</div>
|
|
||||||
<svg
|
|
||||||
height="24"
|
|
||||||
width="24"
|
|
||||||
fill="currentColor"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 24 24"><path d="M0 0h24v24H0z" fill="none" />
|
|
||||||
<path
|
|
||||||
d="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1 2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9 0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5.1-.8.1l-5.2 2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z" /></svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<div class="w-full lg:w-1/4">
|
|
||||||
<div
|
|
||||||
class="widget w-full p-4 rounded-lg bg-white border border-grey-100">
|
|
||||||
<div class="flex flex-row items-center justify-between">
|
|
||||||
<div class="flex flex-col">
|
|
||||||
<div class="text-xs uppercase font-light text-grey-500">
|
|
||||||
{$_('total-scans')}
|
|
||||||
</div>
|
|
||||||
<div class="text-xl font-bold">{stats.total_scans}</div>
|
|
||||||
</div><svg
|
|
||||||
stroke="currentColor"
|
|
||||||
fill="currentColor"
|
|
||||||
stroke-width="2"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
size="24"
|
|
||||||
class="stroke-current text-grey-500"
|
|
||||||
height="24"
|
|
||||||
width="24"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"><polyline
|
|
||||||
points="22 12 18 12 15 21 9 3 6 12 2 12" /></svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="w-full lg:w-1/4">
|
|
||||||
<div
|
|
||||||
class="widget w-full p-4 rounded-lg bg-white border border-grey-100">
|
|
||||||
<div class="flex flex-row items-center justify-between">
|
|
||||||
<div class="flex flex-col">
|
|
||||||
<div class="text-xs uppercase font-light text-grey-500">
|
|
||||||
{$_('total-donations')}
|
|
||||||
</div>
|
|
||||||
<div class="text-xl font-bold">{stats.total_donation} €</div>
|
|
||||||
</div><svg
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
height="24"
|
|
||||||
fill="currentColor"
|
|
||||||
width="24"><path d="M0 0h24v24H0z" fill="none" />
|
|
||||||
<path
|
|
||||||
d="M15 18.5A6.48 6.48 0 019.24 15H15v-2H8.58c-.05-.33-.08-.66-.08-1s.03-.67.08-1H15V9H9.24A6.491 6.491 0 0115 5.5c1.61 0 3.09.59 4.23 1.57L21 5.3A8.955 8.955 0 0015 3c-3.92 0-7.24 2.51-8.48 6H3v2h3.06a8.262 8.262 0 000 2H3v2h3.52c1.24 3.49 4.56 6 8.48 6 2.31 0 4.41-.87 6-2.3l-1.78-1.77c-1.13.98-2.6 1.57-4.22 1.57z" /></svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="w-full lg:w-1/4">
|
|
||||||
<div
|
|
||||||
class="widget w-full p-4 rounded-lg bg-white border border-grey-100">
|
|
||||||
<div class="flex flex-row items-center justify-between">
|
|
||||||
<div class="flex flex-col">
|
|
||||||
<div class="text-xs uppercase font-light text-grey-500">
|
|
||||||
{$_('total-distance')}
|
|
||||||
</div>
|
|
||||||
<div class="text-xl font-bold">
|
|
||||||
{stats.total_distance / 1000}
|
|
||||||
km
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<svg
|
|
||||||
fill="currentColor"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
height="24"
|
|
||||||
width="24"><path d="M0 0h24v24H0z" fill="none" />
|
|
||||||
<path
|
|
||||||
d="M21 6H3c-1.1 0-2 .9-2 2v8c0 1.1.9 2 2 2h18c1.1 0 2-.9 2-2V8c0-1.1-.9-2-2-2zm0 10H3V8h2v4h2V8h2v4h2V8h2v4h2V8h2v4h2V8h2v8z" /></svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<a href="/teams/" class="w-full lg:w-1/4">
|
|
||||||
<div
|
|
||||||
class="widget w-full p-4 rounded-lg bg-white border border-grey-100">
|
|
||||||
<div class="flex flex-row items-center justify-between">
|
|
||||||
<div class="flex flex-col">
|
|
||||||
<div class="text-xs uppercase font-light text-grey-500">
|
|
||||||
{$_('count_teams')}
|
|
||||||
</div>
|
|
||||||
<div class="text-xl font-bold">{stats.total_teams}</div>
|
|
||||||
</div>
|
|
||||||
<svg
|
|
||||||
stroke="currentColor"
|
|
||||||
fill="none"
|
|
||||||
stroke-width="2"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
stroke-linecap="round"
|
|
||||||
stroke-linejoin="round"
|
|
||||||
size="24"
|
|
||||||
class="stroke-current text-grey-500"
|
|
||||||
height="24"
|
|
||||||
width="24"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"><path
|
|
||||||
d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2" />
|
|
||||||
<circle cx="9" cy="7" r="4" />
|
|
||||||
<path d="M23 21v-2a4 4 0 0 0-3-3.87" />
|
|
||||||
<path d="M16 3.13a4 4 0 0 1 0 7.75" /></svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
<a href="/orgs/" class="w-full lg:w-1/4">
|
|
||||||
<div
|
|
||||||
class="widget w-full p-4 rounded-lg bg-white border border-grey-100">
|
|
||||||
<div class="flex flex-row items-center justify-between">
|
|
||||||
<div class="flex flex-col">
|
|
||||||
<div class="text-xs uppercase font-light text-grey-500">
|
|
||||||
{$_('count_organizations')}
|
|
||||||
</div>
|
|
||||||
<div class="text-xl font-bold">{stats.total_orgs}</div>
|
|
||||||
</div>
|
|
||||||
<svg
|
|
||||||
height="24"
|
|
||||||
fill="currentColor"
|
|
||||||
width="24"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z" />
|
|
||||||
<path
|
|
||||||
d="M17 11V3H7v4H3v14h8v-4h2v4h8V11h-4zM7 19H5v-2h2v2zm0-4H5v-2h2v2zm0-4H5V9h2v2zm4 4H9v-2h2v2zm0-4H9V9h2v2zm0-4H9V5h2v2zm4 8h-2v-2h2v2zm0-4h-2V9h2v2zm0-4h-2V5h2v2zm4 12h-2v-2h2v2zm0-4h-2v-2h2v2z" /></svg>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</a>
|
|
||||||
</div>
|
|
||||||
{:catch error}
|
|
||||||
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
|
|
||||||
<span class="inline-block align-middle mr-8">
|
|
||||||
<b class="capitalize">{$_('general_promise_error')}</b>
|
|
||||||
{error}
|
|
||||||
</span>
|
|
||||||
</div>
|
|
||||||
{/await}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import {
|
import {
|
||||||
DonationService,
|
DonationService,
|
||||||
DonorService,
|
DonorService,
|
||||||
@@ -9,9 +9,10 @@
|
|||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
import Select from "svelte-select";
|
import Select from "svelte-select";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
import { is_promise } from "svelte/internal";
|
import { is_promise } from "svelte/internal";
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
export let modal_open;
|
export let modal_open;
|
||||||
export let current_donations;
|
const dispatch = createEventDispatcher();
|
||||||
const getDonorLabel = (option) =>
|
const getDonorLabel = (option) =>
|
||||||
option.firstname + " " + (option.middlename || "") + " " + option.lastname;
|
option.firstname + " " + (option.middlename || "") + " " + option.lastname;
|
||||||
const filterDonors = (label, filterText, option) =>
|
const filterDonors = (label, filterText, option) =>
|
||||||
@@ -59,16 +60,16 @@ import { is_promise } from "svelte/internal";
|
|||||||
let amount_cent = Math.floor(amount_input * 100);
|
let amount_cent = Math.floor(amount_input * 100);
|
||||||
processed_last_submit = false;
|
processed_last_submit = false;
|
||||||
const toast = Toastify({
|
const toast = Toastify({
|
||||||
text: $_('adding-donation'),
|
text: $_("adding-donation"),
|
||||||
duration: -1,
|
duration: -1,
|
||||||
}).showToast();
|
}).showToast();
|
||||||
if (is_fixed) {
|
if (is_fixed) {
|
||||||
let postdata = {
|
let postdata = {
|
||||||
donor,
|
donor,
|
||||||
amount: amount_cent,
|
amount: amount_cent,
|
||||||
paidAmount: 0
|
paidAmount: 0,
|
||||||
};
|
};
|
||||||
if(is_paid){
|
if (is_paid) {
|
||||||
postdata.paidAmount = amount_cent;
|
postdata.paidAmount = amount_cent;
|
||||||
}
|
}
|
||||||
DonationService.donationControllerPostFixed(postdata)
|
DonationService.donationControllerPostFixed(postdata)
|
||||||
@@ -79,12 +80,11 @@ import { is_promise } from "svelte/internal";
|
|||||||
modal_open = false;
|
modal_open = false;
|
||||||
//
|
//
|
||||||
Toastify({
|
Toastify({
|
||||||
text: $_('donation_added'),
|
text: $_("donation_added"),
|
||||||
duration: 500,
|
duration: 500,
|
||||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
current_donations.push(result);
|
dispatch("created", { donations: [result] });
|
||||||
current_donations = current_donations;
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
//
|
//
|
||||||
@@ -108,12 +108,11 @@ import { is_promise } from "svelte/internal";
|
|||||||
modal_open = false;
|
modal_open = false;
|
||||||
//
|
//
|
||||||
Toastify({
|
Toastify({
|
||||||
text: $_('donation_added'),
|
text: $_("donation_added"),
|
||||||
duration: 500,
|
duration: 500,
|
||||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
current_donations.push(result);
|
dispatch("created", { donations: [result] });
|
||||||
current_donations = current_donations;
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
//
|
//
|
||||||
@@ -128,6 +127,207 @@ import { is_promise } from "svelte/internal";
|
|||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{#if modal_open}
|
||||||
|
<div
|
||||||
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
|
use:clickOutside
|
||||||
|
on:click_outside={() => {
|
||||||
|
modal_open = false;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
||||||
|
>
|
||||||
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
|
data-id="modal_backdrop"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
|
aria-hidden="true">​</span
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby="modal-headline"
|
||||||
|
>
|
||||||
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
|
<div class="sm:flex sm:items-start">
|
||||||
|
<div
|
||||||
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="h-6 w-6 text-blue-600"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
{#if is_fixed}
|
||||||
|
{$_("create-a-new-fixed-donation")}
|
||||||
|
{:else}{$_("create-a-new-distance-donation")}{/if}
|
||||||
|
</h3>
|
||||||
|
<label class="content-center align-middle object-center">
|
||||||
|
<span class="ml-2 text-base" class:text-gray-300={is_fixed}
|
||||||
|
>{$_("distance-donation")}</span
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
class="toggle relative w-10 h-5 transition-all duration-200 ease-in-out bg-gray-400 rounded-full shadow-inner outline-none appearance-none align-middle"
|
||||||
|
type="checkbox"
|
||||||
|
bind:checked={is_fixed}
|
||||||
|
/>
|
||||||
|
<span class="ml-2 text-base" class:text-gray-300={!is_fixed}
|
||||||
|
>{$_("fixed-donation")}</span
|
||||||
|
>
|
||||||
|
</label>
|
||||||
|
<div class="mt-2 mb-6">
|
||||||
|
<p class="text-sm text-gray-500">
|
||||||
|
{$_(
|
||||||
|
"please-provide-the-nessecary-information-to-create-a-new-donation"
|
||||||
|
)}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-cols-6 gap-6">
|
||||||
|
<div class="col-span-6">
|
||||||
|
<label
|
||||||
|
for="donor"
|
||||||
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>{$_("donor")}</label
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
itemFilter={(label, filterText, option) =>
|
||||||
|
filterDonors(label, filterText, option)}
|
||||||
|
items={donors}
|
||||||
|
showChevron={true}
|
||||||
|
placeholder={$_("search-for-donor-name-or-id")}
|
||||||
|
noOptionsMessage={$_("no-donors-found")}
|
||||||
|
on:select={(selectedValue) =>
|
||||||
|
(donor = selectedValue.detail.value.id)}
|
||||||
|
on:clear={() => (donors = null)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{#if !is_fixed}
|
||||||
|
<div class="col-span-6">
|
||||||
|
<label
|
||||||
|
for="donor"
|
||||||
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>{$_("runner")}</label
|
||||||
|
>
|
||||||
|
<Select
|
||||||
|
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
itemFilter={(label, filterText, option) =>
|
||||||
|
filterDonors(label, filterText, option)}
|
||||||
|
items={runners}
|
||||||
|
showChevron={true}
|
||||||
|
placeholder={$_("search-for-runner-by-name-or-id")}
|
||||||
|
noOptionsMessage={$_("no-runners-found")}
|
||||||
|
on:select={(selectedValue) =>
|
||||||
|
(runner = selectedValue.detail.value.id)}
|
||||||
|
on:clear={() => (runner = null)}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
<div class="col-span-6">
|
||||||
|
<label
|
||||||
|
for="donation_amount_eur"
|
||||||
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>
|
||||||
|
{#if !is_fixed}
|
||||||
|
{$_("amount-per-kilometer")}
|
||||||
|
{:else}{$_("donation-amount")}{/if}</label
|
||||||
|
>
|
||||||
|
<div class="mt-1 flex rounded-md shadow-sm">
|
||||||
|
<input
|
||||||
|
autocomplete="off"
|
||||||
|
class:border-red-500={!is_amount_valid}
|
||||||
|
class:focus:border-red-500={!is_amount_valid}
|
||||||
|
class:focus:ring-red-500={!is_amount_valid}
|
||||||
|
bind:value={amount_input}
|
||||||
|
type="number"
|
||||||
|
step="0.01"
|
||||||
|
name="donation_amount_eur"
|
||||||
|
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
|
||||||
|
placeholder="2.00"
|
||||||
|
/>
|
||||||
|
<span
|
||||||
|
class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm"
|
||||||
|
>€</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{#if !is_amount_valid}
|
||||||
|
<span
|
||||||
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
|
>
|
||||||
|
{$_("donation-amount-must-be-greater-that-0-00eur")}
|
||||||
|
</span>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{#if is_fixed}
|
||||||
|
<div class="col-span-6">
|
||||||
|
<label
|
||||||
|
for="paid"
|
||||||
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>{$_("already-paid")}</label
|
||||||
|
>
|
||||||
|
<p class="text-gray-500">
|
||||||
|
<input
|
||||||
|
id="paid"
|
||||||
|
bind:checked={is_paid}
|
||||||
|
name="paid"
|
||||||
|
type="checkbox"
|
||||||
|
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
|
/>
|
||||||
|
<span class="align-text-bottom">
|
||||||
|
{#if is_paid}
|
||||||
|
{$_("paid")}
|
||||||
|
{:else}
|
||||||
|
{$_("open")}
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||||
|
<button
|
||||||
|
disabled={!createbtnenabled}
|
||||||
|
class:opacity-50={!createbtnenabled}
|
||||||
|
on:click={submit}
|
||||||
|
type="button"
|
||||||
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>
|
||||||
|
{$_("create")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
modal_open = false;
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>
|
||||||
|
{$_("cancel")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.toggle:before {
|
.toggle:before {
|
||||||
content: "";
|
content: "";
|
||||||
@@ -152,173 +352,3 @@ import { is_promise } from "svelte/internal";
|
|||||||
left: 1.25rem;
|
left: 1.25rem;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
{#if modal_open}
|
|
||||||
<div
|
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
|
||||||
on:click_outside={() => {
|
|
||||||
modal_open = false;
|
|
||||||
}}>
|
|
||||||
<div
|
|
||||||
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
|
||||||
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
|
||||||
<div
|
|
||||||
class="absolute inset-0 bg-gray-500 opacity-75"
|
|
||||||
data-id="modal_backdrop" />
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
|
||||||
aria-hidden="true">​</span>
|
|
||||||
<div
|
|
||||||
class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
|
||||||
role="dialog"
|
|
||||||
aria-modal="true"
|
|
||||||
aria-labelledby="modal-headline">
|
|
||||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
|
||||||
<div class="sm:flex sm:items-start">
|
|
||||||
<div
|
|
||||||
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
|
|
||||||
<svg
|
|
||||||
class="h-6 w-6 text-blue-600"
|
|
||||||
fill="currentColor"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
width="24"
|
|
||||||
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
|
||||||
<path
|
|
||||||
d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z" /></svg>
|
|
||||||
</div>
|
|
||||||
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
|
||||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
|
||||||
{#if is_fixed}
|
|
||||||
{$_('create-a-new-fixed-donation')}
|
|
||||||
{:else}{$_('create-a-new-distance-donation')}{/if}
|
|
||||||
</h3>
|
|
||||||
<label class="content-center align-middle object-center">
|
|
||||||
<span
|
|
||||||
class="ml-2 text-base"
|
|
||||||
class:text-gray-300={is_fixed}>{$_('distance-donation')}</span>
|
|
||||||
<input
|
|
||||||
class="toggle relative w-10 h-5 transition-all duration-200 ease-in-out bg-gray-400 rounded-full shadow-inner outline-none appearance-none align-middle"
|
|
||||||
type="checkbox"
|
|
||||||
bind:checked={is_fixed} />
|
|
||||||
<span
|
|
||||||
class="ml-2 text-base "
|
|
||||||
class:text-gray-300={!is_fixed}>{$_('fixed-donation')}</span>
|
|
||||||
</label>
|
|
||||||
<div class="mt-2 mb-6">
|
|
||||||
<p class="text-sm text-gray-500">
|
|
||||||
{$_('please-provide-the-nessecary-information-to-create-a-new-donation')}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="grid grid-cols-6 gap-6">
|
|
||||||
<div class="col-span-6">
|
|
||||||
<label
|
|
||||||
for="donor"
|
|
||||||
class="block text-sm font-medium text-gray-700">{$_('donor')}</label>
|
|
||||||
<Select
|
|
||||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
|
||||||
itemFilter={(label, filterText, option) => filterDonors(label, filterText, option)}
|
|
||||||
items={donors}
|
|
||||||
showChevron={true}
|
|
||||||
placeholder={$_('search-for-donor-name-or-id')}
|
|
||||||
noOptionsMessage={$_('no-donors-found')}
|
|
||||||
on:select={(selectedValue) => (donor = selectedValue.detail.value.id)}
|
|
||||||
on:clear={() => (donors = null)} />
|
|
||||||
</div>
|
|
||||||
{#if !is_fixed}
|
|
||||||
<div class="col-span-6">
|
|
||||||
<label
|
|
||||||
for="donor"
|
|
||||||
class="block text-sm font-medium text-gray-700">{$_('runner')}</label>
|
|
||||||
<Select
|
|
||||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
|
||||||
itemFilter={(label, filterText, option) => filterDonors(label, filterText, option)}
|
|
||||||
items={runners}
|
|
||||||
showChevron={true}
|
|
||||||
placeholder={$_('search-for-runner-by-name-or-id')}
|
|
||||||
noOptionsMessage={$_('no-runners-found')}
|
|
||||||
on:select={(selectedValue) => (runner = selectedValue.detail.value.id)}
|
|
||||||
on:clear={() => (runner = null)} />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
<div class="col-span-6">
|
|
||||||
<label
|
|
||||||
for="donation_amount_eur"
|
|
||||||
class="block text-sm font-medium text-gray-700">
|
|
||||||
{#if !is_fixed}
|
|
||||||
{$_('amount-per-kilometer')}
|
|
||||||
{:else}{$_('donation-amount')}{/if}</label>
|
|
||||||
<div class="mt-1 flex rounded-md shadow-sm">
|
|
||||||
<input
|
|
||||||
autocomplete="off"
|
|
||||||
class:border-red-500={!is_amount_valid}
|
|
||||||
class:focus:border-red-500={!is_amount_valid}
|
|
||||||
class:focus:ring-red-500={!is_amount_valid}
|
|
||||||
bind:value={amount_input}
|
|
||||||
type="number"
|
|
||||||
step="0.01"
|
|
||||||
name="donation_amount_eur"
|
|
||||||
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
|
|
||||||
placeholder="2.00" />
|
|
||||||
<span
|
|
||||||
class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm">€</span>
|
|
||||||
</div>
|
|
||||||
{#if !is_amount_valid}
|
|
||||||
<span
|
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
|
||||||
{$_('donation-amount-must-be-greater-that-0-00eur')}
|
|
||||||
</span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{#if is_fixed}
|
|
||||||
<div class="col-span-6">
|
|
||||||
<label
|
|
||||||
for="paid"
|
|
||||||
class="block text-sm font-medium text-gray-700">{$_('already-paid')}</label>
|
|
||||||
<p class="text-gray-500">
|
|
||||||
<input
|
|
||||||
id="paid"
|
|
||||||
bind:checked={is_paid}
|
|
||||||
name="paid"
|
|
||||||
type="checkbox"
|
|
||||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" >
|
|
||||||
<span class="align-text-bottom">
|
|
||||||
|
|
||||||
{#if is_paid}
|
|
||||||
{$_('paid')}
|
|
||||||
{:else}
|
|
||||||
{$_('open')}
|
|
||||||
{/if}
|
|
||||||
</span>
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
|
||||||
<button
|
|
||||||
disabled={!createbtnenabled}
|
|
||||||
class:opacity-50={!createbtnenabled}
|
|
||||||
on:click={submit}
|
|
||||||
type="button"
|
|
||||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
|
||||||
{$_('create')}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
modal_open = false;
|
|
||||||
}}
|
|
||||||
type="button"
|
|
||||||
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
|
|
||||||
{$_('cancel')}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
@@ -1,19 +1,21 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import { DonationService } from "@odit/lfk-client-js";
|
import { DonationService } from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
export let payment_modal_open = false;
|
export let payment_modal_open = false;
|
||||||
export let current_donations = [];
|
|
||||||
export let editable = {};
|
|
||||||
export let original_data = {};
|
export let original_data = {};
|
||||||
export let paid_amount_input = 0;
|
export let paid_amount_input = 0;
|
||||||
$:processed_last_submit=true;
|
const dispatch = createEventDispatcher();
|
||||||
|
$: processed_last_submit = true;
|
||||||
function focus(el) {
|
function focus(el) {
|
||||||
el.focus();
|
el.focus();
|
||||||
}
|
}
|
||||||
$: createbtnenabled = is_paid_amount_valid && !(paid_amount_input*100 == original_data.paidAmount)
|
$: createbtnenabled =
|
||||||
|
is_paid_amount_valid &&
|
||||||
|
!(paid_amount_input * 100 == original_data.paidAmount);
|
||||||
$: is_paid_amount_valid = paid_amount_input > 0;
|
$: is_paid_amount_valid = paid_amount_input > 0;
|
||||||
(() => {
|
(() => {
|
||||||
document.onkeydown = (e) => {
|
document.onkeydown = (e) => {
|
||||||
@@ -33,61 +35,56 @@
|
|||||||
if (processed_last_submit === true) {
|
if (processed_last_submit === true) {
|
||||||
processed_last_submit = false;
|
processed_last_submit = false;
|
||||||
const toast = Toastify({
|
const toast = Toastify({
|
||||||
text: $_('updating-donation'),
|
text: $_("updating-donation"),
|
||||||
duration: -1,
|
duration: -1,
|
||||||
}).showToast();
|
}).showToast();
|
||||||
|
const editable = Object.assign({}, original_data);
|
||||||
editable.donor = editable.donor.id;
|
editable.donor = editable.donor.id;
|
||||||
editable.paidAmount = paid_amount_input*100;
|
editable.paidAmount = paid_amount_input * 100;
|
||||||
if(editable.responseType == "DISTANCEDONATION" || editable.runner){
|
if (editable.responseType == "DISTANCEDONATION" || editable.runner) {
|
||||||
editable.runner = editable.runner.id;
|
editable.runner = editable.runner.id;
|
||||||
DonationService.donationControllerPutDistance(original_data.id, editable)
|
DonationService.donationControllerPutDistance(
|
||||||
.then((result) => {
|
original_data.id,
|
||||||
let id = original_data.id;
|
editable
|
||||||
editable = {};
|
)
|
||||||
original_data = {};
|
.then((result) => {
|
||||||
payment_modal_open = false;
|
payment_modal_open = false;
|
||||||
//
|
//
|
||||||
Toastify({
|
Toastify({
|
||||||
text: $_('donation-updated'),
|
text: $_("donation-updated"),
|
||||||
duration: 500,
|
duration: 500,
|
||||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
current_donations[current_donations.findIndex((c) => c.id === id)] = result;
|
dispatch("created", { donation: response });
|
||||||
current_donations = current_donations;
|
})
|
||||||
})
|
.catch((err) => {
|
||||||
.catch((err) => {
|
//
|
||||||
//
|
})
|
||||||
})
|
.finally(() => {
|
||||||
.finally(() => {
|
processed_last_submit = true;
|
||||||
processed_last_submit = true;
|
//
|
||||||
//
|
toast.hideToast();
|
||||||
toast.hideToast();
|
});
|
||||||
});
|
} else {
|
||||||
}
|
DonationService.donationControllerPutFixed(original_data.id, editable)
|
||||||
else{
|
.then((result) => {
|
||||||
DonationService.donationControllerPutFixed(original_data.id, editable)
|
payment_modal_open = false;
|
||||||
.then((result) => {
|
//
|
||||||
let id = original_data.id;
|
Toastify({
|
||||||
editable = {};
|
text: $_("donation-updated"),
|
||||||
original_data = {};
|
duration: 500,
|
||||||
payment_modal_open = false;
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
//
|
}).showToast();
|
||||||
Toastify({
|
dispatch("created", { donation: response });
|
||||||
text: $_('donation-updated'),
|
})
|
||||||
duration: 500,
|
.catch((err) => {
|
||||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
//
|
||||||
}).showToast();
|
})
|
||||||
current_donations[current_donations.findIndex((c) => c.id === id)] = result;
|
.finally(() => {
|
||||||
current_donations = current_donations;
|
processed_last_submit = true;
|
||||||
})
|
//
|
||||||
.catch((err) => {
|
toast.hideToast();
|
||||||
//
|
});
|
||||||
})
|
|
||||||
.finally(() => {
|
|
||||||
processed_last_submit = true;
|
|
||||||
//
|
|
||||||
toast.hideToast();
|
|
||||||
});
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -96,57 +93,71 @@
|
|||||||
{#if payment_modal_open}
|
{#if payment_modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={() => {
|
on:click_outside={() => {
|
||||||
payment_modal_open = false;
|
payment_modal_open = false;
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
||||||
|
>
|
||||||
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
<div
|
<div
|
||||||
class="absolute inset-0 bg-gray-500 opacity-75"
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
data-id="modal_backdrop" />
|
data-id="modal_backdrop"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
aria-hidden="true">​</span>
|
aria-hidden="true">​</span
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
aria-labelledby="modal-headline">
|
aria-labelledby="modal-headline"
|
||||||
|
>
|
||||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
<div class="sm:flex sm:items-start">
|
<div class="sm:flex sm:items-start">
|
||||||
<div
|
<div
|
||||||
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
||||||
|
>
|
||||||
<svg
|
<svg
|
||||||
class="h-6 w-6 text-blue-600"
|
class="h-6 w-6 text-blue-600"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
height="24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
d="M22 10v10a1 1 0 01-1 1H3a1 1 0 01-1-1V10h20zm0-2H2V4a1 1 0 011-1h18a1 1 0 011 1v4zm-7 8v2h4v-2h-4z" /></svg>
|
d="M22 10v10a1 1 0 01-1 1H3a1 1 0 01-1-1V10h20zm0-2H2V4a1 1 0 011-1h18a1 1 0 011 1v4zm-7 8v2h4v-2h-4z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
{$_('enter-payment')}
|
{$_("enter-payment")}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="mt-2 mb-6">
|
<div class="mt-2 mb-6">
|
||||||
<p class="text-sm text-gray-500">
|
<p class="text-sm text-gray-500">
|
||||||
{$_('you-can-enter-the-donations-paid-amount-manually-or-use-the-max-button-to-use-the-donations-exact-amount')}
|
{$_(
|
||||||
|
"you-can-enter-the-donations-paid-amount-manually-or-use-the-max-button-to-use-the-donations-exact-amount"
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols gap-6">
|
<div class="grid grid-cols gap-6">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<label
|
<label
|
||||||
for="token"
|
for="token"
|
||||||
class="block text-sm font-medium text-gray-700">{$_('paid-amount')}</label>
|
class="block text-sm font-medium text-gray-700"
|
||||||
<div class="inline-flex border-gray-300 border rounded-l-md rounded-r-md bg-gray-50 text-gray-500 w-full">
|
>{$_("paid-amount")}</label
|
||||||
<input
|
>
|
||||||
|
<div
|
||||||
|
class="inline-flex border-gray-300 border rounded-l-md rounded-r-md bg-gray-50 text-gray-500 w-full"
|
||||||
|
>
|
||||||
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
class:border-red-500={!is_paid_amount_valid}
|
class:border-red-500={!is_paid_amount_valid}
|
||||||
class:focus:border-red-500={!is_paid_amount_valid}
|
class:focus:border-red-500={!is_paid_amount_valid}
|
||||||
@@ -156,47 +167,55 @@
|
|||||||
step="0.01"
|
step="0.01"
|
||||||
name="donation_amount_eur"
|
name="donation_amount_eur"
|
||||||
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm p-2"
|
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm p-2"
|
||||||
placeholder="2.00" />
|
placeholder="2.00"
|
||||||
|
/>
|
||||||
<button
|
<button
|
||||||
on:click={
|
on:click={() => {
|
||||||
()=>{
|
paid_amount_input = paid_amount_input = (
|
||||||
paid_amount_input=paid_amount_input = (original_data.amount/100).toFixed(2);
|
original_data.amount / 100
|
||||||
}
|
).toFixed(2);
|
||||||
}
|
}}
|
||||||
class="inline-flex items-center p-r-2 text-indigo-300 hover:text-indigo-700 text-sm">MAX</button>
|
class="inline-flex items-center p-r-2 text-indigo-300 hover:text-indigo-700 text-sm"
|
||||||
|
>MAX</button
|
||||||
|
>
|
||||||
<span
|
<span
|
||||||
class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm">€</span>
|
class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm"
|
||||||
|
>€</span
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
{#if !is_paid_amount_valid}
|
{#if !is_paid_amount_valid}
|
||||||
<span
|
<span
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{$_('payment-amount-must-be-greater-than-0-00eur')}
|
>
|
||||||
|
{$_("payment-amount-must-be-greater-than-0-00eur")}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
</div>
|
||||||
<button
|
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||||
disabled={!createbtnenabled}
|
<button
|
||||||
class:opacity-50={!createbtnenabled}
|
disabled={!createbtnenabled}
|
||||||
on:click={submit}
|
class:opacity-50={!createbtnenabled}
|
||||||
type="button"
|
on:click={submit}
|
||||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
type="button"
|
||||||
{$_('save-changes')}
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
</button>
|
>
|
||||||
<button
|
{$_("save-changes")}
|
||||||
on:click={() => {
|
</button>
|
||||||
payment_modal_open = false;
|
<button
|
||||||
}}
|
on:click={() => {
|
||||||
type="button"
|
payment_modal_open = false;
|
||||||
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
|
}}
|
||||||
{$_('cancel')}
|
type="button"
|
||||||
</button>
|
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
</div>
|
>
|
||||||
|
{$_("cancel")}
|
||||||
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -0,0 +1,122 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import { clickOutside } from "../base/outsideclick";
|
||||||
|
import { createEventDispatcher, onMount } from "svelte";
|
||||||
|
export let modal_open;
|
||||||
|
export let delete_donation = {
|
||||||
|
id: 0,
|
||||||
|
runner: {
|
||||||
|
firstname: "",
|
||||||
|
lastname: "",
|
||||||
|
},
|
||||||
|
donor: {
|
||||||
|
firstname: "",
|
||||||
|
lastname: "",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
onMount(() => {
|
||||||
|
document.onkeydown = (e) => {
|
||||||
|
e = e || window.event;
|
||||||
|
if (e.key === "Escape") {
|
||||||
|
modal_open = false;
|
||||||
|
}
|
||||||
|
if (e.keyCode === 13) {
|
||||||
|
if (createbtnenabled === true) {
|
||||||
|
createbtnenabled = false;
|
||||||
|
submit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
async function submit() {
|
||||||
|
dispatch("delete", { id: delete_donation.id });
|
||||||
|
modal_open = false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if modal_open}
|
||||||
|
<div
|
||||||
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
|
use:clickOutside
|
||||||
|
on:click_outside={() => {
|
||||||
|
modal_open = false;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
||||||
|
>
|
||||||
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
|
data-id="modal_backdrop"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
|
aria-hidden="true">​</span
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby="modal-headline"
|
||||||
|
>
|
||||||
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
|
<div class="sm:flex sm:items-start">
|
||||||
|
<div
|
||||||
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="h-6 w-6 text-blue-600"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
{$_("confirm-delete")}
|
||||||
|
</h3>
|
||||||
|
<div class="mt-2 mb-6">
|
||||||
|
<p class="text-sm text-gray-500">
|
||||||
|
{$_("please-confirm-the-deletion-of-donation")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="w-full">
|
||||||
|
<span class="inline-block"
|
||||||
|
><b>{$_("donor")}</b>: {delete_donation.donor.firstname}
|
||||||
|
{delete_donation.donor.lastname}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||||
|
<button
|
||||||
|
on:click={submit}
|
||||||
|
type="button"
|
||||||
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>
|
||||||
|
{$_("delete")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
modal_open = false;
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>
|
||||||
|
{$_("cancel")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
export let donor;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if !donor || donor.firstname == 0}
|
||||||
|
{$_("donor-has-no-associated-donations")}
|
||||||
|
{:else}
|
||||||
|
<div class="flex items-center">
|
||||||
|
<a
|
||||||
|
href="../donors/{donor.id}"
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
||||||
|
>{donor.firstname}
|
||||||
|
{#if donor.middlename}{donor.middlename}{/if}
|
||||||
|
{donor.lastname}</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,18 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
export let runner;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if !runner || runner.firstname == 0}
|
||||||
|
{$_("fixed-donation")}
|
||||||
|
{:else}
|
||||||
|
<div class="text-sm font-medium text-gray-900">
|
||||||
|
<a
|
||||||
|
href="../runners/{runner.id}"
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
||||||
|
>{runner.firstname}
|
||||||
|
{#if runner.middlename}{runner.middlename}{/if}
|
||||||
|
{runner.lastname}</a
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
export let status;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if status == "PAID"}
|
||||||
|
<span
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"
|
||||||
|
>{$_("paid")}</span
|
||||||
|
>
|
||||||
|
{:else}
|
||||||
|
<span
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800"
|
||||||
|
>{$_("open")}</span
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import TableActions from "../shared/TableActions.svelte";
|
||||||
|
|
||||||
|
export let detailsLink;
|
||||||
|
export let detailsAction;
|
||||||
|
export let deleteEnabled;
|
||||||
|
export let deleteAction;
|
||||||
|
export let paymentAction;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<button
|
||||||
|
on:click={paymentAction}
|
||||||
|
class="text-[#025a21] hover:text-green-900 mr-4">{$_("enter-payment")}</button
|
||||||
|
>
|
||||||
|
<TableActions
|
||||||
|
bind:detailsAction
|
||||||
|
bind:detailsLink
|
||||||
|
bind:deleteAction
|
||||||
|
bind:deleteEnabled
|
||||||
|
/>
|
||||||
@@ -5,25 +5,33 @@
|
|||||||
import DonationsOverview from "./DonationsOverview.svelte";
|
import DonationsOverview from "./DonationsOverview.svelte";
|
||||||
$: current_donations = [];
|
$: current_donations = [];
|
||||||
export let modal_open = false;
|
export let modal_open = false;
|
||||||
|
let addDonations;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_('donations')}
|
{$_("donations")}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('DONATION:CREATE')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:CREATE")}
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
modal_open = true;
|
modal_open = true;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
{$_('add-donation')}
|
>
|
||||||
|
{$_("add-donation")}
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
<DonationsOverview bind:current_donations />
|
<DonationsOverview bind:current_donations bind:addDonations />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('DONATION:CREATE')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:CREATE")}
|
||||||
<AddDonationModal bind:current_donations bind:modal_open />
|
<AddDonationModal
|
||||||
|
on:created={(event) => {
|
||||||
|
console.log(event)
|
||||||
|
addDonations(event.detail.donations);
|
||||||
|
}}
|
||||||
|
bind:modal_open
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1,235 +1,287 @@
|
|||||||
<script>
|
<script>
|
||||||
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { DonationService, DonorService } from "@odit/lfk-client-js";
|
import { DonationService } from "@odit/lfk-client-js";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import Toastify from "toastify-js";
|
|
||||||
import DonationsEmptyState from "./DonationsEmptyState.svelte";
|
import DonationsEmptyState from "./DonationsEmptyState.svelte";
|
||||||
import AddDonationPaymentModal from "./AddDonationPaymentModal.svelte";
|
import AddDonationPaymentModal from "./AddDonationPaymentModal.svelte";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import {
|
||||||
|
createSvelteTable,
|
||||||
|
flexRender,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
renderComponent,
|
||||||
|
} from "@tanstack/svelte-table";
|
||||||
|
import { writable } from "svelte/store";
|
||||||
|
import TableBottom from "../shared/TableBottom.svelte";
|
||||||
|
import InputElement from "../shared/InputElement.svelte";
|
||||||
|
import TableHeader from "../shared/TableHeader.svelte";
|
||||||
|
import DonationDonor from "./DonationDonor.svelte";
|
||||||
|
import DonationRunner from "./DonationRunner.svelte";
|
||||||
|
import DonationStatus from "./DonationStatus.svelte";
|
||||||
|
import DonationTableAction from "./DonationTableAction.svelte";
|
||||||
|
import DeleteDonationModal from "./DeleteDonationModal.svelte";
|
||||||
|
import {
|
||||||
|
donationDonorFilter,
|
||||||
|
donationRunnerFilter,
|
||||||
|
} from "../shared/tablefilters";
|
||||||
$: searchvalue = "";
|
$: searchvalue = "";
|
||||||
$: active_deletes = [];
|
$: active_deletes = [];
|
||||||
|
$: active_edits = [];
|
||||||
|
$: selectedDonations =
|
||||||
|
$table?.getSelectedRowModel().rows.map((row) => row.original) || [];
|
||||||
|
$: selected =
|
||||||
|
$table?.getSelectedRowModel().rows.map((row) => row.index) || [];
|
||||||
|
$: dataLoaded = false;
|
||||||
|
|
||||||
export let current_donations = [];
|
export let current_donations = [];
|
||||||
export let payment_modal_open = false;
|
export const addDonations = (donations) => {
|
||||||
export let editable = {};
|
current_donations = current_donations.concat(...donations);
|
||||||
export let original_data = {};
|
options.update((options) => ({
|
||||||
export let paid_amount_input = 0;
|
...options,
|
||||||
const donations_promise = DonationService.donationControllerGetAll().then(
|
data: current_donations,
|
||||||
(val) => {
|
}));
|
||||||
current_donations = val;
|
};
|
||||||
}
|
|
||||||
);
|
//Section table
|
||||||
function should_display_based_on_id(id) {
|
const columns = [
|
||||||
if (searchvalue.toString().slice(-1) === "*") {
|
{
|
||||||
return id.toString().startsWith(searchvalue.replace("*", ""));
|
accessorKey: "id",
|
||||||
}
|
header: () => "id",
|
||||||
return id.toString() === searchvalue;
|
filterFn: `equalsString`,
|
||||||
}
|
},
|
||||||
function open_payment_modal(donation) {
|
{
|
||||||
editable = Object.assign({}, donation);
|
accessorKey: "donor",
|
||||||
original_data = Object.assign({}, donation);
|
header: () => $_("donor"),
|
||||||
paid_amount_input = (donation.paidAmount/100).toFixed(2);
|
cell: (info) => {
|
||||||
payment_modal_open = true;
|
return renderComponent(DonationDonor, { donor: info.getValue() });
|
||||||
|
},
|
||||||
|
filterFn: `donor`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "runner",
|
||||||
|
header: () => $_("runner"),
|
||||||
|
cell: (info) => {
|
||||||
|
return renderComponent(DonationRunner, { runner: info.getValue() });
|
||||||
|
},
|
||||||
|
filterFn: `runner`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "amountPerDistance",
|
||||||
|
header: () => $_("amount-per-kilometer"),
|
||||||
|
cell: (info) => {
|
||||||
|
if (!info.getValue()) {
|
||||||
|
return $_("fixed-donation");
|
||||||
|
}
|
||||||
|
return `${(info.getValue() / 100)
|
||||||
|
.toFixed(2)
|
||||||
|
.toLocaleString("de-DE", { valute: "EUR" })} €`;
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "amount",
|
||||||
|
header: () => $_("donation-amount"),
|
||||||
|
cell: (info) => {
|
||||||
|
return `${(info.getValue() / 100)
|
||||||
|
.toFixed(2)
|
||||||
|
.toLocaleString("de-DE", { valute: "EUR" })} €`;
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "paidAmount",
|
||||||
|
header: () => $_("total-paid-amount"),
|
||||||
|
cell: (info) => {
|
||||||
|
return `${(info.getValue() / 100)
|
||||||
|
.toFixed(2)
|
||||||
|
.toLocaleString("de-DE", { valute: "EUR" })} €`;
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "status",
|
||||||
|
header: () => $_("status"),
|
||||||
|
cell: (info) => {
|
||||||
|
return renderComponent(DonationStatus, { status: info.getValue() });
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "actions",
|
||||||
|
header: () => $_("action"),
|
||||||
|
cell: (info) => {
|
||||||
|
return renderComponent(DonationTableAction, {
|
||||||
|
detailsLink: `./${info.row.original.id}`,
|
||||||
|
deleteAction: () => {
|
||||||
|
active_deletes = current_donations.filter(
|
||||||
|
(r) => r.id == info.row.original.id
|
||||||
|
);
|
||||||
|
},
|
||||||
|
paymentAction: () => {
|
||||||
|
active_edits = current_donations.filter(
|
||||||
|
(r) => r.id == info.row.original.id
|
||||||
|
);
|
||||||
|
},
|
||||||
|
deleteEnabled:
|
||||||
|
store.state.jwtinfo.userdetails.permissions.includes(
|
||||||
|
"DONATION:DELETE"
|
||||||
|
),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
enableSorting: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const options = writable({
|
||||||
|
data: [],
|
||||||
|
columns: columns,
|
||||||
|
initialState: {
|
||||||
|
pagination: {
|
||||||
|
pageSize: 50,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
filterFns: {
|
||||||
|
donor: donationDonorFilter,
|
||||||
|
runner: donationRunnerFilter,
|
||||||
|
},
|
||||||
|
enableRowSelection: true,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
});
|
||||||
|
const table = createSvelteTable(options);
|
||||||
|
|
||||||
|
async function deleteDonation(delete_donation_id) {
|
||||||
|
await DonationService.donationControllerRemove(delete_donation_id, true);
|
||||||
|
current_donations = current_donations.filter(
|
||||||
|
(r) => r.id !== delete_donation_id
|
||||||
|
);
|
||||||
|
options.update((options) => ({
|
||||||
|
...options,
|
||||||
|
data: current_donations,
|
||||||
|
}));
|
||||||
|
Toastify({
|
||||||
|
text: $_("donation-deleted"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
let page = 0;
|
||||||
|
while (page >= 0) {
|
||||||
|
const donations = await DonationService.donationControllerGetAll(
|
||||||
|
page,
|
||||||
|
100
|
||||||
|
);
|
||||||
|
if (donations.length == 0) {
|
||||||
|
page = -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_donations = current_donations.concat(...donations);
|
||||||
|
options.update((options) => ({
|
||||||
|
...options,
|
||||||
|
data: current_donations,
|
||||||
|
}));
|
||||||
|
|
||||||
|
dataLoaded = true;
|
||||||
|
page++;
|
||||||
|
}
|
||||||
|
console.log("All donations loaded");
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<AddDonationPaymentModal bind:current_donations bind:original_data bind:editable bind:paid_amount_input bind:payment_modal_open />
|
<AddDonationPaymentModal
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('DONATION:GET')}
|
original_data={active_edits[0]}
|
||||||
{#await donations_promise}
|
payment_modal_open={active_edits.length > 0}
|
||||||
|
paid_amount_input={(active_edits[0]?.paidAmount || 0) / 100}
|
||||||
|
on:created={(event) => {
|
||||||
|
current_donations[
|
||||||
|
current_donations.findIndex((d) => d.id === event.detail.donation.id)
|
||||||
|
].paidAmount = event.detail.donation.paidAmount;
|
||||||
|
options.update((options) => ({
|
||||||
|
...options,
|
||||||
|
data: current_donations,
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
<DeleteDonationModal
|
||||||
|
delete_donation={active_deletes[0]}
|
||||||
|
modal_open={active_deletes.length > 0}
|
||||||
|
on:delete={(event) => {
|
||||||
|
deleteDonation(event.detail.id);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:GET")}
|
||||||
|
{#if !dataLoaded}
|
||||||
<div
|
<div
|
||||||
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
||||||
role="alert">
|
role="alert"
|
||||||
<p class="font-bold">donations are being loaded</p>
|
>
|
||||||
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
<p class="font-bold">{$_("donations-are-being-loaded")}</p>
|
||||||
|
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
||||||
</div>
|
</div>
|
||||||
{:then}
|
{:else if current_donations.length === 0}
|
||||||
{#if current_donations.length === 0}
|
<DonationsEmptyState />
|
||||||
<DonationsEmptyState />
|
{:else}
|
||||||
{:else}
|
<input
|
||||||
<input
|
type="search"
|
||||||
type="search"
|
bind:value={searchvalue}
|
||||||
bind:value={searchvalue}
|
placeholder={$_("datatable.search")}
|
||||||
placeholder={$_('datatable.search')}
|
aria-label={$_("datatable.search")}
|
||||||
aria-label={$_('datatable.search')}
|
class="mb-4"
|
||||||
class="gridjs-input gridjs-search-input mb-4" />
|
/>
|
||||||
<div
|
<div
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
|
||||||
<table class="divide-y divide-gray-200 w-full">
|
>
|
||||||
<thead class="bg-gray-50">
|
<table class="w-full">
|
||||||
<tr>
|
<thead>
|
||||||
<th
|
{#each $table.getHeaderGroups() as headerGroup}
|
||||||
scope="col"
|
<tr class="select-none">
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
<th class="inset-y-0 left-0 px-4 py-2 text-left w-px">
|
||||||
{$_('donor')}
|
<InputElement
|
||||||
</th>
|
type="checkbox"
|
||||||
<th
|
checked={$table.getIsAllRowsSelected()}
|
||||||
scope="col"
|
indeterminate={$table.getIsSomeRowsSelected()}
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
on:change={() => $table.toggleAllRowsSelected()}
|
||||||
{$_('runner')}
|
/>
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('amount-per-kilometer')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('donation-amount')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('paid-amount')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('status')}
|
|
||||||
</th>
|
|
||||||
<th scope="col" class="relative px-6 py-3">
|
|
||||||
<span class="sr-only">{$_('action')}</span>
|
|
||||||
</th>
|
</th>
|
||||||
|
{#each headerGroup.headers as header}
|
||||||
|
<TableHeader {header} />
|
||||||
|
{/each}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
{/each}
|
||||||
<tbody class="divide-y divide-gray-200">
|
</thead>
|
||||||
{#each current_donations as donation}
|
<tbody>
|
||||||
{#if donation.donor.firstname
|
{#each $table.getRowModel().rows as row}
|
||||||
.toLowerCase()
|
<tr>
|
||||||
.includes(
|
<td class="inset-y-0 left-0 px-4 py-2 text-center w-px">
|
||||||
searchvalue.toLowerCase()
|
<InputElement
|
||||||
) || donation.donor.lastname
|
type="checkbox"
|
||||||
.toLowerCase()
|
checked={row.getIsSelected()}
|
||||||
.includes(
|
on:change={() => row.toggleSelected()}
|
||||||
searchvalue.toLowerCase()
|
/>
|
||||||
) || donation.runner?.firstname
|
</td>
|
||||||
.toLowerCase()
|
{#each row.getVisibleCells() as cell}
|
||||||
.includes(
|
<td>
|
||||||
searchvalue.toLowerCase()
|
<svelte:component
|
||||||
) || donation.runner?.lastname
|
this={flexRender(
|
||||||
.toLowerCase()
|
cell.column.columnDef.cell,
|
||||||
.includes(
|
cell.getContext()
|
||||||
searchvalue.toLowerCase()
|
)}
|
||||||
) || should_display_based_on_id(donation.id)}
|
/>
|
||||||
<tr data-rowid="donation_{donation.id}">
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
{/each}
|
||||||
<div class="flex items-center">
|
</tr>
|
||||||
<a
|
{/each}
|
||||||
href="../donors/{donation.donor.id}"
|
</tbody>
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{donation.donor.firstname}
|
</table>
|
||||||
{donation.donor.middlename || ''}
|
|
||||||
{donation.donor.lastname}</a>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
{#if donation.runner}
|
|
||||||
<div class="text-sm font-medium text-gray-900">
|
|
||||||
<a
|
|
||||||
href="../runners/{donation.runner.id}"
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{donation.runner.firstname}
|
|
||||||
{donation.runner.middlename || ''}
|
|
||||||
{donation.runner.lastname}</a>
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<div class="text-sm font-medium text-gray-900">
|
|
||||||
{$_('fixed-donation')}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
{#if donation.amountPerDistance}
|
|
||||||
<div class="text-sm font-medium text-gray-900">
|
|
||||||
{(donation.amountPerDistance / 100)
|
|
||||||
.toFixed(2)
|
|
||||||
.toLocaleString('de-DE', { valute: 'EUR' })}€
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<div class="text-sm font-medium text-gray-900">
|
|
||||||
{$_('fixed-donation')}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<div class="text-sm font-medium text-gray-900">
|
|
||||||
{(donation.amount / 100)
|
|
||||||
.toFixed(2)
|
|
||||||
.toLocaleString('de-DE', { valute: 'EUR' })}€
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<div class="text-sm font-medium text-gray-900">
|
|
||||||
{(donation.paidAmount / 100)
|
|
||||||
.toFixed(2)
|
|
||||||
.toLocaleString('de-DE', { valute: 'EUR' })}€
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
{#if donation.status =="PAID"}
|
|
||||||
<span
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">{$_('paid')}</span>
|
|
||||||
{:else}
|
|
||||||
<span
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">{$_('open')}</span>
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
{#if active_deletes[donation.id] === true}
|
|
||||||
<td
|
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[donation.id] = false;
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">{$_('cancel-delete')}</button>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
DonationService.donationControllerRemove(donation.id, false).then(
|
|
||||||
(resp) => {
|
|
||||||
current_donations = current_donations.filter(
|
|
||||||
(obj) => obj.id !== donation.id
|
|
||||||
);
|
|
||||||
Toastify({
|
|
||||||
text: $_('donation-deleted'),
|
|
||||||
duration: 500,
|
|
||||||
backgroundColor:
|
|
||||||
'linear-gradient(to right, #00b09b, #96c93d)',
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('confirm-delete')}</button>
|
|
||||||
</td>
|
|
||||||
{:else}
|
|
||||||
<td
|
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
||||||
<button
|
|
||||||
on:click={() => {open_payment_modal(donation);}}
|
|
||||||
class="text-[#025a21] hover:text-green-900 mr-4">{$_('enter-payment')}</button>
|
|
||||||
<a
|
|
||||||
href="./{donation.id}"
|
|
||||||
class="text-indigo-600 hover:text-indigo-900">{$_('details')}</a>
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('DONATION:DELETE')}
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[donation.id] = true;
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
{/if}
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{:catch error}
|
|
||||||
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
|
|
||||||
<span class="inline-block align-middle mr-8">
|
|
||||||
<b class="capitalize">{$_('general_promise_error')}</b>
|
|
||||||
{error}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
{/await}
|
<div class="h-2" />
|
||||||
|
<TableBottom {table} {selected} />
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1,15 +1,13 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import {
|
import { DonorService } from "@odit/lfk-client-js";
|
||||||
DonorService
|
|
||||||
} from "@odit/lfk-client-js";
|
|
||||||
import isEmail from "validator/es/lib/isEmail";
|
import isEmail from "validator/es/lib/isEmail";
|
||||||
import isMobilePhone from "validator/es/lib/isMobilePhone";
|
import isMobilePhone from "validator/es/lib/isMobilePhone";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
export let modal_open;
|
export let modal_open;
|
||||||
export let current_donors;
|
|
||||||
let firstname_input;
|
let firstname_input;
|
||||||
let lastname_input;
|
let lastname_input;
|
||||||
let middlename_input;
|
let middlename_input;
|
||||||
@@ -19,6 +17,7 @@
|
|||||||
let address_input2;
|
let address_input2;
|
||||||
let address_zipcode;
|
let address_zipcode;
|
||||||
let address_city;
|
let address_city;
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
function focus(el) {
|
function focus(el) {
|
||||||
el.focus();
|
el.focus();
|
||||||
}
|
}
|
||||||
@@ -75,7 +74,7 @@
|
|||||||
if (processed_last_submit === true) {
|
if (processed_last_submit === true) {
|
||||||
processed_last_submit = false;
|
processed_last_submit = false;
|
||||||
const toast = Toastify({
|
const toast = Toastify({
|
||||||
text: $_('donor-is-being-added'),
|
text: $_("donor-is-being-added"),
|
||||||
duration: -1,
|
duration: -1,
|
||||||
}).showToast();
|
}).showToast();
|
||||||
let address = {};
|
let address = {};
|
||||||
@@ -92,7 +91,7 @@
|
|||||||
firstname: firstname_input_value,
|
firstname: firstname_input_value,
|
||||||
lastname: lastname_input_value,
|
lastname: lastname_input_value,
|
||||||
address,
|
address,
|
||||||
receiptNeeded: address_checked
|
receiptNeeded: address_checked,
|
||||||
};
|
};
|
||||||
if (middlename_input_value) {
|
if (middlename_input_value) {
|
||||||
postdata.middlename = middlename_input_value;
|
postdata.middlename = middlename_input_value;
|
||||||
@@ -112,12 +111,11 @@
|
|||||||
modal_open = false;
|
modal_open = false;
|
||||||
//
|
//
|
||||||
Toastify({
|
Toastify({
|
||||||
text: $_('donor-added'),
|
text: $_("donor-added"),
|
||||||
duration: 500,
|
duration: 500,
|
||||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
current_donors.push(result);
|
dispatch("created", { donors: [result] });
|
||||||
current_donors = current_donors;
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
//
|
//
|
||||||
@@ -134,58 +132,70 @@
|
|||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={() => {
|
on:click_outside={() => {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
}}>
|
}}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
||||||
|
>
|
||||||
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
<div
|
<div
|
||||||
class="absolute inset-0 bg-gray-500 opacity-75"
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
data-id="modal_backdrop" />
|
data-id="modal_backdrop"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
aria-hidden="true">​</span>
|
aria-hidden="true">​</span
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
aria-labelledby="modal-headline">
|
aria-labelledby="modal-headline"
|
||||||
|
>
|
||||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
<div class="sm:flex sm:items-start">
|
<div class="sm:flex sm:items-start">
|
||||||
<div
|
<div
|
||||||
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
||||||
|
>
|
||||||
<svg
|
<svg
|
||||||
class="h-6 w-6 text-blue-600"
|
class="h-6 w-6 text-blue-600"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
height="24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path
|
<path
|
||||||
d="M9.33 11.5h2.17A4.5 4.5 0 0 1 16 16H8.999L9 17h8v-1a5.578 5.578 0 0 0-.886-3H19a5 5 0 0 1 4.516 2.851C21.151 18.972 17.322 21 13 21c-2.761 0-5.1-.59-7-1.625L6 10.071A6.967 6.967 0 0 1 9.33 11.5zM5 19a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v9zM18 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6zm-7-3a3 3 0 1 1 0 6 3 3 0 0 1 0-6z" /></svg>
|
d="M9.33 11.5h2.17A4.5 4.5 0 0 1 16 16H8.999L9 17h8v-1a5.578 5.578 0 0 0-.886-3H19a5 5 0 0 1 4.516 2.851C21.151 18.972 17.322 21 13 21c-2.761 0-5.1-.59-7-1.625L6 10.071A6.967 6.967 0 0 1 9.33 11.5zM5 19a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v9zM18 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6zm-7-3a3 3 0 1 1 0 6 3 3 0 0 1 0-6z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
{$_('create-a-new-donor')}
|
{$_("create-a-new-donor")}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="mt-2 mb-6">
|
<div class="mt-2 mb-6">
|
||||||
<p class="text-sm text-gray-500">
|
<p class="text-sm text-gray-500">
|
||||||
{$_('please-provide-the-nessecary-information-to-add-a-new-donor')}
|
{$_(
|
||||||
|
"please-provide-the-nessecary-information-to-add-a-new-donor"
|
||||||
|
)}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="grid grid-cols-6 gap-6">
|
<div class="grid grid-cols-6 gap-6">
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
<label
|
<label
|
||||||
for="firstname"
|
for="firstname"
|
||||||
class="block text-sm font-medium text-gray-700">{$_('first-name')}</label>
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>{$_("first-name")}</label
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
use:focus
|
use:focus
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('first-name')}
|
placeholder={$_("first-name")}
|
||||||
class:border-red-500={!isFirstnameValid}
|
class:border-red-500={!isFirstnameValid}
|
||||||
class:focus:border-red-500={!isFirstnameValid}
|
class:focus:border-red-500={!isFirstnameValid}
|
||||||
class:focus:ring-red-500={!isFirstnameValid}
|
class:focus:ring-red-500={!isFirstnameValid}
|
||||||
@@ -193,34 +203,41 @@
|
|||||||
bind:this={firstname_input}
|
bind:this={firstname_input}
|
||||||
type="text"
|
type="text"
|
||||||
name="firstname"
|
name="firstname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
{#if !isFirstnameValid}
|
{#if !isFirstnameValid}
|
||||||
<span
|
<span
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{$_('first-name-is-required')}
|
>
|
||||||
|
{$_("first-name-is-required")}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
<label
|
<label
|
||||||
for="trackname"
|
for="trackname"
|
||||||
class="block text-sm font-medium text-gray-700">{$_('middle-name')}</label>
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>{$_("middle-name")}</label
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('middle-name')}
|
placeholder={$_("middle-name")}
|
||||||
bind:value={middlename_input_value}
|
bind:value={middlename_input_value}
|
||||||
bind:this={middlename_input}
|
bind:this={middlename_input}
|
||||||
type="text"
|
type="text"
|
||||||
name="trackname"
|
name="trackname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
<label
|
<label
|
||||||
for="lastname"
|
for="lastname"
|
||||||
class="block text-sm font-medium text-gray-700">{$_('last-name')}</label>
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>{$_("last-name")}</label
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder="{$_('last-name')}"
|
placeholder={$_("last-name")}
|
||||||
class:border-red-500={!isLastnameValid}
|
class:border-red-500={!isLastnameValid}
|
||||||
class:focus:border-red-500={!isLastnameValid}
|
class:focus:border-red-500={!isLastnameValid}
|
||||||
class:focus:ring-red-500={!isLastnameValid}
|
class:focus:ring-red-500={!isLastnameValid}
|
||||||
@@ -228,21 +245,25 @@
|
|||||||
bind:this={lastname_input}
|
bind:this={lastname_input}
|
||||||
type="text"
|
type="text"
|
||||||
name="lastname"
|
name="lastname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
{#if !isLastnameValid}
|
{#if !isLastnameValid}
|
||||||
<span
|
<span
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{$_('last-name-is-required')}
|
>
|
||||||
|
{$_("last-name-is-required")}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
<label
|
<label
|
||||||
for="phone"
|
for="phone"
|
||||||
class="block text-sm font-medium text-gray-700">{$_('phone')}</label>
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>{$_("phone")}</label
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('phone')}
|
placeholder={$_("phone")}
|
||||||
class:border-red-500={!isPhoneValidOrEmpty}
|
class:border-red-500={!isPhoneValidOrEmpty}
|
||||||
class:focus:border-red-500={!isPhoneValidOrEmpty}
|
class:focus:border-red-500={!isPhoneValidOrEmpty}
|
||||||
class:focus:ring-red-500={!isPhoneValidOrEmpty}
|
class:focus:ring-red-500={!isPhoneValidOrEmpty}
|
||||||
@@ -250,21 +271,27 @@
|
|||||||
bind:this={phone_input}
|
bind:this={phone_input}
|
||||||
type="tel"
|
type="tel"
|
||||||
name="phone"
|
name="phone"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
{#if !isPhoneValidOrEmpty}
|
{#if !isPhoneValidOrEmpty}
|
||||||
<span
|
<span
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{@html $_('the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number')}
|
>
|
||||||
|
{@html $_(
|
||||||
|
"the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number"
|
||||||
|
)}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
<label
|
<label
|
||||||
for="email"
|
for="email"
|
||||||
class="block text-sm font-medium text-gray-700">{$_('e-mail-adress')}</label>
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>{$_("e-mail-adress")}</label
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('e-mail-adress')}
|
placeholder={$_("e-mail-adress")}
|
||||||
class:border-red-500={!isEmailValidOrEmpty}
|
class:border-red-500={!isEmailValidOrEmpty}
|
||||||
class:focus:border-red-500={!isEmailValidOrEmpty}
|
class:focus:border-red-500={!isEmailValidOrEmpty}
|
||||||
class:focus:ring-red-500={!isEmailValidOrEmpty}
|
class:focus:ring-red-500={!isEmailValidOrEmpty}
|
||||||
@@ -272,11 +299,13 @@
|
|||||||
bind:this={email_input}
|
bind:this={email_input}
|
||||||
type="email"
|
type="email"
|
||||||
name="email"
|
name="email"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
{#if !isEmailValidOrEmpty}
|
{#if !isEmailValidOrEmpty}
|
||||||
<span
|
<span
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{$_('valid-email-is-required')}
|
>
|
||||||
|
{$_("valid-email-is-required")}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
@@ -287,19 +316,22 @@
|
|||||||
id="comments"
|
id="comments"
|
||||||
name="comments"
|
name="comments"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" />
|
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-3 text-sm">
|
<div class="ml-3 text-sm">
|
||||||
<label
|
<label for="comments" class="font-medium text-gray-700"
|
||||||
for="comments"
|
>{$_("receipt-needed")}</label
|
||||||
class="font-medium text-gray-700">{$_('receipt-needed')}</label>
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{#if address_checked === true}
|
{#if address_checked === true}
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
<label
|
<label
|
||||||
for="address1"
|
for="address1"
|
||||||
class="block text-sm font-medium text-gray-700">{$_('address')}</label>
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>{$_("address")}</label
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder="Address"
|
placeholder="Address"
|
||||||
@@ -310,34 +342,41 @@
|
|||||||
bind:this={address_input1}
|
bind:this={address_input1}
|
||||||
type="text"
|
type="text"
|
||||||
name="address1"
|
name="address1"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
{#if !isAddress1Valid}
|
{#if !isAddress1Valid}
|
||||||
<span
|
<span
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{$_('address-is-required')}
|
>
|
||||||
|
{$_("address-is-required")}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
<label
|
<label
|
||||||
for="address2"
|
for="address2"
|
||||||
class="block text-sm font-medium text-gray-700">{$_('apartment-suite-etc')}</label>
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>{$_("apartment-suite-etc")}</label
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('apartment-suite-etc')}
|
placeholder={$_("apartment-suite-etc")}
|
||||||
bind:value={address_input2_value}
|
bind:value={address_input2_value}
|
||||||
bind:this={address_input2}
|
bind:this={address_input2}
|
||||||
type="text"
|
type="text"
|
||||||
name="address2"
|
name="address2"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
<label
|
<label
|
||||||
for="zipcode"
|
for="zipcode"
|
||||||
class="block text-sm font-medium text-gray-700">{$_('zip-postal-code')}</label>
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>{$_("zip-postal-code")}</label
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('zip-postal-code')}
|
placeholder={$_("zip-postal-code")}
|
||||||
class:border-red-500={!iszipcodevalid}
|
class:border-red-500={!iszipcodevalid}
|
||||||
class:focus:border-red-500={!iszipcodevalid}
|
class:focus:border-red-500={!iszipcodevalid}
|
||||||
class:focus:ring-red-500={!iszipcodevalid}
|
class:focus:ring-red-500={!iszipcodevalid}
|
||||||
@@ -345,18 +384,22 @@
|
|||||||
bind:this={address_zipcode}
|
bind:this={address_zipcode}
|
||||||
type="text"
|
type="text"
|
||||||
name="zipcode"
|
name="zipcode"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
{#if !iszipcodevalid}
|
{#if !iszipcodevalid}
|
||||||
<span
|
<span
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{$_('valid-zipcode-postal-code-is-required')}
|
>
|
||||||
|
{$_("valid-zipcode-postal-code-is-required")}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
<label
|
<label
|
||||||
for="city"
|
for="city"
|
||||||
class="block text-sm font-medium text-gray-700">City</label>
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>City</label
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder="City"
|
placeholder="City"
|
||||||
@@ -367,11 +410,13 @@
|
|||||||
bind:this={address_city}
|
bind:this={address_city}
|
||||||
type="text"
|
type="text"
|
||||||
name="city"
|
name="city"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
{#if !iscityvalid}
|
{#if !iscityvalid}
|
||||||
<span
|
<span
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{$_('valid-city-is-required')}
|
>
|
||||||
|
{$_("valid-city-is-required")}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
@@ -386,16 +431,18 @@
|
|||||||
class:opacity-50={!createbtnenabled}
|
class:opacity-50={!createbtnenabled}
|
||||||
on:click={submit}
|
on:click={submit}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
{$_('create')}
|
>
|
||||||
|
{$_("create")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
|
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
{$_('cancel')}
|
>
|
||||||
|
{$_("cancel")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import { DonorService } from "@odit/lfk-client-js";
|
import { DonorService } from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
@@ -13,60 +13,61 @@
|
|||||||
dispatch("cancelDelete", { id: delete_donor.id });
|
dispatch("cancelDelete", { id: delete_donor.id });
|
||||||
}
|
}
|
||||||
function deleteDonor() {
|
function deleteDonor() {
|
||||||
DonorService.donorControllerRemove(
|
dispatch("delete", { id: delete_donor.id });
|
||||||
delete_donor.id,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
.then((resp) => {
|
|
||||||
Toastify({
|
|
||||||
text: $_('donor-deleted'),
|
|
||||||
duration: 500,
|
|
||||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
location.replace("./");
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={cancelDelete}>
|
on:click_outside={cancelDelete}
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
||||||
|
>
|
||||||
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
<div
|
<div
|
||||||
class="absolute inset-0 bg-gray-500 opacity-75"
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
data-id="modal_backdrop" />
|
data-id="modal_backdrop"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
aria-hidden="true">​</span>
|
aria-hidden="true">​</span
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
aria-labelledby="modal-headline">
|
aria-labelledby="modal-headline"
|
||||||
|
>
|
||||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
<div class="sm:flex sm:items-start">
|
<div class="sm:flex sm:items-start">
|
||||||
<div
|
<div
|
||||||
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
||||||
<svg class="h-6 w-6 text-blue-600" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M9.33 11.5h2.17A4.5 4.5 0 0116 16H9v1h8v-1a5.58 5.58 0 00-.89-3H19a5 5 0 014.52 2.85A13.15 13.15 0 0113 21c-2.76 0-5.1-.59-7-1.63v-9.3a6.97 6.97 0 013.33 1.43zM5 19a1 1 0 01-1 1H2a1 1 0 01-1-1v-9a1 1 0 011-1h2a1 1 0 011 1v9zM18 5a3 3 0 110 6 3 3 0 010-6zm-7-3a3 3 0 110 6 3 3 0 010-6z"/></svg>
|
>
|
||||||
|
<svg
|
||||||
|
class="h-6 w-6 text-blue-600"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" /><path
|
||||||
|
d="M9.33 11.5h2.17A4.5 4.5 0 0116 16H9v1h8v-1a5.58 5.58 0 00-.89-3H19a5 5 0 014.52 2.85A13.15 13.15 0 0113 21c-2.76 0-5.1-.59-7-1.63v-9.3a6.97 6.97 0 013.33 1.43zM5 19a1 1 0 01-1 1H2a1 1 0 01-1-1v-9a1 1 0 011-1h2a1 1 0 011 1v9zM18 5a3 3 0 110 6 3 3 0 010-6zm-7-3a3 3 0 110 6 3 3 0 010-6z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
{$_('attention')}
|
{$_("attention")}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="mt-2 mb-6">
|
<div class="mt-2 mb-6">
|
||||||
<p class="text-sm text-gray-500">
|
<p class="text-sm text-gray-500">
|
||||||
{$_(
|
{$_(
|
||||||
'do-you-want-to-delete-this-donor-with-all-related-donations'
|
"do-you-want-to-delete-this-donor-with-all-related-donations"
|
||||||
)}
|
)}
|
||||||
<br />
|
<br />
|
||||||
{$_('all-associated-donations-will-get-deleted-as-well')}
|
{$_("all-associated-donations-will-get-deleted-as-well")}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -76,14 +77,16 @@
|
|||||||
<button
|
<button
|
||||||
on:click={deleteDonor}
|
on:click={deleteDonor}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
{$_('confirm-delete-donor-with-all-donations')}
|
>
|
||||||
|
{$_("confirm-delete-donor-with-all-donations")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={cancelDelete}
|
on:click={cancelDelete}
|
||||||
type="button"
|
type="button"
|
||||||
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
|
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
{$_('cancel-keep-donor')}
|
>
|
||||||
|
{$_("cancel-keep-donor")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
export let address;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if !address || !address.address1}
|
||||||
|
{$_("no-address")}
|
||||||
|
{:else}
|
||||||
|
{address.address1}<br />
|
||||||
|
<!-- {address.address2 || ''}<br /> -->
|
||||||
|
{address.postalcode}
|
||||||
|
{address.city}
|
||||||
|
{address.country}
|
||||||
|
{/if}
|
||||||
@@ -207,7 +207,7 @@
|
|||||||
<a
|
<a
|
||||||
href="../donations/{d.id}"
|
href="../donations/{d.id}"
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-600 text-white mr-1">{d.runner.firstname}
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-600 text-white mr-1">{d.runner.firstname}
|
||||||
{d.runner.middlename}
|
{d.runner.middlename || ""}
|
||||||
{d.runner.lastname}</a>
|
{d.runner.lastname}</a>
|
||||||
{:else}
|
{:else}
|
||||||
<a
|
<a
|
||||||
|
|||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
export let donations;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if !donations || donations.length == 0}
|
||||||
|
{$_('donor-has-no-associated-donations')}
|
||||||
|
{:else}
|
||||||
|
{#each donations as donation}
|
||||||
|
{#if donation.responseType === "DISTANCEDONATION"}
|
||||||
|
<a
|
||||||
|
href="../donations/{donation.id}"
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-600 text-white mr-1"
|
||||||
|
>{donation.runner.firstname}
|
||||||
|
{donation.runner.middlename || ""}
|
||||||
|
{donation.runner.lastname}</a
|
||||||
|
>
|
||||||
|
{:else}
|
||||||
|
<a
|
||||||
|
href="../donations/{donation.id}"
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-700 text-white mr-1"
|
||||||
|
>{$_("fixed-donation")}:
|
||||||
|
{(donation.amount / 100)
|
||||||
|
.toFixed(2)
|
||||||
|
.toLocaleString("de-DE", { valute: "EUR" })}€</a
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
{/if}
|
||||||
@@ -5,50 +5,73 @@
|
|||||||
import DonorsOverview from "./DonorsOverview.svelte";
|
import DonorsOverview from "./DonorsOverview.svelte";
|
||||||
$: current_donors = [];
|
$: current_donors = [];
|
||||||
export let modal_open = false;
|
export let modal_open = false;
|
||||||
|
let addDonors;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_('donors')}
|
{$_("donors")}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('DONOR:CREATE')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:CREATE")}
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
modal_open = true;
|
modal_open = true;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
{$_('add-donor')}
|
>
|
||||||
|
{$_("add-donor")}
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('DONOR:GET')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:GET")}
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
const data = (current_donors.filter(d=>d.receiptNeeded===true)).map(function (d) {
|
const data = current_donors
|
||||||
d.address.address2=d.address.address2===""?"":" "+d.address.address2;
|
.filter((d) => d.receiptNeeded === true)
|
||||||
const address=`${d.address.address1}${d.address.address2}, ${d.address.postalcode} ${d.address.city}, ${d.address.country}`;
|
.map(function (d) {
|
||||||
return [d.firstname,d.middlename,d.lastname,d.paidDonationAmount,address];
|
d.address.address2 =
|
||||||
})
|
d.address.address2 === "" ? "" : " " + d.address.address2;
|
||||||
let csv = `${$_('csv_import__firstname')};${$_('csv_import__middlename')};${$_('csv_import__lastname')};${$_('total_donation_amount_in_eur')};${$_('address')}\n`;
|
const address = `${d.address.address1}${d.address.address2}, ${d.address.postalcode} ${d.address.city}, ${d.address.country}`;
|
||||||
data.forEach(function(row) {
|
return [
|
||||||
csv += row.join(';');
|
d.firstname,
|
||||||
|
d.middlename,
|
||||||
|
d.lastname,
|
||||||
|
d.paidDonationAmount,
|
||||||
|
address,
|
||||||
|
];
|
||||||
|
});
|
||||||
|
let csv = `${$_("csv_import__firstname")};${$_(
|
||||||
|
"csv_import__middlename"
|
||||||
|
)};${$_("csv_import__lastname")};${$_(
|
||||||
|
"total_donation_amount_in_eur"
|
||||||
|
)};${$_("address")}\n`;
|
||||||
|
data.forEach(function (row) {
|
||||||
|
csv += row.join(";");
|
||||||
csv += "\n";
|
csv += "\n";
|
||||||
});
|
});
|
||||||
let hiddenElement = document.createElement('a');
|
let hiddenElement = document.createElement("a");
|
||||||
hiddenElement.href = 'data:text/csv;charset=utf-8,' + encodeURI(csv);
|
hiddenElement.href = "data:text/csv;charset=utf-8," + encodeURI(csv);
|
||||||
hiddenElement.target = '_blank';
|
hiddenElement.target = "_blank";
|
||||||
hiddenElement.download = `${$_('filename_sponsoringquittungsliste')}.csv`;
|
hiddenElement.download = `${$_(
|
||||||
hiddenElement.click();
|
"filename_sponsoringquittungsliste"
|
||||||
hiddenElement.remove();
|
)}.csv`;
|
||||||
|
hiddenElement.click();
|
||||||
|
hiddenElement.remove();
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
{$_('sponsoring-quittungs-liste_herunterladen')}
|
>
|
||||||
|
{$_("sponsoring-quittungs-liste_herunterladen")}
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
<DonorsOverview bind:current_donors />
|
<DonorsOverview bind:current_donors bind:addDonors />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('DONOR:CREATE')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:CREATE")}
|
||||||
<AddDonorModal bind:current_donors bind:modal_open />
|
<AddDonorModal
|
||||||
|
on:created={(event) => {
|
||||||
|
addDonors(event.detail.donors);
|
||||||
|
}}
|
||||||
|
bind:modal_open
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -5,214 +5,255 @@
|
|||||||
import DonorsEmptyState from "./DonorsEmptyState.svelte";
|
import DonorsEmptyState from "./DonorsEmptyState.svelte";
|
||||||
import ConfirmDonorDeletion from "./ConfirmDonorDeletion.svelte";
|
import ConfirmDonorDeletion from "./ConfirmDonorDeletion.svelte";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
|
import TableBottom from "../shared/TableBottom.svelte";
|
||||||
|
import {
|
||||||
|
createSvelteTable,
|
||||||
|
flexRender,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
renderComponent,
|
||||||
|
} from "@tanstack/svelte-table";
|
||||||
|
import { writable } from "svelte/store";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import InputElement from "../shared/InputElement.svelte";
|
||||||
|
import TableHeader from "../shared/TableHeader.svelte";
|
||||||
|
import TableActions from "../shared/TableActions.svelte";
|
||||||
|
import DonorAddress from "./DonorAddress.svelte";
|
||||||
|
import DonorDonations from "./DonorDonations.svelte";
|
||||||
|
import { filterAddress, filterName } from "../shared/tablefilters";
|
||||||
$: searchvalue = "";
|
$: searchvalue = "";
|
||||||
$: active_deletes = [];
|
$: active_deletes = [];
|
||||||
$: current_donations = [];
|
$: selectedDonors =
|
||||||
let modal_open = false;
|
$table?.getSelectedRowModel().rows.map((row) => row.original) || [];
|
||||||
let delete_donor = {};
|
$: selected =
|
||||||
|
$table?.getSelectedRowModel().rows.map((row) => row.index) || [];
|
||||||
|
|
||||||
|
$: dataLoaded = false;
|
||||||
|
|
||||||
export let current_donors = [];
|
export let current_donors = [];
|
||||||
const donors_promise = DonorService.donorControllerGetAll().then((val) => {
|
export const addDonors = (donors) => {
|
||||||
current_donors = val;
|
current_donors = current_donors.concat(...donors);
|
||||||
|
options.update((options) => ({
|
||||||
|
...options,
|
||||||
|
data: current_donors,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
//Section table
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
accessorKey: "id",
|
||||||
|
header: () => "id",
|
||||||
|
filterFn: `equalsString`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "name",
|
||||||
|
header: () => $_("name"),
|
||||||
|
cell: (info) => {
|
||||||
|
const d = info.row.original;
|
||||||
|
if (d.middlename) {
|
||||||
|
return `${d.firstname} ${d.middlename} ${d.lastname}`;
|
||||||
|
} else {
|
||||||
|
return `${d.firstname} ${d.lastname}`;
|
||||||
|
}
|
||||||
|
},
|
||||||
|
filterFn: `name`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "address",
|
||||||
|
header: () => $_("contact-information"),
|
||||||
|
cell: (info) => {
|
||||||
|
return renderComponent(DonorAddress, { address: info.getValue() });
|
||||||
|
},
|
||||||
|
filterFn: `address`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "donations",
|
||||||
|
header: () => $_("sponsorings"),
|
||||||
|
cell: (info) => {
|
||||||
|
return renderComponent(DonorDonations, { donations: info.getValue() });
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "donationAmount",
|
||||||
|
header: () => $_("total-donation-amount"),
|
||||||
|
cell: (info) => {
|
||||||
|
return `${(info.getValue() / 100)
|
||||||
|
.toFixed(2)
|
||||||
|
.toLocaleString("de-DE", { valute: "EUR" })}€`;
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "paidDonationAmount",
|
||||||
|
header: () => $_("total-paid-amount"),
|
||||||
|
cell: (info) => {
|
||||||
|
return `${(info.getValue() / 100)
|
||||||
|
.toFixed(2)
|
||||||
|
.toLocaleString("de-DE", { valute: "EUR" })}€`;
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "actions",
|
||||||
|
header: () => $_("action"),
|
||||||
|
cell: (info) => {
|
||||||
|
return renderComponent(TableActions, {
|
||||||
|
detailsLink: `./${info.row.original.id}`,
|
||||||
|
deleteAction: () => {
|
||||||
|
active_deletes = current_donors.filter(
|
||||||
|
(r) => r.id == info.row.original.id
|
||||||
|
);
|
||||||
|
},
|
||||||
|
deleteEnabled:
|
||||||
|
store.state.jwtinfo.userdetails.permissions.includes(
|
||||||
|
"DONOR:DELETE"
|
||||||
|
),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
enableSorting: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const options = writable({
|
||||||
|
data: [],
|
||||||
|
columns: columns,
|
||||||
|
initialState: {
|
||||||
|
pagination: {
|
||||||
|
pageSize: 50,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
filterFns: {
|
||||||
|
name: filterName,
|
||||||
|
address: filterAddress,
|
||||||
|
},
|
||||||
|
enableRowSelection: true,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
});
|
});
|
||||||
const donation_promise = DonationService.donationControllerGetAll().then(
|
const table = createSvelteTable(options);
|
||||||
(val) => {
|
|
||||||
current_donations = val;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
function should_display_based_on_id(id) {
|
function should_display_based_on_id(id) {
|
||||||
if (searchvalue.toString().slice(-1) === "*") {
|
if (searchvalue.toString().slice(-1) === "*") {
|
||||||
return id.toString().startsWith(searchvalue.replace("*", ""));
|
return id.toString().startsWith(searchvalue.replace("*", ""));
|
||||||
}
|
}
|
||||||
return id.toString() === searchvalue;
|
return id.toString() === searchvalue;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
let page = 0;
|
||||||
|
while (page >= 0) {
|
||||||
|
const donors = await DonorService.donorControllerGetAll(page, 500);
|
||||||
|
if (donors.length == 0) {
|
||||||
|
page = -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_donors = current_donors.concat(...donors);
|
||||||
|
options.update((options) => ({
|
||||||
|
...options,
|
||||||
|
data: current_donors,
|
||||||
|
}));
|
||||||
|
|
||||||
|
dataLoaded = true;
|
||||||
|
page++;
|
||||||
|
}
|
||||||
|
|
||||||
|
console.log("All donors loaded");
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ConfirmDonorDeletion
|
<ConfirmDonorDeletion
|
||||||
on:cancelDelete={(event) => {
|
on:cancelDelete={(event) => {
|
||||||
modal_open = false;
|
active_deletes = active_deletes.filter((a) => a.id !== event.detail.id);
|
||||||
active_deletes[event.detail.id] = false;
|
|
||||||
}}
|
}}
|
||||||
bind:modal_open
|
on:delete={async (event) => {
|
||||||
bind:delete_donor />
|
await DonorService.donorControllerRemove(event.detail.id, true);
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('DONOR:GET')}
|
Toastify({
|
||||||
{#await donors_promise && donation_promise}
|
text: $_("donor-deleted"),
|
||||||
|
duration: 500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
current_donors = current_donors.filter((d) => d.id !== event.detail.id);
|
||||||
|
active_deletes = active_deletes.filter((a) => a.id !== event.detail.id);
|
||||||
|
options.update((options) => ({
|
||||||
|
...options,
|
||||||
|
data: current_donors,
|
||||||
|
}));
|
||||||
|
}}
|
||||||
|
modal_open={active_deletes.length > 0}
|
||||||
|
delete_donor={active_deletes[0]}
|
||||||
|
/>
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:GET")}
|
||||||
|
{#if !dataLoaded}
|
||||||
<div
|
<div
|
||||||
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
||||||
role="alert">
|
role="alert"
|
||||||
<p class="font-bold">{$_('donors-are-being-loaded')}</p>
|
>
|
||||||
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
<p class="font-bold">{$_("donors-are-being-loaded")}</p>
|
||||||
|
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
||||||
</div>
|
</div>
|
||||||
{:then}
|
{:else if current_donors.length === 0}
|
||||||
{#if current_donors.length === 0}
|
<DonorsEmptyState />
|
||||||
<DonorsEmptyState />
|
{:else}
|
||||||
{:else}
|
<input
|
||||||
<input
|
type="search"
|
||||||
type="search"
|
bind:value={searchvalue}
|
||||||
bind:value={searchvalue}
|
placeholder={$_("datatable.search")}
|
||||||
placeholder={$_('datatable.search')}
|
aria-label={$_("datatable.search")}
|
||||||
aria-label={$_('datatable.search')}
|
class="mb-4"
|
||||||
class="gridjs-input gridjs-search-input mb-4" />
|
/>
|
||||||
<div
|
<div
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
|
||||||
<table class="divide-y divide-gray-200 w-full">
|
>
|
||||||
<thead class="bg-gray-50">
|
<table class="w-full">
|
||||||
<tr>
|
<thead>
|
||||||
<th
|
{#each $table.getHeaderGroups() as headerGroup}
|
||||||
scope="col"
|
<tr class="select-none">
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
<th class="inset-y-0 left-0 px-4 py-2 text-left w-px">
|
||||||
{$_('name')}
|
<InputElement
|
||||||
</th>
|
type="checkbox"
|
||||||
<th
|
checked={$table.getIsAllRowsSelected()}
|
||||||
scope="col"
|
indeterminate={$table.getIsSomeRowsSelected()}
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
on:change={() => $table.toggleAllRowsSelected()}
|
||||||
{$_('contact-information')}
|
/>
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('donations')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('total-donation-amount')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('total-paid-amount')}
|
|
||||||
</th>
|
|
||||||
<th scope="col" class="relative px-6 py-3">
|
|
||||||
<span class="sr-only">{$_('action')}</span>
|
|
||||||
</th>
|
</th>
|
||||||
|
{#each headerGroup.headers as header}
|
||||||
|
<TableHeader {header} />
|
||||||
|
{/each}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
{/each}
|
||||||
<tbody class="divide-y divide-gray-200">
|
</thead>
|
||||||
{#each current_donors as donor}
|
<tbody>
|
||||||
{#if donor.firstname
|
{#each $table.getRowModel().rows as row}
|
||||||
.toLowerCase()
|
<tr>
|
||||||
.includes(
|
<td class="inset-y-0 left-0 px-4 py-2 text-center w-px">
|
||||||
searchvalue.toLowerCase()
|
<InputElement
|
||||||
) || donor.lastname
|
type="checkbox"
|
||||||
.toLowerCase()
|
checked={row.getIsSelected()}
|
||||||
.includes(
|
on:change={() => row.toggleSelected()}
|
||||||
searchvalue.toLowerCase()
|
/>
|
||||||
) || should_display_based_on_id(donor.id)}
|
</td>
|
||||||
<tr data-rowid="donor_{donor.id}">
|
{#each row.getVisibleCells() as cell}
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
<td>
|
||||||
<div class="flex items-center">
|
<svelte:component
|
||||||
<div class="ml-4">
|
this={flexRender(
|
||||||
<div class="text-sm font-medium text-gray-900">
|
cell.column.columnDef.cell,
|
||||||
{donor.firstname}
|
cell.getContext()
|
||||||
{donor.middlename || ''}
|
)}
|
||||||
{donor.lastname}
|
/>
|
||||||
</div>
|
</td>
|
||||||
</div>
|
{/each}
|
||||||
</div>
|
</tr>
|
||||||
</td>
|
{/each}
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
</tbody>
|
||||||
{#if donor.email}
|
</table>
|
||||||
<div class="text-sm text-gray-500">{donor.email}</div>
|
|
||||||
{/if}
|
|
||||||
{#if donor.phone}
|
|
||||||
<div class="text-sm text-gray-500">{donor.phone}</div>
|
|
||||||
{/if}
|
|
||||||
{#if donor.address.address1 !== null}
|
|
||||||
{donor.address.address1}<br />
|
|
||||||
{donor.address.address2 || ''}<br />
|
|
||||||
{donor.address.postalcode}
|
|
||||||
{donor.address.city}
|
|
||||||
{donor.address.country}
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
{#if current_donations.filter((d) => d.donor.id == donor.id).length > 0}
|
|
||||||
{#each current_donations.filter((o) => o.donor.id == donor.id) as d}
|
|
||||||
{#if d.responseType === 'DISTANCEDONATION'}
|
|
||||||
<a
|
|
||||||
href="../donations/{d.id}"
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-600 text-white mr-1">{d.runner.firstname}
|
|
||||||
{d.runner.middlename}
|
|
||||||
{d.runner.lastname}</a>
|
|
||||||
{:else}
|
|
||||||
<a
|
|
||||||
href="../donations/{d.id}"
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-700 text-white mr-1">{$_('fixed-donation')}:
|
|
||||||
{(d.amount / 100)
|
|
||||||
.toFixed(2)
|
|
||||||
.toLocaleString('de-DE', { valute: 'EUR' })}€</a>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
{:else}{$_('donor-has-no-associated-donations')}{/if}
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
{(donor.donationAmount / 100)
|
|
||||||
.toFixed(2)
|
|
||||||
.toLocaleString('de-DE', { valute: 'EUR' })}€
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
{(donor.paidDonationAmount / 100)
|
|
||||||
.toFixed(2)
|
|
||||||
.toLocaleString('de-DE', { valute: 'EUR' })}€
|
|
||||||
</td>
|
|
||||||
{#if active_deletes[donor.id] === true}
|
|
||||||
<td
|
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[donor.id] = false;
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">{$_('cancel-delete')}</button>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
DonorService.donorControllerRemove(donor.id, false)
|
|
||||||
.then((resp) => {
|
|
||||||
current_donors = current_donors.filter((obj) => obj.id !== donor.id);
|
|
||||||
Toastify({
|
|
||||||
text: 'Donor deleted',
|
|
||||||
duration: 500,
|
|
||||||
backgroundColor:
|
|
||||||
'linear-gradient(to right, #00b09b, #96c93d)',
|
|
||||||
}).showToast();
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
modal_open = true;
|
|
||||||
delete_donor = donor;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('confirm-delete')}</button>
|
|
||||||
</td>
|
|
||||||
{:else}
|
|
||||||
<td
|
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
||||||
<a
|
|
||||||
href="./{donor.id}"
|
|
||||||
class="text-indigo-600 hover:text-indigo-900">{$_('details')}</a>
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('DONOR:DELETE')}
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[donor.id] = true;
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
{/if}
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{:catch error}
|
|
||||||
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
|
|
||||||
<span class="inline-block align-middle mr-8">
|
|
||||||
<b class="capitalize">{$_('general_promise_error')}</b>
|
|
||||||
{error}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
{/await}
|
<div class="h-2" />
|
||||||
|
<TableBottom {table} {selected} />
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
export let modal_open;
|
export let modal_open;
|
||||||
(function () {
|
(function () {
|
||||||
document.onkeydown = function (e) {
|
document.onkeydown = function (e) {
|
||||||
@@ -25,7 +25,7 @@
|
|||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={() => {
|
on:click_outside={() => {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
|
|||||||
@@ -32,8 +32,12 @@
|
|||||||
target="_blank"
|
target="_blank"
|
||||||
rel="noopener, noreferrer"
|
rel="noopener, noreferrer"
|
||||||
href="https://git.odit.services/lfk/frontend/src/tag/{releaseinfo}">{releaseinfo}</a>
|
href="https://git.odit.services/lfk/frontend/src/tag/{releaseinfo}">{releaseinfo}</a>
|
||||||
-
|
-
|
||||||
<a class="underline" href="https://docs.lauf-fuer-kaya.de" target="_blank">{$_('documentation')}</a>
|
<a
|
||||||
|
rel="noopener, noreferrer"
|
||||||
|
class="underline"
|
||||||
|
href="https://docs.lauf-fuer-kaya.de"
|
||||||
|
target="_blank">{$_('documentation')}</a>
|
||||||
-
|
-
|
||||||
<a class="underline" href="/privacy">{$_('privacy')}</a>
|
<a class="underline" href="/privacy">{$_('privacy')}</a>
|
||||||
-
|
-
|
||||||
|
|||||||
@@ -2,7 +2,7 @@
|
|||||||
import { _, getLocaleFromNavigator } from "svelte-i18n";
|
import { _, getLocaleFromNavigator } from "svelte-i18n";
|
||||||
import marked from "marked";
|
import marked from "marked";
|
||||||
import Footer from "./Footer.svelte";
|
import Footer from "./Footer.svelte";
|
||||||
import * as css from "../base/simple.css";
|
// import * as css from "../base/simple.css?inline";
|
||||||
let html = "";
|
let html = "";
|
||||||
async function load() {
|
async function load() {
|
||||||
let md = await fetch("/privacy_" + getLocaleFromNavigator() + ".md");
|
let md = await fetch("/privacy_" + getLocaleFromNavigator() + ".md");
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
import { UserGroupService } from "@odit/lfk-client-js";
|
import { UserGroupService } from "@odit/lfk-client-js";
|
||||||
export let modal_open;
|
export let modal_open;
|
||||||
@@ -69,7 +69,7 @@
|
|||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={() => {
|
on:click_outside={() => {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
|
|||||||
@@ -30,7 +30,7 @@
|
|||||||
bind:value={searchvalue}
|
bind:value={searchvalue}
|
||||||
placeholder={$_('datatable.search')}
|
placeholder={$_('datatable.search')}
|
||||||
aria-label={$_('datatable.search')}
|
aria-label={$_('datatable.search')}
|
||||||
class="gridjs-input gridjs-search-input mb-4" />
|
class="mb-4" />
|
||||||
<div
|
<div
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
||||||
<table class="divide-y divide-gray-200 w-full">
|
<table class="divide-y divide-gray-200 w-full">
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import { RunnerOrganizationService } from "@odit/lfk-client-js";
|
import { RunnerOrganizationService } from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
export let modal_open;
|
export let modal_open;
|
||||||
@@ -89,7 +89,7 @@
|
|||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={() => {
|
on:click_outside={() => {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import { RunnerOrganizationService } from "@odit/lfk-client-js";
|
import { RunnerOrganizationService } from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={cancelDelete}>
|
on:click_outside={cancelDelete}>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -119,9 +119,9 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
async function copy() {
|
async function copy() {
|
||||||
if(!editable.registrationKey){
|
if (!editable.registrationKey) {
|
||||||
Toastify({
|
Toastify({
|
||||||
text: $_('you-have-to-save-your-changes-to-generate-a-link'),
|
text: $_("you-have-to-save-your-changes-to-generate-a-link"),
|
||||||
duration: 500,
|
duration: 500,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
@@ -167,7 +167,8 @@
|
|||||||
passed_orgs={[]}
|
passed_orgs={[]}
|
||||||
passed_org={editable}
|
passed_org={editable}
|
||||||
opened_from="OrgDetail"
|
opened_from="OrgDetail"
|
||||||
bind:import_modal_open />
|
bind:import_modal_open
|
||||||
|
/>
|
||||||
<ConfirmOrgDeletion bind:modal_open bind:delete_org />
|
<ConfirmOrgDeletion bind:modal_open bind:delete_org />
|
||||||
{#if data_loaded}
|
{#if data_loaded}
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
@@ -176,29 +177,35 @@
|
|||||||
<span data-id="org_actions_${editable.id}">
|
<span data-id="org_actions_${editable.id}">
|
||||||
<GenerateSponsoringContracts
|
<GenerateSponsoringContracts
|
||||||
bind:sponsoring_contracts_show
|
bind:sponsoring_contracts_show
|
||||||
bind:generate_orgs />
|
bind:generate_orgs
|
||||||
|
/>
|
||||||
<GenerateRunnerCards bind:cards_show bind:generate_orgs />
|
<GenerateRunnerCards bind:cards_show bind:generate_orgs />
|
||||||
<GenerateRunnerCertificates bind:certificates_show bind:generate_orgs />
|
<GenerateRunnerCertificates bind:certificates_show bind:generate_orgs />
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('RUNNER:IMPORT')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:IMPORT")}
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
import_modal_open = true;
|
import_modal_open = true;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
{$_('import-runners')}
|
>
|
||||||
|
{$_("import-runners")}
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('RUNNER:DELETE')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:DELETE")}
|
||||||
{#if delete_triggered}
|
{#if delete_triggered}
|
||||||
<button
|
<button
|
||||||
on:click={deleteOrganization}
|
on:click={deleteOrganization}
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('confirm-delete')}</button>
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>{$_("confirm-delete")}</button
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
delete_triggered = !delete_triggered;
|
delete_triggered = !delete_triggered;
|
||||||
}}
|
}}
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm">{$_('cancel')}</button>
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm"
|
||||||
|
>{$_("cancel")}</button
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
{#if !delete_triggered}
|
{#if !delete_triggered}
|
||||||
<button
|
<button
|
||||||
@@ -206,7 +213,9 @@
|
|||||||
delete_triggered = true;
|
delete_triggered = true;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('delete-organization')}</button>
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>{$_("delete-organization")}</button
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
{#if !delete_triggered}
|
{#if !delete_triggered}
|
||||||
@@ -215,7 +224,9 @@
|
|||||||
disabled={!save_enabled}
|
disabled={!save_enabled}
|
||||||
class:opacity-50={!save_enabled}
|
class:opacity-50={!save_enabled}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('save-changes')}</button>
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>{$_("save-changes")}</button
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
@@ -234,12 +245,13 @@
|
|||||||
class="h-3 w-3 stroke-current"
|
class="h-3 w-3 stroke-current"
|
||||||
height="1em"
|
height="1em"
|
||||||
width="1em"
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"><path
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
|
><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
|
||||||
<polyline points="9 22 9 12 15 12 15 22" /></svg>
|
<polyline points="9 22 9 12 15 12 15 22" /></svg
|
||||||
|
>
|
||||||
</li>
|
</li>
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
<a class="mr-2" href="/">{$_('home')}</a><svg
|
<a class="mr-2" href="/">{$_("home")}</a><svg
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
@@ -249,24 +261,25 @@
|
|||||||
class="h-3 w-3 mr-2 stroke-current"
|
class="h-3 w-3 mr-2 stroke-current"
|
||||||
height="1em"
|
height="1em"
|
||||||
width="1em"
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"><line
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
x1="5"
|
><line x1="5" y1="12" x2="19" y2="12" />
|
||||||
y1="12"
|
<polyline points="12 5 19 12 12 19" /></svg
|
||||||
x2="19"
|
>
|
||||||
y2="12" />
|
|
||||||
<polyline points="12 5 19 12 12 19" /></svg>
|
|
||||||
</li>
|
</li>
|
||||||
<li class="mr-2 flex items-center">
|
<li class="mr-2 flex items-center">
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
height="24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path
|
<path
|
||||||
d="M21 20h2v2H1v-2h2V3a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v17zm-2 0V4H5v16h14zM8 11h3v2H8v-2zm0-4h3v2H8V7zm0 8h3v2H8v-2zm5 0h3v2h-3v-2zm0-4h3v2h-3v-2zm0-4h3v2h-3V7z" /></svg>
|
d="M21 20h2v2H1v-2h2V3a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v17zm-2 0V4H5v16h14zM8 11h3v2H8v-2zm0-4h3v2H8V7zm0 8h3v2H8v-2zm5 0h3v2h-3v-2zm0-4h3v2h-3v-2zm0-4h3v2h-3V7z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
</li>
|
</li>
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
<a class="mr-2" href="./">{$_('organizations')}</a><svg
|
<a class="mr-2" href="./">{$_("organizations")}</a><svg
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
@@ -276,12 +289,10 @@
|
|||||||
class="h-3 w-3 mr-2 stroke-current"
|
class="h-3 w-3 mr-2 stroke-current"
|
||||||
height="1em"
|
height="1em"
|
||||||
width="1em"
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"><line
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
x1="5"
|
><line x1="5" y1="12" x2="19" y2="12" />
|
||||||
y1="12"
|
<polyline points="12 5 19 12 12 19" /></svg
|
||||||
x2="19"
|
>
|
||||||
y2="12" />
|
|
||||||
<polyline points="12 5 19 12 12 19" /></svg>
|
|
||||||
</li>
|
</li>
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
<span class="mr-2">Org-Details #{params.orgid}</span>
|
<span class="mr-2">Org-Details #{params.orgid}</span>
|
||||||
@@ -291,81 +302,88 @@
|
|||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full">
|
||||||
<label for="name" class="font-medium text-gray-700">{$_('name')}</label>
|
<label for="name" class="font-medium text-gray-700">{$_("name")}</label>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('name')}
|
placeholder={$_("name")}
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={editable.name}
|
bind:value={editable.name}
|
||||||
name="name"
|
name="name"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full">
|
||||||
<label
|
<label for="contact" class="font-medium text-gray-700"
|
||||||
for="contact"
|
>{$_("contact")}</label
|
||||||
class="font-medium text-gray-700">{$_('contact')}</label>
|
>
|
||||||
<Select
|
<Select
|
||||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
itemFilter={(label, filterText, option) => label
|
itemFilter={(label, filterText, option) =>
|
||||||
.toLowerCase()
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
.includes(
|
option.value.id.toString().startsWith(filterText.toLowerCase())}
|
||||||
filterText.toLowerCase()
|
|
||||||
) || option.value.id
|
|
||||||
.toString()
|
|
||||||
.startsWith(filterText.toLowerCase())}
|
|
||||||
items={contacts}
|
items={contacts}
|
||||||
showChevron={true}
|
showChevron={true}
|
||||||
placeholder={$_('no-contact-selected')}
|
placeholder={$_("no-contact-selected")}
|
||||||
noOptionsMessage={$_('no-contact-found')}
|
noOptionsMessage={$_("no-contact-found")}
|
||||||
bind:selectedValue={contact}
|
bind:selectedValue={contact}
|
||||||
on:select={(selectedValue) => (editable.contact = selectedValue.detail.value)}
|
on:select={(selectedValue) =>
|
||||||
on:clear={() => (editable.contact = null)} />
|
(editable.contact = selectedValue.detail.value)}
|
||||||
|
on:clear={() => (editable.contact = null)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
<div class="flex items-start mt-2">
|
<div class="flex items-start mt-2">
|
||||||
<div class="flex items-center h-5">
|
<div class="flex items-center h-5">
|
||||||
<input
|
<input
|
||||||
bind:checked={editable.registrationEnabled}
|
bind:checked={editable.registrationEnabled}
|
||||||
id="comments"
|
id="toggle_selfservice_feature"
|
||||||
name="comments"
|
name="toggle_selfservice_feature"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" />
|
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-3 text-sm">
|
<div class="ml-3 text-sm">
|
||||||
<label
|
<label
|
||||||
for="comments"
|
for="toggle_selfservice_feature"
|
||||||
class="font-medium text-gray-700">{$_('selfservice-registration')}</label>
|
class="font-medium text-gray-700"
|
||||||
|
>{$_("selfservice-registration")}</label
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div>
|
<div>
|
||||||
{#if editable.registrationEnabled}
|
{#if editable.registrationEnabled}
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full">
|
||||||
<div on:click={copy} class="inline-flex w-full">
|
<button on:click={copy} class="inline-flex w-full">
|
||||||
<p
|
<p
|
||||||
name="token"
|
name="token"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2">
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
|
||||||
|
>
|
||||||
{#if editable.registrationKey}
|
{#if editable.registrationKey}
|
||||||
{registrationLink}
|
{registrationLink}
|
||||||
{:else}
|
{:else}
|
||||||
{$_('you-have-to-save-your-changes-to-generate-a-link')}
|
{$_("you-have-to-save-your-changes-to-generate-a-link")}
|
||||||
{/if}
|
{/if}
|
||||||
</p>
|
</p>
|
||||||
<div
|
<div
|
||||||
class="bg-gray-200 border-gray-300 border-t border-b border-r text-black rounded-r-md sm:text-sm p-2 mt-1 cursor-pointer">
|
class="bg-gray-200 border-gray-300 border-t border-b border-r text-black rounded-r-md sm:text-sm p-2 mt-1 cursor-pointer"
|
||||||
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
height="24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
d="M7 4V2h10v2h3l1 1v16a1 1 0 01-1 1H4a1 1 0 01-1-1V5l1-1h3zm0 2H5v14h14V6h-2v2H7V6zm2-2v2h6V4H9z" /></svg>
|
d="M7 4V2h10v2h3l1 1v16a1 1 0 01-1 1H4a1 1 0 01-1-1V5l1-1h3zm0 2H5v14h14V6h-2v2H7V6zm2-2v2h6V4H9z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</button>
|
||||||
{#if editable.registrationKey}
|
{#if editable.registrationKey}
|
||||||
<p class="text-gray-500 text-xs">
|
<p class="text-gray-500 text-xs">
|
||||||
{$_('click-to-copy-the-link-into-your-clipboard')}
|
{$_("click-to-copy-the-link-into-your-clipboard")}
|
||||||
</p>
|
</p>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -375,15 +393,17 @@
|
|||||||
<div class="flex items-center h-5">
|
<div class="flex items-center h-5">
|
||||||
<input
|
<input
|
||||||
bind:checked={editable.address_checked}
|
bind:checked={editable.address_checked}
|
||||||
id="comments"
|
id="toggle_address_checkbox"
|
||||||
name="comments"
|
name="toggle_address_checkbox"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" />
|
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-3 text-sm">
|
<div class="ml-3 text-sm">
|
||||||
<label
|
<label
|
||||||
for="comments"
|
for="toggle_address_checkbox"
|
||||||
class="font-medium text-gray-700">{$_('address')}</label>
|
class="font-medium text-gray-700">{$_("address")}</label
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -391,7 +411,9 @@
|
|||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
<label
|
<label
|
||||||
for="address1"
|
for="address1"
|
||||||
class="block text-sm font-medium text-gray-700">{$_('address')}</label>
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>{$_("address")}</label
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder="Address"
|
placeholder="Address"
|
||||||
@@ -401,65 +423,74 @@
|
|||||||
bind:value={editable.address.address1}
|
bind:value={editable.address.address1}
|
||||||
type="text"
|
type="text"
|
||||||
name="address1"
|
name="address1"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
{#if !isAddress1Valid}
|
{#if !isAddress1Valid}
|
||||||
<span
|
<span
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{$_('address-is-required')}
|
>
|
||||||
|
{$_("address-is-required")}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
<label
|
<label
|
||||||
for="address2"
|
for="address2"
|
||||||
class="block text-sm font-medium text-gray-700">{$_('apartment-suite-etc')}</label>
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>{$_("apartment-suite-etc")}</label
|
||||||
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('apartment-suite-etc')}
|
placeholder={$_("apartment-suite-etc")}
|
||||||
bind:value={editable.address.address2}
|
bind:value={editable.address.address2}
|
||||||
type="text"
|
type="text"
|
||||||
name="address2"
|
name="address2"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
<label
|
<label for="zipcode" class="block text-sm font-medium text-gray-700"
|
||||||
for="zipcode"
|
>{$_("zip-postal-code")}</label
|
||||||
class="block text-sm font-medium text-gray-700">{$_('zip-postal-code')}</label>
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('zip-postal-code')}
|
placeholder={$_("zip-postal-code")}
|
||||||
class:border-red-500={!iszipcodevalid}
|
class:border-red-500={!iszipcodevalid}
|
||||||
class:focus:border-red-500={!iszipcodevalid}
|
class:focus:border-red-500={!iszipcodevalid}
|
||||||
class:focus:ring-red-500={!iszipcodevalid}
|
class:focus:ring-red-500={!iszipcodevalid}
|
||||||
bind:value={editable.address.postalcode}
|
bind:value={editable.address.postalcode}
|
||||||
type="text"
|
type="text"
|
||||||
name="zipcode"
|
name="zipcode"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
{#if !iszipcodevalid}
|
{#if !iszipcodevalid}
|
||||||
<span
|
<span
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{$_('valid-zipcode-postal-code-is-required')}
|
>
|
||||||
|
{$_("valid-zipcode-postal-code-is-required")}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
<label
|
<label for="city" class="block text-sm font-medium text-gray-700"
|
||||||
for="city"
|
>{$_("city")}</label
|
||||||
class="block text-sm font-medium text-gray-700">{$_('city')}</label>
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('city')}
|
placeholder={$_("city")}
|
||||||
class:border-red-500={!iscityvalid}
|
class:border-red-500={!iscityvalid}
|
||||||
class:focus:border-red-500={!iscityvalid}
|
class:focus:border-red-500={!iscityvalid}
|
||||||
class:focus:ring-red-500={!iscityvalid}
|
class:focus:ring-red-500={!iscityvalid}
|
||||||
bind:value={editable.address.city}
|
bind:value={editable.address.city}
|
||||||
type="text"
|
type="text"
|
||||||
name="city"
|
name="city"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
{#if !iscityvalid}
|
{#if !iscityvalid}
|
||||||
<span
|
<span
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{$_('valid-city-is-required')}
|
>
|
||||||
|
{$_("valid-city-is-required")}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
@@ -469,7 +500,7 @@
|
|||||||
</section>
|
</section>
|
||||||
{:else}
|
{:else}
|
||||||
{#await promise}
|
{#await promise}
|
||||||
{$_('organization-detail-is-being-loaded')}
|
{$_("organization-detail-is-being-loaded")}
|
||||||
{:catch error}
|
{:catch error}
|
||||||
<PromiseError />
|
<PromiseError />
|
||||||
{/await}
|
{/await}
|
||||||
|
|||||||
@@ -51,7 +51,7 @@
|
|||||||
bind:value={searchvalue}
|
bind:value={searchvalue}
|
||||||
placeholder={$_('datatable.search')}
|
placeholder={$_('datatable.search')}
|
||||||
aria-label={$_('datatable.search')}
|
aria-label={$_('datatable.search')}
|
||||||
class="gridjs-input gridjs-search-input mb-4" />
|
class="mb-4" />
|
||||||
<div class="h-12">
|
<div class="h-12">
|
||||||
<GenerateSponsoringContracts
|
<GenerateSponsoringContracts
|
||||||
bind:sponsoring_contracts_show
|
bind:sponsoring_contracts_show
|
||||||
@@ -132,7 +132,7 @@
|
|||||||
<div class="text-sm font-medium text-gray-900">
|
<div class="text-sm font-medium text-gray-900">
|
||||||
{#if o.address.address1 !== null}
|
{#if o.address.address1 !== null}
|
||||||
{o.address.address1}<br />
|
{o.address.address1}<br />
|
||||||
{o.address.address2 || ''}<br />
|
<!-- {o.address.address2 || ''}<br /> -->
|
||||||
{o.address.postalcode}
|
{o.address.postalcode}
|
||||||
{o.address.city}
|
{o.address.city}
|
||||||
{o.address.country}
|
{o.address.country}
|
||||||
|
|||||||
@@ -1,403 +1,418 @@
|
|||||||
<script>
|
<script>
|
||||||
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
||||||
import {
|
import {
|
||||||
RunnerCardService,
|
RunnerCardService,
|
||||||
RunnerOrganizationService,
|
RunnerOrganizationService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
export let cards_show = false;
|
import { init } from "@paralleldrive/cuid2";
|
||||||
export let generate_cards = [];
|
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
|
||||||
export let generate_runners = [];
|
|
||||||
export let generate_orgs = [];
|
|
||||||
export let generate_teams = [];
|
|
||||||
$: cards_dropdown_open = false;
|
|
||||||
document.addEventListener("click", function (e) {
|
|
||||||
if (
|
|
||||||
e.target.parentNode?.parentNode?.id != "cards:dropdown" &&
|
|
||||||
e.target.parentNode?.parentNode?.id != "cards:dropdown:menu"
|
|
||||||
) {
|
|
||||||
cards_dropdown_open = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function generateRunnerCards(locale) {
|
export let cards_show = false;
|
||||||
cards_dropdown_open = false;
|
export let generate_cards = [];
|
||||||
|
export let generate_runners = [];
|
||||||
|
export let generate_orgs = [];
|
||||||
|
export let generate_teams = [];
|
||||||
|
$: cards_dropdown_open = false;
|
||||||
|
document.addEventListener("click", function (e) {
|
||||||
|
if (
|
||||||
|
e.target.parentNode?.parentNode?.id != "cards:dropdown" &&
|
||||||
|
e.target.parentNode?.parentNode?.id != "cards:dropdown:menu"
|
||||||
|
) {
|
||||||
|
cards_dropdown_open = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (generate_orgs.length > 0) {
|
function generateRunnerCards(locale) {
|
||||||
generateOrgCards(locale);
|
cards_dropdown_open = false;
|
||||||
} else if (generate_teams.length > 0) {
|
|
||||||
generateTeamCards(locale);
|
if (generate_orgs.length > 0) {
|
||||||
} else if (generate_runners.length > 0) {
|
generateOrgCards(locale);
|
||||||
generateRunnersCards(locale);
|
} else if (generate_teams.length > 0) {
|
||||||
|
generateTeamCards(locale);
|
||||||
|
} else if (generate_runners.length > 0) {
|
||||||
|
generateRunnersCards(locale);
|
||||||
|
} else {
|
||||||
|
generateCards(locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateCards(locale) {
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("generating-pdf"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
fetch(
|
||||||
|
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(generate_cards),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
} else {
|
} else {
|
||||||
generateCards(locale);
|
return response.blob();
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
.then((blob) => {
|
||||||
function generateCards(locale) {
|
const url = window.URL.createObjectURL(blob);
|
||||||
const toast = Toastify({
|
let a = document.createElement("a");
|
||||||
text: $_("generating-pdf"),
|
a.href = url;
|
||||||
duration: -1,
|
a.download = `${$_("runnercards")}-${locale}-${createId()}.pdf`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
fetch(
|
})
|
||||||
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
.catch((err) => {
|
||||||
{
|
console.error(err);
|
||||||
method: "POST",
|
});
|
||||||
headers: {
|
}
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(generate_cards),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-generation-failed"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
|
||||||
}).showToast();
|
|
||||||
} else {
|
|
||||||
return response.blob();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('runnercards')}-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateRunnersCards(locale) {
|
async function generateRunnersCards(locale) {
|
||||||
const toast = Toastify({
|
const toast = Toastify({
|
||||||
text: $_("generating-pdf"),
|
text: $_("generating-pdf"),
|
||||||
duration: -1,
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
||||||
|
let cards = [];
|
||||||
|
for (let runner of generate_runners) {
|
||||||
|
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
||||||
|
if (!card) {
|
||||||
|
card = await RunnerCardService.runnerCardControllerPost({
|
||||||
|
runner: runner.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
cards.push(card);
|
||||||
|
}
|
||||||
|
fetch(
|
||||||
|
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(cards),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
if (generate_runners.length == 1) {
|
||||||
|
a.download = `${$_("runnercards")}_${generate_runners[0].firstname}_${
|
||||||
|
generate_runners[0].lastname
|
||||||
|
}-${locale}-${createId()}.pdf`;
|
||||||
|
} else {
|
||||||
|
a.download = `${$_("runnercards")}-${locale}-${createId()}.pdf`;
|
||||||
|
}
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateTeamCards(locale) {
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("generating-pdfs"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
let count = 0;
|
||||||
|
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
||||||
|
for (const t of generate_teams) {
|
||||||
|
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
|
t.id
|
||||||
|
);
|
||||||
|
let cards = [];
|
||||||
|
for (let runner of runners) {
|
||||||
|
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
||||||
|
if (!card) {
|
||||||
|
card = await RunnerCardService.runnerCardControllerPost({
|
||||||
|
runner: runner.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
cards.push(card);
|
||||||
|
}
|
||||||
|
fetch(
|
||||||
|
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(cards),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
count++;
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = `${$_("runnercards")}_${t.name}-${locale}-${createId()}.pdf`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
if (count === generate_teams.length) {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdfs-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateOrgCards(locale) {
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("generating-pdfs"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
||||||
|
let count = 0;
|
||||||
|
let count_orgs = 0;
|
||||||
|
for (const o of generate_orgs) {
|
||||||
|
count_orgs++;
|
||||||
|
let count = 0;
|
||||||
|
let runners =
|
||||||
|
await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
||||||
|
o.id,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
let cards = [];
|
||||||
|
for (let runner of runners) {
|
||||||
|
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
||||||
|
if (!card) {
|
||||||
|
card = await RunnerCardService.runnerCardControllerPost({
|
||||||
|
runner: runner.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
cards.push(card);
|
||||||
|
}
|
||||||
|
await fetch(
|
||||||
|
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(cards),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = `${$_("runnercards")}_${o.name}_direct-${locale}-${createId()}.pdf`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
||||||
|
toast.hideToast();
|
||||||
|
console.log("here");
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdfs-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
for (const t of o.teams) {
|
||||||
|
count++;
|
||||||
|
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
|
t.id
|
||||||
|
);
|
||||||
let cards = [];
|
let cards = [];
|
||||||
for (let runner of generate_runners) {
|
for (let runner of runners) {
|
||||||
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
||||||
if (!card) {
|
if (!card) {
|
||||||
card = await RunnerCardService.runnerCardControllerPost({
|
card = await RunnerCardService.runnerCardControllerPost({
|
||||||
runner: runner.id,
|
runner: runner.id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
cards.push(card);
|
cards.push(card);
|
||||||
}
|
}
|
||||||
fetch(
|
await fetch(
|
||||||
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify(cards),
|
body: JSON.stringify(cards),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status != "200") {
|
if (response.status != "200") {
|
||||||
toast.hideToast();
|
toast.hideToast();
|
||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdf-generation-failed"),
|
text: $_("pdf-generation-failed"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
} else {
|
} else {
|
||||||
return response.blob();
|
return response.blob();
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
if(generate_runners.length == 1){
|
|
||||||
a.download = `${$_('runnercards')}_${generate_runners[0].firstname}_${generate_runners[0].lastname}-${locale}.pdf`;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
a.download = `Runnercards-${locale}.pdf`;
|
|
||||||
}
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateTeamCards(locale) {
|
|
||||||
const toast = Toastify({
|
|
||||||
text: $_("generating-pdfs"),
|
|
||||||
duration: -1,
|
|
||||||
}).showToast();
|
|
||||||
let count = 0;
|
|
||||||
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
|
||||||
for (const t of generate_teams) {
|
|
||||||
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
|
||||||
t.id
|
|
||||||
);
|
|
||||||
let cards = [];
|
|
||||||
for (let runner of runners) {
|
|
||||||
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
|
||||||
if (!card) {
|
|
||||||
card = await RunnerCardService.runnerCardControllerPost({
|
|
||||||
runner: runner.id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
cards.push(card);
|
|
||||||
}
|
}
|
||||||
fetch(
|
})
|
||||||
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
.then((blob) => {
|
||||||
{
|
const url = window.URL.createObjectURL(blob);
|
||||||
method: "POST",
|
let a = document.createElement("a");
|
||||||
headers: {
|
a.href = url;
|
||||||
"Content-Type": "application/json",
|
a.download = `${$_("runnercards")}_${o.name}_${
|
||||||
},
|
t.name
|
||||||
body: JSON.stringify(cards),
|
}-${locale}-${createId()}.pdf`;
|
||||||
}
|
document.body.appendChild(a);
|
||||||
)
|
a.click();
|
||||||
.then((response) => {
|
a.remove();
|
||||||
if (response.status != "200") {
|
if (
|
||||||
toast.hideToast();
|
count === o.teams.length &&
|
||||||
Toastify({
|
count_orgs === generate_orgs.length
|
||||||
text: $_("pdf-generation-failed"),
|
) {
|
||||||
duration: 3500,
|
toast.hideToast();
|
||||||
backgroundColor:
|
Toastify({
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
text: $_("pdfs-successfully-generated"),
|
||||||
}).showToast();
|
duration: 3500,
|
||||||
} else {
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
return response.blob();
|
}).showToast();
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
count++;
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('runnercards')}_${t.name}-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === generate_teams.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateOrgCards(locale) {
|
|
||||||
const toast = Toastify({
|
|
||||||
text: $_("generating-pdfs"),
|
|
||||||
duration: -1,
|
|
||||||
}).showToast();
|
|
||||||
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
|
||||||
let count = 0;
|
|
||||||
let count_orgs =0;
|
|
||||||
for (const o of generate_orgs) {
|
|
||||||
count_orgs++;
|
|
||||||
let count = 0;
|
|
||||||
let runners = await RunnerOrganizationService.runnerOrganizationControllerGetRunners(o.id, true)
|
|
||||||
let cards = [];
|
|
||||||
for (let runner of runners) {
|
|
||||||
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
|
||||||
if (!card) {
|
|
||||||
card = await RunnerCardService.runnerCardControllerPost({
|
|
||||||
runner: runner.id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
cards.push(card);
|
|
||||||
}
|
}
|
||||||
await fetch(
|
})
|
||||||
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
.catch((err) => {});
|
||||||
{
|
}
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(cards),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-generation-failed"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
|
||||||
}).showToast();
|
|
||||||
} else {
|
|
||||||
return response.blob();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('runnercards')}_${o.name}_direct-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
console.log("here")
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
for (const t of o.teams) {
|
|
||||||
count++;
|
|
||||||
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
|
||||||
t.id
|
|
||||||
);
|
|
||||||
let cards = [];
|
|
||||||
for (let runner of runners) {
|
|
||||||
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
|
||||||
if (!card) {
|
|
||||||
card = await RunnerCardService.runnerCardControllerPost({
|
|
||||||
runner: runner.id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
cards.push(card);
|
|
||||||
}
|
|
||||||
await fetch(
|
|
||||||
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(cards),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-generation-failed"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
|
||||||
}).showToast();
|
|
||||||
} else {
|
|
||||||
return response.blob();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('runnercards')}_${o.name}_${t.name}-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if cards_show}
|
{#if cards_show}
|
||||||
<div id="cards:dropdown" class="relative inline-block">
|
<div id="cards:dropdown" class="relative inline-block">
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
cards_dropdown_open = !cards_dropdown_open;
|
cards_dropdown_open = !cards_dropdown_open;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm inline-flex"
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm inline-flex"
|
||||||
id="options-menu"
|
id="options-menu"
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
aria-expanded="true">
|
aria-expanded="true"
|
||||||
{$_('generate-runnercards')}
|
>
|
||||||
<svg
|
{$_("generate-runnercards")}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<svg
|
||||||
width="24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
height="24"
|
width="24"
|
||||||
viewBox="0 0 24 24"
|
height="24"
|
||||||
class="-mr-1 ml-2 h-5 w-5"><path
|
viewBox="0 0 24 24"
|
||||||
fill="none"
|
class="-mr-1 ml-2 h-5 w-5"
|
||||||
d="M0 0h24v24H0z" />
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
d="M3 19h18v2H3v-2zm10-5.83l6.07-6.07 1.42 1.41L12 17 3.52 8.52l1.4-1.42L11 13.17V2h2v11.17z" /></svg>
|
d="M3 19h18v2H3v-2zm10-5.83l6.07-6.07 1.42 1.41L12 17 3.52 8.52l1.4-1.42L11 13.17V2h2v11.17z"
|
||||||
</button>
|
/></svg
|
||||||
</div>
|
>
|
||||||
{#if cards_dropdown_open}
|
</button>
|
||||||
<div
|
|
||||||
class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5"
|
|
||||||
id="cards:dropdown:menu">
|
|
||||||
<div
|
|
||||||
class="py-1"
|
|
||||||
role="menu"
|
|
||||||
aria-orientation="vertical"
|
|
||||||
aria-labelledby="options-menu">
|
|
||||||
<span
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700">{$_('select-language')}</span>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
generateRunnerCards('de');
|
|
||||||
}}
|
|
||||||
type="submit"
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
|
||||||
role="menuitem">
|
|
||||||
{$_('german')}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
generateRunnerCards('en');
|
|
||||||
}}
|
|
||||||
type="submit"
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
|
||||||
role="menuitem">
|
|
||||||
{$_('english')}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
|
{#if cards_dropdown_open}
|
||||||
|
<div
|
||||||
|
class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 z-10"
|
||||||
|
id="cards:dropdown:menu"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="py-1"
|
||||||
|
role="menu"
|
||||||
|
aria-orientation="vertical"
|
||||||
|
aria-labelledby="options-menu"
|
||||||
|
>
|
||||||
|
<span class="block w-full text-left px-4 py-2 text-sm text-gray-700"
|
||||||
|
>{$_("select-language")}</span
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
generateRunnerCards("de");
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
||||||
|
role="menuitem"
|
||||||
|
>
|
||||||
|
{$_("german")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
generateRunnerCards("en");
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
||||||
|
role="menuitem"
|
||||||
|
>
|
||||||
|
{$_("english")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1,331 +1,355 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import {
|
import {
|
||||||
DonationService,
|
DonationService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
RunnerOrganizationService
|
RunnerOrganizationService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
export let certificates_show = false;
|
import { init } from "@paralleldrive/cuid2";
|
||||||
export let generate_runners = [];
|
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
|
||||||
export let generate_orgs = [];
|
|
||||||
export let generate_teams = [];
|
|
||||||
$: certificates_dropdown_open = false;
|
|
||||||
document.addEventListener("click", function (e) {
|
|
||||||
if (
|
|
||||||
e.target.parentNode?.parentNode?.id != "certificates:dropdown" &&
|
|
||||||
e.target.parentNode?.parentNode?.id != "certificates:dropdown:menu"
|
|
||||||
) {
|
|
||||||
certificates_dropdown_open = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function generateCertificates(locale) {
|
export let certificates_show = false;
|
||||||
certificates_dropdown_open = false;
|
export let generate_runners = [];
|
||||||
|
export let generate_orgs = [];
|
||||||
|
export let generate_teams = [];
|
||||||
|
$: certificates_dropdown_open = false;
|
||||||
|
document.addEventListener("click", function (e) {
|
||||||
|
if (
|
||||||
|
e.target.parentNode?.parentNode?.id != "certificates:dropdown" &&
|
||||||
|
e.target.parentNode?.parentNode?.id != "certificates:dropdown:menu"
|
||||||
|
) {
|
||||||
|
certificates_dropdown_open = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (generate_orgs.length > 0) {
|
function generateCertificates(locale) {
|
||||||
generateOrgCertificates(locale);
|
certificates_dropdown_open = false;
|
||||||
} else if (generate_teams.length > 0) {
|
|
||||||
generateTeamCertificates(locale);
|
if (generate_orgs.length > 0) {
|
||||||
|
generateOrgCertificates(locale);
|
||||||
|
} else if (generate_teams.length > 0) {
|
||||||
|
generateTeamCertificates(locale);
|
||||||
|
} else {
|
||||||
|
generateRunnerCertificates(locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateRunnerCertificates(locale) {
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("generating-pdf"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
const current_donations =
|
||||||
|
(await DonationService.donationControllerGetAll()) || [];
|
||||||
|
let certificateRunners = [];
|
||||||
|
for (let runner of generate_runners) {
|
||||||
|
runner.distanceDonations =
|
||||||
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
|
console.log(runner.distanceDonations);
|
||||||
|
certificateRunners.push(runner);
|
||||||
|
}
|
||||||
|
fetch(
|
||||||
|
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(certificateRunners),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
} else {
|
} else {
|
||||||
generateRunnerCertificates(locale);
|
return response.blob();
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
.then((blob) => {
|
||||||
async function generateRunnerCertificates(locale) {
|
const url = window.URL.createObjectURL(blob);
|
||||||
const toast = Toastify({
|
let a = document.createElement("a");
|
||||||
text: $_("generating-pdf"),
|
a.href = url;
|
||||||
duration: -1,
|
if (generate_runners.length == 1) {
|
||||||
|
a.download = `${$_("certificates")}_${
|
||||||
|
generate_runners[0].firstname
|
||||||
|
}_${generate_runners[0].lastname}-${locale}-${createId()}.pdf`;
|
||||||
|
} else {
|
||||||
|
a.download = `${$_("certificates")}-${locale}.pdf`;
|
||||||
|
}
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
const current_donations = (await DonationService.donationControllerGetAll()) || [];
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateTeamCertificates(locale) {
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("generating-pdfs"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
let count = 0;
|
||||||
|
const current_donations =
|
||||||
|
(await DonationService.donationControllerGetAll()) || [];
|
||||||
|
for (const t of generate_teams) {
|
||||||
|
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
|
t.id
|
||||||
|
);
|
||||||
|
let certificateRunners = [];
|
||||||
|
for (let runner of runners) {
|
||||||
|
runner.distanceDonations =
|
||||||
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
|
certificateRunners.push(runner);
|
||||||
|
}
|
||||||
|
fetch(
|
||||||
|
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(certificateRunners),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
count++;
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = `${$_("certificates")}_${t.name}-${locale}-${createId()}.pdf`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
if (count === generate_teams.length) {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdfs-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateOrgCertificates(locale) {
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("generating-pdfs"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
const current_donations =
|
||||||
|
(await DonationService.donationControllerGetAll()) || [];
|
||||||
|
let count = 0;
|
||||||
|
let count_orgs = 0;
|
||||||
|
for (const o of generate_orgs) {
|
||||||
|
count_orgs++;
|
||||||
|
let count = 0;
|
||||||
|
let runners =
|
||||||
|
await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
||||||
|
o.id,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
let certificateRunners = [];
|
||||||
|
for (let runner of runners) {
|
||||||
|
runner.distanceDonations =
|
||||||
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
|
certificateRunners.push(runner);
|
||||||
|
}
|
||||||
|
await fetch(
|
||||||
|
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(certificateRunners),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = `${$_("certificates")}_${o.name}-${locale}-${createId()}.pdf`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
||||||
|
toast.hideToast();
|
||||||
|
console.log("here");
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdfs-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
for (const t of o.teams) {
|
||||||
|
count++;
|
||||||
|
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
|
t.id
|
||||||
|
);
|
||||||
let certificateRunners = [];
|
let certificateRunners = [];
|
||||||
for (let runner of generate_runners) {
|
for (let runner of runners) {
|
||||||
runner.distanceDonations = current_donations.find((d) => d.runner?.id == runner.id) || [];
|
runner.distanceDonations =
|
||||||
certificateRunners.push(runner);
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
|
certificateRunners.push(runner);
|
||||||
}
|
}
|
||||||
fetch(
|
await fetch(
|
||||||
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify(certificateRunners),
|
body: JSON.stringify(certificateRunners),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status != "200") {
|
if (response.status != "200") {
|
||||||
toast.hideToast();
|
toast.hideToast();
|
||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdf-generation-failed"),
|
text: $_("pdf-generation-failed"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
} else {
|
} else {
|
||||||
return response.blob();
|
return response.blob();
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
if(generate_runners.length == 1){
|
|
||||||
a.download = `${$_('certificates')}_${generate_runners[0].firstname}_${generate_runners[0].lastname}-${locale}.pdf`;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
a.download = `${$_('certificates')}-${locale}.pdf`;
|
|
||||||
}
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateTeamCertificates(locale) {
|
|
||||||
const toast = Toastify({
|
|
||||||
text: $_("generating-pdfs"),
|
|
||||||
duration: -1,
|
|
||||||
}).showToast();
|
|
||||||
let count = 0;
|
|
||||||
const current_donations = (await DonationService.donationControllerGetAll()) || [];
|
|
||||||
for (const t of generate_teams) {
|
|
||||||
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
|
||||||
t.id
|
|
||||||
);
|
|
||||||
let certificateRunners = [];
|
|
||||||
for (let runner of runners) {
|
|
||||||
runner.distanceDonations = current_donations.find((d) => d.runner?.id == runner.id) || [];
|
|
||||||
certificateRunners.push(runner);
|
|
||||||
}
|
}
|
||||||
fetch(
|
})
|
||||||
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
.then((blob) => {
|
||||||
{
|
const url = window.URL.createObjectURL(blob);
|
||||||
method: "POST",
|
let a = document.createElement("a");
|
||||||
headers: {
|
a.href = url;
|
||||||
"Content-Type": "application/json",
|
a.download = `${$_("certificates")}_${o.name}_${
|
||||||
},
|
t.name
|
||||||
body: JSON.stringify(certificateRunners),
|
}-${locale}-${createId()}.pdf`;
|
||||||
}
|
document.body.appendChild(a);
|
||||||
)
|
a.click();
|
||||||
.then((response) => {
|
a.remove();
|
||||||
if (response.status != "200") {
|
if (
|
||||||
toast.hideToast();
|
count === o.teams.length &&
|
||||||
Toastify({
|
count_orgs === generate_orgs.length
|
||||||
text: $_("pdf-generation-failed"),
|
) {
|
||||||
duration: 3500,
|
toast.hideToast();
|
||||||
backgroundColor:
|
Toastify({
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
text: $_("pdfs-successfully-generated"),
|
||||||
}).showToast();
|
duration: 3500,
|
||||||
} else {
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
return response.blob();
|
}).showToast();
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
count++;
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('certificates')}_${t.name}-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === generate_teams.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateOrgCertificates(locale) {
|
|
||||||
const toast = Toastify({
|
|
||||||
text: $_("generating-pdfs"),
|
|
||||||
duration: -1,
|
|
||||||
}).showToast();
|
|
||||||
const current_donations = (await DonationService.donationControllerGetAll()) || [];
|
|
||||||
let count = 0;
|
|
||||||
let count_orgs =0;
|
|
||||||
for (const o of generate_orgs) {
|
|
||||||
count_orgs++;
|
|
||||||
let count = 0;
|
|
||||||
let runners = await RunnerOrganizationService.runnerOrganizationControllerGetRunners(o.id, true)
|
|
||||||
let certificateRunners = [];
|
|
||||||
for (let runner of runners) {
|
|
||||||
runner.distanceDonations = current_donations.find((d) => d.runner?.id == runner.id) || [];
|
|
||||||
certificateRunners.push(runner);
|
|
||||||
}
|
}
|
||||||
await fetch(
|
})
|
||||||
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
.catch((err) => {});
|
||||||
{
|
}
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(certificateRunners),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-generation-failed"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
|
||||||
}).showToast();
|
|
||||||
} else {
|
|
||||||
return response.blob();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('certificates')}_${o.name}_direct-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
console.log("here")
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
for (const t of o.teams) {
|
|
||||||
count++;
|
|
||||||
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
|
||||||
t.id
|
|
||||||
);
|
|
||||||
let certificateRunners = [];
|
|
||||||
for (let runner of runners) {
|
|
||||||
runner.distanceDonations = current_donations.find((d) => d.runner?.id == runner.id) || [];
|
|
||||||
certificateRunners.push(runner);
|
|
||||||
}
|
|
||||||
await fetch(
|
|
||||||
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(certificateRunners),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-generation-failed"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
|
||||||
}).showToast();
|
|
||||||
} else {
|
|
||||||
return response.blob();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('certificates')}_${o.name}_${t.name}-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if certificates_show}
|
{#if certificates_show}
|
||||||
<div id="certificates:dropdown" class="relative inline-block">
|
<div id="certificates:dropdown" class="relative inline-block">
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
certificates_dropdown_open = !certificates_dropdown_open;
|
certificates_dropdown_open = !certificates_dropdown_open;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm inline-flex"
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm inline-flex"
|
||||||
id="options-menu"
|
id="options-menu"
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
aria-expanded="true">
|
aria-expanded="true"
|
||||||
{$_('generate-runner-certificates')}
|
>
|
||||||
<svg
|
{$_("generate-runner-certificates")}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<svg
|
||||||
width="24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
height="24"
|
width="24"
|
||||||
viewBox="0 0 24 24"
|
height="24"
|
||||||
class="-mr-1 ml-2 h-5 w-5"><path
|
viewBox="0 0 24 24"
|
||||||
fill="none"
|
class="-mr-1 ml-2 h-5 w-5"
|
||||||
d="M0 0h24v24H0z" />
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
d="M3 19h18v2H3v-2zm10-5.83l6.07-6.07 1.42 1.41L12 17 3.52 8.52l1.4-1.42L11 13.17V2h2v11.17z" /></svg>
|
d="M3 19h18v2H3v-2zm10-5.83l6.07-6.07 1.42 1.41L12 17 3.52 8.52l1.4-1.42L11 13.17V2h2v11.17z"
|
||||||
</button>
|
/></svg
|
||||||
</div>
|
>
|
||||||
{#if certificates_dropdown_open}
|
</button>
|
||||||
<div
|
|
||||||
class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5"
|
|
||||||
id="certificates:dropdown:menu">
|
|
||||||
<div
|
|
||||||
class="py-1"
|
|
||||||
role="menu"
|
|
||||||
aria-orientation="vertical"
|
|
||||||
aria-labelledby="options-menu">
|
|
||||||
<span
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700">{$_('select-language')}</span>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
generateCertificates('de');
|
|
||||||
}}
|
|
||||||
type="submit"
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
|
||||||
role="menuitem">
|
|
||||||
{$_('german')}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
generateCertificates('en');
|
|
||||||
}}
|
|
||||||
type="submit"
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
|
||||||
role="menuitem">
|
|
||||||
{$_('english')}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
|
{#if certificates_dropdown_open}
|
||||||
|
<div
|
||||||
|
class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 z-10"
|
||||||
|
id="certificates:dropdown:menu"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="py-1"
|
||||||
|
role="menu"
|
||||||
|
aria-orientation="vertical"
|
||||||
|
aria-labelledby="options-menu"
|
||||||
|
>
|
||||||
|
<span class="block w-full text-left px-4 py-2 text-sm text-gray-700"
|
||||||
|
>{$_("select-language")}</span
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
generateCertificates("de");
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
||||||
|
role="menuitem"
|
||||||
|
>
|
||||||
|
{$_("german")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
generateCertificates("en");
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
||||||
|
role="menuitem"
|
||||||
|
>
|
||||||
|
{$_("english")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1,306 +1,324 @@
|
|||||||
<script>
|
<script>
|
||||||
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
||||||
import {
|
import {
|
||||||
RunnerOrganizationService,
|
RunnerOrganizationService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
export let sponsoring_contracts_show = false;
|
import { init } from "@paralleldrive/cuid2";
|
||||||
export let generate_runners = [];
|
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
|
||||||
export let generate_orgs = [];
|
|
||||||
export let generate_teams = [];
|
|
||||||
$: sponsoring_contracts_download_open = false;
|
|
||||||
document.addEventListener("click", function (e) {
|
|
||||||
if (
|
|
||||||
e.target.parentNode?.parentNode?.id != "sponsoring:dropdown" &&
|
|
||||||
e.target.parentNode?.parentNode?.id != "sponsoring:dropdown:menu"
|
|
||||||
) {
|
|
||||||
sponsoring_contracts_download_open = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function generateSponsoringContract(locale) {
|
export let sponsoring_contracts_show = false;
|
||||||
sponsoring_contracts_download_open = false;
|
export let generate_runners = [];
|
||||||
|
export let generate_orgs = [];
|
||||||
if (generate_orgs.length > 0) {
|
export let generate_teams = [];
|
||||||
generateOrgContracts(locale);
|
$: sponsoring_contracts_download_open = false;
|
||||||
} else if (generate_teams.length > 0) {
|
document.addEventListener("click", function (e) {
|
||||||
generateTeamContracts(locale);
|
if (
|
||||||
} else {
|
e.target.parentNode?.parentNode?.id != "sponsoring:dropdown" &&
|
||||||
generateRunnerContracts(locale);
|
e.target.parentNode?.parentNode?.id != "sponsoring:dropdown:menu"
|
||||||
}
|
) {
|
||||||
|
sponsoring_contracts_download_open = false;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
async function generateTeamContracts(locale) {
|
function generateSponsoringContract(locale) {
|
||||||
const toast = Toastify({
|
sponsoring_contracts_download_open = false;
|
||||||
text: $_("generating-pdfs"),
|
|
||||||
duration: -1,
|
if (generate_orgs.length > 0) {
|
||||||
}).showToast();
|
generateOrgContracts(locale);
|
||||||
let count = 0;
|
} else if (generate_teams.length > 0) {
|
||||||
for (const t of generate_teams) {
|
generateTeamContracts(locale);
|
||||||
count++;
|
} else {
|
||||||
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
generateRunnerContracts(locale);
|
||||||
t.id
|
|
||||||
);
|
|
||||||
fetch(
|
|
||||||
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(runners),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-generation-failed"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
|
||||||
}).showToast();
|
|
||||||
} else {
|
|
||||||
return response.blob();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('sponsorings')}_${t.name}-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === generate_teams.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function generateOrgContracts(locale) {
|
async function generateTeamContracts(locale) {
|
||||||
const toast = Toastify({
|
const toast = Toastify({
|
||||||
text: $_("generating-pdf"),
|
text: $_("generating-pdfs"),
|
||||||
duration: -1,
|
duration: -1,
|
||||||
}).showToast();
|
}).showToast();
|
||||||
let count_orgs =0;
|
let count = 0;
|
||||||
for (const o of generate_orgs) {
|
for (const t of generate_teams) {
|
||||||
count_orgs++;
|
count++;
|
||||||
let count = 0;
|
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
let runners = await RunnerOrganizationService.runnerOrganizationControllerGetRunners(o.id, true)
|
t.id
|
||||||
await fetch(
|
);
|
||||||
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
fetch(
|
||||||
{
|
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
method: "POST",
|
{
|
||||||
headers: {
|
method: "POST",
|
||||||
"Content-Type": "application/json",
|
headers: {
|
||||||
},
|
"Content-Type": "application/json",
|
||||||
body: JSON.stringify(runners),
|
},
|
||||||
}
|
body: JSON.stringify(runners),
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-generation-failed"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
|
||||||
}).showToast();
|
|
||||||
} else {
|
|
||||||
return response.blob();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('sponsorings')}_${o.name}_direct-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
console.log("here")
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
for (const t of o.teams) {
|
|
||||||
count++;
|
|
||||||
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
|
||||||
t.id
|
|
||||||
);
|
|
||||||
await fetch(
|
|
||||||
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(runners),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-generation-failed"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
|
||||||
}).showToast();
|
|
||||||
} else {
|
|
||||||
return response.blob();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('sponsorings')}_${o.name}_${t.name}-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = `${$_("sponsorings")}_${t.name}-${locale}-${createId()}.pdf`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
if (count === generate_teams.length) {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdfs-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function generateRunnerContracts(locale) {
|
async function generateOrgContracts(locale) {
|
||||||
const toast = Toastify({
|
const toast = Toastify({
|
||||||
text: $_("generating-pdf"),
|
text: $_("generating-pdf"),
|
||||||
duration: -1,
|
duration: -1,
|
||||||
}).showToast();
|
}).showToast();
|
||||||
fetch(
|
let count_orgs = 0;
|
||||||
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
for (const o of generate_orgs) {
|
||||||
{
|
count_orgs++;
|
||||||
method: "POST",
|
let count = 0;
|
||||||
headers: {
|
let runners =
|
||||||
"Content-Type": "application/json",
|
await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
||||||
},
|
o.id,
|
||||||
body: JSON.stringify(generate_runners),
|
true
|
||||||
}
|
);
|
||||||
|
await fetch(
|
||||||
|
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(runners),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = `${$_("sponsorings")}_${o.name}_direct-${locale}-${createId()}.pdf`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
||||||
|
toast.hideToast();
|
||||||
|
console.log("here");
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdfs-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
for (const t of o.teams) {
|
||||||
|
count++;
|
||||||
|
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
|
t.id
|
||||||
|
);
|
||||||
|
await fetch(
|
||||||
|
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(runners),
|
||||||
|
}
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status != "200") {
|
if (response.status != "200") {
|
||||||
toast.hideToast();
|
toast.hideToast();
|
||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdf-generation-failed"),
|
text: $_("pdf-generation-failed"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
} else {
|
} else {
|
||||||
return response.blob();
|
return response.blob();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((blob) => {
|
.then((blob) => {
|
||||||
const url = window.URL.createObjectURL(blob);
|
const url = window.URL.createObjectURL(blob);
|
||||||
let a = document.createElement("a");
|
let a = document.createElement("a");
|
||||||
a.href = url;
|
a.href = url;
|
||||||
if(generate_runners.length == 1){
|
a.download = `${$_("sponsorings")}_${o.name}_${
|
||||||
a.download = `${$_('sponsorings')}_${generate_runners[0].firstname}_${generate_runners[0].lastname}-${locale}.pdf`;
|
t.name
|
||||||
}
|
}-${locale}-${createId()}.pdf`;
|
||||||
a.download = `${$_('sponsorings')}-${locale}.pdf`;
|
document.body.appendChild(a);
|
||||||
document.body.appendChild(a);
|
a.click();
|
||||||
a.click();
|
a.remove();
|
||||||
a.remove();
|
if (
|
||||||
toast.hideToast();
|
count === o.teams.length &&
|
||||||
Toastify({
|
count_orgs === generate_orgs.length
|
||||||
text: $_("pdf-successfully-generated"),
|
) {
|
||||||
duration: 3500,
|
toast.hideToast();
|
||||||
backgroundColor:
|
Toastify({
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
text: $_("pdfs-successfully-generated"),
|
||||||
}).showToast();
|
duration: 3500,
|
||||||
})
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
.catch((err) => {
|
}).showToast();
|
||||||
console.error(err);
|
}
|
||||||
});
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateRunnerContracts(locale) {
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("generating-pdf"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
fetch(
|
||||||
|
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(generate_runners),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
if (generate_runners.length == 1) {
|
||||||
|
a.download = `${$_("sponsorings")}_${generate_runners[0].firstname}_${
|
||||||
|
generate_runners[0].lastname
|
||||||
|
}-${locale}-${createId()}.pdf`;
|
||||||
|
}
|
||||||
|
a.download = `${$_("sponsorings")}-${locale}-${createId()}.pdf`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if sponsoring_contracts_show}
|
{#if sponsoring_contracts_show}
|
||||||
<div id="sponsoring:dropdown" class="relative inline-block">
|
<div id="sponsoring:dropdown" class="relative inline-block">
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
sponsoring_contracts_download_open = !sponsoring_contracts_download_open;
|
sponsoring_contracts_download_open =
|
||||||
}}
|
!sponsoring_contracts_download_open;
|
||||||
type="button"
|
}}
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm inline-flex"
|
type="button"
|
||||||
id="options-menu"
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm inline-flex"
|
||||||
aria-haspopup="true"
|
id="options-menu"
|
||||||
aria-expanded="true">
|
aria-haspopup="true"
|
||||||
{$_('generate-sponsoring-contracts')}
|
aria-expanded="true"
|
||||||
<svg
|
>
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
{$_("generate-sponsoring-contracts")}
|
||||||
width="24"
|
<svg
|
||||||
height="24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
width="24"
|
||||||
class="-mr-1 ml-2 h-5 w-5"><path
|
height="24"
|
||||||
fill="none"
|
viewBox="0 0 24 24"
|
||||||
d="M0 0h24v24H0z" />
|
class="-mr-1 ml-2 h-5 w-5"
|
||||||
<path
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
fill="currentColor"
|
<path
|
||||||
d="M3 19h18v2H3v-2zm10-5.83l6.07-6.07 1.42 1.41L12 17 3.52 8.52l1.4-1.42L11 13.17V2h2v11.17z" /></svg>
|
fill="currentColor"
|
||||||
</button>
|
d="M3 19h18v2H3v-2zm10-5.83l6.07-6.07 1.42 1.41L12 17 3.52 8.52l1.4-1.42L11 13.17V2h2v11.17z"
|
||||||
</div>
|
/></svg
|
||||||
{#if sponsoring_contracts_download_open}
|
>
|
||||||
<div
|
</button>
|
||||||
class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5"
|
|
||||||
id="sponsoring:dropdown:menu">
|
|
||||||
<div
|
|
||||||
class="py-1"
|
|
||||||
role="menu"
|
|
||||||
aria-orientation="vertical"
|
|
||||||
aria-labelledby="options-menu">
|
|
||||||
<span
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700">{$_('select-language')}</span>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
generateSponsoringContract('de');
|
|
||||||
}}
|
|
||||||
type="submit"
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
|
||||||
role="menuitem">
|
|
||||||
{$_('german')}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
generateSponsoringContract('en');
|
|
||||||
}}
|
|
||||||
type="submit"
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
|
||||||
role="menuitem">
|
|
||||||
{$_('english')}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
|
{#if sponsoring_contracts_download_open}
|
||||||
|
<div
|
||||||
|
class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 z-10"
|
||||||
|
id="sponsoring:dropdown:menu"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="py-1"
|
||||||
|
role="menu"
|
||||||
|
aria-orientation="vertical"
|
||||||
|
aria-labelledby="options-menu"
|
||||||
|
>
|
||||||
|
<span class="block w-full text-left px-4 py-2 text-sm text-gray-700"
|
||||||
|
>{$_("select-language")}</span
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
generateSponsoringContract("de");
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
||||||
|
role="menuitem"
|
||||||
|
>
|
||||||
|
{$_("german")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
generateSponsoringContract("en");
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
||||||
|
role="menuitem"
|
||||||
|
>
|
||||||
|
{$_("english")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1,30 +0,0 @@
|
|||||||
<script>
|
|
||||||
import { _, json } from "svelte-i18n";
|
|
||||||
import { getlang } from "./datatable_i18n";
|
|
||||||
import { Grid } from "gridjs";
|
|
||||||
//
|
|
||||||
let table;
|
|
||||||
const datatable = new Grid({
|
|
||||||
columns: ["Name", "Email", "Phone Number"],
|
|
||||||
language: getlang($json("datatable")),
|
|
||||||
sort: true,
|
|
||||||
search: { enabled: true },
|
|
||||||
data: [
|
|
||||||
["John", "john@example.com", "(353) 01 222 3333"],
|
|
||||||
["Mark", "mark@gmail.com", "(01) 22 888 4444"],
|
|
||||||
["Eoin", "eoin@gmail.com", "0097 22 654 00033"],
|
|
||||||
["Sarah", "sarahcdd@gmail.com", "+322 876 1233"],
|
|
||||||
["Afshin", "afshin@mail.com", "(353) 22 87 8356"],
|
|
||||||
],
|
|
||||||
pagination: {
|
|
||||||
enabled: true,
|
|
||||||
limit: 2,
|
|
||||||
summary: false,
|
|
||||||
},
|
|
||||||
});
|
|
||||||
setTimeout(() => {
|
|
||||||
datatable.render(table);
|
|
||||||
}, 0);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<div bind:this={table} />
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import {
|
import {
|
||||||
RunnerService,
|
RunnerService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
@@ -11,8 +11,10 @@
|
|||||||
import isMobilePhone from "validator/es/lib/isMobilePhone";
|
import isMobilePhone from "validator/es/lib/isMobilePhone";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
import Select from "svelte-select";
|
import Select from "svelte-select";
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
export let modal_open;
|
export let modal_open;
|
||||||
export let current_runners;
|
|
||||||
$: selected_team = undefined;
|
$: selected_team = undefined;
|
||||||
let firstname_input;
|
let firstname_input;
|
||||||
let lastname_input;
|
let lastname_input;
|
||||||
@@ -107,8 +109,7 @@
|
|||||||
duration: 500,
|
duration: 500,
|
||||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
current_runners.push(result);
|
dispatch("created", { runners: [result] });
|
||||||
current_runners = current_runners;
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
//
|
//
|
||||||
@@ -125,7 +126,7 @@
|
|||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={() => {
|
on:click_outside={() => {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
|
|||||||
@@ -0,0 +1,115 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import { clickOutside } from "../base/outsideclick";
|
||||||
|
import { createEventDispatcher, onMount } from "svelte";
|
||||||
|
export let modal_open;
|
||||||
|
export let delete_runner = {
|
||||||
|
id: 0,
|
||||||
|
firstname: "",
|
||||||
|
lastname: "",
|
||||||
|
};
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
onMount(() => {
|
||||||
|
document.onkeydown = (e) => {
|
||||||
|
e = e || window.event;
|
||||||
|
if (e.key === "Escape") {
|
||||||
|
modal_open = false;
|
||||||
|
}
|
||||||
|
if (e.keyCode === 13) {
|
||||||
|
if (createbtnenabled === true) {
|
||||||
|
createbtnenabled = false;
|
||||||
|
submit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
async function submit() {
|
||||||
|
dispatch("delete", { id: delete_runner.id });
|
||||||
|
modal_open=false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if modal_open}
|
||||||
|
<div
|
||||||
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
|
use:clickOutside
|
||||||
|
on:click_outside={() => {
|
||||||
|
modal_open = false;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
||||||
|
>
|
||||||
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
|
data-id="modal_backdrop"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
|
aria-hidden="true">​</span
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby="modal-headline"
|
||||||
|
>
|
||||||
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
|
<div class="sm:flex sm:items-start">
|
||||||
|
<div
|
||||||
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
class="h-6 w-6 text-blue-600"
|
||||||
|
fill="currentColor"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
d="M9.83 8.79L8 9.456V13H6V8.05h.015l5.268-1.918c.244-.093.51-.14.782-.131a2.616 2.616 0 0 1 2.427 1.82c.186.583.356.977.51 1.182A4.992 4.992 0 0 0 19 11v2a6.986 6.986 0 0 1-5.402-2.547l-.581 3.297L15 15.67V23h-2v-5.986l-2.05-1.987-.947 4.298-6.894-1.215.348-1.97 4.924.868L9.83 8.79zM13.5 5.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
{$_("confirm-delete")}
|
||||||
|
</h3>
|
||||||
|
<div class="mt-2 mb-6">
|
||||||
|
<p class="text-sm text-gray-500">
|
||||||
|
{$_("please-confirm-the-deletion-of-runner")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="w-full">
|
||||||
|
<span class="inline-block"
|
||||||
|
>{delete_runner.firstname} {delete_runner.lastname}</span
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||||
|
<button
|
||||||
|
on:click={submit}
|
||||||
|
type="button"
|
||||||
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>
|
||||||
|
{$_("delete")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
modal_open = false;
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>
|
||||||
|
{$_("cancel")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -3,7 +3,7 @@
|
|||||||
import { read as readXlsx, utils as xlsx_utils } from "xlsx";
|
import { read as readXlsx, utils as xlsx_utils } from "xlsx";
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
import {
|
import {
|
||||||
ImportService,
|
ImportService,
|
||||||
@@ -16,7 +16,6 @@
|
|||||||
export let passed_org;
|
export let passed_org;
|
||||||
export let passed_orgs;
|
export let passed_orgs;
|
||||||
export let passed_team;
|
export let passed_team;
|
||||||
export let current_runners;
|
|
||||||
export let import_modal_open;
|
export let import_modal_open;
|
||||||
$: searchvalue = "";
|
$: searchvalue = "";
|
||||||
$: importButtonEnabled =
|
$: importButtonEnabled =
|
||||||
@@ -169,7 +168,7 @@
|
|||||||
mapped
|
mapped
|
||||||
)
|
)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
current_runners = current_runners.concat(resp);
|
dispatch("created", { runners: resp });
|
||||||
toast.hideToast();
|
toast.hideToast();
|
||||||
recent_processed = true;
|
recent_processed = true;
|
||||||
Toastify({
|
Toastify({
|
||||||
@@ -198,7 +197,7 @@
|
|||||||
mapped
|
mapped
|
||||||
)
|
)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
current_runners = current_runners.concat(resp);
|
dispatch("created", { runners: resp });
|
||||||
toast.hideToast();
|
toast.hideToast();
|
||||||
recent_processed = true;
|
recent_processed = true;
|
||||||
Toastify({
|
Toastify({
|
||||||
@@ -228,7 +227,7 @@
|
|||||||
{#if import_modal_open}
|
{#if import_modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={() => {
|
on:click_outside={() => {
|
||||||
cancelModal();
|
cancelModal();
|
||||||
|
|||||||
@@ -71,6 +71,9 @@
|
|||||||
}).showToast();
|
}).showToast();
|
||||||
let postdata = {};
|
let postdata = {};
|
||||||
postdata = Object.assign(postdata, editable);
|
postdata = Object.assign(postdata, editable);
|
||||||
|
if (postdata.phone === "") {
|
||||||
|
postdata.phone = null;
|
||||||
|
}
|
||||||
RunnerService.runnerControllerPut(original_data.id, postdata)
|
RunnerService.runnerControllerPut(original_data.id, postdata)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
Object.assign(original_data, editable);
|
Object.assign(original_data, editable);
|
||||||
@@ -95,7 +98,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#await runner_promise}
|
{#await runner_promise}
|
||||||
{$_('loading-runners')}
|
{$_("loading-runners")}
|
||||||
{:then}
|
{:then}
|
||||||
<section class="container p-5 select-none">
|
<section class="container p-5 select-none">
|
||||||
<div class="flex flex-row mb-4">
|
<div class="flex flex-row mb-4">
|
||||||
@@ -109,12 +112,15 @@
|
|||||||
class="flex-shrink-0 w-5 h-5 mr-2"
|
class="flex-shrink-0 w-5 h-5 mr-2"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
height="24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path
|
<path
|
||||||
d="M9.83 8.79L8 9.456V13H6V8.05h.015l5.268-1.918c.244-.093.51-.14.782-.131a2.616 2.616 0 0 1 2.427 1.82c.186.583.356.977.51 1.182A4.992 4.992 0 0 0 19 11v2a6.986 6.986 0 0 1-5.402-2.547l-.581 3.297L15 15.67V23h-2v-5.986l-2.05-1.987-.947 4.298-6.894-1.215.348-1.97 4.924.868L9.83 8.79zM13.5 5.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4z" /></svg>
|
d="M9.83 8.79L8 9.456V13H6V8.05h.015l5.268-1.918c.244-.093.51-.14.782-.131a2.616 2.616 0 0 1 2.427 1.82c.186.583.356.977.51 1.182A4.992 4.992 0 0 0 19 11v2a6.986 6.986 0 0 1-5.402-2.547l-.581 3.297L15 15.67V23h-2v-5.986l-2.05-1.987-.947 4.298-6.894-1.215.348-1.97 4.924.868L9.83 8.79zM13.5 5.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
</li>
|
</li>
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
<a class="mr-2" href="./">{$_('runners')}</a><svg
|
<a class="mr-2" href="./">{$_("runners")}</a><svg
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
@@ -124,17 +130,17 @@
|
|||||||
class="h-3 w-3 mr-2 stroke-current"
|
class="h-3 w-3 mr-2 stroke-current"
|
||||||
height="1em"
|
height="1em"
|
||||||
width="1em"
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"><line
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
x1="5"
|
><line x1="5" y1="12" x2="19" y2="12" />
|
||||||
y1="12"
|
<polyline points="12 5 19 12 12 19" /></svg
|
||||||
x2="19"
|
>
|
||||||
y2="12" />
|
|
||||||
<polyline points="12 5 19 12 12 19" /></svg>
|
|
||||||
</li>
|
</li>
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
<span class="mr-2">{original_data.firstname}
|
<span class="mr-2"
|
||||||
{original_data.middlename || ''}
|
>{original_data.firstname}
|
||||||
{original_data.lastname}</span>
|
{original_data.middlename || ""}
|
||||||
|
{original_data.lastname}</span
|
||||||
|
>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -142,36 +148,42 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
||||||
{original_data.firstname}
|
{original_data.firstname}
|
||||||
{original_data.middlename || ''}
|
{original_data.middlename || ""}
|
||||||
{original_data.lastname}
|
{original_data.lastname}
|
||||||
<span data-id="runner_actions_${editable.id}">
|
<span data-id="runner_actions_${editable.id}">
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('RUNNER:DELETE')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:DELETE")}
|
||||||
{#if delete_triggered}
|
{#if delete_triggered}
|
||||||
<button
|
<button
|
||||||
on:click={deleteRunner}
|
on:click={deleteRunner}
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('confirm-deletion')}</button>
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>{$_("confirm-deletion")}</button
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
delete_triggered = !delete_triggered;
|
delete_triggered = !delete_triggered;
|
||||||
}}
|
}}
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm">{$_('cancel')}</button>
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm"
|
||||||
|
>{$_("cancel")}</button
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
<GenerateSponsoringContracts
|
<GenerateSponsoringContracts
|
||||||
bind:sponsoring_contracts_show
|
bind:sponsoring_contracts_show
|
||||||
bind:generate_runners />
|
bind:generate_runners
|
||||||
<GenerateRunnerCards
|
/>
|
||||||
bind:cards_show
|
<GenerateRunnerCards bind:cards_show bind:generate_runners />
|
||||||
bind:generate_runners />
|
|
||||||
<GenerateRunnerCertificates
|
<GenerateRunnerCertificates
|
||||||
bind:certificates_show
|
bind:certificates_show
|
||||||
bind:generate_runners />
|
bind:generate_runners
|
||||||
|
/>
|
||||||
{#if !delete_triggered}
|
{#if !delete_triggered}
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
delete_triggered = true;
|
delete_triggered = true;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('delete-runner')}</button>
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>{$_("delete-runner")}</button
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
{#if !delete_triggered}
|
{#if !delete_triggered}
|
||||||
@@ -180,121 +192,128 @@
|
|||||||
class:opacity-50={!save_enabled}
|
class:opacity-50={!save_enabled}
|
||||||
type="button"
|
type="button"
|
||||||
on:click={submit}
|
on:click={submit}
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('save-changes')}</button>
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>{$_("save-changes")}</button
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full">
|
||||||
<label
|
<label for="firstname" class="font-medium text-gray-700"
|
||||||
for="firstname"
|
>{$_("first-name")}</label
|
||||||
class="font-medium text-gray-700">{$_('first-name')}</label>
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('first-name')}
|
placeholder={$_("first-name")}
|
||||||
type="text"
|
type="text"
|
||||||
class:border-red-500={!isFirstnameValid}
|
class:border-red-500={!isFirstnameValid}
|
||||||
class:focus:border-red-500={!isFirstnameValid}
|
class:focus:border-red-500={!isFirstnameValid}
|
||||||
class:focus:ring-red-500={!isFirstnameValid}
|
class:focus:ring-red-500={!isFirstnameValid}
|
||||||
bind:value={editable.firstname}
|
bind:value={editable.firstname}
|
||||||
name="firstname"
|
name="firstname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
{#if !isFirstnameValid}
|
{#if !isFirstnameValid}
|
||||||
<span
|
<span
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{$_('first-name-is-required')}
|
>
|
||||||
|
{$_("first-name-is-required")}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full">
|
||||||
<label
|
<label for="middlename" class="font-medium text-gray-700"
|
||||||
for="middlename"
|
>{$_("middle-name")}</label
|
||||||
class="font-medium text-gray-700">{$_('middle-name')}</label>
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('middle-name')}
|
placeholder={$_("middle-name")}
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={editable.middlename}
|
bind:value={editable.middlename}
|
||||||
name="middlename"
|
name="middlename"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full">
|
||||||
<label
|
<label for="lastname" class="font-medium text-gray-700"
|
||||||
for="lastname"
|
>{$_("last-name")}</label
|
||||||
class="font-medium text-gray-700">{$_('last-name')}</label>
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('last-name')}
|
placeholder={$_("last-name")}
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={editable.lastname}
|
bind:value={editable.lastname}
|
||||||
class:border-red-500={!isLastnameValid}
|
class:border-red-500={!isLastnameValid}
|
||||||
class:focus:border-red-500={!isLastnameValid}
|
class:focus:border-red-500={!isLastnameValid}
|
||||||
class:focus:ring-red-500={!isLastnameValid}
|
class:focus:ring-red-500={!isLastnameValid}
|
||||||
name="lastname"
|
name="lastname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
{#if !isLastnameValid}
|
{#if !isLastnameValid}
|
||||||
<span
|
<span
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{$_('last-name-is-required')}
|
>
|
||||||
|
{$_("last-name-is-required")}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full">
|
||||||
<label
|
<label for="email" class="font-medium text-gray-700"
|
||||||
for="email"
|
>{$_("e-mail-adress")}</label
|
||||||
class="font-medium text-gray-700">{$_('e-mail-adress')}</label>
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('e-mail-adress')}
|
placeholder={$_("e-mail-adress")}
|
||||||
type="email"
|
type="email"
|
||||||
bind:value={editable.email}
|
bind:value={editable.email}
|
||||||
class:border-red-500={!isEmailValid}
|
class:border-red-500={!isEmailValid}
|
||||||
class:focus:border-red-500={!isEmailValid}
|
class:focus:border-red-500={!isEmailValid}
|
||||||
class:focus:ring-red-500={!isEmailValid}
|
class:focus:ring-red-500={!isEmailValid}
|
||||||
name="email"
|
name="email"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
{#if !isEmailValid}
|
{#if !isEmailValid}
|
||||||
<span
|
<span
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{$_('valid-email-is-required')}
|
>
|
||||||
|
{$_("valid-email-is-required")}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full">
|
||||||
<label for="phone" class="font-medium text-gray-700">{$_('phone')}</label>
|
<label for="phone" class="font-medium text-gray-700">{$_("phone")}</label>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('phone')}
|
placeholder={$_("phone")}
|
||||||
type="tel"
|
type="tel"
|
||||||
bind:value={editable.phone}
|
bind:value={editable.phone}
|
||||||
name="phone"
|
name="phone"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full">
|
||||||
<span class="font-medium text-gray-700">{$_('group')}</span>
|
<span class="font-medium text-gray-700">{$_("group")}</span>
|
||||||
<Select
|
<Select
|
||||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
itemFilter={(label, filterText, option) => label
|
itemFilter={(label, filterText, option) =>
|
||||||
.toLowerCase()
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
.includes(
|
option.id.value.toString().startsWith(filterText.toLowerCase())}
|
||||||
filterText.toLowerCase()
|
|
||||||
) || option.id.value
|
|
||||||
.toString()
|
|
||||||
.startsWith(filterText.toLowerCase())}
|
|
||||||
items={groups}
|
items={groups}
|
||||||
showChevron={true}
|
showChevron={true}
|
||||||
placeholder={$_('search-for-an-organization-or-team-by-name-or-id')}
|
placeholder={$_("search-for-an-organization-or-team-by-name-or-id")}
|
||||||
noOptionsMessage={$_('no-organization-or-team-found')}
|
noOptionsMessage={$_("no-organization-or-team-found")}
|
||||||
bind:selectedValue={group}
|
bind:selectedValue={group}
|
||||||
on:select={(selectedValue) => {
|
on:select={(selectedValue) => {
|
||||||
editable.group = selectedValue.detail.value.id;
|
editable.group = selectedValue.detail.value.id;
|
||||||
}}
|
}}
|
||||||
on:clear={() => (editable.group = null)} />
|
on:clear={() => (editable.group = null)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full">
|
||||||
<span class="font-medium text-gray-700">{$_('distance')}</span>
|
<span class="font-medium text-gray-700">{$_("distance")}</span>
|
||||||
<br />
|
<br />
|
||||||
<span class="text-gray-700">{original_data.distance} km</span>
|
<span class="text-gray-700">{original_data.distance / 1000} km</span>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{:catch error}
|
{:catch error}
|
||||||
|
|||||||
@@ -7,35 +7,43 @@
|
|||||||
$: current_runners = [];
|
$: current_runners = [];
|
||||||
export let modal_open = false;
|
export let modal_open = false;
|
||||||
export let import_modal_open = false;
|
export let import_modal_open = false;
|
||||||
|
let addRunners;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_('runners')}
|
{$_("runners")}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('RUNNER:CREATE')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:CREATE")}
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
modal_open = true;
|
modal_open = true;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
{$_('laeufer-hinzufuegen')}
|
>
|
||||||
|
{$_("laeufer-hinzufuegen")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
import_modal_open = true;
|
import_modal_open = true;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
{$_('import-runners')}
|
>
|
||||||
|
{$_("import-runners")}
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
<RunnersOverview bind:current_runners />
|
<RunnersOverview bind:current_runners bind:addRunners />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('RUNNER:CREATE')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:CREATE")}
|
||||||
<AddRunnerModal bind:current_runners bind:modal_open />
|
<AddRunnerModal
|
||||||
|
bind:modal_open
|
||||||
|
on:created={(event) => {
|
||||||
|
addRunners(event.detail.runners);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
<ImportRunnerModal
|
<ImportRunnerModal
|
||||||
on:cancelDelete={(event) => {
|
on:cancelDelete={(event) => {
|
||||||
import_modal_open = false;
|
import_modal_open = false;
|
||||||
@@ -43,7 +51,10 @@
|
|||||||
passed_team={{}}
|
passed_team={{}}
|
||||||
passed_orgs={[]}
|
passed_orgs={[]}
|
||||||
passed_org={{}}
|
passed_org={{}}
|
||||||
bind:current_runners
|
|
||||||
opened_from="RunnerOverview"
|
opened_from="RunnerOverview"
|
||||||
bind:import_modal_open />
|
bind:import_modal_open
|
||||||
|
on:created={(event) => {
|
||||||
|
addRunners(event.detail.runners);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1,263 +1,267 @@
|
|||||||
<script>
|
<script>
|
||||||
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
|
||||||
import {
|
import {
|
||||||
|
RunnerOrganizationService,
|
||||||
RunnerService,
|
RunnerService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
RunnerOrganizationService,
|
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
|
import {
|
||||||
|
createSvelteTable,
|
||||||
|
flexRender,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
renderComponent,
|
||||||
|
} from "@tanstack/svelte-table";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import { writable } from "svelte/store";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import RunnersEmptyState from "./RunnersEmptyState.svelte";
|
|
||||||
import Select from "svelte-select";
|
|
||||||
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
|
||||||
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
||||||
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
||||||
$: searchvalue = "";
|
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
||||||
$: active_deletes = [];
|
import InputElement from "../shared/InputElement.svelte";
|
||||||
|
import TableActions from "../shared/TableActions.svelte";
|
||||||
|
import { groupFilter } from "../shared/tablefilters";
|
||||||
|
import DeleteRunnerModal from "./DeleteRunnerModal.svelte";
|
||||||
|
import Toastify from "toastify-js";
|
||||||
|
import TableBottom from "../shared/TableBottom.svelte";
|
||||||
|
import TableHeader from "../shared/TableHeader.svelte";
|
||||||
|
|
||||||
|
$: selectedRunners =
|
||||||
|
$table?.getSelectedRowModel().rows.map((row) => row.original) || [];
|
||||||
|
$: selected =
|
||||||
|
$table?.getSelectedRowModel().rows.map((row) => row.index) || [];
|
||||||
|
|
||||||
|
$: active_delete = undefined;
|
||||||
|
let dataLoaded = false;
|
||||||
export let current_runners = [];
|
export let current_runners = [];
|
||||||
const runners_promise = RunnerService.runnerControllerGetAll().then((val) => {
|
$: sponsoring_contracts_show = selected.length > 0;
|
||||||
current_runners = val;
|
$: cards_show = selected.length > 0;
|
||||||
});
|
$: certificates_show = selected.length > 0;
|
||||||
$: selectedFilter_teams = null;
|
|
||||||
$: selectedFilter = null;
|
|
||||||
$: filter__teams = selectedFilter_teams || [];
|
|
||||||
$: filter__orgs = selectedFilter || [];
|
|
||||||
$: filterGroupIDs = filter__teams.concat(filter__orgs).map((i) => i.value);
|
|
||||||
$: sponsoring_contracts_show = current_runners.some(
|
|
||||||
(r) => r.is_selected === true
|
|
||||||
);
|
|
||||||
$: cards_show = current_runners.some(
|
|
||||||
(r) => r.is_selected === true
|
|
||||||
);
|
|
||||||
$: certificates_show = current_runners.some(
|
|
||||||
(r) => r.is_selected === true
|
|
||||||
);
|
|
||||||
$: generate_runners = current_runners.filter((r) => r.is_selected === true);
|
|
||||||
$: teams = [];
|
$: teams = [];
|
||||||
$: orgs = [];
|
$: orgs = [];
|
||||||
$: mappedteams = teams.map(function (g) {
|
|
||||||
return { value: g.id, label: g.parentGroup.name + " > " + g.name };
|
|
||||||
});
|
|
||||||
$: selectgroups = orgs
|
|
||||||
.map(function (g) {
|
|
||||||
return { value: g.id, label: g.name };
|
|
||||||
})
|
|
||||||
.concat(mappedteams);
|
|
||||||
|
|
||||||
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
export const addRunners = (runners) => {
|
||||||
teams = val;
|
current_runners = current_runners.concat(...runners);
|
||||||
|
options.update((options) => ({
|
||||||
|
...options,
|
||||||
|
data: current_runners,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
//Section table
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
accessorKey: "id",
|
||||||
|
header: () => "id",
|
||||||
|
filterFn: `equalsString`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "firstname",
|
||||||
|
header: () => $_("first-name"),
|
||||||
|
filterFn: `includesString`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "middlename",
|
||||||
|
header: () => $_("middle-name"),
|
||||||
|
cell: (info) => {
|
||||||
|
if (!info || !info.getValue()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return info.getValue();
|
||||||
|
},
|
||||||
|
filterFn: `includesString`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "lastname",
|
||||||
|
header: () => $_("last-name"),
|
||||||
|
filterFn: `includesString`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "group",
|
||||||
|
header: () => $_("group"),
|
||||||
|
cell: (info) => {
|
||||||
|
const group = info.getValue();
|
||||||
|
if (group.responseType === "RUNNERORGANIZATION") {
|
||||||
|
return group.name;
|
||||||
|
}
|
||||||
|
return `${group.parentGroup.name} > ${group.name}`;
|
||||||
|
},
|
||||||
|
filterFn: `group`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "distance",
|
||||||
|
header: () => $_("distance"),
|
||||||
|
cell: (info) => {
|
||||||
|
if (info.getValue() < 1000) {
|
||||||
|
return `${info.getValue()} m`;
|
||||||
|
}
|
||||||
|
return `${(info.getValue() / 1000).toFixed(1)} km`;
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "actions",
|
||||||
|
header: () => $_("action"),
|
||||||
|
cell: (info) => {
|
||||||
|
return renderComponent(TableActions, {
|
||||||
|
detailsLink: `./${info.row.original.id}`,
|
||||||
|
deleteAction: () => {
|
||||||
|
active_delete =
|
||||||
|
current_runners[
|
||||||
|
current_runners.findIndex((r) => r.id == info.row.original.id)
|
||||||
|
];
|
||||||
|
},
|
||||||
|
deleteEnabled:
|
||||||
|
store.state.jwtinfo.userdetails.permissions.includes(
|
||||||
|
"RUNNER:DELETE"
|
||||||
|
),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
enableSorting: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const options = writable({
|
||||||
|
data: [],
|
||||||
|
columns: columns,
|
||||||
|
filterFns: {
|
||||||
|
group: groupFilter,
|
||||||
|
},
|
||||||
|
initialState: {
|
||||||
|
pagination: {
|
||||||
|
pageSize: 50,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
enableRowSelection: true,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
});
|
});
|
||||||
RunnerOrganizationService.runnerOrganizationControllerGetAll().then((val) => {
|
const table = createSvelteTable(options);
|
||||||
orgs = val;
|
|
||||||
});
|
async function deleteRunner(delete_runner_id) {
|
||||||
function should_display_based_on_id(id) {
|
await RunnerService.runnerControllerRemove(delete_runner_id, true);
|
||||||
if (searchvalue.toString().slice(-1) === "*") {
|
current_runners = current_runners.filter((r) => r.id !== delete_runner_id);
|
||||||
return id.toString().startsWith(searchvalue.replace("*", ""));
|
options.update((options) => ({
|
||||||
}
|
...options,
|
||||||
return id.toString() === searchvalue;
|
data: current_runners,
|
||||||
|
}));
|
||||||
|
Toastify({
|
||||||
|
text: $_("runner-deleted"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
||||||
|
teams = val;
|
||||||
|
});
|
||||||
|
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
||||||
|
(val) => {
|
||||||
|
orgs = val;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let page = 0;
|
||||||
|
while (page >= 0) {
|
||||||
|
const runners = await RunnerService.runnerControllerGetAll(page, 1000);
|
||||||
|
if (runners.length == 0) {
|
||||||
|
page = -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_runners = current_runners.concat(...runners);
|
||||||
|
options.update((options) => ({
|
||||||
|
...options,
|
||||||
|
data: current_runners,
|
||||||
|
}));
|
||||||
|
|
||||||
|
dataLoaded = true;
|
||||||
|
page++;
|
||||||
|
}
|
||||||
|
console.log("All runners loaded");
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('RUNNER:GET')}
|
<DeleteRunnerModal
|
||||||
{#await runners_promise}
|
delete_runner={active_delete}
|
||||||
|
modal_open={active_delete != undefined}
|
||||||
|
on:delete={(event) => {
|
||||||
|
deleteRunner(event.detail.id);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET")}
|
||||||
|
{#if !dataLoaded}
|
||||||
<div
|
<div
|
||||||
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
||||||
role="alert">
|
role="alert"
|
||||||
<p class="font-bold">{$_('runners-are-being-loaded')}</p>
|
>
|
||||||
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
<p class="font-bold">{$_("runners-are-being-loaded")}</p>
|
||||||
|
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
||||||
</div>
|
</div>
|
||||||
{:then}
|
{:else}
|
||||||
{#if current_runners.length === 0}
|
<div class="h-12 mt-2">
|
||||||
<RunnersEmptyState />
|
<GenerateSponsoringContracts
|
||||||
{:else}
|
bind:sponsoring_contracts_show
|
||||||
<input
|
bind:generate_runners={selectedRunners}
|
||||||
type="search"
|
/>
|
||||||
bind:value={searchvalue}
|
<GenerateRunnerCards
|
||||||
placeholder={$_('datatable.search')}
|
bind:cards_show
|
||||||
aria-label={$_('datatable.search')}
|
bind:generate_runners={selectedRunners}
|
||||||
class="gridjs-input gridjs-search-input mb-4" />
|
/>
|
||||||
<div class="block mb-6">
|
<GenerateRunnerCertificates
|
||||||
<label
|
bind:certificates_show
|
||||||
for="country"
|
bind:generate_runners={selectedRunners}
|
||||||
class="text-sm font-medium text-gray-700">{$_('filter-by-organization-team')}</label>
|
/>
|
||||||
<Select
|
</div>
|
||||||
on:select={(event) => {
|
<div class="overflow-x-auto">
|
||||||
selectedFilter = event.detail;
|
<table class="w-full">
|
||||||
}}
|
<thead>
|
||||||
selectedValue={selectedFilter}
|
{#each $table.getHeaderGroups() as headerGroup}
|
||||||
placeholder={$_('filter-by-organization-team')}
|
<tr class="select-none">
|
||||||
containerClasses="mt-1 py-2 px-3 border border-gray-300 bg-white rounded-md shadow-sm focus:outline-none focus:ring-indigo-500 focus:border-indigo-500 sm:text-sm"
|
<th class="inset-y-0 left-0 px-4 py-2 text-left w-px">
|
||||||
items={selectgroups}
|
<InputElement
|
||||||
isMulti={true} />
|
type="checkbox"
|
||||||
</div>
|
checked={$table.getIsAllRowsSelected()}
|
||||||
<div class="h-12">
|
indeterminate={$table.getIsSomeRowsSelected()}
|
||||||
<GenerateSponsoringContracts
|
on:change={() => $table.toggleAllRowsSelected()}
|
||||||
bind:sponsoring_contracts_show
|
/>
|
||||||
bind:generate_runners />
|
|
||||||
<GenerateRunnerCards
|
|
||||||
bind:cards_show
|
|
||||||
bind:generate_runners />
|
|
||||||
<GenerateRunnerCertificates
|
|
||||||
bind:certificates_show
|
|
||||||
bind:generate_runners />
|
|
||||||
</div>
|
|
||||||
<div
|
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
|
||||||
<table class="divide-y divide-gray-200 w-full">
|
|
||||||
<thead class="bg-gray-50">
|
|
||||||
<tr>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
<span
|
|
||||||
on:click={() => {
|
|
||||||
const newstate = !current_runners.some((r) => r.is_selected === true);
|
|
||||||
current_runners = current_runners.map((r) => {
|
|
||||||
r.is_selected = newstate;
|
|
||||||
return r;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
class="underline cursor-pointer select-none">{#if current_runners.some((r) => r.is_selected === true)}
|
|
||||||
{$_('deselect-all')}
|
|
||||||
{:else}{$_('select-all')}{/if}
|
|
||||||
</span>
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('name')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('contact-information')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('group')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('distance-in-km')}
|
|
||||||
</th>
|
|
||||||
<th scope="col" class="relative px-6 py-3">
|
|
||||||
<span class="sr-only">{$_('action')}</span>
|
|
||||||
</th>
|
</th>
|
||||||
|
{#each headerGroup.headers as header}
|
||||||
|
<TableHeader {header} />
|
||||||
|
{/each}
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
{/each}
|
||||||
<tbody class="divide-y divide-gray-200">
|
</thead>
|
||||||
{#each current_runners as runner}
|
<tbody>
|
||||||
{#if runner.firstname
|
{#each $table.getRowModel().rows as row}
|
||||||
.toLowerCase()
|
<tr>
|
||||||
.includes(
|
<td class="inset-y-0 left-0 px-4 py-2 text-center w-px">
|
||||||
searchvalue.toLowerCase()
|
<InputElement
|
||||||
) || runner.lastname
|
type="checkbox"
|
||||||
.toLowerCase()
|
checked={row.getIsSelected()}
|
||||||
.includes(
|
on:change={() => row.toggleSelected()}
|
||||||
searchvalue.toLowerCase()
|
/>
|
||||||
) || should_display_based_on_id(runner.id)}
|
</td>
|
||||||
{#if filterGroupIDs.includes(runner.group.id) || filterGroupIDs.includes(runner.group.parentGroup?.id) || filterGroupIDs.length === 0}
|
{#each row.getVisibleCells() as cell}
|
||||||
<tr
|
<td>
|
||||||
data-rowid="user_{runner.id}"
|
<svelte:component
|
||||||
data-groupid={runner.group.id}>
|
this={flexRender(
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
cell.column.columnDef.cell,
|
||||||
<input
|
cell.getContext()
|
||||||
bind:checked={runner.is_selected}
|
)}
|
||||||
type="checkbox"
|
/>
|
||||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" />
|
</td>
|
||||||
</td>
|
{/each}
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
</tr>
|
||||||
<div class="flex items-center">
|
{/each}
|
||||||
<div class="ml-4">
|
</tbody>
|
||||||
<div class="text-sm font-medium text-gray-900">
|
</table>
|
||||||
{runner.firstname}
|
|
||||||
{runner.middlename || ''}
|
|
||||||
{runner.lastname}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
{#if runner.email}
|
|
||||||
<div class="text-sm text-gray-500">{runner.email}</div>
|
|
||||||
{/if}
|
|
||||||
{#if runner.phone}
|
|
||||||
<div class="text-sm text-gray-500">{runner.phone}</div>
|
|
||||||
{/if}
|
|
||||||
{#if runner.address.address1 !== null}
|
|
||||||
{runner.address.address1}<br />
|
|
||||||
{runner.address.address2 || ''}<br />
|
|
||||||
{runner.address.postalcode}
|
|
||||||
{runner.address.city}
|
|
||||||
{runner.address.country}
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
{#if runner.group.responseType === 'RUNNERTEAM'}
|
|
||||||
<a
|
|
||||||
href="../teams/{runner.group.id}"
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{runner.group.parentGroup.name} > {runner.group.name}</a>
|
|
||||||
{/if}
|
|
||||||
{#if runner.group.responseType === 'RUNNERORGANIZATION'}
|
|
||||||
<a
|
|
||||||
href="../orgs/{runner.group.id}"
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{runner.group.name}</a>
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
{runner.distance}
|
|
||||||
</td>
|
|
||||||
{#if active_deletes[runner.id] === true}
|
|
||||||
<td
|
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[runner.id] = false;
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">{$_('cancel-delete')}</button>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
RunnerService.runnerControllerRemove(runner.id, true)
|
|
||||||
.then((resp) => {
|
|
||||||
current_runners = current_runners.filter((obj) => obj.id !== runner.id);
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('confirm-delete')}</button>
|
|
||||||
</td>
|
|
||||||
{:else}
|
|
||||||
<td
|
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
||||||
<a
|
|
||||||
href="./{runner.id}"
|
|
||||||
class="text-indigo-600 hover:text-indigo-900">{$_('details')}</a>
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('RUNNER:DELETE')}
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[runner.id] = true;
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
{/if}
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
{:catch error}
|
|
||||||
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
|
|
||||||
<span class="inline-block align-middle mr-8">
|
|
||||||
<b class="capitalize">{$_('general_promise_error')}</b>
|
|
||||||
{error}
|
|
||||||
</span>
|
|
||||||
</div>
|
</div>
|
||||||
{/await}
|
<div class="h-2" />
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
|
<TableBottom {table} {selected} />
|
||||||
@@ -0,0 +1,35 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
export let groups;
|
||||||
|
export let handler;
|
||||||
|
let selected = "all";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<th style="border-bottom: 1px solid #ddd;">
|
||||||
|
<select
|
||||||
|
on:input={() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (`${selected}`.trim()) {
|
||||||
|
const value = selected;
|
||||||
|
handler.filter(value, (runner) => {
|
||||||
|
if (
|
||||||
|
runner.group.id === value ||
|
||||||
|
runner?.group?.parentGroup?.id === value ||
|
||||||
|
value === "all"
|
||||||
|
)
|
||||||
|
return runner;
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 50);
|
||||||
|
}}
|
||||||
|
bind:value={selected}
|
||||||
|
name="groupfilter"
|
||||||
|
id="groupfilter"
|
||||||
|
>
|
||||||
|
<option value="all">{$_('all')}</option>
|
||||||
|
{#each groups as g}
|
||||||
|
<option value={g.value}>{g.label}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
</th>
|
||||||
@@ -1,23 +1,24 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import {
|
import {
|
||||||
RunnerService,
|
RunnerService,
|
||||||
ScanService,
|
ScanService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
import Select from "svelte-select";
|
import Select from "svelte-select";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
export let modal_open;
|
export let modal_open;
|
||||||
export let current_scans;
|
|
||||||
const getRunnerLabel = (option) =>
|
const getRunnerLabel = (option) =>
|
||||||
option.firstname + " " + (option.middlename || "") + " " + option.lastname;
|
option.firstname + " " + (option.middlename || "") + " " + option.lastname;
|
||||||
const filterRunners = (label, filterText, option) =>
|
const filterRunners = (label, filterText, option) =>
|
||||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
option.value.toString().startsWith(filterText.toLowerCase());
|
option.value.id.toString().startsWith(filterText.toLowerCase());
|
||||||
function focus(el) {
|
function focus(el) {
|
||||||
el.focus();
|
el.focus();
|
||||||
}
|
}
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
$: runner = 0;
|
$: runner = 0;
|
||||||
$: runners = [];
|
$: runners = [];
|
||||||
RunnerService.runnerControllerGetAll().then((val) => {
|
RunnerService.runnerControllerGetAll().then((val) => {
|
||||||
@@ -63,8 +64,7 @@
|
|||||||
duration: 500,
|
duration: 500,
|
||||||
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
current_scans.push(result);
|
dispatch("created", { scans: [result] });
|
||||||
current_scans = current_scans;
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
//
|
//
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={() => {
|
on:click_outside={() => {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
|
|||||||
@@ -0,0 +1,110 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import { clickOutside } from "../base/outsideclick";
|
||||||
|
import { createEventDispatcher, onMount } from "svelte";
|
||||||
|
export let modal_open;
|
||||||
|
export let delete_scan = {
|
||||||
|
id: 0,
|
||||||
|
runner: {
|
||||||
|
firstname: "",
|
||||||
|
lastname: "",
|
||||||
|
},
|
||||||
|
};
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
onMount(() => {
|
||||||
|
document.onkeydown = (e) => {
|
||||||
|
e = e || window.event;
|
||||||
|
if (e.key === "Escape") {
|
||||||
|
modal_open = false;
|
||||||
|
}
|
||||||
|
if (e.keyCode === 13) {
|
||||||
|
if (createbtnenabled === true) {
|
||||||
|
createbtnenabled = false;
|
||||||
|
submit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
});
|
||||||
|
async function submit() {
|
||||||
|
dispatch("delete", { id: delete_scan.id });
|
||||||
|
modal_open = false;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if modal_open}
|
||||||
|
<div
|
||||||
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
|
use:clickOutside
|
||||||
|
on:click_outside={() => {
|
||||||
|
modal_open = false;
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
||||||
|
>
|
||||||
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
|
data-id="modal_backdrop"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
|
aria-hidden="true">​</span
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby="modal-headline"
|
||||||
|
>
|
||||||
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
|
<div class="sm:flex sm:items-start">
|
||||||
|
<div
|
||||||
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
class="h-6 w-6 text-blue-600"
|
||||||
|
fill="currentColor"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
d="M9.83 8.79L8 9.456V13H6V8.05h.015l5.268-1.918c.244-.093.51-.14.782-.131a2.616 2.616 0 0 1 2.427 1.82c.186.583.356.977.51 1.182A4.992 4.992 0 0 0 19 11v2a6.986 6.986 0 0 1-5.402-2.547l-.581 3.297L15 15.67V23h-2v-5.986l-2.05-1.987-.947 4.298-6.894-1.215.348-1.97 4.924.868L9.83 8.79zM13.5 5.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
{$_("confirm-delete")}
|
||||||
|
</h3>
|
||||||
|
<div class="mt-2 mb-6">
|
||||||
|
{$_("please-confirm-the-deletion-of-scan")} #{delete_scan.id}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||||
|
<button
|
||||||
|
on:click={submit}
|
||||||
|
type="button"
|
||||||
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>
|
||||||
|
{$_("delete")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
modal_open = false;
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>
|
||||||
|
{$_("cancel")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,16 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
export let valid = false;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if valid}
|
||||||
|
<span
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"
|
||||||
|
>{$_("valid")}</span
|
||||||
|
>
|
||||||
|
{:else}
|
||||||
|
<span
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800"
|
||||||
|
>{$_("invalid")}</span
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
import ScansOverview from "./ScansOverview.svelte";
|
import ScansOverview from "./ScansOverview.svelte";
|
||||||
$: current_scans = [];
|
$: current_scans = [];
|
||||||
export let modal_open = false;
|
export let modal_open = false;
|
||||||
|
let addScans;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
@@ -21,9 +22,11 @@
|
|||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
<ScansOverview bind:current_scans />
|
<ScansOverview bind:current_scans bind:addScans />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('SCAN:CREATE')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes('SCAN:CREATE')}
|
||||||
<AddScanModal bind:current_scans bind:modal_open />
|
<AddScanModal bind:modal_open on:created={(event)=>{
|
||||||
|
addScans(event.detail.scans)
|
||||||
|
}} />
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1,197 +1,308 @@
|
|||||||
<script>
|
<script>
|
||||||
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import {
|
import { ScanService, TrackService } from "@odit/lfk-client-js";
|
||||||
ScanService,
|
|
||||||
} from "@odit/lfk-client-js";
|
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
|
import {
|
||||||
|
createSvelteTable,
|
||||||
|
flexRender,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
renderComponent,
|
||||||
|
} from "@tanstack/svelte-table";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import { writable } from "svelte/store";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
|
import TableBottom from "../shared/TableBottom.svelte";
|
||||||
|
import TableHeader from "../shared/TableHeader.svelte";
|
||||||
import ScansEmptyState from "./ScansEmptyState.svelte";
|
import ScansEmptyState from "./ScansEmptyState.svelte";
|
||||||
$: searchvalue = "";
|
import InputElement from "../shared/InputElement.svelte";
|
||||||
$: active_deletes = [];
|
import TableActions from "../shared/TableActions.svelte";
|
||||||
|
import { runnerFilter, statusFilter } from "../shared/tablefilters";
|
||||||
|
import CardRunner from "../cards/CardRunner.svelte";
|
||||||
|
import ScanValid from "./ScanValid.svelte";
|
||||||
|
import DeleteScanModal from "./DeleteScanModal.svelte";
|
||||||
|
|
||||||
|
$: selectedScans =
|
||||||
|
$table?.getSelectedRowModel().rows.map((row) => row.original) || [];
|
||||||
|
$: selected =
|
||||||
|
$table?.getSelectedRowModel().rows.map((row) => row.index) || [];
|
||||||
|
|
||||||
|
$: active_delete = undefined;
|
||||||
|
$: dataLoaded = false;
|
||||||
export let current_scans = [];
|
export let current_scans = [];
|
||||||
const scans_promise = ScanService.scanControllerGetAll().then((val) => {
|
export const addScans = (scans) => {
|
||||||
current_scans = val;
|
current_scans = current_scans.concat(...scans);
|
||||||
|
options.update((options) => ({
|
||||||
|
...options,
|
||||||
|
data: current_scans,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
let allTracks = [];
|
||||||
|
TrackService.trackControllerGetAll().then((val) => {
|
||||||
|
allTracks = val;
|
||||||
});
|
});
|
||||||
function should_display_based_on_id(id) {
|
function format_laptime(laptime) {
|
||||||
if (searchvalue.toString().slice(-1) === "*") {
|
if (laptime == 0 || laptime == null) {
|
||||||
return id.toString().startsWith(searchvalue.replace("*", ""));
|
return $_("first-scan-of-the-day");
|
||||||
}
|
}
|
||||||
return id.toString() === searchvalue;
|
if (laptime < 60) {
|
||||||
|
return `${laptime}s`;
|
||||||
|
}
|
||||||
|
if (laptime < 3600) {
|
||||||
|
return `${Math.floor(laptime / 60)}min ${
|
||||||
|
laptime - Math.floor(laptime / 60) * 60
|
||||||
|
}s`;
|
||||||
|
}
|
||||||
|
return `${Math.floor(laptime / 3600)}h ${
|
||||||
|
laptime - Math.floor(laptime / 3600) * 3600
|
||||||
|
}min ${
|
||||||
|
laptime -
|
||||||
|
Math.floor(laptime / 3600) * 3600 -
|
||||||
|
Math.floor(laptime / 60) * 60
|
||||||
|
}`;
|
||||||
}
|
}
|
||||||
function format_laptime(laptime){
|
|
||||||
if(laptime == 0 || laptime == null){return $_('first-scan-of-the-day')}
|
const columns = [
|
||||||
if(laptime < 60){return `${laptime}s`}
|
{
|
||||||
if(laptime < 3600){return `${Math.floor(laptime / 60)}min ${laptime - (Math.floor(laptime / 60)*60)}s`}
|
accessorKey: "id",
|
||||||
return `${Math.floor(laptime / 3600)}h ${laptime - (Math.floor(laptime / 3600)*3600)}min ${laptime - (Math.floor(laptime / 3600)*3600) - (Math.floor(laptime / 60)*60)}`
|
header: () => "id",
|
||||||
|
filterFn: `equalsString`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "runner",
|
||||||
|
header: () => $_("runner"),
|
||||||
|
cell: (info) => {
|
||||||
|
return renderComponent(CardRunner, { runner: info.getValue() });
|
||||||
|
},
|
||||||
|
filterFn: `runner`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "lapTime",
|
||||||
|
header: () => $_("laptime"),
|
||||||
|
cell: (info) => {
|
||||||
|
return format_laptime(info.getValue());
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "timestamp",
|
||||||
|
header: () => $_("timestamp"),
|
||||||
|
cell: (info) => {
|
||||||
|
return new Date(parseInt(info.getValue()) * 1000).toLocaleString();
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "distance",
|
||||||
|
header: () => $_("distance"),
|
||||||
|
cell: (info) => {
|
||||||
|
if (info.getValue() < 1000) {
|
||||||
|
return `${info.getValue()}m`;
|
||||||
|
}
|
||||||
|
return `${(info.getValue() / 1000).toFixed(1)}km`;
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "track",
|
||||||
|
header: () => $_("track"),
|
||||||
|
cell: (info) => {
|
||||||
|
const track = info.getValue();
|
||||||
|
return track?.name || "?";
|
||||||
|
},
|
||||||
|
enableColumnFilter: true,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "valid",
|
||||||
|
cell: (info) => {
|
||||||
|
return renderComponent(ScanValid, { valid: info.getValue() });
|
||||||
|
},
|
||||||
|
header: () => $_("status"),
|
||||||
|
filterFn: `status`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "actions",
|
||||||
|
header: () => $_("action"),
|
||||||
|
cell: (info) => {
|
||||||
|
return renderComponent(TableActions, {
|
||||||
|
detailsLink: `./${info.row.original.id}`,
|
||||||
|
deleteAction: () => {
|
||||||
|
active_delete =
|
||||||
|
current_scans[
|
||||||
|
current_scans.findIndex((r) => r.id == info.row.original.id)
|
||||||
|
];
|
||||||
|
},
|
||||||
|
deleteEnabled:
|
||||||
|
store.state.jwtinfo.userdetails.permissions.includes("SCAN:DELETE"),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
enableSorting: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const options = writable({
|
||||||
|
data: [],
|
||||||
|
columns: columns,
|
||||||
|
initialState: {
|
||||||
|
pagination: {
|
||||||
|
pageSize: 50,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
filterFns: {
|
||||||
|
runner: runnerFilter,
|
||||||
|
status: statusFilter,
|
||||||
|
},
|
||||||
|
enableRowSelection: true,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
});
|
||||||
|
const table = createSvelteTable(options);
|
||||||
|
async function deleteScan(scan_id) {
|
||||||
|
await ScanService.scanControllerRemove(scan_id, true);
|
||||||
|
current_scans = current_scans.filter((r) => r.id !== scan_id);
|
||||||
|
options.update((options) => ({
|
||||||
|
...options,
|
||||||
|
data: current_scans,
|
||||||
|
}));
|
||||||
|
Toastify({
|
||||||
|
text: $_("scan-deleted"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
let page = 0;
|
||||||
|
while (page >= 0) {
|
||||||
|
const scans = await ScanService.scanControllerGetAll(page, 500);
|
||||||
|
if (scans.length == 0) {
|
||||||
|
page = -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_scans = current_scans.concat(...scans);
|
||||||
|
options.update((options) => ({
|
||||||
|
...options,
|
||||||
|
data: current_scans,
|
||||||
|
}));
|
||||||
|
|
||||||
|
dataLoaded = true;
|
||||||
|
page++;
|
||||||
|
}
|
||||||
|
console.log("All scans loaded");
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('SCAN:GET')}
|
<DeleteScanModal
|
||||||
{#await scans_promise}
|
delete_scan={active_delete}
|
||||||
|
modal_open={active_delete != undefined}
|
||||||
|
on:delete={(event) => {
|
||||||
|
deleteScan(event.detail.id);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:GET")}
|
||||||
|
{#if !dataLoaded}
|
||||||
<div
|
<div
|
||||||
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
||||||
role="alert">
|
role="alert"
|
||||||
<p class="font-bold">{$_('scans-are-being-loaded')}</p>
|
>
|
||||||
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
<p class="font-bold">{$_("scans-are-being-loaded")}</p>
|
||||||
|
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
||||||
</div>
|
</div>
|
||||||
{:then}
|
{:else if current_scans.length === 0}
|
||||||
{#if current_scans.length === 0}
|
<ScansEmptyState />
|
||||||
<ScansEmptyState />
|
{:else}
|
||||||
{:else}
|
{#if selected.length > 0}
|
||||||
<input
|
<button
|
||||||
type="search"
|
type="button"
|
||||||
bind:value={searchvalue}
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm inline-flex"
|
||||||
placeholder={$_('datatable.search')}
|
id="options-menu"
|
||||||
aria-label={$_('datatable.search')}
|
on:click={async () => {
|
||||||
class="gridjs-input gridjs-search-input mb-4" />
|
const prom = [];
|
||||||
<div
|
for (const scan of selectedScans) {
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
prom.push(ScanService.scanControllerRemove(scan.id, true));
|
||||||
<table class="divide-y divide-gray-200 w-full">
|
}
|
||||||
<thead class="bg-gray-50">
|
await Promise.all(prom);
|
||||||
<tr>
|
for (const scan of selectedScans) {
|
||||||
<th
|
current_scans = current_scans.filter((r) => r.id !== scan.id);
|
||||||
scope="col"
|
}
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
options.update((options) => ({
|
||||||
{$_('runner')}
|
...options,
|
||||||
</th>
|
data: current_scans,
|
||||||
<th
|
}));
|
||||||
scope="col"
|
$table.resetRowSelection();
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
Toastify({
|
||||||
{$_('distance-track')}
|
text: $_("scan-deleted"),
|
||||||
</th>
|
duration: 3500,
|
||||||
<th
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
scope="col"
|
}).showToast();
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
}}
|
||||||
{$_('laptime')}
|
>
|
||||||
</th>
|
{$_("delete-scans")}
|
||||||
<th
|
<svg
|
||||||
scope="col"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
fill="none"
|
||||||
{$_('status')}
|
viewBox="0 0 24 24"
|
||||||
</th>
|
stroke-width="1.5"
|
||||||
<th scope="col" class="relative px-6 py-3">
|
stroke="currentColor"
|
||||||
<span class="sr-only">{$_('action')}</span>
|
class="w-5 h-5"
|
||||||
</th>
|
>
|
||||||
</tr>
|
<path
|
||||||
</thead>
|
stroke-linecap="round"
|
||||||
<tbody class="divide-y divide-gray-200">
|
stroke-linejoin="round"
|
||||||
{#each current_scans as scan}
|
d="M14.74 9l-.346 9m-4.788 0L9.26 9m9.968-3.21c.342.052.682.107 1.022.166m-1.022-.165L18.16 19.673a2.25 2.25 0 01-2.244 2.077H8.084a2.25 2.25 0 01-2.244-2.077L4.772 5.79m14.456 0a48.108 48.108 0 00-3.478-.397m-12 .562c.34-.059.68-.114 1.022-.165m0 0a48.11 48.11 0 013.478-.397m7.5 0v-.916c0-1.18-.91-2.164-2.09-2.201a51.964 51.964 0 00-3.32 0c-1.18.037-2.09 1.022-2.09 2.201v.916m7.5 0a48.667 48.667 0 00-7.5 0"
|
||||||
{#if scan.track?.name
|
/>
|
||||||
.toLowerCase()
|
</svg>
|
||||||
.includes(
|
</button>
|
||||||
searchvalue.toLowerCase()
|
|
||||||
) || scan.runner?.firstname
|
|
||||||
.toLowerCase()
|
|
||||||
.includes(
|
|
||||||
searchvalue.toLowerCase()
|
|
||||||
) || scan.runner?.lastname
|
|
||||||
.toLowerCase()
|
|
||||||
.includes(
|
|
||||||
searchvalue.toLowerCase()
|
|
||||||
) || should_display_based_on_id(scan.id)}
|
|
||||||
<tr data-rowid="scan_{scan.id}">
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<div class="flex items-center">
|
|
||||||
<a
|
|
||||||
href="../runners/{scan.runner.id}"
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{scan.runner.firstname}
|
|
||||||
{scan.runner.middlename || ''}
|
|
||||||
{scan.runner.lastname}</a>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<div class="text-sm font-medium text-gray-900">
|
|
||||||
{#if scan.distance < 1000}
|
|
||||||
{scan.distance}m
|
|
||||||
{:else}{scan.distance / 1000}km{/if}
|
|
||||||
{#if scan.track}
|
|
||||||
<a
|
|
||||||
href="../tracks"
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{scan.track.name}
|
|
||||||
</a>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
{#if scan.responseType === "TRACKSCAN"}
|
|
||||||
<div class="text-sm font-medium text-gray-900">
|
|
||||||
{format_laptime(scan.lapTime)}
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<div class="text-sm font-medium text-gray-900">
|
|
||||||
{$_('scan-with-fixed-distance')}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<div class="flex items-center">
|
|
||||||
{#if scan.valid}
|
|
||||||
<span
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">{$_('valid')}</span>
|
|
||||||
{:else}
|
|
||||||
<span
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">{$_('invalid')}</span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
|
|
||||||
{#if active_deletes[scan.id] === true}
|
|
||||||
<td
|
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[scan.id] = false;
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">{$_('cancel-delete')}</button>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
ScanService.scanControllerRemove(scan.id, false).then(
|
|
||||||
(resp) => {
|
|
||||||
current_scans = current_scans.filter(
|
|
||||||
(obj) => obj.id !== scan.id
|
|
||||||
);
|
|
||||||
Toastify({
|
|
||||||
text: 'Scan deleted',
|
|
||||||
duration: 500,
|
|
||||||
backgroundColor:
|
|
||||||
'linear-gradient(to right, #00b09b, #96c93d)',
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
);
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('confirm-delete')}</button>
|
|
||||||
</td>
|
|
||||||
{:else}
|
|
||||||
<td
|
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
||||||
<a
|
|
||||||
href="./{scan.id}"
|
|
||||||
class="text-indigo-600 hover:text-indigo-900">{$_('details')}</a>
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('SCAN:DELETE')}
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[scan.id] = true;
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
{/if}
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
{/if}
|
{/if}
|
||||||
{:catch error}
|
<div class="overflow-x-auto">
|
||||||
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
|
<table class="w-full">
|
||||||
<span class="inline-block align-middle mr-8">
|
<thead>
|
||||||
<b class="capitalize">{$_('general_promise_error')}</b>
|
{#each $table.getHeaderGroups() as headerGroup}
|
||||||
{error}
|
<tr class="select-none">
|
||||||
</span>
|
<th class="inset-y-0 left-0 px-4 py-2 text-left w-px">
|
||||||
|
<InputElement
|
||||||
|
type="checkbox"
|
||||||
|
checked={$table.getIsAllRowsSelected()}
|
||||||
|
indeterminate={$table.getIsSomeRowsSelected()}
|
||||||
|
on:change={() => $table.toggleAllRowsSelected()}
|
||||||
|
/>
|
||||||
|
</th>
|
||||||
|
{#each headerGroup.headers as header}
|
||||||
|
<TableHeader {header} />
|
||||||
|
{/each}
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#each $table.getRowModel().rows as row}
|
||||||
|
<tr>
|
||||||
|
<td class="inset-y-0 left-0 px-4 py-2 text-center w-px">
|
||||||
|
<InputElement
|
||||||
|
type="checkbox"
|
||||||
|
checked={row.getIsSelected()}
|
||||||
|
on:change={() => row.toggleSelected()}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
{#each row.getVisibleCells() as cell}
|
||||||
|
<td>
|
||||||
|
<svelte:component
|
||||||
|
this={flexRender(
|
||||||
|
cell.column.columnDef.cell,
|
||||||
|
cell.getContext()
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
{/each}
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{/await}
|
<TableBottom {table} {selected} />
|
||||||
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
@@ -0,0 +1,50 @@
|
|||||||
|
<script>
|
||||||
|
export let handler;
|
||||||
|
let filterValue = "";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<th>
|
||||||
|
<input
|
||||||
|
on:input={() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
const v = filterValue.toLowerCase();
|
||||||
|
handler.filter(v, (c) => {
|
||||||
|
if (v.startsWith("#")) {
|
||||||
|
return `#${c.runner?.id}`;
|
||||||
|
}
|
||||||
|
if (c.runner) {
|
||||||
|
let runnerName = `${c.runner.firstname} ${c.runner.lastname}`;
|
||||||
|
if (c.runner.middlename) {
|
||||||
|
runnerName = `${c.runner.firstname} ${c.runner.middlename} ${c.runner.lastname}`;
|
||||||
|
}
|
||||||
|
runnerName = runnerName.toLowerCase();
|
||||||
|
return runnerName;
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
}, 150);
|
||||||
|
}}
|
||||||
|
placeholder="Filter"
|
||||||
|
bind:value={filterValue}
|
||||||
|
type="text"
|
||||||
|
name="runnerfilter"
|
||||||
|
id="runnerfilter"
|
||||||
|
/>
|
||||||
|
</th>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
th {
|
||||||
|
border-bottom: 1px solid #e0e0e0;
|
||||||
|
}
|
||||||
|
input {
|
||||||
|
margin: -1px 0 0 0;
|
||||||
|
padding: 0;
|
||||||
|
width: 100%;
|
||||||
|
height: 24px;
|
||||||
|
border: none;
|
||||||
|
text-align: left;
|
||||||
|
background: inherit;
|
||||||
|
outline: 0;
|
||||||
|
font-size: 14px;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,31 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
export let tracks;
|
||||||
|
export let handler;
|
||||||
|
let selected = "all";
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<th style="border-bottom: 1px solid #ddd;">
|
||||||
|
<select
|
||||||
|
on:input={() => {
|
||||||
|
setTimeout(() => {
|
||||||
|
if (`${selected}`.trim()) {
|
||||||
|
const value = selected;
|
||||||
|
handler.filter(value, (scan) => {
|
||||||
|
// TODO: fix filter
|
||||||
|
if (scan.track.id === value || value === "all") return scan.track.id;
|
||||||
|
return "";
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}, 50);
|
||||||
|
}}
|
||||||
|
bind:value={selected}
|
||||||
|
name="trackfilter"
|
||||||
|
id="trackfilter"
|
||||||
|
>
|
||||||
|
<option value="all">{$_("all")}</option>
|
||||||
|
{#each tracks as track}
|
||||||
|
<option value={track.id}>{track.name}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
</th>
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import { ScanStationService, TrackService } from "@odit/lfk-client-js";
|
import { ScanStationService, TrackService } from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
import Select from "svelte-select";
|
import Select from "svelte-select";
|
||||||
@@ -81,7 +81,7 @@
|
|||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={() => {
|
on:click_outside={() => {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import { ScanStationService } from "@odit/lfk-client-js";
|
import { ScanStationService } from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
dispatch("cancelDelete", { id: delete_station.id });
|
dispatch("cancelDelete", { id: delete_station.id });
|
||||||
}
|
}
|
||||||
function deleteStation() {
|
function deleteStation() {
|
||||||
ScanStationService.donorControllerRemove(
|
ScanStationService.scanStationControllerRemove(
|
||||||
delete_station.id,
|
delete_station.id,
|
||||||
true
|
true
|
||||||
)
|
)
|
||||||
@@ -32,7 +32,7 @@
|
|||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={cancelDelete}>
|
on:click_outside={cancelDelete}>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -1,14 +1,18 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
import { tick, createEventDispatcher } from "svelte";
|
import { tick, createEventDispatcher } from "svelte";
|
||||||
|
import bwipjs from "bwip-js";
|
||||||
|
|
||||||
export let copy_modal_open;
|
export let copy_modal_open;
|
||||||
export let new_station;
|
export let new_station;
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
let valueCopy = null;
|
let valueCopy = null;
|
||||||
let areaDom;
|
let areaDom;
|
||||||
let copied = false;
|
let copied = false;
|
||||||
|
$: is_qrcode = false;
|
||||||
|
$: barcode = textToBase64Barcode(new_station.key, is_qrcode);
|
||||||
|
|
||||||
function close() {
|
function close() {
|
||||||
copy_modal_open = false;
|
copy_modal_open = false;
|
||||||
}
|
}
|
||||||
@@ -36,91 +40,167 @@
|
|||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
}
|
}
|
||||||
|
|
||||||
// we can notifi by event or storage about copy status
|
// we can notifi by event or storage about copy status
|
||||||
valueCopy = null;
|
valueCopy = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function textToBase64Barcode(text, is_qrcode) {
|
||||||
|
const canvas = document.createElement("canvas");
|
||||||
|
let bcid = "code128";
|
||||||
|
if (is_qrcode) {
|
||||||
|
bcid = "qrcode";
|
||||||
|
}
|
||||||
|
let codeconfig = {
|
||||||
|
bcid,
|
||||||
|
text: `${text}`,
|
||||||
|
scale: 4,
|
||||||
|
includetext: true,
|
||||||
|
textxalign: "center",
|
||||||
|
backgroundcolor: "ffffff",
|
||||||
|
};
|
||||||
|
if (bcid == "code128") {
|
||||||
|
codeconfig.height = 10;
|
||||||
|
}
|
||||||
|
bwipjs.toCanvas(canvas, codeconfig);
|
||||||
|
return canvas.toDataURL("image/png");
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if copy_modal_open}
|
{#if copy_modal_open}
|
||||||
{#if valueCopy != null}
|
{#if valueCopy != null}
|
||||||
<textarea bind:this={areaDom}>{valueCopy}</textarea>
|
<textarea bind:this={areaDom}>{valueCopy}</textarea>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="fixed z-10 inset-0 overflow-y-auto" use:focusTrap>
|
<div class="fixed z-10 inset-0 overflow-y-auto">
|
||||||
<div
|
<div
|
||||||
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
||||||
|
>
|
||||||
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
<div
|
<div
|
||||||
class="absolute inset-0 bg-gray-500 opacity-75"
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
data-id="modal_backdrop" />
|
data-id="modal_backdrop"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
aria-hidden="true">​</span>
|
aria-hidden="true">​</span
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
aria-labelledby="modal-headline">
|
aria-labelledby="modal-headline"
|
||||||
|
>
|
||||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
<div class="sm:flex sm:items-start">
|
<div class="sm:flex sm:items-start">
|
||||||
<div
|
<div
|
||||||
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
||||||
|
>
|
||||||
<svg
|
<svg
|
||||||
class="h-6 w-6 text-blue-600"
|
class="h-6 w-6 text-blue-600"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z" />
|
viewBox="0 0 24 24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path
|
<path
|
||||||
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z" /></svg>
|
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
{$_('token')}
|
{$_("token")}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="mt-2 mb-6">
|
<div class="mt-2 mb-6">
|
||||||
<p class="text-sm text-gray-500">
|
<p class="text-sm text-gray-500">
|
||||||
{$_('the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again')}
|
{$_(
|
||||||
|
"the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again"
|
||||||
|
)}
|
||||||
<br />
|
<br />
|
||||||
{$_('please-copy-the-token-and-store-it-somewhere-save')}
|
{$_("please-copy-the-token-and-store-it-somewhere-save")}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2 mb-6">
|
<div class="mt-2 mb-6">
|
||||||
<label
|
<label
|
||||||
for="token"
|
for="token"
|
||||||
class="block text-sm font-medium text-gray-700">{$_('token')}</label>
|
class="block text-sm font-medium text-gray-700"
|
||||||
<div on:click={copy} class="inline-flex">
|
>{$_("token")}</label
|
||||||
|
>
|
||||||
|
<button on:click={copy} class="inline-flex">
|
||||||
<p
|
<p
|
||||||
name="token"
|
name="token"
|
||||||
class:bg-green-200={copied}
|
class:bg-green-200={copied}
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2">
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
|
||||||
|
>
|
||||||
{new_station.key}
|
{new_station.key}
|
||||||
</p>
|
</p>
|
||||||
<div
|
<div
|
||||||
class="bg-gray-200 border-gray-300 border-t border-b border-r text-black rounded-r-md sm:text-sm p-2 mt-1 cursor-pointer">
|
class="bg-gray-200 border-gray-300 border-t border-b border-r text-black rounded-r-md sm:text-sm p-2 mt-1 cursor-pointer"
|
||||||
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
height="24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
d="M7 4V2h10v2h3l1 1v16a1 1 0 01-1 1H4a1 1 0 01-1-1V5l1-1h3zm0 2H5v14h14V6h-2v2H7V6zm2-2v2h6V4H9z" /></svg>
|
d="M7 4V2h10v2h3l1 1v16a1 1 0 01-1 1H4a1 1 0 01-1-1V5l1-1h3zm0 2H5v14h14V6h-2v2H7V6zm2-2v2h6V4H9z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</button>
|
||||||
<p class="text-gray-500 text-xs">
|
<p class="text-gray-500 text-xs">
|
||||||
{$_('click-to-copy-token-to-clipboard')}
|
{$_("click-to-copy-token-to-clipboard")}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
<div class="mx-auto text-center items-center">
|
||||||
|
<h2 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
{$_("config-codes")}
|
||||||
|
</h2>
|
||||||
|
<span class="flex items-center text-center">
|
||||||
|
<p class="text-md text-gray-900 mr-3">Format:</p>
|
||||||
|
<label for="codeswitch" class="text-md text-gray-900 mr-3"
|
||||||
|
>Code128</label
|
||||||
|
>
|
||||||
|
<input
|
||||||
|
id="codeswitch"
|
||||||
|
type="checkbox"
|
||||||
|
bind:checked={is_qrcode}
|
||||||
|
class="relative shrink-0 w-[3.25rem] h-7 bg-gray-100 checked:bg-none checked:bg-blue-600 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 border border-transparent ring-1 ring-transparent focus:border-blue-600 focus:ring-blue-600 ring-offset-white focus:outline-none appearance-none before:inline-block before:w-6 before:h-6 before:bg-white checked:before:bg-blue-200 before:translate-x-0 checked:before:translate-x-full before:shadow before:rounded-full before:transform before:ring-0 before:transition before:ease-in-out before:duration-200 dark:before:bg-gray-400 dark:checked:before:bg-blue-200"
|
||||||
|
/>
|
||||||
|
<label for="codeswitch" class="text-md text-gray-900 ml-3"
|
||||||
|
>QR-Code</label
|
||||||
|
>
|
||||||
|
</span>
|
||||||
|
<h3 class="leading-6 font-medium text-gray-900">
|
||||||
|
{$_("api-endpoint")}
|
||||||
|
</h3>
|
||||||
|
<img
|
||||||
|
class:w-[50%]={is_qrcode}
|
||||||
|
class:w-full={!is_qrcode}
|
||||||
|
class="md:w-auto mb-2 mx-auto"
|
||||||
|
alt="Registrierungscode"
|
||||||
|
src={textToBase64Barcode(config.baseurl, is_qrcode)}
|
||||||
|
/>
|
||||||
|
<h3 class="leading-6 font-medium text-gray-900">{$_("token")}</h3>
|
||||||
|
<img
|
||||||
|
class:w-[50%]={is_qrcode}
|
||||||
|
class:w-full={!is_qrcode}
|
||||||
|
class="md:w-auto mb-2 mx-auto"
|
||||||
|
alt="Registrierungscode"
|
||||||
|
src={barcode}
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||||
<button
|
<button
|
||||||
on:click={close}
|
on:click={close}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-green-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-green-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
{$_('yes-i-copied-the-token')}
|
>
|
||||||
|
{$_("yes-i-copied-the-token")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -41,7 +41,7 @@
|
|||||||
bind:value={searchvalue}
|
bind:value={searchvalue}
|
||||||
placeholder={$_('datatable.search')}
|
placeholder={$_('datatable.search')}
|
||||||
aria-label={$_('datatable.search')}
|
aria-label={$_('datatable.search')}
|
||||||
class="gridjs-input gridjs-search-input mb-4" />
|
class="mb-4" />
|
||||||
<div
|
<div
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
||||||
<table class="divide-y divide-gray-200 w-full">
|
<table class="divide-y divide-gray-200 w-full">
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import { MeService } from "@odit/lfk-client-js";
|
import { MeService } from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
@@ -30,7 +30,7 @@
|
|||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={cancelDelete}>
|
on:click_outside={cancelDelete}>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -0,0 +1,20 @@
|
|||||||
|
<script>
|
||||||
|
let className = "";
|
||||||
|
export { className as class };
|
||||||
|
|
||||||
|
export let type;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<input
|
||||||
|
class={`border-1 border-stone-300 border rounded-md shadow ${className} ${
|
||||||
|
type === "checkbox" && "w-5 h-5 text-orange-400"
|
||||||
|
}`}
|
||||||
|
{type}
|
||||||
|
{...$$restProps}
|
||||||
|
on:click
|
||||||
|
on:change
|
||||||
|
on:keydown
|
||||||
|
on:keyup
|
||||||
|
on:mouseenter
|
||||||
|
on:mouseleave
|
||||||
|
/>
|
||||||
@@ -0,0 +1,26 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
|
||||||
|
export let detailsLink;
|
||||||
|
export let detailsAction;
|
||||||
|
export let deleteEnabled;
|
||||||
|
export let deleteAction;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if detailsLink}
|
||||||
|
<a href={detailsLink} class="text-indigo-600 hover:text-indigo-900"
|
||||||
|
>{$_("details")}</a
|
||||||
|
>
|
||||||
|
{:else if detailsAction}
|
||||||
|
<button on:click={detailsAction} class="text-indigo-600 hover:text-indigo-900"
|
||||||
|
>{$_("details")}</button
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
|
{#if deleteEnabled}
|
||||||
|
<button
|
||||||
|
tabindex="0"
|
||||||
|
on:click={deleteAction}
|
||||||
|
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
|
||||||
|
>{$_("delete")}</button
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,71 @@
|
|||||||
|
<script>
|
||||||
|
export let table;
|
||||||
|
export let selected;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="flex items-center gap-2">
|
||||||
|
<button
|
||||||
|
class="border rounded p-1"
|
||||||
|
on:click={() => $table.setPageIndex(0)}
|
||||||
|
disabled={!$table.getCanPreviousPage()}
|
||||||
|
>
|
||||||
|
{"<<"}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="border rounded p-1"
|
||||||
|
on:click={() => $table.previousPage()}
|
||||||
|
disabled={!$table.getCanPreviousPage()}
|
||||||
|
>
|
||||||
|
{"<"}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="border rounded p-1"
|
||||||
|
on:click={() => $table.nextPage()}
|
||||||
|
disabled={!$table.getCanNextPage()}
|
||||||
|
>
|
||||||
|
{">"}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
class="border rounded p-1"
|
||||||
|
on:click={() => $table.setPageIndex($table.getPageCount() - 1)}
|
||||||
|
disabled={!$table.getCanNextPage()}
|
||||||
|
>
|
||||||
|
{">>"}
|
||||||
|
</button>
|
||||||
|
<span class="flex items-center gap-1">
|
||||||
|
<div>Page</div>
|
||||||
|
<strong>
|
||||||
|
{$table.getState().pagination.pageIndex + 1} of{" "}
|
||||||
|
{$table.getPageCount()}
|
||||||
|
</strong>
|
||||||
|
</span>
|
||||||
|
<span class="flex items-center gap-1">
|
||||||
|
| Go to page:
|
||||||
|
<input
|
||||||
|
type="number"
|
||||||
|
defaultValue={$table.getState().pagination.pageIndex + 1}
|
||||||
|
on:change={(e) => {
|
||||||
|
const page = e.target.value ? Number(e.target.value) - 1 : 0;
|
||||||
|
$table.setPageIndex(page);
|
||||||
|
}}
|
||||||
|
class="border p-1 rounded w-16"
|
||||||
|
/>
|
||||||
|
</span>
|
||||||
|
<select
|
||||||
|
value={$table.getState().pagination.pageSize}
|
||||||
|
on:input={(e) => {
|
||||||
|
const ps = Number(e.target.value);
|
||||||
|
console.log({ ps });
|
||||||
|
$table.setPageSize(Number(e.target.value));
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{#each [25, 50, 100, 250, 500] as pageSize}
|
||||||
|
<option value={pageSize}>{pageSize}</option>
|
||||||
|
{/each}
|
||||||
|
</select>
|
||||||
|
</div>
|
||||||
|
<!-- <pre>{JSON.stringify($table.getState(), null, 2)}</pre> -->
|
||||||
|
<div>
|
||||||
|
{Object.keys(selected).length} of{" "}
|
||||||
|
{$table.getPreFilteredRowModel().rows.length} Total Rows Selected
|
||||||
|
</div>
|
||||||
@@ -0,0 +1,57 @@
|
|||||||
|
<script>
|
||||||
|
import { flexRender } from "@tanstack/svelte-table";
|
||||||
|
export let header;
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<th class="cursor-pointer min-w-[5rem]">
|
||||||
|
{#if !header.isPlaceholder}
|
||||||
|
<button
|
||||||
|
class="w-full"
|
||||||
|
tabindex="0"
|
||||||
|
on:click={header.column.getToggleSortingHandler()}
|
||||||
|
>
|
||||||
|
<svelte:component
|
||||||
|
this={flexRender(header.column.columnDef.header, header.getContext())}
|
||||||
|
/>
|
||||||
|
{#if header.column
|
||||||
|
.getIsSorted()
|
||||||
|
.toString() == "asc" && header.column.getCanSort()}
|
||||||
|
🔼
|
||||||
|
{:else if header.column
|
||||||
|
.getIsSorted()
|
||||||
|
.toString() == "desc" && header.column.getCanSort()}
|
||||||
|
🔽
|
||||||
|
{/if}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
{#if header.column.getCanFilter()}
|
||||||
|
<div class="relative max-w-xs">
|
||||||
|
<input
|
||||||
|
title="name-search"
|
||||||
|
value={header.column.getFilterValue() || ""}
|
||||||
|
on:keyup={(e) => {
|
||||||
|
header.column.setFilterValue(e.target.value);
|
||||||
|
}}
|
||||||
|
type="text"
|
||||||
|
class="block w-full rounded-md border-gray-200 py-2 pl-8 text-xs focus:border-blue-500 focus:ring-blue-500"
|
||||||
|
placeholder=""
|
||||||
|
/>
|
||||||
|
<div
|
||||||
|
class="pointer-events-none absolute inset-y-0 left-0 flex items-center pl-2"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="h-3.5 w-3.5 text-gray-400"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width={16}
|
||||||
|
height={16}
|
||||||
|
fill="currentColor"
|
||||||
|
viewBox="0 0 16 16"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001c.03.04.062.078.098.115l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85a1.007 1.007 0 0 0-.115-.1zM12 6.5a5.5 5.5 0 1 1-11 0 5.5 5.5 0 0 1 11 0z"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</th>
|
||||||
@@ -0,0 +1,65 @@
|
|||||||
|
export const groupFilter = (row, columnId, value) => {
|
||||||
|
const group = row.getValue(columnId);
|
||||||
|
if (group.responseType === "RUNNERORGANIZATION") {
|
||||||
|
return group.name.toLowerCase().includes(value.toLowerCase());
|
||||||
|
} else if (value.includes(">")) {
|
||||||
|
return (
|
||||||
|
`${group.parentGroup.name} > ${group.name}`.toLowerCase().includes(value.toLowerCase())
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
group.name.toLowerCase().includes(value.toLowerCase()) ||
|
||||||
|
group.parentGroup.name.toLowerCase().includes(value.toLowerCase())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
export const runnerFilter = (row, columnId, value) => {
|
||||||
|
const runner = row.getValue(columnId);
|
||||||
|
return filterRunner(runner, value)
|
||||||
|
};
|
||||||
|
|
||||||
|
export const donationRunnerFilter = (row, columnId, value) => {
|
||||||
|
const runner = row.getValue(columnId);
|
||||||
|
if (!runner) { return false; }
|
||||||
|
return filterRunner(runner, value)
|
||||||
|
};
|
||||||
|
|
||||||
|
export const donationDonorFilter = (row, columnId, value) => {
|
||||||
|
const runner = row.getValue(columnId);
|
||||||
|
return filterRunner(runner, value)
|
||||||
|
};
|
||||||
|
|
||||||
|
function filterRunner(runner, value) {
|
||||||
|
if (!runner && value == "blanko") { return true }
|
||||||
|
if (!runner) { return false }
|
||||||
|
|
||||||
|
if (value.startsWith("#")) {
|
||||||
|
return runner.id == value.replace("#", "")
|
||||||
|
}
|
||||||
|
|
||||||
|
if (runner.middlename) {
|
||||||
|
return `${runner.firstname} ${runner.middlename} ${runner.lastname}`.toLowerCase().includes(value.toLowerCase())
|
||||||
|
}
|
||||||
|
return `${runner.firstname} ${runner.lastname}`.toLowerCase().includes(value.toLowerCase())
|
||||||
|
}
|
||||||
|
|
||||||
|
export const filterName = (row, columnId, value) => {
|
||||||
|
const obj = row.original;
|
||||||
|
if (obj.middlename) {
|
||||||
|
return `${obj.firstname} ${obj.middlename} ${obj.lastname}`.toLowerCase().includes(value.toLowerCase())
|
||||||
|
}
|
||||||
|
return `${obj.firstname} ${obj.lastname}`.toLowerCase().includes(value.toLowerCase())
|
||||||
|
};
|
||||||
|
|
||||||
|
export const filterAddress = (row, columnId, value) => {
|
||||||
|
const obj = row.original.address;
|
||||||
|
if (obj.address2) {s
|
||||||
|
return `${obj.address1} ${obj.address2} ${obj.postalcode} ${obj.city} ${obj.country}`.toLowerCase().includes(value.toLowerCase())
|
||||||
|
}
|
||||||
|
return `${obj.address1} ${obj.postalcode} ${obj.city} ${obj.country}`.toLowerCase().includes(value.toLowerCase())
|
||||||
|
};
|
||||||
|
|
||||||
|
export const statusFilter = (row, columnId, value) => {
|
||||||
|
const status = row.getValue(columnId);
|
||||||
|
return status.toString().includes(value);
|
||||||
|
};
|
||||||
@@ -0,0 +1,151 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import { clickOutside } from "../base/outsideclick";
|
||||||
|
|
||||||
|
import { StatsClientService } from "@odit/lfk-client-js";
|
||||||
|
import Toastify from "toastify-js";
|
||||||
|
export let modal_open;
|
||||||
|
export let new_client;
|
||||||
|
export let current_clients;
|
||||||
|
export let copy_modal_open;
|
||||||
|
function focus(el) {
|
||||||
|
el.focus();
|
||||||
|
}
|
||||||
|
$: description = "";
|
||||||
|
$: createbtnenabled = description != "";
|
||||||
|
$: processed_last_submit = true;
|
||||||
|
(() => {
|
||||||
|
document.onkeydown = (e) => {
|
||||||
|
e = e || window.event;
|
||||||
|
if (e.key === "Escape") {
|
||||||
|
modal_open = false;
|
||||||
|
}
|
||||||
|
if (e.keyCode === 13) {
|
||||||
|
if (createbtnenabled === true) {
|
||||||
|
createbtnenabled = false;
|
||||||
|
submit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
function submit() {
|
||||||
|
if (processed_last_submit === true) {
|
||||||
|
processed_last_submit = false;
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("statsclient-is-being-added"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
|
||||||
|
StatsClientService.statsClientControllerPost({description})
|
||||||
|
.then((result) => {
|
||||||
|
description = "";
|
||||||
|
modal_open = false;
|
||||||
|
//
|
||||||
|
Toastify({
|
||||||
|
text: $_("scanstation-added"),
|
||||||
|
duration: 500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
current_clients.push(result);
|
||||||
|
current_clients = current_clients;
|
||||||
|
new_client = result;
|
||||||
|
copy_modal_open = true;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
//
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
processed_last_submit = true;
|
||||||
|
//
|
||||||
|
toast.hideToast();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if modal_open}
|
||||||
|
<div
|
||||||
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
|
|
||||||
|
use:clickOutside
|
||||||
|
on:click_outside={() => {
|
||||||
|
modal_open = false;
|
||||||
|
}}>
|
||||||
|
<div
|
||||||
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
||||||
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
|
data-id="modal_backdrop" />
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
|
aria-hidden="true">​</span>
|
||||||
|
<div
|
||||||
|
class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby="modal-headline">
|
||||||
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
|
<div class="sm:flex sm:items-start">
|
||||||
|
<div
|
||||||
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
|
||||||
|
<svg
|
||||||
|
class="h-6 w-6 text-blue-600"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z" /></svg>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
{$_('create-a-new-statsclient')}
|
||||||
|
</h3>
|
||||||
|
<div class="mt-2 mb-6">
|
||||||
|
<p class="text-sm text-gray-500">
|
||||||
|
{$_('please-provide-the-required-information-to-create-a-new-statsclient')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-cols-6 gap-6">
|
||||||
|
<div class="col-span-6">
|
||||||
|
<label
|
||||||
|
for="description"
|
||||||
|
class="block text-sm font-medium text-gray-700">{$_('description')}</label>
|
||||||
|
<input
|
||||||
|
use:focus
|
||||||
|
autocomplete="off"
|
||||||
|
placeholder={$_('description')}
|
||||||
|
bind:value={description}
|
||||||
|
type="text"
|
||||||
|
name="description"
|
||||||
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||||
|
<button
|
||||||
|
disabled={!createbtnenabled}
|
||||||
|
class:opacity-50={!createbtnenabled}
|
||||||
|
on:click={submit}
|
||||||
|
type="button"
|
||||||
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
||||||
|
{$_('create')}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
modal_open = false;
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
|
||||||
|
{$_('cancel')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,88 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import { clickOutside } from "../base/outsideclick";
|
||||||
|
import { StatsClientService } from "@odit/lfk-client-js";
|
||||||
|
import Toastify from "toastify-js";
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
|
export let modal_open;
|
||||||
|
export let delete_station;
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
function cancelDelete() {
|
||||||
|
modal_open = false;
|
||||||
|
dispatch("cancelDelete", { id: delete_station.id });
|
||||||
|
}
|
||||||
|
function deleteClient() {
|
||||||
|
StatsClientService.statsClientControllerRemove(delete_station.id, true)
|
||||||
|
.then((resp) => {
|
||||||
|
Toastify({
|
||||||
|
text: $_('statsclient-deleted'),
|
||||||
|
duration: 500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
location.replace("./");
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if modal_open}
|
||||||
|
<div
|
||||||
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
|
|
||||||
|
use:clickOutside
|
||||||
|
on:click_outside={cancelDelete}>
|
||||||
|
<div
|
||||||
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
||||||
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
|
data-id="modal_backdrop" />
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
|
aria-hidden="true">​</span>
|
||||||
|
<div
|
||||||
|
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby="modal-headline">
|
||||||
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
|
<div class="sm:flex sm:items-start">
|
||||||
|
<div
|
||||||
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
|
||||||
|
<svg class="h-6 w-6 text-blue-600" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z"/></svg>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
{$_('attention')}
|
||||||
|
</h3>
|
||||||
|
<div class="mt-2 mb-6">
|
||||||
|
<p class="text-sm text-gray-500">
|
||||||
|
{$_(
|
||||||
|
'do-you-want-to-delete-this-donor-with-all-related-donations'
|
||||||
|
)}
|
||||||
|
<br />
|
||||||
|
{$_('all-associated-scans-will-get-deleted-as-well')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||||
|
<button
|
||||||
|
on:click={deleteClient}
|
||||||
|
type="button"
|
||||||
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">
|
||||||
|
{$_('confirm-delete-statsclient')}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={cancelDelete}
|
||||||
|
type="button"
|
||||||
|
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
|
||||||
|
{$_('cancel-keep-statsclient')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,147 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
|
||||||
|
import Toastify from "toastify-js";
|
||||||
|
import { tick, createEventDispatcher } from "svelte";
|
||||||
|
export let copy_modal_open;
|
||||||
|
export let new_client;
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
let valueCopy = null;
|
||||||
|
let areaDom;
|
||||||
|
let copied = false;
|
||||||
|
function close() {
|
||||||
|
copy_modal_open = false;
|
||||||
|
}
|
||||||
|
async function copy() {
|
||||||
|
valueCopy = new_client.key;
|
||||||
|
await tick();
|
||||||
|
areaDom.focus();
|
||||||
|
areaDom.select();
|
||||||
|
try {
|
||||||
|
const successful = document.execCommand("copy");
|
||||||
|
if (!successful) {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
Toastify({
|
||||||
|
text: $_("copied-token-to-clipboard"),
|
||||||
|
duration: 500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
copied = true;
|
||||||
|
} catch (err) {
|
||||||
|
Toastify({
|
||||||
|
text: $_("error-whyile-copying-to-clipboard"),
|
||||||
|
duration: 500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
|
|
||||||
|
// we can notifi by event or storage about copy status
|
||||||
|
valueCopy = null;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if copy_modal_open}
|
||||||
|
{#if valueCopy != null}
|
||||||
|
<textarea bind:this={areaDom}>{valueCopy}</textarea>
|
||||||
|
{/if}
|
||||||
|
<div class="fixed z-10 inset-0 overflow-y-auto">
|
||||||
|
<div
|
||||||
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
||||||
|
>
|
||||||
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
|
data-id="modal_backdrop"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
|
aria-hidden="true">​</span
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby="modal-headline"
|
||||||
|
>
|
||||||
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
|
<div class="sm:flex sm:items-start">
|
||||||
|
<div
|
||||||
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="h-6 w-6 text-blue-600"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
{$_("token")}
|
||||||
|
</h3>
|
||||||
|
<div class="mt-2 mb-6">
|
||||||
|
<p class="text-sm text-gray-500">
|
||||||
|
{$_(
|
||||||
|
"the-statsclient-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again"
|
||||||
|
)}
|
||||||
|
<br />
|
||||||
|
{$_("please-copy-the-token-and-store-it-somewhere-save")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 mb-6">
|
||||||
|
<label
|
||||||
|
for="token"
|
||||||
|
class="block text-sm font-medium text-gray-700"
|
||||||
|
>{$_("token")}</label
|
||||||
|
>
|
||||||
|
<button on:click={copy} class="inline-flex">
|
||||||
|
<p
|
||||||
|
name="token"
|
||||||
|
class:bg-green-200={copied}
|
||||||
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
|
||||||
|
>
|
||||||
|
{new_client.key}
|
||||||
|
</p>
|
||||||
|
<div
|
||||||
|
class="bg-gray-200 border-gray-300 border-t border-b border-r text-black rounded-r-md sm:text-sm p-2 mt-1 cursor-pointer"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M7 4V2h10v2h3l1 1v16a1 1 0 01-1 1H4a1 1 0 01-1-1V5l1-1h3zm0 2H5v14h14V6h-2v2H7V6zm2-2v2h6V4H9z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
</button>
|
||||||
|
<p class="text-gray-500 text-xs">
|
||||||
|
{$_("click-to-copy-token-to-clipboard")}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||||
|
<button
|
||||||
|
on:click={close}
|
||||||
|
type="button"
|
||||||
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-green-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>
|
||||||
|
{$_("yes-i-copied-the-token")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
<script>
|
||||||
|
import { t, _ } from "svelte-i18n";
|
||||||
|
import store from "../../store";
|
||||||
|
import Toastify from "toastify-js";
|
||||||
|
import PromiseError from "../base/PromiseError.svelte";
|
||||||
|
import ConfirmStatsClientDeletion from "./ConfirmStatsClientDeletion.svelte";
|
||||||
|
import { StatsClientService } from "@odit/lfk-client-js";
|
||||||
|
let data_loaded = false;
|
||||||
|
let modal_open;
|
||||||
|
let delete_client;
|
||||||
|
export let params;
|
||||||
|
$: delete_triggered = false;
|
||||||
|
$: original_data = {};
|
||||||
|
const promise = StatsClientService.statsClientControllerGetOne(
|
||||||
|
params.clientid
|
||||||
|
).then((data) => {
|
||||||
|
data_loaded = true;
|
||||||
|
original_data = Object.assign(original_data, data);
|
||||||
|
});
|
||||||
|
function deleteClient() {
|
||||||
|
StatsClientService.statsClientControllerRemove(original_data.id, false)
|
||||||
|
.then((resp) => {
|
||||||
|
Toastify({
|
||||||
|
text: $_("statsclient-deleted"),
|
||||||
|
duration: 500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
location.replace("./");
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
modal_open = true;
|
||||||
|
delete_client = original_data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ConfirmStatsClientDeletion bind:modal_open bind:delete_client />
|
||||||
|
{#await promise}
|
||||||
|
{$_('loading-statsclient-details')}
|
||||||
|
{:then}
|
||||||
|
<section class="container p-5 select-none">
|
||||||
|
<div class="flex flex-row mb-4">
|
||||||
|
<div class="w-full">
|
||||||
|
<nav class="w-full flex">
|
||||||
|
<ol class="list-none flex flex-row items-center justify-start">
|
||||||
|
<li class="flex items-center">
|
||||||
|
<svg
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z" /></svg>
|
||||||
|
</li>
|
||||||
|
<li class="flex items-center ml-2">
|
||||||
|
<a class="mr-2" href="./">{$_('statsclient')}</a><svg
|
||||||
|
stroke="currentColor"
|
||||||
|
fill="none"
|
||||||
|
stroke-width="2"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="h-3 w-3 mr-2 stroke-current"
|
||||||
|
height="1em"
|
||||||
|
width="1em"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"><line
|
||||||
|
x1="5"
|
||||||
|
y1="12"
|
||||||
|
x2="19"
|
||||||
|
y2="12" />
|
||||||
|
<polyline points="12 5 19 12 12 19" /></svg>
|
||||||
|
</li>
|
||||||
|
<li class="flex items-center">
|
||||||
|
<span class="mr-2">#{original_data.id}</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
||||||
|
#{original_data.id}
|
||||||
|
<span data-id="stations_actions_${original_data.id}">
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes('STATSCLIENT:DELETE')}
|
||||||
|
{#if delete_triggered}
|
||||||
|
<button
|
||||||
|
on:click={deleteClient}
|
||||||
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('confirm-deletion')}</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
delete_triggered = !delete_triggered;
|
||||||
|
}}
|
||||||
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm">{$_('cancel')}</button>
|
||||||
|
{/if}
|
||||||
|
{#if !delete_triggered}
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
delete_triggered = true;
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('delete-statsclient')}</button>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<!-- -->
|
||||||
|
<div class="text-sm w-full">
|
||||||
|
<label
|
||||||
|
for="description"
|
||||||
|
class="font-medium text-gray-700">{$_('description')}</label>
|
||||||
|
<p
|
||||||
|
name="description"
|
||||||
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" >
|
||||||
|
{original_data.description}</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{:catch error}
|
||||||
|
<PromiseError {error} />
|
||||||
|
{/await}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import store from "../../store";
|
||||||
|
import AddStatsClientModal from "./AddStatsClientModal.svelte";
|
||||||
|
import CopyStatsClientTokenModal from "./CopyStatsClientTokenModal.svelte";
|
||||||
|
import StatsClientsOverview from "./StatsClientsOverview.svelte";
|
||||||
|
export let modal_open = false;
|
||||||
|
export let copy_modal_open = false;
|
||||||
|
export let new_client = {};
|
||||||
|
let current_clients = [];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section class="container p-5">
|
||||||
|
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
|
{$_('statsclients')}
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes('STATSCLIENT:CREATE')}
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
modal_open = true;
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
||||||
|
{$_('create-a-new-statsclient')}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
<StatsClientsOverview bind:current_clients bind:modal_open bind:new_client bind:copy_modal_open />
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes('STATSCLIENT:CREATE')}
|
||||||
|
<AddStatsClientModal bind:modal_open bind:current_clients bind:new_client bind:copy_modal_open/>
|
||||||
|
<CopyStatsClientTokenModal bind:copy_modal_open bind:new_client />
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import AddStatsClientModal from "./AddStatsClientModal.svelte";
|
||||||
|
import CopyScanStationTokenModal from "./CopyStatsClientTokenModal.svelte";
|
||||||
|
import scanstations_empty from "./statsclients_empty.svg";
|
||||||
|
let modal_open = false;
|
||||||
|
let copy_modal_open = false;
|
||||||
|
let new_client = {};
|
||||||
|
let current_clients = [];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="text-center items-center justify-center">
|
||||||
|
<p class="mb-16 text-lg text-gray-500">
|
||||||
|
<img class="w-full h-44" src={scanstations_empty} alt="" />
|
||||||
|
<span class="font-bold">{$_('you-dont-have-any-scanclients-yet')}.</span><br />
|
||||||
|
<span>{$_('add-the-first-statsclient')}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<AddStatsClientModal bind:modal_open bind:current_clients bind:new_client bind:copy_modal_open/>
|
||||||
|
<CopyScanStationTokenModal bind:copy_modal_open bind:new_client />
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import Toastify from "toastify-js";
|
||||||
|
import { StatsClientService } from "@odit/lfk-client-js";
|
||||||
|
const promise = StatsClientService.statsClientControllerGetAll().then(
|
||||||
|
(result) => {
|
||||||
|
current_clients = result;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
import store from "../../store";
|
||||||
|
import StatsClientsEmptyState from "./StatsClientsEmptyState.svelte";
|
||||||
|
import ConfirmStatsClientDeletion from "./ConfirmStatsClientDeletion.svelte";
|
||||||
|
$: searchvalue = "";
|
||||||
|
$: active_deletes = [];
|
||||||
|
let delete_client = {};
|
||||||
|
let modal_open = false;
|
||||||
|
export let current_clients = [];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ConfirmStatsClientDeletion
|
||||||
|
on:cancelDelete={(event) => {
|
||||||
|
modal_open = false;
|
||||||
|
active_deletes[event.detail.id] = false;
|
||||||
|
}}
|
||||||
|
bind:modal_open
|
||||||
|
bind:delete_client />
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes('STATSCLIENT:GET')}
|
||||||
|
{#await promise}
|
||||||
|
<div
|
||||||
|
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
||||||
|
role="alert">
|
||||||
|
<p class="font-bold">{$_('statsclients-are-being-loaded')}</p>
|
||||||
|
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
||||||
|
</div>
|
||||||
|
{:then}
|
||||||
|
{#if current_clients.length === 0}
|
||||||
|
<StatsClientsEmptyState />
|
||||||
|
{:else}
|
||||||
|
<input
|
||||||
|
type="search"
|
||||||
|
bind:value={searchvalue}
|
||||||
|
placeholder={$_('datatable.search')}
|
||||||
|
aria-label={$_('datatable.search')}
|
||||||
|
class="mb-4" />
|
||||||
|
<div
|
||||||
|
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
||||||
|
<table class="divide-y divide-gray-200 w-full">
|
||||||
|
<thead class="bg-gray-50">
|
||||||
|
<tr>
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||||
|
{$_('description')}
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||||
|
{$_('prefix')}
|
||||||
|
</th>
|
||||||
|
<th scope="col" class="relative px-6 py-3">
|
||||||
|
<span class="sr-only">{$_('action')}</span>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="divide-y divide-gray-200">
|
||||||
|
{#each current_clients as c}
|
||||||
|
{#if Object.values(c)
|
||||||
|
.toString()
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(searchvalue)}
|
||||||
|
<tr data-rowid="station_{c.id}">
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="ml-4">
|
||||||
|
<div class="text-sm font-medium text-gray-900">
|
||||||
|
{c.description}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="ml-4">
|
||||||
|
<div class="text-sm font-medium text-gray-900">
|
||||||
|
{c.prefix}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
{#if active_deletes[c.id] === true}
|
||||||
|
<td
|
||||||
|
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
active_deletes[c.id] = false;
|
||||||
|
}}
|
||||||
|
tabindex="0"
|
||||||
|
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">{$_('cancel-delete')}</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
StatsClientService.statsClientControllerRemove(c.id, false)
|
||||||
|
.then((resp) => {
|
||||||
|
current_clients = current_clients.filter((obj) => obj.id !== c.id);
|
||||||
|
Toastify({
|
||||||
|
text: $_('statsclient-deleted'),
|
||||||
|
duration: 500,
|
||||||
|
backgroundColor:
|
||||||
|
'linear-gradient(to right, #00b09b, #96c93d)',
|
||||||
|
}).showToast();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
modal_open = true;
|
||||||
|
delete_client = c;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
tabindex="0"
|
||||||
|
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('confirm-delete')}</button>
|
||||||
|
</td>
|
||||||
|
{:else}
|
||||||
|
<td
|
||||||
|
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||||
|
<a
|
||||||
|
href="/statsclients/{c.id}"
|
||||||
|
class="text-indigo-600 hover:text-indigo-900">{$_('details')}</a>
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes('STATSCLIENT:DELETE')}
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
active_deletes[c.id] = true;
|
||||||
|
}}
|
||||||
|
tabindex="0"
|
||||||
|
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
|
||||||
|
{/if}
|
||||||
|
</td>
|
||||||
|
{/if}
|
||||||
|
</tr>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{:catch error}
|
||||||
|
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
|
||||||
|
<span class="inline-block align-middle mr-8">
|
||||||
|
<b class="capitalize">{$_('general_promise_error')}</b>
|
||||||
|
{error}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{/await}
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 920.11 411.95" width="920.11" height="411.95"><path d="M436.53 410h195.59c7.72 0 7.73-12 0-12h-195.6c-7.71 0-7.73 12 0 12z" fill="#e6e6e6"/><path d="M383.72 149.23H188.79a7.78 7.78 0 00-7.77 7.77v38.72c9.72.23 16.03 8.26 17.56 18v35.1h.74a.44.44 0 01.45.45v18.68a.44.44 0 01-.45.44h-.74v112.9l-.02 7.02h185.16a7.78 7.78 0 007.77-7.77V157a7.78 7.78 0 00-7.77-7.77z" fill="#6c63ff"/><path d="M745.9 21.81v211.9H404.97v-93.3a16 16 0 00-15.98-15.97h-63.94V21.8z" fill="#6c63ff"/><path d="M766.95 263.58h-361.6v-1.47h360.12V12.55A11.09 11.09 0 00754.4 1.48H312.14a11.09 11.09 0 00-11.08 11.07v110.93h-1.47V12.55A12.57 12.57 0 01312.14 0H754.4a12.57 12.57 0 0112.55 12.55z" fill="#3f3d56"/><path d="M732.69 308.62H405.35v-1.48h327.34a32.82 32.82 0 0032.78-32.78v-10.78H405.35v-1.47h361.6v12.25a34.3 34.3 0 01-34.26 34.26z" fill="#3f3d56"/><path d="M635.54 380.98c-18.25-17.52-30.25-40.39-34.11-72.36h-134.5c-1.36 29.91-13.29 52.35-34.8 72.28l-2.28.08c22.2-20.12 34.43-42.72 35.64-73.13l.03-.7h137.22l.08.65c3.79 32.51 16.04 55.52 34.74 73.06zM388.63 411.52H181.46v-1.47h207.17a16 16 0 0015.98-15.98V140.75a16 16 0 00-15.98-15.97H181.46a16 16 0 00-15.98 15.97v54.67h-1.47v-54.67a17.47 17.47 0 0117.45-17.45h207.17a17.47 17.47 0 0117.46 17.45v253.32a17.47 17.47 0 01-17.46 17.45z" fill="#3f3d56"/><path d="M285.05 141.98a5 5 0 115-5 5.01 5.01 0 01-5 5zm0-8.85a3.85 3.85 0 103.85 3.85 3.85 3.85 0 00-3.85-3.85zM285.05 405.86a6.39 6.39 0 116.39-6.38 6.4 6.4 0 01-6.4 6.38zm0-11.3a4.91 4.91 0 104.91 4.92 4.92 4.92 0 00-4.91-4.92zM179.38 411.95H110.8a19.5 19.5 0 01-19.47-19.47V214.89a19.5 19.5 0 0119.47-19.47h68.58a19.5 19.5 0 0119.47 19.47v31.78a1.92 1.92 0 011.19 1.78v20.67a1.92 1.92 0 01-1.19 1.78v121.58a19.5 19.5 0 01-19.47 19.47zM110.8 196.9a18.02 18.02 0 00-18 18v177.58a18.02 18.02 0 0018 18h68.58a18.02 18.02 0 0018-18V269.57h.74a.44.44 0 00.44-.45v-20.67a.44.44 0 00-.44-.45h-.74v-33.1a18.02 18.02 0 00-18-18z" fill="#3f3d56"/><path d="M180.14 201.03h-8.96a6.65 6.65 0 01-6.15 9.16h-39.29a6.65 6.65 0 01-6.15-9.16h-8.36a14 14 0 00-14 14v177.32a14 14 0 0014 13.99h68.9a14 14 0 0014-14V215.04a14 14 0 00-14-14z" fill="#6c63ff"/><path d="M919.23 411.66H.88a.88.88 0 110-1.76h918.35a.88.88 0 110 1.76z" fill="#3f3d56"/><path d="M636 411.25H431.48a15.5 15.5 0 110-31.01H636a15.5 15.5 0 010 31zm-204.52-29.53a14.03 14.03 0 000 28.05H636a14.03 14.03 0 000-28.05z" fill="#3f3d56"/><path fill="#ffb8b8" d="M784.5 293.2l5.72 11.97 48.92-16.4-8.45-17.67-46.2 22.1z"/><path d="M790.15 333.59l-18-37.64 14.54-6.96 11.58 24.21a14.89 14.89 0 01-7 19.85l-1.12.54z" fill="#2f2e41"/><path fill="#ffb8b8" d="M772.96 400.14l13.27-.45.56-51.64-15.55.92 1.72 51.17z"/><path d="M811.97 411.86h-41.72v-16.12h26.84a14.89 14.89 0 0114.88 14.88v1.24zM774.06 392.38a4.97 4.97 0 01-4.84-3.78c-7.26-29.2-34.3-176.34-10.4-205.23l.22-.26.31-.08c1.68-.42 33.33-10.22 51.9 5.08l.21.17 10.34 29.92 27.86 41.35a20.4 20.4 0 01-6.04 28.66l-36.58 23.08a5 5 0 01-5.75-.4 5.06 5.06 0 01-1.5-2.1l-7.69-19.21a5.03 5.03 0 012.4-6.33l17.15-8.57a3.67 3.67 0 001.83-2.5 2.96 2.96 0 00-1.03-2.55l-19.9-17.15a3 3 0 00-4.95 2.38l4.93 130.2a5 5 0 01-4.22 5.13l-13.46 2.13a5.05 5.05 0 01-.8.06z" fill="#2f2e41"/><path d="M808.38 193.41l-.34-.01-49.62-3.68a4.5 4.5 0 01-3.91-5.97 47.1 47.1 0 001.07-27.31c-3.23-12.75-3.3-36.44-3.06-49.42a8.75 8.75 0 018.28-8.53v-.01h1c8.08.12 22.91.7 35.05 3.22a18.39 18.39 0 0114.66 17.7c.28 12.06.32 28.38-1.05 37.66-1.16 7.83.98 22.86 2.35 31.12a4.5 4.5 0 01-4.43 5.23z" fill="#3f3d56"/><path d="M826.09 240.71a10.02 10.02 0 01-3.81-14.9L799.36 127h17.33l20.22 96.87a10.08 10.08 0 01-10.82 16.84zM717.56 137.7l27.43-25.95 10.34 14.47-25.84 22.74 33.89 26.91c.24-.01.49-.04.74-.04a10.85 10.85 0 11-10.75 12.3l-.1.1-35.28-30.56a13.47 13.47 0 01-.43-19.97z" fill="#ffb8b8"/><path d="M801.19 133.33a4.47 4.47 0 01-4.05-2.55 52.81 52.81 0 01-4.47-14.57c-1.2-8.25 4.54-13.15 10.37-14.22 5.67-1.04 12.58 1.45 14.34 9.38a20.45 20.45 0 01.35 2.04c.7 6 1.37 10.68 1.97 13.9a4.5 4.5 0 01-4.2 5.31l-14.08.7-.23.01z" fill="#3f3d56"/><circle cx="781.54" cy="59.98" r="30" fill="#2f2e41"/><circle cx="781.73" cy="67.77" r="24.56" fill="#ffb8b8"/><path d="M738.13 121.38a4.47 4.47 0 01-1.26-4.62 52.81 52.81 0 016.55-13.76c4.7-6.88 12.23-6.63 17.25-3.48 4.89 3.07 8.3 9.57 4.24 16.61a20.45 20.45 0 01-1.12 1.73c-3.54 4.91-6.21 8.8-7.93 11.58a4.5 4.5 0 01-6.7 1.09l-10.85-9q-.1-.07-.18-.15z" fill="#3f3d56"/><path d="M775.72 33.19c-6.04-3.6-7.35-12.57-3.75-18.61s10.86-9.2 17.9-9.4c10.03-.3 19.72 4.7 26.75 11.87s11.66 16.36 15.2 25.76 6.06 19.15 9.54 28.57c1.79 4.83 3.99 9.8 8.07 12.93s10.59 3.7 14.08-.08c-.01 6.06-4.66 11.57-10.42 13.45s-12.29.46-17.34-2.9c-8.76-5.8-13-16.4-15.41-26.64s-3.61-20.95-8.48-30.27c-2.01-3.87-4.77-7.54-8.66-9.5s-9.06-1.85-12.19 1.19c-1.44 1.4-2.38 3.32-4.02 4.5a8.05 8.05 0 01-7.04.72 23.8 23.8 0 01-6.36-3.59" fill="#2f2e41"/><path d="M756.07 51.17a29.38 29.38 0 0042.13 5.26c2.38-1.94 4.6-4.61 4.45-7.68-.16-3.15-2.73-5.62Line truncated
|
||||||
|
After Width: | Height: | Size: 5.0 KiB |
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import {
|
import {
|
||||||
RunnerOrganizationService,
|
RunnerOrganizationService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
@@ -77,7 +77,7 @@
|
|||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={() => {
|
on:click_outside={() => {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import { RunnerTeamService } from "@odit/lfk-client-js";
|
import { RunnerTeamService } from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
@@ -29,7 +29,7 @@
|
|||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={cancelDelete}>
|
on:click_outside={cancelDelete}>
|
||||||
<div
|
<div
|
||||||
|
|||||||
@@ -26,9 +26,9 @@
|
|||||||
export let params;
|
export let params;
|
||||||
export let import_modal_open = false;
|
export let import_modal_open = false;
|
||||||
$: delete_triggered = false;
|
$: delete_triggered = false;
|
||||||
$: save_enabled = !data_changed && teamdata.parentGroup != null;
|
$: save_enabled = data_changed && teamdata.parentGroup != null;
|
||||||
$: data_loaded = false;
|
$: data_loaded = false;
|
||||||
$: data_changed = JSON.stringify(teamdata) === JSON.stringify(original);
|
$: data_changed = !(JSON.stringify(teamdata) === JSON.stringify(original));
|
||||||
$: sponsoring_contracts_show = true;
|
$: sponsoring_contracts_show = true;
|
||||||
$: cards_show = true;
|
$: cards_show = true;
|
||||||
$: certificates_show = true;
|
$: certificates_show = true;
|
||||||
@@ -47,6 +47,8 @@
|
|||||||
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
||||||
(val) => {
|
(val) => {
|
||||||
orgs = val.map((r) => {
|
orgs = val.map((r) => {
|
||||||
|
delete r.contact;
|
||||||
|
r.teams = [];
|
||||||
return { label: r.name, value: r };
|
return { label: r.name, value: r };
|
||||||
});
|
});
|
||||||
group = orgs.find((g) => g.value.id == teamdata.parentGroup.id);
|
group = orgs.find((g) => g.value.id == teamdata.parentGroup.id);
|
||||||
|
|||||||
@@ -57,7 +57,7 @@
|
|||||||
bind:value={searchvalue}
|
bind:value={searchvalue}
|
||||||
placeholder={$_('datatable.search')}
|
placeholder={$_('datatable.search')}
|
||||||
aria-label={$_('datatable.search')}
|
aria-label={$_('datatable.search')}
|
||||||
class="gridjs-input gridjs-search-input mb-4" />
|
class="mb-4" />
|
||||||
<div class="h-12">
|
<div class="h-12">
|
||||||
<GenerateSponsoringContracts
|
<GenerateSponsoringContracts
|
||||||
bind:sponsoring_contracts_show
|
bind:sponsoring_contracts_show
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import { tracks as tracksstore } from "../../store.js";
|
import { tracks as tracksstore } from "../../store.js";
|
||||||
import { TrackService } from "@odit/lfk-client-js";
|
import { TrackService } from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
@@ -75,7 +75,7 @@
|
|||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={() => {
|
on:click_outside={() => {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
|
|||||||
@@ -1,7 +1,7 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
import { focusTrap } from "svelte-focus-trap";
|
|
||||||
import { UserService } from "@odit/lfk-client-js";
|
import { UserService } from "@odit/lfk-client-js";
|
||||||
import isEmail from "validator/es/lib/isEmail";
|
import isEmail from "validator/es/lib/isEmail";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:focusTrap
|
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={() => {
|
on:click_outside={() => {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
|
|||||||
@@ -36,7 +36,7 @@
|
|||||||
bind:value={searchvalue}
|
bind:value={searchvalue}
|
||||||
placeholder={$_('datatable.search')}
|
placeholder={$_('datatable.search')}
|
||||||
aria-label={$_('datatable.search')}
|
aria-label={$_('datatable.search')}
|
||||||
class="gridjs-input gridjs-search-input mb-4" />
|
class="mb-4" />
|
||||||
<!-- {/if} -->
|
<!-- {/if} -->
|
||||||
<!-- <button
|
<!-- <button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
@@ -82,14 +82,6 @@
|
|||||||
<tr data-rowid="user_{u.id}">
|
<tr data-rowid="user_{u.id}">
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
{#if u.profilePic}
|
|
||||||
<div class="flex-shrink-0 h-10 w-10">
|
|
||||||
<img
|
|
||||||
class="h-10 w-10 rounded-full"
|
|
||||||
src={u.profilePic}
|
|
||||||
alt="" />
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
<div class="ml-4">
|
<div class="ml-4">
|
||||||
<div class="text-sm font-medium text-gray-900">
|
<div class="text-sm font-medium text-gray-900">
|
||||||
{u.firstname}
|
{u.firstname}
|
||||||
|
|||||||
+41
-2
@@ -7,8 +7,10 @@
|
|||||||
"add-card": "Karte erstellen",
|
"add-card": "Karte erstellen",
|
||||||
"add-donation": "Sponsoring erstellen",
|
"add-donation": "Sponsoring erstellen",
|
||||||
"add-donor": "Sponsor:in erstellen",
|
"add-donor": "Sponsor:in erstellen",
|
||||||
|
"add-or-update-a-payment": "Zahlung hinzufügen oder bearbeiten",
|
||||||
"add-scan": "Scan erstellen",
|
"add-scan": "Scan erstellen",
|
||||||
"add-the-first-scanstation": "Erstelle deine erste Scannerstation.",
|
"add-the-first-scanstation": "Erstelle deine erste Scannerstation.",
|
||||||
|
"add-the-first-statsclient": "Erstelle deinen ersten Statsclient.",
|
||||||
"add-user-group": "Neue Gruppe erstellen",
|
"add-user-group": "Neue Gruppe erstellen",
|
||||||
"add-your-first-card": "Erstelle deine erste Läuferkarte",
|
"add-your-first-card": "Erstelle deine erste Läuferkarte",
|
||||||
"add-your-first-contact": "Erstelle den ersten Kontakt",
|
"add-your-first-contact": "Erstelle den ersten Kontakt",
|
||||||
@@ -28,17 +30,22 @@
|
|||||||
"address-is-required": "Du musst eine Adresse angeben",
|
"address-is-required": "Du musst eine Adresse angeben",
|
||||||
"after-deletion-we-cant-restore-your-old-profile": "Nach der Löschung können auch die Admins dein Profil nicht wiederherstellen!",
|
"after-deletion-we-cant-restore-your-old-profile": "Nach der Löschung können auch die Admins dein Profil nicht wiederherstellen!",
|
||||||
"after-the-update-youll-get-logged-out-please-login-with-your-new-password-after-that": "Nach der Änderung wirst du abgemeldet - bitte melde dich dann mit deinem neuen Passwort an.",
|
"after-the-update-youll-get-logged-out-please-login-with-your-new-password-after-that": "Nach der Änderung wirst du abgemeldet - bitte melde dich dann mit deinem neuen Passwort an.",
|
||||||
|
"all": "Alle",
|
||||||
"all-associated-donations-will-get-deleted-as-well": "Alle Sponsorings dieser Sponsor:in werden ebenfalls gelöscht",
|
"all-associated-donations-will-get-deleted-as-well": "Alle Sponsorings dieser Sponsor:in werden ebenfalls gelöscht",
|
||||||
"all-associated-runners-will-be-deleted-too": "Alle zugehörigen Läufer:innen werden auch gelöscht!",
|
"all-associated-runners-will-be-deleted-too": "Alle zugehörigen Läufer:innen werden auch gelöscht!",
|
||||||
|
"all-associated-scans-will-get-deleted-as-well": "Alle Scans dieser Station werden ebenfalls gelöscht",
|
||||||
"all-associated-teams-and-runners-will-be-deleted-too": "Alle assoziierten Teams und Läufer:innen werden auch gelöscht!",
|
"all-associated-teams-and-runners-will-be-deleted-too": "Alle assoziierten Teams und Läufer:innen werden auch gelöscht!",
|
||||||
"already-paid": "Bereits bezahlt",
|
"already-paid": "Bereits bezahlt",
|
||||||
"amount": "Anzahl",
|
"amount": "Anzahl",
|
||||||
"amount-per-kilometer": "Betrag pro Kilometer",
|
"amount-per-kilometer": "Betrag pro Kilometer",
|
||||||
"apartment-suite-etc": "Apartment, Wohnung, etc.",
|
"apartment-suite-etc": "Apartment, Wohnung, etc.",
|
||||||
|
"api-endpoint": "API-Endpunkt",
|
||||||
"application_name": "Lauf für Kaya! - Admin",
|
"application_name": "Lauf für Kaya! - Admin",
|
||||||
"applying-changes": "Änderungen anwenden",
|
"applying-changes": "Änderungen anwenden",
|
||||||
"attention": "Achtung!",
|
"attention": "Achtung!",
|
||||||
"author": "Autor:in",
|
"author": "Autor:in",
|
||||||
|
"average-distance": "Durchschnittliche Strecke/Läufer:in",
|
||||||
|
"average-donation": "Durchschnittliches Sponsoring",
|
||||||
"bitte-bestaetige-diese-laeufer-fuer-den-import": "Bitte die Läufer:innen für den Import bestätigen.",
|
"bitte-bestaetige-diese-laeufer-fuer-den-import": "Bitte die Läufer:innen für den Import bestätigen.",
|
||||||
"by": "von",
|
"by": "von",
|
||||||
"cancel": "Abbrechen",
|
"cancel": "Abbrechen",
|
||||||
@@ -46,12 +53,16 @@
|
|||||||
"cancel-keep-donor": "Abbrechen, Sponsor:in behalten",
|
"cancel-keep-donor": "Abbrechen, Sponsor:in behalten",
|
||||||
"cancel-keep-my-profile": "Abbrechen, mein Profil behalten",
|
"cancel-keep-my-profile": "Abbrechen, mein Profil behalten",
|
||||||
"cancel-keep-organization": "Abbrechen und Organisation bearbeiten",
|
"cancel-keep-organization": "Abbrechen und Organisation bearbeiten",
|
||||||
|
"cancel-keep-station": "Abbrechen und Station behalten",
|
||||||
|
"cancel-keep-statsclient": "Abbrechen und Statsclient behalten",
|
||||||
"cancel-keep-team": "Abbrechen, Team behalten",
|
"cancel-keep-team": "Abbrechen, Team behalten",
|
||||||
"cannot-reset-your-password-directly": "Schade. \nWir können das Passwort leider nicht direkt zurücksetzen.\nBitte sende uns eine Mail in der du deine Identität bestätigst.",
|
"cannot-reset-your-password-directly": "Schade. \nWir können das Passwort leider nicht direkt zurücksetzen.\nBitte sende uns eine Mail in der du deine Identität bestätigst.",
|
||||||
|
"card": "Läuferkarte",
|
||||||
"card-added": "Karte wurde hinzugefügt",
|
"card-added": "Karte wurde hinzugefügt",
|
||||||
"card-deleted": "Karte gelöscht",
|
"card-deleted": "Karte gelöscht",
|
||||||
"card-updated": "Karte aktualisiert",
|
"card-updated": "Karte aktualisiert",
|
||||||
"cards": "Läuferkarten",
|
"cards": "Läuferkarten",
|
||||||
|
"cards-deleted": "Karten gelöscht",
|
||||||
"certificates": "Urkunden",
|
"certificates": "Urkunden",
|
||||||
"change-your-password-here": "Hier kannst du dein Passwort ändern",
|
"change-your-password-here": "Hier kannst du dein Passwort ändern",
|
||||||
"changing-your-password": "Passwort wird geändert",
|
"changing-your-password": "Passwort wird geändert",
|
||||||
@@ -60,12 +71,15 @@
|
|||||||
"click-to-copy-token-to-clipboard": "Klicke auf den Token, um ihn in deine Zwischenablage zu kopieren",
|
"click-to-copy-token-to-clipboard": "Klicke auf den Token, um ihn in deine Zwischenablage zu kopieren",
|
||||||
"close": "Schließen",
|
"close": "Schließen",
|
||||||
"code": "Code",
|
"code": "Code",
|
||||||
|
"config-codes": "Konfigurations-Codes",
|
||||||
"configure-the-tracks-and-minimum-lap-times": "Bearbeite die Tracks und ihre minimale Rundenzeit",
|
"configure-the-tracks-and-minimum-lap-times": "Bearbeite die Tracks und ihre minimale Rundenzeit",
|
||||||
"confirm": "Bestätigen",
|
"confirm": "Bestätigen",
|
||||||
"confirm-delete": "Löschung Bestätigen",
|
"confirm-delete": "Löschung Bestätigen",
|
||||||
"confirm-delete-donor-with-all-donations": "Bestätigen, Sponsor:in mit allen Sponsorings löschen",
|
"confirm-delete-donor-with-all-donations": "Bestätigen, Sponsor:in mit allen Sponsorings löschen",
|
||||||
"confirm-delete-my-user-profile": "Bestätigung, mein Benutzerprofil löschen",
|
"confirm-delete-my-user-profile": "Bestätigung, mein Benutzerprofil löschen",
|
||||||
"confirm-delete-organization-and-associated-teams-runners": "Bestätugung, lösche die Organisation und alle zugehörigen Teams und Läufer:innen.",
|
"confirm-delete-organization-and-associated-teams-runners": "Bestätugung, lösche die Organisation und alle zugehörigen Teams und Läufer:innen.",
|
||||||
|
"confirm-delete-station-with-all-scans": "Löschen der Scannerstation mit allen Scans bestätigen",
|
||||||
|
"confirm-delete-statsclient": "Bestätigung, Statsclient löschen",
|
||||||
"confirm-delete-team-and-associated-runners": "Bestätigung, lösche das Team mitsamt seinen Läufer:innen.",
|
"confirm-delete-team-and-associated-runners": "Bestätigung, lösche das Team mitsamt seinen Läufer:innen.",
|
||||||
"confirm-deletion": "Löschung Bestätigen",
|
"confirm-deletion": "Löschung Bestätigen",
|
||||||
"confirm-the-new-password": "Neues Passwort bestätigen",
|
"confirm-the-new-password": "Neues Passwort bestätigen",
|
||||||
@@ -93,6 +107,7 @@
|
|||||||
"create-a-new-runner": "Neue Läufer:in erstellen",
|
"create-a-new-runner": "Neue Läufer:in erstellen",
|
||||||
"create-a-new-scan-fixed-only": "Neuen Scan erstellen (nur mit Festdistanz)",
|
"create-a-new-scan-fixed-only": "Neuen Scan erstellen (nur mit Festdistanz)",
|
||||||
"create-a-new-scanstation": "Neue Station erstellen",
|
"create-a-new-scanstation": "Neue Station erstellen",
|
||||||
|
"create-a-new-statsclient": "Neuen Statsclient erstellen",
|
||||||
"create-a-new-team": "Erstelle ein neues Team",
|
"create-a-new-team": "Erstelle ein neues Team",
|
||||||
"create-a-new-track": "Neuen Track erstellen",
|
"create-a-new-track": "Neuen Track erstellen",
|
||||||
"create-a-new-user": "Neue Benutzer:in anlegen",
|
"create-a-new-user": "Neue Benutzer:in anlegen",
|
||||||
@@ -132,6 +147,7 @@
|
|||||||
"sort_column_descending": "Spalte absteigend sortieren"
|
"sort_column_descending": "Spalte absteigend sortieren"
|
||||||
},
|
},
|
||||||
"delete": "Löschen",
|
"delete": "Löschen",
|
||||||
|
"delete-cards": "Karten löschen",
|
||||||
"delete-contact": "Kontakt löschen",
|
"delete-contact": "Kontakt löschen",
|
||||||
"delete-donation": "Sponsoring löschen",
|
"delete-donation": "Sponsoring löschen",
|
||||||
"delete-donor": "Sponsor:in löschen",
|
"delete-donor": "Sponsor:in löschen",
|
||||||
@@ -140,7 +156,9 @@
|
|||||||
"delete-profile": "Profil löschen",
|
"delete-profile": "Profil löschen",
|
||||||
"delete-runner": "Läufer:in löschen",
|
"delete-runner": "Läufer:in löschen",
|
||||||
"delete-scan": "Scan löschen",
|
"delete-scan": "Scan löschen",
|
||||||
|
"delete-scans": "Scans löschen",
|
||||||
"delete-station": "Station löschen",
|
"delete-station": "Station löschen",
|
||||||
|
"delete-statsclient": "Statsclient löschen",
|
||||||
"delete-team": "Team Löschen",
|
"delete-team": "Team Löschen",
|
||||||
"delete-user": "Benutzer:in löschen",
|
"delete-user": "Benutzer:in löschen",
|
||||||
"deleted-scan": "Scan wurde gelöscht",
|
"deleted-scan": "Scan wurde gelöscht",
|
||||||
@@ -165,10 +183,11 @@
|
|||||||
"donation-updated": "Sponsoring wurde aktualisiert",
|
"donation-updated": "Sponsoring wurde aktualisiert",
|
||||||
"donation_added": "Sponsoring hinzugefügt",
|
"donation_added": "Sponsoring hinzugefügt",
|
||||||
"donations": "Sponsorings",
|
"donations": "Sponsorings",
|
||||||
|
"donations-are-being-loaded": "Sponsorings werden geladen...",
|
||||||
"donor": "Sponsor:in",
|
"donor": "Sponsor:in",
|
||||||
"donor-added": "Sponsor:in hinzugefügt",
|
"donor-added": "Sponsor:in hinzugefügt",
|
||||||
"donor-deleted": "Sponsor:in gelöscht",
|
"donor-deleted": "Sponsor:in gelöscht",
|
||||||
"donor-has-no-associated-donations": "Zur Sponsor:in gibt es noch keine Sponsorings",
|
"donor-has-no-associated-donations": "Keine Sponsorings",
|
||||||
"donor-is-being-added": "Sponsor:in wird hinzugefügt...",
|
"donor-is-being-added": "Sponsor:in wird hinzugefügt...",
|
||||||
"donor-is-being-updated": "Sponsor:in wird aktualisiert",
|
"donor-is-being-updated": "Sponsor:in wird aktualisiert",
|
||||||
"donors": "Sponsor:innen",
|
"donors": "Sponsor:innen",
|
||||||
@@ -234,6 +253,7 @@
|
|||||||
"invalid": "Ungültig",
|
"invalid": "Ungültig",
|
||||||
"invalid-mail-reset": "Das ist keine gültige E-Mail",
|
"invalid-mail-reset": "Das ist keine gültige E-Mail",
|
||||||
"just-enter-how-many-you-want-and-the-system-will-create-them": "Gebe einfach ein, wie viele Blankokarten das System erstellen soll.",
|
"just-enter-how-many-you-want-and-the-system-will-create-them": "Gebe einfach ein, wie viele Blankokarten das System erstellen soll.",
|
||||||
|
"key": "Schlüssel",
|
||||||
"laeufer-hinzufuegen": "Läufer:in hinzufügen",
|
"laeufer-hinzufuegen": "Läufer:in hinzufügen",
|
||||||
"laeufer-importieren": "Läufer:innen importieren",
|
"laeufer-importieren": "Läufer:innen importieren",
|
||||||
"laptime": "Rundenzeit",
|
"laptime": "Rundenzeit",
|
||||||
@@ -266,6 +286,7 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"name-is-required": "Der Gruppenname muss angegeben werden",
|
"name-is-required": "Der Gruppenname muss angegeben werden",
|
||||||
"new-password": "Neues Passwort",
|
"new-password": "Neues Passwort",
|
||||||
|
"no-address": "Keine Adresse hinterlegt",
|
||||||
"no-contact-found": "Keine Kontakte gefunden",
|
"no-contact-found": "Keine Kontakte gefunden",
|
||||||
"no-contact-selected": "Kein Kontakt ausgewählt",
|
"no-contact-selected": "Kein Kontakt ausgewählt",
|
||||||
"no-contact-specified": "Kein Kontakt angegeben",
|
"no-contact-specified": "Kein Kontakt angegeben",
|
||||||
@@ -306,6 +327,10 @@
|
|||||||
"permissions": "Berechtigungen",
|
"permissions": "Berechtigungen",
|
||||||
"permissions-updated": "Berechtigungen aktualisiert!",
|
"permissions-updated": "Berechtigungen aktualisiert!",
|
||||||
"phone": "Telefon",
|
"phone": "Telefon",
|
||||||
|
"please-confirm-the-deletion-of-card": "Bitte bestätige die Löschung der Karte",
|
||||||
|
"please-confirm-the-deletion-of-donation": "Bitte bestätige die Löschung des Sponsorings",
|
||||||
|
"please-confirm-the-deletion-of-runner": "Bitte bestätige die Löschung der Läufer:in",
|
||||||
|
"please-confirm-the-deletion-of-scan": "Bitte bestätige die Löschung des Scans",
|
||||||
"please-copy-the-token-and-store-it-somewhere-save": "Bitte kopiere dir den Token und bewahre ihn gut auf.",
|
"please-copy-the-token-and-store-it-somewhere-save": "Bitte kopiere dir den Token und bewahre ihn gut auf.",
|
||||||
"please-provide-a-password": "Bitte gebe ein Passwort an...",
|
"please-provide-a-password": "Bitte gebe ein Passwort an...",
|
||||||
"please-provide-the-nessecary-information-to-add-a-new-donor": "Bitte mach die Notwendigen Angaben, um eine neue Sponsor:in zu erstellen",
|
"please-provide-the-nessecary-information-to-add-a-new-donor": "Bitte mach die Notwendigen Angaben, um eine neue Sponsor:in zu erstellen",
|
||||||
@@ -320,8 +345,10 @@
|
|||||||
"please-provide-the-required-information-to-add-a-new-track": "Bitte die benötigten Informationen angeben.",
|
"please-provide-the-required-information-to-add-a-new-track": "Bitte die benötigten Informationen angeben.",
|
||||||
"please-provide-the-required-information-to-add-a-new-user": "Bitte gebe alle nötigen Informationen an, im die neue Benutzer:in zu erstellen.",
|
"please-provide-the-required-information-to-add-a-new-user": "Bitte gebe alle nötigen Informationen an, im die neue Benutzer:in zu erstellen.",
|
||||||
"please-provide-the-required-information-to-create-a-new-scanstation": "Bitte gebe alle für eine Scannerstation notwendigen Informationen an",
|
"please-provide-the-required-information-to-create-a-new-scanstation": "Bitte gebe alle für eine Scannerstation notwendigen Informationen an",
|
||||||
|
"please-provide-the-required-information-to-create-a-new-statsclient": "Bitte gebe alle für einen Statsclient notwendigen Informationen an",
|
||||||
"please-request-a-new-reset-mail": "Bitte eine neue Passwortreset-Mail anfordern...",
|
"please-request-a-new-reset-mail": "Bitte eine neue Passwortreset-Mail anfordern...",
|
||||||
"please-wait-a-moment-your-login-is-still-being-processed": "Bitte warte einen Moment, deine Anmeldung wird verarbeitet",
|
"please-wait-a-moment-your-login-is-still-being-processed": "Bitte warte einen Moment, deine Anmeldung wird verarbeitet",
|
||||||
|
"prefix": "Prefix",
|
||||||
"privacy": "Datenschutz",
|
"privacy": "Datenschutz",
|
||||||
"privacy-loading": "Datenschutzerklärung lädt...",
|
"privacy-loading": "Datenschutzerklärung lädt...",
|
||||||
"profile": "Profil",
|
"profile": "Profil",
|
||||||
@@ -336,6 +363,7 @@
|
|||||||
"reset-password": "Passwort zurücksetzen",
|
"reset-password": "Passwort zurücksetzen",
|
||||||
"runner": "Läufer:in",
|
"runner": "Läufer:in",
|
||||||
"runner-added": "Läufer:in hinzugefügt",
|
"runner-added": "Läufer:in hinzugefügt",
|
||||||
|
"runner-deleted": "Läufer:in gelöscht",
|
||||||
"runner-import": "Läufer:innen Import",
|
"runner-import": "Läufer:innen Import",
|
||||||
"runner-is-being-added": "Läufer:in wird hinzugefügt...",
|
"runner-is-being-added": "Läufer:in wird hinzugefügt...",
|
||||||
"runner-updated": "Läufer:in aktualisiert!",
|
"runner-updated": "Läufer:in aktualisiert!",
|
||||||
@@ -347,6 +375,7 @@
|
|||||||
"save": "Speichern",
|
"save": "Speichern",
|
||||||
"save-changes": "Änderungen speichern",
|
"save-changes": "Änderungen speichern",
|
||||||
"scan-added": "Scan hinzugefügt",
|
"scan-added": "Scan hinzugefügt",
|
||||||
|
"scan-deleted": "Scan gelöscht",
|
||||||
"scan-is-being-updated": "Scan wird aktualisiert",
|
"scan-is-being-updated": "Scan wird aktualisiert",
|
||||||
"scan-with-fixed-distance": "Scan mit Festdistanz",
|
"scan-with-fixed-distance": "Scan mit Festdistanz",
|
||||||
"scans": "Scans",
|
"scans": "Scans",
|
||||||
@@ -371,7 +400,12 @@
|
|||||||
"something-about-the-group": "Infos zur Gruppe",
|
"something-about-the-group": "Infos zur Gruppe",
|
||||||
"sponsoring-quittungs-liste_herunterladen": "Sponsoring-Quittungs-Liste herunterladen",
|
"sponsoring-quittungs-liste_herunterladen": "Sponsoring-Quittungs-Liste herunterladen",
|
||||||
"sponsorings": "Sponsoringerklaerungen",
|
"sponsorings": "Sponsoringerklaerungen",
|
||||||
|
"station-deleted": "Scannerstation gelöscht",
|
||||||
"stats-are-being-loaded": "Die Statistiken werden geladen...",
|
"stats-are-being-loaded": "Die Statistiken werden geladen...",
|
||||||
|
"statsclient-deleted": "Statsclient wurde gelöscht",
|
||||||
|
"statsclient-is-being-added": "Statsclient wird angelegt...",
|
||||||
|
"statsclients": "Statsclient (aka Beamershow)",
|
||||||
|
"statsclients-are-being-loaded": "Statsclients werden geladen",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"stuff-that-could-harm-your-profile": "Einstellungen, die deinem Profil nachhaltig schaden können",
|
"stuff-that-could-harm-your-profile": "Einstellungen, die deinem Profil nachhaltig schaden können",
|
||||||
"successful-password-reset": "Passwort erfolgreich zurückgesetzt!",
|
"successful-password-reset": "Passwort erfolgreich zurückgesetzt!",
|
||||||
@@ -387,6 +421,7 @@
|
|||||||
"the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number": "Die angegebene Telefonnummer ist nicht korrekt. <br /> Bitte gebe eine Telefonnummer im internationalen Format an...",
|
"the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number": "Die angegebene Telefonnummer ist nicht korrekt. <br /> Bitte gebe eine Telefonnummer im internationalen Format an...",
|
||||||
"the-scans-distance-must-be-greater-than-0m": "Die Distanz muss größer als 0m sein.",
|
"the-scans-distance-must-be-greater-than-0m": "Die Distanz muss größer als 0m sein.",
|
||||||
"the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "Der Scannerstation Token wird nur einmal angezeigt - du kannst ihn nicht ändern oder ihn dir nochmal anzeigen lassen!",
|
"the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "Der Scannerstation Token wird nur einmal angezeigt - du kannst ihn nicht ändern oder ihn dir nochmal anzeigen lassen!",
|
||||||
|
"the-statsclient-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "Der Statsclient Token wird nur einmal angezeigt - du kannst ihn nicht ändern oder ihn dir nochmal anzeigen lassen!",
|
||||||
"there-are-no-cards-yet": "Es gibt noch keine Läuferkarten.",
|
"there-are-no-cards-yet": "Es gibt noch keine Läuferkarten.",
|
||||||
"there-are-no-contacts-added-yet": "Es wurden noch keine Kontakte hinzugefügt.",
|
"there-are-no-contacts-added-yet": "Es wurden noch keine Kontakte hinzugefügt.",
|
||||||
"there-are-no-donations-yet": "Es gibt noch keine Sponsorings",
|
"there-are-no-donations-yet": "Es gibt noch keine Sponsorings",
|
||||||
@@ -400,11 +435,14 @@
|
|||||||
"this-card-is": "Diese Karte ist",
|
"this-card-is": "Diese Karte ist",
|
||||||
"this-might-take-a-moment": "Das könnte einen kleinen Moment dauern",
|
"this-might-take-a-moment": "Das könnte einen kleinen Moment dauern",
|
||||||
"this-scanstation-is": "Diese Station ist",
|
"this-scanstation-is": "Diese Station ist",
|
||||||
|
"timestamp": "Timestamp",
|
||||||
"token": "Token",
|
"token": "Token",
|
||||||
"total-distance": "gelaufene Strecke",
|
"total-distance": "gelaufene Strecke",
|
||||||
"total-donation-amount": "Gesamtbetrag",
|
"total-donation-amount": "Gesamtbetrag",
|
||||||
|
"total-donation-count": "Gesamte Sponsorings",
|
||||||
"total-donations": "Spendensumme",
|
"total-donations": "Spendensumme",
|
||||||
"total-paid-amount": "Gezahlter Gesamtbetrag",
|
"total-donors": "gesamte Sponsor:innen",
|
||||||
|
"total-paid-amount": "Gezahlt",
|
||||||
"total-scans": "gesamte Scans",
|
"total-scans": "gesamte Scans",
|
||||||
"total_donation_amount_in_eur": "Gesamtbetrag in €",
|
"total_donation_amount_in_eur": "Gesamtbetrag in €",
|
||||||
"track": "Track",
|
"track": "Track",
|
||||||
@@ -453,6 +491,7 @@
|
|||||||
"you-can-enter-the-donations-paid-amount-manually-or-use-the-max-button-to-use-the-donations-exact-amount": "Du kannst den Betrag der Zahlung entweder manuell eingeben oder über den MAX Button auf den Spendenbetrag setzen",
|
"you-can-enter-the-donations-paid-amount-manually-or-use-the-max-button-to-use-the-donations-exact-amount": "Du kannst den Betrag der Zahlung entweder manuell eingeben oder über den MAX Button auf den Spendenbetrag setzen",
|
||||||
"you-can-now-use-your-new-password-to-log-in-to-your-account": "Du kannst dich jetzt mit deinem neuen Passwort anmelden! 🎉",
|
"you-can-now-use-your-new-password-to-log-in-to-your-account": "Du kannst dich jetzt mit deinem neuen Passwort anmelden! 🎉",
|
||||||
"you-can-provide-a-runner-but-you-dont-have-to": "Du kannst eine Läufer:in angeben, musst aber nicht.",
|
"you-can-provide-a-runner-but-you-dont-have-to": "Du kannst eine Läufer:in angeben, musst aber nicht.",
|
||||||
|
"you-dont-have-any-scanclients-yet": "Es gibt noch keine Statsclients",
|
||||||
"you-dont-have-any-scanstations-yet": "Es gibt noch keine Scannerstationen",
|
"you-dont-have-any-scanstations-yet": "Es gibt noch keine Scannerstationen",
|
||||||
"you-have-to-provide-an-organization": "Du musst eine Organisation angeben",
|
"you-have-to-provide-an-organization": "Du musst eine Organisation angeben",
|
||||||
"you-have-to-save-your-changes-to-generate-a-link": "Du musst deine Änderungen speichern, um einen Link zu generieren.",
|
"you-have-to-save-your-changes-to-generate-a-link": "Du musst deine Änderungen speichern, um einen Link zu generieren.",
|
||||||
|
|||||||
+40
-2
@@ -10,6 +10,7 @@
|
|||||||
"add-or-update-a-payment": "Add or update a payment",
|
"add-or-update-a-payment": "Add or update a payment",
|
||||||
"add-scan": "Add scan",
|
"add-scan": "Add scan",
|
||||||
"add-the-first-scanstation": "Add your first scanstation.",
|
"add-the-first-scanstation": "Add your first scanstation.",
|
||||||
|
"add-the-first-statsclient": "Add your first statsclient.",
|
||||||
"add-user-group": "Add User Group",
|
"add-user-group": "Add User Group",
|
||||||
"add-your-first-card": "Add your first card",
|
"add-your-first-card": "Add your first card",
|
||||||
"add-your-first-contact": "Add your first contact",
|
"add-your-first-contact": "Add your first contact",
|
||||||
@@ -29,17 +30,22 @@
|
|||||||
"address-is-required": "Address is required",
|
"address-is-required": "Address is required",
|
||||||
"after-deletion-we-cant-restore-your-old-profile": "After deletion we can't restore your old profile!",
|
"after-deletion-we-cant-restore-your-old-profile": "After deletion we can't restore your old profile!",
|
||||||
"after-the-update-youll-get-logged-out-please-login-with-your-new-password-after-that": "After the update you'll get logged out - Please login with your new password after that.",
|
"after-the-update-youll-get-logged-out-please-login-with-your-new-password-after-that": "After the update you'll get logged out - Please login with your new password after that.",
|
||||||
|
"all": "all",
|
||||||
"all-associated-donations-will-get-deleted-as-well": "All associated donations will get deleted as well",
|
"all-associated-donations-will-get-deleted-as-well": "All associated donations will get deleted as well",
|
||||||
"all-associated-runners-will-be-deleted-too": "All associated runners will be deleted too!",
|
"all-associated-runners-will-be-deleted-too": "All associated runners will be deleted too!",
|
||||||
|
"all-associated-scans-will-get-deleted-as-well": "All associated scans will get deleted as well",
|
||||||
"all-associated-teams-and-runners-will-be-deleted-too": "All associated teams and runners will be deleted too!",
|
"all-associated-teams-and-runners-will-be-deleted-too": "All associated teams and runners will be deleted too!",
|
||||||
"already-paid": "Already paid",
|
"already-paid": "Already paid",
|
||||||
"amount": "Amount",
|
"amount": "Amount",
|
||||||
"amount-per-kilometer": "Amount per kilometer",
|
"amount-per-kilometer": "Amount per kilometer",
|
||||||
"apartment-suite-etc": "Apartment, suite, etc.",
|
"apartment-suite-etc": "Apartment, suite, etc.",
|
||||||
|
"api-endpoint": "API-Endpoint",
|
||||||
"application_name": "Lauf für Kaya! - Admin",
|
"application_name": "Lauf für Kaya! - Admin",
|
||||||
"applying-changes": "Applying Changes",
|
"applying-changes": "Applying Changes",
|
||||||
"attention": "Attention!",
|
"attention": "Attention!",
|
||||||
"author": "Author",
|
"author": "Author",
|
||||||
|
"average-distance": "average distance",
|
||||||
|
"average-donation": "average donation",
|
||||||
"bitte-bestaetige-diese-laeufer-fuer-den-import": "Please confirm these runners for import.",
|
"bitte-bestaetige-diese-laeufer-fuer-den-import": "Please confirm these runners for import.",
|
||||||
"by": "by",
|
"by": "by",
|
||||||
"cancel": "Cancel",
|
"cancel": "Cancel",
|
||||||
@@ -47,12 +53,16 @@
|
|||||||
"cancel-keep-donor": "Cancel, keep donor",
|
"cancel-keep-donor": "Cancel, keep donor",
|
||||||
"cancel-keep-my-profile": "Cancel, keep my profile",
|
"cancel-keep-my-profile": "Cancel, keep my profile",
|
||||||
"cancel-keep-organization": "Cancel, keep organization",
|
"cancel-keep-organization": "Cancel, keep organization",
|
||||||
|
"cancel-keep-station": "Cancel, keep station",
|
||||||
|
"cancel-keep-statsclient": "Cancel and keep statsclient",
|
||||||
"cancel-keep-team": "Cancel, keep team",
|
"cancel-keep-team": "Cancel, keep team",
|
||||||
"cannot-reset-your-password-directly": "Bummer. We unfortunately cannot reset your password directly. Please send us a mail and confirm your identity",
|
"cannot-reset-your-password-directly": "Bummer. We unfortunately cannot reset your password directly. Please send us a mail and confirm your identity",
|
||||||
|
"card": "card",
|
||||||
"card-added": "Card added",
|
"card-added": "Card added",
|
||||||
"card-deleted": "Card deleted",
|
"card-deleted": "Card deleted",
|
||||||
"card-updated": "Card updated",
|
"card-updated": "Card updated",
|
||||||
"cards": "Cards",
|
"cards": "Cards",
|
||||||
|
"cards-deleted": "Cards deleted",
|
||||||
"certificates": "Certificates",
|
"certificates": "Certificates",
|
||||||
"change-your-password-here": "Change your password here",
|
"change-your-password-here": "Change your password here",
|
||||||
"changing-your-password": "Changing your password",
|
"changing-your-password": "Changing your password",
|
||||||
@@ -61,12 +71,15 @@
|
|||||||
"click-to-copy-token-to-clipboard": "Click to copy the token to your clipboard",
|
"click-to-copy-token-to-clipboard": "Click to copy the token to your clipboard",
|
||||||
"close": "Close",
|
"close": "Close",
|
||||||
"code": "Code",
|
"code": "Code",
|
||||||
|
"config-codes": "Config codes",
|
||||||
"configure-the-tracks-and-minimum-lap-times": "configure the tracks & minimum lap times",
|
"configure-the-tracks-and-minimum-lap-times": "configure the tracks & minimum lap times",
|
||||||
"confirm": "Confirm",
|
"confirm": "Confirm",
|
||||||
"confirm-delete": "Confirm Delete",
|
"confirm-delete": "Confirm Delete",
|
||||||
"confirm-delete-donor-with-all-donations": "Confirm, delete donor with all donations",
|
"confirm-delete-donor-with-all-donations": "Confirm, delete donor with all donations",
|
||||||
"confirm-delete-my-user-profile": "Confirm, delete my user profile",
|
"confirm-delete-my-user-profile": "Confirm, delete my user profile",
|
||||||
"confirm-delete-organization-and-associated-teams-runners": "Confirm, delete organization and associated teams+runners.",
|
"confirm-delete-organization-and-associated-teams-runners": "Confirm, delete organization and associated teams+runners.",
|
||||||
|
"confirm-delete-station-with-all-scans": "Confirm deletion of station with all scans",
|
||||||
|
"confirm-delete-statsclient": "Confirm, delete statsclient",
|
||||||
"confirm-delete-team-and-associated-runners": "Confirm, delete team and associated runners.",
|
"confirm-delete-team-and-associated-runners": "Confirm, delete team and associated runners.",
|
||||||
"confirm-deletion": "Confirm Deletion",
|
"confirm-deletion": "Confirm Deletion",
|
||||||
"confirm-the-new-password": "Confirm the new password",
|
"confirm-the-new-password": "Confirm the new password",
|
||||||
@@ -94,6 +107,7 @@
|
|||||||
"create-a-new-runner": "Create a new Runner",
|
"create-a-new-runner": "Create a new Runner",
|
||||||
"create-a-new-scan-fixed-only": "Create a new scan (fixed only)",
|
"create-a-new-scan-fixed-only": "Create a new scan (fixed only)",
|
||||||
"create-a-new-scanstation": "Create a new station",
|
"create-a-new-scanstation": "Create a new station",
|
||||||
|
"create-a-new-statsclient": "Create a new statsclient",
|
||||||
"create-a-new-team": "Create a new team",
|
"create-a-new-team": "Create a new team",
|
||||||
"create-a-new-track": "Create a new Track",
|
"create-a-new-track": "Create a new Track",
|
||||||
"create-a-new-user": "Create a new User",
|
"create-a-new-user": "Create a new User",
|
||||||
@@ -133,6 +147,7 @@
|
|||||||
"an_error_happened_while_fetching_the_data": "An error happened while fetching the data"
|
"an_error_happened_while_fetching_the_data": "An error happened while fetching the data"
|
||||||
},
|
},
|
||||||
"delete": "Delete",
|
"delete": "Delete",
|
||||||
|
"delete-cards": "Delete cards",
|
||||||
"delete-contact": "Delete Contact",
|
"delete-contact": "Delete Contact",
|
||||||
"delete-donation": "Delete Donation",
|
"delete-donation": "Delete Donation",
|
||||||
"delete-donor": "Delete donor",
|
"delete-donor": "Delete donor",
|
||||||
@@ -141,7 +156,9 @@
|
|||||||
"delete-profile": "Delete Profile",
|
"delete-profile": "Delete Profile",
|
||||||
"delete-runner": "Delete Runner",
|
"delete-runner": "Delete Runner",
|
||||||
"delete-scan": "Delete scan",
|
"delete-scan": "Delete scan",
|
||||||
|
"delete-scans": "Delete scans",
|
||||||
"delete-station": "Delete station",
|
"delete-station": "Delete station",
|
||||||
|
"delete-statsclient": "Delete statsclient",
|
||||||
"delete-team": "Delete Team",
|
"delete-team": "Delete Team",
|
||||||
"delete-user": "Delete User",
|
"delete-user": "Delete User",
|
||||||
"deleted-scan": "Deleted scan",
|
"deleted-scan": "Deleted scan",
|
||||||
@@ -166,10 +183,11 @@
|
|||||||
"donation-updated": "Donation updated",
|
"donation-updated": "Donation updated",
|
||||||
"donation_added": "Donation_added",
|
"donation_added": "Donation_added",
|
||||||
"donations": "Donations",
|
"donations": "Donations",
|
||||||
|
"donations-are-being-loaded": "donations are being loaded",
|
||||||
"donor": "Donor",
|
"donor": "Donor",
|
||||||
"donor-added": "Donor added",
|
"donor-added": "Donor added",
|
||||||
"donor-deleted": "donor deleted",
|
"donor-deleted": "donor deleted",
|
||||||
"donor-has-no-associated-donations": "Donor has no associated donations.",
|
"donor-has-no-associated-donations": "No donations",
|
||||||
"donor-is-being-added": "Donor is being added...",
|
"donor-is-being-added": "Donor is being added...",
|
||||||
"donor-is-being-updated": "Donor is being updated",
|
"donor-is-being-updated": "Donor is being updated",
|
||||||
"donors": "Donors",
|
"donors": "Donors",
|
||||||
@@ -235,6 +253,7 @@
|
|||||||
"invalid": "Invalid",
|
"invalid": "Invalid",
|
||||||
"invalid-mail-reset": "the provided email is invalid",
|
"invalid-mail-reset": "the provided email is invalid",
|
||||||
"just-enter-how-many-you-want-and-the-system-will-create-them": "Just enter how many you want and the system will create them",
|
"just-enter-how-many-you-want-and-the-system-will-create-them": "Just enter how many you want and the system will create them",
|
||||||
|
"key": "Key",
|
||||||
"laeufer-hinzufuegen": "Add runner",
|
"laeufer-hinzufuegen": "Add runner",
|
||||||
"laeufer-importieren": "Läufer importieren",
|
"laeufer-importieren": "Läufer importieren",
|
||||||
"laptime": "Laptime",
|
"laptime": "Laptime",
|
||||||
@@ -267,6 +286,7 @@
|
|||||||
"name": "Name",
|
"name": "Name",
|
||||||
"name-is-required": "Name is required",
|
"name-is-required": "Name is required",
|
||||||
"new-password": "New password",
|
"new-password": "New password",
|
||||||
|
"no-address": "no address",
|
||||||
"no-contact-found": "No contacts found",
|
"no-contact-found": "No contacts found",
|
||||||
"no-contact-selected": "No contact selected",
|
"no-contact-selected": "No contact selected",
|
||||||
"no-contact-specified": "no contact specified",
|
"no-contact-specified": "no contact specified",
|
||||||
@@ -307,6 +327,10 @@
|
|||||||
"permissions": "Permissions",
|
"permissions": "Permissions",
|
||||||
"permissions-updated": "Permissions updated!",
|
"permissions-updated": "Permissions updated!",
|
||||||
"phone": "Phone",
|
"phone": "Phone",
|
||||||
|
"please-confirm-the-deletion-of-card": "Please confirm the deletion of this card",
|
||||||
|
"please-confirm-the-deletion-of-donation": "Please confirm the deletion of this donation",
|
||||||
|
"please-confirm-the-deletion-of-runner": "Please confirm the deletion of this runner",
|
||||||
|
"please-confirm-the-deletion-of-scan": "Please confirm the deletion of scan",
|
||||||
"please-copy-the-token-and-store-it-somewhere-save": "Please copy the token and store it somewhere safe.",
|
"please-copy-the-token-and-store-it-somewhere-save": "Please copy the token and store it somewhere safe.",
|
||||||
"please-provide-a-password": "Please provide a password...",
|
"please-provide-a-password": "Please provide a password...",
|
||||||
"please-provide-the-nessecary-information-to-add-a-new-donor": "Please provide the nessecary information to add a new donor",
|
"please-provide-the-nessecary-information-to-add-a-new-donor": "Please provide the nessecary information to add a new donor",
|
||||||
@@ -321,8 +345,10 @@
|
|||||||
"please-provide-the-required-information-to-add-a-new-track": "Please provide the required information to add a new track.",
|
"please-provide-the-required-information-to-add-a-new-track": "Please provide the required information to add a new track.",
|
||||||
"please-provide-the-required-information-to-add-a-new-user": "Please provide the required information to add a new user.",
|
"please-provide-the-required-information-to-add-a-new-user": "Please provide the required information to add a new user.",
|
||||||
"please-provide-the-required-information-to-create-a-new-scanstation": "Please provide the required information to create a new scanstation",
|
"please-provide-the-required-information-to-create-a-new-scanstation": "Please provide the required information to create a new scanstation",
|
||||||
|
"please-provide-the-required-information-to-create-a-new-statsclient": "Please provide the required information to create a new statsclient",
|
||||||
"please-request-a-new-reset-mail": "Please request a new reset mail...",
|
"please-request-a-new-reset-mail": "Please request a new reset mail...",
|
||||||
"please-wait-a-moment-your-login-is-still-being-processed": "Please wait a moment, your login is still being processed",
|
"please-wait-a-moment-your-login-is-still-being-processed": "Please wait a moment, your login is still being processed",
|
||||||
|
"prefix": "Prefix",
|
||||||
"privacy": "Privacy",
|
"privacy": "Privacy",
|
||||||
"privacy-loading": "Privacy loading...",
|
"privacy-loading": "Privacy loading...",
|
||||||
"profile": "Profile",
|
"profile": "Profile",
|
||||||
@@ -337,6 +363,7 @@
|
|||||||
"reset-password": "Reset your password",
|
"reset-password": "Reset your password",
|
||||||
"runner": "Runner",
|
"runner": "Runner",
|
||||||
"runner-added": "Runner added",
|
"runner-added": "Runner added",
|
||||||
|
"runner-deleted": "runner deleted",
|
||||||
"runner-import": "Runner Import",
|
"runner-import": "Runner Import",
|
||||||
"runner-is-being-added": "Runner is being added...",
|
"runner-is-being-added": "Runner is being added...",
|
||||||
"runner-updated": "Runner updated!",
|
"runner-updated": "Runner updated!",
|
||||||
@@ -348,6 +375,7 @@
|
|||||||
"save": "Save",
|
"save": "Save",
|
||||||
"save-changes": "Save Changes",
|
"save-changes": "Save Changes",
|
||||||
"scan-added": "Scan added",
|
"scan-added": "Scan added",
|
||||||
|
"scan-deleted": "scan deleted",
|
||||||
"scan-is-being-updated": "Scan is being updated",
|
"scan-is-being-updated": "Scan is being updated",
|
||||||
"scan-with-fixed-distance": "Scan with fixed distance",
|
"scan-with-fixed-distance": "Scan with fixed distance",
|
||||||
"scans": "Scans",
|
"scans": "Scans",
|
||||||
@@ -372,7 +400,12 @@
|
|||||||
"something-about-the-group": "Something about the group...",
|
"something-about-the-group": "Something about the group...",
|
||||||
"sponsoring-quittungs-liste_herunterladen": "Download donor receipt list",
|
"sponsoring-quittungs-liste_herunterladen": "Download donor receipt list",
|
||||||
"sponsorings": "Sponsorings",
|
"sponsorings": "Sponsorings",
|
||||||
|
"station-deleted": "station deleted",
|
||||||
"stats-are-being-loaded": "stats are being loaded...",
|
"stats-are-being-loaded": "stats are being loaded...",
|
||||||
|
"statsclient-deleted": "Deleted statsclient",
|
||||||
|
"statsclient-is-being-added": "Statsclient is being added...",
|
||||||
|
"statsclients": "Statsclients (aka Beamershow)",
|
||||||
|
"statsclients-are-being-loaded": "Loading statsclients",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"stuff-that-could-harm-your-profile": "Stuff that could harm your profile",
|
"stuff-that-could-harm-your-profile": "Stuff that could harm your profile",
|
||||||
"successful-password-reset": "Successful password reset!",
|
"successful-password-reset": "Successful password reset!",
|
||||||
@@ -388,6 +421,7 @@
|
|||||||
"the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number": "the provided phone number is invalid.<br />please enter a valid international number...",
|
"the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number": "the provided phone number is invalid.<br />please enter a valid international number...",
|
||||||
"the-scans-distance-must-be-greater-than-0m": "The scan's distance must be greater than 0m",
|
"the-scans-distance-must-be-greater-than-0m": "The scan's distance must be greater than 0m",
|
||||||
"the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "The scanstation api token will only get displayed once - you won't be able to change or view it again!",
|
"the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "The scanstation api token will only get displayed once - you won't be able to change or view it again!",
|
||||||
|
"the-statsclient-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "The statsclient api token will only get displayed once - you won't be able to change or view it again!",
|
||||||
"there-are-no-cards-yet": "There are no cards yet.",
|
"there-are-no-cards-yet": "There are no cards yet.",
|
||||||
"there-are-no-contacts-added-yet": "There are no contacts added yet.",
|
"there-are-no-contacts-added-yet": "There are no contacts added yet.",
|
||||||
"there-are-no-donations-yet": "There are no donations yet",
|
"there-are-no-donations-yet": "There are no donations yet",
|
||||||
@@ -401,11 +435,14 @@
|
|||||||
"this-card-is": "This card is",
|
"this-card-is": "This card is",
|
||||||
"this-might-take-a-moment": "This might take a moment 👀",
|
"this-might-take-a-moment": "This might take a moment 👀",
|
||||||
"this-scanstation-is": "This scanstation is",
|
"this-scanstation-is": "This scanstation is",
|
||||||
|
"timestamp": "timestamp",
|
||||||
"token": "Token",
|
"token": "Token",
|
||||||
"total-distance": "total distance",
|
"total-distance": "total distance",
|
||||||
"total-donation-amount": "total donation amount",
|
"total-donation-amount": "total donation amount",
|
||||||
|
"total-donation-count": "total donations (count)",
|
||||||
"total-donations": "total donations",
|
"total-donations": "total donations",
|
||||||
"total-paid-amount": "Total paid amount",
|
"total-donors": "total donors",
|
||||||
|
"total-paid-amount": "Paid",
|
||||||
"total-scans": "total scans",
|
"total-scans": "total scans",
|
||||||
"total_donation_amount_in_eur": "Total donation amount in €",
|
"total_donation_amount_in_eur": "Total donation amount in €",
|
||||||
"track": "Track",
|
"track": "Track",
|
||||||
@@ -454,6 +491,7 @@
|
|||||||
"you-can-enter-the-donations-paid-amount-manually-or-use-the-max-button-to-use-the-donations-exact-amount": "You can enter the donation's paid amount manually or use the MAX button to use the donation's exact amount.",
|
"you-can-enter-the-donations-paid-amount-manually-or-use-the-max-button-to-use-the-donations-exact-amount": "You can enter the donation's paid amount manually or use the MAX button to use the donation's exact amount.",
|
||||||
"you-can-now-use-your-new-password-to-log-in-to-your-account": "You can now use your new password to log in to your account! 🎉",
|
"you-can-now-use-your-new-password-to-log-in-to-your-account": "You can now use your new password to log in to your account! 🎉",
|
||||||
"you-can-provide-a-runner-but-you-dont-have-to": "You can provide a runner, but you don't have to.",
|
"you-can-provide-a-runner-but-you-dont-have-to": "You can provide a runner, but you don't have to.",
|
||||||
|
"you-dont-have-any-scanclients-yet": "You don't have any statsclients yet",
|
||||||
"you-dont-have-any-scanstations-yet": "You don't have any scanstations yet",
|
"you-dont-have-any-scanstations-yet": "You don't have any scanstations yet",
|
||||||
"you-have-to-provide-an-organization": "You have to provide an organization",
|
"you-have-to-provide-an-organization": "You have to provide an organization",
|
||||||
"you-have-to-save-your-changes-to-generate-a-link": "You have to save your changes to generate a link.",
|
"you-have-to-save-your-changes-to-generate-a-link": "You have to save your changes to generate a link.",
|
||||||
|
|||||||
+1
-1
@@ -1,6 +1,6 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
mode: 'jit',
|
mode: 'jit',
|
||||||
purge: [ './src/**/*.svelte' ],
|
content: [ './src/**/*.svelte' ],
|
||||||
theme: {
|
theme: {
|
||||||
extend: {
|
extend: {
|
||||||
colors: {
|
colors: {
|
||||||
|
|||||||
+3
-3
@@ -1,5 +1,5 @@
|
|||||||
const fs = require('fs');
|
import fs from 'fs';
|
||||||
const package = JSON.parse(fs.readFileSync(`./package.json`, { encoding: 'utf-8' }));
|
const packagejson = JSON.parse(fs.readFileSync(`./package.json`, { encoding: 'utf-8' }));
|
||||||
const original = fs.readFileSync(`./index.html`, { encoding: 'utf-8' });
|
const original = fs.readFileSync(`./index.html`, { encoding: 'utf-8' });
|
||||||
let out = original.replace(/RELEASE_INFO-(\S)+-RELEASE_INFO/gi, 'RELEASE_INFO-' + package.version + '-RELEASE_INFO');
|
let out = original.replace(/RELEASE_INFO-(\S)+-RELEASE_INFO/gi, 'RELEASE_INFO-' + packagejson.version + '-RELEASE_INFO');
|
||||||
fs.writeFileSync(`./index.html`, out);
|
fs.writeFileSync(`./index.html`, out);
|
||||||
Loaded 100 of 101 files, more files were not shown because too many files have changed in this diff.
Show more
Reference in new issue
Block a user