Release 0.6.0
This commit is contained in:
1 parent
fd47910d09
commit
b80dded55d
40 files changed
+4080
-856
No files matched your search
@@ -8,6 +8,9 @@ import {
|
||||
type TaxonomyKind
|
||||
} from '#lib/server/content.js';
|
||||
import { getMailConfig } from '#lib/server/config.js';
|
||||
import { createShare, deleteShare, listShares, updateShare } from '#lib/server/shares.js';
|
||||
import { listShows } from '#lib/server/shows.js';
|
||||
import { berlinLocalToUtc } from '#lib/server/time.js';
|
||||
import { createTool, listTools, updateTool, type ToolInput } from '#lib/server/tools.js';
|
||||
import {
|
||||
inviteUser,
|
||||
@@ -28,6 +31,8 @@ export const load: PageServerLoad = ({ locals }) => {
|
||||
users: listUsers(),
|
||||
invitations: listOpenInvitations(),
|
||||
tools: listTools(true),
|
||||
shows: listShows(),
|
||||
shares: listShares(locals.user!),
|
||||
mailTransport: getMailConfig().transport
|
||||
};
|
||||
};
|
||||
@@ -50,6 +55,10 @@ function actionError(cause: unknown): string {
|
||||
if (code === 'INVALID_TOOL_FORMAT')
|
||||
return 'Mindestens ein gewähltes Format existiert nicht mehr.';
|
||||
if (code === 'INVALID_TOOL') return 'Bitte die Werkzeugdaten prüfen.';
|
||||
if (code === 'INVALID_PASSWORD') return 'Ein Freigabepasswort benötigt mindestens 12 Zeichen.';
|
||||
if (code === 'INVALID_EXPIRY') return 'Der Ablaufzeitpunkt muss in der Zukunft liegen.';
|
||||
if (code === 'INVALID_SCOPE') return 'Der Informationsumfang ist ungültig.';
|
||||
if (code === 'INVALID_PASSWORD_MODE') return 'Die Passwortoption ist ungültig.';
|
||||
return 'Die Aktion konnte nicht ausgeführt werden.';
|
||||
}
|
||||
|
||||
@@ -65,6 +74,50 @@ function toolInput(data: FormData): ToolInput {
|
||||
}
|
||||
|
||||
export const actions = {
|
||||
createShare: async ({ locals, request }) => {
|
||||
const actor = requireBarkeeper(locals.user);
|
||||
const data = await request.formData();
|
||||
try {
|
||||
const share = await createShare(actor, {
|
||||
showId: String(data.get('showId') || ''),
|
||||
scope: String(data.get('scope') || ''),
|
||||
password: String(data.get('password') || ''),
|
||||
expiresAtUtc: berlinLocalToUtc(String(data.get('expiresAt') || ''), 'INVALID_EXPIRY')
|
||||
});
|
||||
return {
|
||||
intent: 'createShare',
|
||||
success: 'Leselink angelegt. Der Link wird nur jetzt vollständig angezeigt.',
|
||||
shareUrl: `/freigabe/${share.token}`
|
||||
};
|
||||
} catch (cause) {
|
||||
return fail(400, { intent: 'createShare', error: actionError(cause) });
|
||||
}
|
||||
},
|
||||
updateShare: async ({ locals, request }) => {
|
||||
const actor = requireBarkeeper(locals.user);
|
||||
const data = await request.formData();
|
||||
try {
|
||||
await updateShare(actor, String(data.get('shareId') || ''), {
|
||||
scope: String(data.get('scope') || ''),
|
||||
passwordMode: String(data.get('passwordMode') || ''),
|
||||
password: String(data.get('password') || ''),
|
||||
expiresAtUtc: berlinLocalToUtc(String(data.get('expiresAt') || ''), 'INVALID_EXPIRY')
|
||||
});
|
||||
return { intent: 'updateShare', success: 'Freigabe aktualisiert.' };
|
||||
} catch (cause) {
|
||||
return fail(400, { intent: 'updateShare', error: actionError(cause) });
|
||||
}
|
||||
},
|
||||
deleteShare: async ({ locals, request }) => {
|
||||
const actor = requireBarkeeper(locals.user);
|
||||
const data = await request.formData();
|
||||
try {
|
||||
deleteShare(actor, String(data.get('shareId') || ''));
|
||||
return { intent: 'deleteShare', success: 'Freigabe gelöscht.' };
|
||||
} catch (cause) {
|
||||
return fail(400, { intent: 'deleteShare', error: actionError(cause) });
|
||||
}
|
||||
},
|
||||
invite: async ({ locals, request }) => {
|
||||
const actor = requireBarkeeper(locals.user);
|
||||
const data = await request.formData();
|
||||
|
||||
@@ -1,6 +1,7 @@
|
||||
<script lang="ts">
|
||||
import AppIcon from '#lib/components/AppIcon.svelte';
|
||||
import IconPicker from '#lib/components/IconPicker.svelte';
|
||||
import ShareManagement from '#lib/components/ShareManagement.svelte';
|
||||
import ToolEditorDialog from '#lib/components/ToolEditorDialog.svelte';
|
||||
import type { PageProps } from './$types';
|
||||
let { data, form }: PageProps = $props();
|
||||
@@ -18,8 +19,19 @@
|
||||
<h1>Verwaltung</h1>
|
||||
<p class="page-intro">Konten, Werkzeuge 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}
|
||||
{#if form?.error && !form.intent?.toLowerCase().includes('share')}<div
|
||||
class="form-message error"
|
||||
role="alert"
|
||||
>
|
||||
{form.error}
|
||||
</div>{/if}
|
||||
{#if form?.success && !form.intent?.toLowerCase().includes('share')}<div
|
||||
class="form-message success"
|
||||
role="status"
|
||||
>
|
||||
{form.success}
|
||||
</div>{/if}
|
||||
<ShareManagement shows={data.shows} shares={data.shares} {form} />
|
||||
|
||||
<section class="quiet-panel account-panel">
|
||||
<div class="panel-heading">
|
||||
|
||||
Reference in new issue
Block a user