Compare commits

...

9 Commits
1.0.5 ... 1.0.6

12 changed files with 522 additions and 509 deletions

View File

@ -0,0 +1,33 @@
name: Build release images
on:
push:
tags:
- "*.*.*"
jobs:
build-container:
runs-on: ubuntu-latest
steps:
- name: Checkout
uses: actions/checkout@v4
- name: Set up Node.js
uses: actions/setup-node@v4
with:
node-version: 19
- run: npm i -g pnpm@10.7 && pnpm i
- run: pnpm licenses:export
- name: Login to registry
uses: docker/login-action@v3
with:
registry: registry.odit.services
username: ${{ vars.REGISTRY_USERNAME }}
password: ${{ secrets.REGISTRY_PASSWORD }}
- name: Set up Docker Buildx
uses: docker/setup-buildx-action@v3
- name: Build and push
uses: docker/build-push-action@v6
with:
push: true
tags: |
${{ vars.REGISTRY }}/lfk/beamershow:${{ github.ref_name }}
platforms: linux/amd64,linux/arm64

View File

@ -1,39 +0,0 @@
steps:
- name: build latest
image: woodpeckerci/plugin-docker-buildx
settings:
repo: registry.odit.services/lfk/beamershow
tags:
- latest
registry: registry.odit.services
platforms: linux/amd64,linux/arm64
cache_from: registry.odit.services/lfk/beamershow:latest
username:
from_secret: odit-registry-builder-username
password:
from_secret: odit-registry-builder-password
secrets:
- source: odit-npm-cache-url
target: NPM_REGISTRY_URL
when:
branch: main
- name: build dev
image: woodpeckerci/plugin-docker-buildx
settings:
repo: registry.odit.services/lfk/beamershow
tags:
- dev
registry: registry.odit.services
platforms: linux/amd64,linux/arm64
cache_from: registry.odit.services/lfk/beamershow:dev
username:
from_secret: odit-registry-builder-username
password:
from_secret: odit-registry-builder-password
secrets:
- source: odit-npm-cache-url
target: NPM_REGISTRY_URL
when:
branch: dev
when:
event: push

View File

@ -2,11 +2,25 @@
All notable changes to this project will be documented in this file. Dates are displayed in UTC.
#### [1.0.6](https://git.odit.services/lfk/beamershow/compare/1.0.5...1.0.6)
- feat: show org names for teams_distance slide [`c6f7210`](https://git.odit.services/lfk/beamershow/commit/c6f721019691cdc9f5492f920dbdd99e6b25ca9f)
- chore(deps). bump [`dc0488b`](https://git.odit.services/lfk/beamershow/commit/dc0488b1b7632326f4dd3bf5fff0ac8fa91fb128)
- ci: move to gitea actions [`e6ff8ef`](https://git.odit.services/lfk/beamershow/commit/e6ff8ef80b667692574319f20bebe6a4e872ca6e)
- chore: update readme [`aa707ff`](https://git.odit.services/lfk/beamershow/commit/aa707ff0ccaa2cb4a69d3c7b396591cd40827c6d)
- chore(deps): pnpm@10 [`c286969`](https://git.odit.services/lfk/beamershow/commit/c286969a9de52519005013a6798f711cef26b465)
- ci: change release message [`4920da1`](https://git.odit.services/lfk/beamershow/commit/4920da1df1a51a071eeba44d8d2c1cb6c5f8d09c)
- fix: i18n [`f9a84f7`](https://git.odit.services/lfk/beamershow/commit/f9a84f798b1052530688aaabf654b08c2d466da5)
- fix(login): bg image [`14ae9e4`](https://git.odit.services/lfk/beamershow/commit/14ae9e49fbdc10a1c5681212713b166e333e4b4d)
#### [1.0.5](https://git.odit.services/lfk/beamershow/compare/1.0.4...1.0.5)
> 18 December 2024
- chore(deps): bump some [`ab4f82c`](https://git.odit.services/lfk/beamershow/commit/ab4f82ccf14a1569921845910e3b2a740f74aeea)
- feat(ci)!: Switched to woodpecker [`1235776`](https://git.odit.services/lfk/beamershow/commit/1235776a6255a3925f98ac6cacd3167f6e86e363)
- chore: remove husky [`72d34cb`](https://git.odit.services/lfk/beamershow/commit/72d34cbfd7f7e47f0239416469533aea772daa79)
- 🚀Bumped version to 1.0.5 [`4874b22`](https://git.odit.services/lfk/beamershow/commit/4874b227960c30b65d7bc822f987c9b957144953)
- chore(deps): pnpm@9 + node@23 [`c4ad18c`](https://git.odit.services/lfk/beamershow/commit/c4ad18cb4ff4dd13e50f4674d7b6016ed788ff63)
- feat(footer): cleaned up text [`b10e964`](https://git.odit.services/lfk/beamershow/commit/b10e964ad900fcfd2503884c248ea0f6d11a2fb9)
- feat: improved background img import [`919b295`](https://git.odit.services/lfk/beamershow/commit/919b2956ab5253a3697c14ac284f6da700afda91)

View File

@ -1,9 +1,9 @@
FROM registry.odit.services/hub/library/node:23.4.0-alpine3.20 as build
FROM registry.odit.services/hub/library/node:23.11.0-alpine3.21 as build
ARG NPM_REGISTRY_URL=https://registry.npmjs.org
WORKDIR /app
COPY . ./
RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@9 && pnpm i
RUN npm config set registry $NPM_REGISTRY_URL && npm i -g pnpm@10.7 && pnpm i
RUN pnpm build
# final image

View File

@ -7,17 +7,17 @@ This is an API client for [https://git.odit.services/lfk/backend](@lfk/backend)
## Dev🛠
### 🚀 Getting Started
```
yarn
pnpm i
```
### Development
```
yarn dev
pnpm dev
/
yarn dev --open
pnpm dev --open
```
### Build
```
yarn build
pnpm build
```
## Use (quickstart) 🔥

View File

@ -1,6 +1,6 @@
{
"name": "@lfk/beamershow",
"version": "1.0.5",
"version": "1.0.6",
"scripts": {
"dev": "vite",
"build": "vite build",
@ -9,19 +9,19 @@
"release": "release-it --only-version"
},
"devDependencies": {
"@odit/license-exporter": "0.0.11",
"@odit/license-exporter": "0.2.0",
"@philippdormann/release-it": "1.0.0",
"@svitejs/vite-plugin-svelte": "0.11.1",
"@tsconfig/svelte": "1.0.10",
"@types/html-minifier": "4.0.5",
"axios": "0.21.1",
"html-minifier": "4.0.0",
"prettier": "3.4.2",
"prettier-plugin-svelte": "3.3.2",
"prettier": "3.5.3",
"prettier-plugin-svelte": "3.3.3",
"svelte": "3.36.0",
"svelte-i18n": "3.3.9",
"svelte-preprocess": "4.7.0",
"validator": "13.12.0",
"validator": "13.15.0",
"vite": "2.1.4",
"vite-plugin-windicss": "1.9.4"
},
@ -29,11 +29,11 @@
"git": {
"commit": true,
"requireCleanWorkingDir": false,
"commitMessage": "🚀Bumped version to ${version}",
"commitMessage": "chore: release ${version}",
"requireBranch": "main",
"push": true,
"tag": true,
"tagName": null,
"tagName": "${version}",
"tagAnnotation": "${version}"
},
"npm": {
@ -44,6 +44,6 @@
}
},
"dependencies": {
"@fontsource/athiti": "5.1.0"
"@fontsource/athiti": "5.2.5"
}
}

87
pnpm-lock.yaml generated
View File

@ -9,12 +9,12 @@ importers:
.:
dependencies:
'@fontsource/athiti':
specifier: 5.1.0
version: 5.1.0
specifier: 5.2.5
version: 5.2.5
devDependencies:
'@odit/license-exporter':
specifier: 0.0.11
version: 0.0.11
specifier: 0.2.0
version: 0.2.0
'@philippdormann/release-it':
specifier: 1.0.0
version: 1.0.0
@ -34,11 +34,11 @@ importers:
specifier: 4.0.0
version: 4.0.0
prettier:
specifier: 3.4.2
version: 3.4.2
specifier: 3.5.3
version: 3.5.3
prettier-plugin-svelte:
specifier: 3.3.2
version: 3.3.2(prettier@3.4.2)(svelte@3.36.0)
specifier: 3.3.3
version: 3.3.3(prettier@3.5.3)(svelte@3.36.0)
svelte:
specifier: 3.36.0
version: 3.36.0
@ -49,8 +49,8 @@ importers:
specifier: 4.7.0
version: 4.7.0(postcss@8.4.21)(sass@1.60.0)(svelte@3.36.0)
validator:
specifier: 13.12.0
version: 13.12.0
specifier: 13.15.0
version: 13.15.0
vite:
specifier: 2.1.4
version: 2.1.4
@ -75,8 +75,8 @@ packages:
resolution: {integrity: sha512-u7stbOuYjaPezCuLj29hNW1v64M2Md2qupEKP1fHc7WdOA3DgLh37suiSrZYY7haUB7iBeQZ9P1uiRF359do3g==}
engines: {node: '>=6.9.0'}
'@fontsource/athiti@5.1.0':
resolution: {integrity: sha512-iQsMj7twMf8bmqW0zBOQX6S3oYdRjjgoGO9JOtLPd9T0pzQ1zxGQmp2eEc3ny/Gd5PDRSmn8E5CNwSjUVl0raA==}
'@fontsource/athiti@5.2.5':
resolution: {integrity: sha512-vHoAKBBw+wI4y3bGOkiogOkgcoLH7+SWtNNo/nBQ1XfhvfRPX/91xGtclEdwqUlbOJTCkNzEecdKChJQ5MsDFg==}
'@formatjs/ecma402-abstract@1.11.4':
resolution: {integrity: sha512-EBikYFp2JCdIfGEb5G9dyCkTGDmC57KSHhRQOC3aYxoPWVZvfWCDjZwkGYHN7Lis/fmuWl906bnNTJifDQ3sXw==}
@ -167,8 +167,8 @@ packages:
'@octokit/types@13.6.2':
resolution: {integrity: sha512-WpbZfZUcZU77DrSW4wbsSgTPfKcp286q3ItaIgvSbBpZJlu6mnYXAkjZz6LVZPXkEvLIM8McanyZejKTYUHipA==}
'@odit/license-exporter@0.0.11':
resolution: {integrity: sha512-jB5XQF913xaRSF0Hjoqaei/qcTGwBEUc2IZ68OcFShwL/fLfBhI4yhlc9nm9gHgWDEKOInI7mVE8xgpHuiGasA==}
'@odit/license-exporter@0.2.0':
resolution: {integrity: sha512-RRyfQzDLoyLQlGSd8ThJQ3h0fiCe4tkmm935AUvSVQWP+p88FcnI4iaktKBJJVBnIpDhkv/7sDSA5dFc/QMM5w==}
hasBin: true
'@philippdormann/release-it@1.0.0':
@ -389,8 +389,9 @@ packages:
resolution: {integrity: sha512-ouuZd4/dm2Sw5Gmqy6bGyNNNe1qt9RpmxveLSO7KcgsTnU7RXfsw+/bukWGo1abgBiMAic068rclZsO4IWmmxQ==}
engines: {node: '>= 12'}
cliui@7.0.4:
resolution: {integrity: sha512-OcRE68cOsVMXp1Yvonl/fzkQOyjLSu/8bhPDfQt0e0/Eb283TKP20Fs2MqoPsr9SwA595rRCA+QMzYc9nBP+JQ==}
cliui@8.0.1:
resolution: {integrity: sha512-BSeNnyus75C4//NQ9gQt1/csTXyo/8Sb+afLAkzAptFuMsod9HFokGNudZpi/oQV73hnVK+sR+5PVRMd+Dr7YQ==}
engines: {node: '>=12'}
clone@1.0.4:
resolution: {integrity: sha512-JQHZ2QMW6l3aH/j6xCqQThY/9OH4D/9ls34cgkUBiEeocRTU04tHfKPBsUK1PqZCUQM7GiA0IIXJSuXHI64Kbg==}
@ -512,8 +513,8 @@ packages:
resolution: {integrity: sha512-VtUf6aQ89VTmMLKrWHYG50uByMF4JQlVysb8dmg6cOgW8JnFCipmz7p+HNBl+RR3LLCuBxFGVauAe2wfnF9bLg==}
hasBin: true
escalade@3.1.1:
resolution: {integrity: sha512-k0er2gUkLf8O0zKJiAhmkTnJlTvINGv7ygDNPbeIsX/TJjGJZHuh9B2UxbsaEkmlEo9MfhrSzmhIlhRlI2GXnw==}
escalade@3.2.0:
resolution: {integrity: sha512-WUj2qlxaQtO4g6Pq5c29GTcWGDyd8itL8zTlipgECz3JesAiiOKotd8JU6otB3PACgG6xkJUyVhboMS+bje/jA==}
engines: {node: '>=6'}
escape-goat@4.0.0:
@ -1080,14 +1081,14 @@ packages:
resolution: {integrity: sha512-tP7u/Sn/dVxK2NnruI4H9BG+x+Wxz6oeZ1cJ8P6G/PZY0IKk4k/63TDsQf2kQq3+qoJeLm2kIBUNlZe3zgb4Zg==}
engines: {node: ^10 || ^12 || >=14}
prettier-plugin-svelte@3.3.2:
resolution: {integrity: sha512-kRPjH8wSj2iu+dO+XaUv4vD8qr5mdDmlak3IT/7AOgGIMRG86z/EHOLauFcClKEnOUf4A4nOA7sre5KrJD4Raw==}
prettier-plugin-svelte@3.3.3:
resolution: {integrity: sha512-yViK9zqQ+H2qZD1w/bH7W8i+bVfKrD8GIFjkFe4Thl6kCT9SlAsXVNmt3jCvQOCsnOhcvYgsoVlRV/Eu6x5nNw==}
peerDependencies:
prettier: ^3.0.0
svelte: ^3.2.0 || ^4.0.0-next.0 || ^5.0.0-next.0
prettier@3.4.2:
resolution: {integrity: sha512-e9MewbtFo+Fevyuxn/4rrcDAaq0IYxPGLvObpQjiZBMAzB9IGmzlnG9RZy3FFas+eBMu2vA0CszMeduow5dIuQ==}
prettier@3.5.3:
resolution: {integrity: sha512-QQtaxnoDJeAkDvDKWCLiwIXkTgRhwYDEQCghU9Z6q03iyek/rxRh/2lC3HB7P8sWT2xC/y5JDctPLBIGzHKbhw==}
engines: {node: '>=14'}
hasBin: true
@ -1429,8 +1430,8 @@ packages:
util-deprecate@1.0.2:
resolution: {integrity: sha512-EPD5q1uXyFxJpCrLnCc1nHnq3gOa6DZBocAIiI2TaSCA7VCJ1UJDMagCzIkXNsUYfD1daK//LTEQ8xiIbrHtcw==}
validator@13.12.0:
resolution: {integrity: sha512-c1Q0mCiPlgdTVVVIJIrBuxNicYE+t/7oKeI9MWLj3fh/uq2Pxh/3eeWbVZ4OcGW1TUf53At0njHw5SMdA3tmMg==}
validator@13.15.0:
resolution: {integrity: sha512-36B2ryl4+oL5QxZ3AzD0t5SsMNGvTtQHpjgFO5tbNxfXbMFkY822ktCDe1MnlqV3301QQI9SLHDNJokDI+Z9pA==}
engines: {node: '>= 0.10'}
vite-plugin-windicss@1.9.4:
@ -1493,17 +1494,13 @@ packages:
resolution: {integrity: sha512-0pfFzegeDWJHJIAmTLRP2DwHjdF5s7jo9tuztdQxAhINCdvS+3nGINqPd00AphqJR/0LhANUS6/+7SCb98YOfA==}
engines: {node: '>=10'}
yargs-parser@20.2.9:
resolution: {integrity: sha512-y11nGElTIV+CT3Zv9t7VKl+Q3hTQoT9a1Qzezhhl6Rp21gJ/IVTW7Z3y9EWXhuUBC2Shnf+DX0antecpAwSP8w==}
engines: {node: '>=10'}
yargs-parser@21.1.1:
resolution: {integrity: sha512-tVpsJW7DdjecAiFpbIB1e3qxIQsE6NoPc5/eTdrbbIC4h0LVsWhnoa3g+m2HclBIujHzsxZ4VJVA+GUuc2/LBw==}
engines: {node: '>=12'}
yargs@16.2.0:
resolution: {integrity: sha512-D1mvvtDG0L5ft/jGWkLpG1+m0eQxOfaBvTNELraWj22wSVUMWxZUvYgJYcKh6jGGIkJFhH4IZPQhR4TKpc8mBw==}
engines: {node: '>=10'}
yargs@17.7.2:
resolution: {integrity: sha512-7dSzzRQ++CKnNI/krKnYRV7JKKPUXMEh61soaHKg9mrWEhzFWhFnxPxGl+69cD1Ou63C13NUPCnmIcrvqCuM6w==}
engines: {node: '>=12'}
yoctocolors-cjs@2.1.2:
resolution: {integrity: sha512-cYVsTjKl8b+FrnidjibDWskAv7UKOfcwaVZdp/it9n1s9fU3IkgDbhdIRKCW4JDsAlECJY0ytoVPT3sK6kideA==}
@ -1525,7 +1522,7 @@ snapshots:
chalk: 2.4.2
js-tokens: 4.0.0
'@fontsource/athiti@5.1.0': {}
'@fontsource/athiti@5.2.5': {}
'@formatjs/ecma402-abstract@1.11.4':
dependencies:
@ -1632,9 +1629,9 @@ snapshots:
dependencies:
'@octokit/openapi-types': 22.2.0
'@odit/license-exporter@0.0.11':
'@odit/license-exporter@0.2.0':
dependencies:
yargs: 16.2.0
yargs: 17.7.2
'@philippdormann/release-it@1.0.0':
dependencies:
@ -1906,7 +1903,7 @@ snapshots:
cli-width@4.1.0: {}
cliui@7.0.4:
cliui@8.0.1:
dependencies:
string-width: 4.2.3
strip-ansi: 6.0.1
@ -2008,7 +2005,7 @@ snapshots:
esbuild@0.9.7: {}
escalade@3.1.1: {}
escalade@3.2.0: {}
escape-goat@4.0.0: {}
@ -2552,12 +2549,12 @@ snapshots:
picocolors: 1.0.0
source-map-js: 1.0.2
prettier-plugin-svelte@3.3.2(prettier@3.4.2)(svelte@3.36.0):
prettier-plugin-svelte@3.3.3(prettier@3.5.3)(svelte@3.36.0):
dependencies:
prettier: 3.4.2
prettier: 3.5.3
svelte: 3.36.0
prettier@3.4.2: {}
prettier@3.5.3: {}
proto-list@1.2.4: {}
@ -2838,7 +2835,7 @@ snapshots:
util-deprecate@1.0.2: {}
validator@13.12.0: {}
validator@13.15.0: {}
vite-plugin-windicss@1.9.4(vite@2.1.4):
dependencies:
@ -2905,18 +2902,16 @@ snapshots:
y18n@5.0.8: {}
yargs-parser@20.2.9: {}
yargs-parser@21.1.1: {}
yargs@16.2.0:
yargs@17.7.2:
dependencies:
cliui: 7.0.4
escalade: 3.1.1
cliui: 8.0.1
escalade: 3.2.0
get-caller-file: 2.0.5
require-directory: 2.1.1
string-width: 4.2.3
y18n: 5.0.8
yargs-parser: 20.2.9
yargs-parser: 21.1.1
yoctocolors-cjs@2.1.2: {}

3
pnpm-workspace.yaml Normal file
View File

@ -0,0 +1,3 @@
onlyBuiltDependencies:
- esbuild
- svelte-preprocess

View File

@ -1,416 +1,420 @@
<script>
import axios from "axios";
import bg from "/beamershow_background.png?import";
import { _ } from "svelte-i18n";
import { slide } from "svelte/transition";
import { apikey, api_endpoint, laptime_track } from "./store.js";
function init(el) {
el.focus();
}
$: pages = [
"general",
"runners_distance",
// "runners_laptime",
"orgs_distance",
// "teams_distance",
];
$: current_page = "general";
$: general = {};
$: runners = [];
$: runners_by_laptime = [];
$: orgs = [];
$: teams = [];
import axios from "axios";
import bg from "/beamershow_background.png?inline";
import { _ } from "svelte-i18n";
import { slide } from "svelte/transition";
import { apikey, api_endpoint, laptime_track } from "./store.js";
$: pages = [
"general",
"runners_distance",
// "runners_laptime",
"orgs_distance",
// "teams_distance",
];
$: current_page = "general";
$: general = {};
$: runners = [];
$: runners_by_laptime = [];
$: orgs = [];
$: teams = [];
let time = new Date();
$: hours = (time.getHours() + "").padStart(2, "0");
$: minutes = (time.getMinutes() + "").padStart(2, "0");
$: seconds = (time.getSeconds() + "").padStart(2, "0");
function format_laptime(laptime) {
if (laptime < 60) {
return `${laptime}s`;
}
if (laptime < 3600) {
return `${Math.floor(laptime / 60)}min ${
laptime - Math.floor(laptime / 60) * 60
}s`;
}
return `${Math.floor(laptime / 3600)}h ${
laptime - Math.floor(laptime / 3600) * 3600
}min ${
laptime -
Math.floor(laptime / 3600) * 3600 -
Math.floor(laptime / 60) * 60
}`;
}
function stats_general() {
axios
.request({
method: "GET",
url: $api_endpoint + "api/stats/",
headers: { Authorization: "Bearer " + $apikey },
})
.then(function ({ data }) {
general = data;
})
.catch(function (e) {
console.log(e);
});
}
function stats_runners() {
axios
.request({
method: "GET",
url: $api_endpoint + "api/stats/runners/distance",
headers: { Authorization: "Bearer " + $apikey },
})
.then(function ({ data }) {
runners = data;
})
.catch(function (e) {
console.log(e);
});
}
function stats_runners_by_laptime() {
axios
.request({
method: "GET",
url:
$api_endpoint + "api/stats/runners/laptime?track=" + $laptime_track,
headers: { Authorization: "Bearer " + $apikey },
})
.then(function ({ data }) {
runners_by_laptime = data;
})
.catch(function (e) {
console.log(e);
});
}
function stats_orgs() {
axios
.request({
method: "GET",
url: $api_endpoint + "api/stats/organizations/distance",
headers: { Authorization: "Bearer " + $apikey },
})
.then(function ({ data }) {
orgs = data;
})
.catch(function (e) {
console.log(e);
});
}
function stats_teams() {
axios
.request({
method: "GET",
url: $api_endpoint + "api/stats/teams/distance",
headers: { Authorization: "Bearer " + $apikey },
})
.then(function ({ data }) {
teams = data;
})
.catch(function (e) {
console.log(e);
});
}
Array.prototype.cycle = function (str) {
const i = this.indexOf(str);
if (i === -1) return undefined;
return this[(i + 1) % this.length];
};
function fetch_all() {
stats_general();
stats_runners();
// stats_runners_by_laptime();
stats_orgs();
stats_teams();
}
fetch_all();
setInterval(() => {
time = new Date();
}, 1000);
setInterval(() => {
fetch_all();
}, 50000);
setInterval(() => {
current_page = pages.cycle(current_page);
}, 20000);
let time = new Date();
$: hours = (time.getHours() + "").padStart(2, "0");
$: minutes = (time.getMinutes() + "").padStart(2, "0");
$: seconds = (time.getSeconds() + "").padStart(2, "0");
function format_laptime(laptime) {
if (laptime < 60) {
return `${laptime}s`;
}
if (laptime < 3600) {
return `${Math.floor(laptime / 60)}min ${
laptime - Math.floor(laptime / 60) * 60
}s`;
}
return `${Math.floor(laptime / 3600)}h ${
laptime - Math.floor(laptime / 3600) * 3600
}min ${
laptime -
Math.floor(laptime / 3600) * 3600 -
Math.floor(laptime / 60) * 60
}`;
}
function stats_general() {
axios
.request({
method: "GET",
url: $api_endpoint + "api/stats/",
headers: { Authorization: "Bearer " + $apikey },
})
.then(function ({ data }) {
general = data;
})
.catch(function (e) {
console.log(e);
});
}
function stats_runners() {
axios
.request({
method: "GET",
url: $api_endpoint + "api/stats/runners/distance",
headers: { Authorization: "Bearer " + $apikey },
})
.then(function ({ data }) {
runners = data;
})
.catch(function (e) {
console.log(e);
});
}
function stats_runners_by_laptime() {
axios
.request({
method: "GET",
url:
$api_endpoint + "api/stats/runners/laptime?track=" + $laptime_track,
headers: { Authorization: "Bearer " + $apikey },
})
.then(function ({ data }) {
runners_by_laptime = data;
})
.catch(function (e) {
console.log(e);
});
}
function stats_orgs() {
axios
.request({
method: "GET",
url: $api_endpoint + "api/stats/organizations/distance",
headers: { Authorization: "Bearer " + $apikey },
})
.then(function ({ data }) {
orgs = data;
})
.catch(function (e) {
console.log(e);
});
}
function stats_teams() {
axios
.request({
method: "GET",
url: $api_endpoint + "api/stats/teams/distance",
headers: { Authorization: "Bearer " + $apikey },
})
.then(function ({ data }) {
teams = data;
})
.catch(function (e) {
console.log(e);
});
}
Array.prototype.cycle = function (str) {
const i = this.indexOf(str);
if (i === -1) return undefined;
return this[(i + 1) % this.length];
};
function fetch_all() {
stats_general();
stats_runners();
// stats_runners_by_laptime();
stats_orgs();
stats_teams();
}
fetch_all();
setInterval(() => {
time = new Date();
}, 1000);
setInterval(() => {
fetch_all();
}, 50000);
setInterval(() => {
current_page = pages.cycle(current_page);
}, 20000);
</script>
<div
class="min-h-screen flex items-center justify-center bg-gray-100"
style="background-image: url({bg});background-position: center;background-size: contain;background-repeat:no-repeat;"
class="min-h-screen flex items-center justify-center bg-gray-100"
style="background-image: url({bg});background-position: center;background-size: contain;background-repeat:no-repeat;"
>
<div class="w-full">
<div class="w-3/4 xl:w-1/2 mx-auto">
<!-- -->
{#if current_page === "general"}
<div transition:slide|local>
<h1
class="mr-6 text-5xl xl:text-7xl font-bold text-center text-gray-900"
>
Statistiken
</h1>
<!-- -->
<div class="flex flex-wrap -mx-1 overflow-hidden mt-5">
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/2 md:w-1/3">
<h1 class="text-5xl font-bold text-center text-gray-900">
{general.total_runners || "0"}
</h1>
<h1 class="text-2xl font-semibold text-center text-gray-900">
{$_("laeufer")}
</h1>
</div>
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/2 md:w-1/3">
<h1 class="text-5xl font-bold text-center text-gray-900">
{general.total_distance / 1000 || 0}
</h1>
<h1 class="text-2xl font-semibold text-center text-gray-900">
{$_("kilometer-gesamt")}
</h1>
</div>
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/2 md:w-1/3">
<h1 class="text-5xl font-bold text-center text-gray-900">
{parseFloat(
((general.total_donation || 0) / 100).toFixed(2)
).toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}) || "0"} €
</h1>
<h1 class="text-2xl font-semibold text-center text-gray-900">
{$_("spendensumme")}
</h1>
</div>
</div>
</div>
{:else if current_page === "runners_distance"}
<div transition:slide|local>
<h1
class="mr-6 text-5xl xl:text-7xl font-bold text-center text-gray-900 mb-3"
>
{$_("top-laeufer")} ({$_("distanz")})
</h1>
{#if runners.length === 0}
<p class="w-full text-center text-3xl font-semibold">
Noch keine Daten...
</p>
{:else}
<table
class="table font-semibold p-4 bg-white shadow rounded-lg w-full"
>
<thead>
<tr>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("platz")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("laeufer")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("organisation")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("kilometer")}
</th>
</tr>
</thead>
<tbody>
{#each runners as r, i}
<tr class="text-gray-700">
<td class="border p-4 dark:border-dark-5">
{i + 1}
</td>
<td class="border p-4 dark:border-dark-5">
{r.firstname}
{r.lastname}
</td>
<td class="border p-4 dark:border-dark-5">
{r.group.name}
</td>
<td class="border p-4 dark:border-dark-5">
{r.distance / 1000} km
</td>
</tr>
{/each}
</tbody>
</table>
{/if}
</div>
{:else if current_page === "runners_laptime"}
<div transition:slide|local>
<h1
class="mr-6 text-5xl xl:text-7xl font-bold text-center text-gray-900 mb-3"
>
{$_("top-laeufer")} ({$_("rundenzeit")})
</h1>
{#if runners_by_laptime.length === 0}
<p class="w-full text-center text-3xl font-semibold">
Noch keine Daten...
</p>
{:else}
<table
class="table font-semibold p-4 bg-white shadow rounded-lg w-full"
>
<thead>
<tr>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("platz")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("laeufer")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("organisation")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("schnellste-rundenzeit")}
</th>
</tr>
</thead>
<tbody>
{#each runners_by_laptime as r, i}
<tr class="text-gray-700">
<td class="border p-4 dark:border-dark-5">
{i + 1}
</td>
<td class="border p-4 dark:border-dark-5">
{r.firstname}
{r.lastname}
</td>
<td class="border p-4 dark:border-dark-5">
{r.group.name}
</td>
<td class="border p-4 dark:border-dark-5">
{format_laptime(r.minLaptime)}
</td>
</tr>
{/each}
</tbody>
</table>
{/if}
</div>
{:else if current_page === "orgs_distance"}
<div transition:slide|local>
<h1
class="mr-6 text-5xl xl:text-7xl font-bold text-center text-gray-900 mb-3"
>
{$_("top-organisationen")}
</h1>
<table
class="table font-semibold p-4 bg-white shadow rounded-lg w-full"
>
<thead>
<tr>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("platz")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("organsiation")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("kilometer")}
</th>
</tr>
</thead>
<tbody>
{#each orgs as o, i}
<tr class="text-gray-700">
<td class="border p-4 dark:border-dark-5">
{i + 1}
</td>
<td class="border p-4 dark:border-dark-5">
{o.name}
</td>
<td class="border p-4 dark:border-dark-5">
{o.distance / 1000} km
</td>
</tr>
{/each}
</tbody>
</table>
</div>
{:else if current_page === "teams_distance"}
<div transition:slide|local>
<h1
class="mr-6 text-5xl xl:text-7xl font-bold text-center text-gray-900 mb-3"
>
{$_("top-teams")}
</h1>
<table
class="table font-semibold p-4 bg-white shadow rounded-lg w-full"
>
<thead>
<tr>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("platz")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("team")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("kilometer")}
</th>
</tr>
</thead>
<tbody>
{#each teams as t, i}
<tr class="text-gray-700">
<td class="border p-4 dark:border-dark-5">
{i + 1}
</td>
<td class="border p-4 dark:border-dark-5">
{t.name}
</td>
<td class="border p-4 dark:border-dark-5">
{t.distance / 1000} km
</td>
</tr>
{/each}
</tbody>
</table>
</div>
{:else}
<!-- content here -->
{/if}
</div>
</div>
<h1
class="text-6xl font-semibold text-right text-gray-900 font-mono top-2 w-full fixed pr-4 xl:top-6 xl:pr-8"
>
{hours}:{minutes}:{seconds}
</h1>
<h1
class="text-xl xl:text-3xl font-medium text-center text-gray-900 font-mono bottom-2 xl:bottom-4 w-full fixed"
>
<span class="text-black font-extrabold">Lauf für Kaya!</span> - powered by ODIT.Services
</h1>
<div class="w-full">
<div class="w-3/4 xl:w-1/2 mx-auto">
<!-- -->
{#if current_page === "general"}
<div transition:slide|local>
<h1
class="mr-6 text-5xl xl:text-7xl font-bold text-center text-gray-900"
>
{$_("statistiken")}
</h1>
<!-- -->
<div class="flex flex-wrap -mx-1 overflow-hidden mt-5">
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/2 md:w-1/3">
<h1 class="text-5xl font-bold text-center text-gray-900">
{general.total_runners || "0"}
</h1>
<h1 class="text-2xl font-semibold text-center text-gray-900">
{$_("laeufer")}
</h1>
</div>
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/2 md:w-1/3">
<h1 class="text-5xl font-bold text-center text-gray-900">
{general.total_distance / 1000 || 0}
</h1>
<h1 class="text-2xl font-semibold text-center text-gray-900">
{$_("kilometer-gesamt")}
</h1>
</div>
<div class="my-1 px-1 w-full overflow-hidden sm:w-1/2 md:w-1/3">
<h1 class="text-5xl font-bold text-center text-gray-900">
{parseFloat(
((general.total_donation || 0) / 100).toFixed(2)
).toLocaleString(undefined, {
minimumFractionDigits: 2,
maximumFractionDigits: 2,
}) || "0"} €
</h1>
<h1 class="text-2xl font-semibold text-center text-gray-900">
{$_("spendensumme")}
</h1>
</div>
</div>
</div>
{:else if current_page === "runners_distance"}
<div transition:slide|local>
<h1
class="mr-6 text-5xl xl:text-7xl font-bold text-center text-gray-900 mb-3"
>
{$_("top-laeufer")} ({$_("distanz")})
</h1>
{#if runners.length === 0}
<p class="w-full text-center text-3xl font-semibold">
Noch keine Daten...
</p>
{:else}
<table
class="table font-semibold p-4 bg-white shadow rounded-lg w-full"
>
<thead>
<tr>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("platz")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("laeufer")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("organisation")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("kilometer")}
</th>
</tr>
</thead>
<tbody>
{#each runners as r, i}
<tr class="text-gray-700">
<td class="border p-4 dark:border-dark-5">
{i + 1}
</td>
<td class="border p-4 dark:border-dark-5">
{r.firstname}
{r.lastname}
</td>
<td class="border p-4 dark:border-dark-5">
{r.group.name}
</td>
<td class="border p-4 dark:border-dark-5">
{r.distance / 1000} km
</td>
</tr>
{/each}
</tbody>
</table>
{/if}
</div>
{:else if current_page === "runners_laptime"}
<div transition:slide|local>
<h1
class="mr-6 text-5xl xl:text-7xl font-bold text-center text-gray-900 mb-3"
>
{$_("top-laeufer")} ({$_("rundenzeit")})
</h1>
{#if runners_by_laptime.length === 0}
<p class="w-full text-center text-3xl font-semibold">
Noch keine Daten...
</p>
{:else}
<table
class="table font-semibold p-4 bg-white shadow rounded-lg w-full"
>
<thead>
<tr>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("platz")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("laeufer")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("organisation")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("schnellste-rundenzeit")}
</th>
</tr>
</thead>
<tbody>
{#each runners_by_laptime as r, i}
<tr class="text-gray-700">
<td class="border p-4 dark:border-dark-5">
{i + 1}
</td>
<td class="border p-4 dark:border-dark-5">
{r.firstname}
{r.lastname}
</td>
<td class="border p-4 dark:border-dark-5">
{r.group.name}
</td>
<td class="border p-4 dark:border-dark-5">
{format_laptime(r.minLaptime)}
</td>
</tr>
{/each}
</tbody>
</table>
{/if}
</div>
{:else if current_page === "orgs_distance"}
<div transition:slide|local>
<h1
class="mr-6 text-5xl xl:text-7xl font-bold text-center text-gray-900 mb-3"
>
{$_("top-organisationen")}
</h1>
{#if orgs.length === 0}
<p class="w-full text-center text-3xl font-semibold">
Noch keine Daten...
</p>
{:else}
<table
class="table font-semibold p-4 bg-white shadow rounded-lg w-full"
>
<thead>
<tr>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("platz")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("organsiation")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("kilometer")}
</th>
</tr>
</thead>
<tbody>
{#each orgs as o, i}
<tr class="text-gray-700">
<td class="border p-4 dark:border-dark-5">
{i + 1}
</td>
<td class="border p-4 dark:border-dark-5">
{o.name}
</td>
<td class="border p-4 dark:border-dark-5">
{o.distance / 1000} km
</td>
</tr>
{/each}
</tbody>
</table>
{/if}
</div>
{:else if current_page === "teams_distance"}
<div transition:slide|local>
<h1
class="mr-6 text-5xl xl:text-7xl font-bold text-center text-gray-900 mb-3"
>
{$_("top-teams")}
</h1>
<table
class="table font-semibold p-4 bg-white shadow rounded-lg w-full"
>
<thead>
<tr>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("platz")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("team")}
</th>
<th
class="border p-4 dark:border-dark-5 whitespace-nowrap font-normal text-gray-900"
>
{$_("kilometer")}
</th>
</tr>
</thead>
<tbody>
{#each teams as t, i}
<tr class="text-gray-700">
<td class="border p-4 dark:border-dark-5">
{i + 1}
</td>
<td class="border p-4 dark:border-dark-5">
{t.parent.name}<br />
{t.name}
</td>
<td class="border p-4 dark:border-dark-5">
{t.distance / 1000} km
</td>
</tr>
{/each}
</tbody>
</table>
</div>
{:else}
<!-- content here -->
{/if}
</div>
</div>
<h1
class="text-6xl font-semibold text-right text-gray-900 font-mono top-2 w-full fixed pr-4 xl:top-6 xl:pr-8"
>
{hours}:{minutes}:{seconds}
</h1>
<h1
class="text-xl xl:text-3xl font-medium text-center text-gray-900 font-mono bottom-2 xl:bottom-4 w-full fixed"
>
<span class="text-black font-extrabold">Lauf für Kaya!</span> - powered by ODIT.Services
</h1>
</div>

View File

@ -1,4 +1,5 @@
<script>
import bg from "/beamershow_background.png?inline";
import { apikey, lang, api_endpoint, laptime_track, clear } from "./store.js";
import isURL from "validator/lib/isURL";
import isUUID from "validator/lib/isUUID";
@ -253,7 +254,7 @@
<img
alt=""
class="object-cover w-full h-screen hidden md:block"
src="https://source.unsplash.com/IXUM4cJynP0"
src={bg}
/>
</div>
</div>

View File

@ -30,6 +30,7 @@
"spendensumme": "Spendensumme",
"station_description": "Beschreibung der Scanstation",
"station_id": "Scanstations-ID",
"statistiken": "Statistiken",
"team": "Team",
"the_provided_scan_station_is_disabled": "Die angegebene Scanstation ist deaktiviert.",
"the_provided_scan_station_token_is_invalid": "Der angegebene Scanstation-Token ist ungültig.",

View File

@ -30,6 +30,7 @@
"spendensumme": "Donations",
"station_description": "Station Description",
"station_id": "Scanstation ID",
"statistiken": "Statistics",
"team": "Team",
"the_provided_scan_station_is_disabled": "The provided scan station is disabled.",
"the_provided_scan_station_token_is_invalid": "The provided scan station token is invalid.",