restructure: flatten workspace nesting, move devcontainer to root
- backend/workspaces/backend/ → backend/ - backend/workspaces/frontend/ → frontend/ - backend/.devcontainer/ + .vscode/ → repo root (where VS Code expects them) - loose scripts/SQL files → scripts/ - replace nested git repo with single repo at project root - update docker-compose.yml build context and devcontainer.json path - add root .gitignore Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
49
frontend/src/routes/documents/[id]/edit/+page.server.ts
Normal file
49
frontend/src/routes/documents/[id]/edit/+page.server.ts
Normal file
@@ -0,0 +1,49 @@
|
||||
import { error, redirect } from '@sveltejs/kit';
|
||||
import { env } from '$env/dynamic/private';
|
||||
|
||||
export async function load({ params, fetch }) {
|
||||
const { id } = params;
|
||||
|
||||
|
||||
const baseUrl = 'http://localhost:8080';
|
||||
|
||||
try {
|
||||
// Parallel Dokument und Personen laden
|
||||
const [docRes, personsRes] = await Promise.all([
|
||||
fetch(`${baseUrl}/api/documents/${id}`),
|
||||
fetch(`${baseUrl}/api/persons`)
|
||||
]);
|
||||
|
||||
if (!docRes.ok) throw error(docRes.status, 'Dokument nicht gefunden');
|
||||
if (!personsRes.ok) throw error(personsRes.status, 'Personen konnten nicht geladen werden');
|
||||
|
||||
return {
|
||||
document: await docRes.json(),
|
||||
persons: await personsRes.json()
|
||||
};
|
||||
} catch (e) {
|
||||
console.error(e);
|
||||
throw error(500, 'Ladefehler');
|
||||
}
|
||||
}
|
||||
|
||||
export const actions = {
|
||||
default: async ({ request, params, fetch }) => {
|
||||
const baseUrl = env.API_INTERNAL_URL || 'http://localhost:8080';
|
||||
|
||||
const formData = await request.formData();
|
||||
|
||||
// Sende den FormData Request direkt an das Spring Backend weiter
|
||||
// (Spring kann Multipart verarbeiten)
|
||||
const res = await fetch(`${baseUrl}/api/documents/${params.id}`, {
|
||||
method: "PUT",
|
||||
body: formData
|
||||
});
|
||||
|
||||
if (!res.ok) {
|
||||
return { success: false, message: 'Speichern fehlgeschlagen' };
|
||||
}
|
||||
|
||||
throw redirect(303, `/documents/${params.id}`);
|
||||
}
|
||||
};
|
||||
190
frontend/src/routes/documents/[id]/edit/+page.svelte
Normal file
190
frontend/src/routes/documents/[id]/edit/+page.svelte
Normal file
@@ -0,0 +1,190 @@
|
||||
<script lang="ts">
|
||||
import { enhance } from '$app/forms';
|
||||
import TagInput from '$lib/components/TagInput.svelte';
|
||||
export let data;
|
||||
export let form; // Rückgabe der Action (Fehler etc.)
|
||||
|
||||
let { document: doc, persons } = data;
|
||||
let tags = doc.tags ? doc.tags.map(t => t.name) : [];
|
||||
</script>
|
||||
|
||||
<div class="max-w-4xl mx-auto p-6 bg-white shadow mt-10 rounded-lg">
|
||||
<h1 class="text-2xl font-bold mb-6">Dokument bearbeiten</h1>
|
||||
|
||||
{#if form?.message}
|
||||
<div class="bg-red-100 text-red-700 p-3 rounded mb-4">{form.message}</div>
|
||||
{/if}
|
||||
|
||||
<form method="POST" enctype="multipart/form-data" use:enhance class="space-y-6">
|
||||
<!-- Datei Austausch -->
|
||||
<div class="bg-blue-50 p-4 rounded border border-blue-100">
|
||||
<label for="file-upload" class="block text-sm font-medium text-gray-700 mb-2"
|
||||
>Datei ersetzen (optional)</label
|
||||
>
|
||||
<div class="flex items-center gap-4">
|
||||
<span class="text-xs text-gray-500">Aktuell: {doc.originalFilename}</span>
|
||||
<!-- ID hinzugefügt -->
|
||||
<input
|
||||
id="file-upload"
|
||||
type="file"
|
||||
name="file"
|
||||
class="block w-full text-sm text-gray-500
|
||||
file:mr-4 file:py-2 file:px-4
|
||||
file:rounded-full file:border-0
|
||||
file:text-sm file:font-semibold
|
||||
file:bg-blue-50 file:text-blue-700
|
||||
hover:file:bg-blue-100"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<div class="grid grid-cols-1 md:grid-cols-2 gap-6">
|
||||
<!-- Titel -->
|
||||
<div>
|
||||
<label for="title" class="block text-sm font-medium text-gray-700">Titel</label>
|
||||
<!-- ID hinzugefügt -->
|
||||
<input
|
||||
id="title"
|
||||
type="text"
|
||||
name="title"
|
||||
value={doc.title || ''}
|
||||
required
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm focus:border-blue-500 focus:ring-blue-500"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label for="documentLocation" class="block text-sm font-medium text-gray-700"
|
||||
>Dokumentenort</label
|
||||
>
|
||||
<!-- ID hinzugefügt -->
|
||||
<input
|
||||
id="documentLocation"
|
||||
type="text"
|
||||
name="documentLocation"
|
||||
value={doc.documentLocation || ''}
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Datum -->
|
||||
<div>
|
||||
<label for="documentDate" class="block text-sm font-medium text-gray-700">Datum</label>
|
||||
<!-- ID hinzugefügt -->
|
||||
<input
|
||||
id="documentDate"
|
||||
type="text"
|
||||
name="documentDate"
|
||||
value={doc.documentDate || ''}
|
||||
placeholder="YYYY-MM-DD"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm"
|
||||
/>
|
||||
</div>
|
||||
|
||||
<!-- Ort -->
|
||||
<div>
|
||||
<label for="location" class="block text-sm font-medium text-gray-700">Ort</label>
|
||||
<!-- ID hinzugefügt -->
|
||||
<input
|
||||
id="location"
|
||||
type="text"
|
||||
name="location"
|
||||
value={doc.location || ''}
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm"
|
||||
/>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Sender -->
|
||||
<div>
|
||||
<label for="senderId" class="block text-sm font-medium text-gray-700">Absender</label>
|
||||
<!-- ID hinzugefügt -->
|
||||
<select
|
||||
id="senderId"
|
||||
name="senderId"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm"
|
||||
>
|
||||
<option value="">-- Unbekannt --</option>
|
||||
{#each persons as person}
|
||||
<option value={person.id} selected={doc.sender?.id === person.id}>
|
||||
{person.firstName}
|
||||
{person.lastName}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<!-- Empfänger (Multi-Select) -->
|
||||
<div>
|
||||
<label for="receiverIds" class="block text-sm font-medium text-gray-700"
|
||||
>Empfänger (Strg+Klick für mehrere)</label
|
||||
>
|
||||
<!-- ID hinzugefügt -->
|
||||
<select
|
||||
id="receiverIds"
|
||||
name="receiverIds"
|
||||
multiple
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm h-32"
|
||||
>
|
||||
{#each persons as person}
|
||||
<option value={person.id} selected={doc.receivers?.some((r) => r.id === person.id)}>
|
||||
{person.firstName}
|
||||
{person.lastName}
|
||||
</option>
|
||||
{/each}
|
||||
</select>
|
||||
</div>
|
||||
|
||||
<div>
|
||||
<label class="block text-sm font-bold text-brand-navy uppercase tracking-widest mb-2">
|
||||
Schlagworte
|
||||
</label>
|
||||
<TagInput bind:tags />
|
||||
<input type="hidden" name="tags" value={tags.join(',')} />
|
||||
</div>
|
||||
|
||||
<!-- Inhalt -->
|
||||
<div>
|
||||
<label for="summary" class="block text-sm font-medium text-gray-700">Inhalt</label>
|
||||
<!-- ID hinzugefügt -->
|
||||
<textarea
|
||||
id="summary"
|
||||
name="summary"
|
||||
rows="2"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm font-serif"
|
||||
>{doc.summary || ''}</textarea
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Transkription -->
|
||||
<div>
|
||||
<label for="transcription" class="block text-sm font-medium text-gray-700"
|
||||
>Transkription</label
|
||||
>
|
||||
<!-- ID hinzugefügt -->
|
||||
<textarea
|
||||
id="transcription"
|
||||
name="transcription"
|
||||
rows="10"
|
||||
class="mt-1 block w-full rounded-md border-gray-300 shadow-sm font-serif"
|
||||
>{doc.transcription || ''}</textarea
|
||||
>
|
||||
</div>
|
||||
|
||||
<!-- Buttons -->
|
||||
<div class="flex justify-end gap-4">
|
||||
<a
|
||||
href="/documents/{doc.id}"
|
||||
class="px-4 py-2 border border-gray-300 rounded-md text-sm font-medium text-gray-700 hover:bg-gray-50"
|
||||
>
|
||||
Abbrechen
|
||||
</a>
|
||||
<button
|
||||
type="submit"
|
||||
class="px-4 py-2 border border-transparent rounded-md shadow-sm text-sm font-medium text-white bg-blue-600 hover:bg-blue-700"
|
||||
>
|
||||
Speichern
|
||||
</button>
|
||||
</div>
|
||||
</form>
|
||||
</div>
|
||||
Reference in New Issue
Block a user