Compare commits
13 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
68bf3717f9
|
|||
|
f88c6e0dba
|
|||
|
12050cdda9
|
|||
|
01e77a97f3
|
|||
|
10824b5d9b
|
|||
|
d9870e03bc
|
|||
|
785b9e0b60
|
|||
|
fce2bc645e
|
|||
|
991716a7f5
|
|||
|
aa720f2460
|
|||
|
ac4ef8fb6d
|
|||
|
eae0afda23
|
|||
|
5291f8a4d1
|
43
CHANGELOG.md
43
CHANGELOG.md
@@ -2,9 +2,52 @@
|
|||||||
|
|
||||||
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.10.4](https://git.odit.services/lfk/frontend/compare/1.10.3...1.10.4)
|
||||||
|
|
||||||
|
- fix(runners): Fix runner overview sort [`f88c6e0`](https://git.odit.services/lfk/frontend/commit/f88c6e0dbab620887e180de0d3eab03b8215a477)
|
||||||
|
|
||||||
|
#### [1.10.3](https://git.odit.services/lfk/frontend/compare/1.10.2...1.10.3)
|
||||||
|
|
||||||
|
> 17 April 2025
|
||||||
|
|
||||||
|
- feat(pdf): Send selfservicelink for generation [`01e77a9`](https://git.odit.services/lfk/frontend/commit/01e77a97f3f28700e0249d35afd9641b56d9c55d)
|
||||||
|
- chore(release): 1.10.3 [`12050cd`](https://git.odit.services/lfk/frontend/commit/12050cdda95b5f8eb5b414b81655d06faae3ef1e)
|
||||||
|
- chore(deps): Bump @odit/lfk-client-js [`10824b5`](https://git.odit.services/lfk/frontend/commit/10824b5d9b207e14a37fa23e90d54337d76e60a9)
|
||||||
|
|
||||||
|
#### [1.10.2](https://git.odit.services/lfk/frontend/compare/1.10.1...1.10.2)
|
||||||
|
|
||||||
|
> 11 April 2025
|
||||||
|
|
||||||
|
- refactor(runners): filter table for created_via [`785b9e0`](https://git.odit.services/lfk/frontend/commit/785b9e0b60a9961f99d0c519d6bb12dc735ac605)
|
||||||
|
- chore(release): 1.10.2 [`d9870e0`](https://git.odit.services/lfk/frontend/commit/d9870e03bc3175ee9b299174a19f257d6046a718)
|
||||||
|
|
||||||
|
#### [1.10.1](https://git.odit.services/lfk/frontend/compare/1.10.0...1.10.1)
|
||||||
|
|
||||||
|
> 9 April 2025
|
||||||
|
|
||||||
|
- feat: runner list filtered by created_via [`991716a`](https://git.odit.services/lfk/frontend/commit/991716a7f55d0414111ad264ad1e93de9e82971a)
|
||||||
|
- chore(release): 1.10.1 [`fce2bc6`](https://git.odit.services/lfk/frontend/commit/fce2bc645e040322f4d1b98a1ed1ab5df7227b6d)
|
||||||
|
|
||||||
|
#### [1.10.0](https://git.odit.services/lfk/frontend/compare/1.9.11...1.10.0)
|
||||||
|
|
||||||
|
> 9 April 2025
|
||||||
|
|
||||||
|
- feat: working CardAssignment [`ac4ef8f`](https://git.odit.services/lfk/frontend/commit/ac4ef8fb6ded5c5d5678a651420e356b3ef45399)
|
||||||
|
- chore(release): 1.10.0 [`aa720f2`](https://git.odit.services/lfk/frontend/commit/aa720f2460079e35eed9d87a2ac580a3305efbd5)
|
||||||
|
|
||||||
|
#### [1.9.11](https://git.odit.services/lfk/frontend/compare/1.9.10...1.9.11)
|
||||||
|
|
||||||
|
> 8 April 2025
|
||||||
|
|
||||||
|
- feat(dash): add runnersViaKiosk [`5291f8a`](https://git.odit.services/lfk/frontend/commit/5291f8a4d1721cd0c745191ebc85f221c34a23c8)
|
||||||
|
- chore(release): 1.9.11 [`eae0afd`](https://git.odit.services/lfk/frontend/commit/eae0afda23a54020e25821c0188d8cbec3139593)
|
||||||
|
|
||||||
#### [1.9.10](https://git.odit.services/lfk/frontend/compare/1.9.9...1.9.10)
|
#### [1.9.10](https://git.odit.services/lfk/frontend/compare/1.9.9...1.9.10)
|
||||||
|
|
||||||
|
> 8 April 2025
|
||||||
|
|
||||||
- feat: add experimental ui for mobile card assignment [`d7c9c27`](https://git.odit.services/lfk/frontend/commit/d7c9c27ec7a1fea1cbaf26914843d044bbae32fe)
|
- feat: add experimental ui for mobile card assignment [`d7c9c27`](https://git.odit.services/lfk/frontend/commit/d7c9c27ec7a1fea1cbaf26914843d044bbae32fe)
|
||||||
|
- chore(release): 1.9.10 [`e2d7de1`](https://git.odit.services/lfk/frontend/commit/e2d7de1e9e1fd134f54876fa80f19f94fbea3672)
|
||||||
|
|
||||||
#### [1.9.9](https://git.odit.services/lfk/frontend/compare/1.9.8...1.9.9)
|
#### [1.9.9](https://git.odit.services/lfk/frontend/compare/1.9.8...1.9.9)
|
||||||
|
|
||||||
|
|||||||
@@ -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.9.10-RELEASE_INFO</span
|
>RELEASE_INFO-1.10.4-RELEASE_INFO</span
|
||||||
>
|
>
|
||||||
<noscript>You need to enable JavaScript to run this app.</noscript>
|
<noscript>You need to enable JavaScript to run this app.</noscript>
|
||||||
<script src="/env.js"></script>
|
<script src="/env.js"></script>
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
{
|
{
|
||||||
"name": "@odit/lfk-frontend",
|
"name": "@odit/lfk-frontend",
|
||||||
"version": "1.9.10",
|
"version": "1.10.4",
|
||||||
"type": "module",
|
"type": "module",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"i18n-order": "node order.js",
|
"i18n-order": "node order.js",
|
||||||
@@ -43,7 +43,7 @@
|
|||||||
},
|
},
|
||||||
"dependencies": {
|
"dependencies": {
|
||||||
"@fontsource/athiti": "^5.2.5",
|
"@fontsource/athiti": "^5.2.5",
|
||||||
"@odit/lfk-client-js": "1.2.0",
|
"@odit/lfk-client-js": "1.2.4",
|
||||||
"@paralleldrive/cuid2": "2.2.2",
|
"@paralleldrive/cuid2": "2.2.2",
|
||||||
"@tanstack/svelte-table": "8.9.1",
|
"@tanstack/svelte-table": "8.9.1",
|
||||||
"bwip-js": "3.4.0",
|
"bwip-js": "3.4.0",
|
||||||
|
|||||||
10
pnpm-lock.yaml
generated
10
pnpm-lock.yaml
generated
@@ -12,8 +12,8 @@ importers:
|
|||||||
specifier: ^5.2.5
|
specifier: ^5.2.5
|
||||||
version: 5.2.5
|
version: 5.2.5
|
||||||
'@odit/lfk-client-js':
|
'@odit/lfk-client-js':
|
||||||
specifier: 1.2.0
|
specifier: 1.2.4
|
||||||
version: 1.2.0
|
version: 1.2.4
|
||||||
'@paralleldrive/cuid2':
|
'@paralleldrive/cuid2':
|
||||||
specifier: 2.2.2
|
specifier: 2.2.2
|
||||||
version: 2.2.2
|
version: 2.2.2
|
||||||
@@ -355,8 +355,8 @@ packages:
|
|||||||
'@octokit/types@13.6.1':
|
'@octokit/types@13.6.1':
|
||||||
resolution: {integrity: sha512-PHZE9Z+kWXb23Ndik8MKPirBPziOc0D2/3KH1P+6jK5nGWe96kadZuE4jev2/Jq7FvIfTlT2Ltg8Fv2x1v0a5g==}
|
resolution: {integrity: sha512-PHZE9Z+kWXb23Ndik8MKPirBPziOc0D2/3KH1P+6jK5nGWe96kadZuE4jev2/Jq7FvIfTlT2Ltg8Fv2x1v0a5g==}
|
||||||
|
|
||||||
'@odit/lfk-client-js@1.2.0':
|
'@odit/lfk-client-js@1.2.4':
|
||||||
resolution: {integrity: sha512-RR/Ij3PDMF840VJtphO51k+3voJcTlvRIxzTFBkvrwriBmLJwchBQxq40K4/kyVIFH7lLwO3uJy0PaxgEoTbFQ==}
|
resolution: {integrity: sha512-eJRsjtpMm/VsQ1v2I+inMWCZmzL+WoOvsA+hj8IGsyCVn0td+z/HAwQ0SuXXNZpLPL3qSlENHXjFNrgztExEgA==}
|
||||||
|
|
||||||
'@odit/license-exporter@0.2.0':
|
'@odit/license-exporter@0.2.0':
|
||||||
resolution: {integrity: sha512-RRyfQzDLoyLQlGSd8ThJQ3h0fiCe4tkmm935AUvSVQWP+p88FcnI4iaktKBJJVBnIpDhkv/7sDSA5dFc/QMM5w==}
|
resolution: {integrity: sha512-RRyfQzDLoyLQlGSd8ThJQ3h0fiCe4tkmm935AUvSVQWP+p88FcnI4iaktKBJJVBnIpDhkv/7sDSA5dFc/QMM5w==}
|
||||||
@@ -2176,7 +2176,7 @@ snapshots:
|
|||||||
dependencies:
|
dependencies:
|
||||||
'@octokit/openapi-types': 22.2.0
|
'@octokit/openapi-types': 22.2.0
|
||||||
|
|
||||||
'@odit/lfk-client-js@1.2.0': {}
|
'@odit/lfk-client-js@1.2.4': {}
|
||||||
|
|
||||||
'@odit/license-exporter@0.2.0':
|
'@odit/license-exporter@0.2.0':
|
||||||
dependencies:
|
dependencies:
|
||||||
|
|||||||
BIN
public/beep.mp3
Normal file
BIN
public/beep.mp3
Normal file
Binary file not shown.
@@ -136,7 +136,7 @@
|
|||||||
</Route>
|
</Route>
|
||||||
<Route path="/runners/*">
|
<Route path="/runners/*">
|
||||||
<Route path="/">
|
<Route path="/">
|
||||||
<Runners />
|
<Runners created_via="all" />
|
||||||
</Route>
|
</Route>
|
||||||
<Route path="/:runnerid" let:params>
|
<Route path="/:runnerid" let:params>
|
||||||
<RunnerDetail {params} />
|
<RunnerDetail {params} />
|
||||||
|
|||||||
@@ -41,7 +41,27 @@
|
|||||||
</svg>
|
</svg>
|
||||||
<span>{$_("dashboard-title")}</span>
|
<span>{$_("dashboard-title")}</span>
|
||||||
</a>
|
</a>
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET")}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET") && store.state.jwtinfo.userdetails.permissions.includes("CARD:GET")}
|
||||||
|
<a
|
||||||
|
class:activenav={$router.path.includes("/cardassignment/")}
|
||||||
|
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="/cardassignment/"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
fill="currentColor"
|
||||||
|
class="flex-shrink-0 w-5 h-5 mr-2 transition group-hover:text-gray-600"
|
||||||
|
>
|
||||||
|
<path
|
||||||
|
fill-rule="evenodd"
|
||||||
|
d="M14.615 1.595a.75.75 0 0 1 .359.852L12.982 9.75h7.268a.75.75 0 0 1 .548 1.262l-10.5 11.25a.75.75 0 0 1-1.272-.71l1.992-7.302H3.75a.75.75 0 0 1-.548-1.262l10.5-11.25a.75.75 0 0 1 .913-.143Z"
|
||||||
|
clip-rule="evenodd"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
|
||||||
|
<span>Card Assignment</span>
|
||||||
|
</a>
|
||||||
<a
|
<a
|
||||||
class:activenav={$router.path.includes("/runners/")}
|
class:activenav={$router.path.includes("/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"
|
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full font-semibold"
|
||||||
|
|||||||
@@ -234,6 +234,23 @@
|
|||||||
/></svg
|
/></svg
|
||||||
>
|
>
|
||||||
</StatCard>
|
</StatCard>
|
||||||
|
<StatCard
|
||||||
|
title={$_('runners_via_kiosk')}
|
||||||
|
value={stats.runnersViaKiosk}
|
||||||
|
href="/runners/"
|
||||||
|
>
|
||||||
|
<svg
|
||||||
|
height="24"
|
||||||
|
width="24"
|
||||||
|
fill="currentColor"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
><path d="M0 0h24v24H0z" fill="none" />
|
||||||
|
<path
|
||||||
|
d="M13.49 5.48c1.1 0 2-.9 2-2s-.9-2-2-2-2 .9-2 2 .9 2 2 2zm-3.6 13.9l1-4.4 2.1 2v6h2v-7.5l-2.1-2 .6-3c1.3 1.5 3.3 2.5 5.5 2.5v-2c-1.9 0-3.5-1-4.3-2.4l-1-1.6c-.4-.6-1-1-1.7-1-.3 0-.5.1-.8.1l-5.2 2.2v4.7h2v-3.4l1.8-.7-1.6 8.1-4.9-1-.4 2 7 1.4z"
|
||||||
|
/></svg
|
||||||
|
>
|
||||||
|
</StatCard>
|
||||||
</div>
|
</div>
|
||||||
{: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">
|
||||||
|
|||||||
@@ -1,26 +1,30 @@
|
|||||||
<script>
|
<script>
|
||||||
|
import { RunnerCardService, RunnerService } from "@odit/lfk-client-js";
|
||||||
import QrCodeScanner from "./QrCodeScanner.svelte";
|
import QrCodeScanner from "./QrCodeScanner.svelte";
|
||||||
let state = "scan_runner";
|
let state = "scan_runner";
|
||||||
let runnerID = undefined;
|
let runnerinfo = { id: 0, firstname: "", lastname: "" };
|
||||||
let cardInfo = "";
|
let cardCode = "";
|
||||||
|
$: scannerActive = state.includes("scan");
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<div class="p-4">
|
<div class="p-4">
|
||||||
<h3 class="text-3xl font-bold">Card Assignment for Mobile</h3>
|
<h3 class="text-3xl font-bold">Card Assignment for Mobile</h3>
|
||||||
{#if state === "done"}
|
<!-- <p>state</p>
|
||||||
<p>Assigned Card {cardInfo} ✅</p>
|
<p>{state}</p>
|
||||||
<p>(not really, needs to be implemented)</p>
|
<p>scannerActive</p>
|
||||||
{:else}
|
<p>{scannerActive}</p> -->
|
||||||
|
{#if state.includes("scan_")}
|
||||||
<!-- -->
|
<!-- -->
|
||||||
{#if state === "scan_runner"}
|
{#if state === "scan_runner"}
|
||||||
<h3 class="text-xl font-bold">Scan Runner (Selfservice QR)</h3>
|
<h3 class="text-xl font-bold">Scan Runner (Selfservice QR)</h3>
|
||||||
{/if}
|
{/if}
|
||||||
{#if state === "scan_card"}
|
{#if state === "scan_card"}
|
||||||
<h3 class="text-xl font-bold">Runner Scanned</h3>
|
<h3 class="text-xl font-bold">Runner Scanned</h3>
|
||||||
<p>{runnerID}</p>
|
<p>{runnerinfo.firstname} {runnerinfo.lastname} [#{runnerinfo.id}]</p>
|
||||||
<h3 class="text-xl font-bold">Scan Card (Code 128 Barcode)</h3>
|
<h3 class="text-xl font-bold">Scan Card (Code 128 Barcode)</h3>
|
||||||
{/if}
|
{/if}
|
||||||
<QrCodeScanner
|
<QrCodeScanner
|
||||||
|
paused={!scannerActive}
|
||||||
on:detect={(e) => {
|
on:detect={(e) => {
|
||||||
console.log({ type: "DETECT", code: e.detail.decodedText });
|
console.log({ type: "DETECT", code: e.detail.decodedText });
|
||||||
if (state === "scan_runner") {
|
if (state === "scan_runner") {
|
||||||
@@ -29,13 +33,18 @@
|
|||||||
"https://portal.lauf-fuer-kaya.de/profile/"
|
"https://portal.lauf-fuer-kaya.de/profile/"
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
runnerID = JSON.parse(
|
const runnerID = JSON.parse(
|
||||||
atob(
|
atob(
|
||||||
e.detail.decodedText
|
e.detail.decodedText
|
||||||
.replace("https://portal.lauf-fuer-kaya.de/profile/", "")
|
.replace("https://portal.lauf-fuer-kaya.de/profile/", "")
|
||||||
.split(".")[1]
|
.split(".")[1]
|
||||||
)
|
)
|
||||||
).id;
|
).id;
|
||||||
|
new Audio("/beep.mp3").play();
|
||||||
|
RunnerService.runnerControllerGetOne(runnerID).then((runner) => {
|
||||||
|
console.log(runner);
|
||||||
|
runnerinfo = runner;
|
||||||
|
});
|
||||||
state = "scan_card";
|
state = "scan_card";
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -45,8 +54,25 @@
|
|||||||
"https://portal.lauf-fuer-kaya.de/profile/"
|
"https://portal.lauf-fuer-kaya.de/profile/"
|
||||||
)
|
)
|
||||||
) {
|
) {
|
||||||
cardInfo = e.detail.decodedText;
|
cardCode = e.detail.decodedText;
|
||||||
state = "done";
|
new Audio("/beep.mp3").play();
|
||||||
|
state = "assigning";
|
||||||
|
RunnerCardService.runnerCardControllerGetAll().then((cards) => {
|
||||||
|
console.log(cards);
|
||||||
|
const card = cards.find((c) => c.code === cardCode);
|
||||||
|
if (card) {
|
||||||
|
console.log("card found", card);
|
||||||
|
RunnerCardService.runnerCardControllerPut(card.id, {
|
||||||
|
enabled: true,
|
||||||
|
id: card.id,
|
||||||
|
runner: runnerinfo.id,
|
||||||
|
}).then(() => {
|
||||||
|
state = "done";
|
||||||
|
});
|
||||||
|
} else {
|
||||||
|
state = "error_card_404";
|
||||||
|
}
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}}
|
}}
|
||||||
@@ -58,8 +84,8 @@
|
|||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
state = "scan_runner";
|
state = "scan_runner";
|
||||||
runnerID = undefined;
|
runnerinfo = { id: 0, firstname: "", lastname: "" };
|
||||||
cardInfo = "";
|
cardCode = "";
|
||||||
}}
|
}}
|
||||||
type="button"
|
type="button"
|
||||||
class="py-3 px-4 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-red-100 text-red-800 hover:bg-red-200 focus:outline-hidden focus:bg-red-200 disabled:opacity-50 disabled:pointer-events-none dark:text-red-500 dark:bg-red-800/30 dark:hover:bg-red-800/20 dark:focus:bg-red-800/20 w-full mt-2"
|
class="py-3 px-4 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-red-100 text-red-800 hover:bg-red-200 focus:outline-hidden focus:bg-red-200 disabled:opacity-50 disabled:pointer-events-none dark:text-red-500 dark:bg-red-800/30 dark:hover:bg-red-800/20 dark:focus:bg-red-800/20 w-full mt-2"
|
||||||
@@ -68,5 +94,30 @@
|
|||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
<!-- -->
|
<!-- -->
|
||||||
|
{:else}
|
||||||
|
<!-- -->
|
||||||
|
{#if state === "assigning"}
|
||||||
|
<p>Assigning Card {cardCode} ⌛</p>
|
||||||
|
<p>Please wait a moment while we assign the card...</p>
|
||||||
|
{/if}
|
||||||
|
{#if state === "done"}
|
||||||
|
<p>
|
||||||
|
Assigned Card {cardCode} to {runnerinfo.firstname}
|
||||||
|
{runnerinfo.lastname} [#{runnerinfo.id}] ✅
|
||||||
|
</p>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
// state = "scan_runner";
|
||||||
|
// runnerinfo = { id: 0, firstname: "", lastname: "" };
|
||||||
|
// cardCode = "";
|
||||||
|
location.reload();
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
class="py-3 px-4 inline-flex items-center gap-x-2 text-sm font-medium rounded-lg border border-transparent bg-blue-100 text-blue-800 hover:bg-blue-200 focus:outline-hidden focus:bg-blue-200 disabled:opacity-50 disabled:pointer-events-none dark:text-blue-500 dark:bg-blue-800/30 dark:hover:bg-blue-800/20 dark:focus:bg-blue-800/20 w-full mt-2"
|
||||||
|
>
|
||||||
|
Done
|
||||||
|
</button>
|
||||||
|
{/if}
|
||||||
|
<!-- -->
|
||||||
{/if}
|
{/if}
|
||||||
</div>
|
</div>
|
||||||
|
|||||||
@@ -14,12 +14,16 @@
|
|||||||
const dispatch = createEventDispatcher();
|
const dispatch = createEventDispatcher();
|
||||||
|
|
||||||
function onScanSuccess(decodedText, decodedResult) {
|
function onScanSuccess(decodedText, decodedResult) {
|
||||||
dispatch("detect", { decodedText });
|
if (!paused) {
|
||||||
|
dispatch("detect", { decodedText });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// usually better to ignore and keep scanning
|
// usually better to ignore and keep scanning
|
||||||
function onScanFailure(message) {
|
function onScanFailure(message) {
|
||||||
dispatch("error", { message });
|
if (!paused) {
|
||||||
|
dispatch("error", { message });
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
let scanner;
|
let scanner;
|
||||||
|
|||||||
@@ -100,6 +100,7 @@ class DocumentServer {
|
|||||||
first_name: runners[i].firstname,
|
first_name: runners[i].firstname,
|
||||||
middle_name: runners[i].middlename,
|
middle_name: runners[i].middlename,
|
||||||
last_name: runners[i].lastname,
|
last_name: runners[i].lastname,
|
||||||
|
self_service_link: runners[i].selfserviceLink,
|
||||||
group: {
|
group: {
|
||||||
id: runners[i].group.id,
|
id: runners[i].group.id,
|
||||||
name: runners[i].group.name,
|
name: runners[i].group.name,
|
||||||
|
|||||||
@@ -1,175 +1,180 @@
|
|||||||
<script>
|
<script>
|
||||||
import { _ } from "svelte-i18n";
|
import { _ } from "svelte-i18n";
|
||||||
import {
|
import {
|
||||||
DonationService,
|
DonationService,
|
||||||
RunnerTeamService,
|
RunnerTeamService,
|
||||||
RunnerOrganizationService,
|
RunnerOrganizationService,
|
||||||
} from "@odit/lfk-client-js";
|
RunnerService
|
||||||
import { init } from "@paralleldrive/cuid2";
|
} from "@odit/lfk-client-js";
|
||||||
import toast from "svelte-french-toast";
|
import { init } from "@paralleldrive/cuid2";
|
||||||
import DocumentServer from "./DocumentServer";
|
import toast from "svelte-french-toast";
|
||||||
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
|
import DocumentServer from "./DocumentServer";
|
||||||
const documentServer = new DocumentServer(
|
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
|
||||||
config.baseurl_documentserver,
|
const documentServer = new DocumentServer(
|
||||||
config.documentserver_key
|
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 = [];
|
||||||
|
|
||||||
function generateCertificates(locale) {
|
function generateCertificates(locale) {
|
||||||
if (generate_orgs.length > 0) {
|
if (generate_orgs.length > 0) {
|
||||||
generateOrgCertificates(locale);
|
generateOrgCertificates(locale);
|
||||||
} else if (generate_teams.length > 0) {
|
} else if (generate_teams.length > 0) {
|
||||||
generateTeamCertificates(locale);
|
generateTeamCertificates(locale);
|
||||||
} else {
|
} else {
|
||||||
generateRunnerCertificates(locale);
|
generateRunnerCertificates(locale);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
function download(blob, fileName) {
|
function download(blob, fileName) {
|
||||||
const url = window.URL.createObjectURL(blob);
|
const url = window.URL.createObjectURL(blob);
|
||||||
let a = document.createElement("a");
|
let a = document.createElement("a");
|
||||||
a.href = url;
|
a.href = url;
|
||||||
a.download = fileName;
|
a.download = fileName;
|
||||||
document.body.appendChild(a);
|
document.body.appendChild(a);
|
||||||
a.click();
|
a.click();
|
||||||
a.remove();
|
a.remove();
|
||||||
toast.dismiss();
|
toast.dismiss();
|
||||||
toast.success($_("pdf-successfully-generated"));
|
toast.success($_("pdf-successfully-generated"));
|
||||||
}
|
}
|
||||||
|
|
||||||
async function generateRunnerCertificates(locale) {
|
async function generateRunnerCertificates(locale) {
|
||||||
toast.loading($_("generating-pdf"));
|
toast.loading($_("generating-pdf"));
|
||||||
const current_donations =
|
const current_donations =
|
||||||
(await DonationService.donationControllerGetAll()) || [];
|
(await DonationService.donationControllerGetAll()) || [];
|
||||||
let certificateRunners = [];
|
let certificateRunners = [];
|
||||||
for (let runner of generate_runners) {
|
for (let runner of generate_runners) {
|
||||||
runner.distanceDonations =
|
const linkRunner = await RunnerService.runnerControllerGetOne(runner.id)
|
||||||
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
linkRunner.distanceDonations =
|
||||||
certificateRunners.push(runner);
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
}
|
certificateRunners.push(linkRunner);
|
||||||
documentServer
|
}
|
||||||
.generateCertificates(certificateRunners, locale)
|
documentServer
|
||||||
.then((blob) => {
|
.generateCertificates(certificateRunners, locale)
|
||||||
let fileName = `${$_("certificates")}-${locale}.pdf`;
|
.then((blob) => {
|
||||||
if (generate_runners.length == 1) {
|
let fileName = `${$_("certificates")}-${locale}.pdf`;
|
||||||
fileName = `${$_("certificates")}_${
|
if (generate_runners.length == 1) {
|
||||||
generate_runners[0].firstname
|
fileName = `${$_("certificates")}_${
|
||||||
}_${generate_runners[0].lastname}-${locale}-${createId()}.pdf`;
|
generate_runners[0].firstname
|
||||||
}
|
}_${generate_runners[0].lastname}-${locale}-${createId()}.pdf`;
|
||||||
download(blob, fileName);
|
}
|
||||||
})
|
download(blob, fileName);
|
||||||
.catch((err) => {});
|
})
|
||||||
}
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
|
||||||
async function generateTeamCertificates(locale) {
|
async function generateTeamCertificates(locale) {
|
||||||
toast.loading($_("generating-pdfs"));
|
toast.loading($_("generating-pdfs"));
|
||||||
let count = 0;
|
let count = 0;
|
||||||
const current_donations =
|
const current_donations =
|
||||||
(await DonationService.donationControllerGetAll()) || [];
|
(await DonationService.donationControllerGetAll()) || [];
|
||||||
for (const t of generate_teams) {
|
for (const t of generate_teams) {
|
||||||
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
t.id
|
t.id,
|
||||||
);
|
true
|
||||||
let certificateRunners = [];
|
);
|
||||||
for (let runner of runners) {
|
let certificateRunners = [];
|
||||||
runner.distanceDonations =
|
for (let runner of runners) {
|
||||||
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
runner.distanceDonations =
|
||||||
certificateRunners.push(runner);
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
}
|
certificateRunners.push(runner);
|
||||||
documentServer
|
}
|
||||||
.generateCertificates(certificateRunners, locale)
|
documentServer
|
||||||
.then((blob) => {
|
.generateCertificates(certificateRunners, locale)
|
||||||
count++;
|
.then((blob) => {
|
||||||
download(
|
count++;
|
||||||
blob,
|
download(
|
||||||
`${$_("certificates")}_${t.name}-${locale}-${createId()}.pdf`
|
blob,
|
||||||
);
|
`${$_("certificates")}_${t.name}-${locale}-${createId()}.pdf`
|
||||||
})
|
);
|
||||||
.catch((err) => {});
|
})
|
||||||
}
|
.catch((err) => {});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
async function generateOrgCertificates(locale) {
|
async function generateOrgCertificates(locale) {
|
||||||
toast.loading($_("generating-pdfs"));
|
toast.loading($_("generating-pdfs"));
|
||||||
const current_donations =
|
const current_donations =
|
||||||
(await DonationService.donationControllerGetAll()) || [];
|
(await DonationService.donationControllerGetAll()) || [];
|
||||||
let count = 0;
|
let count = 0;
|
||||||
let count_orgs = 0;
|
let count_orgs = 0;
|
||||||
for (const o of generate_orgs) {
|
for (const o of generate_orgs) {
|
||||||
count_orgs++;
|
count_orgs++;
|
||||||
let count = 0;
|
let count = 0;
|
||||||
let runners =
|
let runners =
|
||||||
await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
||||||
o.id,
|
o.id,
|
||||||
true
|
true,
|
||||||
);
|
true
|
||||||
let certificateRunners = [];
|
);
|
||||||
for (let runner of runners) {
|
let certificateRunners = [];
|
||||||
runner.distanceDonations =
|
for (let runner of runners) {
|
||||||
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
runner.distanceDonations =
|
||||||
certificateRunners.push(runner);
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
}
|
certificateRunners.push(runner);
|
||||||
await documentServer
|
}
|
||||||
.generateCertificates(certificateRunners, locale)
|
await documentServer
|
||||||
.then((blob) => {
|
.generateCertificates(certificateRunners, locale)
|
||||||
download(
|
.then((blob) => {
|
||||||
blob,
|
download(
|
||||||
`${$_("certificates")}_${o.name}-${locale}-${createId()}.pdf`
|
blob,
|
||||||
);
|
`${$_("certificates")}_${o.name}-${locale}-${createId()}.pdf`
|
||||||
})
|
);
|
||||||
.catch((err) => {});
|
})
|
||||||
for (const t of o.teams) {
|
.catch((err) => {});
|
||||||
count++;
|
for (const t of o.teams) {
|
||||||
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
count++;
|
||||||
t.id
|
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
);
|
t.id,
|
||||||
let certificateRunners = [];
|
true
|
||||||
for (let runner of runners) {
|
);
|
||||||
runner.distanceDonations =
|
let certificateRunners = [];
|
||||||
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
for (let runner of runners) {
|
||||||
certificateRunners.push(runner);
|
runner.distanceDonations =
|
||||||
}
|
current_donations.filter((d) => d.runner?.id == runner.id) || [];
|
||||||
await documentServer
|
certificateRunners.push(runner);
|
||||||
.generateCertificates(certificateRunners, locale)
|
}
|
||||||
.then((blob) => {
|
await documentServer
|
||||||
download(
|
.generateCertificates(certificateRunners, locale)
|
||||||
blob,
|
.then((blob) => {
|
||||||
`${$_("certificates")}_${o.name}_${
|
download(
|
||||||
t.name
|
blob,
|
||||||
}-${locale}-${createId()}.pdf`
|
`${$_("certificates")}_${o.name}_${
|
||||||
);
|
t.name
|
||||||
if (
|
}-${locale}-${createId()}.pdf`
|
||||||
count === o.teams.length &&
|
);
|
||||||
count_orgs === generate_orgs.length
|
if (
|
||||||
) {
|
count === o.teams.length &&
|
||||||
toast.dismiss();
|
count_orgs === generate_orgs.length
|
||||||
toast.success($_("pdfs-successfully-generated"));
|
) {
|
||||||
}
|
toast.dismiss();
|
||||||
})
|
toast.success($_("pdfs-successfully-generated"));
|
||||||
.catch((err) => {});
|
}
|
||||||
}
|
})
|
||||||
}
|
.catch((err) => {});
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
{#if certificates_show}
|
{#if certificates_show}
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
generateCertificates("de");
|
generateCertificates("de");
|
||||||
}}
|
}}
|
||||||
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-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-runner-certificates")}: DE
|
{$_("generate-runner-certificates")}: DE
|
||||||
</button>
|
</button>
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
generateCertificates("en");
|
generateCertificates("en");
|
||||||
}}
|
}}
|
||||||
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-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-runner-certificates")}: EN
|
{$_("generate-runner-certificates")}: EN
|
||||||
</button>
|
</button>
|
||||||
{/if}
|
{/if}
|
||||||
|
|||||||
@@ -100,7 +100,7 @@
|
|||||||
<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">
|
||||||
<a class="mr-2" href="./"
|
<a class="mr-2" href="/runners/"
|
||||||
><svg
|
><svg
|
||||||
xmlns="http://www.w3.org/2000/svg"
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
width="24"
|
width="24"
|
||||||
|
|||||||
@@ -32,6 +32,7 @@
|
|||||||
|
|
||||||
$: active_delete = undefined;
|
$: active_delete = undefined;
|
||||||
let dataLoaded = false;
|
let dataLoaded = false;
|
||||||
|
export let created_via = "all";
|
||||||
export let current_runners = [];
|
export let current_runners = [];
|
||||||
$: sponsoring_contracts_show = selected.length > 0;
|
$: sponsoring_contracts_show = selected.length > 0;
|
||||||
$: cards_show = selected.length > 0;
|
$: cards_show = selected.length > 0;
|
||||||
@@ -75,6 +76,11 @@
|
|||||||
header: () => $_("last-name"),
|
header: () => $_("last-name"),
|
||||||
filterFn: `includesString`,
|
filterFn: `includesString`,
|
||||||
},
|
},
|
||||||
|
{
|
||||||
|
accessorKey: "created_via",
|
||||||
|
header: () => "created_via",
|
||||||
|
filterFn: `includesString`,
|
||||||
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "group",
|
accessorKey: "group",
|
||||||
header: () => $_("group"),
|
header: () => $_("group"),
|
||||||
@@ -86,6 +92,11 @@
|
|||||||
return `${group.parentGroup.name} > ${group.name}`;
|
return `${group.parentGroup.name} > ${group.name}`;
|
||||||
},
|
},
|
||||||
filterFn: `group`,
|
filterFn: `group`,
|
||||||
|
sortingFn: (rowA, rowB, col)=> {
|
||||||
|
return rowA.original.group.name.localeCompare(
|
||||||
|
rowB.original.group.name,
|
||||||
|
)
|
||||||
|
},
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
accessorKey: "distance",
|
accessorKey: "distance",
|
||||||
@@ -103,7 +114,7 @@
|
|||||||
header: () => $_("action"),
|
header: () => $_("action"),
|
||||||
cell: (info) => {
|
cell: (info) => {
|
||||||
return renderComponent(TableActions, {
|
return renderComponent(TableActions, {
|
||||||
detailsLink: `./${info.row.original.id}`,
|
detailsLink: `/runners/${info.row.original.id}`,
|
||||||
deleteAction: () => {
|
deleteAction: () => {
|
||||||
active_delete =
|
active_delete =
|
||||||
current_runners[
|
current_runners[
|
||||||
@@ -161,7 +172,11 @@
|
|||||||
|
|
||||||
let page = 0;
|
let page = 0;
|
||||||
while (page >= 0) {
|
while (page >= 0) {
|
||||||
const runners = await RunnerService.runnerControllerGetAll(page, 500);
|
const runners = await RunnerService.runnerControllerGetAll(
|
||||||
|
page,
|
||||||
|
500,
|
||||||
|
created_via
|
||||||
|
);
|
||||||
if (runners.length == 0) {
|
if (runners.length == 0) {
|
||||||
page = -2;
|
page = -2;
|
||||||
}
|
}
|
||||||
@@ -190,6 +205,9 @@
|
|||||||
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
|
||||||
{$_("runners")}
|
{$_("runners")}
|
||||||
</h4>
|
</h4>
|
||||||
|
{#if created_via !== "all"}
|
||||||
|
<p>created_via={created_via}</p>
|
||||||
|
{/if}
|
||||||
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:CREATE")}
|
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:CREATE")}
|
||||||
<button
|
<button
|
||||||
on:click={() => {
|
on:click={() => {
|
||||||
|
|||||||
@@ -382,6 +382,7 @@
|
|||||||
"runners": "Läufer",
|
"runners": "Läufer",
|
||||||
"runners-are-being-imported": "Läufer werden importiert ...",
|
"runners-are-being-imported": "Läufer werden importiert ...",
|
||||||
"runners-are-being-loaded": "Läufer werden geladen ...",
|
"runners-are-being-loaded": "Läufer werden geladen ...",
|
||||||
|
"runners_via_kiosk": "Läufer via Kiosk",
|
||||||
"save": "Speichern",
|
"save": "Speichern",
|
||||||
"save-changes": "Änderungen speichern",
|
"save-changes": "Änderungen speichern",
|
||||||
"scan-added": "Scan hinzugefügt",
|
"scan-added": "Scan hinzugefügt",
|
||||||
|
|||||||
@@ -382,6 +382,7 @@
|
|||||||
"runners": "Runners",
|
"runners": "Runners",
|
||||||
"runners-are-being-imported": "Runners are being imported...",
|
"runners-are-being-imported": "Runners are being imported...",
|
||||||
"runners-are-being-loaded": "runners are being loaded...",
|
"runners-are-being-loaded": "runners are being loaded...",
|
||||||
|
"runners_via_kiosk": "Runners via Kiosk",
|
||||||
"save": "Save",
|
"save": "Save",
|
||||||
"save-changes": "Save Changes",
|
"save-changes": "Save Changes",
|
||||||
"scan-added": "Scan added",
|
"scan-added": "Scan added",
|
||||||
|
|||||||
18
yarn.lock
18
yarn.lock
@@ -491,10 +491,10 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
"@odit/lfk-client-js@npm:1.1.3":
|
"@odit/lfk-client-js@npm:1.2.4":
|
||||||
version: 1.1.3
|
version: 1.2.4
|
||||||
resolution: "@odit/lfk-client-js@npm:1.1.3"
|
resolution: "@odit/lfk-client-js@npm:1.2.4"
|
||||||
checksum: 10c0/c5108400dc40b6eb5d4c467238c178779454bf46301559034fbfd2d7666e863af5d5df8208b501ec6dad1b97994e2005d879f2d5b5f3e0439f01f34ecd97f895
|
checksum: 10c0/503b3eec7fe66f8d42b137660fd5a7cda2f067c6c79fbe3c15613fb7a06284adb3e186a645f8e48c6de015fb2c8c0a42074551201fd0244215e8ba444dfe17e2
|
||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
@@ -503,7 +503,7 @@ __metadata:
|
|||||||
resolution: "@odit/lfk-frontend@workspace:."
|
resolution: "@odit/lfk-frontend@workspace:."
|
||||||
dependencies:
|
dependencies:
|
||||||
"@fontsource/athiti": "npm:^5.2.5"
|
"@fontsource/athiti": "npm:^5.2.5"
|
||||||
"@odit/lfk-client-js": "npm:1.1.3"
|
"@odit/lfk-client-js": "npm:1.2.4"
|
||||||
"@odit/license-exporter": "npm:0.2.0"
|
"@odit/license-exporter": "npm:0.2.0"
|
||||||
"@paralleldrive/cuid2": "npm:2.2.2"
|
"@paralleldrive/cuid2": "npm:2.2.2"
|
||||||
"@sveltejs/vite-plugin-svelte": "npm:2.1.1"
|
"@sveltejs/vite-plugin-svelte": "npm:2.1.1"
|
||||||
@@ -513,6 +513,7 @@ __metadata:
|
|||||||
bwip-js: "npm:3.4.0"
|
bwip-js: "npm:3.4.0"
|
||||||
check-password-strength: "npm:2.0.10"
|
check-password-strength: "npm:2.0.10"
|
||||||
csvtojson: "npm:2.0.10"
|
csvtojson: "npm:2.0.10"
|
||||||
|
html5-qrcode: "npm:^2.3.8"
|
||||||
localforage: "npm:1.10.0"
|
localforage: "npm:1.10.0"
|
||||||
marked: "npm:4.3.0"
|
marked: "npm:4.3.0"
|
||||||
postcss: "npm:8.5.3"
|
postcss: "npm:8.5.3"
|
||||||
@@ -2032,6 +2033,13 @@ __metadata:
|
|||||||
languageName: node
|
languageName: node
|
||||||
linkType: hard
|
linkType: hard
|
||||||
|
|
||||||
|
"html5-qrcode@npm:^2.3.8":
|
||||||
|
version: 2.3.8
|
||||||
|
resolution: "html5-qrcode@npm:2.3.8"
|
||||||
|
checksum: 10c0/3d7d0b3687e41a6fc0a06345f67e89ad3c7c00a3d0d8846d6fd31985e1ed2ac1c310e625f0b650dbc689f6b83469e3378417e7431ae5a9194178f1172bf6a93a
|
||||||
|
languageName: node
|
||||||
|
linkType: hard
|
||||||
|
|
||||||
"http-cache-semantics@npm:^4.1.1":
|
"http-cache-semantics@npm:^4.1.1":
|
||||||
version: 4.1.1
|
version: 4.1.1
|
||||||
resolution: "http-cache-semantics@npm:4.1.1"
|
resolution: "http-cache-semantics@npm:4.1.1"
|
||||||
|
|||||||
Reference in New Issue
Block a user