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, {