Commits vergleichen

..

1 Commits

Autor SHA1 Nachricht Datum
cb65e96165 Update Backend
Alle Prüfungen waren erfolgreich
SteamWarCI Build successful
2024-11-23 13:28:33 +01:00
23 geänderte Dateien mit 493 neuen und 310 gelöschten Zeilen

Datei anzeigen

@ -15,6 +15,7 @@ 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",

Datei-Diff unterdrückt, da er zu groß ist Diff laden

Datei anzeigen

@ -23,21 +23,17 @@
import UserInfo from "./dashboard/UserInfo.svelte"; import UserInfo from "./dashboard/UserInfo.svelte";
import {dataRepo} from "@repo/data.ts"; import {dataRepo} from "@repo/data.ts";
import {schemRepo} from "@repo/schem.ts"; import {schemRepo} from "@repo/schem.ts";
import SWPaginator from "@components/styled/SWPaginator.svelte";
import UploadModal from "@components/dashboard/UploadModal.svelte";
import SWButton from "@components/styled/SWButton.svelte";
let userFetch = getUser(); let userFetch = getUser();
let schematicFetch = getSchematics();
function getUser() { function getUser() {
return $dataRepo.getMe() return $dataRepo.getMe()
} }
function getSchematics() { let uploadOpen = false;
return $schemRepo.getRootSchematicList()
}
function getSchematic(id: number) {
return $schemRepo.getSchematicList(id)
}
</script> </script>
{#await userFetch} {#await userFetch}
@ -45,16 +41,15 @@
{:then user} {:then user}
<UserInfo {user} /> <UserInfo {user} />
<hr> <hr>
<div>
{#await schematicFetch} <div class="flex flex-col justify-center">
<p>{t("status.loading")}</p> <SWButton on:click={() => uploadOpen = true}>
{:then schematics} {t("dashboard.schematic.upload")}
<SchematicList {schematics} {user} on:reset={() => schematicFetch = getSchematics()} on:to={(e) => schematicFetch = getSchematic(e.detail.id) } /> </SWButton>
{:catch error}
<p>error: {error.message}</p>
{/await}
</div> </div>
{:catch error} {:catch error}
<p>error: {error.message}</p> <p>error: {error.message}</p>
{/await} {/await}
<UploadModal bind:open={uploadOpen} on:refresh />

Datei anzeigen

@ -33,13 +33,6 @@
export let group: string | null = ""; export let group: string | null = "";
export let groupSearch = ""; export let groupSearch = "";
$: selectPlayers = $players.map(player => {
return {
name: player.name,
value: player.id.toString()
};
}).sort((a, b) => a.name.localeCompare(b.name));
$: selectableTeams = teams.map(team => { $: selectableTeams = teams.map(team => {
return { return {
name: team.name, name: team.name,

Datei anzeigen

@ -32,8 +32,8 @@
$: lowerCaseSearch = search.toLowerCase(); $: lowerCaseSearch = search.toLowerCase();
$: filteredPlayers = $players.filter(value => value.name.toLowerCase().includes(lowerCaseSearch)); $: filteredPlayers = $players.filter(value => value.name.toLowerCase().includes(lowerCaseSearch));
let selectedPlayer: number | null = null; let selectedPlayer: string | null = null;
$: player = $players.find(value => value.id === selectedPlayer); $: player = $players.find(value => value.uuid === selectedPlayer);
let playerPerms = loadPlayer(selectedPlayer); let playerPerms = loadPlayer(selectedPlayer);
$: playerPerms = loadPlayer(selectedPlayer); $: playerPerms = loadPlayer(selectedPlayer);
@ -44,7 +44,7 @@
let resetPassword = ""; let resetPassword = "";
let resetPasswordRepeat = ""; let resetPasswordRepeat = "";
function loadPlayer(id: number | null) { function loadPlayer(id: string | null) {
if (!id) { if (!id) {
return; return;
} }
@ -122,10 +122,10 @@
</div> </div>
{#if filteredPlayers.length < 100} {#if filteredPlayers.length < 100}
<ul class="flex-1 overflow-scroll"> <ul class="flex-1 overflow-scroll">
{#each filteredPlayers as player (player.id)} {#each filteredPlayers as player (player.uuid)}
<li class="p-4 transition-colors hover:bg-gray-700 cursor-pointer" <li class="p-4 transition-colors hover:bg-gray-700 cursor-pointer"
class:text-orange-500={player.id === selectedPlayer} class:text-orange-500={player.uuid === selectedPlayer}
on:click|preventDefault={() => selectedPlayer = player.id}> on:click|preventDefault={() => selectedPlayer = player.uuid}>
{player.name} {player.name}
</li> </li>
{/each} {/each}

Datei anzeigen

@ -96,7 +96,7 @@
$: selectPlayers = $players.map(player => { $: selectPlayers = $players.map(player => {
return { return {
name: player.name, name: player.name,
value: player.id.toString() value: player.uuid
}; };
}).sort((a, b) => a.name.localeCompare(b.name)); }).sort((a, b) => a.name.localeCompare(b.name));
let spectatePort = ""; let spectatePort = "";

Datei anzeigen

@ -39,14 +39,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(), {
addReferee: [parseInt(selectedPlayer)] addReferee: [selectedPlayer]
})).referees; })).referees;
} }
reset(); reset();
} }
function removeReferee(id: number) { 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] removeReferee: [id]
@ -64,7 +64,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.id)}> <SWButton on:click={removeReferee(referee.uuid)}>
Entfernen Entfernen
</SWButton> </SWButton>
</li> </li>
@ -83,7 +83,7 @@
<div class="flex flex-grow justify-center h-80"> <div class="flex flex-grow justify-center h-80">
<div> <div>
<TypeAheadSearch bind:searchValue bind:selected={selectedPlayer} <TypeAheadSearch bind:searchValue bind:selected={selectedPlayer}
items={$players.map(v => ({ name: v.name, value: v.id.toString() }))}/> items={$players.map(v => ({ name: v.name, value: v.uuid }))}/>
</div> </div>
</div> </div>
<div slot="footer" class="flex flex-grow justify-end"> <div slot="footer" class="flex flex-grow justify-end">

Datei anzeigen

@ -40,7 +40,6 @@
export let schematics: SchematicList; export let schematics: SchematicList;
export let user: Player; export let user: Player;
let uploadOpen = false;
let infoModalId: number | null = null; let infoModalId: number | null = null;
function schemListClick(isDir: boolean, id: number) { function schemListClick(isDir: boolean, id: number) {
@ -77,11 +76,6 @@
</BreadcrumbItem> </BreadcrumbItem>
{/each} {/each}
</Breadcrumb> </Breadcrumb>
<div class="flex flex-col justify-center">
<SWButton on:click={() => uploadOpen = true}>
{t("dashboard.schematic.upload")}
</SWButton>
</div>
</div> </div>
<table> <table>
<tbody> <tbody>
@ -133,8 +127,6 @@
<SWPaginator bind:page maxPage={maxPage} /> <SWPaginator bind:page maxPage={maxPage} />
<UploadModal bind:open={uploadOpen} on:refresh />
{#if infoModalId !== null} {#if infoModalId !== null}
<SchematicInfo schematicId={infoModalId} {user} on:reset={() => infoModalId = null} /> <SchematicInfo schematicId={infoModalId} {user} on:reset={() => infoModalId = null} />
{/if} {/if}

Datei anzeigen

@ -38,8 +38,8 @@ export interface UpdateEvent {
maxTeamMembers?: number; maxTeamMembers?: number;
schemType?: string | null; schemType?: string | null;
publicSchemsOnly?: boolean; publicSchemsOnly?: boolean;
addReferee?: number[]; addReferee?: string[];
removeReferee?: number[]; removeReferee?: string[];
} }
export class EventRepo { export class EventRepo {

Datei anzeigen

@ -36,11 +36,11 @@ export class PermsRepo {
} }
} }
public async getPerms(userId: number): Promise<UserPerms> { public async getPerms(userId: string): Promise<UserPerms> {
return await fetchWithToken(this.token, `/perms/user/${userId}`).then(value => value.json()).then(UserPermsSchema.parse); return await fetchWithToken(this.token, `/perms/user/${userId}`).then(value => value.json()).then(UserPermsSchema.parse);
} }
public async setPrefix(userId: number, prefix: string): Promise<void> { public async setPrefix(userId: string, prefix: string): Promise<void> {
const res = await fetchWithToken(this.token, `/perms/user/${userId}/prefix/${prefix}`, { const res = await fetchWithToken(this.token, `/perms/user/${userId}/prefix/${prefix}`, {
method: "PUT", method: "PUT",
}); });
@ -50,7 +50,7 @@ export class PermsRepo {
} }
} }
public async addPerm(userId: number, perm: string): Promise<void> { public async addPerm(userId: string, perm: string): Promise<void> {
const res = await fetchWithToken(this.token, `/perms/user/${userId}/${perm}`, { const res = await fetchWithToken(this.token, `/perms/user/${userId}/${perm}`, {
method: "PUT", method: "PUT",
}); });
@ -60,7 +60,7 @@ export class PermsRepo {
} }
} }
public async removePerm(userId: number, perm: string): Promise<void> { public async removePerm(userId: string, perm: string): Promise<void> {
const res = await fetchWithToken(this.token, `/perms/user/${userId}/${perm}`, { const res = await fetchWithToken(this.token, `/perms/user/${userId}/${perm}`, {
method: "DELETE", method: "DELETE",
}); });

Datei anzeigen

@ -18,26 +18,13 @@
*/ */
import {fetchWithToken, tokenStore} from "./repo.ts"; import {fetchWithToken, tokenStore} from "./repo.ts";
import {type Schematic, type SchematicInfo, type SchematicList, SchematicSchema} from "@type/schem.ts"; import {type Schematic, SchematicSchema} from "@type/schem.ts";
import {SchematicInfoSchema, SchematicListSchema} from "@type/schem.ts";
import {derived} from "svelte/store"; import {derived} from "svelte/store";
export class SchematicRepo { export class SchematicRepo {
constructor(private token: string) { constructor(private token: string) {
} }
public async getRootSchematicList(): Promise<SchematicList> {
return await fetchWithToken(this.token, "/schem").then(value => value.json()).then(SchematicListSchema.parse);
}
public async getSchematicList(id: number): Promise<SchematicList> {
return await fetchWithToken(this.token, `/schem/${id}/list`).then(value => value.json()).then(SchematicListSchema.parse);
}
public async getSchematicInfo(id: number): Promise<SchematicInfo> {
return await fetchWithToken(this.token, `/schem/${id}`).then(value => value.json()).then(SchematicInfoSchema.parse);
}
public async getSchematicCodeInfo(code: string): Promise<Schematic> { public async getSchematicCodeInfo(code: string): Promise<Schematic> {
return await fetchWithToken(this.token, `/download/${code}/info`).then(value => value.json()).then(SchematicSchema.parse); return await fetchWithToken(this.token, `/download/${code}/info`).then(value => value.json()).then(SchematicSchema.parse);
} }

Datei anzeigen

@ -35,7 +35,7 @@ export class StatsRepo {
return await fetchWithToken(this.token, "/stats/fights").then(value => value.json()).then(FightStatsSchema.parse); return await fetchWithToken(this.token, "/stats/fights").then(value => value.json()).then(FightStatsSchema.parse);
} }
public async getUserStats(id: number): Promise<UserStats> { public async getUserStats(id: string): Promise<UserStats> {
return await fetchWithToken(this.token, `/stats/user/${id}`).then(value => value.json()).then(UserStatsSchema.parse); return await fetchWithToken(this.token, `/stats/user/${id}`).then(value => value.json()).then(UserStatsSchema.parse);
} }
} }

Datei anzeigen

@ -25,7 +25,7 @@ export class UserRepo {
constructor(private token: string) { constructor(private token: string) {
} }
public async setPassword(id: number, password: string): Promise<void> { public async setPassword(id: string, password: string): Promise<void> {
await fetchWithToken(this.token, `/user/${id}/admin/password`, { await fetchWithToken(this.token, `/user/${id}/admin/password`, {
method: "PUT", method: "PUT",
body: password, body: password,

Datei anzeigen

@ -33,19 +33,19 @@ export const schemTypes = cached<SchematicType[]>([], () =>
.then(res => res.json())); .then(res => res.json()));
export const players = cached<Player[]>([], async () => { export const players = cached<Player[]>([], async () => {
const res = await fetchWithToken(get(tokenStore), "/data/users"); const res = await fetchWithToken(get(tokenStore), "/data/admin/users");
return z.array(PlayerSchema).parse(await res.json()); return z.array(PlayerSchema).parse(await res.json());
}); });
export const gamemodes = cached<string[]>([], async () => { export const gamemodes = cached<string[]>([], async () => {
const res = await fetchWithToken(get(tokenStore), "/data/gamemodes"); const res = await fetchWithToken(get(tokenStore), "/data/admin/gamemodes");
return z.array(z.string()).parse(await res.json()); return z.array(z.string()).parse(await res.json());
}); });
export const maps = cachedFamily<string, string[]>([], async (gamemode) => { export const maps = cachedFamily<string, string[]>([], async (gamemode) => {
if (get(gamemodes).every(value => value !== gamemode)) return []; if (get(gamemodes).every(value => value !== gamemode)) return [];
const res = await fetchWithToken(get(tokenStore), `/data/gamemodes/${gamemode}/maps`); const res = await fetchWithToken(get(tokenStore), `/data/admin/gamemodes/${gamemode}/maps`);
if (!res.ok) { if (!res.ok) {
return []; return [];
} else { } else {
@ -54,7 +54,7 @@ export const maps = cachedFamily<string, string[]>([], async (gamemode) => {
}); });
export const groups = cached<string[]>([], async () => { export const groups = cached<string[]>([], async () => {
const res = await fetchWithToken(get(tokenStore), "/data/groups"); const res = await fetchWithToken(get(tokenStore), "/data/admin/groups");
return z.array(z.string()).parse(await res.json()); return z.array(z.string()).parse(await res.json());
}); });

Datei anzeigen

@ -27,7 +27,6 @@ export const SchematicTypeSchema = z.object({
export type SchematicType = z.infer<typeof SchematicTypeSchema>; export type SchematicType = z.infer<typeof SchematicTypeSchema>;
export const PlayerSchema = z.object({ export const PlayerSchema = z.object({
id: z.number(),
name: z.string(), name: z.string(),
uuid: z.string(), uuid: z.string(),
prefix: z.string(), prefix: z.string(),

Datei anzeigen

@ -74,6 +74,7 @@ export const announcements = defineCollection({
schema: ({image}) => z.object({ schema: ({image}) => z.object({
title: z.string(), title: z.string(),
description: z.string(), description: z.string(),
author: z.string().optional(),
image: image().optional(), image: image().optional(),
tags: z.array(z.string()), tags: z.array(z.string()),
created: z.date(), created: z.date(),

Datei anzeigen

@ -8,7 +8,7 @@
"subtitle": { "subtitle": {
"1": "WarGears, AirShips, WarShips", "1": "WarGears, AirShips, WarShips",
"2": "Spieler Online: ", "2": "Spieler Online: ",
"3": "Version: 1.12 - 1.20" "3": "Version: 1.12 - 1.21"
}, },
"join": "Jetzt Spielen", "join": "Jetzt Spielen",
"benefits": { "benefits": {

Datei anzeigen

@ -1,5 +1,5 @@
--- ---
import {CollectionEntry, getCollection} from "astro:content"; import {type CollectionEntry, getCollection} from "astro:content";
import {astroI18n, createGetStaticPaths} from "astro-i18n"; import {astroI18n, createGetStaticPaths} from "astro-i18n";
import PageLayout from "../layouts/PageLayout.astro"; import PageLayout from "../layouts/PageLayout.astro";
import LanguageWarning from "../components/LanguageWarning.astro"; import LanguageWarning from "../components/LanguageWarning.astro";
@ -41,7 +41,7 @@ export const getStaticPaths = createGetStaticPaths(async () => {
})); }));
}); });
const {page, german} = Astro.props; const {page, german} = Astro.props as { page: CollectionEntry<"pages">, german: boolean };
const {Content} = await page.render(); const {Content} = await page.render();
--- ---

Datei anzeigen

@ -61,7 +61,7 @@ const ogImage = await getImage({
}, },
article: { article: {
publishedTime: post.data.created.toISOString(), publishedTime: post.data.created.toISOString(),
author: "SteamWar.de", authors: [post.data.author ?? "SteamWar.de"],
tags: post.data.tags, tags: post.data.tags,
}, },
}} }}
@ -77,7 +77,7 @@ const ogImage = await getImage({
)} )}
<div class={post.data.image ? "absolute bottom-8 left-2" : "mb-4"}> <div class={post.data.image ? "absolute bottom-8 left-2" : "mb-4"}>
<h1 class="text-4xl mb-0" transition:name={post.data.title + "-title"}>{post.data.title}</h1> <h1 class="text-4xl mb-0" transition:name={post.data.title + "-title"}>{post.data.title}</h1>
<h5 class="flex items-center mt-2 text-neutral-300"> <div class="flex items-center mt-2 text-neutral-300">
<TagSolid class="w-4 h-4 mr-2"/> <TagSolid class="w-4 h-4 mr-2"/>
<div transition:name={post.data.title + "-tags"}> <div transition:name={post.data.title + "-tags"}>
{post.data.tags.map(tag => ( {post.data.tags.map(tag => (
@ -89,7 +89,14 @@ const ogImage = await getImage({
day: "numeric", day: "numeric",
month: "short", month: "short",
year: "numeric", year: "numeric",
}).format(post.data.created)} </h5> }).format(post.data.created)}
{post.data.author && (
<Fragment>
<Image src={`https://vzge.me/face/64/${post.data.author}`} alt={post.data.author} width={16} height={16} class="mx-1" />
{post.data.author}
</Fragment>
)}
</div>
</div> </div>
</div> </div>
{german && ( {german && (

Datei anzeigen

@ -1,6 +1,6 @@
--- ---
import Dashboard from "../components/Dashboard.svelte"; import DashboardComponent from "@components/DashboardComponent.svelte";
import PageLayout from "../layouts/PageLayout.astro"; import PageLayout from "@layouts/PageLayout.astro";
import {t} from "astro-i18n"; import {t} from "astro-i18n";
--- ---
@ -16,5 +16,5 @@ import {t} from "astro-i18n";
} }
}); });
</script> </script>
<Dashboard client:only="svelte" /> <DashboardComponent client:only="svelte" />
</PageLayout> </PageLayout>

Datei anzeigen

@ -11,7 +11,7 @@ import {t} from "astro-i18n";
import {l} from "@utils/util"; import {l} from "@utils/util";
import PlayerCount from "@components/PlayerCount.svelte"; import PlayerCount from "@components/PlayerCount.svelte";
import "../../public/fonts/barlow-condensed/barlow-condensed.css"; import "../../public/fonts/barlow-condensed/barlow-condensed.css";
import {Player} from "../components/types/data"; import {type Player} from "../components/types/data";
import PostComponent from "../components/PostComponent.astro"; import PostComponent from "../components/PostComponent.astro";
import BackgroundImage from "../components/BackgroundImage.astro"; import BackgroundImage from "../components/BackgroundImage.astro";

Datei anzeigen

@ -1,5 +1,5 @@
--- ---
import Login from "@components/Login.svelte"; import LoginComponent from "@components/Login.svelte";
import NavbarLayout from "@layouts/NavbarLayout.astro"; import NavbarLayout from "@layouts/NavbarLayout.astro";
import {t} from "astro-i18n"; import {t} from "astro-i18n";
import BackgroundImage from "../components/BackgroundImage.astro"; import BackgroundImage from "../components/BackgroundImage.astro";
@ -23,6 +23,6 @@ import BackgroundImage from "../components/BackgroundImage.astro";
</div> </div>
<div class="h-screen mx-auto p-8 rounded-b-md pt-40 sm:pt-28 md:pt-14 flex flex-col justify-center items-center <div class="h-screen mx-auto p-8 rounded-b-md pt-40 sm:pt-28 md:pt-14 flex flex-col justify-center items-center
dark:text-white " style="width: min(100vw, 75em);"> dark:text-white " style="width: min(100vw, 75em);">
<Login client:load/> <LoginComponent client:load/>
</div> </div>
</NavbarLayout> </NavbarLayout>

Datei anzeigen

@ -1,6 +1,6 @@
--- ---
import {createGetStaticPaths, t} from "astro-i18n"; import {createGetStaticPaths, t} from "astro-i18n";
import {getCollection, CollectionEntry} from "astro:content"; import {getCollection, type CollectionEntry} from "astro:content";
import PageLayout from "../../layouts/PageLayout.astro"; import PageLayout from "../../layouts/PageLayout.astro";
import EloTable from "../../components/EloTable.svelte"; import EloTable from "../../components/EloTable.svelte";