diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasBase.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasBase.tsx index f7965ee1c6..893aa96615 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasBase.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasBase.tsx @@ -7,6 +7,7 @@ import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/ho import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState'; import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue'; import { WorkflowDiagramRightClickCommandMenu } from '@/workflow/workflow-diagram/components/WorkflowDiagramRightClickCommandMenu'; +import { useResetWorkflowInsertStepIds } from '@/workflow/workflow-diagram/hooks/useResetWorkflowInsertStepIds'; import { workflowDiagramComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramComponentState'; import { workflowDiagramPanOnDragComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramPanOnDragComponentState'; import { workflowDiagramWaitingNodesDimensionsComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramWaitingNodesDimensionsComponentState'; @@ -24,7 +25,6 @@ import { WorkflowDiagramConnection } from '@/workflow/workflow-diagram/workflow- import { WorkflowDiagramCustomMarkers } from '@/workflow/workflow-diagram/workflow-edges/components/WorkflowDiagramCustomMarkers'; import { useEdgeState } from '@/workflow/workflow-diagram/workflow-edges/hooks/useEdgeState'; import { type WorkflowDiagramEdgeComponentProps } from '@/workflow/workflow-diagram/workflow-edges/types/WorkflowDiagramEdgeComponentProps'; -import { workflowInsertStepIdsComponentState } from '@/workflow/workflow-steps/states/workflowInsertStepIdsComponentState'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; import { @@ -170,12 +170,10 @@ export const WorkflowDiagramCanvasBase = ({ const setWorkflowDiagram = useSetRecoilComponentState( workflowDiagramComponentState, ); - const setWorkflowInsertStepIds = useSetRecoilComponentState( - workflowInsertStepIdsComponentState, - ); const setWorkflowSelectedNode = useSetRecoilComponentState( workflowSelectedNodeComponentState, ); + const { resetWorkflowInsertStepIds } = useResetWorkflowInsertStepIds(); const workflowDiagramWaitingNodesDimensionsState = useRecoilComponentCallbackState( workflowDiagramWaitingNodesDimensionsComponentState, @@ -217,17 +215,7 @@ export const WorkflowDiagramCanvasBase = ({ }; useListenToSidePanelClosing(() => { - reactflow.setNodes((nodes) => - nodes.map((node) => ({ ...node, selected: false })), - ); - reactflow.setEdges((edges) => - edges.map((edge) => ({ ...edge, selected: false })), - ); - setWorkflowInsertStepIds({ - parentStepId: undefined, - nextStepId: undefined, - position: undefined, - }); + resetWorkflowInsertStepIds(); setWorkflowSelectedNode(undefined); }); diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/__stories__/WorkflowDiagramEmptyTriggerEditable.stories.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/__stories__/WorkflowDiagramEmptyTriggerEditable.stories.tsx index 62ab3e11a2..23a7fe50ed 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/__stories__/WorkflowDiagramEmptyTriggerEditable.stories.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/__stories__/WorkflowDiagramEmptyTriggerEditable.stories.tsx @@ -1,6 +1,7 @@ import { type Meta, type StoryObj } from '@storybook/react'; import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext'; +import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState'; import '@xyflow/react/dist/style.css'; import { RecoilRoot } from 'recoil'; import { ComponentDecorator } from 'twenty-ui/testing'; @@ -18,6 +19,9 @@ export default meta; type Story = StoryObj; export const Default: Story = { + args: { + id: 'trigger-node', + }, decorators: [ (Story) => (
@@ -36,10 +40,22 @@ export const Default: Story = { }; export const Selected: Story = { + args: { + id: 'trigger-node', + }, decorators: [ (Story) => ( -
- +
+ { + set( + workflowSelectedNodeComponentState.atomFamily({ + instanceId: 'workflow-visualizer-instance-id', + }), + 'trigger-node', + ); + }} + > diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/__stories__/WorkflowDiagramStepNodeEditableContent.stories.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/__stories__/WorkflowDiagramStepNodeEditableContent.stories.tsx index 414b44e184..3f7c85db11 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/__stories__/WorkflowDiagramStepNodeEditableContent.stories.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/__stories__/WorkflowDiagramStepNodeEditableContent.stories.tsx @@ -1,6 +1,7 @@ import { type Meta, type StoryObj } from '@storybook/react'; import { WorkflowVisualizerComponentInstanceContext } from '@/workflow/workflow-diagram/states/contexts/WorkflowVisualizerComponentInstanceContext'; +import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState'; import { type WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram'; import '@xyflow/react/dist/style.css'; import { RecoilRoot } from 'recoil'; @@ -149,8 +150,19 @@ export const Catalog: CatalogStory< decorators: [ (Story, { args }) => { return ( -
- +
+ { + if (args.selected) { + set( + workflowSelectedNodeComponentState.atomFamily({ + instanceId: 'workflow-visualizer-instance-id', + }), + args.id, + ); + } + }} + > diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/hooks/useResetWorkflowInsertStepIds.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/hooks/useResetWorkflowInsertStepIds.ts new file mode 100644 index 0000000000..b97304cb49 --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/hooks/useResetWorkflowInsertStepIds.ts @@ -0,0 +1,19 @@ +import { useRecoilComponentCallbackState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentCallbackState'; +import { workflowInsertStepIdsComponentState } from '@/workflow/workflow-steps/states/workflowInsertStepIdsComponentState'; +import { useRecoilCallback } from 'recoil'; + +export const useResetWorkflowInsertStepIds = () => { + const workflowInsertStepIdsState = useRecoilComponentCallbackState( + workflowInsertStepIdsComponentState, + ); + + const resetWorkflowInsertStepIds = useRecoilCallback( + ({ reset }) => + () => { + reset(workflowInsertStepIdsState); + }, + [workflowInsertStepIdsState], + ); + + return { resetWorkflowInsertStepIds }; +}; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/hooks/useStartNodeCreation.ts b/packages/twenty-front/src/modules/workflow/workflow-diagram/hooks/useStartNodeCreation.ts index a3f1717814..4b1b75d9fa 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/hooks/useStartNodeCreation.ts +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/hooks/useStartNodeCreation.ts @@ -3,7 +3,9 @@ import { useWorkflowCommandMenu } from '@/command-menu/hooks/useWorkflowCommandM import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState'; import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; +import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState'; import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState'; +import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState'; import { type WorkflowStepConnectionOptions } from '@/workflow/workflow-diagram/workflow-iterator/types/WorkflowStepConnectionOptions'; import { workflowInsertStepIdsComponentState } from '@/workflow/workflow-steps/states/workflowInsertStepIdsComponentState'; import { useCallback, useContext } from 'react'; @@ -16,6 +18,10 @@ export const useStartNodeCreation = () => { const [workflowInsertStepIds, setWorkflowInsertStepIds] = useRecoilComponentState(workflowInsertStepIdsComponentState); + const setWorkflowSelectedNode = useSetRecoilComponentState( + workflowSelectedNodeComponentState, + ); + const { openWorkflowCreateStepInCommandMenu } = useWorkflowCommandMenu(); const workflowVisualizerWorkflowId = useRecoilComponentValue( @@ -49,6 +55,8 @@ export const useStartNodeCreation = () => { connectionOptions, }); + setWorkflowSelectedNode(undefined); + if (!isDefined(workflowVisualizerWorkflowId)) { return; } @@ -61,6 +69,7 @@ export const useStartNodeCreation = () => { }, [ setWorkflowInsertStepIds, + setWorkflowSelectedNode, workflowVisualizerWorkflowId, isInRightDrawer, openWorkflowCreateStepInCommandMenu, diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramEmptyTriggerEditable.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramEmptyTriggerEditable.tsx index 9bac70c015..d5f4e23d90 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramEmptyTriggerEditable.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramEmptyTriggerEditable.tsx @@ -1,9 +1,12 @@ import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; import { useWorkflowCommandMenu } from '@/command-menu/hooks/useWorkflowCommandMenu'; import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState'; +import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState'; import { WORKFLOW_DIAGRAM_STEP_NODE_BASE_CLICK_OUTSIDE_ID } from '@/workflow/workflow-diagram/constants/WorkflowDiagramStepNodeClickOutsideId'; +import { useResetWorkflowInsertStepIds } from '@/workflow/workflow-diagram/hooks/useResetWorkflowInsertStepIds'; +import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState'; import { WorkflowNodeContainer } from '@/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeContainer'; import { WorkflowNodeIconContainer } from '@/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeIconContainer'; import { WorkflowNodeLabel } from '@/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeLabel'; @@ -15,7 +18,7 @@ import { useContext } from 'react'; import { useSetRecoilState } from 'recoil'; import { isDefined } from 'twenty-shared/utils'; -export const WorkflowDiagramEmptyTriggerEditable = () => { +export const WorkflowDiagramEmptyTriggerEditable = ({ id }: { id: string }) => { const { t } = useLingui(); const { openWorkflowTriggerTypeInCommandMenu } = useWorkflowCommandMenu(); @@ -24,17 +27,28 @@ export const WorkflowDiagramEmptyTriggerEditable = () => { workflowVisualizerWorkflowIdComponentState, ); + const [workflowSelectedNode, setWorkflowSelectedNode] = + useRecoilComponentState(workflowSelectedNodeComponentState); + const { isInRightDrawer } = useContext(ActionMenuContext); const setCommandMenuNavigationStack = useSetRecoilState( commandMenuNavigationStackState, ); + const selected = workflowSelectedNode === id; + + const { resetWorkflowInsertStepIds } = useResetWorkflowInsertStepIds(); + const handleClick = () => { if (!isInRightDrawer) { setCommandMenuNavigationStack([]); } + resetWorkflowInsertStepIds(); + + setWorkflowSelectedNode(id); + if (!isDefined(workflowVisualizerWorkflowId)) { return; } @@ -46,15 +60,20 @@ export const WorkflowDiagramEmptyTriggerEditable = () => { - {t`Trigger`} + + {t`Trigger`} + - {t`Add a Trigger`} + + {t`Add a Trigger`} + ); diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramEmptyTriggerReadonly.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramEmptyTriggerReadonly.tsx index a515956c06..8d4501828c 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramEmptyTriggerReadonly.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramEmptyTriggerReadonly.tsx @@ -1,8 +1,8 @@ import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; import { useWorkflowCommandMenu } from '@/command-menu/hooks/useWorkflowCommandMenu'; import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState'; +import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; -import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState'; import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState'; import { workflowVisualizerWorkflowVersionIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowVersionIdComponentState'; import { WORKFLOW_DIAGRAM_STEP_NODE_BASE_CLICK_OUTSIDE_ID } from '@/workflow/workflow-diagram/constants/WorkflowDiagramStepNodeClickOutsideId'; @@ -20,7 +20,7 @@ import { isDefined } from 'twenty-shared/utils'; import { TRIGGER_STEP_ID } from 'twenty-shared/workflow'; import { useIcons } from 'twenty-ui/display'; -export const WorkflowDiagramEmptyTriggerReadonly = () => { +export const WorkflowDiagramEmptyTriggerReadonly = ({ id }: { id: string }) => { const { getIcon } = useIcons(); const { t } = useLingui(); @@ -31,18 +31,19 @@ export const WorkflowDiagramEmptyTriggerReadonly = () => { workflowVisualizerWorkflowVersionIdComponentState, ); + const [workflowSelectedNode, setWorkflowSelectedNode] = + useRecoilComponentState(workflowSelectedNodeComponentState); + const { isInRightDrawer } = useContext(ActionMenuContext); const { openWorkflowViewStepInCommandMenu } = useWorkflowCommandMenu(); - const setWorkflowSelectedNode = useSetRecoilComponentState( - workflowSelectedNodeComponentState, - ); - const setCommandMenuNavigationStack = useSetRecoilState( commandMenuNavigationStackState, ); + const selected = workflowSelectedNode === id; + const handleClick = () => { if ( !isDefined(workflowVisualizerWorkflowId) || @@ -72,15 +73,20 @@ export const WorkflowDiagramEmptyTriggerReadonly = () => { - {t`Trigger`} + + {t`Trigger`} + - {t`Add a Trigger`} + + {t`Add a Trigger`} + ); diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditable.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditable.tsx index 45a125e88e..f47c91f4b6 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditable.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditable.tsx @@ -1,9 +1,10 @@ import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; import { useWorkflowCommandMenu } from '@/command-menu/hooks/useWorkflowCommandMenu'; import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState'; +import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; -import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState'; import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState'; +import { useResetWorkflowInsertStepIds } from '@/workflow/workflow-diagram/hooks/useResetWorkflowInsertStepIds'; import { workflowSelectedNodeComponentState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeComponentState'; import { type WorkflowDiagramStepNodeData } from '@/workflow/workflow-diagram/types/WorkflowDiagram'; import { getWorkflowNodeIconKey } from '@/workflow/workflow-diagram/utils/getWorkflowNodeIconKey'; @@ -16,11 +17,9 @@ import { useIcons } from 'twenty-ui/display'; export const WorkflowDiagramStepNodeEditable = ({ id, data, - selected, }: { id: string; data: WorkflowDiagramStepNodeData; - selected?: boolean; }) => { const { getIcon } = useIcons(); @@ -28,41 +27,48 @@ export const WorkflowDiagramStepNodeEditable = ({ workflowVisualizerWorkflowIdComponentState, ); - const setWorkflowSelectedNode = useSetRecoilComponentState( - workflowSelectedNodeComponentState, - ); + const [workflowSelectedNode, setWorkflowSelectedNode] = + useRecoilComponentState(workflowSelectedNodeComponentState); + + const selected = workflowSelectedNode === id; const { openWorkflowEditStepInCommandMenu } = useWorkflowCommandMenu(); + const { resetWorkflowInsertStepIds } = useResetWorkflowInsertStepIds(); + const { isInRightDrawer } = useContext(ActionMenuContext); const setCommandMenuNavigationStack = useSetRecoilState( commandMenuNavigationStackState, ); + const handleClick = () => { + if (!isInRightDrawer) { + setCommandMenuNavigationStack([]); + } + + resetWorkflowInsertStepIds(); + + setWorkflowSelectedNode(id); + + if (isDefined(workflowVisualizerWorkflowId)) { + openWorkflowEditStepInCommandMenu( + workflowVisualizerWorkflowId, + data.name, + getIcon(getWorkflowNodeIconKey(data)), + id, + ); + + return; + } + }; + return ( { - if (!isInRightDrawer) { - setCommandMenuNavigationStack([]); - } - - setWorkflowSelectedNode(id); - - if (isDefined(workflowVisualizerWorkflowId)) { - openWorkflowEditStepInCommandMenu( - workflowVisualizerWorkflowId, - data.name, - getIcon(getWorkflowNodeIconKey(data)), - id, - ); - - return; - } - }} + selected={selected} + onClick={handleClick} /> ); }; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditableContent.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditableContent.tsx index 724a7aba2c..258938db1e 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditableContent.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditableContent.tsx @@ -87,6 +87,7 @@ export const WorkflowDiagramStepNodeEditableContent = ({ onMouseEnter={handleMouseEnter} onMouseLeave={handleMouseLeave} isConnectable={isNodeConnectable} + selected={selected} > @@ -96,10 +97,15 @@ export const WorkflowDiagramStepNodeEditableContent = ({ - {capitalize(data.nodeType)} + + {capitalize(data.nodeType)} + - + {data.name} diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeReadonly.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeReadonly.tsx index aa39ca9210..83db1fdfd0 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeReadonly.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeReadonly.tsx @@ -1,8 +1,8 @@ import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; import { useWorkflowCommandMenu } from '@/command-menu/hooks/useWorkflowCommandMenu'; import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState'; +import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; -import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState'; import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState'; import { workflowVisualizerWorkflowVersionIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowVersionIdComponentState'; import { WORKFLOW_DIAGRAM_STEP_NODE_BASE_CLICK_OUTSIDE_ID } from '@/workflow/workflow-diagram/constants/WorkflowDiagramStepNodeClickOutsideId'; @@ -28,11 +28,9 @@ import { useIcons } from 'twenty-ui/display'; export const WorkflowDiagramStepNodeReadonly = ({ id, - selected, data, }: { id: string; - selected: boolean; data: WorkflowDiagramStepNodeData; }) => { const { getIcon } = useIcons(); @@ -44,9 +42,10 @@ export const WorkflowDiagramStepNodeReadonly = ({ workflowVisualizerWorkflowVersionIdComponentState, ); - const setWorkflowSelectedNode = useSetRecoilComponentState( - workflowSelectedNodeComponentState, - ); + const [workflowSelectedNode, setWorkflowSelectedNode] = + useRecoilComponentState(workflowSelectedNodeComponentState); + + const selected = workflowSelectedNode === id; const { openWorkflowViewStepInCommandMenu } = useWorkflowCommandMenu(); @@ -89,6 +88,7 @@ export const WorkflowDiagramStepNodeReadonly = ({ @@ -97,10 +97,15 @@ export const WorkflowDiagramStepNodeReadonly = ({ - {capitalize(data.nodeType)} + + {capitalize(data.nodeType)} + - + {data.name} diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeContainer.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeContainer.tsx index 0959f4125a..02b9298b26 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeContainer.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeContainer.tsx @@ -6,6 +6,7 @@ import styled from '@emotion/styled'; const StyledNodeContainer = styled.div<{ runStatus?: WorkflowRunStepStatus; isConnectable?: boolean; + selected: boolean; }>` align-items: center; display: flex; @@ -21,30 +22,31 @@ const StyledNodeContainer = styled.div<{ position: relative; transition: border-color 0.1s; - &:hover { - background: linear-gradient( - 0deg, - ${({ theme }) => theme.background.transparent.lighter} 0%, - ${({ theme }) => theme.background.transparent.lighter} 100% - ), - ${({ theme }) => theme.background.secondary}; - ${({ theme, isConnectable }) => - isConnectable && - css` - border-color: ${theme.color.blue} !important; - `}; - } - - ${({ theme, runStatus }) => { + ${({ theme, runStatus, selected, isConnectable }) => { const colors = getWorkflowDiagramColors({ theme, runStatus }); - return css` - border-color: ${colors.unselected.borderColor}; - background: ${colors.unselected.background}; + const background = selected + ? colors.selected.background + : colors.unselected.background; - .selected & { - background-color: ${colors.selected.background}; - border-color: ${colors.selected.borderColor}; + return css` + background: ${background}; + border-color: ${selected + ? colors.selected.borderColor + : colors.unselected.borderColor}; + + &:hover { + background: linear-gradient( + 0deg, + ${theme.background.transparent.lighter} 0%, + ${theme.background.transparent.lighter} 100% + ), + ${background}; + + ${isConnectable && + css` + border-color: ${theme.color.blue} !important; + `}; } `; }} diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeLabel.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeLabel.tsx index 068c91cf6f..907e4562e4 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeLabel.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeLabel.tsx @@ -1,24 +1,21 @@ +import type { WorkflowRunStepStatus } from '@/workflow/types/Workflow'; +import { getWorkflowDiagramColors } from '@/workflow/workflow-diagram/utils/getWorkflowDiagramColors'; +import { css } from '@emotion/react'; import styled from '@emotion/styled'; import { Label } from 'twenty-ui/display'; -import type { WorkflowRunStepStatus } from '@/workflow/types/Workflow'; -import { css } from '@emotion/react'; -import { getWorkflowDiagramColors } from '@/workflow/workflow-diagram/utils/getWorkflowDiagramColors'; const StyledNodeLabel = styled(Label)<{ runStatus?: WorkflowRunStepStatus; + selected: boolean; }>` box-sizing: border-box; flex: 1 0 0; - ${({ theme, runStatus }) => { + ${({ theme, runStatus, selected }) => { const colors = getWorkflowDiagramColors({ theme, runStatus }); return css` - color: ${colors.unselected.color}; - - .selected & { - color: ${colors.selected.color}; - } + color: ${selected ? colors.selected.color : colors.unselected.color}; `; }} `; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeTitle.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeTitle.tsx index cd1992d488..be0a9e47e8 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeTitle.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowNodeTitle.tsx @@ -1,11 +1,12 @@ -import styled from '@emotion/styled'; +import type { WorkflowRunStepStatus } from '@/workflow/types/Workflow'; import { getWorkflowDiagramColors } from '@/workflow/workflow-diagram/utils/getWorkflowDiagramColors'; import { css } from '@emotion/react'; -import type { WorkflowRunStepStatus } from '@/workflow/types/Workflow'; +import styled from '@emotion/styled'; const StyledNodeTitle = styled.div<{ highlight?: boolean; runStatus?: WorkflowRunStepStatus; + selected: boolean; }>` box-sizing: border-box; -webkit-box-orient: vertical; @@ -17,7 +18,7 @@ const StyledNodeTitle = styled.div<{ overflow: hidden; text-overflow: ellipsis; - ${({ theme, highlight, runStatus }) => { + ${({ theme, highlight, runStatus, selected }) => { const colors = getWorkflowDiagramColors({ theme, runStatus }); if (true === highlight) { @@ -27,11 +28,9 @@ const StyledNodeTitle = styled.div<{ } return css` - color: ${colors.unselected.titleColor}; - - .selected & { - color: ${colors.selected.titleColor}; - } + color: ${selected + ? colors.selected.titleColor + : colors.unselected.titleColor}; `; }} `; diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowRunDiagramStepNode.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowRunDiagramStepNode.tsx index 1d732ffbb8..b03129600a 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowRunDiagramStepNode.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowRunDiagramStepNode.tsx @@ -1,8 +1,8 @@ import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext'; import { useWorkflowCommandMenu } from '@/command-menu/hooks/useWorkflowCommandMenu'; import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState'; +import { useRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentState'; import { useRecoilComponentValue } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValue'; -import { useSetRecoilComponentState } from '@/ui/utilities/state/component-state/hooks/useSetRecoilComponentState'; import { useWorkflowRun } from '@/workflow/hooks/useWorkflowRun'; import { useWorkflowRunIdOrThrow } from '@/workflow/hooks/useWorkflowRunIdOrThrow'; import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/workflowVisualizerWorkflowIdComponentState'; @@ -80,11 +80,9 @@ const StyledRightPartContainer = styled.div` export const WorkflowRunDiagramStepNode = ({ id, data, - selected, }: { id: string; data: WorkflowRunDiagramStepNodeData; - selected: boolean; }) => { const { getIcon } = useIcons(); const theme = useTheme(); @@ -94,9 +92,10 @@ export const WorkflowRunDiagramStepNode = ({ ); const workflowRunId = useWorkflowRunIdOrThrow(); - const setWorkflowSelectedNode = useSetRecoilComponentState( - workflowSelectedNodeComponentState, - ); + const [workflowSelectedNode, setWorkflowSelectedNode] = + useRecoilComponentState(workflowSelectedNodeComponentState); + + const selected = workflowSelectedNode === id; const { openWorkflowRunViewStepInCommandMenu } = useWorkflowCommandMenu(); @@ -142,6 +141,7 @@ export const WorkflowRunDiagramStepNode = ({ data-click-outside-id={WORKFLOW_DIAGRAM_STEP_NODE_BASE_CLICK_OUTSIDE_ID} runStatus={data.runStatus} onClick={handleClick} + selected={selected} > @@ -150,7 +150,7 @@ export const WorkflowRunDiagramStepNode = ({ - + {capitalize(data.nodeType)} @@ -187,7 +187,7 @@ export const WorkflowRunDiagramStepNode = ({ - + {data.name}