fix: eliminate workflow editing flicker on active-to-draft transitions (#21176)
## Before https://github.com/user-attachments/assets/5108a9d8-2017-41d5-855c-98714cbd4237 ## After https://github.com/user-attachments/assets/0a78d1e1-354f-4f3f-8ec4-6f46517619e4 ## Summary - Fixes visual flickering/glitching in the workflow show page header and canvas when editing an active workflow or discarding a draft - Root cause: SSE events re-added discarded drafts to Apollo cache, and multiple hook instances had independent state causing version oscillation between DRAFT and ACTIVE - Rewrites `useWorkflowWithCurrentVersion` with a module-level `discardedDraftId` variable shared across all instances, Apollo cache seeding in mutation callbacks, and `lastValidResult` caching to prevent null renders ## Test plan - [x] Open a workflow show page with an ACTIVE workflow - [x] Drag a node to change position → verify no flicker, status shows DRAFT smoothly - [x] Discard the draft → verify header does NOT flicker between DRAFT/ACTIVE, position resets cleanly - [x] Click on manual trigger and edit settings → verify the edit works (draft created, settings saved) - [x] Repeat discard + edit cycle multiple times to confirm stability
This commit is contained in:
@@ -1,9 +1,5 @@
|
||||
import { useEffect } from 'react';
|
||||
|
||||
import { useFindOneRecord } from '@/object-record/hooks/useFindOneRecord';
|
||||
import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
|
||||
import { useSetAtomFamilyState } from '@/ui/utilities/state/jotai/hooks/useSetAtomFamilyState';
|
||||
import { shouldWorkflowRefetchRequestFamilyState } from '@/workflow/states/shouldWorkflowRefetchRequestFamilyState';
|
||||
import { useEffectiveDraftVersionId } from '@/workflow/hooks/useEffectiveDraftVersionId';
|
||||
import {
|
||||
type Workflow,
|
||||
type WorkflowVersion,
|
||||
@@ -21,62 +17,45 @@ type WorkflowWithAllVersions = Omit<Workflow, 'versions'> & {
|
||||
export const useWorkflowWithCurrentVersion = (
|
||||
workflowId: string | undefined,
|
||||
): WorkflowWithCurrentVersion | undefined => {
|
||||
const shouldWorkflowRefetchRequest = useAtomFamilyStateValue(
|
||||
shouldWorkflowRefetchRequestFamilyState,
|
||||
workflowId ?? '',
|
||||
);
|
||||
const setShouldWorkflowRefetchRequest = useSetAtomFamilyState(
|
||||
shouldWorkflowRefetchRequestFamilyState,
|
||||
workflowId ?? '',
|
||||
);
|
||||
|
||||
const { record: workflow, refetch: refetchWorkflow } =
|
||||
useFindOneRecord<WorkflowWithAllVersions>({
|
||||
objectNameSingular: CoreObjectNameSingular.Workflow,
|
||||
objectRecordId: workflowId,
|
||||
recordGqlFields: {
|
||||
const { record: workflow } = useFindOneRecord<WorkflowWithAllVersions>({
|
||||
objectNameSingular: CoreObjectNameSingular.Workflow,
|
||||
objectRecordId: workflowId,
|
||||
recordGqlFields: {
|
||||
id: true,
|
||||
name: true,
|
||||
statuses: true,
|
||||
lastPublishedVersionId: true,
|
||||
versions: {
|
||||
id: true,
|
||||
status: true,
|
||||
name: true,
|
||||
statuses: true,
|
||||
lastPublishedVersionId: true,
|
||||
versions: {
|
||||
id: true,
|
||||
status: true,
|
||||
name: true,
|
||||
createdAt: true,
|
||||
},
|
||||
createdAt: true,
|
||||
},
|
||||
skip: !isDefined(workflowId),
|
||||
});
|
||||
},
|
||||
skip: !isDefined(workflowId),
|
||||
});
|
||||
|
||||
useEffect(() => {
|
||||
if (shouldWorkflowRefetchRequest) {
|
||||
setShouldWorkflowRefetchRequest(false);
|
||||
refetchWorkflow();
|
||||
}
|
||||
}, [
|
||||
shouldWorkflowRefetchRequest,
|
||||
setShouldWorkflowRefetchRequest,
|
||||
refetchWorkflow,
|
||||
]);
|
||||
|
||||
const draftVersion = workflow?.versions.find(
|
||||
const draftVersionFromServer = workflow?.versions.find(
|
||||
(workflowVersion) => workflowVersion.status === 'DRAFT',
|
||||
);
|
||||
|
||||
const workflowVersions = [...(workflow?.versions ?? [])];
|
||||
const { effectiveDraftId, lastDiscardedDraftId } = useEffectiveDraftVersionId(
|
||||
draftVersionFromServer,
|
||||
);
|
||||
|
||||
workflowVersions.sort((a, b) => (a.createdAt > b.createdAt ? -1 : 1));
|
||||
const workflowVersions = [...(workflow?.versions ?? [])]
|
||||
.filter((version) => version.id !== lastDiscardedDraftId)
|
||||
.sort((a, b) => (a.createdAt > b.createdAt ? -1 : 1));
|
||||
|
||||
const latestVersion = workflowVersions[0];
|
||||
|
||||
const currentVersionWithoutSteps = draftVersion ?? latestVersion;
|
||||
const currentVersionId = effectiveDraftId ?? latestVersion?.id;
|
||||
|
||||
const { record: currentVersionWithSteps } = useFindOneRecord<WorkflowVersion>(
|
||||
{
|
||||
objectNameSingular: CoreObjectNameSingular.WorkflowVersion,
|
||||
objectRecordId: currentVersionWithoutSteps?.id,
|
||||
skip: !isDefined(currentVersionWithoutSteps?.id),
|
||||
objectRecordId: currentVersionId,
|
||||
skip: !isDefined(currentVersionId),
|
||||
},
|
||||
);
|
||||
|
||||
|
||||
Reference in New Issue
Block a user