diff --git a/frontend/src/routes/geschichten/+page.server.ts b/frontend/src/routes/geschichten/+page.server.ts new file mode 100644 index 00000000..66e3fdf1 --- /dev/null +++ b/frontend/src/routes/geschichten/+page.server.ts @@ -0,0 +1,36 @@ +import { error } from '@sveltejs/kit'; +import { createApiClient } from '$lib/api.server'; +import { getErrorMessage } from '$lib/errors'; +import type { PageServerLoad } from './$types'; + +export const load: PageServerLoad = async ({ url, fetch }) => { + const api = createApiClient(fetch); + const personId = url.searchParams.get('personId') ?? undefined; + const documentId = url.searchParams.get('documentId') ?? undefined; + + const [listResult, personResult] = await Promise.all([ + api.GET('/api/geschichten', { + params: { + query: { + status: 'PUBLISHED', + personId, + documentId + } + } + }), + personId + ? api.GET('/api/persons/{id}', { params: { path: { id: personId } } }) + : Promise.resolve(null) + ]); + + if (!listResult.response.ok) { + const code = (listResult.error as unknown as { code?: string })?.code; + throw error(listResult.response.status, getErrorMessage(code)); + } + + return { + geschichten: listResult.data ?? [], + personFilter: personResult && personResult.response.ok ? personResult.data! : null, + documentFilter: documentId ?? null + }; +}; diff --git a/frontend/src/routes/geschichten/+page.svelte b/frontend/src/routes/geschichten/+page.svelte new file mode 100644 index 00000000..d85aeab3 --- /dev/null +++ b/frontend/src/routes/geschichten/+page.svelte @@ -0,0 +1,130 @@ + + +
+
+

{m.geschichten_index_title()}

+ {#if data.canBlogWrite} + + {m.geschichten_new_button()} + + {/if} +
+ + +
+ + + {#if data.personFilter} + + {:else} + + {/if} +
+ + {#if showPersonPicker} +
+ +
+ {/if} + + + {#if data.geschichten.length === 0} +
+ {#if data.personFilter} + {m.geschichten_empty_for_person({ name: filterName })} + {:else} + {m.geschichten_empty_no_filter()} + {/if} +
+ {:else} + + {/if} +
diff --git a/frontend/src/routes/geschichten/[id]/+page.server.ts b/frontend/src/routes/geschichten/[id]/+page.server.ts new file mode 100644 index 00000000..bb4b3314 --- /dev/null +++ b/frontend/src/routes/geschichten/[id]/+page.server.ts @@ -0,0 +1,16 @@ +import { error } from '@sveltejs/kit'; +import { createApiClient } from '$lib/api.server'; +import { getErrorMessage } from '$lib/errors'; +import type { PageServerLoad } from './$types'; + +export const load: PageServerLoad = async ({ params, fetch }) => { + const api = createApiClient(fetch); + const result = await api.GET('/api/geschichten/{id}', { + params: { path: { id: params.id } } + }); + if (!result.response.ok) { + const code = (result.error as unknown as { code?: string })?.code; + throw error(result.response.status, getErrorMessage(code)); + } + return { geschichte: result.data! }; +}; diff --git a/frontend/src/routes/geschichten/[id]/+page.svelte b/frontend/src/routes/geschichten/[id]/+page.svelte new file mode 100644 index 00000000..e96af176 --- /dev/null +++ b/frontend/src/routes/geschichten/[id]/+page.svelte @@ -0,0 +1,133 @@ + + +
+
+ +
+ +
+
+

+ {g.title} +

+

+ {authorName()} + {#if publishedAt}· {m.geschichten_published_on({ date: publishedAt })}{/if} +

+
+ +
+ + + {@html sanitized} +
+
+ + + {#if g.persons && g.persons.length > 0} +
+

+ {m.geschichten_persons_section()} +

+ +
+ {/if} + + + {#if g.documents && g.documents.length > 0} +
+

+ {m.geschichten_documents_section()} +

+ +
+ {/if} + + + {#if data.canBlogWrite} +
+ + {m.btn_edit()} + + +
+ {/if} +
diff --git a/frontend/src/routes/geschichten/[id]/edit/+page.server.ts b/frontend/src/routes/geschichten/[id]/edit/+page.server.ts new file mode 100644 index 00000000..7d397921 --- /dev/null +++ b/frontend/src/routes/geschichten/[id]/edit/+page.server.ts @@ -0,0 +1,20 @@ +import { error, redirect } from '@sveltejs/kit'; +import { createApiClient } from '$lib/api.server'; +import { getErrorMessage } from '$lib/errors'; +import type { PageServerLoad } from './$types'; + +export const load: PageServerLoad = async ({ params, fetch, parent }) => { + const layout = await parent(); + if (!layout.canBlogWrite) { + throw redirect(303, `/geschichten/${params.id}`); + } + const api = createApiClient(fetch); + const result = await api.GET('/api/geschichten/{id}', { + params: { path: { id: params.id } } + }); + if (!result.response.ok) { + const code = (result.error as unknown as { code?: string })?.code; + throw error(result.response.status, getErrorMessage(code)); + } + return { geschichte: result.data! }; +}; diff --git a/frontend/src/routes/geschichten/[id]/edit/+page.svelte b/frontend/src/routes/geschichten/[id]/edit/+page.svelte new file mode 100644 index 00000000..80bf0bf7 --- /dev/null +++ b/frontend/src/routes/geschichten/[id]/edit/+page.svelte @@ -0,0 +1,60 @@ + + +
+
+ +
+ +

+ {m.btn_edit()}: {data.geschichte.title} +

+ + {#if errorMessage} + + {/if} + + +
diff --git a/frontend/src/routes/geschichten/new/+page.server.ts b/frontend/src/routes/geschichten/new/+page.server.ts new file mode 100644 index 00000000..66f748e8 --- /dev/null +++ b/frontend/src/routes/geschichten/new/+page.server.ts @@ -0,0 +1,33 @@ +import { redirect } from '@sveltejs/kit'; +import { createApiClient } from '$lib/api.server'; +import type { PageServerLoad } from './$types'; + +export const load: PageServerLoad = async ({ url, fetch, parent }) => { + const layout = await parent(); + if (!layout.canBlogWrite) { + throw redirect(303, '/geschichten'); + } + + const api = createApiClient(fetch); + const personId = url.searchParams.get('personId'); + const documentId = url.searchParams.get('documentId'); + + const [personResult, documentResult] = await Promise.all([ + personId + ? api.GET('/api/persons/{id}', { params: { path: { id: personId } } }) + : Promise.resolve(null), + documentId + ? api.GET('/api/documents/{id}', { params: { path: { id: documentId } } }) + : Promise.resolve(null) + ]); + + // Silently ignore 404/403 to avoid leaking entity existence on unknown IDs. + const initialPersons = + personResult && personResult.response.ok && personResult.data ? [personResult.data] : []; + const initialDocuments = + documentResult && documentResult.response.ok && documentResult.data + ? [documentResult.data] + : []; + + return { initialPersons, initialDocuments }; +}; diff --git a/frontend/src/routes/geschichten/new/+page.svelte b/frontend/src/routes/geschichten/new/+page.svelte new file mode 100644 index 00000000..57f9cf49 --- /dev/null +++ b/frontend/src/routes/geschichten/new/+page.svelte @@ -0,0 +1,64 @@ + + +
+
+ +
+ +

{m.geschichten_new_button()}

+ + {#if errorMessage} + + {/if} + + +