From f45a682249d8b5ed74b95edb7845c622bdbcdd28 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rapha=C3=ABl=20Bosi?= <71827178+bosiraphael@users.noreply.github.com> Date: Fri, 7 Mar 2025 18:18:24 +0100 Subject: [PATCH] 491 save the page component instance id for side panel navigation (Part 2) (#10732) This PR follows #10700, it is the same refactor but for the workflows pages. - Duplicates the right drawer workflow pages for the command menu and replace the states used in these pages by component states - We store the component instance id upon navigation to restore the states when we navigate back to a page There are still states which are not component states inside the workflow diagram and workflow command menu pages, we should convert them in a futur refactor. `closeCommandMenu` was called programmatically in multiple places for the workflow, I refactored that to only rely on the click outside listener. This introduced a wiggling bug on the workflow canvas when we change node selection. This should be fixed in another PR by updating the canvas animation to take the animation values of the command menu instead. I'm thinking we could use [motion values](https://motion.dev/docs/react-motion-value) for this as I told you @Devessier --- .../activities/emails/hooks/useEmailThread.ts | 5 +- .../components/CommandMenuContainer.tsx | 8 +- .../constants/CommandMenuPagesConfig.tsx | 22 ++-- .../{useCommandMenu.tsx => useCommandMenu.ts} | 113 ++++++++++++++++++ .../CommandMenuSearchRecordsPage.tsx | 0 .../CommandMenuWorkflowSelectAction.tsx | 16 +++ ...CommandMenuWorkflowSelectActionContent.tsx | 45 +++++++ .../states/workflowIdComponentState.ts | 10 ++ .../CommandMenuWorkflowEditStep.tsx | 23 ++++ .../CommandMenuWorkflowEditStepContent.tsx | 30 +++++ .../CommandMenuWorkflowRunViewStep.tsx | 85 +++++++++++++ .../CommandMenuWorkflowViewStep.tsx | 17 +++ .../CommandMenuWorkflowSelectTriggerType.tsx | 16 +++ ...ndMenuWorkflowSelectTriggerTypeContent.tsx | 100 ++++++++++++++++ .../components/WorkflowDiagramCanvasBase.tsx | 4 - .../WorkflowDiagramCanvasEditableEffect.tsx | 46 +++++-- .../WorkflowDiagramCanvasReadonlyEffect.tsx | 28 ++++- .../WorkflowRunDiagramCanvasEffect.tsx | 27 ++++- .../hooks/useStartNodeCreation.ts | 28 ++++- ...DrawerWorkflowSelectTriggerTypeContent.tsx | 23 +++- 20 files changed, 597 insertions(+), 49 deletions(-) rename packages/twenty-front/src/modules/command-menu/hooks/{useCommandMenu.tsx => useCommandMenu.ts} (84%) rename packages/twenty-front/src/modules/command-menu/pages/{ => search}/components/CommandMenuSearchRecordsPage.tsx (100%) create mode 100644 packages/twenty-front/src/modules/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectAction.tsx create mode 100644 packages/twenty-front/src/modules/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectActionContent.tsx create mode 100644 packages/twenty-front/src/modules/command-menu/pages/workflow/states/workflowIdComponentState.ts create mode 100644 packages/twenty-front/src/modules/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStep.tsx create mode 100644 packages/twenty-front/src/modules/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStepContent.tsx create mode 100644 packages/twenty-front/src/modules/command-menu/pages/workflow/step/view-run/components/CommandMenuWorkflowRunViewStep.tsx create mode 100644 packages/twenty-front/src/modules/command-menu/pages/workflow/step/view/components/CommandMenuWorkflowViewStep.tsx create mode 100644 packages/twenty-front/src/modules/command-menu/pages/workflow/trigger-type/components/CommandMenuWorkflowSelectTriggerType.tsx create mode 100644 packages/twenty-front/src/modules/command-menu/pages/workflow/trigger-type/components/CommandMenuWorkflowSelectTriggerTypeContent.tsx diff --git a/packages/twenty-front/src/modules/activities/emails/hooks/useEmailThread.ts b/packages/twenty-front/src/modules/activities/emails/hooks/useEmailThread.ts index e46e8fc58..c2fa722ed 100644 --- a/packages/twenty-front/src/modules/activities/emails/hooks/useEmailThread.ts +++ b/packages/twenty-front/src/modules/activities/emails/hooks/useEmailThread.ts @@ -1,14 +1,12 @@ import { useRecoilCallback } from 'recoil'; import { useOpenEmailThreadRightDrawer } from '@/activities/emails/right-drawer/hooks/useOpenEmailThreadRightDrawer'; -import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu'; import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState'; import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState'; export const useEmailThread = () => { const { closeRightDrawer } = useRightDrawer(); - const { closeCommandMenu } = useCommandMenu(); const openEmailThreadRightDrawer = useOpenEmailThreadRightDrawer(); const openEmailThread = useRecoilCallback( @@ -25,14 +23,13 @@ export const useEmailThread = () => { if (isRightDrawerOpen && viewableEmailThreadId === threadId) { set(viewableRecordIdState, null); closeRightDrawer(); - closeCommandMenu(); return; } openEmailThreadRightDrawer(); set(viewableRecordIdState, threadId); }, - [closeRightDrawer, closeCommandMenu, openEmailThreadRightDrawer], + [closeRightDrawer, openEmailThreadRightDrawer], ); return { openEmailThread }; diff --git a/packages/twenty-front/src/modules/command-menu/components/CommandMenuContainer.tsx b/packages/twenty-front/src/modules/command-menu/components/CommandMenuContainer.tsx index 509cb682b..c94309276 100644 --- a/packages/twenty-front/src/modules/command-menu/components/CommandMenuContainer.tsx +++ b/packages/twenty-front/src/modules/command-menu/components/CommandMenuContainer.tsx @@ -23,7 +23,6 @@ import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/u import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope'; import { useListenClickOutside } from '@/ui/utilities/pointer-event/hooks/useListenClickOutside'; import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; -import { workflowReactFlowRefState } from '@/workflow/workflow-diagram/states/workflowReactFlowRefState'; import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { useTheme } from '@emotion/react'; import styled from '@emotion/styled'; @@ -64,15 +63,10 @@ export const CommandMenuContainer = ({ const commandMenuRef = useRef(null); - const workflowReactFlowRef = useRecoilValue(workflowReactFlowRefState); - useCommandMenuHotKeys(); useListenClickOutside({ - refs: [ - commandMenuRef, - ...(workflowReactFlowRef ? [workflowReactFlowRef] : []), - ], + refs: [commandMenuRef], callback: closeCommandMenu, listenerId: 'COMMAND_MENU_LISTENER_ID', hotkeyScope: AppHotkeyScope.CommandMenuOpen, diff --git a/packages/twenty-front/src/modules/command-menu/constants/CommandMenuPagesConfig.tsx b/packages/twenty-front/src/modules/command-menu/constants/CommandMenuPagesConfig.tsx index 89c739aaa..706ebc3f3 100644 --- a/packages/twenty-front/src/modules/command-menu/constants/CommandMenuPagesConfig.tsx +++ b/packages/twenty-front/src/modules/command-menu/constants/CommandMenuPagesConfig.tsx @@ -1,15 +1,15 @@ import { RightDrawerAIChat } from '@/activities/copilot/right-drawer/components/RightDrawerAIChat'; import { CommandMenu } from '@/command-menu/components/CommandMenu'; import { CommandMenuCalendarEventPage } from '@/command-menu/pages/calendar-event/components/CommandMenuCalendarEventPage'; -import { CommandMenuSearchRecordsPage } from '@/command-menu/pages/components/CommandMenuSearchRecordsPage'; import { CommandMenuMessageThreadPage } from '@/command-menu/pages/message-thread/components/CommandMenuMessageThreadPage'; import { CommandMenuRecordPage } from '@/command-menu/pages/record-page/components/CommandMenuRecordPage'; +import { CommandMenuSearchRecordsPage } from '@/command-menu/pages/search/components/CommandMenuSearchRecordsPage'; +import { CommandMenuWorkflowSelectAction } from '@/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectAction'; +import { CommandMenuWorkflowEditStep } from '@/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStep'; +import { CommandMenuWorkflowRunViewStep } from '@/command-menu/pages/workflow/step/view-run/components/CommandMenuWorkflowRunViewStep'; +import { CommandMenuWorkflowViewStep } from '@/command-menu/pages/workflow/step/view/components/CommandMenuWorkflowViewStep'; +import { CommandMenuWorkflowSelectTriggerType } from '@/command-menu/pages/workflow/trigger-type/components/CommandMenuWorkflowSelectTriggerType'; import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages'; -import { RightDrawerWorkflowEditStep } from '@/workflow/workflow-steps/components/RightDrawerWorkflowEditStep'; -import { RightDrawerWorkflowRunViewStep } from '@/workflow/workflow-steps/components/RightDrawerWorkflowRunViewStep'; -import { RightDrawerWorkflowViewStep } from '@/workflow/workflow-steps/components/RightDrawerWorkflowViewStep'; -import { RightDrawerWorkflowSelectAction } from '@/workflow/workflow-steps/workflow-actions/components/RightDrawerWorkflowSelectAction'; -import { RightDrawerWorkflowSelectTriggerType } from '@/workflow/workflow-trigger/components/RightDrawerWorkflowSelectTriggerType'; export const COMMAND_MENU_PAGES_CONFIG = new Map< CommandMenuPages, @@ -22,14 +22,14 @@ export const COMMAND_MENU_PAGES_CONFIG = new Map< [CommandMenuPages.Copilot, ], [ CommandMenuPages.WorkflowStepSelectTriggerType, - , + , ], [ CommandMenuPages.WorkflowStepSelectAction, - , + , ], - [CommandMenuPages.WorkflowStepEdit, ], - [CommandMenuPages.WorkflowStepView, ], - [CommandMenuPages.WorkflowRunStepView, ], + [CommandMenuPages.WorkflowStepEdit, ], + [CommandMenuPages.WorkflowStepView, ], + [CommandMenuPages.WorkflowRunStepView, ], [CommandMenuPages.SearchRecords, ], ]); diff --git a/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.tsx b/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.ts similarity index 84% rename from packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.tsx rename to packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.ts index 6b7d9a2c2..d6f969267 100644 --- a/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.tsx +++ b/packages/twenty-front/src/modules/command-menu/hooks/useCommandMenu.ts @@ -6,11 +6,13 @@ import { useSelectableList } from '@/ui/layout/selectable-list/hooks/useSelectab import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope'; import { AppHotkeyScope } from '@/ui/utilities/hotkey/types/AppHotkeyScope'; import { + IconBolt, IconCalendarEvent, IconComponent, IconDotsVertical, IconMail, IconSearch, + IconSettingsAutomation, useIcons, } from 'twenty-ui'; @@ -21,6 +23,7 @@ import { useCopyContextStoreStates } from '@/command-menu/hooks/useCopyContextSt import { useResetContextStoreStates } from '@/command-menu/hooks/useResetContextStoreStates'; import { viewableRecordIdComponentState } from '@/command-menu/pages/record-page/states/viewableRecordIdComponentState'; import { viewableRecordNameSingularComponentState } from '@/command-menu/pages/record-page/states/viewableRecordNameSingularComponentState'; +import { workflowIdComponentState } from '@/command-menu/pages/workflow/states/workflowIdComponentState'; import { commandMenuNavigationStackState } from '@/command-menu/states/commandMenuNavigationStackState'; import { commandMenuPageInfoState } from '@/command-menu/states/commandMenuPageInfoState'; import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState'; @@ -393,6 +396,111 @@ export const useCommandMenu = () => { [getIcon, navigateCommandMenu], ); + const openWorkflowTriggerTypeInCommandMenu = useRecoilCallback( + ({ set }) => { + return (workflowId: string) => { + const pageId = v4(); + + set( + workflowIdComponentState.atomFamily({ instanceId: pageId }), + workflowId, + ); + + navigateCommandMenu({ + page: CommandMenuPages.WorkflowStepSelectTriggerType, + pageTitle: t`Trigger Type`, + pageIcon: IconBolt, + pageId, + }); + }; + }, + [navigateCommandMenu], + ); + + const openWorkflowActionInCommandMenu = useRecoilCallback( + ({ set }) => { + return (workflowId: string) => { + const pageId = v4(); + + set( + workflowIdComponentState.atomFamily({ instanceId: pageId }), + workflowId, + ); + + navigateCommandMenu({ + page: CommandMenuPages.WorkflowStepSelectAction, + pageTitle: t`Select Action`, + pageIcon: IconSettingsAutomation, + pageId, + }); + }; + }, + [navigateCommandMenu], + ); + + const openWorkflowEditStepInCommandMenu = useRecoilCallback( + ({ set }) => { + return (workflowId: string, title: string, icon: IconComponent) => { + const pageId = v4(); + + set( + workflowIdComponentState.atomFamily({ instanceId: pageId }), + workflowId, + ); + + navigateCommandMenu({ + page: CommandMenuPages.WorkflowStepEdit, + pageTitle: title, + pageIcon: icon, + pageId, + }); + }; + }, + [navigateCommandMenu], + ); + + const openWorkflowViewStepInCommandMenu = useRecoilCallback( + ({ set }) => { + return (workflowId: string, title: string, icon: IconComponent) => { + const pageId = v4(); + + set( + workflowIdComponentState.atomFamily({ instanceId: pageId }), + workflowId, + ); + + navigateCommandMenu({ + page: CommandMenuPages.WorkflowStepView, + pageTitle: title, + pageIcon: icon, + pageId, + }); + }; + }, + [navigateCommandMenu], + ); + + const openWorkflowViewRunStepInCommandMenu = useRecoilCallback( + ({ set }) => { + return (workflowId: string, title: string, icon: IconComponent) => { + const pageId = v4(); + + set( + workflowIdComponentState.atomFamily({ instanceId: pageId }), + workflowId, + ); + + navigateCommandMenu({ + page: CommandMenuPages.WorkflowRunStepView, + pageTitle: title, + pageIcon: icon, + pageId, + }); + }; + }, + [navigateCommandMenu], + ); + const openRecordsSearchPage = () => { navigateCommandMenu({ page: CommandMenuPages.SearchRecords, @@ -512,5 +620,10 @@ export const useCommandMenu = () => { setGlobalCommandMenuContext, openCalendarEventInCommandMenu, openEmailThreadInCommandMenu, + openWorkflowTriggerTypeInCommandMenu, + openWorkflowActionInCommandMenu, + openWorkflowEditStepInCommandMenu, + openWorkflowViewStepInCommandMenu, + openWorkflowViewRunStepInCommandMenu, }; }; diff --git a/packages/twenty-front/src/modules/command-menu/pages/components/CommandMenuSearchRecordsPage.tsx b/packages/twenty-front/src/modules/command-menu/pages/search/components/CommandMenuSearchRecordsPage.tsx similarity index 100% rename from packages/twenty-front/src/modules/command-menu/pages/components/CommandMenuSearchRecordsPage.tsx rename to packages/twenty-front/src/modules/command-menu/pages/search/components/CommandMenuSearchRecordsPage.tsx diff --git a/packages/twenty-front/src/modules/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectAction.tsx b/packages/twenty-front/src/modules/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectAction.tsx new file mode 100644 index 000000000..588adc218 --- /dev/null +++ b/packages/twenty-front/src/modules/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectAction.tsx @@ -0,0 +1,16 @@ +import { CommandMenuWorkflowSelectActionContent } from '@/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectActionContent'; +import { workflowIdComponentState } from '@/command-menu/pages/workflow/states/workflowIdComponentState'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion'; +import { isDefined } from 'twenty-shared'; + +export const CommandMenuWorkflowSelectAction = () => { + const workflowId = useRecoilComponentValueV2(workflowIdComponentState); + const workflow = useWorkflowWithCurrentVersion(workflowId); + + if (!isDefined(workflow)) { + return null; + } + + return ; +}; diff --git a/packages/twenty-front/src/modules/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectActionContent.tsx b/packages/twenty-front/src/modules/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectActionContent.tsx new file mode 100644 index 000000000..7999c5805 --- /dev/null +++ b/packages/twenty-front/src/modules/command-menu/pages/workflow/action/components/CommandMenuWorkflowSelectActionContent.tsx @@ -0,0 +1,45 @@ +import { WorkflowWithCurrentVersion } from '@/workflow/types/Workflow'; +import { RightDrawerStepListContainer } from '@/workflow/workflow-steps/components/RightDrawerWorkflowSelectStepContainer'; +import { RightDrawerWorkflowSelectStepTitle } from '@/workflow/workflow-steps/components/RightDrawerWorkflowSelectStepTitle'; +import { useCreateStep } from '@/workflow/workflow-steps/hooks/useCreateStep'; +import { OTHER_ACTIONS } from '@/workflow/workflow-steps/workflow-actions/constants/OtherActions'; +import { RECORD_ACTIONS } from '@/workflow/workflow-steps/workflow-actions/constants/RecordActions'; +import { MenuItemCommand, useIcons } from 'twenty-ui'; + +export const CommandMenuWorkflowSelectActionContent = ({ + workflow, +}: { + workflow: WorkflowWithCurrentVersion; +}) => { + const { getIcon } = useIcons(); + const { createStep } = useCreateStep({ + workflow, + }); + + return ( + + + Records + + {RECORD_ACTIONS.map((action) => ( + createStep(action.type)} + /> + ))} + + Other + + {OTHER_ACTIONS.map((action) => ( + createStep(action.type)} + /> + ))} + + ); +}; diff --git a/packages/twenty-front/src/modules/command-menu/pages/workflow/states/workflowIdComponentState.ts b/packages/twenty-front/src/modules/command-menu/pages/workflow/states/workflowIdComponentState.ts new file mode 100644 index 000000000..35bb2d051 --- /dev/null +++ b/packages/twenty-front/src/modules/command-menu/pages/workflow/states/workflowIdComponentState.ts @@ -0,0 +1,10 @@ +import { CommandMenuPageComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuPageComponentInstanceContext'; +import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2'; + +export const workflowIdComponentState = createComponentStateV2< + string | undefined +>({ + key: 'command-menu/workflow-id', + defaultValue: undefined, + componentInstanceContext: CommandMenuPageComponentInstanceContext, +}); diff --git a/packages/twenty-front/src/modules/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStep.tsx b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStep.tsx new file mode 100644 index 000000000..3022c0a5c --- /dev/null +++ b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStep.tsx @@ -0,0 +1,23 @@ +import { workflowIdComponentState } from '@/command-menu/pages/workflow/states/workflowIdComponentState'; +import { CommandMenuWorkflowEditStepContent } from '@/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStepContent'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion'; +import { WorkflowVersionComponentInstanceContext } from '@/workflow/states/context/WorkflowVersionComponentInstanceContext'; +import { isDefined } from 'twenty-shared'; + +export const CommandMenuWorkflowEditStep = () => { + const workflowId = useRecoilComponentValueV2(workflowIdComponentState); + const workflow = useWorkflowWithCurrentVersion(workflowId); + + if (!isDefined(workflow)) { + return null; + } + + return ( + + + + ); +}; diff --git a/packages/twenty-front/src/modules/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStepContent.tsx b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStepContent.tsx new file mode 100644 index 000000000..b7620d641 --- /dev/null +++ b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/edit/components/CommandMenuWorkflowEditStepContent.tsx @@ -0,0 +1,30 @@ +import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow'; +import { WorkflowWithCurrentVersion } from '@/workflow/types/Workflow'; +import { useWorkflowSelectedNodeOrThrow } from '@/workflow/workflow-diagram/hooks/useWorkflowSelectedNodeOrThrow'; +import { WorkflowStepDetail } from '@/workflow/workflow-steps/components/WorkflowStepDetail'; +import { useUpdateStep } from '@/workflow/workflow-steps/hooks/useUpdateStep'; +import { useUpdateWorkflowVersionTrigger } from '@/workflow/workflow-trigger/hooks/useUpdateWorkflowVersionTrigger'; + +export const CommandMenuWorkflowEditStepContent = ({ + workflow, +}: { + workflow: WorkflowWithCurrentVersion; +}) => { + const flow = useFlowOrThrow(); + const workflowSelectedNode = useWorkflowSelectedNodeOrThrow(); + + const { updateTrigger } = useUpdateWorkflowVersionTrigger({ workflow }); + const { updateStep } = useUpdateStep({ + workflow, + }); + + return ( + + ); +}; diff --git a/packages/twenty-front/src/modules/command-menu/pages/workflow/step/view-run/components/CommandMenuWorkflowRunViewStep.tsx b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/view-run/components/CommandMenuWorkflowRunViewStep.tsx new file mode 100644 index 000000000..4dd1bf926 --- /dev/null +++ b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/view-run/components/CommandMenuWorkflowRunViewStep.tsx @@ -0,0 +1,85 @@ +import { ShowPageSubContainerTabListContainer } from '@/ui/layout/show-page/components/ShowPageSubContainerTabListContainer'; +import { SingleTabProps, TabList } from '@/ui/layout/tab/components/TabList'; +import { useTabList } from '@/ui/layout/tab/hooks/useTabList'; +import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow'; +import { useWorkflowRun } from '@/workflow/hooks/useWorkflowRun'; +import { useWorkflowRunIdOrThrow } from '@/workflow/hooks/useWorkflowRunIdOrThrow'; +import { useWorkflowSelectedNodeOrThrow } from '@/workflow/workflow-diagram/hooks/useWorkflowSelectedNodeOrThrow'; +import { WorkflowRunStepInputDetail } from '@/workflow/workflow-steps/components/WorkflowRunStepInputDetail'; +import { WorkflowStepDetail } from '@/workflow/workflow-steps/components/WorkflowStepDetail'; +import { WORKFLOW_RUN_STEP_SIDE_PANEL_TAB_LIST_COMPONENT_ID } from '@/workflow/workflow-steps/constants/WorkflowRunStepSidePanelTabListComponentId'; +import { getWorkflowRunStepExecutionStatus } from '@/workflow/workflow-steps/utils/getWorkflowRunStepExecutionStatus'; +import { TRIGGER_STEP_ID } from '@/workflow/workflow-trigger/constants/TriggerStepId'; +import styled from '@emotion/styled'; +import { isDefined } from 'twenty-shared'; +import { IconLogin2, IconLogout, IconStepInto } from 'twenty-ui'; + +const StyledTabListContainer = styled(ShowPageSubContainerTabListContainer)` + background-color: ${({ theme }) => theme.background.secondary}; +`; + +type TabId = 'node' | 'input' | 'output'; + +export const CommandMenuWorkflowRunViewStep = () => { + const flow = useFlowOrThrow(); + const workflowSelectedNode = useWorkflowSelectedNodeOrThrow(); + const workflowRunId = useWorkflowRunIdOrThrow(); + + const workflowRun = useWorkflowRun({ workflowRunId }); + + const { activeTabId } = useTabList( + WORKFLOW_RUN_STEP_SIDE_PANEL_TAB_LIST_COMPONENT_ID, + ); + + const stepExecutionStatus = isDefined(workflowRun) + ? getWorkflowRunStepExecutionStatus({ + workflowRunOutput: workflowRun.output, + stepId: workflowSelectedNode, + }) + : undefined; + + const isInputTabDisabled = + workflowSelectedNode === TRIGGER_STEP_ID || + stepExecutionStatus === 'running' || + stepExecutionStatus === 'not-executed'; + + const tabs: SingleTabProps[] = [ + { id: 'node', title: 'Node', Icon: IconStepInto }, + { + id: 'input', + title: 'Input', + Icon: IconLogin2, + disabled: isInputTabDisabled, + }, + { id: 'output', title: 'Output', Icon: IconLogout }, + ]; + + if (!isDefined(workflowRun)) { + return null; + } + + return ( + <> + + + + + {activeTabId === 'node' ? ( + + ) : null} + + {activeTabId === 'input' ? ( + + ) : null} + + ); +}; diff --git a/packages/twenty-front/src/modules/command-menu/pages/workflow/step/view/components/CommandMenuWorkflowViewStep.tsx b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/view/components/CommandMenuWorkflowViewStep.tsx new file mode 100644 index 000000000..93586fdac --- /dev/null +++ b/packages/twenty-front/src/modules/command-menu/pages/workflow/step/view/components/CommandMenuWorkflowViewStep.tsx @@ -0,0 +1,17 @@ +import { useFlowOrThrow } from '@/workflow/hooks/useFlowOrThrow'; +import { useWorkflowSelectedNodeOrThrow } from '@/workflow/workflow-diagram/hooks/useWorkflowSelectedNodeOrThrow'; +import { WorkflowStepDetail } from '@/workflow/workflow-steps/components/WorkflowStepDetail'; + +export const CommandMenuWorkflowViewStep = () => { + const flow = useFlowOrThrow(); + const workflowSelectedNode = useWorkflowSelectedNodeOrThrow(); + + return ( + + ); +}; diff --git a/packages/twenty-front/src/modules/command-menu/pages/workflow/trigger-type/components/CommandMenuWorkflowSelectTriggerType.tsx b/packages/twenty-front/src/modules/command-menu/pages/workflow/trigger-type/components/CommandMenuWorkflowSelectTriggerType.tsx new file mode 100644 index 000000000..2a8c38528 --- /dev/null +++ b/packages/twenty-front/src/modules/command-menu/pages/workflow/trigger-type/components/CommandMenuWorkflowSelectTriggerType.tsx @@ -0,0 +1,16 @@ +import { workflowIdComponentState } from '@/command-menu/pages/workflow/states/workflowIdComponentState'; +import { CommandMenuWorkflowSelectTriggerTypeContent } from '@/command-menu/pages/workflow/trigger-type/components/CommandMenuWorkflowSelectTriggerTypeContent'; +import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2'; +import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion'; +import { isDefined } from 'twenty-shared'; + +export const CommandMenuWorkflowSelectTriggerType = () => { + const workflowId = useRecoilComponentValueV2(workflowIdComponentState); + const workflow = useWorkflowWithCurrentVersion(workflowId); + + if (!isDefined(workflow)) { + return null; + } + + return ; +}; diff --git a/packages/twenty-front/src/modules/command-menu/pages/workflow/trigger-type/components/CommandMenuWorkflowSelectTriggerTypeContent.tsx b/packages/twenty-front/src/modules/command-menu/pages/workflow/trigger-type/components/CommandMenuWorkflowSelectTriggerTypeContent.tsx new file mode 100644 index 000000000..c94fe92da --- /dev/null +++ b/packages/twenty-front/src/modules/command-menu/pages/workflow/trigger-type/components/CommandMenuWorkflowSelectTriggerTypeContent.tsx @@ -0,0 +1,100 @@ +import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu'; +import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; +import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; +import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages'; +import { + WorkflowTriggerType, + WorkflowWithCurrentVersion, +} from '@/workflow/types/Workflow'; +import { workflowSelectedNodeState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeState'; +import { RightDrawerStepListContainer } from '@/workflow/workflow-steps/components/RightDrawerWorkflowSelectStepContainer'; +import { RightDrawerWorkflowSelectStepTitle } from '@/workflow/workflow-steps/components/RightDrawerWorkflowSelectStepTitle'; +import { DATABASE_TRIGGER_TYPES } from '@/workflow/workflow-trigger/constants/DatabaseTriggerTypes'; +import { OTHER_TRIGGER_TYPES } from '@/workflow/workflow-trigger/constants/OtherTriggerTypes'; +import { TRIGGER_STEP_ID } from '@/workflow/workflow-trigger/constants/TriggerStepId'; +import { useUpdateWorkflowVersionTrigger } from '@/workflow/workflow-trigger/hooks/useUpdateWorkflowVersionTrigger'; +import { getTriggerDefaultDefinition } from '@/workflow/workflow-trigger/utils/getTriggerDefaultDefinition'; +import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; +import { useSetRecoilState } from 'recoil'; +import { MenuItemCommand, useIcons } from 'twenty-ui'; +import { FeatureFlagKey } from '~/generated-metadata/graphql'; + +export const CommandMenuWorkflowSelectTriggerTypeContent = ({ + workflow, +}: { + workflow: WorkflowWithCurrentVersion; +}) => { + const { getIcon } = useIcons(); + const { updateTrigger } = useUpdateWorkflowVersionTrigger({ workflow }); + + const { activeObjectMetadataItems } = useFilteredObjectMetadataItems(); + + const { openRightDrawer } = useRightDrawer(); + const setWorkflowSelectedNode = useSetRecoilState(workflowSelectedNodeState); + const { openWorkflowEditStepInCommandMenu } = useCommandMenu(); + const isCommandMenuV2Enabled = useIsFeatureEnabled( + FeatureFlagKey.IsCommandMenuV2Enabled, + ); + + const handleTriggerTypeClick = ({ + type, + defaultLabel, + icon, + }: { + type: WorkflowTriggerType; + defaultLabel: string; + icon: string; + }) => { + return async () => { + await updateTrigger( + getTriggerDefaultDefinition({ + defaultLabel, + type, + activeObjectMetadataItems, + }), + ); + + setWorkflowSelectedNode(TRIGGER_STEP_ID); + + if (isCommandMenuV2Enabled) { + openWorkflowEditStepInCommandMenu( + workflow.id, + defaultLabel, + getIcon(icon), + ); + } else { + openRightDrawer(RightDrawerPages.WorkflowStepEdit, { + title: defaultLabel, + Icon: getIcon(icon), + }); + } + }; + }; + + return ( + + + Data + + {DATABASE_TRIGGER_TYPES.map((action) => ( + + ))} + + Others + + {OTHER_TRIGGER_TYPES.map((action) => ( + + ))} + + ); +}; 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 add12217e..bbb7a8dad 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 @@ -1,4 +1,3 @@ -import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu'; import { useListenRightDrawerClose } from '@/ui/layout/right-drawer/hooks/useListenRightDrawerClose'; import { WorkflowDiagramCustomMarkers } from '@/workflow/workflow-diagram/components/WorkflowDiagramCustomMarkers'; import { useRightDrawerState } from '@/workflow/workflow-diagram/hooks/useRightDrawerState'; @@ -209,8 +208,6 @@ export const WorkflowDiagramCanvasBase = ({ ); }, [reactflow, rightDrawerState, rightDrawerWidth]); - const { closeCommandMenu } = useCommandMenu(); - return ( @@ -251,7 +248,6 @@ export const WorkflowDiagramCanvasBase = ({ nodesFocusable={false} edgesFocusable={false} nodesDraggable={false} - onPaneClick={closeCommandMenu} nodesConnectable={false} paneClickDistance={10} // Fix small unwanted user dragging does not select node > diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditableEffect.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditableEffect.tsx index 55a18adba..f7009a93f 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditableEffect.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasEditableEffect.tsx @@ -5,6 +5,7 @@ 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 { workflowIdState } from '@/workflow/states/workflowIdState'; 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'; @@ -15,12 +16,14 @@ import { } from '@/workflow/workflow-diagram/types/WorkflowDiagram'; import { getWorkflowNodeIconKey } from '@/workflow/workflow-diagram/utils/getWorkflowNodeIconKey'; import { isCreateStepNode } from '@/workflow/workflow-diagram/utils/isCreateStepNode'; +import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { useLingui } from '@lingui/react/macro'; import { OnSelectionChangeParams, useOnSelectionChange } from '@xyflow/react'; import { useCallback, useContext } from 'react'; -import { useSetRecoilState } from 'recoil'; +import { useRecoilValue, useSetRecoilState } from 'recoil'; import { isDefined } from 'twenty-shared'; import { IconBolt, useIcons } from 'twenty-ui'; +import { FeatureFlagKey } from '~/generated-metadata/graphql'; export const WorkflowDiagramCanvasEditableEffect = () => { const { t } = useLingui(); @@ -28,7 +31,10 @@ export const WorkflowDiagramCanvasEditableEffect = () => { const { startNodeCreation } = useStartNodeCreation(); const { openRightDrawer, closeRightDrawer } = useRightDrawer(); - const { closeCommandMenu } = useCommandMenu(); + const { + openWorkflowTriggerTypeInCommandMenu, + openWorkflowEditStepInCommandMenu, + } = useCommandMenu(); const setHotkeyScope = useSetHotkeyScope(); @@ -40,6 +46,12 @@ export const WorkflowDiagramCanvasEditableEffect = () => { const { isInRightDrawer } = useContext(ActionMenuContext); + const workflowId = useRecoilValue(workflowIdState); + + const isCommandMenuV2Enabled = useIsFeatureEnabled( + FeatureFlagKey.IsCommandMenuV2Enabled, + ); + const handleSelectionChange = useCallback( ({ nodes }: OnSelectionChangeParams) => { const selectedNode = nodes[0] as WorkflowDiagramNode; @@ -51,12 +63,16 @@ export const WorkflowDiagramCanvasEditableEffect = () => { if (isClosingStep) { closeRightDrawer(); - closeCommandMenu(); return; } const isEmptyTriggerNode = selectedNode.type === EMPTY_TRIGGER_STEP_ID; if (isEmptyTriggerNode) { + if (isCommandMenuV2Enabled && isDefined(workflowId)) { + openWorkflowTriggerTypeInCommandMenu(workflowId); + return; + } + openRightDrawer(RightDrawerPages.WorkflowStepSelectTriggerType, { title: t`Trigger Type`, Icon: IconBolt, @@ -74,6 +90,17 @@ export const WorkflowDiagramCanvasEditableEffect = () => { const selectedNodeData = selectedNode.data as WorkflowDiagramStepNodeData; setWorkflowSelectedNode(selectedNode.id); + + if (isCommandMenuV2Enabled && isDefined(workflowId)) { + openWorkflowEditStepInCommandMenu( + workflowId, + selectedNodeData.name, + getIcon(getWorkflowNodeIconKey(selectedNodeData)), + ); + + return; + } + setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false }); openRightDrawer(RightDrawerPages.WorkflowStepEdit, { title: selectedNodeData.name, @@ -82,15 +109,18 @@ export const WorkflowDiagramCanvasEditableEffect = () => { }, [ isInRightDrawer, - setWorkflowSelectedNode, - setHotkeyScope, - openRightDrawer, - getIcon, + isCommandMenuV2Enabled, setCommandMenuNavigationStack, closeRightDrawer, - closeCommandMenu, + workflowId, + openRightDrawer, t, + openWorkflowTriggerTypeInCommandMenu, startNodeCreation, + openWorkflowEditStepInCommandMenu, + getIcon, + setWorkflowSelectedNode, + setHotkeyScope, ], ); diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasReadonlyEffect.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasReadonlyEffect.tsx index 59c19f4f0..92d539467 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasReadonlyEffect.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowDiagramCanvasReadonlyEffect.tsx @@ -3,6 +3,7 @@ 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 { workflowIdState } from '@/workflow/states/workflowIdState'; import { EMPTY_TRIGGER_STEP_ID } from '@/workflow/workflow-diagram/constants/EmptyTriggerStepId'; import { useTriggerNodeSelection } from '@/workflow/workflow-diagram/hooks/useTriggerNodeSelection'; import { workflowSelectedNodeState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeState'; @@ -11,18 +12,25 @@ import { WorkflowDiagramStepNodeData, } from '@/workflow/workflow-diagram/types/WorkflowDiagram'; import { getWorkflowNodeIconKey } from '@/workflow/workflow-diagram/utils/getWorkflowNodeIconKey'; +import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { OnSelectionChangeParams, useOnSelectionChange } from '@xyflow/react'; import { useCallback } from 'react'; -import { useSetRecoilState } from 'recoil'; +import { useRecoilValue, useSetRecoilState } from 'recoil'; import { isDefined } from 'twenty-shared'; import { useIcons } from 'twenty-ui'; +import { FeatureFlagKey } from '~/generated-metadata/graphql'; export const WorkflowDiagramCanvasReadonlyEffect = () => { const { getIcon } = useIcons(); const { openRightDrawer, closeRightDrawer } = useRightDrawer(); const setWorkflowSelectedNode = useSetRecoilState(workflowSelectedNodeState); const setHotkeyScope = useSetHotkeyScope(); - const { closeCommandMenu } = useCommandMenu(); + const { openWorkflowViewStepInCommandMenu } = useCommandMenu(); + const isCommandMenuV2Enabled = useIsFeatureEnabled( + FeatureFlagKey.IsCommandMenuV2Enabled, + ); + + const workflowId = useRecoilValue(workflowIdState); const handleSelectionChange = useCallback( ({ nodes }: OnSelectionChangeParams) => { @@ -31,7 +39,6 @@ export const WorkflowDiagramCanvasReadonlyEffect = () => { if (isClosingStep || selectedNode.type === EMPTY_TRIGGER_STEP_ID) { closeRightDrawer(); - closeCommandMenu(); return; } @@ -40,6 +47,15 @@ export const WorkflowDiagramCanvasReadonlyEffect = () => { const selectedNodeData = selectedNode.data as WorkflowDiagramStepNodeData; + if (isCommandMenuV2Enabled && isDefined(workflowId)) { + openWorkflowViewStepInCommandMenu( + workflowId, + selectedNodeData.name, + getIcon(getWorkflowNodeIconKey(selectedNodeData)), + ); + return; + } + openRightDrawer(RightDrawerPages.WorkflowStepView, { title: selectedNodeData.name, Icon: getIcon(getWorkflowNodeIconKey(selectedNodeData)), @@ -48,10 +64,12 @@ export const WorkflowDiagramCanvasReadonlyEffect = () => { [ setWorkflowSelectedNode, setHotkeyScope, - openRightDrawer, + isCommandMenuV2Enabled, closeRightDrawer, - closeCommandMenu, + openWorkflowViewStepInCommandMenu, + workflowId, getIcon, + openRightDrawer, ], ); diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunDiagramCanvasEffect.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunDiagramCanvasEffect.tsx index fc1c17794..62e471936 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunDiagramCanvasEffect.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunDiagramCanvasEffect.tsx @@ -5,6 +5,7 @@ import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPage import { useTabListStates } from '@/ui/layout/tab/hooks/internal/useTabListStates'; import { useSetHotkeyScope } from '@/ui/utilities/hotkey/hooks/useSetHotkeyScope'; import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue'; +import { workflowIdState } from '@/workflow/states/workflowIdState'; import { workflowSelectedNodeState } from '@/workflow/workflow-diagram/states/workflowSelectedNodeState'; import { WorkflowDiagramNode, @@ -14,18 +15,25 @@ import { getWorkflowNodeIconKey } from '@/workflow/workflow-diagram/utils/getWor import { WORKFLOW_RUN_STEP_SIDE_PANEL_TAB_LIST_COMPONENT_ID } from '@/workflow/workflow-steps/constants/WorkflowRunStepSidePanelTabListComponentId'; import { WorkflowRunTabId } from '@/workflow/workflow-steps/types/WorkflowRunTabId'; import { TRIGGER_STEP_ID } from '@/workflow/workflow-trigger/constants/TriggerStepId'; +import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { OnSelectionChangeParams, useOnSelectionChange } from '@xyflow/react'; import { useCallback } from 'react'; -import { useRecoilCallback, useSetRecoilState } from 'recoil'; +import { useRecoilCallback, useRecoilValue, useSetRecoilState } from 'recoil'; import { isDefined } from 'twenty-shared'; import { useIcons } from 'twenty-ui'; +import { FeatureFlagKey } from '~/generated-metadata/graphql'; export const WorkflowRunDiagramCanvasEffect = () => { const { getIcon } = useIcons(); const { openRightDrawer, closeRightDrawer } = useRightDrawer(); const setWorkflowSelectedNode = useSetRecoilState(workflowSelectedNodeState); const setHotkeyScope = useSetHotkeyScope(); - const { closeCommandMenu } = useCommandMenu(); + const { openWorkflowViewRunStepInCommandMenu } = useCommandMenu(); + const isCommandMenuV2Enabled = useIsFeatureEnabled( + FeatureFlagKey.IsCommandMenuV2Enabled, + ); + + const workflowId = useRecoilValue(workflowIdState); const { activeTabIdState: workflowRunRightDrawerListActiveTabIdState } = useTabListStates({ @@ -57,7 +65,6 @@ export const WorkflowRunDiagramCanvasEffect = () => { if (isClosingStep) { closeRightDrawer(); - closeCommandMenu(); return; } @@ -74,6 +81,16 @@ export const WorkflowRunDiagramCanvasEffect = () => { goBackToFirstWorkflowRunRightDrawerTabIfNeeded(); } + if (isCommandMenuV2Enabled && isDefined(workflowId)) { + openWorkflowViewRunStepInCommandMenu( + workflowId, + selectedNodeData.name, + getIcon(getWorkflowNodeIconKey(selectedNodeData)), + ); + + return; + } + openRightDrawer(RightDrawerPages.WorkflowRunStepView, { title: selectedNodeData.name, Icon: getIcon(getWorkflowNodeIconKey(selectedNodeData)), @@ -82,11 +99,13 @@ export const WorkflowRunDiagramCanvasEffect = () => { [ setWorkflowSelectedNode, setHotkeyScope, + isCommandMenuV2Enabled, + workflowId, openRightDrawer, getIcon, closeRightDrawer, - closeCommandMenu, goBackToFirstWorkflowRunRightDrawerTabIfNeeded, + openWorkflowViewRunStepInCommandMenu, ], ); 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 91099e0a9..f550e45ad 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 @@ -1,11 +1,16 @@ +import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu'; 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 { workflowIdState } from '@/workflow/states/workflowIdState'; import { workflowCreateStepFromParentStepIdState } from '@/workflow/workflow-steps/states/workflowCreateStepFromParentStepIdState'; +import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { useCallback } from 'react'; -import { useSetRecoilState } from 'recoil'; +import { useRecoilValue, useSetRecoilState } from 'recoil'; +import { isDefined } from 'twenty-shared'; import { IconSettingsAutomation } from 'twenty-ui'; +import { FeatureFlagKey } from '~/generated-metadata/graphql'; export const useStartNodeCreation = () => { const { openRightDrawer } = useRightDrawer(); @@ -13,6 +18,13 @@ export const useStartNodeCreation = () => { workflowCreateStepFromParentStepIdState, ); const setHotkeyScope = useSetHotkeyScope(); + const { openWorkflowActionInCommandMenu } = useCommandMenu(); + + const workflowId = useRecoilValue(workflowIdState); + + const isCommandMenuV2Enabled = useIsFeatureEnabled( + FeatureFlagKey.IsCommandMenuV2Enabled, + ); /** * This function is used in a context where dependencies shouldn't change much. @@ -22,13 +34,25 @@ export const useStartNodeCreation = () => { (parentNodeId: string) => { setWorkflowCreateStepFromParentStepId(parentNodeId); + if (isCommandMenuV2Enabled && isDefined(workflowId)) { + openWorkflowActionInCommandMenu(workflowId); + return; + } + setHotkeyScope(RightDrawerHotkeyScope.RightDrawer, { goto: false }); openRightDrawer(RightDrawerPages.WorkflowStepSelectAction, { title: 'Select Action', Icon: IconSettingsAutomation, }); }, - [setWorkflowCreateStepFromParentStepId, setHotkeyScope, openRightDrawer], + [ + setWorkflowCreateStepFromParentStepId, + isCommandMenuV2Enabled, + openWorkflowActionInCommandMenu, + workflowId, + setHotkeyScope, + openRightDrawer, + ], ); return { diff --git a/packages/twenty-front/src/modules/workflow/workflow-trigger/components/RightDrawerWorkflowSelectTriggerTypeContent.tsx b/packages/twenty-front/src/modules/workflow/workflow-trigger/components/RightDrawerWorkflowSelectTriggerTypeContent.tsx index 78e5e3299..b8996a11e 100644 --- a/packages/twenty-front/src/modules/workflow/workflow-trigger/components/RightDrawerWorkflowSelectTriggerTypeContent.tsx +++ b/packages/twenty-front/src/modules/workflow/workflow-trigger/components/RightDrawerWorkflowSelectTriggerTypeContent.tsx @@ -1,3 +1,4 @@ +import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu'; import { useFilteredObjectMetadataItems } from '@/object-metadata/hooks/useFilteredObjectMetadataItems'; import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer'; import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages'; @@ -13,8 +14,10 @@ import { OTHER_TRIGGER_TYPES } from '@/workflow/workflow-trigger/constants/Other import { TRIGGER_STEP_ID } from '@/workflow/workflow-trigger/constants/TriggerStepId'; import { useUpdateWorkflowVersionTrigger } from '@/workflow/workflow-trigger/hooks/useUpdateWorkflowVersionTrigger'; import { getTriggerDefaultDefinition } from '@/workflow/workflow-trigger/utils/getTriggerDefaultDefinition'; +import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; import { useSetRecoilState } from 'recoil'; import { MenuItemCommand, useIcons } from 'twenty-ui'; +import { FeatureFlagKey } from '~/generated-metadata/graphql'; export const RightDrawerWorkflowSelectTriggerTypeContent = ({ workflow, @@ -28,6 +31,10 @@ export const RightDrawerWorkflowSelectTriggerTypeContent = ({ const { openRightDrawer } = useRightDrawer(); const setWorkflowSelectedNode = useSetRecoilState(workflowSelectedNodeState); + const { openWorkflowEditStepInCommandMenu } = useCommandMenu(); + const isCommandMenuV2Enabled = useIsFeatureEnabled( + FeatureFlagKey.IsCommandMenuV2Enabled, + ); const handleTriggerTypeClick = ({ type, @@ -49,10 +56,18 @@ export const RightDrawerWorkflowSelectTriggerTypeContent = ({ setWorkflowSelectedNode(TRIGGER_STEP_ID); - openRightDrawer(RightDrawerPages.WorkflowStepEdit, { - title: defaultLabel, - Icon: getIcon(icon), - }); + if (isCommandMenuV2Enabled) { + openWorkflowEditStepInCommandMenu( + workflow.id, + defaultLabel, + getIcon(icon), + ); + } else { + openRightDrawer(RightDrawerPages.WorkflowStepEdit, { + title: defaultLabel, + Icon: getIcon(icon), + }); + } }; };