From 9d0f1819eca2bd8faf96e4d2a6ee89b40d0ea2ae Mon Sep 17 00:00:00 2001 From: JzoNg Date: Wed, 3 Jun 2026 14:41:13 +0800 Subject: [PATCH] fix(web): do not sync draft when readonly --- .../__tests__/snippet-main.spec.tsx | 21 ++++++++++++++++++- .../snippets/components/snippet-main.tsx | 14 +++++++++++-- 2 files changed, 32 insertions(+), 3 deletions(-) diff --git a/web/app/components/snippets/components/__tests__/snippet-main.spec.tsx b/web/app/components/snippets/components/__tests__/snippet-main.spec.tsx index ad11a1d4436..aa7f2664997 100644 --- a/web/app/components/snippets/components/__tests__/snippet-main.spec.tsx +++ b/web/app/components/snippets/components/__tests__/snippet-main.spec.tsx @@ -9,6 +9,7 @@ import SnippetMain from '../snippet-main' const mockSyncInputFieldsDraft = vi.fn() const mockDoSyncWorkflowDraft = vi.fn() +const mockSyncWorkflowDraftWhenPageClose = vi.fn() const mockReset = vi.fn() const mockSetFields = vi.fn() const mockPublishSnippetMutateAsync = vi.fn() @@ -98,7 +99,7 @@ vi.mock('@/app/components/snippets/hooks/use-nodes-sync-draft', () => ({ useNodesSyncDraft: () => ({ doSyncWorkflowDraft: mockDoSyncWorkflowDraft, syncInputFieldsDraft: mockSyncInputFieldsDraft, - syncWorkflowDraftWhenPageClose: vi.fn(), + syncWorkflowDraftWhenPageClose: mockSyncWorkflowDraftWhenPageClose, }), })) @@ -369,6 +370,24 @@ describe('SnippetMain', () => { expect(mockSyncInputFieldsDraft).not.toHaveBeenCalled() }) + it('should not sync draft from workflow autosave while readonly', async () => { + renderSnippetMain({ hasInitialDraftChanges: true }) + + fireEvent.click(screen.getByRole('button', { name: 'exit without save' })) + await waitFor(() => { + expect(screen.getByRole('button', { name: 'edit' })).toBeInTheDocument() + }) + mockDoSyncWorkflowDraft.mockClear() + + const doSyncWorkflowDraft = capturedHooksStore?.doSyncWorkflowDraft as (() => Promise) + const syncWorkflowDraftWhenPageClose = capturedHooksStore?.syncWorkflowDraftWhenPageClose as (() => void) + await doSyncWorkflowDraft() + syncWorkflowDraftWhenPageClose() + + expect(mockDoSyncWorkflowDraft).not.toHaveBeenCalled() + expect(mockSyncWorkflowDraftWhenPageClose).not.toHaveBeenCalled() + }) + it('should skip forced draft sync caused by re-entering editing mode', async () => { renderSnippetMain({ hasInitialDraftChanges: true }) diff --git a/web/app/components/snippets/components/snippet-main.tsx b/web/app/components/snippets/components/snippet-main.tsx index bf184236e92..410189071f0 100644 --- a/web/app/components/snippets/components/snippet-main.tsx +++ b/web/app/components/snippets/components/snippet-main.tsx @@ -388,6 +388,9 @@ const SnippetMain = ({ const doSyncWorkflowDraft = useCallback(( ...args: Parameters ) => { + if (!isEditing) + return Promise.resolve() + const [ notRefreshWhenSyncError, callback, @@ -403,6 +406,13 @@ const SnippetMain = ({ return syncWorkflowDraft(...args) }, [isEditing, setHasDraftChanges, syncWorkflowDraft]) + const syncWorkflowDraftWhenPageCloseInEditing = useCallback(() => { + if (!isEditing) + return + + syncWorkflowDraftWhenPageClose() + }, [isEditing, syncWorkflowDraftWhenPageClose]) + const handleFieldsChangeInEditing = useCallback((nextFields: SnippetInputField[]) => { handleFieldsChange(nextFields) setHasDraftChanges(true) @@ -488,7 +498,7 @@ const SnippetMain = ({ const hooksStore = useMemo(() => { return { doSyncWorkflowDraft, - syncWorkflowDraftWhenPageClose, + syncWorkflowDraftWhenPageClose: syncWorkflowDraftWhenPageCloseInEditing, handleRefreshWorkflowDraft, handleBackupDraft, handleLoadBackupDraft, @@ -544,7 +554,7 @@ const SnippetMain = ({ renameInspectVarName, resetConversationVar, resetToLastRunVar, - syncWorkflowDraftWhenPageClose, + syncWorkflowDraftWhenPageCloseInEditing, ]) return (