feat(frontend): add System tab to admin panel with backfill-versions action
Some checks failed
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Successful in 2m13s
CI / Backend Unit Tests (pull_request) Successful in 2m17s
CI / E2E Tests (pull_request) Failing after 22m45s
Some checks failed
CI / Backend Unit Tests (push) Has been cancelled
CI / E2E Tests (push) Has been cancelled
CI / Unit & Component Tests (push) Has been cancelled
CI / Unit & Component Tests (pull_request) Successful in 2m13s
CI / Backend Unit Tests (pull_request) Successful in 2m17s
CI / E2E Tests (pull_request) Failing after 22m45s
Admin can trigger an initial history snapshot for all documents without version history. Shows count of backfilled documents after completion. Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
This commit is contained in:
@@ -233,5 +233,10 @@
|
||||
"history_field_summary": "Zusammenfassung",
|
||||
"history_field_sender": "Absender",
|
||||
"history_field_receivers": "Empfänger",
|
||||
"history_field_tags": "Schlagworte"
|
||||
"history_field_tags": "Schlagworte",
|
||||
"admin_tab_system": "System",
|
||||
"admin_system_backfill_heading": "Verlaufsdaten auffüllen",
|
||||
"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."
|
||||
}
|
||||
|
||||
@@ -233,5 +233,10 @@
|
||||
"history_field_summary": "Summary",
|
||||
"history_field_sender": "Sender",
|
||||
"history_field_receivers": "Receivers",
|
||||
"history_field_tags": "Tags"
|
||||
"history_field_tags": "Tags",
|
||||
"admin_tab_system": "System",
|
||||
"admin_system_backfill_heading": "Backfill history data",
|
||||
"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."
|
||||
}
|
||||
|
||||
@@ -233,5 +233,10 @@
|
||||
"history_field_summary": "Resumen",
|
||||
"history_field_sender": "Remitente",
|
||||
"history_field_receivers": "Destinatarios",
|
||||
"history_field_tags": "Etiquetas"
|
||||
"history_field_tags": "Etiquetas",
|
||||
"admin_tab_system": "Sistema",
|
||||
"admin_system_backfill_heading": "Completar datos de historial",
|
||||
"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."
|
||||
}
|
||||
|
||||
@@ -228,6 +228,22 @@ export interface paths {
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/admin/backfill-versions": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
get?: never;
|
||||
put?: never;
|
||||
post: operations["backfillVersions"];
|
||||
delete?: never;
|
||||
options?: never;
|
||||
head?: never;
|
||||
patch?: never;
|
||||
trace?: never;
|
||||
};
|
||||
"/api/groups/{id}": {
|
||||
parameters: {
|
||||
query?: never;
|
||||
@@ -548,6 +564,10 @@ export interface components {
|
||||
/** Format: date-time */
|
||||
startedAt?: string;
|
||||
};
|
||||
BackfillResult: {
|
||||
/** Format: int32 */
|
||||
count: number;
|
||||
};
|
||||
DocumentVersionSummary: {
|
||||
/** Format: uuid */
|
||||
id: string;
|
||||
@@ -1106,6 +1126,26 @@ export interface operations {
|
||||
};
|
||||
};
|
||||
};
|
||||
backfillVersions: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
header?: never;
|
||||
path?: never;
|
||||
cookie?: never;
|
||||
};
|
||||
requestBody?: never;
|
||||
responses: {
|
||||
/** @description OK */
|
||||
200: {
|
||||
headers: {
|
||||
[name: string]: unknown;
|
||||
};
|
||||
content: {
|
||||
"*/*": components["schemas"]["BackfillResult"];
|
||||
};
|
||||
};
|
||||
};
|
||||
};
|
||||
deleteGroup: {
|
||||
parameters: {
|
||||
query?: never;
|
||||
|
||||
@@ -9,6 +9,8 @@ let activeTab = $state('users');
|
||||
let editingTagId: string | null = $state(null);
|
||||
let editingTagName = $state('');
|
||||
let editingGroupId: string | null = $state(null);
|
||||
let backfillResult: number | null = $state(null);
|
||||
let backfillLoading = $state(false);
|
||||
|
||||
const availablePermissions = ['WRITE_ALL', 'ADMIN', 'ADMIN_USER', 'ADMIN_TAG', 'ADMIN_PERMISSION'];
|
||||
|
||||
@@ -29,6 +31,20 @@ function startEditGroup(id: string) {
|
||||
function cancelEditGroup() {
|
||||
editingGroupId = null;
|
||||
}
|
||||
|
||||
async function backfillVersions() {
|
||||
backfillLoading = true;
|
||||
backfillResult = null;
|
||||
try {
|
||||
const res = await fetch('/api/admin/backfill-versions', { method: 'POST' });
|
||||
if (res.ok) {
|
||||
const data = await res.json();
|
||||
backfillResult = data.count;
|
||||
}
|
||||
} finally {
|
||||
backfillLoading = false;
|
||||
}
|
||||
}
|
||||
</script>
|
||||
|
||||
<div class="mx-auto max-w-7xl py-8 font-sans sm:px-6 lg:px-8">
|
||||
@@ -58,6 +74,13 @@ function cancelEditGroup() {
|
||||
: 'text-gray-500 hover:text-brand-navy'}"
|
||||
onclick={() => (activeTab = 'tags')}>{m.admin_tab_tags()}</button
|
||||
>
|
||||
<button
|
||||
class="rounded-md px-4 py-2 text-sm font-bold tracking-wide uppercase transition {activeTab ===
|
||||
'system'
|
||||
? 'bg-brand-navy text-white'
|
||||
: 'text-gray-500 hover:text-brand-navy'}"
|
||||
onclick={() => (activeTab = 'system')}>{m.admin_tab_system()}</button
|
||||
>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
@@ -495,5 +518,22 @@ function cancelEditGroup() {
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
{:else if activeTab === 'system'}
|
||||
<div class="rounded-sm border border-brand-sand bg-white p-6 shadow-sm">
|
||||
<h2 class="mb-1 text-lg font-bold text-gray-700">{m.admin_system_backfill_heading()}</h2>
|
||||
<p class="mb-4 text-sm text-gray-500">{m.admin_system_backfill_description()}</p>
|
||||
<button
|
||||
onclick={backfillVersions}
|
||||
disabled={backfillLoading}
|
||||
class="rounded bg-brand-navy px-6 py-2 text-sm font-bold text-white uppercase transition hover:bg-brand-mint hover:text-brand-navy disabled:cursor-not-allowed disabled:opacity-50"
|
||||
>
|
||||
{backfillLoading ? '…' : m.admin_system_backfill_btn()}
|
||||
</button>
|
||||
{#if backfillResult !== null}
|
||||
<p class="mt-4 text-sm font-medium text-brand-navy">
|
||||
{m.admin_system_backfill_success({ count: backfillResult })}
|
||||
</p>
|
||||
{/if}
|
||||
</div>
|
||||
{/if}
|
||||
</div>
|
||||
|
||||
Reference in New Issue
Block a user