From 58e737d5cd606a42d98050e8210d7751100680b4 Mon Sep 17 00:00:00 2001 From: Meik Date: Thu, 7 May 2026 23:57:42 +0200 Subject: [PATCH] Automate Paperless webhook setup --- frontend/src/api/config.ts | 10 ++++ frontend/src/locales/de/common.json | 6 +++ frontend/src/locales/en/common.json | 6 +++ frontend/src/routes/Settings.tsx | 30 ++++++++++++ src/index.ts | 48 +++++++++++++++++- src/paperlessClient.ts | 76 +++++++++++++++++++++++++++++ src/runtimeSettings.ts | 9 +++- src/settingsStore.ts | 3 +- 8 files changed, 184 insertions(+), 4 deletions(-) diff --git a/frontend/src/api/config.ts b/frontend/src/api/config.ts index 911f3c9..b547456 100644 --- a/frontend/src/api/config.ts +++ b/frontend/src/api/config.ts @@ -53,6 +53,7 @@ export interface SettingsResponse { aiSystemPrompt: string | null; aiTimeoutSeconds: number; aiMaxTokens: number; + paperlessWorkflowId: number | null; }; secrets: { paperlessTokenSet: boolean; @@ -121,3 +122,12 @@ export async function triggerNtfyTest(): Promise { export async function triggerAiTest(): Promise { await request("/settings/test/ai", { method: "POST" }); } + +export async function setupPaperlessWebhook(): Promise<{ + status: string; + workflowId: number | null; + webhookUrl: string; + settings: SettingsResponse; +}> { + return request("/settings/paperless-webhook/setup", { method: "POST" }); +} diff --git a/frontend/src/locales/de/common.json b/frontend/src/locales/de/common.json index 8398058..910be1f 100644 --- a/frontend/src/locales/de/common.json +++ b/frontend/src/locales/de/common.json @@ -199,6 +199,12 @@ "webhookSecretRemove": "Webhook-Secret löschen", "webhookSecretInfo": "Ein Webhook-Secret ist hinterlegt. Lasse das Feld leer, um es unverändert zu lassen.", "webhookSecretHelp": "Paperless sendet diesen Wert im Header x-contract-companion-secret.", + "webhookSetup": "Paperless automatisch konfigurieren", + "webhookSetupRunning": "Konfiguriere Paperless…", + "webhookSetupSuccess": "Paperless-Workflow konfiguriert (ID {{id}})", + "webhookSetupError": "Paperless-Workflow konnte nicht konfiguriert werden", + "webhookSetupHelp": "Legt ein Secret an und erstellt oder aktualisiert in Paperless den Workflow \"Contract Companion AI Review\".", + "webhookWorkflowInfo": "Paperless-Workflow ID {{id}} ist verknüpft.", "ical": "iCal-Abo", "icalFeedUrl": "Feed-URL", "paperlessApiUrl": "Paperless API URL", diff --git a/frontend/src/locales/en/common.json b/frontend/src/locales/en/common.json index 0a1dc48..a63ebb0 100644 --- a/frontend/src/locales/en/common.json +++ b/frontend/src/locales/en/common.json @@ -199,6 +199,12 @@ "webhookSecretRemove": "Remove webhook secret", "webhookSecretInfo": "A webhook secret is stored. Leave empty to keep it.", "webhookSecretHelp": "Paperless sends this value in the x-contract-companion-secret header.", + "webhookSetup": "Configure Paperless automatically", + "webhookSetupRunning": "Configuring Paperless…", + "webhookSetupSuccess": "Paperless workflow configured (ID {{id}})", + "webhookSetupError": "Unable to configure Paperless workflow", + "webhookSetupHelp": "Creates a secret and creates or updates the Paperless workflow \"Contract Companion AI Review\".", + "webhookWorkflowInfo": "Paperless workflow ID {{id}} is linked.", "ical": "iCal subscription", "icalFeedUrl": "Feed URL", "paperlessApiUrl": "Paperless API URL", diff --git a/frontend/src/routes/Settings.tsx b/frontend/src/routes/Settings.tsx index ac79a8d..2ac508e 100644 --- a/frontend/src/routes/Settings.tsx +++ b/frontend/src/routes/Settings.tsx @@ -35,6 +35,7 @@ import { fetchServerConfig, fetchSettings, resetIcalSecret, + setupPaperlessWebhook, triggerAiTest, triggerMailTest, triggerNtfyTest, @@ -263,6 +264,15 @@ export default function SettingsPage() { onError: (error: Error) => showMessage(error.message ?? t("settings.aiTestError"), "error") }); + const paperlessWebhookSetupMutation = useMutation({ + mutationFn: () => setupPaperlessWebhook(), + onSuccess: async (result) => { + showMessage(t("settings.webhookSetupSuccess", { id: result.workflowId ?? "-" }), "success"); + await Promise.all([refetchSettings(), refetchServerConfig()]); + }, + onError: (error: Error) => showMessage(error.message ?? t("settings.webhookSetupError"), "error") + }); + const createCategoryMutation = useMutation({ mutationFn: (name: string) => apiCreateCategory(name), onSuccess: async (category) => { @@ -858,6 +868,26 @@ export default function SettingsPage() { {t("settings.webhookSecretInfo")} )} + {settingsData?.values.paperlessWorkflowId && ( + + {t("settings.webhookWorkflowInfo", { id: settingsData.values.paperlessWorkflowId })} + + )} + + + {paperlessWebhookSetupMutation.isPending && } + + + {t("settings.webhookSetupHelp")} +