Commits vergleichen

...

25 Commits

Autor SHA1 Nachricht Datum
TheBreadBeard
437dfa223b Update neujahrsevent-2025-eventplan.md
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2025-01-01 18:34:35 +01:00
012a56e177 Merge remote-tracking branch 'origin/master'
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2025-01-01 17:09:02 +01:00
9f60071e48 Some (alot) of fixes 2025-01-01 17:08:55 +01:00
3bcadde949 Merge pull request 'Merge branch neujahrsevent-2025-eventplan' (#23) from neujahrsevent-2025-eventplan into master
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Reviewed-on: #23
2025-01-01 15:20:47 +01:00
f5332411d2 Fixes
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2025-01-01 14:25:33 +01:00
TheBreadBeard
b546c7b2b2 Update neujahrsevent-2025-eventplan.md
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2025-01-01 13:45:48 +01:00
TheBreadBeard
7716aa1e89 Create page announcements/de/neujahrsevent-2025-eventplan.md
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
2025-01-01 13:42:09 +01:00
a7e961fc0c Fixes
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2024-12-21 16:13:33 +01:00
8c6f5f5729 Fix Render
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2024-12-21 16:06:23 +01:00
41a3b75c97 Fix Render
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2024-12-21 16:03:45 +01:00
fe9610a970 Kampfplan
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2024-12-21 15:58:22 +01:00
6b38f37711 Add Redirects
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2024-12-17 20:44:53 +01:00
68b8e92661 Add latest announcements
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2024-12-15 14:51:55 +01:00
a29689da0a Add latest announcements
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
2024-12-15 14:50:32 +01:00
292d1b6bcc Fixes
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2024-12-15 12:02:54 +01:00
9e6ef73ccb Fixes
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
2024-12-15 11:59:28 +01:00
02ab822801 Fixes
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
2024-12-15 11:49:43 +01:00
d7000c084b Fixes
Einige Prüfungen sind fehlgeschlagen
SteamWarCI Build failed
2024-12-14 18:10:50 +01:00
d4ac123654 Fix Modal
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2024-12-08 17:21:17 +01:00
e93445d933 Merge branch 'kick-ai-bots'
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2024-12-08 17:10:32 +01:00
2383cd6472 Fix Styles
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2024-12-08 17:10:01 +01:00
d86a8493d1 Merge pull request 'Give AI bots the boot' (#22) from kick-ai-bots into master
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Reviewed-on: #22
Reviewed-by: Chaoscaot <chaos@chaoscaot.de>
2024-11-26 15:34:50 +01:00
5f90025493 Give AI bots the boot
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
Mix of

- https://blog.cloudflare.com/declaring-your-aindependence-block-ai-bots-scrapers-and-crawlers-with-a-single-click/
- https://www.google.com/robots.txt
2024-11-26 15:31:44 +01:00
bbb6d87ccc Fix Build
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2024-11-24 23:05:29 +01:00
0ab7d204f2 Fix Build
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2024-11-24 23:00:44 +01:00
43 geänderte Dateien mit 728 neuen und 298 gelöschten Zeilen

Datei anzeigen

@ -15,7 +15,6 @@ export default defineConfig({
output: "static", output: "static",
image: { image: {
service: sharpImageService(), service: sharpImageService(),
domains: [ "vzge.me" ]
}, },
compressHTML: true, compressHTML: true,
site: "https://steamwar.de", site: "https://steamwar.de",
@ -34,9 +33,27 @@ export default defineConfig({
}, },
}), }),
robotsTxt({ robotsTxt({
policy: [{ policy: [
userAgent: "*", disallow: ["/admin", "/login", "/dashboard", "/de", "/_astro"], { userAgent: "*", disallow: ["/admin", "/login", "/dashboard", "/de", "/_astro"] },
}], { userAgent: "anthropic-ai", disallow: "/" },
{ userAgent: "Applebot-Extended", disallow: "/" },
{ userAgent: "Bytespider", disallow: "/" },
{ userAgent: "CCBot", disallow: "/" },
{ userAgent: "ChatGPT-User", disallow: "/" },
{ userAgent: "ClaudeBot", disallow: "/" },
{ userAgent: "Claude-Web", disallow: "/" },
{ userAgent: "cohere-ai", disallow: "/" },
{ userAgent: "Diffbot", disallow: "/" },
{ userAgent: "FacebookBot", disallow: "/" },
{ userAgent: "GPTBot", disallow: "/" },
{ userAgent: "ImagesiftBot", disallow: "/" },
{ userAgent: "Meta-ExternalAgent", disallow: "/" },
{ userAgent: "Meta-ExternalFetcher", disallow: "/" },
{ userAgent: "omgili", disallow: "/" },
{ userAgent: "OmigliBot", disallow: "/" },
{ userAgent: "PerplexityBot", disallow: "/" },
{ userAgent: "Timpibot", disallow: "/" }
],
}), }),
mdx(), mdx(),
], ],

Datei anzeigen

@ -34,7 +34,7 @@
"eslint-plugin-svelte": "^2.46.0", "eslint-plugin-svelte": "^2.46.0",
"postcss-nesting": "^13.0.1", "postcss-nesting": "^13.0.1",
"sass": "^1.81.0", "sass": "^1.81.0",
"svelte": "^5.2.7", "svelte": "^5.16.0",
"tailwind-merge": "^2.5.5", "tailwind-merge": "^2.5.5",
"tailwindcss": "^3.4.15", "tailwindcss": "^3.4.15",
"three": "^0.170.0", "three": "^0.170.0",

162
pnpm-lock.yaml generiert
Datei anzeigen

@ -55,10 +55,10 @@ dependencies:
version: 2.5.2 version: 2.5.2
flowbite-svelte: flowbite-svelte:
specifier: ^0.47.3 specifier: ^0.47.3
version: 0.47.3(svelte@5.2.7) version: 0.47.3(svelte@5.16.0)
flowbite-svelte-icons: flowbite-svelte-icons:
specifier: ^2.0.2 specifier: ^2.0.2
version: 2.0.2(svelte@5.2.7)(tailwind-merge@2.5.5)(tailwindcss@3.4.15) version: 2.0.2(svelte@5.16.0)(tailwind-merge@2.5.5)(tailwindcss@3.4.15)
qs: qs:
specifier: ^6.13.1 specifier: ^6.13.1
version: 6.13.1 version: 6.13.1
@ -67,10 +67,10 @@ dependencies:
version: 0.33.5 version: 0.33.5
svelte-awesome: svelte-awesome:
specifier: ^3.3.5 specifier: ^3.3.5
version: 3.3.5(svelte@5.2.7) version: 3.3.5(svelte@5.16.0)
svelte-codemirror-editor: svelte-codemirror-editor:
specifier: ^1.4.1 specifier: ^1.4.1
version: 1.4.1(codemirror@6.0.1)(svelte@5.2.7) version: 1.4.1(codemirror@6.0.1)(svelte@5.16.0)
svelte-spa-router: svelte-spa-router:
specifier: ^4.0.1 specifier: ^4.0.1
version: 4.0.1 version: 4.0.1
@ -81,7 +81,7 @@ dependencies:
devDependencies: devDependencies:
'@astrojs/svelte': '@astrojs/svelte':
specifier: ^6.0.2 specifier: ^6.0.2
version: 6.0.2(@types/node@22.9.3)(astro@4.16.14)(sass@1.81.0)(svelte@5.2.7)(typescript@5.7.2) version: 6.0.2(@types/node@22.9.3)(astro@4.16.14)(sass@1.81.0)(svelte@5.16.0)(typescript@5.7.2)
'@astrojs/tailwind': '@astrojs/tailwind':
specifier: ^5.1.2 specifier: ^5.1.2
version: 5.1.2(astro@4.16.14)(tailwindcss@3.4.15) version: 5.1.2(astro@4.16.14)(tailwindcss@3.4.15)
@ -123,7 +123,7 @@ devDependencies:
version: 6.10.2(eslint@9.15.0) version: 6.10.2(eslint@9.15.0)
eslint-plugin-svelte: eslint-plugin-svelte:
specifier: ^2.46.0 specifier: ^2.46.0
version: 2.46.0(eslint@9.15.0)(svelte@5.2.7) version: 2.46.0(eslint@9.15.0)(svelte@5.16.0)
postcss-nesting: postcss-nesting:
specifier: ^13.0.1 specifier: ^13.0.1
version: 13.0.1(postcss@8.4.49) version: 13.0.1(postcss@8.4.49)
@ -131,8 +131,8 @@ devDependencies:
specifier: ^1.81.0 specifier: ^1.81.0
version: 1.81.0 version: 1.81.0
svelte: svelte:
specifier: ^5.2.7 specifier: ^5.16.0
version: 5.2.7 version: 5.16.0
tailwind-merge: tailwind-merge:
specifier: ^2.5.5 specifier: ^2.5.5
version: 2.5.5 version: 2.5.5
@ -279,7 +279,7 @@ packages:
zod: 3.23.8 zod: 3.23.8
dev: false dev: false
/@astrojs/svelte@6.0.2(@types/node@22.9.3)(astro@4.16.14)(sass@1.81.0)(svelte@5.2.7)(typescript@5.7.2): /@astrojs/svelte@6.0.2(@types/node@22.9.3)(astro@4.16.14)(sass@1.81.0)(svelte@5.16.0)(typescript@5.7.2):
resolution: {integrity: sha512-Jn60LLH+AbjtLIOQuL0SUI0fxMwpT89VraoGkEwF33ZgCT59H8fMQOj9eNf632P/SHRbKpD+Q+PJjODn5OcKoQ==} resolution: {integrity: sha512-Jn60LLH+AbjtLIOQuL0SUI0fxMwpT89VraoGkEwF33ZgCT59H8fMQOj9eNf632P/SHRbKpD+Q+PJjODn5OcKoQ==}
engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0} engines: {node: ^18.17.1 || ^20.3.0 || >=21.0.0}
peerDependencies: peerDependencies:
@ -287,10 +287,10 @@ packages:
svelte: ^5.1.16 svelte: ^5.1.16
typescript: ^5.3.3 typescript: ^5.3.3
dependencies: dependencies:
'@sveltejs/vite-plugin-svelte': 4.0.1(svelte@5.2.7)(vite@5.4.11) '@sveltejs/vite-plugin-svelte': 4.0.1(svelte@5.16.0)(vite@5.4.11)
astro: 4.16.14(@types/node@22.9.3)(sass@1.81.0)(typescript@5.7.2) astro: 4.16.14(@types/node@22.9.3)(sass@1.81.0)(typescript@5.7.2)
svelte: 5.2.7 svelte: 5.16.0
svelte2tsx: 0.7.28(svelte@5.2.7)(typescript@5.7.2) svelte2tsx: 0.7.28(svelte@5.16.0)(typescript@5.7.2)
typescript: 5.7.2 typescript: 5.7.2
vite: 5.4.11(@types/node@22.9.3)(sass@1.81.0) vite: 5.4.11(@types/node@22.9.3)(sass@1.81.0)
transitivePeerDependencies: transitivePeerDependencies:
@ -513,26 +513,21 @@ packages:
'@babel/helper-string-parser': 7.25.9 '@babel/helper-string-parser': 7.25.9
'@babel/helper-validator-identifier': 7.25.9 '@babel/helper-validator-identifier': 7.25.9
/@codemirror/autocomplete@6.18.3(@codemirror/language@6.10.4)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.3): /@codemirror/autocomplete@6.18.4:
resolution: {integrity: sha512-1dNIOmiM0z4BIBwxmxEfA1yoxh1MF/6KPBbh20a5vphGV0ictKlgQsbJs6D6SkR6iJpGbpwRsa6PFMNlg9T9pQ==} resolution: {integrity: sha512-sFAphGQIqyQZfP2ZBsSHV7xQvo9Py0rV0dW7W3IMRdS+zDuNb2l3no78CvUaWKGfzFjI4FTrLdUSj86IGb2hRA==}
peerDependencies:
'@codemirror/language': ^6.0.0
'@codemirror/state': ^6.0.0
'@codemirror/view': ^6.0.0
'@lezer/common': ^1.0.0
dependencies: dependencies:
'@codemirror/language': 6.10.4 '@codemirror/language': 6.10.8
'@codemirror/state': 6.4.1 '@codemirror/state': 6.5.0
'@codemirror/view': 6.35.0 '@codemirror/view': 6.36.1
'@lezer/common': 1.2.3 '@lezer/common': 1.2.3
dev: false dev: false
/@codemirror/commands@6.7.1: /@codemirror/commands@6.7.1:
resolution: {integrity: sha512-llTrboQYw5H4THfhN4U3qCnSZ1SOJ60ohhz+SzU0ADGtwlc533DtklQP0vSFaQuCPDn3BPpOd1GbbnUtwNjsrw==} resolution: {integrity: sha512-llTrboQYw5H4THfhN4U3qCnSZ1SOJ60ohhz+SzU0ADGtwlc533DtklQP0vSFaQuCPDn3BPpOd1GbbnUtwNjsrw==}
dependencies: dependencies:
'@codemirror/language': 6.10.4 '@codemirror/language': 6.10.8
'@codemirror/state': 6.4.1 '@codemirror/state': 6.5.0
'@codemirror/view': 6.35.0 '@codemirror/view': 6.36.1
'@lezer/common': 1.2.3 '@lezer/common': 1.2.3
dev: false dev: false
@ -554,19 +549,30 @@ packages:
style-mod: 4.1.2 style-mod: 4.1.2
dev: false dev: false
/@codemirror/lint@6.8.3: /@codemirror/language@6.10.8:
resolution: {integrity: sha512-GSGfKxCo867P7EX1k2LoCrjuQFeqVgPGRRsSl4J4c0KMkD+k1y6WYvTQkzv0iZ8JhLJDujEvlnMchv4CZQLh3Q==} resolution: {integrity: sha512-wcP8XPPhDH2vTqf181U8MbZnW+tDyPYy0UzVOa+oHORjyT+mhhom9vBd7dApJwoDz9Nb/a8kHjJIsuA/t8vNFw==}
dependencies: dependencies:
'@codemirror/state': 6.4.1 '@codemirror/state': 6.5.0
'@codemirror/view': 6.35.0 '@codemirror/view': 6.36.1
'@lezer/common': 1.2.3
'@lezer/highlight': 1.2.1
'@lezer/lr': 1.4.2
style-mod: 4.1.2
dev: false
/@codemirror/lint@6.8.4:
resolution: {integrity: sha512-u4q7PnZlJUojeRe8FJa/njJcMctISGgPQ4PnWsd9268R4ZTtU+tfFYmwkBvgcrK2+QQ8tYFVALVb5fVJykKc5A==}
dependencies:
'@codemirror/state': 6.5.0
'@codemirror/view': 6.36.1
crelt: 1.0.6 crelt: 1.0.6
dev: false dev: false
/@codemirror/search@6.5.8: /@codemirror/search@6.5.8:
resolution: {integrity: sha512-PoWtZvo7c1XFeZWmmyaOp2G0XVbOnm+fJzvghqGAktBW3cufwJUWvSCcNG0ppXiBEM05mZu6RhMtXPv2hpllig==} resolution: {integrity: sha512-PoWtZvo7c1XFeZWmmyaOp2G0XVbOnm+fJzvghqGAktBW3cufwJUWvSCcNG0ppXiBEM05mZu6RhMtXPv2hpllig==}
dependencies: dependencies:
'@codemirror/state': 6.4.1 '@codemirror/state': 6.5.0
'@codemirror/view': 6.35.0 '@codemirror/view': 6.36.1
crelt: 1.0.6 crelt: 1.0.6
dev: false dev: false
@ -574,6 +580,12 @@ packages:
resolution: {integrity: sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==} resolution: {integrity: sha512-QkEyUiLhsJoZkbumGZlswmAhA7CBU02Wrz7zvH4SrcifbsqwlXShVXg65f3v/ts57W3dqyamEriMhij1Z3Zz4A==}
dev: false dev: false
/@codemirror/state@6.5.0:
resolution: {integrity: sha512-MwBHVK60IiIHDcoMet78lxt6iw5gJOGSbNbOIVBHWVXIH4/Nq1+GQgLLGgI1KlnN86WDXsPudVaqYHKBIx7Eyw==}
dependencies:
'@marijn/find-cluster-break': 1.0.2
dev: false
/@codemirror/view@6.35.0: /@codemirror/view@6.35.0:
resolution: {integrity: sha512-I0tYy63q5XkaWsJ8QRv5h6ves7kvtrBWjBcnf/bzohFJQc5c14a1AQRdE8QpPF9eMp5Mq2FMm59TCj1gDfE7kw==} resolution: {integrity: sha512-I0tYy63q5XkaWsJ8QRv5h6ves7kvtrBWjBcnf/bzohFJQc5c14a1AQRdE8QpPF9eMp5Mq2FMm59TCj1gDfE7kw==}
dependencies: dependencies:
@ -582,6 +594,14 @@ packages:
w3c-keyname: 2.2.8 w3c-keyname: 2.2.8
dev: false dev: false
/@codemirror/view@6.36.1:
resolution: {integrity: sha512-miD1nyT4m4uopZaDdO2uXU/LLHliKNYL9kB1C1wJHrunHLm/rpkb5QVSokqgw9hFqEZakrdlb/VGWX8aYZTslQ==}
dependencies:
'@codemirror/state': 6.5.0
style-mod: 4.1.2
w3c-keyname: 2.2.8
dev: false
/@csstools/selector-resolve-nested@3.0.0(postcss-selector-parser@7.0.0): /@csstools/selector-resolve-nested@3.0.0(postcss-selector-parser@7.0.0):
resolution: {integrity: sha512-ZoK24Yku6VJU1gS79a5PFmC8yn3wIapiKmPgun0hZgEI5AOqgH2kiPRsPz1qkGv4HL+wuDLH83yQyk6inMYrJQ==} resolution: {integrity: sha512-ZoK24Yku6VJU1gS79a5PFmC8yn3wIapiKmPgun0hZgEI5AOqgH2kiPRsPz1qkGv4HL+wuDLH83yQyk6inMYrJQ==}
engines: {node: '>=18'} engines: {node: '>=18'}
@ -1364,6 +1384,10 @@ packages:
'@lezer/common': 1.2.3 '@lezer/common': 1.2.3
dev: false dev: false
/@marijn/find-cluster-break@1.0.2:
resolution: {integrity: sha512-l0h88YhZFyKdXIFNfSWpyjStDjGHwZ/U7iobcK1cQQD8sejsONdQtTVU+1wVN1PBw40PiiHB1vA5S7VTfQiP9g==}
dev: false
/@mdx-js/mdx@3.1.0(acorn@8.14.0): /@mdx-js/mdx@3.1.0(acorn@8.14.0):
resolution: {integrity: sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==} resolution: {integrity: sha512-/QxEhPAvGwbQmy1Px8F899L5Uc2KZ6JtXwlCgJmjSTBedwOZkByYcBG4GceIGPXRDsmfxhHazuS+hlOShRLeDw==}
dependencies: dependencies:
@ -1796,7 +1820,7 @@ packages:
/@shikijs/vscode-textmate@9.3.0: /@shikijs/vscode-textmate@9.3.0:
resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==} resolution: {integrity: sha512-jn7/7ky30idSkd/O5yDBfAnVt+JJpepofP/POZ1iMOxK59cOfqIgg/Dj0eFsjOTMw+4ycJN0uhZH/Eb0bs/EUA==}
/@sveltejs/vite-plugin-svelte-inspector@3.0.1(@sveltejs/vite-plugin-svelte@4.0.1)(svelte@5.2.7)(vite@5.4.11): /@sveltejs/vite-plugin-svelte-inspector@3.0.1(@sveltejs/vite-plugin-svelte@4.0.1)(svelte@5.16.0)(vite@5.4.11):
resolution: {integrity: sha512-2CKypmj1sM4GE7HjllT7UKmo4Q6L5xFRd7VMGEWhYnZ+wc6AUVU01IBd7yUi6WnFndEwWoMNOd6e8UjoN0nbvQ==} resolution: {integrity: sha512-2CKypmj1sM4GE7HjllT7UKmo4Q6L5xFRd7VMGEWhYnZ+wc6AUVU01IBd7yUi6WnFndEwWoMNOd6e8UjoN0nbvQ==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22} engines: {node: ^18.0.0 || ^20.0.0 || >=22}
peerDependencies: peerDependencies:
@ -1804,27 +1828,27 @@ packages:
svelte: ^5.0.0-next.96 || ^5.0.0 svelte: ^5.0.0-next.96 || ^5.0.0
vite: ^5.0.0 vite: ^5.0.0
dependencies: dependencies:
'@sveltejs/vite-plugin-svelte': 4.0.1(svelte@5.2.7)(vite@5.4.11) '@sveltejs/vite-plugin-svelte': 4.0.1(svelte@5.16.0)(vite@5.4.11)
debug: 4.3.7 debug: 4.3.7
svelte: 5.2.7 svelte: 5.16.0
vite: 5.4.11(@types/node@22.9.3)(sass@1.81.0) vite: 5.4.11(@types/node@22.9.3)(sass@1.81.0)
transitivePeerDependencies: transitivePeerDependencies:
- supports-color - supports-color
dev: true dev: true
/@sveltejs/vite-plugin-svelte@4.0.1(svelte@5.2.7)(vite@5.4.11): /@sveltejs/vite-plugin-svelte@4.0.1(svelte@5.16.0)(vite@5.4.11):
resolution: {integrity: sha512-prXoAE/GleD2C4pKgHa9vkdjpzdYwCSw/kmjw6adIyu0vk5YKCfqIztkLg10m+kOYnzZu3bb0NaPTxlWre2a9Q==} resolution: {integrity: sha512-prXoAE/GleD2C4pKgHa9vkdjpzdYwCSw/kmjw6adIyu0vk5YKCfqIztkLg10m+kOYnzZu3bb0NaPTxlWre2a9Q==}
engines: {node: ^18.0.0 || ^20.0.0 || >=22} engines: {node: ^18.0.0 || ^20.0.0 || >=22}
peerDependencies: peerDependencies:
svelte: ^5.0.0-next.96 || ^5.0.0 svelte: ^5.0.0-next.96 || ^5.0.0
vite: ^5.0.0 vite: ^5.0.0
dependencies: dependencies:
'@sveltejs/vite-plugin-svelte-inspector': 3.0.1(@sveltejs/vite-plugin-svelte@4.0.1)(svelte@5.2.7)(vite@5.4.11) '@sveltejs/vite-plugin-svelte-inspector': 3.0.1(@sveltejs/vite-plugin-svelte@4.0.1)(svelte@5.16.0)(vite@5.4.11)
debug: 4.3.7 debug: 4.3.7
deepmerge: 4.3.1 deepmerge: 4.3.1
kleur: 4.1.5 kleur: 4.1.5
magic-string: 0.30.13 magic-string: 0.30.13
svelte: 5.2.7 svelte: 5.16.0
vite: 5.4.11(@types/node@22.9.3)(sass@1.81.0) vite: 5.4.11(@types/node@22.9.3)(sass@1.81.0)
vitefu: 1.0.3(vite@5.4.11) vitefu: 1.0.3(vite@5.4.11)
transitivePeerDependencies: transitivePeerDependencies:
@ -2762,18 +2786,16 @@ packages:
resolution: {integrity: sha512-Gaz4gHnkbHMGgahNt3CA5HBk5lLQBqmD/pBgeB4kQU6OedZmqMBjlRF0LSrp2tJ4wlLNPm2FfaUd1pDy0mdlpA==} resolution: {integrity: sha512-Gaz4gHnkbHMGgahNt3CA5HBk5lLQBqmD/pBgeB4kQU6OedZmqMBjlRF0LSrp2tJ4wlLNPm2FfaUd1pDy0mdlpA==}
dev: false dev: false
/codemirror@6.0.1(@lezer/common@1.2.3): /codemirror@6.0.1:
resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==} resolution: {integrity: sha512-J8j+nZ+CdWmIeFIGXEFbFPtpiYacFMDR8GlHK3IyHQJMCaVRfGx9NT+Hxivv1ckLWPvNdZqndbr/7lVhrf/Svg==}
dependencies: dependencies:
'@codemirror/autocomplete': 6.18.3(@codemirror/language@6.10.4)(@codemirror/state@6.4.1)(@codemirror/view@6.35.0)(@lezer/common@1.2.3) '@codemirror/autocomplete': 6.18.4
'@codemirror/commands': 6.7.1 '@codemirror/commands': 6.7.1
'@codemirror/language': 6.10.4 '@codemirror/language': 6.10.8
'@codemirror/lint': 6.8.3 '@codemirror/lint': 6.8.4
'@codemirror/search': 6.5.8 '@codemirror/search': 6.5.8
'@codemirror/state': 6.4.1 '@codemirror/state': 6.5.0
'@codemirror/view': 6.35.0 '@codemirror/view': 6.36.1
transitivePeerDependencies:
- '@lezer/common'
dev: false dev: false
/collapse-white-space@2.1.0: /collapse-white-space@2.1.0:
@ -3404,7 +3426,7 @@ packages:
string.prototype.includes: 2.0.1 string.prototype.includes: 2.0.1
dev: true dev: true
/eslint-plugin-svelte@2.46.0(eslint@9.15.0)(svelte@5.2.7): /eslint-plugin-svelte@2.46.0(eslint@9.15.0)(svelte@5.16.0):
resolution: {integrity: sha512-1A7iEMkzmCZ9/Iz+EAfOGYL8IoIG6zeKEq1SmpxGeM5SXmoQq+ZNnCpXFVJpsxPWYx8jIVGMerQMzX20cqUl0g==} resolution: {integrity: sha512-1A7iEMkzmCZ9/Iz+EAfOGYL8IoIG6zeKEq1SmpxGeM5SXmoQq+ZNnCpXFVJpsxPWYx8jIVGMerQMzX20cqUl0g==}
engines: {node: ^14.17.0 || >=16.0.0} engines: {node: ^14.17.0 || >=16.0.0}
peerDependencies: peerDependencies:
@ -3425,8 +3447,8 @@ packages:
postcss-safe-parser: 6.0.0(postcss@8.4.49) postcss-safe-parser: 6.0.0(postcss@8.4.49)
postcss-selector-parser: 6.1.2 postcss-selector-parser: 6.1.2
semver: 7.6.3 semver: 7.6.3
svelte: 5.2.7 svelte: 5.16.0
svelte-eslint-parser: 0.43.0(svelte@5.2.7) svelte-eslint-parser: 0.43.0(svelte@5.16.0)
transitivePeerDependencies: transitivePeerDependencies:
- ts-node - ts-node
dev: true dev: true
@ -3505,8 +3527,8 @@ packages:
- supports-color - supports-color
dev: true dev: true
/esm-env@1.1.4: /esm-env@1.2.1:
resolution: {integrity: sha512-oO82nKPHKkzIj/hbtuDYy/JHqBHFlMIW36SDiPCVsj87ntDLcWN+sJ1erdVryd4NxODacFTsdrIE3b7IamqbOg==} resolution: {integrity: sha512-U9JedYYjCnadUlXk7e1Kr+aENQhtUaoaV9+gZm1T8LC/YBAPJx3NSPIAurFOC0U5vrdSevnUJS2/wUVxGwPhng==}
/espree@10.3.0: /espree@10.3.0:
resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==} resolution: {integrity: sha512-0QYC8b24HWY8zjRnDTL6RiHfDbAWn63qb4LMj1Z4b076A4une81+z03Kg7l7mn/48PUTqoLptSXez8oknU8Clg==}
@ -3538,11 +3560,10 @@ packages:
estraverse: 5.3.0 estraverse: 5.3.0
dev: true dev: true
/esrap@1.2.2: /esrap@1.3.2:
resolution: {integrity: sha512-F2pSJklxx1BlQIQgooczXCPHmcWpn6EsP5oo73LQfonG9fIlIENQ8vMmfGXeojP9MrkzUNAfyU5vdFlR9shHAw==} resolution: {integrity: sha512-C4PXusxYhFT98GjLSmb20k9PREuUdporer50dhzGuJu9IJXktbMddVCMLAERl5dAHyAi73GWWCE4FVHGP1794g==}
dependencies: dependencies:
'@jridgewell/sourcemap-codec': 1.5.0 '@jridgewell/sourcemap-codec': 1.5.0
'@types/estree': 1.0.6
/esrecurse@4.3.0: /esrecurse@4.3.0:
resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==} resolution: {integrity: sha512-KmfKL3b6G+RXvP8N1vr3Tq1kL/oCFgn2NYXEtqP8/L3pKapUA4G8cFVaoF3SU323CD4XypR/ffioHmkti6/Tag==}
@ -3724,7 +3745,7 @@ packages:
- rollup - rollup
dev: false dev: false
/flowbite-svelte-icons@2.0.2(svelte@5.2.7)(tailwind-merge@2.5.5)(tailwindcss@3.4.15): /flowbite-svelte-icons@2.0.2(svelte@5.16.0)(tailwind-merge@2.5.5)(tailwindcss@3.4.15):
resolution: {integrity: sha512-Vkmduy2867Rk8R7TziPirsWkixJnToFBEXRaN4ouJabOx62NQjiBbHFe+HTaMOQmdp4FNMI2Nhtk2I2CQ8r3RQ==} resolution: {integrity: sha512-Vkmduy2867Rk8R7TziPirsWkixJnToFBEXRaN4ouJabOx62NQjiBbHFe+HTaMOQmdp4FNMI2Nhtk2I2CQ8r3RQ==}
engines: {node: '>=18.0.0', npm: '>=7.0.0'} engines: {node: '>=18.0.0', npm: '>=7.0.0'}
peerDependencies: peerDependencies:
@ -3732,12 +3753,12 @@ packages:
tailwind-merge: ^2.3.0 tailwind-merge: ^2.3.0
tailwindcss: ^3.4.3 tailwindcss: ^3.4.3
dependencies: dependencies:
svelte: 5.2.7 svelte: 5.16.0
tailwind-merge: 2.5.5 tailwind-merge: 2.5.5
tailwindcss: 3.4.15 tailwindcss: 3.4.15
dev: false dev: false
/flowbite-svelte@0.47.3(svelte@5.2.7): /flowbite-svelte@0.47.3(svelte@5.16.0):
resolution: {integrity: sha512-1Wdbx+YV6S20dnnMERr/XFNjO+sb22QOrZtIK0Wa8SXxxuYPmbkT3b4mR4TYwUWvWheXsWvlcPLSlV8YGJgItw==} resolution: {integrity: sha512-1Wdbx+YV6S20dnnMERr/XFNjO+sb22QOrZtIK0Wa8SXxxuYPmbkT3b4mR4TYwUWvWheXsWvlcPLSlV8YGJgItw==}
engines: {node: '>=18.0.0', pnpm: '>=8.0.0'} engines: {node: '>=18.0.0', pnpm: '>=8.0.0'}
peerDependencies: peerDependencies:
@ -3746,7 +3767,7 @@ packages:
'@floating-ui/dom': 1.6.12 '@floating-ui/dom': 1.6.12
apexcharts: 3.54.1 apexcharts: 3.54.1
flowbite: 2.5.2 flowbite: 2.5.2
svelte: 5.2.7 svelte: 5.16.0
tailwind-merge: 2.5.5 tailwind-merge: 2.5.5
transitivePeerDependencies: transitivePeerDependencies:
- rollup - rollup
@ -6542,25 +6563,25 @@ packages:
resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==} resolution: {integrity: sha512-ot0WnXS9fgdkgIcePe6RHNk1WA8+muPa6cSjeR3V8K27q9BB1rTE3R1p7Hv0z1ZyAc8s6Vvv8DIyWf681MAt0w==}
engines: {node: '>= 0.4'} engines: {node: '>= 0.4'}
/svelte-awesome@3.3.5(svelte@5.2.7): /svelte-awesome@3.3.5(svelte@5.16.0):
resolution: {integrity: sha512-RIi+OI6CEn+fTdYy7UOgImEUWvdQSwP9SiMC44UKyFO+8+gjj+NgTG67hI8j2rTHQVvCP820Uj+4UoZG8CCUfA==} resolution: {integrity: sha512-RIi+OI6CEn+fTdYy7UOgImEUWvdQSwP9SiMC44UKyFO+8+gjj+NgTG67hI8j2rTHQVvCP820Uj+4UoZG8CCUfA==}
peerDependencies: peerDependencies:
svelte: '>= 3.43.1 < 6' svelte: '>= 3.43.1 < 6'
dependencies: dependencies:
svelte: 5.2.7 svelte: 5.16.0
dev: false dev: false
/svelte-codemirror-editor@1.4.1(codemirror@6.0.1)(svelte@5.2.7): /svelte-codemirror-editor@1.4.1(codemirror@6.0.1)(svelte@5.16.0):
resolution: {integrity: sha512-Pv350iro0Y/AZTT/y2OLaonheQqAwl50Hdfipa2Jv1Z04TSP5kPUyxQnRjqxeRW7DXOX9s5Nd11tHdBl9iYSzw==} resolution: {integrity: sha512-Pv350iro0Y/AZTT/y2OLaonheQqAwl50Hdfipa2Jv1Z04TSP5kPUyxQnRjqxeRW7DXOX9s5Nd11tHdBl9iYSzw==}
peerDependencies: peerDependencies:
codemirror: ^6.0.0 codemirror: ^6.0.0
svelte: ^3.0.0 || ^4.0.0 || ^5.0.0 svelte: ^3.0.0 || ^4.0.0 || ^5.0.0
dependencies: dependencies:
codemirror: 6.0.1(@lezer/common@1.2.3) codemirror: 6.0.1
svelte: 5.2.7 svelte: 5.16.0
dev: false dev: false
/svelte-eslint-parser@0.43.0(svelte@5.2.7): /svelte-eslint-parser@0.43.0(svelte@5.16.0):
resolution: {integrity: sha512-GpU52uPKKcVnh8tKN5P4UZpJ/fUDndmq7wfsvoVXsyP+aY0anol7Yqo01fyrlaWGMFfm4av5DyrjlaXdLRJvGA==} resolution: {integrity: sha512-GpU52uPKKcVnh8tKN5P4UZpJ/fUDndmq7wfsvoVXsyP+aY0anol7Yqo01fyrlaWGMFfm4av5DyrjlaXdLRJvGA==}
engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0} engines: {node: ^12.22.0 || ^14.17.0 || >=16.0.0}
peerDependencies: peerDependencies:
@ -6574,7 +6595,7 @@ packages:
espree: 9.6.1 espree: 9.6.1
postcss: 8.4.49 postcss: 8.4.49
postcss-scss: 4.0.9(postcss@8.4.49) postcss-scss: 4.0.9(postcss@8.4.49)
svelte: 5.2.7 svelte: 5.16.0
dev: true dev: true
/svelte-spa-router@4.0.1: /svelte-spa-router@4.0.1:
@ -6583,7 +6604,7 @@ packages:
regexparam: 2.0.2 regexparam: 2.0.2
dev: false dev: false
/svelte2tsx@0.7.28(svelte@5.2.7)(typescript@5.7.2): /svelte2tsx@0.7.28(svelte@5.16.0)(typescript@5.7.2):
resolution: {integrity: sha512-TJjA+kU8AnkyoprZPgQACMfTX8N0MA5NsIL//h9IuHOxmmaCLluqhcZU+fCkWipi5c/pooHLFOMpqjhq4v7JLQ==} resolution: {integrity: sha512-TJjA+kU8AnkyoprZPgQACMfTX8N0MA5NsIL//h9IuHOxmmaCLluqhcZU+fCkWipi5c/pooHLFOMpqjhq4v7JLQ==}
peerDependencies: peerDependencies:
svelte: ^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0 svelte: ^3.55 || ^4.0.0-next.0 || ^4.0 || ^5.0.0-next.0
@ -6591,12 +6612,12 @@ packages:
dependencies: dependencies:
dedent-js: 1.0.1 dedent-js: 1.0.1
pascal-case: 3.1.2 pascal-case: 3.1.2
svelte: 5.2.7 svelte: 5.16.0
typescript: 5.7.2 typescript: 5.7.2
dev: true dev: true
/svelte@5.2.7: /svelte@5.16.0:
resolution: {integrity: sha512-cEhPGuLHiH2+Z8B1FwQgiZJgA39uUmJR4516TKrM5zrp0/cuwJkfhUfcTxhAkznanAF5fXUKzvYR4o+Ksx3ZCQ==} resolution: {integrity: sha512-Ygqsiac6UogVED2ruKclU+pOeMThxWtp9LG+li7BXeDKC2paVIsRTMkNmcON4Zejerd1s5sZHWx6ZtU85xklVg==}
engines: {node: '>=18'} engines: {node: '>=18'}
dependencies: dependencies:
'@ampproject/remapping': 2.3.0 '@ampproject/remapping': 2.3.0
@ -6606,8 +6627,9 @@ packages:
acorn-typescript: 1.4.13(acorn@8.14.0) acorn-typescript: 1.4.13(acorn@8.14.0)
aria-query: 5.3.2 aria-query: 5.3.2
axobject-query: 4.1.0 axobject-query: 4.1.0
esm-env: 1.1.4 clsx: 2.1.1
esrap: 1.2.2 esm-env: 1.2.1
esrap: 1.3.2
is-reference: 3.0.3 is-reference: 3.0.3
locate-character: 3.0.0 locate-character: 3.0.0
magic-string: 0.30.13 magic-string: 0.30.13

Datei anzeigen

@ -37,13 +37,9 @@
<p>{t("status.loading")}</p> <p>{t("status.loading")}</p>
{:then user} {:then user}
<UserInfo {user} /> <UserInfo {user} />
<hr> <SWButton onclick={() => uploadOpen = true}>
{t("dashboard.schematic.upload")}
<div class="flex flex-col justify-center"> </SWButton>
<SWButton on:click={() => uploadOpen = true}>
{t("dashboard.schematic.upload")}
</SWButton>
</div>
{:catch error} {:catch error}
<p>error: {error.message}</p> <p>error: {error.message}</p>
{/await} {/await}

Datei anzeigen

@ -42,34 +42,32 @@
} }
</script> </script>
<div> <div class="p-3 bg-gray-200 dark:bg-neutral-800 rounded-2xl w-3/4 mx-auto">
<table> <table>
<tr class="font-bold border-b"> <thead>
{#each Array(rows) as i (i)} <tr class="font-bold border-b">
<td>{t("announcements.table.time")}</td> {#each Array(rows) as i (i)}
<td>{t("announcements.table.blue")}</td> <td>{t("announcements.table.time")}</td>
<td>{t("announcements.table.red")}</td> <td>{t("announcements.table.blue")}</td>
<td>{t("announcements.table.winner")}</td> <td>{t("announcements.table.red")}</td>
{/each} <td>{t("announcements.table.winner")}</td>
</tr>
{#each window(event.fights.filter(f => f.group === group), rows) as fights}
<tr>
{#each fights as fight (fight.id)}
<td>{Intl.DateTimeFormat(astroI18n.locale, {
hour: "numeric",
minute: "numeric",
}).format(new Date(fight.start))}</td>
<td class:font-bold={fight.ergebnis === 1} class:italic={fight.ergebnis === 3}>{fight.blueTeam.kuerzel}</td>
<td class:font-bold={fight.ergebnis === 2} class:italic={fight.ergebnis === 3}>{fight.redTeam.kuerzel}</td>
<td>{getWinner(fight)}</td>
{/each} {/each}
</tr> </tr>
{/each} </thead>
<tbody>
{#each window(event.fights.filter(f => f.group === group), rows) as fights}
<tr>
{#each fights as fight (fight.id)}
<td>{Intl.DateTimeFormat(astroI18n.locale, {
hour: "numeric",
minute: "numeric",
}).format(new Date(fight.start))}</td>
<td class:font-bold={fight.ergebnis === 1} class:italic={fight.ergebnis === 3}>{fight.blueTeam.kuerzel}</td>
<td class:font-bold={fight.ergebnis === 2} class:italic={fight.ergebnis === 3}>{fight.redTeam.kuerzel}</td>
<td>{getWinner(fight)}</td>
{/each}
</tr>
{/each}
</tbody>
</table> </table>
</div> </div>
<style lang="scss">
div {
@apply p-3 bg-gray-200 dark:bg-neutral-800 rounded-2xl w-3/4 mx-auto;
}
</style>

Datei anzeigen

@ -48,30 +48,25 @@
}).sort((a, b) => b.points - a.points); }).sort((a, b) => b.points - a.points);
</script> </script>
<div> <div class="p-3 bg-gray-200 dark:bg-neutral-800 rounded-2xl w-3/4 mx-auto">
<table> <table class="w-full">
<tr class="font-bold border-b"> <thead>
{#each Array(rows) as i (i)} <tr class="font-bold border-b">
<td>{t("announcements.table.team")}</td> {#each Array(rows) as i (i)}
<td>{t("announcements.table.points")}</td> <td>{t("announcements.table.team")}</td>
{/each} <td>{t("announcements.table.points")}</td>
</tr>
{#each window(teamPoints, rows) as teams}
<tr>
{#each teams as team (team.team.id)}
<td>{team.team.name}</td>
<td>{team.points}</td>
{/each} {/each}
</tr> </tr>
{/each} </thead>
<tbody>
{#each window(teamPoints, rows) as teams}
<tr>
{#each teams as team (team.team.id)}
<td>{team.team.name}</td>
<td>{team.points}</td>
{/each}
</tr>
{/each}
</tbody>
</table> </table>
</div> </div>
<style lang="scss">
table {
@apply w-full;
}
div {
@apply p-3 bg-gray-200 dark:bg-neutral-800 rounded-2xl w-3/4 mx-auto;
}
</style>

Datei anzeigen

@ -110,7 +110,7 @@
<span class="btn__text">{t("navbar.links.account")}</span> <span class="btn__text">{t("navbar.links.account")}</span>
</a> </a>
<!-- <!--
<button class="btn my-1" on:click={() => searchOpen = true}> <button class="btn my-1" onclick={() => searchOpen = true}>
<SearchOutline ariaLabel="Site Search" class="inline-block h-6"/> <SearchOutline ariaLabel="Site Search" class="inline-block h-6"/>
</button> </button>
--> -->

Datei anzeigen

@ -32,7 +32,7 @@
<Modal bind:open title={error.message}> <Modal bind:open title={error.message}>
<p>{error.stack}</p> <p>{error.stack}</p>
{#snippet footer()} {#snippet footer()}
<Button on:click={() => open = false}>Close</Button> <Button onclick={() => open = false}>Close</Button>
{/snippet} {/snippet}
</Modal> </Modal>
{/if} {/if}

Datei anzeigen

@ -36,25 +36,22 @@
leftText = false, leftText = false,
searchValue = $bindable(items.find(item => item.value === selected)?.name || "") searchValue = $bindable(items.find(item => item.value === selected)?.name || "")
}: Props = $props(); }: Props = $props();
let open = $state(false);
let filteredItems = $derived(items.filter(item => item.name.toLowerCase().includes(searchValue.toLowerCase())).filter((value, index) => index < maxItems)); let filteredItems = $derived(items.filter(item => item.name.toLowerCase().includes(searchValue.toLowerCase())).filter((value, index) => index < maxItems));
function selectItem(item: { name: string, value: string }) { function selectItem(item: { name: string, value: string }) {
selected = item.value; selected = item.value;
searchValue = ""; searchValue = "";
open = false;
} }
</script> </script>
<Button color="light" <Button color="light">{selected === null ? 'Auswählen' : items.find(value => value.value === selected)?.name}</Button>
on:click={() => open = true}>{selected === null ? 'Auswählen' : items.find(value => value.value === selected)?.name}</Button> <Dropdown class="w-60">
<Dropdown bind:open class="w-60">
{#snippet header()} {#snippet header()}
<div class="overflow-y-auto p-3 text-sm w-60" > <div class="overflow-y-auto p-3 text-sm w-60" >
<Search bind:value={searchValue} on:focus={() => open = true} on:keydown={() => open = true}/> <Search bind:value={searchValue} />
</div> </div>
{/snippet} {/snippet}
{#each filteredItems as item (item)} {#each filteredItems as item (item)}
<button onclick={() => selectItem(item)} <button onclick={() => selectItem(item)}
class="rounded p-2 hover:bg-gray-100 dark:hover:bg-gray-600 w-full cursor-pointer border-b border-b-gray-600" class="rounded p-2 hover:bg-gray-100 dark:hover:bg-gray-600 w-full cursor-pointer border-b border-b-gray-600"

Datei anzeigen

@ -168,11 +168,11 @@
</div> </div>
<div> <div>
{#if selectedBranch !== "master"} {#if selectedBranch !== "master"}
<Button on:click={createFile} color="alternative" disabled={!selectedPath}>Create File <Button onclick={createFile} color="alternative" disabled={!selectedPath}>Create File
</Button> </Button>
<Button on:click={() => deleteBranch(false)} color="none">Delete Branch</Button> <Button onclick={() => deleteBranch(false)} color="none">Delete Branch</Button>
{:else} {:else}
<Button on:click={createBranch}>Create Branch</Button> <Button onclick={createBranch}>Create Branch</Button>
{/if} {/if}
</div> </div>
</div> </div>
@ -193,7 +193,7 @@
</li> </li>
{/each} {/each}
{:else} {:else}
<Button on:click={newAnnouncement}>Neue Ankündigung</Button> <Button onclick={newAnnouncement}>Neue Ankündigung</Button>
{/if} {/if}
</ul> </ul>
{:catch error} {:catch error}

Datei anzeigen

@ -36,7 +36,7 @@
Mod-Tool Mod-Tool
</span> </span>
</NavBrand> </NavBrand>
<NavHamburger on:click={toggle}/> <NavHamburger onclick={toggle}/>
<NavUl {hidden}> <NavUl {hidden}>
<NavLi href="#/edit">Edit Pages</NavLi> <NavLi href="#/edit">Edit Pages</NavLi>
<NavLi href="#/perms">Permissions</NavLi> <NavLi href="#/perms">Permissions</NavLi>
@ -51,7 +51,7 @@
<Spinner size={16}/> <Spinner size={16}/>
</div> </div>
{:then data} {:then data}
<Button class="fixed bottom-6 right-6 !p-4 z-10 shadow-lg" on:click={() => showAdd = true}> <Button class="fixed bottom-6 right-6 !p-4 z-10 shadow-lg" onclick={() => showAdd = true}>
<PlusOutline/> <PlusOutline/>
</Button> </Button>

Datei anzeigen

@ -155,14 +155,14 @@
<h1>Permissions</h1> <h1>Permissions</h1>
{#each perms.perms as perm} {#each perms.perms as perm}
<Checkbox checked={activePerms.includes(perm)} <Checkbox checked={activePerms.includes(perm)}
on:click={togglePerm(perm)}>{capitalize(perm.toLowerCase())}</Checkbox> onclick={togglePerm(perm)}>{capitalize(perm.toLowerCase())}</Checkbox>
{/each} {/each}
<div class="mt-4"> <div class="mt-4">
<Button disabled={prefixEdit === (player?.prefix.name ?? "") && activePerms === (player?.perms ?? [])} <Button disabled={prefixEdit === (player?.prefix.name ?? "") && activePerms === (player?.perms ?? [])}
on:click={save}>Save onclick={save}>Save
</Button> </Button>
{#if $me != null && $me.perms.includes("ADMINISTRATION")} {#if $me != null && $me.perms.includes("ADMINISTRATION")}
<Button on:click={() => resetPasswordModal = true}> <Button onclick={() => resetPasswordModal = true}>
Reset Password Reset Password
</Button> </Button>
@ -174,10 +174,10 @@
{#snippet footer()} {#snippet footer()}
<Button class="ml-auto mr-4" on:click={resetResetPassword}> <Button class="ml-auto mr-4" onclick={resetResetPassword}>
Cancel Cancel
</Button> </Button>
<Button disabled={resetPassword === "" || resetPassword !== resetPasswordRepeat} on:click={resetPW}> <Button disabled={resetPassword === "" || resetPassword !== resetPasswordRepeat} onclick={resetPW}>
Reset Password Reset Password
</Button> </Button>

Datei anzeigen

@ -84,10 +84,10 @@
<Toolbar class="!bg-gray-900"> <Toolbar class="!bg-gray-900">
{#snippet end()} {#snippet end()}
<ToolbarGroup > <ToolbarGroup >
<ToolbarButton on:click={deletePage}> <ToolbarButton onclick={deletePage}>
Delete Delete
</ToolbarButton> </ToolbarButton>
<ToolbarButton color="primary" on:click={savePage}> <ToolbarButton color="primary" onclick={savePage}>
Save Save
</ToolbarButton> </ToolbarButton>
</ToolbarGroup> </ToolbarGroup>

Datei anzeigen

@ -43,8 +43,6 @@
let member = $state(event.maxTeamMembers); let member = $state(event.maxTeamMembers);
let schemType = $state(event.schemType); let schemType = $state(event.schemType);
let publicOnly = $state(event.publicSchemsOnly); let publicOnly = $state(event.publicSchemsOnly);
let addReferee: {name: string, id: number}[] = [];
let removeReferee: {name: string, id: number}[] = [];
let errorOpen = $state(false); let errorOpen = $state(false);
let error: any = $state(undefined); let error: any = $state(undefined);
@ -69,9 +67,7 @@
endDate.diff(dayjs(event.end)) !== 0 || endDate.diff(dayjs(event.end)) !== 0 ||
member !== event.maxTeamMembers || member !== event.maxTeamMembers ||
schemType != event.schemType || schemType != event.schemType ||
publicOnly !== event.publicSchemsOnly || publicOnly !== event.publicSchemsOnly);
addReferee.length > 0 ||
removeReferee.length > 0);
async function del() { async function del() {
@ -95,8 +91,8 @@
publicSchemsOnly: publicOnly, publicSchemsOnly: publicOnly,
schemType: schemType ?? "null", schemType: schemType ?? "null",
start: startDate, start: startDate,
addReferee: addReferee.map((ref) => ref.id), addReferee: [],
removeReferee: removeReferee.map((ref) => ref.id) removeReferee: []
}; };
try { try {
@ -153,8 +149,8 @@
</div> </div>
<Toggle bind:checked={publicOnly} class="mt-4">Public Schematics Only</Toggle> <Toggle bind:checked={publicOnly} class="mt-4">Public Schematics Only</Toggle>
<div class="flex mt-4"> <div class="flex mt-4">
<Button disabled={!changed} on:click={update}>Update</Button> <Button disabled={!changed} onclick={update}>Update</Button>
<Button class="ml-4" color="red" on:click={() => deleteOpen = true}>Delete</Button> <Button class="ml-4" color="red" onclick={() => deleteOpen = true}>Delete</Button>
</div> </div>
</form> </form>
@ -163,8 +159,8 @@
<Modal bind:open={deleteOpen} outsideclose title="Delete {event.name}?"> <Modal bind:open={deleteOpen} outsideclose title="Delete {event.name}?">
<p>Are you sure you want to delete {event.name}?</p> <p>Are you sure you want to delete {event.name}?</p>
<div class="flex justify-end"> <div class="flex justify-end">
<Button on:click={() => deleteOpen = false}>Cancel</Button> <Button onclick={() => deleteOpen = false}>Cancel</Button>
<Button class="ml-4" color="red" on:click={del}>Delete</Button> <Button class="ml-4" color="red" onclick={del}>Delete</Button>
</div> </div>
</Modal> </Modal>

Datei anzeigen

@ -19,7 +19,7 @@
<script lang="ts"> <script lang="ts">
import {EditOutline, TrashBinOutline} from "flowbite-svelte-icons"; import {EditOutline, TrashBinOutline} from "flowbite-svelte-icons";
import {Button, Modal, Toolbar, ToolbarButton} from "flowbite-svelte"; import {Button, Checkbox, Modal, Toolbar, ToolbarButton} from "flowbite-svelte";
import type {EventFight, ExtendedEvent} from "@type/event.ts"; import type {EventFight, ExtendedEvent} from "@type/event.ts";
import FightEditModal from "./modals/FightEditModal.svelte"; import FightEditModal from "./modals/FightEditModal.svelte";
import {createEventDispatcher} from "svelte"; import {createEventDispatcher} from "svelte";
@ -32,6 +32,8 @@
i: number; i: number;
selected?: boolean; selected?: boolean;
hideEdit?: boolean; hideEdit?: boolean;
select: () => void;
update: () => void;
} }
let { let {
@ -39,29 +41,34 @@
data = $bindable(), data = $bindable(),
i, i,
selected = false, selected = false,
hideEdit = false hideEdit = false,
select,
update,
}: Props = $props(); }: Props = $props();
let deleteOpen = $state(false); let deleteOpen = $state(false);
let editOpen = $state(false); let editOpen = $state(false);
let dispatcher = createEventDispatcher();
function dispatchSelect() { function dispatchSelect() {
setTimeout(() => { setTimeout(() => {
if (!deleteOpen && !editOpen) { if (!deleteOpen && !editOpen) {
dispatcher("select"); select();
} }
}, 1); }, 1);
} }
async function deleteFight() { async function deleteFight() {
await $fightRepo.deleteFight(fight.id); await $fightRepo.deleteFight(fight.id);
dispatcher("update"); update();
} }
let isUneven = $derived(i % 2 === 0);
</script> </script>
<div class="flex h-16 {i % 2 === 0 ? 'bg-gray-800' : ''} mx-4 mt-6 rounded border {selected ? 'border-orange-700' : 'border-gray-700'} p-2 hover:bg-gray-700 transition justify-between shadow-lg cursor-pointer" <div class={{"flex h-16 mx-4 mt-6 rounded border p-2 hover:bg-gray-700 transition justify-between shadow-lg cursor-pointer": true,
"bg-gray-800": isUneven,
"border-orange-700": selected,
"border-gray-700": !selected}}
onclick={dispatchSelect} onkeypress={dispatchSelect} role="checkbox" aria-checked={selected} tabindex="0" onclick={dispatchSelect} onkeypress={dispatchSelect} role="checkbox" aria-checked={selected} tabindex="0"
> >
<div class="flex"> <div class="flex">
@ -99,10 +106,10 @@
</div> </div>
{#if !hideEdit} {#if !hideEdit}
<Toolbar embedded> <Toolbar embedded>
<ToolbarButton on:click={() => editOpen = true}> <ToolbarButton onclick={() => editOpen = true}>
<EditOutline/> <EditOutline/>
</ToolbarButton> </ToolbarButton>
<ToolbarButton color="red" on:click={() => deleteOpen = true}> <ToolbarButton color="red" onclick={() => deleteOpen = true}>
<TrashBinOutline/> <TrashBinOutline/>
</ToolbarButton> </ToolbarButton>
</Toolbar> </Toolbar>
@ -116,7 +123,7 @@
<p class="mb-5"> <p class="mb-5">
Are you sure you want to delete this fight? Are you sure you want to delete this fight?
</p> </p>
<Button color="red" on:click={deleteFight}>Delete Fight</Button> <Button color="red" onclick={deleteFight}>Delete Fight</Button>
<Button color="alternative">Cancel</Button> <Button color="alternative">Cancel</Button>
</div> </div>
</Modal> </Modal>

Datei anzeigen

@ -82,7 +82,7 @@
} else { } else {
groupFights.forEach(fight => selectedFights.add(fight)); groupFights.forEach(fight => selectedFights.add(fight));
} }
selectedFights = selectedFights; selectedFights = new Set(selectedFights);
} }
let deleteOpen = $state(false); let deleteOpen = $state(false);
@ -194,27 +194,27 @@
<div class="pb-28"> <div class="pb-28">
<Toolbar class="mx-4 mt-2 w-fit"> <Toolbar class="mx-4 mt-2 w-fit">
<ToolbarGroup> <ToolbarGroup>
<Checkbox class="ml-2" checked={selectedFights.size === fights.length} on:click={cycleSelect}/> <Checkbox class="ml-2" checked={selectedFights.size === fights.length} onclick={cycleSelect}/>
<Tooltip>Select Upcoming</Tooltip> <Tooltip>Select Upcoming</Tooltip>
</ToolbarGroup> </ToolbarGroup>
<ToolbarGroup> <ToolbarGroup>
<ToolbarButton on:click={() => selectedFights.size > 0 ? changeTimeOpen = true : changeTimeOpen = false}> <ToolbarButton onclick={() => selectedFights.size > 0 ? changeTimeOpen = true : changeTimeOpen = false}>
<CalendarWeekOutline/> <CalendarWeekOutline/>
</ToolbarButton> </ToolbarButton>
<Tooltip>Reschedule Fights</Tooltip> <Tooltip>Reschedule Fights</Tooltip>
<ToolbarButton on:click={() => selectedFights.size > 0 ? spectatePortOpen = true : spectatePortOpen = false} <ToolbarButton onclick={() => selectedFights.size > 0 ? spectatePortOpen = true : spectatePortOpen = false}
disabled={changedTime === undefined}> disabled={changedTime === undefined}>
<ProfileCardOutline/> <ProfileCardOutline/>
</ToolbarButton> </ToolbarButton>
<Tooltip>Change Spectate Port</Tooltip> <Tooltip>Change Spectate Port</Tooltip>
<ToolbarButton on:click={() => selectedFights.size > 0 ? groupChangeOpen = true : groupChangeOpen = false}> <ToolbarButton onclick={() => selectedFights.size > 0 ? groupChangeOpen = true : groupChangeOpen = false}>
<UsersGroupOutline/> <UsersGroupOutline/>
</ToolbarButton> </ToolbarButton>
<Tooltip>Change Group</Tooltip> <Tooltip>Change Group</Tooltip>
</ToolbarGroup> </ToolbarGroup>
<ToolbarGroup> <ToolbarGroup>
<ToolbarButton color="red" <ToolbarButton color="red"
on:click={() => selectedFights.size > 0 ? deleteOpen = true : deleteOpen = false}> onclick={() => selectedFights.size > 0 ? deleteOpen = true : deleteOpen = false}>
<TrashBinOutline/> <TrashBinOutline/>
</ToolbarButton> </ToolbarButton>
<Tooltip>Delete</Tooltip> <Tooltip>Delete</Tooltip>
@ -223,20 +223,21 @@
{#each groupedFights as group} {#each groupedFights as group}
<div class="flex mt-4"> <div class="flex mt-4">
<Checkbox class="ml-2 text-center" checked={group.fights.every(gf => selectedFights.has(gf))} <Checkbox class="ml-2 text-center" checked={group.fights.every(gf => selectedFights.has(gf))}
on:click={() => cycleGroup(group.fights)}/> onclick={() => cycleGroup(group.fights)}/>
<h1 class="ml-4 text-2xl">{group.group ?? "Ungrouped"}</h1> <h1 class="ml-4 text-2xl">{group.group ?? "Ungrouped"}</h1>
</div> </div>
{#each group.fights.sort((a, b) => a.start - b.start) as fight, i (fight.id)} {#each group.fights.sort((a, b) => a.start - b.start) as fight, i (fight.id)}
<FightCard {fight} {i} {data} selected={selectedFights.has(fight)} {@const isSelected = selectedFights.has(fight)}
on:select={() => { <FightCard {fight} {i} {data} selected={isSelected}
select={() => {
if (selectedFights.has(fight)) { if (selectedFights.has(fight)) {
selectedFights.delete(fight); selectedFights.delete(fight);
} else { } else {
selectedFights.add(fight); selectedFights.add(fight);
} }
selectedFights = selectedFights;
}} selectedFights = new Set(selectedFights);
on:update={async () => fights = await $fightRepo.listFights(data.event.id)} }} update={async () => fights = await $fightRepo.listFights(data.event.id)}
/> />
{/each} {/each}
{/each} {/each}
@ -249,8 +250,8 @@
<p>Are you sure you want to delete {selectedFights.size} fights?</p> <p>Are you sure you want to delete {selectedFights.size} fights?</p>
{#snippet footer()} {#snippet footer()}
<Button color="red" class="ml-auto" on:click={deleteFights}>Delete</Button> <Button color="red" class="ml-auto" onclick={deleteFights}>Delete</Button>
<Button on:click={() => deleteOpen = false} color="alternative">Cancel</Button> <Button onclick={() => deleteOpen = false} color="alternative">Cancel</Button>
{/snippet} {/snippet}
</Modal> </Modal>
@ -262,8 +263,8 @@
</div> </div>
{#snippet footer()} {#snippet footer()}
<Button class="ml-auto" on:click={updateSpectatePort}>Change</Button> <Button class="ml-auto" onclick={updateSpectatePort}>Change</Button>
<Button on:click={() => spectatePortOpen = false} color="alternative">Cancel</Button> <Button onclick={() => spectatePortOpen = false} color="alternative">Cancel</Button>
{/snippet} {/snippet}
</Modal> </Modal>
@ -276,8 +277,8 @@
</div> </div>
{#snippet footer()} {#snippet footer()}
<Button class="ml-auto" on:click={updateGroup}>Change</Button> <Button class="ml-auto" onclick={updateGroup}>Change</Button>
<Button on:click={() => groupChangeOpen = false} color="alternative">Cancel</Button> <Button onclick={() => groupChangeOpen = false} color="alternative">Cancel</Button>
{/snippet} {/snippet}
</Modal> </Modal>
@ -295,14 +296,14 @@
:{("0" + deltaTime.minutes()).slice(-2)}</p> :{("0" + deltaTime.minutes()).slice(-2)}</p>
{#snippet footer()} {#snippet footer()}
<Button class="ml-auto" on:click={updateStartTime}>Update</Button> <Button class="ml-auto" onclick={updateStartTime}>Update</Button>
<Button on:click={() => changeTimeOpen = false} color="alternative">Cancel</Button> <Button onclick={() => changeTimeOpen = false} color="alternative">Cancel</Button>
{/snippet} {/snippet}
</Modal> </Modal>
<SpeedDial> <SpeedDial>
<SpeedDialButton name="Add" on:click={() => createOpen = true}> <SpeedDialButton name="Add" onclick={() => createOpen = true}>
<PlusOutline/> <PlusOutline/>
</SpeedDialButton> </SpeedDialButton>
<SpeedDialButton name="Generate" href="#/event/{data.event.id}/generate"> <SpeedDialButton name="Generate" href="#/event/{data.event.id}/generate">

Datei anzeigen

@ -43,6 +43,14 @@
async function addReferee() { async function addReferee() {
if (selectedPlayer) { if (selectedPlayer) {
referees = (await $eventRepo.updateEvent(data.event.id.toString(), { referees = (await $eventRepo.updateEvent(data.event.id.toString(), {
deadline: null,
end: null,
maxTeamMembers: null,
name: null,
publicSchemsOnly: null,
removeReferee: null,
schemType: null,
start: null,
addReferee: [selectedPlayer] addReferee: [selectedPlayer]
})).referees; })).referees;
} }
@ -53,7 +61,15 @@
function removeReferee(id: string) { function removeReferee(id: string) {
return async () => { return async () => {
referees = (await $eventRepo.updateEvent(data.event.id.toString(), { referees = (await $eventRepo.updateEvent(data.event.id.toString(), {
removeReferee: [id] deadline: null,
end: null,
maxTeamMembers: null,
name: null,
publicSchemsOnly: null,
addReferee: null,
schemType: null,
start: null,
removeReferee: [id],
})).referees; })).referees;
} }
} }
@ -68,7 +84,7 @@
{#each referees as referee} {#each referees as referee}
<li class="flex flex-grow justify-between"> <li class="flex flex-grow justify-between">
{referee.name} {referee.name}
<SWButton on:click={removeReferee(referee.uuid)}> <SWButton onclick={removeReferee(referee.uuid)}>
Entfernen Entfernen
</SWButton> </SWButton>
</li> </li>
@ -79,7 +95,7 @@
{/if} {/if}
</ul> </ul>
<Button class="fixed bottom-6 right-6 !p-4 z-10 shadow-lg" on:click={() => showAdd = true}> <Button class="fixed bottom-6 right-6 !p-4 z-10 shadow-lg" onclick={() => showAdd = true}>
<PlusOutline/> <PlusOutline/>
</Button> </Button>
@ -92,8 +108,8 @@
</div> </div>
{#snippet footer()} {#snippet footer()}
<div class="flex flex-grow justify-end"> <div class="flex flex-grow justify-end">
<SWButton on:click={reset} type="gray">Abbrechen</SWButton> <SWButton onclick={reset} type="gray">Abbrechen</SWButton>
<SWButton on:click={addReferee}>Hinzufügen</SWButton> <SWButton onclick={addReferee}>Hinzufügen</SWButton>
</div> </div>
{/snippet} {/snippet}
</SWModal> </SWModal>

Datei anzeigen

@ -102,8 +102,8 @@
</div> </div>
{#snippet footer()} {#snippet footer()}
<Button on:click={create} class="mr-auto" disabled={!canCreate}>Create</Button> <Button onclick={create} class="mr-auto" disabled={!canCreate}>Create</Button>
<Button color="light" on:click={() => open = false}>Cancel</Button> <Button color="light" onclick={() => open = false}>Cancel</Button>
{/snippet} {/snippet}
</Modal> </Modal>

Datei anzeigen

@ -35,12 +35,13 @@
open?: boolean; open?: boolean;
} }
let { fight = $bindable(), data, open = $bindable(false) }: Props = $props(); let { fight = $bindable(), data = $bindable(), open = $bindable(false) }: Props = $props();
let redTeam = $state(fight.redTeam.id.toString()); let redTeam = $state(fight.redTeam.id.toString());
let blueTeam = $state(fight.blueTeam.id.toString()); let blueTeam = $state(fight.blueTeam.id.toString());
let start = $state(dayjs(fight.start).utc(true).toISOString().slice(0, -1)); let start = $state(dayjs(fight.start).utc(true).toISOString().slice(0, -1));
let spectatePort = $state(fight.spectatePort?.toString() ?? null); let spectatePort = $state(fight.spectatePort?.toString() ?? null);
$inspect(spectatePort, fight.spectatePort)
let gamemode = $state(fight.spielmodus); let gamemode = $state(fight.spielmodus);
let map = $state(fight.map); let map = $state(fight.map);
let group = $state(fight.group); let group = $state(fight.group);
@ -62,6 +63,8 @@
start: dayjs(start) start: dayjs(start)
}; };
console.log(update)
$fightRepo.updateFight(fight.id, update) $fightRepo.updateFight(fight.id, update)
.then(value => { .then(value => {
open = false; open = false;
@ -90,8 +93,8 @@
/> />
</div> </div>
<div class="flex"> <div class="flex">
<Button on:click={save}>Save</Button> <Button onclick={save}>Save</Button>
<Button color="light" class="ml-auto" on:click={() => open = false}>Cancel</Button> <Button color="light" class="ml-auto" onclick={() => open = false}>Cancel</Button>
</div> </div>
</Modal> </Modal>

Datei anzeigen

@ -176,7 +176,7 @@
</div> </div>
<div class="flex items-center mr-4"> <div class="flex items-center mr-4">
<Button on:click={() => showAutoGrouping = true}>Automatic Grouping</Button> <Button onclick={() => showAutoGrouping = true}>Automatic Grouping</Button>
</div> </div>
</div> </div>
@ -238,7 +238,7 @@
{/each} {/each}
</div> </div>
<Button class="!p-4 fixed bottom-4 right-4" pill disabled={!generateDisabled} on:click={generateFights}> <Button class="!p-4 fixed bottom-4 right-4" pill disabled={!generateDisabled} onclick={generateFights}>
<PlusOutline/> <PlusOutline/>
</Button> </Button>
@ -248,8 +248,8 @@
{#snippet footer()} {#snippet footer()}
<Button class="ml-auto" on:click={createGroups}>Create</Button> <Button class="ml-auto" onclick={createGroups}>Create</Button>
<Button color="alternative" on:click={() => showAutoGrouping = false}>Cancel</Button> <Button color="alternative" onclick={() => showAutoGrouping = false}>Cancel</Button>
{/snippet} {/snippet}
</Modal> </Modal>

Datei anzeigen

@ -90,8 +90,8 @@
</div> </div>
{#snippet footer()} {#snippet footer()}
<Button color="alternative" on:click={() => open = false} class="mr-auto">Cancel</Button> <Button color="alternative" onclick={() => open = false} class="mr-auto">Cancel</Button>
<Button on:click={createEvent} disabled={!canSubmit}>Create</Button> <Button onclick={createEvent} disabled={!canSubmit}>Create</Button>
{/snippet} {/snippet}
</Modal> </Modal>

Datei anzeigen

@ -130,7 +130,7 @@
</tr> </tr>
{/if} {/if}
{#each pagedSchematics as schem (schem.id)} {#each pagedSchematics as schem (schem.id)}
<SchematicListTile schem={schem} players={schematics.players} on:click={schemListClick(schem.type == null, schem.id)} /> <SchematicListTile schem={schem} players={schematics.players} onclick={schemListClick(schem.type == null, schem.id)} />
{/each} {/each}
</tbody> </tbody>
</table> </table>

Datei anzeigen

@ -31,15 +31,15 @@ export interface CreateEvent {
} }
export interface UpdateEvent { export interface UpdateEvent {
name?: string; name: string | null;
start?: Dayjs; start: Dayjs | null;
end?: Dayjs; end: Dayjs | null;
deadline?: Dayjs; deadline: Dayjs | null;
maxTeamMembers?: number; maxTeamMembers: number | null;
schemType?: string | null; schemType: string | null;
publicSchemsOnly?: boolean; publicSchemsOnly: boolean | null;
addReferee?: string[]; addReferee: string[] | null;
removeReferee?: string[]; removeReferee: string[] | null;
} }
export class EventRepo { export class EventRepo {

Datei anzeigen

@ -80,7 +80,7 @@ export class FightRepo {
blueTeam: fight.blueTeam, blueTeam: fight.blueTeam,
redTeam: fight.redTeam, redTeam: fight.redTeam,
start: fight.start?.valueOf(), start: fight.start?.valueOf(),
spectatePort: fight.spectatePort ?? 0, spectatePort: fight.spectatePort,
group: fight.group, group: fight.group,
}), }),
}).then(value => value.json()) }).then(value => value.json())

Datei anzeigen

@ -29,7 +29,7 @@ import {pageRepo} from "@repo/page.ts";
import {dataRepo} from "@repo/data.ts"; import {dataRepo} from "@repo/data.ts";
export const schemTypes = cached<SchematicType[]>([], () => export const schemTypes = cached<SchematicType[]>([], () =>
fetchWithToken(get(tokenStore), "/data/schematicTypes") fetchWithToken(get(tokenStore), "/data/admin/schematicTypes")
.then(res => res.json())); .then(res => res.json()));
export const players = cached<Player[]>([], async () => { export const players = cached<Player[]>([], async () => {

Datei anzeigen

@ -18,19 +18,17 @@
--> -->
<script lang="ts"> <script lang="ts">
import { createBubbler } from 'svelte/legacy';
const bubble = createBubbler();
import "@styles/button.css" import "@styles/button.css"
interface Props { interface Props {
type?: "primary" | "ghost" | "gray"; type?: "primary" | "ghost" | "gray";
children?: import('svelte').Snippet; children: import('svelte').Snippet;
} onclick: () => void;
}
let { type = "primary", children }: Props = $props(); let { type = "primary", onclick, children }: Props = $props();
</script> </script>
<button onclick={bubble('click')} class="btn" class:btn-gray={type === "gray"} class:btn-text={type === "ghost"}> <button onclick={onclick} class="btn" class:btn-gray={type === "gray"} class:btn-text={type === "ghost"}>
{@render children?.()} {@render children()}
</button> </button>

Datei anzeigen

@ -18,28 +18,29 @@
--> -->
<script lang="ts"> <script lang="ts">
import { run, createBubbler, stopPropagation } from 'svelte/legacy'; import {onMount} from "svelte";
import {stopPropagation} from "@components/util.ts";
const bubble = createBubbler();
import {createEventDispatcher, onMount} from "svelte";
interface Props { interface Props {
title: string; title: string;
open: boolean; open: boolean;
children?: import('svelte').Snippet; children?: import('svelte').Snippet;
footer?: import('svelte').Snippet; footer?: import('svelte').Snippet;
onclose?: () => void;
onclick?: () => void;
} }
let { let {
title, title,
open = $bindable(), open = $bindable(),
children, children,
footer footer,
onclose = () => {},
onclick = () => {}
}: Props = $props(); }: Props = $props();
let internalOpen = $state(open); let internalOpen = $state(open);
const dispatch = createEventDispatcher();
let dialog: HTMLDialogElement = $state(); let dialog: HTMLDialogElement = $state();
@ -53,52 +54,30 @@
function close() { function close() {
open = false; open = false;
internalOpen = false; internalOpen = false;
dispatch("close"); onclose()
} }
run(() => {
if (open && !internalOpen) { $effect(() => {
dialog.showModal(); if (open && !internalOpen) {
internalOpen = true; dialog.showModal();
} else if (!open && internalOpen) { internalOpen = true;
dialog.close(); } else if (!open && internalOpen) {
internalOpen = false; dialog.close();
} internalOpen = false;
}); }
})
</script> </script>
<dialog bind:this={dialog} onclose={close} oncancel={close} onclick={() => dialog.close()} aria-hidden="true"> <dialog bind:this={dialog} onclose={close} onclick={(e) => dialog.close()} aria-hidden="true" class="max-h-full max-w-md w-full rounded-lg shadow-lg dark:bg-neutral-800 dark:text-neutral-100">
<div onclick={stopPropagation(bubble('click'))} aria-hidden="true"> <div onclick={stopPropagation(onclick)} aria-hidden="true">
<div class="spaced bordered"> <div class="p-6 border-b border-neutral-200 dark:border-neutral-700">
<h1>{title}</h1> <h1 class="text-4xl font-bold">{title}</h1>
</div> </div>
<div class="spaced main bordered"> <div class="p-6 main border-b border-neutral-200 dark:border-neutral-700">
{@render children?.()} {@render children?.()}
</div> </div>
<div class="footer spaced" onclick={() => dialog.close()} aria-hidden="true"> <div class="flex mx-4 my-2 p-6" onclick={() => dialog.close()} aria-hidden="true">
{@render footer?.()} {@render footer?.()}
</div> </div>
</div> </div>
</dialog> </dialog>
<style lang="scss">
h1 {
@apply text-4xl font-bold;
}
dialog {
@apply max-h-full max-w-md w-full rounded-lg shadow-lg
dark:bg-neutral-800 dark:text-neutral-100;
}
.spaced {
@apply p-6;
}
.bordered {
@apply border-b border-neutral-200 dark:border-neutral-700;
}
.footer {
@apply flex mx-4 my-2;
}
</style>

Datei anzeigen

@ -23,4 +23,11 @@ export function window<T>(arr: T[], len: number): T[][] {
result.push(arr.slice(i, i + len)); result.push(arr.slice(i, i + len));
} }
return result; return result;
}
export function stopPropagation(a: any) {
return (e: Event) => {
e.stopPropagation();
a(e);
};
} }

Datei anzeigen

@ -0,0 +1,22 @@
---
title: Adventskalender Schems
key: adventskalender-schems
description: Gesucht werden Schematics für den Adventskalender 2024.
created: 2024-10-13
tags:
- offtopic
---
**Hallo Liebe Community,**
auch dieses Jahr möchten wir einen Adventskalender organisieren. Dafür sind wir nach wie vor auf der Suche nach Technik welch wir hinter den Türchen verstecken können. Es werden keine Fertige MWGs, WS, WGs oder AS gesucht. sondern nur Technik. Es ist egal ob es sich dabei über Verteidigungs- oder Angriffstechnik handelt. (Schilde, Missels, Kanonen etc..)
Schems von Spielern welch angenommen werden bekommen nach dem Adventskalender automatisch alle Schems zur Verfügung.
Ihr könnt die Schematics entweder über unsere Discordfunktion im Bereich Support mit dem Raster Questions einreichen, oder bei **YoyoNow** persönlich abgeben. Idealerweise über Discord oder per private Nachricht auf dem Minecraftserver.
Wir benötigen diese Schems bis zum **1.11.2024** um noch Zeit zu haben diese zu Prüfen und zu Testen. Es wäre sehr schade, wenn wir auf Grund fehlender Schems dieses Jahr keinen Adventskalender zustande bekommen und bedanke mich schon im voraus für Eure mithilfe.
Viele Grüße
Steamwar Serverteam

Datei anzeigen

@ -0,0 +1,44 @@
---
title: HalloweenFN Kampfplan Abstimmung
key: halloween-fn-kampfplan-abstimmung
description: Abstimmung über den Kampfplan für die Halloween Fight Night.
created: 2024-10-23
tags:
- event
- wargear
image: ../../../images/SwFightNightLogoHalloween.png
---
Ahoi Community.
Es gab mehr Anmeldungen am Event als erwartet. Dies führt über eine sehr lange Laufzeit der Kämpfe. Hier werden auch beide offene Arenen benutzt.
wie im DC Bereich angekündigt eine Auswahl an Optionen vom Kampfplan.
## Option 1: All vs All
Geschätzte maximale Dauer 11 Stunden. auf zwei Tage verteilt
- Samstag 26.10.2024 und Sonntag 27.10.2024 Stimme 1
- Samstag 26.10.2024 und Samstag 2.11.2024 Stimme 2
## Option 2 Gruppenphase + Kleines KO Halbfinale, Platz 3, Finale
Geschätzte maximale Dauer 5 Stunden Gruppe + 1 Stunde KO
- Samstag 26.10.2024 und Sonntag 27.10.2024 Stimme 3
- Samstag 26.10.2024 und Sonntag 2.11.2024 Stimme 4
- Samstag 26.10.2024 In einem Stück Stimme 5
## Option 3 Gruppenphase + großes KO Viertelfinale, Halbfinale, Platz 3, Finale
Geschätzte maximale Dauer 5 Stunden Gruppe + 2 Stunden KO
- Samstag 26.10.2024 und Sonntag 27.10.2024 Stimme 6
- Samstag 26.10.2024 und Sonntag 2.11.2024 Stimme 7
Die Kampftage würden um jeweils 17 Uhr starten.
Beachtet, bei der geschätzten Dauer, dass es durchaus die Möglichkeit gibt Fights vorzuschieben um die Dauer zu reduzieren. Die Kämpfe wurde mit max. 30 Min versehen.
Ich Bitte nur Spieler abstimmen zu lassen welch am Event Teilnehmen. Vielen Dank.

Datei anzeigen

@ -0,0 +1,64 @@
---
title: Halloween Fight Night
key: halloween-fight-night
description: Halloween Event im Wargear Modus.
created: 2024-08-31
tags:
- event
- wargear
image: ../../../images/SwFightNightLogoHalloween.png
---
**Liebe Community,**
die Tage werden langsam kürzer und die Nächte länger. Es geht auf dem Herbst zu und erinnert
daran, dass das Jahr wieder halb vorbei ist. Wie im letzten Jahr wird wieder ein Halloween Event
veranstaltet. Dieses Mal im Spielmodus **Wargear**. Es wird ein Wargear Event sein ohne Automatiks,
zusätzlich wird es mit einem Designcontest begleitet.
- Das Event wird am **26.10.2024** Stattfinden
- Standard Wargear Regelwerk ohne Automatische Kanonen
- Design Regel: **Halloween**
- Anmelde + Einsendeschluss **21.10.2024**
- Ernennung des Teamvertreter **21.10.2024**
- Hot fixes bis **24.10.2024** möglich
Neben dem eigentlichen Turnier wird das Außendesign bewertet. Die Bewertung des Außendedigns
wird zu **70% Das SW Builderteam** übernehmen und **30% die Userbewertung**. Die prozentuale
Bewertung soll dazu dienen, dass große Teams Ihr eigenes Design nicht hoch puschen können.
---
## Fight Bewertung
- Klassisches Alle vs Alle Turnier
- Sieg 1 Punkt
- Niederlage 0 Punkte
- Kampfleiter kann TechKO ermitteln
- Bei unentschieden (Beide WGs besitzen noch funktionsfähige Kanonen), wird das WG welch im besseren zustand ist zum Sieger ernannt.
## Design Bewertung
- **Userbewertung (30%)** wird über den Discord Community Server von SW organisiert. (Bilder vom Außendesign werden gepostet und per Abstimmung ausgelost)
---
- **Builderbewertung (70%)** läuft nach folgende Kriterien ab.
- Form des WGs
- Farbgestaltung
- Muster
- Thematisierung: Thema Halloween / Gruse
---
Es wird also 3 Sieges- Plätze geben welch wie Folgt ermittelt wird.
- Gesamtsieger: Höchste Fight Platzierung und Design Platzierung im Durchschnitt
- FN- Sieger : Höchste Fight Platzierung
- Designsieger: Bestes Design
**Das Wargeardesign vom Gesamtsieger wird bis zum nächsten Halloween in der Lobby ausgestellt.**
Wir wünschen alle Teilnehmenden Teams viel Spaß und Erfolg. Natürlich auch
**HAPPY HALLOWEEN**

Datei anzeigen

@ -0,0 +1,99 @@
---
title: Halloween Fight Night Abschluss
key: halloween-fn-abschluss
description: Abschluss des Halloween Fight Night Events.
created: 2024-11-11
tags:
- event
- wargear
image: ../../../images/SwFightNightLogoHalloween.png
---
**Geehrte Community.**
die Userbewertungen, Builderbwertungen und der Kampftag liegen schon eine weile zurück und die Auswertung wurde abgeschlossen.
## Builderbewertung Design:
1. GG
2. AD
3. GP
4. Hlcy
5. FK
6. WT
7. LKT
8. DFD
9. WF
10. Ouro
## Userbewertung Design:
1. GG
2. GP
3. Hlcy
4. FK
5. WT
6. AD
7. DFD
8. LKT
9. WF
10. Ouro
## Zusammenrechnung.
Die Punkte wurden wie folgt vergeben. Sowohl Designplatz als auch Fightplatz
1. Platz 10 Punkte
2. Platz 9 Punkte
3. Platz 8 Punkte
4. Platz 7 Punkte
5. Platz 6 Punkte
6. Platz 5 Punkte
7. Platz 4 Punkte
8. Platz 3 Punkte
9. Platz 2 Punkte
10. Platz 1 Punkt
(Builderbwertung Punktzahl * 7) + (Userbewertung Punktzahl *3)
## Designgesamtergebnis
| Platz | Team | Punkte |
|-------|----------------------|--------|
| 1 | GG | 100 |
| 2 | GP | 83 |
| 3 | AD | 78 |
| 4 | Hlcy | 73 |
| 5 | FK | 63 |
| 6 | WT | 53 |
| 7 | LKT | 37 |
| 8 | DFD | 33 |
| 9 | WF | 20 |#
| 10 | Ouro (Publicwargear) | 10 |
Somit gewinnt GG den Designcontest
## Gesamtsieger
Designpunkte + (Kampfplatzierung * 100) : 2 Bei gleicher Punktzahl erhält das Team welch im Durchschnitt der 3 Bewertungen besser abgeschlossen hat einen extra Punkt. Teams welch trotz Anmeldung nicht anwesend waren bekommen alle Punkte abgezogen.
| Platz | Team | Punkte |
|-------|--------------|--------|
| 1 | GP | 91,5 |
| 2 | GG | 90 |
| 3 | Hlcy | 81,5 |
| 4 | AD | 64 |
| 5 | FK | 57,5 |
| 6 | WT | 56,5 |
| 7 | DFD | 51,5 |
| 8 | LKT | 48,5 |
| 9 | WF | 30 |
| 10 | Ouro | 0 |
Somit ist **GurkenParade** der Sieger des Events.
In den kommenden Tagen wird mit GP Rücksprache gehalten um Ihr EventWG zu Modifizieren sodass es auf der Lobby ausgestellt werden kann. Wir bedanken uns für die rege Teilnahme und wünschen weiterhin viel Spaß bei unseren kommenden Events.
**Liebe Grüße**
Steamwar Team

Datei anzeigen

@ -0,0 +1,85 @@
---
title: HalloweenFN Kampfplan
key: halloween-fn-kampfplan
description: Der Kampfplan für die Halloween Fight Night.
created: 2024-10-25
tags:
- event
- wargear
image: ../../../images/SwFightNightLogoHalloween.png
---
Info: 2 Gruppen. Kampftag 26.10.2024
## Gruppenphase
| Gruppe A | Punkte | Gruppe B | Punkte |
|----------|--------|----------|--------|
| GP | 4 | Hlcy | 4 |
| DFD | 3 | GG | 3 |
| LKT | 2 | WT | 2 |
| FK | 1 | AD | 1 |
| WF | 0 | Our | 0 |
## Kampfplan Gruppe A
| Begegnung | Zeit | Ergebnis |
|------------|-------|----------|
| LKT vs GP | 17:00 | GP |
| FK vs WF | 17:30 | FK |
| DFD vs GP | 18:00 | GP |
| WF vs LKT | 18:30 | LKT |
| FK vs DFD | 19:00 | DFD |
| WF vs GP | 19:30 | GP |
| LKT vs DFD | 20:00 | DFD |
| GP vs FK | 20:30 | GP |
| WF vs DFD | 21:00 | DFD |
| LKT vs FK | 21:30 | LKT |
## Kampfplan Gruppe B
| Begegnung | Zeit | Ergebnis |
|--------------|-------|----------|
| GG vs WT | 17:15 | GG |
| AD vs Ouro | 17:45 | AD |
| GG vs Hlcy | 18:15 | Hlcy |
| AD vs WT | 18:45 | WT |
| Hlcy vs Ouro | 19:15 | Hlcy |
| AD vs GG | 19:45 | GG |
| WT vs Hlcy | 20:15 | Hlcy |
| Ouro vs GG | 20:45 | GG |
| AD vs Hlcy | 21:15 | Hlcy |
| Ouro vs WT | 21:45 | WT |
## KO Phase.
### Erste beiden einer Gruppe kommen weiter.
| Begegnung | Zeit | Ergebnis |
|-------------|-------|----------|
| GP vs GG | 22:00 | GP |
| Hlcy vs DFD | 22:15 | Hlcy |
| GG vs DFD | 22:30 | GG |
| GP vs Hlcy | 23:15 | GP |
## Endergebnis Fight Tag
1. GP
2. Hlcy
3. GG
## Endergebnis Design Contest
1. GG
2. GP
3. AD
4. Hlcy
5. FK
6. WT
7. DFD
8. LKT
9. WF
10. Ouro
# Gesamtsieger
**GP**

Datei anzeigen

@ -0,0 +1,17 @@
---
title: Neujahrsevent 2025 Eventplan
key: Neujahrsevent-2025-eventplan
description: Der Kampfplan für das Neujahrsevent 2025.
created: 2025-01-01
tags:
- event
- microwargear
---
# Gruppenphase
<group-table data-event="64"> </group-table>
## Kampfplan
<fight-table data-event="64" data-group="Gruppe 1"> </fight-table>

Datei anzeigen

@ -0,0 +1,18 @@
---
title: Schneeballschlacht Kampfplan
key: schneeballschlacht-eventplan
description: Der Kampfplan für die Schneeballschlacht.
created: 2024-12-21
tags:
- event
- miniwargear
image: ../../../images/SchneeballschlachtMWG.png
---
# Gruppenphase
<group-table data-event="65"> </group-table>
## Kampfplan
<fight-table data-event="65" data-group="Gruppe 1"> </fight-table>

Datei anzeigen

@ -0,0 +1,38 @@
---
title: Schneeballschlacht
key: schneeballschlacht
description: Die Schneeballschlacht auf SteamWar.
created: 2024-11-17
tags:
- event
- miniwargear
image: ../../../images/SchneeballschlachtMWG.png
---
**Ahoi Liebe Community,**
Die Tage werden kürzer und kälter, es geht auf die weiße Jahreszeit zu. Wenn der erste Schnee liegt, wird es Zeit, sich mit Mütze und Handschuhen zu bewaffnen und nach draußen zu eilen. Auch auf SteamWar wird dieses Jahr eine Schneeballschlacht stattfinden, im Modus MiniWarGear. Das Event wird, wie auch schon das Halloween-Event, von einer Community-Abstimmung begleitet, Das MWG-Regelwerk wurde mit einigen zusätzlichen Regeln erweitert.
- Das Event wird am **22.12.2024** stattfinden
- Einsendeschluss **18.12.2024**, Hotfixes dürfen bis zum **20.12.2024** Eingesendet werden
- Design-Regel: **Weihnachtliches/Winterliches Design**
## Regeln:
- Regelwerk: **MiniWarGear**, ohne MGs, 120 TNT trotzdem erlaubt
- **Weißer Trockenbeton**/**White Concrete Powder** darf zum Gegner geschossen und/oder geboosted werden, beginnend ab der Ausfahrzeit
- Solche „Schneeballkanonen“ zählen nicht zum Kanonenlimit und dürfen vorbeladen sein, solange sie keine Projektile schießen können
- Schneeballkanonen dürfen Wasser für ihre Treibladungen benutzen
- Der Turnieraufbau ist wie folgt:
- Alle 20 min Start, jeweils zwei Fights je 10 min versetzt
- Struktur: Ranglistenturnier (Gruppenphase, in KO-Phase wird jeder Platz (1, 2, 3, 4, 5, 6, …) umkämpft
## Die beste „Schneeballkanone“ wird per Uservoting wie folgt besimmt
- Jedes Team muss am Tag des Turnieres (z.B. nach Ende der Fights) Bild/Videomaterial von ihrer Schneeballkanone per Discord an Zent4rus oder zSalos schicken, diese werden danach unter einem Thread zur Abstimmung veröffentlicht
- Die Darstellung der Schneeballkanone (mit/ohne Techhider, mit/ohne MWG außen rum) obliegt den Teams selbst
- Sieger von bester Schneeballkanone wird durch Uservote bestimmt (ähnlich wie bei WG – Designcontest)
- Die Abstimmung endet drei Tage nach Veröffentlichung der Abstimmung
Der Gesamtsieger wird mit folgender Formel bestimmt: 0,66 * Fightplatzierung + 0,33 * Platzierung Uservoting, bei Gleichstand bestimmt die Fightplatzierung
**Wir wünschen allen teilnehmenden Teams viel Erfolg!**

Datei anzeigen

@ -146,7 +146,8 @@
"winner": "Sieger", "winner": "Sieger",
"notPlayed": "Nicht gespielt", "notPlayed": "Nicht gespielt",
"draw": "Unentschieden", "draw": "Unentschieden",
"points": "Punkte" "points": "Punkte",
"team": "Team"
} }
}, },
"blog": { "blog": {

Binäre Datei nicht angezeigt.

Nachher

Breite:  |  Höhe:  |  Größe: 387 KiB

Binäre Datei nicht angezeigt.

Nachher

Breite:  |  Höhe:  |  Größe: 83 KiB

Datei anzeigen

@ -105,48 +105,48 @@ const ogImage = await getImage({
<Content/> <Content/>
<script> <script>
import FightTable from "@components/FightTable.svelte"; import FightTable from "@components/FightTable.svelte";
// @ts-expect-error Import Schenanigans
import {get} from "svelte/store"; import {get} from "svelte/store";
import GroupTable from "@components/GroupTable.svelte"; import GroupTable from "@components/GroupTable.svelte";
import {eventRepo} from "../../components/repo/event"; import {eventRepo} from "../../components/repo/event";
import type {ExtendedEvent} from "@type/event"; import type {ExtendedEvent} from "@type/event";
import {mount} from "svelte";
const eventMounts: Map<string, ((ev: ExtendedEvent) => void)[]> = new Map(); const eventMounts: Map<string, ((ev: ExtendedEvent) => void)[]> = new Map();
class FightTableElement extends HTMLElement { class FightTableElement extends HTMLElement {
connectedCallback(): void { connectedCallback(): void {
if (!eventMounts.has(this.dataset["event"])) { if (!eventMounts.has(this.dataset["event"]!)) {
eventMounts.set(this.dataset["event"], []); eventMounts.set(this.dataset["event"]!, []);
} }
const rows = Number.parseInt(this.dataset["rows"]); const rows = Number.parseInt(this.dataset["rows"]!);
eventMounts.get(this.dataset["event"]).push(ev => { eventMounts.get(this.dataset["event"]!)!.push(ev => {
new FightTable({ mount(FightTable, {
target: this, target: this,
props: { props: {
event: ev, event: ev,
group: this.dataset["group"], group: this.dataset["group"],
rows: !isNaN(rows) ? rows : 1, rows: !isNaN(rows) ? rows : 1,
}, },
}); });
}); });
} }
} }
class GroupTableElement extends HTMLElement { class GroupTableElement extends HTMLElement {
connectedCallback(): void { connectedCallback(): void {
if (!eventMounts.has(this.dataset["event"])) { if (!eventMounts.has(this.dataset["event"]!)) {
eventMounts.set(this.dataset["event"], []); eventMounts.set(this.dataset["event"]!, []);
} }
const rows = Number.parseInt(this.dataset["rows"]); const rows = Number.parseInt(this.dataset["rows"]!);
eventMounts.get(this.dataset["event"]).push(ev => { eventMounts.get(this.dataset["event"]!)!.push(ev => {
new GroupTable({ mount(GroupTable, {
target: this, target: this,
props: { props: {
event: ev, event: ev,
group: this.dataset["group"], group: this.dataset["group"],
rows: !isNaN(rows) ? rows : 1, rows: !isNaN(rows) ? rows : 1,
}, },
}); });
}); });
} }
} }
@ -157,7 +157,7 @@ const ogImage = await getImage({
function mountEvent() { function mountEvent() {
for (const key of eventMounts.keys()) { for (const key of eventMounts.keys()) {
get(eventRepo).getEvent(key).then(ev => { get(eventRepo).getEvent(key).then(ev => {
for (const mount of eventMounts.get(key)) { for (const mount of eventMounts.get(key)!) {
mount(ev); mount(ev);
} }
}); });

5
src/pages/discord.astro Normale Datei
Datei anzeigen

@ -0,0 +1,5 @@
---
import Redirect from "../layouts/Redirect.astro";
---
<Redirect url="https://discord.gg/prFBhCe4Rt" />

5
src/pages/youtube.astro Normale Datei
Datei anzeigen

@ -0,0 +1,5 @@
---
import Redirect from "../layouts/Redirect.astro";
---
<Redirect url="https://www.youtube.com/channel/UCCLzHkbVfs6TQh3dskWDGgQ" />

Datei anzeigen

@ -18,7 +18,7 @@
*/ */
table { table {
@apply w-full rounded-2xl shadow-lg overflow-clip; @apply w-full overflow-clip;
:not(:has([data-no-head])) { :not(:has([data-no-head])) {
} }