271 remove is command menu v2 enabled (#10809)

Closes https://github.com/twentyhq/core-team-issues/issues/271

This PR
- Removes the feature flag IS_COMMAND_MENU_V2_ENABLED
- Removes all old Right drawer components
- Removes the Action menu bar
- Removes unused Copilot page
This commit is contained in:
Raphaël Bosi
2025-03-12 16:26:29 +01:00
committed by GitHub
parent 1b0413bf8b
commit daa501549e
124 changed files with 281 additions and 4222 deletions

View File

@ -1,61 +0,0 @@
import styled from '@emotion/styled';
import { useBottomBarInternalHotkeyScopeManagement } from '@/ui/layout/bottom-bar/hooks/useBottomBarInternalHotkeyScopeManagement';
import { BottomBarInstanceContext } from '@/ui/layout/bottom-bar/states/contexts/BottomBarInstanceContext';
import { isBottomBarOpenedComponentState } from '@/ui/layout/bottom-bar/states/isBottomBarOpenedComponentState';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useRecoilComponentValueV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentValueV2';
const StyledContainerActionBar = styled.div`
align-items: center;
background: ${({ theme }) => theme.background.secondary};
border: 1px solid ${({ theme }) => theme.border.color.medium};
border-radius: ${({ theme }) => theme.border.radius.md};
bottom: 38px;
box-shadow: ${({ theme }) => theme.boxShadow.strong};
display: flex;
height: 48px;
width: max-content;
left: 50%;
padding-left: ${({ theme }) => theme.spacing(2)};
padding-right: ${({ theme }) => theme.spacing(2)};
position: absolute;
top: auto;
transform: translateX(-50%);
z-index: 1;
`;
type BottomBarProps = {
bottomBarId: string;
bottomBarHotkeyScopeFromParent: HotkeyScope;
children: React.ReactNode;
};
export const BottomBar = ({
bottomBarId,
bottomBarHotkeyScopeFromParent,
children,
}: BottomBarProps) => {
const isBottomBarOpen = useRecoilComponentValueV2(
isBottomBarOpenedComponentState,
bottomBarId,
);
useBottomBarInternalHotkeyScopeManagement({
bottomBarId,
bottomBarHotkeyScopeFromParent,
});
if (!isBottomBarOpen) {
return null;
}
return (
<BottomBarInstanceContext.Provider value={{ instanceId: bottomBarId }}>
<StyledContainerActionBar data-select-disable className="bottom-bar">
{children}
</StyledContainerActionBar>
</BottomBarInstanceContext.Provider>
);
};

View File

@ -1,63 +0,0 @@
import { BottomBar } from '@/ui/layout/bottom-bar/components/BottomBar';
import { isBottomBarOpenedComponentState } from '@/ui/layout/bottom-bar/states/isBottomBarOpenedComponentState';
import styled from '@emotion/styled';
import { Meta, StoryObj } from '@storybook/react';
import { RecoilRoot } from 'recoil';
import { Button, IconPlus } from 'twenty-ui';
const StyledContainer = styled.div`
display: flex;
gap: 10px;
`;
const meta: Meta<typeof BottomBar> = {
title: 'UI/Layout/BottomBar/BottomBar',
component: BottomBar,
args: {
bottomBarId: 'test',
bottomBarHotkeyScopeFromParent: { scope: 'test' },
children: (
<StyledContainer>
<Button title="Test 1" Icon={IconPlus} />
<Button title="Test 2" Icon={IconPlus} />
<Button title="Test 3" Icon={IconPlus} />
</StyledContainer>
),
},
argTypes: {
bottomBarId: { control: false },
bottomBarHotkeyScopeFromParent: { control: false },
children: { control: false },
},
};
export default meta;
export const Default: StoryObj<typeof BottomBar> = {
decorators: [
(Story) => (
<RecoilRoot
initializeState={({ set }) => {
set(
isBottomBarOpenedComponentState.atomFamily({
instanceId: 'test',
}),
true,
);
}}
>
<Story />
</RecoilRoot>
),
],
};
export const Closed: StoryObj<typeof BottomBar> = {
decorators: [
(Story) => (
<RecoilRoot>
<Story />
</RecoilRoot>
),
],
};

View File

@ -1,87 +0,0 @@
import { useRecoilCallback } from 'recoil';
import { bottomBarHotkeyComponentState } from '@/ui/layout/bottom-bar/states/bottomBarHotkeyComponentState';
import { isBottomBarOpenedComponentState } from '@/ui/layout/bottom-bar/states/isBottomBarOpenedComponentState';
import { usePreviousHotkeyScope } from '@/ui/utilities/hotkey/hooks/usePreviousHotkeyScope';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { isDefined } from 'twenty-shared';
export const useBottomBar = () => {
const {
setHotkeyScopeAndMemorizePreviousScope,
goBackToPreviousHotkeyScope,
} = usePreviousHotkeyScope();
const closeBottomBar = useRecoilCallback(
({ set }) =>
(specificComponentId: string) => {
goBackToPreviousHotkeyScope();
set(
isBottomBarOpenedComponentState.atomFamily({
instanceId: specificComponentId,
}),
false,
);
},
[goBackToPreviousHotkeyScope],
);
const openBottomBar = useRecoilCallback(
({ set, snapshot }) =>
(specificComponentId: string, customHotkeyScope?: HotkeyScope) => {
const bottomBarHotkeyScope = snapshot
.getLoadable(
bottomBarHotkeyComponentState.atomFamily({
instanceId: specificComponentId,
}),
)
.getValue();
set(
isBottomBarOpenedComponentState.atomFamily({
instanceId: specificComponentId,
}),
true,
);
if (isDefined(customHotkeyScope)) {
setHotkeyScopeAndMemorizePreviousScope(
customHotkeyScope.scope,
customHotkeyScope.customScopes,
);
} else if (isDefined(bottomBarHotkeyScope)) {
setHotkeyScopeAndMemorizePreviousScope(
bottomBarHotkeyScope.scope,
bottomBarHotkeyScope.customScopes,
);
}
},
[setHotkeyScopeAndMemorizePreviousScope],
);
const toggleBottomBar = useRecoilCallback(
({ snapshot }) =>
(specificComponentId: string) => {
const isBottomBarOpen = snapshot
.getLoadable(
isBottomBarOpenedComponentState.atomFamily({
instanceId: specificComponentId,
}),
)
.getValue();
if (isBottomBarOpen) {
closeBottomBar(specificComponentId);
} else {
openBottomBar(specificComponentId);
}
},
[closeBottomBar, openBottomBar],
);
return {
closeBottomBar,
openBottomBar,
toggleBottomBar,
};
};

View File

@ -1,27 +0,0 @@
import { useEffect } from 'react';
import { bottomBarHotkeyComponentState } from '@/ui/layout/bottom-bar/states/bottomBarHotkeyComponentState';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { useRecoilComponentStateV2 } from '@/ui/utilities/state/component-state/hooks/useRecoilComponentStateV2';
import { isDeeplyEqual } from '~/utils/isDeeplyEqual';
export const useBottomBarInternalHotkeyScopeManagement = ({
bottomBarId,
bottomBarHotkeyScopeFromParent,
}: {
bottomBarId?: string;
bottomBarHotkeyScopeFromParent?: HotkeyScope;
}) => {
const [bottomBarHotkeyScope, setBottomBarHotkeyScope] =
useRecoilComponentStateV2(bottomBarHotkeyComponentState, bottomBarId);
useEffect(() => {
if (!isDeeplyEqual(bottomBarHotkeyScopeFromParent, bottomBarHotkeyScope)) {
setBottomBarHotkeyScope(bottomBarHotkeyScopeFromParent);
}
}, [
bottomBarHotkeyScope,
bottomBarHotkeyScopeFromParent,
setBottomBarHotkeyScope,
]);
};

View File

@ -1,11 +0,0 @@
import { BottomBarInstanceContext } from '@/ui/layout/bottom-bar/states/contexts/BottomBarInstanceContext';
import { HotkeyScope } from '@/ui/utilities/hotkey/types/HotkeyScope';
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
export const bottomBarHotkeyComponentState = createComponentStateV2<
HotkeyScope | null | undefined
>({
key: 'bottomBarHotkeyComponentState',
defaultValue: null,
componentInstanceContext: BottomBarInstanceContext,
});

View File

@ -1,3 +0,0 @@
import { createComponentInstanceContext } from '@/ui/utilities/state/component-state/utils/createComponentInstanceContext';
export const BottomBarInstanceContext = createComponentInstanceContext();

View File

@ -1,8 +0,0 @@
import { BottomBarInstanceContext } from '@/ui/layout/bottom-bar/states/contexts/BottomBarInstanceContext';
import { createComponentStateV2 } from '@/ui/utilities/state/component-state/utils/createComponentStateV2';
export const isBottomBarOpenedComponentState = createComponentStateV2<boolean>({
key: 'isBottomBarOpenedComponentState',
defaultValue: false,
componentInstanceContext: BottomBarInstanceContext,
});

View File

@ -1,21 +1,12 @@
import {
AnimatedButton,
IconButton,
IconDotsVertical,
IconX,
getOsControlSymbol,
useIsMobile,
} from 'twenty-ui';
import { AnimatedButton, getOsControlSymbol, useIsMobile } from 'twenty-ui';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { isCommandMenuOpenedState } from '@/command-menu/states/isCommandMenuOpenedState';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { t } from '@lingui/core/macro';
import { motion } from 'framer-motion';
import { useRecoilValue } from 'recoil';
import { FeatureFlagKey } from '~/generated/graphql';
const StyledButtonWrapper = styled.div`
z-index: 30;
@ -108,10 +99,6 @@ export const PageHeaderOpenCommandMenuButton = () => {
const { toggleCommandMenu } = useCommandMenu();
const isCommandMenuOpened = useRecoilValue(isCommandMenuOpenedState);
const isCommandMenuV2Enabled = useIsFeatureEnabled(
FeatureFlagKey.IsCommandMenuV2Enabled,
);
const isMobile = useIsMobile();
const ariaLabel = isCommandMenuOpened
@ -122,37 +109,24 @@ export const PageHeaderOpenCommandMenuButton = () => {
return (
<StyledButtonWrapper>
{isCommandMenuV2Enabled ? (
<AnimatedButton
animatedSvg={
<AnimatedIcon isCommandMenuOpened={isCommandMenuOpened} />
}
className="page-header-command-menu-button"
dataTestId="page-header-command-menu-button"
size={isMobile ? 'medium' : 'small'}
variant="secondary"
accent="default"
hotkeys={[getOsControlSymbol(), 'K']}
ariaLabel={ariaLabel}
onClick={toggleCommandMenu}
animate={{
rotate: isCommandMenuOpened ? 90 : 0,
}}
transition={{
duration: theme.animation.duration.normal,
ease: 'easeInOut',
}}
/>
) : (
<IconButton
Icon={isCommandMenuOpened ? IconX : IconDotsVertical}
size="medium"
dataTestId="more-showpage-button"
accent="default"
variant="secondary"
onClick={toggleCommandMenu}
/>
)}
<AnimatedButton
animatedSvg={<AnimatedIcon isCommandMenuOpened={isCommandMenuOpened} />}
className="page-header-command-menu-button"
dataTestId="page-header-command-menu-button"
size={isMobile ? 'medium' : 'small'}
variant="secondary"
accent="default"
hotkeys={[getOsControlSymbol(), 'K']}
ariaLabel={ariaLabel}
onClick={toggleCommandMenu}
animate={{
rotate: isCommandMenuOpened ? 90 : 0,
}}
transition={{
duration: theme.animation.duration.normal,
ease: 'easeInOut',
}}
/>
</StyledButtonWrapper>
);
};

View File

@ -1,18 +1,12 @@
import { useHasObjectReadOnlyPermission } from '@/settings/roles/hooks/useHasObjectReadOnlyPermission';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { useLingui } from '@lingui/react/macro';
import { Button, IconButton, IconPlus, useIsMobile } from 'twenty-ui';
import { FeatureFlagKey } from '~/generated/graphql';
import { Button, IconPlus, useIsMobile } from 'twenty-ui';
type PageAddButtonProps = {
onClick?: () => void;
};
export const PageAddButton = ({ onClick }: PageAddButtonProps) => {
const isCommandMenuV2Enabled = useIsFeatureEnabled(
FeatureFlagKey.IsCommandMenuV2Enabled,
);
const hasObjectReadOnlyPermission = useHasObjectReadOnlyPermission();
const isMobile = useIsMobile();
@ -24,29 +18,15 @@ export const PageAddButton = ({ onClick }: PageAddButtonProps) => {
}
return (
<>
{isCommandMenuV2Enabled ? (
<Button
Icon={IconPlus}
dataTestId="add-button"
size={isMobile ? 'medium' : 'small'}
variant="secondary"
accent="default"
title={isMobile ? '' : t`New record`}
onClick={onClick}
ariaLabel={t`New record`}
/>
) : (
<IconButton
Icon={IconPlus}
dataTestId="add-button"
size="medium"
variant="secondary"
accent="default"
ariaLabel={t`Add`}
onClick={onClick}
/>
)}
</>
<Button
Icon={IconPlus}
dataTestId="add-button"
size={isMobile ? 'medium' : 'small'}
variant="secondary"
accent="default"
title={isMobile ? '' : t`New record`}
onClick={onClick}
ariaLabel={t`New record`}
/>
);
};

View File

@ -1,9 +1,7 @@
import { ReactNode } from 'react';
import styled from '@emotion/styled';
import { ReactNode } from 'react';
import { MOBILE_VIEWPORT } from 'twenty-ui';
import { RightDrawer } from '@/ui/layout/right-drawer/components/RightDrawer';
import { PagePanel } from './PagePanel';
type PageBodyProps = {
@ -45,6 +43,5 @@ export const PageBody = ({ children }: PageBodyProps) => (
<StyledLeftContainer>
<PagePanel>{children}</PagePanel>
</StyledLeftContainer>
<RightDrawer />
</StyledMainContainer>
);

View File

@ -3,9 +3,6 @@ import styled from '@emotion/styled';
import { ReactNode } from 'react';
import { useRecoilValue } from 'recoil';
import {
IconButton,
IconChevronDown,
IconChevronUp,
IconComponent,
IconX,
LightIconButton,
@ -17,8 +14,6 @@ import { NavigationDrawerCollapseButton } from '@/ui/navigation/navigation-drawe
import { isNavigationDrawerExpandedState } from '@/ui/navigation/states/isNavigationDrawerExpanded';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { FeatureFlagKey } from '~/generated/graphql';
export const PAGE_BAR_MIN_HEIGHT = 40;
@ -94,11 +89,6 @@ type PageHeaderProps = {
title?: ReactNode;
hasClosePageButton?: boolean;
onClosePage?: () => void;
hasPaginationButtons?: boolean;
hasPreviousRecord?: boolean;
hasNextRecord?: boolean;
navigateToPreviousRecord?: () => void;
navigateToNextRecord?: () => void;
Icon?: IconComponent;
children?: ReactNode;
};
@ -107,9 +97,6 @@ export const PageHeader = ({
title,
hasClosePageButton,
onClosePage,
hasPaginationButtons,
navigateToPreviousRecord,
navigateToNextRecord,
Icon,
children,
}: PageHeaderProps) => {
@ -119,10 +106,6 @@ export const PageHeader = ({
isNavigationDrawerExpandedState,
);
const isCommandMenuV2Enabled = useIsFeatureEnabled(
FeatureFlagKey.IsCommandMenuV2Enabled,
);
return (
<StyledTopBarContainer>
<StyledLeftContainer>
@ -141,25 +124,11 @@ export const PageHeader = ({
)}
<StyledTopBarIconStyledTitleContainer>
{!isCommandMenuV2Enabled && hasPaginationButtons && (
<>
<IconButton
Icon={IconChevronUp}
size="small"
variant="secondary"
onClick={() => navigateToPreviousRecord?.()}
/>
<IconButton
Icon={IconChevronDown}
size="small"
variant="secondary"
onClick={() => navigateToNextRecord?.()}
/>
</>
{Icon && (
<StyledIconContainer>
<Icon size={theme.icon.size.md} />
</StyledIconContainer>
)}
<StyledIconContainer>
{Icon && <Icon size={theme.icon.size.md} />}
</StyledIconContainer>
{title && (
<StyledTitleContainer data-testid="top-bar-title">
{typeof title === 'string' ? (

View File

@ -1,16 +0,0 @@
import { TableHotkeyScope } from '@/object-record/record-table/types/TableHotkeyScope';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
type PageHotkeysEffectProps = {
onAddButtonClick?: () => void;
};
export const PageHotkeysEffect = ({
onAddButtonClick,
}: PageHotkeysEffectProps) => {
useScopedHotkeys('c', () => onAddButtonClick?.(), TableHotkeyScope.Table, [
onAddButtonClick,
]);
return <></>;
};

View File

@ -1,94 +0,0 @@
import { isRightDrawerAnimationCompletedState } from '@/ui/layout/right-drawer/states/isRightDrawerAnimationCompletedState';
import { isRightDrawerMinimizedState } from '@/ui/layout/right-drawer/states/isRightDrawerMinimizedState';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { motion } from 'framer-motion';
import { useRecoilValue, useSetRecoilState } from 'recoil';
import { isDefined } from 'twenty-shared';
import { isRightDrawerOpenState } from '../states/isRightDrawerOpenState';
import { rightDrawerPageState } from '../states/rightDrawerPageState';
import { RIGHT_DRAWER_ANIMATION_VARIANTS } from '@/ui/layout/right-drawer/constants/RightDrawerAnimationVariants';
import { RightDrawerAnimationVariant } from '@/ui/layout/right-drawer/types/RightDrawerAnimationVariant';
import { RightDrawerRouter } from './RightDrawerRouter';
const StyledContainer = styled(motion.div)<{ isRightDrawerMinimized: boolean }>`
background: ${({ theme }) => theme.background.primary};
border-left: ${({ theme, isRightDrawerMinimized }) =>
isRightDrawerMinimized
? `1px solid ${theme.border.color.strong}`
: `1px solid ${theme.border.color.medium}`};
border-top: ${({ theme, isRightDrawerMinimized }) =>
isRightDrawerMinimized ? `1px solid ${theme.border.color.strong}` : 'none'};
border-top-left-radius: ${({ theme, isRightDrawerMinimized }) =>
isRightDrawerMinimized ? theme.border.radius.md : '0'};
box-shadow: ${({ theme, isRightDrawerMinimized }) =>
isRightDrawerMinimized ? 'none' : theme.boxShadow.light};
height: 100dvh;
overflow-x: hidden;
position: fixed;
right: 0;
top: 0;
z-index: 30;
.modal-backdrop {
background: ${({ theme }) => theme.background.overlayTertiary};
}
`;
const StyledRightDrawer = styled.div`
display: flex;
flex-direction: row;
width: 100%;
`;
export const RightDrawer = () => {
const theme = useTheme();
const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState);
const isRightDrawerMinimized = useRecoilValue(isRightDrawerMinimizedState);
const setIsRightDrawerAnimationCompleted = useSetRecoilState(
isRightDrawerAnimationCompletedState,
);
const rightDrawerPage = useRecoilValue(rightDrawerPageState);
const isMobile = useIsMobile();
const targetVariantForAnimation: RightDrawerAnimationVariant =
!isRightDrawerOpen
? 'closed'
: isRightDrawerMinimized
? 'minimized'
: isMobile
? 'fullScreen'
: 'normal';
const handleAnimationComplete = () => {
setIsRightDrawerAnimationCompleted(isRightDrawerOpen);
};
if (!isDefined(rightDrawerPage)) {
return <></>;
}
return (
<StyledContainer
isRightDrawerMinimized={isRightDrawerMinimized}
animate={targetVariantForAnimation}
variants={RIGHT_DRAWER_ANIMATION_VARIANTS}
transition={{ duration: theme.animation.duration.normal }}
onAnimationComplete={handleAnimationComplete}
>
<StyledRightDrawer>
{isRightDrawerOpen && <RightDrawerRouter />}
</StyledRightDrawer>
</StyledContainer>
);
};

View File

@ -1,84 +0,0 @@
import { RIGHT_DRAWER_CLICK_OUTSIDE_LISTENER_ID } from '@/ui/layout/right-drawer/constants/RightDrawerClickOutsideListener';
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
import { isRightDrawerMinimizedState } from '@/ui/layout/right-drawer/states/isRightDrawerMinimizedState';
import { isRightDrawerOpenState } from '@/ui/layout/right-drawer/states/isRightDrawerOpenState';
import { rightDrawerCloseEventState } from '@/ui/layout/right-drawer/states/rightDrawerCloseEventsState';
import { RightDrawerHotkeyScope } from '@/ui/layout/right-drawer/types/RightDrawerHotkeyScope';
import { useScopedHotkeys } from '@/ui/utilities/hotkey/hooks/useScopedHotkeys';
import {
ClickOutsideMode,
useListenClickOutside,
} from '@/ui/utilities/pointer-event/hooks/useListenClickOutside';
import { workflowReactFlowRefState } from '@/workflow/workflow-diagram/states/workflowReactFlowRefState';
import styled from '@emotion/styled';
import { useRef } from 'react';
import { useRecoilCallback, useRecoilValue } from 'recoil';
import { Key } from 'ts-key-enum';
const StyledRightDrawerPage = styled.div`
display: flex;
flex-direction: column;
height: 100%;
width: 100%;
`;
export const RightDrawerContainer = ({
children,
}: {
children: React.ReactNode;
}) => {
const rightDrawerRef = useRef<HTMLDivElement>(null);
const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState);
const isRightDrawerMinimized = useRecoilValue(isRightDrawerMinimizedState);
const { closeRightDrawer } = useRightDrawer();
const workflowReactFlowRef = useRecoilValue(workflowReactFlowRefState);
useListenClickOutside({
refs: [
rightDrawerRef,
...(workflowReactFlowRef ? [workflowReactFlowRef] : []),
],
excludeClassNames: ['confirmation-modal'],
listenerId: RIGHT_DRAWER_CLICK_OUTSIDE_LISTENER_ID,
callback: useRecoilCallback(
({ snapshot, set }) =>
(event) => {
const isRightDrawerOpen = snapshot
.getLoadable(isRightDrawerOpenState)
.getValue();
const isRightDrawerMinimized = snapshot
.getLoadable(isRightDrawerMinimizedState)
.getValue();
if (isRightDrawerOpen && !isRightDrawerMinimized) {
set(rightDrawerCloseEventState, event);
closeRightDrawer();
}
},
[closeRightDrawer],
),
mode: ClickOutsideMode.comparePixels,
});
useScopedHotkeys(
[Key.Escape],
() => {
if (isRightDrawerOpen && !isRightDrawerMinimized) {
closeRightDrawer();
}
},
RightDrawerHotkeyScope.RightDrawer,
[isRightDrawerOpen, isRightDrawerMinimized],
);
return (
<StyledRightDrawerPage ref={rightDrawerRef}>
{children}
</StyledRightDrawerPage>
);
};

View File

@ -1,68 +0,0 @@
import styled from '@emotion/styled';
import { useRecoilState, useRecoilValue } from 'recoil';
import { RightDrawerCalendarEvent } from '@/activities/calendar/right-drawer/components/RightDrawerCalendarEvent';
import { RightDrawerAIChat } from '@/activities/copilot/right-drawer/components/RightDrawerAIChat';
import { RightDrawerEmailThread } from '@/activities/emails/right-drawer/components/RightDrawerEmailThread';
import { RightDrawerRecord } from '@/object-record/record-right-drawer/components/RightDrawerRecord';
import { isRightDrawerMinimizedState } from '@/ui/layout/right-drawer/states/isRightDrawerMinimizedState';
import { RightDrawerContainer } from '@/ui/layout/right-drawer/components/RightDrawerContainer';
import { RightDrawerTopBar } from '@/ui/layout/right-drawer/components/RightDrawerTopBar';
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';
import { isDefined } from 'twenty-shared';
import { rightDrawerPageState } from '../states/rightDrawerPageState';
import { RightDrawerPages } from '../types/RightDrawerPages';
const StyledRightDrawerBody = styled.div`
display: flex;
flex-direction: column;
height: calc(
100vh - ${({ theme }) => theme.spacing(14)} - 1px
); // (-1 for border)
//overflow: auto;
position: relative;
`;
const RIGHT_DRAWER_PAGES_CONFIG = {
[RightDrawerPages.ViewEmailThread]: <RightDrawerEmailThread />,
[RightDrawerPages.ViewCalendarEvent]: <RightDrawerCalendarEvent />,
[RightDrawerPages.ViewRecord]: <RightDrawerRecord />,
[RightDrawerPages.Copilot]: <RightDrawerAIChat />,
[RightDrawerPages.WorkflowStepSelectTriggerType]: (
<RightDrawerWorkflowSelectTriggerType />
),
[RightDrawerPages.WorkflowStepSelectAction]: (
<RightDrawerWorkflowSelectAction />
),
[RightDrawerPages.WorkflowStepEdit]: <RightDrawerWorkflowEditStep />,
[RightDrawerPages.WorkflowStepView]: <RightDrawerWorkflowViewStep />,
[RightDrawerPages.WorkflowRunStepView]: <RightDrawerWorkflowRunViewStep />,
} satisfies Record<RightDrawerPages, JSX.Element>;
export const RightDrawerRouter = () => {
const [rightDrawerPage] = useRecoilState(rightDrawerPageState);
const rightDrawerPageComponent = isDefined(rightDrawerPage) ? (
RIGHT_DRAWER_PAGES_CONFIG[rightDrawerPage]
) : (
<></>
);
const isRightDrawerMinimized = useRecoilValue(isRightDrawerMinimizedState);
return (
<RightDrawerContainer>
<RightDrawerTopBar />
{!isRightDrawerMinimized && (
<StyledRightDrawerBody>
{rightDrawerPageComponent}
</StyledRightDrawerBody>
)}
</RightDrawerContainer>
);
};

View File

@ -1,140 +0,0 @@
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { useRecoilState, useRecoilValue } from 'recoil';
import { Chip, ChipAccent, ChipSize, useIcons } from 'twenty-ui';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { getBasePathToShowPage } from '@/object-metadata/utils/getBasePathToShowPage';
import { isNewViewableRecordLoadingState } from '@/object-record/record-right-drawer/states/isNewViewableRecordLoading';
import { viewableRecordIdState } from '@/object-record/record-right-drawer/states/viewableRecordIdState';
import { viewableRecordNameSingularState } from '@/object-record/record-right-drawer/states/viewableRecordNameSingularState';
import { RightDrawerTopBarCloseButton } from '@/ui/layout/right-drawer/components/RightDrawerTopBarCloseButton';
import { RightDrawerTopBarExpandButton } from '@/ui/layout/right-drawer/components/RightDrawerTopBarExpandButton';
import { RightDrawerTopBarMinimizeButton } from '@/ui/layout/right-drawer/components/RightDrawerTopBarMinimizeButton';
import { StyledRightDrawerTopBar } from '@/ui/layout/right-drawer/components/StyledRightDrawerTopBar';
import { RIGHT_DRAWER_PAGE_ICONS } from '@/ui/layout/right-drawer/constants/RightDrawerPageIcons';
import { RIGHT_DRAWER_PAGE_TITLES } from '@/ui/layout/right-drawer/constants/RightDrawerPageTitles';
import { isRightDrawerMinimizedState } from '@/ui/layout/right-drawer/states/isRightDrawerMinimizedState';
import { rightDrawerPageState } from '@/ui/layout/right-drawer/states/rightDrawerPageState';
import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages';
import { useIsMobile } from '@/ui/utilities/responsive/hooks/useIsMobile';
const StyledTopBarWrapper = styled.div`
align-items: center;
display: flex;
`;
const StyledMinimizeTopBarTitleContainer = styled.div`
align-items: center;
display: flex;
gap: ${({ theme }) => theme.spacing(1)};
height: 24px;
width: 168px;
`;
const StyledMinimizeTopBarTitle = styled.div`
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
`;
const StyledMinimizeTopBarIcon = styled.div`
align-items: center;
display: flex;
`;
export const RightDrawerTopBar = () => {
const isMobile = useIsMobile();
const rightDrawerPage = useRecoilValue(rightDrawerPageState);
const [isRightDrawerMinimized, setIsRightDrawerMinimized] = useRecoilState(
isRightDrawerMinimizedState,
);
const theme = useTheme();
const handleOnclick = () => {
if (isRightDrawerMinimized) {
setIsRightDrawerMinimized(false);
}
};
const { getIcon } = useIcons();
const viewableRecordNameSingular = useRecoilValue(
viewableRecordNameSingularState,
);
const isNewViewableRecordLoading = useRecoilValue(
isNewViewableRecordLoadingState,
);
const viewableRecordId = useRecoilValue(viewableRecordIdState);
const { objectMetadataItem } = useObjectMetadataItem({
objectNameSingular: viewableRecordNameSingular ?? 'company',
});
if (!rightDrawerPage) {
return null;
}
const PageIcon = getIcon(RIGHT_DRAWER_PAGE_ICONS[rightDrawerPage]);
const ObjectIcon = getIcon(objectMetadataItem.icon);
const isViewRecordRightDrawerPage =
rightDrawerPage === RightDrawerPages.ViewRecord;
const label = isViewRecordRightDrawerPage
? objectMetadataItem.labelSingular
: RIGHT_DRAWER_PAGE_TITLES[rightDrawerPage];
const Icon = isViewRecordRightDrawerPage ? ObjectIcon : PageIcon;
return (
<StyledRightDrawerTopBar
onClick={handleOnclick}
isRightDrawerMinimized={isRightDrawerMinimized}
>
{!isRightDrawerMinimized && (
<Chip
disabled={isNewViewableRecordLoading}
label={label}
leftComponent={() => <Icon size={theme.icon.size.md} />}
size={ChipSize.Large}
accent={ChipAccent.TextSecondary}
clickable={false}
/>
)}
{isRightDrawerMinimized && (
<StyledMinimizeTopBarTitleContainer>
<StyledMinimizeTopBarIcon>
<Icon size={theme.icon.size.md} />
</StyledMinimizeTopBarIcon>
<StyledMinimizeTopBarTitle>{label}</StyledMinimizeTopBarTitle>
</StyledMinimizeTopBarTitleContainer>
)}
<StyledTopBarWrapper>
{!isMobile && !isRightDrawerMinimized && (
<RightDrawerTopBarMinimizeButton />
)}
{!isMobile &&
!isRightDrawerMinimized &&
isViewRecordRightDrawerPage && (
<RightDrawerTopBarExpandButton
to={
getBasePathToShowPage({
objectNameSingular: viewableRecordNameSingular ?? '',
}) + viewableRecordId
}
/>
)}
<RightDrawerTopBarCloseButton />
</StyledTopBarWrapper>
</StyledRightDrawerTopBar>
);
};

View File

@ -1,20 +0,0 @@
import { IconX, LightIconButton } from 'twenty-ui';
import { useRightDrawer } from '../hooks/useRightDrawer';
export const RightDrawerTopBarCloseButton = () => {
const { closeRightDrawer } = useRightDrawer();
const handleButtonClick = () => {
closeRightDrawer();
};
return (
<LightIconButton
Icon={IconX}
onClick={handleButtonClick}
size="medium"
accent="tertiary"
/>
);
};

View File

@ -1,17 +0,0 @@
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
import { IconExternalLink, LightIconButton, UndecoratedLink } from 'twenty-ui';
export const RightDrawerTopBarExpandButton = ({ to }: { to: string }) => {
const { closeRightDrawer } = useRightDrawer();
return (
<UndecoratedLink to={to}>
<LightIconButton
size="medium"
accent="tertiary"
Icon={IconExternalLink}
onClick={() => closeRightDrawer()}
/>
</UndecoratedLink>
);
};

View File

@ -1,21 +0,0 @@
import { IconMinus, LightIconButton } from 'twenty-ui';
import { useRightDrawer } from '@/ui/layout/right-drawer/hooks/useRightDrawer';
export const RightDrawerTopBarMinimizeButton = () => {
const { isRightDrawerMinimized, minimizeRightDrawer, maximizeRightDrawer } =
useRightDrawer();
const handleButtonClick = () => {
isRightDrawerMinimized ? maximizeRightDrawer() : minimizeRightDrawer();
};
return (
<LightIconButton
Icon={IconMinus}
onClick={handleButtonClick}
size="medium"
accent="tertiary"
/>
);
};

View File

@ -1,22 +0,0 @@
import styled from '@emotion/styled';
export const StyledRightDrawerTopBar = styled.div<{
isRightDrawerMinimized: boolean;
}>`
align-items: center;
background: ${({ theme }) => theme.background.secondary};
border-bottom: 1px solid ${({ theme }) => theme.border.color.light};
color: ${({ theme }) => theme.font.color.secondary};
display: flex;
flex-direction: row;
font-size: ${({ theme }) => theme.font.size.md};
gap: ${({ theme }) => theme.spacing(1)};
height: ${({ isRightDrawerMinimized }) =>
isRightDrawerMinimized ? '40px' : '56px'};
justify-content: space-between;
padding-left: ${({ theme }) => theme.spacing(2)};
padding-right: ${({ theme }) => theme.spacing(2)};
cursor: ${({ isRightDrawerMinimized }) =>
isRightDrawerMinimized ? 'pointer' : 'default'};
`;

View File

@ -1,56 +0,0 @@
import { expect } from '@storybook/jest';
import { Meta, StoryObj } from '@storybook/react';
import { RightDrawerTopBar } from '../RightDrawerTopBar';
import { ComponentWithRouterDecorator } from '~/testing/decorators/ComponentWithRouterDecorator';
import { ObjectMetadataItemsDecorator } from '~/testing/decorators/ObjectMetadataItemsDecorator';
import { SnackBarDecorator } from '~/testing/decorators/SnackBarDecorator';
import { useSetRecoilState } from 'recoil';
import { rightDrawerPageState } from '@/ui/layout/right-drawer/states/rightDrawerPageState';
import { isRightDrawerMinimizedState } from '@/ui/layout/right-drawer/states/isRightDrawerMinimizedState';
import { useEffect } from 'react';
import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages';
import { IconsProviderDecorator } from '~/testing/decorators/IconsProviderDecorator';
import { within } from '@storybook/test';
const RightDrawerTopBarStateSetterEffect = () => {
const setRightDrawerPage = useSetRecoilState(rightDrawerPageState);
const setIsRightDrawerMinimizedState = useSetRecoilState(
isRightDrawerMinimizedState,
);
useEffect(() => {
setRightDrawerPage(RightDrawerPages.ViewRecord);
setIsRightDrawerMinimizedState(false);
}, [setIsRightDrawerMinimizedState, setRightDrawerPage]);
return null;
};
const meta: Meta<typeof RightDrawerTopBar> = {
title: 'Modules/Activities/RightDrawer/RightDrawerTopBar',
component: RightDrawerTopBar,
decorators: [
(Story) => (
<div style={{ width: '500px' }}>
<Story />
<RightDrawerTopBarStateSetterEffect />
</div>
),
IconsProviderDecorator,
ComponentWithRouterDecorator,
ObjectMetadataItemsDecorator,
SnackBarDecorator,
],
};
export default meta;
type Story = StoryObj<typeof RightDrawerTopBar>;
export const Default: Story = {
play: async () => {
const canvas = within(document.body);
expect(await canvas.findByText('Company')).toBeInTheDocument();
},
};

View File

@ -1,32 +0,0 @@
import { THEME_COMMON } from 'twenty-ui';
export const RIGHT_DRAWER_ANIMATION_VARIANTS = {
fullScreen: {
x: '0%',
width: '100%',
height: '100%',
bottom: '0',
top: '0',
},
normal: {
x: '0%',
width: THEME_COMMON.rightDrawerWidth,
height: '100%',
bottom: '0',
top: '0',
},
closed: {
x: '100%',
width: '0',
height: '100%',
bottom: '0',
top: 'auto',
},
minimized: {
x: '0%',
width: 220,
height: 41,
bottom: '0',
top: 'auto',
},
};

View File

@ -1,2 +0,0 @@
export const RIGHT_DRAWER_CLICK_OUTSIDE_LISTENER_ID =
'right-drawer-click-outside-listener';

View File

@ -1,13 +0,0 @@
import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages';
export const RIGHT_DRAWER_PAGE_ICONS = {
[RightDrawerPages.ViewEmailThread]: 'IconMail',
[RightDrawerPages.ViewCalendarEvent]: 'IconCalendarEvent',
[RightDrawerPages.ViewRecord]: 'Icon123',
[RightDrawerPages.Copilot]: 'IconSparkles',
[RightDrawerPages.WorkflowStepSelectTriggerType]: 'IconSparkles',
[RightDrawerPages.WorkflowStepSelectAction]: 'IconSparkles',
[RightDrawerPages.WorkflowStepEdit]: 'IconSparkles',
[RightDrawerPages.WorkflowStepView]: 'IconSparkles',
[RightDrawerPages.WorkflowRunStepView]: 'IconSparkles',
} satisfies Record<RightDrawerPages, string>;

View File

@ -1,13 +0,0 @@
import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages';
export const RIGHT_DRAWER_PAGE_TITLES = {
[RightDrawerPages.ViewEmailThread]: 'Email Thread',
[RightDrawerPages.ViewCalendarEvent]: 'Calendar Event',
[RightDrawerPages.ViewRecord]: 'Record Editor',
[RightDrawerPages.Copilot]: 'Copilot',
[RightDrawerPages.WorkflowStepSelectTriggerType]: 'Workflow',
[RightDrawerPages.WorkflowStepSelectAction]: 'Workflow',
[RightDrawerPages.WorkflowStepEdit]: 'Workflow',
[RightDrawerPages.WorkflowStepView]: 'Workflow',
[RightDrawerPages.WorkflowRunStepView]: 'Workflow',
} satisfies Record<RightDrawerPages, string>;

View File

@ -1,52 +0,0 @@
import { renderHook } from '@testing-library/react';
import { act } from 'react-dom/test-utils';
import { RecoilRoot, useRecoilValue } from 'recoil';
import { IconList } from 'twenty-ui';
import { isRightDrawerOpenState } from '../../states/isRightDrawerOpenState';
import { rightDrawerPageState } from '../../states/rightDrawerPageState';
import { RightDrawerPages } from '../../types/RightDrawerPages';
import { useRightDrawer } from '../useRightDrawer';
describe('useRightDrawer', () => {
it('Should test the default behavior of useRightDrawer and change the states as the function calls', async () => {
const useCombinedHooks = () => {
const { openRightDrawer, closeRightDrawer } = useRightDrawer();
const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState);
const rightDrawerPage = useRecoilValue(rightDrawerPageState);
return {
openRightDrawer,
closeRightDrawer,
isRightDrawerOpen,
rightDrawerPage,
};
};
const { result } = renderHook(() => useCombinedHooks(), {
wrapper: RecoilRoot,
});
expect(result.current.rightDrawerPage).toBeNull();
expect(result.current.isRightDrawerOpen).toBeFalsy();
expect(result.current.openRightDrawer).toBeInstanceOf(Function);
expect(result.current.closeRightDrawer).toBeInstanceOf(Function);
await act(async () => {
result.current.openRightDrawer(RightDrawerPages.ViewRecord, {
title: 'Company',
Icon: IconList,
});
});
expect(result.current.rightDrawerPage).toEqual(RightDrawerPages.ViewRecord);
expect(result.current.isRightDrawerOpen).toBeTruthy();
await act(async () => {
result.current.closeRightDrawer();
});
expect(result.current.isRightDrawerOpen).toBeFalsy();
});
});

View File

@ -1,114 +0,0 @@
import { useRecoilCallback, useRecoilValue } from 'recoil';
import { isRightDrawerMinimizedState } from '@/ui/layout/right-drawer/states/isRightDrawerMinimizedState';
import { rightDrawerCloseEventState } from '@/ui/layout/right-drawer/states/rightDrawerCloseEventsState';
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { emitRightDrawerCloseEvent } from '@/ui/layout/right-drawer/utils/emitRightDrawerCloseEvent';
import { mapRightDrawerPageToCommandMenuPage } from '@/ui/layout/right-drawer/utils/mapRightDrawerPageToCommandMenuPage';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { isDefined } from 'twenty-shared';
import { IconComponent } from 'twenty-ui';
import { FeatureFlagKey } from '~/generated/graphql';
import { isRightDrawerOpenState } from '../states/isRightDrawerOpenState';
import { rightDrawerPageState } from '../states/rightDrawerPageState';
import { RightDrawerPages } from '../types/RightDrawerPages';
export const useRightDrawer = () => {
const isRightDrawerOpen = useRecoilValue(isRightDrawerOpenState);
const isRightDrawerMinimized = useRecoilValue(isRightDrawerMinimizedState);
const rightDrawerPage = useRecoilValue(rightDrawerPageState);
const isCommandMenuV2Enabled = useIsFeatureEnabled(
FeatureFlagKey.IsCommandMenuV2Enabled,
);
const { navigateCommandMenu } = useCommandMenu();
const openRightDrawer = useRecoilCallback(
({ set }) =>
(
rightDrawerPage: RightDrawerPages,
commandMenuPageInfo: {
title: string;
Icon: IconComponent;
},
) => {
if (isCommandMenuV2Enabled) {
const commandMenuPage =
mapRightDrawerPageToCommandMenuPage(rightDrawerPage);
navigateCommandMenu({
page: commandMenuPage,
pageTitle: commandMenuPageInfo.title,
pageIcon: commandMenuPageInfo.Icon,
});
return;
}
set(rightDrawerPageState, rightDrawerPage);
set(isRightDrawerOpenState, true);
set(isRightDrawerMinimizedState, false);
},
[isCommandMenuV2Enabled, navigateCommandMenu],
);
const closeRightDrawer = useRecoilCallback(
({ set }) =>
(args?: { emitCloseEvent?: boolean }) => {
set(isRightDrawerOpenState, false);
set(isRightDrawerMinimizedState, false);
if (isDefined(args?.emitCloseEvent) && args?.emitCloseEvent) {
emitRightDrawerCloseEvent();
}
},
[],
);
const minimizeRightDrawer = useRecoilCallback(
({ set }) =>
() => {
set(isRightDrawerOpenState, true);
set(isRightDrawerMinimizedState, true);
},
[],
);
const maximizeRightDrawer = useRecoilCallback(
({ set }) =>
() => {
set(isRightDrawerMinimizedState, false);
set(isRightDrawerOpenState, true);
},
[],
);
const isSameEventThanRightDrawerClose = useRecoilCallback(
({ snapshot }) =>
(event: MouseEvent | TouchEvent) => {
const rightDrawerCloseEvent = snapshot
.getLoadable(rightDrawerCloseEventState)
.getValue();
const isSameEvent =
rightDrawerCloseEvent?.target === event.target &&
rightDrawerCloseEvent?.timeStamp === event.timeStamp;
return isSameEvent;
},
[],
);
return {
rightDrawerPage,
isRightDrawerOpen,
isRightDrawerMinimized,
openRightDrawer,
closeRightDrawer,
minimizeRightDrawer,
maximizeRightDrawer,
isSameEventThanRightDrawerClose,
};
};

View File

@ -1,6 +0,0 @@
import { createState } from '@ui/utilities/state/utils/createState';
export const isRightDrawerAnimationCompletedState = createState<boolean>({
key: 'isRightDrawerAnimationCompletedState',
defaultValue: false,
});

View File

@ -1,6 +0,0 @@
import { createState } from '@ui/utilities/state/utils/createState';
export const isRightDrawerMinimizedState = createState<boolean>({
key: 'ui/layout/is-right-drawer-minimized',
defaultValue: false,
});

View File

@ -1,6 +0,0 @@
import { createState } from '@ui/utilities/state/utils/createState';
export const isRightDrawerOpenState = createState<boolean>({
key: 'ui/layout/is-right-drawer-open',
defaultValue: false,
});

View File

@ -1,8 +0,0 @@
import { createState } from '@ui/utilities/state/utils/createState';
import { MessageThread } from '@/activities/emails/types/MessageThread';
export const messageThreadState = createState<MessageThread | null>({
key: 'messageThreadState',
defaultValue: null,
});

View File

@ -1,6 +0,0 @@
import { createState } from '@ui/utilities/state/utils/createState';
export const rightDrawerCloseEventState = createState<Event | null>({
key: 'rightDrawerCloseEventState',
defaultValue: null,
});

View File

@ -1,9 +0,0 @@
import { createState } from '@ui/utilities/state/utils/createState';
import { RightDrawerTopBarDropdownButtons } from '@/ui/layout/right-drawer/types/RightDrawerTopBarDropdownButtons';
export const rightDrawerTopBarDropdownButtonState =
createState<RightDrawerTopBarDropdownButtons | null>({
key: 'rightDrawerTopBarDropdownButtonState',
defaultValue: null,
});

View File

@ -1,8 +0,0 @@
import { createState } from '@ui/utilities/state/utils/createState';
import { RightDrawerPages } from '../types/RightDrawerPages';
export const rightDrawerPageState = createState<RightDrawerPages | null>({
key: 'ui/layout/right-drawer-page',
defaultValue: null,
});

View File

@ -1,4 +0,0 @@
import { RIGHT_DRAWER_ANIMATION_VARIANTS } from '@/ui/layout/right-drawer/constants/RightDrawerAnimationVariants';
export type RightDrawerAnimationVariant =
keyof typeof RIGHT_DRAWER_ANIMATION_VARIANTS;

View File

@ -1,3 +0,0 @@
export enum RightDrawerHotkeyScope {
RightDrawer = 'right-drawer',
}

View File

@ -1,11 +0,0 @@
export enum RightDrawerPages {
ViewEmailThread = 'view-email-thread',
ViewCalendarEvent = 'view-calendar-event',
ViewRecord = 'view-record',
Copilot = 'copilot',
WorkflowStepSelectTriggerType = 'workflow-step-select-trigger-type',
WorkflowStepSelectAction = 'workflow-step-select-action',
WorkflowStepView = 'workflow-step-view',
WorkflowStepEdit = 'workflow-step-edit',
WorkflowRunStepView = 'workflow-run-step-view',
}

View File

@ -1,3 +0,0 @@
export enum RightDrawerTopBarDropdownButtons {
EmailThreadSubscribers = 'EmailThreadSubscribers',
}

View File

@ -1,28 +0,0 @@
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
import { RightDrawerPages } from '@/ui/layout/right-drawer/types/RightDrawerPages';
export const mapRightDrawerPageToCommandMenuPage = (
rightDrawerPage: RightDrawerPages,
) => {
const rightDrawerPagesToCommandMenuPages: Record<
RightDrawerPages,
CommandMenuPages
> = {
[RightDrawerPages.ViewRecord]: CommandMenuPages.ViewRecord,
[RightDrawerPages.ViewEmailThread]: CommandMenuPages.ViewEmailThread,
[RightDrawerPages.ViewCalendarEvent]: CommandMenuPages.ViewCalendarEvent,
[RightDrawerPages.Copilot]: CommandMenuPages.Copilot,
[RightDrawerPages.WorkflowStepSelectTriggerType]:
CommandMenuPages.WorkflowStepSelectTriggerType,
[RightDrawerPages.WorkflowStepSelectAction]:
CommandMenuPages.WorkflowStepSelectAction,
[RightDrawerPages.WorkflowStepView]: CommandMenuPages.WorkflowStepView,
[RightDrawerPages.WorkflowRunStepView]:
CommandMenuPages.WorkflowRunStepView,
[RightDrawerPages.WorkflowStepEdit]: CommandMenuPages.WorkflowStepEdit,
};
return (
rightDrawerPagesToCommandMenuPages[rightDrawerPage] ?? CommandMenuPages.Root
);
};

View File

@ -1,12 +1,5 @@
import styled from '@emotion/styled';
import {
Button,
IconButton,
IconCheckbox,
IconNotes,
IconPlus,
MenuItem,
} from 'twenty-ui';
import { Button, IconCheckbox, IconNotes, IconPlus, MenuItem } from 'twenty-ui';
import { useOpenCreateActivityDrawer } from '@/activities/hooks/useOpenCreateActivityDrawer';
import { ActivityTargetableObject } from '@/activities/types/ActivityTargetableEntity';
@ -18,8 +11,6 @@ import { SHOW_PAGE_ADD_BUTTON_DROPDOWN_ID } from '@/ui/layout/show-page/constant
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { isWorkflowSubObjectMetadata } from '@/object-metadata/utils/isWorkflowSubObjectMetadata';
import { useHasObjectReadOnlyPermission } from '@/settings/roles/hooks/useHasObjectReadOnlyPermission';
import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
import { FeatureFlagKey } from '~/generated/graphql';
import { Dropdown } from '../../dropdown/components/Dropdown';
const StyledContainer = styled.div`
@ -56,10 +47,6 @@ export const ShowPageAddButton = ({
closeDropdown();
};
const isCommandMenuV2Enabled = useIsFeatureEnabled(
FeatureFlagKey.IsCommandMenuV2Enabled,
);
if (
activityTargetObject.targetObjectNameSingular ===
CoreObjectNameSingular.Task ||
@ -79,25 +66,15 @@ export const ShowPageAddButton = ({
<Dropdown
dropdownId={SHOW_PAGE_ADD_BUTTON_DROPDOWN_ID}
clickableComponent={
isCommandMenuV2Enabled ? (
<Button
Icon={IconPlus}
dataTestId="add-button"
size="small"
variant="secondary"
accent="default"
title="New note/task"
ariaLabel="New note/task"
/>
) : (
<IconButton
Icon={IconPlus}
size="medium"
dataTestId="add-showpage-button"
accent="default"
variant="secondary"
/>
)
<Button
Icon={IconPlus}
dataTestId="add-button"
size="small"
variant="secondary"
accent="default"
title="New note/task"
ariaLabel="New note/task"
/>
}
dropdownComponents={
<DropdownMenuItemsContainer>