Dieser Commit ist enthalten in:
Chaoscaot 2023-08-30 14:17:40 +02:00
Ursprung 4a501ea870
Commit 69abda05f7
Signiert von: Chaoscaot
GPG-Schlüssel-ID: BDF8FADD7D5EDB7A
12 geänderte Dateien mit 281 neuen und 43 gelöschten Zeilen

Datei anzeigen

@ -12,17 +12,18 @@
"devDependencies": {
"@sveltejs/vite-plugin-svelte": "^2.4.1",
"@tsconfig/svelte": "^4.0.1",
"@types/color": "^3.0.3",
"autoprefixer": "^10.4.14",
"flowbite-svelte-icons": "^0.2.5",
"flowbite": "^1.7.0",
"flowbite-svelte": "^0.39.2",
"svelte-awesome": "^3.2.0",
"tailwind-merge": "^1.13.2",
"flowbite-svelte-icons": "^0.2.5",
"postcss": "^8.4.24",
"sass": "^1.62.0",
"svelte": "^4.0.1",
"svelte-awesome": "^3.2.0",
"svelte-check": "^3.4.3",
"svelte-preprocess": "^5.0.3",
"tailwind-merge": "^1.13.2",
"tailwindcss": "^3.3.2",
"tslib": "^2.5.0",
"typescript": "^5.0.2",

Datei anzeigen

@ -1,33 +1,19 @@
lockfileVersion: '6.0'
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false
dependencies:
'@popperjs/core':
specifier: ^2.11.8
version: 2.11.8
color:
specifier: ^4.2.3
version: 4.2.3
flowbite:
specifier: ^1.7.0
version: 1.7.0
flowbite-svelte:
specifier: ^0.39.2
version: 0.39.2(svelte@4.0.1)
install:
specifier: ^0.13.0
version: 0.13.0
moment:
specifier: ^2.29.4
version: 2.29.4
svelte-awesome:
specifier: ^3.2.0
version: 3.2.0(svelte@4.0.1)
svelte-spa-router:
specifier: ^3.3.0
version: 3.3.0
tailwind-merge:
specifier: ^1.13.2
version: 1.13.2
zod:
specifier: ^3.21.4
version: 3.21.4
@ -39,9 +25,18 @@ devDependencies:
'@tsconfig/svelte':
specifier: ^4.0.1
version: 4.0.1
'@types/color':
specifier: ^3.0.3
version: 3.0.3
autoprefixer:
specifier: ^10.4.14
version: 10.4.14(postcss@8.4.24)
flowbite:
specifier: ^1.7.0
version: 1.7.0
flowbite-svelte:
specifier: ^0.39.2
version: 0.39.2(svelte@4.0.1)
flowbite-svelte-icons:
specifier: ^0.2.5
version: 0.2.5(svelte@4.0.1)(tailwind-merge@1.13.2)(tailwindcss@3.3.2)
@ -54,12 +49,18 @@ devDependencies:
svelte:
specifier: ^4.0.1
version: 4.0.1
svelte-awesome:
specifier: ^3.2.0
version: 3.2.0(svelte@4.0.1)
svelte-check:
specifier: ^3.4.3
version: 3.4.3(postcss@8.4.24)(sass@1.62.0)(svelte@4.0.1)
svelte-preprocess:
specifier: ^5.0.3
version: 5.0.4(postcss@8.4.24)(sass@1.62.0)(svelte@4.0.1)(typescript@5.1.3)
tailwind-merge:
specifier: ^1.13.2
version: 1.13.2
tailwindcss:
specifier: ^3.3.2
version: 3.3.2
@ -86,6 +87,7 @@ packages:
dependencies:
'@jridgewell/gen-mapping': 0.3.3
'@jridgewell/trace-mapping': 0.3.18
dev: true
/@esbuild/android-arm64@0.17.19:
resolution: {integrity: sha512-KBMWvEZooR7+kzY0BtbTQn0OAYY7CsiydT63pVEaPtVYF0hXbUaOyZog37DKxK7NF3XacBJOpYT4adIJh+avxA==}
@ -292,26 +294,32 @@ packages:
'@jridgewell/set-array': 1.1.2
'@jridgewell/sourcemap-codec': 1.4.15
'@jridgewell/trace-mapping': 0.3.18
dev: true
/@jridgewell/resolve-uri@3.1.0:
resolution: {integrity: sha512-F2msla3tad+Mfht5cJq7LSXcdudKTWCVYUgw6pLFOOHSTtZlj6SWNYAp+AhuqLmWdBO2X5hPrLcu8cVP8fy28w==}
engines: {node: '>=6.0.0'}
dev: true
/@jridgewell/set-array@1.1.2:
resolution: {integrity: sha512-xnkseuNADM0gt2bs+BvhO0p78Mk762YnZdsuzFV018NoG1Sj1SCQvpSqa7XUaTam5vAGasABV9qXASMKnFMwMw==}
engines: {node: '>=6.0.0'}
dev: true
/@jridgewell/sourcemap-codec@1.4.14:
resolution: {integrity: sha512-XPSJHWmi394fuUuzDnGz1wiKqWfo1yXecHQMRf2l6hztTO+nPru658AyDngaBe7isIxEkRsPR3FZh+s7iVa4Uw==}
dev: true
/@jridgewell/sourcemap-codec@1.4.15:
resolution: {integrity: sha512-eF2rxCRulEKXHTRiDrDy6erMYWqNw4LPdQ8UQA4huuxaQsVeRPFl2oM8oDGxMFhJUWZf9McpLtJasDDZb/Bpeg==}
dev: true
/@jridgewell/trace-mapping@0.3.18:
resolution: {integrity: sha512-w+niJYzMHdd7USdiH2U6869nqhD2nbfZXND5Yp93qIbEmnDNk7PD48o+YchRVpzMU7M6jVCbenTR7PA1FLQ9pA==}
dependencies:
'@jridgewell/resolve-uri': 3.1.0
'@jridgewell/sourcemap-codec': 1.4.14
dev: true
/@nodelib/fs.scandir@2.1.5:
resolution: {integrity: sha512-vq24Bq3ym5HEQm2NKCr3yXDwjc7vTsEThRDnkp2DK9p1uqLR+DHurm/NOTo0KG7HYHU7eppKZj3MyqYuMBf62g==}
@ -336,7 +344,7 @@ packages:
/@popperjs/core@2.11.8:
resolution: {integrity: sha512-P1st0aksCrn9sGZhp8GMYwBnQsbvAWsZAX44oXNNvLHGqAOcoVxmjZiohstwQ7SqKnbR47akdNi+uleWD8+g6A==}
dev: false
dev: true
/@sveltejs/vite-plugin-svelte-inspector@1.0.2(@sveltejs/vite-plugin-svelte@2.4.1)(svelte@4.0.1)(vite@4.3.9):
resolution: {integrity: sha512-Cy1dUMcYCnDVV/hPLXa43YZJ2jGKVW5rA0xuNL9dlmYhT0yoS1g7+FOFSRlgk0BXKk/Oc7grs+8BVA5Iz2fr8A==}
@ -378,8 +386,25 @@ packages:
resolution: {integrity: sha512-B+XlGpmuAQzJqDoBATNCvEPqQg0HkO7S8pM14QDI5NsmtymzRexQ1N+nX2H6RTtFbuFgaZD4I8AAi8voGg0GLg==}
dev: true
/@types/color-convert@2.0.0:
resolution: {integrity: sha512-m7GG7IKKGuJUXvkZ1qqG3ChccdIM/qBBo913z+Xft0nKCX4hAU/IxKwZBU4cpRZ7GS5kV4vOblUkILtSShCPXQ==}
dependencies:
'@types/color-name': 1.1.1
dev: true
/@types/color-name@1.1.1:
resolution: {integrity: sha512-rr+OQyAjxze7GgWrSaJwydHStIhHq2lvY3BOC2Mj7KnzI7XK0Uw1TOOdI9lDoajEbSWLiYgoo4f1R51erQfhPQ==}
dev: true
/@types/color@3.0.3:
resolution: {integrity: sha512-X//qzJ3d3Zj82J9sC/C18ZY5f43utPbAJ6PhYt/M7uG6etcF6MRpKdN880KBy43B0BMzSfeT96MzrsNjFI3GbA==}
dependencies:
'@types/color-convert': 2.0.0
dev: true
/@types/estree@1.0.1:
resolution: {integrity: sha512-LG4opVs2ANWZ1TJoKc937iMmNstM/d0ae1vNbnBvBhqCSezgVUOzcLCqbI5elV8Vy6WKwKjaqR+zO9VKirBBCA==}
dev: true
/@types/pug@2.0.6:
resolution: {integrity: sha512-SnHmG9wN1UVmagJOnyo/qkk0Z7gejYxOYYmaAwr5u2yFYfsupN3sg10kyzN8Hep/2zbHxCnsumxOoRIRMBwKCg==}
@ -389,6 +414,7 @@ packages:
resolution: {integrity: sha512-F0SAmZ8iUtS//m8DmCTA0jlh6TDKkHQyK6xc6V4KDTyZKA9dnvX9/3sRTVQrWm79glUAZbnmmNcdYwUIHWVybw==}
engines: {node: '>=0.4.0'}
hasBin: true
dev: true
/any-promise@1.3.0:
resolution: {integrity: sha512-7UvmKalWRt1wgjL1RrGxoSJW/0QZFIegpeGvZG9kjp8vrRu55XTHbwnqq2GpXm9uLbcuhxm3IqX9OB4MZR1b2A==}
@ -410,6 +436,7 @@ packages:
resolution: {integrity: sha512-b0P0sZPKtyu8HkeRAfCq0IfURZK+SuwMjY1UXGBU27wpAiTwQAIlq56IbIO+ytk/JjS1fMR14ee5WBBfKi5J6A==}
dependencies:
dequal: 2.0.3
dev: true
/autoprefixer@10.4.14(postcss@8.4.24):
resolution: {integrity: sha512-FQzyfOsTlwVzjHxKEqRIAdJx9niO6VCBCoEwax/VLSoQF29ggECcPuBqUMZ+u8jCZOPSy8b8/8KnuFbp0SaFZQ==}
@ -431,6 +458,7 @@ packages:
resolution: {integrity: sha512-jsyHu61e6N4Vbz/v18DHwWYKK0bSWLqn47eeDSKPB7m8tqMHF9YJ+mhIk2lVteyZrY8tnSj/jHOv4YiTCuCJgg==}
dependencies:
dequal: 2.0.3
dev: true
/balanced-match@1.0.2:
resolution: {integrity: sha512-3oSeUO0TMV67hN1AmbXsK4yaqU7tjiHlbxRDZOpH0KW9+CeX4bRAaX0Anxt0tx2MrpRpWwQaPwIlISEJhYU5Pw==}
@ -507,6 +535,7 @@ packages:
acorn: 8.10.0
estree-walker: 3.0.3
periscopic: 3.1.0
dev: true
/color-convert@2.0.1:
resolution: {integrity: sha512-RRECPsj7iu/xb5oKYcsFHSppFNnsj/52OVTRKb4zP5onXwVF3zVmmToNcOfGC+CRDpfK/U584fMg38ZHCaElKQ==}
@ -549,6 +578,7 @@ packages:
dependencies:
mdn-data: 2.0.30
source-map-js: 1.0.2
dev: true
/cssesc@3.0.0:
resolution: {integrity: sha512-/Tb/JcjK111nNScGob5MNtsntNM1aCNUDipB/TkwZFhyDrrE47SOx/18wF2bbjgc3ZzCSKW1T5nt5EbFoAz/Vg==}
@ -576,6 +606,7 @@ packages:
/dequal@2.0.3:
resolution: {integrity: sha512-0je+qPKHEMohvfRTCEo3CrPG6cAzAYgmzKyxRiYSSDkS6eGJdyVJm7WaYA5ECaAD9wLB2T4EEeymA5aFVcYXCA==}
engines: {node: '>=6'}
dev: true
/detect-indent@6.1.0:
resolution: {integrity: sha512-reYkTUJAZb9gUuZ2RvVCNhVHdg62RHnJ7WJl8ftMi4diZ6NWlciOzQN88pUhSELEwflJht4oQDv0F0BMlwaYtA==}
@ -637,6 +668,7 @@ packages:
resolution: {integrity: sha512-7RUKfXgSMMkzt6ZuXmqapOurLGPPfgj6l9uRZ7lRGolvk0y2yocc35LdcxKC5PQZdn2DMqioAQ2NoWcrTKmm6g==}
dependencies:
'@types/estree': 1.0.1
dev: true
/fast-glob@3.2.12:
resolution: {integrity: sha512-DVj4CQIYYow0BlaelwK1pHl5n5cRSJfM60UA0zK891sVInoPri2Ekj7+e1CT3/3qxXenpI+nBBmQAcJPJgaj4w==}
@ -684,14 +716,14 @@ packages:
flowbite: 1.7.0
svelte: 4.0.1
tailwind-merge: 1.13.2
dev: false
dev: true
/flowbite@1.7.0:
resolution: {integrity: sha512-OTTmnhRgv85Rs+mcMaVU7zB6EvRQs7BaQziyMUsZLRjW9aUpeQyqKjLmxsVMMCdr8isYPCLd6UL7X1IaSVI0WQ==}
dependencies:
'@popperjs/core': 2.11.8
mini-svg-data-uri: 1.4.4
dev: false
dev: true
/fraction.js@4.2.0:
resolution: {integrity: sha512-MhLuK+2gUcnZe8ZHlaaINnQLl0xRIGRfcGk2yl8xoQAfHrSsL3rYu6FCmBdkdbhc9EPlwyGHewaRsvwRMJtAlA==}
@ -783,11 +815,6 @@ packages:
resolution: {integrity: sha512-k/vGaX4/Yla3WzyMCvTQOXYeIHvqOKtnqBduzTHpzpQZzAskKMhZ2K+EnBiSM9zGSoIFeMpXKxa4dYeZIQqewQ==}
dev: true
/install@0.13.0:
resolution: {integrity: sha512-zDml/jzr2PKU9I8J/xyZBQn8rPCAY//UOYNmR01XwNwyfhEWObo2SWfSl1+0tm1u6PhxLwDnfsT/6jB7OUxqFA==}
engines: {node: '>= 0.10'}
dev: false
/is-arrayish@0.3.2:
resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
dev: false
@ -826,6 +853,7 @@ packages:
resolution: {integrity: sha512-baJJdQLiYaJdvFbJqXrcGv3WU3QCzBlUcI5QhbesIm6/xPsvmO+2CDoi/GMOFBQEQm+PXkwOPrp9KK5ozZsp2w==}
dependencies:
'@types/estree': 1.0.1
dev: true
/jiti@1.18.2:
resolution: {integrity: sha512-QAdOptna2NYiSSpv0O/BwoHBSmz4YhpzJHyi+fnMRTXFjp7B8i/YG5Z8IfusxB1ufjcD2Sre1F3R+nX3fvy7gg==}
@ -848,6 +876,7 @@ packages:
/locate-character@3.0.0:
resolution: {integrity: sha512-SW13ws7BjaeJ6p7Q6CO2nchbYEc3X3J6WrmTTDto7yMPqVSZTUyY5Tjbid+Ab8gLnATtygYtiDIJGQRRn2ZOiA==}
dev: true
/magic-string@0.27.0:
resolution: {integrity: sha512-8UnnX2PeRAPZuN12svgR9j7M1uWMovg/CEnIwIG0LFkXSJJe4PdfUGiTGl8V9bsBHFUtfVINcSyYxd7q+kx9fA==}
@ -861,9 +890,11 @@ packages:
engines: {node: '>=12'}
dependencies:
'@jridgewell/sourcemap-codec': 1.4.15
dev: true
/mdn-data@2.0.30:
resolution: {integrity: sha512-GaqWWShW4kv/G9IEucWScBx9G1/vsFZZJUO+tD26M8J8z3Kw5RDQjaoZe03YAClgeS/SWPOcb4nkFBTEi5DUEA==}
dev: true
/merge2@1.4.1:
resolution: {integrity: sha512-8q7VEgMJW4J8tcfVPy8g09NcQwZdbwFEqhe/WZkoIzjn/3TGDwtOCYtXGxA3O8tPzpczCCDgv+P2P5y00ZJOOg==}
@ -886,7 +917,7 @@ packages:
/mini-svg-data-uri@1.4.4:
resolution: {integrity: sha512-r9deDe9p5FJUPZAk3A59wGH7Ii9YrjjWw0jmw/liSbHl2CHiyXj6FcDXDu2K3TjVAXqiJdaw3xxwlZZr9E6nHg==}
hasBin: true
dev: false
dev: true
/minimatch@3.1.2:
resolution: {integrity: sha512-J7p63hRiAjw1NDEww1W7i37+ByIrOWO5XQQAzZ3VOcL0PNybwpfmV/N05zFAzwQ9USyEcX6t3UO+K5aqBQOIHw==}
@ -984,6 +1015,7 @@ packages:
'@types/estree': 1.0.1
estree-walker: 3.0.3
is-reference: 3.0.1
dev: true
/picocolors@1.0.0:
resolution: {integrity: sha512-1fygroTLlHu66zi26VoTDv8yRgm0Fccecssto+MhsZ0D/DGW2sm8E8AjW7NU5VVTRt5GxbeZ5qBuJr+HyLYkjQ==}
@ -1181,6 +1213,7 @@ packages:
/source-map-js@1.0.2:
resolution: {integrity: sha512-R0XvVJ9WusLiqTCEiGCmICCMplcCkIwwR11mOSD9CR5u+IXYdiseeEuXCVAjS54zqwkLcPNnmU4OeJ6tUrWhDw==}
engines: {node: '>=0.10.0'}
dev: true
/strip-indent@3.0.0:
resolution: {integrity: sha512-laJTa3Jb+VQpaC6DseHhF7dXVqHTfJPCRDaEbid/drOhgitgYku/letMUqOXFoWV0zIIUbjpdH2t+tYj4bQMRQ==}
@ -1214,7 +1247,7 @@ packages:
svelte: ^3.43.1
dependencies:
svelte: 4.0.1
dev: false
dev: true
/svelte-check@3.4.3(postcss@8.4.24)(sass@1.62.0)(svelte@4.0.1):
resolution: {integrity: sha512-O07soQFY3X0VDt+bcGc6D5naz0cLtjwnmNP9JsEBPVyMemFEqUhL2OdLqvkl5H/u8Jwm50EiAU4BPRn5iin/kg==}
@ -1324,9 +1357,11 @@ packages:
locate-character: 3.0.0
magic-string: 0.30.0
periscopic: 3.1.0
dev: true
/tailwind-merge@1.13.2:
resolution: {integrity: sha512-R2/nULkdg1VR/EL4RXg4dEohdoxNUJGLMnWIQnPKL+O9Twu7Cn3Rxi4dlXkDzZrEGtR+G+psSXFouWlpTyLhCQ==}
dev: true
/tailwindcss@3.3.2:
resolution: {integrity: sha512-9jPkMiIBXvPc2KywkraqsUfbfj+dHDb+JPWtSJa9MLFdrPyazI7q6WX2sUrm7R9eVR7qqv3Pas7EvQFzxKnI6w==}
@ -1465,7 +1500,3 @@ packages:
/zod@3.21.4:
resolution: {integrity: sha512-m46AKbrzKVzOzs/DZgVnG5H55N1sv1M8qZU3A8RIKbs3mrACDNeIOeilDymVb2HdmP8uwshOCF4uJ8uM9rCqJw==}
dev: false
settings:
autoInstallPeers: true
excludeLinksFromLockfile: false

Datei anzeigen

@ -7,6 +7,7 @@
const routes: RouteDefinition = {
'/': wrap({asyncComponent: () => import('./pages/Home.svelte'), conditions: detail => get(tokenStore) != ""}),
'/perms': wrap({asyncComponent: () => import('./pages/Perms.svelte'), conditions: detail => get(tokenStore) != ""}),
'/login': wrap({asyncComponent: () => import('./pages/Login.svelte'), conditions: detail => get(tokenStore) == ""}),
'/event/:id': wrap({asyncComponent: () => import('./pages/Event.svelte'), conditions: detail => get(tokenStore) != ""}),
'/event/:id/generate': wrap({asyncComponent: () => import('./pages/Generate.svelte'), conditions: detail => get(tokenStore) != ""}),

Datei anzeigen

@ -1,7 +1,7 @@
<script lang="ts">
import {Button, Dropdown, DropdownItem, Search} from 'flowbite-svelte'
export let selected: string = ''
export let selected: string = null
export let items: {name: string, value: string}[] = []
export let searchValue = items.find(item => item.value === selected)?.name || ''

Datei anzeigen

@ -26,6 +26,7 @@
</NavBrand>
<NavHamburger on:click={toggle} />
<NavUl {hidden}>
<NavLi href="#/perms">Permissions</NavLi>
<NavLi on:click={() => showLogoutModal = true} class="cursor-pointer select-none">Logout</NavLi>
</NavUl>
</Navbar>

123
src/pages/Perms.svelte Normale Datei
Datei anzeigen

@ -0,0 +1,123 @@
<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";
import {permsRepo} from "../repo/repo";
import {capitalize} from "../util";
let search = "";
$: lowerCaseSearch = search.toLowerCase();
$: filteredPlayers = $players.filter(value => value.name.toLowerCase().includes(lowerCaseSearch));
let selectedPlayer = null;
$: player = $players.find(value => value.id === selectedPlayer);
let playerPerms = loadPlayer(selectedPlayer);
$: playerPerms = loadPlayer(selectedPlayer);
let prefixEdit = "PREFIX_NONE";
let activePerms = [];
function loadPlayer(id: number) {
if (!id) {
return;
}
return $permsRepo.getPerms(id).then(value => {
activePerms = value.perms;
prefixEdit = value.prefix.name;
return value;
})
}
function togglePerm(perm: string) {
return () => {
if (activePerms.includes(perm)) {
activePerms = activePerms.filter(value => value !== perm);
} else {
activePerms = [...activePerms, perm];
}
}
}
function save() {
playerPerms.then(async perms => {
if (perms.prefix.name != prefixEdit) {
await $permsRepo.setPrefix(selectedPlayer, prefixEdit);
}
for (let value of activePerms) {
if (!perms.perms.includes(value)) {
await $permsRepo.addPerm(selectedPlayer, value);
}
}
for (let value of perms.perms) {
if (!activePerms.includes(value)) {
await $permsRepo.removePerm(selectedPlayer, value);
}
}
playerPerms = loadPlayer(selectedPlayer);
})
}
let permsFuture = $permsRepo.listPerms();
</script>
<div class="flex flex-col h-screen overflow-hidden">
<Navbar let:hidden let:toggle>
<NavBrand href="#">
<ArrowLeftSolid></ArrowLeftSolid>
<span class="ml-4 self-center whitespace-nowrap text-xl font-semibold dark:text-white">
Permissions
</span>
</NavBrand>
</Navbar>
<div class="p-4 flex-1 overflow-hidden">
<div class="grid md:grid-cols-3 grid-cols-1 h-full gap-8">
<Card class="h-full flex flex-col overflow-hidden !max-w-full">
<div class="border-b border-b-gray-600 pb-2">
<Label for="user_search" class="mb-2">Search Users...</Label>
<Input type="text" id="user_search" placeholder="Name..." bind:value={search}/>
</div>
{#if filteredPlayers.length < 100}
<ul class="flex-1 overflow-scroll">
{#each filteredPlayers as player}
<li class="p-4 transition-colors hover:bg-gray-700 cursor-pointer" class:text-orange-500={player.id === selectedPlayer} on:click|preventDefault={() => selectedPlayer = player.id}>
{player.name}
</li>
{/each}
</ul>
{/if}
</Card>
<Card class="!max-w-full" style="grid-column: 2/4">
{#if selectedPlayer}
<h1 class="text-3xl">{player.name}</h1>
{#await permsFuture}
<Spinner></Spinner>
{:then perms}
{#await playerPerms}
<Spinner></Spinner>
{:then player}
<h1>Prefix</h1>
{#each Object.entries(perms.prefixes) as [key, prefix]}
<Radio name="prefix" bind:group={prefixEdit} value={prefix.name}>{capitalize(prefix.name.substring(7).toLowerCase())}</Radio>
{/each}
<h1>Permissions</h1>
{#each perms.perms as perm}
<Checkbox checked={activePerms.includes(perm)} on:click={togglePerm(perm)}>{capitalize(perm.toLowerCase())}</Checkbox>
{/each}
<div class="mt-4">
<Button disabled={prefixEdit === player.prefix.name && activePerms === player.perms} on:click={save}>Save</Button>
</div>
{:catch error}
<p>{error.toString()}</p>
{/await}
{:catch error}
<p>{error.toString()}</p>
{/await}
{/if}
</Card>
</div>
</div>
</div>

Datei anzeigen

@ -3,11 +3,10 @@
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.js";
import type {CreateFight} from "../../../repo/fight";
import ErrorModal from "../../../components/ErrorModal.svelte";
import {createEventDispatcher} from "svelte";
import moment from "moment";
import Number = types.Number;
let dispatch = createEventDispatcher();

57
src/repo/perms.ts Normale Datei
Datei anzeigen

@ -0,0 +1,57 @@
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);
}
}
}

Datei anzeigen

@ -1,6 +1,7 @@
import {derived, writable} from "svelte/store";
import {EventRepo} from "./event.js";
import {FightRepo} from "./fight.js";
import {PermsRepo} from "./perms.js";
export { EventRepo } from "./event.js"
@ -11,3 +12,4 @@ 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))

Datei anzeigen

@ -1,11 +1,11 @@
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 {get, writable} from "svelte/store";
import {tokenStore} from "../repo/repo.js";
import {PlayerSchema} from "../types/data.js";
import {z} from "zod";
import {TeamSchema} from "../types/team.js";
import {get, writable} from "svelte/store";
import {permsRepo, tokenStore} from "../repo/repo.js";
import {z} from "zod";
export const schemTypes = cached<SchematicType[]>([], () => {
return fetch("https://steamwar.de/eventplanner-api/data/schematicTypes", {headers: {"X-SW-Auth": get(tokenStore)}})

Datei anzeigen

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

23
src/types/perms.ts Normale Datei
Datei anzeigen

@ -0,0 +1,23 @@
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>;