feat: add editing and deleting flags
This commit is contained in:
parent
8b03521382
commit
67d275f15b
2 changed files with 92 additions and 12 deletions
|
@ -7,7 +7,7 @@
|
||||||
import { addToast } from "$lib/toast";
|
import { addToast } from "$lib/toast";
|
||||||
import { encode } from "base64-arraybuffer";
|
import { encode } from "base64-arraybuffer";
|
||||||
import unknownFlag from "./unknown_flag.png";
|
import unknownFlag from "./unknown_flag.png";
|
||||||
import { apiFetchClient } from "$lib/api/fetch";
|
import { apiFetchClient, fastFetchClient } from "$lib/api/fetch";
|
||||||
import ErrorAlert from "$lib/components/ErrorAlert.svelte";
|
import ErrorAlert from "$lib/components/ErrorAlert.svelte";
|
||||||
|
|
||||||
const MAX_FLAG_BYTES = 500_000;
|
const MAX_FLAG_BYTES = 500_000;
|
||||||
|
@ -18,11 +18,13 @@
|
||||||
let error: APIError | null = null;
|
let error: APIError | null = null;
|
||||||
|
|
||||||
let filtered: PrideFlag[];
|
let filtered: PrideFlag[];
|
||||||
$: filtered = search
|
$: filtered = filterFlags(search, data.flags);
|
||||||
? data.flags.filter((flag) =>
|
|
||||||
flag.name.toLocaleLowerCase().includes(search.toLocaleLowerCase()),
|
const filterFlags = (search: string, flags: PrideFlag[]) => {
|
||||||
)
|
return search
|
||||||
: data.flags;
|
? flags.filter((flag) => flag.name.toLocaleLowerCase().includes(search.toLocaleLowerCase()))
|
||||||
|
: flags;
|
||||||
|
};
|
||||||
|
|
||||||
// NEW FLAG UPLOADING CODE
|
// NEW FLAG UPLOADING CODE
|
||||||
let modalOpen = false;
|
let modalOpen = false;
|
||||||
|
@ -81,6 +83,20 @@
|
||||||
error = e as APIError;
|
error = e as APIError;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
// DELETE FLAG CODE
|
||||||
|
const deleteFlag = async (id: string) => {
|
||||||
|
try {
|
||||||
|
await fastFetchClient(`/users/@me/flags/${id}`, "DELETE");
|
||||||
|
|
||||||
|
error = null;
|
||||||
|
|
||||||
|
addToast({ header: "Deleted flag", body: "Successfully deleted flag!" });
|
||||||
|
data.flags = data.flags.filter((entry) => entry.id !== id);
|
||||||
|
} catch (e) {
|
||||||
|
error = e as APIError;
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<h1>Pride flags ({data.flags.length})</h1>
|
<h1>Pride flags ({data.flags.length})</h1>
|
||||||
|
@ -98,13 +114,13 @@
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
<div class="p-2">
|
<div class="p-2">
|
||||||
{#each filtered as flag}
|
{#each filtered as flag (flag.id)}
|
||||||
<Flag {flag} />
|
<Flag bind:flag {deleteFlag} />
|
||||||
{:else}
|
{:else}
|
||||||
{#if data.flags.length === 0}
|
{#if data.flags.length === 0}
|
||||||
You haven't uploaded any flags yet, press the button above to do so.
|
You haven't uploaded any flags yet, press the button above to do so.
|
||||||
{:else}
|
{:else}
|
||||||
There are no flags matching your search <strong>{search}</strong>
|
There are no flags matching your search <strong>{search}</strong>.
|
||||||
{/if}
|
{/if}
|
||||||
{/each}
|
{/each}
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -1,15 +1,75 @@
|
||||||
<script lang="ts">
|
<script lang="ts">
|
||||||
import { flagURL, type PrideFlag } from "$lib/api/entities";
|
import { flagURL, type APIError, type PrideFlag } from "$lib/api/entities";
|
||||||
import { Button } from "sveltestrap";
|
import { apiFetchClient } from "$lib/api/fetch";
|
||||||
|
import { addToast } from "$lib/toast";
|
||||||
|
import { Button, Input, Modal, ModalBody, ModalFooter, ModalHeader } from "sveltestrap";
|
||||||
|
|
||||||
export let flag: PrideFlag;
|
export let flag: PrideFlag;
|
||||||
|
export let deleteFlag: (id: string) => Promise<void>;
|
||||||
|
|
||||||
|
let error: APIError | null = null;
|
||||||
|
|
||||||
|
let modalOpen = false;
|
||||||
|
const toggleModal = () => (modalOpen = !modalOpen);
|
||||||
|
|
||||||
|
let deleteModalOpen = false;
|
||||||
|
const toggleDeleteModal = () => (deleteModalOpen = !deleteModalOpen);
|
||||||
|
|
||||||
|
let name = flag.name;
|
||||||
|
let description = flag.description;
|
||||||
|
|
||||||
|
const updateFlag = async () => {
|
||||||
|
try {
|
||||||
|
const resp = await apiFetchClient<PrideFlag>(`/users/@me/flags/${flag.id}`, "PATCH", {
|
||||||
|
name,
|
||||||
|
description: description || null,
|
||||||
|
});
|
||||||
|
|
||||||
|
error = null;
|
||||||
|
flag = resp;
|
||||||
|
|
||||||
|
addToast({ header: "Updated flag", body: "Successfully updated flag!" });
|
||||||
|
toggleModal();
|
||||||
|
} catch (e) {
|
||||||
|
error = e as APIError;
|
||||||
|
}
|
||||||
|
};
|
||||||
</script>
|
</script>
|
||||||
|
|
||||||
<Button outline class="m-1">
|
<Button outline class="m-1" on:click={toggleModal}>
|
||||||
<img class="flag" src={flagURL(flag)} alt={flag.description ?? flag.name} />
|
<img class="flag" src={flagURL(flag)} alt={flag.description ?? flag.name} />
|
||||||
{flag.name}
|
{flag.name}
|
||||||
</Button>
|
</Button>
|
||||||
|
|
||||||
|
<Modal isOpen={modalOpen} toggle={toggleModal}>
|
||||||
|
<ModalHeader toggle={toggleModal}>Edit {flag.name} flag</ModalHeader>
|
||||||
|
<ModalBody>
|
||||||
|
<p>
|
||||||
|
<label for="name" class="form-label">Name</label>
|
||||||
|
<Input id="name" bind:value={name} />
|
||||||
|
</p>
|
||||||
|
<p>
|
||||||
|
<label for="description" class="form-label">Description</label>
|
||||||
|
<textarea id="description" class="form-control" bind:value={description} />
|
||||||
|
</p>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button color="danger" on:click={toggleDeleteModal}>Delete flag</Button>
|
||||||
|
<Button disabled={!name} color="success" on:click={() => updateFlag()}>Edit flag</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
|
<Modal isOpen={deleteModalOpen} toggle={toggleDeleteModal}>
|
||||||
|
<ModalHeader toggle={toggleDeleteModal}>Delete {flag.name} flag</ModalHeader>
|
||||||
|
<ModalBody>
|
||||||
|
Are you sure you want to delete the {flag.name} flag? <strong>This cannot be undone!</strong>
|
||||||
|
</ModalBody>
|
||||||
|
<ModalFooter>
|
||||||
|
<Button color="danger" on:click={() => deleteFlag(flag.id)}>Delete flag</Button>
|
||||||
|
<Button color="secondary" on:click={toggleDeleteModal}>Cancel</Button>
|
||||||
|
</ModalFooter>
|
||||||
|
</Modal>
|
||||||
|
|
||||||
<style>
|
<style>
|
||||||
.flag {
|
.flag {
|
||||||
height: 2rem;
|
height: 2rem;
|
||||||
|
@ -17,4 +77,8 @@
|
||||||
border-radius: 3px;
|
border-radius: 3px;
|
||||||
margin-left: -5px;
|
margin-left: -5px;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
textarea {
|
||||||
|
height: 100px;
|
||||||
|
}
|
||||||
</style>
|
</style>
|
||||||
|
|
Loading…
Reference in a new issue