Compare commits
100
Commits
1.4.5
...
fecf3b59a3
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
fecf3b59a3
|
||
|
|
18a4623e71
|
||
|
|
968a7ccc0e
|
||
|
|
6249502a88
|
||
|
|
8a78034079
|
||
|
|
7633b7b056
|
||
|
|
b8e6b24bf3
|
||
|
|
97b7ca931f
|
||
|
|
48dd9acde5
|
||
|
|
5147a20b3c
|
||
|
|
bb2319a78d
|
||
|
|
7c10d95c1c
|
||
|
|
f734d1e3f6
|
||
|
|
e567bb35c3
|
||
|
|
3ec18a6964
|
||
|
|
847fa288f1
|
||
|
|
824ecfab2e
|
||
|
|
5f5d8277b9
|
||
|
|
0a6cf619b0
|
||
|
|
050a146ae0
|
||
|
|
1bc53146b9
|
||
|
|
e82350df4a
|
||
|
|
3d3ce2918b
|
||
|
|
79e6a4212d
|
||
|
|
37cdbba0a3
|
||
|
|
c37fb98bed
|
||
|
|
975f145444
|
||
|
|
391186d01f
|
||
|
|
ae056cd88c
|
||
|
|
7f989b206b
|
||
|
|
65ce02e777
|
||
|
|
878d9714cb
|
||
|
|
f99b7f4bb8
|
||
|
|
e23098410c
|
||
|
|
04494d2a2a
|
||
|
|
e2d6fbb513
|
||
|
|
477c650f3f
|
||
|
|
fc15c68cba
|
||
|
|
32b5f5420b
|
||
|
|
ee87f82799
|
||
|
|
7c08f522aa
|
||
|
|
e211554579
|
||
|
|
7ba890dfd7
|
||
|
|
68b4309164
|
||
|
|
d803f3d490
|
||
|
|
5468766d87
|
||
|
|
e967d8d20c
|
||
|
|
ad4db882f0
|
||
|
|
84aa846b87
|
||
|
|
3532968b33
|
||
|
|
6bb49db4ee
|
||
|
|
38fb111f7a
|
||
|
|
a50447f457
|
||
|
|
b1a2044631
|
||
|
|
c883920caa
|
||
|
|
21453ef272
|
||
|
|
10182433f8
|
||
|
|
b338f33a63
|
||
|
|
cb82200481
|
||
|
|
9abf74d6d2
|
||
|
|
50e81a6cb5
|
||
|
|
8fae1fb6b3
|
||
|
|
372fa110ec
|
||
|
|
35bec9fe58
|
||
|
|
93d67bdba9
|
||
|
|
a5e72a18e3
|
||
|
|
91d2f46b93
|
||
|
|
c60bae4533
|
||
|
|
43ac878d44
|
||
|
|
ceabd06a43
|
||
|
|
9bfc0c5338
|
||
|
|
fb8206ff13
|
||
|
|
dceb0ef461
|
||
|
|
88bc1982ca
|
||
|
|
e741a9d7e7
|
||
|
|
65f1d22205
|
||
|
|
d867c08aba
|
||
|
|
6193eff38e | ||
|
|
f1929e7cf9
|
||
|
|
373484c242
|
||
|
|
f77460bb0c
|
||
|
|
574e0dcb05
|
||
|
|
7b19a0aa08
|
||
|
|
08642d7618 | ||
|
|
c3e9c27cd3
|
||
|
|
29a2854671
|
||
|
|
8e6786e722
|
||
|
|
6ad40564e3
|
||
|
|
776973bfe9
|
||
|
|
6025e43baa
|
||
|
|
d9a47f882c
|
||
|
|
4235758a6d
|
||
|
|
59fe2dfabb
|
||
|
|
6364536dcd
|
||
|
|
a8a771114d
|
||
|
|
4e0a2c8301
|
||
|
|
b6fed92a17
|
||
|
|
97b57aeb0c
|
||
|
|
e25ed1fff9
|
||
|
|
a2ff5b8a14
|
No files matched your search
+3
-1
@@ -1,2 +1,4 @@
|
|||||||
public/env.sample.js
|
public/env.sample.js
|
||||||
.pnpm-store
|
.pnpm-store
|
||||||
|
.yarn
|
||||||
|
.pnp.*
|
||||||
-101
@@ -1,101 +0,0 @@
|
|||||||
---
|
|
||||||
kind: secret
|
|
||||||
name: docker_username
|
|
||||||
get:
|
|
||||||
path: odit-registry-builder
|
|
||||||
name: username
|
|
||||||
|
|
||||||
---
|
|
||||||
kind: secret
|
|
||||||
name: docker_password
|
|
||||||
get:
|
|
||||||
path: odit-registry-builder
|
|
||||||
name: password
|
|
||||||
|
|
||||||
---
|
|
||||||
kind: secret
|
|
||||||
name: git_ssh
|
|
||||||
get:
|
|
||||||
path: odit-git-bot
|
|
||||||
name: sshkey
|
|
||||||
|
|
||||||
---
|
|
||||||
kind: secret
|
|
||||||
name: npm_url
|
|
||||||
get:
|
|
||||||
path: odit-npm-cache
|
|
||||||
name: url
|
|
||||||
|
|
||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
type: kubernetes
|
|
||||||
name: build:dev
|
|
||||||
|
|
||||||
steps:
|
|
||||||
- name: run full license export
|
|
||||||
depends_on: ["clone"]
|
|
||||||
image: registry.odit.services/hub/library/node:19.7.0-alpine3.16
|
|
||||||
commands:
|
|
||||||
- npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@8
|
|
||||||
- pnpm i
|
|
||||||
- pnpm licenses:export
|
|
||||||
environment:
|
|
||||||
NPM_REGISTRY_URL:
|
|
||||||
from_secret: npm_url
|
|
||||||
- name: push new licenses file to repo
|
|
||||||
depends_on: ["run full license export"]
|
|
||||||
image: appleboy/drone-git-push
|
|
||||||
settings:
|
|
||||||
branch: dev
|
|
||||||
commit: true
|
|
||||||
commit_message: new license file version [CI SKIP]
|
|
||||||
author_email: bot@odit.services
|
|
||||||
remote: git@git.odit.services:lfk/frontend.git
|
|
||||||
ssh_key:
|
|
||||||
from_secret: git_ssh
|
|
||||||
- name: build dev
|
|
||||||
depends_on: ["clone"]
|
|
||||||
image: registry.odit.services/library/drone-kaniko
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
build_args:
|
|
||||||
- NPM_REGISTRY_URL:
|
|
||||||
from_secret: npm_url
|
|
||||||
repo: lfk/frontend
|
|
||||||
tags:
|
|
||||||
- dev
|
|
||||||
cache: true
|
|
||||||
registry: registry.odit.services
|
|
||||||
trigger:
|
|
||||||
branch:
|
|
||||||
- dev
|
|
||||||
event:
|
|
||||||
- push
|
|
||||||
|
|
||||||
---
|
|
||||||
kind: pipeline
|
|
||||||
type: kubernetes
|
|
||||||
name: build:tags
|
|
||||||
steps:
|
|
||||||
- name: build $DRONE_TAG
|
|
||||||
depends_on: ["clone"]
|
|
||||||
image: registry.odit.services/library/drone-kaniko
|
|
||||||
settings:
|
|
||||||
username:
|
|
||||||
from_secret: docker_username
|
|
||||||
password:
|
|
||||||
from_secret: docker_password
|
|
||||||
build_args:
|
|
||||||
- NPM_REGISTRY_URL:
|
|
||||||
from_secret: npm_url
|
|
||||||
repo: lfk/frontend
|
|
||||||
tags:
|
|
||||||
- "${DRONE_TAG}"
|
|
||||||
cache: true
|
|
||||||
registry: registry.odit.services
|
|
||||||
trigger:
|
|
||||||
event:
|
|
||||||
- tag
|
|
||||||
@@ -0,0 +1,34 @@
|
|||||||
|
name: Build Latest and dev images
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
branches:
|
||||||
|
- dev
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-container:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 19
|
||||||
|
- run: npm i -g pnpm@8 && pnpm i
|
||||||
|
- run: pnpm licenses:export
|
||||||
|
- name: Login to registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: registry.odit.services
|
||||||
|
username: ${{ vars.REGISTRY_USERNAME }}
|
||||||
|
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
${{ vars.REGISTRY }}/lfk/frontend:dev
|
||||||
|
${{ vars.REGISTRY }}/lfk/frontend:latest
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
@@ -0,0 +1,33 @@
|
|||||||
|
name: Build release images
|
||||||
|
on:
|
||||||
|
push:
|
||||||
|
tags:
|
||||||
|
- "*.*.*"
|
||||||
|
|
||||||
|
jobs:
|
||||||
|
build-container:
|
||||||
|
runs-on: ubuntu-latest
|
||||||
|
steps:
|
||||||
|
- name: Checkout
|
||||||
|
uses: actions/checkout@v4
|
||||||
|
- name: Set up Node.js
|
||||||
|
uses: actions/setup-node@v4
|
||||||
|
with:
|
||||||
|
node-version: 19
|
||||||
|
- run: npm i -g pnpm@8 && pnpm i
|
||||||
|
- run: pnpm licenses:export
|
||||||
|
- name: Login to registry
|
||||||
|
uses: docker/login-action@v3
|
||||||
|
with:
|
||||||
|
registry: registry.odit.services
|
||||||
|
username: ${{ vars.REGISTRY_USERNAME }}
|
||||||
|
password: ${{ secrets.REGISTRY_PASSWORD }}
|
||||||
|
- name: Set up Docker Buildx
|
||||||
|
uses: docker/setup-buildx-action@v3
|
||||||
|
- name: Build and push
|
||||||
|
uses: docker/build-push-action@v6
|
||||||
|
with:
|
||||||
|
push: true
|
||||||
|
tags: |
|
||||||
|
${{ vars.REGISTRY }}/lfk/frontend:${{ github.ref_name }}
|
||||||
|
platforms: linux/amd64,linux/arm64
|
||||||
+3
-1
@@ -3,4 +3,6 @@ node_modules
|
|||||||
public/env.js
|
public/env.js
|
||||||
public/index.html
|
public/index.html
|
||||||
/dist
|
/dist
|
||||||
.pnpm-store
|
.pnpm-store
|
||||||
|
.yarn
|
||||||
|
.pnp.*
|
||||||
+180
@@ -2,10 +2,190 @@
|
|||||||
|
|
||||||
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
|
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
|
||||||
|
|
||||||
|
#### [1.8.2](https://git.odit.services/lfk/frontend/compare/1.8.1...1.8.2)
|
||||||
|
|
||||||
|
- feat: improvement of card,certificate,sponsoringcontract action buttons [`7633b7b`](https://git.odit.services/lfk/frontend/commit/7633b7b05671342bc30e0bbecbcd9450e06b5e4d)
|
||||||
|
- feat(dashboard): active item for teams + runners [`8a78034`](https://git.odit.services/lfk/frontend/commit/8a780340792445fff1f78db994fb78acb5da8304)
|
||||||
|
|
||||||
|
#### [1.8.1](https://git.odit.services/lfk/frontend/compare/1.8.0...1.8.1)
|
||||||
|
|
||||||
|
> 26 March 2025
|
||||||
|
|
||||||
|
- 🚀RELEASE v1.8.1 [`b8e6b24`](https://git.odit.services/lfk/frontend/commit/b8e6b24bf32379c3f4a1679d422e6fdcc45f7c99)
|
||||||
|
- fix(pdf_generation): Only load direct runners for direct calls [`97b7ca9`](https://git.odit.services/lfk/frontend/commit/97b7ca931f607ee64509ad10c2269632fc691091)
|
||||||
|
|
||||||
|
#### [1.8.0](https://git.odit.services/lfk/frontend/compare/1.7.0...1.8.0)
|
||||||
|
|
||||||
|
> 26 March 2025
|
||||||
|
|
||||||
|
- wip [`824ecfa`](https://git.odit.services/lfk/frontend/commit/824ecfab2e976cd7c6cd2851be8a9be5c6b686e1)
|
||||||
|
- wip [`0a6cf61`](https://git.odit.services/lfk/frontend/commit/0a6cf619b09be837d5503f4695250c7edaeeaff5)
|
||||||
|
- feat: improve fonts + button positions [`c37fb98`](https://git.odit.services/lfk/frontend/commit/c37fb98bed377744981e927ea8d22db9e20c55ca)
|
||||||
|
- 🚀RELEASE v1.8.0 [`48dd9ac`](https://git.odit.services/lfk/frontend/commit/48dd9acde595b882630855d5e6af3cfa18fc9ecf)
|
||||||
|
- wip [`1bc5314`](https://git.odit.services/lfk/frontend/commit/1bc53146b9f024f3cab613b227d29304d687c92b)
|
||||||
|
- wip [`e82350d`](https://git.odit.services/lfk/frontend/commit/e82350df4af082d2bbb322658c6c022d83b819ae)
|
||||||
|
- wip [`37cdbba`](https://git.odit.services/lfk/frontend/commit/37cdbba0a3563875e19bee560f2cd5c8fc2d7a6e)
|
||||||
|
- feat: improve input readability [`79e6a42`](https://git.odit.services/lfk/frontend/commit/79e6a4212d06029766d0a853686ed97879ebd349)
|
||||||
|
- wip [`5f5d827`](https://git.odit.services/lfk/frontend/commit/5f5d8277b98363ef15a92621fca0a209345aca95)
|
||||||
|
- chore(deps): bump [`bb2319a`](https://git.odit.services/lfk/frontend/commit/bb2319a78d253a2d6239a0d3daedc90fd29abdd0)
|
||||||
|
- feat: cleanup TeamDetail + OrgDetail [`f734d1e`](https://git.odit.services/lfk/frontend/commit/f734d1e3f643a500a6432a389c3103045cc51262)
|
||||||
|
- refactor(ci): Switch to actions for dev [`847fa28`](https://git.odit.services/lfk/frontend/commit/847fa288f1b5bbc422cc2944bbe66e80c5a00407)
|
||||||
|
- refactor(ci): Add Gitea workflow for building release images and remove Woodpecker configuration [`3ec18a6`](https://git.odit.services/lfk/frontend/commit/3ec18a696435ada26bf2de2220b190dc630a9759)
|
||||||
|
- feat: athiti font [`391186d`](https://git.odit.services/lfk/frontend/commit/391186d01f3b96638a3569dc2843bf181dc3f02c)
|
||||||
|
- fix(DonorDetail): donor deletion [`5147a20`](https://git.odit.services/lfk/frontend/commit/5147a20b3c4a46968482b1e3517047351c94f77e)
|
||||||
|
- feat(dashboard): full width for sidebar items [`975f145`](https://git.odit.services/lfk/frontend/commit/975f145444e5a478524ea2cbbfb9059b93617185)
|
||||||
|
- wip [`3d3ce29`](https://git.odit.services/lfk/frontend/commit/3d3ce2918bc20cf1080a2b5153ddd8aaf51374b4)
|
||||||
|
- feat(RunnerOrganizationService.runnerOrganizationControllerGetRunners): load all runners in org [`7c10d95`](https://git.odit.services/lfk/frontend/commit/7c10d95c1c68f4842fd323698e004a5ebf2c96cf)
|
||||||
|
- wip [`050a146`](https://git.odit.services/lfk/frontend/commit/050a146ae070d67d8308db4b9612fd6eacbb9923)
|
||||||
|
- fix(ci): Correct tag pattern syntax in release workflow [`e567bb3`](https://git.odit.services/lfk/frontend/commit/e567bb35c3b3f6eb73a2f0bc72f601e70f881ac8)
|
||||||
|
|
||||||
|
#### [1.7.0](https://git.odit.services/lfk/frontend/compare/1.6.0...1.7.0)
|
||||||
|
|
||||||
|
> 17 December 2024
|
||||||
|
|
||||||
|
- refactor(pdfgeneration): Switch cards over to new service [`e230984`](https://git.odit.services/lfk/frontend/commit/e23098410c7d0b326cdbbb3a4b63fed10611e252)
|
||||||
|
- refactor(pdfgeneration): Switch to new document-server api [`878d971`](https://git.odit.services/lfk/frontend/commit/878d9714cbc0a60cfd96bd1faf8af6af46e6fb5e)
|
||||||
|
- refactor(pdfgeneration): Switched contract generation over to new document-server [`f99b7f4`](https://git.odit.services/lfk/frontend/commit/f99b7f4bb8f166bb966022ddd10689c082d248f0)
|
||||||
|
- refactor(cards): Switched over to new document-server api [`65ce02e`](https://git.odit.services/lfk/frontend/commit/65ce02e777e6e9b3cfed248de680e5f292b3a639)
|
||||||
|
- 🚀RELEASE v1.7.0 [`ae056cd`](https://git.odit.services/lfk/frontend/commit/ae056cd88cb27f003845fa4534553cde841c7f99)
|
||||||
|
- fix(pdfgeneration): Added parent_group [`7f989b2`](https://git.odit.services/lfk/frontend/commit/7f989b206b16e2687d01a38da8e3ea9be0a52ba5)
|
||||||
|
|
||||||
|
#### [1.6.0](https://git.odit.services/lfk/frontend/compare/1.5.3...1.6.0)
|
||||||
|
|
||||||
|
> 11 December 2024
|
||||||
|
|
||||||
|
- refactor(orgs): Swtich to new selfservice baseurl [`e2d6fbb`](https://git.odit.services/lfk/frontend/commit/e2d6fbb513dc9fe7ce05855edb4b0b4b5daeb07a)
|
||||||
|
- chore: bump [`04494d2`](https://git.odit.services/lfk/frontend/commit/04494d2a2a542f25f785f3bb23e49e5eb0691c0a)
|
||||||
|
|
||||||
|
#### [1.5.3](https://git.odit.services/lfk/frontend/compare/1.5.2...1.5.3)
|
||||||
|
|
||||||
|
> 26 November 2024
|
||||||
|
|
||||||
|
- feat(dx): Yarn support [`fc15c68`](https://git.odit.services/lfk/frontend/commit/fc15c68cba0d1986563eaf63da3a68784a685a9e)
|
||||||
|
- feat(about): cleanup ui [`84aa846`](https://git.odit.services/lfk/frontend/commit/84aa846b87186b52a2f8632724d4f2cb70af062b)
|
||||||
|
- feat(dashboard): reorder menu items [`e967d8d`](https://git.odit.services/lfk/frontend/commit/e967d8d20c6972b64b0096594a09043553e9c7e5)
|
||||||
|
- fix: unexpected/ missing props [`d803f3d`](https://git.odit.services/lfk/frontend/commit/d803f3d4905d6f792b77d17025467ac13c29068b)
|
||||||
|
- chore(deps): bump some [`68b4309`](https://git.odit.services/lfk/frontend/commit/68b4309164eac40b6fda969b60a7e238985d49f8)
|
||||||
|
- 🚀RELEASE v1.5.3 [`477c650`](https://git.odit.services/lfk/frontend/commit/477c650f3f6dd2eadf5f1cc404e8fc9b02a7841b)
|
||||||
|
- fix(ci): Switch over to new woodpecker version [`7ba890d`](https://git.odit.services/lfk/frontend/commit/7ba890dfd7ba908ebef0338f6faa5e7d804cb5ef)
|
||||||
|
- refactor(ci): Only build licences, don't export [`32b5f54`](https://git.odit.services/lfk/frontend/commit/32b5f5420bf9ff656b713d61b3a0113b9d6cb69f)
|
||||||
|
- feat: cleanup random page toasts [`ad4db88`](https://git.odit.services/lfk/frontend/commit/ad4db882f0f4d00a80ae5e0072e09c071c07ffa2)
|
||||||
|
- fix(ci): Update git pushb settings [`ee87f82`](https://git.odit.services/lfk/frontend/commit/ee87f82799ce559fd43d671ab412f2643eafeac6)
|
||||||
|
- fix(ci): Update relase machanism [`7c08f52`](https://git.odit.services/lfk/frontend/commit/7c08f522aa4b2986544a4c0e5d3261c4c7296121)
|
||||||
|
- fix(ci): Install pnpm [`e211554`](https://git.odit.services/lfk/frontend/commit/e211554579b1f27d13194eff4aad76f6f030141e)
|
||||||
|
- fix(orgs): ImportRunnerModal props [`5468766`](https://git.odit.services/lfk/frontend/commit/5468766d875a6278f01ed1fd9573688374befdd5)
|
||||||
|
|
||||||
|
#### [1.5.2](https://git.odit.services/lfk/frontend/compare/1.5.1...1.5.2)
|
||||||
|
|
||||||
|
> 21 November 2024
|
||||||
|
|
||||||
|
- feat: improved dashboard titles ui + a11y [`21453ef`](https://git.odit.services/lfk/frontend/commit/21453ef272665c0b7c7b04009b7b74e110fbd988)
|
||||||
|
- feat: improved dashboard titles ui + a11y [`c883920`](https://git.odit.services/lfk/frontend/commit/c883920caaaaef30a8e54dd0e7eecd68943f3041)
|
||||||
|
- feat(dashboard): improved a11y of active sidebar menu item [`a50447f`](https://git.odit.services/lfk/frontend/commit/a50447f457ecc045995efb7b952b07ea09c91373)
|
||||||
|
- feat: improved mobile buttons + search ui [`38fb111`](https://git.odit.services/lfk/frontend/commit/38fb111f7a2b5a1a01b17b00e89ee081e4b91bd9)
|
||||||
|
- feat(i18n/de): rename "Track" to "Laufstrecke" [`1018243`](https://git.odit.services/lfk/frontend/commit/10182433f825968ee55298399b231173698a795c)
|
||||||
|
- 🚀RELEASE v1.5.2 [`3532968`](https://git.odit.services/lfk/frontend/commit/3532968b3399b985b1ed28ba6b89a13f35f9289b)
|
||||||
|
- feat(dashboard): improved mobile ui hamburger button [`b338f33`](https://git.odit.services/lfk/frontend/commit/b338f33a63ad8e98ab44deff2f80dbd5fe2a0fc2)
|
||||||
|
- feat(dashboard): match greeting style with rest of titles [`b1a2044`](https://git.odit.services/lfk/frontend/commit/b1a20446314d1b25e9f653bd2767b072fd629f97)
|
||||||
|
- feat(dashboard): add lfk icon and app name to mobile nav bar [`6bb49db`](https://git.odit.services/lfk/frontend/commit/6bb49db4eee95486f5a947d708b80a7a94d36933)
|
||||||
|
- feat(users/UsersOverview): improve ui by adding borders to badges [`cb82200`](https://git.odit.services/lfk/frontend/commit/cb82200481c629a0dd8b235821115ae4276948ca)
|
||||||
|
|
||||||
|
#### [1.5.1](https://git.odit.services/lfk/frontend/compare/1.5.0...1.5.1)
|
||||||
|
|
||||||
|
> 21 November 2024
|
||||||
|
|
||||||
|
- chore(deps): pnpm@9 [`35bec9f`](https://git.odit.services/lfk/frontend/commit/35bec9fe584b93cd52e8bab4e469713468a67f70)
|
||||||
|
- chore(deps): bump some [`8fae1fb`](https://git.odit.services/lfk/frontend/commit/8fae1fb6b3e033f789d2568cbd2640c0d163dc53)
|
||||||
|
- fix(scanstations): CopyScanStationTokenModal open after create [`372fa11`](https://git.odit.services/lfk/frontend/commit/372fa110ec402dae166a302f2209c79353983148)
|
||||||
|
- 🚀RELEASE v1.5.1 [`9abf74d`](https://git.odit.services/lfk/frontend/commit/9abf74d6d217e7745c1055bdbfbe97de7b14572f)
|
||||||
|
- fix(config): add explicit window.config [`91d2f46`](https://git.odit.services/lfk/frontend/commit/91d2f46b934bcba1429bd1d96e772c25c42a3e28)
|
||||||
|
- fix(dockerfile): AS casing [`50e81a6`](https://git.odit.services/lfk/frontend/commit/50e81a6cb5773381e153cbec3bed7db820ced84a)
|
||||||
|
- refactor(scanstations/CopyScanStationTokenModal): drop dispatch [`a5e72a1`](https://git.odit.services/lfk/frontend/commit/a5e72a18e368b5a7ee7b4e1894de613ecb767f28)
|
||||||
|
- chore(deps): node:23.2.0 [`93d67bd`](https://git.odit.services/lfk/frontend/commit/93d67bdba90a67b45d8895d9facaf66e908d53d6)
|
||||||
|
- fix(tracks/AddTrackModal): i18n [`c60bae4`](https://git.odit.services/lfk/frontend/commit/c60bae45334c2aa90d8931da07691c196469da46)
|
||||||
|
- fix: tailwind config [`43ac878`](https://git.odit.services/lfk/frontend/commit/43ac878d44b556c6d7811610f6fe0c9a5eff305f)
|
||||||
|
|
||||||
|
#### [1.5.0](https://git.odit.services/lfk/frontend/compare/1.4.13...1.5.0)
|
||||||
|
|
||||||
|
> 20 November 2024
|
||||||
|
|
||||||
|
- feat(ci)!: Switch to woodpecker [`fb8206f`](https://git.odit.services/lfk/frontend/commit/fb8206ff130f4f65dcf619a2a786e7d5895b77a1)
|
||||||
|
- 🚀RELEASE v1.5.0 [`ceabd06`](https://git.odit.services/lfk/frontend/commit/ceabd06a4319c3c9ffab680f909730d5bd789540)
|
||||||
|
- fix(components): Add missing toast imports [`9bfc0c5`](https://git.odit.services/lfk/frontend/commit/9bfc0c5338933e832d5df50457c7978c026d8df6)
|
||||||
|
|
||||||
|
#### [1.4.13](https://git.odit.services/lfk/frontend/compare/1.4.12...1.4.13)
|
||||||
|
|
||||||
|
> 31 July 2023
|
||||||
|
|
||||||
|
- 🚀RELEASE v1.4.13 [`dceb0ef`](https://git.odit.services/lfk/frontend/commit/dceb0ef46197dc56e29c5f52a5bd8f9fe9b70b27)
|
||||||
|
- Show donations as euro in export [`88bc198`](https://git.odit.services/lfk/frontend/commit/88bc1982cab4481e2e9245f81eff27e095b66a0f)
|
||||||
|
- new license file version [CI SKIP] [`6193eff`](https://git.odit.services/lfk/frontend/commit/6193eff38e1a9d5726bc7d572ab36b921de843d0)
|
||||||
|
|
||||||
|
#### [1.4.12](https://git.odit.services/lfk/frontend/compare/1.4.11...1.4.12)
|
||||||
|
|
||||||
|
> 18 May 2023
|
||||||
|
|
||||||
|
- 🚀RELEASE v1.4.12 [`65f1d22`](https://git.odit.services/lfk/frontend/commit/65f1d222050b0dec81fc847c1921b6135a55ce50)
|
||||||
|
- fix(donation/payment): Funny javascript number to float conversion where integers were needed [`d867c08`](https://git.odit.services/lfk/frontend/commit/d867c08aba234d3a7fe9e2311d37dc5e96fc2afc)
|
||||||
|
- new license file version [CI SKIP] [`08642d7`](https://git.odit.services/lfk/frontend/commit/08642d7618faeae31f0acfe776642c9fa156e5ff)
|
||||||
|
|
||||||
|
#### [1.4.11](https://git.odit.services/lfk/frontend/compare/1.4.10...1.4.11)
|
||||||
|
|
||||||
|
> 10 May 2023
|
||||||
|
|
||||||
|
- chore(deps): Lockfile [`f77460b`](https://git.odit.services/lfk/frontend/commit/f77460bb0c8ce6d0f3d83a077017d5fc7bf55af7)
|
||||||
|
- 🚀RELEASE v1.4.11 [`373484c`](https://git.odit.services/lfk/frontend/commit/373484c2424bea7ae0d70d342e0ae2076aab1b6a)
|
||||||
|
- feat(orgs): Show total distance [`574e0dc`](https://git.odit.services/lfk/frontend/commit/574e0dcb051305bde2fc76d8456a35baec0cf309)
|
||||||
|
- chore(deps): More bumps [`7b19a0a`](https://git.odit.services/lfk/frontend/commit/7b19a0aa08bb6c89c51d27c0d05777e8fcfdad17)
|
||||||
|
|
||||||
|
#### [1.4.10](https://git.odit.services/lfk/frontend/compare/1.4.9...1.4.10)
|
||||||
|
|
||||||
|
> 10 May 2023
|
||||||
|
|
||||||
|
- chore(deps): Bumped svelte-table [`29a2854`](https://git.odit.services/lfk/frontend/commit/29a2854671b3af5b85ea96d050a9076f47b6575d)
|
||||||
|
- 🚀RELEASE v1.4.10 [`c3e9c27`](https://git.odit.services/lfk/frontend/commit/c3e9c27cd3d4b916f1661d4958cabab038918587)
|
||||||
|
- chore(deps): Pin and bump [`8e6786e`](https://git.odit.services/lfk/frontend/commit/8e6786e72227b3f07cc805f0957d5b7fd123ec13)
|
||||||
|
- chore(deps): Bumped scanclientjs [`6ad4056`](https://git.odit.services/lfk/frontend/commit/6ad40564e3e342046f6ee19fab9e455ec3bbff9b)
|
||||||
|
|
||||||
|
#### [1.4.9](https://git.odit.services/lfk/frontend/compare/1.4.8...1.4.9)
|
||||||
|
|
||||||
|
> 9 May 2023
|
||||||
|
|
||||||
|
- 🚀RELEASE v1.4.9 [`776973b`](https://git.odit.services/lfk/frontend/commit/776973bfe9b34c26a1c80d5e458cc2644dd9036b)
|
||||||
|
- Changed the in table replacement method [`d9a47f8`](https://git.odit.services/lfk/frontend/commit/d9a47f882c1c6bcf98ef85d50d70c010d54b326e)
|
||||||
|
- Fixed empty return [`6025e43`](https://git.odit.services/lfk/frontend/commit/6025e43baa8516657a60a1de9a82c2189221c6ac)
|
||||||
|
|
||||||
|
#### [1.4.8](https://git.odit.services/lfk/frontend/compare/1.4.7...1.4.8)
|
||||||
|
|
||||||
|
> 9 May 2023
|
||||||
|
|
||||||
|
- Switched donor loading to non-paginated [`59fe2df`](https://git.odit.services/lfk/frontend/commit/59fe2dfabb224863876c4db31a965c34a51a9369)
|
||||||
|
- 🚀RELEASE v1.4.8 [`4235758`](https://git.odit.services/lfk/frontend/commit/4235758a6d1499715287d6ab193cc87c68d5742e)
|
||||||
|
|
||||||
|
#### [1.4.7](https://git.odit.services/lfk/frontend/compare/1.4.6...1.4.7)
|
||||||
|
|
||||||
|
> 4 May 2023
|
||||||
|
|
||||||
|
- Paginated modal data loading [`a8a7711`](https://git.odit.services/lfk/frontend/commit/a8a771114df6eb57d5b1d5497a5be49e619d4102)
|
||||||
|
- Moved loading to onmount [`4e0a2c8`](https://git.odit.services/lfk/frontend/commit/4e0a2c83015bde5e360c5fb2c0babbeaa03dc2b5)
|
||||||
|
- 🚀RELEASE v1.4.7 [`6364536`](https://git.odit.services/lfk/frontend/commit/6364536dcd840c71f7cb6afb31bbc4f160ac4f73)
|
||||||
|
|
||||||
|
#### [1.4.6](https://git.odit.services/lfk/frontend/compare/1.4.5...1.4.6)
|
||||||
|
|
||||||
|
> 4 May 2023
|
||||||
|
|
||||||
|
- 🚀RELEASE v1.4.6 [`b6fed92`](https://git.odit.services/lfk/frontend/commit/b6fed92a176af1c975484d9146ee5634e0031401)
|
||||||
|
- fix(donor/details): don't load donations [`a2ff5b8`](https://git.odit.services/lfk/frontend/commit/a2ff5b8a142ce4e6b8876f64935f9787ec44a51e)
|
||||||
|
- fix(donor/detail): Set email to null to avoid vaidation errors [`97b57ae`](https://git.odit.services/lfk/frontend/commit/97b57aeb0cc9058542a36dea9c8b2852169c250f)
|
||||||
|
- fix(donor/detail): Set phone to null to avoid vaidation errors [`e25ed1f`](https://git.odit.services/lfk/frontend/commit/e25ed1fff9b200605d5d2b78238b774ec7289aaa)
|
||||||
|
|
||||||
#### [1.4.5](https://git.odit.services/lfk/frontend/compare/1.4.4...1.4.5)
|
#### [1.4.5](https://git.odit.services/lfk/frontend/compare/1.4.4...1.4.5)
|
||||||
|
|
||||||
|
> 4 May 2023
|
||||||
|
|
||||||
- Revert "revert: buggy pagination" [`dacb2f8`](https://git.odit.services/lfk/frontend/commit/dacb2f8ace373f6594fc64af133971af053f00c0)
|
- Revert "revert: buggy pagination" [`dacb2f8`](https://git.odit.services/lfk/frontend/commit/dacb2f8ace373f6594fc64af133971af053f00c0)
|
||||||
- fix: Removed dynamic pagesize adjustments [`803d64c`](https://git.odit.services/lfk/frontend/commit/803d64c78caa570d31d6055e70e2d2af6834f04b)
|
- fix: Removed dynamic pagesize adjustments [`803d64c`](https://git.odit.services/lfk/frontend/commit/803d64c78caa570d31d6055e70e2d2af6834f04b)
|
||||||
|
- 🚀RELEASE v1.4.5 [`0284f18`](https://git.odit.services/lfk/frontend/commit/0284f18beb8b24d4d4d071eca13bc5868666232c)
|
||||||
|
|
||||||
#### [1.4.4](https://git.odit.services/lfk/frontend/compare/1.4.3...1.4.4)
|
#### [1.4.4](https://git.odit.services/lfk/frontend/compare/1.4.3...1.4.4)
|
||||||
|
|
||||||
|
|||||||
+4
-4
@@ -1,9 +1,9 @@
|
|||||||
FROM registry.odit.services/hub/library/node:20.0.0-alpine3.17 as build
|
FROM registry.odit.services/hub/library/node:23.10.0-alpine3.21 AS build
|
||||||
ARG NPM_REGISTRY_URL=https://registry.npmjs.org
|
ARG NPM_REGISTRY_URL=https://registry.npmjs.org
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
|
|
||||||
COPY package.json pnpm-lock.yaml vite.config.js tailwind.config.js postcss.config.cjs index.html ./
|
COPY package.json pnpm-lock.yaml vite.config.js tailwind.config.cjs postcss.config.cjs index.html ./
|
||||||
RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@8
|
RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@9
|
||||||
RUN mkdir /pnpm && pnpm config set store-dir /pnpm && pnpm i
|
RUN mkdir /pnpm && pnpm config set store-dir /pnpm && pnpm i
|
||||||
|
|
||||||
COPY src ./src
|
COPY src ./src
|
||||||
@@ -11,6 +11,6 @@ COPY public ./public
|
|||||||
RUN pnpm build
|
RUN pnpm build
|
||||||
|
|
||||||
# final image
|
# final image
|
||||||
FROM registry.odit.services/library/nginx-brotli:3.15 as final
|
FROM registry.odit.services/library/nginx-brotli:3.15 AS final
|
||||||
COPY --from=build /app/dist /usr/share/nginx/html
|
COPY --from=build /app/dist /usr/share/nginx/html
|
||||||
COPY ./nginx.conf /etc/nginx/nginx.conf
|
COPY ./nginx.conf /etc/nginx/nginx.conf
|
||||||
+2
-2
@@ -1,4 +1,4 @@
|
|||||||
<!DOCTYPE html>
|
<!doctype html>
|
||||||
<html lang="en">
|
<html lang="en">
|
||||||
<head>
|
<head>
|
||||||
<meta charset="utf-8" />
|
<meta charset="utf-8" />
|
||||||
@@ -13,7 +13,7 @@
|
|||||||
|
|
||||||
<body>
|
<body>
|
||||||
<span style="display: none; visibility: hidden" id="buildinfo"
|
<span style="display: none; visibility: hidden" id="buildinfo"
|
||||||
>RELEASE_INFO-1.4.5-RELEASE_INFO</span
|
>RELEASE_INFO-1.8.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>
|
||||||
|
|||||||
+17
-16
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@odit/lfk-frontend",
|
"name": "@odit/lfk-frontend",
|
||||||
"version": "1.4.5",
|
"version": "1.8.2",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"i18n-order": "node order.js",
|
"i18n-order": "node order.js",
|
||||||
@@ -12,16 +12,16 @@
|
|||||||
},
|
},
|
||||||
"license": "CC-BY-NC-SA-4.0",
|
"license": "CC-BY-NC-SA-4.0",
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@odit/license-exporter": "0.0.12",
|
"@odit/license-exporter": "0.2.0",
|
||||||
"@sveltejs/vite-plugin-svelte": "2.1.1",
|
"@sveltejs/vite-plugin-svelte": "2.1.1",
|
||||||
"auto-changelog": "2.4.0",
|
"auto-changelog": "2.5.0",
|
||||||
"autoprefixer": "10.4.14",
|
"autoprefixer": "10.4.21",
|
||||||
"postcss": "8.4.23",
|
"postcss": "8.5.3",
|
||||||
"prettier": "^2.8.8",
|
"prettier": "3.5.3",
|
||||||
"prettier-plugin-svelte": "^2.10.0",
|
"prettier-plugin-svelte": "3.3.3",
|
||||||
"release-it": "15.10.1",
|
"release-it": "17.10.0",
|
||||||
"svelte-select": "3.17.0",
|
"svelte-select": "3.17.0",
|
||||||
"tailwindcss": "3.3.2",
|
"tailwindcss": "3.4.15",
|
||||||
"vite": "4.3.3"
|
"vite": "4.3.3"
|
||||||
},
|
},
|
||||||
"release-it": {
|
"release-it": {
|
||||||
@@ -42,19 +42,20 @@
|
|||||||
}
|
}
|
||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@odit/lfk-client-js": "1.1.1",
|
"@fontsource/athiti": "^5.2.5",
|
||||||
"@paralleldrive/cuid2": "^2.2.0",
|
"@odit/lfk-client-js": "1.1.3",
|
||||||
"@tanstack/svelte-table": "^8.8.6",
|
"@paralleldrive/cuid2": "2.2.2",
|
||||||
"bwip-js": "^3.4.0",
|
"@tanstack/svelte-table": "8.9.1",
|
||||||
"check-password-strength": "2.0.7",
|
"bwip-js": "3.4.0",
|
||||||
|
"check-password-strength": "2.0.10",
|
||||||
"csvtojson": "2.0.10",
|
"csvtojson": "2.0.10",
|
||||||
"localforage": "1.10.0",
|
"localforage": "1.10.0",
|
||||||
"marked": "4.3.0",
|
"marked": "4.3.0",
|
||||||
"svelte": "3.58.0",
|
"svelte": "3.58.0",
|
||||||
"svelte-french-toast": "1.0.4-beta.0",
|
"svelte-french-toast": "1.2.0",
|
||||||
"svelte-i18n": "3.6.0",
|
"svelte-i18n": "3.6.0",
|
||||||
"tinro": "0.6.12",
|
"tinro": "0.6.12",
|
||||||
"validator": "13.9.0",
|
"validator": "13.15.0",
|
||||||
"xlsx": "0.18.5"
|
"xlsx": "0.18.5"
|
||||||
},
|
},
|
||||||
"volta": {
|
"volta": {
|
||||||
|
|||||||
Generated
+4566
-3415
File diff suppressed because it is too large.
Load diff
@@ -1,5 +1,6 @@
|
|||||||
const config = {
|
const config = {
|
||||||
baseurl: "http://localhost:4010",
|
baseurl: "http://localhost:4010",
|
||||||
|
baseurl_selfservice: "http://localhost:5174",
|
||||||
baseurl_documentserver: "http://localhost:4010/documents",
|
baseurl_documentserver: "http://localhost:4010/documents",
|
||||||
documentserver_key:
|
documentserver_key:
|
||||||
"NqZSYTy5AFQ7MppbLW5moqpTk7u7YrNUHKYhKYuThnnya2WpCOIU694hIZT1FzYe",
|
"NqZSYTy5AFQ7MppbLW5moqpTk7u7YrNUHKYhKYuThnnya2WpCOIU694hIZT1FzYe",
|
||||||
@@ -8,3 +9,4 @@ const config = {
|
|||||||
default_password: "demo",
|
default_password: "demo",
|
||||||
prefersHashRouting: true,
|
prefersHashRouting: true,
|
||||||
};
|
};
|
||||||
|
window.config = config;
|
||||||
+265
-1
@@ -1 +1,265 @@
|
|||||||
[{"author":"ODIT.Services","repo":{"type":"git","url":"git+https://git.odit.services/lfk/lfk-client-js"},"description":"A lib to interact with https://git.odit.services/lfk/backend. Use this version for native JS applications.","name":"@odit/lfk-client-js","license":"CC-BY-NC-SA-4.0","version":"1.1.1","licensetext":"Creative Commons Attribution-NonCommercial-ShareAlike 4.0 International Creative\r\nCommons Corporation (\"Creative Commons\") is not a law firm and does not provide\r\nlegal services or legal advice. Distribution of Creative Commons public licenses\r\ndoes not create a lawyer-client or other relationship. Creative Commons makes\r\nits licenses and related information available on an \"as-is\" basis. Creative\r\nCommons gives no warranties regarding its licenses, any material licensed\r\nunder their terms and conditions, or any related information. Creative Commons\r\ndisclaims all liability for damages resulting from their use to the fullest\r\nextent possible.\r\n\r\nUsing Creative Commons Public Licenses\r\n\r\nCreative Commons public licenses provide a standard set of terms and conditions\r\nthat creators and other rights holders may use to share original works of\r\nauthorship and other material subject to copyright and certain other rights\r\nspecified in the public license below. The following considerations are for\r\ninformational purposes only, are not exhaustive, and do not form part of our\r\nlicenses.\r\n\r\nConsiderations for licensors: Our public licenses are intended for use by\r\nthose authorized to give the public permission to use material in ways otherwise\r\nrestricted by copyright and certain other rights. Our licenses are irrevocable.\r\nLicensors should read and understand the terms and conditions of the license\r\nthey choose before applying it. Licensors should also secure all rights necessary\r\nbefore applying our licenses so that the public can reuse the material as\r\nexpected. Licensors should clearly mark any material not subject to the license.\r\nThis includes other CC-licensed material, or material used under an exception\r\nor limitation to copyright. More considerations for licensors : wiki.creativecommons.org/Considerations_for_licensors\r\n\r\nConsiderations for the public: By using one of our public licenses, a licensor\r\ngrants the public permission to use the licensed material under specified\r\nterms and conditions. If the licensor's permission is not necessary for any\r\nreason–for example, because of any applicable exception or limitation to copyright–then\r\nthat use is not regulated by the license. Our licenses grant only permissions\r\nunder copyright and certain other rights that a licensor has authority to\r\ngrant. Use of the licensed material may still be restricted for other reasons,\r\nincluding because others have copyright or other rights in the material. A\r\nlicensor may make special requests, such as asking that all changes be marked\r\nor described. Although not required by our licenses, you are encouraged to\r\nrespect those requests where reasonable. More considerations for the public\r\n: wiki.creativecommons.org/Considerations_for_licensees\r\n\r\nCreative Commons Attribution-NonCommercial-ShareAlike 4.0 International Public\r\nLicense\r\n\r\nBy exercising the Licensed Rights (defined below), You accept and agree to\r\nbe bound by the terms and conditions of this Creative Commons Attribution-NonCommercial-ShareAlike\r\n4.0 International Public License (\"Public License\"). To the extent this Public\r\nLicense may be interpreted as a contract, You are granted the Licensed Rights\r\nin consideration of Your acceptance of these terms and conditions, and the\r\nLicensor grants You such rights in consideration of benefits the Licensor\r\nreceives from making the Licensed Material available under these terms and\r\nconditions.\r\n\r\nSection 1 – Definitions.\r\n\r\na. Adapted Material means material subject to Copyright and Similar Rights\r\nthat is derived from or based upon the Licensed Material and in which the\r\nLicensed Material is translated, altered, arranged, transformed, or otherwise\r\nmodified in a manner requiring permission under the Copyright and Similar\r\nRights held by the Licensor. For purposes of this Public License, where the\r\nLicensed Material is a musical work, performance, or sound recording, Adapted\r\nMaterial is always produced where the Licensed Material is synched in timed\r\nrelation with a moving image.\r\n\r\nb. Adapter's License means the license You apply to Your Copyright and Similar\r\nRights in Your contributions to Adapted Material in accordance with the terms\r\nand conditions of this Public License.\r\n\r\nc. BY-NC-SA Compatible License means a license listed at creativecommons.org/compatiblelicenses,\r\napproved by Creative Commons as essentially the equivalent of this Public\r\nLicense.\r\n\r\nd. Copyright and Similar Rights means copyright and/or similar rights closely\r\nrelated to copLine truncated
|
[
|
||||||
|
{
|
||||||
|
"author": "ODIT.Services",
|
||||||
|
"repo": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "git+https://git.odit.services/lfk/lfk-client-js"
|
||||||
|
},
|
||||||
|
"description": "A lib to interact with https://git.odit.services/lfk/backend. Use this version for native JS applications.",
|
||||||
|
"name": "@odit/lfk-client-js",
|
||||||
|
"license": "CC-BY-NC-SA-4.0",
|
||||||
|
"version": "1.1.2",
|
||||||
|
"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 copyright including, without limitation, performance, broadcast,\r\nsound recording, and Sui Generis Database Rights, without regard to how the\r\nrights are labeled or categorized. For purposes of this Public License, the\r\nrights specified in Section 2(b)(1)-(2) are not Copyright and Similar RightLine 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": "Tanner Linsley",
|
||||||
|
"repo": { "type": "git", "url": "https://github.com/tanstack/table" },
|
||||||
|
"description": "Headless UI for building powerful tables & datagrids for Svelte.",
|
||||||
|
"name": "@tanstack/svelte-table",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "8.9.1",
|
||||||
|
"licensetext": ""
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Mark Warren <mwarren@metafloor.com>",
|
||||||
|
"repo": { "type": "git", "url": "https://github.com/metafloor/bwip-js" },
|
||||||
|
"description": "JavaScript barcode generator supporting over 100 types and standards.",
|
||||||
|
"name": "bwip-js",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "3.4.0",
|
||||||
|
"licensetext": "bwip-js : Barcode Writer in Pure JavaScript\n\nCopyright (c) 2011-2019 Mark Warren\n\nThe MIT License\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\nall copies 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\nTHE SOFTWARE.\n\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "deanilvincent",
|
||||||
|
"repo": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/deanilvincent/check-password-strength"
|
||||||
|
},
|
||||||
|
"description": "A NPM Password strength checker based from Javascript RegExp. Check passphrase if it's \"Too weak\", \"Weak\", \"Medium\" or \"Strong\"",
|
||||||
|
"name": "check-password-strength",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "2.0.7",
|
||||||
|
"licensetext": "MIT License\r\n\r\nCopyright (c) 2020 Mark Deanil Vicente\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in all\r\ncopies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r\nSOFTWARE.\r\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Keyang Xiang <keyang.xiang@gmail.com>",
|
||||||
|
"repo": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/Keyang/node-csvtojson"
|
||||||
|
},
|
||||||
|
"description": "A tool concentrating on converting csv data to JSON with customised parser supporting",
|
||||||
|
"name": "csvtojson",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "2.0.10",
|
||||||
|
"licensetext": "Copyright (C) 2013 Keyang Xiang\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Mozilla",
|
||||||
|
"repo": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.comlocalForage/localForage"
|
||||||
|
},
|
||||||
|
"description": "Offline storage, improved.",
|
||||||
|
"name": "localforage",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"version": "1.10.0",
|
||||||
|
"licensetext": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under thiLine truncated
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Christopher Jeffrey",
|
||||||
|
"repo": { "url": "git://github.com/markedjs/marked" },
|
||||||
|
"description": "A markdown parser built for speed",
|
||||||
|
"name": "marked",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "4.3.0",
|
||||||
|
"licensetext": "# License information\n\n## Contribution License Agreement\n\nIf you contribute code to this project, you are implicitly allowing your code\nto be distributed under the MIT license. You are also implicitly verifying that\nall code is your original work. `</legalese>`\n\n## Marked\n\nCopyright (c) 2018+, MarkedJS (https://github.com/markedjs/)\nCopyright (c) 2011-2018, Christopher Jeffrey (https://github.com/chjj/)\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\nall copies 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\nTHE SOFTWARE.\n\n## Markdown\n\nCopyright © 2004, John Gruber\nhttp://daringfireball.net/\nAll rights reserved.\n\nRedistribution and use in source and binary forms, with or without modification, are permitted provided that the following conditions are met:\n\n* Redistributions of source code must retain the above copyright notice, this list of conditions and the following disclaimer.\n* Redistributions in binary form must reproduce the above copyright notice, this list of conditions and the following disclaimer in the documentation and/or other materials provided with the distribution.\n* Neither the name “Markdown” nor the names of its contributors may be used to endorse or promote products derived from this software without specific prior written permission.\n\nThis software is provided by the copyright holders and contributors “as is” and any express or implied warranties, including, but not limited to, the implied warranties of merchantability and fitness for a particular purpose are disclaimed. In no event shall the copyright owner or contributors be liable for any direct, indirect, incidental, special, exemplary, or consequential damages (including, but not limited to, procurement of substitute goods or services; loss of use, data, or profits; or business interruption) however caused and on any theory of liability, whether in contract, strict liability, or tort (including negligence or otherwise) arising in any way out of the use of this software, even if advised of the possibility of such damage.\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Rich Harris",
|
||||||
|
"repo": { "type": "git", "url": "https://github.com/sveltejs/svelte" },
|
||||||
|
"description": "Cybernetically enhanced web apps",
|
||||||
|
"name": "svelte",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "3.58.0",
|
||||||
|
"licensetext": "Copyright (c) 2016-23 [these people](https://github.com/sveltejs/svelte/graphs/contributors)\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Kabir Goel",
|
||||||
|
"repo": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/kbrgl/svelte-french-toast"
|
||||||
|
},
|
||||||
|
"description": "Buttery smooth Svelte toasts. Lightweight, customizable, and beautiful by default.",
|
||||||
|
"name": "svelte-french-toast",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "1.0.4-beta.0",
|
||||||
|
"licensetext": "MIT License\n\nCopyright (c) 2022 Kabir Goel\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": "Christian Kaisermann <christian@kaisermann.me>",
|
||||||
|
"repo": { "url": "https://github.com/kaisermann/svelte-i18n" },
|
||||||
|
"description": "Internationalization library for Svelte",
|
||||||
|
"name": "svelte-i18n",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "3.6.0",
|
||||||
|
"licensetext": "Copyright 2017 Christian Kaisermann <christian@kaisermann.me>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Alexey Schebelev",
|
||||||
|
"repo": { "type": "git", "url": "https://github.com/AlexxNB/tinro" },
|
||||||
|
"description": "tinro is a tiny declarative router for Svelte",
|
||||||
|
"name": "tinro",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "0.6.12",
|
||||||
|
"licensetext": "MIT License\n\nCopyright (c) 2020 Alexey Schebelev\n\nPermission is hereby granted, free of charge, to any person obtaining a copy\nof this software and associated documentation files (the \"Software\"), to deal\nin the Software without restriction, including without limitation the rights\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\ncopies of the Software, and to permit persons to whom the Software is\nfurnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all\ncopies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\nSOFTWARE.\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Chris O'Hara <cohara87@gmail.com>",
|
||||||
|
"repo": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/validatorjs/validator.js"
|
||||||
|
},
|
||||||
|
"description": "String validation and sanitization",
|
||||||
|
"name": "validator",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "13.9.0",
|
||||||
|
"licensetext": "Copyright (c) 2018 Chris O'Hara <cohara87@gmail.com>\n\nPermission is hereby granted, free of charge, to any person obtaining\na copy of this software and associated documentation files (the\n\"Software\"), to deal in the Software without restriction, including\nwithout limitation the rights to use, copy, modify, merge, publish,\ndistribute, sublicense, and/or sell copies of the Software, and to\npermit persons to whom the Software is furnished to do so, subject to\nthe following conditions:\n\nThe above copyright notice and this permission notice shall be\nincluded in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\nEXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\nMERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\nNONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\nLIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\nOF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\nWITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "sheetjs",
|
||||||
|
"repo": { "type": "git", "url": "https://github.comSheetJS/sheetjs" },
|
||||||
|
"description": "SheetJS Spreadsheet data parser and writer",
|
||||||
|
"name": "xlsx",
|
||||||
|
"license": "Apache-2.0",
|
||||||
|
"version": "0.18.5",
|
||||||
|
"licensetext": " Apache License\n Version 2.0, January 2004\n http://www.apache.org/licenses/\n\n TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n\n 1. Definitions.\n\n \"License\" shall mean the terms and conditions for use, reproduction,\n and distribution as defined by Sections 1 through 9 of this document.\n\n \"Licensor\" shall mean the copyright owner or entity authorized by\n the copyright owner that is granting the License.\n\n \"Legal Entity\" shall mean the union of the acting entity and all\n other entities that control, are controlled by, or are under common\n control with that entity. For the purposes of this definition,\n \"control\" means (i) the power, direct or indirect, to cause the\n direction or management of such entity, whether by contract or\n otherwise, or (ii) ownership of fifty percent (50%) or more of the\n outstanding shares, or (iii) beneficial ownership of such entity.\n\n \"You\" (or \"Your\") shall mean an individual or Legal Entity\n exercising permissions granted by this License.\n\n \"Source\" form shall mean the preferred form for making modifications,\n including but not limited to software source code, documentation\n source, and configuration files.\n\n \"Object\" form shall mean any form resulting from mechanical\n transformation or translation of a Source form, including but\n not limited to compiled object code, generated documentation,\n and conversions to other media types.\n\n \"Work\" shall mean the work of authorship, whether in Source or\n Object form, made available under the License, as indicated by a\n copyright notice that is included in or attached to the work\n (an example is provided in the Appendix below).\n\n \"Derivative Works\" shall mean any work, whether in Source or Object\n form, that is based on (or derived from) the Work and for which the\n editorial revisions, annotations, elaborations, or other modifications\n represent, as a whole, an original work of authorship. For the purposes\n of this License, Derivative Works shall not include works that remain\n separable from, or merely link (or bind by name) to the interfaces of,\n the Work and Derivative Works thereof.\n\n \"Contribution\" shall mean any work of authorship, including\n the original version of the Work and any modifications or additions\n to that Work or Derivative Works thereof, that is intentionally\n submitted to Licensor for inclusion in the Work by the copyright owner\n or by an individual or Legal Entity authorized to submit on behalf of\n the copyright owner. For the purposes of this definition, \"submitted\"\n means any form of electronic, verbal, or written communication sent\n to the Licensor or its representatives, including but not limited to\n communication on electronic mailing lists, source code control systems,\n and issue tracking systems that are managed by, or on behalf of, the\n Licensor for the purpose of discussing and improving the Work, but\n excluding communication that is conspicuously marked or otherwise\n designated in writing by the copyright owner as \"Not a Contribution.\"\n\n \"Contributor\" shall mean Licensor and any individual or Legal Entity\n on behalf of whom a Contribution has been received by Licensor and\n subsequently incorporated within the Work.\n\n 2. Grant of Copyright License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n copyright license to reproduce, prepare Derivative Works of,\n publicly display, publicly perform, sublicense, and distribute the\n Work and such Derivative Works in Source or Object form.\n\n 3. Grant of Patent License. Subject to the terms and conditions of\n this License, each Contributor hereby grants to You a perpetual,\n worldwide, non-exclusive, no-charge, royalty-free, irrevocable\n (except as stated in this section) patent license to make, have made,\n use, offer to sell, sell, import, and otherwise transfer the Work,\n where such license applies only to those patent claims licensable\n by such Contributor that are necessarily infringed by their\n Contribution(s) alone or by combination of their Contribution(s)\n with the Work to which such Contribution(s) was submitted. If You\n institute patent litigation against any entity (including a\n cross-claim or counterclaim in a lawsuit) alleging that the Work\n or a Contribution incorporated within the Work constitutes direct\n or contributory patent infringement, then any patent licenses\n granted to You under thiLine truncated
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "ODIT.Services",
|
||||||
|
"repo": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://git.odit.services/odit/license-exporter"
|
||||||
|
},
|
||||||
|
"description": "A simple license crawler for crediting open source work",
|
||||||
|
"name": "@odit/license-exporter",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "0.2.0",
|
||||||
|
"licensetext": "MIT License Copyright (c) 2020-2022 ODIT.Services (info@odit.services)\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is furnished\r\nto do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice (including the next\r\nparagraph) shall be included in all copies or substantial portions of the\r\nSoftware.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS\r\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS\r\nOR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,\r\nWHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF\r\nOR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\r\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "dominikg",
|
||||||
|
"repo": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/sveltejs/vite-plugin-svelte",
|
||||||
|
"directory": "packages/vite-plugin-svelte"
|
||||||
|
},
|
||||||
|
"description": "",
|
||||||
|
"name": "@sveltejs/vite-plugin-svelte",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "2.1.1",
|
||||||
|
"licensetext": "MIT License\n\nCopyright (c) 2021 [these people](https://github.com/sveltejs/vite-plugin-svelte/graphs/contributors)\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": "Pete Cook <pete@cookpete.com> (https://github.com/cookpete)",
|
||||||
|
"repo": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/CookPete/auto-changelog"
|
||||||
|
},
|
||||||
|
"description": "Command line tool for generating a changelog from git tags and commit history",
|
||||||
|
"name": "auto-changelog",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "2.4.0",
|
||||||
|
"licensetext": "The MIT License\n\nCopyright (c) 2017 Pete Cook https://cookpete.com\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\nall copies 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\nTHE SOFTWARE.\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Andrey Sitnik <andrey@sitnik.ru>",
|
||||||
|
"repo": { "url": "postcss/autoprefixer" },
|
||||||
|
"description": "Parse CSS and add vendor prefixes to CSS rules using values from the Can I Use website",
|
||||||
|
"name": "autoprefixer",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "10.4.14",
|
||||||
|
"licensetext": "The MIT License (MIT)\n\nCopyright 2013 Andrey Sitnik <andrey@sitnik.ru>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject 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, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Andrey Sitnik <andrey@sitnik.ru>",
|
||||||
|
"repo": { "url": "postcss/postcss" },
|
||||||
|
"description": "Tool for transforming styles with JS plugins",
|
||||||
|
"name": "postcss",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "8.4.23",
|
||||||
|
"licensetext": "The MIT License (MIT)\n\nCopyright 2013 Andrey Sitnik <andrey@sitnik.ru>\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of\nthis software and associated documentation files (the \"Software\"), to deal in\nthe Software without restriction, including without limitation the rights to\nuse, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of\nthe Software, and to permit persons to whom the Software is furnished to do so,\nsubject 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, FITNESS\nFOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR\nCOPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER\nIN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN\nCONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "James Long",
|
||||||
|
"repo": { "url": "prettier/prettier" },
|
||||||
|
"description": "Prettier is an opinionated code formatter",
|
||||||
|
"name": "prettier",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "2.8.8",
|
||||||
|
"licensetext": "# Prettier license\n\nPrettier is released under the MIT license:\n\nCopyright © James Long and contributors\n\nPermission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the \"Software\"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:\n\nThe above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.\n\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n## Licenses of bundled dependencies\n\nThe published Prettier artifact additionally contains code with the following licenses:\nMIT, ISC, BSD-2-Clause, BSD-3-Clause, Apache-2.0, 0BSD\n\n## Bundled dependencies\n\n### @angular/compiler@v12.2.16\n\nLicense: MIT\nBy: angular\nRepository: <https://github.com/angular/angular.git>\n\n----------------------------------------\n\n### @babel/code-frame@v7.18.6\n\nLicense: MIT\nBy: The Babel Team\nRepository: <https://github.com/babel/babel.git>\n\n> MIT License\n>\n> Copyright (c) 2014-present Sebastian McKenzie and other contributors\n>\n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> \"Software\"), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n>\n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n----------------------------------------\n\n### @babel/helper-validator-identifier@v7.19.1\n\nLicense: MIT\nBy: The Babel Team\nRepository: <https://github.com/babel/babel.git>\n\n> MIT License\n>\n> Copyright (c) 2014-present Sebastian McKenzie and other contributors\n>\n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> \"Software\"), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n>\n> The above copyright notice and this permission notice shall be\n> included in all copies or substantial portions of the Software.\n>\n> THE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND,\n> EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF\n> MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND\n> NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE\n> LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION\n> OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION\n> WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.\n\n----------------------------------------\n\n### @babel/highlight@v7.18.6\n\nLicense: MIT\nBy: The Babel Team\nRepository: <https://github.com/babel/babel.git>\n\n> MIT License\n>\n> Copyright (c) 2014-present Sebastian McKenzie and other contributors\n>\n> Permission is hereby granted, free of charge, to any person obtaining\n> a copy of this software and associated documentation files (the\n> \"Software\"), to deal in the Software without restriction, including\n> without limitation the rights to use, copy, modify, merge, publish,\n> distribute, sublicense, and/or sell copies of the Software, and to\n> permit persons to whom the Software is furnished to do so, subject to\n> the following conditions:\n>\n> The above copyright notice and this permission notice shall be\n> included in all copies or subLine truncated
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "James Birtles <jameshbirtles@gmail.com>",
|
||||||
|
"repo": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/sveltejs/prettier-plugin-svelte"
|
||||||
|
},
|
||||||
|
"description": "Svelte plugin for prettier",
|
||||||
|
"name": "prettier-plugin-svelte",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "2.10.0",
|
||||||
|
"licensetext": "MIT License\r\n\r\nCopyright (c) 2019 [Contributors](https://github.com/sveltejs/prettier-plugin-svelte/graphs/contributors)\r\n\r\nPermission is hereby granted, free of charge, to any person obtaining a copy\r\nof this software and associated documentation files (the \"Software\"), to deal\r\nin the Software without restriction, including without limitation the rights\r\nto use, copy, modify, merge, publish, distribute, sublicense, and/or sell\r\ncopies of the Software, and to permit persons to whom the Software is\r\nfurnished to do so, subject to the following conditions:\r\n\r\nThe above copyright notice and this permission notice shall be included in all\r\ncopies or substantial portions of the Software.\r\n\r\nTHE SOFTWARE IS PROVIDED \"AS IS\", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR\r\nIMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,\r\nFITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE\r\nAUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER\r\nLIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,\r\nOUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE\r\nSOFTWARE.\r\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "Lars Kappert",
|
||||||
|
"repo": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/release-it/release-it"
|
||||||
|
},
|
||||||
|
"description": "Generic CLI tool to automate versioning and package publishing-related tasks.",
|
||||||
|
"name": "release-it",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "15.10.3",
|
||||||
|
"licensetext": "MIT License\n\nCopyright (c) 2018 Lars Kappert\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": "rob-balfre",
|
||||||
|
"repo": { "url": "https://rob-balfre@github.com/rob-balfre/svelte-select" },
|
||||||
|
"description": "A <Select> component for Svelte apps",
|
||||||
|
"name": "svelte-select",
|
||||||
|
"license": "LIL",
|
||||||
|
"version": "3.17.0",
|
||||||
|
"licensetext": "Copyright (c) 2019 Robert Balfre\n\nPermission is hereby granted by the authors of this software, to any person, to use the software for any purpose, free of charge, including the rights to run, read, copy, change, distribute and sell it, and including usage rights to any patents the authors may hold on it, subject to the following conditions:\n\nThis license, or a link to its text, must be included with all copies of the software and any derivative works.\n\nAny modification to the software submitted to the authors may be incorporated into the software under the terms of this license.\n\nThe software is provided \"as is\", without warranty of any kind, including but not limited to the warranties of title, fitness, merchantability and non-infringement. The authors have no obligation to provide support or updates for the software, and may not be held liable for any damages, claims or other liability arising from its use.\n"
|
||||||
|
},
|
||||||
|
{
|
||||||
|
"author": "?",
|
||||||
|
"repo": { "url": "https://github.com/tailwindlabs/tailwindcss" },
|
||||||
|
"description": "A utility-first CSS framework for rapidly building custom user interfaces.",
|
||||||
|
"name": "tailwindcss",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "3.3.2",
|
||||||
|
"licensetext": "MIT License\n\nCopyright (c) Tailwind Labs, Inc.\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": "Evan You",
|
||||||
|
"repo": {
|
||||||
|
"type": "git",
|
||||||
|
"url": "https://github.com/vitejs/vite",
|
||||||
|
"directory": "packages/vite"
|
||||||
|
},
|
||||||
|
"description": "Native-ESM powered web dev build tool",
|
||||||
|
"name": "vite",
|
||||||
|
"license": "MIT",
|
||||||
|
"version": "4.3.3",
|
||||||
|
"licensetext": "# Vite core license\nVite is released under the MIT license:\n\nMIT License\n\nCopyright (c) 2019-present, Yuxi (Evan) You and Vite contributors\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\n# Licenses of bundled dependencies\nThe published Vite artifact additionally contains code with the following licenses:\nApache-2.0, BSD-2-Clause, CC0-1.0, ISC, MIT\n\n# Bundled dependencies:\n## @ampproject/remapping\nLicense: Apache-2.0\nBy: Justin Ridgewell\nRepository: git+https://github.com/ampproject/remapping.git\n\n> Apache License\n> Version 2.0, January 2004\n> http://www.apache.org/licenses/\n> \n> TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION\n> \n> 1. Definitions.\n> \n> \"License\" shall mean the terms and conditions for use, reproduction,\n> and distribution as defined by Sections 1 through 9 of this document.\n> \n> \"Licensor\" shall mean the copyright owner or entity authorized by\n> the copyright owner that is granting the License.\n> \n> \"Legal Entity\" shall mean the union of the acting entity and all\n> other entities that control, are controlled by, or are under common\n> control with that entity. For the purposes of this definition,\n> \"control\" means (i) the power, direct or indirect, to cause the\n> direction or management of such entity, whether by contract or\n> otherwise, or (ii) ownership of fifty percent (50%) or more of the\n> outstanding shares, or (iii) beneficial ownership of such entity.\n> \n> \"You\" (or \"Your\") shall mean an individual or Legal Entity\n> exercising permissions granted by this License.\n> \n> \"Source\" form shall mean the preferred form for making modifications,\n> including but not limited to software source code, documentation\n> source, and configuration files.\n> \n> \"Object\" form shall mean any form resulting from mechanical\n> transformation or translation of a Source form, including but\n> not limited to compiled object code, generated documentation,\n> and conversions to other media types.\n> \n> \"Work\" shall mean the work of authorship, whether in Source or\n> Object form, made available under the License, as indicated by a\n> copyright notice that is included in or attached to the work\n> (an example is provided in the Appendix below).\n> \n> \"Derivative Works\" shall mean any work, whether in Source or Object\n> form, that is based on (or derived from) the Work and for which the\n> editorial revisions, annotations, elaborations, or other modifications\n> represent, as a whole, an original work of authorship. For the purposes\n> of this License, Derivative Works shall not include works that remain\n> separable from, or merely link (or bind by name) to the interfaces of,\n> the Work and Derivative Works thereof.\n> \n> \"Contribution\" shall mean any work of authorship, including\n> the original version of the Work and any modifications or additions\n> to that Work or Derivative Works thereof, that is intentionally\n> submitted to Licensor for inclusion in the Work by the copyright owner\n> or by an individual or Legal Entity authorized to submit on behalf of\n> the copyright owner. For the purposes of this definition, \"submitted\"\n> means any form of electronic, verbal, or written communication sent\n> to the Licensor or its representatives, including but not limited to\n> communication on electronic mailing lists, source code control systems,\n> and issue tracking systems that are managed by, or on behalf of, the\n> Licensor for the purpose of discussing and improving the Work, but\n> excluding communication that is conspicuously marked or otherwise\n> designated in writing by the copyright owner as \"Not a CLine truncated
|
||||||
|
}
|
||||||
|
]
|
||||||
@@ -20,7 +20,6 @@
|
|||||||
OpenAPI.TOKEN = value.access_token;
|
OpenAPI.TOKEN = value.access_token;
|
||||||
const jwtinfo = JSON.parse(atob(OpenAPI.TOKEN.split(".")[1]));
|
const jwtinfo = JSON.parse(atob(OpenAPI.TOKEN.split(".")[1]));
|
||||||
store.login(value, jwtinfo);
|
store.login(value, jwtinfo);
|
||||||
toast($_("welcome_wavinghand"));
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
@@ -50,7 +49,6 @@
|
|||||||
store.login(result.access_token, jwtinfo);
|
store.login(result.access_token, jwtinfo);
|
||||||
location.replace("/");
|
location.replace("/");
|
||||||
toast.dismiss();
|
toast.dismiss();
|
||||||
toast($_("welcome_wavinghand"));
|
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
toast.dismiss();
|
toast.dismiss();
|
||||||
|
|||||||
@@ -5,8 +5,11 @@
|
|||||||
import { RunnerCardService } from "@odit/lfk-client-js";
|
import { RunnerCardService } from "@odit/lfk-client-js";
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
import toast from "svelte-french-toast";
|
import toast from "svelte-french-toast";
|
||||||
|
import DocumentServer from "../pdf_generation/DocumentServer";
|
||||||
export let bulk_modal_open;
|
export let bulk_modal_open;
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
const documentServer = new DocumentServer(config.baseurl_documentserver,config.documentserver_key);
|
||||||
|
|
||||||
|
|
||||||
$: card_count = 0;
|
$: card_count = 0;
|
||||||
$: is_card_count_valid = card_count > 0;
|
$: is_card_count_valid = card_count > 0;
|
||||||
@@ -60,24 +63,7 @@
|
|||||||
toast.success($_("created-blanco-cards"));
|
toast.success($_("created-blanco-cards"));
|
||||||
toast.loading($_("generating-pdf"));
|
toast.loading($_("generating-pdf"));
|
||||||
dispatch("created", { cards: result });
|
dispatch("created", { cards: result });
|
||||||
fetch(
|
documentServer.generateCards(result, "de")
|
||||||
`${config.baseurl_documentserver}/cards?&download=true&key=${config.documentserver_key}`,
|
|
||||||
{
|
|
||||||
method: "POST",
|
|
||||||
headers: {
|
|
||||||
"Content-Type": "application/json",
|
|
||||||
},
|
|
||||||
body: JSON.stringify(result),
|
|
||||||
}
|
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.dismiss();
|
|
||||||
toast.error($_("pdf-generation-failed"));
|
|
||||||
} else {
|
|
||||||
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");
|
||||||
@@ -177,7 +163,7 @@
|
|||||||
type="number"
|
type="number"
|
||||||
step="1"
|
step="1"
|
||||||
name="amount"
|
name="amount"
|
||||||
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
|
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 p-2"
|
||||||
placeholder="400"
|
placeholder="400"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -148,7 +148,7 @@
|
|||||||
>{$_("runner")}</label
|
>{$_("runner")}</label
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
itemFilter={(label, filterText, option) =>
|
itemFilter={(label, filterText, option) =>
|
||||||
filterRunners(label, filterText, option)}
|
filterRunners(label, filterText, option)}
|
||||||
items={runners}
|
items={runners}
|
||||||
|
|||||||
@@ -139,7 +139,7 @@
|
|||||||
>{$_("runner")}</label
|
>{$_("runner")}</label
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
itemFilter={(label, filterText, option) =>
|
itemFilter={(label, filterText, option) =>
|
||||||
filterRunners(label, filterText, option)}
|
filterRunners(label, filterText, option)}
|
||||||
items={runners}
|
items={runners}
|
||||||
|
|||||||
@@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
{#if enabled}
|
{#if enabled}
|
||||||
<span
|
<span
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-green-100 text-green-800"
|
||||||
>{$_("enabled")}</span
|
>{$_("enabled")}</span
|
||||||
>
|
>
|
||||||
{:else}
|
{:else}
|
||||||
<span
|
<span
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800"
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-red-100 text-red-800"
|
||||||
>{$_("disabled")}</span
|
>{$_("disabled")}</span
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -11,29 +11,29 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_("cards")}
|
{$_("cards")}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:CREATE")}
|
</h4>
|
||||||
<button
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:CREATE")}
|
||||||
on:click={() => {
|
<button
|
||||||
modal_open = true;
|
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"
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
{$_("add-card")}
|
>
|
||||||
</button>
|
{$_("add-card")}
|
||||||
<button
|
</button>
|
||||||
on:click={() => {
|
<button
|
||||||
bulk_modal_open = true;
|
on:click={() => {
|
||||||
}}
|
bulk_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"
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
{$_("create-bulk-cards")}
|
>
|
||||||
</button>
|
{$_("create-bulk-cards")}
|
||||||
{/if}
|
</button>
|
||||||
</span>
|
{/if}
|
||||||
<CardsOverview bind:current_cards bind:addCards />
|
<CardsOverview bind:current_cards bind:addCards />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
<div class="text-center items-center justify-center">
|
<div class="text-center items-center justify-center">
|
||||||
<p class="mb-16 text-lg text-gray-500">
|
<p class="mb-16 text-lg text-gray-500">
|
||||||
<img class="m-auto" style="height:15rem" src={cards_empty} alt="" />
|
<img class="m-auto mt-2" style="height:15rem" src={cards_empty} alt="" />
|
||||||
<span class="font-bold">{$_("there-are-no-cards-yet")}</span><br />
|
<span class="font-bold">{$_("there-are-no-cards-yet")}</span><br />
|
||||||
<span>{$_("add-your-first-card")}</span>
|
<span>{$_("add-your-first-card")}</span>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -151,7 +151,6 @@
|
|||||||
}
|
}
|
||||||
|
|
||||||
onMount(async () => {
|
onMount(async () => {
|
||||||
toast.loading($_("loading-cards"));
|
|
||||||
let page = 0;
|
let page = 0;
|
||||||
let pagesize = 500;
|
let pagesize = 500;
|
||||||
while (page >= 0) {
|
while (page >= 0) {
|
||||||
@@ -172,8 +171,6 @@
|
|||||||
dataLoaded = true;
|
dataLoaded = true;
|
||||||
page++;
|
page++;
|
||||||
}
|
}
|
||||||
toast.dismiss();
|
|
||||||
toast.success($_("all-cards-loaded"));
|
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
@@ -219,7 +216,7 @@
|
|||||||
{#if selected.length > 0}
|
{#if selected.length > 0}
|
||||||
<button
|
<button
|
||||||
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 inline-flex"
|
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:w-auto sm:text-sm inline-flex"
|
||||||
id="options-menu"
|
id="options-menu"
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
const prom = [];
|
const prom = [];
|
||||||
|
|||||||
@@ -208,7 +208,7 @@
|
|||||||
bind:this={firstname_input}
|
bind:this={firstname_input}
|
||||||
type="text"
|
type="text"
|
||||||
name="firstname"
|
name="firstname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isFirstnameValid}
|
{#if !isFirstnameValid}
|
||||||
<span
|
<span
|
||||||
@@ -231,7 +231,7 @@
|
|||||||
bind:this={middlename_input}
|
bind:this={middlename_input}
|
||||||
type="text"
|
type="text"
|
||||||
name="trackname"
|
name="trackname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
@@ -250,7 +250,7 @@
|
|||||||
bind:this={lastname_input}
|
bind:this={lastname_input}
|
||||||
type="text"
|
type="text"
|
||||||
name="lastname"
|
name="lastname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isLastnameValid}
|
{#if !isLastnameValid}
|
||||||
<span
|
<span
|
||||||
@@ -270,7 +270,7 @@
|
|||||||
name="team"
|
name="team"
|
||||||
multiple
|
multiple
|
||||||
bind:value={selected_team}
|
bind:value={selected_team}
|
||||||
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-neutral-800 rounded-md p-2"
|
||||||
>
|
>
|
||||||
{#each teams as team}
|
{#each teams as team}
|
||||||
<option value={team.id}>
|
<option value={team.id}>
|
||||||
@@ -300,7 +300,7 @@
|
|||||||
bind:this={phone_input}
|
bind:this={phone_input}
|
||||||
type="tel"
|
type="tel"
|
||||||
name="phone"
|
name="phone"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isPhoneValidOrEmpty}
|
{#if !isPhoneValidOrEmpty}
|
||||||
<span
|
<span
|
||||||
@@ -328,7 +328,7 @@
|
|||||||
bind:this={email_input}
|
bind:this={email_input}
|
||||||
type="email"
|
type="email"
|
||||||
name="email"
|
name="email"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isEmailValidOrEmpty}
|
{#if !isEmailValidOrEmpty}
|
||||||
<span
|
<span
|
||||||
@@ -349,7 +349,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-3 text-sm">
|
<div class="ml-3 text-sm">
|
||||||
<label for="comments" class="font-medium text-gray-700"
|
<label for="comments" class="font-semibold text-gray-700"
|
||||||
>{$_("address")}</label
|
>{$_("address")}</label
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@@ -371,7 +371,7 @@
|
|||||||
bind:this={address_input1}
|
bind:this={address_input1}
|
||||||
type="text"
|
type="text"
|
||||||
name="address1"
|
name="address1"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isAddress1Valid}
|
{#if !isAddress1Valid}
|
||||||
<span
|
<span
|
||||||
@@ -394,7 +394,7 @@
|
|||||||
bind:this={address_input2}
|
bind:this={address_input2}
|
||||||
type="text"
|
type="text"
|
||||||
name="address2"
|
name="address2"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
@@ -413,7 +413,7 @@
|
|||||||
bind:this={address_zipcode}
|
bind:this={address_zipcode}
|
||||||
type="text"
|
type="text"
|
||||||
name="zipcode"
|
name="zipcode"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !iszipcodevalid}
|
{#if !iszipcodevalid}
|
||||||
<span
|
<span
|
||||||
@@ -439,7 +439,7 @@
|
|||||||
bind:this={address_city}
|
bind:this={address_city}
|
||||||
type="text"
|
type="text"
|
||||||
name="city"
|
name="city"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !iscityvalid}
|
{#if !iscityvalid}
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -1,417 +1,399 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import {
|
import {
|
||||||
GroupContactService,
|
GroupContactService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
RunnerOrganizationService,
|
RunnerOrganizationService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
import PromiseError from "../base/PromiseError.svelte";
|
import PromiseError from "../base/PromiseError.svelte";
|
||||||
import isEmail from "validator/es/lib/isEmail";
|
import isEmail from "validator/es/lib/isEmail";
|
||||||
import toast from "svelte-french-toast";
|
import toast from "svelte-french-toast";
|
||||||
let data_loaded = false;
|
let data_loaded = false;
|
||||||
let orgs = [];
|
let orgs = [];
|
||||||
let teams = [];
|
let teams = [];
|
||||||
export let params;
|
export let params;
|
||||||
$: delete_triggered = false;
|
$: delete_triggered = false;
|
||||||
$: original_data = {};
|
$: original_data = {};
|
||||||
$: editable = {};
|
$: editable = {};
|
||||||
$: changes_performed = !(
|
$: changes_performed = !(
|
||||||
JSON.stringify(original_data) === JSON.stringify(editable)
|
JSON.stringify(original_data) === JSON.stringify(editable)
|
||||||
);
|
);
|
||||||
$: isEmailValid =
|
$: isEmailValid =
|
||||||
(editable.email || "") === "" ||
|
(editable.email || "") === "" ||
|
||||||
(editable.email && isEmail(editable.email || ""));
|
(editable.email && isEmail(editable.email || ""));
|
||||||
$: isFirstnameValid = editable.firstname !== "";
|
$: isFirstnameValid = editable.firstname !== "";
|
||||||
$: isLastnameValid = editable.lastname !== "";
|
$: isLastnameValid = editable.lastname !== "";
|
||||||
$: save_enabled =
|
$: save_enabled =
|
||||||
changes_performed &&
|
changes_performed &&
|
||||||
isFirstnameValid &&
|
isFirstnameValid &&
|
||||||
isLastnameValid &&
|
isLastnameValid &&
|
||||||
isEmailValid &&
|
isEmailValid &&
|
||||||
isPhoneValidOrEmpty &&
|
isPhoneValidOrEmpty &&
|
||||||
((isAddress1Valid && iszipcodevalid && iscityvalid) ||
|
((isAddress1Valid && iszipcodevalid && iscityvalid) ||
|
||||||
editable.address_checked === false);
|
editable.address_checked === false);
|
||||||
const promise = GroupContactService.groupContactControllerGetOne(
|
const promise = GroupContactService.groupContactControllerGetOne(
|
||||||
params.contact
|
params.contact
|
||||||
).then((data) => {
|
).then((data) => {
|
||||||
data_loaded = true;
|
data_loaded = true;
|
||||||
original_data = Object.assign(original_data, data);
|
original_data = Object.assign(original_data, data);
|
||||||
editable = Object.assign(editable, original_data);
|
editable = Object.assign(editable, original_data);
|
||||||
editable.groups = editable.groups.map((g) => g.id);
|
editable.groups = editable.groups.map((g) => g.id);
|
||||||
original_data.groups = original_data.groups.map((g) => g.id);
|
original_data.groups = original_data.groups.map((g) => g.id);
|
||||||
editable.address_checked = editable.address.address1 !== null;
|
editable.address_checked = editable.address.address1 !== null;
|
||||||
original_data.address_checked = editable.address.address1 !== null;
|
original_data.address_checked = editable.address.address1 !== null;
|
||||||
if (editable.address_checked === false) {
|
if (editable.address_checked === false) {
|
||||||
editable.address = {
|
editable.address = {
|
||||||
address1: "",
|
address1: "",
|
||||||
address2: "",
|
address2: "",
|
||||||
city: "",
|
city: "",
|
||||||
postalcode: "",
|
postalcode: "",
|
||||||
country: "",
|
country: "",
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
RunnerOrganizationService.runnerOrganizationControllerGetAll().then((val) => {
|
RunnerOrganizationService.runnerOrganizationControllerGetAll().then((val) => {
|
||||||
orgs = val;
|
orgs = val;
|
||||||
});
|
});
|
||||||
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
||||||
teams = val;
|
teams = val;
|
||||||
});
|
});
|
||||||
$: isPhoneValidOrEmpty =
|
$: isPhoneValidOrEmpty =
|
||||||
editable.phone?.includes("+") ||
|
editable.phone?.includes("+") ||
|
||||||
editable.phone === "" ||
|
editable.phone === "" ||
|
||||||
editable.phone === null;
|
editable.phone === null;
|
||||||
$: isAddress1Valid = editable.address?.address1?.trim().length !== 0;
|
$: isAddress1Valid = editable.address?.address1?.trim().length !== 0;
|
||||||
$: iszipcodevalid = editable.address?.postalcode?.trim().length !== 0;
|
$: iszipcodevalid = editable.address?.postalcode?.trim().length !== 0;
|
||||||
$: iscityvalid = editable.address?.city?.trim().length !== 0;
|
$: iscityvalid = editable.address?.city?.trim().length !== 0;
|
||||||
function submit() {
|
function submit() {
|
||||||
if (data_loaded === true && save_enabled) {
|
if (data_loaded === true && save_enabled) {
|
||||||
toast.loading($_("contact-is-being-updated"));
|
toast.loading($_("contact-is-being-updated"));
|
||||||
editable.address.country = "DE";
|
editable.address.country = "DE";
|
||||||
if (editable.address_checked === false) {
|
if (editable.address_checked === false) {
|
||||||
editable.address = null;
|
editable.address = null;
|
||||||
}
|
}
|
||||||
if (editable.email) editable.email = editable.email;
|
if (editable.email) editable.email = editable.email;
|
||||||
if (editable.phone) editable.phone = editable.phone;
|
if (editable.phone) editable.phone = editable.phone;
|
||||||
if (editable.middlename) editable.middlename = editable.middlename;
|
if (editable.middlename) editable.middlename = editable.middlename;
|
||||||
GroupContactService.groupContactControllerPut(original_data.id, editable)
|
GroupContactService.groupContactControllerPut(original_data.id, editable)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
Object.assign(original_data, editable);
|
Object.assign(original_data, editable);
|
||||||
original_data = original_data;
|
original_data = original_data;
|
||||||
toast.dismiss();
|
toast.dismiss();
|
||||||
toast.success($_("updated-contact"));
|
toast.success($_("updated-contact"));
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function deleteContact() {
|
function deleteContact() {
|
||||||
GroupContactService.groupContactControllerRemove(original_data.id, true)
|
GroupContactService.groupContactControllerRemove(original_data.id, true)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
location.replace("./");
|
location.replace("./");
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#await promise}
|
{#await promise}
|
||||||
{$_("loading-contact-details")}
|
{$_("loading-contact-details")}
|
||||||
{: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">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<nav class="w-full flex">
|
<nav class="w-full flex">
|
||||||
<ol class="list-none flex flex-row items-center justify-start">
|
<ol class="list-none flex flex-row items-center justify-start">
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
<svg
|
<a class="mr-2" href="./"
|
||||||
fill="currentColor"
|
><svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
width="24"
|
||||||
width="24"
|
height="24"
|
||||||
height="24"
|
viewBox="0 0 24 24"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
fill="none"
|
||||||
<path
|
stroke="currentColor"
|
||||||
d="M2 22a8 8 0 1 1 16 0H2zm8-9c-3.315 0-6-2.685-6-6s2.685-6 6-6 6 2.685 6 6-2.685 6-6 6zm10 4h4v2h-4v-2zm-3-5h7v2h-7v-2zm2-5h5v2h-5V7z"
|
stroke-width="2"
|
||||||
/></svg
|
stroke-linecap="round"
|
||||||
>
|
stroke-linejoin="round"
|
||||||
</li>
|
class="inline-block"
|
||||||
<li class="flex items-center ml-2">
|
><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg
|
||||||
<a class="mr-2" href="./">{$_("contacts")}</a><svg
|
>
|
||||||
stroke="currentColor"
|
{$_("contacts")}</a
|
||||||
fill="none"
|
>
|
||||||
stroke-width="2"
|
</li>
|
||||||
viewBox="0 0 24 24"
|
</ol>
|
||||||
stroke-linecap="round"
|
</nav>
|
||||||
stroke-linejoin="round"
|
</div>
|
||||||
class="h-3 w-3 mr-2 stroke-current"
|
</div>
|
||||||
height="1em"
|
<div class="mb-4 text-3xl font-extrabold leading-tight">
|
||||||
width="1em"
|
{original_data.firstname}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
{original_data.middlename || ""}
|
||||||
><line x1="5" y1="12" x2="19" y2="12" />
|
{original_data.lastname}
|
||||||
<polyline points="12 5 19 12 12 19" /></svg
|
<div data-id="contact_actions_${editable.id}">
|
||||||
>
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT:DELETE")}
|
||||||
</li>
|
{#if delete_triggered}
|
||||||
<li class="flex items-center">
|
<button
|
||||||
<span class="mr-2"
|
on:click={deleteContact}
|
||||||
>{original_data.firstname}
|
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:w-auto sm:text-sm"
|
||||||
{original_data.middlename || ""}
|
>{$_("confirm-deletion")}</button
|
||||||
{original_data.lastname}</span
|
>
|
||||||
>
|
<button
|
||||||
</li>
|
on:click={() => {
|
||||||
</ol>
|
delete_triggered = !delete_triggered;
|
||||||
</nav>
|
}}
|
||||||
</div>
|
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"
|
||||||
</div>
|
>{$_("cancel")}</button
|
||||||
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
>
|
||||||
{original_data.firstname}
|
{/if}
|
||||||
{original_data.middlename || ""}
|
{#if !delete_triggered}
|
||||||
{original_data.lastname}
|
<button
|
||||||
<span data-id="contact_actions_${editable.id}">
|
on:click={() => {
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT:DELETE")}
|
delete_triggered = true;
|
||||||
{#if delete_triggered}
|
}}
|
||||||
<button
|
type="button"
|
||||||
on:click={deleteContact}
|
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:w-auto sm:text-sm"
|
||||||
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-contact")}</button
|
||||||
>{$_("confirm-deletion")}</button
|
>
|
||||||
>
|
{/if}
|
||||||
<button
|
{/if}
|
||||||
on:click={() => {
|
{#if !delete_triggered}
|
||||||
delete_triggered = !delete_triggered;
|
<button
|
||||||
}}
|
disabled={!save_enabled}
|
||||||
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"
|
class:opacity-50={!save_enabled}
|
||||||
>{$_("cancel")}</button
|
type="button"
|
||||||
>
|
on:click={submit}
|
||||||
{/if}
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
{#if !delete_triggered}
|
>{$_("save-changes")}</button
|
||||||
<button
|
>
|
||||||
on:click={() => {
|
{/if}
|
||||||
delete_triggered = true;
|
</div>
|
||||||
}}
|
</div>
|
||||||
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"
|
<div class="text-sm w-full mt-2">
|
||||||
>{$_("delete-contact")}</button
|
<label for="firstname" class="font-semibold text-gray-700"
|
||||||
>
|
>{$_("first-name")}</label
|
||||||
{/if}
|
>
|
||||||
{/if}
|
<input
|
||||||
{#if !delete_triggered}
|
autocomplete="off"
|
||||||
<button
|
placeholder={$_("first-name")}
|
||||||
disabled={!save_enabled}
|
type="text"
|
||||||
class:opacity-50={!save_enabled}
|
class:border-red-500={!isFirstnameValid}
|
||||||
type="button"
|
class:focus:border-red-500={!isFirstnameValid}
|
||||||
on:click={submit}
|
class:focus:ring-red-500={!isFirstnameValid}
|
||||||
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"
|
bind:value={editable.firstname}
|
||||||
>{$_("save-changes")}</button
|
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-neutral-800 rounded-md p-2"
|
||||||
{/if}
|
/>
|
||||||
</span>
|
{#if !isFirstnameValid}
|
||||||
</div>
|
<span
|
||||||
<!-- -->
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
<div class="text-sm w-full">
|
>
|
||||||
<label for="firstname" class="font-medium text-gray-700"
|
{$_("first-name-is-required")}
|
||||||
>{$_("first-name")}</label
|
</span>
|
||||||
>
|
{/if}
|
||||||
<input
|
</div>
|
||||||
autocomplete="off"
|
<div class="text-sm w-full mt-2">
|
||||||
placeholder={$_("first-name")}
|
<label for="middlename" class="font-semibold text-gray-700"
|
||||||
type="text"
|
>{$_("middle-name")}</label
|
||||||
class:border-red-500={!isFirstnameValid}
|
>
|
||||||
class:focus:border-red-500={!isFirstnameValid}
|
<input
|
||||||
class:focus:ring-red-500={!isFirstnameValid}
|
autocomplete="off"
|
||||||
bind:value={editable.firstname}
|
placeholder={$_("middle-name")}
|
||||||
name="firstname"
|
type="text"
|
||||||
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"
|
bind:value={editable.middlename}
|
||||||
/>
|
name="middlename"
|
||||||
{#if !isFirstnameValid}
|
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-neutral-800 rounded-md p-2"
|
||||||
<span
|
/>
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
</div>
|
||||||
>
|
<div class="text-sm w-full mt-2">
|
||||||
{$_("first-name-is-required")}
|
<label for="lastname" class="font-semibold text-gray-700"
|
||||||
</span>
|
>{$_("last-name")}</label
|
||||||
{/if}
|
>
|
||||||
</div>
|
<input
|
||||||
<div class="text-sm w-full">
|
autocomplete="off"
|
||||||
<label for="middlename" class="font-medium text-gray-700"
|
placeholder={$_("last-name")}
|
||||||
>{$_("middle-name")}</label
|
type="text"
|
||||||
>
|
bind:value={editable.lastname}
|
||||||
<input
|
class:border-red-500={!isLastnameValid}
|
||||||
autocomplete="off"
|
class:focus:border-red-500={!isLastnameValid}
|
||||||
placeholder={$_("middle-name")}
|
class:focus:ring-red-500={!isLastnameValid}
|
||||||
type="text"
|
name="lastname"
|
||||||
bind:value={editable.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-neutral-800 rounded-md p-2"
|
||||||
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"
|
{#if !isLastnameValid}
|
||||||
/>
|
<span
|
||||||
</div>
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
<div class="text-sm w-full">
|
>
|
||||||
<label for="lastname" class="font-medium text-gray-700"
|
{$_("last-name-is-required")}
|
||||||
>{$_("last-name")}</label
|
</span>
|
||||||
>
|
{/if}
|
||||||
<input
|
</div>
|
||||||
autocomplete="off"
|
<div class="text-sm w-full mt-2">
|
||||||
placeholder={$_("last-name")}
|
<label for="email" class="font-semibold text-gray-700"
|
||||||
type="text"
|
>{$_("e-mail-adress")}</label
|
||||||
bind:value={editable.lastname}
|
>
|
||||||
class:border-red-500={!isLastnameValid}
|
<input
|
||||||
class:focus:border-red-500={!isLastnameValid}
|
autocomplete="off"
|
||||||
class:focus:ring-red-500={!isLastnameValid}
|
placeholder={$_("e-mail-adress")}
|
||||||
name="lastname"
|
type="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"
|
bind:value={editable.email}
|
||||||
/>
|
class:border-red-500={!isEmailValid}
|
||||||
{#if !isLastnameValid}
|
class:focus:border-red-500={!isEmailValid}
|
||||||
<span
|
class:focus:ring-red-500={!isEmailValid}
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
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-neutral-800 rounded-md p-2"
|
||||||
{$_("last-name-is-required")}
|
/>
|
||||||
</span>
|
{#if !isEmailValid}
|
||||||
{/if}
|
<span
|
||||||
</div>
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
<div class="text-sm w-full">
|
>
|
||||||
<label for="email" class="font-medium text-gray-700"
|
{$_("valid-email-is-required")}
|
||||||
>{$_("e-mail-adress")}</label
|
</span>
|
||||||
>
|
{/if}
|
||||||
<input
|
</div>
|
||||||
autocomplete="off"
|
<div class="text-sm w-full mt-2">
|
||||||
placeholder={$_("e-mail-adress")}
|
<label for="phone" class="font-semibold text-gray-700">{$_("phone")}</label>
|
||||||
type="email"
|
<input
|
||||||
bind:value={editable.email}
|
autocomplete="off"
|
||||||
class:border-red-500={!isEmailValid}
|
placeholder={$_("phone")}
|
||||||
class:focus:border-red-500={!isEmailValid}
|
type="tel"
|
||||||
class:focus:ring-red-500={!isEmailValid}
|
class:border-red-500={!isPhoneValidOrEmpty}
|
||||||
name="email"
|
class:focus:border-red-500={!isPhoneValidOrEmpty}
|
||||||
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:focus:ring-red-500={!isPhoneValidOrEmpty}
|
||||||
/>
|
bind:value={editable.phone}
|
||||||
{#if !isEmailValid}
|
name="phone"
|
||||||
<span
|
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-neutral-800 rounded-md p-2"
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
/>
|
||||||
>
|
{#if !isPhoneValidOrEmpty}
|
||||||
{$_("valid-email-is-required")}
|
<span
|
||||||
</span>
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{/if}
|
>
|
||||||
</div>
|
{$_("valid-international-phone-number-is-required")}
|
||||||
<div class="text-sm w-full">
|
</span>
|
||||||
<label for="phone" class="font-medium text-gray-700">{$_("phone")}</label>
|
{/if}
|
||||||
<input
|
</div>
|
||||||
autocomplete="off"
|
<div class="text-sm w-full mt-2">
|
||||||
placeholder={$_("phone")}
|
<span class="font-semibold text-gray-700">{$_("groups")}</span>
|
||||||
type="tel"
|
<select
|
||||||
class:border-red-500={!isPhoneValidOrEmpty}
|
bind:value={editable.groups}
|
||||||
class:focus:border-red-500={!isPhoneValidOrEmpty}
|
name="team"
|
||||||
class:focus:ring-red-500={!isPhoneValidOrEmpty}
|
multiple
|
||||||
bind:value={editable.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-neutral-800 rounded-md p-2"
|
||||||
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"
|
{#each teams as team}
|
||||||
/>
|
<option value={team.id}>
|
||||||
{#if !isPhoneValidOrEmpty}
|
{team.parentGroup.name}
|
||||||
<span
|
>
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
{team.name}
|
||||||
>
|
</option>
|
||||||
{$_("valid-international-phone-number-is-required")}
|
{/each}
|
||||||
</span>
|
{#each orgs as org}
|
||||||
{/if}
|
<option value={org.id}>{org.name}</option>
|
||||||
</div>
|
{/each}
|
||||||
<div class="text-sm w-full">
|
</select>
|
||||||
<span class="font-medium text-gray-700">{$_("groups")}</span>
|
</div>
|
||||||
<select
|
<!-- -->
|
||||||
bind:value={editable.groups}
|
<div class="flex items-start mt-2">
|
||||||
name="team"
|
<div class="flex items-center h-5">
|
||||||
multiple
|
<input
|
||||||
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"
|
bind:checked={editable.address_checked}
|
||||||
>
|
id="comments"
|
||||||
{#each teams as team}
|
name="comments"
|
||||||
<option value={team.id}>
|
type="checkbox"
|
||||||
{team.parentGroup.name}
|
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
>
|
/>
|
||||||
{team.name}
|
</div>
|
||||||
</option>
|
<div class="ml-3 text-sm">
|
||||||
{/each}
|
<label for="comments" class="font-semibold text-gray-700"
|
||||||
{#each orgs as org}
|
>{$_("address")}</label
|
||||||
<option value={org.id}>{org.name}</option>
|
>
|
||||||
{/each}
|
</div>
|
||||||
</select>
|
</div>
|
||||||
</div>
|
{#if editable.address_checked === true}
|
||||||
<!-- -->
|
<div class="col-span-6">
|
||||||
<div class="flex items-start mt-2">
|
<label for="address1" class="block text-sm font-medium text-gray-700"
|
||||||
<div class="flex items-center h-5">
|
>{$_("address")}</label
|
||||||
<input
|
>
|
||||||
bind:checked={editable.address_checked}
|
<input
|
||||||
id="comments"
|
autocomplete="off"
|
||||||
name="comments"
|
placeholder="Address"
|
||||||
type="checkbox"
|
class:border-red-500={!isAddress1Valid}
|
||||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
class:focus:border-red-500={!isAddress1Valid}
|
||||||
/>
|
class:focus:ring-red-500={!isAddress1Valid}
|
||||||
</div>
|
bind:value={editable.address.address1}
|
||||||
<div class="ml-3 text-sm">
|
type="text"
|
||||||
<label for="comments" class="font-medium text-gray-700"
|
name="address1"
|
||||||
>{$_("address")}</label
|
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-neutral-800 rounded-md p-2"
|
||||||
>
|
/>
|
||||||
</div>
|
{#if !isAddress1Valid}
|
||||||
</div>
|
<span
|
||||||
{#if editable.address_checked === true}
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
<div class="col-span-6">
|
>
|
||||||
<label for="address1" class="block text-sm font-medium text-gray-700"
|
{$_("address-is-required")}
|
||||||
>{$_("address")}</label
|
</span>
|
||||||
>
|
{/if}
|
||||||
<input
|
</div>
|
||||||
autocomplete="off"
|
<div class="col-span-6">
|
||||||
placeholder="Address"
|
<label for="address2" class="block text-sm font-medium text-gray-700"
|
||||||
class:border-red-500={!isAddress1Valid}
|
>{$_("apartment-suite-etc")}</label
|
||||||
class:focus:border-red-500={!isAddress1Valid}
|
>
|
||||||
class:focus:ring-red-500={!isAddress1Valid}
|
<input
|
||||||
bind:value={editable.address.address1}
|
autocomplete="off"
|
||||||
type="text"
|
placeholder={$_("apartment-suite-etc")}
|
||||||
name="address1"
|
bind:value={editable.address.address2}
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
type="text"
|
||||||
/>
|
name="address2"
|
||||||
{#if !isAddress1Valid}
|
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-neutral-800 rounded-md p-2"
|
||||||
<span
|
/>
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
</div>
|
||||||
>
|
<div class="col-span-6">
|
||||||
{$_("address-is-required")}
|
<label for="zipcode" class="block text-sm font-medium text-gray-700"
|
||||||
</span>
|
>{$_("zip-postal-code")}</label
|
||||||
{/if}
|
>
|
||||||
</div>
|
<input
|
||||||
<div class="col-span-6">
|
autocomplete="off"
|
||||||
<label for="address2" class="block text-sm font-medium text-gray-700"
|
placeholder={$_("zip-postal-code")}
|
||||||
>{$_("apartment-suite-etc")}</label
|
class:border-red-500={!iszipcodevalid}
|
||||||
>
|
class:focus:border-red-500={!iszipcodevalid}
|
||||||
<input
|
class:focus:ring-red-500={!iszipcodevalid}
|
||||||
autocomplete="off"
|
bind:value={editable.address.postalcode}
|
||||||
placeholder={$_("apartment-suite-etc")}
|
type="text"
|
||||||
bind:value={editable.address.address2}
|
name="zipcode"
|
||||||
type="text"
|
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-neutral-800 rounded-md p-2"
|
||||||
name="address2"
|
/>
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
{#if !iszipcodevalid}
|
||||||
/>
|
<span
|
||||||
</div>
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
<div class="col-span-6">
|
>
|
||||||
<label for="zipcode" class="block text-sm font-medium text-gray-700"
|
{$_("valid-zipcode-postal-code-is-required")}
|
||||||
>{$_("zip-postal-code")}</label
|
</span>
|
||||||
>
|
{/if}
|
||||||
<input
|
</div>
|
||||||
autocomplete="off"
|
<div class="col-span-6">
|
||||||
placeholder={$_("zip-postal-code")}
|
<label for="city" class="block text-sm font-medium text-gray-700"
|
||||||
class:border-red-500={!iszipcodevalid}
|
>{$_("city")}</label
|
||||||
class:focus:border-red-500={!iszipcodevalid}
|
>
|
||||||
class:focus:ring-red-500={!iszipcodevalid}
|
<input
|
||||||
bind:value={editable.address.postalcode}
|
autocomplete="off"
|
||||||
type="text"
|
placeholder={$_("city")}
|
||||||
name="zipcode"
|
class:border-red-500={!iscityvalid}
|
||||||
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:focus:border-red-500={!iscityvalid}
|
||||||
/>
|
class:focus:ring-red-500={!iscityvalid}
|
||||||
{#if !iszipcodevalid}
|
bind:value={editable.address.city}
|
||||||
<span
|
type="text"
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
name="city"
|
||||||
>
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
{$_("valid-zipcode-postal-code-is-required")}
|
/>
|
||||||
</span>
|
{#if !iscityvalid}
|
||||||
{/if}
|
<span
|
||||||
</div>
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
<div class="col-span-6">
|
>
|
||||||
<label for="city" class="block text-sm font-medium text-gray-700"
|
{$_("valid-city-is-required")}
|
||||||
>{$_("city")}</label
|
</span>
|
||||||
>
|
{/if}
|
||||||
<input
|
</div>
|
||||||
autocomplete="off"
|
{/if}
|
||||||
placeholder={$_("city")}
|
</section>
|
||||||
class:border-red-500={!iscityvalid}
|
|
||||||
class:focus:border-red-500={!iscityvalid}
|
|
||||||
class:focus:ring-red-500={!iscityvalid}
|
|
||||||
bind:value={editable.address.city}
|
|
||||||
type="text"
|
|
||||||
name="city"
|
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
|
||||||
/>
|
|
||||||
{#if !iscityvalid}
|
|
||||||
<span
|
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
|
||||||
>
|
|
||||||
{$_("valid-city-is-required")}
|
|
||||||
</span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</section>
|
|
||||||
{:catch error}
|
{:catch error}
|
||||||
<PromiseError {error} />
|
<PromiseError {error} />
|
||||||
{/await}
|
{/await}
|
||||||
@@ -8,20 +8,20 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_("contacts")}
|
{$_("contacts")}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT:CREATE")}
|
</h4>
|
||||||
<button
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT:CREATE")}
|
||||||
on:click={() => {
|
<button
|
||||||
modal_open = true;
|
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"
|
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:w-auto sm:text-sm"
|
||||||
{$_("create-a-new-contact")}
|
>
|
||||||
</button>
|
{$_("create-a-new-contact")}
|
||||||
{/if}
|
</button>
|
||||||
</span>
|
{/if}
|
||||||
<ContactsOverview bind:current_contacts />
|
<ContactsOverview bind:current_contacts />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@@ -1,198 +1,198 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { GroupContactService } from "@odit/lfk-client-js";
|
import { GroupContactService } from "@odit/lfk-client-js";
|
||||||
const promise = GroupContactService.groupContactControllerGetAll().then(
|
const promise = GroupContactService.groupContactControllerGetAll().then(
|
||||||
(result) => {
|
(result) => {
|
||||||
current_contacts = result;
|
current_contacts = result;
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import ContactsEmptyState from "./ContactsEmptyState.svelte";
|
import ContactsEmptyState from "./ContactsEmptyState.svelte";
|
||||||
import toast from "svelte-french-toast";
|
import toast from "svelte-french-toast";
|
||||||
$: searchvalue = "";
|
$: searchvalue = "";
|
||||||
$: active_deletes = [];
|
$: active_deletes = [];
|
||||||
export let current_contacts = [];
|
export let current_contacts = [];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:GET")}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:GET")}
|
||||||
{#await promise}
|
{#await 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">{$_("contacts-are-being-loaded")}</p>
|
<p class="font-bold">{$_("contacts-are-being-loaded")}</p>
|
||||||
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
||||||
</div>
|
</div>
|
||||||
{:then}
|
{:then}
|
||||||
{#if current_contacts.length === 0}
|
{#if current_contacts.length === 0}
|
||||||
<ContactsEmptyState />
|
<ContactsEmptyState />
|
||||||
{:else}
|
{:else}
|
||||||
<input
|
<input
|
||||||
type="search"
|
type="search"
|
||||||
bind:value={searchvalue}
|
bind:value={searchvalue}
|
||||||
placeholder={$_("datatable.search")}
|
placeholder={$_("datatable.search")}
|
||||||
aria-label={$_("datatable.search")}
|
aria-label={$_("datatable.search")}
|
||||||
class="mb-4"
|
class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
|
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
|
||||||
>
|
>
|
||||||
<table class="divide-y divide-gray-200 w-full">
|
<table class="divide-y divide-gray-200 w-full">
|
||||||
<thead class="bg-gray-50">
|
<thead class="bg-gray-50">
|
||||||
<tr class="odd:bg-white even:bg-gray-100">
|
<tr class="odd:bg-white even:bg-gray-100">
|
||||||
<th
|
<th
|
||||||
scope="col"
|
scope="col"
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||||
>
|
>
|
||||||
{$_("name")}
|
{$_("name")}
|
||||||
</th>
|
</th>
|
||||||
<th
|
<th
|
||||||
scope="col"
|
scope="col"
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||||
>
|
>
|
||||||
{$_("groups")}
|
{$_("groups")}
|
||||||
</th>
|
</th>
|
||||||
<th
|
<th
|
||||||
scope="col"
|
scope="col"
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||||
>
|
>
|
||||||
{$_("address")}
|
{$_("address")}
|
||||||
</th>
|
</th>
|
||||||
<th scope="col" class="relative px-6 py-3">
|
<th scope="col" class="relative px-6 py-3">
|
||||||
<span class="sr-only">{$_("action")}</span>
|
<span class="sr-only">{$_("action")}</span>
|
||||||
</th>
|
</th>
|
||||||
</tr>
|
</tr>
|
||||||
</thead>
|
</thead>
|
||||||
<tbody class="divide-y divide-gray-200">
|
<tbody class="divide-y divide-gray-200">
|
||||||
{#each current_contacts as t}
|
{#each current_contacts as t}
|
||||||
{#if Object.values(t)
|
{#if Object.values(t)
|
||||||
.toString()
|
.toString()
|
||||||
.toLowerCase()
|
.toLowerCase()
|
||||||
.includes(searchvalue)}
|
.includes(searchvalue)}
|
||||||
<tr
|
<tr
|
||||||
class="odd:bg-white even:bg-gray-100"
|
class="odd:bg-white even:bg-gray-100"
|
||||||
data-rowid="team_{t.id}"
|
data-rowid="team_{t.id}"
|
||||||
>
|
>
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="ml-4">
|
<div class="ml-4">
|
||||||
<div class="text-sm font-medium text-gray-900">
|
<div class="text-sm font-medium text-gray-900">
|
||||||
{t.firstname}
|
{t.firstname}
|
||||||
{t.middlename || ""}
|
{t.middlename || ""}
|
||||||
{t.lastname}
|
{t.lastname}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="ml-4">
|
<div
|
||||||
<div class="text-sm font-medium text-gray-900">
|
class="text-sm font-medium text-gray-900 gap-0.5 flex flex-wrap"
|
||||||
{#if t.groups.length > 0}
|
>
|
||||||
{#each t.groups as g}
|
{#if t.groups.length > 0}
|
||||||
{#if g.responseType === "RUNNERORGANIZATION"}
|
{#each t.groups as g}
|
||||||
<a
|
{#if g.responseType === "RUNNERORGANIZATION"}
|
||||||
href="../orgs/{g.id}"
|
<a
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
href="../orgs/{g.id}"
|
||||||
>{g.name}</a
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800 border border-current"
|
||||||
>
|
>{g.name}</a
|
||||||
{:else}
|
>
|
||||||
<a
|
{:else}
|
||||||
href="../teams/{g.id}"
|
<a
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
href="../teams/{g.id}"
|
||||||
>{g.parentGroup.name}
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800 border border-current"
|
||||||
>
|
>{g.parentGroup.name}
|
||||||
{g.name}</a
|
>
|
||||||
>
|
{g.name}</a
|
||||||
{/if}
|
>
|
||||||
{/each}
|
{/if}
|
||||||
{:else}
|
{/each}
|
||||||
{$_("contact-is-not-a-member-in-any-group")}
|
{:else}
|
||||||
{/if}
|
{$_("contact-is-not-a-member-in-any-group")}
|
||||||
</div>
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<div class="ml-4">
|
<div class="ml-4">
|
||||||
<div class="text-sm font-medium text-gray-900">
|
<div class="text-sm font-medium text-gray-900">
|
||||||
{#if t.address.address1 !== null}
|
{#if t.address.address1 !== null}
|
||||||
{t.address.address1}<br />
|
{t.address.address1}<br />
|
||||||
{t.address.address2 || ""}<br />
|
{t.address.address2 || ""}<br />
|
||||||
{t.address.postalcode}
|
{t.address.postalcode}
|
||||||
{t.address.city}
|
{t.address.city}
|
||||||
{t.address.country}
|
{t.address.country}
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</td>
|
</td>
|
||||||
{#if active_deletes[t.id] === true}
|
{#if active_deletes[t.id] === true}
|
||||||
<td
|
<td
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
|
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
active_deletes[t.id] = false;
|
active_deletes[t.id] = false;
|
||||||
}}
|
}}
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer"
|
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer"
|
||||||
>{$_("cancel-delete")}</button
|
>{$_("cancel-delete")}</button
|
||||||
>
|
>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
toast.loading($_("deleting-contact"));
|
toast.loading($_("deleting-contact"));
|
||||||
GroupContactService.groupContactControllerRemove(
|
GroupContactService.groupContactControllerRemove(
|
||||||
t.id,
|
t.id,
|
||||||
false
|
false
|
||||||
).then((resp) => {
|
).then((resp) => {
|
||||||
current_contacts = current_contacts.filter(
|
current_contacts = current_contacts.filter(
|
||||||
(obj) => obj.id !== t.id
|
(obj) => obj.id !== t.id
|
||||||
);
|
);
|
||||||
toast.dismiss();
|
toast.dismiss();
|
||||||
toast($_("contact-deleted"));
|
toast($_("contact-deleted"));
|
||||||
});
|
});
|
||||||
}}
|
}}
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
|
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
|
||||||
>{$_("confirm-delete")}</button
|
>{$_("confirm-delete")}</button
|
||||||
>
|
>
|
||||||
</td>
|
</td>
|
||||||
{:else}
|
{:else}
|
||||||
<td
|
<td
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
|
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
|
||||||
>
|
>
|
||||||
<a
|
<a
|
||||||
href="./{t.id}"
|
href="./{t.id}"
|
||||||
class="text-indigo-600 hover:text-indigo-900"
|
class="text-indigo-600 hover:text-indigo-900"
|
||||||
>{$_("details")}</a
|
>{$_("details")}</a
|
||||||
>
|
>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:DELETE")}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:DELETE")}
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
active_deletes[t.id] = true;
|
active_deletes[t.id] = true;
|
||||||
}}
|
}}
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
|
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
|
||||||
>{$_("delete")}</button
|
>{$_("delete")}</button
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
{/if}
|
{/if}
|
||||||
</tr>
|
</tr>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</tbody>
|
</tbody>
|
||||||
</table>
|
</table>
|
||||||
</div>
|
</div>
|
||||||
{/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}
|
||||||
@@ -1,431 +1,439 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import localForage from "localforage";
|
import localForage from "localforage";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import { router } from "tinro";
|
import { router } from "tinro";
|
||||||
import NoComponentLoaded from "../base/NoComponentLoaded.svelte";
|
import NoComponentLoaded from "../base/NoComponentLoaded.svelte";
|
||||||
import { AuthService } from "@odit/lfk-client-js";
|
import { AuthService } from "@odit/lfk-client-js";
|
||||||
import { Toaster } from "svelte-french-toast";
|
import { Toaster } from "svelte-french-toast";
|
||||||
$: navOpen = false;
|
$: navOpen = false;
|
||||||
function logout() {
|
function logout() {
|
||||||
localForage.clear();
|
localForage.clear();
|
||||||
location.replace("/");
|
location.replace("/");
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="min-h-screen bg-gray-50">
|
<section class="min-h-screen bg-gray-50">
|
||||||
<div
|
<div
|
||||||
class:collapsed_navigation={!navOpen}
|
class:collapsed_navigation={!navOpen}
|
||||||
class="select-none fixed top-0 left-0 z-20 h-full pb-10 overflow-x-hidden overflow-y-auto transition origin-left transform border-r w-60 bg-gray-50"
|
style="z-index:2;"
|
||||||
>
|
class="select-none fixed top-0 left-0 h-full pb-10 overflow-x-hidden overflow-y-auto transition origin-left transform border-r w-60 bg-gray-50"
|
||||||
<a href="/" class="flex items-center px-4 py-5">
|
>
|
||||||
<img src="/lfk-logo.png" alt="Logo" class="h-10" />
|
<a href="/" class="flex items-center px-4 py-5">
|
||||||
<h3 class="text-lg font-bold">LfK!Admin</h3>
|
<img src="/lfk-logo.png" alt="Logo" class="h-10" />
|
||||||
</a>
|
<h3 class="text-lg font-bold">LfK!Admin</h3>
|
||||||
<nav class="text-sm font-medium text-gray-600" aria-label="Main Navigation">
|
</a>
|
||||||
<a
|
<nav class="text-sm font-medium text-gray-600" aria-label="Main Navigation">
|
||||||
class:bg-gray-100={$router.path === "/"}
|
<a
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
class:activenav={$router.path === "/"}
|
||||||
href="/"
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
>
|
href="/"
|
||||||
<svg
|
>
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
viewBox="0 0 20 20"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
fill="currentColor"
|
viewBox="0 0 20 20"
|
||||||
>
|
fill="currentColor"
|
||||||
<path
|
>
|
||||||
d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"
|
<path
|
||||||
/>
|
d="M10.707 2.293a1 1 0 00-1.414 0l-7 7a1 1 0 001.414 1.414L4 10.414V17a1 1 0 001 1h2a1 1 0 001-1v-2a1 1 0 011-1h2a1 1 0 011 1v2a1 1 0 001 1h2a1 1 0 001-1v-6.586l.293.293a1 1 0 001.414-1.414l-7-7z"
|
||||||
</svg>
|
/>
|
||||||
<span>{$_("dashboard-title")}</span>
|
</svg>
|
||||||
</a>
|
<span>{$_("dashboard-title")}</span>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION:GET")}
|
</a>
|
||||||
<a
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET")}
|
||||||
class:bg-gray-100={$router.path.includes("/orgs/")}
|
<a
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
class:activenav={$router.path.includes("/runners/")}
|
||||||
href="/orgs/"
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
>
|
href="/runners/"
|
||||||
<svg
|
>
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
<svg
|
||||||
fill="currentColor"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
viewBox="0 0 24 24"
|
||||||
viewBox="0 0 24 24"
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
width="24"
|
fill="currentColor"
|
||||||
height="24"
|
width="24"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
height="24"
|
||||||
<path
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
d="M17 19h2v-8h-6v8h2v-6h2v6zM3 19V4a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v5h2v10h1v2H2v-2h1zm4-8v2h2v-2H7zm0 4v2h2v-2H7zm0-8v2h2V7H7z"
|
<path
|
||||||
/></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
|
||||||
<span>{$_("orgs")}</span>
|
>
|
||||||
</a>
|
<span>{$_("runners")}</span>
|
||||||
{/if}
|
</a>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("USER:GET")}
|
{/if}
|
||||||
<a
|
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:GET")}
|
||||||
class:bg-gray-100={$router.path === "/users/"}
|
<a
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
class:activenav={$router.path.includes("/teams/")}
|
||||||
href="/users/"
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
>
|
href="/teams/"
|
||||||
<svg
|
>
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<svg
|
||||||
width="24"
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
height="24"
|
fill="currentColor"
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
width="24"
|
||||||
fill="currentColor"
|
height="24"
|
||||||
viewBox="0 0 24 24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
viewBox="0 0 640 512"
|
||||||
<path
|
><path
|
||||||
d="M12 14v8H4a8 8 0 018-8zm0-1a6 6 0 110-12 6 6 0 010 12zm2.6 5.81a3.51 3.51 0 010-1.62l-1-.57 1-1.74 1 .58a3.5 3.5 0 011.4-.82V13.5h2v1.15a3.5 3.5 0 011.4.8l1-.57 1 1.74-1 .57a3.51 3.51 0 010 1.62l1 .57-1 1.74-1-.58a3.5 3.5 0 01-1.4.82v1.14h-2v-1.15a3.5 3.5 0 01-1.4-.8l-1 .57-1-1.74 1-.57zM18 17a1 1 0 100 2 1 1 0 000-2z"
|
fill="currentColor"
|
||||||
/></svg
|
d="M96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm448 0c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm32 32h-64c-17.6 0-33.5 7.1-45.1 18.6 40.3 22.1 68.9 62 75.1 109.4h66c17.7 0 32-14.3 32-32v-32c0-35.3-28.7-64-64-64zm-256 0c61.9 0 112-50.1 112-112S381.9 32 320 32 208 82.1 208 144s50.1 112 112 112zm76.8 32h-8.3c-20.8 10-43.9 16-68.5 16s-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48v-28.8c0-63.6-51.6-115.2-115.2-115.2zm-223.7-13.4C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z"
|
||||||
>
|
/></svg
|
||||||
<span>{$_("users")}</span>
|
>
|
||||||
</a>
|
<span>{$_("teams")}</span>
|
||||||
{/if}
|
</a>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("USERGROUP:GET")}
|
{/if}
|
||||||
<a
|
{#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION:GET")}
|
||||||
class:bg-gray-100={$router.path === "/groups/"}
|
<a
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
class:activenav={$router.path.includes("/orgs/")}
|
||||||
href="/groups/"
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
>
|
href="/orgs/"
|
||||||
<svg
|
>
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
<svg
|
||||||
fill="currentColor"
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
width="24"
|
fill="currentColor"
|
||||||
height="24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
viewBox="0 0 24 24"
|
||||||
viewBox="0 0 640 512"
|
width="24"
|
||||||
><path
|
height="24"
|
||||||
fill="currentColor"
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
d="M610.5 341.3c2.6-14.1 2.6-28.5 0-42.6l25.8-14.9c3-1.7 4.3-5.2 3.3-8.5-6.7-21.6-18.2-41.2-33.2-57.4-2.3-2.5-6-3.1-9-1.4l-25.8 14.9c-10.9-9.3-23.4-16.5-36.9-21.3v-29.8c0-3.4-2.4-6.4-5.7-7.1-22.3-5-45-4.8-66.2 0-3.3.7-5.7 3.7-5.7 7.1v29.8c-13.5 4.8-26 12-36.9 21.3l-25.8-14.9c-2.9-1.7-6.7-1.1-9 1.4-15 16.2-26.5 35.8-33.2 57.4-1 3.3.4 6.8 3.3 8.5l25.8 14.9c-2.6 14.1-2.6 28.5 0 42.6l-25.8 14.9c-3 1.7-4.3 5.2-3.3 8.5 6.7 21.6 18.2 41.1 33.2 57.4 2.3 2.5 6 3.1 9 1.4l25.8-14.9c10.9 9.3 23.4 16.5 36.9 21.3v29.8c0 3.4 2.4 6.4 5.7 7.1 22.3 5 45 4.8 66.2 0 3.3-.7 5.7-3.7 5.7-7.1v-29.8c13.5-4.8 26-12 36.9-21.3l25.8 14.9c2.9 1.7 6.7 1.1 9-1.4 15-16.2 26.5-35.8 33.2-57.4 1-3.3-.4-6.8-3.3-8.5l-25.8-14.9zM496 368.5c-26.8 0-48.5-21.8-48.5-48.5s21.8-48.5 48.5-48.5 48.5 21.8 48.5 48.5-21.7 48.5-48.5 48.5zM96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm224 32c1.9 0 3.7-.5 5.6-.6 8.3-21.7 20.5-42.1 36.3-59.2 7.4-8 17.9-12.6 28.9-12.6 6.9 0 13.7 1.8 19.6 5.3l7.9 4.6c.8-.5 1.6-.9 2.4-1.4 7-14.6 11.2-30.8 11.2-48 0-61.9-50.1-112-112-112S208 82.1 208 144c0 61.9 50.1 112 112 112zm105.2 194.5c-2.3-1.2-4.6-2.6-6.8-3.9-8.2 4.8-15.3 9.8-27.5 9.8-10.9 0-21.4-4.6-28.9-12.6-18.3-19.8-32.3-43.9-40.2-69.6-10.7-34.5 24.9-49.7 25.8-50.3-.1-2.6-.1-5.2 0-7.8l-7.9-4.6c-3.8-2.2-7-5-9.8-8.1-3.3.2-6.5.6-9.8.6-24.6 0-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h255.4c-3.7-6-6.2-12.8-6.2-20.3v-9.2zM173.1 274.6C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z"
|
<path
|
||||||
/></svg
|
d="M17 19h2v-8h-6v8h2v-6h2v6zM3 19V4a1 1 0 0 1 1-1h14a1 1 0 0 1 1 1v5h2v10h1v2H2v-2h1zm4-8v2h2v-2H7zm0 4v2h2v-2H7zm0-8v2h2V7H7z"
|
||||||
>
|
/></svg
|
||||||
<span>{$_("user-groups")}</span>
|
>
|
||||||
</a>
|
<span>{$_("orgs")}</span>
|
||||||
{/if}
|
</a>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET")}
|
{/if}
|
||||||
<a
|
{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:GET")}
|
||||||
class:bg-gray-100={$router.path === "/runners/"}
|
<a
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
class:activenav={$router.path.includes("/donors/")}
|
||||||
href="/runners/"
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
>
|
href="/donors/"
|
||||||
<svg
|
>
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<svg
|
||||||
viewBox="0 0 24 24"
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
fill="currentColor"
|
||||||
fill="currentColor"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
viewBox="0 0 24 24"
|
||||||
height="24"
|
width="24"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
height="24"
|
||||||
<path
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
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"
|
<path
|
||||||
/></svg
|
d="M9.33 11.5h2.17A4.5 4.5 0 0 1 16 16H8.999L9 17h8v-1a5.578 5.578 0 0 0-.886-3H19a5 5 0 0 1 4.516 2.851C21.151 18.972 17.322 21 13 21c-2.761 0-5.1-.59-7-1.625L6 10.071A6.967 6.967 0 0 1 9.33 11.5zM5 19a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v9zM18 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6zm-7-3a3 3 0 1 1 0 6 3 3 0 0 1 0-6z"
|
||||||
>
|
/></svg
|
||||||
<span>{$_("runners")}</span>
|
>
|
||||||
</a>
|
<span>{$_("donors")}</span>
|
||||||
{/if}
|
</a>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:GET")}
|
{/if}
|
||||||
<a
|
{#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:GET")}
|
||||||
class:bg-gray-100={$router.path === "/teams/"}
|
<a
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
class:activenav={$router.path.includes("/donations/")}
|
||||||
href="/teams/"
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
>
|
href="/donations/"
|
||||||
<svg
|
>
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
<svg
|
||||||
fill="currentColor"
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
width="24"
|
fill="currentColor"
|
||||||
height="24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
viewBox="0 0 24 24"
|
||||||
viewBox="0 0 640 512"
|
width="24"
|
||||||
><path
|
height="24"
|
||||||
fill="currentColor"
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
d="M96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm448 0c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm32 32h-64c-17.6 0-33.5 7.1-45.1 18.6 40.3 22.1 68.9 62 75.1 109.4h66c17.7 0 32-14.3 32-32v-32c0-35.3-28.7-64-64-64zm-256 0c61.9 0 112-50.1 112-112S381.9 32 320 32 208 82.1 208 144s50.1 112 112 112zm76.8 32h-8.3c-20.8 10-43.9 16-68.5 16s-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48v-28.8c0-63.6-51.6-115.2-115.2-115.2zm-223.7-13.4C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z"
|
<path
|
||||||
/></svg
|
d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z"
|
||||||
>
|
/></svg
|
||||||
<span>{$_("teams")}</span>
|
>
|
||||||
</a>
|
<span>{$_("donations")}</span>
|
||||||
{/if}
|
</a>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:GET")}
|
{/if}
|
||||||
<a
|
{#if store.state.jwtinfo.userdetails.permissions.includes("TRACK:GET")}
|
||||||
class:bg-gray-100={$router.path.includes("/donors/")}
|
<a
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
class:activenav={$router.path === "/tracks/"}
|
||||||
href="/donors/"
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
>
|
href="/tracks/"
|
||||||
<svg
|
>
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
<svg
|
||||||
fill="currentColor"
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
fill="currentColor"
|
||||||
viewBox="0 0 24 24"
|
width="24"
|
||||||
width="24"
|
height="24"
|
||||||
height="24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
viewBox="0 0 640 512"
|
||||||
<path
|
><path
|
||||||
d="M9.33 11.5h2.17A4.5 4.5 0 0 1 16 16H8.999L9 17h8v-1a5.578 5.578 0 0 0-.886-3H19a5 5 0 0 1 4.516 2.851C21.151 18.972 17.322 21 13 21c-2.761 0-5.1-.59-7-1.625L6 10.071A6.967 6.967 0 0 1 9.33 11.5zM5 19a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v9zM18 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6zm-7-3a3 3 0 1 1 0 6 3 3 0 0 1 0-6z"
|
fill="currentColor"
|
||||||
/></svg
|
d="M635.7 167.2L556.1 31.7c-8.8-15-28.3-20.1-43.5-11.5l-69 39.1L503.3 161c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L416 75l-55.2 31.3 27.9 47.4c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L333.2 122 278 153.3 337.8 255c2.2 3.7.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9l-59.7-101.7-55.2 31.3 27.9 47.4c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9l-27.9-47.5-55.2 31.3 59.7 101.7c2.2 3.7.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L84.9 262.9l-69 39.1C.7 310.7-4.6 329.8 4.2 344.8l79.6 135.6c8.8 15 28.3 20.1 43.5 11.5L624.1 210c15.2-8.6 20.4-27.8 11.6-42.8z"
|
||||||
>
|
/></svg
|
||||||
<span>{$_("donors")}</span>
|
>
|
||||||
</a>
|
<span>{$_("tracks")}</span>
|
||||||
{/if}
|
</a>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:GET")}
|
{/if}
|
||||||
<a
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:GET")}
|
||||||
class:bg-gray-100={$router.path.includes("/donations/")}
|
<a
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
class:activenav={$router.path === "/cards/"}
|
||||||
href="/donations/"
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
>
|
href="/cards/"
|
||||||
<svg
|
>
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
<svg
|
||||||
fill="currentColor"
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
fill="currentColor"
|
||||||
viewBox="0 0 24 24"
|
width="24"
|
||||||
width="24"
|
height="24"
|
||||||
height="24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
viewBox="0 0 24 24"
|
||||||
<path
|
>
|
||||||
d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z"
|
<path fill="none" d="M0 0h24v24H0z" />
|
||||||
/></svg
|
<path
|
||||||
>
|
fill="currentColor"
|
||||||
<span>{$_("donations")}</span>
|
d="M22 10v10a1 1 0 01-1 1H3a1 1 0 01-1-1V10h20zm0-2H2V4a1 1 0 011-1h18a1 1 0 011 1v4zm-7 8v2h4v-2h-4z"
|
||||||
</a>
|
/></svg
|
||||||
{/if}
|
>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("TRACK:GET")}
|
<span>{$_("cards")}</span>
|
||||||
<a
|
</a>
|
||||||
class:bg-gray-100={$router.path === "/tracks/"}
|
{/if}
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
{#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:GET")}
|
||||||
href="/tracks/"
|
<a
|
||||||
>
|
class:activenav={$router.path.includes("/scans/")}
|
||||||
<svg
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
href="/scans/"
|
||||||
fill="currentColor"
|
>
|
||||||
width="24"
|
<svg
|
||||||
height="24"
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
fill="currentColor"
|
||||||
viewBox="0 0 640 512"
|
width="24"
|
||||||
><path
|
height="24"
|
||||||
fill="currentColor"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
d="M635.7 167.2L556.1 31.7c-8.8-15-28.3-20.1-43.5-11.5l-69 39.1L503.3 161c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L416 75l-55.2 31.3 27.9 47.4c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L333.2 122 278 153.3 337.8 255c2.2 3.7.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9l-59.7-101.7-55.2 31.3 27.9 47.4c2.2 3.8.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9l-27.9-47.5-55.2 31.3 59.7 101.7c2.2 3.7.9 8.5-2.9 10.7l-13.8 7.8c-3.8 2.2-8.7.9-10.9-2.9L84.9 262.9l-69 39.1C.7 310.7-4.6 329.8 4.2 344.8l79.6 135.6c8.8 15 28.3 20.1 43.5 11.5L624.1 210c15.2-8.6 20.4-27.8 11.6-42.8z"
|
viewBox="0 0 24 24"
|
||||||
/></svg
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
>
|
<path
|
||||||
<span>{$_("tracks")}</span>
|
fill="currentColor"
|
||||||
</a>
|
d="M2 4h2v16H2V4zm4 0h1v16H6V4zm2 0h2v16H8V4zm3 0h2v16h-2V4zm3 0h2v16h-2V4zm3 0h1v16h-1V4zm2 0h3v16h-3V4z"
|
||||||
{/if}
|
/></svg
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:GET")}
|
>
|
||||||
<a
|
<span>Scans</span>
|
||||||
class:bg-gray-100={$router.path === "/cards/"}
|
</a>
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
{/if}
|
||||||
href="/cards/"
|
{#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT:GET")}
|
||||||
>
|
<a
|
||||||
<svg
|
class:activenav={$router.path.includes("/contacts/")}
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
fill="currentColor"
|
href="/contacts/"
|
||||||
width="24"
|
>
|
||||||
height="24"
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
fill="currentColor"
|
||||||
viewBox="0 0 24 24"
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
>
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
<path fill="none" d="M0 0h24v24H0z" />
|
viewBox="0 0 24 24"
|
||||||
<path
|
width="24"
|
||||||
fill="currentColor"
|
height="24"
|
||||||
d="M22 10v10a1 1 0 01-1 1H3a1 1 0 01-1-1V10h20zm0-2H2V4a1 1 0 011-1h18a1 1 0 011 1v4zm-7 8v2h4v-2h-4z"
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
/></svg
|
<path
|
||||||
>
|
d="M2 22a8 8 0 1 1 16 0H2zm8-9c-3.315 0-6-2.685-6-6s2.685-6 6-6 6 2.685 6 6-2.685 6-6 6zm10 4h4v2h-4v-2zm-3-5h7v2h-7v-2zm2-5h5v2h-5V7z"
|
||||||
<span>{$_("cards")}</span>
|
/></svg
|
||||||
</a>
|
>
|
||||||
{/if}
|
<span>{$_("contacts")}</span>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:GET")}
|
</a>
|
||||||
<a
|
{/if}
|
||||||
class:bg-gray-100={$router.path === "/scans/"}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("STATION:GET")}
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
<a
|
||||||
href="/scans/"
|
class:activenav={$router.path.includes("/scanstations/")}
|
||||||
>
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
<svg
|
href="/scanstations/"
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
>
|
||||||
fill="currentColor"
|
<svg
|
||||||
width="24"
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
height="24"
|
fill="currentColor"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
width="24"
|
||||||
viewBox="0 0 24 24"
|
height="24"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
viewBox="0 0 24 24"
|
||||||
<path
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
fill="currentColor"
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
d="M2 4h2v16H2V4zm4 0h1v16H6V4zm2 0h2v16H8V4zm3 0h2v16h-2V4zm3 0h2v16h-2V4zm3 0h1v16h-1V4zm2 0h3v16h-3V4z"
|
<path
|
||||||
/></svg
|
fill="currentColor"
|
||||||
>
|
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z"
|
||||||
<span>Scans</span>
|
/></svg
|
||||||
</a>
|
>
|
||||||
{/if}
|
<span>{$_("scanstations")}</span>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT:GET")}
|
</a>
|
||||||
<a
|
{/if}
|
||||||
class:bg-gray-100={$router.path === "/contacts/"}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:GET")}
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
<a
|
||||||
href="/contacts/"
|
class:activenav={$router.path.includes("/statsclients/")}
|
||||||
>
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
<svg
|
href="/statsclients/"
|
||||||
fill="currentColor"
|
>
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
viewBox="0 0 24 24"
|
fill="currentColor"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
viewBox="0 0 24 24"
|
||||||
<path
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
d="M2 22a8 8 0 1 1 16 0H2zm8-9c-3.315 0-6-2.685-6-6s2.685-6 6-6 6 2.685 6 6-2.685 6-6 6zm10 4h4v2h-4v-2zm-3-5h7v2h-7v-2zm2-5h5v2h-5V7z"
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
/></svg
|
<path
|
||||||
>
|
fill="currentColor"
|
||||||
<span>{$_("contacts")}</span>
|
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z"
|
||||||
</a>
|
/></svg
|
||||||
{/if}
|
>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("STATION:GET")}
|
<span>{$_("statsclients")}</span>
|
||||||
<a
|
</a>
|
||||||
class:bg-gray-100={$router.path === "/scanstations/"}
|
{/if}
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
{#if store.state.jwtinfo.userdetails.permissions.includes("USER:GET")}
|
||||||
href="/scanstations/"
|
<a
|
||||||
>
|
class:activenav={$router.path.includes("/users/")}
|
||||||
<svg
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
href="/users/"
|
||||||
fill="currentColor"
|
>
|
||||||
width="24"
|
<svg
|
||||||
height="24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
width="24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
height="24"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
<path
|
fill="currentColor"
|
||||||
fill="currentColor"
|
viewBox="0 0 24 24"
|
||||||
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z"
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
/></svg
|
<path
|
||||||
>
|
d="M12 14v8H4a8 8 0 018-8zm0-1a6 6 0 110-12 6 6 0 010 12zm2.6 5.81a3.51 3.51 0 010-1.62l-1-.57 1-1.74 1 .58a3.5 3.5 0 011.4-.82V13.5h2v1.15a3.5 3.5 0 011.4.8l1-.57 1 1.74-1 .57a3.51 3.51 0 010 1.62l1 .57-1 1.74-1-.58a3.5 3.5 0 01-1.4.82v1.14h-2v-1.15a3.5 3.5 0 01-1.4-.8l-1 .57-1-1.74 1-.57zM18 17a1 1 0 100 2 1 1 0 000-2z"
|
||||||
<span>{$_("scanstations")}</span>
|
/></svg
|
||||||
</a>
|
>
|
||||||
{/if}
|
<span>{$_("users")}</span>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:GET")}
|
</a>
|
||||||
<a
|
{/if}
|
||||||
class:bg-gray-100={$router.path === "/statsclients/"}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("USERGROUP:GET")}
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
<a
|
||||||
href="/statsclients/"
|
class:activenav={$router.path.includes("/groups/")}
|
||||||
>
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
<svg
|
href="/groups/"
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
>
|
||||||
fill="currentColor"
|
<svg
|
||||||
width="24"
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
height="24"
|
fill="currentColor"
|
||||||
viewBox="0 0 24 24"
|
width="24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
height="24"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
<path
|
viewBox="0 0 640 512"
|
||||||
fill="currentColor"
|
><path
|
||||||
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z"
|
fill="currentColor"
|
||||||
/></svg
|
d="M610.5 341.3c2.6-14.1 2.6-28.5 0-42.6l25.8-14.9c3-1.7 4.3-5.2 3.3-8.5-6.7-21.6-18.2-41.2-33.2-57.4-2.3-2.5-6-3.1-9-1.4l-25.8 14.9c-10.9-9.3-23.4-16.5-36.9-21.3v-29.8c0-3.4-2.4-6.4-5.7-7.1-22.3-5-45-4.8-66.2 0-3.3.7-5.7 3.7-5.7 7.1v29.8c-13.5 4.8-26 12-36.9 21.3l-25.8-14.9c-2.9-1.7-6.7-1.1-9 1.4-15 16.2-26.5 35.8-33.2 57.4-1 3.3.4 6.8 3.3 8.5l25.8 14.9c-2.6 14.1-2.6 28.5 0 42.6l-25.8 14.9c-3 1.7-4.3 5.2-3.3 8.5 6.7 21.6 18.2 41.1 33.2 57.4 2.3 2.5 6 3.1 9 1.4l25.8-14.9c10.9 9.3 23.4 16.5 36.9 21.3v29.8c0 3.4 2.4 6.4 5.7 7.1 22.3 5 45 4.8 66.2 0 3.3-.7 5.7-3.7 5.7-7.1v-29.8c13.5-4.8 26-12 36.9-21.3l25.8 14.9c2.9 1.7 6.7 1.1 9-1.4 15-16.2 26.5-35.8 33.2-57.4 1-3.3-.4-6.8-3.3-8.5l-25.8-14.9zM496 368.5c-26.8 0-48.5-21.8-48.5-48.5s21.8-48.5 48.5-48.5 48.5 21.8 48.5 48.5-21.7 48.5-48.5 48.5zM96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm224 32c1.9 0 3.7-.5 5.6-.6 8.3-21.7 20.5-42.1 36.3-59.2 7.4-8 17.9-12.6 28.9-12.6 6.9 0 13.7 1.8 19.6 5.3l7.9 4.6c.8-.5 1.6-.9 2.4-1.4 7-14.6 11.2-30.8 11.2-48 0-61.9-50.1-112-112-112S208 82.1 208 144c0 61.9 50.1 112 112 112zm105.2 194.5c-2.3-1.2-4.6-2.6-6.8-3.9-8.2 4.8-15.3 9.8-27.5 9.8-10.9 0-21.4-4.6-28.9-12.6-18.3-19.8-32.3-43.9-40.2-69.6-10.7-34.5 24.9-49.7 25.8-50.3-.1-2.6-.1-5.2 0-7.8l-7.9-4.6c-3.8-2.2-7-5-9.8-8.1-3.3.2-6.5.6-9.8.6-24.6 0-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h255.4c-3.7-6-6.2-12.8-6.2-20.3v-9.2zM173.1 274.6C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z"
|
||||||
>
|
/></svg
|
||||||
<span>{$_("statsclients")}</span>
|
>
|
||||||
</a>
|
<span>{$_("user-groups")}</span>
|
||||||
{/if}
|
</a>
|
||||||
<a
|
{/if}
|
||||||
class:bg-gray-100={$router.path === "/settings/"}
|
<a
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
class:activenav={$router.path === "/settings/"}
|
||||||
href="/settings/"
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
>
|
href="/settings/"
|
||||||
<svg
|
>
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
viewBox="0 0 20 20"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
fill="currentColor"
|
viewBox="0 0 20 20"
|
||||||
>
|
fill="currentColor"
|
||||||
<path
|
>
|
||||||
fill-rule="evenodd"
|
<path
|
||||||
d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z"
|
fill-rule="evenodd"
|
||||||
clip-rule="evenodd"
|
d="M11.49 3.17c-.38-1.56-2.6-1.56-2.98 0a1.532 1.532 0 01-2.286.948c-1.372-.836-2.942.734-2.106 2.106.54.886.061 2.042-.947 2.287-1.561.379-1.561 2.6 0 2.978a1.532 1.532 0 01.947 2.287c-.836 1.372.734 2.942 2.106 2.106a1.532 1.532 0 012.287.947c.379 1.561 2.6 1.561 2.978 0a1.533 1.533 0 012.287-.947c1.372.836 2.942-.734 2.106-2.106a1.533 1.533 0 01.947-2.287c1.561-.379 1.561-2.6 0-2.978a1.532 1.532 0 01-.947-2.287c.836-1.372-.734-2.942-2.106-2.106a1.532 1.532 0 01-2.287-.947zM10 13a3 3 0 100-6 3 3 0 000 6z"
|
||||||
/>
|
clip-rule="evenodd"
|
||||||
</svg>
|
/>
|
||||||
<span>{$_("settings")}</span>
|
</svg>
|
||||||
</a>
|
<span>{$_("settings")}</span>
|
||||||
<a
|
</a>
|
||||||
class:bg-gray-100={$router.path === "/about/"}
|
<a
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
class:activenav={$router.path === "/about/"}
|
||||||
href="/about/"
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
>
|
href="/about/"
|
||||||
<svg
|
>
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
fill="none"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
stroke="currentColor"
|
fill="none"
|
||||||
stroke-width="2"
|
stroke="currentColor"
|
||||||
stroke-linecap="round"
|
stroke-width="2"
|
||||||
stroke-linejoin="round"
|
stroke-linecap="round"
|
||||||
viewBox="0 0 24 24"
|
stroke-linejoin="round"
|
||||||
><circle cx="12" cy="12" r="10" />
|
viewBox="0 0 24 24"
|
||||||
<path d="M12 16v-4M12 8h.01" /></svg
|
><circle cx="12" cy="12" r="10" />
|
||||||
>
|
<path d="M12 16v-4M12 8h.01" /></svg
|
||||||
<span>{$_("about")}</span>
|
>
|
||||||
</a>
|
<span>{$_("about")}</span>
|
||||||
<button
|
</a>
|
||||||
tabindex="0"
|
<button
|
||||||
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
|
tabindex="0"
|
||||||
on:click={() => {
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
AuthService.authControllerLogout();
|
on:click={() => {
|
||||||
logout();
|
AuthService.authControllerLogout();
|
||||||
}}
|
logout();
|
||||||
>
|
}}
|
||||||
<svg
|
>
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2 text-gray-400 transition group-hover:text-gray-600"
|
<svg
|
||||||
fill="currentColor"
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
width="24"
|
fill="currentColor"
|
||||||
height="24"
|
width="24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
height="24"
|
||||||
viewBox="0 0 24 24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
viewBox="0 0 24 24"
|
||||||
<path
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2a9.985 9.985 0 0 1 8 4h-2.71a8 8 0 1 0 .001 12h2.71A9.985 9.985 0 0 1 12 22zm7-6v-3h-8v-2h8V8l5 4-5 4z"
|
<path
|
||||||
/></svg
|
d="M12 22C6.477 22 2 17.523 2 12S6.477 2 12 2a9.985 9.985 0 0 1 8 4h-2.71a8 8 0 1 0 .001 12h2.71A9.985 9.985 0 0 1 12 22zm7-6v-3h-8v-2h8V8l5 4-5 4z"
|
||||||
>
|
/></svg
|
||||||
<span>{$_("logout")}</span>
|
>
|
||||||
</button>
|
<span>{$_("logout")}</span>
|
||||||
</nav>
|
</button>
|
||||||
</div>
|
</nav>
|
||||||
<div class="ml-0 transition md:ml-60">
|
</div>
|
||||||
<header
|
<div class="ml-0 transition md:ml-60">
|
||||||
class="flex items-center justify-between w-full px-4 bg-white border-b h-14 md:hidden"
|
<header
|
||||||
>
|
class="flex items-center w-full px-4 bg-white border-b h-14 md:hidden"
|
||||||
<button
|
>
|
||||||
on:click={() => {
|
<button
|
||||||
navOpen = true;
|
on:click={() => {
|
||||||
}}
|
navOpen = true;
|
||||||
class="block btn btn-light md:hidden"
|
}}
|
||||||
>
|
class="block btn btn-light md:hidden"
|
||||||
<span class="sr-only">Menu</span><svg
|
>
|
||||||
class="w-4 h-4"
|
<span class="sr-only">Menu</span><svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 20 20"
|
fill="none"
|
||||||
fill="currentcolor"
|
viewBox="0 0 24 24"
|
||||||
><path
|
stroke-width="1.5"
|
||||||
fill-rule="evenodd"
|
stroke="currentColor"
|
||||||
d="M3 5a1 1 0 011-1h12a1 1 0 110 2H4A1 1 0 013 5zm0 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1zm0 5a1 1 0 011-1h12a1 1 0 110 2H4a1 1 0 01-1-1z"
|
class="size-6"
|
||||||
clip-rule="evenodd"
|
>
|
||||||
/></svg
|
<path
|
||||||
></button
|
stroke-linecap="round"
|
||||||
>
|
stroke-linejoin="round"
|
||||||
</header>
|
d="M3.75 6.75h16.5M3.75 12h16.5m-16.5 5.25h16.5"
|
||||||
<Toaster position="top-right" />
|
/>
|
||||||
<slot>
|
</svg>
|
||||||
<NoComponentLoaded />
|
</button>
|
||||||
</slot>
|
<span class="inline-block">
|
||||||
</div>
|
<img src="/lfk-logo.png" alt="Logo" class="h-8 inline-block" />
|
||||||
{#if navOpen === true}
|
<span class="text-lg font-bold">LfK!Admin</span>
|
||||||
<button
|
</span>
|
||||||
on:click={() => {
|
</header>
|
||||||
navOpen = false;
|
<Toaster position="top-right" />
|
||||||
}}
|
<slot>
|
||||||
class:hidden={!navOpen}
|
<NoComponentLoaded />
|
||||||
class="fixed inset-0 z-10 w-screen h-screen bg-black bg-opacity-25 md:hidden"
|
</slot>
|
||||||
/>
|
</div>
|
||||||
{/if}
|
{#if navOpen === true}
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
navOpen = false;
|
||||||
|
}}
|
||||||
|
class:hidden={!navOpen}
|
||||||
|
class="fixed inset-0 z-10 w-screen h-screen bg-black bg-opacity-25 md:hidden"
|
||||||
|
/>
|
||||||
|
{/if}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.collapsed_navigation {
|
.collapsed_navigation {
|
||||||
transform: translateX(-100%);
|
transform: translateX(-100%);
|
||||||
}
|
}
|
||||||
@media (min-width: 768px) {
|
@media (min-width: 768px) {
|
||||||
.collapsed_navigation {
|
.collapsed_navigation {
|
||||||
transform: translateX(0px);
|
transform: translateX(0px);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</style>
|
</style>
|
||||||
@@ -3,18 +3,16 @@
|
|||||||
import { StatsService } from "@odit/lfk-client-js";
|
import { StatsService } from "@odit/lfk-client-js";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import StatCard from "./StatCard.svelte";
|
import StatCard from "./StatCard.svelte";
|
||||||
let navOpen = false;
|
|
||||||
const stats_promise = StatsService.statsControllerGet();
|
const stats_promise = StatsService.statsControllerGet();
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="p-2 md:p-5 overflow-x-hidden">
|
<div class="p-2 md:p-5 overflow-x-hidden">
|
||||||
<h1 class="text-3xl leading-tight mb-4">
|
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_("dashboard-greeting")},
|
{$_("dashboard-greeting")} <span class="text-blue-500"
|
||||||
<span class="text-blue-500"
|
|
||||||
>{store.state.jwtinfo.userdetails.firstname}
|
>{store.state.jwtinfo.userdetails.firstname}
|
||||||
{store.state.jwtinfo.userdetails.lastname}</span
|
{store.state.jwtinfo.userdetails.lastname}</span
|
||||||
>
|
>
|
||||||
</h1>
|
</h4>
|
||||||
{#await stats_promise}
|
{#await stats_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"
|
||||||
@@ -25,7 +23,7 @@
|
|||||||
</div>
|
</div>
|
||||||
{:then stats}
|
{:then stats}
|
||||||
<div
|
<div
|
||||||
class="grid gap-2 grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 2xl:grid-cols-6 sm:gap-4"
|
class="grid gap-1 grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 2xl:grid-cols-6 sm:gap-4"
|
||||||
>
|
>
|
||||||
<StatCard
|
<StatCard
|
||||||
title={$_("runners")}
|
title={$_("runners")}
|
||||||
|
|||||||
@@ -7,13 +7,13 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<a {href}>
|
<a {href}>
|
||||||
<div class="p-4 rounded-lg bg-white border border-grey-100">
|
<div class="p-3 py-4 sm:p-4 rounded-lg bg-white border border-grey-100">
|
||||||
<div class="flex flex-row items-center justify-between">
|
<div class="flex flex-row items-center justify-between">
|
||||||
<div class="flex flex-col">
|
<div class="flex flex-col">
|
||||||
<div class="text-xs uppercase font-normal text-grey-500">
|
<div class="text-md sm:text-xs uppercase font-normal text-grey-500">
|
||||||
{title}
|
{title}
|
||||||
</div>
|
</div>
|
||||||
<div class="text-xl font-bold font-mono">{value}</div>
|
<div class="text-2xl sm:text-xl font-bold font-mono">{value}</div>
|
||||||
</div>
|
</div>
|
||||||
<slot />
|
<slot />
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -8,7 +8,7 @@
|
|||||||
RunnerService,
|
RunnerService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
import Select from "svelte-select";
|
import Select from "svelte-select";
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher, onMount } from "svelte";
|
||||||
import toast from "svelte-french-toast";
|
import toast from "svelte-french-toast";
|
||||||
export let modal_open;
|
export let modal_open;
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
@@ -23,16 +23,6 @@
|
|||||||
$: runners = [];
|
$: runners = [];
|
||||||
$: is_fixed = false;
|
$: is_fixed = false;
|
||||||
$: is_paid = false;
|
$: is_paid = false;
|
||||||
DonorService.donorControllerGetAll().then((val) => {
|
|
||||||
donors = val.map((r) => {
|
|
||||||
return { label: getDonorLabel(r), value: r };
|
|
||||||
});
|
|
||||||
});
|
|
||||||
RunnerService.runnerControllerGetAll().then((val) => {
|
|
||||||
runners = val.map((r) => {
|
|
||||||
return { label: getDonorLabel(r), value: r };
|
|
||||||
});
|
|
||||||
});
|
|
||||||
$: amount_input = 0;
|
$: amount_input = 0;
|
||||||
$: processed_last_submit = true;
|
$: processed_last_submit = true;
|
||||||
$: is_amount_valid = amount_input > 0;
|
$: is_amount_valid = amount_input > 0;
|
||||||
@@ -89,7 +79,7 @@
|
|||||||
amountPerDistance: amount_cent,
|
amountPerDistance: amount_cent,
|
||||||
};
|
};
|
||||||
DonationService.donationControllerPostDistance(postdata)
|
DonationService.donationControllerPostDistance(postdata)
|
||||||
.then((result) => {
|
.then((result) => {
|
||||||
donor = donors[0].id || 0;
|
donor = donors[0].id || 0;
|
||||||
runner = runners[0].id || 0;
|
runner = runners[0].id || 0;
|
||||||
amount_input = 0;
|
amount_input = 0;
|
||||||
@@ -108,6 +98,19 @@
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
donors = (await DonorService.donorControllerGetAll()).map(
|
||||||
|
(r) => {
|
||||||
|
return { label: getDonorLabel(r), value: r };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
runners = (await RunnerService.runnerControllerGetAll()).map(
|
||||||
|
(r) => {
|
||||||
|
return { label: getDonorLabel(r), value: r };
|
||||||
|
}
|
||||||
|
);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
@@ -189,7 +192,7 @@
|
|||||||
>{$_("donor")}</label
|
>{$_("donor")}</label
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
itemFilter={(label, filterText, option) =>
|
itemFilter={(label, filterText, option) =>
|
||||||
filterDonors(label, filterText, option)}
|
filterDonors(label, filterText, option)}
|
||||||
items={donors}
|
items={donors}
|
||||||
@@ -209,7 +212,7 @@
|
|||||||
>{$_("runner")}</label
|
>{$_("runner")}</label
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
itemFilter={(label, filterText, option) =>
|
itemFilter={(label, filterText, option) =>
|
||||||
filterDonors(label, filterText, option)}
|
filterDonors(label, filterText, option)}
|
||||||
items={runners}
|
items={runners}
|
||||||
@@ -241,7 +244,7 @@
|
|||||||
type="number"
|
type="number"
|
||||||
step="0.01"
|
step="0.01"
|
||||||
name="donation_amount_eur"
|
name="donation_amount_eur"
|
||||||
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
|
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 p-2"
|
||||||
placeholder="2.00"
|
placeholder="2.00"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -33,7 +33,7 @@
|
|||||||
toast.loading($_("updating-donation"));
|
toast.loading($_("updating-donation"));
|
||||||
const editable = Object.assign({}, original_data);
|
const editable = Object.assign({}, original_data);
|
||||||
editable.donor = editable.donor.id;
|
editable.donor = editable.donor.id;
|
||||||
editable.paidAmount = paid_amount_input * 100;
|
editable.paidAmount = Math.round(paid_amount_input * 100);
|
||||||
if (editable.responseType == "DISTANCEDONATION" || editable.runner) {
|
if (editable.responseType == "DISTANCEDONATION" || editable.runner) {
|
||||||
editable.runner = editable.runner.id;
|
editable.runner = editable.runner.id;
|
||||||
DonationService.donationControllerPutDistance(
|
DonationService.donationControllerPutDistance(
|
||||||
@@ -46,7 +46,7 @@
|
|||||||
toast.dismiss();
|
toast.dismiss();
|
||||||
|
|
||||||
toast.success($_("donation-updated"));
|
toast.success($_("donation-updated"));
|
||||||
dispatch("created", { donation: response });
|
dispatch("created", { donation: result });
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
//
|
//
|
||||||
@@ -61,7 +61,7 @@
|
|||||||
//
|
//
|
||||||
toast.dismiss();
|
toast.dismiss();
|
||||||
toast.success($_("donation-updated"));
|
toast.success($_("donation-updated"));
|
||||||
dispatch("created", { donation: response });
|
dispatch("created", { donation: result });
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
//
|
//
|
||||||
|
|||||||
@@ -1,364 +1,352 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import {
|
import {
|
||||||
DonationService,
|
DonationService,
|
||||||
DonorService,
|
DonorService,
|
||||||
RunnerService,
|
RunnerService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
|
import toast from "svelte-french-toast";
|
||||||
|
|
||||||
import PromiseError from "../base/PromiseError.svelte";
|
import PromiseError from "../base/PromiseError.svelte";
|
||||||
import Select from "svelte-select";
|
import Select from "svelte-select";
|
||||||
let data_loaded = false;
|
let data_loaded = false;
|
||||||
export let params;
|
export let params;
|
||||||
$: delete_triggered = false;
|
$: delete_triggered = false;
|
||||||
$: original_data = {};
|
$: original_data = {};
|
||||||
$: editable = {};
|
$: editable = {};
|
||||||
$: donor = {};
|
$: donor = {};
|
||||||
$: runner = {};
|
$: runner = {};
|
||||||
$: current_donors = [];
|
$: current_donors = [];
|
||||||
$: current_runners = [];
|
$: current_runners = [];
|
||||||
$: amount_input = 0;
|
$: amount_input = 0;
|
||||||
$: is_amount_valid = amount_input > 0;
|
$: is_amount_valid = amount_input > 0;
|
||||||
$: paid_amount_input = 0;
|
$: paid_amount_input = 0;
|
||||||
$: is_paid_amount_valid = paid_amount_input > 0;
|
$: is_paid_amount_valid = paid_amount_input > 0;
|
||||||
$: is_everything_set =
|
$: is_everything_set =
|
||||||
editable.donor != null &&
|
editable.donor != null &&
|
||||||
((original_data.responseType == "DISTANCEDONATION" &&
|
((original_data.responseType == "DISTANCEDONATION" &&
|
||||||
editable?.runner != null) ||
|
editable?.runner != null) ||
|
||||||
original_data.responseType !== "DISTANCEDONATION");
|
original_data.responseType !== "DISTANCEDONATION");
|
||||||
$: changes_performed =
|
$: changes_performed =
|
||||||
!(JSON.stringify(original_data) === JSON.stringify(editable)) ||
|
!(JSON.stringify(original_data) === JSON.stringify(editable)) ||
|
||||||
(original_data.responseType == "DISTANCEDONATION" &&
|
(original_data.responseType == "DISTANCEDONATION" &&
|
||||||
!(Math.floor(amount_input * 100) === original_data.amountPerDistance)) ||
|
!(Math.floor(amount_input * 100) === original_data.amountPerDistance)) ||
|
||||||
(original_data.responseType !== "DISTANCEDONATION" &&
|
(original_data.responseType !== "DISTANCEDONATION" &&
|
||||||
!(Math.floor(amount_input * 100) === original_data.amount)) ||
|
!(Math.floor(amount_input * 100) === original_data.amount)) ||
|
||||||
!(Math.floor(paid_amount_input * 100) === original_data.paidAmount);
|
!(Math.floor(paid_amount_input * 100) === original_data.paidAmount);
|
||||||
$: save_enabled = changes_performed && is_amount_valid && is_everything_set;
|
$: save_enabled = changes_performed && is_amount_valid && is_everything_set;
|
||||||
|
|
||||||
const promise = DonationService.donationControllerGetOne(
|
const promise = DonationService.donationControllerGetOne(
|
||||||
params.donationid
|
params.donationid
|
||||||
).then((data) => {
|
).then((data) => {
|
||||||
data_loaded = true;
|
data_loaded = true;
|
||||||
original_data = Object.assign({}, data);
|
original_data = Object.assign({}, data);
|
||||||
editable = Object.assign({}, original_data);
|
editable = Object.assign({}, original_data);
|
||||||
paid_amount_input = data.paidAmount / 100;
|
paid_amount_input = data.paidAmount / 100;
|
||||||
if (data.responseType == "DISTANCEDONATION") {
|
if (data.responseType == "DISTANCEDONATION") {
|
||||||
amount_input = data.amountPerDistance / 100;
|
amount_input = data.amountPerDistance / 100;
|
||||||
RunnerService.runnerControllerGetAll().then((val) => {
|
RunnerService.runnerControllerGetAll().then((val) => {
|
||||||
current_runners = val.map((r) => {
|
current_runners = val.map((r) => {
|
||||||
return { label: getDonorLabel(r), value: r };
|
return { label: getDonorLabel(r), value: r };
|
||||||
});
|
});
|
||||||
runner = current_runners.find((g) => g.value.id == editable.runner.id);
|
runner = current_runners.find((g) => g.value.id == editable.runner.id);
|
||||||
});
|
});
|
||||||
} else {
|
} else {
|
||||||
amount_input = data.amount / 100;
|
amount_input = data.amount / 100;
|
||||||
}
|
}
|
||||||
DonorService.donorControllerGetAll().then((val) => {
|
DonorService.donorControllerGetAll().then((val) => {
|
||||||
current_donors = val.map((r) => {
|
current_donors = val.map((r) => {
|
||||||
return { label: getDonorLabel(r), value: r };
|
return { label: getDonorLabel(r), value: r };
|
||||||
});
|
});
|
||||||
donor = current_donors.find((g) => g.value.id == editable.donor.id);
|
donor = current_donors.find((g) => g.value.id == editable.donor.id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
const getDonorLabel = (option) =>
|
const getDonorLabel = (option) =>
|
||||||
option.firstname + " " + (option.middlename || "") + " " + option.lastname;
|
option.firstname + " " + (option.middlename || "") + " " + option.lastname;
|
||||||
const filterDonors = (label, filterText, option) =>
|
const filterDonors = (label, filterText, option) =>
|
||||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
option.value.id.toString().startsWith(filterText.toLowerCase());
|
option.value.id.toString().startsWith(filterText.toLowerCase());
|
||||||
|
|
||||||
function submit() {
|
function submit() {
|
||||||
if (data_loaded === true && save_enabled) {
|
if (data_loaded === true && save_enabled) {
|
||||||
toast($_("updating-donation"));
|
toast($_("updating-donation"));
|
||||||
let postdata = {};
|
let postdata = {};
|
||||||
editable.paidAmount = paid_amount_input * 100;
|
editable.paidAmount = paid_amount_input * 100;
|
||||||
if (original_data.responseType === "DISTANCEDONATION") {
|
if (original_data.responseType === "DISTANCEDONATION") {
|
||||||
editable.amountPerDistance = Math.floor(amount_input * 100);
|
editable.amountPerDistance = Math.floor(amount_input * 100);
|
||||||
postdata = Object.assign(postdata, editable);
|
postdata = Object.assign(postdata, editable);
|
||||||
postdata.runner = postdata.runner.id;
|
postdata.runner = postdata.runner.id;
|
||||||
postdata.donor = postdata.donor.id;
|
postdata.donor = postdata.donor.id;
|
||||||
DonationService.donationControllerPutDistance(
|
DonationService.donationControllerPutDistance(
|
||||||
original_data.id,
|
original_data.id,
|
||||||
postdata
|
postdata
|
||||||
)
|
)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
Object.assign(original_data, editable);
|
Object.assign(original_data, editable);
|
||||||
original_data = original_data;
|
original_data = original_data;
|
||||||
toast.success($_("donation-updated"));
|
toast.success($_("donation-updated"));
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
} else {
|
} else {
|
||||||
editable.amount = Math.floor(amount_input * 100);
|
editable.amount = Math.floor(amount_input * 100);
|
||||||
postdata = Object.assign(postdata, editable);
|
postdata = Object.assign(postdata, editable);
|
||||||
postdata.donor = postdata.donor.id;
|
postdata.donor = postdata.donor.id;
|
||||||
DonationService.donationControllerPutFixed(original_data.id, postdata)
|
DonationService.donationControllerPutFixed(original_data.id, postdata)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
Object.assign(original_data, editable);
|
Object.assign(original_data, editable);
|
||||||
original_data = original_data;
|
original_data = original_data;
|
||||||
toast.success($_("donation-updated"));
|
toast.success($_("donation-updated"));
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function deleteDonation() {
|
function deleteDonation() {
|
||||||
DonationService.donationControllerRemove(original_data.id, false)
|
DonationService.donationControllerRemove(original_data.id, false)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
toast($_("donation-deleted"));
|
toast($_("donation-deleted"));
|
||||||
location.replace("./");
|
location.replace("./");
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
modal_open = true;
|
modal_open = true;
|
||||||
delete_donor = original_data;
|
delete_donor = original_data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#await promise}
|
{#await promise}
|
||||||
{$_("loading-donation-details")}
|
{$_("loading-donation-details")}
|
||||||
{: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">
|
||||||
<div class="w-full">
|
<div class="mt-2 w-full">
|
||||||
<nav class="w-full flex">
|
<nav class="w-full flex">
|
||||||
<ol class="list-none flex flex-row items-center justify-start">
|
<ol class="list-none flex flex-row items-center justify-start">
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
<svg
|
<a class="mr-2" href="./"
|
||||||
fill="currentColor"
|
><svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
width="24"
|
||||||
width="24"
|
height="24"
|
||||||
height="24"
|
viewBox="0 0 24 24"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
fill="none"
|
||||||
<path
|
stroke="currentColor"
|
||||||
d="M14 2a8 8 0 013.3 15.3A8 8 0 116.7 6.7 8 8 0 0114 2zm-3 7H9v1a2.5 2.5 0 00-.16 5h2.25a.5.5 0 010 1H7v2h2v1h2v-1a2.5 2.5 0 00.16-5H8.91a.5.5 0 010-1H13v-2h-2V9zm3-5a5.99 5.99 0 00-4.48 2.01 8 8 0 018.47 8.47A6 6 0 0014 4z"
|
stroke-width="2"
|
||||||
/></svg
|
stroke-linecap="round"
|
||||||
>
|
stroke-linejoin="round"
|
||||||
</li>
|
class="inline-block"
|
||||||
<li class="flex items-center ml-2">
|
><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg
|
||||||
<a class="mr-2" href="./">{$_("donations")}</a><svg
|
>
|
||||||
stroke="currentColor"
|
{$_("donations")}</a
|
||||||
fill="none"
|
>
|
||||||
stroke-width="2"
|
</li>
|
||||||
viewBox="0 0 24 24"
|
</ol>
|
||||||
stroke-linecap="round"
|
</nav>
|
||||||
stroke-linejoin="round"
|
</div>
|
||||||
class="h-3 w-3 mr-2 stroke-current"
|
</div>
|
||||||
height="1em"
|
<div class="mb-4 text-3xl font-extrabold leading-tight">
|
||||||
width="1em"
|
{original_data.donor.firstname}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
{original_data.donor.middlename || ""}
|
||||||
><line x1="5" y1="12" x2="19" y2="12" />
|
{original_data.donor.lastname}
|
||||||
<polyline points="12 5 19 12 12 19" /></svg
|
>
|
||||||
>
|
{#if original_data.responseType == "DISTANCEDONATION"}
|
||||||
</li>
|
{original_data.runner.firstname}
|
||||||
<li class="flex items-center">
|
{original_data.runner.middlename || ""}
|
||||||
<span class="mr-2">{original_data.id}</span>
|
{original_data.runner.lastname}
|
||||||
</li>
|
{:else}
|
||||||
</ol>
|
{$_("fixed-donation")}:
|
||||||
</nav>
|
{amount_input.toFixed(2).toLocaleString("de-DE", { valute: "EUR" })}€
|
||||||
</div>
|
{/if}
|
||||||
</div>
|
[#{original_data.id}]
|
||||||
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
<div data-id="donation_actions_${original_data.id}">
|
||||||
{original_data.donor.firstname}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:DELETE")}
|
||||||
{original_data.donor.middlename || ""}
|
{#if delete_triggered}
|
||||||
{original_data.donor.lastname}
|
<button
|
||||||
>
|
on:click={deleteDonation}
|
||||||
{#if original_data.responseType == "DISTANCEDONATION"}
|
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:w-auto sm:text-sm"
|
||||||
{original_data.runner.firstname}
|
>{$_("confirm-deletion")}</button
|
||||||
{original_data.runner.middlename || ""}
|
>
|
||||||
{original_data.runner.lastname}
|
<button
|
||||||
{:else}
|
on:click={() => {
|
||||||
{$_("fixed-donation")}:
|
delete_triggered = !delete_triggered;
|
||||||
{amount_input.toFixed(2).toLocaleString("de-DE", { valute: "EUR" })}€
|
}}
|
||||||
{/if}
|
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"
|
||||||
<span data-id="donation_actions_${original_data.id}">
|
>{$_("cancel")}</button
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:DELETE")}
|
>
|
||||||
{#if delete_triggered}
|
{/if}
|
||||||
<button
|
{#if !delete_triggered}
|
||||||
on:click={deleteDonation}
|
<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:"
|
on:click={() => {
|
||||||
>{$_("confirm-deletion")}</button
|
delete_triggered = true;
|
||||||
>
|
}}
|
||||||
<button
|
type="button"
|
||||||
on:click={() => {
|
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:w-auto sm:text-sm"
|
||||||
delete_triggered = !delete_triggered;
|
>{$_("delete-donation")}</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:"
|
{/if}
|
||||||
>{$_("cancel")}</button
|
{/if}
|
||||||
>
|
{#if !delete_triggered}
|
||||||
{/if}
|
<button
|
||||||
{#if !delete_triggered}
|
disabled={!save_enabled}
|
||||||
<button
|
class:opacity-50={!save_enabled}
|
||||||
on:click={() => {
|
type="button"
|
||||||
delete_triggered = true;
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
type="button"
|
>{$_("save-changes")}</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:"
|
>
|
||||||
>{$_("delete-donation")}</button
|
{/if}
|
||||||
>
|
</div>
|
||||||
{/if}
|
</div>
|
||||||
{/if}
|
<!-- -->
|
||||||
{#if !delete_triggered}
|
<div>
|
||||||
<button
|
<span class="font-semibold text-gray-700"
|
||||||
disabled={!save_enabled}
|
>{$_("total-donation-amount")}:</span
|
||||||
class:opacity-50={!save_enabled}
|
>
|
||||||
type="button"
|
<span
|
||||||
on:click={submit}
|
>{(editable.amount / 100)
|
||||||
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:"
|
.toFixed(2)
|
||||||
>{$_("save-changes")}</button
|
.toLocaleString("de-DE", { valute: "EUR" })}€</span
|
||||||
>
|
>
|
||||||
{/if}
|
|
|
||||||
</span>
|
<span class="font-semibold text-gray-700">{$_("paid-amount")}:</span>
|
||||||
</div>
|
<span
|
||||||
<!-- -->
|
>{(editable.paidAmount / 100)
|
||||||
<div>
|
.toFixed(2)
|
||||||
<span class="font-medium text-gray-700"
|
.toLocaleString("de-DE", { valute: "EUR" })}€</span
|
||||||
>{$_("total-donation-amount")}:</span
|
>
|
||||||
>
|
|
|
||||||
<span
|
<span class="font-semibold text-gray-700">{$_("status")}:</span>
|
||||||
>{(editable.amount / 100)
|
{#if editable.status == "PAID"}
|
||||||
.toFixed(2)
|
<span
|
||||||
.toLocaleString("de-DE", { valute: "EUR" })}€</span
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-green-100 text-green-800"
|
||||||
>
|
>{$_("paid")}</span
|
||||||
|
|
>
|
||||||
<span class="font-medium text-gray-700">{$_("paid-amount")}:</span>
|
{:else}
|
||||||
<span
|
<span
|
||||||
>{(editable.paidAmount / 100)
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-red-100 text-red-800"
|
||||||
.toFixed(2)
|
>{$_("open")}</span
|
||||||
.toLocaleString("de-DE", { valute: "EUR" })}€</span
|
>
|
||||||
>
|
{/if}
|
||||||
|
|
</div>
|
||||||
<span class="font-medium text-gray-700">{$_("status")}:</span>
|
<br />
|
||||||
{#if editable.status == "PAID"}
|
<div class=" mt-2 w-full">
|
||||||
<span
|
<label for="donor" class="block font-semibold text-gray-700"
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"
|
>{$_("donor")}</label
|
||||||
>{$_("paid")}</span
|
>
|
||||||
>
|
<Select
|
||||||
{:else}
|
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-neutral-800 rounded-md p-2"
|
||||||
<span
|
itemFilter={(label, filterText, option) =>
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800"
|
filterDonors(label, filterText, option)}
|
||||||
>{$_("open")}</span
|
items={current_donors}
|
||||||
>
|
showChevron={true}
|
||||||
{/if}
|
placeholder={$_("search-for-donor-name-or-id")}
|
||||||
</div>
|
noOptionsMessage={$_("no-donors-found")}
|
||||||
<br />
|
bind:selectedValue={donor}
|
||||||
<div class=" w-full">
|
on:select={(selectedValue) => {
|
||||||
<label for="donor" class="block font-medium text-gray-700"
|
editable.donor = selectedValue.detail.value;
|
||||||
>{$_("donor")}</label
|
editable.donor.donationAmount = original_data.donor.donationAmount;
|
||||||
>
|
editable.donor.paidDonationAmount =
|
||||||
<Select
|
original_data.donor.paidDonationAmount;
|
||||||
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) =>
|
on:clear={() => (editable.donor = null)}
|
||||||
filterDonors(label, filterText, option)}
|
/>
|
||||||
items={current_donors}
|
</div>
|
||||||
showChevron={true}
|
{#if original_data.responseType == "DISTANCEDONATION"}
|
||||||
placeholder={$_("search-for-donor-name-or-id")}
|
<div class=" mt-2 w-full">
|
||||||
noOptionsMessage={$_("no-donors-found")}
|
<label for="donor" class="block font-semibold text-gray-700"
|
||||||
bind:selectedValue={donor}
|
>{$_("runner")}</label
|
||||||
on:select={(selectedValue) => {
|
>
|
||||||
editable.donor = selectedValue.detail.value;
|
<Select
|
||||||
editable.donor.donationAmount = original_data.donor.donationAmount;
|
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-neutral-800 rounded-md p-2"
|
||||||
editable.donor.paidDonationAmount =
|
itemFilter={(label, filterText, option) =>
|
||||||
original_data.donor.paidDonationAmount;
|
filterDonors(label, filterText, option)}
|
||||||
}}
|
items={current_runners}
|
||||||
on:clear={() => (editable.donor = null)}
|
showChevron={true}
|
||||||
/>
|
placeholder={$_("search-for-runner-by-name-or-id")}
|
||||||
</div>
|
noOptionsMessage={$_("no-runners-found")}
|
||||||
{#if original_data.responseType == "DISTANCEDONATION"}
|
bind:selectedValue={runner}
|
||||||
<div class=" w-full">
|
on:select={(selectedValue) =>
|
||||||
<label for="donor" class="block font-medium text-gray-700"
|
(editable.runner = selectedValue.detail.value)}
|
||||||
>{$_("runner")}</label
|
on:clear={() => (editable.runner = null)}
|
||||||
>
|
/>
|
||||||
<Select
|
</div>
|
||||||
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"
|
{/if}
|
||||||
itemFilter={(label, filterText, option) =>
|
<div class=" mt-2 w-full">
|
||||||
filterDonors(label, filterText, option)}
|
<label for="lastname" class="font-semibold text-gray-700">
|
||||||
items={current_runners}
|
{#if original_data.responseType == "DISTANCEDONATION"}
|
||||||
showChevron={true}
|
{$_("amount-per-kilometer")}
|
||||||
placeholder={$_("search-for-runner-by-name-or-id")}
|
{:else}{$_("donation-amount")}{/if}
|
||||||
noOptionsMessage={$_("no-runners-found")}
|
</label>
|
||||||
bind:selectedValue={runner}
|
<div class="mt-1 flex rounded-md shadow-sm">
|
||||||
on:select={(selectedValue) =>
|
<input
|
||||||
(editable.runner = selectedValue.detail.value)}
|
autocomplete="off"
|
||||||
on:clear={() => (editable.runner = null)}
|
class:border-red-500={!is_amount_valid}
|
||||||
/>
|
class:focus:border-red-500={!is_amount_valid}
|
||||||
</div>
|
class:focus:ring-red-500={!is_amount_valid}
|
||||||
{/if}
|
bind:value={amount_input}
|
||||||
<div class=" w-full">
|
type="number"
|
||||||
<label for="lastname" class="font-medium text-gray-700">
|
step="0.01"
|
||||||
{#if original_data.responseType == "DISTANCEDONATION"}
|
name="donation_amount_eur"
|
||||||
{$_("amount-per-kilometer")}
|
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 p-2"
|
||||||
{:else}{$_("donation-amount")}{/if}
|
placeholder="2.00"
|
||||||
</label>
|
/>
|
||||||
<div class="mt-1 flex rounded-md shadow-sm">
|
<span
|
||||||
<input
|
class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500"
|
||||||
autocomplete="off"
|
>€</span
|
||||||
class:border-red-500={!is_amount_valid}
|
>
|
||||||
class:focus:border-red-500={!is_amount_valid}
|
</div>
|
||||||
class:focus:ring-red-500={!is_amount_valid}
|
{#if !is_amount_valid}
|
||||||
bind:value={amount_input}
|
<span
|
||||||
type="number"
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
step="0.01"
|
>
|
||||||
name="donation_amount_eur"
|
{$_("donation-amount-must-be-greater-that-0-00eur")}
|
||||||
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm: border-gray-300 border bg-gray-50 text-gray-500 p-2"
|
</span>
|
||||||
placeholder="2.00"
|
{/if}
|
||||||
/>
|
</div>
|
||||||
<span
|
<div class="mt-2 w-full">
|
||||||
class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500"
|
<label for="token" class="block font-semibold text-gray-700"
|
||||||
>€</span
|
>{$_("paid-amount")}</label
|
||||||
>
|
>
|
||||||
</div>
|
<div
|
||||||
{#if !is_amount_valid}
|
class="inline-flex border-gray-300 border rounded-l-md rounded-r-md bg-gray-50 text-gray-500 w-full"
|
||||||
<span
|
>
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
<input
|
||||||
>
|
autocomplete="off"
|
||||||
{$_("donation-amount-must-be-greater-that-0-00eur")}
|
class:border-red-500={!is_amount_valid}
|
||||||
</span>
|
class:focus:border-red-500={!is_amount_valid}
|
||||||
{/if}
|
class:focus:ring-red-500={!is_amount_valid}
|
||||||
</div>
|
bind:value={paid_amount_input}
|
||||||
<div class="w-full">
|
type="number"
|
||||||
<label for="token" class="block text-sm font-medium text-gray-700"
|
step="0.01"
|
||||||
>{$_("paid-amount")}</label
|
name="donation_amount_eur"
|
||||||
>
|
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm p-2"
|
||||||
<div
|
placeholder="2.00"
|
||||||
class="inline-flex border-gray-300 border rounded-l-md rounded-r-md bg-gray-50 text-gray-500 w-full"
|
/>
|
||||||
>
|
<button
|
||||||
<input
|
on:click={() => {
|
||||||
autocomplete="off"
|
paid_amount_input = paid_amount_input = (
|
||||||
class:border-red-500={!is_amount_valid}
|
original_data.amount / 100
|
||||||
class:focus:border-red-500={!is_amount_valid}
|
).toFixed(2);
|
||||||
class:focus:ring-red-500={!is_amount_valid}
|
}}
|
||||||
bind:value={paid_amount_input}
|
class="inline-flex items-center p-r-2 text-indigo-300 hover:text-indigo-700 text-sm"
|
||||||
type="number"
|
>MAX</button
|
||||||
step="0.01"
|
>
|
||||||
name="donation_amount_eur"
|
<span
|
||||||
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm p-2"
|
class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm"
|
||||||
placeholder="2.00"
|
>€</span
|
||||||
/>
|
>
|
||||||
<button
|
</div>
|
||||||
on:click={() => {
|
{#if !is_paid_amount_valid}
|
||||||
paid_amount_input = paid_amount_input = (
|
<span
|
||||||
original_data.amount / 100
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
).toFixed(2);
|
>
|
||||||
}}
|
{$_("payment-amount-must-be-greater-than-0-00eur")}
|
||||||
class="inline-flex items-center p-r-2 text-indigo-300 hover:text-indigo-700 text-sm"
|
</span>
|
||||||
>MAX</button
|
{/if}
|
||||||
>
|
</div>
|
||||||
<span
|
</section>
|
||||||
class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm"
|
|
||||||
>€</span
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
{#if !is_paid_amount_valid}
|
|
||||||
<span
|
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
|
||||||
>
|
|
||||||
{$_("payment-amount-must-be-greater-than-0-00eur")}
|
|
||||||
</span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{:catch error}
|
{:catch error}
|
||||||
<PromiseError {error} />
|
<PromiseError {error} />
|
||||||
{/await}
|
{/await}
|
||||||
@@ -9,7 +9,7 @@
|
|||||||
<div class="flex items-center">
|
<div class="flex items-center">
|
||||||
<a
|
<a
|
||||||
href="../donors/{donor.id}"
|
href="../donors/{donor.id}"
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800 border border-current"
|
||||||
>{donor.firstname}
|
>{donor.firstname}
|
||||||
{#if donor.middlename}{donor.middlename}{/if}
|
{#if donor.middlename}{donor.middlename}{/if}
|
||||||
{donor.lastname}</a
|
{donor.lastname}</a
|
||||||
|
|||||||
@@ -9,7 +9,7 @@
|
|||||||
<div class="text-sm font-medium text-gray-900">
|
<div class="text-sm font-medium text-gray-900">
|
||||||
<a
|
<a
|
||||||
href="../runners/{runner.id}"
|
href="../runners/{runner.id}"
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800 border border-current"
|
||||||
>{runner.firstname}
|
>{runner.firstname}
|
||||||
{#if runner.middlename}{runner.middlename}{/if}
|
{#if runner.middlename}{runner.middlename}{/if}
|
||||||
{runner.lastname}</a
|
{runner.lastname}</a
|
||||||
|
|||||||
@@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
{#if status == "PAID"}
|
{#if status == "PAID"}
|
||||||
<span
|
<span
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-green-100 text-green-800"
|
||||||
>{$_("paid")}</span
|
>{$_("paid")}</span
|
||||||
>
|
>
|
||||||
{:else}
|
{:else}
|
||||||
<span
|
<span
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800"
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-red-100 text-red-800"
|
||||||
>{$_("open")}</span
|
>{$_("open")}</span
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -9,20 +9,20 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_("donations")}
|
{$_("donations")}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:CREATE")}
|
</h4>
|
||||||
<button
|
{#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:CREATE")}
|
||||||
on:click={() => {
|
<button
|
||||||
modal_open = true;
|
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"
|
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:w-auto sm:text-sm"
|
||||||
{$_("add-donation")}
|
>
|
||||||
</button>
|
{$_("add-donation")}
|
||||||
{/if}
|
</button>
|
||||||
</span>
|
{/if}
|
||||||
<DonationsOverview bind:current_donations bind:addDonations />
|
<DonationsOverview bind:current_donations bind:addDonations />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
<div class="text-center items-center justify-center">
|
<div class="text-center items-center justify-center">
|
||||||
<p class="mb-16 text-lg text-gray-500">
|
<p class="mb-16 text-lg text-gray-500">
|
||||||
<img class="m-auto" style="height:15rem" src={donations_empty} alt="" />
|
<img class="m-auto mt-2" style="height:15rem" src={donations_empty} alt="" />
|
||||||
<span class="font-bold">{$_("there-are-no-donations-yet")}</span><br />
|
<span class="font-bold">{$_("there-are-no-donations-yet")}</span><br />
|
||||||
<span>{$_("add-your-fist-donation")}</span>
|
<span>{$_("add-your-fist-donation")}</span>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -195,9 +195,12 @@
|
|||||||
payment_modal_open={active_edits.length > 0}
|
payment_modal_open={active_edits.length > 0}
|
||||||
paid_amount_input={(active_edits[0]?.paidAmount || 0) / 100}
|
paid_amount_input={(active_edits[0]?.paidAmount || 0) / 100}
|
||||||
on:created={(event) => {
|
on:created={(event) => {
|
||||||
current_donations[
|
current_donations = current_donations.map((d)=>{
|
||||||
current_donations.findIndex((d) => d.id === event.detail.donation.id)
|
if(d.id === event.detail.donation.id){
|
||||||
].paidAmount = event.detail.donation.paidAmount;
|
d.paidAmount = event.detail.donation.paidAmount;
|
||||||
|
}
|
||||||
|
return d;
|
||||||
|
})
|
||||||
options.update((options) => ({
|
options.update((options) => ({
|
||||||
...options,
|
...options,
|
||||||
data: current_donations,
|
data: current_donations,
|
||||||
@@ -228,7 +231,7 @@
|
|||||||
bind:value={searchvalue}
|
bind:value={searchvalue}
|
||||||
placeholder={$_("datatable.search")}
|
placeholder={$_("datatable.search")}
|
||||||
aria-label={$_("datatable.search")}
|
aria-label={$_("datatable.search")}
|
||||||
class="mb-4"
|
class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
|
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
|
||||||
|
|||||||
@@ -196,7 +196,7 @@
|
|||||||
bind:this={firstname_input}
|
bind:this={firstname_input}
|
||||||
type="text"
|
type="text"
|
||||||
name="firstname"
|
name="firstname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isFirstnameValid}
|
{#if !isFirstnameValid}
|
||||||
<span
|
<span
|
||||||
@@ -219,7 +219,7 @@
|
|||||||
bind:this={middlename_input}
|
bind:this={middlename_input}
|
||||||
type="text"
|
type="text"
|
||||||
name="trackname"
|
name="trackname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
@@ -238,7 +238,7 @@
|
|||||||
bind:this={lastname_input}
|
bind:this={lastname_input}
|
||||||
type="text"
|
type="text"
|
||||||
name="lastname"
|
name="lastname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isLastnameValid}
|
{#if !isLastnameValid}
|
||||||
<span
|
<span
|
||||||
@@ -264,7 +264,7 @@
|
|||||||
bind:this={phone_input}
|
bind:this={phone_input}
|
||||||
type="tel"
|
type="tel"
|
||||||
name="phone"
|
name="phone"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isPhoneValidOrEmpty}
|
{#if !isPhoneValidOrEmpty}
|
||||||
<span
|
<span
|
||||||
@@ -292,7 +292,7 @@
|
|||||||
bind:this={email_input}
|
bind:this={email_input}
|
||||||
type="email"
|
type="email"
|
||||||
name="email"
|
name="email"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isEmailValidOrEmpty}
|
{#if !isEmailValidOrEmpty}
|
||||||
<span
|
<span
|
||||||
@@ -313,7 +313,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-3 text-sm">
|
<div class="ml-3 text-sm">
|
||||||
<label for="comments" class="font-medium text-gray-700"
|
<label for="comments" class="font-semibold text-gray-700"
|
||||||
>{$_("receipt-needed")}</label
|
>{$_("receipt-needed")}</label
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@@ -335,7 +335,7 @@
|
|||||||
bind:this={address_input1}
|
bind:this={address_input1}
|
||||||
type="text"
|
type="text"
|
||||||
name="address1"
|
name="address1"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isAddress1Valid}
|
{#if !isAddress1Valid}
|
||||||
<span
|
<span
|
||||||
@@ -358,7 +358,7 @@
|
|||||||
bind:this={address_input2}
|
bind:this={address_input2}
|
||||||
type="text"
|
type="text"
|
||||||
name="address2"
|
name="address2"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
@@ -377,7 +377,7 @@
|
|||||||
bind:this={address_zipcode}
|
bind:this={address_zipcode}
|
||||||
type="text"
|
type="text"
|
||||||
name="zipcode"
|
name="zipcode"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !iszipcodevalid}
|
{#if !iszipcodevalid}
|
||||||
<span
|
<span
|
||||||
@@ -403,7 +403,7 @@
|
|||||||
bind:this={address_city}
|
bind:this={address_city}
|
||||||
type="text"
|
type="text"
|
||||||
name="city"
|
name="city"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !iscityvalid}
|
{#if !iscityvalid}
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -1,438 +1,413 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { DonorService } from "@odit/lfk-client-js";
|
||||||
import store from "../../store";
|
import { _ } from "svelte-i18n";
|
||||||
import { DonorService, DonationService } from "@odit/lfk-client-js";
|
import store from "../../store";
|
||||||
|
import toast from "svelte-french-toast";
|
||||||
import PromiseError from "../base/PromiseError.svelte";
|
import isEmail from "validator/es/lib/isEmail";
|
||||||
import isEmail from "validator/es/lib/isEmail";
|
import PromiseError from "../base/PromiseError.svelte";
|
||||||
import ConfirmDonorDeletion from "./ConfirmDonorDeletion.svelte";
|
let data_loaded = false;
|
||||||
import toast from "svelte-french-toast";
|
export let params;
|
||||||
let data_loaded = false;
|
$: delete_triggered = false;
|
||||||
export let params;
|
$: original_data = {};
|
||||||
$: delete_triggered = false;
|
$: editable = {};
|
||||||
$: original_data = {};
|
$: changes_performed = !(
|
||||||
$: editable = {};
|
JSON.stringify(original_data) === JSON.stringify(editable)
|
||||||
$: current_donations = [];
|
);
|
||||||
$: changes_performed = !(
|
$: isEmailValid =
|
||||||
JSON.stringify(original_data) === JSON.stringify(editable)
|
(editable.email || "") === "" ||
|
||||||
);
|
(editable.email && isEmail(editable.email || ""));
|
||||||
$: isEmailValid =
|
$: isFirstnameValid = editable.firstname !== "";
|
||||||
(editable.email || "") === "" ||
|
$: isLastnameValid = editable.lastname !== "";
|
||||||
(editable.email && isEmail(editable.email || ""));
|
$: save_enabled =
|
||||||
$: isFirstnameValid = editable.firstname !== "";
|
changes_performed &&
|
||||||
$: isLastnameValid = editable.lastname !== "";
|
isFirstnameValid &&
|
||||||
$: save_enabled =
|
isLastnameValid &&
|
||||||
changes_performed &&
|
isEmailValid &&
|
||||||
isFirstnameValid &&
|
isPhoneValidOrEmpty &&
|
||||||
isLastnameValid &&
|
((isAddress1Valid && iszipcodevalid && iscityvalid) ||
|
||||||
isEmailValid &&
|
editable.address_checked === false);
|
||||||
isPhoneValidOrEmpty &&
|
const promise = DonorService.donorControllerGetOne(params.donorid).then(
|
||||||
((isAddress1Valid && iszipcodevalid && iscityvalid) ||
|
(data) => {
|
||||||
editable.address_checked === false);
|
data_loaded = true;
|
||||||
const donation_promise = DonationService.donationControllerGetAll().then(
|
original_data = Object.assign(original_data, data);
|
||||||
(val) => {
|
editable = Object.assign(editable, original_data);
|
||||||
current_donations = val;
|
editable.address_checked = editable.address.address1 !== null;
|
||||||
}
|
original_data.address_checked = editable.address.address1 !== null;
|
||||||
);
|
if (editable.address_checked === false) {
|
||||||
const promise = DonorService.donorControllerGetOne(params.donorid).then(
|
editable.address = {
|
||||||
(data) => {
|
address1: "",
|
||||||
data_loaded = true;
|
address2: "",
|
||||||
original_data = Object.assign(original_data, data);
|
city: "",
|
||||||
editable = Object.assign(editable, original_data);
|
postalcode: "",
|
||||||
editable.address_checked = editable.address.address1 !== null;
|
country: "",
|
||||||
original_data.address_checked = editable.address.address1 !== null;
|
};
|
||||||
if (editable.address_checked === false) {
|
}
|
||||||
editable.address = {
|
}
|
||||||
address1: "",
|
);
|
||||||
address2: "",
|
$: isPhoneValidOrEmpty =
|
||||||
city: "",
|
editable.phone?.includes("+") ||
|
||||||
postalcode: "",
|
editable.phone === "" ||
|
||||||
country: "",
|
editable.phone === null;
|
||||||
};
|
$: isAddress1Valid = editable.address?.address1?.trim().length !== 0;
|
||||||
}
|
$: iszipcodevalid = editable.address?.postalcode?.trim().length !== 0;
|
||||||
}
|
$: iscityvalid = editable.address?.city?.trim().length !== 0;
|
||||||
);
|
function submit() {
|
||||||
$: isPhoneValidOrEmpty =
|
if (data_loaded === true && save_enabled) {
|
||||||
editable.phone?.includes("+") ||
|
toast($_("donor-is-being-updated"));
|
||||||
editable.phone === "" ||
|
editable.address.country = "DE";
|
||||||
editable.phone === null;
|
if (editable.address_checked === false) {
|
||||||
$: isAddress1Valid = editable.address?.address1?.trim().length !== 0;
|
editable.address = null;
|
||||||
$: iszipcodevalid = editable.address?.postalcode?.trim().length !== 0;
|
}
|
||||||
$: iscityvalid = editable.address?.city?.trim().length !== 0;
|
if (editable.email) editable.email = editable.email;
|
||||||
let modal_open = false;
|
else editable.email = null;
|
||||||
let delete_donor = {};
|
if (editable.phone) editable.phone = editable.phone;
|
||||||
function submit() {
|
else editable.phone = null;
|
||||||
if (data_loaded === true && save_enabled) {
|
if (editable.middlename) editable.middlename = editable.middlename;
|
||||||
toast($_("donor-is-being-updated"));
|
editable.receiptNeeded = editable.address_checked;
|
||||||
editable.address.country = "DE";
|
DonorService.donorControllerPut(original_data.id, editable)
|
||||||
if (editable.address_checked === false) {
|
.then((resp) => {
|
||||||
editable.address = null;
|
Object.assign(original_data, editable);
|
||||||
}
|
original_data = original_data;
|
||||||
if (editable.email) editable.email = editable.email;
|
toast.success($_("updated-donor"));
|
||||||
if (editable.phone) editable.phone = editable.phone;
|
})
|
||||||
if (editable.middlename) editable.middlename = editable.middlename;
|
.catch((err) => {});
|
||||||
editable.receiptNeeded = editable.address_checked;
|
} else {
|
||||||
DonorService.donorControllerPut(original_data.id, editable)
|
}
|
||||||
.then((resp) => {
|
}
|
||||||
Object.assign(original_data, editable);
|
function deleteDonor() {
|
||||||
original_data = original_data;
|
DonorService.donorControllerRemove(original_data.id, true)
|
||||||
toast.success($_("updated-donor"));
|
.then((resp) => {
|
||||||
})
|
toast($_("donor-deleted"));
|
||||||
.catch((err) => {});
|
location.replace("./");
|
||||||
} else {
|
})
|
||||||
}
|
.catch((err) => {
|
||||||
}
|
console.log(err);
|
||||||
function deleteDonor() {
|
});
|
||||||
DonorService.donorControllerRemove(original_data.id, false)
|
}
|
||||||
.then((resp) => {
|
|
||||||
toast($_("donor-deleted"));
|
|
||||||
location.replace("./");
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
modal_open = true;
|
|
||||||
delete_donor = original_data;
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ConfirmDonorDeletion bind:modal_open bind:delete_donor />
|
{#await promise}
|
||||||
{#await promise && donation_promise}
|
{$_("loading-donor-details")}
|
||||||
{$_("loading-donor-details")}
|
|
||||||
{: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">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<nav class="w-full flex">
|
<nav class="w-full flex">
|
||||||
<ol class="list-none flex flex-row items-center justify-start">
|
<ol class="list-none flex flex-row items-center justify-start">
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
<svg
|
<a class="mr-2" href="./"
|
||||||
fill="currentColor"
|
><svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
width="24"
|
||||||
width="24"
|
height="24"
|
||||||
height="24"
|
viewBox="0 0 24 24"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
fill="none"
|
||||||
<path
|
stroke="currentColor"
|
||||||
d="M9.33 11.5h2.17A4.5 4.5 0 0 1 16 16H8.999L9 17h8v-1a5.578 5.578 0 0 0-.886-3H19a5 5 0 0 1 4.516 2.851C21.151 18.972 17.322 21 13 21c-2.761 0-5.1-.59-7-1.625L6 10.071A6.967 6.967 0 0 1 9.33 11.5zM5 19a1 1 0 0 1-1 1H2a1 1 0 0 1-1-1v-9a1 1 0 0 1 1-1h2a1 1 0 0 1 1 1v9zM18 5a3 3 0 1 1 0 6 3 3 0 0 1 0-6zm-7-3a3 3 0 1 1 0 6 3 3 0 0 1 0-6z"
|
stroke-width="2"
|
||||||
/></svg
|
stroke-linecap="round"
|
||||||
>
|
stroke-linejoin="round"
|
||||||
</li>
|
class="inline-block"
|
||||||
<li class="flex items-center ml-2">
|
><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg
|
||||||
<a class="mr-2" href="./">{$_("donors")}</a><svg
|
>
|
||||||
stroke="currentColor"
|
{$_("donors")}</a
|
||||||
fill="none"
|
>
|
||||||
stroke-width="2"
|
</li>
|
||||||
viewBox="0 0 24 24"
|
</ol>
|
||||||
stroke-linecap="round"
|
</nav>
|
||||||
stroke-linejoin="round"
|
</div>
|
||||||
class="h-3 w-3 mr-2 stroke-current"
|
</div>
|
||||||
height="1em"
|
<div class="mb-4 text-3xl font-extrabold leading-tight">
|
||||||
width="1em"
|
{original_data.firstname}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
{original_data.middlename || ""}
|
||||||
><line x1="5" y1="12" x2="19" y2="12" />
|
{original_data.lastname}
|
||||||
<polyline points="12 5 19 12 12 19" /></svg
|
<div data-id="donor_actions_${editable.id}">
|
||||||
>
|
{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:DELETE")}
|
||||||
</li>
|
{#if delete_triggered}
|
||||||
<li class="flex items-center">
|
<button
|
||||||
<span class="mr-2"
|
on:click={deleteDonor}
|
||||||
>{original_data.firstname}
|
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:w-auto sm:text-sm"
|
||||||
{original_data.middlename || ""}
|
>{$_("confirm-deletion")}</button
|
||||||
{original_data.lastname}</span
|
>
|
||||||
>
|
<button
|
||||||
</li>
|
on:click={() => {
|
||||||
</ol>
|
delete_triggered = !delete_triggered;
|
||||||
</nav>
|
}}
|
||||||
</div>
|
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"
|
||||||
</div>
|
>{$_("cancel")}</button
|
||||||
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
>
|
||||||
{original_data.firstname}
|
{/if}
|
||||||
{original_data.middlename || ""}
|
{#if !delete_triggered}
|
||||||
{original_data.lastname}
|
<button
|
||||||
<span data-id="donor_actions_${editable.id}">
|
on:click={() => {
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:DELETE")}
|
delete_triggered = true;
|
||||||
{#if delete_triggered}
|
}}
|
||||||
<button
|
type="button"
|
||||||
on:click={deleteDonor}
|
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:w-auto sm:text-sm"
|
||||||
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:"
|
>{$_("delete-donor")}</button
|
||||||
>{$_("confirm-deletion")}</button
|
>
|
||||||
>
|
{/if}
|
||||||
<button
|
{/if}
|
||||||
on:click={() => {
|
{#if !delete_triggered}
|
||||||
delete_triggered = !delete_triggered;
|
<button
|
||||||
}}
|
disabled={!save_enabled}
|
||||||
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:"
|
class:opacity-50={!save_enabled}
|
||||||
>{$_("cancel")}</button
|
type="button"
|
||||||
>
|
on:click={submit}
|
||||||
{/if}
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
{#if !delete_triggered}
|
>{$_("save-changes")}</button
|
||||||
<button
|
>
|
||||||
on:click={() => {
|
{/if}
|
||||||
delete_triggered = true;
|
</div>
|
||||||
}}
|
</div>
|
||||||
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:"
|
<div>
|
||||||
>{$_("delete-donor")}</button
|
<span class="font-semibold text-gray-700"
|
||||||
>
|
>{$_("total-donation-amount")}:</span
|
||||||
{/if}
|
>
|
||||||
{/if}
|
<span
|
||||||
{#if !delete_triggered}
|
>{(editable.donationAmount / 100)
|
||||||
<button
|
.toFixed(2)
|
||||||
disabled={!save_enabled}
|
.toLocaleString("de-DE", { valute: "EUR" })}€</span
|
||||||
class:opacity-50={!save_enabled}
|
>
|
||||||
type="button"
|
|
|
||||||
on:click={submit}
|
<span class="font-semibold text-gray-700">{$_("total-paid-amount")}:</span
|
||||||
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:"
|
>
|
||||||
>{$_("save-changes")}</button
|
<span
|
||||||
>
|
>{(editable.paidDonationAmount / 100)
|
||||||
{/if}
|
.toFixed(2)
|
||||||
</span>
|
.toLocaleString("de-DE", { valute: "EUR" })}€</span
|
||||||
</div>
|
>
|
||||||
<!-- -->
|
<br />
|
||||||
<div>
|
<span class="font-semibold text-gray-700">{$_("donations")}:</span>
|
||||||
<span class="font-medium text-gray-700"
|
{#if original_data.donations.length > 0}
|
||||||
>{$_("total-donation-amount")}:</span
|
{#each original_data.donations as d}
|
||||||
>
|
{#if d.responseType === "DISTANCEDONATION"}
|
||||||
<span
|
<a
|
||||||
>{(editable.donationAmount / 100)
|
href="../donations/{d.id}"
|
||||||
.toFixed(2)
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-600 text-white mr-1"
|
||||||
.toLocaleString("de-DE", { valute: "EUR" })}€</span
|
>{d.runner.firstname}
|
||||||
>
|
{d.runner.middlename || ""}
|
||||||
|
|
{d.runner.lastname}</a
|
||||||
<span class="font-medium text-gray-700">{$_("total-paid-amount")}:</span>
|
>
|
||||||
<span
|
{:else}
|
||||||
>{(editable.paidDonationAmount / 100)
|
<a
|
||||||
.toFixed(2)
|
href="../donations/{d.id}"
|
||||||
.toLocaleString("de-DE", { valute: "EUR" })}€</span
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-green-700 text-white mr-1"
|
||||||
>
|
>{$_("fixed-donation")}:
|
||||||
<br />
|
{(d.amount / 100)
|
||||||
<span class="font-medium text-gray-700">{$_("donations")}:</span>
|
.toFixed(2)
|
||||||
{#if current_donations.filter((d) => d.donor.id == editable.id).length > 0}
|
.toLocaleString("de-DE", { valute: "EUR" })}€</a
|
||||||
{#each current_donations.filter((o) => o.donor.id == editable.id) as d}
|
>
|
||||||
{#if d.responseType === "DISTANCEDONATION"}
|
{/if}
|
||||||
<a
|
{/each}
|
||||||
href="../donations/{d.id}"
|
{:else}{$_("donor-has-no-associated-donations")}{/if}
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-blue-600 text-white mr-1"
|
</div>
|
||||||
>{d.runner.firstname}
|
<div class="mt-2 w-full">
|
||||||
{d.runner.middlename || ""}
|
<label for="firstname" class="font-semibold text-gray-700"
|
||||||
{d.runner.lastname}</a
|
>{$_("first-name")}</label
|
||||||
>
|
>
|
||||||
{:else}
|
<input
|
||||||
<a
|
autocomplete="off"
|
||||||
href="../donations/{d.id}"
|
placeholder={$_("first-name")}
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-700 text-white mr-1"
|
type="text"
|
||||||
>{$_("fixed-donation")}:
|
class:border-red-500={!isFirstnameValid}
|
||||||
{(d.amount / 100)
|
class:focus:border-red-500={!isFirstnameValid}
|
||||||
.toFixed(2)
|
class:focus:ring-red-500={!isFirstnameValid}
|
||||||
.toLocaleString("de-DE", { valute: "EUR" })}€</a
|
bind:value={editable.firstname}
|
||||||
>
|
name="firstname"
|
||||||
{/if}
|
class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
{/each}
|
/>
|
||||||
{:else}{$_("donor-has-no-associated-donations")}{/if}
|
{#if !isFirstnameValid}
|
||||||
</div>
|
<span
|
||||||
<div class=" w-full">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
<label for="firstname" class="font-medium text-gray-700"
|
>
|
||||||
>{$_("first-name")}</label
|
{$_("first-name-is-required")}
|
||||||
>
|
</span>
|
||||||
<input
|
{/if}
|
||||||
autocomplete="off"
|
</div>
|
||||||
placeholder={$_("first-name")}
|
<div class="mt-2 w-full">
|
||||||
type="text"
|
<label for="middlename" class="font-semibold text-gray-700"
|
||||||
class:border-red-500={!isFirstnameValid}
|
>{$_("middle-name")}</label
|
||||||
class:focus:border-red-500={!isFirstnameValid}
|
>
|
||||||
class:focus:ring-red-500={!isFirstnameValid}
|
<input
|
||||||
bind:value={editable.firstname}
|
autocomplete="off"
|
||||||
name="firstname"
|
placeholder={$_("middle-name")}
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
type="text"
|
||||||
/>
|
bind:value={editable.middlename}
|
||||||
{#if !isFirstnameValid}
|
name="middlename"
|
||||||
<span
|
class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
/>
|
||||||
>
|
</div>
|
||||||
{$_("first-name-is-required")}
|
<div class="mt-2 w-full">
|
||||||
</span>
|
<label for="lastname" class="font-semibold text-gray-700"
|
||||||
{/if}
|
>{$_("last-name")}</label
|
||||||
</div>
|
>
|
||||||
<div class=" w-full">
|
<input
|
||||||
<label for="middlename" class="font-medium text-gray-700"
|
autocomplete="off"
|
||||||
>{$_("middle-name")}</label
|
placeholder={$_("last-name")}
|
||||||
>
|
type="text"
|
||||||
<input
|
bind:value={editable.lastname}
|
||||||
autocomplete="off"
|
class:border-red-500={!isLastnameValid}
|
||||||
placeholder={$_("middle-name")}
|
class:focus:border-red-500={!isLastnameValid}
|
||||||
type="text"
|
class:focus:ring-red-500={!isLastnameValid}
|
||||||
bind:value={editable.middlename}
|
name="lastname"
|
||||||
name="middlename"
|
class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
/>
|
||||||
/>
|
{#if !isLastnameValid}
|
||||||
</div>
|
<span
|
||||||
<div class=" w-full">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
<label for="lastname" class="font-medium text-gray-700"
|
>
|
||||||
>{$_("last-name")}</label
|
{$_("last-name-is-required")}
|
||||||
>
|
</span>
|
||||||
<input
|
{/if}
|
||||||
autocomplete="off"
|
</div>
|
||||||
placeholder={$_("last-name")}
|
<div class="mt-2 w-full">
|
||||||
type="text"
|
<label for="email" class="font-semibold text-gray-700"
|
||||||
bind:value={editable.lastname}
|
>{$_("e-mail-adress")}</label
|
||||||
class:border-red-500={!isLastnameValid}
|
>
|
||||||
class:focus:border-red-500={!isLastnameValid}
|
<input
|
||||||
class:focus:ring-red-500={!isLastnameValid}
|
autocomplete="off"
|
||||||
name="lastname"
|
placeholder={$_("e-mail-adress")}
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
type="email"
|
||||||
/>
|
bind:value={editable.email}
|
||||||
{#if !isLastnameValid}
|
class:border-red-500={!isEmailValid}
|
||||||
<span
|
class:focus:border-red-500={!isEmailValid}
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
class:focus:ring-red-500={!isEmailValid}
|
||||||
>
|
name="email"
|
||||||
{$_("last-name-is-required")}
|
class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
</span>
|
/>
|
||||||
{/if}
|
{#if !isEmailValid}
|
||||||
</div>
|
<span
|
||||||
<div class=" w-full">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
<label for="email" class="font-medium text-gray-700"
|
>
|
||||||
>{$_("e-mail-adress")}</label
|
{$_("valid-email-is-required")}
|
||||||
>
|
</span>
|
||||||
<input
|
{/if}
|
||||||
autocomplete="off"
|
</div>
|
||||||
placeholder={$_("e-mail-adress")}
|
<div class="mt-2 w-full">
|
||||||
type="email"
|
<label for="phone" class="font-semibold text-gray-700"
|
||||||
bind:value={editable.email}
|
>{$_("phone")}</label
|
||||||
class:border-red-500={!isEmailValid}
|
>
|
||||||
class:focus:border-red-500={!isEmailValid}
|
<input
|
||||||
class:focus:ring-red-500={!isEmailValid}
|
autocomplete="off"
|
||||||
name="email"
|
placeholder={$_("phone")}
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
type="tel"
|
||||||
/>
|
class:border-red-500={!isPhoneValidOrEmpty}
|
||||||
{#if !isEmailValid}
|
class:focus:border-red-500={!isPhoneValidOrEmpty}
|
||||||
<span
|
class:focus:ring-red-500={!isPhoneValidOrEmpty}
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
bind:value={editable.phone}
|
||||||
>
|
name="phone"
|
||||||
{$_("valid-email-is-required")}
|
class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
</span>
|
/>
|
||||||
{/if}
|
{#if !isPhoneValidOrEmpty}
|
||||||
</div>
|
<span
|
||||||
<div class=" w-full">
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
<label for="phone" class="font-medium text-gray-700">{$_("phone")}</label>
|
>
|
||||||
<input
|
{$_("valid-international-phone-number-is-required")}
|
||||||
autocomplete="off"
|
</span>
|
||||||
placeholder={$_("phone")}
|
{/if}
|
||||||
type="tel"
|
</div>
|
||||||
class:border-red-500={!isPhoneValidOrEmpty}
|
<div class="flex items-start mt-2">
|
||||||
class:focus:border-red-500={!isPhoneValidOrEmpty}
|
<div class="flex items-center h-5">
|
||||||
class:focus:ring-red-500={!isPhoneValidOrEmpty}
|
<input
|
||||||
bind:value={editable.phone}
|
bind:checked={editable.address_checked}
|
||||||
name="phone"
|
id="comments"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
name="comments"
|
||||||
/>
|
type="checkbox"
|
||||||
{#if !isPhoneValidOrEmpty}
|
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
<span
|
/>
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
</div>
|
||||||
>
|
<div class="ml-3">
|
||||||
{$_("valid-international-phone-number-is-required")}
|
<label for="comments" class="font-semibold text-gray-700"
|
||||||
</span>
|
>{$_("receipt-needed")}</label
|
||||||
{/if}
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="flex items-start mt-2">
|
</div>
|
||||||
<div class="flex items-center h-5">
|
{#if editable.address_checked === true}
|
||||||
<input
|
<div class="col-span-6">
|
||||||
bind:checked={editable.address_checked}
|
<label for="address1" class="block font-medium text-gray-700"
|
||||||
id="comments"
|
>{$_("address")}</label
|
||||||
name="comments"
|
>
|
||||||
type="checkbox"
|
<input
|
||||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
autocomplete="off"
|
||||||
/>
|
placeholder="Address"
|
||||||
</div>
|
class:border-red-500={!isAddress1Valid}
|
||||||
<div class="ml-3">
|
class:focus:border-red-500={!isAddress1Valid}
|
||||||
<label for="comments" class="font-medium text-gray-700"
|
class:focus:ring-red-500={!isAddress1Valid}
|
||||||
>{$_("receipt-needed")}</label
|
bind:value={editable.address.address1}
|
||||||
>
|
type="text"
|
||||||
</div>
|
name="address1"
|
||||||
</div>
|
class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
{#if editable.address_checked === true}
|
/>
|
||||||
<div class="col-span-6">
|
{#if !isAddress1Valid}
|
||||||
<label for="address1" class="block font-medium text-gray-700"
|
<span
|
||||||
>{$_("address")}</label
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
>
|
>
|
||||||
<input
|
{$_("address-is-required")}
|
||||||
autocomplete="off"
|
</span>
|
||||||
placeholder="Address"
|
{/if}
|
||||||
class:border-red-500={!isAddress1Valid}
|
</div>
|
||||||
class:focus:border-red-500={!isAddress1Valid}
|
<div class="col-span-6">
|
||||||
class:focus:ring-red-500={!isAddress1Valid}
|
<label for="address2" class="block font-medium text-gray-700"
|
||||||
bind:value={editable.address.address1}
|
>{$_("apartment-suite-etc")}</label
|
||||||
type="text"
|
>
|
||||||
name="address1"
|
<input
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
autocomplete="off"
|
||||||
/>
|
placeholder={$_("apartment-suite-etc")}
|
||||||
{#if !isAddress1Valid}
|
bind:value={editable.address.address2}
|
||||||
<span
|
type="text"
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
name="address2"
|
||||||
>
|
class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
{$_("address-is-required")}
|
/>
|
||||||
</span>
|
</div>
|
||||||
{/if}
|
<div class="col-span-6">
|
||||||
</div>
|
<label for="zipcode" class="block font-medium text-gray-700"
|
||||||
<div class="col-span-6">
|
>{$_("zip-postal-code")}</label
|
||||||
<label for="address2" class="block font-medium text-gray-700"
|
>
|
||||||
>{$_("apartment-suite-etc")}</label
|
<input
|
||||||
>
|
autocomplete="off"
|
||||||
<input
|
placeholder={$_("zip-postal-code")}
|
||||||
autocomplete="off"
|
class:border-red-500={!iszipcodevalid}
|
||||||
placeholder={$_("apartment-suite-etc")}
|
class:focus:border-red-500={!iszipcodevalid}
|
||||||
bind:value={editable.address.address2}
|
class:focus:ring-red-500={!iszipcodevalid}
|
||||||
type="text"
|
bind:value={editable.address.postalcode}
|
||||||
name="address2"
|
type="text"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
name="zipcode"
|
||||||
/>
|
class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
</div>
|
/>
|
||||||
<div class="col-span-6">
|
{#if !iszipcodevalid}
|
||||||
<label for="zipcode" class="block font-medium text-gray-700"
|
<span
|
||||||
>{$_("zip-postal-code")}</label
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
>
|
>
|
||||||
<input
|
{$_("valid-zipcode-postal-code-is-required")}
|
||||||
autocomplete="off"
|
</span>
|
||||||
placeholder={$_("zip-postal-code")}
|
{/if}
|
||||||
class:border-red-500={!iszipcodevalid}
|
</div>
|
||||||
class:focus:border-red-500={!iszipcodevalid}
|
<div class="col-span-6">
|
||||||
class:focus:ring-red-500={!iszipcodevalid}
|
<label for="city" class="block font-medium text-gray-700"
|
||||||
bind:value={editable.address.postalcode}
|
>{$_("city")}</label
|
||||||
type="text"
|
>
|
||||||
name="zipcode"
|
<input
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
autocomplete="off"
|
||||||
/>
|
placeholder={$_("city")}
|
||||||
{#if !iszipcodevalid}
|
class:border-red-500={!iscityvalid}
|
||||||
<span
|
class:focus:border-red-500={!iscityvalid}
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
class:focus:ring-red-500={!iscityvalid}
|
||||||
>
|
bind:value={editable.address.city}
|
||||||
{$_("valid-zipcode-postal-code-is-required")}
|
type="text"
|
||||||
</span>
|
name="city"
|
||||||
{/if}
|
class="focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
</div>
|
/>
|
||||||
<div class="col-span-6">
|
{#if !iscityvalid}
|
||||||
<label for="city" class="block font-medium text-gray-700"
|
<span
|
||||||
>{$_("city")}</label
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
>
|
>
|
||||||
<input
|
{$_("valid-city-is-required")}
|
||||||
autocomplete="off"
|
</span>
|
||||||
placeholder={$_("city")}
|
{/if}
|
||||||
class:border-red-500={!iscityvalid}
|
</div>
|
||||||
class:focus:border-red-500={!iscityvalid}
|
{/if}
|
||||||
class:focus:ring-red-500={!iscityvalid}
|
</section>
|
||||||
bind:value={editable.address.city}
|
|
||||||
type="text"
|
|
||||||
name="city"
|
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm: border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
|
||||||
/>
|
|
||||||
{#if !iscityvalid}
|
|
||||||
<span
|
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
|
||||||
>
|
|
||||||
{$_("valid-city-is-required")}
|
|
||||||
</span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</section>
|
|
||||||
{:catch error}
|
{:catch error}
|
||||||
<PromiseError {error} />
|
<PromiseError {error} />
|
||||||
{/await}
|
{/await}
|
||||||
@@ -18,7 +18,7 @@
|
|||||||
{:else}
|
{:else}
|
||||||
<a
|
<a
|
||||||
href="../donations/{donation.id}"
|
href="../donations/{donation.id}"
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-700 text-white mr-1"
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-green-700 text-white mr-1"
|
||||||
>{$_("fixed-donation")}:
|
>{$_("fixed-donation")}:
|
||||||
{(donation.amount / 100)
|
{(donation.amount / 100)
|
||||||
.toFixed(2)
|
.toFixed(2)
|
||||||
|
|||||||
@@ -9,61 +9,61 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_("donors")}
|
{$_("donors")}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:CREATE")}
|
</h4>
|
||||||
<button
|
{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:CREATE")}
|
||||||
on:click={() => {
|
<button
|
||||||
modal_open = true;
|
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"
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
{$_("add-donor")}
|
>
|
||||||
</button>
|
{$_("add-donor")}
|
||||||
{/if}
|
</button>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:GET")}
|
{/if}
|
||||||
<button
|
{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:GET")}
|
||||||
on:click={() => {
|
<button
|
||||||
const data = current_donors
|
on:click={() => {
|
||||||
.filter((d) => d.receiptNeeded === true)
|
const data = current_donors
|
||||||
.map(function (d) {
|
.filter((d) => d.receiptNeeded === true)
|
||||||
d.address.address2 =
|
.map(function (d) {
|
||||||
d.address.address2 === "" ? "" : " " + d.address.address2;
|
d.address.address2 =
|
||||||
const address = `${d.address.address1}${d.address.address2}, ${d.address.postalcode} ${d.address.city}, ${d.address.country}`;
|
d.address.address2 === "" ? "" : " " + d.address.address2;
|
||||||
return [
|
const address = `${d.address.address1}${d.address.address2}, ${d.address.postalcode} ${d.address.city}, ${d.address.country}`;
|
||||||
d.firstname,
|
return [
|
||||||
d.middlename,
|
d.firstname,
|
||||||
d.lastname,
|
d.middlename,
|
||||||
d.paidDonationAmount,
|
d.lastname,
|
||||||
address,
|
(d.paidDonationAmount/100).toFixed(2),
|
||||||
];
|
address,
|
||||||
});
|
];
|
||||||
let csv = `${$_("csv_import__firstname")};${$_(
|
|
||||||
"csv_import__middlename"
|
|
||||||
)};${$_("csv_import__lastname")};${$_(
|
|
||||||
"total_donation_amount_in_eur"
|
|
||||||
)};${$_("address")}\n`;
|
|
||||||
data.forEach(function (row) {
|
|
||||||
csv += row.join(";");
|
|
||||||
csv += "\n";
|
|
||||||
});
|
});
|
||||||
let hiddenElement = document.createElement("a");
|
let csv = `${$_("csv_import__firstname")};${$_(
|
||||||
hiddenElement.href = "data:text/csv;charset=utf-8," + encodeURI(csv);
|
"csv_import__middlename"
|
||||||
hiddenElement.target = "_blank";
|
)};${$_("csv_import__lastname")};${$_(
|
||||||
hiddenElement.download = `${$_(
|
"total_donation_amount_in_eur"
|
||||||
"filename_sponsoringquittungsliste"
|
)};${$_("address")}\n`;
|
||||||
)}.csv`;
|
data.forEach(function (row) {
|
||||||
hiddenElement.click();
|
csv += row.join(";");
|
||||||
hiddenElement.remove();
|
csv += "\n";
|
||||||
}}
|
});
|
||||||
type="button"
|
let hiddenElement = document.createElement("a");
|
||||||
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"
|
hiddenElement.href = "data:text/csv;charset=utf-8," + encodeURI(csv);
|
||||||
>
|
hiddenElement.target = "_blank";
|
||||||
{$_("sponsoring-quittungs-liste_herunterladen")}
|
hiddenElement.download = `${$_(
|
||||||
</button>
|
"filename_sponsoringquittungsliste"
|
||||||
{/if}
|
)}.csv`;
|
||||||
</span>
|
hiddenElement.click();
|
||||||
|
hiddenElement.remove();
|
||||||
|
}}
|
||||||
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
|
>
|
||||||
|
{$_("sponsoring-quittungs-liste_herunterladen")}
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
<DonorsOverview bind:current_donors bind:addDonors />
|
<DonorsOverview bind:current_donors bind:addDonors />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@@ -202,7 +202,7 @@
|
|||||||
bind:value={searchvalue}
|
bind:value={searchvalue}
|
||||||
placeholder={$_("datatable.search")}
|
placeholder={$_("datatable.search")}
|
||||||
aria-label={$_("datatable.search")}
|
aria-label={$_("datatable.search")}
|
||||||
class="mb-4"
|
class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
|
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
|
||||||
|
|||||||
+189
-203
@@ -1,210 +1,196 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import { clickOutside } from "../base/outsideclick";
|
import { clickOutside } from "../base/outsideclick";
|
||||||
|
|
||||||
export let modal_open;
|
let modal_open = false;
|
||||||
(function () {
|
(function () {
|
||||||
document.onkeydown = function (e) {
|
document.onkeydown = function (e) {
|
||||||
e = e || window.event;
|
e = e || window.event;
|
||||||
if (e.key === "Escape") {
|
if (e.key === "Escape") {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
})();
|
})();
|
||||||
const license_promise = fetch("/licenses.json");
|
const license_promise = fetch("/licenses.json");
|
||||||
let licenses = [];
|
let licenses = [];
|
||||||
$: currentlicense = "";
|
$: currentlicense = "";
|
||||||
$: licensetext = "";
|
$: licensetext = "";
|
||||||
license_promise
|
license_promise
|
||||||
.then((response) => response.json())
|
.then((response) => response.json())
|
||||||
.then((json) => {
|
.then((json) => {
|
||||||
licenses = json;
|
licenses = json;
|
||||||
});
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if modal_open}
|
{#if modal_open}
|
||||||
<div
|
<div
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
use:clickOutside
|
use:clickOutside
|
||||||
on:click_outside={() => {
|
on:click_outside={() => {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
}}
|
}}
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 sm:block sm:p-0"
|
||||||
>
|
>
|
||||||
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
<div
|
<div
|
||||||
class="absolute inset-0 bg-gray-500 opacity-75"
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
data-id="modal_backdrop"
|
data-id="modal_backdrop"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
aria-hidden="true">​</span
|
aria-hidden="true">​</span
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
aria-labelledby="modal-headline"
|
aria-labelledby="modal-headline"
|
||||||
>
|
>
|
||||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
<div class="sm:flex sm:items-start">
|
<div class="sm:flex sm:items-start">
|
||||||
<div
|
<div
|
||||||
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
class="h-6 w-6 text-blue-600"
|
class="h-6 w-6 text-blue-600"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path
|
<path
|
||||||
d="M14 20v2H2v-2h12zM14.586.686l7.778 7.778L20.95 9.88l-1.06-.354L17.413 12l5.657 5.657-1.414 1.414L16 13.414l-2.404 2.404.283 1.132-1.415 1.414-7.778-7.778 1.415-1.414 1.13.282 6.294-6.293-.353-1.06L14.586.686z"
|
d="M14 20v2H2v-2h12zM14.586.686l7.778 7.778L20.95 9.88l-1.06-.354L17.413 12l5.657 5.657-1.414 1.414L16 13.414l-2.404 2.404.283 1.132-1.415 1.414-7.778-7.778 1.415-1.414 1.13.282 6.294-6.293-.353-1.06L14.586.686z"
|
||||||
/></svg
|
/></svg
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
<div class="mt-3 sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
<h3 class="text-lg leading-6 font-medium">
|
<h3 class="text-lg leading-6 font-medium">
|
||||||
{$_("read-license")}
|
{$_("read-license")}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="mt-2 mb-6">
|
<div class="mt-2 mb-6">
|
||||||
<p class="text-sm text-gray-500">{currentlicense}</p>
|
<p class="text-sm text-gray-500">{currentlicense}</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2 mb-6">
|
<div class="mt-2 mb-6">
|
||||||
<p class="text-sm text-gray-500">{licensetext}</p>
|
<p class="text-sm text-gray-500">{licensetext}</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:w-auto sm:text-sm"
|
||||||
>
|
>
|
||||||
{$_("close")}
|
{$_("close")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
<!-- /// -->
|
<!-- /// -->
|
||||||
<div class="pt-12 px-4 sm:px-6 lg:px-8 lg:pt-20 bg-gray-900 pb-12">
|
<section class="container p-5">
|
||||||
<div class="text-center mb-8">
|
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
<h1
|
{$_("about")}
|
||||||
class="mt-9 font-display text-4xl leading-none font-semibold text-white sm:text-5xl lg:text-6xl"
|
</h4>
|
||||||
>
|
<p class="mt-2 mb-2">
|
||||||
{$_("about")}
|
Lauf für Kaya!
|
||||||
🧾
|
<strong class="font-medium">
|
||||||
</h1>
|
{$_("by")}
|
||||||
<p
|
<a href="https://odit.services" class="underline">ODIT.Services</a>
|
||||||
class="mt-2 max-w-xl mx-auto text-xl lg:max-w-3xl lg:text-2xl text-gray-300"
|
</strong>
|
||||||
>
|
<br />
|
||||||
Lauf für Kaya!
|
<span>{$_("lfk-is-os")}</span>
|
||||||
<strong class="text-white font-medium">
|
</p>
|
||||||
{$_("by")}
|
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
<a href="https://odit.services" class="underline">ODIT.Services</a>
|
{$_("credits")}
|
||||||
</strong>
|
</h4>
|
||||||
<br />
|
<p class="text-left">{$_("oss_credit_description")}</p>
|
||||||
<span class="text-lg">{$_("lfk-is-os")}</span>
|
<div class="mt-5 overflow-x-auto">
|
||||||
</p>
|
{#await license_promise}
|
||||||
</div>
|
<p>{$_("licenses-are-being-loaded")}</p>
|
||||||
</div>
|
{:then}
|
||||||
|
<table class="font-mono">
|
||||||
<div class="pt-0 pb-16 overflow-hidden lg:pt-12 lg:py-24">
|
<thead class="border-b border-gray-400">
|
||||||
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
<tr class="odd:bg-white even:bg-gray-100">
|
||||||
<h2 class="text-4xl font-display font-semibold md:text-5xl">
|
<th>{$_("dependency_name")}</th>
|
||||||
{$_("credits")}
|
<th>{$_("license")}</th>
|
||||||
</h2>
|
<th>{$_("repo_link")}</th>
|
||||||
<div class="max-w-3xl mx-auto text-xl leading-8 font-medium mt-8">
|
<th>{$_("installed-version")}</th>
|
||||||
<p class="text-center">{$_("oss_credit_description")}</p>
|
<th>{$_("author")}</th>
|
||||||
</div>
|
</tr>
|
||||||
<div class="w-screen leading-8 pl-5 mt-5">
|
</thead>
|
||||||
{#await license_promise}
|
<tbody>
|
||||||
<p class="text-center w-full">{$_("licenses-are-being-loaded")}</p>
|
{#each licenses as l}
|
||||||
{:then}
|
<tr class="odd:bg-white even:bg-gray-100 *:p-2">
|
||||||
<table>
|
<td>{l.name}</td>
|
||||||
<thead class="border-b border-gray-400">
|
<td>
|
||||||
<tr class="odd:bg-white even:bg-gray-100">
|
<button
|
||||||
<th>{$_("dependency_name")}</th>
|
class="underline cursor-pointer"
|
||||||
<th>{$_("license")}</th>
|
on:click={() => {
|
||||||
<th>{$_("repo_link")}</th>
|
modal_open = true;
|
||||||
<th>{$_("installed-version")}</th>
|
currentlicense = l.name + "@" + l.version;
|
||||||
<th>{$_("author")}</th>
|
licensetext =
|
||||||
</tr>
|
l.licensetext || $_("no-license-text-could-be-found");
|
||||||
</thead>
|
}}>{l.license || "?"}</button
|
||||||
<tbody>
|
>
|
||||||
{#each licenses as l}
|
</td>
|
||||||
<tr class="odd:bg-white even:bg-gray-100">
|
<td>
|
||||||
<td>{l.name}</td>
|
{(l.repo?.url || l.repo)
|
||||||
<td>
|
.replace("git+", "")
|
||||||
{l.license || "?"}<br /><button
|
.replace("git://", "")}
|
||||||
class="underline cursor-pointer"
|
</td>
|
||||||
on:click={() => {
|
<td>{l.version || "?"}</td>
|
||||||
modal_open = true;
|
<td>{l.author?.name || l.author || "?"}</td>
|
||||||
currentlicense = l.name + "@" + l.version;
|
</tr>
|
||||||
licensetext =
|
{/each}
|
||||||
l.licensetext || $_("no-license-text-could-be-found");
|
</tbody>
|
||||||
}}>{$_("read-license")}</button
|
</table>
|
||||||
>
|
{:catch error}
|
||||||
</td>
|
<div
|
||||||
<td>
|
class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500"
|
||||||
{(l.repo?.url || l.repo)
|
>
|
||||||
.replace("git+", "")
|
<span class="inline-block align-middle mr-8">
|
||||||
.replace("git://", "")}
|
<b class="capitalize">{$_("general_promise_error")}</b>
|
||||||
</td>
|
{error}
|
||||||
<td>{l.version || "?"}</td>
|
</span>
|
||||||
<td>{l.author?.name || l.author || "?"}</td>
|
</div>
|
||||||
</tr>
|
{/await}
|
||||||
{/each}
|
</div>
|
||||||
</tbody>
|
<div class="w-full mt-8">
|
||||||
</table>
|
<p class="font-medium">{$_("icon-image-credits")}</p>
|
||||||
{:catch error}
|
<ul class="list-disc ml-6">
|
||||||
<div
|
<li>
|
||||||
class="text-white px-6 py-4 border-0 rounded relative mb-4 bg-red-500"
|
<a
|
||||||
>
|
class="underline"
|
||||||
<span class="inline-block align-middle mr-8">
|
target="_blank"
|
||||||
<b class="capitalize">{$_("general_promise_error")}</b>
|
rel="noopener noreferrer"
|
||||||
{error}
|
href="https://storyset.com">https://storyset.com</a
|
||||||
</span>
|
>
|
||||||
</div>
|
</li>
|
||||||
{/await}
|
<li>
|
||||||
</div>
|
<a
|
||||||
<div class="w-full leading-8 mt-8">
|
class="underline"
|
||||||
<p class="text-xl font-medium">{$_("icon-image-credits")}</p>
|
target="_blank"
|
||||||
<ul class="list-disc">
|
rel="noopener noreferrer"
|
||||||
<li>
|
href="https://undraw.co">https://undraw.co</a
|
||||||
<a
|
>
|
||||||
class="underline"
|
</li>
|
||||||
target="_blank"
|
<li>
|
||||||
rel="noopener noreferrer"
|
<a
|
||||||
href="https://storyset.com">https://storyset.com</a
|
class="underline"
|
||||||
>
|
target="_blank"
|
||||||
</li>
|
rel="noopener noreferrer"
|
||||||
<li>
|
href="https://remixicon.com">https://remixicon.com</a
|
||||||
<a
|
>
|
||||||
class="underline"
|
</li>
|
||||||
target="_blank"
|
</ul>
|
||||||
rel="noopener noreferrer"
|
</div>
|
||||||
href="https://undraw.co">https://undraw.co</a
|
</section>
|
||||||
>
|
|
||||||
</li>
|
|
||||||
<li>
|
|
||||||
<a
|
|
||||||
class="underline"
|
|
||||||
target="_blank"
|
|
||||||
rel="noopener noreferrer"
|
|
||||||
href="https://remixicon.com">https://remixicon.com</a
|
|
||||||
>
|
|
||||||
</li>
|
|
||||||
</ul>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
@@ -130,7 +130,7 @@
|
|||||||
bind:value={name_input_value}
|
bind:value={name_input_value}
|
||||||
type="text"
|
type="text"
|
||||||
name="firstname"
|
name="firstname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isNameValid}
|
{#if !isNameValid}
|
||||||
<span
|
<span
|
||||||
@@ -152,7 +152,7 @@
|
|||||||
bind:value={description_input_value}
|
bind:value={description_input_value}
|
||||||
type="text"
|
type="text"
|
||||||
name="trackname"
|
name="trackname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -1,237 +1,227 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import { UserGroupService } from "@odit/lfk-client-js";
|
import { UserGroupService } from "@odit/lfk-client-js";
|
||||||
|
import toast from "svelte-french-toast";
|
||||||
|
|
||||||
import PromiseError from "../base/PromiseError.svelte";
|
import PromiseError from "../base/PromiseError.svelte";
|
||||||
let data_loaded = false;
|
let data_loaded = false;
|
||||||
export let params;
|
export let params;
|
||||||
const promise = UserGroupService.userGroupControllerGetOne(params.groupid);
|
const promise = UserGroupService.userGroupControllerGetOne(params.groupid);
|
||||||
const colors = [
|
const colors = [
|
||||||
"#f3558e",
|
"#f3558e",
|
||||||
"#17b978",
|
"#17b978",
|
||||||
"#3498db",
|
"#3498db",
|
||||||
"#3f3b3b",
|
"#3f3b3b",
|
||||||
"#775ada",
|
"#775ada",
|
||||||
"#7ed6df_#000000",
|
"#7ed6df_#000000",
|
||||||
"#000000",
|
"#000000",
|
||||||
"#21e6c1_#000000",
|
"#21e6c1_#000000",
|
||||||
"#c0392b",
|
"#c0392b",
|
||||||
"#d35400",
|
"#d35400",
|
||||||
"#7f8c8d",
|
"#7f8c8d",
|
||||||
"#6ab04c",
|
"#6ab04c",
|
||||||
"#4834d4",
|
"#4834d4",
|
||||||
"#ff1f5a",
|
"#ff1f5a",
|
||||||
"#eac100",
|
"#eac100",
|
||||||
];
|
];
|
||||||
let matched_colors = [];
|
let matched_colors = [];
|
||||||
$: delete_triggered = false;
|
$: delete_triggered = false;
|
||||||
$: search_permission = "";
|
$: search_permission = "";
|
||||||
$: original_data = {};
|
$: original_data = {};
|
||||||
$: editable = {};
|
$: editable = {};
|
||||||
$: changes_performed = !(
|
$: changes_performed = !(
|
||||||
JSON.stringify(original_data) == JSON.stringify(editable)
|
JSON.stringify(original_data) == JSON.stringify(editable)
|
||||||
);
|
);
|
||||||
$: isGroupnameValid = editable.name !== "";
|
$: isGroupnameValid = editable.name !== "";
|
||||||
$: save_enabled = changes_performed && isGroupnameValid;
|
$: save_enabled = changes_performed && isGroupnameValid;
|
||||||
promise.then((data) => {
|
promise.then((data) => {
|
||||||
let current_target = "";
|
let current_target = "";
|
||||||
let colorindex = -1;
|
let colorindex = -1;
|
||||||
data.permissions = data.permissions.sort();
|
data.permissions = data.permissions.sort();
|
||||||
data.permissions.forEach((p) => {
|
data.permissions.forEach((p) => {
|
||||||
const target = p.split(":")[0];
|
const target = p.split(":")[0];
|
||||||
if (current_target !== p.split(":")[0]) {
|
if (current_target !== p.split(":")[0]) {
|
||||||
colorindex++;
|
colorindex++;
|
||||||
current_target = p.split(":")[0];
|
current_target = p.split(":")[0];
|
||||||
}
|
}
|
||||||
let background = colors[colorindex];
|
let background = colors[colorindex];
|
||||||
let foreground = "#fff";
|
let foreground = "#fff";
|
||||||
if (background.includes("_")) {
|
if (background.includes("_")) {
|
||||||
foreground = background.split("_")[1];
|
foreground = background.split("_")[1];
|
||||||
background = background.split("_")[0];
|
background = background.split("_")[0];
|
||||||
}
|
}
|
||||||
matched_colors[target] = [background, foreground];
|
matched_colors[target] = [background, foreground];
|
||||||
});
|
});
|
||||||
data_loaded = true;
|
data_loaded = true;
|
||||||
original_data = Object.assign(original_data, data);
|
original_data = Object.assign(original_data, data);
|
||||||
editable = Object.assign(editable, original_data);
|
editable = Object.assign(editable, original_data);
|
||||||
});
|
});
|
||||||
function submit() {
|
function submit() {
|
||||||
if (data_loaded === true && save_enabled) {
|
if (data_loaded === true && save_enabled) {
|
||||||
toast($_("updating-group"));
|
toast($_("updating-group"));
|
||||||
UserGroupService.userGroupControllerPut(original_data.id, editable)
|
UserGroupService.userGroupControllerPut(original_data.id, editable)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
Object.assign(original_data, editable);
|
Object.assign(original_data, editable);
|
||||||
original_data = editable;
|
original_data = editable;
|
||||||
Object.assign(original_data, editable);
|
Object.assign(original_data, editable);
|
||||||
toast.success($_("group-updated"));
|
toast.success($_("group-updated"));
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function deleteGroup() {
|
function deleteGroup() {
|
||||||
UserGroupService.userGroupControllerRemove(original_data.id, true)
|
UserGroupService.userGroupControllerRemove(original_data.id, true)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
location.replace("./");
|
location.replace("./");
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#await promise}
|
{#await promise}
|
||||||
{$_("loading-group-detail")}
|
{$_("loading-group-detail")}
|
||||||
{: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">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<nav class="w-full flex">
|
<nav class="w-full flex">
|
||||||
<ol class="list-none flex flex-row items-center justify-start">
|
<ol class="list-none flex flex-row items-center justify-start">
|
||||||
<li class="flex items-center">
|
<li class="flex items-center"></li>
|
||||||
<svg
|
<li class="flex items-center">
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2"
|
<a class="mr-2" href="../"
|
||||||
fill="currentColor"
|
><svg
|
||||||
width="24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
height="24"
|
width="24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
height="24"
|
||||||
viewBox="0 0 640 512"
|
viewBox="0 0 24 24"
|
||||||
><path
|
fill="none"
|
||||||
fill="currentColor"
|
stroke="currentColor"
|
||||||
d="M610.5 341.3c2.6-14.1 2.6-28.5 0-42.6l25.8-14.9c3-1.7 4.3-5.2 3.3-8.5-6.7-21.6-18.2-41.2-33.2-57.4-2.3-2.5-6-3.1-9-1.4l-25.8 14.9c-10.9-9.3-23.4-16.5-36.9-21.3v-29.8c0-3.4-2.4-6.4-5.7-7.1-22.3-5-45-4.8-66.2 0-3.3.7-5.7 3.7-5.7 7.1v29.8c-13.5 4.8-26 12-36.9 21.3l-25.8-14.9c-2.9-1.7-6.7-1.1-9 1.4-15 16.2-26.5 35.8-33.2 57.4-1 3.3.4 6.8 3.3 8.5l25.8 14.9c-2.6 14.1-2.6 28.5 0 42.6l-25.8 14.9c-3 1.7-4.3 5.2-3.3 8.5 6.7 21.6 18.2 41.1 33.2 57.4 2.3 2.5 6 3.1 9 1.4l25.8-14.9c10.9 9.3 23.4 16.5 36.9 21.3v29.8c0 3.4 2.4 6.4 5.7 7.1 22.3 5 45 4.8 66.2 0 3.3-.7 5.7-3.7 5.7-7.1v-29.8c13.5-4.8 26-12 36.9-21.3l25.8 14.9c2.9 1.7 6.7 1.1 9-1.4 15-16.2 26.5-35.8 33.2-57.4 1-3.3-.4-6.8-3.3-8.5l-25.8-14.9zM496 368.5c-26.8 0-48.5-21.8-48.5-48.5s21.8-48.5 48.5-48.5 48.5 21.8 48.5 48.5-21.7 48.5-48.5 48.5zM96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm224 32c1.9 0 3.7-.5 5.6-.6 8.3-21.7 20.5-42.1 36.3-59.2 7.4-8 17.9-12.6 28.9-12.6 6.9 0 13.7 1.8 19.6 5.3l7.9 4.6c.8-.5 1.6-.9 2.4-1.4 7-14.6 11.2-30.8 11.2-48 0-61.9-50.1-112-112-112S208 82.1 208 144c0 61.9 50.1 112 112 112zm105.2 194.5c-2.3-1.2-4.6-2.6-6.8-3.9-8.2 4.8-15.3 9.8-27.5 9.8-10.9 0-21.4-4.6-28.9-12.6-18.3-19.8-32.3-43.9-40.2-69.6-10.7-34.5 24.9-49.7 25.8-50.3-.1-2.6-.1-5.2 0-7.8l-7.9-4.6c-3.8-2.2-7-5-9.8-8.1-3.3.2-6.5.6-9.8.6-24.6 0-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h255.4c-3.7-6-6.2-12.8-6.2-20.3v-9.2zM173.1 274.6C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z"
|
stroke-width="2"
|
||||||
/></svg
|
stroke-linecap="round"
|
||||||
>
|
stroke-linejoin="round"
|
||||||
</li>
|
class="inline-block"
|
||||||
<li class="flex items-center">
|
><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg
|
||||||
<a class="mr-2" href="../">{$_("groups")}</a><svg
|
>
|
||||||
stroke="currentColor"
|
{$_("groups")}</a
|
||||||
fill="none"
|
>
|
||||||
stroke-width="2"
|
</li>
|
||||||
viewBox="0 0 24 24"
|
</ol>
|
||||||
stroke-linecap="round"
|
</nav>
|
||||||
stroke-linejoin="round"
|
</div>
|
||||||
class="h-3 w-3 mr-2 stroke-current"
|
</div>
|
||||||
height="1em"
|
<div class="mb-4 text-3xl font-extrabold leading-tight">
|
||||||
width="1em"
|
{editable.name}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<div data-id="group_actions_${editable.id}">
|
||||||
><line x1="5" y1="12" x2="19" y2="12" />
|
{#if store.state.jwtinfo.userdetails.permissions.includes("USERGROUP:DELETE")}
|
||||||
<polyline points="12 5 19 12 12 19" /></svg
|
{#if delete_triggered}
|
||||||
>
|
<button
|
||||||
</li>
|
on:click={deleteGroup}
|
||||||
<li class="flex items-center">
|
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:w-auto sm:text-sm"
|
||||||
<span class="mr-2">{editable.name}</span>
|
>{$_("confirm-deletion")}</button
|
||||||
</li>
|
>
|
||||||
</ol>
|
<button
|
||||||
</nav>
|
on:click={() => {
|
||||||
</div>
|
delete_triggered = !delete_triggered;
|
||||||
</div>
|
}}
|
||||||
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
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"
|
||||||
{original_data.name}
|
>{$_("cancel")}</button
|
||||||
<span data-id="group_actions_${editable.id}">
|
>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("USERGROUP:DELETE")}
|
{/if}
|
||||||
{#if delete_triggered}
|
{#if !delete_triggered}
|
||||||
<button
|
<button
|
||||||
on:click={deleteGroup}
|
on:click={() => {
|
||||||
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_triggered = true;
|
||||||
>{$_("confirm-deletion")}</button
|
}}
|
||||||
>
|
type="button"
|
||||||
<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:w-auto sm:text-sm"
|
||||||
on:click={() => {
|
>{$_("delete-group")}</button
|
||||||
delete_triggered = !delete_triggered;
|
>
|
||||||
}}
|
{/if}
|
||||||
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"
|
{/if}
|
||||||
>{$_("cancel")}</button
|
{#if !delete_triggered}
|
||||||
>
|
<button
|
||||||
{/if}
|
disabled={!save_enabled}
|
||||||
{#if !delete_triggered}
|
class:opacity-50={!save_enabled}
|
||||||
<button
|
type="button"
|
||||||
on:click={() => {
|
on:click={submit}
|
||||||
delete_triggered = true;
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
}}
|
>{$_("save-changes")}</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"
|
{/if}
|
||||||
>{$_("delete-group")}</button
|
</div>
|
||||||
>
|
</div>
|
||||||
{/if}
|
<!-- -->
|
||||||
{/if}
|
<div class="text-sm w-full mt-2">
|
||||||
{#if !delete_triggered}
|
<label for="title" class="font-semibold text-gray-700">{$_("name")}</label
|
||||||
<button
|
>
|
||||||
disabled={!save_enabled}
|
<input
|
||||||
class:opacity-50={!save_enabled}
|
autocomplete="off"
|
||||||
type="button"
|
placeholder={$_("name")}
|
||||||
on:click={submit}
|
type="text"
|
||||||
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"
|
bind:value={editable.name}
|
||||||
>{$_("save-changes")}</button
|
class:border-red-500={!isGroupnameValid}
|
||||||
>
|
class:focus:border-red-500={!isGroupnameValid}
|
||||||
{/if}
|
class:focus:ring-red-500={!isGroupnameValid}
|
||||||
</span>
|
name="title"
|
||||||
</div>
|
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-neutral-800 rounded-md p-2"
|
||||||
<!-- -->
|
/>
|
||||||
<div class="text-sm w-full">
|
{#if !isGroupnameValid}
|
||||||
<label for="title" class="font-medium text-gray-700">{$_("name")}</label>
|
<span
|
||||||
<input
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
autocomplete="off"
|
>
|
||||||
placeholder={$_("name")}
|
{$_("group-name-is-required")}
|
||||||
type="text"
|
</span>
|
||||||
bind:value={editable.name}
|
{/if}
|
||||||
class:border-red-500={!isGroupnameValid}
|
</div>
|
||||||
class:focus:border-red-500={!isGroupnameValid}
|
<div class="text-sm w-full mt-2">
|
||||||
class:focus:ring-red-500={!isGroupnameValid}
|
<label for="groupdescription" class="font-semibold text-gray-700"
|
||||||
name="title"
|
>{$_("description")}</label
|
||||||
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"
|
>
|
||||||
/>
|
<input
|
||||||
{#if !isGroupnameValid}
|
autocomplete="off"
|
||||||
<span
|
placeholder={$_("description")}
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
type="text"
|
||||||
>
|
bind:value={editable.description}
|
||||||
{$_("group-name-is-required")}
|
name="groupdescription"
|
||||||
</span>
|
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-neutral-800 rounded-md p-2"
|
||||||
{/if}
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full mt-2">
|
||||||
<label for="firstname" class="font-medium text-gray-700"
|
<p class="font-semibold mb-4">
|
||||||
>{$_("description")}</label
|
{$_("permissions")}
|
||||||
>
|
</p>
|
||||||
<input
|
<div>
|
||||||
autocomplete="off"
|
<a
|
||||||
placeholder={$_("description")}
|
class="px-4 py-2 bg-gray-500 rounded-md text-white"
|
||||||
type="text"
|
href="/groups/{params.groupid}/permissions/"
|
||||||
bind:value={editable.description}
|
>{$_("edit-permissions")}</a
|
||||||
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"
|
</div>
|
||||||
/>
|
<div class="w-full sm:my-px sm:px-px sm:w-1/2">
|
||||||
</div>
|
<input
|
||||||
<div class="text-sm w-full mt-8">
|
autocomplete="off"
|
||||||
<p class="font-medium mb-4">
|
placeholder={$_("search-for-permission")}
|
||||||
{$_("permissions")}
|
type="text"
|
||||||
<a
|
bind:value={search_permission}
|
||||||
class="px-4 py-2 bg-gray-500 rounded-md text-white"
|
class="mt-4 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-neutral-800 rounded-md p-2"
|
||||||
href="/groups/{params.groupid}/permissions/"
|
/>
|
||||||
>{$_("edit-permissions")}</a
|
</div>
|
||||||
>
|
{#each original_data.permissions as p}
|
||||||
</p>
|
{#if p.toLowerCase().includes(search_permission.toLowerCase())}
|
||||||
<div class="w-full sm:my-px sm:px-px sm:w-1/2">
|
<span
|
||||||
<input
|
style="background:{matched_colors[
|
||||||
autocomplete="off"
|
p.split(':')[0]
|
||||||
placeholder={$_("search-for-permission")}
|
][0]};color:{matched_colors[p.split(':')[0]][1]};"
|
||||||
type="text"
|
class="mt-1 inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-indigo-100 rounded"
|
||||||
bind:value={search_permission}
|
>{p}</span
|
||||||
class="mt-4 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>
|
{/if}
|
||||||
{#each original_data.permissions as p}
|
{/each}
|
||||||
{#if p.toLowerCase().includes(search_permission.toLowerCase())}
|
</div>
|
||||||
<span
|
</section>
|
||||||
style="background:{matched_colors[
|
|
||||||
p.split(':')[0]
|
|
||||||
][0]};color:{matched_colors[p.split(':')[0]][1]};"
|
|
||||||
class="mt-1 inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-indigo-100 rounded"
|
|
||||||
>{p}</span
|
|
||||||
>
|
|
||||||
<!-- -->
|
|
||||||
{/if}
|
|
||||||
{/each}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{:catch error}
|
{:catch error}
|
||||||
<PromiseError {error} />
|
<PromiseError {error} />
|
||||||
{/await}
|
{/await}
|
||||||
@@ -5,6 +5,7 @@
|
|||||||
CreatePermission,
|
CreatePermission,
|
||||||
UserGroupService,
|
UserGroupService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
|
import toast from 'svelte-french-toast'
|
||||||
|
|
||||||
import PromiseError from "../base/PromiseError.svelte";
|
import PromiseError from "../base/PromiseError.svelte";
|
||||||
export let params;
|
export let params;
|
||||||
@@ -132,27 +133,25 @@
|
|||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-8 text-3xl font-extrabold">
|
<div class="mb-4 text-3xl font-extrabold">
|
||||||
{$_("permissions")}:
|
<div>
|
||||||
{original_data.name}
|
|
||||||
<span>
|
|
||||||
{#if promises.length === 0}
|
{#if promises.length === 0}
|
||||||
<button
|
<button
|
||||||
disabled={save_enabled}
|
disabled={save_enabled}
|
||||||
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"
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
>{$_("save-changes")}</button
|
>{$_("save-changes")}</button
|
||||||
>
|
>
|
||||||
{:else}
|
{:else}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-yellow-600 text-base font-medium text-white hover:bg-yellow-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-yellow-500 sm:ml-3 sm:w-auto sm:text-sm"
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-yellow-600 text-base font-medium text-white hover:bg-yellow-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-yellow-500 sm:w-auto sm:text-sm"
|
||||||
>{$_("applying-changes")}</button
|
>{$_("applying-changes")}</button
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
</span>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
<div class="flex flex-wrap -mx-1 overflow-hidden">
|
<div class="flex flex-wrap -mx-1 overflow-hidden">
|
||||||
@@ -192,7 +191,7 @@
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-200 text-base font-medium text-black hover:bg-green-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 sm:ml-3 sm:w-auto sm:text-sm"
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-200 text-base font-medium text-black hover:bg-green-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 sm:w-auto sm:text-sm"
|
||||||
>+</button
|
>+</button
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
@@ -232,7 +231,7 @@
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-300 text-base font-medium text-black hover:bg-red-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm"
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-300 text-base font-medium text-black hover:bg-red-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:w-auto sm:text-sm"
|
||||||
>-</button
|
>-</button
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -8,20 +8,20 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_("user-groups")}
|
{$_("user-groups")}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("USERGROUP:CREATE")}
|
</h4>
|
||||||
<button
|
{#if store.state.jwtinfo.userdetails.permissions.includes("USERGROUP:CREATE")}
|
||||||
on:click={() => {
|
<button
|
||||||
modal_open = true;
|
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"
|
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:w-auto sm:text-sm"
|
||||||
{$_("add-user-group")}
|
>
|
||||||
</button>
|
{$_("add-user-group")}
|
||||||
{/if}
|
</button>
|
||||||
</span>
|
{/if}
|
||||||
<UserGroupsOverview bind:current_groups />
|
<UserGroupsOverview bind:current_groups />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@@ -31,7 +31,7 @@
|
|||||||
bind:value={searchvalue}
|
bind:value={searchvalue}
|
||||||
placeholder={$_("datatable.search")}
|
placeholder={$_("datatable.search")}
|
||||||
aria-label={$_("datatable.search")}
|
aria-label={$_("datatable.search")}
|
||||||
class="mb-4"
|
class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
|
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
|
||||||
|
|||||||
@@ -153,7 +153,7 @@
|
|||||||
bind:this={name_input_dom}
|
bind:this={name_input_dom}
|
||||||
type="text"
|
type="text"
|
||||||
name="firstname"
|
name="firstname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isOrgnameValid}
|
{#if !isOrgnameValid}
|
||||||
<span
|
<span
|
||||||
@@ -174,7 +174,7 @@
|
|||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="ml-3 text-sm">
|
<div class="ml-3 text-sm">
|
||||||
<label for="comments" class="font-medium text-gray-700"
|
<label for="comments" class="font-semibold text-gray-700"
|
||||||
>{$_("address")}</label
|
>{$_("address")}</label
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
@@ -196,7 +196,7 @@
|
|||||||
bind:this={address_input1}
|
bind:this={address_input1}
|
||||||
type="text"
|
type="text"
|
||||||
name="address1"
|
name="address1"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isAddress1Valid}
|
{#if !isAddress1Valid}
|
||||||
<span
|
<span
|
||||||
@@ -219,7 +219,7 @@
|
|||||||
bind:this={address_input2}
|
bind:this={address_input2}
|
||||||
type="text"
|
type="text"
|
||||||
name="address2"
|
name="address2"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
@@ -238,7 +238,7 @@
|
|||||||
bind:this={address_zipcode}
|
bind:this={address_zipcode}
|
||||||
type="text"
|
type="text"
|
||||||
name="zipcode"
|
name="zipcode"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !iszipcodevalid}
|
{#if !iszipcodevalid}
|
||||||
<span
|
<span
|
||||||
@@ -264,7 +264,7 @@
|
|||||||
bind:this={address_city}
|
bind:this={address_city}
|
||||||
type="text"
|
type="text"
|
||||||
name="city"
|
name="city"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !iscityvalid}
|
{#if !iscityvalid}
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -1,108 +0,0 @@
|
|||||||
<script>
|
|
||||||
import { _ } from "svelte-i18n";
|
|
||||||
import { clickOutside } from "../base/outsideclick";
|
|
||||||
|
|
||||||
import { RunnerOrganizationService } from "@odit/lfk-client-js";
|
|
||||||
|
|
||||||
import { createEventDispatcher } from "svelte";
|
|
||||||
export let modal_open;
|
|
||||||
export let delete_org;
|
|
||||||
const dispatch = createEventDispatcher();
|
|
||||||
function cancelDelete() {
|
|
||||||
modal_open = false;
|
|
||||||
dispatch("cancelDelete", { id: delete_org.id });
|
|
||||||
}
|
|
||||||
function deleteOrg() {
|
|
||||||
RunnerOrganizationService.runnerOrganizationControllerRemove(
|
|
||||||
delete_org.id,
|
|
||||||
true
|
|
||||||
)
|
|
||||||
.then((resp) => {
|
|
||||||
toast($_("organization-deleted"));
|
|
||||||
location.replace("./");
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
</script>
|
|
||||||
|
|
||||||
{#if modal_open}
|
|
||||||
<div
|
|
||||||
class="fixed z-10 inset-0 overflow-y-auto"
|
|
||||||
use:clickOutside
|
|
||||||
on:click_outside={cancelDelete}
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
|
||||||
>
|
|
||||||
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
|
||||||
<div
|
|
||||||
class="absolute inset-0 bg-gray-500 opacity-75"
|
|
||||||
data-id="modal_backdrop"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<span
|
|
||||||
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
|
||||||
aria-hidden="true">​</span
|
|
||||||
>
|
|
||||||
<div
|
|
||||||
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
|
||||||
role="dialog"
|
|
||||||
aria-modal="true"
|
|
||||||
aria-labelledby="modal-headline"
|
|
||||||
>
|
|
||||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
|
||||||
<div class="sm:flex sm:items-start">
|
|
||||||
<div
|
|
||||||
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
|
||||||
>
|
|
||||||
<svg
|
|
||||||
class="h-6 w-6 text-blue-600"
|
|
||||||
fill="currentColor"
|
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
|
||||||
viewBox="0 0 640 512"
|
|
||||||
><path
|
|
||||||
fill="currentColor"
|
|
||||||
d="M96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm448 0c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm32 32h-64c-17.6 0-33.5 7.1-45.1 18.6 40.3 22.1 68.9 62 75.1 109.4h66c17.7 0 32-14.3 32-32v-32c0-35.3-28.7-64-64-64zm-256 0c61.9 0 112-50.1 112-112S381.9 32 320 32 208 82.1 208 144s50.1 112 112 112zm76.8 32h-8.3c-20.8 10-43.9 16-68.5 16s-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48v-28.8c0-63.6-51.6-115.2-115.2-115.2zm-223.7-13.4C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z"
|
|
||||||
/></svg
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
|
||||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
|
||||||
{$_("attention")}
|
|
||||||
</h3>
|
|
||||||
<div class="mt-2 mb-6">
|
|
||||||
<p class="text-sm text-gray-500">
|
|
||||||
{$_(
|
|
||||||
"do-you-want-to-delete-the-organization-delete_org-name",
|
|
||||||
{
|
|
||||||
values: { orgname: delete_org.name },
|
|
||||||
}
|
|
||||||
)}<br />
|
|
||||||
{$_("all-associated-teams-and-runners-will-be-deleted-too")}
|
|
||||||
</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={deleteOrg}
|
|
||||||
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-organization-and-associated-teams-runners")}
|
|
||||||
</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-organization")}
|
|
||||||
</button>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
@@ -0,0 +1,104 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import { clickOutside } from "../base/outsideclick";
|
||||||
|
|
||||||
|
import { RunnerOrganizationService } from "@odit/lfk-client-js";
|
||||||
|
|
||||||
|
import { createEventDispatcher } from "svelte";
|
||||||
|
export let modal_open;
|
||||||
|
export let delete_org;
|
||||||
|
const dispatch = createEventDispatcher();
|
||||||
|
function cancelDelete() {
|
||||||
|
modal_open = false;
|
||||||
|
dispatch("cancelDelete", { id: delete_org.id });
|
||||||
|
}
|
||||||
|
function deleteOrg() {
|
||||||
|
RunnerOrganizationService.runnerOrganizationControllerRemove(
|
||||||
|
delete_org.id,
|
||||||
|
true
|
||||||
|
)
|
||||||
|
.then((resp) => {
|
||||||
|
toast($_("organization-deleted"));
|
||||||
|
location.replace("./");
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if modal_open}
|
||||||
|
<div
|
||||||
|
class="fixed z-10 inset-0 overflow-y-auto"
|
||||||
|
use:clickOutside
|
||||||
|
on:click_outside={cancelDelete}
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
||||||
|
>
|
||||||
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
|
<div
|
||||||
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
|
data-id="modal_backdrop"
|
||||||
|
/>
|
||||||
|
</div>
|
||||||
|
<span
|
||||||
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
|
aria-hidden="true">​</span
|
||||||
|
>
|
||||||
|
<div
|
||||||
|
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
|
role="dialog"
|
||||||
|
aria-modal="true"
|
||||||
|
aria-labelledby="modal-headline"
|
||||||
|
>
|
||||||
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
|
<div class="sm:flex sm:items-start">
|
||||||
|
<div
|
||||||
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
class="h-6 w-6 text-blue-600"
|
||||||
|
fill="currentColor"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 640 512"
|
||||||
|
><path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm448 0c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm32 32h-64c-17.6 0-33.5 7.1-45.1 18.6 40.3 22.1 68.9 62 75.1 109.4h66c17.7 0 32-14.3 32-32v-32c0-35.3-28.7-64-64-64zm-256 0c61.9 0 112-50.1 112-112S381.9 32 320 32 208 82.1 208 144s50.1 112 112 112zm76.8 32h-8.3c-20.8 10-43.9 16-68.5 16s-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48v-28.8c0-63.6-51.6-115.2-115.2-115.2zm-223.7-13.4C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</div>
|
||||||
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
|
{$_("do-you-want-to-delete-the-organization-delete_org-name", {
|
||||||
|
values: { orgname: delete_org.name },
|
||||||
|
})}
|
||||||
|
</h3>
|
||||||
|
<div class="mt-2 mb-6">
|
||||||
|
<p class="text-sm text-gray-500">
|
||||||
|
{$_("all-associated-teams-and-runners-will-be-deleted-too")}
|
||||||
|
</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={deleteOrg}
|
||||||
|
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-organization-and-associated-teams-runners")}
|
||||||
|
</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-organization")}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -1,482 +1,421 @@
|
|||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
GroupContactService,
|
GroupContactService,
|
||||||
RunnerOrganizationService,
|
RunnerOrganizationService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
import toast from "svelte-french-toast";
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
import store from "../../store";
|
import { tick } from "svelte";
|
||||||
import ConfirmOrgDeletion from "./ConfirmOrgDeletion.svelte";
|
import Select from "svelte-select";
|
||||||
import ImportRunnerModal from "../runners/ImportRunnerModal.svelte";
|
import store from "../../store";
|
||||||
import PromiseError from "../base/PromiseError.svelte";
|
import PromiseError from "../base/PromiseError.svelte";
|
||||||
import Select from "svelte-select";
|
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
||||||
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
||||||
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
||||||
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
import ImportRunnerModal from "../runners/ImportRunnerModal.svelte";
|
||||||
import { tick } from "svelte";
|
import ConfirmOrgDeletionModal from "./ConfirmOrgDeletionModal.svelte";
|
||||||
$: delete_triggered = false;
|
$: address_valid_or_none =
|
||||||
$: address_valid_or_none =
|
(isAddress1Valid && iszipcodevalid && iscityvalid) ||
|
||||||
(isAddress1Valid && iszipcodevalid && iscityvalid) ||
|
editable.address_checked === false;
|
||||||
editable.address_checked === false;
|
$: save_enabled = data_changed && address_valid_or_none;
|
||||||
$: save_enabled = data_changed && address_valid_or_none;
|
let original = "";
|
||||||
let original = "";
|
let original_object = {};
|
||||||
let original_object = {};
|
let contacts = [];
|
||||||
let contacts = [];
|
let valueCopy = null;
|
||||||
let valueCopy = null;
|
let areaDom;
|
||||||
let areaDom;
|
export let params;
|
||||||
let copied = false;
|
$: editable = {};
|
||||||
export let params;
|
$: contact = {};
|
||||||
$: editable = {};
|
$: data_loaded = false;
|
||||||
$: contact = {};
|
$: data_changed = !(JSON.stringify(editable) === original);
|
||||||
$: data_loaded = false;
|
$: isAddress1Valid = editable.address?.address1?.trim().length !== 0;
|
||||||
$: data_changed = !(JSON.stringify(editable) === original);
|
$: iszipcodevalid = editable.address?.postalcode?.trim().length !== 0;
|
||||||
$: isAddress1Valid = editable.address?.address1?.trim().length !== 0;
|
$: iscityvalid = editable.address?.city?.trim().length !== 0;
|
||||||
$: iszipcodevalid = editable.address?.postalcode?.trim().length !== 0;
|
$: sponsoring_contracts_show = true;
|
||||||
$: iscityvalid = editable.address?.city?.trim().length !== 0;
|
$: cards_show = true;
|
||||||
$: sponsoring_contracts_show = true;
|
$: certificates_show = true;
|
||||||
$: cards_show = true;
|
$: generate_orgs = [original_object];
|
||||||
$: certificates_show = true;
|
$: registrationLink = `${config.baseurl_selfservice}/register/${editable.registrationKey}`;
|
||||||
$: generate_orgs = [original_object];
|
const getContactLabel = (option) =>
|
||||||
$: registrationLink = `${config.baseurl}/selfservice/register/${editable.registrationKey}`;
|
option.firstname + " " + (option.middlename || "") + " " + option.lastname;
|
||||||
const getContactLabel = (option) =>
|
const promise = RunnerOrganizationService.runnerOrganizationControllerGetOne(
|
||||||
option.firstname + " " + (option.middlename || "") + " " + option.lastname;
|
params.orgid
|
||||||
const promise = RunnerOrganizationService.runnerOrganizationControllerGetOne(
|
).then((value) => {
|
||||||
params.orgid
|
data_loaded = true;
|
||||||
).then((value) => {
|
value.address_checked = value.address.address1 !== null;
|
||||||
data_loaded = true;
|
if (value.address_checked === false) {
|
||||||
value.address_checked = value.address.address1 !== null;
|
value.address = {
|
||||||
if (value.address_checked === false) {
|
address1: "",
|
||||||
value.address = {
|
address2: "",
|
||||||
address1: "",
|
city: "",
|
||||||
address2: "",
|
postalcode: "",
|
||||||
city: "",
|
country: "",
|
||||||
postalcode: "",
|
};
|
||||||
country: "",
|
}
|
||||||
};
|
editable = Object.assign(editable, value);
|
||||||
}
|
editable = editable;
|
||||||
editable = Object.assign(editable, value);
|
original_object = Object.assign(editable, value);
|
||||||
editable = editable;
|
original = JSON.stringify(value);
|
||||||
original_object = Object.assign(editable, value);
|
GroupContactService.groupContactControllerGetAll().then((val) => {
|
||||||
original = JSON.stringify(value);
|
contacts = val.map((r) => {
|
||||||
GroupContactService.groupContactControllerGetAll().then((val) => {
|
return { label: getContactLabel(r), value: r };
|
||||||
contacts = val.map((r) => {
|
});
|
||||||
return { label: getContactLabel(r), value: r };
|
if (editable.contact) {
|
||||||
});
|
contact = contacts.find((g) => g.value.id == editable.contact.id);
|
||||||
if (editable.contact) {
|
} else {
|
||||||
contact = contacts.find((g) => g.value.id == editable.contact.id);
|
contact = null;
|
||||||
} else {
|
}
|
||||||
contact = null;
|
});
|
||||||
}
|
});
|
||||||
});
|
let modal_open = false;
|
||||||
});
|
let delete_org = {};
|
||||||
let modal_open = false;
|
function deleteOrganization() {
|
||||||
let delete_org = {};
|
RunnerOrganizationService.runnerOrganizationControllerRemove(
|
||||||
function deleteOrganization() {
|
original_object.id,
|
||||||
RunnerOrganizationService.runnerOrganizationControllerRemove(
|
false
|
||||||
original_object.id,
|
)
|
||||||
false
|
.then((resp) => {
|
||||||
)
|
toast($_("organization-deleted"));
|
||||||
.then((resp) => {
|
location.replace("./");
|
||||||
toast($_("organization-deleted"));
|
})
|
||||||
location.replace("./");
|
.catch((err) => {});
|
||||||
})
|
}
|
||||||
.catch((err) => {
|
function submit() {
|
||||||
modal_open = true;
|
if (data_loaded === true && save_enabled) {
|
||||||
delete_org = original_object;
|
toast($_("updating-organization"));
|
||||||
});
|
let postdata = Object.assign({}, editable);
|
||||||
}
|
if (postdata.address_checked === false) {
|
||||||
function submit() {
|
postdata.address = null;
|
||||||
if (data_loaded === true && save_enabled) {
|
}
|
||||||
toast($_("updating-organization"));
|
postdata.contact = postdata.contact?.id;
|
||||||
let postdata = Object.assign({}, editable);
|
RunnerOrganizationService.runnerOrganizationControllerPut(
|
||||||
if (postdata.address_checked === false) {
|
original_object.id,
|
||||||
postdata.address = null;
|
postdata
|
||||||
}
|
)
|
||||||
postdata.contact = postdata.contact?.id;
|
.then((resp) => {
|
||||||
RunnerOrganizationService.runnerOrganizationControllerPut(
|
editable.registrationKey = resp.registrationKey;
|
||||||
original_object.id,
|
original_object = Object.assign({}, editable);
|
||||||
postdata
|
original = JSON.stringify(original_object);
|
||||||
)
|
toast.success($_("updated-organization"));
|
||||||
.then((resp) => {
|
})
|
||||||
editable.registrationKey = resp.registrationKey;
|
.catch((err) => {});
|
||||||
original_object = Object.assign({}, editable);
|
} else {
|
||||||
original = JSON.stringify(original_object);
|
}
|
||||||
toast.success($_("updated-organization"));
|
}
|
||||||
})
|
async function copy() {
|
||||||
.catch((err) => {});
|
if (!editable.registrationKey) {
|
||||||
} else {
|
toast.error($_("you-have-to-save-your-changes-to-generate-a-link"));
|
||||||
}
|
return;
|
||||||
}
|
}
|
||||||
async function copy() {
|
valueCopy = registrationLink;
|
||||||
if (!editable.registrationKey) {
|
await tick();
|
||||||
toast.error($_("you-have-to-save-your-changes-to-generate-a-link"));
|
areaDom.focus();
|
||||||
return;
|
areaDom.select();
|
||||||
}
|
try {
|
||||||
valueCopy = registrationLink;
|
const successful = document.execCommand("copy");
|
||||||
await tick();
|
if (!successful) {
|
||||||
areaDom.focus();
|
throw new Error();
|
||||||
areaDom.select();
|
}
|
||||||
try {
|
toast($_("copied-link-to-clipboard"));
|
||||||
const successful = document.execCommand("copy");
|
} catch (err) {
|
||||||
if (!successful) {
|
toast.error($_("error-whyile-copying-to-clipboard"));
|
||||||
throw new Error();
|
}
|
||||||
}
|
// we can notifi by event or storage about copy status
|
||||||
toast($_("copied-link-to-clipboard"));
|
valueCopy = null;
|
||||||
copied = true;
|
}
|
||||||
} catch (err) {
|
export let import_modal_open = false;
|
||||||
toast.error($_("error-whyile-copying-to-clipboard"));
|
|
||||||
}
|
|
||||||
// we can notifi by event or storage about copy status
|
|
||||||
valueCopy = null;
|
|
||||||
}
|
|
||||||
export let import_modal_open = false;
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if valueCopy != null}<textarea bind:this={areaDom}>{valueCopy}</textarea>{/if}
|
{#if valueCopy != null}<textarea bind:this={areaDom}>{valueCopy}</textarea>{/if}
|
||||||
<ImportRunnerModal
|
<ImportRunnerModal
|
||||||
on:cancelDelete={(event) => {
|
on:cancelDelete={(event) => {
|
||||||
import_modal_open = false;
|
import_modal_open = false;
|
||||||
}}
|
}}
|
||||||
current_runners={[]}
|
current_runners={[]}
|
||||||
passed_team={{}}
|
passed_team={{}}
|
||||||
passed_orgs={[]}
|
passed_orgs={[]}
|
||||||
passed_org={editable}
|
passed_org={editable}
|
||||||
opened_from="OrgDetail"
|
opened_from="OrgDetail"
|
||||||
bind:import_modal_open
|
bind:import_modal_open
|
||||||
/>
|
/>
|
||||||
<ConfirmOrgDeletion bind:modal_open bind:delete_org />
|
<ConfirmOrgDeletionModal bind:modal_open bind:delete_org />
|
||||||
{#if data_loaded}
|
{#if data_loaded}
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
<div class="flex flex-row mb-4">
|
||||||
{original_object.name}
|
<div class="w-full">
|
||||||
<span data-id="org_actions_${editable.id}">
|
<nav class="w-full flex">
|
||||||
<GenerateSponsoringContracts
|
<ol class="list-none flex flex-row items-center justify-start">
|
||||||
bind:sponsoring_contracts_show
|
<li class="flex items-center">
|
||||||
bind:generate_orgs
|
<a class="mr-2" href="./"
|
||||||
/>
|
><svg
|
||||||
<GenerateRunnerCards bind:cards_show bind:generate_orgs />
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
<GenerateRunnerCertificates bind:certificates_show bind:generate_orgs />
|
width="24"
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:IMPORT")}
|
height="24"
|
||||||
<button
|
viewBox="0 0 24 24"
|
||||||
on:click={() => {
|
fill="none"
|
||||||
import_modal_open = true;
|
stroke="currentColor"
|
||||||
}}
|
stroke-width="2"
|
||||||
type="button"
|
stroke-linecap="round"
|
||||||
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"
|
stroke-linejoin="round"
|
||||||
>
|
class="inline-block"
|
||||||
{$_("import-runners")}
|
><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg
|
||||||
</button>
|
>
|
||||||
{/if}
|
{$_("organizations")}</a
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:DELETE")}
|
>
|
||||||
{#if delete_triggered}
|
</li>
|
||||||
<button
|
</ol>
|
||||||
on:click={deleteOrganization}
|
</nav>
|
||||||
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"
|
</div>
|
||||||
>{$_("confirm-delete")}</button
|
</div>
|
||||||
>
|
<div class="mb-4 text-3xl font-extrabold leading-tight">
|
||||||
<button
|
{original_object.name} [#{params.orgid}]
|
||||||
on:click={() => {
|
<div data-id="org_actions_${editable.id}">
|
||||||
delete_triggered = !delete_triggered;
|
<GenerateSponsoringContracts
|
||||||
}}
|
bind:sponsoring_contracts_show
|
||||||
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"
|
bind:generate_orgs
|
||||||
>{$_("cancel")}</button
|
/>
|
||||||
>
|
<GenerateRunnerCards bind:cards_show bind:generate_orgs />
|
||||||
{/if}
|
<GenerateRunnerCertificates bind:certificates_show bind:generate_orgs />
|
||||||
{#if !delete_triggered}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:IMPORT")}
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
delete_triggered = true;
|
import_modal_open = 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"
|
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:w-auto sm:text-sm"
|
||||||
>{$_("delete-organization")}</button
|
>
|
||||||
>
|
{$_("import-runners")}
|
||||||
{/if}
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
{#if !delete_triggered}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:DELETE")}
|
||||||
<button
|
<button
|
||||||
on:click={submit}
|
on:click={() => {
|
||||||
disabled={!save_enabled}
|
modal_open = true;
|
||||||
class:opacity-50={!save_enabled}
|
delete_org = original_object;
|
||||||
type="button"
|
}}
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
type="button"
|
||||||
>{$_("save-changes")}</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:w-auto sm:text-sm"
|
||||||
>
|
>{$_("delete-organization")}</button
|
||||||
{/if}
|
>
|
||||||
</span>
|
{/if}
|
||||||
</div>
|
<button
|
||||||
<div class="flex flex-row mb-4">
|
on:click={submit}
|
||||||
<div class="w-full">
|
disabled={!save_enabled}
|
||||||
<nav class="w-full flex">
|
class:opacity-50={!save_enabled}
|
||||||
<ol class="list-none flex flex-row items-center justify-start">
|
type="button"
|
||||||
<li class="mr-2 flex items-center">
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
<svg
|
>{$_("save-changes")}</button
|
||||||
stroke="currentColor"
|
>
|
||||||
fill="none"
|
</div>
|
||||||
stroke-width="2"
|
</div>
|
||||||
viewBox="0 0 24 24"
|
<div class="text-sm w-full mt-2">
|
||||||
stroke-linecap="round"
|
<label for="name" class="font-semibold text-gray-700">{$_("name")}</label>
|
||||||
stroke-linejoin="round"
|
<input
|
||||||
class="h-3 w-3 stroke-current"
|
autocomplete="off"
|
||||||
height="1em"
|
placeholder={$_("name")}
|
||||||
width="1em"
|
type="text"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
bind:value={editable.name}
|
||||||
><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
|
name="name"
|
||||||
<polyline points="9 22 9 12 15 12 15 22" /></svg
|
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-neutral-800 rounded-md p-2"
|
||||||
>
|
/>
|
||||||
</li>
|
</div>
|
||||||
<li class="flex items-center">
|
<div class="text-sm w-full mt-2">
|
||||||
<a class="mr-2" href="/">{$_("home")}</a><svg
|
<label for="contact" class="font-semibold text-gray-700"
|
||||||
stroke="currentColor"
|
>{$_("contact")}</label
|
||||||
fill="none"
|
>
|
||||||
stroke-width="2"
|
<Select
|
||||||
viewBox="0 0 24 24"
|
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-neutral-800 rounded-md p-2"
|
||||||
stroke-linecap="round"
|
itemFilter={(label, filterText, option) =>
|
||||||
stroke-linejoin="round"
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
class="h-3 w-3 mr-2 stroke-current"
|
option.value.id.toString().startsWith(filterText.toLowerCase())}
|
||||||
height="1em"
|
items={contacts}
|
||||||
width="1em"
|
showChevron={true}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
placeholder={$_("no-contact-selected")}
|
||||||
><line x1="5" y1="12" x2="19" y2="12" />
|
noOptionsMessage={$_("no-contact-found")}
|
||||||
<polyline points="12 5 19 12 12 19" /></svg
|
bind:selectedValue={contact}
|
||||||
>
|
on:select={(selectedValue) =>
|
||||||
</li>
|
(editable.contact = selectedValue.detail.value)}
|
||||||
<li class="mr-2 flex items-center">
|
on:clear={() => (editable.contact = null)}
|
||||||
<svg
|
/>
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
</div>
|
||||||
viewBox="0 0 24 24"
|
<div>
|
||||||
width="24"
|
<div class="flex items-start mt-2">
|
||||||
height="24"
|
<div class="flex items-center h-5">
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
<input
|
||||||
<path
|
bind:checked={editable.registrationEnabled}
|
||||||
d="M21 20h2v2H1v-2h2V3a1 1 0 0 1 1-1h16a1 1 0 0 1 1 1v17zm-2 0V4H5v16h14zM8 11h3v2H8v-2zm0-4h3v2H8V7zm0 8h3v2H8v-2zm5 0h3v2h-3v-2zm0-4h3v2h-3v-2zm0-4h3v2h-3V7z"
|
id="toggle_selfservice_feature"
|
||||||
/></svg
|
name="toggle_selfservice_feature"
|
||||||
>
|
type="checkbox"
|
||||||
</li>
|
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
<li class="flex items-center">
|
/>
|
||||||
<a class="mr-2" href="./">{$_("organizations")}</a><svg
|
</div>
|
||||||
stroke="currentColor"
|
<div class="ml-3 text-sm">
|
||||||
fill="none"
|
<label
|
||||||
stroke-width="2"
|
for="toggle_selfservice_feature"
|
||||||
viewBox="0 0 24 24"
|
class="font-semibold text-gray-700"
|
||||||
stroke-linecap="round"
|
>{$_("selfservice-registration")}</label
|
||||||
stroke-linejoin="round"
|
>
|
||||||
class="h-3 w-3 mr-2 stroke-current"
|
</div>
|
||||||
height="1em"
|
</div>
|
||||||
width="1em"
|
<div>
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
{#if editable.registrationEnabled}
|
||||||
><line x1="5" y1="12" x2="19" y2="12" />
|
<div class="text-sm w-full mt-2">
|
||||||
<polyline points="12 5 19 12 12 19" /></svg
|
<button on:click={copy} class="inline-flex w-full">
|
||||||
>
|
<p
|
||||||
</li>
|
name="token"
|
||||||
<li class="flex items-center">
|
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-neutral-800 p-2"
|
||||||
<span class="mr-2">Org-Details #{params.orgid}</span>
|
>
|
||||||
</li>
|
{#if editable.registrationKey}
|
||||||
</ol>
|
{registrationLink}
|
||||||
</nav>
|
{:else}
|
||||||
</div>
|
{$_("you-have-to-save-your-changes-to-generate-a-link")}
|
||||||
</div>
|
{/if}
|
||||||
<div class="text-sm w-full">
|
</p>
|
||||||
<label for="name" class="font-medium text-gray-700">{$_("name")}</label>
|
<div
|
||||||
<input
|
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"
|
||||||
autocomplete="off"
|
>
|
||||||
placeholder={$_("name")}
|
<svg
|
||||||
type="text"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
bind:value={editable.name}
|
viewBox="0 0 24 24"
|
||||||
name="name"
|
width="24"
|
||||||
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"
|
height="24"
|
||||||
/>
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
</div>
|
<path
|
||||||
<div class="text-sm w-full">
|
fill="currentColor"
|
||||||
<label for="contact" class="font-medium text-gray-700"
|
d="M7 4V2h10v2h3l1 1v16a1 1 0 01-1 1H4a1 1 0 01-1-1V5l1-1h3zm0 2H5v14h14V6h-2v2H7V6zm2-2v2h6V4H9z"
|
||||||
>{$_("contact")}</label
|
/></svg
|
||||||
>
|
>
|
||||||
<Select
|
</div>
|
||||||
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"
|
</button>
|
||||||
itemFilter={(label, filterText, option) =>
|
{#if editable.registrationKey}
|
||||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
<p class="text-gray-500 text-xs">
|
||||||
option.value.id.toString().startsWith(filterText.toLowerCase())}
|
{$_("click-to-copy-the-link-into-your-clipboard")}
|
||||||
items={contacts}
|
</p>
|
||||||
showChevron={true}
|
{/if}
|
||||||
placeholder={$_("no-contact-selected")}
|
</div>
|
||||||
noOptionsMessage={$_("no-contact-found")}
|
{/if}
|
||||||
bind:selectedValue={contact}
|
<!-- -->
|
||||||
on:select={(selectedValue) =>
|
<div>
|
||||||
(editable.contact = selectedValue.detail.value)}
|
<div class="flex items-start mt-2">
|
||||||
on:clear={() => (editable.contact = null)}
|
<div class="flex items-center h-5">
|
||||||
/>
|
<input
|
||||||
</div>
|
bind:checked={editable.address_checked}
|
||||||
<div>
|
id="toggle_address_checkbox"
|
||||||
<div class="flex items-start mt-2">
|
name="toggle_address_checkbox"
|
||||||
<div class="flex items-center h-5">
|
type="checkbox"
|
||||||
<input
|
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
bind:checked={editable.registrationEnabled}
|
/>
|
||||||
id="toggle_selfservice_feature"
|
</div>
|
||||||
name="toggle_selfservice_feature"
|
<div class="ml-3 text-sm">
|
||||||
type="checkbox"
|
<label
|
||||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
for="toggle_address_checkbox"
|
||||||
/>
|
class="font-semibold text-gray-700">{$_("address")}</label
|
||||||
</div>
|
>
|
||||||
<div class="ml-3 text-sm">
|
</div>
|
||||||
<label
|
</div>
|
||||||
for="toggle_selfservice_feature"
|
</div>
|
||||||
class="font-medium text-gray-700"
|
{#if editable.address_checked === true}
|
||||||
>{$_("selfservice-registration")}</label
|
<div class="col-span-6">
|
||||||
>
|
<label
|
||||||
</div>
|
for="address1"
|
||||||
</div>
|
class="block text-sm font-medium text-gray-700"
|
||||||
<div>
|
>{$_("address")}</label
|
||||||
{#if editable.registrationEnabled}
|
>
|
||||||
<div class="text-sm w-full">
|
<input
|
||||||
<button on:click={copy} class="inline-flex w-full">
|
autocomplete="off"
|
||||||
<p
|
placeholder="Address"
|
||||||
name="token"
|
class:border-red-500={!isAddress1Valid}
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
|
class:focus:border-red-500={!isAddress1Valid}
|
||||||
>
|
class:focus:ring-red-500={!isAddress1Valid}
|
||||||
{#if editable.registrationKey}
|
bind:value={editable.address.address1}
|
||||||
{registrationLink}
|
type="text"
|
||||||
{:else}
|
name="address1"
|
||||||
{$_("you-have-to-save-your-changes-to-generate-a-link")}
|
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-neutral-800 rounded-md p-2"
|
||||||
{/if}
|
/>
|
||||||
</p>
|
{#if !isAddress1Valid}
|
||||||
<div
|
<span
|
||||||
class="bg-gray-200 border-gray-300 border-t border-b border-r text-black rounded-r-md sm:text-sm p-2 mt-1 cursor-pointer"
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
>
|
>
|
||||||
<svg
|
{$_("address-is-required")}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
</span>
|
||||||
viewBox="0 0 24 24"
|
{/if}
|
||||||
width="24"
|
</div>
|
||||||
height="24"
|
<div class="col-span-6">
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
<label
|
||||||
<path
|
for="address2"
|
||||||
fill="currentColor"
|
class="block text-sm font-medium text-gray-700"
|
||||||
d="M7 4V2h10v2h3l1 1v16a1 1 0 01-1 1H4a1 1 0 01-1-1V5l1-1h3zm0 2H5v14h14V6h-2v2H7V6zm2-2v2h6V4H9z"
|
>{$_("apartment-suite-etc")}</label
|
||||||
/></svg
|
>
|
||||||
>
|
<input
|
||||||
</div>
|
autocomplete="off"
|
||||||
</button>
|
placeholder={$_("apartment-suite-etc")}
|
||||||
{#if editable.registrationKey}
|
bind:value={editable.address.address2}
|
||||||
<p class="text-gray-500 text-xs">
|
type="text"
|
||||||
{$_("click-to-copy-the-link-into-your-clipboard")}
|
name="address2"
|
||||||
</p>
|
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-neutral-800 rounded-md p-2"
|
||||||
{/if}
|
/>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
<div class="col-span-6">
|
||||||
<!-- -->
|
<label for="zipcode" class="block text-sm font-medium text-gray-700"
|
||||||
<div>
|
>{$_("zip-postal-code")}</label
|
||||||
<div class="flex items-start mt-2">
|
>
|
||||||
<div class="flex items-center h-5">
|
<input
|
||||||
<input
|
autocomplete="off"
|
||||||
bind:checked={editable.address_checked}
|
placeholder={$_("zip-postal-code")}
|
||||||
id="toggle_address_checkbox"
|
class:border-red-500={!iszipcodevalid}
|
||||||
name="toggle_address_checkbox"
|
class:focus:border-red-500={!iszipcodevalid}
|
||||||
type="checkbox"
|
class:focus:ring-red-500={!iszipcodevalid}
|
||||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
bind:value={editable.address.postalcode}
|
||||||
/>
|
type="text"
|
||||||
</div>
|
name="zipcode"
|
||||||
<div class="ml-3 text-sm">
|
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-neutral-800 rounded-md p-2"
|
||||||
<label
|
/>
|
||||||
for="toggle_address_checkbox"
|
{#if !iszipcodevalid}
|
||||||
class="font-medium text-gray-700">{$_("address")}</label
|
<span
|
||||||
>
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
</div>
|
>
|
||||||
</div>
|
{$_("valid-zipcode-postal-code-is-required")}
|
||||||
</div>
|
</span>
|
||||||
{#if editable.address_checked === true}
|
{/if}
|
||||||
<div class="col-span-6">
|
</div>
|
||||||
<label
|
<div class="col-span-6">
|
||||||
for="address1"
|
<label for="city" class="block text-sm font-medium text-gray-700"
|
||||||
class="block text-sm font-medium text-gray-700"
|
>{$_("city")}</label
|
||||||
>{$_("address")}</label
|
>
|
||||||
>
|
<input
|
||||||
<input
|
autocomplete="off"
|
||||||
autocomplete="off"
|
placeholder={$_("city")}
|
||||||
placeholder="Address"
|
class:border-red-500={!iscityvalid}
|
||||||
class:border-red-500={!isAddress1Valid}
|
class:focus:border-red-500={!iscityvalid}
|
||||||
class:focus:border-red-500={!isAddress1Valid}
|
class:focus:ring-red-500={!iscityvalid}
|
||||||
class:focus:ring-red-500={!isAddress1Valid}
|
bind:value={editable.address.city}
|
||||||
bind:value={editable.address.address1}
|
type="text"
|
||||||
type="text"
|
name="city"
|
||||||
name="address1"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
/>
|
||||||
/>
|
{#if !iscityvalid}
|
||||||
{#if !isAddress1Valid}
|
<span
|
||||||
<span
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
>
|
||||||
>
|
{$_("valid-city-is-required")}
|
||||||
{$_("address-is-required")}
|
</span>
|
||||||
</span>
|
{/if}
|
||||||
{/if}
|
</div>
|
||||||
</div>
|
{/if}
|
||||||
<div class="col-span-6">
|
<div class="text-sm w-full mt-2">
|
||||||
<label
|
<span class="font-semibold text-gray-700">{$_("distance")}</span>
|
||||||
for="address2"
|
<br />
|
||||||
class="block text-sm font-medium text-gray-700"
|
<span class="text-gray-700"
|
||||||
>{$_("apartment-suite-etc")}</label
|
>{(original_object.total_distance / 1000).toFixed(2)} km</span
|
||||||
>
|
>
|
||||||
<input
|
</div>
|
||||||
autocomplete="off"
|
</div>
|
||||||
placeholder={$_("apartment-suite-etc")}
|
</div>
|
||||||
bind:value={editable.address.address2}
|
</section>
|
||||||
type="text"
|
|
||||||
name="address2"
|
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="col-span-6">
|
|
||||||
<label for="zipcode" class="block text-sm font-medium text-gray-700"
|
|
||||||
>{$_("zip-postal-code")}</label
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
autocomplete="off"
|
|
||||||
placeholder={$_("zip-postal-code")}
|
|
||||||
class:border-red-500={!iszipcodevalid}
|
|
||||||
class:focus:border-red-500={!iszipcodevalid}
|
|
||||||
class:focus:ring-red-500={!iszipcodevalid}
|
|
||||||
bind:value={editable.address.postalcode}
|
|
||||||
type="text"
|
|
||||||
name="zipcode"
|
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
|
||||||
/>
|
|
||||||
{#if !iszipcodevalid}
|
|
||||||
<span
|
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
|
||||||
>
|
|
||||||
{$_("valid-zipcode-postal-code-is-required")}
|
|
||||||
</span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
<div class="col-span-6">
|
|
||||||
<label for="city" class="block text-sm font-medium text-gray-700"
|
|
||||||
>{$_("city")}</label
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
autocomplete="off"
|
|
||||||
placeholder={$_("city")}
|
|
||||||
class:border-red-500={!iscityvalid}
|
|
||||||
class:focus:border-red-500={!iscityvalid}
|
|
||||||
class:focus:ring-red-500={!iscityvalid}
|
|
||||||
bind:value={editable.address.city}
|
|
||||||
type="text"
|
|
||||||
name="city"
|
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
|
||||||
/>
|
|
||||||
{#if !iscityvalid}
|
|
||||||
<span
|
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
|
||||||
>
|
|
||||||
{$_("valid-city-is-required")}
|
|
||||||
</span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{:else}
|
{:else}
|
||||||
{#await promise}
|
{#await promise}
|
||||||
{$_("organization-detail-is-being-loaded")}
|
{$_("organization-detail-is-being-loaded")}
|
||||||
{:catch error}
|
{:catch error}
|
||||||
<PromiseError />
|
<PromiseError />
|
||||||
{/await}
|
{/await}
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1,250 +0,0 @@
|
|||||||
<script>
|
|
||||||
import { _ } from "svelte-i18n";
|
|
||||||
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
|
||||||
let modal_open = false;
|
|
||||||
let delete_org = {};
|
|
||||||
import { RunnerOrganizationService } from "@odit/lfk-client-js";
|
|
||||||
import store from "../../store";
|
|
||||||
import OrgsEmptyState from "./OrgsEmptyState.svelte";
|
|
||||||
import ConfirmOrgDeletion from "./ConfirmOrgDeletion.svelte";
|
|
||||||
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
|
||||||
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
|
||||||
import toast from "svelte-french-toast";
|
|
||||||
$: searchvalue = "";
|
|
||||||
$: active_deletes = [];
|
|
||||||
$: sponsoring_contracts_show = current_organizations.some(
|
|
||||||
(r) => r.is_selected === true
|
|
||||||
);
|
|
||||||
$: cards_show = current_organizations.some((r) => r.is_selected === true);
|
|
||||||
$: generate_orgs = current_organizations.filter(
|
|
||||||
(r) => r.is_selected === true
|
|
||||||
);
|
|
||||||
$: certificates_show = current_organizations.some(
|
|
||||||
(r) => r.is_selected === true
|
|
||||||
);
|
|
||||||
export let current_organizations = [];
|
|
||||||
|
|
||||||
const promise =
|
|
||||||
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
|
||||||
(val) => {
|
|
||||||
current_organizations = val;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<ConfirmOrgDeletion
|
|
||||||
on:cancelDelete={(event) => {
|
|
||||||
modal_open = false;
|
|
||||||
active_deletes[event.detail.id] = false;
|
|
||||||
}}
|
|
||||||
bind:modal_open
|
|
||||||
bind:delete_org
|
|
||||||
/>
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION: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">{$_("organizations-are-being-loaded")}</p>
|
|
||||||
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
|
||||||
</div>
|
|
||||||
{:then}
|
|
||||||
{#if current_organizations.length === 0}
|
|
||||||
<OrgsEmptyState />
|
|
||||||
{:else}
|
|
||||||
<input
|
|
||||||
type="search"
|
|
||||||
bind:value={searchvalue}
|
|
||||||
placeholder={$_("datatable.search")}
|
|
||||||
aria-label={$_("datatable.search")}
|
|
||||||
class="mb-4"
|
|
||||||
/>
|
|
||||||
<div class="h-12">
|
|
||||||
<GenerateSponsoringContracts
|
|
||||||
bind:sponsoring_contracts_show
|
|
||||||
bind:generate_orgs
|
|
||||||
/>
|
|
||||||
<GenerateRunnerCards bind:cards_show bind:generate_orgs />
|
|
||||||
<GenerateRunnerCertificates bind:certificates_show bind:generate_orgs />
|
|
||||||
</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 class="odd:bg-white even:bg-gray-100">
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
const newstate = !current_organizations.some(
|
|
||||||
(r) => r.is_selected === true
|
|
||||||
);
|
|
||||||
current_organizations = current_organizations.map((r) => {
|
|
||||||
r.is_selected = newstate;
|
|
||||||
return r;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
class="underline cursor-pointer select-none"
|
|
||||||
>{#if current_organizations.some((r) => r.is_selected === true)}
|
|
||||||
{$_("deselect-all")}
|
|
||||||
{:else}{$_("select-all")}{/if}
|
|
||||||
</button>
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
|
||||||
>
|
|
||||||
{$_("name")}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
|
||||||
>
|
|
||||||
{$_("address")}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
|
||||||
>
|
|
||||||
{$_("contact")}
|
|
||||||
</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_organizations as o}
|
|
||||||
{#if Object.values(o)
|
|
||||||
.toString()
|
|
||||||
.toLowerCase()
|
|
||||||
.includes(searchvalue)}
|
|
||||||
<tr
|
|
||||||
class="odd:bg-white even:bg-gray-100"
|
|
||||||
data-rowid="org_{o.id}"
|
|
||||||
>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<input
|
|
||||||
bind:checked={o.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">
|
|
||||||
{o.name}
|
|
||||||
</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">
|
|
||||||
{#if o.address.address1 !== null}
|
|
||||||
{o.address.address1}<br />
|
|
||||||
<!-- {o.address.address2 || ''}<br /> -->
|
|
||||||
{o.address.postalcode}
|
|
||||||
{o.address.city}
|
|
||||||
{o.address.country}
|
|
||||||
{/if}
|
|
||||||
</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">
|
|
||||||
{#if o.contact}
|
|
||||||
<a
|
|
||||||
href="../contacts/{o.contact.id}"
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
|
||||||
>{o.contact.firstname}
|
|
||||||
{o.contact.middlename || ""}
|
|
||||||
{o.contact.lastname}</a
|
|
||||||
>
|
|
||||||
{:else}{$_("no-contact-specified")}{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
{#if active_deletes[o.id] === true}
|
|
||||||
<td
|
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[o.id] = false;
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer"
|
|
||||||
>{$_("cancel-delete")}</button
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
toast.loading($_("deleting-organization"));
|
|
||||||
RunnerOrganizationService.runnerOrganizationControllerRemove(
|
|
||||||
o.id,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
.then((resp) => {
|
|
||||||
current_organizations =
|
|
||||||
current_organizations.filter(
|
|
||||||
(obj) => obj.id !== o.id
|
|
||||||
);
|
|
||||||
toast($_("organization-deleted"));
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
modal_open = true;
|
|
||||||
delete_org = o;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
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="./{o.id}"
|
|
||||||
class="text-indigo-600 hover:text-indigo-900"
|
|
||||||
>{$_("details")}</a
|
|
||||||
>
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION:DELETE")}
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[o.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}
|
|
||||||
+245
-46
@@ -1,54 +1,253 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
||||||
import store from "../../store";
|
let delete_org = {};
|
||||||
import AddOrgModal from "./AddOrgModal.svelte";
|
import { RunnerOrganizationService } from "@odit/lfk-client-js";
|
||||||
export let modal_open = false;
|
import store from "../../store";
|
||||||
import OrgOverview from "./OrgOverview.svelte";
|
import OrgsEmptyState from "./OrgsEmptyState.svelte";
|
||||||
import ImportRunnerModal from "../runners/ImportRunnerModal.svelte";
|
import ConfirmOrgDeletionModal from "./ConfirmOrgDeletionModal.svelte";
|
||||||
let current_organizations = [];
|
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
||||||
export let import_modal_open = false;
|
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
||||||
|
import toast from "svelte-french-toast";
|
||||||
|
$: searchvalue = "";
|
||||||
|
$: active_deletes = [];
|
||||||
|
$: sponsoring_contracts_show = current_organizations.some(
|
||||||
|
(r) => r.is_selected === true
|
||||||
|
);
|
||||||
|
$: cards_show = current_organizations.some((r) => r.is_selected === true);
|
||||||
|
$: generate_orgs = current_organizations.filter(
|
||||||
|
(r) => r.is_selected === true
|
||||||
|
);
|
||||||
|
$: certificates_show = current_organizations.some(
|
||||||
|
(r) => r.is_selected === true
|
||||||
|
);
|
||||||
|
let current_organizations = [];
|
||||||
|
|
||||||
|
const promise =
|
||||||
|
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
||||||
|
(val) => {
|
||||||
|
current_organizations = val;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import AddOrgModal from "./AddOrgModal.svelte";
|
||||||
|
let delete_modal_open = false;
|
||||||
|
let modal_open = false;
|
||||||
|
import ImportRunnerModal from "../runners/ImportRunnerModal.svelte";
|
||||||
|
let import_modal_open = false;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_("organizations")}
|
{$_("organizations")}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION:CREATE")}
|
</h4>
|
||||||
<button
|
{#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION:CREATE")}
|
||||||
on:click={() => {
|
<button
|
||||||
modal_open = true;
|
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"
|
type="button"
|
||||||
>
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
{$_("create-organization")}
|
>
|
||||||
</button>
|
{$_("create-organization")}
|
||||||
{/if}
|
</button>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:IMPORT")}
|
{/if}
|
||||||
<button
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:IMPORT")}
|
||||||
on:click={() => {
|
<button
|
||||||
import_modal_open = true;
|
on:click={() => {
|
||||||
}}
|
import_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"
|
type="button"
|
||||||
>
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
{$_("import-runners")}
|
>
|
||||||
</button>
|
{$_("import-runners")}
|
||||||
{/if}
|
</button>
|
||||||
</span>
|
{/if}
|
||||||
<OrgOverview bind:current_organizations />
|
<ConfirmOrgDeletionModal
|
||||||
|
on:cancelDelete={(event) => {
|
||||||
|
delete_modal_open = false;
|
||||||
|
active_deletes[event.detail.id] = false;
|
||||||
|
}}
|
||||||
|
bind:modal_open={delete_modal_open}
|
||||||
|
bind:delete_org
|
||||||
|
/>
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION: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">{$_("organizations-are-being-loaded")}</p>
|
||||||
|
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
||||||
|
</div>
|
||||||
|
{:then}
|
||||||
|
{#if current_organizations.length === 0}
|
||||||
|
<OrgsEmptyState />
|
||||||
|
{:else}
|
||||||
|
<input
|
||||||
|
type="search"
|
||||||
|
bind:value={searchvalue}
|
||||||
|
placeholder={$_("datatable.search")}
|
||||||
|
aria-label={$_("datatable.search")}
|
||||||
|
class="w-full sm:w-auto sm:mt-0 p-2 rounded-md border mb-1 lg:mb-0"
|
||||||
|
/>
|
||||||
|
<GenerateSponsoringContracts
|
||||||
|
bind:sponsoring_contracts_show
|
||||||
|
bind:generate_orgs
|
||||||
|
/>
|
||||||
|
<GenerateRunnerCards bind:cards_show bind:generate_orgs />
|
||||||
|
<GenerateRunnerCertificates bind:certificates_show bind:generate_orgs />
|
||||||
|
<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 class="odd:bg-white even:bg-gray-100">
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
const newstate = !current_organizations.some(
|
||||||
|
(r) => r.is_selected === true
|
||||||
|
);
|
||||||
|
current_organizations = current_organizations.map((r) => {
|
||||||
|
r.is_selected = newstate;
|
||||||
|
return r;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
class="underline cursor-pointer select-none"
|
||||||
|
>{#if current_organizations.some((r) => r.is_selected === true)}
|
||||||
|
{$_("deselect-all")}
|
||||||
|
{:else}{$_("select-all")}{/if}
|
||||||
|
</button>
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||||
|
>
|
||||||
|
{$_("name")}
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||||
|
>
|
||||||
|
{$_("address")}
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||||
|
>
|
||||||
|
{$_("contact")}
|
||||||
|
</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_organizations as o}
|
||||||
|
{#if Object.values(o)
|
||||||
|
.toString()
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(searchvalue)}
|
||||||
|
<tr
|
||||||
|
class="odd:bg-white even:bg-gray-100"
|
||||||
|
data-rowid="org_{o.id}"
|
||||||
|
>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
|
<input
|
||||||
|
bind:checked={o.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="text-sm font-medium text-gray-900">
|
||||||
|
{o.name}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="text-sm font-medium text-gray-900">
|
||||||
|
{#if o.address.address1 !== null}
|
||||||
|
{o.address.address1}<br />
|
||||||
|
<!-- {o.address.address2 || ''}<br /> -->
|
||||||
|
{o.address.postalcode}
|
||||||
|
{o.address.city}
|
||||||
|
{o.address.country}
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="text-sm font-medium text-gray-900">
|
||||||
|
{#if o.contact}
|
||||||
|
<a
|
||||||
|
href="../contacts/{o.contact.id}"
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800 border border-current"
|
||||||
|
>{o.contact.firstname}
|
||||||
|
{o.contact.middlename || ""}
|
||||||
|
{o.contact.lastname}</a
|
||||||
|
>
|
||||||
|
{:else}{$_("no-contact-specified")}{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td
|
||||||
|
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
|
||||||
|
>
|
||||||
|
<a
|
||||||
|
href="./{o.id}"
|
||||||
|
class="text-indigo-600 hover:text-indigo-900"
|
||||||
|
>{$_("details")}</a
|
||||||
|
>
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION:DELETE")}
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
active_deletes[o.id] = true;
|
||||||
|
delete_modal_open = true;
|
||||||
|
delete_org = o;
|
||||||
|
}}
|
||||||
|
tabindex="0"
|
||||||
|
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
|
||||||
|
>{$_("delete")}</button
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
|
</td>
|
||||||
|
</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}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION:CREATE")}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION:CREATE")}
|
||||||
<AddOrgModal bind:current_organizations bind:modal_open />
|
<AddOrgModal bind:current_organizations bind:modal_open />
|
||||||
<ImportRunnerModal
|
<ImportRunnerModal
|
||||||
on:cancelDelete={(event) => {
|
on:cancelDelete={(event) => {
|
||||||
import_modal_open = false;
|
import_modal_open = false;
|
||||||
}}
|
}}
|
||||||
passed_team={{}}
|
passed_team={{}}
|
||||||
passed_org={{}}
|
passed_org={{}}
|
||||||
passed_orgs={current_organizations}
|
passed_orgs={current_organizations}
|
||||||
opened_from="OrgOverview"
|
opened_from="OrgOverview"
|
||||||
current_runners={[]}
|
bind:import_modal_open
|
||||||
bind:import_modal_open
|
/>
|
||||||
/>
|
|
||||||
{/if}
|
{/if}
|
||||||
@@ -0,0 +1,150 @@
|
|||||||
|
class DocumentServer {
|
||||||
|
baseUrl: string;
|
||||||
|
apiKey: string;
|
||||||
|
|
||||||
|
constructor(baseUrl: string, apiKey: string) {
|
||||||
|
this.baseUrl = baseUrl;
|
||||||
|
this.apiKey = apiKey;
|
||||||
|
}
|
||||||
|
|
||||||
|
async generateCards(cards: any[], locale: string) {
|
||||||
|
const generateCards = new Array<any>();
|
||||||
|
|
||||||
|
for (let i = 0; i < cards.length; i++) {
|
||||||
|
const card = {
|
||||||
|
id: cards[i].id,
|
||||||
|
enabled: cards[i].enabled,
|
||||||
|
code: cards[i].code,
|
||||||
|
runner: {
|
||||||
|
id: cards[i]?.runner?.id,
|
||||||
|
first_name: cards[i]?.runner?.firstname,
|
||||||
|
middle_name: cards[i]?.runner?.middlename,
|
||||||
|
last_name: cards[i]?.runner?.lastname,
|
||||||
|
group: {
|
||||||
|
id: cards[i]?.runner?.group.id,
|
||||||
|
name: cards[i]?.runner?.group.name,
|
||||||
|
parent_group: {
|
||||||
|
id: cards[i]?.runner?.group?.parentGroup?.id,
|
||||||
|
name: cards[i]?.runner?.group?.parentGroup?.name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
generateCards.push(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(
|
||||||
|
`${this.baseUrl}/v1/pdfs/cards?key=${this.apiKey}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
locale,
|
||||||
|
cards: generateCards,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const blob = await response.blob();
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
async generateContracts(runners: any[], locale: string) {
|
||||||
|
const generateRunners = new Array<any>();
|
||||||
|
|
||||||
|
for (let i = 0; i < runners.length; i++) {
|
||||||
|
console.log(runners[i]);
|
||||||
|
const card = {
|
||||||
|
id: runners[i].id,
|
||||||
|
first_name: runners[i].firstname,
|
||||||
|
middle_name: runners[i].middlename,
|
||||||
|
last_name: runners[i].lastname,
|
||||||
|
group: {
|
||||||
|
id: runners[i].group.id,
|
||||||
|
name: runners[i].group.name,
|
||||||
|
parent_group: {
|
||||||
|
id: runners[i]?.group?.parentGroup?.id,
|
||||||
|
name: runners[i]?.group?.parentGroup?.name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
};
|
||||||
|
generateRunners.push(card);
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(
|
||||||
|
`${this.baseUrl}/v1/pdfs/contracts?key=${this.apiKey}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
locale,
|
||||||
|
runners: generateRunners,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const blob = await response.blob();
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
|
||||||
|
async generateCertificates(runners: any[], locale: string) {
|
||||||
|
const generateRunners = new Array<any>();
|
||||||
|
|
||||||
|
for (let i = 0; i < runners.length; i++) {
|
||||||
|
const certificate = {
|
||||||
|
id: runners[i].id,
|
||||||
|
first_name: runners[i].firstname,
|
||||||
|
middle_name: runners[i].middlename,
|
||||||
|
last_name: runners[i].lastname,
|
||||||
|
group: {
|
||||||
|
id: runners[i].group.id,
|
||||||
|
name: runners[i].group.name,
|
||||||
|
parent_group: {
|
||||||
|
id: runners[i]?.group?.parentGroup?.id,
|
||||||
|
name: runners[i]?.group?.parentGroup?.name,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
distance: runners[i].distance,
|
||||||
|
distance_donations: runners[i].distanceDonations.map(
|
||||||
|
(distanceDonation: any) => {
|
||||||
|
return {
|
||||||
|
id: distanceDonation.id,
|
||||||
|
amount: distanceDonation.amount,
|
||||||
|
amount_per_distance: distanceDonation.amountPerDistance,
|
||||||
|
donor: {
|
||||||
|
id: distanceDonation.donor.id,
|
||||||
|
first_name: distanceDonation.donor.firstname,
|
||||||
|
middle_name: distanceDonation.donor.middlename,
|
||||||
|
last_name: distanceDonation.donor.lastname,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
},
|
||||||
|
),
|
||||||
|
};
|
||||||
|
generateRunners.push(certificate);
|
||||||
|
}
|
||||||
|
|
||||||
|
const response = await fetch(
|
||||||
|
`${this.baseUrl}/v1/pdfs/certificates?key=${this.apiKey}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify({
|
||||||
|
locale,
|
||||||
|
runners: generateRunners,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
);
|
||||||
|
|
||||||
|
const blob = await response.blob();
|
||||||
|
return blob;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
export default DocumentServer;
|
||||||
@@ -1,364 +1,197 @@
|
|||||||
<script>
|
<script>
|
||||||
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import {
|
import {
|
||||||
RunnerCardService,
|
RunnerCardService,
|
||||||
RunnerOrganizationService,
|
RunnerOrganizationService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
|
import toast from "svelte-french-toast";
|
||||||
|
import DocumentServer from "./DocumentServer.ts";
|
||||||
|
|
||||||
import { init } from "@paralleldrive/cuid2";
|
import { init } from "@paralleldrive/cuid2";
|
||||||
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
|
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
|
||||||
|
const documentServer = new DocumentServer(
|
||||||
|
config.baseurl_documentserver,
|
||||||
|
config.documentserver_key
|
||||||
|
);
|
||||||
|
|
||||||
export let cards_show = false;
|
export let cards_show = false;
|
||||||
export let generate_cards = [];
|
export let generate_cards = [];
|
||||||
export let generate_runners = [];
|
export let generate_runners = [];
|
||||||
export let generate_orgs = [];
|
export let generate_orgs = [];
|
||||||
export let generate_teams = [];
|
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) {
|
function download(blob, fileName) {
|
||||||
cards_dropdown_open = false;
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = fileName;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
toast.dismiss();
|
||||||
|
toast($_("pdf-successfully-generated"));
|
||||||
|
}
|
||||||
|
|
||||||
if (generate_orgs.length > 0) {
|
function generateRunnerCards(locale) {
|
||||||
generateOrgCards(locale);
|
if (generate_orgs.length > 0) {
|
||||||
} else if (generate_teams.length > 0) {
|
generateOrgCards(locale);
|
||||||
generateTeamCards(locale);
|
} else if (generate_teams.length > 0) {
|
||||||
} else if (generate_runners.length > 0) {
|
generateTeamCards(locale);
|
||||||
generateRunnersCards(locale);
|
} else if (generate_runners.length > 0) {
|
||||||
} else {
|
generateRunnersCards(locale);
|
||||||
generateCards(locale);
|
} else {
|
||||||
}
|
generateCards(locale);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
function generateCards(locale) {
|
function generateCards(locale) {
|
||||||
toast.loading($_("generating-pdf"));
|
toast.loading($_("generating-pdf"));
|
||||||
fetch(
|
documentServer
|
||||||
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
.generateCards(generate_cards, locale)
|
||||||
{
|
.then((blob) => {
|
||||||
method: "POST",
|
download(blob, `${$_("runnercards")}-${locale}-${createId()}.pdf`);
|
||||||
headers: {
|
})
|
||||||
"Content-Type": "application/json",
|
.catch((err) => {
|
||||||
},
|
console.error(err);
|
||||||
body: JSON.stringify(generate_cards),
|
});
|
||||||
}
|
}
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.dismiss();
|
|
||||||
toast.error($_("pdf-generation-failed"));
|
|
||||||
} else {
|
|
||||||
return response.blob();
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.then((blob) => {
|
|
||||||
const url = window.URL.createObjectURL(blob);
|
|
||||||
let a = document.createElement("a");
|
|
||||||
a.href = url;
|
|
||||||
a.download = `${$_("runnercards")}-${locale}-${createId()}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
toast.dismiss();
|
|
||||||
toast($_("pdf-successfully-generated"));
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateRunnersCards(locale) {
|
async function generateRunnersCards(locale) {
|
||||||
toast.loading($_("generating-pdf"));
|
toast.loading($_("generating-pdf"));
|
||||||
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
||||||
let cards = [];
|
let cards = [];
|
||||||
for (let runner of generate_runners) {
|
for (let runner of generate_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(
|
documentServer
|
||||||
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
.generateCards(cards, locale)
|
||||||
{
|
.then((blob) => {
|
||||||
method: "POST",
|
let fileName = `${$_("runnercards")}-${locale}-${createId()}.pdf`;
|
||||||
headers: {
|
if (generate_runners.length == 1) {
|
||||||
"Content-Type": "application/json",
|
fileName = `${$_("runnercards")}_${generate_runners[0].firstname}_${
|
||||||
},
|
generate_runners[0].lastname
|
||||||
body: JSON.stringify(cards),
|
}-${locale}-${createId()}.pdf`;
|
||||||
}
|
}
|
||||||
)
|
download(blob, fileName);
|
||||||
.then((response) => {
|
})
|
||||||
if (response.status != "200") {
|
.catch((err) => {});
|
||||||
toast.dismiss();
|
}
|
||||||
toast.error($_("pdf-generation-failed"));
|
|
||||||
} 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.dismiss();
|
|
||||||
toast($_("pdf-successfully-generated"));
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateTeamCards(locale) {
|
async function generateTeamCards(locale) {
|
||||||
toast.loading($_("generating-pdfs"));
|
toast.loading($_("generating-pdfs"));
|
||||||
let count = 0;
|
let count = 0;
|
||||||
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
||||||
for (const t of generate_teams) {
|
for (const t of generate_teams) {
|
||||||
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
t.id
|
t.id
|
||||||
);
|
);
|
||||||
let cards = [];
|
let cards = [];
|
||||||
for (let runner of runners) {
|
for (let runner of runners) {
|
||||||
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
||||||
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(
|
documentServer
|
||||||
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
.generateCards(cards, locale)
|
||||||
{
|
.then((blob) => {
|
||||||
method: "POST",
|
download(
|
||||||
headers: {
|
blob,
|
||||||
"Content-Type": "application/json",
|
`${$_("runnercards")}_${t.name}-${locale}-${createId()}.pdf`
|
||||||
},
|
);
|
||||||
body: JSON.stringify(cards),
|
})
|
||||||
}
|
.catch((err) => {});
|
||||||
)
|
}
|
||||||
.then((response) => {
|
}
|
||||||
if (response.status != "200") {
|
|
||||||
toast.dismiss();
|
|
||||||
toast.error($_("pdf-generation-failed"));
|
|
||||||
} 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.dismiss();
|
|
||||||
toast.success($_("pdfs-successfully-generated"));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateOrgCards(locale) {
|
async function generateOrgCards(locale) {
|
||||||
toast.loading($_("generating-pdfs"));
|
toast.loading($_("generating-pdfs"));
|
||||||
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
||||||
let count = 0;
|
let count = 0;
|
||||||
let count_orgs = 0;
|
let count_orgs = 0;
|
||||||
for (const o of generate_orgs) {
|
for (const o of generate_orgs) {
|
||||||
count_orgs++;
|
count_orgs++;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
let runners =
|
let runners =
|
||||||
await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
||||||
o.id,
|
o.id,
|
||||||
true
|
true
|
||||||
);
|
);
|
||||||
let cards = [];
|
let cards = [];
|
||||||
for (let runner of runners) {
|
for (let runner of runners) {
|
||||||
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
||||||
if (!card) {
|
if (!card) {
|
||||||
card = await RunnerCardService.runnerCardControllerPost({
|
card = await RunnerCardService.runnerCardControllerPost({
|
||||||
runner: runner.id,
|
runner: runner.id,
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
cards.push(card);
|
cards.push(card);
|
||||||
}
|
}
|
||||||
await fetch(
|
await documentServer
|
||||||
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
.generateCards(cards, locale)
|
||||||
{
|
.then((blob) => {
|
||||||
method: "POST",
|
download(
|
||||||
headers: {
|
blob,
|
||||||
"Content-Type": "application/json",
|
`${$_("runnercards")}_${o.name}_direct-${locale}-${createId()}.pdf`
|
||||||
},
|
);
|
||||||
body: JSON.stringify(cards),
|
})
|
||||||
}
|
.catch((err) => {});
|
||||||
)
|
for (const t of o.teams) {
|
||||||
.then((response) => {
|
count++;
|
||||||
if (response.status != "200") {
|
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
toast.dismiss();
|
t.id
|
||||||
toast.error($_("pdf-generation-failed"));
|
);
|
||||||
} else {
|
let cards = [];
|
||||||
return response.blob();
|
for (let runner of runners) {
|
||||||
}
|
let card = current_cards.find((c) => c.runner?.id == runner.id);
|
||||||
})
|
if (!card) {
|
||||||
.then((blob) => {
|
card = await RunnerCardService.runnerCardControllerPost({
|
||||||
const url = window.URL.createObjectURL(blob);
|
runner: runner.id,
|
||||||
let a = document.createElement("a");
|
});
|
||||||
a.href = url;
|
}
|
||||||
a.download = `${$_("runnercards")}_${
|
cards.push(card);
|
||||||
o.name
|
}
|
||||||
}_direct-${locale}-${createId()}.pdf`;
|
await documentServer
|
||||||
document.body.appendChild(a);
|
.generateCards(cards, locale)
|
||||||
a.click();
|
.then((blob) => {
|
||||||
a.remove();
|
download(
|
||||||
if (count === o.teams.length && count_orgs === generate_orgs.length) {
|
blob,
|
||||||
toast.dismiss();
|
`${$_("runnercards")}_${o.name}_${
|
||||||
toast.success($_("pdfs-successfully-generated"));
|
t.name
|
||||||
}
|
}-${locale}-${createId()}.pdf`
|
||||||
})
|
);
|
||||||
.catch((err) => {});
|
})
|
||||||
for (const t of o.teams) {
|
.catch((err) => {});
|
||||||
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.dismiss();
|
|
||||||
toast.error($_("pdf-generation-failed"));
|
|
||||||
} 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}-${createId()}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (
|
|
||||||
count === o.teams.length &&
|
|
||||||
count_orgs === generate_orgs.length
|
|
||||||
) {
|
|
||||||
toast.dismiss();
|
|
||||||
toast($_("pdfs-successfully-generated"));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if cards_show}
|
{#if cards_show}
|
||||||
<div id="cards:dropdown" class="relative inline-block">
|
<button
|
||||||
<div>
|
on:click={() => {
|
||||||
<button
|
generateRunnerCards("de");
|
||||||
on:click={() => {
|
}}
|
||||||
cards_dropdown_open = !cards_dropdown_open;
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
}}
|
>
|
||||||
type="button"
|
{$_("generate-runnercards")}: DE
|
||||||
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"
|
</button>
|
||||||
id="options-menu"
|
<button
|
||||||
aria-haspopup="true"
|
on:click={() => {
|
||||||
aria-expanded="true"
|
generateRunnerCards("en");
|
||||||
>
|
}}
|
||||||
{$_("generate-runnercards")}
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
<svg
|
>
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
{$_("generate-runnercards")}: EN
|
||||||
width="24"
|
</button>
|
||||||
height="24"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
class="-mr-1 ml-2 h-5 w-5"
|
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
|
||||||
<path
|
|
||||||
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
|
|
||||||
>
|
|
||||||
</button>
|
|
||||||
</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,312 +1,175 @@
|
|||||||
<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 { init } from "@paralleldrive/cuid2";
|
import { init } from "@paralleldrive/cuid2";
|
||||||
import toast from "svelte-french-toast";
|
import toast from "svelte-french-toast";
|
||||||
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
|
import DocumentServer from "./DocumentServer";
|
||||||
|
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
|
||||||
|
const documentServer = new DocumentServer(
|
||||||
|
config.baseurl_documentserver,
|
||||||
|
config.documentserver_key
|
||||||
|
);
|
||||||
|
|
||||||
export let certificates_show = false;
|
export let certificates_show = false;
|
||||||
export let generate_runners = [];
|
export let generate_runners = [];
|
||||||
export let generate_orgs = [];
|
export let generate_orgs = [];
|
||||||
export let generate_teams = [];
|
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) {
|
function generateCertificates(locale) {
|
||||||
certificates_dropdown_open = false;
|
if (generate_orgs.length > 0) {
|
||||||
|
generateOrgCertificates(locale);
|
||||||
|
} else if (generate_teams.length > 0) {
|
||||||
|
generateTeamCertificates(locale);
|
||||||
|
} else {
|
||||||
|
generateRunnerCertificates(locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
function download(blob, fileName) {
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = fileName;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
toast.dismiss();
|
||||||
|
toast($_("pdf-successfully-generated"));
|
||||||
|
}
|
||||||
|
|
||||||
if (generate_orgs.length > 0) {
|
async function generateRunnerCertificates(locale) {
|
||||||
generateOrgCertificates(locale);
|
toast.loading($_("generating-pdf"));
|
||||||
} else if (generate_teams.length > 0) {
|
const current_donations =
|
||||||
generateTeamCertificates(locale);
|
(await DonationService.donationControllerGetAll()) || [];
|
||||||
} else {
|
let certificateRunners = [];
|
||||||
generateRunnerCertificates(locale);
|
for (let runner of generate_runners) {
|
||||||
}
|
runner.distanceDonations =
|
||||||
}
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
|
certificateRunners.push(runner);
|
||||||
|
}
|
||||||
|
documentServer
|
||||||
|
.generateCertificates(certificateRunners, locale)
|
||||||
|
.then((blob) => {
|
||||||
|
let fileName = `${$_("certificates")}-${locale}.pdf`;
|
||||||
|
if (generate_runners.length == 1) {
|
||||||
|
fileName = `${$_("certificates")}_${
|
||||||
|
generate_runners[0].firstname
|
||||||
|
}_${generate_runners[0].lastname}-${locale}-${createId()}.pdf`;
|
||||||
|
}
|
||||||
|
download(blob, fileName);
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
|
||||||
async function generateRunnerCertificates(locale) {
|
async function generateTeamCertificates(locale) {
|
||||||
toast.loading($_("generating-pdf"));
|
toast.loading($_("generating-pdfs"));
|
||||||
const current_donations =
|
let count = 0;
|
||||||
(await DonationService.donationControllerGetAll()) || [];
|
const current_donations =
|
||||||
let certificateRunners = [];
|
(await DonationService.donationControllerGetAll()) || [];
|
||||||
for (let runner of generate_runners) {
|
for (const t of generate_teams) {
|
||||||
runner.distanceDonations =
|
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
t.id
|
||||||
certificateRunners.push(runner);
|
);
|
||||||
}
|
let certificateRunners = [];
|
||||||
fetch(
|
for (let runner of runners) {
|
||||||
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
runner.distanceDonations =
|
||||||
{
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
method: "POST",
|
certificateRunners.push(runner);
|
||||||
headers: {
|
}
|
||||||
"Content-Type": "application/json",
|
documentServer
|
||||||
},
|
.generateCertificates(certificateRunners, locale)
|
||||||
body: JSON.stringify(certificateRunners),
|
.then((blob) => {
|
||||||
}
|
count++;
|
||||||
)
|
download(
|
||||||
.then((response) => {
|
blob,
|
||||||
if (response.status != "200") {
|
`${$_("certificates")}_${t.name}-${locale}-${createId()}.pdf`
|
||||||
toast.dismiss();
|
);
|
||||||
toast.error($_("pdf-generation-failed"));
|
})
|
||||||
} else {
|
.catch((err) => {});
|
||||||
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}-${createId()}.pdf`;
|
|
||||||
} else {
|
|
||||||
a.download = `${$_("certificates")}-${locale}.pdf`;
|
|
||||||
}
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
toast.dismiss();
|
|
||||||
toast($_("pdf-successfully-generated"));
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateTeamCertificates(locale) {
|
async function generateOrgCertificates(locale) {
|
||||||
toast.loading($_("generating-pdfs"));
|
toast.loading($_("generating-pdfs"));
|
||||||
let count = 0;
|
const current_donations =
|
||||||
const current_donations =
|
(await DonationService.donationControllerGetAll()) || [];
|
||||||
(await DonationService.donationControllerGetAll()) || [];
|
let count = 0;
|
||||||
for (const t of generate_teams) {
|
let count_orgs = 0;
|
||||||
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
for (const o of generate_orgs) {
|
||||||
t.id
|
count_orgs++;
|
||||||
);
|
let count = 0;
|
||||||
let certificateRunners = [];
|
let runners =
|
||||||
for (let runner of runners) {
|
await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
||||||
runner.distanceDonations =
|
o.id,
|
||||||
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
true
|
||||||
certificateRunners.push(runner);
|
);
|
||||||
}
|
let certificateRunners = [];
|
||||||
fetch(
|
for (let runner of runners) {
|
||||||
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
runner.distanceDonations =
|
||||||
{
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
method: "POST",
|
certificateRunners.push(runner);
|
||||||
headers: {
|
}
|
||||||
"Content-Type": "application/json",
|
await documentServer
|
||||||
},
|
.generateCertificates(certificateRunners, locale)
|
||||||
body: JSON.stringify(certificateRunners),
|
.then((blob) => {
|
||||||
}
|
download(
|
||||||
)
|
blob,
|
||||||
.then((response) => {
|
`${$_("certificates")}_${o.name}-${locale}-${createId()}.pdf`
|
||||||
if (response.status != "200") {
|
);
|
||||||
toast.dismiss();
|
})
|
||||||
toast.error($_("pdf-generation-failed"));
|
.catch((err) => {});
|
||||||
} else {
|
for (const t of o.teams) {
|
||||||
return response.blob();
|
count++;
|
||||||
}
|
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
})
|
t.id
|
||||||
.then((blob) => {
|
);
|
||||||
count++;
|
let certificateRunners = [];
|
||||||
const url = window.URL.createObjectURL(blob);
|
for (let runner of runners) {
|
||||||
let a = document.createElement("a");
|
runner.distanceDonations =
|
||||||
a.href = url;
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
a.download = `${$_("certificates")}_${
|
certificateRunners.push(runner);
|
||||||
t.name
|
}
|
||||||
}-${locale}-${createId()}.pdf`;
|
await documentServer
|
||||||
document.body.appendChild(a);
|
.generateCertificates(certificateRunners, locale)
|
||||||
a.click();
|
.then((blob) => {
|
||||||
a.remove();
|
download(
|
||||||
if (count === generate_teams.length) {
|
blob,
|
||||||
toast.dismiss();
|
`${$_("certificates")}_${o.name}_${
|
||||||
toast.success($_("pdfs-successfully-generated"));
|
t.name
|
||||||
}
|
}-${locale}-${createId()}.pdf`
|
||||||
})
|
);
|
||||||
.catch((err) => {});
|
if (
|
||||||
}
|
count === o.teams.length &&
|
||||||
}
|
count_orgs === generate_orgs.length
|
||||||
|
) {
|
||||||
async function generateOrgCertificates(locale) {
|
toast.dismiss();
|
||||||
toast.loading($_("generating-pdfs"));
|
toast($_("pdfs-successfully-generated"));
|
||||||
const current_donations =
|
}
|
||||||
(await DonationService.donationControllerGetAll()) || [];
|
})
|
||||||
let count = 0;
|
.catch((err) => {});
|
||||||
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.dismiss();
|
|
||||||
toast.error($_("pdf-generation-failed"));
|
|
||||||
} 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.dismiss();
|
|
||||||
toast.success($_("pdfs-successfully-generated"));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.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.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.dismiss();
|
|
||||||
toast.error($_("pdf-generation-failed"));
|
|
||||||
} 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}-${createId()}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (
|
|
||||||
count === o.teams.length &&
|
|
||||||
count_orgs === generate_orgs.length
|
|
||||||
) {
|
|
||||||
toast.dismiss();
|
|
||||||
toast($_("pdfs-successfully-generated"));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if certificates_show}
|
{#if certificates_show}
|
||||||
<div id="certificates:dropdown" class="relative inline-block">
|
<button
|
||||||
<div>
|
on:click={() => {
|
||||||
<button
|
generateCertificates("de");
|
||||||
on:click={() => {
|
}}
|
||||||
certificates_dropdown_open = !certificates_dropdown_open;
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
}}
|
>
|
||||||
type="button"
|
{$_("generate-runner-certificates")}: DE
|
||||||
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"
|
</button>
|
||||||
id="options-menu"
|
<button
|
||||||
aria-haspopup="true"
|
on:click={() => {
|
||||||
aria-expanded="true"
|
generateCertificates("en");
|
||||||
>
|
}}
|
||||||
{$_("generate-runner-certificates")}
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
<svg
|
>
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
{$_("generate-runner-certificates")}: EN
|
||||||
width="24"
|
</button>
|
||||||
height="24"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
class="-mr-1 ml-2 h-5 w-5"
|
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
|
||||||
<path
|
|
||||||
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
|
|
||||||
>
|
|
||||||
</button>
|
|
||||||
</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,283 +1,138 @@
|
|||||||
<script>
|
<script>
|
||||||
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import {
|
import {
|
||||||
RunnerOrganizationService,
|
RunnerOrganizationService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
|
import DocumentServer from "./DocumentServer";
|
||||||
|
import { init } from "@paralleldrive/cuid2";
|
||||||
|
import toast from "svelte-french-toast";
|
||||||
|
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
|
||||||
|
const documentServer = new DocumentServer(
|
||||||
|
config.baseurl_documentserver,
|
||||||
|
config.documentserver_key
|
||||||
|
);
|
||||||
|
|
||||||
import { init } from "@paralleldrive/cuid2";
|
export let sponsoring_contracts_show = false;
|
||||||
import toast from "svelte-french-toast";
|
export let generate_runners = [];
|
||||||
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
|
export let generate_orgs = [];
|
||||||
|
export let generate_teams = [];
|
||||||
|
|
||||||
export let sponsoring_contracts_show = false;
|
function generateSponsoringContract(locale) {
|
||||||
export let generate_runners = [];
|
if (generate_orgs.length > 0) {
|
||||||
export let generate_orgs = [];
|
generateOrgContracts(locale);
|
||||||
export let generate_teams = [];
|
} else if (generate_teams.length > 0) {
|
||||||
$: sponsoring_contracts_download_open = false;
|
generateTeamContracts(locale);
|
||||||
document.addEventListener("click", function (e) {
|
} else {
|
||||||
if (
|
generateRunnerContracts(locale);
|
||||||
e.target.parentNode?.parentNode?.id != "sponsoring:dropdown" &&
|
}
|
||||||
e.target.parentNode?.parentNode?.id != "sponsoring:dropdown:menu"
|
}
|
||||||
) {
|
function download(blob, fileName) {
|
||||||
sponsoring_contracts_download_open = false;
|
const url = window.URL.createObjectURL(blob);
|
||||||
}
|
let a = document.createElement("a");
|
||||||
});
|
a.href = url;
|
||||||
|
a.download = fileName;
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
toast.dismiss();
|
||||||
|
toast($_("pdf-successfully-generated"));
|
||||||
|
}
|
||||||
|
|
||||||
function generateSponsoringContract(locale) {
|
async function generateTeamContracts(locale) {
|
||||||
sponsoring_contracts_download_open = false;
|
toast.loading($_("generating-pdfs"));
|
||||||
|
let count = 0;
|
||||||
|
for (const t of generate_teams) {
|
||||||
|
count++;
|
||||||
|
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
|
t.id
|
||||||
|
);
|
||||||
|
documentServer
|
||||||
|
.generateContracts(runners, locale)
|
||||||
|
.then((blob) => {
|
||||||
|
download(
|
||||||
|
blob,
|
||||||
|
`${$_("sponsorings")}_${t.name}-${locale}-${createId()}.pdf`
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
if (generate_orgs.length > 0) {
|
async function generateOrgContracts(locale) {
|
||||||
generateOrgContracts(locale);
|
toast.loading($_("generating-pdf"));
|
||||||
} else if (generate_teams.length > 0) {
|
let count_orgs = 0;
|
||||||
generateTeamContracts(locale);
|
for (const o of generate_orgs) {
|
||||||
} else {
|
count_orgs++;
|
||||||
generateRunnerContracts(locale);
|
let count = 0;
|
||||||
}
|
let runners =
|
||||||
}
|
await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
||||||
|
o.id,
|
||||||
|
true
|
||||||
|
);
|
||||||
|
await documentServer
|
||||||
|
.generateContracts(runners, locale)
|
||||||
|
.then((blob) => {
|
||||||
|
download(
|
||||||
|
blob,
|
||||||
|
`${$_("sponsorings")}_${o.name}_direct-${locale}-${createId()}.pdf`
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
for (const t of o.teams) {
|
||||||
|
count++;
|
||||||
|
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
|
t.id
|
||||||
|
);
|
||||||
|
await documentServer
|
||||||
|
.generateContracts(runners, locale)
|
||||||
|
.then((blob) => {
|
||||||
|
download(
|
||||||
|
blob,
|
||||||
|
`${$_("sponsorings")}_${o.name}_${
|
||||||
|
t.name
|
||||||
|
}-${locale}-${createId()}.pdf`
|
||||||
|
);
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function generateTeamContracts(locale) {
|
function generateRunnerContracts(locale) {
|
||||||
toast.loading($_("generating-pdfs"));
|
toast.loading($_("generating-pdf"));
|
||||||
let count = 0;
|
documentServer
|
||||||
for (const t of generate_teams) {
|
.generateContracts(generate_runners, locale)
|
||||||
count++;
|
.then((blob) => {
|
||||||
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
let fileName = `${$_("sponsorings")}-${locale}-${createId()}.pdf`;
|
||||||
t.id
|
if (generate_runners.length == 1) {
|
||||||
);
|
fileName = `${$_("sponsorings")}_${generate_runners[0].firstname}_${
|
||||||
fetch(
|
generate_runners[0].lastname
|
||||||
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
}-${locale}-${createId()}.pdf`;
|
||||||
{
|
}
|
||||||
method: "POST",
|
download(blob, fileName);
|
||||||
headers: {
|
})
|
||||||
"Content-Type": "application/json",
|
.catch((err) => {
|
||||||
},
|
console.error(err);
|
||||||
body: JSON.stringify(runners),
|
});
|
||||||
}
|
}
|
||||||
)
|
|
||||||
.then((response) => {
|
|
||||||
if (response.status != "200") {
|
|
||||||
toast.dismiss();
|
|
||||||
toast.error($_("pdf-generation-failed"));
|
|
||||||
} 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.dismiss();
|
|
||||||
toast.success($_("pdfs-successfully-generated"));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
async function generateOrgContracts(locale) {
|
|
||||||
toast.loading($_("generating-pdf"));
|
|
||||||
let count_orgs = 0;
|
|
||||||
for (const o of generate_orgs) {
|
|
||||||
count_orgs++;
|
|
||||||
let count = 0;
|
|
||||||
let runners =
|
|
||||||
await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
|
||||||
o.id,
|
|
||||||
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.dismiss();
|
|
||||||
toast.error($_("pdf-generation-failed"));
|
|
||||||
} 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.dismiss();
|
|
||||||
toast.success($_("pdfs-successfully-generated"));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.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.dismiss();
|
|
||||||
toast.error($_("pdf-generation-failed"));
|
|
||||||
} 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}-${createId()}.pdf`;
|
|
||||||
document.body.appendChild(a);
|
|
||||||
a.click();
|
|
||||||
a.remove();
|
|
||||||
if (
|
|
||||||
count === o.teams.length &&
|
|
||||||
count_orgs === generate_orgs.length
|
|
||||||
) {
|
|
||||||
toast.dismiss();
|
|
||||||
toast($_("pdfs-successfully-generated"));
|
|
||||||
}
|
|
||||||
})
|
|
||||||
.catch((err) => {});
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
function generateRunnerContracts(locale) {
|
|
||||||
toast.loading($_("generating-pdf"));
|
|
||||||
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.dismiss();
|
|
||||||
toast.error($_("pdf-generation-failed"));
|
|
||||||
} 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.dismiss();
|
|
||||||
toast($_("pdf-successfully-generated"));
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
console.error(err);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if sponsoring_contracts_show}
|
{#if sponsoring_contracts_show}
|
||||||
<div id="sponsoring:dropdown" class="relative inline-block">
|
<button
|
||||||
<div>
|
on:click={() => {
|
||||||
<button
|
generateSponsoringContract("de");
|
||||||
on:click={() => {
|
}}
|
||||||
sponsoring_contracts_download_open =
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
!sponsoring_contracts_download_open;
|
>
|
||||||
}}
|
{$_("generate-sponsoring-contracts")}: DE
|
||||||
type="button"
|
</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"
|
<button
|
||||||
id="options-menu"
|
on:click={() => {
|
||||||
aria-haspopup="true"
|
generateSponsoringContract("en");
|
||||||
aria-expanded="true"
|
}}
|
||||||
>
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
{$_("generate-sponsoring-contracts")}
|
>
|
||||||
<svg
|
{$_("generate-sponsoring-contracts")}: EN
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
</button>
|
||||||
width="24"
|
|
||||||
height="24"
|
|
||||||
viewBox="0 0 24 24"
|
|
||||||
class="-mr-1 ml-2 h-5 w-5"
|
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
|
||||||
<path
|
|
||||||
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
|
|
||||||
>
|
|
||||||
</button>
|
|
||||||
</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}
|
||||||
@@ -66,7 +66,7 @@
|
|||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
<span
|
<span
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-green-100 text-green-800"
|
||||||
>
|
>
|
||||||
Active
|
Active
|
||||||
</span>
|
</span>
|
||||||
|
|||||||
@@ -12,6 +12,7 @@
|
|||||||
import Select from "svelte-select";
|
import Select from "svelte-select";
|
||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
import toast from 'svelte-french-toast'
|
||||||
|
|
||||||
export let modal_open;
|
export let modal_open;
|
||||||
$: selected_team = undefined;
|
$: selected_team = undefined;
|
||||||
@@ -188,7 +189,7 @@
|
|||||||
bind:this={firstname_input}
|
bind:this={firstname_input}
|
||||||
type="text"
|
type="text"
|
||||||
name="firstname"
|
name="firstname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isFirstnameValid}
|
{#if !isFirstnameValid}
|
||||||
<span
|
<span
|
||||||
@@ -211,7 +212,7 @@
|
|||||||
bind:this={middlename_input}
|
bind:this={middlename_input}
|
||||||
type="text"
|
type="text"
|
||||||
name="trackname"
|
name="trackname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
@@ -230,7 +231,7 @@
|
|||||||
bind:this={lastname_input}
|
bind:this={lastname_input}
|
||||||
type="text"
|
type="text"
|
||||||
name="lastname"
|
name="lastname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isLastnameValid}
|
{#if !isLastnameValid}
|
||||||
<span
|
<span
|
||||||
@@ -247,7 +248,7 @@
|
|||||||
>{$_("team")}</label
|
>{$_("team")}</label
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
itemFilter={(label, filterText, option) =>
|
itemFilter={(label, filterText, option) =>
|
||||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
option.value.id
|
option.value.id
|
||||||
@@ -280,7 +281,7 @@
|
|||||||
bind:this={phone_input}
|
bind:this={phone_input}
|
||||||
type="tel"
|
type="tel"
|
||||||
name="phone"
|
name="phone"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isPhoneValidOrEmpty}
|
{#if !isPhoneValidOrEmpty}
|
||||||
<span
|
<span
|
||||||
@@ -308,7 +309,7 @@
|
|||||||
bind:this={email_input}
|
bind:this={email_input}
|
||||||
type="email"
|
type="email"
|
||||||
name="email"
|
name="email"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isEmailValidOrEmpty}
|
{#if !isEmailValidOrEmpty}
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -268,7 +268,7 @@
|
|||||||
<select
|
<select
|
||||||
name="team"
|
name="team"
|
||||||
bind:value={selected_org}
|
bind:value={selected_org}
|
||||||
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-neutral-800 rounded-md p-2"
|
||||||
>
|
>
|
||||||
{#each passed_orgs as o}
|
{#each passed_orgs as o}
|
||||||
<option value={o.id}>{o.name}</option>
|
<option value={o.id}>{o.name}</option>
|
||||||
@@ -279,7 +279,7 @@
|
|||||||
{#if opened_from === "RunnerOverview"}
|
{#if opened_from === "RunnerOverview"}
|
||||||
<p>{$_("group")}</p>
|
<p>{$_("group")}</p>
|
||||||
<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-neutral-800 rounded-md p-2"
|
||||||
itemFilter={(label, filterText, option) =>
|
itemFilter={(label, filterText, option) =>
|
||||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
option.id.value
|
option.id.value
|
||||||
|
|||||||
@@ -1,315 +1,297 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
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";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import {
|
import {
|
||||||
RunnerService,
|
RunnerService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
RunnerOrganizationService,
|
RunnerOrganizationService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
import PromiseError from "../base/PromiseError.svelte";
|
import PromiseError from "../base/PromiseError.svelte";
|
||||||
import isEmail from "validator/es/lib/isEmail";
|
import isEmail from "validator/es/lib/isEmail";
|
||||||
import Select from "svelte-select";
|
import Select from "svelte-select";
|
||||||
import toast from "svelte-french-toast";
|
import toast from "svelte-french-toast";
|
||||||
let data_loaded = false;
|
let data_loaded = false;
|
||||||
export let params;
|
export let params;
|
||||||
const runner_promise = RunnerService.runnerControllerGetOne(params.runnerid);
|
const runner_promise = RunnerService.runnerControllerGetOne(params.runnerid);
|
||||||
$: delete_triggered = false;
|
$: delete_triggered = false;
|
||||||
$: original_data_pdf = {};
|
$: original_data_pdf = {};
|
||||||
$: original_data = {};
|
$: original_data = {};
|
||||||
$: editable = {};
|
$: editable = {};
|
||||||
$: group = {};
|
$: group = {};
|
||||||
$: changes_performed = !(
|
$: changes_performed = !(
|
||||||
JSON.stringify(original_data) == JSON.stringify(editable)
|
JSON.stringify(original_data) == JSON.stringify(editable)
|
||||||
);
|
);
|
||||||
$: isEmailValid =
|
$: isEmailValid =
|
||||||
(editable.email || "") === "" ||
|
(editable.email || "") === "" ||
|
||||||
(editable.email && isEmail(editable.email || ""));
|
(editable.email && isEmail(editable.email || ""));
|
||||||
$: isFirstnameValid = editable.firstname !== "";
|
$: isFirstnameValid = editable.firstname !== "";
|
||||||
$: isLastnameValid = editable.lastname !== "";
|
$: isLastnameValid = editable.lastname !== "";
|
||||||
$: save_enabled =
|
$: save_enabled =
|
||||||
changes_performed &&
|
changes_performed &&
|
||||||
isFirstnameValid &&
|
isFirstnameValid &&
|
||||||
isLastnameValid &&
|
isLastnameValid &&
|
||||||
isEmailValid &&
|
isEmailValid &&
|
||||||
editable.group != null;
|
editable.group != null;
|
||||||
$: sponsoring_contracts_show = true;
|
$: sponsoring_contracts_show = true;
|
||||||
$: cards_show = true;
|
$: cards_show = true;
|
||||||
$: certificates_show = true;
|
$: certificates_show = true;
|
||||||
$: generate_runners = [original_data_pdf];
|
$: generate_runners = [original_data_pdf];
|
||||||
runner_promise.then((data) => {
|
runner_promise.then((data) => {
|
||||||
data_loaded = true;
|
data_loaded = true;
|
||||||
original_data_pdf = Object.assign(original_data_pdf, data);
|
original_data_pdf = Object.assign(original_data_pdf, data);
|
||||||
data.group = data.group.id;
|
data.group = data.group.id;
|
||||||
original_data = Object.assign(original_data, data);
|
original_data = Object.assign(original_data, data);
|
||||||
editable = Object.assign(editable, original_data);
|
editable = Object.assign(editable, original_data);
|
||||||
|
|
||||||
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
||||||
(val) => {
|
(val) => {
|
||||||
const orgs = val.map((r) => {
|
const orgs = val.map((r) => {
|
||||||
return { label: r.name, value: r };
|
return { label: r.name, value: r };
|
||||||
});
|
});
|
||||||
groups = groups.concat(orgs);
|
groups = groups.concat(orgs);
|
||||||
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
||||||
const teams = val.map((r) => {
|
const teams = val.map((r) => {
|
||||||
return { label: `${r.parentGroup.name} > ${r.name}`, value: r };
|
return { label: `${r.parentGroup.name} > ${r.name}`, value: r };
|
||||||
});
|
});
|
||||||
groups = groups.concat(teams);
|
groups = groups.concat(teams);
|
||||||
group = groups.find((g) => g.value.id == editable.group);
|
group = groups.find((g) => g.value.id == editable.group);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
});
|
});
|
||||||
let groups = [];
|
let groups = [];
|
||||||
function submit() {
|
function submit() {
|
||||||
if (data_loaded === true && save_enabled) {
|
if (data_loaded === true && save_enabled) {
|
||||||
toast.loading($_("updating-runner"));
|
toast.loading($_("updating-runner"));
|
||||||
let postdata = {};
|
let postdata = {};
|
||||||
postdata = Object.assign(postdata, editable);
|
postdata = Object.assign(postdata, editable);
|
||||||
if (postdata.phone === "") {
|
if (postdata.phone === "") {
|
||||||
postdata.phone = null;
|
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);
|
||||||
original_data = original_data;
|
original_data = original_data;
|
||||||
toast.dismiss();
|
toast.dismiss();
|
||||||
toast.success($_("runner-updated"));
|
toast.success($_("runner-updated"));
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function deleteRunner() {
|
function deleteRunner() {
|
||||||
RunnerService.runnerControllerRemove(original_data.id, true)
|
RunnerService.runnerControllerRemove(original_data.id, true)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
location.replace("./");
|
location.replace("./");
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
}
|
}
|
||||||
</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">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<nav class="w-full flex">
|
<nav class="w-full flex">
|
||||||
<ol class="list-none flex flex-row items-center justify-start">
|
<ol class="list-none flex flex-row items-center justify-start">
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
<svg
|
<a class="mr-2" href="./"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
><svg
|
||||||
viewBox="0 0 24 24"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2"
|
width="24"
|
||||||
fill="currentColor"
|
height="24"
|
||||||
width="24"
|
viewBox="0 0 24 24"
|
||||||
height="24"
|
fill="none"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
stroke="currentColor"
|
||||||
<path
|
stroke-width="2"
|
||||||
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"
|
stroke-linecap="round"
|
||||||
/></svg
|
stroke-linejoin="round"
|
||||||
>
|
class="inline-block"
|
||||||
</li>
|
><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg
|
||||||
<li class="flex items-center">
|
>
|
||||||
<a class="mr-2" href="./">{$_("runners")}</a><svg
|
{$_("runners")}</a
|
||||||
stroke="currentColor"
|
>
|
||||||
fill="none"
|
</li>
|
||||||
stroke-width="2"
|
</ol>
|
||||||
viewBox="0 0 24 24"
|
</nav>
|
||||||
stroke-linecap="round"
|
</div>
|
||||||
stroke-linejoin="round"
|
</div>
|
||||||
class="h-3 w-3 mr-2 stroke-current"
|
<div class="mb-4 text-3xl font-extrabold leading-tight">
|
||||||
height="1em"
|
{original_data.firstname}
|
||||||
width="1em"
|
{original_data.middlename || ""}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
{original_data.lastname} [#{params.runnerid}]
|
||||||
><line x1="5" y1="12" x2="19" y2="12" />
|
<span data-id="runner_actions_${editable.id}">
|
||||||
<polyline points="12 5 19 12 12 19" /></svg
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:DELETE")}
|
||||||
>
|
<div>
|
||||||
</li>
|
{#if delete_triggered}
|
||||||
<li class="flex items-center">
|
<button
|
||||||
<span class="mr-2"
|
on:click={deleteRunner}
|
||||||
>{original_data.firstname}
|
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:w-auto sm:text-sm"
|
||||||
{original_data.middlename || ""}
|
>{$_("confirm-deletion")}</button
|
||||||
{original_data.lastname}</span
|
>
|
||||||
>
|
<button
|
||||||
</li>
|
on:click={() => {
|
||||||
</ol>
|
delete_triggered = !delete_triggered;
|
||||||
</nav>
|
}}
|
||||||
</div>
|
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"
|
||||||
</div>
|
>{$_("cancel")}</button
|
||||||
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
>
|
||||||
{original_data.firstname}
|
{:else}
|
||||||
{original_data.middlename || ""}
|
<button
|
||||||
{original_data.lastname}
|
on:click={() => {
|
||||||
<span data-id="runner_actions_${editable.id}">
|
delete_triggered = true;
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:DELETE")}
|
}}
|
||||||
{#if delete_triggered}
|
type="button"
|
||||||
<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:w-auto sm:text-sm"
|
||||||
on:click={deleteRunner}
|
>{$_("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"
|
>
|
||||||
>{$_("confirm-deletion")}</button
|
<button
|
||||||
>
|
disabled={!save_enabled}
|
||||||
<button
|
class:opacity-50={!save_enabled}
|
||||||
on:click={() => {
|
type="button"
|
||||||
delete_triggered = !delete_triggered;
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
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"
|
>{$_("save-changes")}</button
|
||||||
>{$_("cancel")}</button
|
>
|
||||||
>
|
{/if}
|
||||||
{/if}
|
<GenerateSponsoringContracts
|
||||||
<GenerateSponsoringContracts
|
bind:sponsoring_contracts_show
|
||||||
bind:sponsoring_contracts_show
|
bind:generate_runners
|
||||||
bind:generate_runners
|
/>
|
||||||
/>
|
<GenerateRunnerCards bind:cards_show bind:generate_runners />
|
||||||
<GenerateRunnerCards bind:cards_show bind:generate_runners />
|
<GenerateRunnerCertificates
|
||||||
<GenerateRunnerCertificates
|
bind:certificates_show
|
||||||
bind:certificates_show
|
bind:generate_runners
|
||||||
bind:generate_runners
|
/>
|
||||||
/>
|
</div>
|
||||||
{#if !delete_triggered}
|
{/if}
|
||||||
<button
|
</span>
|
||||||
on:click={() => {
|
</div>
|
||||||
delete_triggered = true;
|
<!-- -->
|
||||||
}}
|
<div class="text-sm w-full mt-2">
|
||||||
type="button"
|
<label for="firstname" class="font-semibold text-gray-700"
|
||||||
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"
|
>{$_("first-name")}</label
|
||||||
>{$_("delete-runner")}</button
|
>
|
||||||
>
|
<input
|
||||||
{/if}
|
autocomplete="off"
|
||||||
{/if}
|
placeholder={$_("first-name")}
|
||||||
{#if !delete_triggered}
|
type="text"
|
||||||
<button
|
class:border-red-500={!isFirstnameValid}
|
||||||
disabled={!save_enabled}
|
class:focus:border-red-500={!isFirstnameValid}
|
||||||
class:opacity-50={!save_enabled}
|
class:focus:ring-red-500={!isFirstnameValid}
|
||||||
type="button"
|
bind:value={editable.firstname}
|
||||||
on:click={submit}
|
name="firstname"
|
||||||
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"
|
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-neutral-800 rounded-md p-2"
|
||||||
>{$_("save-changes")}</button
|
/>
|
||||||
>
|
{#if !isFirstnameValid}
|
||||||
{/if}
|
<span
|
||||||
</span>
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
</div>
|
>
|
||||||
<!-- -->
|
{$_("first-name-is-required")}
|
||||||
<div class="text-sm w-full">
|
</span>
|
||||||
<label for="firstname" class="font-medium text-gray-700"
|
{/if}
|
||||||
>{$_("first-name")}</label
|
</div>
|
||||||
>
|
<div class="text-sm w-full mt-2">
|
||||||
<input
|
<label for="middlename" class="font-semibold text-gray-700"
|
||||||
autocomplete="off"
|
>{$_("middle-name")}</label
|
||||||
placeholder={$_("first-name")}
|
>
|
||||||
type="text"
|
<input
|
||||||
class:border-red-500={!isFirstnameValid}
|
autocomplete="off"
|
||||||
class:focus:border-red-500={!isFirstnameValid}
|
placeholder={$_("middle-name")}
|
||||||
class:focus:ring-red-500={!isFirstnameValid}
|
type="text"
|
||||||
bind:value={editable.firstname}
|
bind:value={editable.middlename}
|
||||||
name="firstname"
|
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-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isFirstnameValid}
|
</div>
|
||||||
<span
|
<div class="text-sm w-full mt-2">
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
<label for="lastname" class="font-semibold text-gray-700"
|
||||||
>
|
>{$_("last-name")}</label
|
||||||
{$_("first-name-is-required")}
|
>
|
||||||
</span>
|
<input
|
||||||
{/if}
|
autocomplete="off"
|
||||||
</div>
|
placeholder={$_("last-name")}
|
||||||
<div class="text-sm w-full">
|
type="text"
|
||||||
<label for="middlename" class="font-medium text-gray-700"
|
bind:value={editable.lastname}
|
||||||
>{$_("middle-name")}</label
|
class:border-red-500={!isLastnameValid}
|
||||||
>
|
class:focus:border-red-500={!isLastnameValid}
|
||||||
<input
|
class:focus:ring-red-500={!isLastnameValid}
|
||||||
autocomplete="off"
|
name="lastname"
|
||||||
placeholder={$_("middle-name")}
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
type="text"
|
/>
|
||||||
bind:value={editable.middlename}
|
{#if !isLastnameValid}
|
||||||
name="middlename"
|
<span
|
||||||
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="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
/>
|
>
|
||||||
</div>
|
{$_("last-name-is-required")}
|
||||||
<div class="text-sm w-full">
|
</span>
|
||||||
<label for="lastname" class="font-medium text-gray-700"
|
{/if}
|
||||||
>{$_("last-name")}</label
|
</div>
|
||||||
>
|
<div class="text-sm w-full mt-2">
|
||||||
<input
|
<label for="email" class="font-semibold text-gray-700"
|
||||||
autocomplete="off"
|
>{$_("e-mail-adress")}</label
|
||||||
placeholder={$_("last-name")}
|
>
|
||||||
type="text"
|
<input
|
||||||
bind:value={editable.lastname}
|
autocomplete="off"
|
||||||
class:border-red-500={!isLastnameValid}
|
placeholder={$_("e-mail-adress")}
|
||||||
class:focus:border-red-500={!isLastnameValid}
|
type="email"
|
||||||
class:focus:ring-red-500={!isLastnameValid}
|
bind:value={editable.email}
|
||||||
name="lastname"
|
class:border-red-500={!isEmailValid}
|
||||||
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:focus:border-red-500={!isEmailValid}
|
||||||
/>
|
class:focus:ring-red-500={!isEmailValid}
|
||||||
{#if !isLastnameValid}
|
name="email"
|
||||||
<span
|
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-neutral-800 rounded-md p-2"
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
/>
|
||||||
>
|
{#if !isEmailValid}
|
||||||
{$_("last-name-is-required")}
|
<span
|
||||||
</span>
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
{/if}
|
>
|
||||||
</div>
|
{$_("valid-email-is-required")}
|
||||||
<div class="text-sm w-full">
|
</span>
|
||||||
<label for="email" class="font-medium text-gray-700"
|
{/if}
|
||||||
>{$_("e-mail-adress")}</label
|
</div>
|
||||||
>
|
<div class="text-sm w-full mt-2">
|
||||||
<input
|
<label for="phone" class="font-semibold text-gray-700"
|
||||||
autocomplete="off"
|
>{$_("phone")}</label
|
||||||
placeholder={$_("e-mail-adress")}
|
>
|
||||||
type="email"
|
<input
|
||||||
bind:value={editable.email}
|
autocomplete="off"
|
||||||
class:border-red-500={!isEmailValid}
|
placeholder={$_("phone")}
|
||||||
class:focus:border-red-500={!isEmailValid}
|
type="tel"
|
||||||
class:focus:ring-red-500={!isEmailValid}
|
bind:value={editable.phone}
|
||||||
name="email"
|
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-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isEmailValid}
|
</div>
|
||||||
<span
|
<div class="text-sm w-full mt-2">
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
<span class="font-semibold text-gray-700">{$_("group")}</span>
|
||||||
>
|
<Select
|
||||||
{$_("valid-email-is-required")}
|
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-neutral-800 rounded-md p-2"
|
||||||
</span>
|
itemFilter={(label, filterText, option) =>
|
||||||
{/if}
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
</div>
|
option.id.value.toString().startsWith(filterText.toLowerCase())}
|
||||||
<div class="text-sm w-full">
|
items={groups}
|
||||||
<label for="phone" class="font-medium text-gray-700">{$_("phone")}</label>
|
showChevron={true}
|
||||||
<input
|
placeholder={$_("search-for-an-organization-or-team-by-name-or-id")}
|
||||||
autocomplete="off"
|
noOptionsMessage={$_("no-organization-or-team-found")}
|
||||||
placeholder={$_("phone")}
|
bind:selectedValue={group}
|
||||||
type="tel"
|
on:select={(selectedValue) => {
|
||||||
bind:value={editable.phone}
|
editable.group = selectedValue.detail.value.id;
|
||||||
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"
|
on:clear={() => (editable.group = null)}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full mt-2">
|
||||||
<span class="font-medium text-gray-700">{$_("group")}</span>
|
<span class="font-semibold text-gray-700">{$_("distance")}</span>
|
||||||
<Select
|
<br />
|
||||||
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"
|
<span class="text-gray-700">{original_data.distance / 1000} km</span>
|
||||||
itemFilter={(label, filterText, option) =>
|
</div>
|
||||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
</section>
|
||||||
option.id.value.toString().startsWith(filterText.toLowerCase())}
|
|
||||||
items={groups}
|
|
||||||
showChevron={true}
|
|
||||||
placeholder={$_("search-for-an-organization-or-team-by-name-or-id")}
|
|
||||||
noOptionsMessage={$_("no-organization-or-team-found")}
|
|
||||||
bind:selectedValue={group}
|
|
||||||
on:select={(selectedValue) => {
|
|
||||||
editable.group = selectedValue.detail.value.id;
|
|
||||||
}}
|
|
||||||
on:clear={() => (editable.group = null)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="text-sm w-full">
|
|
||||||
<span class="font-medium text-gray-700">{$_("distance")}</span>
|
|
||||||
<br />
|
|
||||||
<span class="text-gray-700">{original_data.distance / 1000} km</span>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{:catch error}
|
{:catch error}
|
||||||
<PromiseError {error} />
|
<PromiseError {error} />
|
||||||
{/await}
|
{/await}
|
||||||
@@ -1,60 +1,317 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import {
|
||||||
import store from "../../store";
|
RunnerOrganizationService,
|
||||||
import AddRunnerModal from "./AddRunnerModal.svelte";
|
RunnerService,
|
||||||
import ImportRunnerModal from "./ImportRunnerModal.svelte";
|
RunnerTeamService,
|
||||||
import RunnersOverview from "./RunnersOverview.svelte";
|
} from "@odit/lfk-client-js";
|
||||||
$: current_runners = [];
|
import {
|
||||||
export let modal_open = false;
|
createSvelteTable,
|
||||||
export let import_modal_open = false;
|
flexRender,
|
||||||
let addRunners;
|
getCoreRowModel,
|
||||||
|
getFilteredRowModel,
|
||||||
|
getPaginationRowModel,
|
||||||
|
getSortedRowModel,
|
||||||
|
renderComponent,
|
||||||
|
} from "@tanstack/svelte-table";
|
||||||
|
import { onMount } from "svelte";
|
||||||
|
import { writable } from "svelte/store";
|
||||||
|
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
||||||
|
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
||||||
|
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
||||||
|
import InputElement from "../shared/InputElement.svelte";
|
||||||
|
import TableActions from "../shared/TableActions.svelte";
|
||||||
|
import { groupFilter } from "../shared/tablefilters";
|
||||||
|
import DeleteRunnerModal from "./DeleteRunnerModal.svelte";
|
||||||
|
import TableBottom from "../shared/TableBottom.svelte";
|
||||||
|
import TableHeader from "../shared/TableHeader.svelte";
|
||||||
|
|
||||||
|
$: selectedRunners =
|
||||||
|
$table?.getSelectedRowModel().rows.map((row) => row.original) || [];
|
||||||
|
$: selected =
|
||||||
|
$table?.getSelectedRowModel().rows.map((row) => row.index) || [];
|
||||||
|
|
||||||
|
$: active_delete = undefined;
|
||||||
|
let dataLoaded = false;
|
||||||
|
export let current_runners = [];
|
||||||
|
$: sponsoring_contracts_show = selected.length > 0;
|
||||||
|
$: cards_show = selected.length > 0;
|
||||||
|
$: certificates_show = selected.length > 0;
|
||||||
|
$: teams = [];
|
||||||
|
$: orgs = [];
|
||||||
|
|
||||||
|
export const addRunners = (runners) => {
|
||||||
|
current_runners = current_runners.concat(...runners);
|
||||||
|
options.update((options) => ({
|
||||||
|
...options,
|
||||||
|
data: current_runners,
|
||||||
|
}));
|
||||||
|
};
|
||||||
|
|
||||||
|
//Section table
|
||||||
|
const columns = [
|
||||||
|
{
|
||||||
|
accessorKey: "id",
|
||||||
|
header: () => "id",
|
||||||
|
filterFn: `equalsString`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "firstname",
|
||||||
|
header: () => $_("first-name"),
|
||||||
|
filterFn: `includesString`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "middlename",
|
||||||
|
header: () => $_("middle-name"),
|
||||||
|
cell: (info) => {
|
||||||
|
if (!info || !info.getValue()) {
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
return info.getValue();
|
||||||
|
},
|
||||||
|
filterFn: `includesString`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "lastname",
|
||||||
|
header: () => $_("last-name"),
|
||||||
|
filterFn: `includesString`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "group",
|
||||||
|
header: () => $_("group"),
|
||||||
|
cell: (info) => {
|
||||||
|
const group = info.getValue();
|
||||||
|
if (group.responseType === "RUNNERORGANIZATION") {
|
||||||
|
return group.name;
|
||||||
|
}
|
||||||
|
return `${group.parentGroup.name} > ${group.name}`;
|
||||||
|
},
|
||||||
|
filterFn: `group`,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "distance",
|
||||||
|
header: () => $_("distance"),
|
||||||
|
cell: (info) => {
|
||||||
|
if (info.getValue() < 1000) {
|
||||||
|
return `${info.getValue()} m`;
|
||||||
|
}
|
||||||
|
return `${(info.getValue() / 1000).toFixed(1)} km`;
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "actions",
|
||||||
|
header: () => $_("action"),
|
||||||
|
cell: (info) => {
|
||||||
|
return renderComponent(TableActions, {
|
||||||
|
detailsLink: `./${info.row.original.id}`,
|
||||||
|
deleteAction: () => {
|
||||||
|
active_delete =
|
||||||
|
current_runners[
|
||||||
|
current_runners.findIndex((r) => r.id == info.row.original.id)
|
||||||
|
];
|
||||||
|
},
|
||||||
|
deleteEnabled:
|
||||||
|
store.state.jwtinfo.userdetails.permissions.includes(
|
||||||
|
"RUNNER:DELETE"
|
||||||
|
),
|
||||||
|
});
|
||||||
|
},
|
||||||
|
enableColumnFilter: false,
|
||||||
|
enableSorting: false,
|
||||||
|
},
|
||||||
|
];
|
||||||
|
const options = writable({
|
||||||
|
data: [],
|
||||||
|
columns: columns,
|
||||||
|
filterFns: {
|
||||||
|
group: groupFilter,
|
||||||
|
},
|
||||||
|
initialState: {
|
||||||
|
pagination: {
|
||||||
|
pageSize: 50,
|
||||||
|
},
|
||||||
|
},
|
||||||
|
enableRowSelection: true,
|
||||||
|
getCoreRowModel: getCoreRowModel(),
|
||||||
|
getFilteredRowModel: getFilteredRowModel(),
|
||||||
|
getPaginationRowModel: getPaginationRowModel(),
|
||||||
|
getSortedRowModel: getSortedRowModel(),
|
||||||
|
});
|
||||||
|
const table = createSvelteTable(options);
|
||||||
|
|
||||||
|
async function deleteRunner(delete_runner_id) {
|
||||||
|
await RunnerService.runnerControllerRemove(delete_runner_id, true);
|
||||||
|
current_runners = current_runners.filter((r) => r.id !== delete_runner_id);
|
||||||
|
options.update((options) => ({
|
||||||
|
...options,
|
||||||
|
data: current_runners,
|
||||||
|
}));
|
||||||
|
toast($_("runner-deleted"));
|
||||||
|
}
|
||||||
|
|
||||||
|
onMount(async () => {
|
||||||
|
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
||||||
|
teams = val;
|
||||||
|
});
|
||||||
|
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
||||||
|
(val) => {
|
||||||
|
orgs = val;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
|
||||||
|
let page = 0;
|
||||||
|
while (page >= 0) {
|
||||||
|
const runners = await RunnerService.runnerControllerGetAll(page, 500);
|
||||||
|
if (runners.length == 0) {
|
||||||
|
page = -2;
|
||||||
|
}
|
||||||
|
|
||||||
|
current_runners = current_runners.concat(...runners);
|
||||||
|
options.update((options) => ({
|
||||||
|
...options,
|
||||||
|
data: current_runners,
|
||||||
|
}));
|
||||||
|
|
||||||
|
dataLoaded = true;
|
||||||
|
page++;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import store from "../../store";
|
||||||
|
import AddRunnerModal from "./AddRunnerModal.svelte";
|
||||||
|
import ImportRunnerModal from "./ImportRunnerModal.svelte";
|
||||||
|
$: current_runners = [];
|
||||||
|
export let modal_open = false;
|
||||||
|
export let import_modal_open = false;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_("runners")}
|
{$_("runners")}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:CREATE")}
|
</h4>
|
||||||
<button
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:CREATE")}
|
||||||
on:click={() => {
|
<button
|
||||||
modal_open = true;
|
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"
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
{$_("laeufer-hinzufuegen")}
|
>
|
||||||
</button>
|
{$_("laeufer-hinzufuegen")}
|
||||||
<button
|
</button>
|
||||||
on:click={() => {
|
<button
|
||||||
import_modal_open = true;
|
on:click={() => {
|
||||||
}}
|
import_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"
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
{$_("import-runners")}
|
>
|
||||||
</button>
|
{$_("import-runners")}
|
||||||
{/if}
|
</button>
|
||||||
</span>
|
{/if}
|
||||||
<RunnersOverview bind:current_runners bind:addRunners />
|
<DeleteRunnerModal
|
||||||
|
delete_runner={active_delete}
|
||||||
|
modal_open={active_delete != undefined}
|
||||||
|
on:delete={(event) => {
|
||||||
|
deleteRunner(event.detail.id);
|
||||||
|
}}
|
||||||
|
/>
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET")}
|
||||||
|
{#if !dataLoaded}
|
||||||
|
<div
|
||||||
|
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">{$_("runners-are-being-loaded")}</p>
|
||||||
|
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
||||||
|
</div>
|
||||||
|
{:else}
|
||||||
|
<GenerateSponsoringContracts
|
||||||
|
bind:sponsoring_contracts_show
|
||||||
|
bind:generate_runners={selectedRunners}
|
||||||
|
/>
|
||||||
|
<GenerateRunnerCards
|
||||||
|
bind:cards_show
|
||||||
|
bind:generate_runners={selectedRunners}
|
||||||
|
/>
|
||||||
|
<GenerateRunnerCertificates
|
||||||
|
bind:certificates_show
|
||||||
|
bind:generate_runners={selectedRunners}
|
||||||
|
/>
|
||||||
|
<div class="overflow-x-auto">
|
||||||
|
<table class="w-full">
|
||||||
|
<thead class="border-b border-gray-400">
|
||||||
|
{#each $table.getHeaderGroups() as headerGroup}
|
||||||
|
<tr class="select-none">
|
||||||
|
<th class="inset-y-0 left-0 px-4 py-2 text-left w-px">
|
||||||
|
<InputElement
|
||||||
|
type="checkbox"
|
||||||
|
checked={$table.getIsAllRowsSelected()}
|
||||||
|
indeterminate={$table.getIsSomeRowsSelected()}
|
||||||
|
on:change={() => $table.toggleAllRowsSelected()}
|
||||||
|
/>
|
||||||
|
</th>
|
||||||
|
{#each headerGroup.headers as header}
|
||||||
|
<TableHeader {header} />
|
||||||
|
{/each}
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</thead>
|
||||||
|
<tbody>
|
||||||
|
{#each $table.getRowModel().rows as row}
|
||||||
|
<tr class="odd:bg-white even:bg-gray-100">
|
||||||
|
<td class="inset-y-0 left-0 px-4 py-2 text-center w-px">
|
||||||
|
<InputElement
|
||||||
|
type="checkbox"
|
||||||
|
checked={row.getIsSelected()}
|
||||||
|
on:change={() => row.toggleSelected()}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
{#each row.getVisibleCells() as cell}
|
||||||
|
<td>
|
||||||
|
<svelte:component
|
||||||
|
this={flexRender(
|
||||||
|
cell.column.columnDef.cell,
|
||||||
|
cell.getContext()
|
||||||
|
)}
|
||||||
|
/>
|
||||||
|
</td>
|
||||||
|
{/each}
|
||||||
|
</tr>
|
||||||
|
{/each}
|
||||||
|
</tbody>
|
||||||
|
</table>
|
||||||
|
</div>
|
||||||
|
<div class="h-2" />
|
||||||
|
{/if}
|
||||||
|
{/if}
|
||||||
|
<TableBottom {table} {selected} />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:CREATE")}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:CREATE")}
|
||||||
<AddRunnerModal
|
<AddRunnerModal
|
||||||
bind:modal_open
|
bind:modal_open
|
||||||
on:created={(event) => {
|
on:created={(event) => {
|
||||||
addRunners(event.detail.runners);
|
addRunners(event.detail.runners);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
<ImportRunnerModal
|
<ImportRunnerModal
|
||||||
on:cancelDelete={(event) => {
|
on:cancelDelete={(event) => {
|
||||||
import_modal_open = false;
|
import_modal_open = false;
|
||||||
}}
|
}}
|
||||||
passed_team={{}}
|
passed_team={{}}
|
||||||
passed_orgs={[]}
|
passed_orgs={[]}
|
||||||
passed_org={{}}
|
passed_org={{}}
|
||||||
opened_from="RunnerOverview"
|
opened_from="RunnerOverview"
|
||||||
bind:import_modal_open
|
bind:import_modal_open
|
||||||
on:created={(event) => {
|
on:created={(event) => {
|
||||||
addRunners(event.detail.runners);
|
addRunners(event.detail.runners);
|
||||||
}}
|
}}
|
||||||
/>
|
/>
|
||||||
{/if}
|
{/if}
|
||||||
|
|
||||||
|
<style>
|
||||||
|
table tbody tr td:nth-child(2) {
|
||||||
|
font-family: monospace;
|
||||||
|
}
|
||||||
|
</style>
|
||||||
@@ -1,267 +0,0 @@
|
|||||||
<script>
|
|
||||||
import {
|
|
||||||
RunnerOrganizationService,
|
|
||||||
RunnerService,
|
|
||||||
RunnerTeamService,
|
|
||||||
} from "@odit/lfk-client-js";
|
|
||||||
import {
|
|
||||||
createSvelteTable,
|
|
||||||
flexRender,
|
|
||||||
getCoreRowModel,
|
|
||||||
getFilteredRowModel,
|
|
||||||
getPaginationRowModel,
|
|
||||||
getSortedRowModel,
|
|
||||||
renderComponent,
|
|
||||||
} from "@tanstack/svelte-table";
|
|
||||||
import { onMount } from "svelte";
|
|
||||||
import { _ } from "svelte-i18n";
|
|
||||||
import { writable } from "svelte/store";
|
|
||||||
import store from "../../store";
|
|
||||||
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
|
||||||
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
|
||||||
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
|
||||||
import InputElement from "../shared/InputElement.svelte";
|
|
||||||
import TableActions from "../shared/TableActions.svelte";
|
|
||||||
import { groupFilter } from "../shared/tablefilters";
|
|
||||||
import DeleteRunnerModal from "./DeleteRunnerModal.svelte";
|
|
||||||
import TableBottom from "../shared/TableBottom.svelte";
|
|
||||||
import TableHeader from "../shared/TableHeader.svelte";
|
|
||||||
|
|
||||||
$: selectedRunners =
|
|
||||||
$table?.getSelectedRowModel().rows.map((row) => row.original) || [];
|
|
||||||
$: selected =
|
|
||||||
$table?.getSelectedRowModel().rows.map((row) => row.index) || [];
|
|
||||||
|
|
||||||
$: active_delete = undefined;
|
|
||||||
let dataLoaded = false;
|
|
||||||
export let current_runners = [];
|
|
||||||
$: sponsoring_contracts_show = selected.length > 0;
|
|
||||||
$: cards_show = selected.length > 0;
|
|
||||||
$: certificates_show = selected.length > 0;
|
|
||||||
$: teams = [];
|
|
||||||
$: orgs = [];
|
|
||||||
|
|
||||||
export const addRunners = (runners) => {
|
|
||||||
current_runners = current_runners.concat(...runners);
|
|
||||||
options.update((options) => ({
|
|
||||||
...options,
|
|
||||||
data: current_runners,
|
|
||||||
}));
|
|
||||||
};
|
|
||||||
|
|
||||||
//Section table
|
|
||||||
const columns = [
|
|
||||||
{
|
|
||||||
accessorKey: "id",
|
|
||||||
header: () => "id",
|
|
||||||
filterFn: `equalsString`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: "firstname",
|
|
||||||
header: () => $_("first-name"),
|
|
||||||
filterFn: `includesString`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: "middlename",
|
|
||||||
header: () => $_("middle-name"),
|
|
||||||
cell: (info) => {
|
|
||||||
if (!info || !info.getValue()) {
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
return info.getValue();
|
|
||||||
},
|
|
||||||
filterFn: `includesString`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: "lastname",
|
|
||||||
header: () => $_("last-name"),
|
|
||||||
filterFn: `includesString`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: "group",
|
|
||||||
header: () => $_("group"),
|
|
||||||
cell: (info) => {
|
|
||||||
const group = info.getValue();
|
|
||||||
if (group.responseType === "RUNNERORGANIZATION") {
|
|
||||||
return group.name;
|
|
||||||
}
|
|
||||||
return `${group.parentGroup.name} > ${group.name}`;
|
|
||||||
},
|
|
||||||
filterFn: `group`,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: "distance",
|
|
||||||
header: () => $_("distance"),
|
|
||||||
cell: (info) => {
|
|
||||||
if (info.getValue() < 1000) {
|
|
||||||
return `${info.getValue()} m`;
|
|
||||||
}
|
|
||||||
return `${(info.getValue() / 1000).toFixed(1)} km`;
|
|
||||||
},
|
|
||||||
enableColumnFilter: false,
|
|
||||||
},
|
|
||||||
{
|
|
||||||
accessorKey: "actions",
|
|
||||||
header: () => $_("action"),
|
|
||||||
cell: (info) => {
|
|
||||||
return renderComponent(TableActions, {
|
|
||||||
detailsLink: `./${info.row.original.id}`,
|
|
||||||
deleteAction: () => {
|
|
||||||
active_delete =
|
|
||||||
current_runners[
|
|
||||||
current_runners.findIndex((r) => r.id == info.row.original.id)
|
|
||||||
];
|
|
||||||
},
|
|
||||||
deleteEnabled:
|
|
||||||
store.state.jwtinfo.userdetails.permissions.includes(
|
|
||||||
"RUNNER:DELETE"
|
|
||||||
),
|
|
||||||
});
|
|
||||||
},
|
|
||||||
enableColumnFilter: false,
|
|
||||||
enableSorting: false,
|
|
||||||
},
|
|
||||||
];
|
|
||||||
const options = writable({
|
|
||||||
data: [],
|
|
||||||
columns: columns,
|
|
||||||
filterFns: {
|
|
||||||
group: groupFilter,
|
|
||||||
},
|
|
||||||
initialState: {
|
|
||||||
pagination: {
|
|
||||||
pageSize: 50,
|
|
||||||
},
|
|
||||||
},
|
|
||||||
enableRowSelection: true,
|
|
||||||
getCoreRowModel: getCoreRowModel(),
|
|
||||||
getFilteredRowModel: getFilteredRowModel(),
|
|
||||||
getPaginationRowModel: getPaginationRowModel(),
|
|
||||||
getSortedRowModel: getSortedRowModel(),
|
|
||||||
});
|
|
||||||
const table = createSvelteTable(options);
|
|
||||||
|
|
||||||
async function deleteRunner(delete_runner_id) {
|
|
||||||
await RunnerService.runnerControllerRemove(delete_runner_id, true);
|
|
||||||
current_runners = current_runners.filter((r) => r.id !== delete_runner_id);
|
|
||||||
options.update((options) => ({
|
|
||||||
...options,
|
|
||||||
data: current_runners,
|
|
||||||
}));
|
|
||||||
toast($_("runner-deleted"));
|
|
||||||
}
|
|
||||||
|
|
||||||
onMount(async () => {
|
|
||||||
RunnerTeamService.runnerTeamControllerGetAll().then((val) => {
|
|
||||||
teams = val;
|
|
||||||
});
|
|
||||||
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
|
||||||
(val) => {
|
|
||||||
orgs = val;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
|
|
||||||
let page = 0;
|
|
||||||
while (page >= 0) {
|
|
||||||
const runners = await RunnerService.runnerControllerGetAll(page, 500);
|
|
||||||
if (runners.length == 0) {
|
|
||||||
page = -2;
|
|
||||||
}
|
|
||||||
|
|
||||||
current_runners = current_runners.concat(...runners);
|
|
||||||
options.update((options) => ({
|
|
||||||
...options,
|
|
||||||
data: current_runners,
|
|
||||||
}));
|
|
||||||
|
|
||||||
dataLoaded = true;
|
|
||||||
page++;
|
|
||||||
}
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<DeleteRunnerModal
|
|
||||||
delete_runner={active_delete}
|
|
||||||
modal_open={active_delete != undefined}
|
|
||||||
on:delete={(event) => {
|
|
||||||
deleteRunner(event.detail.id);
|
|
||||||
}}
|
|
||||||
/>
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET")}
|
|
||||||
{#if !dataLoaded}
|
|
||||||
<div
|
|
||||||
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">{$_("runners-are-being-loaded")}</p>
|
|
||||||
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
|
||||||
</div>
|
|
||||||
{:else}
|
|
||||||
<div class="h-12 mt-2">
|
|
||||||
<GenerateSponsoringContracts
|
|
||||||
bind:sponsoring_contracts_show
|
|
||||||
bind:generate_runners={selectedRunners}
|
|
||||||
/>
|
|
||||||
<GenerateRunnerCards
|
|
||||||
bind:cards_show
|
|
||||||
bind:generate_runners={selectedRunners}
|
|
||||||
/>
|
|
||||||
<GenerateRunnerCertificates
|
|
||||||
bind:certificates_show
|
|
||||||
bind:generate_runners={selectedRunners}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="overflow-x-auto">
|
|
||||||
<table class="w-full">
|
|
||||||
<thead class="border-b border-gray-400">
|
|
||||||
{#each $table.getHeaderGroups() as headerGroup}
|
|
||||||
<tr class="select-none">
|
|
||||||
<th class="inset-y-0 left-0 px-4 py-2 text-left w-px">
|
|
||||||
<InputElement
|
|
||||||
type="checkbox"
|
|
||||||
checked={$table.getIsAllRowsSelected()}
|
|
||||||
indeterminate={$table.getIsSomeRowsSelected()}
|
|
||||||
on:change={() => $table.toggleAllRowsSelected()}
|
|
||||||
/>
|
|
||||||
</th>
|
|
||||||
{#each headerGroup.headers as header}
|
|
||||||
<TableHeader {header} />
|
|
||||||
{/each}
|
|
||||||
</tr>
|
|
||||||
{/each}
|
|
||||||
</thead>
|
|
||||||
<tbody>
|
|
||||||
{#each $table.getRowModel().rows as row}
|
|
||||||
<tr class="odd:bg-white even:bg-gray-100">
|
|
||||||
<td class="inset-y-0 left-0 px-4 py-2 text-center w-px">
|
|
||||||
<InputElement
|
|
||||||
type="checkbox"
|
|
||||||
checked={row.getIsSelected()}
|
|
||||||
on:change={() => row.toggleSelected()}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
{#each row.getVisibleCells() as cell}
|
|
||||||
<td>
|
|
||||||
<svelte:component
|
|
||||||
this={flexRender(
|
|
||||||
cell.column.columnDef.cell,
|
|
||||||
cell.getContext()
|
|
||||||
)}
|
|
||||||
/>
|
|
||||||
</td>
|
|
||||||
{/each}
|
|
||||||
</tr>
|
|
||||||
{/each}
|
|
||||||
</tbody>
|
|
||||||
</table>
|
|
||||||
</div>
|
|
||||||
<div class="h-2" />
|
|
||||||
{/if}
|
|
||||||
{/if}
|
|
||||||
<TableBottom {table} {selected} />
|
|
||||||
|
|
||||||
<style>
|
|
||||||
table tbody tr td:nth-child(2) {
|
|
||||||
font-family: monospace;
|
|
||||||
}
|
|
||||||
</style>
|
|
||||||
@@ -131,7 +131,7 @@
|
|||||||
>{$_("runner")}</label
|
>{$_("runner")}</label
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
itemFilter={(label, filterText, option) =>
|
itemFilter={(label, filterText, option) =>
|
||||||
filterRunners(label, filterText, option)}
|
filterRunners(label, filterText, option)}
|
||||||
items={runners}
|
items={runners}
|
||||||
@@ -160,7 +160,7 @@
|
|||||||
type="number"
|
type="number"
|
||||||
step="1"
|
step="1"
|
||||||
name="donation_amount_eur"
|
name="donation_amount_eur"
|
||||||
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
|
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 p-2"
|
||||||
placeholder="400"
|
placeholder="400"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -1,288 +1,273 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import { RunnerService, ScanService } from "@odit/lfk-client-js";
|
import { RunnerService, ScanService } from "@odit/lfk-client-js";
|
||||||
|
|
||||||
import PromiseError from "../base/PromiseError.svelte";
|
import PromiseError from "../base/PromiseError.svelte";
|
||||||
import Select from "svelte-select";
|
import Select from "svelte-select";
|
||||||
let data_loaded = false;
|
let data_loaded = false;
|
||||||
export let params;
|
export let params;
|
||||||
$: delete_triggered = false;
|
$: delete_triggered = false;
|
||||||
$: original_data = {};
|
$: original_data = {};
|
||||||
$: editable = {};
|
$: editable = {};
|
||||||
$: current_runners = [];
|
$: current_runners = [];
|
||||||
$: is_distance_valid = editable.distance > 0;
|
$: is_distance_valid = editable.distance > 0;
|
||||||
$: is_everything_set =
|
$: is_everything_set =
|
||||||
editable.runner != null &&
|
editable.runner != null &&
|
||||||
((original_data.responseType === "TRACKSCAN" && editable.track != null) ||
|
((original_data.responseType === "TRACKSCAN" && editable.track != null) ||
|
||||||
original_data.responseType !== "TRACKSCAN");
|
original_data.responseType !== "TRACKSCAN");
|
||||||
$: runner = {};
|
$: runner = {};
|
||||||
$: changes_performed = !(
|
$: changes_performed = !(
|
||||||
JSON.stringify(original_data) === JSON.stringify(editable)
|
JSON.stringify(original_data) === JSON.stringify(editable)
|
||||||
);
|
);
|
||||||
$: save_enabled = changes_performed && is_everything_set && is_distance_valid;
|
$: save_enabled = changes_performed && is_everything_set && is_distance_valid;
|
||||||
|
|
||||||
const promise = ScanService.scanControllerGetOne(params.scanid).then(
|
const promise = ScanService.scanControllerGetOne(params.scanid).then(
|
||||||
(data) => {
|
(data) => {
|
||||||
data_loaded = true;
|
data_loaded = true;
|
||||||
original_data = Object.assign(original_data, data);
|
original_data = Object.assign(original_data, data);
|
||||||
original_data.runner = original_data.runner.id;
|
original_data.runner = original_data.runner.id;
|
||||||
editable = Object.assign(editable, original_data);
|
editable = Object.assign(editable, original_data);
|
||||||
RunnerService.runnerControllerGetAll().then((val) => {
|
RunnerService.runnerControllerGetAll().then((val) => {
|
||||||
current_runners = val.map((r) => {
|
current_runners = val.map((r) => {
|
||||||
return { label: getRunnerLabel(r), value: r };
|
return { label: getRunnerLabel(r), value: r };
|
||||||
});
|
});
|
||||||
runner = current_runners.find((r) => r.value.id == editable.runner);
|
runner = current_runners.find((r) => r.value.id == editable.runner);
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
const getRunnerLabel = (option) =>
|
const getRunnerLabel = (option) =>
|
||||||
option.firstname + " " + (option.middlename || "") + " " + option.lastname;
|
option.firstname + " " + (option.middlename || "") + " " + option.lastname;
|
||||||
const filterRunners = (label, filterText, option) =>
|
const filterRunners = (label, filterText, option) =>
|
||||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
option.value.id.toString().startsWith(filterText.toLowerCase());
|
option.value.id.toString().startsWith(filterText.toLowerCase());
|
||||||
|
|
||||||
function submit() {
|
function submit() {
|
||||||
if (data_loaded === true && save_enabled) {
|
if (data_loaded === true && save_enabled) {
|
||||||
toast($_("scan-is-being-updated"));
|
toast($_("scan-is-being-updated"));
|
||||||
let postdata = {};
|
let postdata = {};
|
||||||
if (original_data.responseType === "TRACKSCAN") {
|
if (original_data.responseType === "TRACKSCAN") {
|
||||||
postdata = Object.assign(postdata, editable);
|
postdata = Object.assign(postdata, editable);
|
||||||
postdata.track = postdata.track.id;
|
postdata.track = postdata.track.id;
|
||||||
ScanService.scanControllerPutTrackScan(original_data.id, postdata)
|
ScanService.scanControllerPutTrackScan(original_data.id, postdata)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
Object.assign(original_data, editable);
|
Object.assign(original_data, editable);
|
||||||
original_data = original_data;
|
original_data = original_data;
|
||||||
toast.success($_("updated-scan"));
|
toast.success($_("updated-scan"));
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
} else {
|
} else {
|
||||||
postdata = Object.assign(postdata, editable);
|
postdata = Object.assign(postdata, editable);
|
||||||
ScanService.scanControllerPut(original_data.id, postdata)
|
ScanService.scanControllerPut(original_data.id, postdata)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
Object.assign(original_data, editable);
|
Object.assign(original_data, editable);
|
||||||
original_data = original_data;
|
original_data = original_data;
|
||||||
toast.success($_("updated-scan"));
|
toast.success($_("updated-scan"));
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function deleteScan() {
|
function deleteScan() {
|
||||||
ScanService.scanControllerRemove(original_data.id, false)
|
ScanService.scanControllerRemove(original_data.id, false)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
toast($_("deleted-scan"));
|
toast($_("deleted-scan"));
|
||||||
location.replace("./");
|
location.replace("./");
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
modal_open = true;
|
modal_open = true;
|
||||||
delete_scan = original_data;
|
delete_scan = original_data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function format_laptime(laptime) {
|
function format_laptime(laptime) {
|
||||||
if (laptime == 0 || laptime == null) {
|
if (laptime == 0 || laptime == null) {
|
||||||
return $_("first-scan-of-the-day");
|
return $_("first-scan-of-the-day");
|
||||||
}
|
}
|
||||||
if (laptime < 60) {
|
if (laptime < 60) {
|
||||||
return `${laptime}s`;
|
return `${laptime}s`;
|
||||||
}
|
}
|
||||||
if (laptime < 3600) {
|
if (laptime < 3600) {
|
||||||
return `${Math.floor(laptime / 60)}min ${
|
return `${Math.floor(laptime / 60)}min ${
|
||||||
laptime - Math.floor(laptime / 60) * 60
|
laptime - Math.floor(laptime / 60) * 60
|
||||||
}s`;
|
}s`;
|
||||||
}
|
}
|
||||||
return `${Math.floor(laptime / 3600)}h ${
|
return `${Math.floor(laptime / 3600)}h ${
|
||||||
laptime - Math.floor(laptime / 3600) * 3600
|
laptime - Math.floor(laptime / 3600) * 3600
|
||||||
}min ${
|
}min ${
|
||||||
laptime -
|
laptime -
|
||||||
Math.floor(laptime / 3600) * 3600 -
|
Math.floor(laptime / 3600) * 3600 -
|
||||||
Math.floor(laptime / 60) * 60
|
Math.floor(laptime / 60) * 60
|
||||||
}`;
|
}`;
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#await promise}
|
{#await promise}
|
||||||
Loading scan details
|
Loading scan details
|
||||||
{: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">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<nav class="w-full flex">
|
<nav class="w-full flex">
|
||||||
<ol class="list-none flex flex-row items-center justify-start">
|
<ol class="list-none flex flex-row items-center justify-start">
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
<svg
|
<a class="mr-2" href="./"
|
||||||
fill="currentColor"
|
><svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
width="24"
|
||||||
width="24"
|
height="24"
|
||||||
height="24"
|
viewBox="0 0 24 24"
|
||||||
><path
|
fill="none"
|
||||||
fill="currentColor"
|
stroke="currentColor"
|
||||||
d="M2 4h2v16H2V4zm4 0h1v16H6V4zm2 0h2v16H8V4zm3 0h2v16h-2V4zm3 0h2v16h-2V4zm3 0h1v16h-1V4zm2 0h3v16h-3V4z"
|
stroke-width="2"
|
||||||
/></svg
|
stroke-linecap="round"
|
||||||
>
|
stroke-linejoin="round"
|
||||||
</li>
|
class="inline-block"
|
||||||
<li class="flex items-center ml-2">
|
><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg
|
||||||
<a class="mr-2" href="./">Scans</a><svg
|
> Scans</a
|
||||||
stroke="currentColor"
|
>
|
||||||
fill="none"
|
</li>
|
||||||
stroke-width="2"
|
</ol>
|
||||||
viewBox="0 0 24 24"
|
</nav>
|
||||||
stroke-linecap="round"
|
</div>
|
||||||
stroke-linejoin="round"
|
</div>
|
||||||
class="h-3 w-3 mr-2 stroke-current"
|
<div class="mb-4 text-3xl font-extrabold leading-tight">
|
||||||
height="1em"
|
{runner.value?.firstname}
|
||||||
width="1em"
|
{runner.value?.middlename || ""}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
{runner.value?.lastname}
|
||||||
><line x1="5" y1="12" x2="19" y2="12" />
|
- Scan #{original_data.id}
|
||||||
<polyline points="12 5 19 12 12 19" /></svg
|
<div data-id="donation_actions_${original_data.id}">
|
||||||
>
|
{#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:DELETE")}
|
||||||
</li>
|
{#if delete_triggered}
|
||||||
<li class="flex items-center">
|
<button
|
||||||
<span class="mr-2">{original_data.id}</span>
|
on:click={deleteScan}
|
||||||
</li>
|
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:w-auto sm:text-sm"
|
||||||
</ol>
|
>{$_("confirm-deletion")}</button
|
||||||
</nav>
|
>
|
||||||
</div>
|
<button
|
||||||
</div>
|
on:click={() => {
|
||||||
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
delete_triggered = !delete_triggered;
|
||||||
{runner.value?.firstname}
|
}}
|
||||||
{runner.value?.middlename || ""}
|
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"
|
||||||
{runner.value?.lastname}
|
>{$_("cancel")}</button
|
||||||
#{original_data.id}
|
>
|
||||||
<span data-id="donation_actions_${original_data.id}">
|
{/if}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:DELETE")}
|
{#if !delete_triggered}
|
||||||
{#if delete_triggered}
|
<button
|
||||||
<button
|
on:click={() => {
|
||||||
on:click={deleteScan}
|
delete_triggered = true;
|
||||||
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:"
|
}}
|
||||||
>{$_("confirm-deletion")}</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:w-auto sm:text-sm"
|
||||||
<button
|
>{$_("delete-scan")}</button
|
||||||
on:click={() => {
|
>
|
||||||
delete_triggered = !delete_triggered;
|
{/if}
|
||||||
}}
|
{/if}
|
||||||
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:"
|
{#if !delete_triggered}
|
||||||
>{$_("cancel")}</button
|
<button
|
||||||
>
|
disabled={!save_enabled}
|
||||||
{/if}
|
class:opacity-50={!save_enabled}
|
||||||
{#if !delete_triggered}
|
type="button"
|
||||||
<button
|
on:click={submit}
|
||||||
on:click={() => {
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
delete_triggered = true;
|
>{$_("save-changes")}</button
|
||||||
}}
|
>
|
||||||
type="button"
|
{/if}
|
||||||
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:"
|
</div>
|
||||||
>{$_("delete-scan")}</button
|
</div>
|
||||||
>
|
<!-- -->
|
||||||
{/if}
|
<div class="w-full inline-flex">
|
||||||
{/if}
|
<label for="valid" class="block font-medium text-gray-700"
|
||||||
{#if !delete_triggered}
|
>{$_("status")}:
|
||||||
<button
|
</label>
|
||||||
disabled={!save_enabled}
|
|
||||||
class:opacity-50={!save_enabled}
|
<input
|
||||||
type="button"
|
id="valid"
|
||||||
on:click={submit}
|
on:change={() => {
|
||||||
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:"
|
editable.valid = !editable.valid;
|
||||||
>{$_("save-changes")}</button
|
}}
|
||||||
>
|
name="valid"
|
||||||
{/if}
|
type="checkbox"
|
||||||
</span>
|
checked={editable.valid}
|
||||||
</div>
|
class="focus:ring-indigo-500 align-bottom h-7 w-5font-medium text-indigo-600 border-gray-300 rounded"
|
||||||
<!-- -->
|
/>
|
||||||
<div class="w-full inline-flex">
|
|
||||||
<label for="valid" class="block font-medium text-gray-700"
|
<p class="font-medium">
|
||||||
>{$_("status")}:
|
{#if editable.valid}{$_("valid")}{:else}{$_("invalid")}{/if}
|
||||||
</label>
|
</p>
|
||||||
|
</div>
|
||||||
<input
|
{#if editable.responseType === "TRACKSCAN"}
|
||||||
id="valid"
|
<div class="w-full inline-flex">
|
||||||
on:change={() => {
|
<label for="valid" class="block font-semibold text-gray-700"
|
||||||
editable.valid = !editable.valid;
|
>{$_("track")}:
|
||||||
}}
|
</label>
|
||||||
name="valid"
|
<a
|
||||||
type="checkbox"
|
href="../tracks"
|
||||||
checked={editable.valid}
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800 border border-current"
|
||||||
class="focus:ring-indigo-500 align-bottom h-7 w-5font-medium text-indigo-600 border-gray-300 rounded"
|
>{editable.track.name}
|
||||||
/>
|
</a>
|
||||||
|
</div>
|
||||||
<p class="font-medium">
|
<div class="w-full inline-flex pb-3">
|
||||||
{#if editable.valid}{$_("valid")}{:else}{$_("invalid")}{/if}
|
<label for="valid" class="block font-semibold text-gray-700"
|
||||||
</p>
|
>{$_("laptime")}: {format_laptime(editable.laptime)}
|
||||||
</div>
|
</label>
|
||||||
{#if editable.responseType === "TRACKSCAN"}
|
</div>
|
||||||
<div class="w-full inline-flex">
|
{/if}
|
||||||
<label for="valid" class="block font-semibold text-gray-700"
|
<div class=" w-full">
|
||||||
>{$_("track")}:
|
<label for="runner" class="block font-medium text-gray-700"
|
||||||
</label>
|
>{$_("runner")}</label
|
||||||
<a
|
>
|
||||||
href="../tracks"
|
<Select
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
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-neutral-800 rounded-md p-2"
|
||||||
>{editable.track.name}
|
itemFilter={(label, filterText, option) =>
|
||||||
</a>
|
filterRunners(label, filterText, option)}
|
||||||
</div>
|
items={current_runners}
|
||||||
<div class="w-full inline-flex pb-3">
|
showChevron={true}
|
||||||
<label for="valid" class="block font-semibold text-gray-700"
|
isDisabled={editable.responseType === "TRACKSCAN"}
|
||||||
>{$_("laptime")}: {format_laptime(editable.laptime)}
|
placeholder={$_("search-for-runner-by-name-or-id")}
|
||||||
</label>
|
noOptionsMessage={$_("no-runners-found")}
|
||||||
</div>
|
bind:selectedValue={runner}
|
||||||
{/if}
|
on:select={(selectedValue) => {
|
||||||
<div class=" w-full">
|
editable.runner = selectedValue.detail.value.id;
|
||||||
<label for="runner" class="block font-medium text-gray-700"
|
}}
|
||||||
>{$_("runner")}</label
|
on:clear={() => (editable.runner = null)}
|
||||||
>
|
/>
|
||||||
<Select
|
</div>
|
||||||
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"
|
<div class=" w-full">
|
||||||
itemFilter={(label, filterText, option) =>
|
<label
|
||||||
filterRunners(label, filterText, option)}
|
for="scan_distance"
|
||||||
items={current_runners}
|
class="block text-sm font-medium text-gray-700"
|
||||||
showChevron={true}
|
>
|
||||||
isDisabled={editable.responseType === "TRACKSCAN"}
|
{$_("distance")}</label
|
||||||
placeholder={$_("search-for-runner-by-name-or-id")}
|
>
|
||||||
noOptionsMessage={$_("no-runners-found")}
|
<div class="mt-1 flex rounded-md shadow-sm">
|
||||||
bind:selectedValue={runner}
|
<input
|
||||||
on:select={(selectedValue) => {
|
autocomplete="off"
|
||||||
editable.runner = selectedValue.detail.value.id;
|
class:border-red-500={!is_distance_valid}
|
||||||
}}
|
class:focus:border-red-500={!is_distance_valid}
|
||||||
on:clear={() => (editable.runner = null)}
|
class:focus:ring-red-500={!is_distance_valid}
|
||||||
/>
|
bind:value={editable.distance}
|
||||||
</div>
|
disabled={editable.responseType === "TRACKSCAN"}
|
||||||
<div class=" w-full">
|
type="number"
|
||||||
<label
|
step="1"
|
||||||
for="scan_distance"
|
name="scan_distance"
|
||||||
class="block text-sm font-medium text-gray-700"
|
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 p-2"
|
||||||
>
|
placeholder="400"
|
||||||
{$_("distance")}</label
|
/>
|
||||||
>
|
<span
|
||||||
<div class="mt-1 flex rounded-md shadow-sm">
|
class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm"
|
||||||
<input
|
>m</span
|
||||||
autocomplete="off"
|
>
|
||||||
class:border-red-500={!is_distance_valid}
|
</div>
|
||||||
class:focus:border-red-500={!is_distance_valid}
|
{#if !is_distance_valid}
|
||||||
class:focus:ring-red-500={!is_distance_valid}
|
<span
|
||||||
bind:value={editable.distance}
|
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
||||||
disabled={editable.responseType === "TRACKSCAN"}
|
>
|
||||||
type="number"
|
{$_("the-scans-distance-must-be-greater-than-0m")}
|
||||||
step="1"
|
</span>
|
||||||
name="scan_distance"
|
{/if}
|
||||||
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
|
</div>
|
||||||
placeholder="400"
|
</section>
|
||||||
/>
|
|
||||||
<span
|
|
||||||
class="inline-flex items-center px-3 rounded-r-md border border-gray-300 bg-gray-50 text-gray-500 text-sm"
|
|
||||||
>m</span
|
|
||||||
>
|
|
||||||
</div>
|
|
||||||
{#if !is_distance_valid}
|
|
||||||
<span
|
|
||||||
class="flex items-center font-medium tracking-wide text-red-500 text-xs mt-1 ml-1"
|
|
||||||
>
|
|
||||||
{$_("the-scans-distance-must-be-greater-than-0m")}
|
|
||||||
</span>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{:catch error}
|
{:catch error}
|
||||||
<PromiseError {error} />
|
<PromiseError {error} />
|
||||||
{/await}
|
{/await}
|
||||||
@@ -5,12 +5,12 @@
|
|||||||
|
|
||||||
{#if valid}
|
{#if valid}
|
||||||
<span
|
<span
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-green-100 text-green-800"
|
||||||
>{$_("valid")}</span
|
>{$_("valid")}</span
|
||||||
>
|
>
|
||||||
{:else}
|
{:else}
|
||||||
<span
|
<span
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800"
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-red-100 text-red-800"
|
||||||
>{$_("invalid")}</span
|
>{$_("invalid")}</span
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -9,20 +9,20 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_("scans")}
|
{$_("scans")}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:CREATE")}
|
</h4>
|
||||||
<button
|
{#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:CREATE")}
|
||||||
on:click={() => {
|
<button
|
||||||
modal_open = true;
|
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"
|
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:w-auto sm:text-sm"
|
||||||
{$_("add-scan")}
|
>
|
||||||
</button>
|
{$_("add-scan")}
|
||||||
{/if}
|
</button>
|
||||||
</span>
|
{/if}
|
||||||
<ScansOverview bind:current_scans bind:addScans />
|
<ScansOverview bind:current_scans bind:addScans />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@@ -5,7 +5,7 @@
|
|||||||
|
|
||||||
<div class="text-center items-center justify-center">
|
<div class="text-center items-center justify-center">
|
||||||
<p class="mb-16 text-lg text-gray-500">
|
<p class="mb-16 text-lg text-gray-500">
|
||||||
<img class="m-auto" style="height:15rem" src={scans_empty} alt="" />
|
<img class="m-auto mt-2" style="height:15rem" src={scans_empty} alt="" />
|
||||||
<span class="font-bold">{$_("there-are-no-scans-yet")}</span><br />
|
<span class="font-bold">{$_("there-are-no-scans-yet")}</span><br />
|
||||||
<span>{$_("add-your-fist-scan")}</span>
|
<span>{$_("add-your-fist-scan")}</span>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -220,7 +220,7 @@
|
|||||||
{#if selected.length > 0}
|
{#if selected.length > 0}
|
||||||
<button
|
<button
|
||||||
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 inline-flex"
|
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:w-auto sm:text-sm inline-flex"
|
||||||
id="options-menu"
|
id="options-menu"
|
||||||
on:click={async () => {
|
on:click={async () => {
|
||||||
const prom = [];
|
const prom = [];
|
||||||
|
|||||||
@@ -133,7 +133,7 @@
|
|||||||
class="block text-sm font-medium text-gray-700">Track</label
|
class="block text-sm font-medium text-gray-700">Track</label
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
itemFilter={(label, filterText, option) =>
|
itemFilter={(label, filterText, option) =>
|
||||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
option.value.id
|
option.value.id
|
||||||
@@ -161,11 +161,11 @@
|
|||||||
bind:value={description}
|
bind:value={description}
|
||||||
type="text"
|
type="text"
|
||||||
name="description"
|
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"
|
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-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
<label for="enabled" class="font-medium text-gray-700"
|
<label for="enabled" class="font-semibold text-gray-700"
|
||||||
>{$_("enabled_large")}</label
|
>{$_("enabled_large")}</label
|
||||||
>
|
>
|
||||||
<br />
|
<br />
|
||||||
|
|||||||
@@ -1,200 +1,199 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
|
import { tick } from "svelte";
|
||||||
|
import bwipjs from "bwip-js";
|
||||||
|
import toast from "svelte-french-toast";
|
||||||
|
|
||||||
import { tick, createEventDispatcher } from "svelte";
|
export let copy_modal_open;
|
||||||
import bwipjs from "bwip-js";
|
export let new_station;
|
||||||
|
let valueCopy = null;
|
||||||
|
let areaDom;
|
||||||
|
let copied = false;
|
||||||
|
$: is_qrcode = false;
|
||||||
|
$: barcode = textToBase64Barcode(new_station.key, is_qrcode);
|
||||||
|
|
||||||
export let copy_modal_open;
|
function close() {
|
||||||
export let new_station;
|
copy_modal_open = false;
|
||||||
const dispatch = createEventDispatcher();
|
}
|
||||||
let valueCopy = null;
|
async function copy() {
|
||||||
let areaDom;
|
valueCopy = new_station.key;
|
||||||
let copied = false;
|
await tick();
|
||||||
$: is_qrcode = false;
|
areaDom.focus();
|
||||||
$: barcode = textToBase64Barcode(new_station.key, is_qrcode);
|
areaDom.select();
|
||||||
|
try {
|
||||||
|
const successful = document.execCommand("copy");
|
||||||
|
if (!successful) {
|
||||||
|
throw new Error();
|
||||||
|
}
|
||||||
|
toast($_("copied-token-to-clipboard"));
|
||||||
|
copied = true;
|
||||||
|
} catch (err) {
|
||||||
|
toast.Error($_("error-whyile-copying-to-clipboard"));
|
||||||
|
}
|
||||||
|
// we can notify by event or storage about copy status
|
||||||
|
valueCopy = null;
|
||||||
|
}
|
||||||
|
|
||||||
function close() {
|
function textToBase64Barcode(text, is_qrcode) {
|
||||||
copy_modal_open = false;
|
const canvas = document.createElement("canvas");
|
||||||
}
|
let bcid = "code128";
|
||||||
async function copy() {
|
if (is_qrcode) {
|
||||||
valueCopy = new_station.key;
|
bcid = "qrcode";
|
||||||
await tick();
|
}
|
||||||
areaDom.focus();
|
let codeconfig = {
|
||||||
areaDom.select();
|
bcid,
|
||||||
try {
|
text: `${text}`,
|
||||||
const successful = document.execCommand("copy");
|
scale: 4,
|
||||||
if (!successful) {
|
includetext: true,
|
||||||
throw new Error();
|
textxalign: "center",
|
||||||
}
|
backgroundcolor: "ffffff",
|
||||||
toast($_("copied-token-to-clipboard"));
|
};
|
||||||
copied = true;
|
if (bcid == "code128") {
|
||||||
} catch (err) {
|
codeconfig.height = 10;
|
||||||
toast.Error($_("error-whyile-copying-to-clipboard"));
|
}
|
||||||
}
|
bwipjs.toCanvas(canvas, codeconfig);
|
||||||
// we can notify by event or storage about copy status
|
return canvas.toDataURL("image/png");
|
||||||
valueCopy = null;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
function textToBase64Barcode(text, is_qrcode) {
|
|
||||||
const canvas = document.createElement("canvas");
|
|
||||||
let bcid = "code128";
|
|
||||||
if (is_qrcode) {
|
|
||||||
bcid = "qrcode";
|
|
||||||
}
|
|
||||||
let codeconfig = {
|
|
||||||
bcid,
|
|
||||||
text: `${text}`,
|
|
||||||
scale: 4,
|
|
||||||
includetext: true,
|
|
||||||
textxalign: "center",
|
|
||||||
backgroundcolor: "ffffff",
|
|
||||||
};
|
|
||||||
if (bcid == "code128") {
|
|
||||||
codeconfig.height = 10;
|
|
||||||
}
|
|
||||||
bwipjs.toCanvas(canvas, codeconfig);
|
|
||||||
return canvas.toDataURL("image/png");
|
|
||||||
}
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if copy_modal_open}
|
{#if copy_modal_open}
|
||||||
{#if valueCopy != null}
|
{#if valueCopy != null}
|
||||||
<textarea bind:this={areaDom}>{valueCopy}</textarea>
|
<textarea bind:this={areaDom}>{valueCopy}</textarea>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="fixed z-10 inset-0 overflow-y-auto">
|
<div class="fixed z-10 inset-0 overflow-y-auto">
|
||||||
<div
|
<div
|
||||||
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
class="flex items-end justify-center min-h-screen pt-4 px-4 pb-20 text-center sm:block sm:p-0"
|
||||||
>
|
>
|
||||||
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
<div class="fixed inset-0 transition-opacity" aria-hidden="true">
|
||||||
<div
|
<div
|
||||||
class="absolute inset-0 bg-gray-500 opacity-75"
|
class="absolute inset-0 bg-gray-500 opacity-75"
|
||||||
data-id="modal_backdrop"
|
data-id="modal_backdrop"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<span
|
<span
|
||||||
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
class="hidden sm:inline-block sm:align-middle sm:h-screen"
|
||||||
aria-hidden="true">​</span
|
aria-hidden="true">​</span
|
||||||
>
|
>
|
||||||
<div
|
<div
|
||||||
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
class="inline-block align-bottom bg-white rounded-lg text-left overflow-hidden shadow-xl transform transition-all sm:my-8 sm:align-middle sm:max-w-lg sm:w-full"
|
||||||
role="dialog"
|
role="dialog"
|
||||||
aria-modal="true"
|
aria-modal="true"
|
||||||
aria-labelledby="modal-headline"
|
aria-labelledby="modal-headline"
|
||||||
>
|
>
|
||||||
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
<div class="bg-white px-4 pt-5 pb-4 sm:p-6 sm:pb-4">
|
||||||
<div class="sm:flex sm:items-start">
|
<div class="sm:flex sm:items-start">
|
||||||
<div
|
<div
|
||||||
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
class="mx-auto flex-shrink-0 flex items-center justify-center h-12 w-12 rounded-full bg-blue-100 sm:mx-0 sm:h-10 sm:w-10"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
class="h-6 w-6 text-blue-600"
|
class="h-6 w-6 text-blue-600"
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path
|
<path
|
||||||
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z"
|
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z"
|
||||||
/></svg
|
/></svg
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
<div class="mt-3 text-center sm:mt-0 sm:ml-4 sm:text-left">
|
||||||
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
<h3 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
{$_("token")}
|
{$_("token")}
|
||||||
</h3>
|
</h3>
|
||||||
<div class="mt-2 mb-6">
|
<div class="mt-2 mb-6">
|
||||||
<p class="text-sm text-gray-500">
|
<p class="text-sm text-gray-500">
|
||||||
{$_(
|
{$_(
|
||||||
"the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again"
|
"the-scanstations-api-token-will-only-get-displayed-once-you-wont-be-able-to-change-or-view-it-again"
|
||||||
)}
|
)}
|
||||||
<br />
|
<br />
|
||||||
{$_("please-copy-the-token-and-store-it-somewhere-save")}
|
{$_("please-copy-the-token-and-store-it-somewhere-save")}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
<div class="mt-2 mb-6">
|
<div class="mt-2 mb-6">
|
||||||
<label
|
<label
|
||||||
for="token"
|
for="token"
|
||||||
class="block text-sm font-medium text-gray-700"
|
class="block text-sm font-medium text-gray-700"
|
||||||
>{$_("token")}</label
|
>{$_("token")}</label
|
||||||
>
|
>
|
||||||
<button on:click={copy} class="inline-flex">
|
<button on:click={copy} class="inline-flex">
|
||||||
<p
|
<p
|
||||||
name="token"
|
name="token"
|
||||||
class:bg-green-200={copied}
|
class:bg-green-200={copied}
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 p-2"
|
||||||
>
|
>
|
||||||
{new_station.key}
|
{new_station.key}
|
||||||
</p>
|
</p>
|
||||||
<div
|
<div
|
||||||
class="bg-gray-200 border-gray-300 border-t border-b border-r text-black rounded-r-md sm:text-sm p-2 mt-1 cursor-pointer"
|
class="bg-gray-200 border-gray-300 border-t border-b border-r text-black rounded-r-md sm:text-sm p-2 mt-1 cursor-pointer"
|
||||||
>
|
>
|
||||||
<svg
|
<svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
viewBox="0 0 24 24"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
><path fill="none" d="M0 0h24v24H0z" />
|
||||||
<path
|
<path
|
||||||
fill="currentColor"
|
fill="currentColor"
|
||||||
d="M7 4V2h10v2h3l1 1v16a1 1 0 01-1 1H4a1 1 0 01-1-1V5l1-1h3zm0 2H5v14h14V6h-2v2H7V6zm2-2v2h6V4H9z"
|
d="M7 4V2h10v2h3l1 1v16a1 1 0 01-1 1H4a1 1 0 01-1-1V5l1-1h3zm0 2H5v14h14V6h-2v2H7V6zm2-2v2h6V4H9z"
|
||||||
/></svg
|
/></svg
|
||||||
>
|
>
|
||||||
</div>
|
</div>
|
||||||
</button>
|
</button>
|
||||||
<p class="text-gray-500 text-xs">
|
<p class="text-gray-500 text-xs">
|
||||||
{$_("click-to-copy-token-to-clipboard")}
|
{$_("click-to-copy-token-to-clipboard")}
|
||||||
</p>
|
</p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mx-auto text-center items-center">
|
<div class="mx-auto text-center items-center">
|
||||||
<h2 class="text-lg leading-6 font-medium text-gray-900">
|
<h2 class="text-lg leading-6 font-medium text-gray-900">
|
||||||
{$_("config-codes")}
|
{$_("config-codes")}
|
||||||
</h2>
|
</h2>
|
||||||
<span class="flex items-center text-center">
|
<span class="flex items-center text-center">
|
||||||
<p class="text-md text-gray-900 mr-3">Format:</p>
|
<p class="text-md text-gray-900 mr-3">Format:</p>
|
||||||
<label for="codeswitch" class="text-md text-gray-900 mr-3"
|
<label for="codeswitch" class="text-md text-gray-900 mr-3"
|
||||||
>Code128</label
|
>Code128</label
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
id="codeswitch"
|
id="codeswitch"
|
||||||
type="checkbox"
|
type="checkbox"
|
||||||
bind:checked={is_qrcode}
|
bind:checked={is_qrcode}
|
||||||
class="relative shrink-0 w-[3.25rem] h-7 bg-gray-100 checked:bg-none checked:bg-blue-600 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 ring-1 ring-transparent focus:border-blue-600 focus:ring-blue-600 ring-offset-white focus:outline-none appearance-none before:inline-block before:w-6 before:h-6 before:bg-white checked:before:bg-blue-200 before:translate-x-0 checked:before:translate-x-full before:shadow before:rounded-full before:transform before:ring-0 before:transition before:ease-in-out before:duration-200"
|
class="relative shrink-0 w-[3.25rem] h-7 bg-gray-100 checked:bg-none checked:bg-blue-600 border-2 border-transparent rounded-full cursor-pointer transition-colors ease-in-out duration-200 ring-1 ring-transparent focus:border-blue-600 focus:ring-blue-600 ring-offset-white focus:outline-none appearance-none before:inline-block before:w-6 before:h-6 before:bg-white checked:before:bg-blue-200 before:translate-x-0 checked:before:translate-x-full before:shadow before:rounded-full before:transform before:ring-0 before:transition before:ease-in-out before:duration-200"
|
||||||
/>
|
/>
|
||||||
<label for="codeswitch" class="text-md text-gray-900 ml-3"
|
<label for="codeswitch" class="text-md text-gray-900 ml-3"
|
||||||
>QR-Code</label
|
>QR-Code</label
|
||||||
>
|
>
|
||||||
</span>
|
</span>
|
||||||
<h3 class="leading-6 font-medium text-gray-900">
|
<h3 class="leading-6 font-medium text-gray-900">
|
||||||
{$_("api-endpoint")}
|
{$_("api-endpoint")}
|
||||||
</h3>
|
</h3>
|
||||||
<img
|
<img
|
||||||
class:w-[50%]={is_qrcode}
|
class:w-[50%]={is_qrcode}
|
||||||
class:w-full={!is_qrcode}
|
class:w-full={!is_qrcode}
|
||||||
class="md:w-auto mb-2 mx-auto"
|
class="md:w-auto mb-2 mx-auto"
|
||||||
alt="Registrierungscode"
|
alt="Registrierungscode"
|
||||||
src={textToBase64Barcode(window.config.baseurl, is_qrcode)}
|
src={textToBase64Barcode(window.config.baseurl, is_qrcode)}
|
||||||
/>
|
/>
|
||||||
<h3 class="leading-6 font-medium text-gray-900">{$_("token")}</h3>
|
<h3 class="leading-6 font-medium text-gray-900">{$_("token")}</h3>
|
||||||
<img
|
<img
|
||||||
class:w-[50%]={is_qrcode}
|
class:w-[50%]={is_qrcode}
|
||||||
class:w-full={!is_qrcode}
|
class:w-full={!is_qrcode}
|
||||||
class="md:w-auto mb-2 mx-auto"
|
class="md:w-auto mb-2 mx-auto"
|
||||||
alt="Registrierungscode"
|
alt="Registrierungscode"
|
||||||
src={barcode}
|
src={barcode}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
<div class="bg-gray-50 px-4 py-3 sm:px-6 sm:flex sm:flex-row-reverse">
|
||||||
<button
|
<button
|
||||||
on:click={close}
|
on:click={close}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-green-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-green-500 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-red-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
>
|
>
|
||||||
{$_("yes-i-copied-the-token")}
|
{$_("yes-i-copied-the-token")}
|
||||||
</button>
|
</button>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1,204 +1,190 @@
|
|||||||
<script>
|
<script>
|
||||||
import { t, _ } from "svelte-i18n";
|
import { t, _ } from "svelte-i18n";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import { ScanStationService, TrackService } from "@odit/lfk-client-js";
|
import { ScanStationService, TrackService } from "@odit/lfk-client-js";
|
||||||
|
|
||||||
import PromiseError from "../base/PromiseError.svelte";
|
import PromiseError from "../base/PromiseError.svelte";
|
||||||
import ConfirmScanStationDeletion from "./ConfirmScanStationDeletion.svelte";
|
import ConfirmScanStationDeletion from "./ConfirmScanStationDeletion.svelte";
|
||||||
import Select from "svelte-select";
|
import Select from "svelte-select";
|
||||||
let data_loaded = false;
|
let data_loaded = false;
|
||||||
let modal_open;
|
let modal_open;
|
||||||
let delete_station;
|
let delete_station;
|
||||||
export let params;
|
export let params;
|
||||||
$: delete_triggered = false;
|
$: delete_triggered = false;
|
||||||
$: original_data = {};
|
$: original_data = {};
|
||||||
$: editable = {};
|
$: editable = {};
|
||||||
$: tracks = [];
|
$: tracks = [];
|
||||||
$: track = {};
|
$: track = {};
|
||||||
$: changes_performed = !(
|
$: changes_performed = !(
|
||||||
JSON.stringify(original_data) === JSON.stringify(editable)
|
JSON.stringify(original_data) === JSON.stringify(editable)
|
||||||
);
|
);
|
||||||
$: save_enabled = changes_performed;
|
$: save_enabled = changes_performed;
|
||||||
const promise = ScanStationService.scanStationControllerGetOne(
|
const promise = ScanStationService.scanStationControllerGetOne(
|
||||||
params.stationid
|
params.stationid
|
||||||
).then((data) => {
|
).then((data) => {
|
||||||
data_loaded = true;
|
data_loaded = true;
|
||||||
data.track = data.track.id;
|
data.track = data.track.id;
|
||||||
original_data = Object.assign(original_data, data);
|
original_data = Object.assign(original_data, data);
|
||||||
editable = Object.assign(editable, original_data);
|
editable = Object.assign(editable, original_data);
|
||||||
TrackService.trackControllerGetAll().then((val) => {
|
TrackService.trackControllerGetAll().then((val) => {
|
||||||
tracks = val.map((t) => {
|
tracks = val.map((t) => {
|
||||||
return { label: t.name || `#{t.id}`, value: t };
|
return { label: t.name || `#{t.id}`, value: t };
|
||||||
});
|
});
|
||||||
track = tracks.find((t) => t.value.id == editable.track);
|
track = tracks.find((t) => t.value.id == editable.track);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
function submit() {
|
function submit() {
|
||||||
if (data_loaded === true && save_enabled) {
|
if (data_loaded === true && save_enabled) {
|
||||||
toast($_("station-is-being-updated"));
|
toast($_("station-is-being-updated"));
|
||||||
ScanStationService.scanStationControllerPut(original_data.id, editable)
|
ScanStationService.scanStationControllerPut(original_data.id, editable)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
Object.assign(original_data, editable);
|
Object.assign(original_data, editable);
|
||||||
original_data = original_data;
|
original_data = original_data;
|
||||||
toast.success($_("updated-station"));
|
toast.success($_("updated-station"));
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
} else {
|
} else {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function deleteStation() {
|
function deleteStation() {
|
||||||
ScanStationService.scanStationControllerRemove(original_data.id, false)
|
ScanStationService.scanStationControllerRemove(original_data.id, false)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
toast($_("station-deleted"));
|
toast($_("station-deleted"));
|
||||||
location.replace("./");
|
location.replace("./");
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
modal_open = true;
|
modal_open = true;
|
||||||
delete_station = original_data;
|
delete_station = original_data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ConfirmScanStationDeletion bind:modal_open bind:delete_station />
|
<ConfirmScanStationDeletion bind:modal_open bind:delete_station />
|
||||||
{#await promise}
|
{#await promise}
|
||||||
{$_("loading-station-details")}
|
{$_("loading-station-details")}
|
||||||
{: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">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<nav class="w-full flex">
|
<nav class="w-full flex">
|
||||||
<ol class="list-none flex flex-row items-center justify-start">
|
<ol class="list-none flex flex-row items-center justify-start">
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
<svg
|
<a class="mr-2" href="./"
|
||||||
fill="currentColor"
|
><svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
width="24"
|
||||||
width="24"
|
height="24"
|
||||||
height="24"
|
viewBox="0 0 24 24"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
fill="none"
|
||||||
<path
|
stroke="currentColor"
|
||||||
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z"
|
stroke-width="2"
|
||||||
/></svg
|
stroke-linecap="round"
|
||||||
>
|
stroke-linejoin="round"
|
||||||
</li>
|
class="inline-block"
|
||||||
<li class="flex items-center ml-2">
|
><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg
|
||||||
<a class="mr-2" href="./">{$_("scanstation")}</a><svg
|
>
|
||||||
stroke="currentColor"
|
{$_("scanstations")}</a
|
||||||
fill="none"
|
>
|
||||||
stroke-width="2"
|
</li>
|
||||||
viewBox="0 0 24 24"
|
</ol>
|
||||||
stroke-linecap="round"
|
</nav>
|
||||||
stroke-linejoin="round"
|
</div>
|
||||||
class="h-3 w-3 mr-2 stroke-current"
|
</div>
|
||||||
height="1em"
|
<div class="mb-4 text-3xl font-extrabold leading-tight">
|
||||||
width="1em"
|
{$_("scanstation")} #{original_data.id}<br>"{original_data.description}"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<div data-id="stations_actions_${editable.id}">
|
||||||
><line x1="5" y1="12" x2="19" y2="12" />
|
{#if store.state.jwtinfo.userdetails.permissions.includes("STATION:DELETE")}
|
||||||
<polyline points="12 5 19 12 12 19" /></svg
|
{#if delete_triggered}
|
||||||
>
|
<button
|
||||||
</li>
|
on:click={deleteStation}
|
||||||
<li class="flex items-center">
|
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:w-auto sm:text-sm"
|
||||||
<span class="mr-2">#{original_data.id}</span>
|
>{$_("confirm-deletion")}</button
|
||||||
</li>
|
>
|
||||||
</ol>
|
<button
|
||||||
</nav>
|
on:click={() => {
|
||||||
</div>
|
delete_triggered = !delete_triggered;
|
||||||
</div>
|
}}
|
||||||
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
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"
|
||||||
#{original_data.id}
|
>{$_("cancel")}</button
|
||||||
<span data-id="stations_actions_${editable.id}">
|
>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("STATION:DELETE")}
|
{/if}
|
||||||
{#if delete_triggered}
|
{#if !delete_triggered}
|
||||||
<button
|
<button
|
||||||
on:click={deleteStation}
|
on:click={() => {
|
||||||
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_triggered = true;
|
||||||
>{$_("confirm-deletion")}</button
|
}}
|
||||||
>
|
type="button"
|
||||||
<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:w-auto sm:text-sm"
|
||||||
on:click={() => {
|
>{$_("delete-station")}</button
|
||||||
delete_triggered = !delete_triggered;
|
>
|
||||||
}}
|
{/if}
|
||||||
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"
|
{/if}
|
||||||
>{$_("cancel")}</button
|
{#if !delete_triggered}
|
||||||
>
|
<button
|
||||||
{/if}
|
disabled={!save_enabled}
|
||||||
{#if !delete_triggered}
|
class:opacity-50={!save_enabled}
|
||||||
<button
|
type="button"
|
||||||
on:click={() => {
|
on:click={submit}
|
||||||
delete_triggered = true;
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
}}
|
>{$_("save-changes")}</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"
|
{/if}
|
||||||
>{$_("delete-station")}</button
|
</div>
|
||||||
>
|
</div>
|
||||||
{/if}
|
<!-- -->
|
||||||
{/if}
|
<div class="mt-2 text-sm w-full">
|
||||||
{#if !delete_triggered}
|
<label for="track" class="block text-sm font-semibold text-gray-700"
|
||||||
<button
|
>Track</label
|
||||||
disabled={!save_enabled}
|
>
|
||||||
class:opacity-50={!save_enabled}
|
<Select
|
||||||
type="button"
|
containerClasses="rounded-l-md 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-neutral-800 rounded-md p-2"
|
||||||
on:click={submit}
|
itemFilter={(label, filterText, option) =>
|
||||||
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"
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
>{$_("save-changes")}</button
|
option.value.id.toString().startsWith(filterText.toLowerCase())}
|
||||||
>
|
items={tracks}
|
||||||
{/if}
|
showChevron={true}
|
||||||
</span>
|
placeholder="Search for a track (by name or id)."
|
||||||
</div>
|
noOptionsMessage="No track found"
|
||||||
<!-- -->
|
bind:selectedValue={track}
|
||||||
<div class="text-sm w-full">
|
on:select={(selectedValue) =>
|
||||||
<label for="track" class="block text-sm font-medium text-gray-700"
|
(editable.track = selectedValue.detail.value.id)}
|
||||||
>Track</label
|
on:clear={() => (track = null)}
|
||||||
>
|
/>
|
||||||
<Select
|
</div>
|
||||||
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"
|
<div class="mt-2 text-sm w-full">
|
||||||
itemFilter={(label, filterText, option) =>
|
<label for="description" class="font-semibold text-gray-700"
|
||||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
>{$_("description")}</label
|
||||||
option.value.id.toString().startsWith(filterText.toLowerCase())}
|
>
|
||||||
items={tracks}
|
<input
|
||||||
showChevron={true}
|
autocomplete="off"
|
||||||
placeholder="Search for a track (by name or id)."
|
placeholder={$_("description")}
|
||||||
noOptionsMessage="No track found"
|
type="text"
|
||||||
bind:selectedValue={track}
|
bind:value={editable.description}
|
||||||
on:select={(selectedValue) =>
|
name="description"
|
||||||
(editable.track = selectedValue.detail.value.id)}
|
class="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-neutral-800 rounded-md p-2"
|
||||||
on:clear={() => (track = null)}
|
/>
|
||||||
/>
|
</div>
|
||||||
</div>
|
<div class="mt-2 text-sm w-full">
|
||||||
<div class="text-sm w-full">
|
<label for="enabled" class="font-semibold text-gray-700"
|
||||||
<label for="description" class="font-medium text-gray-700"
|
>{$_("enabled")}</label
|
||||||
>{$_("description")}</label
|
>
|
||||||
>
|
<br />
|
||||||
<input
|
<p class="text-gray-500">
|
||||||
autocomplete="off"
|
<input
|
||||||
placeholder={$_("description")}
|
id="enabled"
|
||||||
type="text"
|
on:change={() => {
|
||||||
bind:value={editable.description}
|
editable.enabled = !editable.enabled;
|
||||||
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"
|
name="enabled"
|
||||||
/>
|
type="checkbox"
|
||||||
</div>
|
checked={editable.enabled}
|
||||||
<div class="text-sm w-full">
|
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
<label for="enabled" class="ml-1 font-medium text-gray-700"
|
/>
|
||||||
>{$_("enabled")}</label
|
{$_("this-scanstation-is")}
|
||||||
>
|
{#if editable.enabled}{$_("enabled")}{:else}{$_("disabled")}{/if}
|
||||||
<br />
|
</p>
|
||||||
<p class="text-gray-500">
|
</div>
|
||||||
<input
|
</section>
|
||||||
id="enabled"
|
|
||||||
on:change={() => {
|
|
||||||
editable.enabled = !editable.enabled;
|
|
||||||
}}
|
|
||||||
name="enabled"
|
|
||||||
type="checkbox"
|
|
||||||
checked={editable.enabled}
|
|
||||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
|
||||||
/>
|
|
||||||
{$_("this-scanstation-is")}
|
|
||||||
{#if editable.enabled}{$_("enabled")}{:else}{$_("disabled")}{/if}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{:catch error}
|
{:catch error}
|
||||||
<PromiseError {error} />
|
<PromiseError {error} />
|
||||||
{/await}
|
{/await}
|
||||||
@@ -1,44 +1,229 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import AddScanStationModal from "./AddScanStationModal.svelte";
|
import { ScanStationService } from "@odit/lfk-client-js";
|
||||||
import CopyScanStationTokenModal from "./CopyScanStationTokenModal.svelte";
|
import AddScanStationModal from "./AddScanStationModal.svelte";
|
||||||
import ScanStationsOverview from "./ScanStationsOverview.svelte";
|
import CopyScanStationTokenModal from "./CopyScanStationTokenModal.svelte";
|
||||||
export let modal_open = false;
|
import ScanStationsEmptyState from "./ScanStationsEmptyState.svelte";
|
||||||
export let copy_modal_open = false;
|
import ConfirmScanStationDeletion from "./ConfirmScanStationDeletion.svelte";
|
||||||
export let new_station = {};
|
import toast from "svelte-french-toast";
|
||||||
let current_stations = [];
|
//
|
||||||
|
export let modal_open = false;
|
||||||
|
export let copy_modal_open = false;
|
||||||
|
export let new_station = {};
|
||||||
|
//
|
||||||
|
const promise = ScanStationService.scanStationControllerGetAll().then(
|
||||||
|
(result) => {
|
||||||
|
current_stations = result;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$: searchvalue = "";
|
||||||
|
$: active_deletes = [];
|
||||||
|
let delete_station = {};
|
||||||
|
let current_stations = [];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_("scanstations")}
|
{$_("scanstations")}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("STATION:CREATE")}
|
</h4>
|
||||||
<button
|
{#if store.state.jwtinfo.userdetails.permissions.includes("STATION:CREATE")}
|
||||||
on:click={() => {
|
<button
|
||||||
modal_open = true;
|
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"
|
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:w-auto sm:text-sm"
|
||||||
{$_("create-a-new-scanstation")}
|
>
|
||||||
</button>
|
{$_("create-a-new-scanstation")}
|
||||||
{/if}
|
</button>
|
||||||
</span>
|
{/if}
|
||||||
<ScanStationsOverview
|
<ConfirmScanStationDeletion
|
||||||
bind:current_stations
|
on:cancelDelete={(event) => {
|
||||||
bind:modal_open
|
modal_open = false;
|
||||||
bind:new_station
|
active_deletes[event.detail.id] = false;
|
||||||
bind:copy_modal_open
|
}}
|
||||||
/>
|
bind:modal_open
|
||||||
|
bind:delete_station
|
||||||
|
/>
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes("STATION: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">{$_("scanstations-are-being-loaded")}</p>
|
||||||
|
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
||||||
|
</div>
|
||||||
|
{:then}
|
||||||
|
{#if current_stations.length === 0}
|
||||||
|
<ScanStationsEmptyState />
|
||||||
|
{:else}
|
||||||
|
<input
|
||||||
|
type="search"
|
||||||
|
bind:value={searchvalue}
|
||||||
|
placeholder={$_("datatable.search")}
|
||||||
|
aria-label={$_("datatable.search")}
|
||||||
|
class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border"
|
||||||
|
/>
|
||||||
|
<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 class="odd:bg-white even:bg-gray-100">
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||||
|
>
|
||||||
|
{$_("track")}
|
||||||
|
</th>
|
||||||
|
<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"
|
||||||
|
>
|
||||||
|
{$_("status")}
|
||||||
|
</th>
|
||||||
|
<th scope="col" class="relative px-6 py-3">
|
||||||
|
<span class="sr-only">{$_("action")}</span>
|
||||||
|
</th>
|
||||||
|
</tr>
|
||||||
|
</thead>
|
||||||
|
<tbody class="divide-y divide-gray-200">
|
||||||
|
{#each current_stations as s}
|
||||||
|
{#if Object.values(s)
|
||||||
|
.toString()
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(searchvalue)}
|
||||||
|
<tr
|
||||||
|
class="odd:bg-white even:bg-gray-100"
|
||||||
|
data-rowid="station_{s.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">
|
||||||
|
<a
|
||||||
|
href="../tracks"
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800 border border-current"
|
||||||
|
>
|
||||||
|
{s.track.name || s.track.distance + "m"}</a
|
||||||
|
>
|
||||||
|
</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">
|
||||||
|
{s.description}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
|
<div class="flex items-center">
|
||||||
|
{#if s.enabled}
|
||||||
|
<span
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-green-100 text-green-800"
|
||||||
|
>{$_("active")}</span
|
||||||
|
>
|
||||||
|
{:else}
|
||||||
|
<span
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border border-current bg-red-100 text-red-800"
|
||||||
|
>{$_("inactive")}</span
|
||||||
|
>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
{#if active_deletes[s.id] === true}
|
||||||
|
<td
|
||||||
|
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
active_deletes[s.id] = false;
|
||||||
|
}}
|
||||||
|
tabindex="0"
|
||||||
|
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer"
|
||||||
|
>{$_("cancel-delete")}</button
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
ScanStationService.scanStationControllerRemove(
|
||||||
|
s.id,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
.then((resp) => {
|
||||||
|
current_stations = current_stations.filter(
|
||||||
|
(obj) => obj.id !== s.id
|
||||||
|
);
|
||||||
|
toast($_("station-deleted"));
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
modal_open = true;
|
||||||
|
delete_station = s;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
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="/scanstations/{s.id}"
|
||||||
|
class="text-indigo-600 hover:text-indigo-900"
|
||||||
|
>{$_("details")}</a
|
||||||
|
>
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes("STATION:DELETE")}
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
active_deletes[s.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}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("STATION:CREATE")}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("STATION:CREATE")}
|
||||||
<AddScanStationModal
|
<AddScanStationModal
|
||||||
bind:modal_open
|
bind:modal_open
|
||||||
bind:current_stations
|
bind:current_stations
|
||||||
bind:new_station
|
bind:new_station
|
||||||
bind:copy_modal_open
|
bind:copy_modal_open
|
||||||
/>
|
/>
|
||||||
<CopyScanStationTokenModal bind:copy_modal_open bind:new_station />
|
<CopyScanStationTokenModal bind:copy_modal_open bind:new_station />
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1,195 +0,0 @@
|
|||||||
<script>
|
|
||||||
import { _ } from "svelte-i18n";
|
|
||||||
import { ScanStationService } from "@odit/lfk-client-js";
|
|
||||||
const promise = ScanStationService.scanStationControllerGetAll().then(
|
|
||||||
(result) => {
|
|
||||||
current_stations = result;
|
|
||||||
}
|
|
||||||
);
|
|
||||||
import store from "../../store";
|
|
||||||
import ScanStationsEmptyState from "./ScanStationsEmptyState.svelte";
|
|
||||||
import ConfirmScanStationDeletion from "./ConfirmScanStationDeletion.svelte";
|
|
||||||
import toast from "svelte-french-toast";
|
|
||||||
$: searchvalue = "";
|
|
||||||
$: active_deletes = [];
|
|
||||||
let delete_station = {};
|
|
||||||
let modal_open = false;
|
|
||||||
export let current_stations = [];
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<ConfirmScanStationDeletion
|
|
||||||
on:cancelDelete={(event) => {
|
|
||||||
modal_open = false;
|
|
||||||
active_deletes[event.detail.id] = false;
|
|
||||||
}}
|
|
||||||
bind:modal_open
|
|
||||||
bind:delete_station
|
|
||||||
/>
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("STATION: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">{$_("scanstations-are-being-loaded")}</p>
|
|
||||||
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
|
||||||
</div>
|
|
||||||
{:then}
|
|
||||||
{#if current_stations.length === 0}
|
|
||||||
<ScanStationsEmptyState />
|
|
||||||
{:else}
|
|
||||||
<input
|
|
||||||
type="search"
|
|
||||||
bind:value={searchvalue}
|
|
||||||
placeholder={$_("datatable.search")}
|
|
||||||
aria-label={$_("datatable.search")}
|
|
||||||
class="mb-4"
|
|
||||||
/>
|
|
||||||
<div
|
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
|
|
||||||
>
|
|
||||||
<table class="divide-y divide-gray-200 w-full">
|
|
||||||
<thead class="bg-gray-50">
|
|
||||||
<tr class="odd:bg-white even:bg-gray-100">
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
|
||||||
>
|
|
||||||
{$_("track")}
|
|
||||||
</th>
|
|
||||||
<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"
|
|
||||||
>
|
|
||||||
{$_("status")}
|
|
||||||
</th>
|
|
||||||
<th scope="col" class="relative px-6 py-3">
|
|
||||||
<span class="sr-only">{$_("action")}</span>
|
|
||||||
</th>
|
|
||||||
</tr>
|
|
||||||
</thead>
|
|
||||||
<tbody class="divide-y divide-gray-200">
|
|
||||||
{#each current_stations as s}
|
|
||||||
{#if Object.values(s)
|
|
||||||
.toString()
|
|
||||||
.toLowerCase()
|
|
||||||
.includes(searchvalue)}
|
|
||||||
<tr
|
|
||||||
class="odd:bg-white even:bg-gray-100"
|
|
||||||
data-rowid="station_{s.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">
|
|
||||||
<a
|
|
||||||
href="../tracks"
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
|
||||||
>
|
|
||||||
{s.track.name || s.track.distance + "m"}</a
|
|
||||||
>
|
|
||||||
</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">
|
|
||||||
{s.description}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<div class="flex items-center">
|
|
||||||
{#if s.enabled}
|
|
||||||
<span
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"
|
|
||||||
>{$_("active")}</span
|
|
||||||
>
|
|
||||||
{:else}
|
|
||||||
<span
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800"
|
|
||||||
>{$_("inactive")}</span
|
|
||||||
>
|
|
||||||
{/if}
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
{#if active_deletes[s.id] === true}
|
|
||||||
<td
|
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[s.id] = false;
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer"
|
|
||||||
>{$_("cancel-delete")}</button
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
ScanStationService.scanStationControllerRemove(
|
|
||||||
s.id,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
.then((resp) => {
|
|
||||||
current_stations = current_stations.filter(
|
|
||||||
(obj) => obj.id !== s.id
|
|
||||||
);
|
|
||||||
toast($_("station-deleted"));
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
modal_open = true;
|
|
||||||
delete_station = s;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
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="/scanstations/{s.id}"
|
|
||||||
class="text-indigo-600 hover:text-indigo-900"
|
|
||||||
>{$_("details")}</a
|
|
||||||
>
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("STATION:DELETE")}
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[s.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}
|
|
||||||
@@ -2,6 +2,7 @@
|
|||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import isEmail from "validator/es/lib/isEmail";
|
import isEmail from "validator/es/lib/isEmail";
|
||||||
import { MeService } from "@odit/lfk-client-js";
|
import { MeService } from "@odit/lfk-client-js";
|
||||||
|
import toast from 'svelte-french-toast'
|
||||||
|
|
||||||
import ConfirmProfileDeletion from "./ConfirmProfileDeletion.svelte";
|
import ConfirmProfileDeletion from "./ConfirmProfileDeletion.svelte";
|
||||||
import PasswordStrength, {
|
import PasswordStrength, {
|
||||||
@@ -61,21 +62,13 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ConfirmProfileDeletion bind:modal_open bind:delete_triggered />
|
<ConfirmProfileDeletion bind:modal_open bind:delete_triggered />
|
||||||
<div class="pt-12 px-4 sm:px-6 lg:px-8 lg:pt-20 bg-gray-900 pb-12">
|
|
||||||
<div class="text-center mb-8">
|
|
||||||
<h1
|
|
||||||
class="mt-9 font-display text-4xl leading-none font-semibold text-white sm:text-5xl lg:text-6xl"
|
|
||||||
>
|
|
||||||
🔨<br />{$_("settings")}
|
|
||||||
</h1>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
<div class="pt-0 pb-16 bg-gray-50 overflow-hidden lg:pt-12 lg:py-24">
|
<div class="pt-0 pb-16 bg-gray-50 overflow-hidden lg:pt-12 lg:py-24">
|
||||||
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
<div class="max-w-7xl mx-auto py-6 px-4 sm:px-6 lg:px-8">
|
||||||
|
<span class="text-3xl font-bold">{$_("settings")}</span>
|
||||||
<div>
|
<div>
|
||||||
<div class="md:grid md:grid-cols-3 md:gap-6">
|
<div class="md:grid md:grid-cols-3 md:gap-6">
|
||||||
<div class="md:col-span-1">
|
<div class="md:col-span-1">
|
||||||
<div class="px-4 sm:px-0">
|
<div class="sm:px-0">
|
||||||
<h3 class="text-lg font-medium leading-6 text-gray-900">
|
<h3 class="text-lg font-medium leading-6 text-gray-900">
|
||||||
{$_("profile")}
|
{$_("profile")}
|
||||||
</h3>
|
</h3>
|
||||||
@@ -90,8 +83,8 @@
|
|||||||
<div class="mt-5 md:mt-0 md:col-span-2">
|
<div class="mt-5 md:mt-0 md:col-span-2">
|
||||||
<div class="shadow sm:rounded-md sm:overflow-hidden">
|
<div class="shadow sm:rounded-md sm:overflow-hidden">
|
||||||
<div class="px-4 py-5 bg-white space-y-6 sm:p-6">
|
<div class="px-4 py-5 bg-white space-y-6 sm:p-6">
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full mt-2">
|
||||||
<label for="username" class="font-medium text-gray-700"
|
<label for="username" class="font-semibold text-gray-700"
|
||||||
>{$_("username")}</label
|
>{$_("username")}</label
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
@@ -100,11 +93,11 @@
|
|||||||
type="text"
|
type="text"
|
||||||
bind:value={editable.username}
|
bind:value={editable.username}
|
||||||
name="username"
|
name="username"
|
||||||
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-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full mt-2">
|
||||||
<label for="email" class="font-medium text-gray-700"
|
<label for="email" class="font-semibold text-gray-700"
|
||||||
>{$_("e-mail-adress")}</label
|
>{$_("e-mail-adress")}</label
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
@@ -113,7 +106,7 @@
|
|||||||
type="email"
|
type="email"
|
||||||
bind:value={editable.email}
|
bind:value={editable.email}
|
||||||
name="email"
|
name="email"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{#if !isEmail(editable.email)}
|
{#if !isEmail(editable.email)}
|
||||||
@@ -122,8 +115,8 @@
|
|||||||
>{$_("valid-email-is-required")}</span
|
>{$_("valid-email-is-required")}</span
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full mt-2">
|
||||||
<label for="firstname" class="font-medium text-gray-700"
|
<label for="firstname" class="font-semibold text-gray-700"
|
||||||
>{$_("first-name")}</label
|
>{$_("first-name")}</label
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
@@ -132,11 +125,11 @@
|
|||||||
type="text"
|
type="text"
|
||||||
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-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<!-- <div class="text-sm w-full">
|
<!-- <div class="text-sm w-full mt-2">
|
||||||
<label for="middlename" class="font-medium text-gray-700"
|
<label for="middlename" class="font-semibold text-gray-700"
|
||||||
>{$_("middle-name")}</label
|
>{$_("middle-name")}</label
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
@@ -145,11 +138,11 @@
|
|||||||
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-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div> -->
|
</div> -->
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full mt-2">
|
||||||
<label for="lastname" class="font-medium text-gray-700"
|
<label for="lastname" class="font-semibold text-gray-700"
|
||||||
>{$_("last-name")}</label
|
>{$_("last-name")}</label
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
@@ -158,7 +151,7 @@
|
|||||||
type="text"
|
type="text"
|
||||||
bind:value={editable.lastname}
|
bind:value={editable.lastname}
|
||||||
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-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
@@ -168,7 +161,7 @@
|
|||||||
disabled={!save_enabled}
|
disabled={!save_enabled}
|
||||||
class:opacity-50={!save_enabled}
|
class:opacity-50={!save_enabled}
|
||||||
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"
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
>
|
>
|
||||||
{$_("save-changes")}
|
{$_("save-changes")}
|
||||||
</button>
|
</button>
|
||||||
@@ -183,7 +176,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="md:grid md:grid-cols-3 md:gap-6">
|
<div class="md:grid md:grid-cols-3 md:gap-6">
|
||||||
<div class="md:col-span-1">
|
<div class="md:col-span-1">
|
||||||
<div class="px-4 sm:px-0">
|
<div class="sm:px-0">
|
||||||
<h3 class="text-lg font-medium leading-6 text-gray-900">
|
<h3 class="text-lg font-medium leading-6 text-gray-900">
|
||||||
{$_("password")}
|
{$_("password")}
|
||||||
</h3>
|
</h3>
|
||||||
@@ -198,7 +191,7 @@
|
|||||||
<div class="mt-5 md:mt-0 md:col-span-2">
|
<div class="mt-5 md:mt-0 md:col-span-2">
|
||||||
<div class="shadow sm:rounded-md sm:overflow-hidden">
|
<div class="shadow sm:rounded-md sm:overflow-hidden">
|
||||||
<div class="px-4 py-3 bg-gray-50 text-left sm:px-6">
|
<div class="px-4 py-3 bg-gray-50 text-left sm:px-6">
|
||||||
<label for="new_password" class="font-medium text-gray-700"
|
<label for="new_password" class="font-semibold text-gray-700"
|
||||||
>{$_("new-password")}</label
|
>{$_("new-password")}</label
|
||||||
>
|
>
|
||||||
<div class="-mt-px relative">
|
<div class="-mt-px relative">
|
||||||
@@ -211,7 +204,7 @@
|
|||||||
placeholder={$_("password")}
|
placeholder={$_("password")}
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<label for="new_password" class="font-medium text-gray-700"
|
<label for="new_password" class="font-semibold text-gray-700"
|
||||||
>{$_("confirm-the-new-password")}</label
|
>{$_("confirm-the-new-password")}</label
|
||||||
>
|
>
|
||||||
<div class="-mt-px relative">
|
<div class="-mt-px relative">
|
||||||
@@ -232,7 +225,7 @@
|
|||||||
disabled={!update_password_enabled}
|
disabled={!update_password_enabled}
|
||||||
class:opacity-50={!update_password_enabled}
|
class:opacity-50={!update_password_enabled}
|
||||||
on:click={changePassword}
|
on:click={changePassword}
|
||||||
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"
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
>
|
>
|
||||||
{$_("update-password")}
|
{$_("update-password")}
|
||||||
</button>
|
</button>
|
||||||
@@ -254,7 +247,7 @@
|
|||||||
<div>
|
<div>
|
||||||
<div class="md:grid md:grid-cols-3 md:gap-6">
|
<div class="md:grid md:grid-cols-3 md:gap-6">
|
||||||
<div class="md:col-span-1">
|
<div class="md:col-span-1">
|
||||||
<div class="px-4 sm:px-0">
|
<div class="sm:px-0">
|
||||||
<h3 class="text-lg font-medium leading-6 text-gray-900">
|
<h3 class="text-lg font-medium leading-6 text-gray-900">
|
||||||
{$_("danger-zone")}
|
{$_("danger-zone")}
|
||||||
</h3>
|
</h3>
|
||||||
|
|||||||
@@ -1,26 +1,26 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
|
|
||||||
export let detailsLink;
|
export let detailsLink = null;
|
||||||
export let detailsAction;
|
export let detailsAction = null;
|
||||||
export let deleteEnabled;
|
export let deleteEnabled;
|
||||||
export let deleteAction;
|
export let deleteAction;
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if detailsLink}
|
{#if detailsLink}
|
||||||
<a href={detailsLink} class="text-indigo-600 hover:text-indigo-900"
|
<a href={detailsLink} class="text-indigo-600 hover:text-indigo-900"
|
||||||
>{$_("details")}</a
|
>{$_("details")}</a
|
||||||
>
|
>
|
||||||
{:else if detailsAction}
|
{:else if detailsAction}
|
||||||
<button on:click={detailsAction} class="text-indigo-600 hover:text-indigo-900"
|
<button on:click={detailsAction} class="text-indigo-600 hover:text-indigo-900"
|
||||||
>{$_("details")}</button
|
>{$_("details")}</button
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
{#if deleteEnabled}
|
{#if deleteEnabled}
|
||||||
<button
|
<button
|
||||||
tabindex="0"
|
tabindex="0"
|
||||||
on:click={deleteAction}
|
on:click={deleteAction}
|
||||||
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
|
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
|
||||||
>{$_("delete")}</button
|
>{$_("delete")}</button
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -126,7 +126,7 @@
|
|||||||
bind:value={description}
|
bind:value={description}
|
||||||
type="text"
|
type="text"
|
||||||
name="description"
|
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"
|
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-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -5,14 +5,14 @@
|
|||||||
import { createEventDispatcher } from "svelte";
|
import { createEventDispatcher } from "svelte";
|
||||||
import toast from "svelte-french-toast";
|
import toast from "svelte-french-toast";
|
||||||
export let modal_open;
|
export let modal_open;
|
||||||
export let delete_station;
|
export let delete_client;
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
function cancelDelete() {
|
function cancelDelete() {
|
||||||
modal_open = false;
|
modal_open = false;
|
||||||
dispatch("cancelDelete", { id: delete_station.id });
|
dispatch("cancelDelete", { id: delete_client.id });
|
||||||
}
|
}
|
||||||
function deleteClient() {
|
function deleteClient() {
|
||||||
StatsClientService.statsClientControllerRemove(delete_station.id, true)
|
StatsClientService.statsClientControllerRemove(delete_client.id, true)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
toast($_("statsclient-deleted"));
|
toast($_("statsclient-deleted"));
|
||||||
location.replace("./");
|
location.replace("./");
|
||||||
|
|||||||
@@ -4,6 +4,7 @@
|
|||||||
import { tick, createEventDispatcher } from "svelte";
|
import { tick, createEventDispatcher } from "svelte";
|
||||||
export let copy_modal_open;
|
export let copy_modal_open;
|
||||||
export let new_client;
|
export let new_client;
|
||||||
|
import toast from 'svelte-french-toast'
|
||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
let valueCopy = null;
|
let valueCopy = null;
|
||||||
let areaDom;
|
let areaDom;
|
||||||
@@ -95,7 +96,7 @@
|
|||||||
<p
|
<p
|
||||||
name="token"
|
name="token"
|
||||||
class:bg-green-200={copied}
|
class:bg-green-200={copied}
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 p-2"
|
||||||
>
|
>
|
||||||
{new_client.key}
|
{new_client.key}
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -1,124 +1,110 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import PromiseError from "../base/PromiseError.svelte";
|
import PromiseError from "../base/PromiseError.svelte";
|
||||||
import ConfirmStatsClientDeletion from "./ConfirmStatsClientDeletion.svelte";
|
import ConfirmStatsClientDeletion from "./ConfirmStatsClientDeletion.svelte";
|
||||||
import { StatsClientService } from "@odit/lfk-client-js";
|
import { StatsClientService } from "@odit/lfk-client-js";
|
||||||
import toast from "svelte-french-toast";
|
import toast from "svelte-french-toast";
|
||||||
let data_loaded = false;
|
let data_loaded = false;
|
||||||
let modal_open;
|
let modal_open;
|
||||||
let delete_client;
|
let delete_client;
|
||||||
export let params;
|
export let params;
|
||||||
$: delete_triggered = false;
|
$: delete_triggered = false;
|
||||||
$: original_data = {};
|
$: original_data = {};
|
||||||
const promise = StatsClientService.statsClientControllerGetOne(
|
const promise = StatsClientService.statsClientControllerGetOne(
|
||||||
params.clientid
|
params.clientid
|
||||||
).then((data) => {
|
).then((data) => {
|
||||||
data_loaded = true;
|
data_loaded = true;
|
||||||
original_data = Object.assign(original_data, data);
|
original_data = Object.assign(original_data, data);
|
||||||
});
|
});
|
||||||
function deleteClient() {
|
function deleteClient() {
|
||||||
StatsClientService.statsClientControllerRemove(original_data.id, false)
|
StatsClientService.statsClientControllerRemove(original_data.id, false)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
toast($_("statsclient-deleted"));
|
toast($_("statsclient-deleted"));
|
||||||
location.replace("./");
|
location.replace("./");
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
modal_open = true;
|
modal_open = true;
|
||||||
delete_client = original_data;
|
delete_client = original_data;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ConfirmStatsClientDeletion bind:modal_open bind:delete_client />
|
<ConfirmStatsClientDeletion bind:modal_open bind:delete_client />
|
||||||
{#await promise}
|
{#await promise}
|
||||||
{$_("loading-statsclient-details")}
|
{$_("loading-statsclient-details")}
|
||||||
{: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">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<nav class="w-full flex">
|
<nav class="w-full flex">
|
||||||
<ol class="list-none flex flex-row items-center justify-start">
|
<ol class="list-none flex flex-row items-center justify-start">
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
<svg
|
<a class="mr-2" href="./"
|
||||||
fill="currentColor"
|
><svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
viewBox="0 0 24 24"
|
width="24"
|
||||||
width="24"
|
height="24"
|
||||||
height="24"
|
viewBox="0 0 24 24"
|
||||||
><path fill="none" d="M0 0h24v24H0z" />
|
fill="none"
|
||||||
<path
|
stroke="currentColor"
|
||||||
d="M4 5v11h16V5H4zM2 4a1 1 0 011-1h18a1 1 0 011 1v14H2V4zM1 19h22v2H1v-2z"
|
stroke-width="2"
|
||||||
/></svg
|
stroke-linecap="round"
|
||||||
>
|
stroke-linejoin="round"
|
||||||
</li>
|
class="inline-block"
|
||||||
<li class="flex items-center ml-2">
|
><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg
|
||||||
<a class="mr-2" href="./">{$_("statsclient")}</a><svg
|
>
|
||||||
stroke="currentColor"
|
{$_("statsclients")}</a
|
||||||
fill="none"
|
>
|
||||||
stroke-width="2"
|
</li>
|
||||||
viewBox="0 0 24 24"
|
</ol>
|
||||||
stroke-linecap="round"
|
</nav>
|
||||||
stroke-linejoin="round"
|
</div>
|
||||||
class="h-3 w-3 mr-2 stroke-current"
|
</div>
|
||||||
height="1em"
|
<div class="mb-4 text-3xl font-extrabold leading-tight">
|
||||||
width="1em"
|
{$_("statsclient")} #{original_data.id}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<div data-id="stations_actions_${original_data.id}">
|
||||||
><line x1="5" y1="12" x2="19" y2="12" />
|
{#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:DELETE")}
|
||||||
<polyline points="12 5 19 12 12 19" /></svg
|
{#if delete_triggered}
|
||||||
>
|
<button
|
||||||
</li>
|
on:click={deleteClient}
|
||||||
<li class="flex items-center">
|
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:w-auto sm:text-sm"
|
||||||
<span class="mr-2">#{original_data.id}</span>
|
>{$_("confirm-deletion")}</button
|
||||||
</li>
|
>
|
||||||
</ol>
|
<button
|
||||||
</nav>
|
on:click={() => {
|
||||||
</div>
|
delete_triggered = !delete_triggered;
|
||||||
</div>
|
}}
|
||||||
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
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"
|
||||||
#{original_data.id}
|
>{$_("cancel")}</button
|
||||||
<span data-id="stations_actions_${original_data.id}">
|
>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:DELETE")}
|
{/if}
|
||||||
{#if delete_triggered}
|
{#if !delete_triggered}
|
||||||
<button
|
<button
|
||||||
on:click={deleteClient}
|
on:click={() => {
|
||||||
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_triggered = true;
|
||||||
>{$_("confirm-deletion")}</button
|
}}
|
||||||
>
|
type="button"
|
||||||
<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:w-auto sm:text-sm"
|
||||||
on:click={() => {
|
>{$_("delete-statsclient")}</button
|
||||||
delete_triggered = !delete_triggered;
|
>
|
||||||
}}
|
{/if}
|
||||||
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"
|
{/if}
|
||||||
>{$_("cancel")}</button
|
</div>
|
||||||
>
|
</div>
|
||||||
{/if}
|
<!-- -->
|
||||||
{#if !delete_triggered}
|
<div class="text-sm w-full mt-2">
|
||||||
<button
|
<label for="description" class="font-semibold text-gray-700"
|
||||||
on:click={() => {
|
>{$_("description")}</label
|
||||||
delete_triggered = true;
|
>
|
||||||
}}
|
<p
|
||||||
type="button"
|
name="description"
|
||||||
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"
|
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-neutral-800 rounded-md p-2"
|
||||||
>{$_("delete-statsclient")}</button
|
>
|
||||||
>
|
{original_data.description}
|
||||||
{/if}
|
</p>
|
||||||
{/if}
|
</div>
|
||||||
</span>
|
</section>
|
||||||
</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}
|
{:catch error}
|
||||||
<PromiseError {error} />
|
<PromiseError {error} />
|
||||||
{/await}
|
{/await}
|
||||||
@@ -1,44 +1,39 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import AddStatsClientModal from "./AddStatsClientModal.svelte";
|
import AddStatsClientModal from "./AddStatsClientModal.svelte";
|
||||||
import CopyStatsClientTokenModal from "./CopyStatsClientTokenModal.svelte";
|
import CopyStatsClientTokenModal from "./CopyStatsClientTokenModal.svelte";
|
||||||
import StatsClientsOverview from "./StatsClientsOverview.svelte";
|
import StatsClientsOverview from "./StatsClientsOverview.svelte";
|
||||||
export let modal_open = false;
|
export let modal_open = false;
|
||||||
export let copy_modal_open = false;
|
export let copy_modal_open = false;
|
||||||
export let new_client = {};
|
export let new_client = {};
|
||||||
let current_clients = [];
|
let current_clients = [];
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_("statsclients")}
|
{$_("statsclients")}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:CREATE")}
|
</h4>
|
||||||
<button
|
{#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:CREATE")}
|
||||||
on:click={() => {
|
<button
|
||||||
modal_open = true;
|
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"
|
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:w-auto sm:text-sm"
|
||||||
{$_("create-a-new-statsclient")}
|
>
|
||||||
</button>
|
{$_("create-a-new-statsclient")}
|
||||||
{/if}
|
</button>
|
||||||
</span>
|
{/if}
|
||||||
<StatsClientsOverview
|
<StatsClientsOverview bind:current_clients />
|
||||||
bind:current_clients
|
|
||||||
bind:modal_open
|
|
||||||
bind:new_client
|
|
||||||
bind:copy_modal_open
|
|
||||||
/>
|
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:CREATE")}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:CREATE")}
|
||||||
<AddStatsClientModal
|
<AddStatsClientModal
|
||||||
bind:modal_open
|
bind:modal_open
|
||||||
bind:current_clients
|
bind:current_clients
|
||||||
bind:new_client
|
bind:new_client
|
||||||
bind:copy_modal_open
|
bind:copy_modal_open
|
||||||
/>
|
/>
|
||||||
<CopyStatsClientTokenModal bind:copy_modal_open bind:new_client />
|
<CopyStatsClientTokenModal bind:copy_modal_open bind:new_client />
|
||||||
{/if}
|
{/if}
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
bind:value={searchvalue}
|
bind:value={searchvalue}
|
||||||
placeholder={$_("datatable.search")}
|
placeholder={$_("datatable.search")}
|
||||||
aria-label={$_("datatable.search")}
|
aria-label={$_("datatable.search")}
|
||||||
class="mb-4"
|
class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border"
|
||||||
/>
|
/>
|
||||||
<div
|
<div
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
|
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll"
|
||||||
|
|||||||
@@ -141,7 +141,7 @@
|
|||||||
bind:this={teamname_input_dom}
|
bind:this={teamname_input_dom}
|
||||||
type="text"
|
type="text"
|
||||||
name="firstname"
|
name="firstname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isTeamNameValid}
|
{#if !isTeamNameValid}
|
||||||
<span
|
<span
|
||||||
@@ -158,7 +158,7 @@
|
|||||||
>{$_("organization")}</label
|
>{$_("organization")}</label
|
||||||
>
|
>
|
||||||
<Select
|
<Select
|
||||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
itemFilter={(label, filterText, option) =>
|
itemFilter={(label, filterText, option) =>
|
||||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
option.value.id
|
option.value.id
|
||||||
|
|||||||
@@ -1,300 +1,264 @@
|
|||||||
<script>
|
<script>
|
||||||
import {
|
import {
|
||||||
GroupContactService,
|
GroupContactService,
|
||||||
RunnerOrganizationService,
|
RunnerOrganizationService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
} from "@odit/lfk-client-js";
|
} from "@odit/lfk-client-js";
|
||||||
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
||||||
|
import toast from "svelte-french-toast";
|
||||||
|
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import Select from "svelte-select";
|
import Select from "svelte-select";
|
||||||
import ImportRunnerModal from "../runners/ImportRunnerModal.svelte";
|
import ImportRunnerModal from "../runners/ImportRunnerModal.svelte";
|
||||||
import PromiseError from "../base/PromiseError.svelte";
|
import PromiseError from "../base/PromiseError.svelte";
|
||||||
import ConfirmTeamDeletion from "./ConfirmTeamDeletion.svelte";
|
import ConfirmTeamDeletion from "./ConfirmTeamDeletion.svelte";
|
||||||
import Teams from "./Teams.svelte";
|
import Teams from "./Teams.svelte";
|
||||||
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
||||||
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
||||||
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
||||||
let [teamdata, original, delete_team, orgs, contacts, modal_open] = [
|
let [teamdata, original, delete_team, orgs, contacts, modal_open] = [
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
{},
|
{},
|
||||||
[],
|
[],
|
||||||
[],
|
[],
|
||||||
false,
|
false,
|
||||||
];
|
];
|
||||||
export let params;
|
export let params;
|
||||||
export let import_modal_open = false;
|
export let import_modal_open = false;
|
||||||
$: delete_triggered = false;
|
$: delete_triggered = false;
|
||||||
$: save_enabled = data_changed && teamdata.parentGroup != null;
|
$: save_enabled = data_changed && teamdata.parentGroup != null;
|
||||||
$: data_loaded = false;
|
$: data_loaded = false;
|
||||||
$: data_changed = !(JSON.stringify(teamdata) === JSON.stringify(original));
|
$: data_changed = !(JSON.stringify(teamdata) === JSON.stringify(original));
|
||||||
$: sponsoring_contracts_show = true;
|
$: sponsoring_contracts_show = true;
|
||||||
$: cards_show = true;
|
$: cards_show = true;
|
||||||
$: certificates_show = true;
|
$: certificates_show = true;
|
||||||
$: generate_teams = [original];
|
$: generate_teams = [original];
|
||||||
$: group = {};
|
$: group = {};
|
||||||
$: contact = {};
|
$: contact = {};
|
||||||
//
|
//
|
||||||
const getContactLabel = (option) =>
|
const getContactLabel = (option) =>
|
||||||
option.firstname + " " + (option.middlename || "") + " " + option.lastname;
|
option.firstname + " " + (option.middlename || "") + " " + option.lastname;
|
||||||
const promise = RunnerTeamService.runnerTeamControllerGetOne(
|
const promise = RunnerTeamService.runnerTeamControllerGetOne(
|
||||||
params.teamid
|
params.teamid
|
||||||
).then((value) => {
|
).then((value) => {
|
||||||
data_loaded = true;
|
data_loaded = true;
|
||||||
teamdata = Object.assign(teamdata, value);
|
teamdata = Object.assign(teamdata, value);
|
||||||
original = Object.assign(original, value);
|
original = Object.assign(original, value);
|
||||||
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
RunnerOrganizationService.runnerOrganizationControllerGetAll().then(
|
||||||
(val) => {
|
(val) => {
|
||||||
orgs = val.map((r) => {
|
orgs = val.map((r) => {
|
||||||
delete r.contact;
|
delete r.contact;
|
||||||
r.teams = [];
|
r.teams = [];
|
||||||
return { label: r.name, value: r };
|
return { label: r.name, value: r };
|
||||||
});
|
});
|
||||||
group = orgs.find((g) => g.value.id == teamdata.parentGroup.id);
|
group = orgs.find((g) => g.value.id == teamdata.parentGroup.id);
|
||||||
}
|
}
|
||||||
);
|
);
|
||||||
GroupContactService.groupContactControllerGetAll().then((val) => {
|
GroupContactService.groupContactControllerGetAll().then((val) => {
|
||||||
contacts = val.map((r) => {
|
contacts = val.map((r) => {
|
||||||
return { label: getContactLabel(r), value: r };
|
return { label: getContactLabel(r), value: r };
|
||||||
});
|
});
|
||||||
if (teamdata.contact) {
|
if (teamdata.contact) {
|
||||||
contact = contacts.find((g) => g.value.id == teamdata.contact.id);
|
contact = contacts.find((g) => g.value.id == teamdata.contact.id);
|
||||||
} else {
|
} else {
|
||||||
contact = null;
|
contact = null;
|
||||||
}
|
}
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
function deleteTeam() {
|
function deleteTeam() {
|
||||||
RunnerTeamService.runnerTeamControllerRemove(original.id, false)
|
RunnerTeamService.runnerTeamControllerRemove(original.id, false)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
toast($_("team-deleted"));
|
toast($_("team-deleted"));
|
||||||
location.replace("./");
|
location.replace("./");
|
||||||
})
|
})
|
||||||
.catch((err) => {
|
.catch((err) => {
|
||||||
modal_open = true;
|
modal_open = true;
|
||||||
delete_team = original;
|
delete_team = original;
|
||||||
});
|
});
|
||||||
}
|
}
|
||||||
function submit() {
|
function submit() {
|
||||||
if (data_loaded === true && save_enabled) {
|
if (data_loaded === true && save_enabled) {
|
||||||
toast($_("updating-team"));
|
toast($_("updating-team"));
|
||||||
let postdata = teamdata;
|
let postdata = teamdata;
|
||||||
postdata.parentGroup = teamdata.parentGroup.id;
|
postdata.parentGroup = teamdata.parentGroup.id;
|
||||||
postdata.contact = teamdata.contact?.id;
|
postdata.contact = teamdata.contact?.id;
|
||||||
RunnerTeamService.runnerTeamControllerPut(original.id, postdata)
|
RunnerTeamService.runnerTeamControllerPut(original.id, postdata)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
Object.assign(original, teamdata);
|
Object.assign(original, teamdata);
|
||||||
original = original;
|
original = original;
|
||||||
toast.success($_("updated-team"));
|
toast.success($_("updated-team"));
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<ImportRunnerModal
|
<ImportRunnerModal
|
||||||
current_runners={[]}
|
current_runners={[]}
|
||||||
on:cancelDelete={(event) => {
|
on:cancelDelete={(event) => {
|
||||||
import_modal_open = false;
|
import_modal_open = false;
|
||||||
}}
|
}}
|
||||||
passed_team={teamdata}
|
passed_team={teamdata}
|
||||||
passed_orgs={[]}
|
passed_orgs={[]}
|
||||||
passed_org={{}}
|
passed_org={{}}
|
||||||
opened_from="TeamDetail"
|
opened_from="TeamDetail"
|
||||||
bind:import_modal_open
|
bind:import_modal_open
|
||||||
/>
|
/>
|
||||||
<ConfirmTeamDeletion bind:modal_open bind:delete_team />
|
<ConfirmTeamDeletion bind:modal_open bind:delete_team />
|
||||||
{#if data_loaded}
|
{#if data_loaded}
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<div class="mb-8 text-3xl font-extrabold leading-tight">
|
<div class="flex flex-row mb-4">
|
||||||
{original.name}
|
<div class="w-full">
|
||||||
<span data-id="org_actions_${teamdata.id}">
|
<nav class="w-full flex">
|
||||||
<GenerateSponsoringContracts
|
<ol class="list-none flex flex-row items-center justify-start">
|
||||||
bind:sponsoring_contracts_show
|
<li class="flex items-center">
|
||||||
bind:generate_teams
|
<a class="mr-2" href="./"
|
||||||
/>
|
><svg
|
||||||
<GenerateRunnerCards bind:cards_show bind:generate_teams />
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
<GenerateRunnerCertificates
|
width="24"
|
||||||
bind:certificates_show
|
height="24"
|
||||||
bind:generate_teams
|
viewBox="0 0 24 24"
|
||||||
/>
|
fill="none"
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:IMPORT")}
|
stroke="currentColor"
|
||||||
<button
|
stroke-width="2"
|
||||||
on:click={() => {
|
stroke-linecap="round"
|
||||||
import_modal_open = true;
|
stroke-linejoin="round"
|
||||||
}}
|
class="inline-block"
|
||||||
type="button"
|
><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg
|
||||||
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"
|
>
|
||||||
>
|
{$_("teams")}</a
|
||||||
{$_("import-runners")}
|
>
|
||||||
</button>
|
</li>
|
||||||
{/if}
|
</ol>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:DELETE")}
|
</nav>
|
||||||
{#if delete_triggered}
|
</div>
|
||||||
<button
|
</div>
|
||||||
on:click={deleteTeam}
|
<div class="mb-4 text-3xl font-extrabold leading-tight">
|
||||||
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"
|
{#if group}
|
||||||
>{$_("confirm-delete")}</button
|
{group.label}{" > "}
|
||||||
>
|
{/if}
|
||||||
<button
|
{original.name} [#{params.teamid}]
|
||||||
on:click={() => {
|
<div data-id="org_actions_${teamdata.id}">
|
||||||
delete_triggered = !delete_triggered;
|
<GenerateSponsoringContracts
|
||||||
}}
|
bind:sponsoring_contracts_show
|
||||||
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"
|
bind:generate_teams
|
||||||
>{$_("cancel")}</button
|
/>
|
||||||
>
|
<GenerateRunnerCards bind:cards_show bind:generate_teams />
|
||||||
{/if}
|
<GenerateRunnerCertificates
|
||||||
{#if !delete_triggered}
|
bind:certificates_show
|
||||||
<button
|
bind:generate_teams
|
||||||
on:click={() => {
|
/>
|
||||||
delete_triggered = true;
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:IMPORT")}
|
||||||
}}
|
<button
|
||||||
type="button"
|
on:click={() => {
|
||||||
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"
|
import_modal_open = true;
|
||||||
>{$_("delete-team")}</button
|
}}
|
||||||
>
|
type="button"
|
||||||
{/if}
|
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:w-auto sm:text-sm"
|
||||||
{/if}
|
>
|
||||||
{#if !delete_triggered}
|
{$_("import-runners")}
|
||||||
<button
|
</button>
|
||||||
on:click={submit}
|
{/if}
|
||||||
disabled={!save_enabled}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:DELETE")}
|
||||||
class:opacity-50={!save_enabled}
|
{#if delete_triggered}
|
||||||
type="button"
|
<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"
|
on:click={deleteTeam}
|
||||||
>{$_("save-changes")}</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:w-auto sm:text-sm"
|
||||||
>
|
>{$_("confirm-delete")}</button
|
||||||
{/if}
|
>
|
||||||
</span>
|
<button
|
||||||
</div>
|
on:click={() => {
|
||||||
<div class="flex flex-row mb-4">
|
delete_triggered = !delete_triggered;
|
||||||
<div class="w-full">
|
}}
|
||||||
<nav class="w-full flex">
|
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"
|
||||||
<ol class="list-none flex flex-row items-center justify-start">
|
>{$_("cancel")}</button
|
||||||
<li class="mr-2 flex items-center">
|
>
|
||||||
<svg
|
{/if}
|
||||||
stroke="currentColor"
|
{#if !delete_triggered}
|
||||||
fill="none"
|
<button
|
||||||
stroke-width="2"
|
on:click={() => {
|
||||||
viewBox="0 0 24 24"
|
delete_triggered = true;
|
||||||
stroke-linecap="round"
|
}}
|
||||||
stroke-linejoin="round"
|
type="button"
|
||||||
class="h-3 w-3 stroke-current"
|
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:w-auto sm:text-sm"
|
||||||
height="1em"
|
>{$_("delete-team")}</button
|
||||||
width="1em"
|
>
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
{/if}
|
||||||
><path d="M3 9l9-7 9 7v11a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2z" />
|
{/if}
|
||||||
<polyline points="9 22 9 12 15 12 15 22" /></svg
|
{#if !delete_triggered}
|
||||||
>
|
<button
|
||||||
</li>
|
on:click={submit}
|
||||||
<li class="flex items-center">
|
disabled={!save_enabled}
|
||||||
<a class="mr-2" href="/">Home</a><svg
|
class:opacity-50={!save_enabled}
|
||||||
stroke="currentColor"
|
type="button"
|
||||||
fill="none"
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
stroke-width="2"
|
>{$_("save-changes")}</button
|
||||||
viewBox="0 0 24 24"
|
>
|
||||||
stroke-linecap="round"
|
{/if}
|
||||||
stroke-linejoin="round"
|
</div>
|
||||||
class="h-3 w-3 mr-2 stroke-current"
|
</div>
|
||||||
height="1em"
|
<div class="text-sm w-full mt-2">
|
||||||
width="1em"
|
<label for="name" class="font-semibold text-gray-700">Name</label>
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<input
|
||||||
><line x1="5" y1="12" x2="19" y2="12" />
|
autocomplete="off"
|
||||||
<polyline points="12 5 19 12 12 19" /></svg
|
placeholder="Name"
|
||||||
>
|
type="text"
|
||||||
</li>
|
bind:value={teamdata.name}
|
||||||
<li class="mr-2 flex items-center">
|
name="name"
|
||||||
<svg
|
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-neutral-800 rounded-md p-2"
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2"
|
/>
|
||||||
fill="currentColor"
|
</div>
|
||||||
width="24"
|
<div class="text-sm w-full mt-2">
|
||||||
height="24"
|
<label for="contact" class="font-semibold text-gray-700"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
>{$_("contact")}</label
|
||||||
viewBox="0 0 640 512"
|
>
|
||||||
><path
|
<Select
|
||||||
fill="currentColor"
|
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-neutral-800 rounded-md p-2"
|
||||||
d="M96 224c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm448 0c35.3 0 64-28.7 64-64s-28.7-64-64-64-64 28.7-64 64 28.7 64 64 64zm32 32h-64c-17.6 0-33.5 7.1-45.1 18.6 40.3 22.1 68.9 62 75.1 109.4h66c17.7 0 32-14.3 32-32v-32c0-35.3-28.7-64-64-64zm-256 0c61.9 0 112-50.1 112-112S381.9 32 320 32 208 82.1 208 144s50.1 112 112 112zm76.8 32h-8.3c-20.8 10-43.9 16-68.5 16s-47.6-6-68.5-16h-8.3C179.6 288 128 339.6 128 403.2V432c0 26.5 21.5 48 48 48h288c26.5 0 48-21.5 48-48v-28.8c0-63.6-51.6-115.2-115.2-115.2zm-223.7-13.4C161.5 263.1 145.6 256 128 256H64c-35.3 0-64 28.7-64 64v32c0 17.7 14.3 32 32 32h65.9c6.3-47.4 34.9-87.3 75.2-109.4z"
|
itemFilter={(label, filterText, option) =>
|
||||||
/></svg
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
>
|
option.value.id.toString().startsWith(filterText.toLowerCase())}
|
||||||
</li>
|
items={contacts}
|
||||||
<li class="flex items-center">
|
showChevron={true}
|
||||||
<a class="mr-2" href="./">Teams</a><svg
|
placeholder={$_("no-contact-selected")}
|
||||||
stroke="currentColor"
|
noOptionsMessage={$_("no-contact-found")}
|
||||||
fill="none"
|
bind:selectedValue={contact}
|
||||||
stroke-width="2"
|
on:select={(selectedValue) =>
|
||||||
viewBox="0 0 24 24"
|
(teamdata.contact = selectedValue.detail.value)}
|
||||||
stroke-linecap="round"
|
on:clear={() => (teamdata.contact = null)}
|
||||||
stroke-linejoin="round"
|
/>
|
||||||
class="h-3 w-3 mr-2 stroke-current"
|
</div>
|
||||||
height="1em"
|
<div class="text-sm w-full mt-2">
|
||||||
width="1em"
|
<label for="org" class="font-semibold text-gray-700"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
>{$_("organization")}</label
|
||||||
><line x1="5" y1="12" x2="19" y2="12" />
|
>
|
||||||
<polyline points="12 5 19 12 12 19" /></svg
|
<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-neutral-800 rounded-md p-2"
|
||||||
</li>
|
itemFilter={(label, filterText, option) =>
|
||||||
<li class="flex items-center">
|
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
||||||
<span class="mr-2">Team-Details #{params.teamid}</span>
|
option.id.value.toString().startsWith(filterText.toLowerCase())}
|
||||||
</li>
|
items={orgs}
|
||||||
</ol>
|
showChevron={true}
|
||||||
</nav>
|
placeholder={$_("search-for-an-organization-by-name-or-id")}
|
||||||
</div>
|
noOptionsMessage={$_("no-organizations-found")}
|
||||||
</div>
|
bind:selectedValue={group}
|
||||||
<div class="text-sm w-full">
|
on:select={(selectedValue) =>
|
||||||
<label for="name" class="font-medium text-gray-700">Name</label>
|
(teamdata.parentGroup = selectedValue.detail.value)}
|
||||||
<input
|
on:clear={() => (teamdata.parentGroup = null)}
|
||||||
autocomplete="off"
|
/>
|
||||||
placeholder="Name"
|
</div>
|
||||||
type="text"
|
<div class="text-sm w-full mt-2">
|
||||||
bind:value={teamdata.name}
|
<span class="font-semibold text-gray-700">{$_("distance")}</span>
|
||||||
name="name"
|
<br />
|
||||||
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"
|
<span class="text-gray-700"
|
||||||
/>
|
>{(original.total_distance / 1000).toFixed(2)} km</span
|
||||||
</div>
|
>
|
||||||
<div class="text-sm w-full">
|
</div>
|
||||||
<label for="contact" class="font-medium text-gray-700"
|
</section>
|
||||||
>{$_("contact")}</label
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
|
||||||
itemFilter={(label, filterText, option) =>
|
|
||||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
|
||||||
option.value.id.toString().startsWith(filterText.toLowerCase())}
|
|
||||||
items={contacts}
|
|
||||||
showChevron={true}
|
|
||||||
placeholder={$_("no-contact-selected")}
|
|
||||||
noOptionsMessage={$_("no-contact-found")}
|
|
||||||
bind:selectedValue={contact}
|
|
||||||
on:select={(selectedValue) =>
|
|
||||||
(teamdata.contact = selectedValue.detail.value)}
|
|
||||||
on:clear={() => (teamdata.contact = null)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<div class="text-sm w-full">
|
|
||||||
<label for="org" class="font-medium text-gray-700"
|
|
||||||
>{$_("organization")}</label
|
|
||||||
>
|
|
||||||
<Select
|
|
||||||
containerClasses="rounded-l-md mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
|
||||||
itemFilter={(label, filterText, option) =>
|
|
||||||
label.toLowerCase().includes(filterText.toLowerCase()) ||
|
|
||||||
option.id.value.toString().startsWith(filterText.toLowerCase())}
|
|
||||||
items={orgs}
|
|
||||||
showChevron={true}
|
|
||||||
placeholder={$_("search-for-an-organization-by-name-or-id")}
|
|
||||||
noOptionsMessage={$_("no-organizations-found")}
|
|
||||||
bind:selectedValue={group}
|
|
||||||
on:select={(selectedValue) =>
|
|
||||||
(teamdata.parentGroup = selectedValue.detail.value)}
|
|
||||||
on:clear={() => (teamdata.parentGroup = null)}
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
</section>
|
|
||||||
{:else}
|
{:else}
|
||||||
{#await promise}
|
{#await promise}
|
||||||
{$_("team-detail-is-being-loaded")}
|
{$_("team-detail-is-being-loaded")}
|
||||||
{:catch error}
|
{:catch error}
|
||||||
<PromiseError />
|
<PromiseError />
|
||||||
{/await}
|
{/await}
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1,30 +1,262 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import AddTeamModal from "./AddTeamModal.svelte";
|
||||||
import store from "../../store";
|
let current_teams = [];
|
||||||
import AddTeamModal from "./AddTeamModal.svelte";
|
import { _ } from "svelte-i18n";
|
||||||
export let modal_open = false;
|
import { RunnerTeamService } from "@odit/lfk-client-js";
|
||||||
import TeamsOverview from "./TeamsOverview.svelte";
|
const teams_promise = RunnerTeamService.runnerTeamControllerGetAll();
|
||||||
let current_teams = [];
|
import store, { users as usersstore } from "../../store.js";
|
||||||
|
import TeamsEmptyState from "./TeamsEmptyState.svelte";
|
||||||
|
import ConfirmTeamDeletion from "./ConfirmTeamDeletion.svelte";
|
||||||
|
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
||||||
|
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
||||||
|
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
||||||
|
import toast from "svelte-french-toast";
|
||||||
|
$: searchvalue = "";
|
||||||
|
$: active_deletes = [];
|
||||||
|
$: sponsoring_contracts_show = current_teams.some(
|
||||||
|
(r) => r.is_selected === true
|
||||||
|
);
|
||||||
|
$: cards_show = current_teams.some((r) => r.is_selected === true);
|
||||||
|
$: certificates_show = current_teams.some((r) => r.is_selected === true);
|
||||||
|
$: generate_teams = current_teams.filter((r) => r.is_selected === true);
|
||||||
|
let modal_open = false;
|
||||||
|
let delete_team = {};
|
||||||
|
usersstore.subscribe((val) => {
|
||||||
|
current_teams = val;
|
||||||
|
});
|
||||||
|
teams_promise.then((data) => {
|
||||||
|
usersstore.set(data);
|
||||||
|
});
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_("teams")}
|
{$_("teams")}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:CREATE")}
|
</h4>
|
||||||
<button
|
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:CREATE")}
|
||||||
on:click={() => {
|
<button
|
||||||
modal_open = true;
|
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"
|
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:w-auto sm:text-sm"
|
||||||
{$_("create-team")}
|
>
|
||||||
</button>
|
{$_("create-team")}
|
||||||
{/if}
|
</button>
|
||||||
</span>
|
{/if}
|
||||||
<TeamsOverview bind:current_teams />
|
<ConfirmTeamDeletion
|
||||||
|
on:cancelDelete={(event) => {
|
||||||
|
modal_open = false;
|
||||||
|
active_deletes[event.detail.id] = false;
|
||||||
|
}}
|
||||||
|
bind:modal_open
|
||||||
|
bind:delete_team
|
||||||
|
/>
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:GET")}
|
||||||
|
{#await teams_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">{$_("teams-are-being-loaded")}</p>
|
||||||
|
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
||||||
|
</div>
|
||||||
|
{:then}
|
||||||
|
{#if current_teams.length === 0}
|
||||||
|
<TeamsEmptyState />
|
||||||
|
{:else}
|
||||||
|
<input
|
||||||
|
type="search"
|
||||||
|
bind:value={searchvalue}
|
||||||
|
placeholder={$_("datatable.search")}
|
||||||
|
aria-label={$_("datatable.search")}
|
||||||
|
class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border"
|
||||||
|
/>
|
||||||
|
<GenerateSponsoringContracts
|
||||||
|
bind:sponsoring_contracts_show
|
||||||
|
bind:generate_teams
|
||||||
|
/>
|
||||||
|
<GenerateRunnerCards bind:cards_show bind:generate_teams />
|
||||||
|
<GenerateRunnerCertificates
|
||||||
|
bind:certificates_show
|
||||||
|
bind:generate_teams
|
||||||
|
/>
|
||||||
|
<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 class="odd:bg-white even:bg-gray-100">
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
const newstate = !current_teams.some(
|
||||||
|
(r) => r.is_selected === true
|
||||||
|
);
|
||||||
|
current_teams = current_teams.map((r) => {
|
||||||
|
r.is_selected = newstate;
|
||||||
|
return r;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
class="underline cursor-pointer select-none"
|
||||||
|
>{#if current_teams.some((r) => r.is_selected === true)}
|
||||||
|
{$_("deselect-all")}
|
||||||
|
{:else}{$_("select-all")}{/if}
|
||||||
|
</button>
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||||
|
>
|
||||||
|
{$_("name")}
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||||
|
>
|
||||||
|
{$_("organization")}
|
||||||
|
</th>
|
||||||
|
<th
|
||||||
|
scope="col"
|
||||||
|
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
||||||
|
>
|
||||||
|
{$_("contact")}
|
||||||
|
</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_teams as t}
|
||||||
|
{#if Object.values(t)
|
||||||
|
.toString()
|
||||||
|
.toLowerCase()
|
||||||
|
.includes(searchvalue)}
|
||||||
|
<tr
|
||||||
|
class="odd:bg-white even:bg-gray-100"
|
||||||
|
data-rowid="team_{t.id}"
|
||||||
|
>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
|
<input
|
||||||
|
bind:checked={t.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="text-sm font-medium text-gray-900">
|
||||||
|
{t.name}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="text-sm font-medium text-gray-900">
|
||||||
|
{#if t.parentGroup}
|
||||||
|
<a
|
||||||
|
href="../orgs/{t.parentGroup.id}"
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800 border border-current"
|
||||||
|
>{t.parentGroup.name}</a
|
||||||
|
>
|
||||||
|
{:else}{$_("no-organization-specified")}{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
|
<div class="flex items-center">
|
||||||
|
<div class="text-sm font-medium text-gray-900">
|
||||||
|
{#if t.contact}
|
||||||
|
<a
|
||||||
|
href="../contacts/{t.contact.id}"
|
||||||
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800 border border-current"
|
||||||
|
>{t.contact.firstname}
|
||||||
|
{t.contact.middlename || ""}
|
||||||
|
{t.contact.lastname}</a
|
||||||
|
>
|
||||||
|
{:else}{$_("no-contact-specified")}{/if}
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
</td>
|
||||||
|
{#if active_deletes[t.id] === true}
|
||||||
|
<td
|
||||||
|
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
active_deletes[t.id] = false;
|
||||||
|
}}
|
||||||
|
tabindex="0"
|
||||||
|
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer"
|
||||||
|
>{$_("cancel-delete")}</button
|
||||||
|
>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
RunnerTeamService.runnerTeamControllerRemove(
|
||||||
|
t.id,
|
||||||
|
false
|
||||||
|
)
|
||||||
|
.then((resp) => {
|
||||||
|
current_teams = current_teams.filter(
|
||||||
|
(obj) => obj.id !== t.id
|
||||||
|
);
|
||||||
|
toast($_("team-deleted"));
|
||||||
|
})
|
||||||
|
.catch((err) => {
|
||||||
|
modal_open = true;
|
||||||
|
delete_team = t;
|
||||||
|
});
|
||||||
|
}}
|
||||||
|
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="./{t.id}"
|
||||||
|
class="text-indigo-600 hover:text-indigo-900"
|
||||||
|
>{$_("details")}</a
|
||||||
|
>
|
||||||
|
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:DELETE")}
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
active_deletes[t.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}
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:CREATE")}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:CREATE")}
|
||||||
<AddTeamModal bind:current_teams bind:modal_open />
|
<AddTeamModal bind:current_teams bind:modal_open />
|
||||||
{/if}
|
{/if}
|
||||||
@@ -1,247 +0,0 @@
|
|||||||
<script>
|
|
||||||
import { _ } from "svelte-i18n";
|
|
||||||
import { RunnerTeamService } from "@odit/lfk-client-js";
|
|
||||||
const teams_promise = RunnerTeamService.runnerTeamControllerGetAll();
|
|
||||||
import store, { users as usersstore } from "../../store.js";
|
|
||||||
import TeamsEmptyState from "./TeamsEmptyState.svelte";
|
|
||||||
import ConfirmTeamDeletion from "./ConfirmTeamDeletion.svelte";
|
|
||||||
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
|
||||||
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
|
||||||
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
|
||||||
import toast from "svelte-french-toast";
|
|
||||||
$: searchvalue = "";
|
|
||||||
$: active_deletes = [];
|
|
||||||
$: sponsoring_contracts_show = current_teams.some(
|
|
||||||
(r) => r.is_selected === true
|
|
||||||
);
|
|
||||||
$: cards_show = current_teams.some((r) => r.is_selected === true);
|
|
||||||
$: certificates_show = current_teams.some((r) => r.is_selected === true);
|
|
||||||
$: generate_teams = current_teams.filter((r) => r.is_selected === true);
|
|
||||||
export let current_teams = [];
|
|
||||||
let modal_open = false;
|
|
||||||
let delete_team = {};
|
|
||||||
usersstore.subscribe((val) => {
|
|
||||||
current_teams = val;
|
|
||||||
});
|
|
||||||
teams_promise.then((data) => {
|
|
||||||
usersstore.set(data);
|
|
||||||
});
|
|
||||||
</script>
|
|
||||||
|
|
||||||
<ConfirmTeamDeletion
|
|
||||||
on:cancelDelete={(event) => {
|
|
||||||
modal_open = false;
|
|
||||||
active_deletes[event.detail.id] = false;
|
|
||||||
}}
|
|
||||||
bind:modal_open
|
|
||||||
bind:delete_team
|
|
||||||
/>
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:GET")}
|
|
||||||
{#await teams_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">{$_("teams-are-being-loaded")}</p>
|
|
||||||
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
|
|
||||||
</div>
|
|
||||||
{:then}
|
|
||||||
{#if current_teams.length === 0}
|
|
||||||
<TeamsEmptyState />
|
|
||||||
{:else}
|
|
||||||
<input
|
|
||||||
type="search"
|
|
||||||
bind:value={searchvalue}
|
|
||||||
placeholder={$_("datatable.search")}
|
|
||||||
aria-label={$_("datatable.search")}
|
|
||||||
class="mb-4"
|
|
||||||
/>
|
|
||||||
<div class="h-12">
|
|
||||||
<GenerateSponsoringContracts
|
|
||||||
bind:sponsoring_contracts_show
|
|
||||||
bind:generate_teams
|
|
||||||
/>
|
|
||||||
<GenerateRunnerCards bind:cards_show bind:generate_teams />
|
|
||||||
<GenerateRunnerCertificates
|
|
||||||
bind:certificates_show
|
|
||||||
bind:generate_teams
|
|
||||||
/>
|
|
||||||
</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 class="odd:bg-white even:bg-gray-100">
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
const newstate = !current_teams.some(
|
|
||||||
(r) => r.is_selected === true
|
|
||||||
);
|
|
||||||
current_teams = current_teams.map((r) => {
|
|
||||||
r.is_selected = newstate;
|
|
||||||
return r;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
class="underline cursor-pointer select-none"
|
|
||||||
>{#if current_teams.some((r) => r.is_selected === true)}
|
|
||||||
{$_("deselect-all")}
|
|
||||||
{:else}{$_("select-all")}{/if}
|
|
||||||
</button>
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
|
||||||
>
|
|
||||||
{$_("name")}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
|
||||||
>
|
|
||||||
{$_("organization")}
|
|
||||||
</th>
|
|
||||||
<th
|
|
||||||
scope="col"
|
|
||||||
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
|
|
||||||
>
|
|
||||||
{$_("contact")}
|
|
||||||
</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_teams as t}
|
|
||||||
{#if Object.values(t)
|
|
||||||
.toString()
|
|
||||||
.toLowerCase()
|
|
||||||
.includes(searchvalue)}
|
|
||||||
<tr
|
|
||||||
class="odd:bg-white even:bg-gray-100"
|
|
||||||
data-rowid="team_{t.id}"
|
|
||||||
>
|
|
||||||
<td class="px-6 py-4 whitespace-nowrap">
|
|
||||||
<input
|
|
||||||
bind:checked={t.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">
|
|
||||||
{t.name}
|
|
||||||
</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">
|
|
||||||
{#if t.parentGroup}
|
|
||||||
<a
|
|
||||||
href="../orgs/{t.parentGroup.id}"
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
|
||||||
>{t.parentGroup.name}</a
|
|
||||||
>
|
|
||||||
{:else}{$_("no-organization-specified")}{/if}
|
|
||||||
</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">
|
|
||||||
{#if t.contact}
|
|
||||||
<a
|
|
||||||
href="../contacts/{t.contact.id}"
|
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
|
||||||
>{t.contact.firstname}
|
|
||||||
{t.contact.middlename || ""}
|
|
||||||
{t.contact.lastname}</a
|
|
||||||
>
|
|
||||||
{:else}{$_("no-contact-specified")}{/if}
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</div>
|
|
||||||
</td>
|
|
||||||
{#if active_deletes[t.id] === true}
|
|
||||||
<td
|
|
||||||
class="px-6 py-4 whitespace-nowrap text-right text-sm font-medium"
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[t.id] = false;
|
|
||||||
}}
|
|
||||||
tabindex="0"
|
|
||||||
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer"
|
|
||||||
>{$_("cancel-delete")}</button
|
|
||||||
>
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
RunnerTeamService.runnerTeamControllerRemove(
|
|
||||||
t.id,
|
|
||||||
false
|
|
||||||
)
|
|
||||||
.then((resp) => {
|
|
||||||
current_teams = current_teams.filter(
|
|
||||||
(obj) => obj.id !== t.id
|
|
||||||
);
|
|
||||||
toast($_("team-deleted"));
|
|
||||||
})
|
|
||||||
.catch((err) => {
|
|
||||||
modal_open = true;
|
|
||||||
delete_team = t;
|
|
||||||
});
|
|
||||||
}}
|
|
||||||
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="./{t.id}"
|
|
||||||
class="text-indigo-600 hover:text-indigo-900"
|
|
||||||
>{$_("details")}</a
|
|
||||||
>
|
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:DELETE")}
|
|
||||||
<button
|
|
||||||
on:click={() => {
|
|
||||||
active_deletes[t.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}
|
|
||||||
@@ -139,7 +139,7 @@
|
|||||||
bind:this={trackname_input}
|
bind:this={trackname_input}
|
||||||
type="text"
|
type="text"
|
||||||
name="trackname"
|
name="trackname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if isTracknameValid}
|
{#if isTracknameValid}
|
||||||
<span
|
<span
|
||||||
@@ -164,7 +164,7 @@
|
|||||||
bind:value={tracklength}
|
bind:value={tracklength}
|
||||||
type="number"
|
type="number"
|
||||||
name="track_length_m"
|
name="track_length_m"
|
||||||
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
|
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 p-2"
|
||||||
placeholder="1000"
|
placeholder="1000"
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
@@ -195,7 +195,7 @@
|
|||||||
bind:value={track_min_duration}
|
bind:value={track_min_duration}
|
||||||
type="number"
|
type="number"
|
||||||
name="track_min_duration"
|
name="track_min_duration"
|
||||||
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 p-2"
|
class="focus:ring-indigo-500 focus:border-indigo-500 flex-1 block w-full rounded-none rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 p-2"
|
||||||
placeholder={smart_track_min_duration_placeholder}
|
placeholder={smart_track_min_duration_placeholder}
|
||||||
/>
|
/>
|
||||||
<span
|
<span
|
||||||
@@ -223,7 +223,7 @@
|
|||||||
type="button"
|
type="button"
|
||||||
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-blue-600 text-base font-medium text-white hover:bg-blue-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-blue-500 sm:ml-3 sm:w-auto sm:text-sm"
|
||||||
>
|
>
|
||||||
Create
|
{$_("create")}
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
|
|||||||
@@ -19,18 +19,18 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
Tracks
|
{$_("tracks")}
|
||||||
<button
|
</h4>
|
||||||
on:click={() => {
|
<button
|
||||||
modal_open = true;
|
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"
|
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:w-auto sm:text-sm"
|
||||||
{$_("create-track")}
|
>
|
||||||
</button>
|
{$_("create-track")}
|
||||||
</span>
|
</button>
|
||||||
{#await tracks_promise}
|
{#await tracks_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"
|
||||||
@@ -101,7 +101,7 @@
|
|||||||
<div class="ml-4">
|
<div class="ml-4">
|
||||||
{#if editTracks.findIndex((tr) => tr.id === t.id) !== -1}
|
{#if editTracks.findIndex((tr) => tr.id === t.id) !== -1}
|
||||||
<input
|
<input
|
||||||
class="shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-0.5"
|
class="shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-0.5"
|
||||||
type="text"
|
type="text"
|
||||||
value={t.name}
|
value={t.name}
|
||||||
on:input={(e) => {
|
on:input={(e) => {
|
||||||
@@ -124,7 +124,7 @@
|
|||||||
<div class="ml-4">
|
<div class="ml-4">
|
||||||
{#if editTracks.findIndex((tr) => tr.id === t.id) !== -1}
|
{#if editTracks.findIndex((tr) => tr.id === t.id) !== -1}
|
||||||
<input
|
<input
|
||||||
class="shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-0.5"
|
class="shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-0.5"
|
||||||
type="number"
|
type="number"
|
||||||
value={t.distance}
|
value={t.distance}
|
||||||
on:input={(e) => {
|
on:input={(e) => {
|
||||||
@@ -147,7 +147,7 @@
|
|||||||
<div class="ml-4">
|
<div class="ml-4">
|
||||||
{#if editTracks.findIndex((tr) => tr.id === t.id) !== -1}
|
{#if editTracks.findIndex((tr) => tr.id === t.id) !== -1}
|
||||||
<input
|
<input
|
||||||
class="shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-0.5"
|
class="shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-0.5"
|
||||||
type="number"
|
type="number"
|
||||||
value={t.minimumLapTime}
|
value={t.minimumLapTime}
|
||||||
on:input={(e) => {
|
on:input={(e) => {
|
||||||
|
|||||||
@@ -156,7 +156,7 @@
|
|||||||
bind:this={firstname_input}
|
bind:this={firstname_input}
|
||||||
type="text"
|
type="text"
|
||||||
name="firstname"
|
name="firstname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isFirstnameValid}
|
{#if !isFirstnameValid}
|
||||||
<span
|
<span
|
||||||
@@ -179,7 +179,7 @@
|
|||||||
bind:this={middlename_input}
|
bind:this={middlename_input}
|
||||||
type="text"
|
type="text"
|
||||||
name="trackname"
|
name="trackname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div> -->
|
</div> -->
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
@@ -198,7 +198,7 @@
|
|||||||
bind:this={lastname_input}
|
bind:this={lastname_input}
|
||||||
type="text"
|
type="text"
|
||||||
name="lastname"
|
name="lastname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isLastnameValid}
|
{#if !isLastnameValid}
|
||||||
<span
|
<span
|
||||||
@@ -224,7 +224,7 @@
|
|||||||
bind:this={password_input}
|
bind:this={password_input}
|
||||||
type="password"
|
type="password"
|
||||||
name="password"
|
name="password"
|
||||||
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-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
<PasswordStrength
|
<PasswordStrength
|
||||||
bind:password_change={password_input_value}
|
bind:password_change={password_input_value}
|
||||||
@@ -243,7 +243,7 @@
|
|||||||
bind:this={username_input}
|
bind:this={username_input}
|
||||||
type="text"
|
type="text"
|
||||||
name="trackname"
|
name="trackname"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="col-span-6">
|
<div class="col-span-6">
|
||||||
@@ -259,7 +259,7 @@
|
|||||||
bind:this={email_input}
|
bind:this={email_input}
|
||||||
type="email"
|
type="email"
|
||||||
name="email"
|
name="email"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
{#if !isEmailValid}
|
{#if !isEmailValid}
|
||||||
<span
|
<span
|
||||||
|
|||||||
@@ -1,235 +1,217 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import isEmail from "validator/es/lib/isEmail";
|
import isEmail from "validator/es/lib/isEmail";
|
||||||
import { UserService, UserGroupService } from "@odit/lfk-client-js";
|
import { UserService, UserGroupService } from "@odit/lfk-client-js";
|
||||||
import PromiseError from "../base/PromiseError.svelte";
|
import PromiseError from "../base/PromiseError.svelte";
|
||||||
import toast from "svelte-french-toast";
|
import toast from "svelte-french-toast";
|
||||||
export let params;
|
export let params;
|
||||||
const user_promise = UserService.userControllerGetOne(params.userid);
|
const user_promise = UserService.userControllerGetOne(params.userid);
|
||||||
let data_loaded = false;
|
let data_loaded = false;
|
||||||
let usergroups_array_original = [];
|
let usergroups_array_original = [];
|
||||||
const colors = [
|
const colors = [
|
||||||
"#f3558e",
|
"#f3558e",
|
||||||
"#17b978",
|
"#17b978",
|
||||||
"#3498db",
|
"#3498db",
|
||||||
"#3f3b3b",
|
"#3f3b3b",
|
||||||
"#775ada",
|
"#775ada",
|
||||||
"#7ed6df_#000000",
|
"#7ed6df_#000000",
|
||||||
"#000000",
|
"#000000",
|
||||||
"#21e6c1_#000000",
|
"#21e6c1_#000000",
|
||||||
"#c0392b",
|
"#c0392b",
|
||||||
"#d35400",
|
"#d35400",
|
||||||
"#7f8c8d",
|
"#7f8c8d",
|
||||||
"#6ab04c",
|
"#6ab04c",
|
||||||
"#4834d4",
|
"#4834d4",
|
||||||
"#ff1f5a",
|
"#ff1f5a",
|
||||||
"#eac100",
|
"#eac100",
|
||||||
];
|
];
|
||||||
let matched_colors = [];
|
let matched_colors = [];
|
||||||
$: delete_triggered = false;
|
$: delete_triggered = false;
|
||||||
$: original_data = {};
|
$: original_data = {};
|
||||||
$: editable_userdata = {};
|
$: editable_userdata = {};
|
||||||
$: allgroups = [];
|
$: allgroups = [];
|
||||||
$: allgroups_ids = [];
|
$: allgroups_ids = [];
|
||||||
$: usergroups_array = [];
|
$: usergroups_array = [];
|
||||||
$: search_permission = "";
|
$: search_permission = "";
|
||||||
user_promise.then((data) => {
|
user_promise.then((data) => {
|
||||||
let current_target = "";
|
let current_target = "";
|
||||||
let colorindex = -1;
|
let colorindex = -1;
|
||||||
// alphabetically sort permissions for color compatibility for target
|
// alphabetically sort permissions for color compatibility for target
|
||||||
data.permissions = data.permissions.sort();
|
data.permissions = data.permissions.sort();
|
||||||
data.permissions.forEach((p) => {
|
data.permissions.forEach((p) => {
|
||||||
const target = p.split(":")[0];
|
const target = p.split(":")[0];
|
||||||
if (current_target !== p.split(":")[0]) {
|
if (current_target !== p.split(":")[0]) {
|
||||||
colorindex++;
|
colorindex++;
|
||||||
current_target = p.split(":")[0];
|
current_target = p.split(":")[0];
|
||||||
}
|
}
|
||||||
let background = colors[colorindex];
|
let background = colors[colorindex];
|
||||||
let foreground = "#fff";
|
let foreground = "#fff";
|
||||||
if (background.includes("_")) {
|
if (background.includes("_")) {
|
||||||
foreground = background.split("_")[1];
|
foreground = background.split("_")[1];
|
||||||
background = background.split("_")[0];
|
background = background.split("_")[0];
|
||||||
}
|
}
|
||||||
matched_colors[target] = [background, foreground];
|
matched_colors[target] = [background, foreground];
|
||||||
});
|
});
|
||||||
//
|
//
|
||||||
data_loaded = true;
|
data_loaded = true;
|
||||||
original_data = Object.assign(original_data, data);
|
original_data = Object.assign(original_data, data);
|
||||||
editable_userdata = data;
|
editable_userdata = data;
|
||||||
data.groups.forEach((g) => {
|
data.groups.forEach((g) => {
|
||||||
usergroups_array = usergroups_array.concat([g.id]);
|
usergroups_array = usergroups_array.concat([g.id]);
|
||||||
});
|
});
|
||||||
usergroups_array_original = usergroups_array;
|
usergroups_array_original = usergroups_array;
|
||||||
allgroups.forEach((g) => {
|
allgroups.forEach((g) => {
|
||||||
allgroups_ids.push(g.id);
|
allgroups_ids.push(g.id);
|
||||||
});
|
});
|
||||||
});
|
});
|
||||||
UserGroupService.userGroupControllerGetAll().then((data) => {
|
UserGroupService.userGroupControllerGetAll().then((data) => {
|
||||||
allgroups = data;
|
allgroups = data;
|
||||||
});
|
});
|
||||||
$: changes_performed = !(
|
$: changes_performed = !(
|
||||||
JSON.stringify(original_data) == JSON.stringify(editable_userdata)
|
JSON.stringify(original_data) == JSON.stringify(editable_userdata)
|
||||||
);
|
);
|
||||||
$: groups_changed =
|
$: groups_changed =
|
||||||
JSON.stringify(usergroups_array) ===
|
JSON.stringify(usergroups_array) ===
|
||||||
JSON.stringify(usergroups_array_original);
|
JSON.stringify(usergroups_array_original);
|
||||||
$: save_enabled =
|
$: save_enabled =
|
||||||
(changes_performed || !groups_changed) && isEmail(editable_userdata.email);
|
(changes_performed || !groups_changed) && isEmail(editable_userdata.email);
|
||||||
function submit() {
|
function submit() {
|
||||||
if (data_loaded === true && save_enabled) {
|
if (data_loaded === true && save_enabled) {
|
||||||
editable_userdata.groups = usergroups_array;
|
editable_userdata.groups = usergroups_array;
|
||||||
toast.loading($_("updating-user"));
|
toast.loading($_("updating-user"));
|
||||||
UserService.userControllerPut(original_data.id, editable_userdata)
|
UserService.userControllerPut(original_data.id, editable_userdata)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
Object.assign(original_data, resp);
|
Object.assign(original_data, resp);
|
||||||
Object.assign(editable_userdata, resp);
|
Object.assign(editable_userdata, resp);
|
||||||
original_data.permissions = resp.permissions;
|
original_data.permissions = resp.permissions;
|
||||||
usergroups_array = [];
|
usergroups_array = [];
|
||||||
resp.groups.forEach((g) => {
|
resp.groups.forEach((g) => {
|
||||||
usergroups_array = usergroups_array.concat([g.id]);
|
usergroups_array = usergroups_array.concat([g.id]);
|
||||||
});
|
});
|
||||||
usergroups_array_original = usergroups_array;
|
usergroups_array_original = usergroups_array;
|
||||||
//
|
//
|
||||||
toast.dismiss();
|
toast.dismiss();
|
||||||
toast($_("user-updated"));
|
toast($_("user-updated"));
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function deleteUser() {
|
function deleteUser() {
|
||||||
UserService.userControllerRemove(original_data.id, true)
|
UserService.userControllerRemove(original_data.id, true)
|
||||||
.then((resp) => {
|
.then((resp) => {
|
||||||
location.replace("./");
|
location.replace("./");
|
||||||
})
|
})
|
||||||
.catch((err) => {});
|
.catch((err) => {});
|
||||||
}
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#await user_promise}
|
{#await user_promise}
|
||||||
<!-- -->
|
<!-- -->
|
||||||
{:then user}
|
{:then user}
|
||||||
<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">
|
||||||
<div class="w-full">
|
<div class="w-full">
|
||||||
<nav class="w-full flex">
|
<nav class="w-full flex">
|
||||||
<ol class="list-none flex flex-row items-center justify-start">
|
<ol class="list-none flex flex-row items-center justify-start">
|
||||||
<li class="flex items-center">
|
<li class="flex items-center">
|
||||||
<svg
|
<a class="mr-2" href="./"
|
||||||
class="flex-shrink-0 w-5 h-5 mr-2"
|
><svg
|
||||||
fill="currentColor"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
height="24"
|
height="24"
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
viewBox="0 0 24 24"
|
||||||
viewBox="0 0 24 24"
|
fill="none"
|
||||||
><path
|
stroke="currentColor"
|
||||||
fill="currentColor"
|
stroke-width="2"
|
||||||
d="M12 14v8H4a8 8 0 018-8zm0-1a6 6 0 110-12 6 6 0 010 12zm2.6 5.81a3.51 3.51 0 010-1.62l-1-.57 1-1.74 1 .58a3.5 3.5 0 011.4-.82V13.5h2v1.15a3.5 3.5 0 011.4.8l1-.57 1 1.74-1 .57a3.51 3.51 0 010 1.62l1 .57-1 1.74-1-.58a3.5 3.5 0 01-1.4.82v1.14h-2v-1.15a3.5 3.5 0 01-1.4-.8l-1 .57-1-1.74 1-.57zM18 17a1 1 0 100 2 1 1 0 000-2z"
|
stroke-linecap="round"
|
||||||
/></svg
|
stroke-linejoin="round"
|
||||||
>
|
class="inline-block"
|
||||||
</li>
|
><path d="m12 19-7-7 7-7" /><path d="M19 12H5" /></svg
|
||||||
<li class="flex items-center">
|
>
|
||||||
<a class="mr-2" href="./">{$_("users")}</a><svg
|
{$_("users")}</a
|
||||||
stroke="currentColor"
|
>
|
||||||
fill="none"
|
</li>
|
||||||
stroke-width="2"
|
</ol>
|
||||||
viewBox="0 0 24 24"
|
</nav>
|
||||||
stroke-linecap="round"
|
</div>
|
||||||
stroke-linejoin="round"
|
</div>
|
||||||
class="h-3 w-3 mr-2 stroke-current"
|
<div class="mb-4 text-3xl font-extrabold">
|
||||||
height="1em"
|
{original_data.firstname}
|
||||||
width="1em"
|
{original_data.lastname}
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
<span data-id="user_actions_${editable_userdata.id}">
|
||||||
><line x1="5" y1="12" x2="19" y2="12" />
|
{#if store.state.jwtinfo.userdetails.permissions.includes("USER:DELETE")}
|
||||||
<polyline points="12 5 19 12 12 19" /></svg
|
{#if delete_triggered}
|
||||||
>
|
<button
|
||||||
</li>
|
on:click={deleteUser}
|
||||||
<li class="flex items-center">
|
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:w-auto sm:text-sm"
|
||||||
<span class="mr-2"
|
>{$_("confirm-delete")}</button
|
||||||
>{original_data.firstname}
|
>
|
||||||
{original_data.lastname}</span
|
<button
|
||||||
>
|
on:click={() => {
|
||||||
</li>
|
delete_triggered = !delete_triggered;
|
||||||
</ol>
|
}}
|
||||||
</nav>
|
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"
|
||||||
</div>
|
>{$_("cancel")}</button
|
||||||
</div>
|
>
|
||||||
<div class="mb-8 text-3xl font-extrabold">
|
{/if}
|
||||||
{original_data.firstname}
|
{#if !delete_triggered}
|
||||||
{original_data.lastname}
|
<button
|
||||||
<span data-id="user_actions_${editable_userdata.id}">
|
on:click={() => {
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("USER:DELETE")}
|
delete_triggered = true;
|
||||||
{#if delete_triggered}
|
}}
|
||||||
<button
|
type="button"
|
||||||
on:click={deleteUser}
|
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:w-auto sm:text-sm"
|
||||||
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-user")}</button
|
||||||
>{$_("confirm-delete")}</button
|
>
|
||||||
>
|
{/if}
|
||||||
<button
|
{/if}
|
||||||
on:click={() => {
|
{#if !delete_triggered}
|
||||||
delete_triggered = !delete_triggered;
|
<button
|
||||||
}}
|
disabled={!save_enabled}
|
||||||
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"
|
class:opacity-50={!save_enabled}
|
||||||
>{$_("cancel")}</button
|
type="button"
|
||||||
>
|
on:click={submit}
|
||||||
{/if}
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
{#if !delete_triggered}
|
>{$_("save-changes")}</button
|
||||||
<button
|
>
|
||||||
on:click={() => {
|
{/if}
|
||||||
delete_triggered = true;
|
</span>
|
||||||
}}
|
</div>
|
||||||
type="button"
|
<div class="mt-3 text-sm w-full">
|
||||||
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"
|
<label for="enabled" class="font-semibold text-gray-700"
|
||||||
>{$_("delete-user")}</button
|
>{$_("active")}?</label
|
||||||
>
|
>
|
||||||
{/if}
|
<br />
|
||||||
{/if}
|
<p class="text-gray-500">
|
||||||
{#if !delete_triggered}
|
<input
|
||||||
<button
|
id="enabled"
|
||||||
disabled={!save_enabled}
|
on:change={() => {
|
||||||
class:opacity-50={!save_enabled}
|
editable_userdata.enabled = !editable_userdata.enabled;
|
||||||
type="button"
|
}}
|
||||||
on:click={submit}
|
name="enabled"
|
||||||
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"
|
type="checkbox"
|
||||||
>{$_("save-changes")}</button
|
checked={editable_userdata.enabled}
|
||||||
>
|
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
||||||
{/if}
|
/>
|
||||||
</span>
|
{$_("set-the-user-active-inactive")}
|
||||||
</div>
|
</p>
|
||||||
<div class="mt-3 text-sm w-full">
|
</div>
|
||||||
<label for="enabled" class="ml-1 font-medium text-gray-700"
|
<div class="text-sm w-full mt-2">
|
||||||
>{$_("active")}?</label
|
<label for="firstname" class="font-semibold text-gray-700"
|
||||||
>
|
>{$_("first-name")}</label
|
||||||
<br />
|
>
|
||||||
<p class="text-gray-500">
|
<input
|
||||||
<input
|
autocomplete="off"
|
||||||
id="enabled"
|
placeholder={$_("first-name")}
|
||||||
on:change={() => {
|
type="text"
|
||||||
editable_userdata.enabled = !editable_userdata.enabled;
|
bind:value={editable_userdata.firstname}
|
||||||
}}
|
name="firstname"
|
||||||
name="enabled"
|
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-neutral-800 rounded-md p-2"
|
||||||
type="checkbox"
|
/>
|
||||||
checked={editable_userdata.enabled}
|
</div>
|
||||||
class="focus:ring-indigo-500 h-4 w-4 text-indigo-600 border-gray-300 rounded"
|
<!-- <div class="text-sm w-full mt-2">
|
||||||
/>
|
<label for="middlename" class="font-semibold text-gray-700"
|
||||||
{$_("set-the-user-active-inactive")}
|
|
||||||
</p>
|
|
||||||
</div>
|
|
||||||
<div class="text-sm w-full">
|
|
||||||
<label for="firstname" class="font-medium text-gray-700"
|
|
||||||
>{$_("first-name")}</label
|
|
||||||
>
|
|
||||||
<input
|
|
||||||
autocomplete="off"
|
|
||||||
placeholder={$_("first-name")}
|
|
||||||
type="text"
|
|
||||||
bind:value={editable_userdata.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"
|
|
||||||
/>
|
|
||||||
</div>
|
|
||||||
<!-- <div class="text-sm w-full">
|
|
||||||
<label for="middlename" class="font-medium text-gray-700"
|
|
||||||
>{$_("middle-name")}</label
|
>{$_("middle-name")}</label
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
@@ -238,102 +220,102 @@
|
|||||||
type="text"
|
type="text"
|
||||||
bind:value={editable_userdata.middlename}
|
bind:value={editable_userdata.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-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div> -->
|
</div> -->
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full mt-2">
|
||||||
<label for="lastname" class="font-medium text-gray-700"
|
<label for="lastname" class="font-semibold text-gray-700"
|
||||||
>{$_("last-name")}</label
|
>{$_("last-name")}</label
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_("last-name")}
|
placeholder={$_("last-name")}
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={editable_userdata.lastname}
|
bind:value={editable_userdata.lastname}
|
||||||
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-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full mt-2">
|
||||||
<label for="email" class="font-medium text-gray-700"
|
<label for="email" class="font-semibold text-gray-700"
|
||||||
>{$_("e-mail-adress")}</label
|
>{$_("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_userdata.email}
|
bind:value={editable_userdata.email}
|
||||||
name="email"
|
name="email"
|
||||||
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
|
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{#if !isEmail(editable_userdata.email)}
|
{#if !isEmail(editable_userdata.email)}
|
||||||
<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")}</span
|
>{$_("valid-email-is-required")}</span
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full mt-2">
|
||||||
<label for="username" class="font-medium text-gray-700"
|
<label for="username" class="font-semibold text-gray-700"
|
||||||
>{$_("username")}</label
|
>{$_("username")}</label
|
||||||
>
|
>
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_("username")}
|
placeholder={$_("username")}
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={editable_userdata.username}
|
bind:value={editable_userdata.username}
|
||||||
name="username"
|
name="username"
|
||||||
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-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full">
|
<div class="text-sm w-full mt-2">
|
||||||
<span class="font-medium">{$_("groups")}</span>
|
<span class="font-semibold">{$_("groups")}</span>
|
||||||
<!-- svelte-ignore a11y-no-onchange -->
|
<!-- svelte-ignore a11y-no-onchange -->
|
||||||
<select
|
<select
|
||||||
bind:value={usergroups_array}
|
bind:value={usergroups_array}
|
||||||
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-neutral-800 rounded-md p-2"
|
||||||
multiple
|
multiple
|
||||||
>
|
>
|
||||||
{#each allgroups as g}
|
{#each allgroups as g}
|
||||||
{#if usergroups_array.includes(g.id)}
|
{#if usergroups_array.includes(g.id)}
|
||||||
<option selected value={g.id}>{g.name}</option>
|
<option selected value={g.id}>{g.name}</option>
|
||||||
{:else}
|
{:else}
|
||||||
<option value={g.id}>{g.name}</option>
|
<option value={g.id}>{g.name}</option>
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="text-sm w-full mt-8">
|
<div class="text-sm w-full mt-8">
|
||||||
<p class="font-medium mb-4">
|
<p class="font-medium mb-4">
|
||||||
{$_("permissions")}
|
{$_("permissions")}
|
||||||
<a
|
<a
|
||||||
class="px-4 py-2 bg-gray-500 rounded-md text-white"
|
class="px-4 py-2 bg-gray-500 rounded-md text-white"
|
||||||
href="/users/{params.userid}/permissions/">{$_("edit-permissions")}</a
|
href="/users/{params.userid}/permissions/">{$_("edit-permissions")}</a
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
<div class="w-full sm:my-px sm:px-px sm:w-1/2">
|
<div class="w-full sm:my-px sm:px-px sm:w-1/2">
|
||||||
<input
|
<input
|
||||||
autocomplete="off"
|
autocomplete="off"
|
||||||
placeholder={$_("search-for-permission")}
|
placeholder={$_("search-for-permission")}
|
||||||
type="text"
|
type="text"
|
||||||
bind:value={search_permission}
|
bind:value={search_permission}
|
||||||
class="mt-4 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-4 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-neutral-800 rounded-md p-2"
|
||||||
/>
|
/>
|
||||||
</div>
|
</div>
|
||||||
{#each original_data.permissions as p}
|
{#each original_data.permissions as p}
|
||||||
{#if p.toLowerCase().includes(search_permission.toLowerCase())}
|
{#if p.toLowerCase().includes(search_permission.toLowerCase())}
|
||||||
<span
|
<span
|
||||||
style="background:{matched_colors[
|
style="background:{matched_colors[
|
||||||
p.split(':')[0]
|
p.split(':')[0]
|
||||||
][0]};color:{matched_colors[p.split(':')[0]][1]};"
|
][0]};color:{matched_colors[p.split(':')[0]][1]};"
|
||||||
class="mt-1 inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-indigo-100 rounded"
|
class="mt-1 inline-flex items-center justify-center px-2 py-1 text-xs font-bold leading-none text-indigo-100 rounded"
|
||||||
>{p}</span
|
>{p}</span
|
||||||
>
|
>
|
||||||
<!-- -->
|
<!-- -->
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
</section>
|
</section>
|
||||||
{:catch error}
|
{:catch error}
|
||||||
<PromiseError {error} />
|
<PromiseError {error} />
|
||||||
{/await}
|
{/await}
|
||||||
@@ -138,7 +138,7 @@
|
|||||||
</nav>
|
</nav>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
<div class="mb-8 text-3xl font-extrabold">
|
<div class="mb-4 text-3xl font-extrabold">
|
||||||
{$_("permissions")}:
|
{$_("permissions")}:
|
||||||
{original_data.firstname}
|
{original_data.firstname}
|
||||||
{original_data.middlename || ""}
|
{original_data.middlename || ""}
|
||||||
@@ -150,13 +150,13 @@
|
|||||||
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"
|
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:w-auto sm:text-sm mb-1 lg:mb-0"
|
||||||
>{$_("save-changes")}</button
|
>{$_("save-changes")}</button
|
||||||
>
|
>
|
||||||
{:else}
|
{:else}
|
||||||
<button
|
<button
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-yellow-600 text-base font-medium text-white hover:bg-yellow-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-yellow-500 sm:ml-3 sm:w-auto sm:text-sm"
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-yellow-600 text-base font-medium text-white hover:bg-yellow-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-yellow-500 sm:w-auto sm:text-sm"
|
||||||
>{$_("applying-changes")}</button
|
>{$_("applying-changes")}</button
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
@@ -203,7 +203,7 @@
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-200 text-base font-medium text-black hover:bg-green-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 sm:ml-3 sm:w-auto sm:text-sm"
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-200 text-base font-medium text-black hover:bg-green-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-green-500 sm:w-auto sm:text-sm"
|
||||||
>+</button
|
>+</button
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
@@ -243,7 +243,7 @@
|
|||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-300 text-base font-medium text-black hover:bg-red-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm"
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-300 text-base font-medium text-black hover:bg-red-700 hover:text-white focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:w-auto sm:text-sm"
|
||||||
>-</button
|
>-</button
|
||||||
>
|
>
|
||||||
</p>
|
</p>
|
||||||
|
|||||||
@@ -8,20 +8,20 @@
|
|||||||
</script>
|
</script>
|
||||||
|
|
||||||
<section class="container p-5">
|
<section class="container p-5">
|
||||||
<span class="mb-1 text-3xl font-extrabold leading-tight">
|
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_("users")}
|
{$_("users")}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("USER:CREATE")}
|
</h4>
|
||||||
<button
|
{#if store.state.jwtinfo.userdetails.permissions.includes("USER:CREATE")}
|
||||||
on:click={() => {
|
<button
|
||||||
modal_open = true;
|
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"
|
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:w-auto sm:text-sm"
|
||||||
{$_("create-user")}
|
>
|
||||||
</button>
|
{$_("create-user")}
|
||||||
{/if}
|
</button>
|
||||||
</span>
|
{/if}
|
||||||
<UsersOverview bind:current_users />
|
<UsersOverview bind:current_users />
|
||||||
</section>
|
</section>
|
||||||
|
|
||||||
|
|||||||
@@ -37,7 +37,7 @@
|
|||||||
bind:value={searchvalue}
|
bind:value={searchvalue}
|
||||||
placeholder={$_("datatable.search")}
|
placeholder={$_("datatable.search")}
|
||||||
aria-label={$_("datatable.search")}
|
aria-label={$_("datatable.search")}
|
||||||
class="mb-4"
|
class="mb-2 w-full sm:w-auto mt-1 sm:mt-0 p-2 rounded-md border"
|
||||||
/>
|
/>
|
||||||
<!-- {/if} -->
|
<!-- {/if} -->
|
||||||
<!-- <button
|
<!-- <button
|
||||||
@@ -45,7 +45,7 @@
|
|||||||
advanced_search = !advanced_search;
|
advanced_search = !advanced_search;
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="w-full inline-flex 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">
|
class="w-full inline-flex 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:w-auto sm:text-sm">
|
||||||
{#if advanced_search}
|
{#if advanced_search}
|
||||||
toggle simple search
|
toggle simple search
|
||||||
{:else}toggle advanced search{/if}
|
{:else}toggle advanced search{/if}
|
||||||
@@ -105,21 +105,21 @@
|
|||||||
<td class="px-6 py-4 whitespace-nowrap">
|
<td class="px-6 py-4 whitespace-nowrap">
|
||||||
{#if u.enabled}
|
{#if u.enabled}
|
||||||
<span
|
<span
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-green-100 text-green-800"
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border bg-green-100 text-green-800"
|
||||||
>{$_("active")}</span
|
>{$_("active")}</span
|
||||||
>
|
>
|
||||||
{:else}
|
{:else}
|
||||||
<span
|
<span
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-red-100 text-red-800"
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border bg-red-100 text-red-800"
|
||||||
>{$_("inactive")}</span
|
>{$_("inactive")}</span
|
||||||
>
|
>
|
||||||
{/if}
|
{/if}
|
||||||
</td>
|
</td>
|
||||||
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500">
|
<td class="px-6 py-4 whitespace-nowrap text-sm text-gray-500 gap-0.5 flex flex-wrap">
|
||||||
{#each u.groups as g}
|
{#each u.groups as g}
|
||||||
<a
|
<a
|
||||||
href="../groups/{g.id}"
|
href="../groups/{g.id}"
|
||||||
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full bg-gray-100 text-gray-800"
|
class="px-2 inline-flex text-xs leading-5 font-semibold rounded-full border bg-gray-100 text-gray-800 border-current"
|
||||||
>{g.name}</a
|
>{g.name}</a
|
||||||
>
|
>
|
||||||
{/each}
|
{/each}
|
||||||
|
|||||||
+21
-19
@@ -37,6 +37,7 @@
|
|||||||
"all-associated-scans-will-get-deleted-as-well": "Alle Scans dieser Station werden ebenfalls gelöscht",
|
"all-associated-scans-will-get-deleted-as-well": "Alle Scans dieser Station werden ebenfalls gelöscht",
|
||||||
"all-associated-teams-and-runners-will-be-deleted-too": "Alle assoziierten Teams und Läufer werden auch gelöscht!",
|
"all-associated-teams-and-runners-will-be-deleted-too": "Alle assoziierten Teams und Läufer werden auch gelöscht!",
|
||||||
"all-cards-loaded": "Alle Karten geladen",
|
"all-cards-loaded": "Alle Karten geladen",
|
||||||
|
"all-donors-loaded": "Alle Sponsoren geladen",
|
||||||
"already-paid": "Bereits bezahlt",
|
"already-paid": "Bereits bezahlt",
|
||||||
"amount": "Anzahl",
|
"amount": "Anzahl",
|
||||||
"amount-per-kilometer": "Betrag pro Kilometer",
|
"amount-per-kilometer": "Betrag pro Kilometer",
|
||||||
@@ -54,9 +55,9 @@
|
|||||||
"cancel-delete": "Löschen abbrechen",
|
"cancel-delete": "Löschen abbrechen",
|
||||||
"cancel-keep-donor": "Abbrechen, Sponsor behalten",
|
"cancel-keep-donor": "Abbrechen, Sponsor 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, Organisation behalten",
|
||||||
"cancel-keep-station": "Abbrechen und Station behalten",
|
"cancel-keep-station": "Abbrechen, Station behalten",
|
||||||
"cancel-keep-statsclient": "Abbrechen und Statsclient behalten",
|
"cancel-keep-statsclient": "Abbrechen, Statsclient behalten",
|
||||||
"cancel-keep-team": "Abbrechen, Team behalten",
|
"cancel-keep-team": "Abbrechen, Team behalten",
|
||||||
"cannot-reset-your-password-directly": "Schade. \nWir können das Passwort leider nicht direkt zurücksetzen.\nBitte sende uns eine Mail in der du deine Identität bestätigst.",
|
"cannot-reset-your-password-directly": "Schade. \nWir können das Passwort leider nicht direkt zurücksetzen.\nBitte sende uns eine Mail in der du deine Identität bestätigst.",
|
||||||
"card": "Läuferkarte",
|
"card": "Läuferkarte",
|
||||||
@@ -78,7 +79,7 @@
|
|||||||
"confirm-delete": "Löschung Bestätigen",
|
"confirm-delete": "Löschung Bestätigen",
|
||||||
"confirm-delete-donor-with-all-donations": "Bestätigen, Sponsor mit allen Sponsorings löschen",
|
"confirm-delete-donor-with-all-donations": "Bestätigen, Sponsor 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.",
|
"confirm-delete-organization-and-associated-teams-runners": "Organisation & alle zugehörigen Teams und Läufer löschen",
|
||||||
"confirm-delete-station-with-all-scans": "Löschen der Scannerstation mit allen Scans bestätigen",
|
"confirm-delete-station-with-all-scans": "Löschen der Scannerstation mit allen Scans bestätigen",
|
||||||
"confirm-delete-statsclient": "Bestätigung, Statsclient löschen",
|
"confirm-delete-statsclient": "Bestätigung, Statsclient löschen",
|
||||||
"confirm-delete-team-and-associated-runners": "Bestätigung, lösche das Team mitsamt seinen Läufern.",
|
"confirm-delete-team-and-associated-runners": "Bestätigung, lösche das Team mitsamt seinen Läufern.",
|
||||||
@@ -111,7 +112,7 @@
|
|||||||
"create-a-new-scanstation": "Neue Station erstellen",
|
"create-a-new-scanstation": "Neue Station erstellen",
|
||||||
"create-a-new-statsclient": "Neuen Statsclient 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": "Neue Laufstrecke erstellen",
|
||||||
"create-a-new-user": "Neuen Benutzer anlegen",
|
"create-a-new-user": "Neuen Benutzer anlegen",
|
||||||
"create-a-new-user-group": "Erstelle eine neue Gruppe",
|
"create-a-new-user-group": "Erstelle eine neue Gruppe",
|
||||||
"create-and-generate-pdf": "Erstellen und PDF herunterladen",
|
"create-and-generate-pdf": "Erstellen und PDF herunterladen",
|
||||||
@@ -119,7 +120,7 @@
|
|||||||
"create-bulk-cards": "Blankokarten erstellen",
|
"create-bulk-cards": "Blankokarten erstellen",
|
||||||
"create-organization": "Organisation erstellen",
|
"create-organization": "Organisation erstellen",
|
||||||
"create-team": "Team erstellen",
|
"create-team": "Team erstellen",
|
||||||
"create-track": "Track erstellen",
|
"create-track": "Laufstrecke erstellen",
|
||||||
"create-user": "Benutzer anlegen",
|
"create-user": "Benutzer anlegen",
|
||||||
"create-without-pdf": "Ohne PDF erstellen",
|
"create-without-pdf": "Ohne PDF erstellen",
|
||||||
"created-blanco-cards": "Blankokarten wurden erstellt",
|
"created-blanco-cards": "Blankokarten wurden erstellt",
|
||||||
@@ -180,7 +181,7 @@
|
|||||||
"distance-in-km": "Distanz (in KM)",
|
"distance-in-km": "Distanz (in KM)",
|
||||||
"distance-track": "Distanz (+Track)",
|
"distance-track": "Distanz (+Track)",
|
||||||
"do-you-really-want-to-delete-your-profile": "Möchtest du dein Profil wirklich löschen?",
|
"do-you-really-want-to-delete-your-profile": "Möchtest du dein Profil wirklich löschen?",
|
||||||
"do-you-want-to-delete-the-organization-delete_org-name": "Möchtest du die Organisation {orgname} löschen?",
|
"do-you-want-to-delete-the-organization-delete_org-name": "Organisation \"{orgname}\" löschen?",
|
||||||
"do-you-want-to-delete-the-team-delete_team-name": "Möchtest du das Team {teamname} löschen?",
|
"do-you-want-to-delete-the-team-delete_team-name": "Möchtest du das Team {teamname} löschen?",
|
||||||
"do-you-want-to-delete-this-donor-with-all-related-donations": "Möchtest du diese Sponsor mit all ihren Sponsorings löschen?",
|
"do-you-want-to-delete-this-donor-with-all-related-donations": "Möchtest du diese Sponsor mit all ihren Sponsorings löschen?",
|
||||||
"documentation": "Dokumentation",
|
"documentation": "Dokumentation",
|
||||||
@@ -270,6 +271,7 @@
|
|||||||
"loading-contact-details": "Kontaktdaten werden geladen ...",
|
"loading-contact-details": "Kontaktdaten werden geladen ...",
|
||||||
"loading-donation-details": "Lade Sponsoringdetails",
|
"loading-donation-details": "Lade Sponsoringdetails",
|
||||||
"loading-donor-details": "Lade Details",
|
"loading-donor-details": "Lade Details",
|
||||||
|
"loading-donors": "Sponsoren werden geladen",
|
||||||
"loading-group-detail": "Lade Gruppendetails...",
|
"loading-group-detail": "Lade Gruppendetails...",
|
||||||
"loading-profile-data": "Lade Profildaten",
|
"loading-profile-data": "Lade Profildaten",
|
||||||
"loading-runners": "Läufer werden geladen...",
|
"loading-runners": "Läufer werden geladen...",
|
||||||
@@ -452,20 +454,20 @@
|
|||||||
"total-paid-amount": "Gezahlt",
|
"total-paid-amount": "Gezahlt",
|
||||||
"total-scans": "Scans",
|
"total-scans": "Scans",
|
||||||
"total_donation_amount_in_eur": "Gesamtbetrag in €",
|
"total_donation_amount_in_eur": "Gesamtbetrag in €",
|
||||||
"track": "Track",
|
"track": "Laufstrecke",
|
||||||
"track-added": "Track hinzugefügt",
|
"track-added": "Laufstrecke hinzugefügt",
|
||||||
"track-data-is-being-loaded": "Trackdaten werden geladen",
|
"track-data-is-being-loaded": "Laufstrecke wird geladen",
|
||||||
"track-deleted": "Track gelöscht",
|
"track-deleted": "Laufstrecke gelöscht",
|
||||||
"track-is-being-added": "Track wird hinzugefügt...",
|
"track-is-being-added": "Laufstrecke wird hinzugefügt...",
|
||||||
"track-is-being-deleted": "Track wird gelöscht",
|
"track-is-being-deleted": "Laufstrecke wird gelöscht",
|
||||||
"track-is-being-updated": "Track wird aktualisiert...",
|
"track-is-being-updated": "Laufstrecke wird aktualisiert...",
|
||||||
"track-length-in-m": "Tracklänge (in Metern)",
|
"track-length-in-m": "Laufstrecke in Metern",
|
||||||
"track-length-must-be-greater-than-0": "Die Länge muss größer als 0 (Meter) sein",
|
"track-length-must-be-greater-than-0": "Die Länge muss größer als 0 (Meter) sein",
|
||||||
"track-name": "Trackname",
|
"track-name": "Name der Laufstrecke",
|
||||||
"track-name-must-not-be-empty": "Der Name muss angegeben werden",
|
"track-name-must-not-be-empty": "Der Name muss angegeben werden",
|
||||||
"track-updated": "Track aktualisiert",
|
"track-updated": "Laufstrecke aktualisiert",
|
||||||
"track-was-updated": "Track wurde aktualisiert",
|
"track-was-updated": "Laufstrecke wurde aktualisiert",
|
||||||
"tracks": "Tracks",
|
"tracks": "Laufstrecken",
|
||||||
"unpaid": "Offen",
|
"unpaid": "Offen",
|
||||||
"update-card": "Karte aktualisieren",
|
"update-card": "Karte aktualisieren",
|
||||||
"update-password": "Passwort ändern",
|
"update-password": "Passwort ändern",
|
||||||
|
|||||||
@@ -37,6 +37,7 @@
|
|||||||
"all-associated-scans-will-get-deleted-as-well": "All associated scans will get deleted as well",
|
"all-associated-scans-will-get-deleted-as-well": "All associated scans will get deleted as well",
|
||||||
"all-associated-teams-and-runners-will-be-deleted-too": "All associated teams and runners will be deleted too!",
|
"all-associated-teams-and-runners-will-be-deleted-too": "All associated teams and runners will be deleted too!",
|
||||||
"all-cards-loaded": "All cards loaded",
|
"all-cards-loaded": "All cards loaded",
|
||||||
|
"all-donors-loaded": "All donors loaded",
|
||||||
"already-paid": "Already paid",
|
"already-paid": "Already paid",
|
||||||
"amount": "Amount",
|
"amount": "Amount",
|
||||||
"amount-per-kilometer": "Amount per kilometer",
|
"amount-per-kilometer": "Amount per kilometer",
|
||||||
@@ -270,6 +271,7 @@
|
|||||||
"loading-contact-details": "Loading contact details...",
|
"loading-contact-details": "Loading contact details...",
|
||||||
"loading-donation-details": "Loading donation details",
|
"loading-donation-details": "Loading donation details",
|
||||||
"loading-donor-details": "Loading donor details",
|
"loading-donor-details": "Loading donor details",
|
||||||
|
"loading-donors": "Loading donors",
|
||||||
"loading-group-detail": "Loading group detail...",
|
"loading-group-detail": "Loading group detail...",
|
||||||
"loading-profile-data": "Loading profile data",
|
"loading-profile-data": "Loading profile data",
|
||||||
"loading-runners": "loading runners...",
|
"loading-runners": "loading runners...",
|
||||||
|
|||||||
@@ -1,5 +1,11 @@
|
|||||||
import "./style.css";
|
import "./style.css";
|
||||||
import App from "./App.svelte";
|
import App from "./App.svelte";
|
||||||
|
import "@fontsource/athiti/200.css";
|
||||||
|
import "@fontsource/athiti/300.css";
|
||||||
|
import "@fontsource/athiti/400.css";
|
||||||
|
import "@fontsource/athiti/500.css";
|
||||||
|
import "@fontsource/athiti/600.css";
|
||||||
|
import "@fontsource/athiti/700.css";
|
||||||
|
|
||||||
const app = new App({
|
const app = new App({
|
||||||
target: document.body,
|
target: document.body,
|
||||||
|
|||||||
@@ -1,3 +1,10 @@
|
|||||||
@tailwind base;
|
@tailwind base;
|
||||||
@tailwind components;
|
@tailwind components;
|
||||||
|
.activenav {
|
||||||
|
@apply bg-gray-300;
|
||||||
|
@apply text-black;
|
||||||
|
}
|
||||||
|
* {
|
||||||
|
font-family: Athiti;
|
||||||
|
}
|
||||||
@tailwind utilities;
|
@tailwind utilities;
|
||||||
@@ -1,4 +1,5 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
|
darkMode: 'selector',
|
||||||
mode: "jit",
|
mode: "jit",
|
||||||
content: ["./src/**/*.svelte"],
|
content: ["./src/**/*.svelte"],
|
||||||
theme: {
|
theme: {
|
||||||
+2
-2
@@ -1,10 +1,10 @@
|
|||||||
import fs from "fs";
|
import fs from "fs";
|
||||||
const packagejson = JSON.parse(
|
const packagejson = JSON.parse(
|
||||||
fs.readFileSync(`./package.json`, { encoding: "utf-8" })
|
fs.readFileSync(`./package.json`, { encoding: "utf-8" }),
|
||||||
);
|
);
|
||||||
const original = fs.readFileSync(`./index.html`, { encoding: "utf-8" });
|
const original = fs.readFileSync(`./index.html`, { encoding: "utf-8" });
|
||||||
let out = original.replace(
|
let out = original.replace(
|
||||||
/RELEASE_INFO-(\S)+-RELEASE_INFO/gi,
|
/RELEASE_INFO-(\S)+-RELEASE_INFO/gi,
|
||||||
"RELEASE_INFO-" + packagejson.version + "-RELEASE_INFO"
|
"RELEASE_INFO-" + packagejson.version + "-RELEASE_INFO",
|
||||||
);
|
);
|
||||||
fs.writeFileSync(`./index.html`, out);
|
fs.writeFileSync(`./index.html`, out);
|
||||||
Reference in new issue
Block a user