204 lines
7.0 KiB
Svelte
204 lines
7.0 KiB
Svelte
<script lang="ts">
|
||
import type { PageProps } from './$types';
|
||
let { data, form }: PageProps = $props();
|
||
|
||
function confirmTaxonomyRemoval(event: SubmitEvent) {
|
||
if (!confirm('Eintrag wirklich entfernen?')) event.preventDefault();
|
||
}
|
||
</script>
|
||
|
||
<svelte:head><title>Verwaltung | Sendewerk</title></svelte:head>
|
||
|
||
<div class="page-wrap narrow-page">
|
||
<header class="page-heading">
|
||
<h1>Verwaltung</h1>
|
||
<p class="page-intro">Konten, Rollen und bestehende Taxonomie verwalten.</p>
|
||
</header>
|
||
{#if form?.error}<div class="form-message error" role="alert">{form.error}</div>{/if}
|
||
{#if form?.success}<div class="form-message success" role="status">{form.success}</div>{/if}
|
||
|
||
<section class="quiet-panel account-panel">
|
||
<div class="panel-heading">
|
||
<div>
|
||
<p class="eyebrow">Konten & Rollen</p>
|
||
<h2>Redaktionszugänge</h2>
|
||
</div>
|
||
<span class="mail-mode"
|
||
>Mail: {data.mailTransport === 'local' ? 'lokale Outbox' : 'SMTP'}</span
|
||
>
|
||
</div>
|
||
<div class="account-list">
|
||
{#each data.users as user (user.id)}
|
||
<article class="account-row">
|
||
<div><strong>{user.displayName}</strong><small>{user.email}</small></div>
|
||
<span class:locked={user.lockedAtUtc} class="account-status"
|
||
>{user.lockedAtUtc ? 'Gesperrt' : 'Aktiv'}</span
|
||
>
|
||
<form method="POST" action="?/role" class="inline-account-form">
|
||
<input type="hidden" name="userId" value={user.id} />
|
||
<label class="sr-only" for={`role-${user.id}`}>Rolle für {user.displayName}</label>
|
||
<select id={`role-${user.id}`} name="role">
|
||
<option value="barkeeper" selected={user.role === 'barkeeper'}>Barkeeper</option>
|
||
<option value="thekencrew" selected={user.role === 'thekencrew'}>Thekencrew</option>
|
||
</select>
|
||
<button class="text-button" type="submit">Rolle speichern</button>
|
||
</form>
|
||
<form method="POST" action={user.lockedAtUtc ? '?/unlock' : '?/lock'}>
|
||
<input type="hidden" name="userId" value={user.id} />
|
||
<button
|
||
class="secondary-button"
|
||
type="submit"
|
||
disabled={user.id === data.user?.id}
|
||
title={user.id === data.user?.id
|
||
? 'Das eigene Konto kann nicht gesperrt werden.'
|
||
: undefined}
|
||
>{user.lockedAtUtc
|
||
? 'Entsperren'
|
||
: user.id === data.user?.id
|
||
? 'Eigenes Konto'
|
||
: 'Sperren'}</button
|
||
>
|
||
</form>
|
||
</article>
|
||
{/each}
|
||
</div>
|
||
</section>
|
||
|
||
<div class="management-grid">
|
||
<section class="quiet-panel invite-panel">
|
||
<p class="eyebrow">Einladung</p>
|
||
<h2>Neues Konto einladen</h2>
|
||
<form class="compact-form" method="POST" action="?/invite">
|
||
<label
|
||
>E-Mail<input
|
||
name="email"
|
||
type="email"
|
||
required
|
||
maxlength="254"
|
||
value={form?.intent === 'invite' ? (form.email ?? '') : ''}
|
||
/></label
|
||
>
|
||
<label
|
||
>Rolle<select name="role"
|
||
><option value="thekencrew">Thekencrew</option><option value="barkeeper"
|
||
>Barkeeper</option
|
||
></select
|
||
></label
|
||
>
|
||
<button class="primary-button" type="submit">Einladung erstellen</button>
|
||
</form>
|
||
</section>
|
||
<section class="quiet-panel invite-panel">
|
||
<p class="eyebrow">Offene Einladungen</p>
|
||
<h2>Noch nicht angenommen</h2>
|
||
{#if data.invitations.length}
|
||
<div class="invitation-list">
|
||
{#each data.invitations as invitation (invitation.id)}
|
||
<div>
|
||
<span
|
||
><strong>{invitation.email}</strong><small
|
||
>{invitation.role === 'barkeeper' ? 'Barkeeper' : 'Thekencrew'}</small
|
||
></span
|
||
>
|
||
<form method="POST" action="?/revokeInvitation">
|
||
<input type="hidden" name="invitationId" value={invitation.id} /><button
|
||
class="text-button"
|
||
type="submit">Widerrufen</button
|
||
>
|
||
</form>
|
||
</div>
|
||
{/each}
|
||
</div>
|
||
{:else}<p class="quiet-copy">Keine offenen Einladungen.</p>{/if}
|
||
</section>
|
||
</div>
|
||
|
||
<h2 class="section-heading">Taxonomie</h2>
|
||
<div class="settings-grid">
|
||
<section class="quiet-panel taxonomy-panel">
|
||
<p class="eyebrow">Abschnittskategorien</p>
|
||
<h2>Struktur im Ablauf</h2>
|
||
<div class="taxonomy-list editable-taxonomy">
|
||
{#each data.taxonomy.categories as category (category.id)}<span
|
||
><i style={`--tax-color: ${category.color}`}></i>{category.name}
|
||
<form method="POST" action="?/deleteTaxonomy" onsubmit={confirmTaxonomyRemoval}>
|
||
<input type="hidden" name="kind" value="category" /><input
|
||
type="hidden"
|
||
name="taxonomyId"
|
||
value={category.id}
|
||
/><button type="submit" aria-label={`${category.name} entfernen`}>×</button>
|
||
</form></span
|
||
>{/each}
|
||
</div>
|
||
<form class="taxonomy-form" method="POST" action="?/createTaxonomy">
|
||
<input type="hidden" name="kind" value="category" /><label
|
||
><span class="sr-only">Neue Abschnittskategorie</span><input
|
||
name="name"
|
||
required
|
||
maxlength="80"
|
||
placeholder="Neue Kategorie"
|
||
/></label
|
||
><label class="color-field"
|
||
><span class="sr-only">Farbe</span><input
|
||
name="color"
|
||
type="color"
|
||
value="#67DDE8"
|
||
/></label
|
||
><button class="text-button" type="submit">Hinzufügen</button>
|
||
</form>
|
||
</section>
|
||
<section class="quiet-panel taxonomy-panel">
|
||
<p class="eyebrow">Formate</p>
|
||
<h2>Form des Stücks</h2>
|
||
<div class="taxonomy-list editable-taxonomy">
|
||
{#each data.taxonomy.formats as format (format.id)}<span
|
||
>{format.name}
|
||
<form method="POST" action="?/deleteTaxonomy" onsubmit={confirmTaxonomyRemoval}>
|
||
<input type="hidden" name="kind" value="format" /><input
|
||
type="hidden"
|
||
name="taxonomyId"
|
||
value={format.id}
|
||
/><button type="submit" aria-label={`${format.name} entfernen`}>×</button>
|
||
</form></span
|
||
>{/each}
|
||
</div>
|
||
<form class="taxonomy-form" method="POST" action="?/createTaxonomy">
|
||
<input type="hidden" name="kind" value="format" /><label
|
||
><span class="sr-only">Neues Format</span><input
|
||
name="name"
|
||
required
|
||
maxlength="80"
|
||
placeholder="Neues Format"
|
||
/></label
|
||
><button class="text-button" type="submit">Hinzufügen</button>
|
||
</form>
|
||
</section>
|
||
<section class="quiet-panel taxonomy-panel">
|
||
<p class="eyebrow">Themen</p>
|
||
<h2>Inhaltliche Zuordnung</h2>
|
||
<div class="taxonomy-list editable-taxonomy">
|
||
{#each data.taxonomy.topics as topic (topic.id)}<span
|
||
>{topic.name}
|
||
<form method="POST" action="?/deleteTaxonomy" onsubmit={confirmTaxonomyRemoval}>
|
||
<input type="hidden" name="kind" value="topic" /><input
|
||
type="hidden"
|
||
name="taxonomyId"
|
||
value={topic.id}
|
||
/><button type="submit" aria-label={`${topic.name} entfernen`}>×</button>
|
||
</form></span
|
||
>{/each}
|
||
</div>
|
||
<form class="taxonomy-form" method="POST" action="?/createTaxonomy">
|
||
<input type="hidden" name="kind" value="topic" /><label
|
||
><span class="sr-only">Neues Thema</span><input
|
||
name="name"
|
||
required
|
||
maxlength="80"
|
||
placeholder="Neues Thema"
|
||
/></label
|
||
><button class="text-button" type="submit">Hinzufügen</button>
|
||
</form>
|
||
</section>
|
||
</div>
|
||
</div>
|