Continue workflow folders re-ordering (#9315)
- put actions in steps - move hooks - move states
This commit is contained in:
@ -2,10 +2,10 @@ import { useListenRightDrawerClose } from '@/ui/layout/right-drawer/hooks/useLis
|
||||
import { isRightDrawerMinimizedState } from '@/ui/layout/right-drawer/states/isRightDrawerMinimizedState';
|
||||
import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState';
|
||||
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
|
||||
import { workflowReactFlowRefState } from '@/workflow/states/workflowReactFlowRefState';
|
||||
import { WorkflowVersionStatus } from '@/workflow/types/Workflow';
|
||||
import { WorkflowVersionStatusTag } from '@/workflow/workflow-diagram/components/WorkflowVersionStatusTag';
|
||||
import { workflowDiagramState } from '@/workflow/workflow-diagram/states/workflowDiagramState';
|
||||
import { workflowReactFlowRefState } from '@/workflow/workflow-diagram/states/workflowReactFlowRefState';
|
||||
import {
|
||||
WorkflowDiagram,
|
||||
WorkflowDiagramEdge,
|
||||
|
||||
@ -2,11 +2,11 @@ import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
|
||||
import { RightDrawerHotkeyScope } from '@/ui/layout/right-drawer/types/RightDrawerHotkeyScope';
|
||||
import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages';
|
||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||
import { useStartNodeCreation } from '@/workflow/hooks/useStartNodeCreation';
|
||||
import { useTriggerNodeSelection } from '@/workflow/hooks/useTriggerNodeSelection';
|
||||
import { workflowSelectedNodeState } from '@/workflow/states/workflowSelectedNodeState';
|
||||
import { CREATE_STEP_STEP_ID } from '@/workflow/workflow-diagram/constants/CreateStepStepId';
|
||||
import { EMPTY_TRIGGER_STEP_ID } from '@/workflow/workflow-diagram/constants/EmptyTriggerStepId';
|
||||
import { useStartNodeCreation } from '@/workflow/workflow-diagram/hooks/useStartNodeCreation';
|
||||
import { useTriggerNodeSelection } from '@/workflow/workflow-diagram/hooks/useTriggerNodeSelection';
|
||||
import { workflowSelectedNodeState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeState';
|
||||
import { WorkflowDiagramNode } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { OnSelectionChangeParams, useOnSelectionChange } from '@xyflow/react';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
@ -2,8 +2,8 @@ import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
|
||||
import { RightDrawerHotkeyScope } from '@/ui/layout/right-drawer/types/RightDrawerHotkeyScope';
|
||||
import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages';
|
||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||
import { useTriggerNodeSelection } from '@/workflow/hooks/useTriggerNodeSelection';
|
||||
import { workflowSelectedNodeState } from '@/workflow/states/workflowSelectedNodeState';
|
||||
import { useTriggerNodeSelection } from '@/workflow/workflow-diagram/hooks/useTriggerNodeSelection';
|
||||
import { workflowSelectedNodeState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeState';
|
||||
import { WorkflowDiagramNode } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { OnSelectionChangeParams, useOnSelectionChange } from '@xyflow/react';
|
||||
import { useCallback } from 'react';
|
||||
|
||||
@ -1,9 +1,9 @@
|
||||
import { useDeleteStep } from '@/workflow/hooks/useDeleteStep';
|
||||
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
|
||||
import { workflowIdState } from '@/workflow/states/workflowIdState';
|
||||
import { assertWorkflowWithCurrentVersionIsDefined } from '@/workflow/utils/assertWorkflowWithCurrentVersionIsDefined';
|
||||
import { WorkflowDiagramStepNodeBase } from '@/workflow/workflow-diagram/components/WorkflowDiagramStepNodeBase';
|
||||
import { WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { useDeleteStep } from '@/workflow/workflow-steps/hooks/useDeleteStep';
|
||||
import { useRecoilValue } from 'recoil';
|
||||
import { FloatingIconButton, IconTrash } from 'twenty-ui';
|
||||
|
||||
|
||||
@ -0,0 +1,65 @@
|
||||
import { useTriggerNodeSelection } from '@/workflow/workflow-diagram/hooks/useTriggerNodeSelection';
|
||||
import { workflowDiagramTriggerNodeSelectionState } from '@/workflow/workflow-diagram/states/workflowDiagramTriggerNodeSelectionState';
|
||||
import { act, renderHook } from '@testing-library/react';
|
||||
import { useReactFlow } from '@xyflow/react';
|
||||
import { RecoilRoot, useRecoilState } from 'recoil';
|
||||
|
||||
jest.mock('@xyflow/react', () => ({
|
||||
useReactFlow: jest.fn(),
|
||||
}));
|
||||
|
||||
const wrapper = ({ children }: { children: React.ReactNode }) => (
|
||||
<RecoilRoot>{children}</RecoilRoot>
|
||||
);
|
||||
|
||||
describe('useTriggerNodeSelection', () => {
|
||||
const mockSetNodes = jest.fn();
|
||||
|
||||
beforeEach(() => {
|
||||
(useReactFlow as jest.Mock).mockReturnValue({
|
||||
setNodes: mockSetNodes,
|
||||
});
|
||||
});
|
||||
|
||||
afterEach(() => {
|
||||
jest.clearAllMocks();
|
||||
});
|
||||
|
||||
it('should trigger node selection', () => {
|
||||
const { result } = renderHook(
|
||||
() => {
|
||||
const [
|
||||
workflowDiagramTriggerNodeSelection,
|
||||
setWorkflowDiagramTriggerNodeSelection,
|
||||
] = useRecoilState(workflowDiagramTriggerNodeSelectionState);
|
||||
|
||||
useTriggerNodeSelection();
|
||||
|
||||
return {
|
||||
workflowDiagramTriggerNodeSelection,
|
||||
setWorkflowDiagramTriggerNodeSelection,
|
||||
};
|
||||
},
|
||||
{
|
||||
wrapper,
|
||||
},
|
||||
);
|
||||
|
||||
const mockNodeId = 'test-node-id';
|
||||
|
||||
act(() => {
|
||||
result.current.setWorkflowDiagramTriggerNodeSelection(mockNodeId);
|
||||
});
|
||||
|
||||
expect(result.current.workflowDiagramTriggerNodeSelection).toBeUndefined();
|
||||
});
|
||||
|
||||
it('should not trigger update if state is not defined', () => {
|
||||
renderHook(() => useTriggerNodeSelection(), {
|
||||
wrapper,
|
||||
});
|
||||
|
||||
// Ensure updateNode is not called when state is undefined
|
||||
expect(mockSetNodes).not.toHaveBeenCalled();
|
||||
});
|
||||
});
|
||||
@ -0,0 +1,33 @@
|
||||
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
|
||||
import { RightDrawerHotkeyScope } from '@/ui/layout/right-drawer/types/RightDrawerHotkeyScope';
|
||||
import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages';
|
||||
import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope';
|
||||
import { workflowCreateStepFromParentStepIdState } from '@/workflow/workflow-steps/states/workflowCreateStepFromParentStepIdState';
|
||||
import { useCallback } from 'react';
|
||||
import { useSetRecoilState } from 'recoil';
|
||||
|
||||
export const useStartNodeCreation = () => {
|
||||
const { openRightDrawer } = useRightDrawer();
|
||||
const setWorkflowCreateStepFromParentStepId = useSetRecoilState(
|
||||
workflowCreateStepFromParentStepIdState,
|
||||
);
|
||||
const setHotkeyScope = useSetHotkeyScope();
|
||||
|
||||
/**
|
||||
* This function is used in a context where dependencies shouldn't change much.
|
||||
* That's why its wrapped in a `useCallback` hook. Removing memoization might break the app unexpectedly.
|
||||
*/
|
||||
const startNodeCreation = useCallback(
|
||||
(parentNodeId: string) => {
|
||||
setWorkflowCreateStepFromParentStepId(parentNodeId);
|
||||
|
||||
setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false });
|
||||
openRightDrawer(RightDrawerPages.WorkflowStepSelectAction);
|
||||
},
|
||||
[openRightDrawer, setWorkflowCreateStepFromParentStepId, setHotkeyScope],
|
||||
);
|
||||
|
||||
return {
|
||||
startNodeCreation,
|
||||
};
|
||||
};
|
||||
@ -0,0 +1,37 @@
|
||||
import { workflowDiagramTriggerNodeSelectionState } from '@/workflow/workflow-diagram/states/workflowDiagramTriggerNodeSelectionState';
|
||||
import {
|
||||
WorkflowDiagramEdge,
|
||||
WorkflowDiagramNode,
|
||||
} from '@/workflow/workflow-diagram/types/WorkflowDiagram';
|
||||
import { useReactFlow } from '@xyflow/react';
|
||||
import { useEffect } from 'react';
|
||||
import { useRecoilState } from 'recoil';
|
||||
import { isDefined } from 'twenty-ui';
|
||||
|
||||
export const useTriggerNodeSelection = () => {
|
||||
const reactflow = useReactFlow<WorkflowDiagramNode, WorkflowDiagramEdge>();
|
||||
|
||||
const [
|
||||
workflowDiagramTriggerNodeSelection,
|
||||
setWorkflowDiagramTriggerNodeSelection,
|
||||
] = useRecoilState(workflowDiagramTriggerNodeSelectionState);
|
||||
|
||||
useEffect(() => {
|
||||
if (!isDefined(workflowDiagramTriggerNodeSelection)) {
|
||||
return;
|
||||
}
|
||||
|
||||
reactflow.setNodes((nodes) =>
|
||||
nodes.map((node) => ({
|
||||
...node,
|
||||
selected: workflowDiagramTriggerNodeSelection === node.id,
|
||||
})),
|
||||
);
|
||||
|
||||
setWorkflowDiagramTriggerNodeSelection(undefined);
|
||||
}, [
|
||||
reactflow,
|
||||
setWorkflowDiagramTriggerNodeSelection,
|
||||
workflowDiagramTriggerNodeSelection,
|
||||
]);
|
||||
};
|
||||
@ -0,0 +1,8 @@
|
||||
import { createState } from '@ui/utilities/state/utils/createState';
|
||||
|
||||
export const workflowDiagramTriggerNodeSelectionState = createState<
|
||||
string | undefined
|
||||
>({
|
||||
key: 'workflowDiagramTriggerNodeSelectionState',
|
||||
defaultValue: undefined,
|
||||
});
|
||||
@ -0,0 +1,8 @@
|
||||
import { createState } from '@ui/utilities/state/utils/createState';
|
||||
import { RefObject } from 'react';
|
||||
|
||||
export const workflowReactFlowRefState =
|
||||
createState<RefObject<HTMLDivElement> | null>({
|
||||
key: 'workflowReactFlowRefState',
|
||||
defaultValue: null,
|
||||
});
|
||||
@ -0,0 +1,6 @@
|
||||
import { createState } from '@ui/utilities/state/utils/createState';
|
||||
|
||||
export const workflowSelectedNodeState = createState<string | undefined>({
|
||||
key: 'workflowSelectedNodeState',
|
||||
defaultValue: undefined,
|
||||
});
|
||||
Reference in New Issue
Block a user