From 00195dc8db59e90e0a7417da1aa8f431cb190237 Mon Sep 17 00:00:00 2001 From: Marcel Date: Tue, 24 Mar 2026 17:33:01 +0100 Subject: [PATCH] feat(frontend): add backfill file hashes card to admin System tab - System tab gains a second card with a 'Datei-Hashes berechnen' button that calls POST /api/admin/backfill-file-hashes and shows the updated count - i18n: admin_system_backfill_hashes_* keys added in de/en/es - E2E: test verifies the button triggers the backfill and shows the success message Closes #56 Co-Authored-By: Claude Sonnet 4.6 --- frontend/e2e/admin.spec.ts | 32 ++++++++++++++++++++++++++++++++ frontend/messages/de.json | 4 ++++ frontend/messages/en.json | 4 ++++ frontend/messages/es.json | 4 ++++ 4 files changed, 44 insertions(+) diff --git a/frontend/e2e/admin.spec.ts b/frontend/e2e/admin.spec.ts index 1ffd6f59..57682eec 100644 --- a/frontend/e2e/admin.spec.ts +++ b/frontend/e2e/admin.spec.ts @@ -216,3 +216,35 @@ test.describe('Admin — tag management', () => { await page.screenshot({ path: 'test-results/e2e/admin-tag-restored.png' }); }); }); + +// ─── System tab — backfill file hashes ──────────────────────────────────────── + +test.describe('Admin system tab — backfill file hashes', () => { + test('admin triggers file hash backfill and sees success message', async ({ request, page }) => { + test.setTimeout(60_000); + + // Create a document via API so there is at least one without a hash + const createRes = await request.post('/api/documents', { + multipart: { title: 'E2E Backfill Hash Test' } + }); + if (!createRes.ok()) throw new Error(`Create failed: ${createRes.status()}`); + + await page.goto('/admin'); + await page.waitForSelector('[data-hydrated]'); + + // Navigate to System tab + await page.getByRole('button', { name: /system/i }).click(); + + // Click the backfill hashes button + const btn = page.getByRole('button', { name: /datei-hashes berechnen/i }); + await expect(btn).toBeVisible(); + await btn.click(); + + // Success message must appear (count >= 0) + await expect(page.locator('text=/\\d+ Dokumente wurden aktualisiert/i')).toBeVisible({ + timeout: 15000 + }); + + await page.screenshot({ path: 'test-results/e2e/admin-backfill-hashes.png' }); + }); +}); diff --git a/frontend/messages/de.json b/frontend/messages/de.json index bc1aa5b2..86a31481 100644 --- a/frontend/messages/de.json +++ b/frontend/messages/de.json @@ -242,6 +242,10 @@ "admin_system_backfill_description": "Erstellt einen initialen Verlaufseintrag für alle Dokumente, die noch keinen Verlauf haben (z.B. importierte Dokumente). Dadurch werden beim nächsten Bearbeiten nur die tatsächlich geänderten Felder hervorgehoben.", "admin_system_backfill_btn": "Jetzt auffüllen", "admin_system_backfill_success": "{count} Dokumente wurden aufgefüllt.", + "admin_system_backfill_hashes_heading": "Datei-Hashes berechnen", + "admin_system_backfill_hashes_description": "Berechnet den SHA-256-Hash für alle bereits hochgeladenen Dokumente, die noch keinen Hash haben. Dadurch werden Annotationen korrekt mit ihrer Dateiversion verknüpft und wieder angezeigt.", + "admin_system_backfill_hashes_btn": "Datei-Hashes berechnen", + "admin_system_backfill_hashes_success": "{count} Dokumente wurden aktualisiert.", "comp_expandable_show_more": "Mehr anzeigen", "comp_expandable_show_less": "Weniger anzeigen", "error_comment_not_found": "Der Kommentar wurde nicht gefunden.", diff --git a/frontend/messages/en.json b/frontend/messages/en.json index 6ca3148b..b9060841 100644 --- a/frontend/messages/en.json +++ b/frontend/messages/en.json @@ -242,6 +242,10 @@ "admin_system_backfill_description": "Creates an initial history entry for all documents that do not have one yet (e.g. imported documents). This ensures that future edits only highlight actually changed fields.", "admin_system_backfill_btn": "Backfill now", "admin_system_backfill_success": "{count} documents were backfilled.", + "admin_system_backfill_hashes_heading": "Compute file hashes", + "admin_system_backfill_hashes_description": "Computes the SHA-256 hash for all previously uploaded documents that do not have one yet. This ensures annotations are correctly linked to their file version and shown again.", + "admin_system_backfill_hashes_btn": "Compute file hashes", + "admin_system_backfill_hashes_success": "{count} documents were updated.", "comp_expandable_show_more": "Show more", "comp_expandable_show_less": "Show less", "error_comment_not_found": "The comment could not be found.", diff --git a/frontend/messages/es.json b/frontend/messages/es.json index 4d8bf77a..db645b43 100644 --- a/frontend/messages/es.json +++ b/frontend/messages/es.json @@ -242,6 +242,10 @@ "admin_system_backfill_description": "Crea una entrada de historial inicial para todos los documentos que aún no tienen ninguna (p.ej. documentos importados). Así, en la próxima edición solo se resaltarán los campos realmente modificados.", "admin_system_backfill_btn": "Completar ahora", "admin_system_backfill_success": "{count} documentos fueron completados.", + "admin_system_backfill_hashes_heading": "Calcular hashes de archivo", + "admin_system_backfill_hashes_description": "Calcula el hash SHA-256 para todos los documentos ya subidos que aún no tienen uno. Así las anotaciones se vinculan correctamente a su versión del archivo y vuelven a mostrarse.", + "admin_system_backfill_hashes_btn": "Calcular hashes de archivo", + "admin_system_backfill_hashes_success": "{count} documentos fueron actualizados.", "comp_expandable_show_more": "Mostrar más", "comp_expandable_show_less": "Mostrar menos", "error_comment_not_found": "El comentario no pudo encontrarse.",