Updates and more
This commit is contained in:
@@ -3,7 +3,7 @@
|
||||
import wrap from "svelte-spa-router/wrap";
|
||||
import Router, {replace} from "svelte-spa-router";
|
||||
import {get} from "svelte/store";
|
||||
import {tokenStore} from "./repo/repo.js";
|
||||
import {tokenStore} from "../repo/repo.js";
|
||||
|
||||
const routes: RouteDefinition = {
|
||||
'/': wrap({asyncComponent: () => import('./pages/Home.svelte'), conditions: detail => get(tokenStore) != ""}),
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import {Input, Label, Select} from "flowbite-svelte";
|
||||
import TypeAheadSearch from "./TypeAheadSearch.svelte";
|
||||
import {gamemodes, groups, maps, players} from "../stores/stores.js";
|
||||
import type {Team} from '../types/team.js';
|
||||
import {gamemodes, groups, maps, players} from "../../stores/stores.js";
|
||||
import type {Team} from '../../types/team.js';
|
||||
|
||||
export let teams: Team[] = [];
|
||||
export let blueTeam: string;
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script lang="ts">
|
||||
import {ArrowLeftSolid} from "flowbite-svelte-icons";
|
||||
import {Button, Card, Input, Label, Navbar, NavBrand, NavHamburger, NavUl, Spinner} from "flowbite-svelte";
|
||||
import {pageRepo} from "../repo/repo.js";
|
||||
import {pageRepo} from "../../repo/repo.js";
|
||||
import {mapToMap, nameRegex} from "../util.ts";
|
||||
import TypeAheadSearch from "../components/TypeAheadSearch.svelte";
|
||||
import {branches} from "../stores/stores.ts";
|
||||
import {branches} from "../../stores/stores.ts";
|
||||
import Editor from "./edit/Editor.svelte";
|
||||
|
||||
$: pagesFuture = $pageRepo.listPages(selectedBranch);
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import EventEdit from "./event/EventEdit.svelte";
|
||||
import {ArrowLeftSolid} from "flowbite-svelte-icons";
|
||||
import FightList from "./event/FightList.svelte";
|
||||
import {eventRepo} from "../repo/repo.js";
|
||||
import {eventRepo} from "../../repo/repo.js";
|
||||
import TeamList from "./event/TeamList.svelte";
|
||||
|
||||
export let params: { id: number } = {};
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import EventEdit from "./event/EventEdit.svelte";
|
||||
import {ArrowLeftSolid} from "flowbite-svelte-icons";
|
||||
import FightList from "./event/FightList.svelte";
|
||||
import {eventRepo} from "../repo/repo.js";
|
||||
import {eventRepo} from "../../repo/repo.js";
|
||||
import TeamList from "./event/TeamList.svelte";
|
||||
import GroupGenerator from "./generate/GroupGenerator.svelte";
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@
|
||||
import {PlusSolid} from "flowbite-svelte-icons";
|
||||
import EventCard from "./home/EventCard.svelte";
|
||||
import CreateEventModal from "./home/CreateEventModal.svelte";
|
||||
import {eventRepo, tokenStore} from "../repo/repo.js";
|
||||
import {eventRepo, tokenStore} from "../../repo/repo.js";
|
||||
|
||||
let events = $eventRepo.listEvents()
|
||||
let showAdd = false
|
||||
|
||||
@@ -3,7 +3,7 @@
|
||||
import {fly} from "svelte/transition";
|
||||
import {replace} from "svelte-spa-router";
|
||||
import {EyeOutline, EyeSlashOutline, EyeSolid} from "flowbite-svelte-icons";
|
||||
import {fetchWithToken, tokenStore} from "../repo/repo.js";
|
||||
import {fetchWithToken, tokenStore} from "../../repo/repo.js";
|
||||
|
||||
let show = false;
|
||||
let loading = false;
|
||||
|
||||
@@ -1,8 +1,8 @@
|
||||
<script lang="ts">
|
||||
import {Button, Card, Checkbox, Input, Label, Navbar, NavBrand, Radio, Spinner} from "flowbite-svelte";
|
||||
import {ArrowLeftSolid} from "flowbite-svelte-icons";
|
||||
import {players} from "../stores/stores.ts";
|
||||
import {permsRepo} from "../repo/repo.ts";
|
||||
import {players} from "../../stores/stores.ts";
|
||||
import {permsRepo} from "../../repo/repo.ts";
|
||||
import {capitalize} from "../util.ts";
|
||||
|
||||
let search = "";
|
||||
|
||||
@@ -2,9 +2,9 @@
|
||||
import {Spinner, Toolbar, ToolbarButton, ToolbarGroup, Tooltip} from "flowbite-svelte";
|
||||
import {markdown} from "@codemirror/lang-markdown";
|
||||
import CodeMirror from "svelte-codemirror-editor";
|
||||
import {pageRepo} from "../../repo/repo.ts";
|
||||
import {pageRepo} from "../../../repo/repo.ts";
|
||||
import {base64ToBytes} from "../../util.ts";
|
||||
import type {Page} from "../../types/page.ts";
|
||||
import type {Page} from "../../../types/page.ts";
|
||||
import {materialDark} from '@ddietr/codemirror-themes/material-dark.js'
|
||||
import {EditOutline} from "flowbite-svelte-icons";
|
||||
import {createEventDispatcher} from "svelte";
|
||||
|
||||
@@ -1,10 +1,10 @@
|
||||
<script lang="ts">
|
||||
import type {ExtendedEvent} from "../../types/event.js";
|
||||
import type {ExtendedEvent} from "../../../types/event.js";
|
||||
import {Button, Heading, Input, Label, Modal, Range, Select, Toast, Toggle} from "flowbite-svelte";
|
||||
import {schemTypes} from "../../stores/stores.js";
|
||||
import {schemTypes} from "../../../stores/stores.js";
|
||||
import moment from "moment/moment.js";
|
||||
import type {UpdateEvent} from "../../repo/event.js";
|
||||
import {eventRepo} from "../../repo/repo.js";
|
||||
import type {UpdateEvent} from "../../../repo/event.js";
|
||||
import {eventRepo} from "../../../repo/repo.js";
|
||||
import ErrorModal from "../../components/ErrorModal.svelte";
|
||||
import {replace} from "svelte-spa-router";
|
||||
import {CheckCircleOutline} from "flowbite-svelte-icons";
|
||||
|
||||
@@ -1,11 +1,11 @@
|
||||
<script lang="ts">
|
||||
import {EditOutline, InboxSolid, TrashBinOutline} from "flowbite-svelte-icons";
|
||||
import {Button, Checkbox, Modal, Toolbar, ToolbarButton} from "flowbite-svelte";
|
||||
import type {EventFight, ExtendedEvent} from "../../types/event.js";
|
||||
import type {EventFight, ExtendedEvent} from "../../../types/event.js";
|
||||
import FightEditModal from "./modals/FightEditModal.svelte";
|
||||
import {createEventDispatcher, onMount} from "svelte";
|
||||
import {fightRepo} from "../../repo/repo.js";
|
||||
import {isWide} from "../../stores/stores.js";
|
||||
import {fightRepo} from "../../../repo/repo.js";
|
||||
import {isWide} from "../../../stores/stores.js";
|
||||
|
||||
export let fight: EventFight;
|
||||
export let data: ExtendedEvent;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import type {EventFight, ExtendedEvent} from "../../types/event.js";
|
||||
import type {EventFight, ExtendedEvent} from "../../../types/event.js";
|
||||
import {
|
||||
Button,
|
||||
Checkbox, Input, Label,
|
||||
@@ -17,10 +17,10 @@
|
||||
} from "flowbite-svelte-icons";
|
||||
import FightCard from "./FightCard.svelte";
|
||||
import CreateFightModal from "./modals/CreateFightModal.svelte";
|
||||
import {fightRepo} from "../../repo/repo.js";
|
||||
import {groups, players} from "../../stores/stores.js";
|
||||
import {fightRepo} from "../../../repo/repo.js";
|
||||
import {groups, players} from "../../../stores/stores.js";
|
||||
import TypeAheadSearch from "../../components/TypeAheadSearch.svelte";
|
||||
import type {UpdateFight} from "../../repo/fight.js";
|
||||
import type {UpdateFight} from "../../../repo/fight.js";
|
||||
import moment from "moment";
|
||||
|
||||
export let data: ExtendedEvent;
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
<script lang="ts">
|
||||
import {Avatar, Button, Modal} from "flowbite-svelte";
|
||||
import type {ExtendedEvent} from "../../types/event.js";
|
||||
import type {ExtendedEvent} from "../../../types/event.js";
|
||||
|
||||
export let data: ExtendedEvent;
|
||||
</script>
|
||||
|
||||
@@ -1,9 +1,9 @@
|
||||
<script lang="ts">
|
||||
import {Button, Modal} from "flowbite-svelte";
|
||||
import type {ExtendedEvent} from "../../../types/event.js";
|
||||
import type {ExtendedEvent} from "../../../../types/event.js";
|
||||
import FightEditPart from "../../../components/FightEditPart.svelte";
|
||||
import {fightRepo} from "../../../repo/repo.js";
|
||||
import type {CreateFight} from "../../../repo/fight.ts";
|
||||
import {fightRepo} from "../../../../repo/repo.js";
|
||||
import type {CreateFight} from "../../../../repo/fight.ts";
|
||||
import ErrorModal from "../../../components/ErrorModal.svelte";
|
||||
import {createEventDispatcher} from "svelte";
|
||||
import moment from "moment";
|
||||
|
||||
@@ -1,12 +1,12 @@
|
||||
<script lang="ts">
|
||||
import {Button, Input, Label, Modal, Select} from "flowbite-svelte";
|
||||
import moment from "moment";
|
||||
import {gamemodes, groups, maps, players} from "../../../stores/stores.js";
|
||||
import type {EventFight, ExtendedEvent} from "../../../types/event.js";
|
||||
import {gamemodes, groups, maps, players} from "../../../../stores/stores.js";
|
||||
import type {EventFight, ExtendedEvent} from "../../../../types/event.js";
|
||||
import TypeAheadSearch from "../../../components/TypeAheadSearch.svelte";
|
||||
import FightEditPart from "../../../components/FightEditPart.svelte";
|
||||
import type {UpdateFight} from "../../../repo/fight.js";
|
||||
import {fightRepo} from "../../../repo/repo.js";
|
||||
import type {UpdateFight} from "../../../../repo/fight.js";
|
||||
import {fightRepo} from "../../../../repo/repo.js";
|
||||
import ErrorModal from "../../../components/ErrorModal.svelte";
|
||||
import {createEventDispatcher} from "svelte";
|
||||
|
||||
|
||||
@@ -1,13 +1,13 @@
|
||||
<script lang="ts">
|
||||
import type {ExtendedEvent} from "../../types/event.js";
|
||||
import type {ExtendedEvent} from "../../../types/event.js";
|
||||
import TeamChip from "./TeamChip.svelte";
|
||||
import type {Team} from "../../types/team.js";
|
||||
import type {Team} from "../../../types/team.js";
|
||||
import DragAcceptor from "./DragAcceptor.svelte";
|
||||
import moment from "moment";
|
||||
import {Button, Input, Label, Modal, Range, Select} from "flowbite-svelte";
|
||||
import {gamemodes, maps} from "../../stores/stores.js";
|
||||
import {gamemodes, maps} from "../../../stores/stores.js";
|
||||
import {PlusSolid} from "flowbite-svelte-icons";
|
||||
import {fightRepo} from "../../repo/repo.js";
|
||||
import {fightRepo} from "../../../repo/repo.js";
|
||||
import {replace} from "svelte-spa-router";
|
||||
|
||||
export let data: ExtendedEvent;
|
||||
|
||||
@@ -1,5 +1,5 @@
|
||||
<script lang="ts">
|
||||
import type {Team} from "../../types/team.js";
|
||||
import type {Team} from "../../../types/team.js";
|
||||
import {brightness, colorFromTeam, lighten} from "../../util.js";
|
||||
|
||||
export let team: Team;
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
import moment from "moment";
|
||||
import {createEventDispatcher} from "svelte";
|
||||
import ErrorModal from "../../components/ErrorModal.svelte";
|
||||
import {eventRepo} from "../../repo/repo.js";
|
||||
import type {SWEvent} from "../../types/event.js";
|
||||
import {eventRepo} from "../../../repo/repo.js";
|
||||
import type {SWEvent} from "../../../types/event.js";
|
||||
|
||||
export let open = false;
|
||||
const dispatch = createEventDispatcher();
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
<script lang="ts">
|
||||
import {Card} from "flowbite-svelte";
|
||||
import {link} from 'svelte-spa-router'
|
||||
import type {ShortEvent} from "../../types/event.js";
|
||||
import type {ShortEvent} from "../../../types/event.js";
|
||||
|
||||
export let event: ShortEvent;
|
||||
|
||||
|
||||
@@ -1,96 +0,0 @@
|
||||
import type {ExtendedEvent, ShortEvent, SWEvent} from "../types/event.js";
|
||||
import {fetchWithToken} from "./repo.js";
|
||||
import type {Moment} from "moment";
|
||||
import {ExtendedEventSchema, ShortEventSchema, SWEventSchema} from "../types/event.js";
|
||||
import {z} from "zod";
|
||||
|
||||
export interface CreateEvent {
|
||||
name: string
|
||||
start: Moment
|
||||
end: Moment
|
||||
}
|
||||
|
||||
export interface UpdateEvent {
|
||||
name: string
|
||||
start: Moment
|
||||
end: Moment
|
||||
deadline: Moment
|
||||
maxTeamMembers: number
|
||||
schemType: string | null
|
||||
publicSchemsOnly: boolean
|
||||
spectateSystem: boolean
|
||||
}
|
||||
|
||||
export class EventRepo {
|
||||
constructor(private token: string) {}
|
||||
|
||||
public async listEvents(): Promise<ShortEvent[]> {
|
||||
const res = await fetchWithToken(this.token, "/events");
|
||||
|
||||
if (res.ok) {
|
||||
return z.array(ShortEventSchema).parse(await res.json());
|
||||
} else {
|
||||
throw new Error("Could not fetch events: " + res.statusText);
|
||||
}
|
||||
}
|
||||
|
||||
public async getEvent(id: string): Promise<ExtendedEvent> {
|
||||
const res = await fetchWithToken(this.token, `/events/${id}`);
|
||||
|
||||
if (res.ok) {
|
||||
return ExtendedEventSchema.parse(await res.json());
|
||||
} else {
|
||||
throw new Error("Could not fetch event: " + res.statusText);
|
||||
}
|
||||
}
|
||||
|
||||
public async createEvent(event: CreateEvent): Promise<SWEvent> {
|
||||
const res = await fetchWithToken(this.token, "/events", {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
name: event.name,
|
||||
start: +event.start,
|
||||
end: +event.end
|
||||
}),
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
return SWEventSchema.parse(await res.json());
|
||||
} else {
|
||||
throw new Error("Could not create event: " + res.statusText);
|
||||
}
|
||||
}
|
||||
|
||||
public async updateEvent(id: string, event: UpdateEvent): Promise<SWEvent> {
|
||||
const res = await fetchWithToken(this.token, `/events/${id}`, {
|
||||
method: "PUT",
|
||||
body: JSON.stringify({
|
||||
name: event.name,
|
||||
start: +event.start,
|
||||
end: +event.end,
|
||||
deadline: +event.deadline,
|
||||
maxTeamMembers: event.maxTeamMembers,
|
||||
schemType: event.schemType,
|
||||
publicSchemsOnly: event.publicSchemsOnly,
|
||||
spectateSystem: event.spectateSystem
|
||||
}),
|
||||
headers: {
|
||||
"Content-Type": "application/json"
|
||||
}
|
||||
});
|
||||
|
||||
if (res.ok) {
|
||||
return SWEventSchema.parse(await res.json());
|
||||
} else {
|
||||
throw new Error("Could not update event: " + res.statusText);
|
||||
}
|
||||
}
|
||||
|
||||
public async deleteEvent(id: string): Promise<boolean> {
|
||||
const res = await fetchWithToken(this.token, `/events/${id}`, {
|
||||
method: "DELETE"
|
||||
});
|
||||
|
||||
return res.ok;
|
||||
}
|
||||
}
|
||||
@@ -1,92 +0,0 @@
|
||||
import type {EventFight} from "../types/event.js";
|
||||
import {fetchWithToken} from "./repo.js";
|
||||
import type {Moment} from "moment";
|
||||
import {z} from "zod";
|
||||
import {EventFightSchema} from "../types/event.js";
|
||||
|
||||
export interface CreateFight {
|
||||
spielmodus: string
|
||||
map: string
|
||||
blueTeam: number
|
||||
redTeam: number
|
||||
start: Moment
|
||||
kampfleiter: number | null
|
||||
group: string | null
|
||||
}
|
||||
|
||||
export interface UpdateFight {
|
||||
spielmodus: string | null
|
||||
map: string | null
|
||||
blueTeam: number | null
|
||||
redTeam: number | null
|
||||
start: Moment | null
|
||||
kampfleiter: number | null
|
||||
group: string | null
|
||||
}
|
||||
|
||||
export class FightRepo {
|
||||
constructor(private token: string) {}
|
||||
|
||||
public async listFights(eventId: number): Promise<EventFight[]> {
|
||||
const res = await fetchWithToken(this.token, `/events/${eventId}/fights`);
|
||||
|
||||
if (res.ok) {
|
||||
return z.array(EventFightSchema).parse(await res.json());
|
||||
} else {
|
||||
throw new Error("Could not fetch fights: " + res.statusText);
|
||||
}
|
||||
}
|
||||
|
||||
public async createFight(eventId: number, fight: CreateFight): Promise<EventFight> {
|
||||
let res = await fetchWithToken(this.token, `/fights`, {
|
||||
method: "POST",
|
||||
body: JSON.stringify({
|
||||
event: eventId,
|
||||
spielmodus: fight.spielmodus,
|
||||
map: fight.map,
|
||||
blueTeam: fight.blueTeam,
|
||||
redTeam: fight.redTeam,
|
||||
start: +fight.start,
|
||||
kampfleiter: fight.kampfleiter,
|
||||
group: fight.group
|
||||
})
|
||||
})
|
||||
|
||||
if (res.ok) {
|
||||
return EventFightSchema.parse(await res.json());
|
||||
} else {
|
||||
throw new Error("Could not create fight: " + res.statusText);
|
||||
}
|
||||
}
|
||||
|
||||
public async updateFight(fightId: number, fight: UpdateFight): Promise<EventFight> {
|
||||
let res = await fetchWithToken(this.token, `/fights/${fightId}`, {
|
||||
method: "PUT",
|
||||
body: JSON.stringify({
|
||||
spielmodus: fight.spielmodus,
|
||||
map: fight.map,
|
||||
blueTeam: fight.blueTeam,
|
||||
redTeam: fight.redTeam,
|
||||
start: fight.start?.valueOf(),
|
||||
kampfleiter: fight.kampfleiter,
|
||||
group: fight.group
|
||||
})
|
||||
})
|
||||
|
||||
if (res.ok) {
|
||||
return EventFightSchema.parse(await res.json());
|
||||
} else {
|
||||
throw new Error("Could not update fight: " + res.statusText);
|
||||
}
|
||||
}
|
||||
|
||||
public async deleteFight(fightId: number): Promise<void> {
|
||||
let res = await fetchWithToken(this.token, `/fights/${fightId}`, {
|
||||
method: "DELETE"
|
||||
})
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error("Could not delete fight: " + res.statusText);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,56 +0,0 @@
|
||||
import type {Page, PageList} from "../types/page.ts";
|
||||
import {fetchWithToken} from "./repo.ts";
|
||||
import {PageListSchema, PageSchema} from "../types/page.ts";
|
||||
import {bytesToBase64} from "../util.ts";
|
||||
import {branches} from "../stores/stores.ts";
|
||||
|
||||
export class PageRepo {
|
||||
constructor(private token: string) {}
|
||||
|
||||
public async listPages(branch: string = "master"): Promise<PageList> {
|
||||
return await fetchWithToken(this.token, `/page?branch=${branch}`)
|
||||
.then(value => value.json())
|
||||
.then(value => PageListSchema.parse(value).map(value1 => ({...value1, path: value1.path.replace("src/content/", "")})))
|
||||
}
|
||||
|
||||
public async getPage(id: number, branch: string = "master"): Promise<Page> {
|
||||
return await fetchWithToken(this.token, `/page/${id}?branch=${branch}`)
|
||||
.then(value => value.json())
|
||||
.then(value => PageSchema.parse(value))
|
||||
}
|
||||
|
||||
public async updatePage(id: number, content: string, sha: string, message: string, branch: string = "master"): Promise<void> {
|
||||
await fetchWithToken(this.token, `/page/${id}?branch=${branch}`, {
|
||||
method: "PUT",
|
||||
body: JSON.stringify({
|
||||
content: bytesToBase64(new TextEncoder().encode(content)),
|
||||
sha, message
|
||||
})
|
||||
})
|
||||
}
|
||||
|
||||
public async getBranches(): Promise<string[]> {
|
||||
return await fetchWithToken(this.token, "/page/branch")
|
||||
.then(value => value.json())
|
||||
}
|
||||
|
||||
public async createBranch(branch: string): Promise<void> {
|
||||
await fetchWithToken(this.token, `/page/branch`, {method: "POST", body: JSON.stringify({branch})})
|
||||
}
|
||||
|
||||
public async deleteBranch(branch: string): Promise<void> {
|
||||
await fetchWithToken(this.token, `/page/branch`, {method: "DELETE", body: JSON.stringify({branch})})
|
||||
}
|
||||
|
||||
public async createFile(path: string, branch: string = "master"): Promise<void> {
|
||||
await fetchWithToken(this.token, `/page?branch=${branch}`, {method: "POST", body: JSON.stringify({path})})
|
||||
}
|
||||
|
||||
public async merge(branch: string, message: string): Promise<void> {
|
||||
await fetchWithToken(this.token, `/page/branch/merge`, {method: "POST", body: JSON.stringify({branch, message})})
|
||||
}
|
||||
|
||||
public async deletePage(id: number, message: string, sha: string, branch: string = "master"): Promise<void> {
|
||||
await fetchWithToken(this.token, `/page/${id}?branch=${branch}`, {method: "DELETE", body: JSON.stringify({message, sha})})
|
||||
}
|
||||
}
|
||||
@@ -1,57 +0,0 @@
|
||||
import type {Perms, UserPerms} from "../types/perms.js";
|
||||
import {fetchWithToken} from "./repo.js";
|
||||
import {PermsSchema, UserPermsSchema} from "../types/perms.js";
|
||||
|
||||
export class PermsRepo {
|
||||
constructor(private token: string) {}
|
||||
|
||||
public async listPerms(): Promise<Perms> {
|
||||
const res = await fetchWithToken(this.token, "/perms");
|
||||
|
||||
if (res.ok) {
|
||||
return PermsSchema.parse(await res.json());
|
||||
} else {
|
||||
throw new Error("Could not fetch perms: " + res.statusText);
|
||||
}
|
||||
}
|
||||
|
||||
public async getPerms(userId: number): Promise<UserPerms> {
|
||||
const res = await fetchWithToken(this.token, `/perms/user/${userId}`);
|
||||
|
||||
if (res.ok) {
|
||||
return UserPermsSchema.parse(await res.json());
|
||||
} else {
|
||||
throw new Error("Could not fetch perms: " + res.statusText);
|
||||
}
|
||||
}
|
||||
|
||||
public async setPrefix(userId: number, prefix: string): Promise<void> {
|
||||
const res = await fetchWithToken(this.token, `/perms/user/${userId}/prefix/${prefix}`, {
|
||||
method: "PUT",
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error("Could not set prefix: " + res.statusText);
|
||||
}
|
||||
}
|
||||
|
||||
public async addPerm(userId: number, perm: string): Promise<void> {
|
||||
const res = await fetchWithToken(this.token, `/perms/user/${userId}/${perm}`, {
|
||||
method: "PUT",
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error("Could not add perm: " + res.statusText);
|
||||
}
|
||||
}
|
||||
|
||||
public async removePerm(userId: number, perm: string): Promise<void> {
|
||||
const res = await fetchWithToken(this.token, `/perms/user/${userId}/${perm}`, {
|
||||
method: "DELETE",
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
throw new Error("Could not remove perm: " + res.statusText);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
import {derived, writable} from "svelte/store";
|
||||
import {EventRepo} from "./event.js";
|
||||
import {FightRepo} from "./fight.js";
|
||||
import {PermsRepo} from "./perms.js";
|
||||
import {PageRepo} from "./page.ts";
|
||||
|
||||
export { EventRepo } from "./event.js"
|
||||
|
||||
export const apiUrl = import.meta.env.PUBLIC_API_SERVER;
|
||||
|
||||
export const fetchWithToken = (token: string, url: string, params: RequestInit = {}) => fetch(`${apiUrl}${url}`, {...params, headers: {"Authorization": "Bearer " + (token), "Content-Type": "application/json", ...params.headers}});
|
||||
export const tokenStore = writable(localStorage.getItem("sw-api-token") ?? "")
|
||||
tokenStore.subscribe((value) => localStorage.setItem("sw-api-token", value))
|
||||
|
||||
export const eventRepo = derived(tokenStore, ($token) => new EventRepo($token))
|
||||
export const fightRepo = derived(tokenStore, ($token) => new FightRepo($token))
|
||||
export const permsRepo = derived(tokenStore, ($token) => new PermsRepo($token))
|
||||
export const pageRepo = derived(tokenStore, ($token) => new PageRepo($token))
|
||||
@@ -1,63 +0,0 @@
|
||||
import {readonly, writable} from "svelte/store";
|
||||
|
||||
import type {Readable, Subscriber, Unsubscriber} from "svelte/store";
|
||||
|
||||
export interface Cached<T> extends Readable<T>{
|
||||
reload: () => void;
|
||||
}
|
||||
|
||||
export function cached<T>(normal: T, init: () => Promise<T>): Cached<T> {
|
||||
const store = writable<T>(normal);
|
||||
let first = true;
|
||||
|
||||
const reload = () => {
|
||||
init().then(data => {
|
||||
store.set(data);
|
||||
});
|
||||
}
|
||||
|
||||
return {
|
||||
...readonly(store),
|
||||
subscribe: (run: Subscriber<T>, invalidate?: (value?: T) => void): Unsubscriber => {
|
||||
if(first) {
|
||||
first = false;
|
||||
reload();
|
||||
}
|
||||
return store.subscribe(run, invalidate);
|
||||
},
|
||||
reload
|
||||
};
|
||||
}
|
||||
|
||||
export function cachedFamily<T, K>(normal: K, init: (arg0: T) => Promise<K>): (arg: T) => Cached<K> {
|
||||
const stores: Map<T, Cached<K>> = new Map();
|
||||
return (arg: T) => {
|
||||
if(stores.has(arg)) {
|
||||
return stores.get(arg)!!;
|
||||
} else {
|
||||
const store = writable<K>(normal);
|
||||
let first = true;
|
||||
|
||||
const reload = () => {
|
||||
init(arg).then(data => {
|
||||
store.set(data);
|
||||
});
|
||||
}
|
||||
|
||||
const cachedStore = {
|
||||
...readonly(store),
|
||||
subscribe: (run: Subscriber<K>, invalidate?: (value?: K) => void): Unsubscriber => {
|
||||
if(first) {
|
||||
first = false;
|
||||
reload();
|
||||
}
|
||||
return store.subscribe(run, invalidate);
|
||||
},
|
||||
reload
|
||||
} as Cached<K>;
|
||||
|
||||
stores.set(arg, cachedStore);
|
||||
return cachedStore;
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,51 +0,0 @@
|
||||
import type {Player, SchematicType} from "../types/data.js";
|
||||
import {PlayerSchema} from "../types/data.js";
|
||||
import {cached, cachedFamily} from "./cached.js";
|
||||
import type {Team} from "../types/team.js";
|
||||
import {TeamSchema} from "../types/team.js";
|
||||
import {get, writable} from "svelte/store";
|
||||
import {apiUrl, fetchWithToken, pageRepo, permsRepo, tokenStore} from "../repo/repo.js";
|
||||
import {z} from "zod";
|
||||
|
||||
export const schemTypes = cached<SchematicType[]>([], () =>
|
||||
fetchWithToken(get(tokenStore), `/data/schematicTypes`)
|
||||
.then(res => res.json()))
|
||||
|
||||
export const players = cached<Player[]>([], async () => {
|
||||
const res = await fetchWithToken(get(tokenStore), `/data/users`);
|
||||
return z.array(PlayerSchema).parse(await res.json());
|
||||
})
|
||||
|
||||
export const gamemodes = cached<string[]>([], async () => {
|
||||
const res = await fetchWithToken(get(tokenStore), `/data/gamemodes`);
|
||||
return z.array(z.string()).parse(await res.json());
|
||||
})
|
||||
|
||||
export const maps = cachedFamily<string, string[]>([], async (gamemode) => {
|
||||
if (get(gamemodes).every(value => value !== gamemode)) return [];
|
||||
|
||||
const res = await fetchWithToken(get(tokenStore), `/data/gamemodes/${gamemode}/maps`);
|
||||
if (!res.ok) {
|
||||
return [];
|
||||
} else {
|
||||
return res.json();
|
||||
}
|
||||
})
|
||||
|
||||
export const groups = cached<string[]>([], async () => {
|
||||
const res = await fetchWithToken(get(tokenStore), `/data/groups`);
|
||||
return z.array(z.string()).parse(await res.json());
|
||||
})
|
||||
|
||||
export const teams = cached<Team[]>([], async () => {
|
||||
const res = await fetchWithToken(get(tokenStore), `/team`);
|
||||
return z.array(TeamSchema).parse(await res.json());
|
||||
})
|
||||
|
||||
export const branches = cached<string[]>([], async () => {
|
||||
const res = await get(pageRepo).getBranches();
|
||||
return z.array(z.string()).parse(res);
|
||||
})
|
||||
|
||||
export const isWide = writable(window.innerWidth >= 640);
|
||||
window.addEventListener("resize", () => isWide.set(window.innerWidth >= 640));
|
||||
@@ -1,16 +0,0 @@
|
||||
import {z} from "zod";
|
||||
|
||||
export const SchematicTypeSchema = z.object({
|
||||
name: z.string(),
|
||||
db: z.string(),
|
||||
})
|
||||
|
||||
export type SchematicType = z.infer<typeof SchematicTypeSchema>;
|
||||
|
||||
export const PlayerSchema = z.object({
|
||||
id: z.number(),
|
||||
name: z.string(),
|
||||
uuid: z.string(),
|
||||
})
|
||||
|
||||
export type Player = z.infer<typeof PlayerSchema>;
|
||||
@@ -1,46 +0,0 @@
|
||||
import type {Team} from "./team.js";
|
||||
import type {Player} from "./data.js";
|
||||
import {z} from "zod";
|
||||
import {TeamSchema} from "./team.js";
|
||||
import {PlayerSchema} from "./data.js";
|
||||
|
||||
export const ShortEventSchema = z.object({
|
||||
id: z.number(),
|
||||
name: z.string(),
|
||||
start: z.number(),
|
||||
end: z.number(),
|
||||
})
|
||||
|
||||
export type ShortEvent = z.infer<typeof ShortEventSchema>;
|
||||
|
||||
export const SWEventSchema = ShortEventSchema.extend({
|
||||
deadline: z.number(),
|
||||
maxTeamMembers: z.number(),
|
||||
schemType: z.string().nullable(),
|
||||
publicSchemsOnly: z.boolean(),
|
||||
spectateSystem: z.boolean(),
|
||||
})
|
||||
|
||||
export type SWEvent = z.infer<typeof SWEventSchema>;
|
||||
|
||||
export const EventFightSchema = z.object({
|
||||
id: z.number(),
|
||||
spielmodus: z.string(),
|
||||
map: z.string(),
|
||||
blueTeam: TeamSchema,
|
||||
redTeam: TeamSchema,
|
||||
kampfleiter: PlayerSchema.nullable(),
|
||||
start: z.number(),
|
||||
ergebnis: z.number(),
|
||||
group: z.string().nullable(),
|
||||
})
|
||||
|
||||
export type EventFight = z.infer<typeof EventFightSchema>;
|
||||
|
||||
export const ExtendedEventSchema = z.object({
|
||||
event: SWEventSchema,
|
||||
teams: z.array(TeamSchema),
|
||||
fights: z.array(EventFightSchema),
|
||||
})
|
||||
|
||||
export type ExtendedEvent = z.infer<typeof ExtendedEventSchema>;
|
||||
@@ -1,32 +0,0 @@
|
||||
import {z} from "zod";
|
||||
|
||||
export const ListPageSchema = z.object({
|
||||
path: z.string(),
|
||||
name: z.string(),
|
||||
sha: z.string(),
|
||||
downloadUrl: z.string().url(),
|
||||
id: z.number().positive()
|
||||
});
|
||||
|
||||
export type ListPage = z.infer<typeof ListPageSchema>;
|
||||
|
||||
export const PageListSchema = z.array(ListPageSchema)
|
||||
|
||||
export type PageList = z.infer<typeof PageListSchema>;
|
||||
|
||||
export const PageSchema = z.object({
|
||||
path: z.string(),
|
||||
name: z.string(),
|
||||
sha: z.string(),
|
||||
downloadUrl: z.string().url(),
|
||||
content: z.string(),
|
||||
size: z.number().gte(0),
|
||||
id: z.number().positive()
|
||||
})
|
||||
|
||||
export type Page = z.infer<typeof PageSchema>;
|
||||
|
||||
export type Pages = {
|
||||
dirs: {[key: string]: Pages},
|
||||
files: {[key: string]: ListPage}
|
||||
}
|
||||
@@ -1,23 +0,0 @@
|
||||
import {z} from "zod";
|
||||
|
||||
export const PrefixSchema = z.object({
|
||||
name: z.string().startsWith("PREFIX_"),
|
||||
colorCode: z.string().length(2).startsWith("§"),
|
||||
chatPrefix: z.string()
|
||||
})
|
||||
|
||||
export type Prefix = z.infer<typeof PrefixSchema>;
|
||||
|
||||
export const PermsSchema = z.object({
|
||||
perms: z.array(z.string()),
|
||||
prefixes: z.record(PrefixSchema),
|
||||
})
|
||||
|
||||
export type Perms = z.infer<typeof PermsSchema>;
|
||||
|
||||
export const UserPermsSchema = z.object({
|
||||
prefix: PrefixSchema,
|
||||
perms: z.array(z.string()),
|
||||
})
|
||||
|
||||
export type UserPerms = z.infer<typeof UserPermsSchema>;
|
||||
@@ -1,12 +0,0 @@
|
||||
import {z} from "zod";
|
||||
|
||||
export const TeamSchema = z.object({
|
||||
id: z.number(),
|
||||
name: z.string(),
|
||||
kuerzel: z.string().min(1).max(4),
|
||||
color: z.string().max(1),
|
||||
})
|
||||
|
||||
export type Team = z.infer<typeof TeamSchema>;
|
||||
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import Color from "color";
|
||||
import type {Team} from "./types/team.js";
|
||||
import type {ListPage, PageList} from "./types/page.ts";
|
||||
import type {Team} from "../types/team.js";
|
||||
import type {ListPage, PageList} from "../types/page.ts";
|
||||
|
||||
export const capitalize = (str: string) => str.charAt(0).toUpperCase() + str.slice(1);
|
||||
|
||||
@@ -9,7 +9,7 @@ export const nameRegex = new RegExp("(?!.*\/).+(?=\\.md)");
|
||||
export function mapToMap(pages: PageList): Map<string, ListPage[]> {
|
||||
const map = new Map();
|
||||
for (const page of pages) {
|
||||
let folder = page.path.substring(0, page.path.indexOf(nameRegex.exec(page.path)[0]));
|
||||
let folder = page.path.substring(0, page.path.indexOf(nameRegex.exec(page.path)!![0]));
|
||||
if (!map.has(folder)) {
|
||||
map.set(folder, []);
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user