Compare commits

...

45 Commits

Author SHA1 Message Date
6364536dcd 🚀RELEASE v1.4.7
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-04 20:30:20 +02:00
a8a771114d Paginated modal data loading 2023-05-04 20:28:21 +02:00
4e0a2c8301 Moved loading to onmount 2023-05-04 20:17:29 +02:00
b6fed92a17 🚀RELEASE v1.4.6
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-04 20:10:57 +02:00
97b57aeb0c fix(donor/detail): Set email to null to avoid vaidation errors 2023-05-04 20:10:21 +02:00
e25ed1fff9 fix(donor/detail): Set phone to null to avoid vaidation errors 2023-05-04 20:09:43 +02:00
a2ff5b8a14 fix(donor/details): don't load donations 2023-05-04 20:07:54 +02:00
0284f18beb 🚀RELEASE v1.4.5
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-04 20:04:02 +02:00
803d64c78c fix: Removed dynamic pagesize adjustments
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-04 20:03:23 +02:00
dacb2f8ace Revert "revert: buggy pagination"
This reverts commit b2648645e8.
2023-05-04 19:57:46 +02:00
b7a53960e5 🚀RELEASE v1.4.4
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-04 14:44:31 +02:00
66f1e6b4fe fix(AddDonationModal): missing toast dismiss on success distance donation
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-04 14:44:17 +02:00
33166bfafc 🚀RELEASE v1.4.3
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-04 14:32:56 +02:00
b2648645e8 revert: buggy pagination
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-04 14:32:37 +02:00
53e3ddb751 🚀RELEASE v1.4.2
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-04 13:55:14 +02:00
edc2dcab92 fix(DonorDetail): missing toast import
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-04 13:53:59 +02:00
d49f545d94 fix(GenerateRunnerCertificates): missing toast import
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-04 13:53:42 +02:00
3b98c99b72 🚀RELEASE v1.4.1
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-01 15:10:55 +02:00
1da775a09b Fixed translation 2023-05-01 15:10:18 +02:00
f0475bd9a0 🚀RELEASE v1.4.0
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-01 15:08:03 +02:00
15d8afefbb Bump dockerfile node
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-01 15:06:15 +02:00
f3bcc01685 Pinned config files used
All checks were successful
continuous-integration/drone/push Build is passing
2023-05-01 15:04:58 +02:00
95238606d5 Switched build image node version
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-01 15:01:49 +02:00
bbf8170cb9 Updated store directory for dockerfil
Some checks failed
continuous-integration/drone/push Build is failing
2023-05-01 14:59:36 +02:00
8c628f23dc Merge pull request 'next' (#180) from next into dev
Some checks failed
continuous-integration/drone/push Build is failing
Reviewed-on: #180
2023-05-01 12:55:19 +00:00
811f5d5754 monospace fonts for IDs in overviews 2023-05-01 14:53:34 +02:00
69ec7fc1fe ScansOverview full month formatting 2023-05-01 14:42:56 +02:00
064197d222 Dynamicly adjust page size for large datasets 2023-05-01 14:35:46 +02:00
e9cf2bc849 Full track table editing 2023-05-01 14:27:56 +02:00
103ad57ddc Added track update toasts 2023-05-01 14:25:22 +02:00
2856c5c1b7 Editing update logic 2023-05-01 14:23:25 +02:00
a953349c14 Updated the track editing switch logic 2023-05-01 14:13:40 +02:00
175d86745f Added edit button for trackscans 2023-05-01 14:05:44 +02:00
081a141218 Implemented delete for new track table 2023-05-01 14:03:46 +02:00
e904ab0b84 fix: a11y in About page 2023-04-27 08:30:12 +02:00
a2f9dbbe01 text cleanups, StatCard improvements 2023-04-27 08:29:07 +02:00
8b922309b9 drop gridjs (TracksOverview Actions will need to be re-implemented) 2023-04-26 23:26:07 +02:00
4c81e3c432 a11y improvements 2023-04-26 23:14:15 +02:00
6c1a707166 cleanup legacy TeamsOverview text 2023-04-26 23:12:03 +02:00
7d8253618b improved StatCard readability 2023-04-26 23:11:01 +02:00
dbaf85799a improved login 2023-04-26 23:09:47 +02:00
daeea24e0e drop middlename for admin users 2023-04-26 23:08:25 +02:00
0fca0352c5 a11y fix OrgOverview 2023-04-26 23:03:53 +02:00
8eaad8219a add missing striped tables 2023-04-26 23:02:13 +02:00
6bc92f4a08 a11y cleanup 2023-04-26 23:02:06 +02:00
46 changed files with 1578 additions and 3027 deletions

View File

@@ -2,8 +2,107 @@
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.4.7](https://git.odit.services/lfk/frontend/compare/1.4.6...1.4.7)
- 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)
#### [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)
> 4 May 2023
- 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)
- 🚀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)
> 4 May 2023
- 🚀RELEASE v1.4.4 [`b7a5396`](https://git.odit.services/lfk/frontend/commit/b7a53960e5f37ae089d77bc11668d917145e2abb)
- fix(AddDonationModal): missing toast dismiss on success distance donation [`66f1e6b`](https://git.odit.services/lfk/frontend/commit/66f1e6b4fe1350ee79673a0aff97e36f44179c92)
#### [1.4.3](https://git.odit.services/lfk/frontend/compare/1.4.2...1.4.3)
> 4 May 2023
- revert: buggy pagination [`b264864`](https://git.odit.services/lfk/frontend/commit/b2648645e8fc05f8742ecfc592557f954261671b)
- 🚀RELEASE v1.4.3 [`33166bf`](https://git.odit.services/lfk/frontend/commit/33166bfafcffb9d86dfc7dfcd2cb8ba5c85da7e7)
#### [1.4.2](https://git.odit.services/lfk/frontend/compare/1.4.1...1.4.2)
> 4 May 2023
- 🚀RELEASE v1.4.2 [`53e3ddb`](https://git.odit.services/lfk/frontend/commit/53e3ddb751c1150a4640ae6302e4df5b88cedc51)
- fix(GenerateRunnerCertificates): missing toast import [`d49f545`](https://git.odit.services/lfk/frontend/commit/d49f545d94acabc0c96860f212466b7a4cbe7dab)
- fix(DonorDetail): missing toast import [`edc2dca`](https://git.odit.services/lfk/frontend/commit/edc2dcab92c3cace05335a283a849c3c978ec8ec)
#### [1.4.1](https://git.odit.services/lfk/frontend/compare/1.4.0...1.4.1)
> 1 May 2023
- 🚀RELEASE v1.4.1 [`3b98c99`](https://git.odit.services/lfk/frontend/commit/3b98c99b72f24b8552e2b2334f13622bdf6ef90d)
- Fixed translation [`1da775a`](https://git.odit.services/lfk/frontend/commit/1da775a09b8be90a49e06aed16df917d221ee989)
#### [1.4.0](https://git.odit.services/lfk/frontend/compare/1.3.4...1.4.0)
> 1 May 2023
- formatting, full migration to svelte-french-toast [`46d076a`](https://git.odit.services/lfk/frontend/commit/46d076af9d65ebb11504a7e6879753780b69db2c)
- drop gridjs (TracksOverview Actions will need to be re-implemented) [`8b92230`](https://git.odit.services/lfk/frontend/commit/8b922309b990c42fcfd57b939abacf4d8c99e638)
- 🚀RELEASE v1.4.0 [`f0475bd`](https://git.odit.services/lfk/frontend/commit/f0475bd9a08d99f58b4d3dce584cd6a3a8630e56)
- Added track update toasts [`103ad57`](https://git.odit.services/lfk/frontend/commit/103ad57ddc8a35ff971bef44053a9e32a7b68233)
- drop legacy ThFilter components [`bc4ac0f`](https://git.odit.services/lfk/frontend/commit/bc4ac0f3160571cd412361de82ef4555ee068677)
- text cleanups, StatCard improvements [`a2f9dbb`](https://git.odit.services/lfk/frontend/commit/a2f9dbbe014b5ae9705e8e7b6944f7f7c576d22e)
- Updated the track editing switch logic [`a953349`](https://git.odit.services/lfk/frontend/commit/a953349c1478b912e08f88c1fb70c74af0bc9bbb)
- chore(deps): bump all [`6154ca7`](https://git.odit.services/lfk/frontend/commit/6154ca7ddfb8b6ad0e1644b8c6756d51f2fbb858)
- svelte-french-toast + translations [`8fb1e0c`](https://git.odit.services/lfk/frontend/commit/8fb1e0ca0f51c90270fb5e1a05be5e8273238a2c)
- Implemented delete for new track table [`081a141`](https://git.odit.services/lfk/frontend/commit/081a141218ab7de2620f7b06083697368d44bf6c)
- striped tabled [`5e82638`](https://git.odit.services/lfk/frontend/commit/5e82638f3594298d0542cd03d5d6aa80aa383b9d)
- add svelte-french-toast [`56c3365`](https://git.odit.services/lfk/frontend/commit/56c33656562079bb773491c8aecedea3f6acdb74)
- Editing update logic [`2856c5c`](https://git.odit.services/lfk/frontend/commit/2856c5c1b786f732b0db80324ea74513e8be186d)
- monospace fonts for IDs in overviews [`811f5d5`](https://git.odit.services/lfk/frontend/commit/811f5d575496be43e5e48197813112d35e79a81f)
- Full track table editing [`e9cf2bc`](https://git.odit.services/lfk/frontend/commit/e9cf2bc8498fc02332059880d7a6994348165b76)
- drop propfilepic [`6952b87`](https://git.odit.services/lfk/frontend/commit/6952b8727f06c520cb60a00acfde1dff52d4f345)
- fix: scan laptime formatting [`01b415d`](https://git.odit.services/lfk/frontend/commit/01b415d4cb147879e959e86d053dc02cae8cfdc9)
- Dynamicly adjust page size for large datasets [`064197d`](https://git.odit.services/lfk/frontend/commit/064197d2226da772907099ecf96c3ab984c9af59)
- ScansOverview full month formatting [`69ec7fc`](https://git.odit.services/lfk/frontend/commit/69ec7fc1fecc67751643ce35f22925f3132b8792)
- translations [`8be40e2`](https://git.odit.services/lfk/frontend/commit/8be40e2d80336f72989deb3e5e20a7cd8f7fb6f1)
- drop middlename for admin users [`daeea24`](https://git.odit.services/lfk/frontend/commit/daeea24e0e99b8a95665167d62d0ee830bdea3de)
- add missing striped tables [`8eaad82`](https://git.odit.services/lfk/frontend/commit/8eaad8219a109fa8b4bd1f719d7079bff8b7c041)
- translation cleanups [`663cb29`](https://git.odit.services/lfk/frontend/commit/663cb29ccde4fa15317f764147187c5b82e748d5)
- Added edit button for trackscans [`175d867`](https://git.odit.services/lfk/frontend/commit/175d86745fb9bfce03fe5f5c638b52467b688938)
- a11y cleanup [`6bc92f4`](https://git.odit.services/lfk/frontend/commit/6bc92f4a080f0c506793866d99c97ccb87ba15b8)
- a11y fix OrgOverview [`0fca035`](https://git.odit.services/lfk/frontend/commit/0fca0352c59cdccb99716355591f88ff573ac949)
- README update [`d32eb82`](https://git.odit.services/lfk/frontend/commit/d32eb8266b0e9daec4b9ba52832d5e5118abec45)
- a11y improvements [`4c81e3c`](https://git.odit.services/lfk/frontend/commit/4c81e3c43218be4b23d137b386520c71d19f5844)
- cleanup legacy TeamsOverview text [`6c1a707`](https://git.odit.services/lfk/frontend/commit/6c1a70716665d57f1326c4475030ae15a7c459e0)
- fix: a11y in About page [`e904ab0`](https://git.odit.services/lfk/frontend/commit/e904ab0b8494ff57579c8954a8eb713fc223a88f)
- improved login [`dbaf857`](https://git.odit.services/lfk/frontend/commit/dbaf85799ac9e56d8760450cfe357df016f10da7)
- chore(deps): node:20.0.0 [`81d4da6`](https://git.odit.services/lfk/frontend/commit/81d4da655099100c631d450caafbf7039fa20592)
- cleanup MainDashContent [`763a01a`](https://git.odit.services/lfk/frontend/commit/763a01af09b36004ceccfa6b182b7dc5ea070128)
- Updated store directory for dockerfil [`bbf8170`](https://git.odit.services/lfk/frontend/commit/bbf8170cb98410bbcd8dc51bb122beee615312ee)
- Bump dockerfile node [`15d8afe`](https://git.odit.services/lfk/frontend/commit/15d8afefbb6b697a6cbdb2d803a7d8edcea4e650)
- Pinned config files used [`f3bcc01`](https://git.odit.services/lfk/frontend/commit/f3bcc01685f3ea3ef6786a8e7d9a5b1a4f829d53)
- Switched build image node version [`9523860`](https://git.odit.services/lfk/frontend/commit/95238606d52ca58985b91ea03f7e9f490fdf2310)
- Merge pull request 'next' (#180) from next into dev [`8c628f2`](https://git.odit.services/lfk/frontend/commit/8c628f23dcfb1f6f120d19bb3ecdb422ca5093cd)
- improved StatCard readability [`7d82536`](https://git.odit.services/lfk/frontend/commit/7d8253618b18719549824ed19e024b8828c9df06)
- new license file version [CI SKIP] [`38a6650`](https://git.odit.services/lfk/frontend/commit/38a665024eb1df3eba66c61d8cb3199000b629e5)
#### [1.3.4](https://git.odit.services/lfk/frontend/compare/1.3.3...1.3.4) #### [1.3.4](https://git.odit.services/lfk/frontend/compare/1.3.3...1.3.4)
> 19 April 2023
- 🚀RELEASE v1.3.4 [`e7b2c64`](https://git.odit.services/lfk/frontend/commit/e7b2c647981111650b3e2e471f4b5195fa6b65b6)
- Smaller sponsoring page size [`7cb6b63`](https://git.odit.services/lfk/frontend/commit/7cb6b63eb9596da4ee84369b220c3e680c607032) - Smaller sponsoring page size [`7cb6b63`](https://git.odit.services/lfk/frontend/commit/7cb6b63eb9596da4ee84369b220c3e680c607032)
#### [1.3.3](https://git.odit.services/lfk/frontend/compare/1.3.2...1.3.3) #### [1.3.3](https://git.odit.services/lfk/frontend/compare/1.3.2...1.3.3)

View File

@@ -2,8 +2,9 @@ FROM registry.odit.services/hub/library/node:20.0.0-alpine3.17 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 *.config.js *.config.cjs index.html ./ COPY package.json pnpm-lock.yaml vite.config.js tailwind.config.js postcss.config.cjs index.html ./
RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@8 && pnpm i RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@8
RUN mkdir /pnpm && pnpm config set store-dir /pnpm && pnpm i
COPY src ./src COPY src ./src
COPY public ./public COPY public ./public

View File

@@ -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.3.4-RELEASE_INFO</span >RELEASE_INFO-1.4.7-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>

View File

@@ -1,6 +1,6 @@
{ {
"name": "@odit/lfk-frontend", "name": "@odit/lfk-frontend",
"version": "1.3.4", "version": "1.4.7",
"type": "module", "type": "module",
"scripts": { "scripts": {
"i18n-order": "node order.js", "i18n-order": "node order.js",
@@ -48,7 +48,6 @@
"bwip-js": "^3.4.0", "bwip-js": "^3.4.0",
"check-password-strength": "2.0.7", "check-password-strength": "2.0.7",
"csvtojson": "2.0.10", "csvtojson": "2.0.10",
"gridjs": "3.4.0",
"localforage": "1.10.0", "localforage": "1.10.0",
"marked": "4.3.0", "marked": "4.3.0",
"svelte": "3.58.0", "svelte": "3.58.0",

3706
pnpm-lock.yaml generated

File diff suppressed because it is too large Load Diff

File diff suppressed because one or more lines are too long

View File

@@ -1,5 +1,4 @@
<script> <script>
import "gridjs/dist/theme/mermaid.css";
import { Route, router } from "tinro"; import { Route, router } from "tinro";
router.subscribe((routeInfo) => { router.subscribe((routeInfo) => {
window.scrollTo(0, 0); window.scrollTo(0, 0);
@@ -23,7 +22,7 @@
name: "lfk_admin", name: "lfk_admin",
version: 1.0, version: 1.0,
storeName: "lfk_admin", storeName: "lfk_admin",
description: "LfK! admin dashbaord", description: "LfK! admin dashboard",
}); });
window.onunhandledrejection = (event) => { window.onunhandledrejection = (event) => {
if (event.reason.toString() == "Error: Unauthorized") { if (event.reason.toString() == "Error: Unauthorized") {

View File

@@ -76,8 +76,8 @@
> >
<div class="max-w-md w-full py-12 px-6" role="main"> <div class="max-w-md w-full py-12 px-6" role="main">
<img style="height:10rem;" class="mx-auto" src="/lfk-logo.png" alt="" /> <img style="height:10rem;" class="mx-auto" src="/lfk-logo.png" alt="" />
<p class="mt-6 text-lg text-center font-bold">{$_("application_name")}</p> <p class="mt-6 text-xl text-center font-bold">{$_("application_name")}</p>
<p class="mt-6 text-sm text-center">{$_("log_in_to_your_account")}</p> <p class="mt-2 mb-6 text-sm text-center">{$_("log_in_to_your_account")}</p>
<div> <div>
<div class="rounded-md shadow-sm"> <div class="rounded-md shadow-sm">
<div> <div>
@@ -129,14 +129,14 @@
</button> </button>
</div> </div>
</div> </div>
<div class="mt-2"> <!-- <div class="mt-2">
<a <a
href="/forgot_password" href="/forgot_password"
class="block w-full text-center py-2 px-3 border border-gray-300 rounded-md font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm" class="block w-full text-center py-2 px-3 border border-gray-300 rounded-md font-medium hover:border-gray-400 focus:outline-none focus:border-gray-400 sm:text-sm"
> >
{$_("forgot_password")} {$_("forgot_password")}
</a> </a>
</div> </div> -->
</div> </div>
</div> </div>
<Footer /> <Footer />

View File

@@ -153,10 +153,11 @@
onMount(async () => { onMount(async () => {
toast.loading($_("loading-cards")); toast.loading($_("loading-cards"));
let page = 0; let page = 0;
let pagesize = 500;
while (page >= 0) { while (page >= 0) {
const cards = await RunnerCardService.runnerCardControllerGetAll( const cards = await RunnerCardService.runnerCardControllerGetAll(
page, page,
150 pagesize
); );
if (cards.length == 0) { if (cards.length == 0) {
page = -2; page = -2;
@@ -310,3 +311,9 @@
<TableBottom {table} {selected} /> <TableBottom {table} {selected} />
{/if} {/if}
{/if} {/if}
<style>
table tbody tr td:nth-child(2) {
font-family: monospace;
}
</style>

View File

@@ -69,7 +69,10 @@
.toString() .toString()
.toLowerCase() .toLowerCase()
.includes(searchvalue)} .includes(searchvalue)}
<tr data-rowid="team_{t.id}"> <tr
class="odd:bg-white even:bg-gray-100"
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">

View File

@@ -20,7 +20,7 @@
> >
<a href="/" class="flex items-center px-4 py-5"> <a href="/" class="flex items-center px-4 py-5">
<img src="/lfk-logo.png" alt="Logo" class="h-10" /> <img src="/lfk-logo.png" alt="Logo" class="h-10" />
<h3 class="text-lg">Lauf für Kaya! Admin</h3> <h3 class="text-lg font-bold">LfK!Admin</h3>
</a> </a>
<nav class="text-sm font-medium text-gray-600" aria-label="Main Navigation"> <nav class="text-sm font-medium text-gray-600" aria-label="Main Navigation">
<a <a
@@ -356,7 +356,7 @@
> >
<span>{$_("about")}</span> <span>{$_("about")}</span>
</a> </a>
<span <button
tabindex="0" tabindex="0"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900" class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-100 hover:text-gray-900"
on:click={() => { on:click={() => {
@@ -377,7 +377,7 @@
/></svg /></svg
> >
<span>{$_("logout")}</span> <span>{$_("logout")}</span>
</span> </button>
</nav> </nav>
</div> </div>
<div class="ml-0 transition md:ml-60"> <div class="ml-0 transition md:ml-60">
@@ -409,7 +409,7 @@
</slot> </slot>
</div> </div>
{#if navOpen === true} {#if navOpen === true}
<div <button
on:click={() => { on:click={() => {
navOpen = false; navOpen = false;
}} }}

View File

@@ -1,31 +1,20 @@
<script> <script>
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import { StatsService } from "@odit/lfk-client-js"; import { StatsService } from "@odit/lfk-client-js";
import StatCards from "./StatCard.svelte";
import store from "../../store"; import store from "../../store";
import StatCard from "./StatCard.svelte"; import StatCard from "./StatCard.svelte";
let navOpen = false; let navOpen = false;
const stats_promise = StatsService.statsControllerGet(); const stats_promise = StatsService.statsControllerGet();
</script> </script>
<div <div class="p-2 md:p-5 overflow-x-hidden">
class="p-5 overflow-x-hidden" <h1 class="text-3xl leading-tight mb-4">
on:click={() => { {$_("dashboard-greeting")},
navOpen = false; <span class="text-blue-500"
}} >{store.state.jwtinfo.userdetails.firstname}
> {store.state.jwtinfo.userdetails.lastname}</span
<h1 class="text-3xl leading-tight">
<span class="font-extrabold">{$_("dashboard-title")}</span>
<span>
-
{$_("dashboard-greeting")},
<span class="text-blue-500"
>{store.state.jwtinfo.userdetails.firstname}
{store.state.jwtinfo.userdetails.lastname}</span
></span
> >
</h1> </h1>
<h1>{$_("general-stats")}</h1>
{#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"
@@ -36,7 +25,7 @@
</div> </div>
{:then stats} {:then stats}
<div <div
class="grid grid-cols-1 sm:grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 2xl:grid-cols-6 gap-4" class="grid gap-2 grid-cols-2 lg:grid-cols-3 xl:grid-cols-5 2xl:grid-cols-6 sm:gap-4"
> >
<StatCard <StatCard
title={$_("runners")} title={$_("runners")}
@@ -109,24 +98,35 @@
</StatCard> </StatCard>
<StatCard <StatCard
title={$_("average-donation")} title={$_("average-donation")}
value={`${(stats.average_donation / 100).toFixed(2)} €`} value={`${parseFloat(stats.average_donation / 100).toLocaleString(
undefined,
{
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}
)}`}
href="/donations/" href="/donations/"
> >
<svg <svg
fill="currentColor"
xmlns="http://www.w3.org/2000/svg" xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
width="24"
height="24" height="24"
><path fill="none" d="M0 0h24v24H0z" /> fill="currentColor"
width="24"
><path d="M0 0h24v24H0z" fill="none" />
<path <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" d="M15 18.5A6.48 6.48 0 019.24 15H15v-2H8.58c-.05-.33-.08-.66-.08-1s.03-.67.08-1H15V9H9.24A6.491 6.491 0 0115 5.5c1.61 0 3.09.59 4.23 1.57L21 5.3A8.955 8.955 0 0015 3c-3.92 0-7.24 2.51-8.48 6H3v2h3.06a8.262 8.262 0 000 2H3v2h3.52c1.24 3.49 4.56 6 8.48 6 2.31 0 4.41-.87 6-2.3l-1.78-1.77c-1.13.98-2.6 1.57-4.22 1.57z"
/></svg /></svg
> >
</StatCard> </StatCard>
<StatCard <StatCard
title={$_("total-donations")} title={$_("total-donations")}
value={`${(stats.total_donation / 100).toFixed(2)} €`} value={`${parseFloat(stats.total_donation / 100).toLocaleString(
undefined,
{
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}
)}`}
href="/donations/" href="/donations/"
> >
<svg <svg
@@ -142,7 +142,7 @@
</StatCard> </StatCard>
<StatCard <StatCard
title={$_("total-distance")} title={$_("total-distance")}
value={`${stats.total_distance / 1000} km`} value={`${stats.total_distance / 1000}km`}
href="/scans/" href="/scans/"
> >
<svg <svg
@@ -158,7 +158,13 @@
</StatCard> </StatCard>
<StatCard <StatCard
title={$_("average-distance")} title={$_("average-distance")}
value={`${(stats.average_distance / 1000).toFixed(2)} km`} value={`${parseFloat(stats.average_distance / 1000).toLocaleString(
undefined,
{
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}
)}km`}
href="/scans/" href="/scans/"
> >
<svg <svg

View File

@@ -10,10 +10,10 @@
<div class="p-4 rounded-lg bg-white border border-grey-100"> <div class="p-4 rounded-lg bg-white border border-grey-100">
<div class="flex flex-row items-center justify-between"> <div class="flex flex-row items-center justify-between">
<div class="flex flex-col"> <div class="flex flex-col">
<div class="text-xs uppercase font-light text-grey-500"> <div class="text-xs uppercase font-normal text-grey-500">
{title} {title}
</div> </div>
<div class="text-xl font-bold">{value}</div> <div class="text-xl font-bold font-mono">{value}</div>
</div> </div>
<slot /> <slot />
</div> </div>

View File

@@ -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;
@@ -95,6 +85,7 @@
amount_input = 0; amount_input = 0;
modal_open = false; modal_open = false;
// //
toast.dismiss();
toast.success($_("donation_added")); toast.success($_("donation_added"));
dispatch("created", { donations: [result] }); dispatch("created", { donations: [result] });
}) })
@@ -107,6 +98,35 @@
} }
} }
} }
onMount(()=>{
loadDonorsAndRunnersPaginated();
})
async function loadDonorsAndRunnersPaginated() {
let page = 0;
let pagesize = 500;
while (page >= 0) {
const don = await DonorService.donorControllerGetAll(page, pagesize);
const run = await RunnerService.runnerControllerGetAll(page, pagesize);
if (don.length == 0 && run.length == 0) {
page = -2;
}
donors = donors.concat(
...run.map((r) => {
return { label: getDonorLabel(r), value: r };
})
);
runners = runners.concat(
...run.map((r) => {
return { label: getDonorLabel(r), value: r };
})
);
dataLoaded = true;
page++;
}
}
</script> </script>
{#if modal_open} {#if modal_open}

View File

@@ -6,7 +6,7 @@
DonorService, DonorService,
RunnerService, RunnerService,
} from "@odit/lfk-client-js"; } 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;

View File

@@ -168,10 +168,11 @@
onMount(async () => { onMount(async () => {
let page = 0; let page = 0;
let pagesize = 300;
while (page >= 0) { while (page >= 0) {
const donations = await DonationService.donationControllerGetAll( const donations = await DonationService.donationControllerGetAll(
page, page,
100 pagesize
); );
if (donations.length == 0) { if (donations.length == 0) {
page = -2; page = -2;
@@ -279,3 +280,9 @@
<TableBottom {table} {selected} /> <TableBottom {table} {selected} />
{/if} {/if}
{/if} {/if}
<style>
table tbody tr td:nth-child(2) {
font-family: monospace;
}
</style>

View File

@@ -2,16 +2,16 @@
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import store from "../../store"; import store from "../../store";
import { DonorService, DonationService } from "@odit/lfk-client-js"; import { DonorService, DonationService } 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 ConfirmDonorDeletion from "./ConfirmDonorDeletion.svelte"; import ConfirmDonorDeletion from "./ConfirmDonorDeletion.svelte";
import toast from "svelte-french-toast";
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_donations = [];
$: changes_performed = !( $: changes_performed = !(
JSON.stringify(original_data) === JSON.stringify(editable) JSON.stringify(original_data) === JSON.stringify(editable)
); );
@@ -28,11 +28,6 @@
isPhoneValidOrEmpty && isPhoneValidOrEmpty &&
((isAddress1Valid && iszipcodevalid && iscityvalid) || ((isAddress1Valid && iszipcodevalid && iscityvalid) ||
editable.address_checked === false); editable.address_checked === false);
const donation_promise = DonationService.donationControllerGetAll().then(
(val) => {
current_donations = val;
}
);
const promise = DonorService.donorControllerGetOne(params.donorid).then( const promise = DonorService.donorControllerGetOne(params.donorid).then(
(data) => { (data) => {
data_loaded = true; data_loaded = true;
@@ -68,7 +63,9 @@
editable.address = null; editable.address = null;
} }
if (editable.email) editable.email = editable.email; if (editable.email) editable.email = editable.email;
else editable.email = null;
if (editable.phone) editable.phone = editable.phone; if (editable.phone) editable.phone = editable.phone;
else editable.phone = null;
if (editable.middlename) editable.middlename = editable.middlename; if (editable.middlename) editable.middlename = editable.middlename;
editable.receiptNeeded = editable.address_checked; editable.receiptNeeded = editable.address_checked;
DonorService.donorControllerPut(original_data.id, editable) DonorService.donorControllerPut(original_data.id, editable)
@@ -95,7 +92,7 @@
</script> </script>
<ConfirmDonorDeletion bind:modal_open bind:delete_donor /> <ConfirmDonorDeletion bind:modal_open bind:delete_donor />
{#await promise && donation_promise} {#await promise}
{$_("loading-donor-details")} {$_("loading-donor-details")}
{:then} {:then}
<section class="container p-5 select-none"> <section class="container p-5 select-none">
@@ -205,8 +202,8 @@
> >
<br /> <br />
<span class="font-medium text-gray-700">{$_("donations")}:</span> <span class="font-medium text-gray-700">{$_("donations")}:</span>
{#if current_donations.filter((d) => d.donor.id == editable.id).length > 0} {#if original_data.donations.length > 0}
{#each current_donations.filter((o) => o.donor.id == editable.id) as d} {#each original_data.donations as d}
{#if d.responseType === "DISTANCEDONATION"} {#if d.responseType === "DISTANCEDONATION"}
<a <a
href="../donations/{d.id}" href="../donations/{d.id}"

View File

@@ -147,8 +147,9 @@
onMount(async () => { onMount(async () => {
let page = 0; let page = 0;
let pagesize = 300;
while (page >= 0) { while (page >= 0) {
const donors = await DonorService.donorControllerGetAll(page, 500); const donors = await DonorService.donorControllerGetAll(page, pagesize);
if (donors.length == 0) { if (donors.length == 0) {
page = -2; page = -2;
} }
@@ -253,3 +254,9 @@
<TableBottom {table} {selected} /> <TableBottom {table} {selected} />
{/if} {/if}
{/if} {/if}
<style>
table tbody tr td:nth-child(2) {
font-family: monospace;
}
</style>

View File

@@ -145,14 +145,14 @@
<tr class="odd:bg-white even:bg-gray-100"> <tr class="odd:bg-white even:bg-gray-100">
<td>{l.name}</td> <td>{l.name}</td>
<td> <td>
{l.license || "?"}<br /><span {l.license || "?"}<br /><button
class="underline cursor-pointer" class="underline cursor-pointer"
on:click={() => { on:click={() => {
modal_open = true; modal_open = true;
currentlicense = l.name + "@" + l.version; currentlicense = l.name + "@" + l.version;
licensetext = licensetext =
l.licensetext || $_("no-license-text-could-be-found"); l.licensetext || $_("no-license-text-could-be-found");
}}>{$_("read-license")}</span }}>{$_("read-license")}</button
> >
</td> </td>
<td> <td>

View File

@@ -2,7 +2,7 @@
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 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;
@@ -215,7 +215,7 @@
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 dark:bg-gray-900 dark:text-gray-100 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-gray-500 rounded-md p-2"
/> />
</div> </div>
{#each original_data.permissions as p} {#each original_data.permissions as p}

View File

@@ -173,7 +173,7 @@
{#each allpermissions as p} {#each allpermissions as p}
{#if !(grantedPermissions.filter((o) => p.target == o.target && p.action == o.action).length > 0)} {#if !(grantedPermissions.filter((o) => p.target == o.target && p.action == o.action).length > 0)}
<p <p
class="block w-full mt-1 text-sm dark:border-gray-600 dark:bg-gray-700 bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:text-gray-300 dark:focus:shadow-outline-gray form-input" class="block w-full mt-1 text-sm bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple form-input"
> >
{p.target + ":" + p.action} {p.target + ":" + p.action}
<button <button
@@ -206,7 +206,7 @@
> >
{#each grantedPermissions as p} {#each grantedPermissions as p}
<p <p
class="block w-full mt-1 text-sm dark:border-gray-600 dark:bg-gray-700 bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:text-gray-300 dark:focus:shadow-outline-gray form-input" class="block w-full mt-1 text-sm bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple form-input"
> >
{p.target + ":" + p.action} {p.target + ":" + p.action}
<button <button

View File

@@ -62,7 +62,10 @@
.toString() .toString()
.toLowerCase() .toLowerCase()
.includes(searchvalue)} .includes(searchvalue)}
<tr data-rowid="user_{group.id}"> <tr
class="odd:bg-white even:bg-gray-100"
data-rowid="user_{group.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">

View File

@@ -4,7 +4,7 @@
RunnerOrganizationService, RunnerOrganizationService,
} from "@odit/lfk-client-js"; } from "@odit/lfk-client-js";
import { getLocaleFromNavigator, _ } from "svelte-i18n"; import { getLocaleFromNavigator, _ } from "svelte-i18n";
import store from "../../store"; import store from "../../store";
import ConfirmOrgDeletion from "./ConfirmOrgDeletion.svelte"; import ConfirmOrgDeletion from "./ConfirmOrgDeletion.svelte";
import ImportRunnerModal from "../runners/ImportRunnerModal.svelte"; import ImportRunnerModal from "../runners/ImportRunnerModal.svelte";
@@ -109,7 +109,7 @@
} }
async function copy() { async function copy() {
if (!editable.registrationKey) { if (!editable.registrationKey) {
toast.error($_("you-have-to-save-your-changes-to-generate-a-link")) toast.error($_("you-have-to-save-your-changes-to-generate-a-link"));
return; return;
} }
valueCopy = registrationLink; valueCopy = registrationLink;
@@ -124,7 +124,7 @@
toast($_("copied-link-to-clipboard")); toast($_("copied-link-to-clipboard"));
copied = true; copied = true;
} catch (err) { } catch (err) {
toast.error($_("error-whyile-copying-to-clipboard")) toast.error($_("error-whyile-copying-to-clipboard"));
} }
// we can notifi by event or storage about copy status // we can notifi by event or storage about copy status
valueCopy = null; valueCopy = null;

View File

@@ -78,7 +78,7 @@
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"
> >
<span <button
on:click={() => { on:click={() => {
const newstate = !current_organizations.some( const newstate = !current_organizations.some(
(r) => r.is_selected === true (r) => r.is_selected === true
@@ -92,7 +92,7 @@
>{#if current_organizations.some((r) => r.is_selected === true)} >{#if current_organizations.some((r) => r.is_selected === true)}
{$_("deselect-all")} {$_("deselect-all")}
{:else}{$_("select-all")}{/if} {:else}{$_("select-all")}{/if}
</span> </button>
</th> </th>
<th <th
scope="col" scope="col"
@@ -123,7 +123,10 @@
.toString() .toString()
.toLowerCase() .toLowerCase()
.includes(searchvalue)} .includes(searchvalue)}
<tr data-rowid="org_{o.id}"> <tr
class="odd:bg-white even:bg-gray-100"
data-rowid="org_{o.id}"
>
<td class="px-6 py-4 whitespace-nowrap"> <td class="px-6 py-4 whitespace-nowrap">
<input <input
bind:checked={o.is_selected} bind:checked={o.is_selected}

View File

@@ -5,8 +5,8 @@
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";
const createId = init({ length: 10, fingerprint: "lfk-frontend" }); const createId = init({ length: 10, fingerprint: "lfk-frontend" });
export let certificates_show = false; export let certificates_show = false;

View File

@@ -163,7 +163,7 @@
let page = 0; let page = 0;
while (page >= 0) { while (page >= 0) {
const runners = await RunnerService.runnerControllerGetAll(page, 1000); const runners = await RunnerService.runnerControllerGetAll(page, 500);
if (runners.length == 0) { if (runners.length == 0) {
page = -2; page = -2;
} }
@@ -259,3 +259,9 @@
{/if} {/if}
{/if} {/if}
<TableBottom {table} {selected} /> <TableBottom {table} {selected} />
<style>
table tbody tr td:nth-child(2) {
font-family: monospace;
}
</style>

View File

@@ -2,7 +2,7 @@
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;

View File

@@ -86,7 +86,17 @@
accessorKey: "timestamp", accessorKey: "timestamp",
header: () => $_("timestamp"), header: () => $_("timestamp"),
cell: (info) => { cell: (info) => {
return new Date(parseInt(info.getValue()) * 1000).toLocaleString(); return new Date(parseInt(info.getValue()) * 1000).toLocaleString(
{ language: "de-DE" },
{
day: "2-digit",
month: "2-digit",
year: "numeric",
hour: "2-digit",
minute: "2-digit",
second: "2-digit",
}
);
}, },
enableColumnFilter: false, enableColumnFilter: false,
}, },
@@ -169,8 +179,9 @@
onMount(async () => { onMount(async () => {
let page = 0; let page = 0;
let pagesize = 500;
while (page >= 0) { while (page >= 0) {
const scans = await ScanService.scanControllerGetAll(page, 500); const scans = await ScanService.scanControllerGetAll(page, pagesize);
if (scans.length == 0) { if (scans.length == 0) {
page = -2; page = -2;
} }
@@ -292,3 +303,9 @@
<TableBottom {table} {selected} /> <TableBottom {table} {selected} />
{/if} {/if}
{/if} {/if}
<style>
table tbody tr td:nth-child(2) {
font-family: monospace;
}
</style>

View File

@@ -159,7 +159,7 @@
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 border border-transparent ring-1 ring-transparent focus:border-blue-600 focus:ring-blue-600 ring-offset-white focus:outline-none appearance-none before:inline-block before:w-6 before:h-6 before:bg-white checked:before:bg-blue-200 before:translate-x-0 checked:before:translate-x-full before:shadow before:rounded-full before:transform before:ring-0 before:transition before:ease-in-out before:duration-200 dark:before:bg-gray-400 dark:checked:before:bg-blue-200" 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

View File

@@ -2,7 +2,7 @@
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";

View File

@@ -80,7 +80,10 @@
.toString() .toString()
.toLowerCase() .toLowerCase()
.includes(searchvalue)} .includes(searchvalue)}
<tr data-rowid="station_{s.id}"> <tr
class="odd:bg-white even:bg-gray-100"
data-rowid="station_{s.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">

View File

@@ -2,7 +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 ConfirmProfileDeletion from "./ConfirmProfileDeletion.svelte"; import ConfirmProfileDeletion from "./ConfirmProfileDeletion.svelte";
import PasswordStrength, { import PasswordStrength, {
password_strong_enough_and_equal, password_strong_enough_and_equal,
@@ -100,7 +100,7 @@
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 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/> />
</div> </div>
<div class="text-sm w-full"> <div class="text-sm w-full">
@@ -113,7 +113,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 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/> />
</div> </div>
{#if !isEmail(editable.email)} {#if !isEmail(editable.email)}
@@ -132,10 +132,10 @@
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 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/> />
</div> </div>
<div class="text-sm w-full"> <!-- <div class="text-sm w-full">
<label for="middlename" class="font-medium text-gray-700" <label for="middlename" class="font-medium text-gray-700"
>{$_("middle-name")}</label >{$_("middle-name")}</label
> >
@@ -145,9 +145,9 @@
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 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/> />
</div> </div> -->
<div class="text-sm w-full"> <div class="text-sm w-full">
<label for="lastname" class="font-medium text-gray-700" <label for="lastname" class="font-medium text-gray-700"
>{$_("last-name")}</label >{$_("last-name")}</label
@@ -158,7 +158,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 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/> />
</div> </div>
</div> </div>

View File

@@ -74,7 +74,10 @@
.toString() .toString()
.toLowerCase() .toLowerCase()
.includes(searchvalue)} .includes(searchvalue)}
<tr data-rowid="station_{c.id}"> <tr
class="odd:bg-white even:bg-gray-100"
data-rowid="station_{c.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">

View File

@@ -5,7 +5,7 @@
RunnerTeamService, RunnerTeamService,
} from "@odit/lfk-client-js"; } from "@odit/lfk-client-js";
import { getLocaleFromNavigator, _ } from "svelte-i18n"; import { getLocaleFromNavigator, _ } from "svelte-i18n";
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";

View File

@@ -22,9 +22,6 @@
</button> </button>
{/if} {/if}
</span> </span>
<p class="mb-8 text-lg text-gray-500">
{$_("everything-is-more-fun-together")}
</p>
<TeamsOverview bind:current_teams /> <TeamsOverview bind:current_teams />
</section> </section>

View File

@@ -77,7 +77,7 @@
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"
> >
<span <button
on:click={() => { on:click={() => {
const newstate = !current_teams.some( const newstate = !current_teams.some(
(r) => r.is_selected === true (r) => r.is_selected === true
@@ -91,7 +91,7 @@
>{#if current_teams.some((r) => r.is_selected === true)} >{#if current_teams.some((r) => r.is_selected === true)}
{$_("deselect-all")} {$_("deselect-all")}
{:else}{$_("select-all")}{/if} {:else}{$_("select-all")}{/if}
</span> </button>
</th> </th>
<th <th
scope="col" scope="col"
@@ -122,7 +122,10 @@
.toString() .toString()
.toLowerCase() .toLowerCase()
.includes(searchvalue)} .includes(searchvalue)}
<tr data-rowid="team_{t.id}"> <tr
class="odd:bg-white even:bg-gray-100"
data-rowid="team_{t.id}"
>
<td class="px-6 py-4 whitespace-nowrap"> <td class="px-6 py-4 whitespace-nowrap">
<input <input
bind:checked={t.is_selected} bind:checked={t.is_selected}

View File

@@ -1,193 +0,0 @@
<script>
import { _, json } from "svelte-i18n";
import TracksEmptyState from "./TracksEmptyState.svelte";
import { TrackService } from "@odit/lfk-client-js";
const tracks_promise = TrackService.trackControllerGetAll();
import { getlang } from "../base/datatable_i18n";
import { Grid, html } from "gridjs";
import { tracks as tracksstore } from "../../store.js";
import toast from "svelte-french-toast";
$: trackscache = [];
$: blocked = [];
let table;
let datatable;
let datatable_inited = false;
tracksstore.subscribe((val) => {
trackscache = val;
setTimeout(() => {
if (val.length > 0) {
renderdatatable();
}
}, 100);
});
tracks_promise.then((data) => {
tracksstore.set(data);
});
window.track__edit_cancel = () => renderdatatable();
window.track__edit_save = () => {
const trackid = parseInt(window.event.target.getAttribute("data-trackid"));
if (blocked.includes(trackid)) {
//
} else {
blocked.push(trackid);
const elem = document.querySelector(
`[data-id="triggered_table_actions_${trackid}"]`
).parentNode.parentNode.parentNode;
toast.loading($_("track-is-being-updated"));
TrackService.trackControllerPut(trackid, {
id: trackid,
name: elem.childNodes[0].childNodes[0].value,
distance: parseInt(elem.childNodes[1].childNodes[0].value),
minimumLapTime: parseInt(elem.childNodes[2].childNodes[0].value),
})
.then((r) => {
toast.dismiss();
toast.success($_("track-was-updated"));
blocked = blocked.filter((e) => e !== trackid);
document
.querySelector(`[data-id="default_table_actions_${trackid}"]`)
.classList.remove("hidden");
document
.querySelector(`[data-id="triggered_table_actions_${trackid}"]`)
.classList.add("hidden");
//
elem.childNodes[0].innerHTML = `<td data-column-id="trackName" class="gridjs-td">${elem.childNodes[0].childNodes[0].value}</td>`;
elem.childNodes[1].innerHTML = `<td data-column-id="trackName" class="gridjs-td">${elem.childNodes[1].childNodes[0].value}</td>`;
elem.childNodes[2].innerHTML = `<td data-column-id="trackName" class="gridjs-td">${elem.childNodes[2].childNodes[0].value}</td>`;
})
.catch((err) => {});
}
};
window.track__delete_handler = () => {
const trackid = parseInt(window.event.target.getAttribute("data-trackid"));
document
.querySelector(`[data-id="default_table_actions_${trackid}"]`)
.classList.add("hidden");
document
.querySelector(`[data-id="deleteconfirmation_table_actions_${trackid}"]`)
.classList.remove("hidden");
};
window.track__delete_cancel = () => {
const trackid = parseInt(window.event.target.getAttribute("data-trackid"));
document
.querySelector(`[data-id="default_table_actions_${trackid}"]`)
.classList.remove("hidden");
document
.querySelector(`[data-id="deleteconfirmation_table_actions_${trackid}"]`)
.classList.add("hidden");
};
window.track__delete_confirm = () => {
const trackid = parseInt(window.event.target.getAttribute("data-trackid"));
TrackService.trackControllerRemove(trackid)
.then(() => {
const newStoreVal = trackscache.filter((obj) => obj.id !== trackid);
tracksstore.set(newStoreVal);
renderdatatable();
})
.catch((err) => {});
};
window.track__edit_handler = () => {
const trackid = parseInt(window.event.target.getAttribute("data-trackid"));
document
.querySelector(`[data-id="default_table_actions_${trackid}"]`)
.classList.add("hidden");
document
.querySelector(`[data-id="triggered_table_actions_${trackid}"]`)
.classList.remove("hidden");
const elem = document.querySelector(
`[data-id="triggered_table_actions_${trackid}"]`
).parentNode.parentNode.parentNode;
const trackname = elem.childNodes[0].textContent;
const tracklength = parseInt(elem.childNodes[1].textContent);
const trackmintime = parseInt(elem.childNodes[2].textContent);
elem.childNodes[0].innerHTML = `<input type="text" value="${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">`;
elem.childNodes[1].innerHTML = `<input type="text" value="${tracklength}" name="tracklength" 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">`;
elem.childNodes[2].innerHTML = `<input type="text" value="${trackmintime}" name="trackmintime" 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">`;
};
//
function renderdatatable() {
let tabledata = [];
trackscache.forEach((track) => {
tabledata.push([
track.name,
track.distance,
track.minimumLapTime || 0,
html(`
<div class="hidden" data-id="triggered_table_actions_${track.id}">
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-green-400 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${
track.id
}" onclick="track__edit_save()">${$_("save")}</button>
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-500 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${
track.id
}" onclick="track__edit_cancel()">${$_("cancel")}</button>
</div>
<div data-id="default_table_actions_${track.id}">
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-400 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${
track.id
}" onclick="track__edit_handler()">${$_("edit")}</button>
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-500 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${
track.id
}" onclick="track__delete_handler()">${$_("delete")}</button>
</div>
<div class="hidden" data-id="deleteconfirmation_table_actions_${
track.id
}">
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-400 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${
track.id
}" onclick="track__delete_cancel()">${$_("cancel")}</button>
<button class="w-full inline-flex justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-red-500 text-base font-medium text-white sm:w-auto sm:text-sm" data-trackid="${
track.id
}" onclick="track__delete_confirm()">${$_("confirm")}</button>
</div>
`),
]);
});
if (datatable_inited === false) {
datatable = new Grid({
columns: [
$_("track-name"),
$_("track-length-in-m"),
$_("minimum-lap-time-in-s"),
$_("action"),
],
language: getlang($json("datatable")),
sort: true,
search: { enabled: true },
data: tabledata,
pagination: {
enabled: true,
limit: 25,
summary: false,
},
}).render(table);
datatable_inited = true;
} else {
datatable.updateConfig({ data: tabledata }).forceRender();
}
}
</script>
{#if trackscache.length > 0}
<div bind:this={table} />
{/if}
{#await tracks_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">{$_("track-data-is-being-loaded")}</p>
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
</div>
{:then}
{#if trackscache.length === 0}
<TracksEmptyState />
{/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}

View File

@@ -2,7 +2,20 @@
import { _ } from "svelte-i18n"; import { _ } from "svelte-i18n";
import AddTrackModal from "./AddTrackModal.svelte"; import AddTrackModal from "./AddTrackModal.svelte";
let modal_open = false; let modal_open = false;
import Tracks from "./Tracks.svelte"; import TracksEmptyState from "./TracksEmptyState.svelte";
import { TrackService } from "@odit/lfk-client-js";
const tracks_promise = TrackService.trackControllerGetAll();
import { tracks as tracksstore } from "../../store.js";
import toast from "svelte-french-toast";
$: trackscache = [];
$: deleteTracks = [];
$: editTracks = [];
tracksstore.subscribe((val) => {
trackscache = val;
});
tracks_promise.then((data) => {
tracksstore.set(data);
});
</script> </script>
<section class="container p-5"> <section class="container p-5">
@@ -18,9 +31,238 @@
{$_("create-track")} {$_("create-track")}
</button> </button>
</span> </span>
<p class="mb-8 text-lg text-gray-500"> {#await tracks_promise}
{$_("configure-the-tracks-and-minimum-lap-times")} <div
</p> class="bg-teal-lightest border-t-4 border-teal rounded-b text-teal-darkest px-4 py-3 shadow-md my-2"
<Tracks /> role="alert"
>
<p class="font-bold">{$_("track-data-is-being-loaded")}</p>
<p class="text-sm">{$_("this-might-take-a-moment")}</p>
</div>
{:then}
{#if trackscache.length === 0}
<TracksEmptyState />
{:else}
<div
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll mt-4"
>
<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"
>
ID
</th>
<th
scope="col"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
>
{$_("track-name")}
</th>
<th
scope="col"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
>
{$_("distance")}
</th>
<th
scope="col"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
>
{$_("minimum-lap-time-in-s")}
</th>
<th
scope="col"
class="px-6 py-3 text-left text-xs font-medium text-gray-500 uppercase tracking-wider"
>
{$_("action")}
</th>
</tr>
</thead>
<tbody class="divide-y divide-gray-200">
{#each trackscache as t}
<tr
class="odd:bg-white even:bg-gray-100"
data-rowid="station_{t.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">
#{t.id}
</div>
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="ml-4">
{#if editTracks.findIndex((tr) => tr.id === t.id) !== -1}
<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"
type="text"
value={t.name}
on:input={(e) => {
const i = editTracks.findIndex(
(tr) => tr.id === t.id
);
editTracks[i].name = e.target.value;
}}
/>
{:else}
<div class="text-sm font-medium text-gray-900">
{t.name}
</div>
{/if}
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="ml-4">
{#if editTracks.findIndex((tr) => tr.id === t.id) !== -1}
<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"
type="number"
value={t.distance}
on:input={(e) => {
const i = editTracks.findIndex(
(tr) => tr.id === t.id
);
editTracks[i].distance = parseInt(e.target.value);
}}
/>
{:else}
<div class="text-sm font-medium text-gray-900">
{t.distance}
</div>
{/if}
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
<div class="ml-4">
{#if editTracks.findIndex((tr) => tr.id === t.id) !== -1}
<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"
type="number"
value={t.minimumLapTime}
on:input={(e) => {
const i = editTracks.findIndex(
(tr) => tr.id === t.id
);
editTracks[i].minimumLapTime = parseInt(e.target.value);
}}
/>
{:else}
<div class="text-sm font-medium text-gray-900">
{t.minimumLapTime}
</div>
{/if}
</div>
</div>
</td>
<td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center">
{#if deleteTracks.includes(t.id)}
<button
tabindex="0"
on:click={() => {
deleteTracks = deleteTracks.filter((tr) => {
tr.id !== t.id;
});
}}
class="ml-4 text-gray-600 hover:text-gray-900 cursor-pointer"
>{$_("cancel")}</button
>
<button
tabindex="0"
on:click={async () => {
TrackService.trackControllerRemove(t.id);
deleteTracks = deleteTracks.filter((tr) => {
tr.id !== t.id;
});
tracksstore.set(
$tracksstore.filter((tr) => tr.id !== t.id)
);
toast($_("track-deleted"));
}}
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
>{$_("confirm-delete")}</button
>
{:else if editTracks.findIndex((tr) => tr.id === t.id) !== -1}
<button
tabindex="0"
on:click={() => {
editTracks = editTracks.filter((tr) => {
tr.id !== t.id;
});
}}
class="ml-4 text-gray-600 hover:text-gray-900 cursor-pointer"
>{$_("cancel")}</button
>
<button
tabindex="0"
on:click={async () => {
toast.loading($_("track-is-being-updated"));
const i = editTracks.findIndex(
(tr) => tr.id === t.id
);
const res = await TrackService.trackControllerPut(
t.id,
editTracks[i]
);
tracksstore.set(
$tracksstore.filter((tr) => tr.id !== t.id)
);
$tracksstore.push(res)
editTracks = editTracks.filter((tr) => {
tr.id !== t.id;
});
toast.dismiss();
toast.success($_("track-updated"));
}}
class="ml-4 text-green-600 hover:text-green-900 cursor-pointer"
>{$_("save")}</button
>
{:else}
<button
tabindex="0"
on:click={() => {
editTracks.push(t);
editTracks = editTracks;
}}
class="ml-4 text-indigo-600 hover:text-indigo-900 cursor-pointer"
>{$_("edit")}</button
>
<button
tabindex="0"
on:click={() => {
deleteTracks.push(t.id);
deleteTracks = deleteTracks;
}}
class="ml-4 text-red-600 hover:text-red-900 cursor-pointer"
>{$_("delete")}</button
>
{/if}
</div>
</td>
</tr>
{/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}
</section> </section>
<AddTrackModal bind:modal_open /> <AddTrackModal bind:modal_open />

View File

@@ -166,7 +166,7 @@
</span> </span>
{/if} {/if}
</div> </div>
<div class="col-span-6"> <!-- <div class="col-span-6">
<label <label
for="trackname" for="trackname"
class="block text-sm font-medium text-gray-700" class="block text-sm font-medium text-gray-700"
@@ -181,7 +181,7 @@
name="trackname" name="trackname"
class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/> />
</div> </div> -->
<div class="col-span-6"> <div class="col-span-6">
<label <label
for="lastname" for="lastname"

View File

@@ -147,7 +147,6 @@
<li class="flex items-center"> <li class="flex items-center">
<span class="mr-2" <span class="mr-2"
>{original_data.firstname} >{original_data.firstname}
{original_data.middlename || ""}
{original_data.lastname}</span {original_data.lastname}</span
> >
</li> </li>
@@ -157,7 +156,6 @@
</div> </div>
<div class="mb-8 text-3xl font-extrabold"> <div class="mb-8 text-3xl font-extrabold">
{original_data.firstname} {original_data.firstname}
{original_data.middlename || ""}
{original_data.lastname} {original_data.lastname}
<span data-id="user_actions_${editable_userdata.id}"> <span data-id="user_actions_${editable_userdata.id}">
{#if store.state.jwtinfo.userdetails.permissions.includes("USER:DELETE")} {#if store.state.jwtinfo.userdetails.permissions.includes("USER:DELETE")}
@@ -227,10 +225,10 @@
type="text" type="text"
bind:value={editable_userdata.firstname} bind:value={editable_userdata.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 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/> />
</div> </div>
<div class="text-sm w-full"> <!-- <div class="text-sm w-full">
<label for="middlename" class="font-medium text-gray-700" <label for="middlename" class="font-medium text-gray-700"
>{$_("middle-name")}</label >{$_("middle-name")}</label
> >
@@ -240,9 +238,9 @@
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 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/> />
</div> </div> -->
<div class="text-sm w-full"> <div class="text-sm w-full">
<label for="lastname" class="font-medium text-gray-700" <label for="lastname" class="font-medium text-gray-700"
>{$_("last-name")}</label >{$_("last-name")}</label
@@ -253,7 +251,7 @@
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 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/> />
</div> </div>
<div class="text-sm w-full"> <div class="text-sm w-full">
@@ -266,7 +264,7 @@
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 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/> />
</div> </div>
{#if !isEmail(editable_userdata.email)} {#if !isEmail(editable_userdata.email)}
@@ -285,7 +283,7 @@
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 dark:bg-gray-900 dark:text-gray-100 rounded-md p-2" class="mt-1 focus:ring-indigo-500 focus:border-indigo-500 block w-full shadow-sm rounded-l-md sm:text-sm border-gray-300 border bg-gray-50 text-gray-500 rounded-md p-2"
/> />
</div> </div>
<div class="text-sm w-full"> <div class="text-sm w-full">
@@ -293,7 +291,7 @@
<!-- 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 dark:bg-gray-900 dark:text-gray-100 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"
multiple multiple
> >
{#each allgroups as g} {#each allgroups as g}
@@ -319,7 +317,7 @@
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 dark:bg-gray-900 dark:text-gray-100 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-gray-500 rounded-md p-2"
/> />
</div> </div>
{#each original_data.permissions as p} {#each original_data.permissions as p}

View File

@@ -184,7 +184,7 @@
{#each allpermissions as p} {#each allpermissions as p}
{#if !(grantedPermissions.filter((o) => p.target == o.target && p.action == o.action).length > 0)} {#if !(grantedPermissions.filter((o) => p.target == o.target && p.action == o.action).length > 0)}
<p <p
class="block w-full mt-1 text-sm dark:border-gray-600 dark:bg-gray-700 bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:text-gray-300 dark:focus:shadow-outline-gray form-input" class="block w-full mt-1 text-sm bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple form-input"
> >
{p.target + ":" + p.action} {p.target + ":" + p.action}
<button <button
@@ -217,7 +217,7 @@
> >
{#each grantedPermissions as p} {#each grantedPermissions as p}
<p <p
class="block w-full mt-1 text-sm dark:border-gray-600 dark:bg-gray-700 bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:text-gray-300 dark:focus:shadow-outline-gray form-input" class="block w-full mt-1 text-sm bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple form-input"
> >
{p.target + ":" + p.action} {p.target + ":" + p.action}
<button <button
@@ -256,7 +256,7 @@
> >
{#each inheritedPermissions as p} {#each inheritedPermissions as p}
<p <p
class="block w-full mt-1 text-sm dark:border-gray-600 dark:bg-gray-700 bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple dark:text-gray-300 dark:focus:shadow-outline-gray form-input" class="block w-full mt-1 text-sm bg-gray-200 p-2 focus:border-purple-400 focus:outline-none focus:shadow-outline-purple form-input"
> >
{p.target + ":" + p.action} {p.target + ":" + p.action}
</p> </p>

View File

@@ -22,7 +22,6 @@
</button> </button>
{/if} {/if}
</span> </span>
<p class="mb-8 text-lg text-gray-500">{$_("manage-admin-users")}</p>
<UsersOverview bind:current_users /> <UsersOverview bind:current_users />
</section> </section>

View File

@@ -85,13 +85,15 @@
.toString() .toString()
.toLowerCase() .toLowerCase()
.includes(searchvalue)} .includes(searchvalue)}
<tr data-rowid="user_{u.id}"> <tr
class="odd:bg-white even:bg-gray-100"
data-rowid="user_{u.id}"
>
<td class="px-6 py-4 whitespace-nowrap"> <td class="px-6 py-4 whitespace-nowrap">
<div class="flex items-center"> <div class="flex items-center">
<div class="ml-4"> <div class="ml-4">
<div class="text-sm font-medium text-gray-900"> <div class="text-sm font-medium text-gray-900">
{u.firstname} {u.firstname}
{u.middlename || ""}
{u.lastname} {u.lastname}
</div> </div>
<div class="text-sm text-gray-500"> <div class="text-sm text-gray-500">

View File

@@ -74,7 +74,6 @@
"close": "Schließen", "close": "Schließen",
"code": "Code", "code": "Code",
"config-codes": "Konfigurations-Codes", "config-codes": "Konfigurations-Codes",
"configure-the-tracks-and-minimum-lap-times": "Bearbeite die Tracks und ihre minimale Rundenzeit",
"confirm": "Bestätigen", "confirm": "Bestätigen",
"confirm-delete": "Löschung Bestätigen", "confirm-delete": "Löschung Bestätigen",
"confirm-delete-donor-with-all-donations": "Bestätigen, Sponsor mit allen Sponsorings löschen", "confirm-delete-donor-with-all-donations": "Bestätigen, Sponsor mit allen Sponsorings löschen",
@@ -206,7 +205,7 @@
"edit": "Bearbeiten", "edit": "Bearbeiten",
"edit-a-card": "Läuferkarte bearbeiten", "edit-a-card": "Läuferkarte bearbeiten",
"edit-permissions": "Berechtigungen bearbeiten", "edit-permissions": "Berechtigungen bearbeiten",
"email_address_or_username": "E-Mail-Adresse/ Benutzername", "email_address_or_username": "E-Mail-Adresse",
"enabled": "aktiviert", "enabled": "aktiviert",
"enabled_large": "Aktiviert", "enabled_large": "Aktiviert",
"english": "Englisch", "english": "Englisch",
@@ -215,7 +214,6 @@
"error-whyile-copying-to-clipboard": "Fehler beim Kopieren in die Zwischenablage", "error-whyile-copying-to-clipboard": "Fehler beim Kopieren in die Zwischenablage",
"error_on_login": "😢Fehler beim Login", "error_on_login": "😢Fehler beim Login",
"everything-concerning-your-profile": "Alles zu deinem Profil", "everything-concerning-your-profile": "Alles zu deinem Profil",
"everything-is-more-fun-together": "Im Team macht's mehr Spaß 🏃‍♂️🏃‍♀️🏃‍♂️",
"faq": "FAQ", "faq": "FAQ",
"filename_sponsoringquittungsliste": "SponsoringQuittungsListe", "filename_sponsoringquittungsliste": "SponsoringQuittungsListe",
"filter-by-organization-team": "Filtern nach Organisation / Team", "filter-by-organization-team": "Filtern nach Organisation / Team",
@@ -390,7 +388,7 @@
"scanstation": "Scanner Station", "scanstation": "Scanner Station",
"scanstation-added": "Station wurde erstellt", "scanstation-added": "Station wurde erstellt",
"scanstation-is-being-added": "Scannerstation wird angelegt...", "scanstation-is-being-added": "Scannerstation wird angelegt...",
"scanstations": "Scanner Stationen", "scanstations": "Scanner",
"scanstations-are-being-loaded": "Scannerstationen werden geladen...", "scanstations-are-being-loaded": "Scannerstationen werden geladen...",
"search-for-an-organization-by-name-or-id": "Suche eine Organisation (via Name oder #ID)", "search-for-an-organization-by-name-or-id": "Suche eine Organisation (via Name oder #ID)",
"search-for-an-organization-or-team-by-name-or-id": "Suche eine Organisation oder ein Team (via Name oder #ID)", "search-for-an-organization-or-team-by-name-or-id": "Suche eine Organisation oder ein Team (via Name oder #ID)",
@@ -413,7 +411,7 @@
"statsclient": "StatsClient", "statsclient": "StatsClient",
"statsclient-deleted": "Statsclient wurde gelöscht", "statsclient-deleted": "Statsclient wurde gelöscht",
"statsclient-is-being-added": "Statsclient wird angelegt...", "statsclient-is-being-added": "Statsclient wird angelegt...",
"statsclients": "Statsclient (aka Beamershow)", "statsclients": "StatsClients",
"statsclients-are-being-loaded": "Statsclients werden geladen", "statsclients-are-being-loaded": "Statsclients werden geladen",
"status": "Status", "status": "Status",
"stuff-that-could-harm-your-profile": "Einstellungen, die deinem Profil nachhaltig schaden können", "stuff-that-could-harm-your-profile": "Einstellungen, die deinem Profil nachhaltig schaden können",
@@ -457,12 +455,15 @@
"track": "Track", "track": "Track",
"track-added": "Track hinzugefügt", "track-added": "Track hinzugefügt",
"track-data-is-being-loaded": "Trackdaten werden geladen", "track-data-is-being-loaded": "Trackdaten werden geladen",
"track-deleted": "Track gelöscht",
"track-is-being-added": "Track wird hinzugefügt...", "track-is-being-added": "Track wird hinzugefügt...",
"track-is-being-deleted": "Track wird gelöscht",
"track-is-being-updated": "Track wird aktualisiert...", "track-is-being-updated": "Track wird aktualisiert...",
"track-length-in-m": "Tracklänge (in Metern)", "track-length-in-m": "Tracklänge (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": "Trackname",
"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-was-updated": "Track wurde aktualisiert", "track-was-updated": "Track wurde aktualisiert",
"tracks": "Tracks", "tracks": "Tracks",
"unpaid": "Offen", "unpaid": "Offen",

View File

@@ -74,7 +74,6 @@
"close": "Close", "close": "Close",
"code": "Code", "code": "Code",
"config-codes": "Config codes", "config-codes": "Config codes",
"configure-the-tracks-and-minimum-lap-times": "configure the tracks & minimum lap times",
"confirm": "Confirm", "confirm": "Confirm",
"confirm-delete": "Confirm Delete", "confirm-delete": "Confirm Delete",
"confirm-delete-donor-with-all-donations": "Confirm, delete donor with all donations", "confirm-delete-donor-with-all-donations": "Confirm, delete donor with all donations",
@@ -206,7 +205,7 @@
"edit": "Edit", "edit": "Edit",
"edit-a-card": "Edit a card", "edit-a-card": "Edit a card",
"edit-permissions": "edit permissions", "edit-permissions": "edit permissions",
"email_address_or_username": "Email / username", "email_address_or_username": "Email",
"enabled": "enabled", "enabled": "enabled",
"enabled_large": "Enabled", "enabled_large": "Enabled",
"english": "English", "english": "English",
@@ -215,7 +214,6 @@
"error-whyile-copying-to-clipboard": "Error while copying to clipboard", "error-whyile-copying-to-clipboard": "Error while copying to clipboard",
"error_on_login": "Error on login", "error_on_login": "Error on login",
"everything-concerning-your-profile": "Everything concerning your profile", "everything-concerning-your-profile": "Everything concerning your profile",
"everything-is-more-fun-together": "everything is more fun together 🏃‍♂️🏃‍♀️🏃‍♂️",
"faq": "FAQ", "faq": "FAQ",
"filename_sponsoringquittungsliste": "DonorReceiptList", "filename_sponsoringquittungsliste": "DonorReceiptList",
"filter-by-organization-team": "Filter by Organization/ Team", "filter-by-organization-team": "Filter by Organization/ Team",
@@ -413,7 +411,7 @@
"statsclient": "statsclient", "statsclient": "statsclient",
"statsclient-deleted": "Deleted statsclient", "statsclient-deleted": "Deleted statsclient",
"statsclient-is-being-added": "Statsclient is being added...", "statsclient-is-being-added": "Statsclient is being added...",
"statsclients": "Statsclients (aka Beamershow)", "statsclients": "Statsclients",
"statsclients-are-being-loaded": "Loading statsclients", "statsclients-are-being-loaded": "Loading statsclients",
"status": "Status", "status": "Status",
"stuff-that-could-harm-your-profile": "Stuff that could harm your profile", "stuff-that-could-harm-your-profile": "Stuff that could harm your profile",
@@ -457,12 +455,15 @@
"track": "Track", "track": "Track",
"track-added": "Track added", "track-added": "Track added",
"track-data-is-being-loaded": "Track data is being loaded", "track-data-is-being-loaded": "Track data is being loaded",
"track-deleted": "Track deleted",
"track-is-being-added": "Track is being added...", "track-is-being-added": "Track is being added...",
"track-is-being-deleted": "Track is being deleted",
"track-is-being-updated": "Track is being updated...", "track-is-being-updated": "Track is being updated...",
"track-length-in-m": "Track Length in m", "track-length-in-m": "Track Length in m",
"track-length-must-be-greater-than-0": "Track length must be greater than 0", "track-length-must-be-greater-than-0": "Track length must be greater than 0",
"track-name": "Track name", "track-name": "Track name",
"track-name-must-not-be-empty": "Track name must not be empty", "track-name-must-not-be-empty": "Track name must not be empty",
"track-updated": "Track deleted",
"track-was-updated": "Track was updated!", "track-was-updated": "Track was updated!",
"tracks": "Tracks", "tracks": "Tracks",
"unpaid": "Unpaid", "unpaid": "Unpaid",

View File

@@ -1,5 +1,4 @@
import "./style.css"; import "./style.css";
import "gridjs/dist/theme/mermaid.css";
import App from "./App.svelte"; import App from "./App.svelte";
const app = new App({ const app = new App({