nitin
2025-09-02 15:50:28 +05:30
committed by GitHub
parent 04d4c07b69
commit 1b2f079359
71 changed files with 2696 additions and 541 deletions
@@ -6,9 +6,13 @@ import { COMMAND_MENU_PAGES_CONFIG } from '@/command-menu/constants/CommandMenuP
import { commandMenuPageInfoState } from '@/command-menu/states/commandMenuPageInfoState';
import { commandMenuPageState } from '@/command-menu/states/commandMenuPageState';
import { CommandMenuPageComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuPageComponentInstanceContext';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { CoreObjectNameSingular } from '@/object-metadata/types/CoreObjectNameSingular';
import { SettingsPath } from '@/types/SettingsPath';
import { useTheme } from '@emotion/react';
import styled from '@emotion/styled';
import { motion } from 'framer-motion';
import { useLocation } from 'react-router-dom';
import { useRecoilValue } from 'recoil';
import { isDefined } from 'twenty-shared/utils';
@@ -19,8 +23,9 @@ const StyledCommandMenuContent = styled.div`
export const CommandMenuRouter = () => {
const commandMenuPage = useRecoilValue(commandMenuPageState);
const commandMenuPageInfo = useRecoilValue(commandMenuPageInfoState);
const location = useLocation();
const objectMetadataItems = useRecoilValue(objectMetadataItemsState);
const commandMenuPageComponent = isDefined(commandMenuPage) ? (
COMMAND_MENU_PAGES_CONFIG.get(commandMenuPage)
@@ -30,6 +35,13 @@ export const CommandMenuRouter = () => {
const theme = useTheme();
const isSettingsPage = location.pathname.includes(SettingsPath.PageLayout);
const objectMetadataItemOverride = isSettingsPage
? objectMetadataItems.find(
(item) => item.nameSingular === CoreObjectNameSingular.Dashboard,
)
: undefined;
return (
<CommandMenuContainer>
<CommandMenuContextChipRecordSetterEffect />
@@ -52,6 +64,7 @@ export const CommandMenuRouter = () => {
isInRightDrawer={true}
displayType="listItem"
actionMenuType="command-menu"
objectMetadataItemOverride={objectMetadataItemOverride}
>
{commandMenuPageComponent}
</ActionMenuContextProvider>
@@ -3,6 +3,8 @@ import { CommandMenuAIChatThreadsPage } from '@/command-menu/pages/AIChatThreads
import { CommandMenuAskAIPage } from '@/command-menu/pages/ask-ai/components/CommandMenuAskAIPage';
import { CommandMenuCalendarEventPage } from '@/command-menu/pages/calendar-event/components/CommandMenuCalendarEventPage';
import { CommandMenuMessageThreadPage } from '@/command-menu/pages/message-thread/components/CommandMenuMessageThreadPage';
import { CommandMenuPageLayoutGraphTypeSelect } from '@/command-menu/pages/page-layout/components/CommandMenuPageLayoutGraphTypeSelect';
import { CommandMenuPageLayoutWidgetTypeSelect } from '@/command-menu/pages/page-layout/components/CommandMenuPageLayoutWidgetTypeSelect';
import { CommandMenuMergeRecordPage } from '@/command-menu/pages/record-page/components/CommandMenuMergeRecordPage';
import { CommandMenuRecordPage } from '@/command-menu/pages/record-page/components/CommandMenuRecordPage';
import { CommandMenuEditRichTextPage } from '@/command-menu/pages/rich-text-page/components/CommandMenuEditRichTextPage';
@@ -38,4 +40,12 @@ export const COMMAND_MENU_PAGES_CONFIG = new Map<
[CommandMenuPages.SearchRecords, <CommandMenuSearchRecordsPage />],
[CommandMenuPages.AskAI, <CommandMenuAskAIPage />],
[CommandMenuPages.ViewPreviousAIChats, <CommandMenuAIChatThreadsPage />],
[
CommandMenuPages.PageLayoutWidgetTypeSelect,
<CommandMenuPageLayoutWidgetTypeSelect />,
],
[
CommandMenuPages.PageLayoutGraphTypeSelect,
<CommandMenuPageLayoutGraphTypeSelect />,
],
]);
@@ -0,0 +1,77 @@
import { useCommandMenu } from '@/command-menu/hooks/useCommandMenu';
import { usePageLayoutWidgetCreate } from '@/settings/page-layout/hooks/usePageLayoutWidgetCreate';
import {
GraphSubType,
WidgetType,
} from '@/settings/page-layout/mocks/mockWidgets';
import styled from '@emotion/styled';
import {
IconChartBar,
IconChartPie,
IconGauge,
IconNumber,
} from 'twenty-ui/display';
import { MenuItemCommand } from 'twenty-ui/navigation';
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
padding: ${({ theme }) => theme.spacing(1)} ${({ theme }) => theme.spacing(2)};
`;
const StyledSectionTitle = styled.div`
color: ${({ theme }) => theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme }) => theme.font.weight.medium};
padding-top: ${({ theme }) => theme.spacing(2)};
padding-bottom: ${({ theme }) => theme.spacing(1)};
padding-left: ${({ theme }) => theme.spacing(1)};
`;
const graphTypeOptions = [
{
type: GraphSubType.BAR,
icon: IconChartBar,
title: 'Bar Chart',
},
{
type: GraphSubType.PIE,
icon: IconChartPie,
title: 'Pie Chart',
},
{
type: GraphSubType.GAUGE,
icon: IconGauge,
title: 'Gauge',
},
{
type: GraphSubType.NUMBER,
icon: IconNumber,
title: 'Number',
},
];
export const CommandMenuPageLayoutGraphTypeSelect = () => {
const { closeCommandMenu } = useCommandMenu();
const { handleCreateWidget } = usePageLayoutWidgetCreate();
const handleSelectGraphType = (graphType: GraphSubType) => {
handleCreateWidget(WidgetType.GRAPH, graphType);
closeCommandMenu();
};
return (
<StyledContainer>
<StyledSectionTitle>Graph type</StyledSectionTitle>
{graphTypeOptions.map((option) => (
<MenuItemCommand
key={option.type}
LeftIcon={option.icon}
text={option.title}
onClick={() => handleSelectGraphType(option.type)}
/>
))}
</StyledContainer>
);
};
@@ -0,0 +1,93 @@
import { useNavigateCommandMenu } from '@/command-menu/hooks/useNavigateCommandMenu';
import { CommandMenuPages } from '@/command-menu/types/CommandMenuPages';
import { WidgetType } from '@/settings/page-layout/mocks/mockWidgets';
import { pageLayoutDraggedAreaState } from '@/settings/page-layout/states/pageLayoutDraggedAreaState';
import styled from '@emotion/styled';
import { useSetRecoilState } from 'recoil';
import { IconChartPie, IconFrame, IconList } from 'twenty-ui/display';
import { MenuItemCommand } from 'twenty-ui/navigation';
const StyledContainer = styled.div`
display: flex;
flex-direction: column;
padding: ${({ theme }) => theme.spacing(1)} ${({ theme }) => theme.spacing(2)};
`;
const StyledSectionTitle = styled.div`
color: ${({ theme }) => theme.font.color.tertiary};
font-size: ${({ theme }) => theme.font.size.sm};
font-weight: ${({ theme }) => theme.font.weight.medium};
padding-top: ${({ theme }) => theme.spacing(2)};
padding-bottom: ${({ theme }) => theme.spacing(1)};
padding-left: ${({ theme }) => theme.spacing(1)};
`;
const StyledDisabledMenuItem = styled.div`
opacity: 0.5;
cursor: not-allowed;
pointer-events: none;
`;
const widgetTypeOptions = [
{
type: WidgetType.GRAPH,
icon: IconChartPie,
title: 'Add a graph',
disabled: false,
},
{
type: WidgetType.VIEW,
icon: IconList,
title: 'Add a view',
disabled: true,
},
{
type: WidgetType.IFRAME,
icon: IconFrame,
title: 'Add an iframe',
disabled: true,
},
];
export const CommandMenuPageLayoutWidgetTypeSelect = () => {
const { navigateCommandMenu } = useNavigateCommandMenu();
const setPageLayoutDraggedArea = useSetRecoilState(
pageLayoutDraggedAreaState,
);
const handleSelectWidget = (widgetType: WidgetType) => {
if (widgetType === WidgetType.GRAPH) {
navigateCommandMenu({
page: CommandMenuPages.PageLayoutGraphTypeSelect,
pageTitle: 'Select Graph Type',
pageIcon: IconChartPie,
});
} else {
setPageLayoutDraggedArea(null);
}
};
return (
<StyledContainer>
<StyledSectionTitle>Widget type</StyledSectionTitle>
{widgetTypeOptions.map((option) => {
const MenuItem = (
<MenuItemCommand
key={option.type}
LeftIcon={option.icon}
text={option.title}
onClick={() => handleSelectWidget(option.type)}
/>
);
return option.disabled ? (
<StyledDisabledMenuItem key={option.type}>
{MenuItem}
</StyledDisabledMenuItem>
) : (
MenuItem
);
})}
</StyledContainer>
);
};
@@ -14,4 +14,6 @@ export enum CommandMenuPages {
SearchRecords = 'search-records',
AskAI = 'ask-ai',
ViewPreviousAIChats = 'view-previous-ai-chats',
PageLayoutWidgetTypeSelect = 'page-layout-widget-type-select',
PageLayoutGraphTypeSelect = 'page-layout-graph-type-select',
}