From 7ea5bdb2171ee54a9c9703c74a6ed1fe4d008c21 Mon Sep 17 00:00:00 2001 From: Albrecht Degering Date: Mon, 20 Jul 2026 20:08:00 +0200 Subject: [PATCH] fix(campaign-ui): make discard restore server state --- .../components/CampaignDraftPageScaffold.tsx | 2 +- .../campaigns/hooks/useCampaignDraftEditor.ts | 22 +++++++++++++++---- .../hooks/useCampaignWorkspaceData.ts | 8 ++++--- 3 files changed, 24 insertions(+), 8 deletions(-) diff --git a/webui/src/features/campaigns/components/CampaignDraftPageScaffold.tsx b/webui/src/features/campaigns/components/CampaignDraftPageScaffold.tsx index 826d107..51519bd 100644 --- a/webui/src/features/campaigns/components/CampaignDraftPageScaffold.tsx +++ b/webui/src/features/campaigns/components/CampaignDraftPageScaffold.tsx @@ -50,7 +50,7 @@ export default function CampaignDraftPageScaffold({
- +
diff --git a/webui/src/features/campaigns/hooks/useCampaignDraftEditor.ts b/webui/src/features/campaigns/hooks/useCampaignDraftEditor.ts index 0b3e0ba..2cf6e6a 100644 --- a/webui/src/features/campaigns/hooks/useCampaignDraftEditor.ts +++ b/webui/src/features/campaigns/hooks/useCampaignDraftEditor.ts @@ -12,7 +12,7 @@ type UseCampaignDraftEditorOptions = { campaignId: string; version: CampaignVersionDetail | null; locked: boolean; - reload: () => Promise; + reload: (options?: {force?: boolean;}) => Promise; setError: (message: string) => void; currentStep: StepValue; currentFlow?: string; @@ -124,12 +124,25 @@ export function useCampaignDraftEditor({ } }, [campaignId, currentFlow, currentStep, draft, extraPayload, isComplete, locked, onSaved, reload, setError, settings, version, workflowState]); + const discardDraft = useCallback(async () => { + if (version) { + const initialDraft = ensureCampaignDraft(version); + const loadedDraft = transformLoadedDraftRef.current?.(version, initialDraft) ?? initialDraft; + setDraft(loadedDraft); + setDirty(false); + setLocalError(""); + setSaveState(loadedLabelRef.current(version)); + onLoadedRef.current?.(version, loadedDraft); + } + await reload({ force: true }); + }, [reload, version]); + const unsavedRegistration = useMemo(() => dirty && !locked ? { title: unsavedTitle, message: unsavedMessage, onSave: () => saveDraft("manual"), - onDiscard: () => setDirty(false) - } : null, [dirty, locked, saveDraft, unsavedMessage, unsavedTitle]); + onDiscard: () => { void discardDraft(); } + } : null, [dirty, discardDraft, locked, saveDraft, unsavedMessage, unsavedTitle]); useRegisterCampaignUnsavedChanges(unsavedRegistration); @@ -145,6 +158,7 @@ export function useCampaignDraftEditor({ setLocalError, patch, markDirty, + discardDraft, saveDraft }; -} \ No newline at end of file +} diff --git a/webui/src/features/campaigns/hooks/useCampaignWorkspaceData.ts b/webui/src/features/campaigns/hooks/useCampaignWorkspaceData.ts index dd6b647..2d446a3 100644 --- a/webui/src/features/campaigns/hooks/useCampaignWorkspaceData.ts +++ b/webui/src/features/campaigns/hooks/useCampaignWorkspaceData.ts @@ -52,14 +52,16 @@ export function useCampaignWorkspaceData( [campaignId, selectedVersionId, includeCurrentVersion, includeSummary, includeVersions, settings.apiBaseUrl, settings.apiKey, settings.accessToken] ); - const reload = useCallback(async () => { + const reload = useCallback(async (options?: {force?: boolean;}) => { if (!campaignId) return; + const force = options?.force === true; setLoading(true); setError(""); try { const shouldLoadVersions = includeCurrentVersion || includeVersions; - let nextWatermark = getDeltaWatermark(queryKey); - let merged: CampaignWorkspaceData = dataRef.current; + if (force) resetDeltaWatermark(queryKey); + let nextWatermark = force ? null : getDeltaWatermark(queryKey); + let merged: CampaignWorkspaceData = force ? initialData : dataRef.current; let hasMore = false; do { const response = await getCampaignWorkspaceDelta(settings, campaignId, {