Compare commits

...

8 Commits

Author SHA1 Message Date
975f145444 feat(dashboard): full width for sidebar items 2025-03-18 00:46:29 +01:00
391186d01f feat: athiti font 2025-03-18 00:46:10 +01:00
ae056cd88c 🚀RELEASE v1.7.0
All checks were successful
ci/woodpecker/push/build Pipeline was successful
ci/woodpecker/tag/release Pipeline was successful
2024-12-17 17:41:11 +01:00
7f989b206b fix(pdfgeneration): Added parent_group
Some checks failed
ci/woodpecker/push/build Pipeline failed
2024-12-17 17:40:19 +01:00
65ce02e777 refactor(cards): Switched over to new document-server api
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-12-17 17:32:33 +01:00
878d9714cb refactor(pdfgeneration): Switch to new document-server api
Some checks failed
ci/woodpecker/push/build Pipeline failed
2024-12-17 17:29:42 +01:00
f99b7f4bb8 refactor(pdfgeneration): Switched contract generation over to new document-server
All checks were successful
ci/woodpecker/push/build Pipeline was successful
2024-12-17 17:19:20 +01:00
e23098410c refactor(pdfgeneration): Switch cards over to new service 2024-12-17 17:09:55 +01:00
27 changed files with 300 additions and 440 deletions

View File

@@ -2,13 +2,31 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [1.7.0](https://git.odit.services/lfk/frontend/compare/1.6.0...1.7.0)
- refactor(pdfgeneration): Switch cards over to new service [`e230984`](https://git.odit.services/lfk/frontend/commit/e23098410c7d0b326cdbbb3a4b63fed10611e252)
- refactor(pdfgeneration): Switch to new document-server api [`878d971`](https://git.odit.services/lfk/frontend/commit/878d9714cbc0a60cfd96bd1faf8af6af46e6fb5e)
- refactor(pdfgeneration): Switched contract generation over to new document-server [`f99b7f4`](https://git.odit.services/lfk/frontend/commit/f99b7f4bb8f166bb966022ddd10689c082d248f0)
- refactor(cards): Switched over to new document-server api [`65ce02e`](https://git.odit.services/lfk/frontend/commit/65ce02e777e6e9b3cfed248de680e5f292b3a639)
- fix(pdfgeneration): Added parent_group [`7f989b2`](https://git.odit.services/lfk/frontend/commit/7f989b206b16e2687d01a38da8e3ea9be0a52ba5)
#### [1.6.0](https://git.odit.services/lfk/frontend/compare/1.5.3...1.6.0)
> 11 December 2024
- refactor(orgs): Swtich to new selfservice baseurl [`e2d6fbb`](https://git.odit.services/lfk/frontend/commit/e2d6fbb513dc9fe7ce05855edb4b0b4b5daeb07a)
- chore: bump [`04494d2`](https://git.odit.services/lfk/frontend/commit/04494d2a2a542f25f785f3bb23e49e5eb0691c0a)
#### [1.5.3](https://git.odit.services/lfk/frontend/compare/1.5.2...1.5.3)
> 26 November 2024
- feat(dx): Yarn support [`fc15c68`](https://git.odit.services/lfk/frontend/commit/fc15c68cba0d1986563eaf63da3a68784a685a9e)
- feat(about): cleanup ui [`84aa846`](https://git.odit.services/lfk/frontend/commit/84aa846b87186b52a2f8632724d4f2cb70af062b)
- feat(dashboard): reorder menu items [`e967d8d`](https://git.odit.services/lfk/frontend/commit/e967d8d20c6972b64b0096594a09043553e9c7e5)
- fix: unexpected/ missing props [`d803f3d`](https://git.odit.services/lfk/frontend/commit/d803f3d4905d6f792b77d17025467ac13c29068b)
- chore(deps): bump some [`68b4309`](https://git.odit.services/lfk/frontend/commit/68b4309164eac40b6fda969b60a7e238985d49f8)
- 🚀RELEASE v1.5.3 [`477c650`](https://git.odit.services/lfk/frontend/commit/477c650f3f6dd2eadf5f1cc404e8fc9b02a7841b)
- fix(ci): Switch over to new woodpecker version [`7ba890d`](https://git.odit.services/lfk/frontend/commit/7ba890dfd7ba908ebef0338f6faa5e7d804cb5ef)
- refactor(ci): Only build licences, don't export [`32b5f54`](https://git.odit.services/lfk/frontend/commit/32b5f5420bf9ff656b713d61b3a0113b9d6cb69f)
- feat: cleanup random page toasts [`ad4db88`](https://git.odit.services/lfk/frontend/commit/ad4db882f0f4d00a80ae5e0072e09c071c07ffa2)

View File

@@ -13,7 +13,7 @@
<body>
<span style="display: none; visibility: hidden" id="buildinfo"
>RELEASE_INFO-1.5.3-RELEASE_INFO</span
>RELEASE_INFO-1.7.0-RELEASE_INFO</span
>
<noscript>You need to enable JavaScript to run this app.</noscript>
<script src="/env.js"></script>

View File

@@ -1,6 +1,6 @@
{
"name": "@odit/lfk-frontend",
"version": "1.6.0",
"version": "1.7.0",
"type": "module",
"scripts": {
"i18n-order": "node order.js",
@@ -42,6 +42,7 @@
}
},
"dependencies": {
"@fontsource/athiti": "^5.2.5",
"@odit/lfk-client-js": "1.1.3",
"@paralleldrive/cuid2": "2.2.2",
"@tanstack/svelte-table": "8.9.1",

8
pnpm-lock.yaml generated
View File

@@ -8,6 +8,9 @@ importers:
.:
dependencies:
'@fontsource/athiti':
specifier: ^5.2.5
version: 5.2.5
'@odit/lfk-client-js':
specifier: 1.1.3
version: 1.1.3
@@ -231,6 +234,9 @@ packages:
cpu: [x64]
os: [win32]
'@fontsource/athiti@5.2.5':
resolution: {integrity: sha512-vHoAKBBw+wI4y3bGOkiogOkgcoLH7+SWtNNo/nBQ1XfhvfRPX/91xGtclEdwqUlbOJTCkNzEecdKChJQ5MsDFg==}
'@formatjs/ecma402-abstract@1.11.4':
resolution: {integrity: sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==}
@@ -2024,6 +2030,8 @@ snapshots:
'@esbuild/win32-x64@0.17.16':
optional: true
'@fontsource/athiti@5.2.5': {}
'@formatjs/ecma402-abstract@1.11.4':
dependencies:
'@formatjs/intl-localematcher': 0.2.25

View File

@@ -5,8 +5,11 @@
import { RunnerCardService } from "@odit/lfk-client-js";
import { createEventDispatcher } from "svelte";
import toast from "svelte-french-toast";
import DocumentServer from "../pdf_generation/DocumentServer";
export let bulk_modal_open;
const dispatch = createEventDispatcher();
const documentServer = new DocumentServer(config.baseurl_documentserver,config.documentserver_key);
$: card_count = 0;
$: is_card_count_valid = card_count > 0;
@@ -60,24 +63,7 @@
toast.success($_("created-blanco-cards"));
toast.loading($_("generating-pdf"));
dispatch("created", { cards: result });
fetch(
`${config.baseurl_documentserver}/cards?&download=true&key=${config.documentserver_key}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(result),
}
)
.then((response) => {
if (response.status != "200") {
toast.dismiss();
toast.error($_("pdf-generation-failed"));
} else {
return response.blob();
}
})
documentServer.generateCards(result, "de")
.then((blob) => {
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");

View File

@@ -11,7 +11,7 @@
</script>
<section class="container p-5">
<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono">
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
{$_("cards")}
</h4>
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:CREATE")}

View File

@@ -8,7 +8,7 @@
</script>
<section class="container p-5">
<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono">
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
{$_("contacts")}
</h4>
{#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT:CREATE")}

View File

@@ -25,7 +25,7 @@
<nav class="text-sm font-medium text-gray-600" aria-label="Main Navigation">
<a
class:activenav={$router.path === "/"}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full"
href="/"
>
<svg
@@ -43,7 +43,7 @@
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:GET")}
<a
class:activenav={$router.path === "/runners/"}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full"
href="/runners/"
>
<svg
@@ -64,7 +64,7 @@
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:GET")}
<a
class:activenav={$router.path === "/teams/"}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full"
href="/teams/"
>
<svg
@@ -85,7 +85,7 @@
{#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION:GET")}
<a
class:activenav={$router.path.includes("/orgs/")}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full"
href="/orgs/"
>
<svg
@@ -106,7 +106,7 @@
{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:GET")}
<a
class:activenav={$router.path.includes("/donors/")}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full"
href="/donors/"
>
<svg
@@ -127,7 +127,7 @@
{#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:GET")}
<a
class:activenav={$router.path.includes("/donations/")}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full"
href="/donations/"
>
<svg
@@ -148,7 +148,7 @@
{#if store.state.jwtinfo.userdetails.permissions.includes("TRACK:GET")}
<a
class:activenav={$router.path === "/tracks/"}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full"
href="/tracks/"
>
<svg
@@ -169,7 +169,7 @@
{#if store.state.jwtinfo.userdetails.permissions.includes("CARD:GET")}
<a
class:activenav={$router.path === "/cards/"}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full"
href="/cards/"
>
<svg
@@ -192,7 +192,7 @@
{#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:GET")}
<a
class:activenav={$router.path === "/scans/"}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full"
href="/scans/"
>
<svg
@@ -214,7 +214,7 @@
{#if store.state.jwtinfo.userdetails.permissions.includes("CONTACT:GET")}
<a
class:activenav={$router.path === "/contacts/"}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full"
href="/contacts/"
>
<svg
@@ -235,7 +235,7 @@
{#if store.state.jwtinfo.userdetails.permissions.includes("STATION:GET")}
<a
class:activenav={$router.path === "/scanstations/"}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full"
href="/scanstations/"
>
<svg
@@ -257,7 +257,7 @@
{#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:GET")}
<a
class:activenav={$router.path === "/statsclients/"}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full"
href="/statsclients/"
>
<svg
@@ -279,7 +279,7 @@
{#if store.state.jwtinfo.userdetails.permissions.includes("USER:GET")}
<a
class:activenav={$router.path === "/users/"}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full"
href="/users/"
>
<svg
@@ -300,7 +300,7 @@
{#if store.state.jwtinfo.userdetails.permissions.includes("USERGROUP:GET")}
<a
class:activenav={$router.path === "/groups/"}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full"
href="/groups/"
>
<svg
@@ -320,7 +320,7 @@
{/if}
<a
class:activenav={$router.path === "/settings/"}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full"
href="/settings/"
>
<svg
@@ -339,7 +339,7 @@
</a>
<a
class:activenav={$router.path === "/about/"}
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full"
href="/about/"
>
<svg
@@ -358,7 +358,7 @@
</a>
<button
tabindex="0"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900"
class="flex items-center px-4 py-3 transition cursor-pointer group hover:bg-gray-200 hover:text-gray-900 w-full"
on:click={() => {
AuthService.authControllerLogout();
logout();

View File

@@ -7,7 +7,7 @@
</script>
<div class="p-2 md:p-5 overflow-x-hidden">
<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono">
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
{$_("dashboard-greeting")} <span class="text-blue-500"
>{store.state.jwtinfo.userdetails.firstname}
{store.state.jwtinfo.userdetails.lastname}</span

View File

@@ -9,7 +9,7 @@
</script>
<section class="container p-5">
<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono">
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
{$_("donations")}
</h4>
{#if store.state.jwtinfo.userdetails.permissions.includes("DONATION:CREATE")}

View File

@@ -9,7 +9,7 @@
</script>
<section class="container p-5">
<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono">
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
{$_("donors")}
</h4>
{#if store.state.jwtinfo.userdetails.permissions.includes("DONOR:CREATE")}

View File

@@ -97,7 +97,7 @@
{/if}
<!-- /// -->
<section class="container p-5">
<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono">
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
{$_("about")}
</h4>
<p class="mt-2 mb-2">
@@ -109,7 +109,7 @@
<br />
<span>{$_("lfk-is-os")}</span>
</p>
<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono">
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
{$_("credits")}
</h4>
<p class="text-left">{$_("oss_credit_description")}</p>

View File

@@ -8,7 +8,7 @@
</script>
<section class="container p-5">
<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono">
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
{$_("user-groups")}
</h4>
{#if store.state.jwtinfo.userdetails.permissions.includes("USERGROUP:CREATE")}

View File

@@ -10,7 +10,7 @@
</script>
<section class="container p-5">
<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono">
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
{$_("organizations")}
</h4>
{#if store.state.jwtinfo.userdetails.permissions.includes("ORGANIZATION:CREATE")}

View File

@@ -0,0 +1,142 @@
class DocumentServer {
baseUrl: string;
apiKey: string;
constructor(baseUrl: string, apiKey: string){
this.baseUrl = baseUrl;
this.apiKey = apiKey;
}
async generateCards(cards: any[], locale: string) {
const generateCards = new Array<any>();
for (let i = 0; i < cards.length; i++) {
const card = {
id: cards[i].id,
enabled: cards[i].enabled,
code: cards[i].code,
runner: {
id: cards[i]?.runner?.id,
first_name: cards[i]?.runner?.firstname,
middle_name: cards[i]?.runner?.middlename,
last_name: cards[i]?.runner?.lastname,
group: {
id: cards[i]?.runner?.group.id,
name: cards[i]?.runner?.group.name,
parent_group: {
id: cards[i]?.runner?.group?.parentGroup?.id,
name: cards[i]?.runner?.group?.parentGroup?.name,
}
}
}
}
generateCards.push(card)
}
const response = await fetch(`${this.baseUrl}/v1/pdfs/cards?key=${this.apiKey}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
locale,
cards: generateCards,
}),
});
const blob = await response.blob();
return blob;
}
async generateContracts(runners: any[], locale: string) {
const generateRunners = new Array<any>();
for (let i = 0; i < runners.length; i++) {
console.log(runners[i])
const card = {
id: runners[i].id,
first_name: runners[i].firstname,
middle_name: runners[i].middlename,
last_name: runners[i].lastname,
group: {
id: runners[i].group.id,
name: runners[i].group.name,
parent_group: {
id: runners[i]?.group?.parentGroup?.id,
name: runners[i]?.group?.parentGroup?.name,
}
}
}
generateRunners.push(card)
}
const response = await fetch(`${this.baseUrl}/v1/pdfs/contracts?key=${this.apiKey}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
locale,
runners: generateRunners,
}),
});
const blob = await response.blob();
return blob;
}
async generateCertificates(runners: any[], locale: string) {
const generateRunners = new Array<any>();
for (let i = 0; i < runners.length; i++) {
const certificate = {
id: runners[i].id,
first_name: runners[i].firstname,
middle_name: runners[i].middlename,
last_name: runners[i].lastname,
group: {
id: runners[i].group.id,
name: runners[i].group.name,
parent_group: {
id: runners[i]?.group?.parentGroup?.id,
name: runners[i]?.group?.parentGroup?.name,
}
},
distance: runners[i].distance,
distance_donations: runners[i].distanceDonations.map((distanceDonation: any) =>{
return {
id: distanceDonation.id,
amount: distanceDonation.amount,
amount_per_distance: distanceDonation.amountPerDistance,
donor: {
id: distanceDonation.donor.id,
first_name: distanceDonation.donor.firstname,
middle_name: distanceDonation.donor.middlename,
last_name: distanceDonation.donor.lastname,
}
}
}),
}
generateRunners.push(certificate)
}
const response = await fetch(`${this.baseUrl}/v1/pdfs/certificates?key=${this.apiKey}`, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
},
body: JSON.stringify({
locale,
runners: generateRunners,
}),
});
const blob = await response.blob();
return blob;
}
}
export default DocumentServer;

View File

@@ -6,9 +6,11 @@
RunnerTeamService,
} from "@odit/lfk-client-js";
import toast from 'svelte-french-toast'
import DocumentServer from "./DocumentServer.ts"
import { init } from "@paralleldrive/cuid2";
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
const documentServer = new DocumentServer(config.baseurl_documentserver,config.documentserver_key);
export let cards_show = false;
export let generate_cards = [];
@@ -25,6 +27,18 @@
}
});
function download (blob, fileName){
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
a.remove();
toast.dismiss();
toast($_("pdf-successfully-generated"));
}
function generateRunnerCards(locale) {
cards_dropdown_open = false;
@@ -41,34 +55,9 @@
function generateCards(locale) {
toast.loading($_("generating-pdf"));
fetch(
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(generate_cards),
}
)
.then((response) => {
if (response.status != "200") {
toast.dismiss();
toast.error($_("pdf-generation-failed"));
} else {
return response.blob();
}
})
documentServer.generateCards(generate_cards, locale)
.then((blob) => {
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
a.download = `${$_("runnercards")}-${locale}-${createId()}.pdf`;
document.body.appendChild(a);
a.click();
a.remove();
toast.dismiss();
toast($_("pdf-successfully-generated"));
download(blob, `${$_("runnercards")}-${locale}-${createId()}.pdf`);
})
.catch((err) => {
console.error(err);
@@ -88,40 +77,15 @@
}
cards.push(card);
}
fetch(
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(cards),
}
)
.then((response) => {
if (response.status != "200") {
toast.dismiss();
toast.error($_("pdf-generation-failed"));
} else {
return response.blob();
}
})
documentServer.generateCards(cards, locale)
.then((blob) => {
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
let fileName = `${$_("runnercards")}-${locale}-${createId()}.pdf`;
if (generate_runners.length == 1) {
a.download = `${$_("runnercards")}_${generate_runners[0].firstname}_${
fileName = `${$_("runnercards")}_${generate_runners[0].firstname}_${
generate_runners[0].lastname
}-${locale}-${createId()}.pdf`;
} else {
a.download = `${$_("runnercards")}-${locale}-${createId()}.pdf`;
}
document.body.appendChild(a);
a.click();
a.remove();
toast.dismiss();
toast($_("pdf-successfully-generated"));
download(blob, fileName);
})
.catch((err) => {});
}
@@ -144,39 +108,11 @@
}
cards.push(card);
}
fetch(
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(cards),
}
)
.then((response) => {
if (response.status != "200") {
toast.dismiss();
toast.error($_("pdf-generation-failed"));
} else {
return response.blob();
}
})
documentServer.generateCards(cards, locale)
.then((blob) => {
count++;
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
a.download = `${$_("runnercards")}_${
download(blob, `${$_("runnercards")}_${
t.name
}-${locale}-${createId()}.pdf`;
document.body.appendChild(a);
a.click();
a.remove();
if (count === generate_teams.length) {
toast.dismiss();
toast.success($_("pdfs-successfully-generated"));
}
}-${locale}-${createId()}.pdf`)
})
.catch((err) => {});
}
@@ -205,38 +141,11 @@
}
cards.push(card);
}
await fetch(
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(cards),
}
)
.then((response) => {
if (response.status != "200") {
toast.dismiss();
toast.error($_("pdf-generation-failed"));
} else {
return response.blob();
}
})
await documentServer.generateCards(cards, locale)
.then((blob) => {
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
a.download = `${$_("runnercards")}_${
download(blob, `${$_("runnercards")}_${
o.name
}_direct-${locale}-${createId()}.pdf`;
document.body.appendChild(a);
a.click();
a.remove();
if (count === o.teams.length && count_orgs === generate_orgs.length) {
toast.dismiss();
toast.success($_("pdfs-successfully-generated"));
}
}_direct-${locale}-${createId()}.pdf`)
})
.catch((err) => {});
for (const t of o.teams) {
@@ -254,41 +163,11 @@
}
cards.push(card);
}
await fetch(
`${config.baseurl_documentserver}/cards?locale=${locale}&download=true&key=${config.documentserver_key}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(cards),
}
)
.then((response) => {
if (response.status != "200") {
toast.dismiss();
toast.error($_("pdf-generation-failed"));
} else {
return response.blob();
}
})
await documentServer.generateCards(cards, locale)
.then((blob) => {
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
a.download = `${$_("runnercards")}_${o.name}_${
download(blob, `${$_("runnercards")}_${o.name}_${
t.name
}-${locale}-${createId()}.pdf`;
document.body.appendChild(a);
a.click();
a.remove();
if (
count === o.teams.length &&
count_orgs === generate_orgs.length
) {
toast.dismiss();
toast($_("pdfs-successfully-generated"));
}
}-${locale}-${createId()}.pdf`)
})
.catch((err) => {});
}

View File

@@ -7,7 +7,10 @@
} from "@odit/lfk-client-js";
import { init } from "@paralleldrive/cuid2";
import toast from "svelte-french-toast";
import DocumentServer from "./DocumentServer";
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
const documentServer = new DocumentServer(config.baseurl_documentserver,config.documentserver_key);
export let certificates_show = false;
export let generate_runners = [];
@@ -34,6 +37,17 @@
generateRunnerCertificates(locale);
}
}
function download (blob, fileName){
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
a.remove();
toast.dismiss();
toast($_("pdf-successfully-generated"));
}
async function generateRunnerCertificates(locale) {
toast.loading($_("generating-pdf"));
@@ -45,40 +59,15 @@
current_donations.filter((d) => d.runner?.id == runner.id) || [];
certificateRunners.push(runner);
}
fetch(
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(certificateRunners),
}
)
.then((response) => {
if (response.status != "200") {
toast.dismiss();
toast.error($_("pdf-generation-failed"));
} else {
return response.blob();
}
})
documentServer.generateCertificates(certificateRunners, locale)
.then((blob) => {
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
let fileName = `${$_("certificates")}-${locale}.pdf`
if (generate_runners.length == 1) {
a.download = `${$_("certificates")}_${
fileName = `${$_("certificates")}_${
generate_runners[0].firstname
}_${generate_runners[0].lastname}-${locale}-${createId()}.pdf`;
} else {
a.download = `${$_("certificates")}-${locale}.pdf`;
}
document.body.appendChild(a);
a.click();
a.remove();
toast.dismiss();
toast($_("pdf-successfully-generated"));
download(blob, fileName);
})
.catch((err) => {});
}
@@ -98,39 +87,12 @@
current_donations.filter((d) => d.runner?.id == runner.id) || [];
certificateRunners.push(runner);
}
fetch(
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(certificateRunners),
}
)
.then((response) => {
if (response.status != "200") {
toast.dismiss();
toast.error($_("pdf-generation-failed"));
} else {
return response.blob();
}
})
documentServer.generateCertificates(certificateRunners, locale)
.then((blob) => {
count++;
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
a.download = `${$_("certificates")}_${
download(blob, `${$_("certificates")}_${
t.name
}-${locale}-${createId()}.pdf`;
document.body.appendChild(a);
a.click();
a.remove();
if (count === generate_teams.length) {
toast.dismiss();
toast.success($_("pdfs-successfully-generated"));
}
}-${locale}-${createId()}.pdf`)
})
.catch((err) => {});
}
@@ -156,38 +118,11 @@
current_donations.filter((d) => d.runner?.id == runner.id) || [];
certificateRunners.push(runner);
}
await fetch(
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(certificateRunners),
}
)
.then((response) => {
if (response.status != "200") {
toast.dismiss();
toast.error($_("pdf-generation-failed"));
} else {
return response.blob();
}
})
await documentServer.generateCertificates(certificateRunners, locale)
.then((blob) => {
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
a.download = `${$_("certificates")}_${
download(blob, `${$_("certificates")}_${
o.name
}-${locale}-${createId()}.pdf`;
document.body.appendChild(a);
a.click();
a.remove();
if (count === o.teams.length && count_orgs === generate_orgs.length) {
toast.dismiss();
toast.success($_("pdfs-successfully-generated"));
}
}-${locale}-${createId()}.pdf`)
})
.catch((err) => {});
for (const t of o.teams) {
@@ -201,34 +136,11 @@
current_donations.filter((d) => d.runner?.id == runner.id) || [];
certificateRunners.push(runner);
}
await fetch(
`${config.baseurl_documentserver}/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(certificateRunners),
}
)
.then((response) => {
if (response.status != "200") {
toast.dismiss();
toast.error($_("pdf-generation-failed"));
} else {
return response.blob();
}
})
await documentServer.generateCertificates(certificateRunners, locale)
.then((blob) => {
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
a.download = `${$_("certificates")}_${o.name}_${
download(blob, `${$_("certificates")}_${o.name}_${
t.name
}-${locale}-${createId()}.pdf`;
document.body.appendChild(a);
a.click();
a.remove();
}-${locale}-${createId()}.pdf`)
if (
count === o.teams.length &&
count_orgs === generate_orgs.length

View File

@@ -4,10 +4,12 @@
RunnerOrganizationService,
RunnerTeamService,
} from "@odit/lfk-client-js";
import DocumentServer from "./DocumentServer";
import { init } from "@paralleldrive/cuid2";
import toast from "svelte-french-toast";
const createId = init({ length: 10, fingerprint: "lfk-frontend" });
const documentServer = new DocumentServer(config.baseurl_documentserver,config.documentserver_key);
export let sponsoring_contracts_show = false;
export let generate_runners = [];
@@ -34,6 +36,17 @@
generateRunnerContracts(locale);
}
}
function download (blob, fileName){
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
a.download = fileName;
document.body.appendChild(a);
a.click();
a.remove();
toast.dismiss();
toast($_("pdf-successfully-generated"));
}
async function generateTeamContracts(locale) {
toast.loading($_("generating-pdfs"));
@@ -43,38 +56,11 @@
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
t.id
);
fetch(
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(runners),
}
)
.then((response) => {
if (response.status != "200") {
toast.dismiss();
toast.error($_("pdf-generation-failed"));
} else {
return response.blob();
}
})
documentServer.generateContracts(runners, locale)
.then((blob) => {
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
a.download = `${$_("sponsorings")}_${
download(blob, `${$_("sponsorings")}_${
t.name
}-${locale}-${createId()}.pdf`;
document.body.appendChild(a);
a.click();
a.remove();
if (count === generate_teams.length) {
toast.dismiss();
toast.success($_("pdfs-successfully-generated"));
}
}-${locale}-${createId()}.pdf`)
})
.catch((err) => {});
}
@@ -91,38 +77,11 @@
o.id,
true
);
await fetch(
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(runners),
}
)
.then((response) => {
if (response.status != "200") {
toast.dismiss();
toast.error($_("pdf-generation-failed"));
} else {
return response.blob();
}
})
await documentServer.generateContracts(runners, locale)
.then((blob) => {
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
a.download = `${$_("sponsorings")}_${
download(blob, `${$_("sponsorings")}_${
o.name
}_direct-${locale}-${createId()}.pdf`;
document.body.appendChild(a);
a.click();
a.remove();
if (count === o.teams.length && count_orgs === generate_orgs.length) {
toast.dismiss();
toast.success($_("pdfs-successfully-generated"));
}
}_direct-${locale}-${createId()}.pdf`)
})
.catch((err) => {});
for (const t of o.teams) {
@@ -130,41 +89,11 @@
let runners = await RunnerTeamService.runnerTeamControllerGetRunners(
t.id
);
await fetch(
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(runners),
}
)
.then((response) => {
if (response.status != "200") {
toast.dismiss();
toast.error($_("pdf-generation-failed"));
} else {
return response.blob();
}
})
await documentServer.generateContracts(runners, locale)
.then((blob) => {
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
a.download = `${$_("sponsorings")}_${o.name}_${
download(blob, `${$_("sponsorings")}_${o.name}_${
t.name
}-${locale}-${createId()}.pdf`;
document.body.appendChild(a);
a.click();
a.remove();
if (
count === o.teams.length &&
count_orgs === generate_orgs.length
) {
toast.dismiss();
toast($_("pdfs-successfully-generated"));
}
}-${locale}-${createId()}.pdf`)
})
.catch((err) => {});
}
@@ -173,39 +102,15 @@
function generateRunnerContracts(locale) {
toast.loading($_("generating-pdf"));
fetch(
`${config.baseurl_documentserver}/contracts?locale=${locale}&download=true&key=${config.documentserver_key}`,
{
method: "POST",
headers: {
"Content-Type": "application/json",
},
body: JSON.stringify(generate_runners),
}
)
.then((response) => {
if (response.status != "200") {
toast.dismiss();
toast.error($_("pdf-generation-failed"));
} else {
return response.blob();
}
})
documentServer.generateContracts(generate_runners, locale)
.then((blob) => {
const url = window.URL.createObjectURL(blob);
let a = document.createElement("a");
a.href = url;
let fileName = `${$_("sponsorings")}-${locale}-${createId()}.pdf`
if (generate_runners.length == 1) {
a.download = `${$_("sponsorings")}_${generate_runners[0].firstname}_${
fileName= `${$_("sponsorings")}_${generate_runners[0].firstname}_${
generate_runners[0].lastname
}-${locale}-${createId()}.pdf`;
}
a.download = `${$_("sponsorings")}-${locale}-${createId()}.pdf`;
document.body.appendChild(a);
a.click();
a.remove();
toast.dismiss();
toast($_("pdf-successfully-generated"));
download(blob, fileName);
})
.catch((err) => {
console.error(err);

View File

@@ -11,7 +11,7 @@
</script>
<section class="container p-5">
<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono">
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
{$_("runners")}
</h4>
{#if store.state.jwtinfo.userdetails.permissions.includes("RUNNER:CREATE")}

View File

@@ -9,7 +9,7 @@
</script>
<section class="container p-5">
<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono">
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
{$_("scans")}
</h4>
{#if store.state.jwtinfo.userdetails.permissions.includes("SCAN:CREATE")}

View File

@@ -24,7 +24,7 @@
</script>
<section class="container p-5">
<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono">
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
{$_("scanstations")}
</h4>
{#if store.state.jwtinfo.userdetails.permissions.includes("STATION:CREATE")}

View File

@@ -11,7 +11,7 @@
</script>
<section class="container p-5">
<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono">
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
{$_("statsclients")}
</h4>
{#if store.state.jwtinfo.userdetails.permissions.includes("STATSCLIENT:CREATE")}

View File

@@ -8,7 +8,7 @@
</script>
<section class="container p-5">
<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono">
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
{$_("teams")}
</h4>
{#if store.state.jwtinfo.userdetails.permissions.includes("TEAM:CREATE")}

View File

@@ -19,7 +19,7 @@
</script>
<section class="container p-5">
<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono">
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
{$_("tracks")}
</h4>
<button

View File

@@ -8,7 +8,7 @@
</script>
<section class="container p-5">
<h4 class="mb-1 text-3xl font-extrabold leading-tight font-mono">
<h4 class="mb-1 text-3xl font-extrabold leading-tight">
{$_("users")}
</h4>
{#if store.state.jwtinfo.userdetails.permissions.includes("USER:CREATE")}

View File

@@ -1,5 +1,11 @@
import "./style.css";
import App from "./App.svelte";
import '@fontsource/athiti/200.css';
import '@fontsource/athiti/300.css';
import '@fontsource/athiti/400.css';
import '@fontsource/athiti/500.css';
import '@fontsource/athiti/600.css';
import '@fontsource/athiti/700.css';
const app = new App({
target: document.body,

View File

@@ -4,4 +4,7 @@
@apply bg-gray-300;
@apply text-black;
}
*{
font-family: Athiti;
}
@tailwind utilities;