Compare commits
71
Commits
0.15.4
..
a6590910cf
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
a6590910cf | ||
|
|
ad454c386c | ||
|
|
0b2c296de0
|
||
|
|
0e85940cba
|
||
|
|
8d479c32f8 | ||
|
|
549785cf7d | ||
|
|
aafc4c8d62
|
||
|
|
47dedbdc73
|
||
|
|
6fe134afc8
|
||
|
|
63a50f92e7
|
||
|
|
ca6da15ef7
|
||
|
|
8dfa19fa0f
|
||
|
|
0feee0ae2f
|
||
|
|
2a6a39916a | ||
|
|
f0a2b2859f
|
||
|
|
32ddb66fc8
|
||
|
|
df63c2388d
|
||
|
|
757655ea63
|
||
|
|
329c1cc037 | ||
|
|
da6dd55d13 | ||
|
|
0e5490f1c8 | ||
|
|
b82d638de1 | ||
|
|
224034dcc6 | ||
|
|
026d3d41c1 | ||
|
|
fd1a06b359 | ||
|
|
452d010183
|
||
|
|
eb1c17e3ac
|
||
|
|
a101873eb0
|
||
|
|
3d2acb692a
|
||
|
|
0900c2691e
|
||
|
|
1337676e08
|
||
|
|
2e075eafab | ||
|
|
14d64b6070 | ||
|
|
81b8fbf4e3 | ||
|
|
24d074752f | ||
|
|
08047a9307 | ||
|
|
1b0cd5b90b | ||
|
|
65e8998894 | ||
|
|
449948050b | ||
|
|
cf97281592 | ||
|
|
75684efa1a | ||
|
|
2c4f27a943 | ||
|
|
53b7dec7cd | ||
|
|
e0cbfb000b
|
||
|
|
3a66f4c862 | ||
|
|
85ceaa464f
|
||
|
|
976755338b
|
||
|
|
1c980059cf
|
||
|
|
2d8c4c1698
|
||
|
|
19a333d7bd
|
||
|
|
96c55db63d
|
||
|
|
fecb07ee37
|
||
|
|
e10c6480a5
|
||
|
|
f3cc07c009
|
||
|
|
068076dd47
|
||
|
|
02158605be
|
||
|
|
674e6a90ec
|
||
|
|
f679330466
|
||
|
|
93fc7c2e83
|
||
|
|
f299617c60
|
||
|
|
28cbc5b98c
|
||
|
|
c28f1ee0bc
|
||
|
|
cff112d705
|
||
|
|
9fc4ad63c4 | ||
|
|
97054a71c1 | ||
|
|
2391668a25
|
||
|
|
717d33547c | ||
|
|
997be32679 | ||
|
|
134f00c40e
|
||
|
|
47c898bdfd
|
||
|
|
e752ee12d1 |
No files matched your search
+19
-9
@@ -43,18 +43,23 @@ steps:
|
|||||||
ssh_key:
|
ssh_key:
|
||||||
from_secret: git_ssh
|
from_secret: git_ssh
|
||||||
- name: build dev
|
- name: build dev
|
||||||
image: plugins/docker
|
depends_on: ["clone"]
|
||||||
depends_on: [clone]
|
image: registry.odit.services/library/drone-kaniko
|
||||||
settings:
|
settings:
|
||||||
username:
|
username:
|
||||||
from_secret: docker_username
|
from_secret: docker_username
|
||||||
password:
|
password:
|
||||||
from_secret: docker_password
|
from_secret: docker_password
|
||||||
repo: registry.odit.services/lfk/frontend
|
build_args:
|
||||||
|
- NPM_REGISTRY_DOMAIN:
|
||||||
|
from_secret: npmjs_domain
|
||||||
|
- NPM_REGISTRY_TOKEN:
|
||||||
|
from_secret: npmjs_token
|
||||||
|
repo: lfk/frontend
|
||||||
tags:
|
tags:
|
||||||
- dev
|
- dev
|
||||||
|
cache: true
|
||||||
registry: registry.odit.services
|
registry: registry.odit.services
|
||||||
mtu: 1000
|
|
||||||
trigger:
|
trigger:
|
||||||
branch:
|
branch:
|
||||||
- dev
|
- dev
|
||||||
@@ -67,18 +72,23 @@ type: kubernetes
|
|||||||
name: build:tags
|
name: build:tags
|
||||||
steps:
|
steps:
|
||||||
- name: build $DRONE_TAG
|
- name: build $DRONE_TAG
|
||||||
image: plugins/docker
|
depends_on: ["clone"]
|
||||||
depends_on: [clone]
|
image: registry.odit.services/library/drone-kaniko
|
||||||
settings:
|
settings:
|
||||||
username:
|
username:
|
||||||
from_secret: docker_username
|
from_secret: docker_username
|
||||||
password:
|
password:
|
||||||
from_secret: docker_password
|
from_secret: docker_password
|
||||||
repo: registry.odit.services/lfk/frontend
|
build_args:
|
||||||
|
- NPM_REGISTRY_DOMAIN:
|
||||||
|
from_secret: npmjs_domain
|
||||||
|
- NPM_REGISTRY_TOKEN:
|
||||||
|
from_secret: npmjs_token
|
||||||
|
repo: lfk/frontend
|
||||||
tags:
|
tags:
|
||||||
- '${DRONE_TAG}'
|
- "${DRONE_TAG}"
|
||||||
|
cache: true
|
||||||
registry: registry.odit.services
|
registry: registry.odit.services
|
||||||
mtu: 1000
|
|
||||||
trigger:
|
trigger:
|
||||||
event:
|
event:
|
||||||
- tag
|
- tag
|
||||||
@@ -8,3 +8,4 @@ public/index.html
|
|||||||
.yarn
|
.yarn
|
||||||
.pnp.js
|
.pnp.js
|
||||||
.yarnrc.yml
|
.yarnrc.yml
|
||||||
|
pnpm-lock.yaml
|
||||||
@@ -2,9 +2,99 @@
|
|||||||
|
|
||||||
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.16.2](https://git.odit.services/lfk/frontend/compare/0.16.1...0.16.2)
|
||||||
|
|
||||||
|
- Fixed scanmodal [`#154`](https://git.odit.services/lfk/frontend/issues/154)
|
||||||
|
- Merge pull request 'feature/147-cardoverview_performance' (#153) from feature/147-cardoverview_performance into dev [`8d479c3`](https://git.odit.services/lfk/frontend/commit/8d479c32f82938904aee6a10deb80fea85487e4b)
|
||||||
|
- Merge pull request 'Fixed scanmodal' (#155) from bugfix/154-scan_select_runner_by_id into dev [`549785c`](https://git.odit.services/lfk/frontend/commit/549785cf7d1c9edc1be37dc745b97096232a08ca)
|
||||||
|
- i18n [`ca6da15`](https://git.odit.services/lfk/frontend/commit/ca6da15ef761184a55b18d56f749f660a32cbb83)
|
||||||
|
- Bsic datatable conversion [`757655e`](https://git.odit.services/lfk/frontend/commit/757655ea63b3667bc4612ae1595eb52910b61137)
|
||||||
|
- 1st datatable try with @vincjo/datatables [`81b8fbf`](https://git.odit.services/lfk/frontend/commit/81b8fbf4e341e6f2998a6e9e2053972c5c225021)
|
||||||
|
- Dasboard Cards redesign [`eb1c17e`](https://git.odit.services/lfk/frontend/commit/eb1c17e3ac7e8f5e7310a90421fc9db3ed15c497)
|
||||||
|
- set .phone to null if empty [`da6dd55`](https://git.odit.services/lfk/frontend/commit/da6dd55d139a672fa50204eabdca67d9740614a0)
|
||||||
|
- add group filtering to table [`14d64b6`](https://git.odit.services/lfk/frontend/commit/14d64b6070d98e6368da5709e9ff8221e8a621c7)
|
||||||
|
- formatting [`24d0747`](https://git.odit.services/lfk/frontend/commit/24d074752f1c5dc1a14b075ac14b448d7e129376)
|
||||||
|
- RunnersOverview loading fix [`2e075ea`](https://git.odit.services/lfk/frontend/commit/2e075eafab5c4d78fd9aa9d66834b477b2685bfc)
|
||||||
|
- Added old formatting for runner and status [`df63c23`](https://git.odit.services/lfk/frontend/commit/df63c2388da359dec9ed9968bc9f970be7092a45)
|
||||||
|
- Added custom status filter [`f0a2b28`](https://git.odit.services/lfk/frontend/commit/f0a2b2859fa18426a454b7d9d6dd22dfdfe7ce27)
|
||||||
|
- Basic checkbox fix [`1337676`](https://git.odit.services/lfk/frontend/commit/1337676e0894c46da0b6dcb7553e5ea8f88d0c14)
|
||||||
|
- Fixed all filter [`8dfa19f`](https://git.odit.services/lfk/frontend/commit/8dfa19fa0f9897c61342ece956df88731c7aa861)
|
||||||
|
- improved runner search [`1b0cd5b`](https://git.odit.services/lfk/frontend/commit/1b0cd5b90bcceb92627c6b7cdcdd7792ed81b50f)
|
||||||
|
- set table-layout:fixed + display when loaded [`65e8998`](https://git.odit.services/lfk/frontend/commit/65e89988943807c1606a8b6aea49564b13d52537)
|
||||||
|
- Trigger edit modal [`32ddb66`](https://git.odit.services/lfk/frontend/commit/32ddb66fc8d8cd689f1104759812f4cee4b7a613)
|
||||||
|
- cleaned up table search [`08047a9`](https://git.odit.services/lfk/frontend/commit/08047a93073c32f5dd7a8e958400ae8a5b7f4035)
|
||||||
|
- Fixed edit update bug [`0feee0a`](https://git.odit.services/lfk/frontend/commit/0feee0ae2fb6d8dba0b6fd72cedc0712dc749511)
|
||||||
|
- fix: z-index on action buttons [`224034d`](https://git.odit.services/lfk/frontend/commit/224034dcc6263d3b0a8ea20045e435142d8ed2af)
|
||||||
|
- rename: ThFilterGroup -> ThFilterStatus [`2a6a399`](https://git.odit.services/lfk/frontend/commit/2a6a39916a03c0466e63354e9f5ad7924cb59b6b)
|
||||||
|
- new license file version [CI SKIP] [`0e5490f`](https://git.odit.services/lfk/frontend/commit/0e5490f1c84217a5a6d5c8745c4667b32ca65e1a)
|
||||||
|
- new license file version [CI SKIP] [`026d3d4`](https://git.odit.services/lfk/frontend/commit/026d3d41c1b976a4dc7c733576a6a9e8d4b13b78)
|
||||||
|
- Updated breakpoints [`452d010`](https://git.odit.services/lfk/frontend/commit/452d0101838d72bff7d588a953faae028e2ff819)
|
||||||
|
- Tailwind bump [`a101873`](https://git.odit.services/lfk/frontend/commit/a101873eb0946b284a11a5081642711f5087da14)
|
||||||
|
- Fixed checkbox show [`0900c26`](https://git.odit.services/lfk/frontend/commit/0900c2691e4cfe5046e8ae186c8ac8884c90abd6)
|
||||||
|
- Removed unused console log [`aafc4c8`](https://git.odit.services/lfk/frontend/commit/aafc4c8d62a7a0a493c8bd60149f90c842534bdd)
|
||||||
|
- i18n import [`6fe134a`](https://git.odit.services/lfk/frontend/commit/6fe134afc8bfef4e7470b7e53b9312b172a7322b)
|
||||||
|
- Merge pull request 'fix: RunnerDetail: set .phone to null if empty' (#152) from bugfix/151-runnerdetail--cannot-unset-phone-number into dev [`329c1cc`](https://git.odit.services/lfk/frontend/commit/329c1cc037a43c818ba3b6c72581d29586d76232)
|
||||||
|
- Merge pull request 'feature/146-runner-table-performance-data-table' (#150) from feature/146-runner-table-performance-data-table into dev [`b82d638`](https://git.odit.services/lfk/frontend/commit/b82d638de1aa1f72aada212cf3e4147d808b4fcf)
|
||||||
|
- Merge pull request 'feature/148-dashboard_statscards' (#149) from feature/148-dashboard_statscards into dev [`fd1a06b`](https://git.odit.services/lfk/frontend/commit/fd1a06b3595b3713ad474e623c74105125602d46)
|
||||||
|
- Fixed top checkbox state [`3d2acb6`](https://git.odit.services/lfk/frontend/commit/3d2acb692a28c116790248679e238fb562b24ac5)
|
||||||
|
|
||||||
|
#### [0.16.1](https://git.odit.services/lfk/frontend/compare/0.16.0...0.16.1)
|
||||||
|
|
||||||
|
> 15 February 2023
|
||||||
|
|
||||||
|
- fix: donor detail: sponsorings: unset middlename will show as "null" [`#145`](https://git.odit.services/lfk/frontend/issues/145)
|
||||||
|
- 🚀RELEASE v0.16.1 [`4499480`](https://git.odit.services/lfk/frontend/commit/449948050b8673d43a8dfbb225c3198e4bbb3c7b)
|
||||||
|
|
||||||
|
#### [0.16.0](https://git.odit.services/lfk/frontend/compare/0.15.6...0.16.0)
|
||||||
|
|
||||||
|
> 3 February 2023
|
||||||
|
|
||||||
|
- First page for statsclients [`f299617`](https://git.odit.services/lfk/frontend/commit/f299617c600d2bba7b4405c7c3acae9fd93aefa8)
|
||||||
|
- 🚀RELEASE v0.16.0 [`75684ef`](https://git.odit.services/lfk/frontend/commit/75684efa1ae0edb4b4d414757c5acf2a77c572e5)
|
||||||
|
- Basic statsclient detail [`0215860`](https://git.odit.services/lfk/frontend/commit/02158605be824e5ac21a6284731138190988c794)
|
||||||
|
- Updated Add modal [`f679330`](https://git.odit.services/lfk/frontend/commit/f679330466205e6480cd7f2b7c2b4fdc41c51525)
|
||||||
|
- Switched drone to kaniko [`1c98005`](https://git.odit.services/lfk/frontend/commit/1c980059cff5c87c452428b53513507c2339451f)
|
||||||
|
- Re-added copy modal [`fecb07e`](https://git.odit.services/lfk/frontend/commit/fecb07ee373dcaaeaea69fdf8d4c6ee2c257c89c)
|
||||||
|
- Added Statsclients to sidebar [`068076d`](https://git.odit.services/lfk/frontend/commit/068076dd47373c673a25e730cb8a57c686682810)
|
||||||
|
- Fixed imports and naming [`f3cc07c`](https://git.odit.services/lfk/frontend/commit/f3cc07c009ed0a34e61f1aad47a1a31778145439)
|
||||||
|
- new license file version [CI SKIP] [`2c4f27a`](https://git.odit.services/lfk/frontend/commit/2c4f27a943bb35be6728bb49bd5c2263cba78165)
|
||||||
|
- Merge pull request 'feature/143-beamershow_clients' (#144) from feature/143-beamershow_clients into dev [`53b7dec`](https://git.odit.services/lfk/frontend/commit/53b7dec7cd516c908d45591b855f4be09371f9b1)
|
||||||
|
- Updated deletion modal [`93fc7c2`](https://git.odit.services/lfk/frontend/commit/93fc7c2e83f78dd88f15d9246127bb9e69f1a8ee)
|
||||||
|
- Updated mounted variables [`674e6a9`](https://git.odit.services/lfk/frontend/commit/674e6a90ec23dde9377bea64c14a50e41ffa450d)
|
||||||
|
- Removed Key after creation [`e10c648`](https://git.odit.services/lfk/frontend/commit/e10c6480a504338b21e30fdf2577e5b6c3b635db)
|
||||||
|
- Updated docker base images [`9767553`](https://git.odit.services/lfk/frontend/commit/976755338b8621064f9a73147aa600af1f77cd51)
|
||||||
|
- Added translation [`96c55db`](https://git.odit.services/lfk/frontend/commit/96c55db63dbfed92b78ff0e7bdab7a8cce4d76e9)
|
||||||
|
- Pinned versions [`cff112d`](https://git.odit.services/lfk/frontend/commit/cff112d705a74a135286943298f3f344341325ac)
|
||||||
|
- Tailwind bump [`e0cbfb0`](https://git.odit.services/lfk/frontend/commit/e0cbfb000bee59a71e06bd58a9c7ef6a0fc7091d)
|
||||||
|
- Added missing translation [`19a333d`](https://git.odit.services/lfk/frontend/commit/19a333d7bda525fbcb3c68f3cbf85a4f925a9707)
|
||||||
|
- Bumped apiclient [`c28f1ee`](https://git.odit.services/lfk/frontend/commit/c28f1ee0bc4456595c21858f38e52ed6f16871c5)
|
||||||
|
- new license file version [CI SKIP] [`3a66f4c`](https://git.odit.services/lfk/frontend/commit/3a66f4c862db9f35c223cc7007b0560fef4e1d63)
|
||||||
|
- Bumped apiclient [`28cbc5b`](https://git.odit.services/lfk/frontend/commit/28cbc5b98ca09657100e1740b83aa2617243b26b)
|
||||||
|
- Ignore pnpm lock [`2d8c4c1`](https://git.odit.services/lfk/frontend/commit/2d8c4c1698a1675f618e85e678012f310f87c6ee)
|
||||||
|
|
||||||
|
#### [0.15.6](https://git.odit.services/lfk/frontend/compare/0.15.5...0.15.6)
|
||||||
|
|
||||||
|
> 19 July 2021
|
||||||
|
|
||||||
|
- 🚀RELEASE v0.15.6 [`9fc4ad6`](https://git.odit.services/lfk/frontend/commit/9fc4ad63c4f77b46d645e83c94b51747b91247b8)
|
||||||
|
- Fixed donations getting reduced to the first one on certificates [`2391668`](https://git.odit.services/lfk/frontend/commit/2391668a25a1e11a1409df572d77ad1635070fbc)
|
||||||
|
- new license file version [CI SKIP] [`97054a7`](https://git.odit.services/lfk/frontend/commit/97054a71c1ab8a045762a55148124965c6994373)
|
||||||
|
|
||||||
|
#### [0.15.5](https://git.odit.services/lfk/frontend/compare/0.15.4...0.15.5)
|
||||||
|
|
||||||
|
> 5 July 2021
|
||||||
|
|
||||||
|
- 🚀RELEASE v0.15.5 [`717d335`](https://git.odit.services/lfk/frontend/commit/717d33547c3378424dd720005da9952f8a753f1a)
|
||||||
|
- Merge pull request 'Fixed kilometer conversion' (#142) from bugfix/141-runner_kilometers into dev [`997be32`](https://git.odit.services/lfk/frontend/commit/997be32679dc38c9fb0e92b6ce011057b854d99d)
|
||||||
|
- Fixed kilometer conversion [`134f00c`](https://git.odit.services/lfk/frontend/commit/134f00c40e0c8252e7604a73151e8d6685b2c61d)
|
||||||
|
- new license file version [CI SKIP] [`e752ee1`](https://git.odit.services/lfk/frontend/commit/e752ee12d17a4423f4364f7766eafbe7d4cef2d1)
|
||||||
|
|
||||||
#### [0.15.4](https://git.odit.services/lfk/frontend/compare/0.15.3...0.15.4)
|
#### [0.15.4](https://git.odit.services/lfk/frontend/compare/0.15.3...0.15.4)
|
||||||
|
|
||||||
|
> 5 July 2021
|
||||||
|
|
||||||
- Merge pull request 'fix total donation sum in dashboard' (#140) from bugfix/139-total-donation-sum-is-wrong into dev [`#139`](https://git.odit.services/lfk/frontend/issues/139)
|
- Merge pull request 'fix total donation sum in dashboard' (#140) from bugfix/139-total-donation-sum-is-wrong into dev [`#139`](https://git.odit.services/lfk/frontend/issues/139)
|
||||||
|
- 🚀RELEASE v0.15.4 [`cc4515f`](https://git.odit.services/lfk/frontend/commit/cc4515ff66b1c1de3747d0ee6cc465574accedb7)
|
||||||
- divide by 100 + toFixes(2) [`b246f2b`](https://git.odit.services/lfk/frontend/commit/b246f2b349b06d1adea318dfad58f97fb1a249bb)
|
- divide by 100 + toFixes(2) [`b246f2b`](https://git.odit.services/lfk/frontend/commit/b246f2b349b06d1adea318dfad58f97fb1a249bb)
|
||||||
|
|
||||||
#### [0.15.3](https://git.odit.services/lfk/frontend/compare/0.15.2...0.15.3)
|
#### [0.15.3](https://git.odit.services/lfk/frontend/compare/0.15.2...0.15.3)
|
||||||
|
|||||||
+5
-5
@@ -1,12 +1,12 @@
|
|||||||
FROM registry.odit.services/hub/library/node:15.14.0-alpine3.13
|
FROM registry.odit.services/hub/library/node:19.5.0-alpine3.16 as build
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
COPY package.json ./
|
COPY package.json ./
|
||||||
RUN yarn
|
RUN npx pnpm i
|
||||||
COPY package.json *.config.js postcss.config.cjs index.html ./
|
COPY package.json *.config.js postcss.config.cjs tailwind.config.js vite.config.js index.html ./
|
||||||
COPY src ./src
|
COPY src ./src
|
||||||
COPY public ./public
|
COPY public ./public
|
||||||
RUN yarn build
|
RUN yarn build
|
||||||
# final image
|
# final image
|
||||||
FROM registry.odit.services/hub/fholzer/nginx-brotli:v1.19.1
|
FROM registry.odit.services/library/nginx-brotli:3.15 as final
|
||||||
COPY --from=0 /app/dist /usr/share/nginx/html
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
COPY ./nginx.conf /etc/nginx/nginx.conf
|
COPY ./nginx.conf /etc/nginx/nginx.conf
|
||||||
+1
-1
@@ -13,7 +13,7 @@
|
|||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<span style="display: none;visibility: hidden;" id="buildinfo">RELEASE_INFO-0.15.4-RELEASE_INFO</span>
|
<span style="display: none;visibility: hidden;" id="buildinfo">RELEASE_INFO-0.16.2-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>
|
||||||
|
|||||||
+60
-56
@@ -1,56 +1,60 @@
|
|||||||
{
|
{
|
||||||
"name": "@odit/lfk-frontend",
|
"name": "@odit/lfk-frontend",
|
||||||
"version": "0.15.4",
|
"version": "0.16.2",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"i18n-order": "node order.js",
|
"i18n-order": "node order.js",
|
||||||
"dev": "vite",
|
"dev": "vite",
|
||||||
"build": "vite build",
|
"build": "vite build",
|
||||||
"release": "release-it",
|
"release": "release-it",
|
||||||
"licenses:export": "license-exporter --json -o public"
|
"licenses:export": "license-exporter --json -o public"
|
||||||
},
|
},
|
||||||
"license": "CC-BY-NC-SA-4.0",
|
"license": "CC-BY-NC-SA-4.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@odit/lfk-client-js": "0.11.0",
|
"@odit/lfk-client-js": "0.13.1",
|
||||||
"@odit/license-exporter": "0.0.11",
|
"@odit/license-exporter": "0.0.11",
|
||||||
"@sveltejs/vite-plugin-svelte": "1.0.0-next.6",
|
"@sveltejs/vite-plugin-svelte": "1.0.0-next.6",
|
||||||
"@types/html-minifier": "4.0.0",
|
"@types/html-minifier": "4.0.0",
|
||||||
"auto-changelog": "2.2.1",
|
"@vincjo/datatables": "^1.1.0",
|
||||||
"autoprefixer": "^10.2.5",
|
"auto-changelog": "2.2.1",
|
||||||
"check-password-strength": "2.0.2",
|
"autoprefixer": "10.2.5",
|
||||||
"csvtojson": "2.0.10",
|
"check-password-strength": "2.0.2",
|
||||||
"gridjs": "3.4.0",
|
"csvtojson": "2.0.10",
|
||||||
"html-minifier": "4.0.0",
|
"gridjs": "3.4.0",
|
||||||
"localforage": "1.9.0",
|
"html-minifier": "4.0.0",
|
||||||
"marked": "2.0.3",
|
"localforage": "1.9.0",
|
||||||
"postcss": "^8.2.10",
|
"marked": "2.0.3",
|
||||||
"release-it": "14.6.1",
|
"postcss": "8.2.10",
|
||||||
"svelte": "3.37.0",
|
"release-it": "14.6.1",
|
||||||
"svelte-focus-trap": "1.2.0",
|
"svelte": "3.37.0",
|
||||||
"svelte-i18n": "3.3.9",
|
"svelte-focus-trap": "1.2.0",
|
||||||
"svelte-preprocess": "^4.7.0",
|
"svelte-i18n": "3.3.9",
|
||||||
"svelte-select": "3.17.0",
|
"svelte-preprocess": "4.7.0",
|
||||||
"tailwindcss": "^2.1.1",
|
"svelte-select": "3.17.0",
|
||||||
"tinro": "0.6.1",
|
"tailwindcss": "3.2.7",
|
||||||
"toastify-js": "1.10.0",
|
"tinro": "0.6.1",
|
||||||
"validator": "13.5.2",
|
"toastify-js": "1.10.0",
|
||||||
"vite": "2.1.5",
|
"validator": "13.5.2",
|
||||||
"xlsx": "0.16.9"
|
"vite": "2.1.5",
|
||||||
},
|
"xlsx": "0.16.9"
|
||||||
"release-it": {
|
},
|
||||||
"git": {
|
"release-it": {
|
||||||
"commit": true,
|
"git": {
|
||||||
"requireCleanWorkingDir": false,
|
"commit": true,
|
||||||
"commitMessage": "🚀RELEASE v${version}",
|
"requireCleanWorkingDir": false,
|
||||||
"push": false,
|
"commitMessage": "🚀RELEASE v${version}",
|
||||||
"tag": true,
|
"push": false,
|
||||||
"tagName": null,
|
"tag": true,
|
||||||
"tagAnnotation": "v${version}"
|
"tagName": null,
|
||||||
},
|
"tagAnnotation": "v${version}"
|
||||||
"npm": {
|
},
|
||||||
"publish": false
|
"npm": {
|
||||||
},
|
"publish": false
|
||||||
"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"
|
"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"
|
||||||
}
|
}
|
||||||
}
|
},
|
||||||
|
"dependencies": {
|
||||||
|
"@paralleldrive/cuid2": "^2.2.0"
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -1 +1 @@
|
|||||||
[{"author":"ODIT.Services","repo":{"type":"git","url":"git+https://git.odit.services/lfk/lfk-client-js"},"description":"A lib to interact with https://git.odit.services/lfk/backend. Use this version for native JS applications.","name":"@odit/lfk-client-js","license":"CC-BY-NC-SA-4.0","version":"0.11.0","licensetext":"Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Creative\r\nCommons Corporation (\"Creative Commons\") is not a law firm and does not provide\r\nlegal services or legal advice. Distribution of Creative Commons public licenses\r\ndoes not create a lawyer-client or other relationship. Creative Commons makes\r\nits licenses and related information available on an \"as-is\" basis. Creative\r\nCommons gives no warranties regarding its licenses, any material licensed\r\nunder their terms and conditions, or any related information. Creative Commons\r\ndisclaims all liability for damages resulting from their use to the fullest\r\nextent possible.\r\n\r\nUsing Creative Commons Public Licenses\r\n\r\nCreative Commons public licenses provide a standard set of terms and conditions\r\nthat creators and other rights holders may use to share original works of\r\nauthorship and other material subject to copyright and certain other rights\r\nspecified in the public license below. The following considerations are for\r\ninformational purposes only, are not exhaustive, and do not form part of our\r\nlicenses.\r\n\r\nConsiderations for licensors: Our public licenses are intended for use by\r\nthose authorized to give the public permission to use material in ways otherwise\r\nrestricted by copyright and certain other rights. Our licenses are irrevocable.\r\nLicensors should read and understand the terms and conditions of the license\r\nthey choose before applying it. Licensors should also secure all rights necessary\r\nbefore applying our licenses so that the public can reuse the material as\r\nexpected. Licensors should clearly mark any material not subject to the license.\r\nThis includes other CC-licensed material, or material used under an exception\r\nor limitation to copyright. More considerations for licensors : wiki.creativecommons.org/Considerations_for_licensors\r\n\r\nConsiderations for the public: By using one of our public licenses, a licensor\r\ngrants the public permission to use the licensed material under specified\r\nterms and conditions. If the licensor's permission is not necessary for any\r\nreason–for example, because of any applicable exception or limitation to copyright–then\r\nthat use is not regulated by the license. Our licenses grant only permissions\r\nunder copyright and certain other rights that a licensor has authority to\r\ngrant. Use of the licensed material may still be restricted for other reasons,\r\nincluding because others have copyright or other rights in the material. A\r\nlicensor may make special requests, such as asking that all changes be marked\r\nor described. Although not required by our licenses, you are encouraged to\r\nrespect those requests where reasonable. More considerations for the public\r\n: wiki.creativecommons.org/Considerations_for_licensees\r\n\r\nCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public\r\nLicense\r\n\r\nBy exercising the Licensed Rights (defined below), You accept and agree to\r\nbe bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-ShareAlike\r\n4.0 International Public License (\"Public License\"). To the extent this Public\r\nLicense may be interpreted as a contract, You are granted the Licensed Rights\r\nin consideration of Your acceptance of these terms and conditions, and the\r\nLicensor grants You such rights in consideration of benefits the Licensor\r\nreceives from making the Licensed Material available under these terms and\r\nconditions.\r\n\r\nSection 1 – Definitions.\r\n\r\na. Adapted Material means material subject to Copyright and Similar Rights\r\nthat is derived from or based upon the Licensed Material and in which the\r\nLicensed Material is translated, altered, arranged, transformed, or otherwise\r\nmodified in a manner requiring permission under the Copyright and Similar\r\nRights held by the Licensor. For purposes of this Public License, where the\r\nLicensed Material is a musical work, performance, or sound recording, Adapted\r\nMaterial is always produced where the Licensed Material is synched in timed\r\nrelation with a moving image.\r\n\r\nb. Adapter's License means the license You apply to Your Copyright and Similar\r\nRights in Your contributions to Adapted Material in accordance with the terms\r\nand conditions of this Public License.\r\n\r\nc. BY-NC-SA Compatible License means a license listed at creativecommons.org/compatiblelicenses,\r\napproved by Creative Commons as essentially the equivalent of this Public\r\nLicense.\r\n\r\nd. Copyright and Similar Rights means copyright and/or similar rights closely\r\nrelated to coLine truncated
|
[{"author":"Eric Elliott","repo":{"type":"git","url":"https://github.com/ericelliott/cuid2"},"description":"","name":"@paralleldrive/cuid2","license":"MIT","version":"2.2.0","licensetext":"MIT License\n\nCopyright (c) 2022 Eric Elliott\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":"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\nLicensorLine truncated
|
||||||
@@ -72,6 +72,8 @@
|
|||||||
import Scans from "./components/scans/Scans.svelte";
|
import Scans from "./components/scans/Scans.svelte";
|
||||||
import ScanDetail from "./components/scans/ScanDetail.svelte";
|
import ScanDetail from "./components/scans/ScanDetail.svelte";
|
||||||
import Cards from "./components/cards/Cards.svelte";
|
import Cards from "./components/cards/Cards.svelte";
|
||||||
|
import StatsClients from "./components/statsclients/StatsClients.svelte";
|
||||||
|
import StatsClientDetail from "./components/statsclients/StatsClientDetail.svelte";
|
||||||
store.init();
|
store.init();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -206,6 +208,14 @@
|
|||||||
<ScanStationDetail {params} />
|
<ScanStationDetail {params} />
|
||||||
</Route>
|
</Route>
|
||||||
</Route>
|
</Route>
|
||||||
|
<Route path="/statsclients/*">
|
||||||
|
<Route path="/">
|
||||||
|
<StatsClients />
|
||||||
|
</Route>
|
||||||
|
<Route path="/:clientid" let:params>
|
||||||
|
<StatsClientDetail {params} />
|
||||||
|
</Route>
|
||||||
|
</Route>
|
||||||
<Route path="/about">
|
<Route path="/about">
|
||||||
<About />
|
<About />
|
||||||
</Route>
|
</Route>
|
||||||
|
|||||||
@@ -5,6 +5,7 @@
|
|||||||
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 = {};
|
||||||
@@ -21,6 +22,10 @@
|
|||||||
$: 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 +70,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) => {
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -3,279 +3,230 @@
|
|||||||
import { RunnerCardService } from "@odit/lfk-client-js";
|
import { RunnerCardService } from "@odit/lfk-client-js";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
|
import { DataHandler, Datatable, Th, ThFilter } from "@vincjo/datatables";
|
||||||
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";
|
||||||
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(
|
||||||
{ runner },
|
{ runner },
|
||||||
{ label: getRunnerLabel(card.runner), value: card.runner }
|
{ label: getRunnerLabel(card.runner), value: card.runner }
|
||||||
);
|
);
|
||||||
card.runner = card.runner.id;
|
card.runner = card.runner.id;
|
||||||
}
|
} else {
|
||||||
else{
|
card.runner = null;
|
||||||
card.runner=null;
|
runner = null;
|
||||||
runner = null
|
|
||||||
}
|
}
|
||||||
editable = Object.assign(editable, card);
|
editable = Object.assign(editable, card);
|
||||||
original_data = Object.assign(original_data, card);
|
original_data = Object.assign(original_data, card);
|
||||||
edit_modal_open = true;
|
edit_modal_open = true;
|
||||||
}
|
}
|
||||||
// -----------------
|
|
||||||
let scrollTop = 0;
|
|
||||||
$: 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>
|
||||||
|
|
||||||
<style>
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:UPDATE")}
|
||||||
table tbody {
|
|
||||||
display: block;
|
|
||||||
overflow-y: scroll;
|
|
||||||
}
|
|
||||||
|
|
||||||
table thead, table tbody tr {
|
|
||||||
display: table;
|
|
||||||
width: 100%;
|
|
||||||
table-layout: fixed;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('CARD:UPDATE')}
|
|
||||||
<CardDetailModal
|
<CardDetailModal
|
||||||
bind:current_cards
|
bind:current_cards
|
||||||
bind:edit_modal_open
|
bind:edit_modal_open
|
||||||
bind:runner
|
bind:runner
|
||||||
bind:editable
|
bind:editable
|
||||||
bind:original_data />
|
bind:original_data
|
||||||
|
on:dataUpdated={(handler.setRows(current_cards))}
|
||||||
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('CARD:GET')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:GET")}
|
||||||
{#await cards_promise}
|
{#await cards_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">{$_('loading-cards')}</p>
|
>
|
||||||
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
<p class="font-bold">{$_("loading-cards")}</p>
|
||||||
|
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
||||||
</div>
|
</div>
|
||||||
{:then}
|
{:then}
|
||||||
{#if current_cards.length === 0}
|
{#if current_cards.length === 0}
|
||||||
<CardsEmptyState />
|
<CardsEmptyState />
|
||||||
{:else}
|
{:else}
|
||||||
<input
|
<div class="h-12">
|
||||||
type="search"
|
<GenerateRunnerCards bind:cards_show bind:generate_cards />
|
||||||
bind:value={searchvalue}
|
</div>
|
||||||
placeholder={$_('datatable.search')}
|
<Datatable {handler}>
|
||||||
aria-label={$_('datatable.search')}
|
<table>
|
||||||
class="gridjs-input gridjs-search-input mb-4" />
|
<thead>
|
||||||
<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>
|
<tr>
|
||||||
<th
|
<th>
|
||||||
scope="col"
|
<input
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
type="checkbox"
|
||||||
<span
|
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={() => {
|
on:click={() => {
|
||||||
const newstate = !current_cards.some((r) => r.is_selected === true);
|
if (generate_cards.length != current_cards.length) {
|
||||||
current_cards = current_cards.map((r) => {
|
generate_cards = current_cards;
|
||||||
r.is_selected = newstate;
|
} else {
|
||||||
return r;
|
generate_cards = [];
|
||||||
});
|
}
|
||||||
}}
|
}}
|
||||||
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>
|
</th>
|
||||||
|
<Th {handler} orderBy="code">{$_("code")}</Th>
|
||||||
|
<Th {handler} orderBy="runner">{$_("runner")}</Th>
|
||||||
|
<Th {handler} orderBy="status">{$_("status")}</Th>
|
||||||
|
<th>{$_("action")}</th>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th />
|
||||||
|
<ThFilter {handler} filterBy="code" />
|
||||||
|
<ThFilter {handler} filterBy="runner" />
|
||||||
|
<ThFilterStatus {handler} />
|
||||||
|
<th />
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="divide-y divide-gray-200 virtual-wrapper"
|
<tbody>
|
||||||
on:scroll={updateScroll}
|
{#each $rows as row}
|
||||||
style="height: 70vh; width:100%"
|
<tr>
|
||||||
bind:this={ele}
|
<td>
|
||||||
>
|
<input
|
||||||
{#each filtered_cards as card, index}
|
type="checkbox"
|
||||||
{#if card.code
|
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
.toLowerCase()
|
checked={generate_cards.filter((i) => i.id == row.id)
|
||||||
.includes(
|
.length > 0}
|
||||||
searchvalue.toLowerCase()
|
on:click={() => {
|
||||||
) || card.runner?.firstname
|
if (
|
||||||
.toLowerCase()
|
generate_cards.findIndex((i) => i.id == row.id) == -1
|
||||||
.includes(
|
) {
|
||||||
searchvalue.toLowerCase()
|
generate_cards.push(row);
|
||||||
) || card.runner?.middlename
|
generate_cards = generate_cards;
|
||||||
.toLowerCase()
|
} else {
|
||||||
.includes(
|
generate_cards = generate_cards.filter(
|
||||||
searchvalue.toLowerCase()
|
(r) => r.id != row.id
|
||||||
) || card.runner?.lastname
|
);
|
||||||
.toLowerCase()
|
}
|
||||||
.includes(
|
console.log(generate_cards);
|
||||||
searchvalue.toLowerCase()
|
}}
|
||||||
) || should_display_based_on_id(card.id)}
|
/>
|
||||||
<tr data-rowid="card_{card.id}">
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
<td>{row.code}</td>
|
||||||
<input
|
<td>
|
||||||
bind:checked={card.is_selected}
|
{#if row.runner}
|
||||||
type="checkbox"
|
<a
|
||||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded" />
|
href="../runners/{row.runner.id}"
|
||||||
</td>
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
>{row.runner.firstname}
|
||||||
<div class="flex items-center">{card.code}</div>
|
{row.runner.middlename || ""}
|
||||||
</td>
|
{row.runner.lastname}</a
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
>
|
||||||
<div class="flex items-center">
|
{:else}{$_("non-blanko")}{/if}
|
||||||
{#if card.runner}
|
</td>
|
||||||
<a
|
<td>
|
||||||
href="../runners/{card.runner.id}"
|
{#if row.enabled}
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{card.runner.firstname}
|
<span
|
||||||
{card.runner.middlename || ''}
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"
|
||||||
{card.runner.lastname}</a>
|
>{$_("enabled")}</span
|
||||||
{:else}{$_('non-blanko')}{/if}
|
>
|
||||||
</div>
|
{:else}
|
||||||
</td>
|
<span
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800"
|
||||||
<div class="flex items-center">
|
>{$_("disabled")}</span
|
||||||
{#if card.enabled}
|
>
|
||||||
<span
|
{/if}
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800">{$_('enabled')}</span>
|
</td>
|
||||||
{:else}
|
<td>
|
||||||
<span
|
{#if active_deletes[row.id] === true}
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800">{$_('disabled')}</span>
|
<button
|
||||||
{/if}
|
on:click={() => {
|
||||||
</div>
|
active_deletes[row.id] = false;
|
||||||
</td>
|
}}
|
||||||
|
tabindex="0"
|
||||||
{#if active_deletes[card.id] === true}
|
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer"
|
||||||
<td
|
>{$_("cancel-delete")}</button
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
active_deletes[card.id] = false;
|
RunnerCardService.runnerCardControllerRemove(
|
||||||
}}
|
row.id,
|
||||||
tabindex="0"
|
true
|
||||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">{$_('cancel-delete')}</button>
|
)
|
||||||
<button
|
.then((resp) => {
|
||||||
on:click={() => {
|
current_cards = current_cards.filter(
|
||||||
RunnerCardService.runnerCardControllerRemove(card.id, false).then(
|
(obj) => obj.id !== row.id
|
||||||
(resp) => {
|
);
|
||||||
current_cards = current_cards.filter(
|
})
|
||||||
(obj) => obj.id !== card.id
|
.catch((err) => {});
|
||||||
);
|
}}
|
||||||
Toastify({
|
tabindex="0"
|
||||||
text: $_('card-deleted'),
|
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
|
||||||
duration: 500,
|
>{$_("confirm-delete")}</button
|
||||||
backgroundColor:
|
>
|
||||||
'linear-gradient(to right, #00b09b, #96c93d)',
|
{:else}
|
||||||
}).showToast();
|
<button
|
||||||
}
|
on:click={() => {
|
||||||
);
|
open_edit_modal(row);
|
||||||
}}
|
}}
|
||||||
tabindex="0"
|
class="text-indigo-600 hover:text-indigo-900"
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('confirm-delete')}</button>
|
>{$_("details")}</button
|
||||||
</td>
|
>
|
||||||
{:else}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:DELETE")}
|
||||||
<td
|
<button
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
on:click={() => {
|
||||||
<button
|
active_deletes[row.id] = true;
|
||||||
on:click={() => {
|
}}
|
||||||
open_edit_modal(card);
|
tabindex="0"
|
||||||
}}
|
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
|
||||||
class="text-indigo-600 hover:text-indigo-900">{$_('details')}</button>
|
>{$_("delete")}</button
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('CARD:DELETE')}
|
>
|
||||||
<button
|
{/if}
|
||||||
on:click={() => {
|
{/if}
|
||||||
active_deletes[card.id] = true;
|
</td>
|
||||||
}}
|
</tr>
|
||||||
tabindex="0"
|
{/each}
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
{/if}
|
|
||||||
</tr>
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</Datatable>
|
||||||
{/if}
|
{/if}
|
||||||
{: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>
|
||||||
{/await}
|
{/await}
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
table tbody {
|
||||||
|
display: block;
|
||||||
|
overflow-y: scroll;
|
||||||
|
}
|
||||||
|
|
||||||
|
table thead,
|
||||||
|
table tbody tr {
|
||||||
|
display: table;
|
||||||
|
width: 100%;
|
||||||
|
table-layout: fixed;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -0,0 +1,29 @@
|
|||||||
|
<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>
|
||||||
@@ -256,6 +256,26 @@
|
|||||||
<span>{$_('scanstations')}</span>
|
<span>{$_('scanstations')}</span>
|
||||||
</a>
|
</a>
|
||||||
{/if}
|
{/if}
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes('STATSCLIENT:GET')}
|
||||||
|
<a
|
||||||
|
class:bg-gray-100={$router.path === '/statsclients/'}
|
||||||
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
||||||
|
href="/statsclients/">
|
||||||
|
<svg
|
||||||
|
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
||||||
|
fill="currentColor"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"><path
|
||||||
|
fill="none"
|
||||||
|
d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z" /></svg>
|
||||||
|
<span>{$_('statsclients')}</span>
|
||||||
|
</a>
|
||||||
|
{/if}
|
||||||
<a
|
<a
|
||||||
class:bg-gray-100={$router.path === '/settings/'}
|
class:bg-gray-100={$router.path === '/settings/'}
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
||||||
|
|||||||
@@ -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}
|
|
||||||
@@ -207,7 +207,7 @@
|
|||||||
<a
|
<a
|
||||||
href="../donations/{d.id}"
|
href="../donations/{d.id}"
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-600 text-white mr-1">{d.runner.firstname}
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-600 text-white mr-1">{d.runner.firstname}
|
||||||
{d.runner.middlename}
|
{d.runner.middlename || ""}
|
||||||
{d.runner.lastname}</a>
|
{d.runner.lastname}</a>
|
||||||
{:else}
|
{:else}
|
||||||
<a
|
<a
|
||||||
|
|||||||
@@ -1,403 +1,418 @@
|
|||||||
<script>
|
<script>
|
||||||
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
||||||
import {
|
import {
|
||||||
RunnerCardService,
|
RunnerCardService,
|
||||||
RunnerOrganizationService,
|
RunnerOrganizationService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
export let cards_show = false;
|
import { init } from "@paralleldrive/cuid2";
|
||||||
export let generate_cards = [];
|
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
|
||||||
export let generate_runners = [];
|
|
||||||
export let generate_orgs = [];
|
|
||||||
export let generate_teams = [];
|
|
||||||
$: cards_dropdown_open = false;
|
|
||||||
document.addEventListener("click", function (e) {
|
|
||||||
if (
|
|
||||||
e.target.parentNode?.parentNode?.id != "cards:dropdown" &&
|
|
||||||
e.target.parentNode?.parentNode?.id != "cards:dropdown:menu"
|
|
||||||
) {
|
|
||||||
cards_dropdown_open = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function generateRunnerCards(locale) {
|
export let cards_show = false;
|
||||||
cards_dropdown_open = false;
|
export let generate_cards = [];
|
||||||
|
export let generate_runners = [];
|
||||||
|
export let generate_orgs = [];
|
||||||
|
export let generate_teams = [];
|
||||||
|
$: cards_dropdown_open = false;
|
||||||
|
document.addEventListener("click", function (e) {
|
||||||
|
if (
|
||||||
|
e.target.parentNode?.parentNode?.id != "cards:dropdown" &&
|
||||||
|
e.target.parentNode?.parentNode?.id != "cards:dropdown:menu"
|
||||||
|
) {
|
||||||
|
cards_dropdown_open = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (generate_orgs.length > 0) {
|
function generateRunnerCards(locale) {
|
||||||
generateOrgCards(locale);
|
cards_dropdown_open = false;
|
||||||
} else if (generate_teams.length > 0) {
|
|
||||||
generateTeamCards(locale);
|
if (generate_orgs.length > 0) {
|
||||||
} else if (generate_runners.length > 0) {
|
generateOrgCards(locale);
|
||||||
generateRunnersCards(locale);
|
} else if (generate_teams.length > 0) {
|
||||||
|
generateTeamCards(locale);
|
||||||
|
} else if (generate_runners.length > 0) {
|
||||||
|
generateRunnersCards(locale);
|
||||||
|
} else {
|
||||||
|
generateCards(locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateCards(locale) {
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("generating-pdf"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
fetch(
|
||||||
|
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(generate_cards),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
} else {
|
} else {
|
||||||
generateCards(locale);
|
return response.blob();
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
.then((blob) => {
|
||||||
function generateCards(locale) {
|
const url = window.URL.createObjectURL(blob);
|
||||||
const toast = Toastify({
|
let a = document.createElement("a");
|
||||||
text: $_("generating-pdf"),
|
a.href = url;
|
||||||
duration: -1,
|
a.download = `${$_("runnercards")}-${locale}-${createId()}.pdf`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
fetch(
|
})
|
||||||
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
.catch((err) => {
|
||||||
{
|
console.error(err);
|
||||||
method: "POST",
|
});
|
||||||
headers: {
|
}
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(generate_cards),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-generation-failed"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
|
||||||
}).showToast();
|
|
||||||
} else {
|
|
||||||
return response.blob();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('runnercards')}-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateRunnersCards(locale) {
|
async function generateRunnersCards(locale) {
|
||||||
const toast = Toastify({
|
const toast = Toastify({
|
||||||
text: $_("generating-pdf"),
|
text: $_("generating-pdf"),
|
||||||
duration: -1,
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
||||||
|
let cards = [];
|
||||||
|
for (let runner of generate_runners) {
|
||||||
|
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
||||||
|
if (!card) {
|
||||||
|
card = await RunnerCardService.runnerCardControllerPost({
|
||||||
|
runner: runner.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
cards.push(card);
|
||||||
|
}
|
||||||
|
fetch(
|
||||||
|
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(cards),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
if (generate_runners.length == 1) {
|
||||||
|
a.download = `${$_("runnercards")}_${generate_runners[0].firstname}_${
|
||||||
|
generate_runners[0].lastname
|
||||||
|
}-${locale}-${createId()}.pdf`;
|
||||||
|
} else {
|
||||||
|
a.download = `${$_("runnercards")}-${locale}-${createId()}.pdf`;
|
||||||
|
}
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateTeamCards(locale) {
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("generating-pdfs"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
let count = 0;
|
||||||
|
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
||||||
|
for (const t of generate_teams) {
|
||||||
|
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
|
t.id
|
||||||
|
);
|
||||||
|
let cards = [];
|
||||||
|
for (let runner of runners) {
|
||||||
|
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
||||||
|
if (!card) {
|
||||||
|
card = await RunnerCardService.runnerCardControllerPost({
|
||||||
|
runner: runner.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
cards.push(card);
|
||||||
|
}
|
||||||
|
fetch(
|
||||||
|
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(cards),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
count++;
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = `${$_("runnercards")}_${t.name}-${locale}-${createId()}.pdf`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
if (count === generate_teams.length) {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdfs-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateOrgCards(locale) {
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("generating-pdfs"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
||||||
|
let count = 0;
|
||||||
|
let count_orgs = 0;
|
||||||
|
for (const o of generate_orgs) {
|
||||||
|
count_orgs++;
|
||||||
|
let count = 0;
|
||||||
|
let runners =
|
||||||
|
await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
||||||
|
o.id,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
let cards = [];
|
||||||
|
for (let runner of runners) {
|
||||||
|
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
||||||
|
if (!card) {
|
||||||
|
card = await RunnerCardService.runnerCardControllerPost({
|
||||||
|
runner: runner.id,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
cards.push(card);
|
||||||
|
}
|
||||||
|
await fetch(
|
||||||
|
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(cards),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = `${$_("runnercards")}_${o.name}_direct-${locale}-${createId()}.pdf`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
||||||
|
toast.hideToast();
|
||||||
|
console.log("here");
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdfs-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
for (const t of o.teams) {
|
||||||
|
count++;
|
||||||
|
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
|
t.id
|
||||||
|
);
|
||||||
let cards = [];
|
let cards = [];
|
||||||
for (let runner of generate_runners) {
|
for (let runner of runners) {
|
||||||
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
||||||
if (!card) {
|
if (!card) {
|
||||||
card = await RunnerCardService.runnerCardControllerPost({
|
card = await RunnerCardService.runnerCardControllerPost({
|
||||||
runner: runner.id,
|
runner: runner.id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
cards.push(card);
|
cards.push(card);
|
||||||
}
|
}
|
||||||
fetch(
|
await fetch(
|
||||||
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify(cards),
|
body: JSON.stringify(cards),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status != "200") {
|
if (response.status != "200") {
|
||||||
toast.hideToast();
|
toast.hideToast();
|
||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdf-generation-failed"),
|
text: $_("pdf-generation-failed"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
} else {
|
} else {
|
||||||
return response.blob();
|
return response.blob();
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
if(generate_runners.length == 1){
|
|
||||||
a.download = `${$_('runnercards')}_${generate_runners[0].firstname}_${generate_runners[0].lastname}-${locale}.pdf`;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
a.download = `Runnercards-${locale}.pdf`;
|
|
||||||
}
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateTeamCards(locale) {
|
|
||||||
const toast = Toastify({
|
|
||||||
text: $_("generating-pdfs"),
|
|
||||||
duration: -1,
|
|
||||||
}).showToast();
|
|
||||||
let count = 0;
|
|
||||||
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
|
||||||
for (const t of generate_teams) {
|
|
||||||
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
|
||||||
t.id
|
|
||||||
);
|
|
||||||
let cards = [];
|
|
||||||
for (let runner of runners) {
|
|
||||||
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
|
||||||
if (!card) {
|
|
||||||
card = await RunnerCardService.runnerCardControllerPost({
|
|
||||||
runner: runner.id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
cards.push(card);
|
|
||||||
}
|
}
|
||||||
fetch(
|
})
|
||||||
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
.then((blob) => {
|
||||||
{
|
const url = window.URL.createObjectURL(blob);
|
||||||
method: "POST",
|
let a = document.createElement("a");
|
||||||
headers: {
|
a.href = url;
|
||||||
"Content-Type": "application/json",
|
a.download = `${$_("runnercards")}_${o.name}_${
|
||||||
},
|
t.name
|
||||||
body: JSON.stringify(cards),
|
}-${locale}-${createId()}.pdf`;
|
||||||
}
|
document.body.appendChild(a);
|
||||||
)
|
a.click();
|
||||||
.then((response) => {
|
a.remove();
|
||||||
if (response.status != "200") {
|
if (
|
||||||
toast.hideToast();
|
count === o.teams.length &&
|
||||||
Toastify({
|
count_orgs === generate_orgs.length
|
||||||
text: $_("pdf-generation-failed"),
|
) {
|
||||||
duration: 3500,
|
toast.hideToast();
|
||||||
backgroundColor:
|
Toastify({
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
text: $_("pdfs-successfully-generated"),
|
||||||
}).showToast();
|
duration: 3500,
|
||||||
} else {
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
return response.blob();
|
}).showToast();
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
count++;
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('runnercards')}_${t.name}-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === generate_teams.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateOrgCards(locale) {
|
|
||||||
const toast = Toastify({
|
|
||||||
text: $_("generating-pdfs"),
|
|
||||||
duration: -1,
|
|
||||||
}).showToast();
|
|
||||||
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
|
||||||
let count = 0;
|
|
||||||
let count_orgs =0;
|
|
||||||
for (const o of generate_orgs) {
|
|
||||||
count_orgs++;
|
|
||||||
let count = 0;
|
|
||||||
let runners = await RunnerOrganizationService.runnerOrganizationControllerGetRunners(o.id, true)
|
|
||||||
let cards = [];
|
|
||||||
for (let runner of runners) {
|
|
||||||
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
|
||||||
if (!card) {
|
|
||||||
card = await RunnerCardService.runnerCardControllerPost({
|
|
||||||
runner: runner.id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
cards.push(card);
|
|
||||||
}
|
}
|
||||||
await fetch(
|
})
|
||||||
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
.catch((err) => {});
|
||||||
{
|
}
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(cards),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-generation-failed"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
|
||||||
}).showToast();
|
|
||||||
} else {
|
|
||||||
return response.blob();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('runnercards')}_${o.name}_direct-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
console.log("here")
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
for (const t of o.teams) {
|
|
||||||
count++;
|
|
||||||
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
|
||||||
t.id
|
|
||||||
);
|
|
||||||
let cards = [];
|
|
||||||
for (let runner of runners) {
|
|
||||||
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
|
||||||
if (!card) {
|
|
||||||
card = await RunnerCardService.runnerCardControllerPost({
|
|
||||||
runner: runner.id,
|
|
||||||
});
|
|
||||||
}
|
|
||||||
cards.push(card);
|
|
||||||
}
|
|
||||||
await fetch(
|
|
||||||
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(cards),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-generation-failed"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
|
||||||
}).showToast();
|
|
||||||
} else {
|
|
||||||
return response.blob();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('runnercards')}_${o.name}_${t.name}-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if cards_show}
|
{#if cards_show}
|
||||||
<div id="cards:dropdown" class="relative inline-block">
|
<div id="cards:dropdown" class="relative inline-block">
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
cards_dropdown_open = !cards_dropdown_open;
|
cards_dropdown_open = !cards_dropdown_open;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm inline-flex"
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm inline-flex"
|
||||||
id="options-menu"
|
id="options-menu"
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
aria-expanded="true">
|
aria-expanded="true"
|
||||||
{$_('generate-runnercards')}
|
>
|
||||||
<svg
|
{$_("generate-runnercards")}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<svg
|
||||||
width="24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
height="24"
|
width="24"
|
||||||
viewBox="0 0 24 24"
|
height="24"
|
||||||
class="-mr-1 ml-2 h-5 w-5"><path
|
viewBox="0 0 24 24"
|
||||||
fill="none"
|
class="-mr-1 ml-2 h-5 w-5"
|
||||||
d="M0 0h24v24H0z" />
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
d="M3 19h18v2H3v-2zm10-5.83l6.07-6.07 1.42 1.41L12 17 3.52 8.52l1.4-1.42L11 13.17V2h2v11.17z" /></svg>
|
d="M3 19h18v2H3v-2zm10-5.83l6.07-6.07 1.42 1.41L12 17 3.52 8.52l1.4-1.42L11 13.17V2h2v11.17z"
|
||||||
</button>
|
/></svg
|
||||||
</div>
|
>
|
||||||
{#if cards_dropdown_open}
|
</button>
|
||||||
<div
|
|
||||||
class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5"
|
|
||||||
id="cards:dropdown:menu">
|
|
||||||
<div
|
|
||||||
class="py-1"
|
|
||||||
role="menu"
|
|
||||||
aria-orientation="vertical"
|
|
||||||
aria-labelledby="options-menu">
|
|
||||||
<span
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700">{$_('select-language')}</span>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
generateRunnerCards('de');
|
|
||||||
}}
|
|
||||||
type="submit"
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
|
||||||
role="menuitem">
|
|
||||||
{$_('german')}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
generateRunnerCards('en');
|
|
||||||
}}
|
|
||||||
type="submit"
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
|
||||||
role="menuitem">
|
|
||||||
{$_('english')}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
|
{#if cards_dropdown_open}
|
||||||
|
<div
|
||||||
|
class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 z-10"
|
||||||
|
id="cards:dropdown:menu"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="py-1"
|
||||||
|
role="menu"
|
||||||
|
aria-orientation="vertical"
|
||||||
|
aria-labelledby="options-menu"
|
||||||
|
>
|
||||||
|
<span class="block w-full text-left px-4 py-2 text-sm text-gray-700"
|
||||||
|
>{$_("select-language")}</span
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
generateRunnerCards("de");
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
||||||
|
role="menuitem"
|
||||||
|
>
|
||||||
|
{$_("german")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
generateRunnerCards("en");
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
||||||
|
role="menuitem"
|
||||||
|
>
|
||||||
|
{$_("english")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1,331 +1,355 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import {
|
import {
|
||||||
DonationService,
|
DonationService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
RunnerOrganizationService
|
RunnerOrganizationService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
export let certificates_show = false;
|
import { init } from "@paralleldrive/cuid2";
|
||||||
export let generate_runners = [];
|
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
|
||||||
export let generate_orgs = [];
|
|
||||||
export let generate_teams = [];
|
|
||||||
$: certificates_dropdown_open = false;
|
|
||||||
document.addEventListener("click", function (e) {
|
|
||||||
if (
|
|
||||||
e.target.parentNode?.parentNode?.id != "certificates:dropdown" &&
|
|
||||||
e.target.parentNode?.parentNode?.id != "certificates:dropdown:menu"
|
|
||||||
) {
|
|
||||||
certificates_dropdown_open = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function generateCertificates(locale) {
|
export let certificates_show = false;
|
||||||
certificates_dropdown_open = false;
|
export let generate_runners = [];
|
||||||
|
export let generate_orgs = [];
|
||||||
|
export let generate_teams = [];
|
||||||
|
$: certificates_dropdown_open = false;
|
||||||
|
document.addEventListener("click", function (e) {
|
||||||
|
if (
|
||||||
|
e.target.parentNode?.parentNode?.id != "certificates:dropdown" &&
|
||||||
|
e.target.parentNode?.parentNode?.id != "certificates:dropdown:menu"
|
||||||
|
) {
|
||||||
|
certificates_dropdown_open = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
if (generate_orgs.length > 0) {
|
function generateCertificates(locale) {
|
||||||
generateOrgCertificates(locale);
|
certificates_dropdown_open = false;
|
||||||
} else if (generate_teams.length > 0) {
|
|
||||||
generateTeamCertificates(locale);
|
if (generate_orgs.length > 0) {
|
||||||
|
generateOrgCertificates(locale);
|
||||||
|
} else if (generate_teams.length > 0) {
|
||||||
|
generateTeamCertificates(locale);
|
||||||
|
} else {
|
||||||
|
generateRunnerCertificates(locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateRunnerCertificates(locale) {
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("generating-pdf"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
const current_donations =
|
||||||
|
(await DonationService.donationControllerGetAll()) || [];
|
||||||
|
let certificateRunners = [];
|
||||||
|
for (let runner of generate_runners) {
|
||||||
|
runner.distanceDonations =
|
||||||
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
|
console.log(runner.distanceDonations);
|
||||||
|
certificateRunners.push(runner);
|
||||||
|
}
|
||||||
|
fetch(
|
||||||
|
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(certificateRunners),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
} else {
|
} else {
|
||||||
generateRunnerCertificates(locale);
|
return response.blob();
|
||||||
}
|
}
|
||||||
}
|
})
|
||||||
|
.then((blob) => {
|
||||||
async function generateRunnerCertificates(locale) {
|
const url = window.URL.createObjectURL(blob);
|
||||||
const toast = Toastify({
|
let a = document.createElement("a");
|
||||||
text: $_("generating-pdf"),
|
a.href = url;
|
||||||
duration: -1,
|
if (generate_runners.length == 1) {
|
||||||
|
a.download = `${$_("certificates")}_${
|
||||||
|
generate_runners[0].firstname
|
||||||
|
}_${generate_runners[0].lastname}-${locale}-${createId()}.pdf`;
|
||||||
|
} else {
|
||||||
|
a.download = `${$_("certificates")}-${locale}.pdf`;
|
||||||
|
}
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
const current_donations = (await DonationService.donationControllerGetAll()) || [];
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateTeamCertificates(locale) {
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("generating-pdfs"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
let count = 0;
|
||||||
|
const current_donations =
|
||||||
|
(await DonationService.donationControllerGetAll()) || [];
|
||||||
|
for (const t of generate_teams) {
|
||||||
|
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
|
t.id
|
||||||
|
);
|
||||||
|
let certificateRunners = [];
|
||||||
|
for (let runner of runners) {
|
||||||
|
runner.distanceDonations =
|
||||||
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
|
certificateRunners.push(runner);
|
||||||
|
}
|
||||||
|
fetch(
|
||||||
|
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(certificateRunners),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
count++;
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = `${$_("certificates")}_${t.name}-${locale}-${createId()}.pdf`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
if (count === generate_teams.length) {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdfs-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateOrgCertificates(locale) {
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("generating-pdfs"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
const current_donations =
|
||||||
|
(await DonationService.donationControllerGetAll()) || [];
|
||||||
|
let count = 0;
|
||||||
|
let count_orgs = 0;
|
||||||
|
for (const o of generate_orgs) {
|
||||||
|
count_orgs++;
|
||||||
|
let count = 0;
|
||||||
|
let runners =
|
||||||
|
await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
||||||
|
o.id,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
let certificateRunners = [];
|
||||||
|
for (let runner of runners) {
|
||||||
|
runner.distanceDonations =
|
||||||
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
|
certificateRunners.push(runner);
|
||||||
|
}
|
||||||
|
await fetch(
|
||||||
|
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(certificateRunners),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = `${$_("certificates")}_${o.name}-${locale}-${createId()}.pdf`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
||||||
|
toast.hideToast();
|
||||||
|
console.log("here");
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdfs-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
for (const t of o.teams) {
|
||||||
|
count++;
|
||||||
|
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
|
t.id
|
||||||
|
);
|
||||||
let certificateRunners = [];
|
let certificateRunners = [];
|
||||||
for (let runner of generate_runners) {
|
for (let runner of runners) {
|
||||||
runner.distanceDonations = current_donations.find((d) => d.runner?.id == runner.id) || [];
|
runner.distanceDonations =
|
||||||
certificateRunners.push(runner);
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
|
certificateRunners.push(runner);
|
||||||
}
|
}
|
||||||
fetch(
|
await fetch(
|
||||||
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
{
|
{
|
||||||
method: "POST",
|
method: "POST",
|
||||||
headers: {
|
headers: {
|
||||||
"Content-Type": "application/json",
|
"Content-Type": "application/json",
|
||||||
},
|
},
|
||||||
body: JSON.stringify(certificateRunners),
|
body: JSON.stringify(certificateRunners),
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status != "200") {
|
if (response.status != "200") {
|
||||||
toast.hideToast();
|
toast.hideToast();
|
||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdf-generation-failed"),
|
text: $_("pdf-generation-failed"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
} else {
|
} else {
|
||||||
return response.blob();
|
return response.blob();
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
if(generate_runners.length == 1){
|
|
||||||
a.download = `${$_('certificates')}_${generate_runners[0].firstname}_${generate_runners[0].lastname}-${locale}.pdf`;
|
|
||||||
}
|
|
||||||
else{
|
|
||||||
a.download = `${$_('certificates')}-${locale}.pdf`;
|
|
||||||
}
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateTeamCertificates(locale) {
|
|
||||||
const toast = Toastify({
|
|
||||||
text: $_("generating-pdfs"),
|
|
||||||
duration: -1,
|
|
||||||
}).showToast();
|
|
||||||
let count = 0;
|
|
||||||
const current_donations = (await DonationService.donationControllerGetAll()) || [];
|
|
||||||
for (const t of generate_teams) {
|
|
||||||
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
|
||||||
t.id
|
|
||||||
);
|
|
||||||
let certificateRunners = [];
|
|
||||||
for (let runner of runners) {
|
|
||||||
runner.distanceDonations = current_donations.find((d) => d.runner?.id == runner.id) || [];
|
|
||||||
certificateRunners.push(runner);
|
|
||||||
}
|
}
|
||||||
fetch(
|
})
|
||||||
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
.then((blob) => {
|
||||||
{
|
const url = window.URL.createObjectURL(blob);
|
||||||
method: "POST",
|
let a = document.createElement("a");
|
||||||
headers: {
|
a.href = url;
|
||||||
"Content-Type": "application/json",
|
a.download = `${$_("certificates")}_${o.name}_${
|
||||||
},
|
t.name
|
||||||
body: JSON.stringify(certificateRunners),
|
}-${locale}-${createId()}.pdf`;
|
||||||
}
|
document.body.appendChild(a);
|
||||||
)
|
a.click();
|
||||||
.then((response) => {
|
a.remove();
|
||||||
if (response.status != "200") {
|
if (
|
||||||
toast.hideToast();
|
count === o.teams.length &&
|
||||||
Toastify({
|
count_orgs === generate_orgs.length
|
||||||
text: $_("pdf-generation-failed"),
|
) {
|
||||||
duration: 3500,
|
toast.hideToast();
|
||||||
backgroundColor:
|
Toastify({
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
text: $_("pdfs-successfully-generated"),
|
||||||
}).showToast();
|
duration: 3500,
|
||||||
} else {
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
return response.blob();
|
}).showToast();
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
count++;
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('certificates')}_${t.name}-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === generate_teams.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateOrgCertificates(locale) {
|
|
||||||
const toast = Toastify({
|
|
||||||
text: $_("generating-pdfs"),
|
|
||||||
duration: -1,
|
|
||||||
}).showToast();
|
|
||||||
const current_donations = (await DonationService.donationControllerGetAll()) || [];
|
|
||||||
let count = 0;
|
|
||||||
let count_orgs =0;
|
|
||||||
for (const o of generate_orgs) {
|
|
||||||
count_orgs++;
|
|
||||||
let count = 0;
|
|
||||||
let runners = await RunnerOrganizationService.runnerOrganizationControllerGetRunners(o.id, true)
|
|
||||||
let certificateRunners = [];
|
|
||||||
for (let runner of runners) {
|
|
||||||
runner.distanceDonations = current_donations.find((d) => d.runner?.id == runner.id) || [];
|
|
||||||
certificateRunners.push(runner);
|
|
||||||
}
|
}
|
||||||
await fetch(
|
})
|
||||||
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
.catch((err) => {});
|
||||||
{
|
}
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(certificateRunners),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-generation-failed"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
|
||||||
}).showToast();
|
|
||||||
} else {
|
|
||||||
return response.blob();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('certificates')}_${o.name}_direct-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
console.log("here")
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
for (const t of o.teams) {
|
|
||||||
count++;
|
|
||||||
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
|
||||||
t.id
|
|
||||||
);
|
|
||||||
let certificateRunners = [];
|
|
||||||
for (let runner of runners) {
|
|
||||||
runner.distanceDonations = current_donations.find((d) => d.runner?.id == runner.id) || [];
|
|
||||||
certificateRunners.push(runner);
|
|
||||||
}
|
|
||||||
await fetch(
|
|
||||||
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(certificateRunners),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-generation-failed"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
|
||||||
}).showToast();
|
|
||||||
} else {
|
|
||||||
return response.blob();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('certificates')}_${o.name}_${t.name}-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if certificates_show}
|
{#if certificates_show}
|
||||||
<div id="certificates:dropdown" class="relative inline-block">
|
<div id="certificates:dropdown" class="relative inline-block">
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
certificates_dropdown_open = !certificates_dropdown_open;
|
certificates_dropdown_open = !certificates_dropdown_open;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm inline-flex"
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm inline-flex"
|
||||||
id="options-menu"
|
id="options-menu"
|
||||||
aria-haspopup="true"
|
aria-haspopup="true"
|
||||||
aria-expanded="true">
|
aria-expanded="true"
|
||||||
{$_('generate-runner-certificates')}
|
>
|
||||||
<svg
|
{$_("generate-runner-certificates")}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<svg
|
||||||
width="24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
height="24"
|
width="24"
|
||||||
viewBox="0 0 24 24"
|
height="24"
|
||||||
class="-mr-1 ml-2 h-5 w-5"><path
|
viewBox="0 0 24 24"
|
||||||
fill="none"
|
class="-mr-1 ml-2 h-5 w-5"
|
||||||
d="M0 0h24v24H0z" />
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
d="M3 19h18v2H3v-2zm10-5.83l6.07-6.07 1.42 1.41L12 17 3.52 8.52l1.4-1.42L11 13.17V2h2v11.17z" /></svg>
|
d="M3 19h18v2H3v-2zm10-5.83l6.07-6.07 1.42 1.41L12 17 3.52 8.52l1.4-1.42L11 13.17V2h2v11.17z"
|
||||||
</button>
|
/></svg
|
||||||
</div>
|
>
|
||||||
{#if certificates_dropdown_open}
|
</button>
|
||||||
<div
|
|
||||||
class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5"
|
|
||||||
id="certificates:dropdown:menu">
|
|
||||||
<div
|
|
||||||
class="py-1"
|
|
||||||
role="menu"
|
|
||||||
aria-orientation="vertical"
|
|
||||||
aria-labelledby="options-menu">
|
|
||||||
<span
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700">{$_('select-language')}</span>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
generateCertificates('de');
|
|
||||||
}}
|
|
||||||
type="submit"
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
|
||||||
role="menuitem">
|
|
||||||
{$_('german')}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
generateCertificates('en');
|
|
||||||
}}
|
|
||||||
type="submit"
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
|
||||||
role="menuitem">
|
|
||||||
{$_('english')}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
|
{#if certificates_dropdown_open}
|
||||||
|
<div
|
||||||
|
class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 z-10"
|
||||||
|
id="certificates:dropdown:menu"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="py-1"
|
||||||
|
role="menu"
|
||||||
|
aria-orientation="vertical"
|
||||||
|
aria-labelledby="options-menu"
|
||||||
|
>
|
||||||
|
<span class="block w-full text-left px-4 py-2 text-sm text-gray-700"
|
||||||
|
>{$_("select-language")}</span
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
generateCertificates("de");
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
||||||
|
role="menuitem"
|
||||||
|
>
|
||||||
|
{$_("german")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
generateCertificates("en");
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
||||||
|
role="menuitem"
|
||||||
|
>
|
||||||
|
{$_("english")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1,306 +1,324 @@
|
|||||||
<script>
|
<script>
|
||||||
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
||||||
import {
|
import {
|
||||||
RunnerOrganizationService,
|
RunnerOrganizationService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
import Toastify from "toastify-js";
|
import Toastify from "toastify-js";
|
||||||
export let sponsoring_contracts_show = false;
|
import { init } from "@paralleldrive/cuid2";
|
||||||
export let generate_runners = [];
|
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
|
||||||
export let generate_orgs = [];
|
|
||||||
export let generate_teams = [];
|
|
||||||
$: sponsoring_contracts_download_open = false;
|
|
||||||
document.addEventListener("click", function (e) {
|
|
||||||
if (
|
|
||||||
e.target.parentNode?.parentNode?.id != "sponsoring:dropdown" &&
|
|
||||||
e.target.parentNode?.parentNode?.id != "sponsoring:dropdown:menu"
|
|
||||||
) {
|
|
||||||
sponsoring_contracts_download_open = false;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
|
|
||||||
function generateSponsoringContract(locale) {
|
export let sponsoring_contracts_show = false;
|
||||||
sponsoring_contracts_download_open = false;
|
export let generate_runners = [];
|
||||||
|
export let generate_orgs = [];
|
||||||
if (generate_orgs.length > 0) {
|
export let generate_teams = [];
|
||||||
generateOrgContracts(locale);
|
$: sponsoring_contracts_download_open = false;
|
||||||
} else if (generate_teams.length > 0) {
|
document.addEventListener("click", function (e) {
|
||||||
generateTeamContracts(locale);
|
if (
|
||||||
} else {
|
e.target.parentNode?.parentNode?.id != "sponsoring:dropdown" &&
|
||||||
generateRunnerContracts(locale);
|
e.target.parentNode?.parentNode?.id != "sponsoring:dropdown:menu"
|
||||||
}
|
) {
|
||||||
|
sponsoring_contracts_download_open = false;
|
||||||
}
|
}
|
||||||
|
});
|
||||||
|
|
||||||
async function generateTeamContracts(locale) {
|
function generateSponsoringContract(locale) {
|
||||||
const toast = Toastify({
|
sponsoring_contracts_download_open = false;
|
||||||
text: $_("generating-pdfs"),
|
|
||||||
duration: -1,
|
if (generate_orgs.length > 0) {
|
||||||
}).showToast();
|
generateOrgContracts(locale);
|
||||||
let count = 0;
|
} else if (generate_teams.length > 0) {
|
||||||
for (const t of generate_teams) {
|
generateTeamContracts(locale);
|
||||||
count++;
|
} else {
|
||||||
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
generateRunnerContracts(locale);
|
||||||
t.id
|
|
||||||
);
|
|
||||||
fetch(
|
|
||||||
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(runners),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-generation-failed"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
|
||||||
}).showToast();
|
|
||||||
} else {
|
|
||||||
return response.blob();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('sponsorings')}_${t.name}-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === generate_teams.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function generateOrgContracts(locale) {
|
async function generateTeamContracts(locale) {
|
||||||
const toast = Toastify({
|
const toast = Toastify({
|
||||||
text: $_("generating-pdf"),
|
text: $_("generating-pdfs"),
|
||||||
duration: -1,
|
duration: -1,
|
||||||
}).showToast();
|
}).showToast();
|
||||||
let count_orgs =0;
|
let count = 0;
|
||||||
for (const o of generate_orgs) {
|
for (const t of generate_teams) {
|
||||||
count_orgs++;
|
count++;
|
||||||
let count = 0;
|
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
let runners = await RunnerOrganizationService.runnerOrganizationControllerGetRunners(o.id, true)
|
t.id
|
||||||
await fetch(
|
);
|
||||||
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
fetch(
|
||||||
{
|
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
method: "POST",
|
{
|
||||||
headers: {
|
method: "POST",
|
||||||
"Content-Type": "application/json",
|
headers: {
|
||||||
},
|
"Content-Type": "application/json",
|
||||||
body: JSON.stringify(runners),
|
},
|
||||||
}
|
body: JSON.stringify(runners),
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-generation-failed"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
|
||||||
}).showToast();
|
|
||||||
} else {
|
|
||||||
return response.blob();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('sponsorings')}_${o.name}_direct-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
console.log("here")
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
for (const t of o.teams) {
|
|
||||||
count++;
|
|
||||||
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
|
||||||
t.id
|
|
||||||
);
|
|
||||||
await fetch(
|
|
||||||
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(runners),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdf-generation-failed"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
|
||||||
}).showToast();
|
|
||||||
} else {
|
|
||||||
return response.blob();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_('sponsorings')}_${o.name}_${t.name}-${locale}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
|
||||||
toast.hideToast();
|
|
||||||
Toastify({
|
|
||||||
text: $_("pdfs-successfully-generated"),
|
|
||||||
duration: 3500,
|
|
||||||
backgroundColor:
|
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
|
||||||
}).showToast();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = `${$_("sponsorings")}_${t.name}-${locale}-${createId()}.pdf`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
if (count === generate_teams.length) {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdfs-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function generateRunnerContracts(locale) {
|
async function generateOrgContracts(locale) {
|
||||||
const toast = Toastify({
|
const toast = Toastify({
|
||||||
text: $_("generating-pdf"),
|
text: $_("generating-pdf"),
|
||||||
duration: -1,
|
duration: -1,
|
||||||
}).showToast();
|
}).showToast();
|
||||||
fetch(
|
let count_orgs = 0;
|
||||||
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
for (const o of generate_orgs) {
|
||||||
{
|
count_orgs++;
|
||||||
method: "POST",
|
let count = 0;
|
||||||
headers: {
|
let runners =
|
||||||
"Content-Type": "application/json",
|
await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
||||||
},
|
o.id,
|
||||||
body: JSON.stringify(generate_runners),
|
true
|
||||||
}
|
);
|
||||||
|
await fetch(
|
||||||
|
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(runners),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = `${$_("sponsorings")}_${o.name}_direct-${locale}-${createId()}.pdf`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
||||||
|
toast.hideToast();
|
||||||
|
console.log("here");
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdfs-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
for (const t of o.teams) {
|
||||||
|
count++;
|
||||||
|
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
|
t.id
|
||||||
|
);
|
||||||
|
await fetch(
|
||||||
|
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(runners),
|
||||||
|
}
|
||||||
)
|
)
|
||||||
.then((response) => {
|
.then((response) => {
|
||||||
if (response.status != "200") {
|
if (response.status != "200") {
|
||||||
toast.hideToast();
|
toast.hideToast();
|
||||||
Toastify({
|
Toastify({
|
||||||
text: $_("pdf-generation-failed"),
|
text: $_("pdf-generation-failed"),
|
||||||
duration: 3500,
|
duration: 3500,
|
||||||
backgroundColor:
|
backgroundColor:
|
||||||
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
}).showToast();
|
}).showToast();
|
||||||
} else {
|
} else {
|
||||||
return response.blob();
|
return response.blob();
|
||||||
}
|
}
|
||||||
})
|
})
|
||||||
.then((blob) => {
|
.then((blob) => {
|
||||||
const url = window.URL.createObjectURL(blob);
|
const url = window.URL.createObjectURL(blob);
|
||||||
let a = document.createElement("a");
|
let a = document.createElement("a");
|
||||||
a.href = url;
|
a.href = url;
|
||||||
if(generate_runners.length == 1){
|
a.download = `${$_("sponsorings")}_${o.name}_${
|
||||||
a.download = `${$_('sponsorings')}_${generate_runners[0].firstname}_${generate_runners[0].lastname}-${locale}.pdf`;
|
t.name
|
||||||
}
|
}-${locale}-${createId()}.pdf`;
|
||||||
a.download = `${$_('sponsorings')}-${locale}.pdf`;
|
document.body.appendChild(a);
|
||||||
document.body.appendChild(a);
|
a.click();
|
||||||
a.click();
|
a.remove();
|
||||||
a.remove();
|
if (
|
||||||
toast.hideToast();
|
count === o.teams.length &&
|
||||||
Toastify({
|
count_orgs === generate_orgs.length
|
||||||
text: $_("pdf-successfully-generated"),
|
) {
|
||||||
duration: 3500,
|
toast.hideToast();
|
||||||
backgroundColor:
|
Toastify({
|
||||||
"linear-gradient(to right, #00b09b, #96c93d)",
|
text: $_("pdfs-successfully-generated"),
|
||||||
}).showToast();
|
duration: 3500,
|
||||||
})
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
.catch((err) => {
|
}).showToast();
|
||||||
console.error(err);
|
}
|
||||||
});
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function generateRunnerContracts(locale) {
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("generating-pdf"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
fetch(
|
||||||
|
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(generate_runners),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
if (generate_runners.length == 1) {
|
||||||
|
a.download = `${$_("sponsorings")}_${generate_runners[0].firstname}_${
|
||||||
|
generate_runners[0].lastname
|
||||||
|
}-${locale}-${createId()}.pdf`;
|
||||||
|
}
|
||||||
|
a.download = `${$_("sponsorings")}-${locale}-${createId()}.pdf`;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
console.error(err);
|
||||||
|
});
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if sponsoring_contracts_show}
|
{#if sponsoring_contracts_show}
|
||||||
<div id="sponsoring:dropdown" class="relative inline-block">
|
<div id="sponsoring:dropdown" class="relative inline-block">
|
||||||
<div>
|
<div>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
sponsoring_contracts_download_open = !sponsoring_contracts_download_open;
|
sponsoring_contracts_download_open =
|
||||||
}}
|
!sponsoring_contracts_download_open;
|
||||||
type="button"
|
}}
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm inline-flex"
|
type="button"
|
||||||
id="options-menu"
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm inline-flex"
|
||||||
aria-haspopup="true"
|
id="options-menu"
|
||||||
aria-expanded="true">
|
aria-haspopup="true"
|
||||||
{$_('generate-sponsoring-contracts')}
|
aria-expanded="true"
|
||||||
<svg
|
>
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
{$_("generate-sponsoring-contracts")}
|
||||||
width="24"
|
<svg
|
||||||
height="24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
width="24"
|
||||||
class="-mr-1 ml-2 h-5 w-5"><path
|
height="24"
|
||||||
fill="none"
|
viewBox="0 0 24 24"
|
||||||
d="M0 0h24v24H0z" />
|
class="-mr-1 ml-2 h-5 w-5"
|
||||||
<path
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
fill="currentColor"
|
<path
|
||||||
d="M3 19h18v2H3v-2zm10-5.83l6.07-6.07 1.42 1.41L12 17 3.52 8.52l1.4-1.42L11 13.17V2h2v11.17z" /></svg>
|
fill="currentColor"
|
||||||
</button>
|
d="M3 19h18v2H3v-2zm10-5.83l6.07-6.07 1.42 1.41L12 17 3.52 8.52l1.4-1.42L11 13.17V2h2v11.17z"
|
||||||
</div>
|
/></svg
|
||||||
{#if sponsoring_contracts_download_open}
|
>
|
||||||
<div
|
</button>
|
||||||
class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5"
|
|
||||||
id="sponsoring:dropdown:menu">
|
|
||||||
<div
|
|
||||||
class="py-1"
|
|
||||||
role="menu"
|
|
||||||
aria-orientation="vertical"
|
|
||||||
aria-labelledby="options-menu">
|
|
||||||
<span
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700">{$_('select-language')}</span>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
generateSponsoringContract('de');
|
|
||||||
}}
|
|
||||||
type="submit"
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
|
||||||
role="menuitem">
|
|
||||||
{$_('german')}
|
|
||||||
</button>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
generateSponsoringContract('en');
|
|
||||||
}}
|
|
||||||
type="submit"
|
|
||||||
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
|
||||||
role="menuitem">
|
|
||||||
{$_('english')}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
</div>
|
||||||
|
{#if sponsoring_contracts_download_open}
|
||||||
|
<div
|
||||||
|
class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5 z-10"
|
||||||
|
id="sponsoring:dropdown:menu"
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="py-1"
|
||||||
|
role="menu"
|
||||||
|
aria-orientation="vertical"
|
||||||
|
aria-labelledby="options-menu"
|
||||||
|
>
|
||||||
|
<span class="block w-full text-left px-4 py-2 text-sm text-gray-700"
|
||||||
|
>{$_("select-language")}</span
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
generateSponsoringContract("de");
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
||||||
|
role="menuitem"
|
||||||
|
>
|
||||||
|
{$_("german")}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
generateSponsoringContract("en");
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
||||||
|
role="menuitem"
|
||||||
|
>
|
||||||
|
{$_("english")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -71,6 +71,9 @@
|
|||||||
}).showToast();
|
}).showToast();
|
||||||
let postdata = {};
|
let postdata = {};
|
||||||
postdata = Object.assign(postdata, editable);
|
postdata = Object.assign(postdata, editable);
|
||||||
|
if (postdata.phone === "") {
|
||||||
|
postdata.phone = null;
|
||||||
|
}
|
||||||
RunnerService.runnerControllerPut(original_data.id, postdata)
|
RunnerService.runnerControllerPut(original_data.id, postdata)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
Object.assign(original_data, editable);
|
Object.assign(original_data, editable);
|
||||||
@@ -95,7 +98,7 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#await runner_promise}
|
{#await runner_promise}
|
||||||
{$_('loading-runners')}
|
{$_("loading-runners")}
|
||||||
{:then}
|
{:then}
|
||||||
<section class="container p-5 select-none">
|
<section class="container p-5 select-none">
|
||||||
<div class="flex flex-row mb-4">
|
<div class="flex flex-row mb-4">
|
||||||
@@ -109,12 +112,15 @@
|
|||||||
class="flex-shrink-0 w-5 h-5 mr-2"
|
class="flex-shrink-0 w-5 h-5 mr-2"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
height="24"
|
||||||
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path
|
<path
|
||||||
d="M9.83 8.79L8 9.456V13H6V8.05h.015l5.268-1.918c.244-.093.51-.14.782-.131a2.616 2.616 0 0 1 2.427 1.82c.186.583.356.977.51 1.182A4.992 4.992 0 0 0 19 11v2a6.986 6.986 0 0 1-5.402-2.547l-.581 3.297L15 15.67V23h-2v-5.986l-2.05-1.987-.947 4.298-6.894-1.215.348-1.97 4.924.868L9.83 8.79zM13.5 5.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4z" /></svg>
|
d="M9.83 8.79L8 9.456V13H6V8.05h.015l5.268-1.918c.244-.093.51-.14.782-.131a2.616 2.616 0 0 1 2.427 1.82c.186.583.356.977.51 1.182A4.992 4.992 0 0 0 19 11v2a6.986 6.986 0 0 1-5.402-2.547l-.581 3.297L15 15.67V23h-2v-5.986l-2.05-1.987-.947 4.298-6.894-1.215.348-1.97 4.924.868L9.83 8.79zM13.5 5.5a2 2 0 1 1 0-4 2 2 0 0 1 0 4z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
</li>
|
</li>
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
<a class="mr-2" href="./">{$_('runners')}</a><svg
|
<a class="mr-2" href="./">{$_("runners")}</a><svg
|
||||||
stroke="currentColor"
|
stroke="currentColor"
|
||||||
fill="none"
|
fill="none"
|
||||||
stroke-width="2"
|
stroke-width="2"
|
||||||
@@ -124,17 +130,17 @@
|
|||||||
class="h-3 w-3 mr-2 stroke-current"
|
class="h-3 w-3 mr-2 stroke-current"
|
||||||
height="1em"
|
height="1em"
|
||||||
width="1em"
|
width="1em"
|
||||||
xmlns="http://www.w3.org/2000/svg"><line
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
x1="5"
|
><line x1="5" y1="12" x2="19" y2="12" />
|
||||||
y1="12"
|
<polyline points="12 5 19 12 12 19" /></svg
|
||||||
x2="19"
|
>
|
||||||
y2="12" />
|
|
||||||
<polyline points="12 5 19 12 12 19" /></svg>
|
|
||||||
</li>
|
</li>
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
<span class="mr-2">{original_data.firstname}
|
<span class="mr-2"
|
||||||
{original_data.middlename || ''}
|
>{original_data.firstname}
|
||||||
{original_data.lastname}</span>
|
{original_data.middlename || ""}
|
||||||
|
{original_data.lastname}</span
|
||||||
|
>
|
||||||
</li>
|
</li>
|
||||||
</ol>
|
</ol>
|
||||||
</nav>
|
</nav>
|
||||||
@@ -142,36 +148,42 @@
|
|||||||
</div>
|
</div>
|
||||||
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
||||||
{original_data.firstname}
|
{original_data.firstname}
|
||||||
{original_data.middlename || ''}
|
{original_data.middlename || ""}
|
||||||
{original_data.lastname}
|
{original_data.lastname}
|
||||||
<span data-id="runner_actions_${editable.id}">
|
<span data-id="runner_actions_${editable.id}">
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('RUNNER:DELETE')}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:DELETE")}
|
||||||
{#if delete_triggered}
|
{#if delete_triggered}
|
||||||
<button
|
<button
|
||||||
on:click={deleteRunner}
|
on:click={deleteRunner}
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('confirm-deletion')}</button>
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>{$_("confirm-deletion")}</button
|
||||||
|
>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
delete_triggered = !delete_triggered;
|
delete_triggered = !delete_triggered;
|
||||||
}}
|
}}
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm">{$_('cancel')}</button>
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm"
|
||||||
|
>{$_("cancel")}</button
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
<GenerateSponsoringContracts
|
<GenerateSponsoringContracts
|
||||||
bind:sponsoring_contracts_show
|
bind:sponsoring_contracts_show
|
||||||
bind:generate_runners />
|
bind:generate_runners
|
||||||
<GenerateRunnerCards
|
/>
|
||||||
bind:cards_show
|
<GenerateRunnerCards bind:cards_show bind:generate_runners />
|
||||||
bind:generate_runners />
|
|
||||||
<GenerateRunnerCertificates
|
<GenerateRunnerCertificates
|
||||||
bind:certificates_show
|
bind:certificates_show
|
||||||
bind:generate_runners />
|
bind:generate_runners
|
||||||
|
/>
|
||||||
{#if !delete_triggered}
|
{#if !delete_triggered}
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
delete_triggered = true;
|
delete_triggered = true;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('delete-runner')}</button>
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>{$_("delete-runner")}</button
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{/if}
|
||||||
{#if !delete_triggered}
|
{#if !delete_triggered}
|
||||||
@@ -180,121 +192,128 @@
|
|||||||
class:opacity-50={!save_enabled}
|
class:opacity-50={!save_enabled}
|
||||||
type="button"
|
type="button"
|
||||||
on:click={submit}
|
on:click={submit}
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('save-changes')}</button>
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
|
>{$_("save-changes")}</button
|
||||||
|
>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full">
|
||||||
<label
|
<label for="firstname" class="font-medium text-gray-700"
|
||||||
for="firstname"
|
>{$_("first-name")}</label
|
||||||
class="font-medium text-gray-700">{$_('first-name')}</label>
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('first-name')}
|
placeholder={$_("first-name")}
|
||||||
type="text"
|
type="text"
|
||||||
class:border-red-500={!isFirstnameValid}
|
class:border-red-500={!isFirstnameValid}
|
||||||
class:focus:border-red-500={!isFirstnameValid}
|
class:focus:border-red-500={!isFirstnameValid}
|
||||||
class:focus:ring-red-500={!isFirstnameValid}
|
class:focus:ring-red-500={!isFirstnameValid}
|
||||||
bind:value={editable.firstname}
|
bind:value={editable.firstname}
|
||||||
name="firstname"
|
name="firstname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
{#if !isFirstnameValid}
|
{#if !isFirstnameValid}
|
||||||
<span
|
<span
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{$_('first-name-is-required')}
|
>
|
||||||
|
{$_("first-name-is-required")}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full">
|
||||||
<label
|
<label for="middlename" class="font-medium text-gray-700"
|
||||||
for="middlename"
|
>{$_("middle-name")}</label
|
||||||
class="font-medium text-gray-700">{$_('middle-name')}</label>
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('middle-name')}
|
placeholder={$_("middle-name")}
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={editable.middlename}
|
bind:value={editable.middlename}
|
||||||
name="middlename"
|
name="middlename"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full">
|
||||||
<label
|
<label for="lastname" class="font-medium text-gray-700"
|
||||||
for="lastname"
|
>{$_("last-name")}</label
|
||||||
class="font-medium text-gray-700">{$_('last-name')}</label>
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('last-name')}
|
placeholder={$_("last-name")}
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={editable.lastname}
|
bind:value={editable.lastname}
|
||||||
class:border-red-500={!isLastnameValid}
|
class:border-red-500={!isLastnameValid}
|
||||||
class:focus:border-red-500={!isLastnameValid}
|
class:focus:border-red-500={!isLastnameValid}
|
||||||
class:focus:ring-red-500={!isLastnameValid}
|
class:focus:ring-red-500={!isLastnameValid}
|
||||||
name="lastname"
|
name="lastname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
{#if !isLastnameValid}
|
{#if !isLastnameValid}
|
||||||
<span
|
<span
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{$_('last-name-is-required')}
|
>
|
||||||
|
{$_("last-name-is-required")}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full">
|
||||||
<label
|
<label for="email" class="font-medium text-gray-700"
|
||||||
for="email"
|
>{$_("e-mail-adress")}</label
|
||||||
class="font-medium text-gray-700">{$_('e-mail-adress')}</label>
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('e-mail-adress')}
|
placeholder={$_("e-mail-adress")}
|
||||||
type="email"
|
type="email"
|
||||||
bind:value={editable.email}
|
bind:value={editable.email}
|
||||||
class:border-red-500={!isEmailValid}
|
class:border-red-500={!isEmailValid}
|
||||||
class:focus:border-red-500={!isEmailValid}
|
class:focus:border-red-500={!isEmailValid}
|
||||||
class:focus:ring-red-500={!isEmailValid}
|
class:focus:ring-red-500={!isEmailValid}
|
||||||
name="email"
|
name="email"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
{#if !isEmailValid}
|
{#if !isEmailValid}
|
||||||
<span
|
<span
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{$_('valid-email-is-required')}
|
>
|
||||||
|
{$_("valid-email-is-required")}
|
||||||
</span>
|
</span>
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full">
|
||||||
<label for="phone" class="font-medium text-gray-700">{$_('phone')}</label>
|
<label for="phone" class="font-medium text-gray-700">{$_("phone")}</label>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_('phone')}
|
placeholder={$_("phone")}
|
||||||
type="tel"
|
type="tel"
|
||||||
bind:value={editable.phone}
|
bind:value={editable.phone}
|
||||||
name="phone"
|
name="phone"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full">
|
||||||
<span class="font-medium text-gray-700">{$_('group')}</span>
|
<span class="font-medium text-gray-700">{$_("group")}</span>
|
||||||
<Select
|
<Select
|
||||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
||||||
itemFilter={(label, filterText, option) => label
|
itemFilter={(label, filterText, option) =>
|
||||||
.toLowerCase()
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
.includes(
|
option.id.value.toString().startsWith(filterText.toLowerCase())}
|
||||||
filterText.toLowerCase()
|
|
||||||
) || option.id.value
|
|
||||||
.toString()
|
|
||||||
.startsWith(filterText.toLowerCase())}
|
|
||||||
items={groups}
|
items={groups}
|
||||||
showChevron={true}
|
showChevron={true}
|
||||||
placeholder={$_('search-for-an-organization-or-team-by-name-or-id')}
|
placeholder={$_("search-for-an-organization-or-team-by-name-or-id")}
|
||||||
noOptionsMessage={$_('no-organization-or-team-found')}
|
noOptionsMessage={$_("no-organization-or-team-found")}
|
||||||
bind:selectedValue={group}
|
bind:selectedValue={group}
|
||||||
on:select={(selectedValue) => {
|
on:select={(selectedValue) => {
|
||||||
editable.group = selectedValue.detail.value.id;
|
editable.group = selectedValue.detail.value.id;
|
||||||
}}
|
}}
|
||||||
on:clear={() => (editable.group = null)} />
|
on:clear={() => (editable.group = null)}
|
||||||
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full">
|
||||||
<span class="font-medium text-gray-700">{$_('distance')}</span>
|
<span class="font-medium text-gray-700">{$_("distance")}</span>
|
||||||
<br />
|
<br />
|
||||||
<span class="text-gray-700">{original_data.distance} km</span>
|
<span class="text-gray-700">{original_data.distance / 1000} km</span>
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{:catch error}
|
{:catch error}
|
||||||
|
|||||||
@@ -1,37 +1,26 @@
|
|||||||
<script>
|
<script>
|
||||||
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import {
|
import {
|
||||||
RunnerService,
|
RunnerService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
RunnerOrganizationService,
|
RunnerOrganizationService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
|
import ThFilterGroup from "./ThFilterGroup.svelte";
|
||||||
|
import { DataHandler, Datatable, Th, ThFilter } from "@vincjo/datatables";
|
||||||
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";
|
||||||
$: searchvalue = "";
|
import { onMount } from "svelte";
|
||||||
$: active_deletes = [];
|
$: active_deletes = [];
|
||||||
export let current_runners = [];
|
let dataLoaded = false;
|
||||||
const runners_promise = RunnerService.runnerControllerGetAll().then((val) => {
|
let current_runners = [];
|
||||||
current_runners = val;
|
const handler = new DataHandler(current_runners, { rowsPerPage: 50 });
|
||||||
});
|
const rows = handler.getRows();
|
||||||
$: selectedFilter_teams = null;
|
$: sponsoring_contracts_show = generate_runners.length > 0;
|
||||||
$: selectedFilter = null;
|
$: cards_show = generate_runners.length > 0;
|
||||||
$: filter__teams = selectedFilter_teams || [];
|
$: certificates_show = generate_runners.length > 0;
|
||||||
$: filter__orgs = selectedFilter || [];
|
$: generate_runners = []; //current_runners.filter((r) => r.selected === true);
|
||||||
$: 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) {
|
||||||
@@ -42,222 +31,193 @@
|
|||||||
return { value: g.id, label: g.name };
|
return { value: g.id, label: g.name };
|
||||||
})
|
})
|
||||||
.concat(mappedteams);
|
.concat(mappedteams);
|
||||||
|
onMount(() => {
|
||||||
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
RunnerService.runnerControllerGetAll().then((val) => {
|
||||||
teams = val;
|
current_runners = val;
|
||||||
|
dataLoaded = true;
|
||||||
|
handler.setRows(val);
|
||||||
|
});
|
||||||
|
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
||||||
|
teams = val;
|
||||||
|
});
|
||||||
|
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
||||||
|
(val) => {
|
||||||
|
orgs = val;
|
||||||
|
}
|
||||||
|
);
|
||||||
});
|
});
|
||||||
RunnerOrganizationService.runnerOrganizationControllerGetAll().then((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}
|
{:else}
|
||||||
{#if current_runners.length === 0}
|
<div class="h-12">
|
||||||
<RunnersEmptyState />
|
<GenerateSponsoringContracts
|
||||||
{:else}
|
bind:sponsoring_contracts_show
|
||||||
<input
|
bind:generate_runners
|
||||||
type="search"
|
/>
|
||||||
bind:value={searchvalue}
|
<GenerateRunnerCards bind:cards_show bind:generate_runners />
|
||||||
placeholder={$_('datatable.search')}
|
<GenerateRunnerCertificates
|
||||||
aria-label={$_('datatable.search')}
|
bind:certificates_show
|
||||||
class="gridjs-input gridjs-search-input mb-4" />
|
bind:generate_runners
|
||||||
<div class="block mb-6">
|
/>
|
||||||
<label
|
</div>
|
||||||
for="country"
|
<Datatable {handler}>
|
||||||
class="text-sm font-medium text-gray-700">{$_('filter-by-organization-team')}</label>
|
<table>
|
||||||
<Select
|
<thead>
|
||||||
on:select={(event) => {
|
<tr>
|
||||||
selectedFilter = event.detail;
|
<th>
|
||||||
}}
|
<input
|
||||||
selectedValue={selectedFilter}
|
type="checkbox"
|
||||||
placeholder={$_('filter-by-organization-team')}
|
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
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"
|
checked={generate_runners.length == current_runners.length}
|
||||||
items={selectgroups}
|
on:click={() => {
|
||||||
isMulti={true} />
|
if (generate_runners.length != current_runners.length) {
|
||||||
</div>
|
generate_runners = current_runners;
|
||||||
<div class="h-12">
|
} else {
|
||||||
<GenerateSponsoringContracts
|
generate_runners = [];
|
||||||
bind:sponsoring_contracts_show
|
}
|
||||||
bind:generate_runners />
|
}}
|
||||||
<GenerateRunnerCards
|
/>
|
||||||
bind:cards_show
|
</th>
|
||||||
bind:generate_runners />
|
<Th {handler} orderBy="id">ID</Th>
|
||||||
<GenerateRunnerCertificates
|
<Th {handler} orderBy="firstname">First Name</Th>
|
||||||
bind:certificates_show
|
<Th {handler} orderBy="middlename">Middle Name</Th>
|
||||||
bind:generate_runners />
|
<Th {handler} orderBy="lastname">Last Name</Th>
|
||||||
</div>
|
<th>Gruppe</th>
|
||||||
<div
|
<Th {handler} orderBy="distance">Distanz</Th>
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
<th>{$_("action")}</th>
|
||||||
<table class="divide-y divide-gray-200 w-full">
|
</tr>
|
||||||
<thead class="bg-gray-50">
|
<tr>
|
||||||
|
<th />
|
||||||
|
<ThFilter {handler} filterBy="id" />
|
||||||
|
<ThFilter {handler} filterBy="firstname" />
|
||||||
|
<ThFilter {handler} filterBy="middlename" />
|
||||||
|
<ThFilter {handler} filterBy="lastname" />
|
||||||
|
<ThFilterGroup groups={selectgroups} {handler} />
|
||||||
|
<th />
|
||||||
|
<th />
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#each $rows as row}
|
||||||
<tr>
|
<tr>
|
||||||
<th
|
<td>
|
||||||
scope="col"
|
<input
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
type="checkbox"
|
||||||
<span
|
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
|
checked={generate_runners.filter((i)=>i.id == row.id).length > 0}
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
const newstate = !current_runners.some((r) => r.is_selected === true);
|
if (
|
||||||
current_runners = current_runners.map((r) => {
|
generate_runners.findIndex((i) => i.id == row.id) == -1
|
||||||
r.is_selected = newstate;
|
) {
|
||||||
return r;
|
generate_runners.push(row);
|
||||||
});
|
generate_runners = generate_runners;
|
||||||
|
} else {
|
||||||
|
generate_runners = generate_runners.filter(
|
||||||
|
(r) => r.id != row.id
|
||||||
|
);
|
||||||
|
}
|
||||||
|
console.log(generate_runners)
|
||||||
}}
|
}}
|
||||||
class="underline cursor-pointer select-none">{#if current_runners.some((r) => r.is_selected === true)}
|
/>
|
||||||
{$_('deselect-all')}
|
</td>
|
||||||
{:else}{$_('select-all')}{/if}
|
<td>{row.id}</td>
|
||||||
</span>
|
<td>{row.firstname}</td>
|
||||||
</th>
|
<td>{row.middlename || ""}</td>
|
||||||
<th
|
<td>{row.lastname}</td>
|
||||||
scope="col"
|
<td
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
>{#if row.group.responseType === "RUNNERTEAM"}
|
||||||
{$_('name')}
|
<a
|
||||||
</th>
|
href="../teams/{row.group.id}"
|
||||||
<th
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
||||||
scope="col"
|
>{row.group.parentGroup.name} > {row.group.name}</a
|
||||||
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"
|
|
||||||
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">
|
|
||||||
<div class="ml-4">
|
|
||||||
<div class="text-sm font-medium text-gray-900">
|
|
||||||
{runner.firstname}
|
|
||||||
{runner.middlename || ''}
|
|
||||||
{runner.lastname}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
{#if runner.email}
|
|
||||||
<div class="text-sm text-gray-500">{runner.email}</div>
|
|
||||||
{/if}
|
|
||||||
{#if runner.phone}
|
|
||||||
<div class="text-sm text-gray-500">{runner.phone}</div>
|
|
||||||
{/if}
|
|
||||||
{#if runner.address.address1 !== null}
|
|
||||||
{runner.address.address1}<br />
|
|
||||||
{runner.address.address2 || ''}<br />
|
|
||||||
{runner.address.postalcode}
|
|
||||||
{runner.address.city}
|
|
||||||
{runner.address.country}
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
{#if runner.group.responseType === 'RUNNERTEAM'}
|
|
||||||
<a
|
|
||||||
href="../teams/{runner.group.id}"
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{runner.group.parentGroup.name} > {runner.group.name}</a>
|
|
||||||
{/if}
|
|
||||||
{#if runner.group.responseType === 'RUNNERORGANIZATION'}
|
|
||||||
<a
|
|
||||||
href="../orgs/{runner.group.id}"
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800">{runner.group.name}</a>
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
{runner.distance}
|
|
||||||
</td>
|
|
||||||
{#if active_deletes[runner.id] === true}
|
|
||||||
<td
|
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[runner.id] = false;
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">{$_('cancel-delete')}</button>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
RunnerService.runnerControllerRemove(runner.id, true)
|
|
||||||
.then((resp) => {
|
|
||||||
current_runners = current_runners.filter((obj) => obj.id !== runner.id);
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('confirm-delete')}</button>
|
|
||||||
</td>
|
|
||||||
{:else}
|
|
||||||
<td
|
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
|
||||||
<a
|
|
||||||
href="./{runner.id}"
|
|
||||||
class="text-indigo-600 hover:text-indigo-900">{$_('details')}</a>
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes('RUNNER:DELETE')}
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[runner.id] = true;
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
|
|
||||||
{/if}
|
|
||||||
</td>
|
|
||||||
{/if}
|
|
||||||
</tr>
|
|
||||||
{/if}
|
{/if}
|
||||||
{/if}
|
{#if row.group.responseType === "RUNNERORGANIZATION"}
|
||||||
{/each}
|
<a
|
||||||
</tbody>
|
href="../orgs/{row.group.id}"
|
||||||
</table>
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
||||||
</div>
|
>{row.group.name}</a
|
||||||
{/if}
|
>
|
||||||
{:catch error}
|
{/if}</td
|
||||||
<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">
|
<td>{row.distance / 1000} km</td>
|
||||||
<b class="capitalize">{$_('general_promise_error')}</b>
|
<td>
|
||||||
{error}
|
{#if active_deletes[row.id] === true}
|
||||||
</span>
|
<button
|
||||||
</div>
|
on:click={() => {
|
||||||
{/await}
|
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={() => {
|
||||||
|
RunnerService.runnerControllerRemove(row.id, true)
|
||||||
|
.then((resp) => {
|
||||||
|
current_runners = current_runners.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}
|
||||||
|
<a
|
||||||
|
href="./{row.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[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>
|
||||||
|
</Datatable>
|
||||||
|
{/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>
|
||||||
|
<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>
|
||||||
@@ -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();
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -0,0 +1,151 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import { clickOutside } from "../base/outsideclick";
|
||||||
|
import { focusTrap } from "svelte-focus-trap";
|
||||||
|
import { StatsClientService } from "@odit/lfk-client-js";
|
||||||
|
import Toastify from "toastify-js";
|
||||||
|
export let modal_open;
|
||||||
|
export let new_client;
|
||||||
|
export let current_clients;
|
||||||
|
export let copy_modal_open;
|
||||||
|
function focus(el) {
|
||||||
|
el.focus();
|
||||||
|
}
|
||||||
|
$: description = "";
|
||||||
|
$: createbtnenabled = description != "";
|
||||||
|
$: processed_last_submit = true;
|
||||||
|
(() => {
|
||||||
|
document.onkeydown = (e) => {
|
||||||
|
e = e || window.event;
|
||||||
|
if (e.key === "Escape") {
|
||||||
|
modal_open = false;
|
||||||
|
}
|
||||||
|
if (e.keyCode === 13) {
|
||||||
|
if (createbtnenabled === true) {
|
||||||
|
createbtnenabled = false;
|
||||||
|
submit();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
})();
|
||||||
|
function submit() {
|
||||||
|
if (processed_last_submit === true) {
|
||||||
|
processed_last_submit = false;
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("statsclient-is-being-added"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
|
||||||
|
StatsClientService.statsClientControllerPost({description})
|
||||||
|
.then((result) => {
|
||||||
|
description = "";
|
||||||
|
modal_open = false;
|
||||||
|
//
|
||||||
|
Toastify({
|
||||||
|
text: $_("scanstation-added"),
|
||||||
|
duration: 500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
current_clients.push(result);
|
||||||
|
current_clients = current_clients;
|
||||||
|
new_client = result;
|
||||||
|
copy_modal_open = true;
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
//
|
||||||
|
})
|
||||||
|
.finally(() => {
|
||||||
|
processed_last_submit = true;
|
||||||
|
//
|
||||||
|
toast.hideToast();
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if modal_open}
|
||||||
|
<div
|
||||||
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
|
use:focusTrap
|
||||||
|
use:clickOutside
|
||||||
|
on:click_outside={() => {
|
||||||
|
modal_open = false;
|
||||||
|
}}>
|
||||||
|
<div
|
||||||
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
||||||
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
|
data-id="modal_backdrop" />
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
|
aria-hidden="true">​</span>
|
||||||
|
<div
|
||||||
|
class="inline-block align-bottom bg-white rounded-lg text-left shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby="modal-headline">
|
||||||
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
|
<div class="sm:flex sm:items-start">
|
||||||
|
<div
|
||||||
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
|
||||||
|
<svg
|
||||||
|
class="h-6 w-6 text-blue-600"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z" /></svg>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
{$_('create-a-new-statsclient')}
|
||||||
|
</h3>
|
||||||
|
<div class="mt-2 mb-6">
|
||||||
|
<p class="text-sm text-gray-500">
|
||||||
|
{$_('please-provide-the-required-information-to-create-a-new-statsclient')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="grid grid-cols-6 gap-6">
|
||||||
|
<div class="col-span-6">
|
||||||
|
<label
|
||||||
|
for="description"
|
||||||
|
class="block text-sm font-medium text-gray-700">{$_('description')}</label>
|
||||||
|
<input
|
||||||
|
use:focus
|
||||||
|
autocomplete="off"
|
||||||
|
placeholder={$_('description')}
|
||||||
|
bind:value={description}
|
||||||
|
type="text"
|
||||||
|
name="description"
|
||||||
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" />
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||||
|
<button
|
||||||
|
disabled={!createbtnenabled}
|
||||||
|
class:opacity-50={!createbtnenabled}
|
||||||
|
on:click={submit}
|
||||||
|
type="button"
|
||||||
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
||||||
|
{$_('create')}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
modal_open = false;
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
|
||||||
|
{$_('cancel')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,92 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import { clickOutside } from "../base/outsideclick";
|
||||||
|
import { focusTrap } from "svelte-focus-trap";
|
||||||
|
import { ScanStationService } from "@odit/lfk-client-js";
|
||||||
|
import Toastify from "toastify-js";
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
|
export let modal_open;
|
||||||
|
export let delete_station;
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
function cancelDelete() {
|
||||||
|
modal_open = false;
|
||||||
|
dispatch("cancelDelete", { id: delete_station.id });
|
||||||
|
}
|
||||||
|
function deleteClient() {
|
||||||
|
ScanStationService.donorControllerRemove(
|
||||||
|
delete_station.id,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
.then((resp) => {
|
||||||
|
Toastify({
|
||||||
|
text: $_('statsclient-deleted'),
|
||||||
|
duration: 500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
location.replace("./");
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if modal_open}
|
||||||
|
<div
|
||||||
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
|
use:focusTrap
|
||||||
|
use:clickOutside
|
||||||
|
on:click_outside={cancelDelete}>
|
||||||
|
<div
|
||||||
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
||||||
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
|
data-id="modal_backdrop" />
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
|
aria-hidden="true">​</span>
|
||||||
|
<div
|
||||||
|
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby="modal-headline">
|
||||||
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
|
<div class="sm:flex sm:items-start">
|
||||||
|
<div
|
||||||
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
|
||||||
|
<svg class="h-6 w-6 text-blue-600" fill="currentColor" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z"/><path d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z"/></svg>
|
||||||
|
</div>
|
||||||
|
<!-- <div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
{$_('attention')}
|
||||||
|
</h3>
|
||||||
|
<div class="mt-2 mb-6">
|
||||||
|
<p class="text-sm text-gray-500">
|
||||||
|
{$_(
|
||||||
|
'do-you-want-to-delete-this-donor-with-all-related-donations'
|
||||||
|
)}
|
||||||
|
<br />
|
||||||
|
{$_('all-associated-scans-will-get-deleted-as-well')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div> -->
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||||
|
<button
|
||||||
|
on:click={deleteClient}
|
||||||
|
type="button"
|
||||||
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">
|
||||||
|
{$_('confirm-delete-statsclient')}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={cancelDelete}
|
||||||
|
type="button"
|
||||||
|
class="mt-3 w-full inline-flex justify-center rounded-md border border-gray-300 shadow-sm px-4 py-2 bg-white text-base font-medium text-gray-700 hover:bg-gray-50 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-indigo-500 sm:mt-0 sm:ml-3 sm:w-auto sm:text-sm">
|
||||||
|
{$_('cancel-keep-statsclient')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,129 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import { focusTrap } from "svelte-focus-trap";
|
||||||
|
import Toastify from "toastify-js";
|
||||||
|
import { tick, createEventDispatcher } from "svelte";
|
||||||
|
export let copy_modal_open;
|
||||||
|
export let new_client;
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
let valueCopy = null;
|
||||||
|
let areaDom;
|
||||||
|
let copied = false;
|
||||||
|
function close() {
|
||||||
|
copy_modal_open = false;
|
||||||
|
}
|
||||||
|
async function copy() {
|
||||||
|
valueCopy = new_client.key;
|
||||||
|
await tick();
|
||||||
|
areaDom.focus();
|
||||||
|
areaDom.select();
|
||||||
|
try {
|
||||||
|
const successful = document.execCommand("copy");
|
||||||
|
if (!successful) {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
Toastify({
|
||||||
|
text: $_("copied-token-to-clipboard"),
|
||||||
|
duration: 500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
copied = true;
|
||||||
|
} catch (err) {
|
||||||
|
Toastify({
|
||||||
|
text: $_("error-whyile-copying-to-clipboard"),
|
||||||
|
duration: 500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
|
|
||||||
|
// we can notifi by event or storage about copy status
|
||||||
|
valueCopy = null;
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if copy_modal_open}
|
||||||
|
{#if valueCopy != null}
|
||||||
|
<textarea bind:this={areaDom}>{valueCopy}</textarea>
|
||||||
|
{/if}
|
||||||
|
<div class="fixed z-10 inset-0 overflow-y-auto" use:focusTrap>
|
||||||
|
<div
|
||||||
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0">
|
||||||
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
|
data-id="modal_backdrop" />
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
|
aria-hidden="true">​</span>
|
||||||
|
<div
|
||||||
|
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby="modal-headline">
|
||||||
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
|
<div class="sm:flex sm:items-start">
|
||||||
|
<div
|
||||||
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10">
|
||||||
|
<svg
|
||||||
|
class="h-6 w-6 text-blue-600"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z" /></svg>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
{$_('token')}
|
||||||
|
</h3>
|
||||||
|
<div class="mt-2 mb-6">
|
||||||
|
<p class="text-sm text-gray-500">
|
||||||
|
{$_('the-statsclient-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again')}
|
||||||
|
<br />
|
||||||
|
{$_('please-copy-the-token-and-store-it-somewhere-save')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
<div class="mt-2 mb-6">
|
||||||
|
<label
|
||||||
|
for="token"
|
||||||
|
class="block text-sm font-medium text-gray-700">{$_('token')}</label>
|
||||||
|
<div on:click={copy} class="inline-flex">
|
||||||
|
<p
|
||||||
|
name="token"
|
||||||
|
class:bg-green-200={copied}
|
||||||
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2">
|
||||||
|
{new_client.key}
|
||||||
|
</p>
|
||||||
|
<div
|
||||||
|
class="bg-gray-200 border-gray-300 border-t border-b border-r text-black rounded-r-md sm:text-sm p-2 mt-1 cursor-pointer">
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M7 4V2h10v2h3l1 1v16a1 1 0 01-1 1H4a1 1 0 01-1-1V5l1-1h3zm0 2H5v14h14V6h-2v2H7V6zm2-2v2h6V4H9z" /></svg>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<p class="text-gray-500 text-xs">
|
||||||
|
{$_('click-to-copy-token-to-clipboard')}
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||||
|
<button
|
||||||
|
on:click={close}
|
||||||
|
type="button"
|
||||||
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-green-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">
|
||||||
|
{$_('yes-i-copied-the-token')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,119 @@
|
|||||||
|
<script>
|
||||||
|
import { t, _ } from "svelte-i18n";
|
||||||
|
import store from "../../store";
|
||||||
|
import Toastify from "toastify-js";
|
||||||
|
import PromiseError from "../base/PromiseError.svelte";
|
||||||
|
import ConfirmStatsClientDeletion from "./ConfirmStatsClientDeletion.svelte";
|
||||||
|
import { StatsClientService } from "@odit/lfk-client-js";
|
||||||
|
let data_loaded = false;
|
||||||
|
let modal_open;
|
||||||
|
let delete_client;
|
||||||
|
export let params;
|
||||||
|
$: delete_triggered = false;
|
||||||
|
$: original_data = {};
|
||||||
|
const promise = StatsClientService.statsClientControllerGetOne(
|
||||||
|
params.clientid
|
||||||
|
).then((data) => {
|
||||||
|
data_loaded = true;
|
||||||
|
original_data = Object.assign(original_data, data);
|
||||||
|
});
|
||||||
|
function deleteClient() {
|
||||||
|
StatsClientService.statsClientControllerRemove(original_data.id, false)
|
||||||
|
.then((resp) => {
|
||||||
|
Toastify({
|
||||||
|
text: $_("statsclient-deleted"),
|
||||||
|
duration: 500,
|
||||||
|
backgroundColor: "linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
location.replace("./");
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
modal_open = true;
|
||||||
|
delete_client = original_data;
|
||||||
|
});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ConfirmStatsClientDeletion bind:modal_open bind:delete_client />
|
||||||
|
{#await promise}
|
||||||
|
{$_('loading-statsclient-details')}
|
||||||
|
{:then}
|
||||||
|
<section class="container p-5 select-none">
|
||||||
|
<div class="flex flex-row mb-4">
|
||||||
|
<div class="w-full">
|
||||||
|
<nav class="w-full flex">
|
||||||
|
<ol class="list-none flex flex-row items-center justify-start">
|
||||||
|
<li class="flex items-center">
|
||||||
|
<svg
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
width="24"
|
||||||
|
height="24"><path fill="none" d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z" /></svg>
|
||||||
|
</li>
|
||||||
|
<li class="flex items-center ml-2">
|
||||||
|
<a class="mr-2" href="./">{$_('statsclient')}</a><svg
|
||||||
|
stroke="currentColor"
|
||||||
|
fill="none"
|
||||||
|
stroke-width="2"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
stroke-linecap="round"
|
||||||
|
stroke-linejoin="round"
|
||||||
|
class="h-3 w-3 mr-2 stroke-current"
|
||||||
|
height="1em"
|
||||||
|
width="1em"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"><line
|
||||||
|
x1="5"
|
||||||
|
y1="12"
|
||||||
|
x2="19"
|
||||||
|
y2="12" />
|
||||||
|
<polyline points="12 5 19 12 12 19" /></svg>
|
||||||
|
</li>
|
||||||
|
<li class="flex items-center">
|
||||||
|
<span class="mr-2">#{original_data.id}</span>
|
||||||
|
</li>
|
||||||
|
</ol>
|
||||||
|
</nav>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
||||||
|
#{original_data.id}
|
||||||
|
<span data-id="stations_actions_${original_data.id}">
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes('STATSCLIENT:DELETE')}
|
||||||
|
{#if delete_triggered}
|
||||||
|
<button
|
||||||
|
on:click={deleteClient}
|
||||||
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('confirm-deletion')}</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
delete_triggered = !delete_triggered;
|
||||||
|
}}
|
||||||
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-400 text-base font-medium text-white sm:w-auto sm:text-sm">{$_('cancel')}</button>
|
||||||
|
{/if}
|
||||||
|
{#if !delete_triggered}
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
delete_triggered = true;
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-600 text-base font-medium text-white hover:bg-red-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm">{$_('delete-statsclient')}</button>
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
<!-- -->
|
||||||
|
<div class="text-sm w-full">
|
||||||
|
<label
|
||||||
|
for="description"
|
||||||
|
class="font-medium text-gray-700">{$_('description')}</label>
|
||||||
|
<p
|
||||||
|
name="description"
|
||||||
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" >
|
||||||
|
{original_data.description}</p>
|
||||||
|
</div>
|
||||||
|
</section>
|
||||||
|
{:catch error}
|
||||||
|
<PromiseError {error} />
|
||||||
|
{/await}
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import store from "../../store";
|
||||||
|
import AddStatsClientModal from "./AddStatsClientModal.svelte";
|
||||||
|
import CopyStatsClientTokenModal from "./CopyStatsClientTokenModal.svelte";
|
||||||
|
import StatsClientsOverview from "./StatsClientsOverview.svelte";
|
||||||
|
export let modal_open = false;
|
||||||
|
export let copy_modal_open = false;
|
||||||
|
export let new_client = {};
|
||||||
|
let current_clients = [];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<section class="container p-5">
|
||||||
|
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
|
{$_('statsclients')}
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes('STATSCLIENT:CREATE')}
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
modal_open = true;
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm">
|
||||||
|
{$_('create-a-new-statsclient')}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
</span>
|
||||||
|
<StatsClientsOverview bind:current_clients bind:modal_open bind:new_client bind:copy_modal_open />
|
||||||
|
</section>
|
||||||
|
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes('STATSCLIENT:CREATE')}
|
||||||
|
<AddStatsClientModal bind:modal_open bind:current_clients bind:new_client bind:copy_modal_open/>
|
||||||
|
<CopyStatsClientTokenModal bind:copy_modal_open bind:new_client />
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1,21 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import AddStatsClientModal from "./AddStatsClientModal.svelte";
|
||||||
|
import CopyScanStationTokenModal from "./CopyStatsClientTokenModal.svelte";
|
||||||
|
import scanstations_empty from "./statsclients_empty.svg";
|
||||||
|
let modal_open = false;
|
||||||
|
let copy_modal_open = false;
|
||||||
|
let new_client = {};
|
||||||
|
let current_clients = [];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<div class="text-center items-center justify-center">
|
||||||
|
<p class="mb-16 text-lg text-gray-500">
|
||||||
|
<img class="w-full h-44" src={scanstations_empty} alt="" />
|
||||||
|
<span class="font-bold">{$_('you-dont-have-any-scanclients-yet')}.</span><br />
|
||||||
|
<span>{$_('add-the-first-statsclient')}</span>
|
||||||
|
</p>
|
||||||
|
</div>
|
||||||
|
|
||||||
|
<AddStatsClientModal bind:modal_open bind:current_clients bind:new_client bind:copy_modal_open/>
|
||||||
|
<CopyScanStationTokenModal bind:copy_modal_open bind:new_client />
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import Toastify from "toastify-js";
|
||||||
|
import { StatsClientService } from "@odit/lfk-client-js";
|
||||||
|
const promise = StatsClientService.statsClientControllerGetAll().then(
|
||||||
|
(result) => {
|
||||||
|
current_clients = result;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
import store from "../../store";
|
||||||
|
import StatsClientsEmptyState from "./StatsClientsEmptyState.svelte";
|
||||||
|
import ConfirmStatsClientDeletion from "./ConfirmStatsClientDeletion.svelte";
|
||||||
|
$: searchvalue = "";
|
||||||
|
$: active_deletes = [];
|
||||||
|
let delete_client = {};
|
||||||
|
let modal_open = false;
|
||||||
|
export let current_clients = [];
|
||||||
|
</script>
|
||||||
|
|
||||||
|
<ConfirmStatsClientDeletion
|
||||||
|
on:cancelDelete={(event) => {
|
||||||
|
modal_open = false;
|
||||||
|
active_deletes[event.detail.id] = false;
|
||||||
|
}}
|
||||||
|
bind:modal_open
|
||||||
|
bind:delete_client />
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes('STATSCLIENT:GET')}
|
||||||
|
{#await promise}
|
||||||
|
<div
|
||||||
|
class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
|
||||||
|
role="alert">
|
||||||
|
<p class="font-bold">{$_('statsclients-are-being-loaded')}</p>
|
||||||
|
<p class="text-sm">{$_('this-might-take-a-moment')}</p>
|
||||||
|
</div>
|
||||||
|
{:then}
|
||||||
|
{#if current_clients.length === 0}
|
||||||
|
<StatsClientsEmptyState />
|
||||||
|
{:else}
|
||||||
|
<input
|
||||||
|
type="search"
|
||||||
|
bind:value={searchvalue}
|
||||||
|
placeholder={$_('datatable.search')}
|
||||||
|
aria-label={$_('datatable.search')}
|
||||||
|
class="gridjs-input gridjs-search-input mb-4" />
|
||||||
|
<div
|
||||||
|
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
||||||
|
<table class="divide-y divide-gray-200 w-full">
|
||||||
|
<thead class="bg-gray-50">
|
||||||
|
<tr>
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||||
|
{$_('description')}
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider">
|
||||||
|
{$_('prefix')}
|
||||||
|
</th>
|
||||||
|
<th scope="col" class="relative px-6 py-3">
|
||||||
|
<span class="sr-only">{$_('action')}</span>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="divide-y divide-gray-200">
|
||||||
|
{#each current_clients as c}
|
||||||
|
{#if Object.values(c)
|
||||||
|
.toString()
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(searchvalue)}
|
||||||
|
<tr data-rowid="station_{c.id}">
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="ml-4">
|
||||||
|
<div class="text-sm font-medium text-gray-900">
|
||||||
|
{c.description}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="ml-4">
|
||||||
|
<div class="text-sm font-medium text-gray-900">
|
||||||
|
{c.prefix}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
{#if active_deletes[c.id] === true}
|
||||||
|
<td
|
||||||
|
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
active_deletes[c.id] = false;
|
||||||
|
}}
|
||||||
|
tabindex="0"
|
||||||
|
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer">{$_('cancel-delete')}</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
StatsClientService.statsClientControllerRemove(c.id, false)
|
||||||
|
.then((resp) => {
|
||||||
|
current_clients = current_clients.filter((obj) => obj.id !== c.id);
|
||||||
|
Toastify({
|
||||||
|
text: $_('statsclient-deleted'),
|
||||||
|
duration: 500,
|
||||||
|
backgroundColor:
|
||||||
|
'linear-gradient(to right, #00b09b, #96c93d)',
|
||||||
|
}).showToast();
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
modal_open = true;
|
||||||
|
delete_client = c;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
tabindex="0"
|
||||||
|
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('confirm-delete')}</button>
|
||||||
|
</td>
|
||||||
|
{:else}
|
||||||
|
<td
|
||||||
|
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium">
|
||||||
|
<a
|
||||||
|
href="/statsclients/{c.id}"
|
||||||
|
class="text-indigo-600 hover:text-indigo-900">{$_('details')}</a>
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes('STATSCLIENT:DELETE')}
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
active_deletes[c.id] = true;
|
||||||
|
}}
|
||||||
|
tabindex="0"
|
||||||
|
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer">{$_('delete')}</button>
|
||||||
|
{/if}
|
||||||
|
</td>
|
||||||
|
{/if}
|
||||||
|
</tr>
|
||||||
|
{/if}
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
{:catch error}
|
||||||
|
<div class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500">
|
||||||
|
<span class="inline-block align-middle mr-8">
|
||||||
|
<b class="capitalize">{$_('general_promise_error')}</b>
|
||||||
|
{error}
|
||||||
|
</span>
|
||||||
|
</div>
|
||||||
|
{/await}
|
||||||
|
{/if}
|
||||||
@@ -0,0 +1 @@
|
|||||||
|
<svg data-name="Layer 1" xmlns="http://www.w3.org/2000/svg" viewBox="0 0 920.11 411.95" width="920.11" height="411.95"><path d="M436.53 410h195.59c7.72 0 7.73-12 0-12h-195.6c-7.71 0-7.73 12 0 12z" fill="#e6e6e6"/><path d="M383.72 149.23H188.79a7.78 7.78 0 00-7.77 7.77v38.72c9.72.23 16.03 8.26 17.56 18v35.1h.74a.44.44 0 01.45.45v18.68a.44.44 0 01-.45.44h-.74v112.9l-.02 7.02h185.16a7.78 7.78 0 007.77-7.77V157a7.78 7.78 0 00-7.77-7.77z" fill="#6c63ff"/><path d="M745.9 21.81v211.9H404.97v-93.3a16 16 0 00-15.98-15.97h-63.94V21.8z" fill="#6c63ff"/><path d="M766.95 263.58h-361.6v-1.47h360.12V12.55A11.09 11.09 0 00754.4 1.48H312.14a11.09 11.09 0 00-11.08 11.07v110.93h-1.47V12.55A12.57 12.57 0 01312.14 0H754.4a12.57 12.57 0 0112.55 12.55z" fill="#3f3d56"/><path d="M732.69 308.62H405.35v-1.48h327.34a32.82 32.82 0 0032.78-32.78v-10.78H405.35v-1.47h361.6v12.25a34.3 34.3 0 01-34.26 34.26z" fill="#3f3d56"/><path d="M635.54 380.98c-18.25-17.52-30.25-40.39-34.11-72.36h-134.5c-1.36 29.91-13.29 52.35-34.8 72.28l-2.28.08c22.2-20.12 34.43-42.72 35.64-73.13l.03-.7h137.22l.08.65c3.79 32.51 16.04 55.52 34.74 73.06zM388.63 411.52H181.46v-1.47h207.17a16 16 0 0015.98-15.98V140.75a16 16 0 00-15.98-15.97H181.46a16 16 0 00-15.98 15.97v54.67h-1.47v-54.67a17.47 17.47 0 0117.45-17.45h207.17a17.47 17.47 0 0117.46 17.45v253.32a17.47 17.47 0 01-17.46 17.45z" fill="#3f3d56"/><path d="M285.05 141.98a5 5 0 115-5 5.01 5.01 0 01-5 5zm0-8.85a3.85 3.85 0 103.85 3.85 3.85 3.85 0 00-3.85-3.85zM285.05 405.86a6.39 6.39 0 116.39-6.38 6.4 6.4 0 01-6.4 6.38zm0-11.3a4.91 4.91 0 104.91 4.92 4.92 4.92 0 00-4.91-4.92zM179.38 411.95H110.8a19.5 19.5 0 01-19.47-19.47V214.89a19.5 19.5 0 0119.47-19.47h68.58a19.5 19.5 0 0119.47 19.47v31.78a1.92 1.92 0 011.19 1.78v20.67a1.92 1.92 0 01-1.19 1.78v121.58a19.5 19.5 0 01-19.47 19.47zM110.8 196.9a18.02 18.02 0 00-18 18v177.58a18.02 18.02 0 0018 18h68.58a18.02 18.02 0 0018-18V269.57h.74a.44.44 0 00.44-.45v-20.67a.44.44 0 00-.44-.45h-.74v-33.1a18.02 18.02 0 00-18-18z" fill="#3f3d56"/><path d="M180.14 201.03h-8.96a6.65 6.65 0 01-6.15 9.16h-39.29a6.65 6.65 0 01-6.15-9.16h-8.36a14 14 0 00-14 14v177.32a14 14 0 0014 13.99h68.9a14 14 0 0014-14V215.04a14 14 0 00-14-14z" fill="#6c63ff"/><path d="M919.23 411.66H.88a.88.88 0 110-1.76h918.35a.88.88 0 110 1.76z" fill="#3f3d56"/><path d="M636 411.25H431.48a15.5 15.5 0 110-31.01H636a15.5 15.5 0 010 31zm-204.52-29.53a14.03 14.03 0 000 28.05H636a14.03 14.03 0 000-28.05z" fill="#3f3d56"/><path fill="#ffb8b8" d="M784.5 293.2l5.72 11.97 48.92-16.4-8.45-17.67-46.2 22.1z"/><path d="M790.15 333.59l-18-37.64 14.54-6.96 11.58 24.21a14.89 14.89 0 01-7 19.85l-1.12.54z" fill="#2f2e41"/><path fill="#ffb8b8" d="M772.96 400.14l13.27-.45.56-51.64-15.55.92 1.72 51.17z"/><path d="M811.97 411.86h-41.72v-16.12h26.84a14.89 14.89 0 0114.88 14.88v1.24zM774.06 392.38a4.97 4.97 0 01-4.84-3.78c-7.26-29.2-34.3-176.34-10.4-205.23l.22-.26.31-.08c1.68-.42 33.33-10.22 51.9 5.08l.21.17 10.34 29.92 27.86 41.35a20.4 20.4 0 01-6.04 28.66l-36.58 23.08a5 5 0 01-5.75-.4 5.06 5.06 0 01-1.5-2.1l-7.69-19.21a5.03 5.03 0 012.4-6.33l17.15-8.57a3.67 3.67 0 001.83-2.5 2.96 2.96 0 00-1.03-2.55l-19.9-17.15a3 3 0 00-4.95 2.38l4.93 130.2a5 5 0 01-4.22 5.13l-13.46 2.13a5.05 5.05 0 01-.8.06z" fill="#2f2e41"/><path d="M808.38 193.41l-.34-.01-49.62-3.68a4.5 4.5 0 01-3.91-5.97 47.1 47.1 0 001.07-27.31c-3.23-12.75-3.3-36.44-3.06-49.42a8.75 8.75 0 018.28-8.53v-.01h1c8.08.12 22.91.7 35.05 3.22a18.39 18.39 0 0114.66 17.7c.28 12.06.32 28.38-1.05 37.66-1.16 7.83.98 22.86 2.35 31.12a4.5 4.5 0 01-4.43 5.23z" fill="#3f3d56"/><path d="M826.09 240.71a10.02 10.02 0 01-3.81-14.9L799.36 127h17.33l20.22 96.87a10.08 10.08 0 01-10.82 16.84zM717.56 137.7l27.43-25.95 10.34 14.47-25.84 22.74 33.89 26.91c.24-.01.49-.04.74-.04a10.85 10.85 0 11-10.75 12.3l-.1.1-35.28-30.56a13.47 13.47 0 01-.43-19.97z" fill="#ffb8b8"/><path d="M801.19 133.33a4.47 4.47 0 01-4.05-2.55 52.81 52.81 0 01-4.47-14.57c-1.2-8.25 4.54-13.15 10.37-14.22 5.67-1.04 12.58 1.45 14.34 9.38a20.45 20.45 0 01.35 2.04c.7 6 1.37 10.68 1.97 13.9a4.5 4.5 0 01-4.2 5.31l-14.08.7-.23.01z" fill="#3f3d56"/><circle cx="781.54" cy="59.98" r="30" fill="#2f2e41"/><circle cx="781.73" cy="67.77" r="24.56" fill="#ffb8b8"/><path d="M738.13 121.38a4.47 4.47 0 01-1.26-4.62 52.81 52.81 0 016.55-13.76c4.7-6.88 12.23-6.63 17.25-3.48 4.89 3.07 8.3 9.57 4.24 16.61a20.45 20.45 0 01-1.12 1.73c-3.54 4.91-6.21 8.8-7.93 11.58a4.5 4.5 0 01-6.7 1.09l-10.85-9q-.1-.07-.18-.15z" fill="#3f3d56"/><path d="M775.72 33.19c-6.04-3.6-7.35-12.57-3.75-18.61s10.86-9.2 17.9-9.4c10.03-.3 19.72 4.7 26.75 11.87s11.66 16.36 15.2 25.76 6.06 19.15 9.54 28.57c1.79 4.83 3.99 9.8 8.07 12.93s10.59 3.7 14.08-.08c-.01 6.06-4.66 11.57-10.42 13.45s-12.29.46-17.34-2.9c-8.76-5.8-13-16.4-15.41-26.64s-3.61-20.95-8.48-30.27c-2.01-3.87-4.77-7.54-8.66-9.5s-9.06-1.85-12.19 1.19c-1.44 1.4-2.38 3.32-4.02 4.5a8.05 8.05 0 01-7.04.72 23.8 23.8 0 01-6.36-3.59" fill="#2f2e41"/><path d="M756.07 51.17a29.38 29.38 0 0042.13 5.26c2.38-1.94 4.6-4.61 4.45-7.68-.16-3.15-2.73-5.62Line truncated
|
||||||
|
After Width: | Height: | Size: 5.0 KiB |
@@ -7,8 +7,10 @@
|
|||||||
"add-card": "Karte erstellen",
|
"add-card": "Karte erstellen",
|
||||||
"add-donation": "Sponsoring erstellen",
|
"add-donation": "Sponsoring erstellen",
|
||||||
"add-donor": "Sponsor:in erstellen",
|
"add-donor": "Sponsor:in erstellen",
|
||||||
|
"add-or-update-a-payment": "Zahlung hinzufügen oder bearbeiten",
|
||||||
"add-scan": "Scan erstellen",
|
"add-scan": "Scan erstellen",
|
||||||
"add-the-first-scanstation": "Erstelle deine erste Scannerstation.",
|
"add-the-first-scanstation": "Erstelle deine erste Scannerstation.",
|
||||||
|
"add-the-first-statsclient": "Erstelle deinen ersten Statsclient.",
|
||||||
"add-user-group": "Neue Gruppe erstellen",
|
"add-user-group": "Neue Gruppe erstellen",
|
||||||
"add-your-first-card": "Erstelle deine erste Läuferkarte",
|
"add-your-first-card": "Erstelle deine erste Läuferkarte",
|
||||||
"add-your-first-contact": "Erstelle den ersten Kontakt",
|
"add-your-first-contact": "Erstelle den ersten Kontakt",
|
||||||
@@ -28,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!",
|
||||||
@@ -46,6 +49,7 @@
|
|||||||
"cancel-keep-donor": "Abbrechen, Sponsor:in behalten",
|
"cancel-keep-donor": "Abbrechen, Sponsor:in behalten",
|
||||||
"cancel-keep-my-profile": "Abbrechen, mein Profil behalten",
|
"cancel-keep-my-profile": "Abbrechen, mein Profil behalten",
|
||||||
"cancel-keep-organization": "Abbrechen und Organisation bearbeiten",
|
"cancel-keep-organization": "Abbrechen und Organisation bearbeiten",
|
||||||
|
"cancel-keep-statsclient": "Abbrechen und Statsclient behalten",
|
||||||
"cancel-keep-team": "Abbrechen, Team behalten",
|
"cancel-keep-team": "Abbrechen, Team behalten",
|
||||||
"cannot-reset-your-password-directly": "Schade. \nWir können das Passwort leider nicht direkt zurücksetzen.\nBitte sende uns eine Mail in der du deine Identität bestätigst.",
|
"cannot-reset-your-password-directly": "Schade. \nWir können das Passwort leider nicht direkt zurücksetzen.\nBitte sende uns eine Mail in der du deine Identität bestätigst.",
|
||||||
"card-added": "Karte wurde hinzugefügt",
|
"card-added": "Karte wurde hinzugefügt",
|
||||||
@@ -66,6 +70,7 @@
|
|||||||
"confirm-delete-donor-with-all-donations": "Bestätigen, Sponsor:in mit allen Sponsorings löschen",
|
"confirm-delete-donor-with-all-donations": "Bestätigen, Sponsor:in mit allen Sponsorings löschen",
|
||||||
"confirm-delete-my-user-profile": "Bestätigung, mein Benutzerprofil löschen",
|
"confirm-delete-my-user-profile": "Bestätigung, mein Benutzerprofil löschen",
|
||||||
"confirm-delete-organization-and-associated-teams-runners": "Bestätugung, lösche die Organisation und alle zugehörigen Teams und Läufer:innen.",
|
"confirm-delete-organization-and-associated-teams-runners": "Bestätugung, lösche die Organisation und alle zugehörigen Teams und Läufer:innen.",
|
||||||
|
"confirm-delete-statsclient": "Bestätigung, Statsclient löschen",
|
||||||
"confirm-delete-team-and-associated-runners": "Bestätigung, lösche das Team mitsamt seinen Läufer:innen.",
|
"confirm-delete-team-and-associated-runners": "Bestätigung, lösche das Team mitsamt seinen Läufer:innen.",
|
||||||
"confirm-deletion": "Löschung Bestätigen",
|
"confirm-deletion": "Löschung Bestätigen",
|
||||||
"confirm-the-new-password": "Neues Passwort bestätigen",
|
"confirm-the-new-password": "Neues Passwort bestätigen",
|
||||||
@@ -93,6 +98,7 @@
|
|||||||
"create-a-new-runner": "Neue Läufer:in erstellen",
|
"create-a-new-runner": "Neue Läufer:in erstellen",
|
||||||
"create-a-new-scan-fixed-only": "Neuen Scan erstellen (nur mit Festdistanz)",
|
"create-a-new-scan-fixed-only": "Neuen Scan erstellen (nur mit Festdistanz)",
|
||||||
"create-a-new-scanstation": "Neue Station erstellen",
|
"create-a-new-scanstation": "Neue Station erstellen",
|
||||||
|
"create-a-new-statsclient": "Neuen Statsclient erstellen",
|
||||||
"create-a-new-team": "Erstelle ein neues Team",
|
"create-a-new-team": "Erstelle ein neues Team",
|
||||||
"create-a-new-track": "Neuen Track erstellen",
|
"create-a-new-track": "Neuen Track erstellen",
|
||||||
"create-a-new-user": "Neue Benutzer:in anlegen",
|
"create-a-new-user": "Neue Benutzer:in anlegen",
|
||||||
@@ -141,6 +147,7 @@
|
|||||||
"delete-runner": "Läufer:in löschen",
|
"delete-runner": "Läufer:in löschen",
|
||||||
"delete-scan": "Scan löschen",
|
"delete-scan": "Scan löschen",
|
||||||
"delete-station": "Station löschen",
|
"delete-station": "Station löschen",
|
||||||
|
"delete-statsclient": "Statsclient löschen",
|
||||||
"delete-team": "Team Löschen",
|
"delete-team": "Team Löschen",
|
||||||
"delete-user": "Benutzer:in löschen",
|
"delete-user": "Benutzer:in löschen",
|
||||||
"deleted-scan": "Scan wurde gelöscht",
|
"deleted-scan": "Scan wurde gelöscht",
|
||||||
@@ -234,6 +241,7 @@
|
|||||||
"invalid": "Ungültig",
|
"invalid": "Ungültig",
|
||||||
"invalid-mail-reset": "Das ist keine gültige E-Mail",
|
"invalid-mail-reset": "Das ist keine gültige E-Mail",
|
||||||
"just-enter-how-many-you-want-and-the-system-will-create-them": "Gebe einfach ein, wie viele Blankokarten das System erstellen soll.",
|
"just-enter-how-many-you-want-and-the-system-will-create-them": "Gebe einfach ein, wie viele Blankokarten das System erstellen soll.",
|
||||||
|
"key": "Schlüssel",
|
||||||
"laeufer-hinzufuegen": "Läufer:in hinzufügen",
|
"laeufer-hinzufuegen": "Läufer:in hinzufügen",
|
||||||
"laeufer-importieren": "Läufer:innen importieren",
|
"laeufer-importieren": "Läufer:innen importieren",
|
||||||
"laptime": "Rundenzeit",
|
"laptime": "Rundenzeit",
|
||||||
@@ -320,8 +328,10 @@
|
|||||||
"please-provide-the-required-information-to-add-a-new-track": "Bitte die benötigten Informationen angeben.",
|
"please-provide-the-required-information-to-add-a-new-track": "Bitte die benötigten Informationen angeben.",
|
||||||
"please-provide-the-required-information-to-add-a-new-user": "Bitte gebe alle nötigen Informationen an, im die neue Benutzer:in zu erstellen.",
|
"please-provide-the-required-information-to-add-a-new-user": "Bitte gebe alle nötigen Informationen an, im die neue Benutzer:in zu erstellen.",
|
||||||
"please-provide-the-required-information-to-create-a-new-scanstation": "Bitte gebe alle für eine Scannerstation notwendigen Informationen an",
|
"please-provide-the-required-information-to-create-a-new-scanstation": "Bitte gebe alle für eine Scannerstation notwendigen Informationen an",
|
||||||
|
"please-provide-the-required-information-to-create-a-new-statsclient": "Bitte gebe alle für einen Statsclient notwendigen Informationen an",
|
||||||
"please-request-a-new-reset-mail": "Bitte eine neue Passwortreset-Mail anfordern...",
|
"please-request-a-new-reset-mail": "Bitte eine neue Passwortreset-Mail anfordern...",
|
||||||
"please-wait-a-moment-your-login-is-still-being-processed": "Bitte warte einen Moment, deine Anmeldung wird verarbeitet",
|
"please-wait-a-moment-your-login-is-still-being-processed": "Bitte warte einen Moment, deine Anmeldung wird verarbeitet",
|
||||||
|
"prefix": "Prefix",
|
||||||
"privacy": "Datenschutz",
|
"privacy": "Datenschutz",
|
||||||
"privacy-loading": "Datenschutzerklärung lädt...",
|
"privacy-loading": "Datenschutzerklärung lädt...",
|
||||||
"profile": "Profil",
|
"profile": "Profil",
|
||||||
@@ -372,6 +382,10 @@
|
|||||||
"sponsoring-quittungs-liste_herunterladen": "Sponsoring-Quittungs-Liste herunterladen",
|
"sponsoring-quittungs-liste_herunterladen": "Sponsoring-Quittungs-Liste herunterladen",
|
||||||
"sponsorings": "Sponsoringerklaerungen",
|
"sponsorings": "Sponsoringerklaerungen",
|
||||||
"stats-are-being-loaded": "Die Statistiken werden geladen...",
|
"stats-are-being-loaded": "Die Statistiken werden geladen...",
|
||||||
|
"statsclient-deleted": "Statsclient wurde gelöscht",
|
||||||
|
"statsclient-is-being-added": "Statsclient wird angelegt...",
|
||||||
|
"statsclients": "Statsclient (aka Beamershow)",
|
||||||
|
"statsclients-are-being-loaded": "Statsclients werden geladen",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"stuff-that-could-harm-your-profile": "Einstellungen, die deinem Profil nachhaltig schaden können",
|
"stuff-that-could-harm-your-profile": "Einstellungen, die deinem Profil nachhaltig schaden können",
|
||||||
"successful-password-reset": "Passwort erfolgreich zurückgesetzt!",
|
"successful-password-reset": "Passwort erfolgreich zurückgesetzt!",
|
||||||
@@ -387,6 +401,7 @@
|
|||||||
"the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number": "Die angegebene Telefonnummer ist nicht korrekt. <br /> Bitte gebe eine Telefonnummer im internationalen Format an...",
|
"the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number": "Die angegebene Telefonnummer ist nicht korrekt. <br /> Bitte gebe eine Telefonnummer im internationalen Format an...",
|
||||||
"the-scans-distance-must-be-greater-than-0m": "Die Distanz muss größer als 0m sein.",
|
"the-scans-distance-must-be-greater-than-0m": "Die Distanz muss größer als 0m sein.",
|
||||||
"the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "Der Scannerstation Token wird nur einmal angezeigt - du kannst ihn nicht ändern oder ihn dir nochmal anzeigen lassen!",
|
"the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "Der Scannerstation Token wird nur einmal angezeigt - du kannst ihn nicht ändern oder ihn dir nochmal anzeigen lassen!",
|
||||||
|
"the-statsclient-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "Der Statsclient Token wird nur einmal angezeigt - du kannst ihn nicht ändern oder ihn dir nochmal anzeigen lassen!",
|
||||||
"there-are-no-cards-yet": "Es gibt noch keine Läuferkarten.",
|
"there-are-no-cards-yet": "Es gibt noch keine Läuferkarten.",
|
||||||
"there-are-no-contacts-added-yet": "Es wurden noch keine Kontakte hinzugefügt.",
|
"there-are-no-contacts-added-yet": "Es wurden noch keine Kontakte hinzugefügt.",
|
||||||
"there-are-no-donations-yet": "Es gibt noch keine Sponsorings",
|
"there-are-no-donations-yet": "Es gibt noch keine Sponsorings",
|
||||||
@@ -453,6 +468,7 @@
|
|||||||
"you-can-enter-the-donations-paid-amount-manually-or-use-the-max-button-to-use-the-donations-exact-amount": "Du kannst den Betrag der Zahlung entweder manuell eingeben oder über den MAX Button auf den Spendenbetrag setzen",
|
"you-can-enter-the-donations-paid-amount-manually-or-use-the-max-button-to-use-the-donations-exact-amount": "Du kannst den Betrag der Zahlung entweder manuell eingeben oder über den MAX Button auf den Spendenbetrag setzen",
|
||||||
"you-can-now-use-your-new-password-to-log-in-to-your-account": "Du kannst dich jetzt mit deinem neuen Passwort anmelden! 🎉",
|
"you-can-now-use-your-new-password-to-log-in-to-your-account": "Du kannst dich jetzt mit deinem neuen Passwort anmelden! 🎉",
|
||||||
"you-can-provide-a-runner-but-you-dont-have-to": "Du kannst eine Läufer:in angeben, musst aber nicht.",
|
"you-can-provide-a-runner-but-you-dont-have-to": "Du kannst eine Läufer:in angeben, musst aber nicht.",
|
||||||
|
"you-dont-have-any-scanclients-yet": "Es gibt noch keine Statsclients",
|
||||||
"you-dont-have-any-scanstations-yet": "Es gibt noch keine Scannerstationen",
|
"you-dont-have-any-scanstations-yet": "Es gibt noch keine Scannerstationen",
|
||||||
"you-have-to-provide-an-organization": "Du musst eine Organisation angeben",
|
"you-have-to-provide-an-organization": "Du musst eine Organisation angeben",
|
||||||
"you-have-to-save-your-changes-to-generate-a-link": "Du musst deine Änderungen speichern, um einen Link zu generieren.",
|
"you-have-to-save-your-changes-to-generate-a-link": "Du musst deine Änderungen speichern, um einen Link zu generieren.",
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
"add-or-update-a-payment": "Add or update a payment",
|
"add-or-update-a-payment": "Add or update a payment",
|
||||||
"add-scan": "Add scan",
|
"add-scan": "Add scan",
|
||||||
"add-the-first-scanstation": "Add your first scanstation.",
|
"add-the-first-scanstation": "Add your first scanstation.",
|
||||||
|
"add-the-first-statsclient": "Add your first statsclient.",
|
||||||
"add-user-group": "Add User Group",
|
"add-user-group": "Add User Group",
|
||||||
"add-your-first-card": "Add your first card",
|
"add-your-first-card": "Add your first card",
|
||||||
"add-your-first-contact": "Add your first contact",
|
"add-your-first-contact": "Add your first contact",
|
||||||
@@ -29,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!",
|
||||||
@@ -47,6 +49,7 @@
|
|||||||
"cancel-keep-donor": "Cancel, keep donor",
|
"cancel-keep-donor": "Cancel, keep donor",
|
||||||
"cancel-keep-my-profile": "Cancel, keep my profile",
|
"cancel-keep-my-profile": "Cancel, keep my profile",
|
||||||
"cancel-keep-organization": "Cancel, keep organization",
|
"cancel-keep-organization": "Cancel, keep organization",
|
||||||
|
"cancel-keep-statsclient": "Cancel and keep statsclient",
|
||||||
"cancel-keep-team": "Cancel, keep team",
|
"cancel-keep-team": "Cancel, keep team",
|
||||||
"cannot-reset-your-password-directly": "Bummer. We unfortunately cannot reset your password directly. Please send us a mail and confirm your identity",
|
"cannot-reset-your-password-directly": "Bummer. We unfortunately cannot reset your password directly. Please send us a mail and confirm your identity",
|
||||||
"card-added": "Card added",
|
"card-added": "Card added",
|
||||||
@@ -67,6 +70,7 @@
|
|||||||
"confirm-delete-donor-with-all-donations": "Confirm, delete donor with all donations",
|
"confirm-delete-donor-with-all-donations": "Confirm, delete donor with all donations",
|
||||||
"confirm-delete-my-user-profile": "Confirm, delete my user profile",
|
"confirm-delete-my-user-profile": "Confirm, delete my user profile",
|
||||||
"confirm-delete-organization-and-associated-teams-runners": "Confirm, delete organization and associated teams+runners.",
|
"confirm-delete-organization-and-associated-teams-runners": "Confirm, delete organization and associated teams+runners.",
|
||||||
|
"confirm-delete-statsclient": "Confirm, delete statsclient",
|
||||||
"confirm-delete-team-and-associated-runners": "Confirm, delete team and associated runners.",
|
"confirm-delete-team-and-associated-runners": "Confirm, delete team and associated runners.",
|
||||||
"confirm-deletion": "Confirm Deletion",
|
"confirm-deletion": "Confirm Deletion",
|
||||||
"confirm-the-new-password": "Confirm the new password",
|
"confirm-the-new-password": "Confirm the new password",
|
||||||
@@ -94,6 +98,7 @@
|
|||||||
"create-a-new-runner": "Create a new Runner",
|
"create-a-new-runner": "Create a new Runner",
|
||||||
"create-a-new-scan-fixed-only": "Create a new scan (fixed only)",
|
"create-a-new-scan-fixed-only": "Create a new scan (fixed only)",
|
||||||
"create-a-new-scanstation": "Create a new station",
|
"create-a-new-scanstation": "Create a new station",
|
||||||
|
"create-a-new-statsclient": "Create a new statsclient",
|
||||||
"create-a-new-team": "Create a new team",
|
"create-a-new-team": "Create a new team",
|
||||||
"create-a-new-track": "Create a new Track",
|
"create-a-new-track": "Create a new Track",
|
||||||
"create-a-new-user": "Create a new User",
|
"create-a-new-user": "Create a new User",
|
||||||
@@ -142,6 +147,7 @@
|
|||||||
"delete-runner": "Delete Runner",
|
"delete-runner": "Delete Runner",
|
||||||
"delete-scan": "Delete scan",
|
"delete-scan": "Delete scan",
|
||||||
"delete-station": "Delete station",
|
"delete-station": "Delete station",
|
||||||
|
"delete-statsclient": "Delete statsclient",
|
||||||
"delete-team": "Delete Team",
|
"delete-team": "Delete Team",
|
||||||
"delete-user": "Delete User",
|
"delete-user": "Delete User",
|
||||||
"deleted-scan": "Deleted scan",
|
"deleted-scan": "Deleted scan",
|
||||||
@@ -235,6 +241,7 @@
|
|||||||
"invalid": "Invalid",
|
"invalid": "Invalid",
|
||||||
"invalid-mail-reset": "the provided email is invalid",
|
"invalid-mail-reset": "the provided email is invalid",
|
||||||
"just-enter-how-many-you-want-and-the-system-will-create-them": "Just enter how many you want and the system will create them",
|
"just-enter-how-many-you-want-and-the-system-will-create-them": "Just enter how many you want and the system will create them",
|
||||||
|
"key": "Key",
|
||||||
"laeufer-hinzufuegen": "Add runner",
|
"laeufer-hinzufuegen": "Add runner",
|
||||||
"laeufer-importieren": "Läufer importieren",
|
"laeufer-importieren": "Läufer importieren",
|
||||||
"laptime": "Laptime",
|
"laptime": "Laptime",
|
||||||
@@ -321,8 +328,10 @@
|
|||||||
"please-provide-the-required-information-to-add-a-new-track": "Please provide the required information to add a new track.",
|
"please-provide-the-required-information-to-add-a-new-track": "Please provide the required information to add a new track.",
|
||||||
"please-provide-the-required-information-to-add-a-new-user": "Please provide the required information to add a new user.",
|
"please-provide-the-required-information-to-add-a-new-user": "Please provide the required information to add a new user.",
|
||||||
"please-provide-the-required-information-to-create-a-new-scanstation": "Please provide the required information to create a new scanstation",
|
"please-provide-the-required-information-to-create-a-new-scanstation": "Please provide the required information to create a new scanstation",
|
||||||
|
"please-provide-the-required-information-to-create-a-new-statsclient": "Please provide the required information to create a new statsclient",
|
||||||
"please-request-a-new-reset-mail": "Please request a new reset mail...",
|
"please-request-a-new-reset-mail": "Please request a new reset mail...",
|
||||||
"please-wait-a-moment-your-login-is-still-being-processed": "Please wait a moment, your login is still being processed",
|
"please-wait-a-moment-your-login-is-still-being-processed": "Please wait a moment, your login is still being processed",
|
||||||
|
"prefix": "Prefix",
|
||||||
"privacy": "Privacy",
|
"privacy": "Privacy",
|
||||||
"privacy-loading": "Privacy loading...",
|
"privacy-loading": "Privacy loading...",
|
||||||
"profile": "Profile",
|
"profile": "Profile",
|
||||||
@@ -373,6 +382,10 @@
|
|||||||
"sponsoring-quittungs-liste_herunterladen": "Download donor receipt list",
|
"sponsoring-quittungs-liste_herunterladen": "Download donor receipt list",
|
||||||
"sponsorings": "Sponsorings",
|
"sponsorings": "Sponsorings",
|
||||||
"stats-are-being-loaded": "stats are being loaded...",
|
"stats-are-being-loaded": "stats are being loaded...",
|
||||||
|
"statsclient-deleted": "Deleted statsclient",
|
||||||
|
"statsclient-is-being-added": "Statsclient is being added...",
|
||||||
|
"statsclients": "Statsclients (aka Beamershow)",
|
||||||
|
"statsclients-are-being-loaded": "Loading statsclients",
|
||||||
"status": "Status",
|
"status": "Status",
|
||||||
"stuff-that-could-harm-your-profile": "Stuff that could harm your profile",
|
"stuff-that-could-harm-your-profile": "Stuff that could harm your profile",
|
||||||
"successful-password-reset": "Successful password reset!",
|
"successful-password-reset": "Successful password reset!",
|
||||||
@@ -388,6 +401,7 @@
|
|||||||
"the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number": "the provided phone number is invalid.<br />please enter a valid international number...",
|
"the-provided-phone-number-is-invalid-less-than-br-greater-than-please-enter-a-valid-international-number": "the provided phone number is invalid.<br />please enter a valid international number...",
|
||||||
"the-scans-distance-must-be-greater-than-0m": "The scan's distance must be greater than 0m",
|
"the-scans-distance-must-be-greater-than-0m": "The scan's distance must be greater than 0m",
|
||||||
"the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "The scanstation api token will only get displayed once - you won't be able to change or view it again!",
|
"the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "The scanstation api token will only get displayed once - you won't be able to change or view it again!",
|
||||||
|
"the-statsclient-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again": "The statsclient api token will only get displayed once - you won't be able to change or view it again!",
|
||||||
"there-are-no-cards-yet": "There are no cards yet.",
|
"there-are-no-cards-yet": "There are no cards yet.",
|
||||||
"there-are-no-contacts-added-yet": "There are no contacts added yet.",
|
"there-are-no-contacts-added-yet": "There are no contacts added yet.",
|
||||||
"there-are-no-donations-yet": "There are no donations yet",
|
"there-are-no-donations-yet": "There are no donations yet",
|
||||||
@@ -454,6 +468,7 @@
|
|||||||
"you-can-enter-the-donations-paid-amount-manually-or-use-the-max-button-to-use-the-donations-exact-amount": "You can enter the donation's paid amount manually or use the MAX button to use the donation's exact amount.",
|
"you-can-enter-the-donations-paid-amount-manually-or-use-the-max-button-to-use-the-donations-exact-amount": "You can enter the donation's paid amount manually or use the MAX button to use the donation's exact amount.",
|
||||||
"you-can-now-use-your-new-password-to-log-in-to-your-account": "You can now use your new password to log in to your account! 🎉",
|
"you-can-now-use-your-new-password-to-log-in-to-your-account": "You can now use your new password to log in to your account! 🎉",
|
||||||
"you-can-provide-a-runner-but-you-dont-have-to": "You can provide a runner, but you don't have to.",
|
"you-can-provide-a-runner-but-you-dont-have-to": "You can provide a runner, but you don't have to.",
|
||||||
|
"you-dont-have-any-scanclients-yet": "You don't have any statsclients yet",
|
||||||
"you-dont-have-any-scanstations-yet": "You don't have any scanstations yet",
|
"you-dont-have-any-scanstations-yet": "You don't have any scanstations yet",
|
||||||
"you-have-to-provide-an-organization": "You have to provide an organization",
|
"you-have-to-provide-an-organization": "You have to provide an organization",
|
||||||
"you-have-to-save-your-changes-to-generate-a-link": "You have to save your changes to generate a link.",
|
"you-have-to-save-your-changes-to-generate-a-link": "You have to save your changes to generate a link.",
|
||||||
|
|||||||
Reference in new issue
Block a user