From cddc92c00ff1e6920babf275746d155ab2115fd3 Mon Sep 17 00:00:00 2001 From: Baptiste Devessier Date: Thu, 5 Sep 2024 16:41:36 +0200 Subject: [PATCH] Display workflow visualizer on show page (#6894) - Removed the route I previously used to visualize workflows - Created another tab in the `` component in which we display the visualizer Questions: - Should I use a feature flag to hide the feature? Closes #6858 --- packages/twenty-front/src/App.tsx | 10 --- ...sePageChangeEffectNavigateLocation.test.ts | 11 ---- .../twenty-front/src/modules/types/AppPath.ts | 2 - .../hooks/__tests__/useShowAuthModal.test.tsx | 11 ---- .../components/ShowPageRightContainer.tsx | 27 ++++++-- .../modules/workflow/components/Workflow.tsx | 48 ++++++++++++++ .../src/pages/workflows/WorkflowShowPage.tsx | 64 ------------------- 7 files changed, 71 insertions(+), 102 deletions(-) create mode 100644 packages/twenty-front/src/modules/workflow/components/Workflow.tsx delete mode 100644 packages/twenty-front/src/pages/workflows/WorkflowShowPage.tsx diff --git a/packages/twenty-front/src/App.tsx b/packages/twenty-front/src/App.tsx index 6ba39e4d91b1..1c6adcfdf60e 100644 --- a/packages/twenty-front/src/App.tsx +++ b/packages/twenty-front/src/App.tsx @@ -50,7 +50,6 @@ import { CreateWorkspace } from '~/pages/onboarding/CreateWorkspace'; import { InviteTeam } from '~/pages/onboarding/InviteTeam'; import { PaymentSuccess } from '~/pages/onboarding/PaymentSuccess'; import { SyncEmails } from '~/pages/onboarding/SyncEmails'; -import { WorkflowShowPage } from '~/pages/workflows/WorkflowShowPage'; import { SettingsRoutes } from '~/SettingsRoutes'; import { getPageTitleFromPath } from '~/utils/title-utils'; @@ -103,7 +102,6 @@ const createRouter = ( isBillingEnabled?: boolean, isCRMMigrationEnabled?: boolean, isServerlessFunctionSettingsEnabled?: boolean, - isWorkflowEnabled?: boolean, ) => createBrowserRouter( createRoutesFromElements( @@ -131,12 +129,6 @@ const createRouter = ( } /> } /> } /> - {isWorkflowEnabled === true ? ( - } - /> - ) : null} { const isServerlessFunctionSettingsEnabled = useIsFeatureEnabled( 'IS_FUNCTION_SETTINGS_ENABLED', ); - const isWorkflowEnabled = useIsFeatureEnabled('IS_WORKFLOW_ENABLED'); const isBillingPageEnabled = billing?.isBillingEnabled && !isFreeAccessEnabled; @@ -176,7 +167,6 @@ export const App = () => { isBillingPageEnabled, isCRMMigrationEnabled, isServerlessFunctionSettingsEnabled, - isWorkflowEnabled, )} /> ); diff --git a/packages/twenty-front/src/hooks/__tests__/usePageChangeEffectNavigateLocation.test.ts b/packages/twenty-front/src/hooks/__tests__/usePageChangeEffectNavigateLocation.test.ts index bde6abe9c771..95c2a58b79c6 100644 --- a/packages/twenty-front/src/hooks/__tests__/usePageChangeEffectNavigateLocation.test.ts +++ b/packages/twenty-front/src/hooks/__tests__/usePageChangeEffectNavigateLocation.test.ts @@ -244,17 +244,6 @@ const testCases = [ { loc: AppPath.Impersonate, isLoggedIn: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.InviteTeam, res: AppPath.InviteTeam }, { loc: AppPath.Impersonate, isLoggedIn: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.Completed, res: undefined }, - { loc: AppPath.WorkflowShowPage, isLoggedIn: true, subscriptionStatus: undefined, onboardingStatus: OnboardingStatus.PlanRequired, res: AppPath.PlanRequired }, - { loc: AppPath.WorkflowShowPage, isLoggedIn: true, subscriptionStatus: SubscriptionStatus.Canceled, onboardingStatus: OnboardingStatus.Completed, res: '/settings/billing' }, - { loc: AppPath.WorkflowShowPage, isLoggedIn: true, subscriptionStatus: SubscriptionStatus.Unpaid, onboardingStatus: OnboardingStatus.Completed, res: '/settings/billing' }, - { loc: AppPath.WorkflowShowPage, isLoggedIn: true, subscriptionStatus: SubscriptionStatus.PastDue, onboardingStatus: OnboardingStatus.Completed, res: undefined }, - { loc: AppPath.WorkflowShowPage, isLoggedIn: false, subscriptionStatus: undefined, onboardingStatus: undefined, res: AppPath.SignInUp }, - { loc: AppPath.WorkflowShowPage, isLoggedIn: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.WorkspaceActivation, res: AppPath.CreateWorkspace }, - { loc: AppPath.WorkflowShowPage, isLoggedIn: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.ProfileCreation, res: AppPath.CreateProfile }, - { loc: AppPath.WorkflowShowPage, isLoggedIn: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.SyncEmail, res: AppPath.SyncEmails }, - { loc: AppPath.WorkflowShowPage, isLoggedIn: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.InviteTeam, res: AppPath.InviteTeam }, - { loc: AppPath.WorkflowShowPage, isLoggedIn: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.Completed, res: undefined }, - { loc: AppPath.Authorize, isLoggedIn: true, subscriptionStatus: undefined, onboardingStatus: OnboardingStatus.PlanRequired, res: AppPath.PlanRequired }, { loc: AppPath.Authorize, isLoggedIn: true, subscriptionStatus: SubscriptionStatus.Canceled, onboardingStatus: OnboardingStatus.Completed, res: '/settings/billing' }, { loc: AppPath.Authorize, isLoggedIn: true, subscriptionStatus: SubscriptionStatus.Unpaid, onboardingStatus: OnboardingStatus.Completed, res: '/settings/billing' }, diff --git a/packages/twenty-front/src/modules/types/AppPath.ts b/packages/twenty-front/src/modules/types/AppPath.ts index 12d6f7c19e7f..dbbab7ad239e 100644 --- a/packages/twenty-front/src/modules/types/AppPath.ts +++ b/packages/twenty-front/src/modules/types/AppPath.ts @@ -26,8 +26,6 @@ export enum AppPath { Developers = `developers`, DevelopersCatchAll = `/${Developers}/*`, - WorkflowShowPage = `/workflow/:workflowId`, - // Impersonate Impersonate = '/impersonate/:userId', diff --git a/packages/twenty-front/src/modules/ui/layout/hooks/__tests__/useShowAuthModal.test.tsx b/packages/twenty-front/src/modules/ui/layout/hooks/__tests__/useShowAuthModal.test.tsx index e81f8701e8e2..ee0a46590417 100644 --- a/packages/twenty-front/src/modules/ui/layout/hooks/__tests__/useShowAuthModal.test.tsx +++ b/packages/twenty-front/src/modules/ui/layout/hooks/__tests__/useShowAuthModal.test.tsx @@ -254,17 +254,6 @@ const testCases = [ { loc: AppPath.Impersonate, isLogged: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.InviteTeam, res: true }, { loc: AppPath.Impersonate, isLogged: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.Completed, res: false }, - { loc: AppPath.WorkflowShowPage, isLogged: true, subscriptionStatus: undefined, onboardingStatus: OnboardingStatus.PlanRequired, res: true }, - { loc: AppPath.WorkflowShowPage, isLogged: true, subscriptionStatus: SubscriptionStatus.Canceled, onboardingStatus: OnboardingStatus.Completed, res: false }, - { loc: AppPath.WorkflowShowPage, isLogged: true, subscriptionStatus: SubscriptionStatus.Unpaid, onboardingStatus: OnboardingStatus.Completed, res: false }, - { loc: AppPath.WorkflowShowPage, isLogged: true, subscriptionStatus: SubscriptionStatus.PastDue, onboardingStatus: OnboardingStatus.Completed, res: false }, - { loc: AppPath.WorkflowShowPage, isLogged: false, subscriptionStatus: undefined, onboardingStatus: undefined, res: true }, - { loc: AppPath.WorkflowShowPage, isLogged: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.WorkspaceActivation, res: true }, - { loc: AppPath.WorkflowShowPage, isLogged: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.ProfileCreation, res: true }, - { loc: AppPath.WorkflowShowPage, isLogged: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.SyncEmail, res: true }, - { loc: AppPath.WorkflowShowPage, isLogged: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.InviteTeam, res: true }, - { loc: AppPath.WorkflowShowPage, isLogged: true, subscriptionStatus: SubscriptionStatus.Active, onboardingStatus: OnboardingStatus.Completed, res: false }, - { loc: AppPath.Authorize, isLogged: true, subscriptionStatus: undefined, onboardingStatus: OnboardingStatus.PlanRequired, res: true }, { loc: AppPath.Authorize, isLogged: true, subscriptionStatus: SubscriptionStatus.Canceled, onboardingStatus: OnboardingStatus.Completed, res: false }, { loc: AppPath.Authorize, isLogged: true, subscriptionStatus: SubscriptionStatus.Unpaid, onboardingStatus: OnboardingStatus.Completed, res: false }, diff --git a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx index 96a129c122e5..0df732bfe2a9 100644 --- a/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx +++ b/packages/twenty-front/src/modules/ui/layout/show-page/components/ShowPageRightContainer.tsx @@ -7,6 +7,7 @@ import { IconMail, IconNotes, IconPaperclip, + IconSettings, IconTimelineEvent, } from 'twenty-ui'; @@ -22,6 +23,8 @@ import { ShowPageActivityContainer } from '@/ui/layout/show-page/components/Show import { TabList } from '@/ui/layout/tab/components/TabList'; import { useTabList } from '@/ui/layout/tab/hooks/useTabList'; import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile'; +import { Workflow } from '@/workflow/components/Workflow'; +import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled'; const StyledShowPageRightContainer = styled.div<{ isMobile: boolean }>` display: flex; @@ -95,6 +98,12 @@ export const ShowPageRightContainer = ({ CoreObjectNameSingular.Person, ].includes(targetObjectNameSingular); + const isWorkflowEnabled = useIsFeatureEnabled('IS_WORKFLOW_ENABLED'); + const isWorkflow = + isWorkflowEnabled && + targetableObject.targetObjectNameSingular === + CoreObjectNameSingular.Workflow; + const shouldDisplayCalendarTab = isCompanyOrPerson; const shouldDisplayEmailsTab = emails && isCompanyOrPerson; @@ -122,7 +131,7 @@ export const ShowPageRightContainer = ({ id: 'timeline', title: 'Timeline', Icon: IconTimelineEvent, - hide: !timeline || isInRightDrawer, + hide: !timeline || isInRightDrawer || isWorkflow, }, { id: 'tasks', @@ -133,7 +142,8 @@ export const ShowPageRightContainer = ({ targetableObject.targetObjectNameSingular === CoreObjectNameSingular.Note || targetableObject.targetObjectNameSingular === - CoreObjectNameSingular.Task, + CoreObjectNameSingular.Task || + isWorkflow, }, { id: 'notes', @@ -144,13 +154,14 @@ export const ShowPageRightContainer = ({ targetableObject.targetObjectNameSingular === CoreObjectNameSingular.Note || targetableObject.targetObjectNameSingular === - CoreObjectNameSingular.Task, + CoreObjectNameSingular.Task || + isWorkflow, }, { id: 'files', title: 'Files', Icon: IconPaperclip, - hide: !notes, + hide: !notes || isWorkflow, }, { id: 'emails', @@ -164,6 +175,12 @@ export const ShowPageRightContainer = ({ Icon: IconCalendarEvent, hide: !shouldDisplayCalendarTab, }, + { + id: 'workflow', + title: 'Workflow', + Icon: IconSettings, + hide: !isWorkflow, + }, ]; const renderActiveTabContent = () => { switch (activeTabId) { @@ -202,6 +219,8 @@ export const ShowPageRightContainer = ({ return ; case 'calendar': return ; + case 'workflow': + return ; default: return <>; } diff --git a/packages/twenty-front/src/modules/workflow/components/Workflow.tsx b/packages/twenty-front/src/modules/workflow/components/Workflow.tsx new file mode 100644 index 000000000000..d0b3331e045c --- /dev/null +++ b/packages/twenty-front/src/modules/workflow/components/Workflow.tsx @@ -0,0 +1,48 @@ +import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity'; +import { WorkflowDiagramCanvas } from '@/workflow/components/WorkflowDiagramCanvas'; +import { WorkflowShowPageEffect } from '@/workflow/components/WorkflowShowPageEffect'; +import { workflowDiagramState } from '@/workflow/states/workflowDiagramState'; +import styled from '@emotion/styled'; +import '@xyflow/react/dist/style.css'; +import { useRecoilValue } from 'recoil'; + +const StyledFlowContainer = styled.div` + height: 100%; + width: 100%; + + /* Below we reset the default styling of Reactflow */ + .react-flow__node-input, + .react-flow__node-default, + .react-flow__node-output, + .react-flow__node-group { + padding: 0; + } + + --xy-node-border-radius: none; + --xy-node-border: none; + --xy-node-background-color: none; + --xy-node-boxshadow-hover: none; + --xy-node-boxshadow-selected: none; +`; + +export const Workflow = ({ + targetableObject, +}: { + targetableObject: ActivityTargetableObject; +}) => { + const workflowId = targetableObject.id; + + const workflowDiagram = useRecoilValue(workflowDiagramState); + + return ( + <> + + + + {workflowDiagram === undefined ? null : ( + + )} + + + ); +}; diff --git a/packages/twenty-front/src/pages/workflows/WorkflowShowPage.tsx b/packages/twenty-front/src/pages/workflows/WorkflowShowPage.tsx deleted file mode 100644 index 5177f98872da..000000000000 --- a/packages/twenty-front/src/pages/workflows/WorkflowShowPage.tsx +++ /dev/null @@ -1,64 +0,0 @@ -import { PageBody } from '@/ui/layout/page/PageBody'; -import { PageContainer } from '@/ui/layout/page/PageContainer'; -import { PageTitle } from '@/ui/utilities/page-title/PageTitle'; -import { WorkflowDiagramCanvas } from '@/workflow/components/WorkflowDiagramCanvas'; -import { WorkflowShowPageEffect } from '@/workflow/components/WorkflowShowPageEffect'; -import { WorkflowShowPageHeader } from '@/workflow/components/WorkflowShowPageHeader'; -import { workflowDiagramState } from '@/workflow/states/workflowDiagramState'; -import styled from '@emotion/styled'; -import '@xyflow/react/dist/style.css'; -import { useParams } from 'react-router-dom'; -import { useRecoilValue } from 'recoil'; -import { IconSettingsAutomation } from 'twenty-ui'; - -const StyledFlowContainer = styled.div` - height: 100%; - width: 100%; - - /* Below we reset the default styling of Reactflow */ - .react-flow__node-input, - .react-flow__node-default, - .react-flow__node-output, - .react-flow__node-group { - padding: 0; - } - - --xy-node-border-radius: none; - --xy-node-border: none; - --xy-node-background-color: none; - --xy-node-boxshadow-hover: none; - --xy-node-boxshadow-selected: none; -`; - -export const WorkflowShowPage = () => { - const parameters = useParams<{ - workflowId: string; - }>(); - - const workflowName = 'Test Workflow'; - - const workflowDiagram = useRecoilValue(workflowDiagramState); - - if (parameters.workflowId === undefined) { - return null; - } - - return ( - - - - - - - - {workflowDiagram === undefined ? null : ( - - )} - - - - ); -};