progress bar + better ui (fix)

This commit is contained in:
Ludwig Lehnert
2026-03-27 20:10:51 +01:00
parent 83fbeff16c
commit 085d5e26cf
3 changed files with 35 additions and 15 deletions

View File

@@ -77,7 +77,13 @@ export function UploadProgressForm({ csrfToken }) {
} }
return ( return (
<form className="form-grid" onSubmit={handleSubmit} encType="multipart/form-data"> <form
className="form-grid"
onSubmit={handleSubmit}
action="/manage/api/upload"
method="post"
encType="multipart/form-data"
>
<input type="hidden" name="csrfToken" value={csrfToken} /> <input type="hidden" name="csrfToken" value={csrfToken} />
<label className="field"> <label className="field">

View File

@@ -101,38 +101,57 @@ function dashboardHref(params = {}) {
: `${managementBasePath}/dashboard`; : `${managementBasePath}/dashboard`;
} }
function jsonError(message, status = 400) { function expectsHtml(request) {
return String(request.headers.get('accept') || '').includes('text/html');
}
function errorResponse(request, message, status = 400) {
if (expectsHtml(request)) {
const target = new URL(dashboardHref({ error: message }), request.url);
return NextResponse.redirect(target, { status: 303 });
}
return NextResponse.json({ ok: false, error: message }, { status }); return NextResponse.json({ ok: false, error: message }, { status });
} }
function successResponse(request, message) {
const redirectPath = dashboardHref({ success: message });
if (expectsHtml(request)) {
const target = new URL(redirectPath, request.url);
return NextResponse.redirect(target, { status: 303 });
}
return NextResponse.json({ ok: true, redirect: redirectPath });
}
export async function POST(request) { export async function POST(request) {
await runCleanupIfNeeded(); await runCleanupIfNeeded();
const user = await getAuthenticatedUser(); const user = await getAuthenticatedUser();
if (!user) { if (!user) {
return jsonError('Nicht angemeldet.', 401); return errorResponse(request, 'Nicht angemeldet.', 401);
} }
let formData; let formData;
try { try {
formData = await request.formData(); formData = await request.formData();
} catch { } catch {
return jsonError('Ungültige Formulardaten.', 400); return errorResponse(request, 'Ungültige Formulardaten.', 400);
} }
try { try {
await verifyCsrf(formData); await verifyCsrf(formData);
} catch { } catch {
return jsonError('CSRF-Prüfung fehlgeschlagen.', 403); return errorResponse(request, 'CSRF-Prüfung fehlgeschlagen.', 403);
} }
const uploadedFile = uploadedFileFromForm(formData, 'file'); const uploadedFile = uploadedFileFromForm(formData, 'file');
if (!uploadedFile || Number(uploadedFile.size || 0) <= 0) { if (!uploadedFile || Number(uploadedFile.size || 0) <= 0) {
return jsonError('Keine Datei hochgeladen.', 400); return errorResponse(request, 'Keine Datei hochgeladen.', 400);
} }
if (maxUploadBytes > 0 && Number(uploadedFile.size || 0) > maxUploadBytes) { if (maxUploadBytes > 0 && Number(uploadedFile.size || 0) > maxUploadBytes) {
return jsonError(`Datei überschreitet das Größenlimit (${maxUploadBytes} Bytes).`, 413); return errorResponse(request, `Datei überschreitet das Größenlimit (${maxUploadBytes} Bytes).`, 413);
} }
const now = Date.now(); const now = Date.now();
@@ -156,7 +175,7 @@ export async function POST(request) {
} }
if (!storedName || !storedPath) { if (!storedName || !storedPath) {
return jsonError('Upload-ID konnte nicht erzeugt werden.', 500); return errorResponse(request, 'Upload-ID konnte nicht erzeugt werden.', 500);
} }
try { try {
@@ -183,11 +202,8 @@ export async function POST(request) {
await getRequestMeta() await getRequestMeta()
); );
} catch { } catch {
return jsonError('Upload fehlgeschlagen.', 500); return errorResponse(request, 'Upload fehlgeschlagen.', 500);
} }
return NextResponse.json({ return successResponse(request, 'Upload abgeschlossen.');
ok: true,
redirect: dashboardHref({ success: 'Upload abgeschlossen.' }),
});
} }

View File

@@ -153,7 +153,6 @@ export async function clearAuthCookie() {
export async function requireAuthenticatedUser() { export async function requireAuthenticatedUser() {
const user = await getAuthenticatedUser(); const user = await getAuthenticatedUser();
if (!user) { if (!user) {
await clearAuthCookie();
redirect('/manage/login'); redirect('/manage/login');
} }
return user; return user;
@@ -162,7 +161,6 @@ export async function requireAuthenticatedUser() {
export async function requireAdminUser() { export async function requireAdminUser() {
const user = await getAuthenticatedUser(); const user = await getAuthenticatedUser();
if (!user || !user.admin) { if (!user || !user.admin) {
await clearAuthCookie();
redirect('/manage/admin'); redirect('/manage/admin');
} }
return user; return user;