Compare commits
127
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
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 |
No files matched your search
@@ -1 +1,2 @@
|
|||||||
public/env.sample.js
|
public/env.sample.js
|
||||||
|
.pnpm-store
|
||||||
+18
-11
@@ -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
|
||||||
@@ -51,10 +62,8 @@ steps:
|
|||||||
password:
|
password:
|
||||||
from_secret: docker_password
|
from_secret: docker_password
|
||||||
build_args:
|
build_args:
|
||||||
- NPM_REGISTRY_DOMAIN:
|
- NPM_REGISTRY_URL:
|
||||||
from_secret: npmjs_domain
|
from_secret: npm_url
|
||||||
- NPM_REGISTRY_TOKEN:
|
|
||||||
from_secret: npmjs_token
|
|
||||||
repo: lfk/frontend
|
repo: lfk/frontend
|
||||||
tags:
|
tags:
|
||||||
- dev
|
- dev
|
||||||
@@ -80,10 +89,8 @@ steps:
|
|||||||
password:
|
password:
|
||||||
from_secret: docker_password
|
from_secret: docker_password
|
||||||
build_args:
|
build_args:
|
||||||
- NPM_REGISTRY_DOMAIN:
|
- NPM_REGISTRY_URL:
|
||||||
from_secret: npmjs_domain
|
from_secret: npm_url
|
||||||
- NPM_REGISTRY_TOKEN:
|
|
||||||
from_secret: npmjs_token
|
|
||||||
repo: lfk/frontend
|
repo: lfk/frontend
|
||||||
tags:
|
tags:
|
||||||
- "${DRONE_TAG}"
|
- "${DRONE_TAG}"
|
||||||
|
|||||||
+1
-6
@@ -1,11 +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
|
|
||||||
pnpm-lock.yaml
|
|
||||||
+111
@@ -2,9 +2,120 @@
|
|||||||
|
|
||||||
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.
|
||||||
|
|
||||||
|
#### [0.17.3](https://git.odit.services/lfk/frontend/compare/0.17.2...0.17.3)
|
||||||
|
|
||||||
|
- dependency fixes [`3ea7a01`](https://git.odit.services/lfk/frontend/commit/3ea7a015a9beba3c2e4d3eb966f24ff6d4ac786e)
|
||||||
|
- 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)
|
#### [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)
|
- 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)
|
#### [0.16.0](https://git.odit.services/lfk/frontend/compare/0.15.6...0.16.0)
|
||||||
|
|
||||||
|
|||||||
+8
-5
@@ -1,11 +1,14 @@
|
|||||||
FROM registry.odit.services/hub/library/node:19.5.0-alpine3.16 as build
|
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 npx pnpm i
|
COPY package.json pnpm-lock.yaml *.config.js *.config.cjs index.html ./
|
||||||
COPY package.json *.config.js postcss.config.cjs tailwind.config.js vite.config.js 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/library/nginx-brotli:3.15 as final
|
FROM registry.odit.services/library/nginx-brotli:3.15 as final
|
||||||
COPY --from=build /app/dist /usr/share/nginx/html
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
|
|||||||
+1
-1
@@ -13,7 +13,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<span style="display: none;visibility: hidden;" id="buildinfo">RELEASE_INFO-0.16.1-RELEASE_INFO</span>
|
<span style="display: none;visibility: hidden;" id="buildinfo">RELEASE_INFO-0.17.3-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>
|
||||||
|
|||||||
+31
-24
@@ -1,6 +1,7 @@
|
|||||||
{
|
{
|
||||||
"name": "@odit/lfk-frontend",
|
"name": "@odit/lfk-frontend",
|
||||||
"version": "0.16.1",
|
"version": "0.17.3",
|
||||||
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"i18n-order": "node order.js",
|
"i18n-order": "node order.js",
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
@@ -10,31 +11,17 @@
|
|||||||
},
|
},
|
||||||
"license": "CC-BY-NC-SA-4.0",
|
"license": "CC-BY-NC-SA-4.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@odit/lfk-client-js": "0.13.1",
|
"@odit/license-exporter": "0.0.12",
|
||||||
"@odit/license-exporter": "0.0.11",
|
"@sveltejs/vite-plugin-svelte": "2.0.4",
|
||||||
"@sveltejs/vite-plugin-svelte": "1.0.0-next.6",
|
"@types/html-minifier": "4.0.2",
|
||||||
"@types/html-minifier": "4.0.0",
|
"auto-changelog": "2.4.0",
|
||||||
"auto-changelog": "2.2.1",
|
"autoprefixer": "10.4.14",
|
||||||
"autoprefixer": "10.2.5",
|
|
||||||
"check-password-strength": "2.0.2",
|
|
||||||
"csvtojson": "2.0.10",
|
|
||||||
"gridjs": "3.4.0",
|
|
||||||
"html-minifier": "4.0.0",
|
"html-minifier": "4.0.0",
|
||||||
"localforage": "1.9.0",
|
"postcss": "8.4.21",
|
||||||
"marked": "2.0.3",
|
"release-it": "15.10.1",
|
||||||
"postcss": "8.2.10",
|
|
||||||
"release-it": "14.6.1",
|
|
||||||
"svelte": "3.37.0",
|
|
||||||
"svelte-focus-trap": "1.2.0",
|
|
||||||
"svelte-i18n": "3.3.9",
|
|
||||||
"svelte-preprocess": "4.7.0",
|
|
||||||
"svelte-select": "3.17.0",
|
"svelte-select": "3.17.0",
|
||||||
"tailwindcss": "3.2.4",
|
"tailwindcss": "3.3.1",
|
||||||
"tinro": "0.6.1",
|
"vite": "4.2.1"
|
||||||
"toastify-js": "1.10.0",
|
|
||||||
"validator": "13.5.2",
|
|
||||||
"vite": "2.1.5",
|
|
||||||
"xlsx": "0.16.9"
|
|
||||||
},
|
},
|
||||||
"release-it": {
|
"release-it": {
|
||||||
"git": {
|
"git": {
|
||||||
@@ -52,5 +39,25 @@
|
|||||||
"hooks": {
|
"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"
|
"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"
|
||||||
}
|
}
|
||||||
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@odit/lfk-client-js": "0.14.3",
|
||||||
|
"@paralleldrive/cuid2": "^2.2.0",
|
||||||
|
"@tanstack/svelte-table": "^8.8.5",
|
||||||
|
"@tanstack/table-core": "^8.8.5",
|
||||||
|
"check-password-strength": "2.0.7",
|
||||||
|
"csvtojson": "2.0.10",
|
||||||
|
"gridjs": "3.4.0",
|
||||||
|
"localforage": "1.10.0",
|
||||||
|
"marked": "2.0.3",
|
||||||
|
"svelte": "3.58.0",
|
||||||
|
"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
+4040
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.13.1","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":"Alexey Schebelev","repo":{"type":"git","url":"https://github.com/AlexxNB/tinro"},"description":"tinro is a tiny declarative router for Svelte","name":"tinro","license":"MIT","version":"0.6.12","licensetext":"MIT License\n\nCopyright (c) 2020 Alexey Schebelev\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"},{"author":"Varun A P","repo":{"type":"git","url":"https://github.com/apvarun/toastify-js"},"description":"Toastify is a lightweight, vanilla JS toast notification library.","name":"toastify-js","license":"MIT","version":"1.12.0","licensetext":"MIT License\n\nCopyright (c) 2018 apvarun\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"},{"author":"Chris O'Hara <cohara87@gmail.com>","repo":{"type":"git","url":"https://github.com/validatorjs/validator.js"},"description":"String validation and sanitization","name":"validator","license":"MIT","version":"13.9.0","licensetext":"Copyright (c) 2018 Chris O'Hara <cohara87@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"},{"author":"sheetjs","repo":{"type":"git","url":"https://github.comSheetJS/sheetjs"},"description":"SheetJS Spreadsheet data parser and writer","name":"xlsx","license":"Apache-2.0","version":"0.16.9","licensetext":" Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" meansLine truncated
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
<script>
|
<script>
|
||||||
import "toastify-js/src/toastify.css";
|
import "toastify-js/src/toastify.css";
|
||||||
import "gridjs/dist/theme/mermaid.css";
|
|
||||||
import { Route, router } from "tinro";
|
import { Route, router } from "tinro";
|
||||||
router.subscribe((routeInfo) => {
|
router.subscribe((routeInfo) => {
|
||||||
window.scrollTo(0, 0);
|
window.scrollTo(0, 0);
|
||||||
|
|||||||
@@ -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 { RunnerCardService } from "@odit/lfk-client-js";
|
import { RunnerCardService } from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
export let bulk_modal_open;
|
export let bulk_modal_open;
|
||||||
@@ -133,7 +133,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,
|
||||||
@@ -11,22 +11,37 @@
|
|||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
export let modal_open;
|
export let modal_open;
|
||||||
export let current_cards;
|
export let current_cards;
|
||||||
const getRunnerLabel = (option) =>
|
|
||||||
option.firstname + " " + (option.middlename || "") + " " + option.lastname;
|
const getRunnerLabel = (option) => {
|
||||||
const filterRunners = (label, filterText, option) =>
|
if (option.middlename) {
|
||||||
|
return option.firstname + " " + option.middlename + " " + option.lastname;
|
||||||
|
}
|
||||||
|
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()) ||
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
option.value.toString().startsWith(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;
|
||||||
(() => {
|
(() => {
|
||||||
@@ -82,65 +97,82 @@
|
|||||||
{#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 +184,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,10 +1,11 @@
|
|||||||
<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 current_cards;
|
||||||
export let runner = {};
|
export let runner = {};
|
||||||
@@ -12,15 +13,26 @@
|
|||||||
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) => {
|
||||||
|
if (filterText.startsWith("#")) {
|
||||||
|
return option.value.id == parseInt(filterText.replace("#",""))
|
||||||
|
}
|
||||||
|
return (
|
||||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
option.value.toString().startsWith(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();
|
||||||
|
function dataUpdated() {
|
||||||
|
dispatch('dataUpdated',);
|
||||||
|
}
|
||||||
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 };
|
||||||
@@ -65,6 +77,7 @@
|
|||||||
}).showToast();
|
}).showToast();
|
||||||
current_cards[current_cards.findIndex((c) => c.id === id)] = result;
|
current_cards[current_cards.findIndex((c) => c.id === id)] = result;
|
||||||
current_cards = current_cards;
|
current_cards = current_cards;
|
||||||
|
dataUpdated();
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
//
|
//
|
||||||
@@ -81,7 +94,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;
|
||||||
|
|||||||
@@ -6,40 +6,30 @@
|
|||||||
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 ThFilterStatus from "./ThFilterStatus.svelte";
|
||||||
|
import ThFilterRunner from "./ThFilterRunner.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) {
|
const handler = new DataHandler(current_cards, { rowsPerPage: 50 });
|
||||||
if (
|
const rows = handler.getRows();
|
||||||
c.code.toLowerCase().includes(searchvalue_lowercase) ||
|
|
||||||
c.runner?.firstname.toLowerCase().includes(searchvalue_lowercase) ||
|
|
||||||
c.runner?.middlename.toLowerCase().includes(searchvalue_lowercase) ||
|
|
||||||
c.runner?.lastname.toLowerCase().includes(searchvalue_lowercase) ||
|
|
||||||
should_display_based_on_id(c.id)
|
|
||||||
) {
|
|
||||||
return true;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
$: searchvalue = "";
|
|
||||||
$: searchvalue_lowercase = searchvalue.toLowerCase();
|
|
||||||
$: active_deletes = [];
|
$: active_deletes = [];
|
||||||
$: cards_show = current_cards.some((r) => r.is_selected === true);
|
$: cards_show = generate_cards.length > 0;
|
||||||
$: generate_cards = current_cards.filter((r) => r.is_selected === true);
|
$: generate_cards = [];
|
||||||
const cards_promise = RunnerCardService.runnerCardControllerGetAll().then(
|
const cards_promise = RunnerCardService.runnerCardControllerGetAll().then(
|
||||||
(val) => {
|
(val) => {
|
||||||
current_cards = val;
|
current_cards = val;
|
||||||
|
handler.setRows(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) =>
|
const getRunnerLabel = (option) =>
|
||||||
option?.firstname + " " + (option?.middlename || "") + " " + (option?.lastname || "{$_('non-blanko')}");
|
option?.firstname +
|
||||||
|
" " +
|
||||||
|
(option?.middlename || "") +
|
||||||
|
" " +
|
||||||
|
(option?.lastname || "{$_('non-blanko')}");
|
||||||
function open_edit_modal(card) {
|
function open_edit_modal(card) {
|
||||||
if (card.runner?.id) {
|
if (card.runner?.id) {
|
||||||
runner = Object.assign(
|
runner = Object.assign(
|
||||||
@@ -47,235 +37,227 @@
|
|||||||
{ 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;
|
|
||||||
$: rendered = filtered_cards;
|
|
||||||
let innerHeight = 0;
|
|
||||||
let ele;
|
|
||||||
$: updateSlice(scrollTop);
|
|
||||||
$: innerHeight = `${filtered_cards.length * 25}px`;
|
|
||||||
$: if (ele) updateSlice();
|
|
||||||
function updateSlice() {
|
|
||||||
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;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:UPDATE")}
|
||||||
|
<CardDetailModal
|
||||||
|
bind:current_cards
|
||||||
|
bind:edit_modal_open
|
||||||
|
bind:runner
|
||||||
|
bind:editable
|
||||||
|
bind:original_data
|
||||||
|
on:dataUpdated={handler.setRows(current_cards)}
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:GET")}
|
||||||
|
{#await cards_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">{$_("loading-cards")}</p>
|
||||||
|
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
||||||
|
</div>
|
||||||
|
{:then}
|
||||||
|
{#if current_cards.length === 0}
|
||||||
|
<CardsEmptyState />
|
||||||
|
{:else}
|
||||||
|
<div class="h-12 mt-1">
|
||||||
|
{#if cards_show}
|
||||||
|
<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 inline-flex"
|
||||||
|
id="options-menu"
|
||||||
|
on:click={async () => {
|
||||||
|
const prom = [];
|
||||||
|
for (const card of generate_cards) {
|
||||||
|
prom.push(
|
||||||
|
RunnerCardService.runnerCardControllerRemove(card.id, true)
|
||||||
|
);
|
||||||
|
}
|
||||||
|
await Promise.all(prom);
|
||||||
|
Toastify({
|
||||||
|
text: $_("cards-deleted"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
//TODO: Delete cards from table
|
||||||
|
}}
|
||||||
|
>
|
||||||
|
{$_("delete-cards")}
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
fill="none"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-width="1.5"
|
||||||
|
stroke="currentColor"
|
||||||
|
class="w-5 h-5"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
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"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
<GenerateRunnerCards bind:cards_show bind:generate_cards />
|
||||||
|
</div>
|
||||||
|
<table>
|
||||||
|
<thead>
|
||||||
|
<tr>
|
||||||
|
<th style="border-bottom: 1px solid #ddd;">
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
|
checked={generate_cards.length == current_cards.length}
|
||||||
|
on:click={() => {
|
||||||
|
if (generate_cards.length != current_cards.length) {
|
||||||
|
generate_cards = current_cards;
|
||||||
|
} else {
|
||||||
|
generate_cards = [];
|
||||||
|
}
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</th>
|
||||||
|
<Th {handler} orderBy="code">{$_("code")}</Th>
|
||||||
|
<Th {handler} orderBy="runner">{$_("runner")}</Th>
|
||||||
|
<Th {handler} orderBy="status">{$_("status")}</Th>
|
||||||
|
<th style="border-bottom: 1px solid #ddd;">{$_("action")}</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th style="border-bottom: 1px solid #ddd;" />
|
||||||
|
<ThFilter {handler} filterBy="code" />
|
||||||
|
<ThFilterRunner {handler} />
|
||||||
|
<ThFilterStatus {handler} />
|
||||||
|
<th style="border-bottom: 1px solid #ddd;" />
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#each $rows as row}
|
||||||
|
<tr>
|
||||||
|
<td>
|
||||||
|
<input
|
||||||
|
type="checkbox"
|
||||||
|
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
|
checked={generate_cards.filter((i) => i.id == row.id).length >
|
||||||
|
0}
|
||||||
|
on:click={() => {
|
||||||
|
if (generate_cards.findIndex((i) => i.id == row.id) == -1) {
|
||||||
|
generate_cards.push(row);
|
||||||
|
generate_cards = generate_cards;
|
||||||
|
} else {
|
||||||
|
generate_cards = generate_cards.filter(
|
||||||
|
(r) => r.id != row.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
console.log(generate_cards);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
<td>{row.code}</td>
|
||||||
|
<td>
|
||||||
|
{#if row.runner}
|
||||||
|
<a
|
||||||
|
href="../runners/{row.runner.id}"
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
||||||
|
>{row.runner.firstname}
|
||||||
|
{row.runner.middlename || ""}
|
||||||
|
{row.runner.lastname}</a
|
||||||
|
>
|
||||||
|
{:else}{$_("non-blanko")}{/if}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{#if row.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}
|
||||||
|
</td>
|
||||||
|
<td>
|
||||||
|
{#if active_deletes[row.id] === true}
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
active_deletes[row.id] = false;
|
||||||
|
}}
|
||||||
|
tabindex="0"
|
||||||
|
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer"
|
||||||
|
>{$_("cancel-delete")}</button
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
RunnerCardService.runnerCardControllerRemove(row.id, true)
|
||||||
|
.then((resp) => {
|
||||||
|
current_cards = current_cards.filter(
|
||||||
|
(obj) => obj.id !== row.id
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}}
|
||||||
|
tabindex="0"
|
||||||
|
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
|
||||||
|
>{$_("confirm-delete")}</button
|
||||||
|
>
|
||||||
|
{:else}
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
open_edit_modal(row);
|
||||||
|
}}
|
||||||
|
class="text-indigo-600 hover:text-indigo-900"
|
||||||
|
>{$_("details")}</button
|
||||||
|
>
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:DELETE")}
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
active_deletes[row.id] = true;
|
||||||
|
}}
|
||||||
|
tabindex="0"
|
||||||
|
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
|
||||||
|
>{$_("delete")}</button
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
</td>
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
{/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}
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
table tbody {
|
table tbody {
|
||||||
display: block;
|
display: block;
|
||||||
overflow-y: scroll;
|
overflow-y: scroll;
|
||||||
}
|
}
|
||||||
|
|
||||||
table thead, table tbody tr {
|
table thead,
|
||||||
|
table tbody tr {
|
||||||
display: table;
|
display: table;
|
||||||
width: 100%;
|
width: 100%;
|
||||||
table-layout: fixed;
|
table-layout: fixed;
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('CARD:UPDATE')}
|
|
||||||
<CardDetailModal
|
|
||||||
bind:current_cards
|
|
||||||
bind:edit_modal_open
|
|
||||||
bind:runner
|
|
||||||
bind:editable
|
|
||||||
bind:original_data />
|
|
||||||
{/if}
|
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('CARD:GET')}
|
|
||||||
{#await cards_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">{$_('loading-cards')}</p>
|
|
||||||
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
|
||||||
</div>
|
|
||||||
{:then}
|
|
||||||
{#if current_cards.length === 0}
|
|
||||||
<CardsEmptyState />
|
|
||||||
{:else}
|
|
||||||
<input
|
|
||||||
type="search"
|
|
||||||
bind:value={searchvalue}
|
|
||||||
placeholder={$_('datatable.search')}
|
|
||||||
aria-label={$_('datatable.search')}
|
|
||||||
class="gridjs-input gridjs-search-input mb-4" />
|
|
||||||
<div class="h-12">
|
|
||||||
<GenerateRunnerCards
|
|
||||||
bind:cards_show
|
|
||||||
bind:generate_cards />
|
|
||||||
</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_cards.some((r) => r.is_selected === true);
|
|
||||||
current_cards = current_cards.map((r) => {
|
|
||||||
r.is_selected = newstate;
|
|
||||||
return r;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
class="underline cursor-pointer select-none">{#if current_cards.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">
|
|
||||||
{$_('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}
|
|
||||||
{#if card.code
|
|
||||||
.toLowerCase()
|
|
||||||
.includes(
|
|
||||||
searchvalue.toLowerCase()
|
|
||||||
) || card.runner?.firstname
|
|
||||||
.toLowerCase()
|
|
||||||
.includes(
|
|
||||||
searchvalue.toLowerCase()
|
|
||||||
) || card.runner?.middlename
|
|
||||||
.toLowerCase()
|
|
||||||
.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>
|
|
||||||
{/await}
|
|
||||||
{/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">
|
||||||
|
|||||||
@@ -1,22 +1,157 @@
|
|||||||
<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
|
||||||
|
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
|
||||||
|
>
|
||||||
|
</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={$_("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/100).toFixed(2)} €</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,
|
||||||
@@ -156,7 +156,7 @@ import { is_promise } from "svelte/internal";
|
|||||||
{#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 { DonationService } from "@odit/lfk-client-js";
|
import { DonationService } from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
export let payment_modal_open = false;
|
export let payment_modal_open = false;
|
||||||
@@ -96,7 +96,7 @@
|
|||||||
{#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;
|
||||||
|
|||||||
@@ -49,7 +49,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 {
|
import {
|
||||||
DonorService
|
DonorService
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
@@ -134,7 +134,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 { 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";
|
||||||
@@ -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
|
||||||
|
|||||||
@@ -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
|
<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";
|
|
||||||
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;
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -326,14 +326,14 @@
|
|||||||
<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>
|
||||||
@@ -375,14 +375,14 @@
|
|||||||
<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>
|
||||||
|
|||||||
@@ -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
|
||||||
|
|||||||
@@ -6,6 +6,9 @@
|
|||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
|
import { init } from "@paralleldrive/cuid2";
|
||||||
|
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
|
||||||
|
|
||||||
export let cards_show = false;
|
export let cards_show = false;
|
||||||
export let generate_cards = [];
|
export let generate_cards = [];
|
||||||
export let generate_runners = [];
|
export let generate_runners = [];
|
||||||
@@ -67,7 +70,7 @@
|
|||||||
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;
|
||||||
a.download = `${$_('runnercards')}-${locale}.pdf`;
|
a.download = `${$_("runnercards")}-${locale}-${createId()}.pdf`;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
a.remove();
|
a.remove();
|
||||||
@@ -75,8 +78,7 @@
|
|||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdf-successfully-generated"),
|
text: $_("pdf-successfully-generated"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
}).showToast();
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
@@ -128,10 +130,11 @@
|
|||||||
let a = document.createElement("a");
|
let a = document.createElement("a");
|
||||||
a.href = url;
|
a.href = url;
|
||||||
if (generate_runners.length == 1) {
|
if (generate_runners.length == 1) {
|
||||||
a.download = `${$_('runnercards')}_${generate_runners[0].firstname}_${generate_runners[0].lastname}-${locale}.pdf`;
|
a.download = `${$_("runnercards")}_${generate_runners[0].firstname}_${
|
||||||
}
|
generate_runners[0].lastname
|
||||||
else{
|
}-${locale}-${createId()}.pdf`;
|
||||||
a.download = `Runnercards-${locale}.pdf`;
|
} else {
|
||||||
|
a.download = `${$_("runnercards")}-${locale}-${createId()}.pdf`;
|
||||||
}
|
}
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
@@ -140,8 +143,7 @@
|
|||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdf-successfully-generated"),
|
text: $_("pdf-successfully-generated"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
}).showToast();
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
@@ -196,7 +198,7 @@
|
|||||||
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;
|
||||||
a.download = `${$_('runnercards')}_${t.name}-${locale}.pdf`;
|
a.download = `${$_("runnercards")}_${t.name}-${locale}-${createId()}.pdf`;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
a.remove();
|
a.remove();
|
||||||
@@ -205,8 +207,7 @@
|
|||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdfs-successfully-generated"),
|
text: $_("pdfs-successfully-generated"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
}).showToast();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -225,7 +226,11 @@
|
|||||||
for (const o of generate_orgs) {
|
for (const o of generate_orgs) {
|
||||||
count_orgs++;
|
count_orgs++;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
let runners = await RunnerOrganizationService.runnerOrganizationControllerGetRunners(o.id, true)
|
let runners =
|
||||||
|
await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
||||||
|
o.id,
|
||||||
|
true
|
||||||
|
);
|
||||||
let cards = [];
|
let cards = [];
|
||||||
for (let runner of 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);
|
||||||
@@ -263,18 +268,17 @@
|
|||||||
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;
|
||||||
a.download = `${$_('runnercards')}_${o.name}_direct-${locale}.pdf`;
|
a.download = `${$_("runnercards")}_${o.name}_direct-${locale}-${createId()}.pdf`;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
a.remove();
|
a.remove();
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
||||||
toast.hideToast();
|
toast.hideToast();
|
||||||
console.log("here")
|
console.log("here");
|
||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdfs-successfully-generated"),
|
text: $_("pdfs-successfully-generated"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
}).showToast();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -321,17 +325,21 @@
|
|||||||
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;
|
||||||
a.download = `${$_('runnercards')}_${o.name}_${t.name}-${locale}.pdf`;
|
a.download = `${$_("runnercards")}_${o.name}_${
|
||||||
|
t.name
|
||||||
|
}-${locale}-${createId()}.pdf`;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
a.remove();
|
a.remove();
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
if (
|
||||||
|
count === o.teams.length &&
|
||||||
|
count_orgs === generate_orgs.length
|
||||||
|
) {
|
||||||
toast.hideToast();
|
toast.hideToast();
|
||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdfs-successfully-generated"),
|
text: $_("pdfs-successfully-generated"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
}).showToast();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -352,49 +360,56 @@
|
|||||||
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')}
|
>
|
||||||
|
{$_("generate-runnercards")}
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
class="-mr-1 ml-2 h-5 w-5"><path
|
class="-mr-1 ml-2 h-5 w-5"
|
||||||
fill="none"
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
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"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{#if cards_dropdown_open}
|
{#if cards_dropdown_open}
|
||||||
<div
|
<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"
|
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">
|
id="cards:dropdown:menu"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="py-1"
|
class="py-1"
|
||||||
role="menu"
|
role="menu"
|
||||||
aria-orientation="vertical"
|
aria-orientation="vertical"
|
||||||
aria-labelledby="options-menu">
|
aria-labelledby="options-menu"
|
||||||
<span
|
>
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700">{$_('select-language')}</span>
|
<span class="block w-full text-left px-4 py-2 text-sm text-gray-700"
|
||||||
|
>{$_("select-language")}</span
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
generateRunnerCards('de');
|
generateRunnerCards("de");
|
||||||
}}
|
}}
|
||||||
type="submit"
|
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"
|
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">
|
role="menuitem"
|
||||||
{$_('german')}
|
>
|
||||||
|
{$_("german")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
generateRunnerCards('en');
|
generateRunnerCards("en");
|
||||||
}}
|
}}
|
||||||
type="submit"
|
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"
|
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">
|
role="menuitem"
|
||||||
{$_('english')}
|
>
|
||||||
|
{$_("english")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -3,9 +3,12 @@
|
|||||||
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";
|
||||||
|
import { init } from "@paralleldrive/cuid2";
|
||||||
|
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
|
||||||
|
|
||||||
export let certificates_show = false;
|
export let certificates_show = false;
|
||||||
export let generate_runners = [];
|
export let generate_runners = [];
|
||||||
export let generate_orgs = [];
|
export let generate_orgs = [];
|
||||||
@@ -37,11 +40,13 @@
|
|||||||
text: $_("generating-pdf"),
|
text: $_("generating-pdf"),
|
||||||
duration: -1,
|
duration: -1,
|
||||||
}).showToast();
|
}).showToast();
|
||||||
const current_donations = (await DonationService.donationControllerGetAll()) || [];
|
const current_donations =
|
||||||
|
(await DonationService.donationControllerGetAll()) || [];
|
||||||
let certificateRunners = [];
|
let certificateRunners = [];
|
||||||
for (let runner of generate_runners) {
|
for (let runner of generate_runners) {
|
||||||
runner.distanceDonations = current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
runner.distanceDonations =
|
||||||
console.log(runner.distanceDonations)
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
|
console.log(runner.distanceDonations);
|
||||||
certificateRunners.push(runner);
|
certificateRunners.push(runner);
|
||||||
}
|
}
|
||||||
fetch(
|
fetch(
|
||||||
@@ -72,10 +77,11 @@
|
|||||||
let a = document.createElement("a");
|
let a = document.createElement("a");
|
||||||
a.href = url;
|
a.href = url;
|
||||||
if (generate_runners.length == 1) {
|
if (generate_runners.length == 1) {
|
||||||
a.download = `${$_('certificates')}_${generate_runners[0].firstname}_${generate_runners[0].lastname}-${locale}.pdf`;
|
a.download = `${$_("certificates")}_${
|
||||||
}
|
generate_runners[0].firstname
|
||||||
else{
|
}_${generate_runners[0].lastname}-${locale}-${createId()}.pdf`;
|
||||||
a.download = `${$_('certificates')}-${locale}.pdf`;
|
} else {
|
||||||
|
a.download = `${$_("certificates")}-${locale}.pdf`;
|
||||||
}
|
}
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
@@ -84,8 +90,7 @@
|
|||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdf-successfully-generated"),
|
text: $_("pdf-successfully-generated"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
}).showToast();
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
@@ -97,14 +102,16 @@
|
|||||||
duration: -1,
|
duration: -1,
|
||||||
}).showToast();
|
}).showToast();
|
||||||
let count = 0;
|
let count = 0;
|
||||||
const current_donations = (await DonationService.donationControllerGetAll()) || [];
|
const current_donations =
|
||||||
|
(await DonationService.donationControllerGetAll()) || [];
|
||||||
for (const t of generate_teams) {
|
for (const t of generate_teams) {
|
||||||
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
t.id
|
t.id
|
||||||
);
|
);
|
||||||
let certificateRunners = [];
|
let certificateRunners = [];
|
||||||
for (let runner of runners) {
|
for (let runner of runners) {
|
||||||
runner.distanceDonations = current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
runner.distanceDonations =
|
||||||
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
certificateRunners.push(runner);
|
certificateRunners.push(runner);
|
||||||
}
|
}
|
||||||
fetch(
|
fetch(
|
||||||
@@ -135,7 +142,7 @@
|
|||||||
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;
|
||||||
a.download = `${$_('certificates')}_${t.name}-${locale}.pdf`;
|
a.download = `${$_("certificates")}_${t.name}-${locale}-${createId()}.pdf`;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
a.remove();
|
a.remove();
|
||||||
@@ -144,8 +151,7 @@
|
|||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdfs-successfully-generated"),
|
text: $_("pdfs-successfully-generated"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
}).showToast();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -158,16 +164,22 @@
|
|||||||
text: $_("generating-pdfs"),
|
text: $_("generating-pdfs"),
|
||||||
duration: -1,
|
duration: -1,
|
||||||
}).showToast();
|
}).showToast();
|
||||||
const current_donations = (await DonationService.donationControllerGetAll()) || [];
|
const current_donations =
|
||||||
|
(await DonationService.donationControllerGetAll()) || [];
|
||||||
let count = 0;
|
let count = 0;
|
||||||
let count_orgs = 0;
|
let count_orgs = 0;
|
||||||
for (const o of generate_orgs) {
|
for (const o of generate_orgs) {
|
||||||
count_orgs++;
|
count_orgs++;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
let runners = await RunnerOrganizationService.runnerOrganizationControllerGetRunners(o.id, true)
|
let runners =
|
||||||
|
await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
||||||
|
o.id,
|
||||||
|
true
|
||||||
|
);
|
||||||
let certificateRunners = [];
|
let certificateRunners = [];
|
||||||
for (let runner of runners) {
|
for (let runner of runners) {
|
||||||
runner.distanceDonations = current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
runner.distanceDonations =
|
||||||
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
certificateRunners.push(runner);
|
certificateRunners.push(runner);
|
||||||
}
|
}
|
||||||
await fetch(
|
await fetch(
|
||||||
@@ -197,18 +209,17 @@
|
|||||||
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;
|
||||||
a.download = `${$_('certificates')}_${o.name}_direct-${locale}.pdf`;
|
a.download = `${$_("certificates")}_${o.name}-${locale}-${createId()}.pdf`;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
a.remove();
|
a.remove();
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
||||||
toast.hideToast();
|
toast.hideToast();
|
||||||
console.log("here")
|
console.log("here");
|
||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdfs-successfully-generated"),
|
text: $_("pdfs-successfully-generated"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
}).showToast();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -220,7 +231,8 @@
|
|||||||
);
|
);
|
||||||
let certificateRunners = [];
|
let certificateRunners = [];
|
||||||
for (let runner of runners) {
|
for (let runner of runners) {
|
||||||
runner.distanceDonations = current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
runner.distanceDonations =
|
||||||
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
certificateRunners.push(runner);
|
certificateRunners.push(runner);
|
||||||
}
|
}
|
||||||
await fetch(
|
await fetch(
|
||||||
@@ -250,17 +262,21 @@
|
|||||||
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;
|
||||||
a.download = `${$_('certificates')}_${o.name}_${t.name}-${locale}.pdf`;
|
a.download = `${$_("certificates")}_${o.name}_${
|
||||||
|
t.name
|
||||||
|
}-${locale}-${createId()}.pdf`;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
a.remove();
|
a.remove();
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
if (
|
||||||
|
count === o.teams.length &&
|
||||||
|
count_orgs === generate_orgs.length
|
||||||
|
) {
|
||||||
toast.hideToast();
|
toast.hideToast();
|
||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdfs-successfully-generated"),
|
text: $_("pdfs-successfully-generated"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
}).showToast();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -281,49 +297,56 @@
|
|||||||
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')}
|
>
|
||||||
|
{$_("generate-runner-certificates")}
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
class="-mr-1 ml-2 h-5 w-5"><path
|
class="-mr-1 ml-2 h-5 w-5"
|
||||||
fill="none"
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
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"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{#if certificates_dropdown_open}
|
{#if certificates_dropdown_open}
|
||||||
<div
|
<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"
|
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">
|
id="certificates:dropdown:menu"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="py-1"
|
class="py-1"
|
||||||
role="menu"
|
role="menu"
|
||||||
aria-orientation="vertical"
|
aria-orientation="vertical"
|
||||||
aria-labelledby="options-menu">
|
aria-labelledby="options-menu"
|
||||||
<span
|
>
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700">{$_('select-language')}</span>
|
<span class="block w-full text-left px-4 py-2 text-sm text-gray-700"
|
||||||
|
>{$_("select-language")}</span
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
generateCertificates('de');
|
generateCertificates("de");
|
||||||
}}
|
}}
|
||||||
type="submit"
|
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"
|
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">
|
role="menuitem"
|
||||||
{$_('german')}
|
>
|
||||||
|
{$_("german")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
generateCertificates('en');
|
generateCertificates("en");
|
||||||
}}
|
}}
|
||||||
type="submit"
|
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"
|
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">
|
role="menuitem"
|
||||||
{$_('english')}
|
>
|
||||||
|
{$_("english")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,6 +5,9 @@
|
|||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
|
import { init } from "@paralleldrive/cuid2";
|
||||||
|
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
|
||||||
|
|
||||||
export let sponsoring_contracts_show = false;
|
export let sponsoring_contracts_show = false;
|
||||||
export let generate_runners = [];
|
export let generate_runners = [];
|
||||||
export let generate_orgs = [];
|
export let generate_orgs = [];
|
||||||
@@ -69,7 +72,7 @@
|
|||||||
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;
|
||||||
a.download = `${$_('sponsorings')}_${t.name}-${locale}.pdf`;
|
a.download = `${$_("sponsorings")}_${t.name}-${locale}-${createId()}.pdf`;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
a.remove();
|
a.remove();
|
||||||
@@ -78,8 +81,7 @@
|
|||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdfs-successfully-generated"),
|
text: $_("pdfs-successfully-generated"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
}).showToast();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -96,7 +98,11 @@
|
|||||||
for (const o of generate_orgs) {
|
for (const o of generate_orgs) {
|
||||||
count_orgs++;
|
count_orgs++;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
let runners = await RunnerOrganizationService.runnerOrganizationControllerGetRunners(o.id, true)
|
let runners =
|
||||||
|
await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
||||||
|
o.id,
|
||||||
|
true
|
||||||
|
);
|
||||||
await fetch(
|
await fetch(
|
||||||
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
{
|
{
|
||||||
@@ -124,18 +130,17 @@
|
|||||||
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;
|
||||||
a.download = `${$_('sponsorings')}_${o.name}_direct-${locale}.pdf`;
|
a.download = `${$_("sponsorings")}_${o.name}_direct-${locale}-${createId()}.pdf`;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
a.remove();
|
a.remove();
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
||||||
toast.hideToast();
|
toast.hideToast();
|
||||||
console.log("here")
|
console.log("here");
|
||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdfs-successfully-generated"),
|
text: $_("pdfs-successfully-generated"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
}).showToast();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -172,17 +177,21 @@
|
|||||||
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;
|
||||||
a.download = `${$_('sponsorings')}_${o.name}_${t.name}-${locale}.pdf`;
|
a.download = `${$_("sponsorings")}_${o.name}_${
|
||||||
|
t.name
|
||||||
|
}-${locale}-${createId()}.pdf`;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
a.remove();
|
a.remove();
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
if (
|
||||||
|
count === o.teams.length &&
|
||||||
|
count_orgs === generate_orgs.length
|
||||||
|
) {
|
||||||
toast.hideToast();
|
toast.hideToast();
|
||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdfs-successfully-generated"),
|
text: $_("pdfs-successfully-generated"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
}).showToast();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
@@ -224,9 +233,11 @@
|
|||||||
let a = document.createElement("a");
|
let a = document.createElement("a");
|
||||||
a.href = url;
|
a.href = url;
|
||||||
if (generate_runners.length == 1) {
|
if (generate_runners.length == 1) {
|
||||||
a.download = `${$_('sponsorings')}_${generate_runners[0].firstname}_${generate_runners[0].lastname}-${locale}.pdf`;
|
a.download = `${$_("sponsorings")}_${generate_runners[0].firstname}_${
|
||||||
|
generate_runners[0].lastname
|
||||||
|
}-${locale}-${createId()}.pdf`;
|
||||||
}
|
}
|
||||||
a.download = `${$_('sponsorings')}-${locale}.pdf`;
|
a.download = `${$_("sponsorings")}-${locale}-${createId()}.pdf`;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
a.remove();
|
a.remove();
|
||||||
@@ -234,8 +245,7 @@
|
|||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdf-successfully-generated"),
|
text: $_("pdf-successfully-generated"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
}).showToast();
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
@@ -249,55 +259,63 @@
|
|||||||
<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"
|
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-sponsoring-contracts')}
|
>
|
||||||
|
{$_("generate-sponsoring-contracts")}
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
class="-mr-1 ml-2 h-5 w-5"><path
|
class="-mr-1 ml-2 h-5 w-5"
|
||||||
fill="none"
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
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"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
{#if sponsoring_contracts_download_open}
|
{#if sponsoring_contracts_download_open}
|
||||||
<div
|
<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"
|
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">
|
id="sponsoring:dropdown:menu"
|
||||||
|
>
|
||||||
<div
|
<div
|
||||||
class="py-1"
|
class="py-1"
|
||||||
role="menu"
|
role="menu"
|
||||||
aria-orientation="vertical"
|
aria-orientation="vertical"
|
||||||
aria-labelledby="options-menu">
|
aria-labelledby="options-menu"
|
||||||
<span
|
>
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700">{$_('select-language')}</span>
|
<span class="block w-full text-left px-4 py-2 text-sm text-gray-700"
|
||||||
|
>{$_("select-language")}</span
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
generateSponsoringContract('de');
|
generateSponsoringContract("de");
|
||||||
}}
|
}}
|
||||||
type="submit"
|
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"
|
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">
|
role="menuitem"
|
||||||
{$_('german')}
|
>
|
||||||
|
{$_("german")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
generateSponsoringContract('en');
|
generateSponsoringContract("en");
|
||||||
}}
|
}}
|
||||||
type="submit"
|
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"
|
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">
|
role="menuitem"
|
||||||
{$_('english')}
|
>
|
||||||
|
{$_("english")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -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,
|
||||||
@@ -125,7 +125,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;
|
||||||
|
|||||||
@@ -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,
|
||||||
@@ -228,7 +228,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,119 +192,126 @@
|
|||||||
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 / 1000} km</span>
|
<span class="text-gray-700">{original_data.distance / 1000} km</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,39 +1,82 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
|
let tablePageCount = [25, 50, 100, 250, 500];
|
||||||
|
import { writable } from "svelte/store";
|
||||||
|
import {
|
||||||
|
createSvelteTable,
|
||||||
|
flexRender,
|
||||||
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
} from "@tanstack/svelte-table";
|
||||||
import {
|
import {
|
||||||
RunnerService,
|
RunnerService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
RunnerOrganizationService,
|
RunnerOrganizationService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
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 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";
|
||||||
let pageLoaded = false;
|
import { onMount } from "svelte";
|
||||||
$: searchvalue = "";
|
import InputElement from "../shared/InputElement.svelte";
|
||||||
|
import { groupFilter } from "../shared/tablefilters";
|
||||||
|
|
||||||
|
$: selectedRunners =
|
||||||
|
$table?.getSelectedRowModel().rows.map((row) => row.original) || [];
|
||||||
|
$: selected =
|
||||||
|
$table?.getSelectedRowModel().rows.map((row) => row.index) || [];
|
||||||
|
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
accessorKey: "id",
|
||||||
|
header: () => "id",
|
||||||
|
filterFn: `equalsString`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "firstname",
|
||||||
|
header: () => $_("first-name"),
|
||||||
|
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,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
//
|
||||||
|
|
||||||
$: active_deletes = [];
|
$: active_deletes = [];
|
||||||
|
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;
|
||||||
pageLoaded = true;
|
$: 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) {
|
$: mappedteams = teams.map(function (g) {
|
||||||
@@ -44,224 +87,245 @@
|
|||||||
return { value: g.id, label: g.name };
|
return { value: g.id, label: g.name };
|
||||||
})
|
})
|
||||||
.concat(mappedteams);
|
.concat(mappedteams);
|
||||||
|
const options = writable({
|
||||||
|
data: [],
|
||||||
|
columns: columns,
|
||||||
|
filterFns: {
|
||||||
|
group: groupFilter,
|
||||||
|
},
|
||||||
|
initialState: {
|
||||||
|
pagination: {
|
||||||
|
pageSize: 50,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
enableRowSelection: true,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
});
|
||||||
|
const table = createSvelteTable(options);
|
||||||
|
onMount(() => {
|
||||||
|
RunnerService.runnerControllerGetAll().then((val) => {
|
||||||
|
current_runners = val;
|
||||||
|
dataLoaded = true;
|
||||||
|
|
||||||
|
options.update((options) => ({
|
||||||
|
...options,
|
||||||
|
data: current_runners,
|
||||||
|
}));
|
||||||
|
});
|
||||||
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
||||||
teams = val;
|
teams = val;
|
||||||
});
|
});
|
||||||
RunnerOrganizationService.runnerOrganizationControllerGetAll().then((val) => {
|
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
||||||
|
(val) => {
|
||||||
orgs = val;
|
orgs = val;
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
function should_display_based_on_id(id) {
|
|
||||||
if (searchvalue.toString().slice(-1) === "*") {
|
|
||||||
return id.toString().startsWith(searchvalue.replace("*", ""));
|
|
||||||
}
|
|
||||||
return id.toString() === searchvalue;
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('RUNNER:GET')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET")}
|
||||||
{#await runners_promise}
|
{#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}
|
|
||||||
{#if current_runners.length === 0}
|
|
||||||
<RunnersEmptyState />
|
|
||||||
{:else}
|
{:else}
|
||||||
<input
|
<div class="h-12 mt-2">
|
||||||
type="search"
|
|
||||||
bind:value={searchvalue}
|
|
||||||
placeholder={$_('datatable.search')}
|
|
||||||
aria-label={$_('datatable.search')}
|
|
||||||
class="gridjs-input gridjs-search-input mb-4" />
|
|
||||||
<div class="block mb-6">
|
|
||||||
<label
|
|
||||||
for="country"
|
|
||||||
class="text-sm font-medium text-gray-700">{$_('filter-by-organization-team')}</label>
|
|
||||||
<Select
|
|
||||||
on:select={(event) => {
|
|
||||||
selectedFilter = event.detail;
|
|
||||||
}}
|
|
||||||
selectedValue={selectedFilter}
|
|
||||||
placeholder={$_('filter-by-organization-team')}
|
|
||||||
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"
|
|
||||||
items={selectgroups}
|
|
||||||
isMulti={true} />
|
|
||||||
</div>
|
|
||||||
<div class="h-12">
|
|
||||||
<GenerateSponsoringContracts
|
<GenerateSponsoringContracts
|
||||||
bind:sponsoring_contracts_show
|
bind:sponsoring_contracts_show
|
||||||
bind:generate_runners />
|
bind:generate_runners={selectedRunners}
|
||||||
|
/>
|
||||||
<GenerateRunnerCards
|
<GenerateRunnerCards
|
||||||
bind:cards_show
|
bind:cards_show
|
||||||
bind:generate_runners />
|
bind:generate_runners={selectedRunners}
|
||||||
|
/>
|
||||||
<GenerateRunnerCertificates
|
<GenerateRunnerCertificates
|
||||||
bind:certificates_show
|
bind:certificates_show
|
||||||
bind:generate_runners />
|
bind:generate_runners={selectedRunners}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div
|
<table class="w-full">
|
||||||
class:hidden={!pageLoaded}
|
<thead>
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
|
{#each $table.getHeaderGroups() as headerGroup}
|
||||||
>
|
<tr class="select-none">
|
||||||
<table class="divide-y divide-gray-200 w-full table-fixed">
|
<th class="inset-y-0 left-0 px-4 py-2 text-left w-px">
|
||||||
<thead class="bg-gray-50">
|
<InputElement
|
||||||
<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>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody class="divide-y divide-gray-200">
|
|
||||||
{#each current_runners as runner}
|
|
||||||
{#if runner.firstname
|
|
||||||
.toLowerCase()
|
|
||||||
.includes(
|
|
||||||
searchvalue.toLowerCase()
|
|
||||||
) || runner.lastname
|
|
||||||
.toLowerCase()
|
|
||||||
.includes(
|
|
||||||
searchvalue.toLowerCase()
|
|
||||||
) || should_display_based_on_id(runner.id)}
|
|
||||||
{#if filterGroupIDs.includes(runner.group.id) || filterGroupIDs.includes(runner.group.parentGroup?.id) || filterGroupIDs.length === 0}
|
|
||||||
<tr
|
|
||||||
data-rowid="user_{runner.id}"
|
|
||||||
data-groupid={runner.group.id}>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<input
|
|
||||||
bind:checked={runner.is_selected}
|
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" />
|
checked={$table.getIsAllRowsSelected()}
|
||||||
</td>
|
indeterminate={$table.getIsSomeRowsSelected()}
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
on:change={() => $table.toggleAllRowsSelected()}
|
||||||
<div class="flex items-center">
|
/>
|
||||||
<div class="ml-4">
|
</th>
|
||||||
<div class="text-sm font-medium text-gray-900">
|
{#each headerGroup.headers as header}
|
||||||
{runner.firstname}
|
<th class="cursor-pointer">
|
||||||
{runner.middlename || ''}
|
{#if !header.isPlaceholder}
|
||||||
{runner.lastname}
|
<div on:click={header.column.getToggleSortingHandler()}>
|
||||||
|
<svelte:component
|
||||||
|
this={flexRender(
|
||||||
|
header.column.columnDef.header,
|
||||||
|
header.getContext()
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
{#if header.column.getIsSorted().toString() == "asc"}
|
||||||
|
🔼
|
||||||
|
{:else if header.column.getIsSorted().toString() == "desc"}
|
||||||
|
🔽
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/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 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>
|
||||||
</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 /1000 } km
|
|
||||||
</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}
|
{/if}
|
||||||
|
</th>
|
||||||
|
{/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>
|
</tr>
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
<div class="h-2" />
|
||||||
{/if}
|
<div class="flex items-center gap-2">
|
||||||
{:catch error}
|
<button
|
||||||
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
|
class="border rounded p-1"
|
||||||
<span class="inline-block align-middle mr-8">
|
on:click={() => $table.setPageIndex(0)}
|
||||||
<b class="capitalize">{$_('general_promise_error')}</b>
|
disabled={!$table.getCanPreviousPage()}
|
||||||
{error}
|
>
|
||||||
|
{"<<"}
|
||||||
|
</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>
|
||||||
|
<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 tablePageCount 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>
|
</div>
|
||||||
{/await}
|
|
||||||
{/if}
|
{/if}
|
||||||
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
thead {
|
||||||
|
background: #fff;
|
||||||
|
}
|
||||||
|
thead {
|
||||||
|
position: sticky;
|
||||||
|
inset-block-start: 0;
|
||||||
|
}
|
||||||
|
tbody td {
|
||||||
|
padding: 4px;
|
||||||
|
}
|
||||||
|
tbody tr:nth-child(even) {
|
||||||
|
background: #fafafa;
|
||||||
|
}
|
||||||
|
tbody tr {
|
||||||
|
transition: all, 0.2s;
|
||||||
|
}
|
||||||
|
tbody tr:hover {
|
||||||
|
background: #f5f5f5;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -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,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,
|
||||||
ScanService,
|
ScanService,
|
||||||
@@ -14,7 +14,7 @@
|
|||||||
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();
|
||||||
}
|
}
|
||||||
@@ -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,125 +1,145 @@
|
|||||||
<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 Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
import ScansEmptyState from "./ScansEmptyState.svelte";
|
import ScansEmptyState from "./ScansEmptyState.svelte";
|
||||||
$: searchvalue = "";
|
import ThFilterRunner from "./ThFilterRunner.svelte";
|
||||||
|
import ThFilterTrack from "./ThFilterTrack.svelte";
|
||||||
$: active_deletes = [];
|
$: active_deletes = [];
|
||||||
export let current_scans = [];
|
export let current_scans = [];
|
||||||
|
const handler = new DataHandler(current_scans, { rowsPerPage: 20 });
|
||||||
|
const rows = handler.getRows();
|
||||||
const scans_promise = ScanService.scanControllerGetAll().then((val) => {
|
const scans_promise = ScanService.scanControllerGetAll().then((val) => {
|
||||||
current_scans = val;
|
current_scans = val;
|
||||||
|
handler.setRows(val);
|
||||||
|
});
|
||||||
|
$: allTracks = [];
|
||||||
|
TrackService.trackControllerGetAll().then((val) => {
|
||||||
|
allTracks = val;
|
||||||
});
|
});
|
||||||
function should_display_based_on_id(id) {
|
|
||||||
if (searchvalue.toString().slice(-1) === "*") {
|
|
||||||
return id.toString().startsWith(searchvalue.replace("*", ""));
|
|
||||||
}
|
|
||||||
return id.toString() === searchvalue;
|
|
||||||
}
|
|
||||||
function format_laptime(laptime) {
|
function format_laptime(laptime) {
|
||||||
if(laptime == 0 || laptime == null){return $_('first-scan-of-the-day')}
|
if (laptime == 0 || laptime == null) {
|
||||||
if(laptime < 60){return `${laptime}s`}
|
return $_("first-scan-of-the-day");
|
||||||
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)}`
|
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
|
||||||
|
}`;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('SCAN:GET')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:GET")}
|
||||||
{#await scans_promise}
|
{#await scans_promise}
|
||||||
<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}
|
{:then}
|
||||||
{#if current_scans.length === 0}
|
{#if current_scans.length === 0}
|
||||||
<ScansEmptyState />
|
<ScansEmptyState />
|
||||||
{:else}
|
{:else}
|
||||||
<input
|
|
||||||
type="search"
|
|
||||||
bind:value={searchvalue}
|
|
||||||
placeholder={$_('datatable.search')}
|
|
||||||
aria-label={$_('datatable.search')}
|
|
||||||
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">
|
<table class="divide-y divide-gray-200 w-full">
|
||||||
<thead class="bg-gray-50">
|
<thead class="bg-gray-50">
|
||||||
<tr>
|
<tr>
|
||||||
|
<Th {handler} orderBy="id">ID</Th>
|
||||||
|
<Th {handler}>
|
||||||
|
{$_("runner")}
|
||||||
|
</Th>
|
||||||
|
<Th {handler}>
|
||||||
|
{$_("distance")}
|
||||||
|
</Th>
|
||||||
|
<Th {handler}>
|
||||||
|
{$_("track")}
|
||||||
|
</Th>
|
||||||
|
<Th {handler}>
|
||||||
|
{$_("laptime")}
|
||||||
|
</Th>
|
||||||
|
<Th {handler}>
|
||||||
|
{$_("status")}
|
||||||
|
</Th>
|
||||||
<th
|
<th
|
||||||
scope="col"
|
scope="col"
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
class="relative px-6 py-3"
|
||||||
{$_('runner')}
|
style="border-bottom: 1px solid #ddd;"
|
||||||
</th>
|
>
|
||||||
<th
|
{$_("action")}
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('distance-track')}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
|
||||||
{$_('laptime')}
|
|
||||||
</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>
|
||||||
</tr>
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<ThFilter {handler} filterBy="id" />
|
||||||
|
<ThFilterRunner {handler} />
|
||||||
|
<th style="border-bottom: 1px solid #ddd;" />
|
||||||
|
<ThFilterTrack tracks={allTracks} {handler} />
|
||||||
|
<!-- <th style="border-bottom: 1px solid #ddd;" /> -->
|
||||||
|
<th style="border-bottom: 1px solid #ddd;" />
|
||||||
|
<th style="border-bottom: 1px solid #ddd;" />
|
||||||
|
<!-- TODO: filter status -->
|
||||||
|
<th style="border-bottom: 1px solid #ddd;" />
|
||||||
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="divide-y divide-gray-200">
|
<tbody class="divide-y divide-gray-200">
|
||||||
{#each current_scans as scan}
|
{#each $rows as scan}
|
||||||
{#if scan.track?.name
|
|
||||||
.toLowerCase()
|
|
||||||
.includes(
|
|
||||||
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}">
|
<tr data-rowid="scan_{scan.id}">
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-left">
|
||||||
|
<div class="text-sm font-medium text-gray-900">
|
||||||
|
{scan.id}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
<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">
|
||||||
<a
|
<a
|
||||||
href="../runners/{scan.runner.id}"
|
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}
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
||||||
{scan.runner.middlename || ''}
|
>{scan.runner.firstname}
|
||||||
{scan.runner.lastname}</a>
|
{scan.runner.middlename || ""}
|
||||||
|
{scan.runner.lastname}</a
|
||||||
|
>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
<td class="px-6 py-4 whitespace-nowrap text-left">
|
||||||
<div class="text-sm font-medium text-gray-900">
|
<div class="text-sm font-medium text-gray-900">
|
||||||
{#if scan.distance < 1000}
|
{#if scan.distance < 1000}
|
||||||
{scan.distance}m
|
{scan.distance}m
|
||||||
{:else}{scan.distance / 1000}km{/if}
|
{:else}{scan.distance / 1000}km{/if}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap text-left">
|
||||||
|
<div class="text-sm font-medium text-gray-900">
|
||||||
{#if scan.track}
|
{#if scan.track}
|
||||||
<a
|
<a
|
||||||
href="../tracks"
|
href="../tracks"
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{scan.track.name}
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
||||||
|
>{scan.track.name}
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
<td class="px-6 py-4 whitespace-nowrap text-left">
|
||||||
{#if scan.responseType === "TRACKSCAN"}
|
{#if scan.responseType === "TRACKSCAN"}
|
||||||
<div class="text-sm font-medium text-gray-900">
|
<div class="text-sm font-medium text-gray-900">
|
||||||
{format_laptime(scan.lapTime)}
|
{format_laptime(scan.lapTime)}
|
||||||
</div>
|
</div>
|
||||||
{:else}
|
{:else}
|
||||||
<div class="text-sm font-medium text-gray-900">
|
<div class="text-sm font-medium text-gray-900">
|
||||||
{$_('scan-with-fixed-distance')}
|
{$_("scan-with-fixed-distance")}
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
@@ -127,23 +147,30 @@
|
|||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
{#if scan.valid}
|
{#if scan.valid}
|
||||||
<span
|
<span
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">{$_('valid')}</span>
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"
|
||||||
|
>{$_("valid")}</span
|
||||||
|
>
|
||||||
{:else}
|
{:else}
|
||||||
<span
|
<span
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">{$_('invalid')}</span>
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800"
|
||||||
|
>{$_("invalid")}</span
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
|
|
||||||
{#if active_deletes[scan.id] === true}
|
{#if active_deletes[scan.id] === true}
|
||||||
<td
|
<td
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
active_deletes[scan.id] = false;
|
active_deletes[scan.id] = false;
|
||||||
}}
|
}}
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">{$_('cancel-delete')}</button>
|
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer"
|
||||||
|
>{$_("cancel-delete")}</button
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
ScanService.scanControllerRemove(scan.id, false).then(
|
ScanService.scanControllerRemove(scan.id, false).then(
|
||||||
@@ -152,35 +179,41 @@
|
|||||||
(obj) => obj.id !== scan.id
|
(obj) => obj.id !== scan.id
|
||||||
);
|
);
|
||||||
Toastify({
|
Toastify({
|
||||||
text: 'Scan deleted',
|
text: "Scan deleted",
|
||||||
duration: 500,
|
duration: 500,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
'linear-gradient(to right, #00b09b, #96c93d)',
|
"linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
}}
|
}}
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('confirm-delete')}</button>
|
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
|
||||||
|
>{$_("confirm-delete")}</button
|
||||||
|
>
|
||||||
</td>
|
</td>
|
||||||
{:else}
|
{:else}
|
||||||
<td
|
<td
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
|
||||||
|
>
|
||||||
<a
|
<a
|
||||||
href="./{scan.id}"
|
href="./{scan.id}"
|
||||||
class="text-indigo-600 hover:text-indigo-900">{$_('details')}</a>
|
class="text-indigo-600 hover:text-indigo-900"
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('SCAN:DELETE')}
|
>{$_("details")}</a
|
||||||
|
>
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:DELETE")}
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
active_deletes[scan.id] = true;
|
active_deletes[scan.id] = true;
|
||||||
}}
|
}}
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
|
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
|
||||||
|
>{$_("delete")}</button
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
{/if}
|
{/if}
|
||||||
</tr>
|
</tr>
|
||||||
{/if}
|
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
@@ -189,7 +222,7 @@
|
|||||||
{:catch error}
|
{:catch error}
|
||||||
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
|
<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">
|
<span class="inline-block align-middle mr-8">
|
||||||
<b class="capitalize">{$_('general_promise_error')}</b>
|
<b class="capitalize">{$_("general_promise_error")}</b>
|
||||||
{error}
|
{error}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -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";
|
||||||
@@ -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,6 +1,6 @@
|
|||||||
<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";
|
||||||
export let copy_modal_open;
|
export let copy_modal_open;
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
{#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">
|
||||||
|
|||||||
@@ -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,20 @@
|
|||||||
|
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(">")) {
|
||||||
|
value = value.split(">")[1];
|
||||||
|
if (value.length == 0) {
|
||||||
|
return group.name.toLowerCase().includes(value.toLowerCase());
|
||||||
|
}
|
||||||
|
return (
|
||||||
|
group.name.toLowerCase().includes(value.toLowerCase()) ||
|
||||||
|
group.parentGroup.name.toLowerCase().includes(value.toLowerCase())
|
||||||
|
);
|
||||||
|
} else {
|
||||||
|
return (
|
||||||
|
group.name.toLowerCase().includes(value.toLowerCase()) ||
|
||||||
|
group.parentGroup.name.toLowerCase().includes(value.toLowerCase())
|
||||||
|
);
|
||||||
|
}
|
||||||
|
};
|
||||||
@@ -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 { StatsClientService } from "@odit/lfk-client-js";
|
import { StatsClientService } from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
export let modal_open;
|
export let modal_open;
|
||||||
@@ -66,7 +66,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";
|
||||||
@@ -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,6 +1,6 @@
|
|||||||
<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";
|
||||||
export let copy_modal_open;
|
export let copy_modal_open;
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
{#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">
|
||||||
|
|||||||
@@ -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 {
|
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
|
||||||
|
|||||||
@@ -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;
|
||||||
|
|||||||
@@ -57,9 +57,9 @@
|
|||||||
.querySelector(`[data-id="triggered_table_actions_${trackid}"]`)
|
.querySelector(`[data-id="triggered_table_actions_${trackid}"]`)
|
||||||
.classList.add("hidden");
|
.classList.add("hidden");
|
||||||
//
|
//
|
||||||
elem.childNodes[0].innerHTML = `<td data-column-id="trackName" class="gridjs-td">${elem.childNodes[0].childNodes[0].value}</td>`;
|
elem.childNodes[0].innerHTML = `<td data-column-id="trackName">${elem.childNodes[0].childNodes[0].value}</td>`;
|
||||||
elem.childNodes[1].innerHTML = `<td data-column-id="trackName" class="gridjs-td">${elem.childNodes[1].childNodes[0].value}</td>`;
|
elem.childNodes[1].innerHTML = `<td data-column-id="trackName">${elem.childNodes[1].childNodes[0].value}</td>`;
|
||||||
elem.childNodes[2].innerHTML = `<td data-column-id="trackName" class="gridjs-td">${elem.childNodes[2].childNodes[0].value}</td>`;
|
elem.childNodes[2].innerHTML = `<td data-column-id="trackName">${elem.childNodes[2].childNodes[0].value}</td>`;
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -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}
|
||||||
|
|||||||
+4
-1
@@ -30,6 +30,7 @@
|
|||||||
"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-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!",
|
||||||
@@ -472,5 +473,7 @@
|
|||||||
"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.",
|
||||||
"you-must-create-at-least-one-card-or-cancel": "Du musst mindestens eine Blankokarte erstellen (oder abbrechen).",
|
"you-must-create-at-least-one-card-or-cancel": "Du musst mindestens eine Blankokarte erstellen (oder abbrechen).",
|
||||||
"zip-postal-code": "Postleitzahl"
|
"zip-postal-code": "Postleitzahl",
|
||||||
|
"delete-cards": "Karten löschen",
|
||||||
|
"cards-deleted": "Karten gelöscht"
|
||||||
}
|
}
|
||||||
+4
-1
@@ -30,6 +30,7 @@
|
|||||||
"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-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!",
|
||||||
@@ -472,5 +473,7 @@
|
|||||||
"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.",
|
||||||
"you-must-create-at-least-one-card-or-cancel": "You must create at least one card (or cancel).",
|
"you-must-create-at-least-one-card-or-cancel": "You must create at least one card (or cancel).",
|
||||||
"zip-postal-code": "ZIP/ postal code"
|
"zip-postal-code": "ZIP/ postal code",
|
||||||
|
"delete-cards": "Delete cards",
|
||||||
|
"cards-deleted": "Cards deleted"
|
||||||
}
|
}
|
||||||
@@ -1,6 +1,5 @@
|
|||||||
import './style.css';
|
import './style.css';
|
||||||
import "toastify-js/src/toastify.css";
|
import "toastify-js/src/toastify.css";
|
||||||
import "gridjs/dist/theme/mermaid.css";
|
|
||||||
import App from './App.svelte';
|
import App from './App.svelte';
|
||||||
|
|
||||||
const app = new App({
|
const app = new App({
|
||||||
|
|||||||
+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: {
|
||||||
|
|||||||
+5
-32
@@ -1,38 +1,11 @@
|
|||||||
import svelte from '@sveltejs/vite-plugin-svelte';
|
// vite.config.js
|
||||||
import { minify } from 'html-minifier';
|
|
||||||
import { defineConfig } from 'vite';
|
import { defineConfig } from 'vite';
|
||||||
//
|
import { svelte } from '@sveltejs/vite-plugin-svelte';
|
||||||
const indexReplace = () => {
|
|
||||||
return {
|
|
||||||
name: 'html-transform',
|
|
||||||
transformIndexHtml(html) {
|
|
||||||
return minify(html, {
|
|
||||||
collapseWhitespace: true
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
};
|
|
||||||
|
|
||||||
export default defineConfig(({ command, mode }) => {
|
export default defineConfig({
|
||||||
const isProduction = mode === 'production';
|
|
||||||
return {
|
|
||||||
// base: './',
|
|
||||||
build: {
|
|
||||||
polyfillDynamicImport: false,
|
|
||||||
cssCodeSplit: false,
|
|
||||||
minify: isProduction
|
|
||||||
},
|
|
||||||
plugins: [
|
plugins: [
|
||||||
svelte({
|
svelte({
|
||||||
//@ts-ignore
|
/* plugin options */
|
||||||
hot: !isProduction,
|
})
|
||||||
emitCss: true,
|
|
||||||
extensions: [ '.md', '.svx', '.svelte' ],
|
|
||||||
preprocess: [
|
|
||||||
//
|
|
||||||
]
|
]
|
||||||
}),
|
|
||||||
indexReplace()
|
|
||||||
]
|
|
||||||
};
|
|
||||||
});
|
});
|
||||||
Reference in new issue
Block a user