Compare commits
39 Commits
0.11.0
...
fa55fce76e
| Author | SHA1 | Date | |
|---|---|---|---|
| fa55fce76e | |||
| f47d5e347d | |||
| 7488a8b597 | |||
| 2e3ac154be | |||
| 2472640755 | |||
| 7b685d6cad | |||
| 17f6f4e616 | |||
| 48cfc15cfb | |||
| bb9b779cee | |||
| af63ce67ae | |||
| 5cc4871ec4 | |||
| c8cfe669b8 | |||
| 8b74d6d759 | |||
| a9227768de | |||
| d966e1d4de | |||
| ceb2146c1b | |||
| 8d006d8c74 | |||
| 777304f259 | |||
| 12433f7c23 | |||
| 44b53da345 | |||
| ab45fc144e | |||
| e99e9e0708 | |||
| 467404bfc8 | |||
| ce50fa2a62 | |||
| 10a011d842 | |||
| 5352410d0c | |||
| c5d155396a | |||
| 93187099d3 | |||
| aa24b1dce5 | |||
| eb3ede9593 | |||
| d7fecfbd0b | |||
| b065b4ff21 | |||
| 0cd3e937d8 | |||
| 6be2ee626a | |||
| 008027db0e | |||
| aec5e3473e | |||
| 95c8fde72f | |||
| 0f32968fae | |||
| ae79e9fea1 |
6
.devcontainer/Dockerfile
Normal file
6
.devcontainer/Dockerfile
Normal file
@@ -0,0 +1,6 @@
|
|||||||
|
FROM mcr.microsoft.com/vscode/devcontainers/base:alpine-3.12
|
||||||
|
RUN apk update
|
||||||
|
RUN apk add --upgrade nodejs-current npm
|
||||||
|
RUN npm i -g yarn rimraf
|
||||||
|
RUN rimraf node_modules
|
||||||
|
RUN yarn set version berry
|
||||||
20
.devcontainer/devcontainer.json
Normal file
20
.devcontainer/devcontainer.json
Normal file
@@ -0,0 +1,20 @@
|
|||||||
|
{
|
||||||
|
"name": "Node.js",
|
||||||
|
"build": {
|
||||||
|
"dockerfile": "Dockerfile"
|
||||||
|
},
|
||||||
|
"settings": {
|
||||||
|
"terminal.integrated.shell.linux": "/bin/sh"
|
||||||
|
},
|
||||||
|
"extensions": [
|
||||||
|
"dbaeumer.vscode-eslint",
|
||||||
|
"2gua.rainbow-brackets",
|
||||||
|
"christian-kohler.npm-intellisense",
|
||||||
|
"remimarsal.prettier-now",
|
||||||
|
"svelte.svelte-vscode",
|
||||||
|
"lokalise.i18n-ally",
|
||||||
|
"fivethree.vscode-svelte-snippets",
|
||||||
|
"voorjaar.windicss-intellisense"
|
||||||
|
],
|
||||||
|
"postCreateCommand": "yarn && yarn dev --open"
|
||||||
|
}
|
||||||
@@ -1,3 +1 @@
|
|||||||
public/env.sample.js
|
public/env.sample.js
|
||||||
public/workbox-*.js
|
|
||||||
public/workbox-*.js.map
|
|
||||||
9
.gitignore
vendored
9
.gitignore
vendored
@@ -1,11 +1,10 @@
|
|||||||
node_modules
|
node_modules
|
||||||
build
|
|
||||||
package-lock.json
|
package-lock.json
|
||||||
yarn.lock
|
yarn.lock
|
||||||
*.map
|
*.map
|
||||||
public/env.js
|
public/env.js
|
||||||
public/sw.js
|
|
||||||
public/index.html
|
|
||||||
public/workbox-*.js
|
|
||||||
svelte.config.js
|
|
||||||
public/index.html
|
public/index.html
|
||||||
|
/dist
|
||||||
|
.yarn
|
||||||
|
.pnp.js
|
||||||
|
.yarnrc.yml
|
||||||
|
|||||||
3
.vscode/extensions.json
vendored
3
.vscode/extensions.json
vendored
@@ -5,7 +5,8 @@
|
|||||||
"remimarsal.prettier-now",
|
"remimarsal.prettier-now",
|
||||||
"svelte.svelte-vscode",
|
"svelte.svelte-vscode",
|
||||||
"lokalise.i18n-ally",
|
"lokalise.i18n-ally",
|
||||||
"fivethree.vscode-svelte-snippets"
|
"fivethree.vscode-svelte-snippets",
|
||||||
|
"voorjaar.windicss-intellisense"
|
||||||
],
|
],
|
||||||
"unwantedRecommendations": [
|
"unwantedRecommendations": [
|
||||||
"antfu.i18n-ally"
|
"antfu.i18n-ally"
|
||||||
|
|||||||
3
.vscode/settings.json
vendored
3
.vscode/settings.json
vendored
@@ -1,4 +1,5 @@
|
|||||||
{
|
{
|
||||||
"i18n-ally.localesPaths": "src/locales",
|
"i18n-ally.localesPaths": "src/locales",
|
||||||
"i18n-ally.keystyle": "nested"
|
"i18n-ally.keystyle": "nested",
|
||||||
|
"windicss.enableCodeFolding": false,
|
||||||
}
|
}
|
||||||
12
Dockerfile
12
Dockerfile
@@ -1,18 +1,14 @@
|
|||||||
FROM node:15.5.1-alpine3.12
|
FROM node:15.5.1-alpine3.12
|
||||||
WORKDIR /app
|
WORKDIR /app
|
||||||
RUN npm i -g pnpm
|
|
||||||
COPY package.json ./
|
COPY package.json ./
|
||||||
RUN pnpm i
|
RUN yarn
|
||||||
COPY package.json *.config.js workbox-config.js template-copy.js index.template.html s-config.template.js ./
|
COPY package.json *.config.js index.html ./
|
||||||
COPY src ./src
|
COPY src ./src
|
||||||
COPY public ./public
|
COPY public ./public
|
||||||
RUN pnpm run build
|
RUN yarn build
|
||||||
# final image
|
# final image
|
||||||
FROM alpine
|
FROM alpine
|
||||||
COPY --from=0 /app/build /app
|
COPY --from=0 /app/dist /app
|
||||||
RUN rm -rf /app/build/_dist_/components
|
|
||||||
RUN rm -rf /app/build/_dist_/locales
|
|
||||||
RUN rm -rf /app/build-manifest.json
|
|
||||||
FROM fholzer/nginx-brotli:v1.19.1
|
FROM fholzer/nginx-brotli:v1.19.1
|
||||||
COPY --from=1 /app /usr/share/nginx/html
|
COPY --from=1 /app /usr/share/nginx/html
|
||||||
COPY ./nginx.conf /etc/nginx/nginx.conf
|
COPY ./nginx.conf /etc/nginx/nginx.conf
|
||||||
22
README.md
Normal file
22
README.md
Normal file
@@ -0,0 +1,22 @@
|
|||||||
|
# @odit/lfk-frontend
|
||||||
|
|
||||||
|
## ✒️ Overview
|
||||||
|
This is an API client for [https://git.odit.services/lfk/backend](@lfk/backend)
|
||||||
|
- WebApp built with [Svelte](https://svelte.dev), [WindiCSS](https://windicss.org/) (to compile [TailwindCSS](https://tailwindcss.com/)) and [Vite](https://vitejs.dev).
|
||||||
|
|
||||||
|
This application is intended for use by admin users/ members only.
|
||||||
|
|
||||||
|
## 🚀 Getting Started
|
||||||
|
```
|
||||||
|
yarn
|
||||||
|
```
|
||||||
|
## Development
|
||||||
|
```
|
||||||
|
yarn dev
|
||||||
|
/
|
||||||
|
yarn dev --open
|
||||||
|
```
|
||||||
|
## Build
|
||||||
|
```
|
||||||
|
yarn build
|
||||||
|
```
|
||||||
@@ -10,14 +10,13 @@
|
|||||||
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
<meta name="viewport" content="width=device-width, initial-scale=1" />
|
||||||
<meta name="description" content="Lauf Für Kaya! - Admin" />
|
<meta name="description" content="Lauf Für Kaya! - Admin" />
|
||||||
<title>Lauf für Kaya! - Admin</title>
|
<title>Lauf für Kaya! - Admin</title>
|
||||||
__TAILWIND_INSERT__
|
|
||||||
</head>
|
</head>
|
||||||
|
|
||||||
<body>
|
<body>
|
||||||
<span style="display: none;visibility: hidden;" id="buildinfo">RELEASE_INFO-0.11.0-RELEASE_INFO</span>
|
<span style="display: none;visibility: hidden;" id="buildinfo">RELEASE_INFO-0.8.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>
|
||||||
<script defer type="module" src="/_dist_/index.js"></script>
|
<script type="module" src="/src/main.js"></script>
|
||||||
</body>
|
</body>
|
||||||
|
|
||||||
</html>
|
</html>
|
||||||
@@ -6,6 +6,15 @@ http {
|
|||||||
server {
|
server {
|
||||||
error_page 404 /index.html;
|
error_page 404 /index.html;
|
||||||
root /usr/share/nginx/html;
|
root /usr/share/nginx/html;
|
||||||
|
location = /index.html {
|
||||||
|
add_header Cache-Control 'no-store';
|
||||||
|
}
|
||||||
|
location = / {
|
||||||
|
add_header Cache-Control 'no-store';
|
||||||
|
}
|
||||||
|
location = /env.js {
|
||||||
|
add_header Cache-Control 'no-store';
|
||||||
|
}
|
||||||
location / {
|
location / {
|
||||||
try_files $uri $uri/ /index.html;
|
try_files $uri $uri/ /index.html;
|
||||||
}
|
}
|
||||||
|
|||||||
62
package.json
62
package.json
@@ -1,46 +1,40 @@
|
|||||||
{
|
{
|
||||||
"name": "@odit/lfk-frontend",
|
"name": "@odit/lfk-frontend",
|
||||||
"version": "0.11.0",
|
"version": "0.8.4",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
"i18n-order": "node order.js",
|
"i18n-order": "node order.js",
|
||||||
"dev:all": "yarn prebuild && snowpack dev",
|
"dev": "vite",
|
||||||
"dev": "cross-env NODE_ENV_ODIT=development_fast node template-copy.js && yarn build:sw && snowpack dev",
|
"build": "vite build",
|
||||||
"build": "yarn prebuild && snowpack build",
|
|
||||||
"prebuild": "cross-env NODE_ENV_ODIT=production node template-copy.js && yarn build:sw",
|
|
||||||
"build:sw": "workbox generateSW workbox-config.js",
|
|
||||||
"release": "release-it",
|
"release": "release-it",
|
||||||
"licenses:export": "license-exporter --json -o public"
|
"licenses:export": "license-exporter --json -o public"
|
||||||
},
|
},
|
||||||
"license": "CC-BY-NC-SA-4.0",
|
"license": "CC-BY-NC-SA-4.0",
|
||||||
"dependencies": {
|
|
||||||
"@odit/lfk-client-js": "0.9.2",
|
|
||||||
"check-password-strength": "^2.0.2",
|
|
||||||
"csvtojson": "^2.0.10",
|
|
||||||
"gridjs": "3.3.0",
|
|
||||||
"localforage": "1.9.0",
|
|
||||||
"marked": "^2.0.1",
|
|
||||||
"svelte-focus-trap": "1.0.1",
|
|
||||||
"svelte-i18n": "3.3.7",
|
|
||||||
"svelte-select": "^3.17.0",
|
|
||||||
"tailwindcss": "2.0.3",
|
|
||||||
"tinro": "0.6.1",
|
|
||||||
"toastify-js": "1.9.3",
|
|
||||||
"validator": "13.5.2",
|
|
||||||
"xlsx": "^0.16.9"
|
|
||||||
},
|
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@odit/license-exporter": "^0.0.11",
|
"check-password-strength": "2.0.2",
|
||||||
"@snowpack/plugin-svelte": "3.5.2",
|
"@odit/lfk-client-js": "0.10.1",
|
||||||
"auto-changelog": "^2.2.1",
|
"@odit/license-exporter": "0.0.11",
|
||||||
|
"@sveltejs/vite-plugin-svelte": "1.0.0-next.5",
|
||||||
|
"@types/html-minifier": "4.0.0",
|
||||||
|
"auto-changelog": "2.2.1",
|
||||||
"autoprefixer": "10.2.5",
|
"autoprefixer": "10.2.5",
|
||||||
"cross-env": "^7.0.3",
|
"csvtojson": "2.0.10",
|
||||||
"postcss": "8.2.8",
|
"gridjs": "3.4.0",
|
||||||
"postcss-load-config": "3.0.1",
|
"html-minifier": "4.0.0",
|
||||||
"release-it": "^14.4.1",
|
"localforage": "1.9.0",
|
||||||
"snowpack": "3.0.13",
|
"marked": "2.0.1",
|
||||||
"svelte": "3.35.0",
|
"release-it": "14.5.1",
|
||||||
"svelte-preprocess": "4.6.9",
|
"svelte": "3.37.0",
|
||||||
"workbox-cli": "6.1.2"
|
"svelte-focus-trap": "1.2.0",
|
||||||
|
"svelte-i18n": "3.3.9",
|
||||||
|
"svelte-preprocess": "4.7.0",
|
||||||
|
"svelte-select": "3.17.0",
|
||||||
|
"tailwindcss": "2.0.4",
|
||||||
|
"tinro": "0.6.1",
|
||||||
|
"toastify-js": "1.10.0",
|
||||||
|
"validator": "13.5.2",
|
||||||
|
"vite": "2.1.5",
|
||||||
|
"vite-plugin-windicss": "0.12.2",
|
||||||
|
"xlsx": "0.16.9"
|
||||||
},
|
},
|
||||||
"release-it": {
|
"release-it": {
|
||||||
"git": {
|
"git": {
|
||||||
@@ -56,7 +50,7 @@
|
|||||||
"publish": false
|
"publish": false
|
||||||
},
|
},
|
||||||
"hooks": {
|
"hooks": {
|
||||||
"after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md && node versionbuilder.js && git add index.template.html && node order.js && git add src/locales"
|
"after:bump": "npx auto-changelog --commit-limit false -p -u --hide-credit && git add CHANGELOG.md && node versionbuilder.js && git add index.html && node order.js && git add src/locales"
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
File diff suppressed because one or more lines are too long
@@ -1,6 +0,0 @@
|
|||||||
const sveltePreprocess = require('svelte-preprocess');
|
|
||||||
const preprocess = sveltePreprocess(__insert__);
|
|
||||||
|
|
||||||
module.exports = {
|
|
||||||
preprocess
|
|
||||||
};
|
|
||||||
@@ -1,26 +0,0 @@
|
|||||||
/** @type {import("snowpack").SnowpackUserConfig } */
|
|
||||||
module.exports = {
|
|
||||||
mount: {
|
|
||||||
public: '/',
|
|
||||||
src: '/_dist_'
|
|
||||||
},
|
|
||||||
plugins: [ '@snowpack/plugin-svelte' ],
|
|
||||||
routes: [
|
|
||||||
/* Enable an SPA Fallback in development: */
|
|
||||||
{ match: 'routes', src: '.*', dest: '/index.html' }
|
|
||||||
],
|
|
||||||
packageOptions: {
|
|
||||||
/* ... */
|
|
||||||
sourceMap: false
|
|
||||||
},
|
|
||||||
devOptions: {
|
|
||||||
/* ... */
|
|
||||||
},
|
|
||||||
buildOptions: {
|
|
||||||
/* ... */
|
|
||||||
},
|
|
||||||
alias: {
|
|
||||||
/* ... */
|
|
||||||
},
|
|
||||||
optimize: { bundle: true, minify: true }
|
|
||||||
};
|
|
||||||
@@ -1,5 +1,4 @@
|
|||||||
<script>
|
<script>
|
||||||
import "./TailwindStyles.svelte";
|
|
||||||
import "toastify-js/src/toastify.css";
|
import "toastify-js/src/toastify.css";
|
||||||
import "gridjs/dist/theme/mermaid.css";
|
import "gridjs/dist/theme/mermaid.css";
|
||||||
import { Route, router } from "tinro";
|
import { Route, router } from "tinro";
|
||||||
@@ -53,7 +52,6 @@
|
|||||||
import { OpenAPI } from "@odit/lfk-client-js";
|
import { OpenAPI } from "@odit/lfk-client-js";
|
||||||
import UserDetail from "./components/users/UserDetail.svelte";
|
import UserDetail from "./components/users/UserDetail.svelte";
|
||||||
OpenAPI.BASE = config.baseurl;
|
OpenAPI.BASE = config.baseurl;
|
||||||
import { register as registerSW } from "./swmodule";
|
|
||||||
import TeamDetail from "./components/teams/TeamDetail.svelte";
|
import TeamDetail from "./components/teams/TeamDetail.svelte";
|
||||||
import UserPermissions from "./components/users/UserPermissions.svelte";
|
import UserPermissions from "./components/users/UserPermissions.svelte";
|
||||||
import GroupPermissions from "./components/groups/GroupPermissions.svelte";
|
import GroupPermissions from "./components/groups/GroupPermissions.svelte";
|
||||||
@@ -75,7 +73,6 @@
|
|||||||
import ScanDetail from "./components/scans/ScanDetail.svelte";
|
import ScanDetail from "./components/scans/ScanDetail.svelte";
|
||||||
import Cards from "./components/cards/Cards.svelte";
|
import Cards from "./components/cards/Cards.svelte";
|
||||||
store.init();
|
store.init();
|
||||||
registerSW();
|
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Route>
|
<Route>
|
||||||
|
|||||||
@@ -1,6 +0,0 @@
|
|||||||
<style global>
|
|
||||||
/*! @import */
|
|
||||||
@tailwind base;
|
|
||||||
@tailwind components;
|
|
||||||
@tailwind utilities;
|
|
||||||
</style>
|
|
||||||
@@ -149,7 +149,7 @@
|
|||||||
}).showToast();
|
}).showToast();
|
||||||
let count = 0;
|
let count = 0;
|
||||||
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
||||||
for await (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
|
||||||
);
|
);
|
||||||
@@ -216,7 +216,7 @@
|
|||||||
}).showToast();
|
}).showToast();
|
||||||
let count = 0;
|
let count = 0;
|
||||||
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
const current_cards = await RunnerCardService.runnerCardControllerGetAll();
|
||||||
for await (const o of generate_orgs) {
|
for (const o of generate_orgs) {
|
||||||
const runners = await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
const runners = await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
||||||
o.id
|
o.id
|
||||||
);
|
);
|
||||||
|
|||||||
273
src/components/pdf_generation/GenerateRunnerCertificates.svelte
Normal file
273
src/components/pdf_generation/GenerateRunnerCertificates.svelte
Normal file
@@ -0,0 +1,273 @@
|
|||||||
|
<script>
|
||||||
|
import { _ } from "svelte-i18n";
|
||||||
|
import {
|
||||||
|
DonationService,
|
||||||
|
RunnerTeamService,
|
||||||
|
RunnerOrganizationService
|
||||||
|
} from "@odit/lfk-client-js";
|
||||||
|
import Toastify from "toastify-js";
|
||||||
|
export let certificates_show = false;
|
||||||
|
export let generate_runners = [];
|
||||||
|
export let generate_orgs = [];
|
||||||
|
export let generate_teams = [];
|
||||||
|
$: certificates_dropdown_open = false;
|
||||||
|
document.addEventListener("click", function (e) {
|
||||||
|
if (
|
||||||
|
e.target.parentNode?.parentNode?.id != "certificates:dropdown" &&
|
||||||
|
e.target.parentNode?.parentNode?.id != "certificates:dropdown:menu"
|
||||||
|
) {
|
||||||
|
certificates_dropdown_open = false;
|
||||||
|
}
|
||||||
|
});
|
||||||
|
|
||||||
|
function generateCertificates(locale) {
|
||||||
|
certificates_dropdown_open = false;
|
||||||
|
|
||||||
|
if (generate_orgs.length > 0) {
|
||||||
|
generateOrgCertificates(locale);
|
||||||
|
} else if (generate_teams.length > 0) {
|
||||||
|
generateTeamCertificates(locale);
|
||||||
|
} else {
|
||||||
|
generateRunnerCertificates(locale);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateRunnerCertificates(locale) {
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("generating-pdf"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
const current_donations = await DonationService.donationControllerGetAll();
|
||||||
|
let certificateRunners = [];
|
||||||
|
for (let runner of generate_runners) {
|
||||||
|
runner.distanceDonations = current_donations.find((d) => d.runner?.id == runner.id) || [];
|
||||||
|
certificateRunners.push(runner);
|
||||||
|
}
|
||||||
|
fetch(
|
||||||
|
`${config.baseurl}/documents/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(certificateRunners),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = "Certificates.pdf";
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateTeamCertificates(locale) {
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("generating-pdfs"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
let count = 0;
|
||||||
|
const current_donations = await DonationService.donationControllerGetAll();
|
||||||
|
for (const t of generate_teams) {
|
||||||
|
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
|
t.id
|
||||||
|
);
|
||||||
|
let certificateRunners = [];
|
||||||
|
for (let runner of runners) {
|
||||||
|
runner.distanceDonations = current_donations.find((d) => d.runner?.id == runner.id) || [];
|
||||||
|
certificateRunners.push(runner);
|
||||||
|
}
|
||||||
|
console.log(certificateRunners)
|
||||||
|
fetch(
|
||||||
|
`${config.baseurl}/documents/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(certificateRunners),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
count++;
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = "Certificates_" + t.name + ".pdf";
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
if (count === generate_teams.length) {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdfs-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
async function generateOrgCertificates(locale) {
|
||||||
|
const toast = Toastify({
|
||||||
|
text: $_("generating-pdf"),
|
||||||
|
duration: -1,
|
||||||
|
}).showToast();
|
||||||
|
let count = 0;
|
||||||
|
const current_donations = await DonationService.donationControllerGetAll();
|
||||||
|
for (const o of generate_orgs) {
|
||||||
|
const runners = await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
||||||
|
o.id
|
||||||
|
);
|
||||||
|
let certificateRunners = [];
|
||||||
|
for (let runner of runners) {
|
||||||
|
runner.distanceDonations = current_donations.find((d) => d.runner?.id == runner.id) || [];
|
||||||
|
certificateRunners.push(runner);
|
||||||
|
}
|
||||||
|
fetch(
|
||||||
|
`${config.baseurl}/documents/certificates?locale=${locale}&download=true&key=${config.documentserver_key}`,
|
||||||
|
{
|
||||||
|
method: "POST",
|
||||||
|
headers: {
|
||||||
|
"Content-Type": "application/json",
|
||||||
|
},
|
||||||
|
body: JSON.stringify(certificateRunners),
|
||||||
|
}
|
||||||
|
)
|
||||||
|
.then((response) => {
|
||||||
|
if (response.status != "200") {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdf-generation-failed"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(90deg, hsla(281, 37%, 45%, 1) 0%, hsla(1, 62%, 48%, 1) 100%)",
|
||||||
|
}).showToast();
|
||||||
|
} else {
|
||||||
|
return response.blob();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.then((blob) => {
|
||||||
|
count++;
|
||||||
|
const url = window.URL.createObjectURL(blob);
|
||||||
|
let a = document.createElement("a");
|
||||||
|
a.href = url;
|
||||||
|
a.download = "Certificates_" + o.name + ".pdf";
|
||||||
|
document.body.appendChild(a);
|
||||||
|
a.click();
|
||||||
|
a.remove();
|
||||||
|
if (count === generate_orgs.length) {
|
||||||
|
toast.hideToast();
|
||||||
|
Toastify({
|
||||||
|
text: $_("pdfs-successfully-generated"),
|
||||||
|
duration: 3500,
|
||||||
|
backgroundColor:
|
||||||
|
"linear-gradient(to right, #00b09b, #96c93d)",
|
||||||
|
}).showToast();
|
||||||
|
}
|
||||||
|
})
|
||||||
|
.catch((err) => {});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
|
||||||
|
{#if certificates_show}
|
||||||
|
<div id="certificates:dropdown" class="relative inline-block">
|
||||||
|
<div>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
certificates_dropdown_open = !certificates_dropdown_open;
|
||||||
|
}}
|
||||||
|
type="button"
|
||||||
|
class="w-full justify-center rounded-md border border-transparent shadow-sm px-4 py-2 bg-gray-600 text-base font-medium text-white hover:bg-gray-700 focus:outline-none focus:ring-2 focus:ring-offset-2 focus:ring-gray-500 sm:ml-3 sm:w-auto sm:text-sm inline-flex"
|
||||||
|
id="options-menu"
|
||||||
|
aria-haspopup="true"
|
||||||
|
aria-expanded="true">
|
||||||
|
{$_('generate-runner-certificates')}
|
||||||
|
<svg
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
width="24"
|
||||||
|
height="24"
|
||||||
|
viewBox="0 0 24 24"
|
||||||
|
class="-mr-1 ml-2 h-5 w-5"><path
|
||||||
|
fill="none"
|
||||||
|
d="M0 0h24v24H0z" />
|
||||||
|
<path
|
||||||
|
fill="currentColor"
|
||||||
|
d="M3 19h18v2H3v-2zm10-5.83l6.07-6.07 1.42 1.41L12 17 3.52 8.52l1.4-1.42L11 13.17V2h2v11.17z" /></svg>
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
{#if certificates_dropdown_open}
|
||||||
|
<div
|
||||||
|
class="origin-top-right absolute right-0 mt-2 w-56 rounded-md shadow-lg bg-white ring-1 ring-black ring-opacity-5"
|
||||||
|
id="certificates:dropdown:menu">
|
||||||
|
<div
|
||||||
|
class="py-1"
|
||||||
|
role="menu"
|
||||||
|
aria-orientation="vertical"
|
||||||
|
aria-labelledby="options-menu">
|
||||||
|
<span
|
||||||
|
class="block w-full text-left px-4 py-2 text-sm text-gray-700">{$_('select-language')}</span>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
generateCertificates('de');
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
||||||
|
role="menuitem">
|
||||||
|
{$_('german')}
|
||||||
|
</button>
|
||||||
|
<button
|
||||||
|
on:click={() => {
|
||||||
|
generateCertificates('en');
|
||||||
|
}}
|
||||||
|
type="submit"
|
||||||
|
class="block w-full text-left px-4 py-2 text-sm text-gray-700 hover:bg-gray-100 hover:text-gray-900 focus:outline-none focus:bg-gray-100 focus:text-gray-900"
|
||||||
|
role="menuitem">
|
||||||
|
{$_('english')}
|
||||||
|
</button>
|
||||||
|
</div>
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
|
</div>
|
||||||
|
{/if}
|
||||||
@@ -37,7 +37,7 @@
|
|||||||
duration: -1,
|
duration: -1,
|
||||||
}).showToast();
|
}).showToast();
|
||||||
let count = 0;
|
let count = 0;
|
||||||
for await (const t of generate_teams) {
|
for (const t of generate_teams) {
|
||||||
count++;
|
count++;
|
||||||
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
const runners = await RunnerTeamService.runnerTeamControllerGetRunners(
|
||||||
t.id
|
t.id
|
||||||
@@ -92,7 +92,7 @@
|
|||||||
text: $_("generating-pdf"),
|
text: $_("generating-pdf"),
|
||||||
duration: -1,
|
duration: -1,
|
||||||
}).showToast();
|
}).showToast();
|
||||||
for await (const o of generate_orgs) {
|
for (const o of generate_orgs) {
|
||||||
const runners = await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
const runners = await RunnerOrganizationService.runnerOrganizationControllerGetRunners(
|
||||||
o.id
|
o.id
|
||||||
);
|
);
|
||||||
|
|||||||
@@ -2,6 +2,7 @@
|
|||||||
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
import { getLocaleFromNavigator, _ } from "svelte-i18n";
|
||||||
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
||||||
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
||||||
|
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
||||||
import store from "../../store";
|
import store from "../../store";
|
||||||
import {
|
import {
|
||||||
RunnerService,
|
RunnerService,
|
||||||
@@ -36,6 +37,7 @@
|
|||||||
editable.group != null;
|
editable.group != null;
|
||||||
$: sponsoring_contracts_show = true;
|
$: sponsoring_contracts_show = true;
|
||||||
$: cards_show = true;
|
$: cards_show = true;
|
||||||
|
$: certificates_show = true;
|
||||||
$: generate_runners = [original_data_pdf];
|
$: generate_runners = [original_data_pdf];
|
||||||
runner_promise.then((data) => {
|
runner_promise.then((data) => {
|
||||||
data_loaded = true;
|
data_loaded = true;
|
||||||
@@ -158,7 +160,10 @@
|
|||||||
bind:sponsoring_contracts_show
|
bind:sponsoring_contracts_show
|
||||||
bind:generate_runners />
|
bind:generate_runners />
|
||||||
<GenerateRunnerCards
|
<GenerateRunnerCards
|
||||||
bind:sponsoring_contracts_show
|
bind:cards_show
|
||||||
|
bind:generate_runners />
|
||||||
|
<GenerateRunnerCertificates
|
||||||
|
bind:certificates_show
|
||||||
bind:generate_runners />
|
bind:generate_runners />
|
||||||
{#if !delete_triggered}
|
{#if !delete_triggered}
|
||||||
<button
|
<button
|
||||||
|
|||||||
@@ -10,6 +10,7 @@
|
|||||||
import Select from "svelte-select";
|
import Select from "svelte-select";
|
||||||
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
import GenerateSponsoringContracts from "../pdf_generation/GenerateSponsoringContracts.svelte";
|
||||||
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
import GenerateRunnerCards from "../pdf_generation/GenerateRunnerCards.svelte";
|
||||||
|
import GenerateRunnerCertificates from "../pdf_generation/GenerateRunnerCertificates.svelte";
|
||||||
$: searchvalue = "";
|
$: searchvalue = "";
|
||||||
$: active_deletes = [];
|
$: active_deletes = [];
|
||||||
export let current_runners = [];
|
export let current_runners = [];
|
||||||
@@ -27,6 +28,9 @@
|
|||||||
$: cards_show = current_runners.some(
|
$: cards_show = current_runners.some(
|
||||||
(r) => r.is_selected === true
|
(r) => r.is_selected === true
|
||||||
);
|
);
|
||||||
|
$: certificates_show = current_runners.some(
|
||||||
|
(r) => r.is_selected === true
|
||||||
|
);
|
||||||
$: generate_runners = current_runners.filter((r) => r.is_selected === true);
|
$: generate_runners = current_runners.filter((r) => r.is_selected === true);
|
||||||
$: teams = [];
|
$: teams = [];
|
||||||
$: orgs = [];
|
$: orgs = [];
|
||||||
@@ -92,6 +96,9 @@
|
|||||||
<GenerateRunnerCards
|
<GenerateRunnerCards
|
||||||
bind:cards_show
|
bind:cards_show
|
||||||
bind:generate_runners />
|
bind:generate_runners />
|
||||||
|
<GenerateRunnerCertificates
|
||||||
|
bind:certificates_show
|
||||||
|
bind:generate_runners />
|
||||||
</div>
|
</div>
|
||||||
<div
|
<div
|
||||||
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
class="shadow border-b border-gray-200 sm:rounded-lg overflow-x-scroll">
|
||||||
|
|||||||
14
src/index.js
14
src/index.js
@@ -1,14 +0,0 @@
|
|||||||
import App from './App.svelte';
|
|
||||||
|
|
||||||
const app = new App({
|
|
||||||
target: document.body
|
|
||||||
});
|
|
||||||
|
|
||||||
export default app;
|
|
||||||
// HMR
|
|
||||||
if (import.meta.hot) {
|
|
||||||
import.meta.hot.accept();
|
|
||||||
import.meta.hot.dispose(() => {
|
|
||||||
app.$destroy();
|
|
||||||
});
|
|
||||||
}
|
|
||||||
@@ -423,5 +423,6 @@
|
|||||||
"you-have-to-provide-an-organization": "Du musst eine Organisation angeben",
|
"you-have-to-provide-an-organization": "Du musst eine Organisation angeben",
|
||||||
"you-have-to-save-your-changes-to-generate-a-link": "Du musst deine Änderungen speichern, um einen Link zu generieren.",
|
"you-have-to-save-your-changes-to-generate-a-link": "Du musst deine Änderungen speichern, um einen Link zu generieren.",
|
||||||
"you-must-create-at-least-one-card-or-cancel": "Du musst mindestens eine Blankokarte erstellen (oder abbrechen).",
|
"you-must-create-at-least-one-card-or-cancel": "Du musst mindestens eine Blankokarte erstellen (oder abbrechen).",
|
||||||
"zip-postal-code": "Postleitzahl"
|
"zip-postal-code": "Postleitzahl",
|
||||||
|
"generate-runner-certificates": "Urkunden generieren"
|
||||||
}
|
}
|
||||||
@@ -424,5 +424,6 @@
|
|||||||
"you-have-to-provide-an-organization": "You have to provide an organization",
|
"you-have-to-provide-an-organization": "You have to provide an organization",
|
||||||
"you-have-to-save-your-changes-to-generate-a-link": "You have to save your changes to generate a link.",
|
"you-have-to-save-your-changes-to-generate-a-link": "You have to save your changes to generate a link.",
|
||||||
"you-must-create-at-least-one-card-or-cancel": "You must create at least one card (or cancel).",
|
"you-must-create-at-least-one-card-or-cancel": "You must create at least one card (or cancel).",
|
||||||
"zip-postal-code": "ZIP/ postal code"
|
"zip-postal-code": "ZIP/ postal code",
|
||||||
|
"generate-runner-certificates": "Generate runner certificates"
|
||||||
}
|
}
|
||||||
9
src/main.js
Normal file
9
src/main.js
Normal file
@@ -0,0 +1,9 @@
|
|||||||
|
import 'windi.css';
|
||||||
|
import "toastify-js/src/toastify.css";
|
||||||
|
import "gridjs/dist/theme/mermaid.css";
|
||||||
|
import App from './App.svelte';
|
||||||
|
|
||||||
|
const app = new App({
|
||||||
|
target: document.body
|
||||||
|
});
|
||||||
|
export default app;
|
||||||
@@ -1,14 +0,0 @@
|
|||||||
export const register = () => {
|
|
||||||
if ('serviceWorker' in navigator) {
|
|
||||||
window.addEventListener('load', () => {
|
|
||||||
navigator.serviceWorker.register('/sw.js').then(
|
|
||||||
(registration) => {
|
|
||||||
// console.log(`sw successful with scope: ${registration.scope}`);
|
|
||||||
},
|
|
||||||
(err) => {
|
|
||||||
// console.log(`sw failed: ${err}`);
|
|
||||||
}
|
|
||||||
);
|
|
||||||
});
|
|
||||||
}
|
|
||||||
};
|
|
||||||
@@ -1,14 +1,13 @@
|
|||||||
module.exports = {
|
module.exports = {
|
||||||
purge: {
|
|
||||||
content: [ './src/**/*.svelte' ]
|
|
||||||
},
|
|
||||||
// darkMode: 'media',
|
|
||||||
variants: {},
|
|
||||||
plugins: [],
|
|
||||||
theme: {
|
theme: {
|
||||||
container: {
|
extend: {
|
||||||
center: true,
|
colors: {
|
||||||
padding: '1.5rem'
|
reepolee: {
|
||||||
|
500: '#b40000',
|
||||||
|
600: '#9c0000',
|
||||||
|
700: '#750000'
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|||||||
@@ -1,19 +0,0 @@
|
|||||||
const fs = require('fs');
|
|
||||||
let content_svelteconfig = fs.readFileSync('./s-config.template.js', { encoding: 'utf8' });
|
|
||||||
let content_html = fs.readFileSync('./index.template.html', { encoding: 'utf8' });
|
|
||||||
if (process.env.NODE_ENV_ODIT == 'development_fast') {
|
|
||||||
content_html = content_html.replace(
|
|
||||||
'__TAILWIND_INSERT__',
|
|
||||||
'<link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/tailwindcss@2.0.2/dist/tailwind.min.css">'
|
|
||||||
);
|
|
||||||
content_svelteconfig = content_svelteconfig.replace('__insert__', '{postcss:{}}');
|
|
||||||
} else {
|
|
||||||
content_html = content_html.replace('__TAILWIND_INSERT__', '');
|
|
||||||
content_svelteconfig = content_svelteconfig.replace(
|
|
||||||
'__insert__',
|
|
||||||
"{postcss:{plugins:[require('tailwindcss'),require('autoprefixer')]}}"
|
|
||||||
);
|
|
||||||
}
|
|
||||||
fs.writeFileSync('./public/index.html', content_html);
|
|
||||||
fs.writeFileSync('./svelte.config.js', content_svelteconfig);
|
|
||||||
console.info('dev setup script done');
|
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
const fs = require('fs');
|
const fs = require('fs');
|
||||||
const package = JSON.parse(fs.readFileSync(`./package.json`, { encoding: 'utf-8' }));
|
const package = JSON.parse(fs.readFileSync(`./package.json`, { encoding: 'utf-8' }));
|
||||||
const original = fs.readFileSync(`./index.template.html`, { encoding: 'utf-8' });
|
const original = fs.readFileSync(`./index.html`, { encoding: 'utf-8' });
|
||||||
let out = original.replace(/RELEASE_INFO-(\S)+-RELEASE_INFO/gi, 'RELEASE_INFO-' + package.version + '-RELEASE_INFO');
|
let out = original.replace(/RELEASE_INFO-(\S)+-RELEASE_INFO/gi, 'RELEASE_INFO-' + package.version + '-RELEASE_INFO');
|
||||||
fs.writeFileSync(`./index.template.html`, out);
|
fs.writeFileSync(`./index.html`, out);
|
||||||
|
|||||||
50
vite.config.js
Normal file
50
vite.config.js
Normal file
@@ -0,0 +1,50 @@
|
|||||||
|
import svelte from '@sveltejs/vite-plugin-svelte';
|
||||||
|
import windiCSS from 'vite-plugin-windicss';
|
||||||
|
import { minify } from 'html-minifier';
|
||||||
|
import { defineConfig } from 'vite';
|
||||||
|
//
|
||||||
|
const indexReplace = () => {
|
||||||
|
return {
|
||||||
|
name: 'html-transform',
|
||||||
|
transformIndexHtml(html) {
|
||||||
|
return minify(html, {
|
||||||
|
collapseWhitespace: true
|
||||||
|
});
|
||||||
|
}
|
||||||
|
};
|
||||||
|
};
|
||||||
|
|
||||||
|
export default defineConfig(({ command, mode }) => {
|
||||||
|
const isProduction = mode === 'production';
|
||||||
|
return {
|
||||||
|
// base: './',
|
||||||
|
build: {
|
||||||
|
polyfillDynamicImport: false,
|
||||||
|
cssCodeSplit: false,
|
||||||
|
minify: isProduction
|
||||||
|
},
|
||||||
|
plugins: [
|
||||||
|
windiCSS({
|
||||||
|
//@ts-ignore
|
||||||
|
verbose: true,
|
||||||
|
silent: false,
|
||||||
|
debug: true,
|
||||||
|
config: 'tailwind.config.js', // tailwind config file path (optional)
|
||||||
|
compile: false, // false: interpretation mode; true: compilation mode
|
||||||
|
prefix: 'windi-', // set compilation mode style prefix
|
||||||
|
globalPreflight: true, // set preflight style is global or scoped
|
||||||
|
globalUtility: true // set utility style is global or scoped
|
||||||
|
}),
|
||||||
|
svelte({
|
||||||
|
//@ts-ignore
|
||||||
|
hot: !isProduction,
|
||||||
|
emitCss: true,
|
||||||
|
extensions: [ '.md', '.svx', '.svelte' ],
|
||||||
|
preprocess: [
|
||||||
|
//
|
||||||
|
]
|
||||||
|
}),
|
||||||
|
indexReplace()
|
||||||
|
]
|
||||||
|
};
|
||||||
|
});
|
||||||
@@ -1,9 +0,0 @@
|
|||||||
module.exports = {
|
|
||||||
globDirectory: 'public',
|
|
||||||
globPatterns: [ '**/*.{js,ico,png,svg,html,webmanifest,txt,json}' ],
|
|
||||||
globIgnores: [ 'env.js', 'env.sample.js' ],
|
|
||||||
swDest: 'public/sw.js',
|
|
||||||
cleanupOutdatedCaches: true,
|
|
||||||
mode: 'production',
|
|
||||||
sourcemap: false
|
|
||||||
};
|
|
||||||
Reference in New Issue
Block a user