diff --git a/packages/twenty-front/src/modules/action-menu/actions/components/Action.tsx b/packages/twenty-front/src/modules/action-menu/actions/components/Action.tsx
deleted file mode 100644
index 7be79eb22a..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/components/Action.tsx
+++ /dev/null
@@ -1,32 +0,0 @@
-import { ActionDisplay } from '@/action-menu/actions/display/components/ActionDisplay';
-import { ActionConfigContext } from '@/action-menu/contexts/ActionConfigContext';
-import { useCloseActionMenu } from '@/action-menu/hooks/useCloseActionMenu';
-import { useContext } from 'react';
-
-export const Action = ({
- onClick,
- closeSidePanelOnShowPageOptionsActionExecution = false,
- closeSidePanelOnCommandMenuListActionExecution = true,
-}: {
- onClick: () => void;
- closeSidePanelOnShowPageOptionsActionExecution?: boolean;
- closeSidePanelOnCommandMenuListActionExecution?: boolean;
-}) => {
- const actionConfig = useContext(ActionConfigContext);
-
- const { closeActionMenu } = useCloseActionMenu({
- closeSidePanelOnShowPageOptionsActionExecution,
- closeSidePanelOnCommandMenuListActionExecution,
- });
-
- if (!actionConfig) {
- return null;
- }
-
- const handleClick = () => {
- closeActionMenu();
- onClick();
- };
-
- return ;
-};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/components/ActionLink.tsx b/packages/twenty-front/src/modules/action-menu/actions/components/ActionLink.tsx
deleted file mode 100644
index a2c5c956c0..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/components/ActionLink.tsx
+++ /dev/null
@@ -1,21 +0,0 @@
-import { ActionDisplay } from '@/action-menu/actions/display/components/ActionDisplay';
-import { useCloseActionMenu } from '@/action-menu/hooks/useCloseActionMenu';
-import { type PathParam } from 'react-router-dom';
-import { type AppPath } from 'twenty-shared/types';
-import { getAppPath } from 'twenty-shared/utils';
-
-export const ActionLink = ({
- to,
- params,
- queryParams,
-}: {
- to: T;
- params?: { [key in PathParam]: string | null };
- queryParams?: Record;
-}) => {
- const { closeActionMenu } = useCloseActionMenu();
-
- const path = getAppPath(to, params, queryParams);
-
- return ;
-};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/display/components/ActionButton.tsx b/packages/twenty-front/src/modules/action-menu/actions/display/components/ActionButton.tsx
deleted file mode 100644
index d862f50c96..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/display/components/ActionButton.tsx
+++ /dev/null
@@ -1,68 +0,0 @@
-import { type ActionDisplayProps } from '@/action-menu/actions/display/components/ActionDisplay';
-import { getActionLabel } from '@/action-menu/utils/getActionLabel';
-import { styled } from '@linaria/react';
-import { isDefined } from 'twenty-shared/utils';
-import { AppTooltip, TooltipDelay, TooltipPosition } from 'twenty-ui/display';
-import { Button, IconButton } from 'twenty-ui/input';
-import { themeCssVariables } from 'twenty-ui/theme-constants';
-
-const StyledWrapper = styled.div`
- font-size: ${themeCssVariables.font.size.md};
-`;
-
-export const ActionButton = ({
- action,
- onClick,
- to,
-}: {
- action: ActionDisplayProps;
- onClick?: (event?: React.MouseEvent) => void;
- to?: string;
-}) => {
- const label = getActionLabel(action.label);
-
- const shortLabel = isDefined(action.shortLabel)
- ? getActionLabel(action.shortLabel)
- : undefined;
-
- const buttonAccent = action.isPrimaryCTA ? 'blue' : 'default';
-
- return (
- <>
- {isDefined(action.shortLabel) ? (
-
- ) : (
-
- )}
- >
- );
-};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/display/components/ActionComponent.tsx b/packages/twenty-front/src/modules/action-menu/actions/display/components/ActionComponent.tsx
deleted file mode 100644
index 02a363666a..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/display/components/ActionComponent.tsx
+++ /dev/null
@@ -1,10 +0,0 @@
-import { type ActionConfig } from '@/action-menu/actions/types/ActionConfig';
-import { ActionConfigContext } from '@/action-menu/contexts/ActionConfigContext';
-
-export const ActionComponent = ({ action }: { action: ActionConfig }) => {
- return (
-
- {action.component}
-
- );
-};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/display/components/HeadlessFrontComponentAction.tsx b/packages/twenty-front/src/modules/action-menu/actions/display/components/HeadlessFrontComponentAction.tsx
deleted file mode 100644
index 4fe5d740d6..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/display/components/HeadlessFrontComponentAction.tsx
+++ /dev/null
@@ -1,42 +0,0 @@
-import { ActionConfigContext } from '@/action-menu/contexts/ActionConfigContext';
-import { useCloseActionMenu } from '@/action-menu/hooks/useCloseActionMenu';
-import { isHeadlessFrontComponentMountedFamilySelector } from '@/front-components/selectors/isHeadlessFrontComponentMountedFamilySelector';
-import { useAtomFamilySelectorValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilySelectorValue';
-import { useContext } from 'react';
-
-import { ActionDisplay } from './ActionDisplay';
-
-export const HeadlessFrontComponentAction = ({
- frontComponentId,
- onClick,
-}: {
- frontComponentId: string;
- onClick: () => void;
-}) => {
- const actionConfig = useContext(ActionConfigContext);
-
- const { closeActionMenu } = useCloseActionMenu({
- closeSidePanelOnShowPageOptionsActionExecution: false,
- closeSidePanelOnCommandMenuListActionExecution: false,
- });
-
- const isMounted = useAtomFamilySelectorValue(
- isHeadlessFrontComponentMountedFamilySelector,
- frontComponentId,
- );
-
- if (!actionConfig) {
- return null;
- }
-
- const handleClick = () => {
- if (isMounted) {
- return;
- }
-
- closeActionMenu();
- onClick();
- };
-
- return ;
-};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/display/components/__stories__/ActionButton.stories.tsx b/packages/twenty-front/src/modules/action-menu/actions/display/components/__stories__/ActionButton.stories.tsx
deleted file mode 100644
index b195d8c659..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/display/components/__stories__/ActionButton.stories.tsx
+++ /dev/null
@@ -1,65 +0,0 @@
-import { ActionButton } from '@/action-menu/actions/display/components/ActionButton';
-import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys';
-import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey';
-import { createMockActionMenuActions } from '@/action-menu/mock/action-menu-actions.mock';
-import { getActionLabel } from '@/action-menu/utils/getActionLabel';
-import { type Meta, type StoryObj } from '@storybook/react-vite';
-import { expect, fn, userEvent, within } from 'storybook/test';
-import { ComponentDecorator, RouterDecorator } from 'twenty-ui/testing';
-
-const meta: Meta = {
- title: 'Modules/ActionMenu/Actions/Display/ActionButton',
- component: ActionButton,
- decorators: [ComponentDecorator, RouterDecorator],
-};
-
-export default meta;
-
-type Story = StoryObj;
-
-const deleteMock = fn();
-const addToFavoritesMock = fn();
-
-const mockActions = createMockActionMenuActions({
- deleteMock,
- addToFavoritesMock,
-});
-
-const addToFavoritesAction = mockActions.find(
- (action) => action.key === SingleRecordActionKeys.ADD_TO_FAVORITES,
-);
-
-const goToPeopleAction = mockActions.find(
- (action) => action.key === NoSelectionRecordActionKeys.GO_TO_PEOPLE,
-);
-
-export const Default: Story = {
- args: {
- action: addToFavoritesAction,
- onClick: addToFavoritesMock,
- },
- play: async ({ canvasElement }) => {
- const canvas = within(canvasElement);
- await userEvent.click(
- await canvas.findByText(
- getActionLabel(addToFavoritesAction?.shortLabel ?? ''),
- ),
- );
- expect(addToFavoritesMock).toHaveBeenCalled();
- },
-};
-
-export const WithLink: Story = {
- args: {
- action: goToPeopleAction,
- to: '/objects/people',
- },
- play: async ({ canvasElement }) => {
- const canvas = within(canvasElement);
- const menuItem = await canvas.findByText(
- getActionLabel(goToPeopleAction?.shortLabel ?? ''),
- );
- expect(menuItem).toBeVisible();
- expect(canvas.getByRole('link')).toHaveAttribute('href', '/objects/people');
- },
-};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/display/components/__stories__/ActionComponent.stories.tsx b/packages/twenty-front/src/modules/action-menu/actions/display/components/__stories__/ActionComponent.stories.tsx
deleted file mode 100644
index aa91f58e75..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/display/components/__stories__/ActionComponent.stories.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-import { type Meta, type StoryObj } from '@storybook/react-vite';
-import { expect, within } from 'storybook/test';
-
-import { ActionComponent } from '@/action-menu/actions/display/components/ActionComponent';
-import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey';
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
-import { createMockActionMenuActions } from '@/action-menu/mock/action-menu-actions.mock';
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
-import { getActionLabel } from '@/action-menu/utils/getActionLabel';
-import { ComponentDecorator } from 'twenty-ui/testing';
-
-const mockActions = createMockActionMenuActions({});
-
-const addToFavoritesAction = mockActions.find(
- (action) => action.key === SingleRecordActionKeys.ADD_TO_FAVORITES,
-);
-
-if (!addToFavoritesAction) {
- throw new Error('Add to favorites action not found');
-}
-
-const meta: Meta = {
- title: 'Modules/ActionMenu/Actions/Display/ActionComponent',
- component: ActionComponent,
- decorators: [
- ComponentDecorator,
- (Story) => (
-
-
-
-
-
- ),
- ],
- args: {
- action: addToFavoritesAction,
- },
- parameters: {
- container: {
- width: 'auto',
- },
- },
-};
-
-export default meta;
-type Story = StoryObj;
-
-export const Default: Story = {
- play: async ({ canvasElement }) => {
- const canvas = within(canvasElement);
-
- expect(
- await canvas.findByText(
- getActionLabel(addToFavoritesAction?.shortLabel ?? ''),
- ),
- ).toBeVisible();
- },
-};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DashboardActionsConfig.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DashboardActionsConfig.tsx
deleted file mode 100644
index 411eccebf6..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DashboardActionsConfig.tsx
+++ /dev/null
@@ -1,203 +0,0 @@
-import { MultipleRecordsActionKeys } from '@/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys';
-import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys';
-import { CancelDashboardSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/dashboard-actions/components/CancelDashboardSingleRecordAction';
-import { DuplicateDashboardSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/dashboard-actions/components/DuplicateDashboardSingleRecordAction';
-import { EditDashboardSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/dashboard-actions/components/EditDashboardSingleRecordAction';
-import { SaveDashboardSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/dashboard-actions/components/SaveDashboardSingleRecordAction';
-import { DashboardSingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/dashboard-actions/types/DashboardSingleRecordActionKeys';
-import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey';
-import { inheritActionsFromDefaultConfig } from '@/action-menu/actions/record-actions/utils/inheritActionsFromDefaultConfig';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionType } from '@/action-menu/actions/types/ActionType';
-import { ActionViewType } from 'twenty-shared/types';
-import { PageLayoutSingleRecordActionKeys } from '@/page-layout/actions/PageLayoutSingleRecordActionKeys';
-import { msg } from '@lingui/core/macro';
-import { isDefined } from 'twenty-shared/utils';
-import {
- IconCancel,
- IconCopyPlus,
- IconDeviceFloppy,
- IconPencil,
-} from 'twenty-ui/display';
-
-export const DASHBOARD_ACTIONS_CONFIG = inheritActionsFromDefaultConfig({
- config: {
- [PageLayoutSingleRecordActionKeys.EDIT_LAYOUT]: {
- key: PageLayoutSingleRecordActionKeys.EDIT_LAYOUT,
- label: msg`Edit Dashboard`,
- shortLabel: msg`Edit`,
- isPinned: true,
- position: 3,
- Icon: IconPencil,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- shouldBeRegistered: ({ selectedRecord, objectPermissions }) =>
- isDefined(selectedRecord) &&
- !selectedRecord?.isRemote &&
- !isDefined(selectedRecord?.deletedAt) &&
- isDefined(selectedRecord?.pageLayoutId) &&
- objectPermissions.canUpdateObjectRecords,
- availableOn: [ActionViewType.SHOW_PAGE],
- component: ,
- },
- [PageLayoutSingleRecordActionKeys.SAVE_LAYOUT]: {
- key: PageLayoutSingleRecordActionKeys.SAVE_LAYOUT,
- label: msg`Save Dashboard`,
- shortLabel: msg`Save`,
- isPinned: true,
- isPrimaryCTA: true,
- position: 4,
- Icon: IconDeviceFloppy,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- shouldBeRegistered: ({ selectedRecord, objectPermissions }) =>
- isDefined(selectedRecord) &&
- !selectedRecord?.isRemote &&
- !isDefined(selectedRecord?.deletedAt) &&
- isDefined(selectedRecord?.pageLayoutId) &&
- objectPermissions.canUpdateObjectRecords,
- availableOn: [ActionViewType.PAGE_EDIT_MODE],
- component: ,
- },
- [PageLayoutSingleRecordActionKeys.CANCEL_LAYOUT_EDITION]: {
- key: PageLayoutSingleRecordActionKeys.CANCEL_LAYOUT_EDITION,
- label: msg`Cancel Edition`,
- shortLabel: msg`Cancel`,
- isPinned: true,
- position: 5,
- Icon: IconCancel,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- shouldBeRegistered: ({ selectedRecord, objectPermissions }) =>
- isDefined(selectedRecord) &&
- !selectedRecord?.isRemote &&
- !isDefined(selectedRecord?.deletedAt) &&
- isDefined(selectedRecord?.pageLayoutId) &&
- objectPermissions.canUpdateObjectRecords,
- availableOn: [ActionViewType.PAGE_EDIT_MODE],
- component: ,
- },
- [DashboardSingleRecordActionKeys.DUPLICATE_DASHBOARD]: {
- key: DashboardSingleRecordActionKeys.DUPLICATE_DASHBOARD,
- label: msg`Duplicate Dashboard`,
- shortLabel: msg`Duplicate`,
- isPinned: false,
- position: 6,
- Icon: IconCopyPlus,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- shouldBeRegistered: ({ selectedRecord, objectPermissions }) =>
- isDefined(selectedRecord) &&
- !selectedRecord?.isRemote &&
- !isDefined(selectedRecord?.deletedAt) &&
- objectPermissions.canUpdateObjectRecords,
- availableOn: [
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.SHOW_PAGE,
- ],
- component: ,
- },
- },
- actionKeys: [
- NoSelectionRecordActionKeys.CREATE_NEW_RECORD,
- SingleRecordActionKeys.ADD_TO_FAVORITES,
- SingleRecordActionKeys.REMOVE_FROM_FAVORITES,
- SingleRecordActionKeys.DELETE,
- SingleRecordActionKeys.DESTROY,
- SingleRecordActionKeys.RESTORE,
- MultipleRecordsActionKeys.DELETE,
- MultipleRecordsActionKeys.DESTROY,
- MultipleRecordsActionKeys.RESTORE,
- NoSelectionRecordActionKeys.SEE_DELETED_RECORDS,
- NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS,
- SingleRecordActionKeys.EXPORT_FROM_RECORD_SHOW,
- SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD,
- SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD,
- NoSelectionRecordActionKeys.GO_TO_WORKFLOWS,
- NoSelectionRecordActionKeys.GO_TO_PEOPLE,
- NoSelectionRecordActionKeys.GO_TO_COMPANIES,
- NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES,
- NoSelectionRecordActionKeys.GO_TO_SETTINGS,
- NoSelectionRecordActionKeys.GO_TO_TASKS,
- NoSelectionRecordActionKeys.GO_TO_NOTES,
- ],
- propertiesToOverwrite: {
- [SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD]: {
- position: 0,
- label: msg`Navigate to next dashboard`,
- },
- [SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD]: {
- position: 1,
- label: msg`Navigate to previous dashboard`,
- },
- [NoSelectionRecordActionKeys.CREATE_NEW_RECORD]: {
- position: 2,
- label: msg`Create new dashboard`,
- },
- [SingleRecordActionKeys.DELETE]: {
- position: 7,
- label: msg`Delete dashboard`,
- },
- [MultipleRecordsActionKeys.DELETE]: {
- position: 12,
- label: msg`Delete dashboards`,
- },
- [SingleRecordActionKeys.ADD_TO_FAVORITES]: {
- position: 8,
- isPinned: true,
- },
- [SingleRecordActionKeys.REMOVE_FROM_FAVORITES]: {
- position: 9,
- isPinned: true,
- },
- [SingleRecordActionKeys.EXPORT_FROM_RECORD_SHOW]: {
- position: 10,
- label: msg`Export dashboard`,
- },
- [SingleRecordActionKeys.DESTROY]: {
- position: 11,
- label: msg`Permanently destroy dashboard`,
- },
- [MultipleRecordsActionKeys.DESTROY]: {
- position: 13,
- label: msg`Permanently destroy dashboards`,
- },
- [SingleRecordActionKeys.RESTORE]: {
- position: 14,
- label: msg`Restore dashboard`,
- },
- [MultipleRecordsActionKeys.RESTORE]: {
- position: 15,
- label: msg`Restore dashboards`,
- },
- [NoSelectionRecordActionKeys.SEE_DELETED_RECORDS]: {
- position: 22,
- label: msg`See deleted dashboards`,
- },
- [NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS]: {
- position: 23,
- label: msg`Hide deleted dashboards`,
- },
- [NoSelectionRecordActionKeys.GO_TO_WORKFLOWS]: {
- position: 24,
- },
- [NoSelectionRecordActionKeys.GO_TO_PEOPLE]: {
- position: 25,
- },
- [NoSelectionRecordActionKeys.GO_TO_COMPANIES]: {
- position: 26,
- },
- [NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES]: {
- position: 27,
- },
- [NoSelectionRecordActionKeys.GO_TO_SETTINGS]: {
- position: 28,
- },
- [NoSelectionRecordActionKeys.GO_TO_TASKS]: {
- position: 29,
- },
- [NoSelectionRecordActionKeys.GO_TO_NOTES]: {
- position: 30,
- },
- },
-});
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DefaultRecordActionsConfig.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DefaultRecordActionsConfig.tsx
deleted file mode 100644
index 0501036f77..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/DefaultRecordActionsConfig.tsx
+++ /dev/null
@@ -1,843 +0,0 @@
-import { ActionLink } from '@/action-menu/actions/components/ActionLink';
-import { DeleteMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/components/DeleteMultipleRecordsAction';
-import { DestroyMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/components/DestroyMultipleRecordsAction';
-import { ExportMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/components/ExportMultipleRecordsAction';
-import { MergeMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/components/MergeMultipleRecordsAction';
-import { RestoreMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/components/RestoreMultipleRecordsAction';
-import { UpdateMultipleRecordsAction } from '@/action-menu/actions/record-actions/multiple-records/components/UpdateMultipleRecordsAction';
-import { MultipleRecordsActionKeys } from '@/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys';
-import { CreateNewIndexRecordNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/components/CreateNewIndexRecordNoSelectionRecordAction';
-import { CreateNewViewNoSelectionRecord } from '@/action-menu/actions/record-actions/no-selection/components/CreateNewViewNoSelectionRecord';
-import { HideDeletedRecordsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/components/HideDeletedRecordsNoSelectionRecordAction';
-import { ImportRecordsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/components/ImportRecordsNoSelectionRecordAction';
-import { SeeDeletedRecordsNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/components/SeeDeletedRecordsNoSelectionRecordAction';
-import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys';
-import { AddToFavoritesSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/components/AddToFavoritesSingleRecordAction';
-import { DeleteSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/components/DeleteSingleRecordAction';
-import { DestroySingleRecordAction } from '@/action-menu/actions/record-actions/single-record/components/DestroySingleRecordAction';
-import { ExportNoteActionSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/components/ExportNoteActionSingleRecordAction';
-import { ExportSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/components/ExportSingleRecordAction';
-import { NavigateToNextRecordSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/components/NavigateToNextRecordSingleRecordAction';
-import { NavigateToPreviousRecordSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/components/NavigateToPreviousRecordSingleRecordAction';
-import { RemoveFromFavoritesSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/components/RemoveFromFavoritesSingleRecordAction';
-import { RestoreSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/components/RestoreSingleRecordAction';
-import { CancelRecordPageLayoutSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/CancelRecordPageLayoutSingleRecordAction';
-import { EditRecordPageLayoutSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/EditRecordPageLayoutSingleRecordAction';
-import { SaveRecordPageLayoutSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/SaveRecordPageLayoutSingleRecordAction';
-import { RecordPageLayoutSingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/record-page-layout-actions/types/RecordPageLayoutSingleRecordActionKeys';
-import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey';
-import { type ActionConfig } from '@/action-menu/actions/types/ActionConfig';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionType } from '@/action-menu/actions/types/ActionType';
-import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
-import { msg } from '@lingui/core/macro';
-import { isNonEmptyString } from '@sniptt/guards';
-import {
- BACKEND_BATCH_REQUEST_MAX_COUNT,
- MUTATION_MAX_MERGE_RECORDS,
-} from 'twenty-shared/constants';
-import {
- ActionViewType,
- AppPath,
- CoreObjectNameSingular,
- SettingsPath,
-} from 'twenty-shared/types';
-import {
- IconArrowMerge,
- IconBuildingSkyscraper,
- IconCancel,
- IconCheckbox,
- IconChevronDown,
- IconChevronUp,
- IconDeviceFloppy,
- IconEdit,
- IconEyeOff,
- IconFileExport,
- IconFileImport,
- IconHeart,
- IconHeartOff,
- IconLayout,
- IconLayoutDashboard,
- IconPencil,
- IconPlus,
- IconRefresh,
- IconRotate2,
- IconSettings,
- IconSettingsAutomation,
- IconTargetArrow,
- IconTrash,
- IconTrashX,
- IconUser,
-} from 'twenty-ui/display';
-
-import { isDefined } from 'twenty-shared/utils';
-import {
- FeatureFlagKey,
- PermissionFlagType,
-} from '~/generated-metadata/graphql';
-
-export const DEFAULT_RECORD_ACTIONS_CONFIG: Record<
- | NoSelectionRecordActionKeys
- | SingleRecordActionKeys
- | MultipleRecordsActionKeys
- | RecordPageLayoutSingleRecordActionKeys,
- ActionConfig
-> = {
- [SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD]: {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD,
- label: msg`Navigate to next record`,
- position: 0,
- isPinned: true,
- Icon: IconChevronDown,
- shouldBeRegistered: ({ isInSidePanel }) => !isInSidePanel,
- availableOn: [ActionViewType.SHOW_PAGE],
- component: ,
- },
- [SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD]: {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD,
- label: msg`Navigate to previous record`,
- position: 1,
- isPinned: true,
- Icon: IconChevronUp,
- shouldBeRegistered: ({ isInSidePanel }) => !isInSidePanel,
- availableOn: [ActionViewType.SHOW_PAGE],
- component: ,
- },
- [NoSelectionRecordActionKeys.CREATE_NEW_RECORD]: {
- type: ActionType.Standard,
- scope: ActionScope.Object,
- key: NoSelectionRecordActionKeys.CREATE_NEW_RECORD,
- label: msg`Create new record`,
- shortLabel: msg`New record`,
- position: 2,
- isPinned: true,
- Icon: IconPlus,
- shouldBeRegistered: ({ objectPermissions, hasAnySoftDeleteFilterOnView }) =>
- (objectPermissions.canUpdateObjectRecords &&
- !hasAnySoftDeleteFilterOnView) ??
- false,
- availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
- component: ,
- },
- [SingleRecordActionKeys.DELETE]: {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: SingleRecordActionKeys.DELETE,
- label: msg`Delete`,
- shortLabel: msg`Delete`,
- position: 3,
- Icon: IconTrash,
- accent: 'default',
- isPinned: true,
- shouldBeRegistered: ({
- selectedRecord,
- hasAnySoftDeleteFilterOnView,
- objectPermissions,
- }) =>
- (isDefined(selectedRecord) &&
- !selectedRecord.isRemote &&
- !hasAnySoftDeleteFilterOnView &&
- objectPermissions.canSoftDeleteObjectRecords &&
- !isDefined(selectedRecord?.deletedAt)) ??
- false,
- availableOn: [
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.SHOW_PAGE,
- ],
- component: ,
- },
- [MultipleRecordsActionKeys.DELETE]: {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: MultipleRecordsActionKeys.DELETE,
- label: msg`Delete records`,
- shortLabel: msg`Delete`,
- position: 4,
- Icon: IconTrash,
- accent: 'default',
- isPinned: true,
- shouldBeRegistered: ({
- objectPermissions,
- isRemote,
- hasAnySoftDeleteFilterOnView,
- numberOfSelectedRecords,
- }) =>
- (objectPermissions.canSoftDeleteObjectRecords &&
- !isRemote &&
- !hasAnySoftDeleteFilterOnView &&
- isDefined(numberOfSelectedRecords) &&
- numberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT) ??
- false,
- availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION],
- component: ,
- },
- [SingleRecordActionKeys.RESTORE]: {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: SingleRecordActionKeys.RESTORE,
- label: msg`Restore record`,
- shortLabel: msg`Restore`,
- position: 5,
- Icon: IconRefresh,
- accent: 'default',
- isPinned: true,
- shouldBeRegistered: ({
- selectedRecord,
- objectPermissions,
- isRemote,
- isShowPage,
- hasAnySoftDeleteFilterOnView,
- }) =>
- (!isRemote &&
- isDefined(selectedRecord?.deletedAt) &&
- objectPermissions.canSoftDeleteObjectRecords &&
- ((isDefined(isShowPage) && isShowPage) ||
- (isDefined(hasAnySoftDeleteFilterOnView) &&
- hasAnySoftDeleteFilterOnView))) ??
- false,
- availableOn: [
- ActionViewType.SHOW_PAGE,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ],
- component: ,
- },
- [MultipleRecordsActionKeys.RESTORE]: {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: MultipleRecordsActionKeys.RESTORE,
- label: msg`Restore records`,
- shortLabel: msg`Restore`,
- position: 6,
- Icon: IconRefresh,
- accent: 'default',
- isPinned: true,
- shouldBeRegistered: ({
- objectPermissions,
- isRemote,
- hasAnySoftDeleteFilterOnView,
- numberOfSelectedRecords,
- }) =>
- (objectPermissions.canSoftDeleteObjectRecords &&
- !isRemote &&
- isDefined(hasAnySoftDeleteFilterOnView) &&
- hasAnySoftDeleteFilterOnView &&
- isDefined(numberOfSelectedRecords) &&
- numberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT) ??
- false,
- availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION],
- component: ,
- },
- [SingleRecordActionKeys.DESTROY]: {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: SingleRecordActionKeys.DESTROY,
- label: msg`Permanently destroy record`,
- shortLabel: msg`Destroy`,
- position: 7,
- Icon: IconTrashX,
- accent: 'danger',
- isPinned: true,
- shouldBeRegistered: ({ selectedRecord, objectPermissions, isRemote }) =>
- (objectPermissions.canDestroyObjectRecords &&
- !isRemote &&
- isDefined(selectedRecord?.deletedAt)) ??
- false,
- availableOn: [
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.SHOW_PAGE,
- ],
- component: ,
- },
- [MultipleRecordsActionKeys.DESTROY]: {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: MultipleRecordsActionKeys.DESTROY,
- label: msg`Permanently destroy records`,
- shortLabel: msg`Destroy`,
- position: 8,
- Icon: IconTrashX,
- accent: 'danger',
- isPinned: true,
- shouldBeRegistered: ({
- objectPermissions,
- isRemote,
- hasAnySoftDeleteFilterOnView,
- numberOfSelectedRecords,
- }) =>
- (objectPermissions.canDestroyObjectRecords &&
- !isRemote &&
- isDefined(hasAnySoftDeleteFilterOnView) &&
- hasAnySoftDeleteFilterOnView &&
- isDefined(numberOfSelectedRecords) &&
- numberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT) ??
- false,
- availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION],
- component: ,
- },
-
- [SingleRecordActionKeys.ADD_TO_FAVORITES]: {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: SingleRecordActionKeys.ADD_TO_FAVORITES,
- label: msg`Add to favorites`,
- shortLabel: msg`Add to favorites`,
- position: 9,
- isPinned: true,
- Icon: IconHeart,
- shouldBeRegistered: ({
- selectedRecord,
- isFavorite,
- hasAnySoftDeleteFilterOnView,
- }) =>
- !selectedRecord?.isRemote &&
- !isFavorite &&
- !isDefined(selectedRecord?.deletedAt) &&
- !hasAnySoftDeleteFilterOnView,
- availableOn: [
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.SHOW_PAGE,
- ],
- component: ,
- },
- [SingleRecordActionKeys.REMOVE_FROM_FAVORITES]: {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: SingleRecordActionKeys.REMOVE_FROM_FAVORITES,
- label: msg`Remove from favorites`,
- shortLabel: msg`Remove from favorites`,
- isPinned: true,
- position: 10,
- Icon: IconHeartOff,
- shouldBeRegistered: ({
- selectedRecord,
- isFavorite,
- hasAnySoftDeleteFilterOnView,
- }) =>
- isDefined(selectedRecord) &&
- !selectedRecord?.isRemote &&
- isDefined(isFavorite) &&
- isFavorite &&
- !isDefined(selectedRecord?.deletedAt) &&
- !hasAnySoftDeleteFilterOnView,
- availableOn: [
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.SHOW_PAGE,
- ],
- component: ,
- },
- [SingleRecordActionKeys.EXPORT_NOTE_TO_PDF]: {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: SingleRecordActionKeys.EXPORT_NOTE_TO_PDF,
- label: msg`Export to PDF`,
- shortLabel: msg`Export`,
- position: 11,
- isPinned: false,
- Icon: IconFileExport,
- shouldBeRegistered: ({ selectedRecord, isNoteOrTask }) =>
- isDefined(isNoteOrTask) &&
- isNoteOrTask &&
- isNonEmptyString(selectedRecord?.bodyV2?.blocknote),
- availableOn: [ActionViewType.SHOW_PAGE],
- component: ,
- },
- [SingleRecordActionKeys.EXPORT_FROM_RECORD_INDEX]: {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: SingleRecordActionKeys.EXPORT_FROM_RECORD_INDEX,
- label: msg`Export`,
- shortLabel: msg`Export`,
- position: 12,
- Icon: IconFileExport,
- accent: 'default',
- isPinned: false,
- shouldBeRegistered: ({ selectedRecord }) =>
- isDefined(selectedRecord) && !selectedRecord.isRemote,
- availableOn: [ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION],
- component: ,
- requiredPermissionFlag: PermissionFlagType.EXPORT_CSV,
- },
- [SingleRecordActionKeys.EXPORT_FROM_RECORD_SHOW]: {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: SingleRecordActionKeys.EXPORT_FROM_RECORD_SHOW,
- label: msg`Export`,
- shortLabel: msg`Export`,
- position: 13,
- Icon: IconFileExport,
- accent: 'default',
- isPinned: false,
- shouldBeRegistered: ({ selectedRecord }) =>
- isDefined(selectedRecord) && !selectedRecord.isRemote,
- availableOn: [ActionViewType.SHOW_PAGE],
- component: ,
- requiredPermissionFlag: PermissionFlagType.EXPORT_CSV,
- },
- [MultipleRecordsActionKeys.UPDATE]: {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: MultipleRecordsActionKeys.UPDATE,
- label: msg`Update records`,
- shortLabel: msg`Update`,
- position: 14,
- Icon: IconEdit,
- accent: 'default',
- isPinned: true,
- shouldBeRegistered: ({ objectPermissions, isRemote }) =>
- objectPermissions.canUpdateObjectRecords && !isRemote,
- availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION],
- component: ,
- },
- [MultipleRecordsActionKeys.MERGE]: {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: MultipleRecordsActionKeys.MERGE,
- label: msg`Merge records`,
- shortLabel: msg`Merge`,
- position: 15,
- Icon: IconArrowMerge,
- accent: 'default',
- isPinned: false,
- shouldBeRegistered: ({
- objectMetadataItem,
- numberOfSelectedRecords,
- objectPermissions,
- }) =>
- isDefined(objectMetadataItem?.duplicateCriteria) &&
- isDefined(numberOfSelectedRecords) &&
- Boolean(objectPermissions.canUpdateObjectRecords) &&
- Boolean(objectPermissions.canDestroyObjectRecords) &&
- numberOfSelectedRecords <= MUTATION_MAX_MERGE_RECORDS,
- availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION],
- component: ,
- },
- [MultipleRecordsActionKeys.EXPORT]: {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: MultipleRecordsActionKeys.EXPORT,
- label: msg`Export records`,
- shortLabel: msg`Export`,
- position: 16,
- Icon: IconFileExport,
- accent: 'default',
- isPinned: false,
- shouldBeRegistered: () => true,
- availableOn: [ActionViewType.INDEX_PAGE_BULK_SELECTION],
- component: ,
- requiredPermissionFlag: PermissionFlagType.EXPORT_CSV,
- },
- [NoSelectionRecordActionKeys.IMPORT_RECORDS]: {
- type: ActionType.Standard,
- scope: ActionScope.Object,
- key: NoSelectionRecordActionKeys.IMPORT_RECORDS,
- label: msg`Import records`,
- shortLabel: msg`Import`,
- position: 17,
- Icon: IconFileImport,
- accent: 'default',
- isPinned: false,
- shouldBeRegistered: ({ hasAnySoftDeleteFilterOnView }) =>
- !hasAnySoftDeleteFilterOnView,
- availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
- component: ,
- requiredPermissionFlag: PermissionFlagType.IMPORT_CSV,
- },
- [NoSelectionRecordActionKeys.EXPORT_VIEW]: {
- type: ActionType.Standard,
- scope: ActionScope.Object,
- key: NoSelectionRecordActionKeys.EXPORT_VIEW,
- label: msg`Export view`,
- shortLabel: msg`Export`,
- position: 18,
- Icon: IconFileExport,
- accent: 'default',
- isPinned: false,
- shouldBeRegistered: () => true,
- availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
- component: ,
- requiredPermissionFlag: PermissionFlagType.EXPORT_CSV,
- },
- [NoSelectionRecordActionKeys.SEE_DELETED_RECORDS]: {
- type: ActionType.Standard,
- scope: ActionScope.Object,
- key: NoSelectionRecordActionKeys.SEE_DELETED_RECORDS,
- label: msg`See deleted records`,
- shortLabel: msg`Deleted records`,
- position: 19,
- Icon: IconRotate2,
- accent: 'default',
- isPinned: false,
- shouldBeRegistered: ({ hasAnySoftDeleteFilterOnView }) =>
- !hasAnySoftDeleteFilterOnView,
- availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
- component: ,
- },
- [NoSelectionRecordActionKeys.CREATE_NEW_VIEW]: {
- type: ActionType.Standard,
- scope: ActionScope.Object,
- key: NoSelectionRecordActionKeys.CREATE_NEW_VIEW,
- label: msg`Create View`,
- shortLabel: msg`Create View`,
- position: 20,
- Icon: IconLayout,
- accent: 'default',
- isPinned: false,
- shouldBeRegistered: ({ hasAnySoftDeleteFilterOnView }) =>
- !hasAnySoftDeleteFilterOnView,
- availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
- component: ,
- },
- [NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS]: {
- type: ActionType.Standard,
- scope: ActionScope.Object,
- key: NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS,
- label: msg`Hide deleted records`,
- shortLabel: msg`Hide deleted`,
- position: 21,
- Icon: IconEyeOff,
- accent: 'default',
- isPinned: false,
- shouldBeRegistered: ({ hasAnySoftDeleteFilterOnView }) =>
- isDefined(hasAnySoftDeleteFilterOnView) && hasAnySoftDeleteFilterOnView,
- availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
- component: ,
- },
- [NoSelectionRecordActionKeys.GO_TO_WORKFLOWS]: {
- type: ActionType.Navigation,
- scope: ActionScope.Global,
- key: NoSelectionRecordActionKeys.GO_TO_WORKFLOWS,
- label: msg`Go to Workflows`,
- shortLabel: msg`See Workflows`,
- position: 22,
- Icon: IconSettingsAutomation,
- accent: 'default',
- isPinned: false,
- shouldBeRegistered: ({
- objectMetadataItem,
- viewType,
- getTargetObjectReadPermission,
- }) =>
- getTargetObjectReadPermission(CoreObjectNameSingular.Workflow) &&
- (objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Workflow ||
- viewType === ActionViewType.SHOW_PAGE),
- availableOn: [
- ActionViewType.INDEX_PAGE_NO_SELECTION,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.INDEX_PAGE_BULK_SELECTION,
- ActionViewType.SHOW_PAGE,
- ActionViewType.PAGE_EDIT_MODE,
- ],
- component: (
-
- ),
- hotKeys: ['G', 'W'],
- },
- [NoSelectionRecordActionKeys.GO_TO_PEOPLE]: {
- type: ActionType.Navigation,
- scope: ActionScope.Global,
- key: NoSelectionRecordActionKeys.GO_TO_PEOPLE,
- label: msg`Go to People`,
- shortLabel: msg`People`,
- position: 23,
- Icon: IconUser,
- isPinned: false,
- availableOn: [
- ActionViewType.INDEX_PAGE_NO_SELECTION,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.INDEX_PAGE_BULK_SELECTION,
- ActionViewType.SHOW_PAGE,
- ActionViewType.PAGE_EDIT_MODE,
- ],
- shouldBeRegistered: ({
- objectMetadataItem,
- viewType,
- getTargetObjectReadPermission,
- }) =>
- getTargetObjectReadPermission(CoreObjectNameSingular.Person) &&
- (objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Person ||
- viewType === ActionViewType.SHOW_PAGE),
- component: (
-
- ),
- hotKeys: ['G', 'P'],
- },
- [NoSelectionRecordActionKeys.GO_TO_COMPANIES]: {
- type: ActionType.Navigation,
- scope: ActionScope.Global,
- key: NoSelectionRecordActionKeys.GO_TO_COMPANIES,
- label: msg`Go to Companies`,
- shortLabel: msg`Companies`,
- position: 24,
- Icon: IconBuildingSkyscraper,
- isPinned: false,
- availableOn: [
- ActionViewType.INDEX_PAGE_NO_SELECTION,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.INDEX_PAGE_BULK_SELECTION,
- ActionViewType.SHOW_PAGE,
- ActionViewType.PAGE_EDIT_MODE,
- ],
- shouldBeRegistered: ({
- objectMetadataItem,
- viewType,
- getTargetObjectReadPermission,
- }) =>
- getTargetObjectReadPermission(CoreObjectNameSingular.Company) &&
- (objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Company ||
- viewType === ActionViewType.SHOW_PAGE),
- component: (
-
- ),
- hotKeys: ['G', 'C'],
- },
- [NoSelectionRecordActionKeys.GO_TO_DASHBOARDS]: {
- type: ActionType.Navigation,
- scope: ActionScope.Global,
- key: NoSelectionRecordActionKeys.GO_TO_DASHBOARDS,
- label: msg`Go to Dashboards`,
- shortLabel: msg`Dashboards`,
- position: 25,
- Icon: IconLayoutDashboard,
- isPinned: false,
- availableOn: [
- ActionViewType.INDEX_PAGE_NO_SELECTION,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.INDEX_PAGE_BULK_SELECTION,
- ActionViewType.SHOW_PAGE,
- ],
- shouldBeRegistered: ({
- objectMetadataItem,
- viewType,
- getTargetObjectReadPermission,
- }) =>
- getTargetObjectReadPermission(CoreObjectNameSingular.Dashboard) &&
- (objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Dashboard ||
- viewType === ActionViewType.SHOW_PAGE),
- component: (
-
- ),
- hotKeys: ['G', 'D'],
- },
- [NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES]: {
- type: ActionType.Navigation,
- scope: ActionScope.Global,
- key: NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES,
- label: msg`Go to Opportunities`,
- shortLabel: msg`Opportunities`,
- position: 26,
- Icon: IconTargetArrow,
- isPinned: false,
- availableOn: [
- ActionViewType.INDEX_PAGE_NO_SELECTION,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.INDEX_PAGE_BULK_SELECTION,
- ActionViewType.SHOW_PAGE,
- ActionViewType.PAGE_EDIT_MODE,
- ],
- shouldBeRegistered: ({
- objectMetadataItem,
- viewType,
- getTargetObjectReadPermission,
- }) =>
- getTargetObjectReadPermission(CoreObjectNameSingular.Opportunity) &&
- (objectMetadataItem?.nameSingular !==
- CoreObjectNameSingular.Opportunity ||
- viewType === ActionViewType.SHOW_PAGE),
- component: (
-
- ),
- hotKeys: ['G', 'O'],
- },
- [NoSelectionRecordActionKeys.GO_TO_SETTINGS]: {
- type: ActionType.Navigation,
- scope: ActionScope.Global,
- key: NoSelectionRecordActionKeys.GO_TO_SETTINGS,
- label: msg`Go to Settings`,
- shortLabel: msg`Settings`,
- position: 27,
- Icon: IconSettings,
- isPinned: false,
- availableOn: [
- ActionViewType.INDEX_PAGE_NO_SELECTION,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.INDEX_PAGE_BULK_SELECTION,
- ActionViewType.SHOW_PAGE,
- ],
- shouldBeRegistered: () => true,
- component: (
-
- ),
- hotKeys: ['G', 'S'],
- },
- [NoSelectionRecordActionKeys.GO_TO_TASKS]: {
- type: ActionType.Navigation,
- scope: ActionScope.Global,
- key: NoSelectionRecordActionKeys.GO_TO_TASKS,
- label: msg`Go to Tasks`,
- shortLabel: msg`Tasks`,
- position: 28,
- Icon: IconCheckbox,
- isPinned: false,
- availableOn: [
- ActionViewType.INDEX_PAGE_NO_SELECTION,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.INDEX_PAGE_BULK_SELECTION,
- ActionViewType.SHOW_PAGE,
- ActionViewType.PAGE_EDIT_MODE,
- ],
- shouldBeRegistered: ({
- objectMetadataItem,
- viewType,
- getTargetObjectReadPermission,
- }) =>
- getTargetObjectReadPermission(CoreObjectNameSingular.Task) &&
- (objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Task ||
- viewType === ActionViewType.SHOW_PAGE),
- component: (
-
- ),
- hotKeys: ['G', 'T'],
- },
- [NoSelectionRecordActionKeys.GO_TO_NOTES]: {
- type: ActionType.Navigation,
- scope: ActionScope.Global,
- key: NoSelectionRecordActionKeys.GO_TO_NOTES,
- label: msg`Go to Notes`,
- shortLabel: msg`Notes`,
- position: 29,
- Icon: IconCheckbox,
- isPinned: false,
- availableOn: [
- ActionViewType.INDEX_PAGE_NO_SELECTION,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.INDEX_PAGE_BULK_SELECTION,
- ActionViewType.SHOW_PAGE,
- ActionViewType.PAGE_EDIT_MODE,
- ],
- shouldBeRegistered: ({
- objectMetadataItem,
- viewType,
- getTargetObjectReadPermission,
- }) =>
- getTargetObjectReadPermission(CoreObjectNameSingular.Note) &&
- (objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Note ||
- viewType === ActionViewType.SHOW_PAGE),
- component: (
-
- ),
- hotKeys: ['G', 'N'],
- },
-
- [RecordPageLayoutSingleRecordActionKeys.EDIT_RECORD_PAGE_LAYOUT]: {
- key: RecordPageLayoutSingleRecordActionKeys.EDIT_RECORD_PAGE_LAYOUT,
- label: msg`Edit Page Layout`,
- shortLabel: msg`Edit Layout`,
- isPinned: true,
- position: 30,
- Icon: IconPencil,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- requiredPermissionFlag: PermissionFlagType.LAYOUTS,
- shouldBeRegistered: ({
- selectedRecord,
- objectPermissions,
- objectMetadataItem,
- isFeatureFlagEnabled,
- }) =>
- isFeatureFlagEnabled(
- FeatureFlagKey.IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED,
- ) &&
- isDefined(selectedRecord) &&
- !selectedRecord?.isRemote &&
- !isDefined(selectedRecord?.deletedAt) &&
- objectPermissions.canUpdateObjectRecords &&
- objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Dashboard,
- availableOn: [ActionViewType.SHOW_PAGE],
- component: ,
- },
- [RecordPageLayoutSingleRecordActionKeys.SAVE_RECORD_PAGE_LAYOUT]: {
- key: RecordPageLayoutSingleRecordActionKeys.SAVE_RECORD_PAGE_LAYOUT,
- label: msg`Save Page Layout`,
- shortLabel: msg`Save`,
- isPinned: true,
- isPrimaryCTA: true,
- position: 31,
- Icon: IconDeviceFloppy,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- requiredPermissionFlag: PermissionFlagType.LAYOUTS,
- shouldBeRegistered: ({
- selectedRecord,
- objectPermissions,
- objectMetadataItem,
- isFeatureFlagEnabled,
- }) =>
- isFeatureFlagEnabled(
- FeatureFlagKey.IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED,
- ) &&
- isDefined(selectedRecord) &&
- !selectedRecord?.isRemote &&
- !isDefined(selectedRecord?.deletedAt) &&
- objectPermissions.canUpdateObjectRecords &&
- objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Dashboard,
- availableOn: [ActionViewType.PAGE_EDIT_MODE],
- component: ,
- },
- [RecordPageLayoutSingleRecordActionKeys.CANCEL_RECORD_PAGE_LAYOUT_EDITION]: {
- key: RecordPageLayoutSingleRecordActionKeys.CANCEL_RECORD_PAGE_LAYOUT_EDITION,
- label: msg`Cancel Edition`,
- shortLabel: msg`Cancel`,
- isPinned: true,
- position: 32,
- Icon: IconCancel,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- requiredPermissionFlag: PermissionFlagType.LAYOUTS,
- shouldBeRegistered: ({
- selectedRecord,
- objectPermissions,
- objectMetadataItem,
- isFeatureFlagEnabled,
- }) =>
- isFeatureFlagEnabled(
- FeatureFlagKey.IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED,
- ) &&
- isDefined(selectedRecord) &&
- !selectedRecord?.isRemote &&
- !isDefined(selectedRecord?.deletedAt) &&
- objectPermissions.canUpdateObjectRecords &&
- objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Dashboard,
- availableOn: [ActionViewType.PAGE_EDIT_MODE],
- component: ,
- },
-};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowActionsConfig.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowActionsConfig.tsx
deleted file mode 100644
index 5e6dbb1f08..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowActionsConfig.tsx
+++ /dev/null
@@ -1,387 +0,0 @@
-import { ActionLink } from '@/action-menu/actions/components/ActionLink';
-import { MultipleRecordsActionKeys } from '@/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys';
-import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys';
-import { NoSelectionWorkflowRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/workflow-actions/types/NoSelectionWorkflowRecordActionKeys';
-import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey';
-import { ActivateWorkflowSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-actions/components/ActivateWorkflowSingleRecordAction';
-import { AddNodeWorkflowSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-actions/components/AddNodeWorkflowSingleRecordAction';
-import { DeactivateWorkflowSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-actions/components/DeactivateWorkflowSingleRecordAction';
-import { DiscardDraftWorkflowSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-actions/components/DiscardDraftWorkflowSingleRecordAction';
-import { DuplicateWorkflowSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-actions/components/DuplicateWorkflowSingleRecordAction';
-import { SeeActiveVersionWorkflowSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-actions/components/SeeActiveVersionWorkflowSingleRecordAction';
-import { SeeRunsWorkflowSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-actions/components/SeeRunsWorkflowSingleRecordAction';
-import { SeeVersionsWorkflowSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-actions/components/SeeVersionsWorkflowSingleRecordAction';
-import { TestWorkflowSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-actions/components/TestWorkflowSingleRecordAction';
-import { TidyUpWorkflowSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-actions/components/TidyUpWorkflowSingleRecordAction';
-import { WorkflowSingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/workflow-actions/types/WorkflowSingleRecordActionsKeys';
-import { inheritActionsFromDefaultConfig } from '@/action-menu/actions/record-actions/utils/inheritActionsFromDefaultConfig';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionType } from '@/action-menu/actions/types/ActionType';
-import { ActionViewType, AppPath } from 'twenty-shared/types';
-import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
-import {
- type WorkflowStep,
- type WorkflowTrigger,
- type WorkflowWithCurrentVersion,
-} from '@/workflow/types/Workflow';
-import { msg } from '@lingui/core/macro';
-import { isDefined } from 'twenty-shared/utils';
-import {
- IconCopy,
- IconHistoryToggle,
- IconNoteOff,
- IconPlayerPause,
- IconPlayerPlay,
- IconPlus,
- IconPower,
- IconReorder,
- IconVersions,
-} from 'twenty-ui/display';
-
-const areWorkflowTriggerAndStepsDefined = (
- workflowWithCurrentVersion: WorkflowWithCurrentVersion | undefined,
-): workflowWithCurrentVersion is WorkflowWithCurrentVersion & {
- currentVersion: {
- trigger: WorkflowTrigger;
- steps: Array;
- };
-} => {
- return (
- isDefined(workflowWithCurrentVersion?.currentVersion?.trigger) &&
- isDefined(workflowWithCurrentVersion.currentVersion?.steps) &&
- workflowWithCurrentVersion.currentVersion.steps.length > 0
- );
-};
-
-export const WORKFLOW_ACTIONS_CONFIG = inheritActionsFromDefaultConfig({
- config: {
- [WorkflowSingleRecordActionKeys.ACTIVATE]: {
- key: WorkflowSingleRecordActionKeys.ACTIVATE,
- label: msg`Activate Workflow`,
- shortLabel: msg`Activate`,
- isPinned: true,
- isPrimaryCTA: true,
- position: 3,
- Icon: IconPower,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
- areWorkflowTriggerAndStepsDefined(workflowWithCurrentVersion) &&
- (workflowWithCurrentVersion.currentVersion.status === 'DRAFT' ||
- !workflowWithCurrentVersion.versions?.some(
- (version) => version.status === 'ACTIVE',
- )) &&
- !isDefined(selectedRecord?.deletedAt),
- availableOn: [
- ActionViewType.SHOW_PAGE,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ],
- component: ,
- },
- [WorkflowSingleRecordActionKeys.DEACTIVATE]: {
- key: WorkflowSingleRecordActionKeys.DEACTIVATE,
- label: msg`Deactivate Workflow`,
- shortLabel: msg`Deactivate`,
- isPinned: true,
- position: 4,
- Icon: IconPlayerPause,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
- isDefined(workflowWithCurrentVersion) &&
- workflowWithCurrentVersion.currentVersion.status === 'ACTIVE' &&
- !isDefined(selectedRecord?.deletedAt),
- availableOn: [
- ActionViewType.SHOW_PAGE,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ],
- component: ,
- },
- [WorkflowSingleRecordActionKeys.DISCARD_DRAFT]: {
- key: WorkflowSingleRecordActionKeys.DISCARD_DRAFT,
- label: msg`Discard Draft`,
- shortLabel: msg`Discard Draft`,
- isPinned: true,
- position: 5,
- Icon: IconNoteOff,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
- isDefined(workflowWithCurrentVersion) &&
- workflowWithCurrentVersion.versions.length > 1 &&
- workflowWithCurrentVersion.currentVersion.status === 'DRAFT' &&
- !isDefined(selectedRecord?.deletedAt),
- availableOn: [
- ActionViewType.SHOW_PAGE,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ],
- component: ,
- },
- [WorkflowSingleRecordActionKeys.TEST]: {
- key: WorkflowSingleRecordActionKeys.TEST,
- label: msg`Test Workflow`,
- shortLabel: msg`Test`,
- isPinned: true,
- position: 6,
- Icon: IconPlayerPlay,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
- areWorkflowTriggerAndStepsDefined(workflowWithCurrentVersion) &&
- ((workflowWithCurrentVersion.currentVersion.trigger.type === 'MANUAL' &&
- !isDefined(
- workflowWithCurrentVersion.currentVersion.trigger.settings
- .objectType,
- )) ||
- workflowWithCurrentVersion.currentVersion.trigger.type ===
- 'WEBHOOK' ||
- workflowWithCurrentVersion.currentVersion.trigger.type === 'CRON') &&
- !isDefined(selectedRecord?.deletedAt),
- availableOn: [
- ActionViewType.SHOW_PAGE,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ],
- component: ,
- },
-
- [WorkflowSingleRecordActionKeys.SEE_ACTIVE_VERSION]: {
- key: WorkflowSingleRecordActionKeys.SEE_ACTIVE_VERSION,
- label: msg`See active version`,
- shortLabel: msg`See active version`,
- isPinned: false,
- position: 7,
- Icon: IconVersions,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- shouldBeRegistered: ({ workflowWithCurrentVersion, selectedRecord }) =>
- (workflowWithCurrentVersion?.statuses?.includes('ACTIVE') || false) &&
- (workflowWithCurrentVersion?.statuses?.includes('DRAFT') || false) &&
- !isDefined(selectedRecord?.deletedAt),
- availableOn: [
- ActionViewType.SHOW_PAGE,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ],
- component: ,
- },
- [WorkflowSingleRecordActionKeys.SEE_RUNS]: {
- key: WorkflowSingleRecordActionKeys.SEE_RUNS,
- label: msg`See runs`,
- shortLabel: msg`See runs`,
- isPinned: true,
- position: 8,
- Icon: IconHistoryToggle,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
- isDefined(workflowWithCurrentVersion) &&
- !isDefined(selectedRecord?.deletedAt),
- availableOn: [
- ActionViewType.SHOW_PAGE,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ],
- component: ,
- },
- [WorkflowSingleRecordActionKeys.SEE_VERSIONS]: {
- key: WorkflowSingleRecordActionKeys.SEE_VERSIONS,
- label: msg`See versions history`,
- shortLabel: msg`See versions`,
- isPinned: false,
- position: 9,
- Icon: IconVersions,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
- isDefined(workflowWithCurrentVersion) &&
- !isDefined(selectedRecord?.deletedAt),
- availableOn: [
- ActionViewType.SHOW_PAGE,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ],
- component: ,
- },
-
- [WorkflowSingleRecordActionKeys.ADD_NODE]: {
- key: WorkflowSingleRecordActionKeys.ADD_NODE,
- label: msg`Add a node`,
- shortLabel: msg`Add a node`,
- isPinned: true,
- position: 10,
- Icon: IconPlus,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
- areWorkflowTriggerAndStepsDefined(workflowWithCurrentVersion) &&
- !isDefined(selectedRecord?.deletedAt),
- availableOn: [ActionViewType.SHOW_PAGE],
- component: ,
- },
- [WorkflowSingleRecordActionKeys.TIDY_UP]: {
- key: WorkflowSingleRecordActionKeys.TIDY_UP,
- label: msg`Tidy up workflow`,
- shortLabel: msg`Tidy up`,
- isPinned: false,
- position: 11,
- Icon: IconReorder,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
- areWorkflowTriggerAndStepsDefined(workflowWithCurrentVersion) &&
- !isDefined(selectedRecord?.deletedAt),
- availableOn: [ActionViewType.SHOW_PAGE],
- component: ,
- },
- [WorkflowSingleRecordActionKeys.DUPLICATE_WORKFLOW]: {
- key: WorkflowSingleRecordActionKeys.DUPLICATE_WORKFLOW,
- label: msg`Duplicate Workflow`,
- shortLabel: msg`Duplicate`,
- isPinned: false,
- position: 12,
- Icon: IconCopy,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
- isDefined(workflowWithCurrentVersion) &&
- isDefined(workflowWithCurrentVersion.currentVersion) &&
- !isDefined(selectedRecord?.deletedAt),
- availableOn: [
- ActionViewType.SHOW_PAGE,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ],
- component: ,
- },
- [NoSelectionWorkflowRecordActionKeys.GO_TO_RUNS]: {
- type: ActionType.Navigation,
- scope: ActionScope.Global,
- key: NoSelectionWorkflowRecordActionKeys.GO_TO_RUNS,
- label: msg`Go to runs`,
- shortLabel: msg`See runs`,
- position: 22,
- Icon: IconHistoryToggle,
- accent: 'default',
- isPinned: true,
- shouldBeRegistered: ({ hasAnySoftDeleteFilterOnView }) =>
- !hasAnySoftDeleteFilterOnView,
- availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
- component: (
-
- ),
- },
- },
- actionKeys: [
- NoSelectionRecordActionKeys.CREATE_NEW_RECORD,
- SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD,
- SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD,
- SingleRecordActionKeys.ADD_TO_FAVORITES,
- SingleRecordActionKeys.REMOVE_FROM_FAVORITES,
- SingleRecordActionKeys.DELETE,
- SingleRecordActionKeys.DESTROY,
- SingleRecordActionKeys.RESTORE,
- SingleRecordActionKeys.EXPORT_FROM_RECORD_INDEX,
- SingleRecordActionKeys.EXPORT_FROM_RECORD_SHOW,
- MultipleRecordsActionKeys.DELETE,
- MultipleRecordsActionKeys.DESTROY,
- MultipleRecordsActionKeys.RESTORE,
- MultipleRecordsActionKeys.EXPORT,
- NoSelectionRecordActionKeys.SEE_DELETED_RECORDS,
- NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS,
- NoSelectionRecordActionKeys.GO_TO_PEOPLE,
- NoSelectionRecordActionKeys.GO_TO_COMPANIES,
- NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES,
- NoSelectionRecordActionKeys.GO_TO_DASHBOARDS,
- NoSelectionRecordActionKeys.GO_TO_SETTINGS,
- NoSelectionRecordActionKeys.GO_TO_TASKS,
- NoSelectionRecordActionKeys.GO_TO_NOTES,
- ],
- propertiesToOverwrite: {
- [SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD]: {
- position: 0,
- label: msg`Navigate to next workflow`,
- },
- [SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD]: {
- position: 1,
- label: msg`Navigate to previous workflow`,
- },
- [NoSelectionRecordActionKeys.CREATE_NEW_RECORD]: {
- position: 2,
- label: msg`Create new workflow`,
- },
- [SingleRecordActionKeys.DELETE]: {
- position: 12,
- label: msg`Delete workflow`,
- },
- [MultipleRecordsActionKeys.DELETE]: {
- position: 13,
- label: msg`Delete workflows`,
- },
- [SingleRecordActionKeys.ADD_TO_FAVORITES]: {
- position: 14,
- isPinned: false,
- },
- [SingleRecordActionKeys.REMOVE_FROM_FAVORITES]: {
- position: 15,
- isPinned: false,
- },
- [SingleRecordActionKeys.DESTROY]: {
- position: 16,
- label: msg`Permanently destroy workflow`,
- },
- [SingleRecordActionKeys.EXPORT_FROM_RECORD_INDEX]: {
- position: 17,
- label: msg`Export workflow`,
- shouldBeRegistered: ({ selectedRecord }) =>
- !isDefined(selectedRecord?.deletedAt),
- },
- [SingleRecordActionKeys.EXPORT_FROM_RECORD_SHOW]: {
- position: 18,
- label: msg`Export workflow`,
- },
- [MultipleRecordsActionKeys.EXPORT]: {
- position: 19,
- label: msg`Export workflows`,
- },
- [NoSelectionRecordActionKeys.EXPORT_VIEW]: {
- position: 20,
- label: msg`Export view`,
- },
- [MultipleRecordsActionKeys.DESTROY]: {
- position: 21,
- label: msg`Permanently destroy workflows`,
- },
- [NoSelectionRecordActionKeys.SEE_DELETED_RECORDS]: {
- position: 22,
- label: msg`See deleted workflows`,
- },
- [NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS]: {
- position: 23,
- label: msg`Hide deleted workflows`,
- },
- [NoSelectionRecordActionKeys.IMPORT_RECORDS]: {
- position: 24,
- label: msg`Import workflows`,
- },
- [NoSelectionRecordActionKeys.GO_TO_PEOPLE]: {
- position: 25,
- },
- [NoSelectionRecordActionKeys.GO_TO_COMPANIES]: {
- position: 26,
- },
- [NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES]: {
- position: 27,
- },
- [NoSelectionRecordActionKeys.GO_TO_DASHBOARDS]: {
- position: 28,
- },
- [NoSelectionRecordActionKeys.GO_TO_SETTINGS]: {
- position: 29,
- },
- [NoSelectionRecordActionKeys.GO_TO_TASKS]: {
- position: 30,
- },
- [NoSelectionRecordActionKeys.GO_TO_NOTES]: {
- position: 31,
- },
- },
-});
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowRunsActionsConfig.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowRunsActionsConfig.tsx
deleted file mode 100644
index 8c0c1c2f1c..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowRunsActionsConfig.tsx
+++ /dev/null
@@ -1,164 +0,0 @@
-import { MultipleRecordsActionKeys } from '@/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys';
-import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys';
-import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey';
-import { SeeVersionWorkflowRunSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-run-actions/components/SeeVersionWorkflowRunSingleRecordAction';
-import { SeeWorkflowWorkflowRunSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-run-actions/components/SeeWorkflowWorkflowRunSingleRecordAction';
-import { StopWorkflowRunSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-run-actions/components/StopWorkflowRunSingleRecordAction';
-import { WorkflowRunSingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/workflow-run-actions/types/WorkflowRunSingleRecordActionsKeys';
-import { inheritActionsFromDefaultConfig } from '@/action-menu/actions/record-actions/utils/inheritActionsFromDefaultConfig';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionType } from '@/action-menu/actions/types/ActionType';
-import { ActionViewType } from 'twenty-shared/types';
-import { msg } from '@lingui/core/macro';
-import {
- IconPlayerStop,
- IconSettingsAutomation,
- IconVersions,
-} from 'twenty-ui/display';
-
-export const WORKFLOW_RUNS_ACTIONS_CONFIG = inheritActionsFromDefaultConfig({
- config: {
- [WorkflowRunSingleRecordActionKeys.SEE_VERSION]: {
- key: WorkflowRunSingleRecordActionKeys.SEE_VERSION,
- label: msg`See version`,
- shortLabel: msg`See version`,
- position: 0,
- isPinned: true,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- Icon: IconVersions,
- shouldBeRegistered: () => true,
- availableOn: [
- ActionViewType.SHOW_PAGE,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ],
- component: ,
- },
-
- [WorkflowRunSingleRecordActionKeys.SEE_WORKFLOW]: {
- key: WorkflowRunSingleRecordActionKeys.SEE_WORKFLOW,
- label: msg`See workflow`,
- shortLabel: msg`See workflow`,
- position: 1,
- isPinned: true,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- Icon: IconSettingsAutomation,
- shouldBeRegistered: () => true,
- availableOn: [
- ActionViewType.SHOW_PAGE,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ],
- component: ,
- },
- [WorkflowRunSingleRecordActionKeys.STOP]: {
- key: WorkflowRunSingleRecordActionKeys.STOP,
- label: msg`Stop`,
- shortLabel: msg`Stop`,
- position: 2,
- isPinned: true,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- Icon: IconPlayerStop,
- shouldBeRegistered: ({ selectedRecord, isSelectAll }) => {
- if (isSelectAll === true) {
- return true;
- }
-
- const stoppableStatuses = ['NOT_STARTED', 'ENQUEUED', 'RUNNING'];
- return stoppableStatuses.includes(selectedRecord?.status);
- },
- availableOn: [
- ActionViewType.SHOW_PAGE,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.INDEX_PAGE_BULK_SELECTION,
- ],
- component: ,
- },
- },
- actionKeys: [
- SingleRecordActionKeys.ADD_TO_FAVORITES,
- SingleRecordActionKeys.REMOVE_FROM_FAVORITES,
- SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD,
- SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD,
- SingleRecordActionKeys.EXPORT_FROM_RECORD_INDEX,
- SingleRecordActionKeys.EXPORT_FROM_RECORD_SHOW,
- MultipleRecordsActionKeys.EXPORT,
- NoSelectionRecordActionKeys.EXPORT_VIEW,
- NoSelectionRecordActionKeys.SEE_DELETED_RECORDS,
- NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS,
- NoSelectionRecordActionKeys.GO_TO_WORKFLOWS,
- NoSelectionRecordActionKeys.GO_TO_PEOPLE,
- NoSelectionRecordActionKeys.GO_TO_COMPANIES,
- NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES,
- NoSelectionRecordActionKeys.GO_TO_DASHBOARDS,
- NoSelectionRecordActionKeys.GO_TO_SETTINGS,
- NoSelectionRecordActionKeys.GO_TO_TASKS,
- NoSelectionRecordActionKeys.GO_TO_NOTES,
- ],
- propertiesToOverwrite: {
- [SingleRecordActionKeys.ADD_TO_FAVORITES]: {
- isPinned: false,
- position: 3,
- },
- [SingleRecordActionKeys.REMOVE_FROM_FAVORITES]: {
- isPinned: false,
- position: 4,
- },
- [SingleRecordActionKeys.EXPORT_FROM_RECORD_INDEX]: {
- position: 5,
- label: msg`Export run`,
- },
- [SingleRecordActionKeys.EXPORT_FROM_RECORD_SHOW]: {
- position: 5,
- label: msg`Export run`,
- },
- [MultipleRecordsActionKeys.EXPORT]: {
- position: 6,
- label: msg`Export runs`,
- },
- [NoSelectionRecordActionKeys.EXPORT_VIEW]: {
- position: 7,
- label: msg`Export view`,
- },
- [NoSelectionRecordActionKeys.SEE_DELETED_RECORDS]: {
- position: 8,
- label: msg`See deleted runs`,
- },
- [NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS]: {
- position: 9,
- label: msg`Hide deleted runs`,
- },
- [SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD]: {
- position: 10,
- },
- [SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD]: {
- position: 11,
- },
- [NoSelectionRecordActionKeys.GO_TO_WORKFLOWS]: {
- position: 12,
- isPinned: true,
- },
- [NoSelectionRecordActionKeys.GO_TO_PEOPLE]: {
- position: 13,
- },
- [NoSelectionRecordActionKeys.GO_TO_COMPANIES]: {
- position: 14,
- },
- [NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES]: {
- position: 15,
- },
- [NoSelectionRecordActionKeys.GO_TO_DASHBOARDS]: {
- position: 16,
- },
- [NoSelectionRecordActionKeys.GO_TO_SETTINGS]: {
- position: 17,
- },
- [NoSelectionRecordActionKeys.GO_TO_TASKS]: {
- position: 18,
- },
- [NoSelectionRecordActionKeys.GO_TO_NOTES]: {
- position: 19,
- },
- },
-});
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowVersionsActionsConfig.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowVersionsActionsConfig.tsx
deleted file mode 100644
index a7a0d98a28..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkflowVersionsActionsConfig.tsx
+++ /dev/null
@@ -1,200 +0,0 @@
-import { ActionLink } from '@/action-menu/actions/components/ActionLink';
-import { MultipleRecordsActionKeys } from '@/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys';
-import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys';
-import { NoSelectionWorkflowRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/workflow-actions/types/NoSelectionWorkflowRecordActionKeys';
-import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey';
-import { SeeRunsWorkflowVersionSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-version-actions/components/SeeRunsWorkflowVersionSingleRecordAction';
-import { SeeVersionsWorkflowVersionSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-version-actions/components/SeeVersionsWorkflowVersionSingleRecordAction';
-import { SeeWorkflowWorkflowVersionSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-version-actions/components/SeeWorkflowWorkflowVersionSingleRecordAction';
-import { UseAsDraftWorkflowVersionSingleRecordAction } from '@/action-menu/actions/record-actions/single-record/workflow-version-actions/components/UseAsDraftWorkflowVersionSingleRecordAction';
-import { WorkflowVersionSingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/workflow-version-actions/types/WorkflowVersionSingleRecordActionsKeys';
-import { inheritActionsFromDefaultConfig } from '@/action-menu/actions/record-actions/utils/inheritActionsFromDefaultConfig';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionType } from '@/action-menu/actions/types/ActionType';
-import { ActionViewType, AppPath } from 'twenty-shared/types';
-import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
-import { msg } from '@lingui/core/macro';
-import { isDefined } from 'twenty-shared/utils';
-import {
- IconHistoryToggle,
- IconPencil,
- IconSettingsAutomation,
- IconVersions,
-} from 'twenty-ui/display';
-
-export const WORKFLOW_VERSIONS_ACTIONS_CONFIG = inheritActionsFromDefaultConfig(
- {
- config: {
- [WorkflowVersionSingleRecordActionKeys.SEE_RUNS]: {
- key: WorkflowVersionSingleRecordActionKeys.SEE_RUNS,
- label: msg`See runs`,
- shortLabel: msg`See runs`,
- position: 1,
- isPinned: true,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- Icon: IconHistoryToggle,
- shouldBeRegistered: ({ workflowWithCurrentVersion }) =>
- isDefined(workflowWithCurrentVersion),
- availableOn: [
- ActionViewType.SHOW_PAGE,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ],
- component: ,
- },
- [WorkflowVersionSingleRecordActionKeys.SEE_WORKFLOW]: {
- key: WorkflowVersionSingleRecordActionKeys.SEE_WORKFLOW,
- label: msg`See workflow`,
- shortLabel: msg`See workflow`,
- position: 2,
- isPinned: true,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- Icon: IconSettingsAutomation,
- shouldBeRegistered: ({ selectedRecord }) =>
- isDefined(selectedRecord?.workflow?.id),
- availableOn: [
- ActionViewType.SHOW_PAGE,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ],
- component: ,
- },
- [WorkflowVersionSingleRecordActionKeys.USE_AS_DRAFT]: {
- key: WorkflowVersionSingleRecordActionKeys.USE_AS_DRAFT,
- label: msg`Use as draft`,
- shortLabel: msg`Use as draft`,
- position: 3,
- isPinned: true,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- Icon: IconPencil,
- shouldBeRegistered: ({ selectedRecord }) =>
- isDefined(selectedRecord) && selectedRecord.status !== 'DRAFT',
- availableOn: [
- ActionViewType.SHOW_PAGE,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ],
- component: ,
- },
- [WorkflowVersionSingleRecordActionKeys.SEE_VERSIONS]: {
- key: WorkflowVersionSingleRecordActionKeys.SEE_VERSIONS,
- label: msg`See versions history`,
- shortLabel: msg`See versions`,
- position: 4,
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- Icon: IconVersions,
- shouldBeRegistered: ({ workflowWithCurrentVersion }) =>
- isDefined(workflowWithCurrentVersion),
- availableOn: [
- ActionViewType.SHOW_PAGE,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ],
- component: ,
- },
- [NoSelectionWorkflowRecordActionKeys.GO_TO_RUNS]: {
- type: ActionType.Navigation,
- scope: ActionScope.Global,
- key: NoSelectionWorkflowRecordActionKeys.GO_TO_RUNS,
- label: msg`Go to runs`,
- shortLabel: msg`See runs`,
- position: 14,
- Icon: IconHistoryToggle,
- accent: 'default',
- isPinned: true,
- shouldBeRegistered: () => true,
- availableOn: [ActionViewType.INDEX_PAGE_NO_SELECTION],
- component: (
-
- ),
- },
- },
- actionKeys: [
- SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD,
- SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD,
- SingleRecordActionKeys.ADD_TO_FAVORITES,
- SingleRecordActionKeys.REMOVE_FROM_FAVORITES,
- SingleRecordActionKeys.EXPORT_FROM_RECORD_INDEX,
- SingleRecordActionKeys.EXPORT_FROM_RECORD_SHOW,
- MultipleRecordsActionKeys.EXPORT,
- NoSelectionRecordActionKeys.EXPORT_VIEW,
- NoSelectionRecordActionKeys.SEE_DELETED_RECORDS,
- NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS,
- NoSelectionRecordActionKeys.GO_TO_WORKFLOWS,
- NoSelectionRecordActionKeys.GO_TO_PEOPLE,
- NoSelectionRecordActionKeys.GO_TO_COMPANIES,
- NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES,
- NoSelectionRecordActionKeys.GO_TO_DASHBOARDS,
- NoSelectionRecordActionKeys.GO_TO_SETTINGS,
- NoSelectionRecordActionKeys.GO_TO_TASKS,
- NoSelectionRecordActionKeys.GO_TO_NOTES,
- ],
- propertiesToOverwrite: {
- [SingleRecordActionKeys.ADD_TO_FAVORITES]: {
- position: 5,
- isPinned: false,
- },
- [SingleRecordActionKeys.REMOVE_FROM_FAVORITES]: {
- position: 6,
- isPinned: false,
- },
- [SingleRecordActionKeys.EXPORT_FROM_RECORD_INDEX]: {
- position: 7,
- label: msg`Export version`,
- },
- [SingleRecordActionKeys.EXPORT_FROM_RECORD_SHOW]: {
- position: 7,
- label: msg`Export version`,
- },
- [MultipleRecordsActionKeys.EXPORT]: {
- position: 8,
- label: msg`Export versions`,
- },
- [NoSelectionRecordActionKeys.EXPORT_VIEW]: {
- position: 9,
- },
- [NoSelectionRecordActionKeys.SEE_DELETED_RECORDS]: {
- position: 10,
- },
- [NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS]: {
- position: 11,
- },
- [SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD]: {
- position: 12,
- label: msg`Navigate to previous version`,
- },
- [SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD]: {
- position: 13,
- label: msg`Navigate to next version`,
- },
- [NoSelectionRecordActionKeys.GO_TO_WORKFLOWS]: {
- position: 15,
- isPinned: true,
- },
- [NoSelectionRecordActionKeys.GO_TO_PEOPLE]: {
- position: 16,
- },
- [NoSelectionRecordActionKeys.GO_TO_COMPANIES]: {
- position: 17,
- },
- [NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES]: {
- position: 18,
- },
- [NoSelectionRecordActionKeys.GO_TO_DASHBOARDS]: {
- position: 19,
- },
- [NoSelectionRecordActionKeys.GO_TO_SETTINGS]: {
- position: 20,
- },
- [NoSelectionRecordActionKeys.GO_TO_TASKS]: {
- position: 21,
- },
- [NoSelectionRecordActionKeys.GO_TO_NOTES]: {
- position: 22,
- },
- },
- },
-);
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkspaceMembersActionsConfig.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkspaceMembersActionsConfig.tsx
deleted file mode 100644
index 91848304c0..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/constants/WorkspaceMembersActionsConfig.tsx
+++ /dev/null
@@ -1,123 +0,0 @@
-import { ActionLink } from '@/action-menu/actions/components/ActionLink';
-import { MultipleRecordsActionKeys } from '@/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys';
-import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys';
-import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey';
-import { inheritActionsFromDefaultConfig } from '@/action-menu/actions/record-actions/utils/inheritActionsFromDefaultConfig';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionType } from '@/action-menu/actions/types/ActionType';
-import { ActionViewType, AppPath, SettingsPath } from 'twenty-shared/types';
-import { msg } from '@lingui/core/macro';
-import { IconSettings } from 'twenty-ui/display';
-
-export const WORKSPACE_MEMBERS_ACTIONS_CONFIG = inheritActionsFromDefaultConfig(
- {
- config: {
- [NoSelectionRecordActionKeys.GO_TO_SETTINGS]: {
- type: ActionType.Navigation,
- scope: ActionScope.Global,
- key: NoSelectionRecordActionKeys.GO_TO_SETTINGS,
- label: msg`Manage members in settings`,
- shortLabel: msg`Manage in settings`,
- position: 14,
- Icon: IconSettings,
- isPinned: true,
- availableOn: [
- ActionViewType.INDEX_PAGE_NO_SELECTION,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.INDEX_PAGE_BULK_SELECTION,
- ActionViewType.SHOW_PAGE,
- ],
- shouldBeRegistered: () => true,
- component: (
-
- ),
- hotKeys: ['G', 'S'],
- },
- },
- actionKeys: [
- SingleRecordActionKeys.ADD_TO_FAVORITES,
- SingleRecordActionKeys.REMOVE_FROM_FAVORITES,
- SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD,
- SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD,
- SingleRecordActionKeys.EXPORT_FROM_RECORD_INDEX,
- SingleRecordActionKeys.EXPORT_FROM_RECORD_SHOW,
- MultipleRecordsActionKeys.EXPORT,
- NoSelectionRecordActionKeys.EXPORT_VIEW,
- NoSelectionRecordActionKeys.SEE_DELETED_RECORDS,
- NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS,
- NoSelectionRecordActionKeys.GO_TO_WORKFLOWS,
- NoSelectionRecordActionKeys.GO_TO_PEOPLE,
- NoSelectionRecordActionKeys.GO_TO_COMPANIES,
- NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES,
- NoSelectionRecordActionKeys.GO_TO_DASHBOARDS,
- NoSelectionRecordActionKeys.GO_TO_TASKS,
- NoSelectionRecordActionKeys.GO_TO_NOTES,
- ],
- propertiesToOverwrite: {
- [SingleRecordActionKeys.ADD_TO_FAVORITES]: {
- isPinned: false,
- position: 0,
- },
- [SingleRecordActionKeys.REMOVE_FROM_FAVORITES]: {
- isPinned: false,
- position: 1,
- },
- [SingleRecordActionKeys.EXPORT_FROM_RECORD_INDEX]: {
- position: 2,
- label: msg`Export member`,
- },
- [SingleRecordActionKeys.EXPORT_FROM_RECORD_SHOW]: {
- position: 2,
- label: msg`Export member`,
- },
- [MultipleRecordsActionKeys.EXPORT]: {
- position: 3,
- label: msg`Export members`,
- },
- [NoSelectionRecordActionKeys.EXPORT_VIEW]: {
- position: 4,
- label: msg`Export view`,
- },
- [NoSelectionRecordActionKeys.SEE_DELETED_RECORDS]: {
- position: 5,
- label: msg`See deleted members`,
- },
- [NoSelectionRecordActionKeys.HIDE_DELETED_RECORDS]: {
- position: 6,
- label: msg`Hide deleted members`,
- },
- [SingleRecordActionKeys.NAVIGATE_TO_PREVIOUS_RECORD]: {
- position: 7,
- },
- [SingleRecordActionKeys.NAVIGATE_TO_NEXT_RECORD]: {
- position: 8,
- },
- [NoSelectionRecordActionKeys.GO_TO_WORKFLOWS]: {
- position: 9,
- },
- [NoSelectionRecordActionKeys.GO_TO_PEOPLE]: {
- position: 10,
- },
- [NoSelectionRecordActionKeys.GO_TO_COMPANIES]: {
- position: 11,
- },
- [NoSelectionRecordActionKeys.GO_TO_OPPORTUNITIES]: {
- position: 12,
- },
- [NoSelectionRecordActionKeys.GO_TO_DASHBOARDS]: {
- position: 13,
- },
- [NoSelectionRecordActionKeys.GO_TO_TASKS]: {
- position: 15,
- },
- [NoSelectionRecordActionKeys.GO_TO_NOTES]: {
- position: 16,
- },
- },
- },
-);
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/workflow-actions/types/NoSelectionWorkflowRecordActionKeys.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/workflow-actions/types/NoSelectionWorkflowRecordActionKeys.ts
deleted file mode 100644
index aa128a112c..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/workflow-actions/types/NoSelectionWorkflowRecordActionKeys.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export enum NoSelectionWorkflowRecordActionKeys {
- GO_TO_RUNS = 'go-to-runs',
-}
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/utils/__tests__/inheritActionsFromDefaultConfig.test.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-actions/utils/__tests__/inheritActionsFromDefaultConfig.test.tsx
deleted file mode 100644
index cf38bbb621..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/utils/__tests__/inheritActionsFromDefaultConfig.test.tsx
+++ /dev/null
@@ -1,324 +0,0 @@
-import { DEFAULT_RECORD_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/DefaultRecordActionsConfig';
-import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys';
-import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey';
-import { type ActionConfig } from '@/action-menu/actions/types/ActionConfig';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionType } from '@/action-menu/actions/types/ActionType';
-import { type DefaultRecordActionConfigKeys } from '@/action-menu/actions/types/DefaultRecordActionConfigKeys';
-import { IconHeart, IconPlus } from 'twenty-ui/display';
-import { inheritActionsFromDefaultConfig } from '@/action-menu/actions/record-actions/utils/inheritActionsFromDefaultConfig';
-
-const MockComponent = Mock Component
;
-
-describe('inheritActionsFromDefaultConfig', () => {
- it('should return empty object when no action keys are provided', () => {
- const result = inheritActionsFromDefaultConfig({
- config: {},
- actionKeys: [],
- propertiesToOverwrite: {},
- });
-
- expect(result).toEqual({});
- });
-
- it('should return only provided config when no default action keys are specified', () => {
- const customConfig: Record = {
- 'custom-action': {
- type: ActionType.Standard,
- scope: ActionScope.Object,
- key: 'custom-action',
- label: 'Custom Action',
- position: 100,
- Icon: IconPlus,
- shouldBeRegistered: () => true,
- component: MockComponent,
- },
- };
-
- const result = inheritActionsFromDefaultConfig({
- config: customConfig,
- actionKeys: [],
- propertiesToOverwrite: {},
- });
-
- expect(result).toEqual(customConfig);
- });
-
- it('should inherit actions from default config', () => {
- const actionKeys: DefaultRecordActionConfigKeys[] = [
- NoSelectionRecordActionKeys.CREATE_NEW_RECORD,
- SingleRecordActionKeys.ADD_TO_FAVORITES,
- ];
-
- const result = inheritActionsFromDefaultConfig({
- config: {},
- actionKeys,
- propertiesToOverwrite: {},
- });
-
- expect(result).toEqual({
- [NoSelectionRecordActionKeys.CREATE_NEW_RECORD]:
- DEFAULT_RECORD_ACTIONS_CONFIG[
- NoSelectionRecordActionKeys.CREATE_NEW_RECORD
- ],
- [SingleRecordActionKeys.ADD_TO_FAVORITES]:
- DEFAULT_RECORD_ACTIONS_CONFIG[SingleRecordActionKeys.ADD_TO_FAVORITES],
- });
- });
-
- it('should overwrite specific properties of inherited actions', () => {
- const actionKeys: DefaultRecordActionConfigKeys[] = [
- NoSelectionRecordActionKeys.CREATE_NEW_RECORD,
- ];
-
- const propertiesToOverwrite = {
- [NoSelectionRecordActionKeys.CREATE_NEW_RECORD]: {
- label: 'Custom Create Label',
- position: 999,
- isPinned: false,
- },
- };
-
- const result = inheritActionsFromDefaultConfig({
- config: {},
- actionKeys,
- propertiesToOverwrite,
- });
-
- const expectedAction = {
- ...DEFAULT_RECORD_ACTIONS_CONFIG[
- NoSelectionRecordActionKeys.CREATE_NEW_RECORD
- ],
- label: 'Custom Create Label',
- position: 999,
- isPinned: false,
- };
-
- expect(result).toEqual({
- [NoSelectionRecordActionKeys.CREATE_NEW_RECORD]: expectedAction,
- });
- });
-
- it('should overwrite properties for multiple actions', () => {
- const actionKeys: DefaultRecordActionConfigKeys[] = [
- NoSelectionRecordActionKeys.CREATE_NEW_RECORD,
- SingleRecordActionKeys.ADD_TO_FAVORITES,
- ];
-
- const propertiesToOverwrite = {
- [NoSelectionRecordActionKeys.CREATE_NEW_RECORD]: {
- position: 10,
- },
- [SingleRecordActionKeys.ADD_TO_FAVORITES]: {
- label: 'Custom Favorite Label',
- Icon: IconHeart,
- },
- };
-
- const result = inheritActionsFromDefaultConfig({
- config: {},
- actionKeys,
- propertiesToOverwrite,
- });
-
- expect(result[NoSelectionRecordActionKeys.CREATE_NEW_RECORD]).toEqual({
- ...DEFAULT_RECORD_ACTIONS_CONFIG[
- NoSelectionRecordActionKeys.CREATE_NEW_RECORD
- ],
- position: 10,
- });
-
- expect(result[SingleRecordActionKeys.ADD_TO_FAVORITES]).toEqual({
- ...DEFAULT_RECORD_ACTIONS_CONFIG[SingleRecordActionKeys.ADD_TO_FAVORITES],
- label: 'Custom Favorite Label',
- Icon: IconHeart,
- });
- });
-
- it('should only overwrite properties for specified actions', () => {
- const actionKeys: DefaultRecordActionConfigKeys[] = [
- NoSelectionRecordActionKeys.CREATE_NEW_RECORD,
- SingleRecordActionKeys.ADD_TO_FAVORITES,
- ];
-
- const propertiesToOverwrite = {
- [NoSelectionRecordActionKeys.CREATE_NEW_RECORD]: {
- position: 10,
- },
- };
-
- const result = inheritActionsFromDefaultConfig({
- config: {},
- actionKeys,
- propertiesToOverwrite,
- });
-
- expect(result[NoSelectionRecordActionKeys.CREATE_NEW_RECORD]).toEqual({
- ...DEFAULT_RECORD_ACTIONS_CONFIG[
- NoSelectionRecordActionKeys.CREATE_NEW_RECORD
- ],
- position: 10,
- });
-
- expect(result[SingleRecordActionKeys.ADD_TO_FAVORITES]).toEqual(
- DEFAULT_RECORD_ACTIONS_CONFIG[SingleRecordActionKeys.ADD_TO_FAVORITES],
- );
- });
-
- it('should merge inherited actions with provided config', () => {
- const customConfig: Record = {
- 'custom-action': {
- type: ActionType.Standard,
- scope: ActionScope.Object,
- key: 'custom-action',
- label: 'Custom Action',
- position: 100,
- Icon: IconPlus,
- shouldBeRegistered: () => true,
- component: MockComponent,
- },
- };
-
- const actionKeys: DefaultRecordActionConfigKeys[] = [
- NoSelectionRecordActionKeys.CREATE_NEW_RECORD,
- ];
-
- const result = inheritActionsFromDefaultConfig({
- config: customConfig,
- actionKeys,
- propertiesToOverwrite: {},
- });
-
- expect(result).toEqual({
- [NoSelectionRecordActionKeys.CREATE_NEW_RECORD]:
- DEFAULT_RECORD_ACTIONS_CONFIG[
- NoSelectionRecordActionKeys.CREATE_NEW_RECORD
- ],
- 'custom-action': customConfig['custom-action'],
- });
- });
-
- it('should prioritize provided config over inherited actions when keys conflict', () => {
- const customConfig: Record = {
- [NoSelectionRecordActionKeys.CREATE_NEW_RECORD]: {
- type: ActionType.Standard,
- scope: ActionScope.Object,
- key: NoSelectionRecordActionKeys.CREATE_NEW_RECORD,
- label: 'Overridden Create Action',
- position: 999,
- Icon: IconHeart,
- shouldBeRegistered: () => false,
- component: MockComponent,
- },
- };
-
- const actionKeys: DefaultRecordActionConfigKeys[] = [
- NoSelectionRecordActionKeys.CREATE_NEW_RECORD,
- ];
-
- const result = inheritActionsFromDefaultConfig({
- config: customConfig,
- actionKeys,
- propertiesToOverwrite: {},
- });
-
- expect(result[NoSelectionRecordActionKeys.CREATE_NEW_RECORD]).toEqual(
- customConfig[NoSelectionRecordActionKeys.CREATE_NEW_RECORD],
- );
- expect(result[NoSelectionRecordActionKeys.CREATE_NEW_RECORD].label).toBe(
- 'Overridden Create Action',
- );
- });
-
- it('should handle complex scenario with inheritance, overrides, and custom config', () => {
- const customConfig: Record = {
- 'custom-action-1': {
- type: ActionType.Standard,
- scope: ActionScope.Object,
- key: 'custom-action-1',
- label: 'Custom Action 1',
- position: 50,
- Icon: IconPlus,
- shouldBeRegistered: () => true,
- component: MockComponent,
- },
- [SingleRecordActionKeys.ADD_TO_FAVORITES]: {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: SingleRecordActionKeys.ADD_TO_FAVORITES,
- label: 'Completely Custom Favorites',
- position: 1000,
- Icon: IconHeart,
- shouldBeRegistered: () => false,
- component: MockComponent,
- },
- };
-
- const actionKeys: DefaultRecordActionConfigKeys[] = [
- NoSelectionRecordActionKeys.CREATE_NEW_RECORD,
- SingleRecordActionKeys.ADD_TO_FAVORITES,
- SingleRecordActionKeys.REMOVE_FROM_FAVORITES,
- ];
-
- const propertiesToOverwrite = {
- [NoSelectionRecordActionKeys.CREATE_NEW_RECORD]: {
- label: 'Modified Create Label',
- position: 5,
- },
- [SingleRecordActionKeys.REMOVE_FROM_FAVORITES]: {
- isPinned: false,
- },
- };
-
- const result = inheritActionsFromDefaultConfig({
- config: customConfig,
- actionKeys,
- propertiesToOverwrite,
- });
-
- expect(Object.keys(result)).toHaveLength(4);
-
- expect(result['custom-action-1']).toEqual(customConfig['custom-action-1']);
-
- expect(result[NoSelectionRecordActionKeys.CREATE_NEW_RECORD]).toEqual({
- ...DEFAULT_RECORD_ACTIONS_CONFIG[
- NoSelectionRecordActionKeys.CREATE_NEW_RECORD
- ],
- label: 'Modified Create Label',
- position: 5,
- });
-
- expect(result[SingleRecordActionKeys.ADD_TO_FAVORITES]).toEqual(
- customConfig[SingleRecordActionKeys.ADD_TO_FAVORITES],
- );
-
- expect(result[SingleRecordActionKeys.REMOVE_FROM_FAVORITES]).toEqual({
- ...DEFAULT_RECORD_ACTIONS_CONFIG[
- SingleRecordActionKeys.REMOVE_FROM_FAVORITES
- ],
- isPinned: false,
- });
- });
-
- it('should handle empty overrides gracefully', () => {
- const actionKeys: DefaultRecordActionConfigKeys[] = [
- NoSelectionRecordActionKeys.CREATE_NEW_RECORD,
- ];
-
- const propertiesToOverwrite = {
- [NoSelectionRecordActionKeys.CREATE_NEW_RECORD]: {},
- };
-
- const result = inheritActionsFromDefaultConfig({
- config: {},
- actionKeys,
- propertiesToOverwrite,
- });
-
- expect(result[NoSelectionRecordActionKeys.CREATE_NEW_RECORD]).toEqual(
- DEFAULT_RECORD_ACTIONS_CONFIG[
- NoSelectionRecordActionKeys.CREATE_NEW_RECORD
- ],
- );
- });
-});
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/utils/inheritActionsFromDefaultConfig.ts b/packages/twenty-front/src/modules/action-menu/actions/record-actions/utils/inheritActionsFromDefaultConfig.ts
deleted file mode 100644
index 52f15c3b84..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/utils/inheritActionsFromDefaultConfig.ts
+++ /dev/null
@@ -1,31 +0,0 @@
-import { DEFAULT_RECORD_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/DefaultRecordActionsConfig';
-import { type ActionConfig } from '@/action-menu/actions/types/ActionConfig';
-import { type DefaultRecordActionConfigKeys } from '@/action-menu/actions/types/DefaultRecordActionConfigKeys';
-
-export const inheritActionsFromDefaultConfig = ({
- config,
- actionKeys,
- propertiesToOverwrite,
-}: {
- config: Record;
- actionKeys: DefaultRecordActionConfigKeys[];
- propertiesToOverwrite: Partial<
- Record>
- >;
-}): Record => {
- const actionsFromDefaultConfig = actionKeys.reduce(
- (acc, key) => ({
- ...acc,
- [key]: {
- ...DEFAULT_RECORD_ACTIONS_CONFIG[key],
- ...propertiesToOverwrite[key],
- },
- }),
- {} as Record,
- );
-
- return {
- ...actionsFromDefaultConfig,
- ...config,
- };
-};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/constants/RecordAgnosticActionsConfig.tsx b/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/constants/RecordAgnosticActionsConfig.tsx
deleted file mode 100644
index 796b5a704d..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/constants/RecordAgnosticActionsConfig.tsx
+++ /dev/null
@@ -1,114 +0,0 @@
-import { ActionOpenSidePanelPage } from '@/action-menu/actions/components/ActionOpenSidePanelPage';
-import { EditNavigationSidebarNoSelectionRecordAction } from '@/action-menu/actions/record-actions/no-selection/components/EditNavigationSidebarNoSelectionRecordAction';
-import { RecordAgnosticActionsKeys } from '@/action-menu/actions/record-agnostic-actions/types/RecordAgnosticActionsKeys';
-import { type ActionConfig } from '@/action-menu/actions/types/ActionConfig';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionType } from '@/action-menu/actions/types/ActionType';
-import { msg } from '@lingui/core/macro';
-import { ActionViewType, SidePanelPages } from 'twenty-shared/types';
-import {
- IconHistory,
- IconLayout,
- IconSearch,
- IconSparkles,
-} from 'twenty-ui/display';
-import { FeatureFlagKey } from '~/generated-metadata/graphql';
-
-export const RECORD_AGNOSTIC_ACTIONS_CONFIG: Record = {
- [RecordAgnosticActionsKeys.SEARCH_RECORDS]: {
- type: ActionType.Standard,
- scope: ActionScope.Global,
- key: RecordAgnosticActionsKeys.SEARCH_RECORDS,
- label: msg`Search records`,
- shortLabel: msg`Search`,
- position: 0,
- isPinned: false,
- Icon: IconSearch,
- availableOn: [ActionViewType.GLOBAL],
- component: (
-
- ),
- hotKeys: ['/'],
- shouldBeRegistered: () => true,
- },
- [RecordAgnosticActionsKeys.SEARCH_RECORDS_FALLBACK]: {
- type: ActionType.Fallback,
- scope: ActionScope.Global,
- key: RecordAgnosticActionsKeys.SEARCH_RECORDS_FALLBACK,
- label: msg`Search records`,
- shortLabel: msg`Search`,
- position: 1,
- isPinned: false,
- Icon: IconSearch,
- availableOn: [ActionViewType.GLOBAL],
- component: (
-
- ),
- hotKeys: ['/'],
- shouldBeRegistered: () => true,
- },
- [RecordAgnosticActionsKeys.ASK_AI]: {
- type: ActionType.Standard,
- scope: ActionScope.Global,
- key: RecordAgnosticActionsKeys.ASK_AI,
- label: msg`Ask AI`,
- shortLabel: msg`Ask AI`,
- position: 2,
- isPinned: false,
- Icon: IconSparkles,
- availableOn: [ActionViewType.GLOBAL],
- component: (
-
- ),
- hotKeys: ['@'],
- shouldBeRegistered: () => true,
- },
- [RecordAgnosticActionsKeys.VIEW_PREVIOUS_AI_CHATS]: {
- type: ActionType.Standard,
- scope: ActionScope.Global,
- key: RecordAgnosticActionsKeys.VIEW_PREVIOUS_AI_CHATS,
- label: msg`View Previous AI Chats`,
- shortLabel: msg`Previous AI Chats`,
- position: 3,
- isPinned: false,
- Icon: IconHistory,
- availableOn: [ActionViewType.GLOBAL],
- component: (
-
- ),
- shouldBeRegistered: () => true,
- },
- [RecordAgnosticActionsKeys.EDIT_NAVIGATION_SIDEBAR]: {
- type: ActionType.Navigation,
- scope: ActionScope.Global,
- key: RecordAgnosticActionsKeys.EDIT_NAVIGATION_SIDEBAR,
- label: msg`Edit navigation sidebar`,
- shortLabel: msg`Edit sidebar`,
- position: 4,
- Icon: IconLayout,
- isPinned: false,
- availableOn: [ActionViewType.GLOBAL],
- shouldBeRegistered: ({ isFeatureFlagEnabled }) =>
- isFeatureFlagEnabled(
- FeatureFlagKey.IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED,
- ),
- component: ,
- },
-};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/hooks/useRecordAgnosticActions.ts b/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/hooks/useRecordAgnosticActions.ts
deleted file mode 100644
index caa3c42359..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/hooks/useRecordAgnosticActions.ts
+++ /dev/null
@@ -1,33 +0,0 @@
-import { RECORD_AGNOSTIC_ACTIONS_CONFIG } from '@/action-menu/actions/record-agnostic-actions/constants/RecordAgnosticActionsConfig';
-import { RecordAgnosticActionsKeys } from '@/action-menu/actions/record-agnostic-actions/types/RecordAgnosticActionsKeys';
-import { type ActionConfig } from '@/action-menu/actions/types/ActionConfig';
-import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
-import { FeatureFlagKey } from '~/generated-metadata/graphql';
-
-export const useRecordAgnosticActions = () => {
- const isAiEnabled = useIsFeatureEnabled(FeatureFlagKey.IS_AI_ENABLED);
-
- const actions: Record = {
- [RecordAgnosticActionsKeys.SEARCH_RECORDS]:
- RECORD_AGNOSTIC_ACTIONS_CONFIG[RecordAgnosticActionsKeys.SEARCH_RECORDS],
- [RecordAgnosticActionsKeys.SEARCH_RECORDS_FALLBACK]:
- RECORD_AGNOSTIC_ACTIONS_CONFIG[
- RecordAgnosticActionsKeys.SEARCH_RECORDS_FALLBACK
- ],
- [RecordAgnosticActionsKeys.EDIT_NAVIGATION_SIDEBAR]:
- RECORD_AGNOSTIC_ACTIONS_CONFIG[
- RecordAgnosticActionsKeys.EDIT_NAVIGATION_SIDEBAR
- ],
- };
-
- if (isAiEnabled) {
- actions[RecordAgnosticActionsKeys.ASK_AI] =
- RECORD_AGNOSTIC_ACTIONS_CONFIG[RecordAgnosticActionsKeys.ASK_AI];
- actions[RecordAgnosticActionsKeys.VIEW_PREVIOUS_AI_CHATS] =
- RECORD_AGNOSTIC_ACTIONS_CONFIG[
- RecordAgnosticActionsKeys.VIEW_PREVIOUS_AI_CHATS
- ];
- }
-
- return actions;
-};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/types/DefaultRecordActionConfigKeys.ts b/packages/twenty-front/src/modules/action-menu/actions/types/DefaultRecordActionConfigKeys.ts
deleted file mode 100644
index f0fa7b8c5e..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/types/DefaultRecordActionConfigKeys.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-import { type MultipleRecordsActionKeys } from '@/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys';
-import { type NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys';
-import { type SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey';
-
-export type DefaultRecordActionConfigKeys =
- | NoSelectionRecordActionKeys
- | SingleRecordActionKeys
- | MultipleRecordsActionKeys;
diff --git a/packages/twenty-front/src/modules/action-menu/actions/utils/getActionConfig.ts b/packages/twenty-front/src/modules/action-menu/actions/utils/getActionConfig.ts
deleted file mode 100644
index 07e9a549b8..0000000000
--- a/packages/twenty-front/src/modules/action-menu/actions/utils/getActionConfig.ts
+++ /dev/null
@@ -1,44 +0,0 @@
-import { DASHBOARD_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/DashboardActionsConfig';
-import { DEFAULT_RECORD_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/DefaultRecordActionsConfig';
-import { WORKFLOW_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/WorkflowActionsConfig';
-import { WORKFLOW_RUNS_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/WorkflowRunsActionsConfig';
-import { WORKFLOW_VERSIONS_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/WorkflowVersionsActionsConfig';
-import { WORKSPACE_MEMBERS_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/WorkspaceMembersActionsConfig';
-import { type ActionConfig } from '@/action-menu/actions/types/ActionConfig';
-import { CoreObjectNameSingular } from 'twenty-shared/types';
-import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
-import { isDefined } from 'twenty-shared/utils';
-
-export const getActionConfig = ({
- objectMetadataItem,
-}: {
- objectMetadataItem?: ObjectMetadataItem;
-}): Record => {
- if (!isDefined(objectMetadataItem)) {
- return {};
- }
-
- switch (objectMetadataItem.nameSingular) {
- case CoreObjectNameSingular.Dashboard: {
- return DASHBOARD_ACTIONS_CONFIG;
- }
- case CoreObjectNameSingular.Workflow: {
- return WORKFLOW_ACTIONS_CONFIG;
- }
- case CoreObjectNameSingular.WorkflowVersion: {
- return WORKFLOW_VERSIONS_ACTIONS_CONFIG;
- }
- case CoreObjectNameSingular.WorkflowRun: {
- return WORKFLOW_RUNS_ACTIONS_CONFIG;
- }
- case CoreObjectNameSingular.WorkspaceMember: {
- return WORKSPACE_MEMBERS_ACTIONS_CONFIG;
- }
- case CoreObjectNameSingular.Company: {
- return DEFAULT_RECORD_ACTIONS_CONFIG;
- }
- default: {
- return DEFAULT_RECORD_ACTIONS_CONFIG;
- }
- }
-};
diff --git a/packages/twenty-front/src/modules/action-menu/components/CommandMenuActionMenuDropdown.tsx b/packages/twenty-front/src/modules/action-menu/components/CommandMenuActionMenuDropdown.tsx
deleted file mode 100644
index e4c8af8909..0000000000
--- a/packages/twenty-front/src/modules/action-menu/components/CommandMenuActionMenuDropdown.tsx
+++ /dev/null
@@ -1,39 +0,0 @@
-import { ActionComponent } from '@/action-menu/actions/display/components/ActionComponent';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
-import { getSidePanelActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getSidePanelActionMenuDropdownIdFromActionMenuId';
-import { OptionsDropdownMenu } from '@/ui/layout/dropdown/components/OptionsDropdownMenu';
-import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
-import { useContext } from 'react';
-
-export const CommandMenuActionMenuDropdown = () => {
- const { actions } = useContext(ActionMenuContext);
-
- const actionMenuId = useAvailableComponentInstanceIdOrThrow(
- ActionMenuComponentInstanceContext,
- );
-
- const dropdownId =
- getSidePanelActionMenuDropdownIdFromActionMenuId(actionMenuId);
-
- const recordSelectionActions = actions.filter(
- (action) => action.scope === ActionScope.RecordSelection,
- );
-
- const selectableItemIdArray = recordSelectionActions.map(
- (action) => action.key,
- );
-
- return (
-
- {recordSelectionActions.map((action) => (
-
- ))}
-
- );
-};
diff --git a/packages/twenty-front/src/modules/action-menu/confirmation-modal/components/ActionMenuConfirmationModalManager.tsx b/packages/twenty-front/src/modules/action-menu/confirmation-modal/components/ActionMenuConfirmationModalManager.tsx
deleted file mode 100644
index 34663df5d6..0000000000
--- a/packages/twenty-front/src/modules/action-menu/confirmation-modal/components/ActionMenuConfirmationModalManager.tsx
+++ /dev/null
@@ -1,67 +0,0 @@
-import { ACTION_MENU_CONFIRMATION_MODAL_RESULT_BROWSER_EVENT_NAME } from '@/action-menu/confirmation-modal/constants/ActionMenuConfirmationModalResultBrowserEventName';
-import { ACTION_MENU_CONFIRMATION_MODAL_INSTANCE_ID } from '@/action-menu/confirmation-modal/constants/ActionMenuConfirmationModalId';
-import { actionMenuConfirmationModalConfigState } from '@/action-menu/confirmation-modal/states/actionMenuConfirmationModalState';
-import {
- type ActionMenuConfirmationModalResult,
- type ActionMenuConfirmationModalResultBrowserEventDetail,
-} from '@/action-menu/confirmation-modal/types/ActionMenuConfirmationModalResultBrowserEventDetail';
-import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
-import { isModalOpenedComponentState } from '@/ui/layout/modal/states/isModalOpenedComponentState';
-import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
-import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
-import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
-
-export const ActionMenuConfirmationModalManager = () => {
- const actionMenuConfirmationModalConfig = useAtomStateValue(
- actionMenuConfirmationModalConfigState,
- );
- const isModalOpened = useAtomComponentStateValue(
- isModalOpenedComponentState,
- ACTION_MENU_CONFIRMATION_MODAL_INSTANCE_ID,
- );
- const setActionMenuConfirmationModalConfig = useSetAtomState(
- actionMenuConfirmationModalConfigState,
- );
-
- const callerId = actionMenuConfirmationModalConfig?.frontComponentId;
-
- const emitConfirmationResult = (
- confirmationResult: ActionMenuConfirmationModalResult,
- ) => {
- if (!callerId) {
- return;
- }
-
- window.dispatchEvent(
- new CustomEvent(
- ACTION_MENU_CONFIRMATION_MODAL_RESULT_BROWSER_EVENT_NAME,
- {
- detail: {
- frontComponentId: callerId,
- confirmationResult,
- },
- },
- ),
- );
-
- setActionMenuConfirmationModalConfig(null);
- };
-
- if (!actionMenuConfirmationModalConfig || !isModalOpened) {
- return null;
- }
-
- return (
- emitConfirmationResult('confirm')}
- onClose={() => emitConfirmationResult('cancel')}
- confirmButtonText={actionMenuConfirmationModalConfig.confirmButtonText}
- confirmButtonAccent={
- actionMenuConfirmationModalConfig.confirmButtonAccent
- }
- />
- );
-};
diff --git a/packages/twenty-front/src/modules/action-menu/confirmation-modal/constants/ActionMenuConfirmationModalId.ts b/packages/twenty-front/src/modules/action-menu/confirmation-modal/constants/ActionMenuConfirmationModalId.ts
deleted file mode 100644
index 069ceccf76..0000000000
--- a/packages/twenty-front/src/modules/action-menu/confirmation-modal/constants/ActionMenuConfirmationModalId.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export const ACTION_MENU_CONFIRMATION_MODAL_INSTANCE_ID =
- 'action-menu-confirmation-modal';
diff --git a/packages/twenty-front/src/modules/action-menu/confirmation-modal/constants/ActionMenuConfirmationModalResultBrowserEventName.ts b/packages/twenty-front/src/modules/action-menu/confirmation-modal/constants/ActionMenuConfirmationModalResultBrowserEventName.ts
deleted file mode 100644
index 1cead0f741..0000000000
--- a/packages/twenty-front/src/modules/action-menu/confirmation-modal/constants/ActionMenuConfirmationModalResultBrowserEventName.ts
+++ /dev/null
@@ -1,2 +0,0 @@
-export const ACTION_MENU_CONFIRMATION_MODAL_RESULT_BROWSER_EVENT_NAME =
- 'action-menu-confirmation-modal-result';
diff --git a/packages/twenty-front/src/modules/action-menu/confirmation-modal/hooks/useActionMenuConfirmationModal.ts b/packages/twenty-front/src/modules/action-menu/confirmation-modal/hooks/useActionMenuConfirmationModal.ts
deleted file mode 100644
index 578c4e9b0e..0000000000
--- a/packages/twenty-front/src/modules/action-menu/confirmation-modal/hooks/useActionMenuConfirmationModal.ts
+++ /dev/null
@@ -1,48 +0,0 @@
-import { useStore } from 'jotai';
-import { useCallback } from 'react';
-
-import { ACTION_MENU_CONFIRMATION_MODAL_INSTANCE_ID } from '@/action-menu/confirmation-modal/constants/ActionMenuConfirmationModalId';
-import {
- type ActionMenuConfirmationModalConfig,
- actionMenuConfirmationModalConfigState,
-} from '@/action-menu/confirmation-modal/states/actionMenuConfirmationModalState';
-import { useModal } from '@/ui/layout/modal/hooks/useModal';
-import { isModalOpenedComponentState } from '@/ui/layout/modal/states/isModalOpenedComponentState';
-import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
-
-export const useActionMenuConfirmationModal = () => {
- const store = useStore();
- const setActionMenuConfirmationModalConfig = useSetAtomState(
- actionMenuConfirmationModalConfigState,
- );
- const { openModal } = useModal();
-
- const openConfirmationModal = useCallback(
- (config: ActionMenuConfirmationModalConfig) => {
- const existingActionMenuConfirmationModalConfig = store.get(
- actionMenuConfirmationModalConfigState.atom,
- );
- const isActionMenuConfirmationModalOpened = store.get(
- isModalOpenedComponentState.atomFamily({
- instanceId: ACTION_MENU_CONFIRMATION_MODAL_INSTANCE_ID,
- }),
- );
-
- if (
- existingActionMenuConfirmationModalConfig !== null ||
- isActionMenuConfirmationModalOpened
- ) {
- throw new Error(
- 'Action menu confirmation modal is already active for another front component',
- );
- }
-
- setActionMenuConfirmationModalConfig(config);
-
- openModal(ACTION_MENU_CONFIRMATION_MODAL_INSTANCE_ID);
- },
- [store, setActionMenuConfirmationModalConfig, openModal],
- );
-
- return { openConfirmationModal };
-};
diff --git a/packages/twenty-front/src/modules/action-menu/confirmation-modal/types/ActionMenuConfirmationModalResultBrowserEventDetail.ts b/packages/twenty-front/src/modules/action-menu/confirmation-modal/types/ActionMenuConfirmationModalResultBrowserEventDetail.ts
deleted file mode 100644
index 3b6ff2217b..0000000000
--- a/packages/twenty-front/src/modules/action-menu/confirmation-modal/types/ActionMenuConfirmationModalResultBrowserEventDetail.ts
+++ /dev/null
@@ -1,6 +0,0 @@
-export type ActionMenuConfirmationModalResult = 'confirm' | 'cancel';
-
-export type ActionMenuConfirmationModalResultBrowserEventDetail = {
- frontComponentId: string;
- confirmationResult: ActionMenuConfirmationModalResult;
-};
diff --git a/packages/twenty-front/src/modules/action-menu/constants/ActionMenuDropdownClickOutsideId.ts b/packages/twenty-front/src/modules/action-menu/constants/ActionMenuDropdownClickOutsideId.ts
deleted file mode 100644
index 86789f2623..0000000000
--- a/packages/twenty-front/src/modules/action-menu/constants/ActionMenuDropdownClickOutsideId.ts
+++ /dev/null
@@ -1 +0,0 @@
-export const ACTION_MENU_DROPDOWN_CLICK_OUTSIDE_ID = 'action-menu-dropdown';
diff --git a/packages/twenty-front/src/modules/action-menu/contexts/ActionConfigContext.tsx b/packages/twenty-front/src/modules/action-menu/contexts/ActionConfigContext.tsx
deleted file mode 100644
index 72930c436b..0000000000
--- a/packages/twenty-front/src/modules/action-menu/contexts/ActionConfigContext.tsx
+++ /dev/null
@@ -1,4 +0,0 @@
-import { type ActionConfig } from '@/action-menu/actions/types/ActionConfig';
-import { createContext } from 'react';
-
-export const ActionConfigContext = createContext(null);
diff --git a/packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContext.ts b/packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContext.ts
deleted file mode 100644
index 1f843e63a1..0000000000
--- a/packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContext.ts
+++ /dev/null
@@ -1,21 +0,0 @@
-import { type ActionConfig } from '@/action-menu/actions/types/ActionConfig';
-import { createContext } from 'react';
-
-export type ActionMenuContextType = {
- isInSidePanel: boolean;
- displayType: 'button' | 'listItem' | 'dropdownItem';
- actionMenuType:
- | 'command-menu'
- | 'show-page-action-menu'
- | 'index-page-action-menu'
- | 'index-page-action-menu-dropdown'
- | 'command-menu-show-page-action-menu-dropdown';
- actions: ActionConfig[];
-};
-
-export const ActionMenuContext = createContext({
- isInSidePanel: false,
- actionMenuType: 'command-menu',
- displayType: 'button',
- actions: [],
-});
diff --git a/packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContextProviderDefault.tsx b/packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContextProviderDefault.tsx
deleted file mode 100644
index 46e65e3fa8..0000000000
--- a/packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContextProviderDefault.tsx
+++ /dev/null
@@ -1,76 +0,0 @@
-import { useRunWorkflowRecordActions } from '@/action-menu/actions/record-actions/run-workflow-actions/hooks/useRunWorkflowRecordActions';
-import { useRunWorkflowRecordAgnosticActions } from '@/action-menu/actions/record-agnostic-actions/run-workflow-actions/hooks/useRunWorkflowRecordAgnosticActions';
-import {
- ActionMenuContext,
- type ActionMenuContextType,
-} from '@/action-menu/contexts/ActionMenuContext';
-import { useRegisteredActions } from '@/action-menu/hooks/useRegisteredActions';
-import { useShouldActionBeRegisteredParams } from '@/action-menu/hooks/useShouldActionBeRegisteredParams';
-import { useCommandMenuContextApi } from '@/action-menu/hooks/useCommandMenuContextApi';
-import { useCommandMenuItemFrontComponentActions } from '@/command-menu-item/hooks/useCommandMenuItemFrontComponentActions';
-import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
-import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
-import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
-
-export const ActionMenuContextProviderDefault = ({
- objectMetadataItem,
- isInSidePanel,
- displayType,
- actionMenuType,
- children,
-}: {
- objectMetadataItem: ObjectMetadataItem;
- isInSidePanel: ActionMenuContextType['isInSidePanel'];
- displayType: ActionMenuContextType['displayType'];
- actionMenuType: ActionMenuContextType['actionMenuType'];
- children: React.ReactNode;
-}) => {
- const params = useShouldActionBeRegisteredParams({
- objectMetadataItem,
- });
-
- const shouldBeRegisteredParams = {
- ...params,
- };
-
- const actions = useRegisteredActions(shouldBeRegisteredParams);
-
- const contextStoreTargetedRecordsRule = useAtomComponentStateValue(
- contextStoreTargetedRecordsRuleComponentState,
- );
-
- const isRecordSelection =
- contextStoreTargetedRecordsRule.mode === 'selection' &&
- contextStoreTargetedRecordsRule.selectedRecordIds.length > 0;
-
- const runWorkflowRecordActions = useRunWorkflowRecordActions({
- objectMetadataItem,
- skip: !isRecordSelection,
- });
-
- const runWorkflowRecordAgnosticActions =
- useRunWorkflowRecordAgnosticActions();
-
- const commandMenuContextApi = useCommandMenuContextApi();
-
- const commandMenuItemFrontComponentActions =
- useCommandMenuItemFrontComponentActions(commandMenuContextApi);
-
- return (
-
- {children}
-
- );
-};
diff --git a/packages/twenty-front/src/modules/action-menu/hooks/useCloseActionMenu.ts b/packages/twenty-front/src/modules/action-menu/hooks/useCloseActionMenu.ts
deleted file mode 100644
index aa0da34fd1..0000000000
--- a/packages/twenty-front/src/modules/action-menu/hooks/useCloseActionMenu.ts
+++ /dev/null
@@ -1,60 +0,0 @@
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
-import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
-import { getSidePanelActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getSidePanelActionMenuDropdownIdFromActionMenuId';
-import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
-import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
-import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
-import { useContext } from 'react';
-import { isDefined } from 'twenty-shared/utils';
-
-export const useCloseActionMenu = ({
- closeSidePanelOnShowPageOptionsActionExecution = false,
- closeSidePanelOnCommandMenuListActionExecution = true,
-}: {
- closeSidePanelOnShowPageOptionsActionExecution?: boolean;
- closeSidePanelOnCommandMenuListActionExecution?: boolean;
-} = {}) => {
- const { actionMenuType, isInSidePanel } = useContext(ActionMenuContext);
-
- const { closeSidePanelMenu } = useSidePanelMenu();
-
- const { closeDropdown } = useCloseDropdown();
-
- const actionMenuId = useAvailableComponentInstanceIdOrThrow(
- ActionMenuComponentInstanceContext,
- );
-
- const dropdownId = isInSidePanel
- ? getSidePanelActionMenuDropdownIdFromActionMenuId(actionMenuId)
- : getActionMenuDropdownIdFromActionMenuId(actionMenuId);
-
- const closeActionMenu = () => {
- if (actionMenuType === 'command-menu') {
- if (
- isDefined(closeSidePanelOnCommandMenuListActionExecution) &&
- !closeSidePanelOnCommandMenuListActionExecution
- ) {
- return;
- }
- closeSidePanelMenu();
- }
-
- if (
- actionMenuType === 'index-page-action-menu-dropdown' ||
- actionMenuType === 'command-menu-show-page-action-menu-dropdown'
- ) {
- closeDropdown(dropdownId);
- }
-
- if (
- actionMenuType === 'command-menu-show-page-action-menu-dropdown' &&
- isDefined(closeSidePanelOnShowPageOptionsActionExecution) &&
- closeSidePanelOnShowPageOptionsActionExecution
- ) {
- closeSidePanelMenu();
- }
- };
-
- return { closeActionMenu };
-};
diff --git a/packages/twenty-front/src/modules/action-menu/hooks/useRegisteredActions.ts b/packages/twenty-front/src/modules/action-menu/hooks/useRegisteredActions.ts
deleted file mode 100644
index 0ca2023b28..0000000000
--- a/packages/twenty-front/src/modules/action-menu/hooks/useRegisteredActions.ts
+++ /dev/null
@@ -1,90 +0,0 @@
-import { useRecordAgnosticActions } from '@/action-menu/actions/record-agnostic-actions/hooks/useRecordAgnosticActions';
-import { useRelatedRecordActions } from '@/action-menu/actions/record-agnostic-actions/hooks/useRelatedRecordActions';
-import { ActionViewType } from 'twenty-shared/types';
-import { type ShouldBeRegisteredFunctionParams } from '@/action-menu/actions/types/ShouldBeRegisteredFunctionParams';
-import { getActionConfig } from '@/action-menu/actions/utils/getActionConfig';
-import { getActionViewType } from '@/action-menu/actions/utils/getActionViewType';
-import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
-import { contextStoreIsPageInEditModeComponentState } from '@/context-store/states/contextStoreIsPageInEditModeComponentState';
-import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
-import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap';
-import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
-import { isDefined } from 'twenty-shared/utils';
-import { useIcons } from 'twenty-ui/display';
-
-export const useRegisteredActions = (
- shouldBeRegisteredParams: ShouldBeRegisteredFunctionParams,
-) => {
- const { objectMetadataItem } = shouldBeRegisteredParams;
-
- const { getIcon } = useIcons();
-
- const contextStoreTargetedRecordsRule = useAtomComponentStateValue(
- contextStoreTargetedRecordsRuleComponentState,
- );
-
- const contextStoreCurrentViewType = useAtomComponentStateValue(
- contextStoreCurrentViewTypeComponentState,
- );
-
- const contextStoreIsPageInEditMode = useAtomComponentStateValue(
- contextStoreIsPageInEditModeComponentState,
- );
-
- const viewType = getActionViewType(
- contextStoreCurrentViewType,
- contextStoreTargetedRecordsRule,
- );
-
- const recordActionConfig = getActionConfig({
- objectMetadataItem,
- });
-
- const relatedRecordActionConfig = useRelatedRecordActions({
- sourceObjectMetadataItem: objectMetadataItem,
- getIcon,
- startPosition: Object.keys(recordActionConfig).length + 1,
- });
-
- const recordAgnosticActionConfig = useRecordAgnosticActions();
-
- const actionsConfig = {
- ...recordActionConfig,
- ...relatedRecordActionConfig,
- ...recordAgnosticActionConfig,
- };
-
- const permissionMap = usePermissionFlagMap();
-
- const actionsToRegister = Object.values(actionsConfig).filter((action) => {
- if (contextStoreIsPageInEditMode) {
- return (
- isDefined(action.availableOn) &&
- action.availableOn.includes(ActionViewType.PAGE_EDIT_MODE)
- );
- }
-
- if (isDefined(viewType)) {
- return (
- action.availableOn?.includes(viewType) ||
- action.availableOn?.includes(ActionViewType.GLOBAL)
- );
- }
-
- return action.availableOn?.includes(ActionViewType.GLOBAL);
- });
-
- const actions = actionsToRegister
- .filter((action) => {
- if (
- isDefined(action.requiredPermissionFlag) &&
- !permissionMap[action.requiredPermissionFlag]
- ) {
- return false;
- }
- return action.shouldBeRegistered(shouldBeRegisteredParams);
- })
- .sort((a, b) => a.position - b.position);
-
- return actions;
-};
diff --git a/packages/twenty-front/src/modules/action-menu/mock/action-menu-actions.mock.tsx b/packages/twenty-front/src/modules/action-menu/mock/action-menu-actions.mock.tsx
deleted file mode 100644
index a467ee63fb..0000000000
--- a/packages/twenty-front/src/modules/action-menu/mock/action-menu-actions.mock.tsx
+++ /dev/null
@@ -1,104 +0,0 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { ActionLink } from '@/action-menu/actions/components/ActionLink';
-import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys';
-import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey';
-import { type ActionConfig } from '@/action-menu/actions/types/ActionConfig';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionType } from '@/action-menu/actions/types/ActionType';
-import {
- ActionViewType,
- CoreObjectNameSingular,
- AppPath,
-} from 'twenty-shared/types';
-import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
-import { msg } from '@lingui/core/macro';
-import {
- IconFileExport,
- IconHeart,
- IconTrash,
- IconUser,
-} from 'twenty-ui/display';
-
-export const createMockActionMenuActions = ({
- deleteMock = () => {},
- addToFavoritesMock = () => {},
- exportMock = () => {},
-}: {
- deleteMock?: () => void;
- addToFavoritesMock?: () => void;
- exportMock?: () => void;
-}): ActionConfig[] => [
- {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: SingleRecordActionKeys.ADD_TO_FAVORITES,
- label: msg`Add to favorites`,
- shortLabel: msg`Add to favorites`,
- position: 2,
- isPinned: true,
- Icon: IconHeart,
- shouldBeRegistered: () => true,
- availableOn: [
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.SHOW_PAGE,
- ],
- component: ,
- },
- {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: SingleRecordActionKeys.EXPORT_FROM_RECORD_INDEX,
- label: msg`Export`,
- shortLabel: msg`Export`,
- position: 4,
- Icon: IconFileExport,
- accent: 'default',
- isPinned: false,
- shouldBeRegistered: () => true,
- availableOn: [ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION],
- component: ,
- },
- {
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
- key: SingleRecordActionKeys.DELETE,
- label: msg`Delete`,
- shortLabel: msg`Delete`,
- position: 7,
- Icon: IconTrash,
- accent: 'default',
- isPinned: true,
- shouldBeRegistered: () => true,
- availableOn: [
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.SHOW_PAGE,
- ],
- component: ,
- },
- {
- type: ActionType.Navigation,
- scope: ActionScope.Global,
- key: NoSelectionRecordActionKeys.GO_TO_PEOPLE,
- label: msg`Go to People`,
- shortLabel: msg`People`,
- position: 19,
- Icon: IconUser,
- isPinned: false,
- availableOn: [
- ActionViewType.INDEX_PAGE_NO_SELECTION,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
- ActionViewType.INDEX_PAGE_BULK_SELECTION,
- ActionViewType.SHOW_PAGE,
- ],
- shouldBeRegistered: ({ objectMetadataItem, viewType }) =>
- objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Person ||
- viewType === ActionViewType.SHOW_PAGE,
- component: (
-
- ),
- hotKeys: ['G', 'P'],
- },
-];
diff --git a/packages/twenty-front/src/modules/action-menu/states/recordIndexActionMenuDropdownPositionComponentState.ts b/packages/twenty-front/src/modules/action-menu/states/recordIndexActionMenuDropdownPositionComponentState.ts
deleted file mode 100644
index d0e471d94f..0000000000
--- a/packages/twenty-front/src/modules/action-menu/states/recordIndexActionMenuDropdownPositionComponentState.ts
+++ /dev/null
@@ -1,13 +0,0 @@
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
-import { type PositionType } from '@/action-menu/types/PositionType';
-import { createAtomComponentState } from '@/ui/utilities/state/jotai/utils/createAtomComponentState';
-
-export const recordIndexActionMenuDropdownPositionComponentState =
- createAtomComponentState({
- key: 'recordIndexActionMenuDropdownPositionComponentState',
- defaultValue: {
- x: null,
- y: null,
- },
- componentInstanceContext: ActionMenuComponentInstanceContext,
- });
diff --git a/packages/twenty-front/src/modules/action-menu/utils/__tests__/getActionMenuDropdownIdFromActionMenuId.test.ts b/packages/twenty-front/src/modules/action-menu/utils/__tests__/getActionMenuDropdownIdFromActionMenuId.test.ts
deleted file mode 100644
index 55fdebed48..0000000000
--- a/packages/twenty-front/src/modules/action-menu/utils/__tests__/getActionMenuDropdownIdFromActionMenuId.test.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
-
-describe('getActionMenuDropdownIdFromActionMenuId', () => {
- it('should return the correct action menu dropdown id', () => {
- expect(getActionMenuDropdownIdFromActionMenuId('action-menu-id')).toBe(
- 'action-menu-dropdown-action-menu-id',
- );
- });
-});
diff --git a/packages/twenty-front/src/modules/action-menu/utils/__tests__/getActionMenuIdFromRecordIndexId.test.ts b/packages/twenty-front/src/modules/action-menu/utils/__tests__/getActionMenuIdFromRecordIndexId.test.ts
deleted file mode 100644
index ff547aa6d6..0000000000
--- a/packages/twenty-front/src/modules/action-menu/utils/__tests__/getActionMenuIdFromRecordIndexId.test.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
-
-describe('getActionMenuIdFromRecordIndexId', () => {
- it('should return the correct action menu id', () => {
- expect(getActionMenuIdFromRecordIndexId('record-index-id')).toBe(
- 'action-menu-record-index-record-index-id',
- );
- });
-});
diff --git a/packages/twenty-front/src/modules/action-menu/utils/__tests__/getSidePanelActionMenuDropdownIdFromActionMenuId.test.ts b/packages/twenty-front/src/modules/action-menu/utils/__tests__/getSidePanelActionMenuDropdownIdFromActionMenuId.test.ts
deleted file mode 100644
index 32b6fdf644..0000000000
--- a/packages/twenty-front/src/modules/action-menu/utils/__tests__/getSidePanelActionMenuDropdownIdFromActionMenuId.test.ts
+++ /dev/null
@@ -1,9 +0,0 @@
-import { getSidePanelActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getSidePanelActionMenuDropdownIdFromActionMenuId';
-
-describe('getSidePanelActionMenuDropdownIdFromActionMenuId', () => {
- it('should return the side panel action menu dropdown id', () => {
- expect(
- getSidePanelActionMenuDropdownIdFromActionMenuId('action-menu-id'),
- ).toBe('side-panel-action-menu-dropdown-action-menu-id');
- });
-});
diff --git a/packages/twenty-front/src/modules/action-menu/utils/getActionMenuDropdownIdFromActionMenuId.ts b/packages/twenty-front/src/modules/action-menu/utils/getActionMenuDropdownIdFromActionMenuId.ts
deleted file mode 100644
index 40b21dbe6c..0000000000
--- a/packages/twenty-front/src/modules/action-menu/utils/getActionMenuDropdownIdFromActionMenuId.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export const getActionMenuDropdownIdFromActionMenuId = (
- actionMenuId: string,
-) => {
- return `action-menu-dropdown-${actionMenuId}`;
-};
diff --git a/packages/twenty-front/src/modules/action-menu/utils/getActionMenuIdFromRecordIndexId.ts b/packages/twenty-front/src/modules/action-menu/utils/getActionMenuIdFromRecordIndexId.ts
deleted file mode 100644
index 883beab4fd..0000000000
--- a/packages/twenty-front/src/modules/action-menu/utils/getActionMenuIdFromRecordIndexId.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export const getActionMenuIdFromRecordIndexId = (recordIndexId: string) => {
- return `action-menu-record-index-${recordIndexId}`;
-};
diff --git a/packages/twenty-front/src/modules/action-menu/utils/getSidePanelActionMenuDropdownIdFromActionMenuId.ts b/packages/twenty-front/src/modules/action-menu/utils/getSidePanelActionMenuDropdownIdFromActionMenuId.ts
deleted file mode 100644
index bde04a52a3..0000000000
--- a/packages/twenty-front/src/modules/action-menu/utils/getSidePanelActionMenuDropdownIdFromActionMenuId.ts
+++ /dev/null
@@ -1,5 +0,0 @@
-export const getSidePanelActionMenuDropdownIdFromActionMenuId = (
- actionMenuId: string,
-) => {
- return `side-panel-action-menu-dropdown-${actionMenuId}`;
-};
diff --git a/packages/twenty-front/src/modules/app/components/AppRouterProviders.tsx b/packages/twenty-front/src/modules/app/components/AppRouterProviders.tsx
index c844351ed0..229610887c 100644
--- a/packages/twenty-front/src/modules/app/components/AppRouterProviders.tsx
+++ b/packages/twenty-front/src/modules/app/components/AppRouterProviders.tsx
@@ -1,5 +1,5 @@
import { AgentChatProvider } from '@/ai/components/AgentChatProvider';
-import { ActionMenuConfirmationModalManager } from '@/action-menu/confirmation-modal/components/ActionMenuConfirmationModalManager';
+import { CommandMenuConfirmationModalManager } from '@/command-menu-item/confirmation-modal/components/CommandMenuConfirmationModalManager';
import { ApolloProvider } from '@/apollo/components/ApolloProvider';
import { MetadataGater } from '@/metadata-store/components/MetadataGater';
import { IsAppMetadataReadyEffect } from '@/metadata-store/effect-components/IsAppMetadataReadyEffect';
@@ -72,7 +72,7 @@ export const AppRouterProviders = () => {
-
+
diff --git a/packages/twenty-front/src/modules/action-menu/components/PageHeaderActionMenuButtons.tsx b/packages/twenty-front/src/modules/command-menu-item/components/PageHeaderCommandMenuButtons.tsx
similarity index 68%
rename from packages/twenty-front/src/modules/action-menu/components/PageHeaderActionMenuButtons.tsx
rename to packages/twenty-front/src/modules/command-menu-item/components/PageHeaderCommandMenuButtons.tsx
index 8150264d7e..d621bf4539 100644
--- a/packages/twenty-front/src/modules/action-menu/components/PageHeaderActionMenuButtons.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/components/PageHeaderCommandMenuButtons.tsx
@@ -1,5 +1,5 @@
-import { ActionComponent } from '@/action-menu/actions/display/components/ActionComponent';
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
+import { CommandMenuItemComponent } from '@/command-menu-item/display/components/CommandMenuItemComponent';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
import { styled } from '@linaria/react';
import { motion } from 'framer-motion';
import { useContext } from 'react';
@@ -11,10 +11,12 @@ const StyledActionContainer = styled(motion.div)`
justify-content: center;
`;
-export const PageHeaderActionMenuButtons = () => {
+export const PageHeaderCommandMenuButtons = () => {
const { theme } = useContext(ThemeContext);
- const { actions } = useContext(ActionMenuContext);
- const pinnedActions = actions.filter((entry) => entry.isPinned).toReversed();
+ const { commandMenuItems } = useContext(CommandMenuContext);
+ const pinnedActions = commandMenuItems
+ .filter((entry) => entry.isPinned)
+ .toReversed();
const actionsWithPositionForAnimation = pinnedActions.map(
(action, index) => ({
@@ -37,7 +39,7 @@ export const PageHeaderActionMenuButtons = () => {
ease: 'easeInOut',
}}
>
-
+
))}
>
diff --git a/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx b/packages/twenty-front/src/modules/command-menu-item/components/RecordIndexCommandMenu.tsx
similarity index 55%
rename from packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx
rename to packages/twenty-front/src/modules/command-menu-item/components/RecordIndexCommandMenu.tsx
index 539fec5a11..af91dd07ee 100644
--- a/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenu.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/components/RecordIndexCommandMenu.tsx
@@ -1,12 +1,12 @@
-import { PageHeaderActionMenuButtons } from '@/action-menu/components/PageHeaderActionMenuButtons';
-import { RecordIndexActionMenuDropdown } from '@/action-menu/components/RecordIndexActionMenuDropdown';
-import { ActionMenuContextProvider } from '@/action-menu/contexts/ActionMenuContextProvider';
+import { PageHeaderCommandMenuButtons } from '@/command-menu-item/components/PageHeaderCommandMenuButtons';
+import { RecordIndexCommandMenuDropdown } from '@/command-menu-item/components/RecordIndexCommandMenuDropdown';
+import { CommandMenuContextProvider } from '@/command-menu-item/contexts/CommandMenuContextProvider';
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
import { useIsMobile } from 'twenty-ui/utilities';
-export const RecordIndexActionMenu = () => {
+export const RecordIndexCommandMenu = () => {
const contextStoreCurrentObjectMetadataItemId = useAtomComponentStateValue(
contextStoreCurrentObjectMetadataItemIdComponentState,
MAIN_CONTEXT_STORE_INSTANCE_ID,
@@ -18,20 +18,20 @@ export const RecordIndexActionMenu = () => {
<>
{contextStoreCurrentObjectMetadataItemId && (
<>
-
- {!isMobile && }
-
- }
+
+
-
-
+
+
>
)}
>
diff --git a/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenuDropdown.tsx b/packages/twenty-front/src/modules/command-menu-item/components/RecordIndexCommandMenuDropdown.tsx
similarity index 64%
rename from packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenuDropdown.tsx
rename to packages/twenty-front/src/modules/command-menu-item/components/RecordIndexCommandMenuDropdown.tsx
index 2a788c73e5..c7453f32e2 100644
--- a/packages/twenty-front/src/modules/action-menu/components/RecordIndexActionMenuDropdown.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/components/RecordIndexCommandMenuDropdown.tsx
@@ -1,11 +1,11 @@
-import { ActionComponent } from '@/action-menu/actions/display/components/ActionComponent';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionType } from '@/action-menu/actions/types/ActionType';
-import { ACTION_MENU_DROPDOWN_CLICK_OUTSIDE_ID } from '@/action-menu/constants/ActionMenuDropdownClickOutsideId';
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
-import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-menu/states/recordIndexActionMenuDropdownPositionComponentState';
-import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
+import { CommandMenuItemComponent } from '@/command-menu-item/display/components/CommandMenuItemComponent';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
+import { COMMAND_MENU_DROPDOWN_CLICK_OUTSIDE_ID } from '@/command-menu-item/constants/CommandMenuDropdownClickOutsideId';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
+import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
+import { recordIndexCommandMenuDropdownPositionComponentState } from '@/command-menu-item/states/recordIndexCommandMenuDropdownPositionComponentState';
+import { getCommandMenuDropdownIdFromCommandMenuId } from '@/command-menu-item/utils/getCommandMenuDropdownIdFromCommandMenuId';
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
@@ -32,25 +32,25 @@ const StyledDropdownMenuContainer = styled.div`
width: 100%;
`;
-export const RecordIndexActionMenuDropdown = () => {
+export const RecordIndexCommandMenuDropdown = () => {
const { t } = useLingui();
- const { actions } = useContext(ActionMenuContext);
+ const { commandMenuItems } = useContext(CommandMenuContext);
- const recordIndexActions = actions.filter(
+ const recordIndexActions = commandMenuItems.filter(
(action) =>
- action.type === ActionType.Standard &&
- action.scope === ActionScope.RecordSelection,
+ action.type === CommandMenuItemType.Standard &&
+ action.scope === CommandMenuItemScope.RecordSelection,
);
- const actionMenuId = useAvailableComponentInstanceIdOrThrow(
- ActionMenuComponentInstanceContext,
+ const commandMenuId = useAvailableComponentInstanceIdOrThrow(
+ CommandMenuComponentInstanceContext,
);
- const dropdownId = getActionMenuDropdownIdFromActionMenuId(actionMenuId);
+ const dropdownId = getCommandMenuDropdownIdFromCommandMenuId(commandMenuId);
const { closeDropdown } = useCloseDropdown();
- const recordIndexActionMenuDropdownPosition = useAtomComponentStateValue(
- recordIndexActionMenuDropdownPositionComponentState,
+ const recordIndexCommandMenuDropdownPosition = useAtomComponentStateValue(
+ recordIndexCommandMenuDropdownPositionComponentState,
dropdownId,
);
@@ -73,13 +73,13 @@ export const RecordIndexActionMenuDropdown = () => {
dropdownPlacement="bottom-start"
dropdownStrategy="absolute"
dropdownOffset={{
- x: recordIndexActionMenuDropdownPosition.x ?? 0,
- y: recordIndexActionMenuDropdownPosition.y ?? 0,
+ x: recordIndexCommandMenuDropdownPosition.x ?? 0,
+ y: recordIndexCommandMenuDropdownPosition.y ?? 0,
}}
dropdownComponents={
{
selectableListInstanceId={dropdownId}
>
{recordIndexActions.map((action) => (
-
+
))}
{
+export const RecordPageSidePanelCommandMenu = () => {
const contextStoreCurrentObjectMetadataItemId = useAtomComponentStateValue(
contextStoreCurrentObjectMetadataItemIdComponentState,
);
@@ -11,13 +11,13 @@ export const RecordShowSidePanelActionMenu = () => {
return (
<>
{contextStoreCurrentObjectMetadataItemId && (
-
-
-
+
+
)}
>
);
diff --git a/packages/twenty-front/src/modules/command-menu-item/components/RecordPageSidePanelCommandMenuDropdown.tsx b/packages/twenty-front/src/modules/command-menu-item/components/RecordPageSidePanelCommandMenuDropdown.tsx
new file mode 100644
index 0000000000..f24e78717f
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/components/RecordPageSidePanelCommandMenuDropdown.tsx
@@ -0,0 +1,39 @@
+import { CommandMenuItemComponent } from '@/command-menu-item/display/components/CommandMenuItemComponent';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
+import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
+import { getSidePanelCommandMenuDropdownIdFromCommandMenuId } from '@/command-menu-item/utils/getSidePanelCommandMenuDropdownIdFromCommandMenuId';
+import { OptionsDropdownMenu } from '@/ui/layout/dropdown/components/OptionsDropdownMenu';
+import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
+import { useContext } from 'react';
+
+export const RecordPageSidePanelCommandMenuDropdown = () => {
+ const { commandMenuItems } = useContext(CommandMenuContext);
+
+ const commandMenuId = useAvailableComponentInstanceIdOrThrow(
+ CommandMenuComponentInstanceContext,
+ );
+
+ const dropdownId =
+ getSidePanelCommandMenuDropdownIdFromCommandMenuId(commandMenuId);
+
+ const recordSelectionActions = commandMenuItems.filter(
+ (action) => action.scope === CommandMenuItemScope.RecordSelection,
+ );
+
+ const selectableItemIdArray = recordSelectionActions.map(
+ (action) => action.key,
+ );
+
+ return (
+
+ {recordSelectionActions.map((action) => (
+
+ ))}
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenu.tsx b/packages/twenty-front/src/modules/command-menu-item/components/RecordShowCommandMenu.tsx
similarity index 74%
rename from packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenu.tsx
rename to packages/twenty-front/src/modules/command-menu-item/components/RecordShowCommandMenu.tsx
index 590c916369..425e9397be 100644
--- a/packages/twenty-front/src/modules/action-menu/components/RecordShowActionMenu.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/components/RecordShowCommandMenu.tsx
@@ -1,12 +1,12 @@
-import { PageHeaderActionMenuButtons } from '@/action-menu/components/PageHeaderActionMenuButtons';
-import { ActionMenuContextProvider } from '@/action-menu/contexts/ActionMenuContextProvider';
+import { PageHeaderCommandMenuButtons } from '@/command-menu-item/components/PageHeaderCommandMenuButtons';
+import { CommandMenuContextProvider } from '@/command-menu-item/contexts/CommandMenuContextProvider';
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
import { useIsMobile } from 'twenty-ui/utilities';
-export const RecordShowActionMenu = () => {
+export const RecordShowCommandMenu = () => {
const contextStoreCurrentObjectMetadataItemId = useAtomComponentStateValue(
contextStoreCurrentObjectMetadataItemIdComponentState,
MAIN_CONTEXT_STORE_INSTANCE_ID,
@@ -26,13 +26,13 @@ export const RecordShowActionMenu = () => {
return (
<>
{hasSelectedRecord && contextStoreCurrentObjectMetadataItemId && (
-
- {!isMobile && }
-
+ {!isMobile && }
+
)}
>
);
diff --git a/packages/twenty-front/src/modules/action-menu/components/RecordShowSidePanelOpenRecordButton.tsx b/packages/twenty-front/src/modules/command-menu-item/components/RecordShowSidePanelOpenRecordButton.tsx
similarity index 91%
rename from packages/twenty-front/src/modules/action-menu/components/RecordShowSidePanelOpenRecordButton.tsx
rename to packages/twenty-front/src/modules/command-menu-item/components/RecordShowSidePanelOpenRecordButton.tsx
index f448a8d309..08ea06df6c 100644
--- a/packages/twenty-front/src/modules/action-menu/components/RecordShowSidePanelOpenRecordButton.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/components/RecordShowSidePanelOpenRecordButton.tsx
@@ -1,5 +1,5 @@
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
-import { getSidePanelActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getSidePanelActionMenuDropdownIdFromActionMenuId';
+import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
+import { getSidePanelCommandMenuDropdownIdFromCommandMenuId } from '@/command-menu-item/utils/getSidePanelCommandMenuDropdownIdFromCommandMenuId';
import { SIDE_PANEL_FOCUS_ID } from '@/side-panel/constants/SidePanelFocusId';
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
import { sidePanelNavigationStackState } from '@/side-panel/states/sidePanelNavigationStackState';
@@ -75,8 +75,8 @@ export const RecordShowSidePanelOpenRecordButton = ({
const navigate = useNavigateApp();
- const actionMenuId = useAvailableComponentInstanceIdOrThrow(
- ActionMenuComponentInstanceContext,
+ const commandMenuId = useAvailableComponentInstanceIdOrThrow(
+ CommandMenuComponentInstanceContext,
);
const { closeDropdown } = useCloseDropdown();
@@ -109,12 +109,12 @@ export const RecordShowSidePanelOpenRecordButton = ({
});
closeDropdown(
- getSidePanelActionMenuDropdownIdFromActionMenuId(actionMenuId),
+ getSidePanelCommandMenuDropdownIdFromCommandMenuId(commandMenuId),
);
closeSidePanelMenu();
}, [
- actionMenuId,
+ commandMenuId,
activeTabId,
closeSidePanelMenu,
closeDropdown,
diff --git a/packages/twenty-front/src/modules/action-menu/components/__stories__/RecordIndexActionMenuDropdown.stories.tsx b/packages/twenty-front/src/modules/command-menu-item/components/__stories__/RecordIndexCommandMenuDropdown.stories.tsx
similarity index 60%
rename from packages/twenty-front/src/modules/action-menu/components/__stories__/RecordIndexActionMenuDropdown.stories.tsx
rename to packages/twenty-front/src/modules/command-menu-item/components/__stories__/RecordIndexCommandMenuDropdown.stories.tsx
index d8cffd46bc..e62ce6b6e8 100644
--- a/packages/twenty-front/src/modules/action-menu/components/__stories__/RecordIndexActionMenuDropdown.stories.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/components/__stories__/RecordIndexCommandMenuDropdown.stories.tsx
@@ -3,11 +3,11 @@ import { Provider as JotaiProvider } from 'jotai';
import * as test from 'storybook/test';
import { expect, userEvent, waitFor, within } from 'storybook/test';
-import { RecordIndexActionMenuDropdown } from '@/action-menu/components/RecordIndexActionMenuDropdown';
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
-import { createMockActionMenuActions } from '@/action-menu/mock/action-menu-actions.mock';
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
-import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-menu/states/recordIndexActionMenuDropdownPositionComponentState';
+import { RecordIndexCommandMenuDropdown } from '@/command-menu-item/components/RecordIndexCommandMenuDropdown';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
+import { createMockCommandMenuItems } from '@/command-menu-item/mock/command-menu-items.mock';
+import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
+import { recordIndexCommandMenuDropdownPositionComponentState } from '@/command-menu-item/states/recordIndexCommandMenuDropdownPositionComponentState';
import { isDropdownOpenComponentState } from '@/ui/layout/dropdown/states/isDropdownOpenComponentState';
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
@@ -18,35 +18,35 @@ const deleteMock = test.fn();
const addToFavoritesMock = test.fn();
const exportMock = test.fn();
-const meta: Meta = {
- title: 'Modules/ActionMenu/RecordIndexActionMenuDropdown',
- component: RecordIndexActionMenuDropdown,
+const meta: Meta = {
+ title: 'Modules/CommandMenu/RecordIndexCommandMenuDropdown',
+ component: RecordIndexCommandMenuDropdown,
decorators: [
(Story) => {
jotaiStore.set(
isDropdownOpenComponentState.atomFamily({
- instanceId: 'action-menu-dropdown-story-action-menu',
+ instanceId: 'command-menu-dropdown-story-command-menu',
}),
true,
);
jotaiStore.set(
- recordIndexActionMenuDropdownPositionComponentState.atomFamily({
- instanceId: 'action-menu-dropdown-story',
+ recordIndexCommandMenuDropdownPositionComponentState.atomFamily({
+ instanceId: 'command-menu-dropdown-story',
}),
{ x: 10, y: 10 },
);
return (
-
- = {
}}
>
-
-
+
+
);
},
@@ -66,17 +66,17 @@ const meta: Meta = {
export default meta;
-type Story = StoryObj;
+type Story = StoryObj;
export const Default: Story = {
args: {
- actionMenuId: 'story',
+ commandMenuId: 'story',
},
};
export const WithInteractions: Story = {
args: {
- actionMenuId: 'story',
+ commandMenuId: 'story',
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement.ownerDocument.body);
diff --git a/packages/twenty-front/src/modules/action-menu/components/__stories__/CommandMenuActionMenuDropdown.stories.tsx b/packages/twenty-front/src/modules/command-menu-item/components/__stories__/RecordShowSidePanelCommandMenuDropdown.stories.tsx
similarity index 71%
rename from packages/twenty-front/src/modules/action-menu/components/__stories__/CommandMenuActionMenuDropdown.stories.tsx
rename to packages/twenty-front/src/modules/command-menu-item/components/__stories__/RecordShowSidePanelCommandMenuDropdown.stories.tsx
index e6f75d1426..9354a42882 100644
--- a/packages/twenty-front/src/modules/action-menu/components/__stories__/CommandMenuActionMenuDropdown.stories.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/components/__stories__/RecordShowSidePanelCommandMenuDropdown.stories.tsx
@@ -3,10 +3,10 @@ import { Provider as JotaiProvider } from 'jotai';
import * as test from 'storybook/test';
import { expect, userEvent, waitFor, within } from 'storybook/test';
-import { CommandMenuActionMenuDropdown } from '@/action-menu/components/CommandMenuActionMenuDropdown';
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
-import { createMockActionMenuActions } from '@/action-menu/mock/action-menu-actions.mock';
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
+import { RecordPageSidePanelCommandMenuDropdown } from '@/command-menu-item/components/RecordPageSidePanelCommandMenuDropdown';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
+import { createMockCommandMenuItems } from '@/command-menu-item/mock/command-menu-items.mock';
+import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
import { ComponentDecorator, RouterDecorator } from 'twenty-ui/testing';
@@ -19,9 +19,9 @@ const deleteMock = test.fn();
const addToFavoritesMock = test.fn();
const exportMock = test.fn();
-const meta: Meta = {
- title: 'Modules/ActionMenu/CommandMenuActionMenuDropdown',
- component: CommandMenuActionMenuDropdown,
+const meta: Meta = {
+ title: 'Modules/CommandMenu/RecordPageSidePanelCommandMenuDropdown',
+ component: RecordPageSidePanelCommandMenuDropdown,
decorators: [
(Story) => (
@@ -35,15 +35,15 @@ const meta: Meta = {
}}
contextStoreNumberOfSelectedRecords={1}
>
-
- = {
}}
>
-
-
+
+
@@ -64,23 +64,23 @@ const meta: Meta = {
RouterDecorator,
],
args: {
- actionMenuId: 'story-action-menu',
+ commandMenuId: 'story-command-menu',
},
};
export default meta;
-type Story = StoryObj;
+type Story = StoryObj;
export const Default: Story = {
args: {
- actionMenuId: 'story-action-menu',
+ commandMenuId: 'story-command-menu',
},
};
export const WithButtonClicks: Story = {
args: {
- actionMenuId: 'story-action-menu',
+ commandMenuId: 'story-command-menu',
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement.ownerDocument.body);
diff --git a/packages/twenty-front/src/modules/command-menu-item/confirmation-modal/components/CommandMenuConfirmationModalManager.tsx b/packages/twenty-front/src/modules/command-menu-item/confirmation-modal/components/CommandMenuConfirmationModalManager.tsx
new file mode 100644
index 0000000000..f562e182ef
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/confirmation-modal/components/CommandMenuConfirmationModalManager.tsx
@@ -0,0 +1,69 @@
+import { COMMAND_MENU_CONFIRMATION_MODAL_RESULT_BROWSER_EVENT_NAME } from '@/command-menu-item/confirmation-modal/constants/CommandMenuItemConfirmationModalResultBrowserEventName';
+import { COMMAND_MENU_CONFIRMATION_MODAL_INSTANCE_ID } from '@/command-menu-item/confirmation-modal/constants/CommandMenuItemConfirmationModalId';
+import { commandMenuItemConfirmationModalConfigState } from '@/command-menu-item/confirmation-modal/states/commandMenuItemConfirmationModalState';
+import {
+ type CommandMenuConfirmationModalResult,
+ type CommandMenuConfirmationModalResultBrowserEventDetail,
+} from '@/command-menu-item/confirmation-modal/types/CommandMenuConfirmationModalResultBrowserEventDetail';
+import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
+import { isModalOpenedComponentState } from '@/ui/layout/modal/states/isModalOpenedComponentState';
+import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
+import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
+import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
+
+export const CommandMenuConfirmationModalManager = () => {
+ const commandMenuItemConfirmationModalConfig = useAtomStateValue(
+ commandMenuItemConfirmationModalConfigState,
+ );
+ const isModalOpened = useAtomComponentStateValue(
+ isModalOpenedComponentState,
+ COMMAND_MENU_CONFIRMATION_MODAL_INSTANCE_ID,
+ );
+ const setCommandMenuItemConfirmationModalConfig = useSetAtomState(
+ commandMenuItemConfirmationModalConfigState,
+ );
+
+ const callerId = commandMenuItemConfirmationModalConfig?.frontComponentId;
+
+ const emitConfirmationResult = (
+ confirmationResult: CommandMenuConfirmationModalResult,
+ ) => {
+ if (!callerId) {
+ return;
+ }
+
+ window.dispatchEvent(
+ new CustomEvent(
+ COMMAND_MENU_CONFIRMATION_MODAL_RESULT_BROWSER_EVENT_NAME,
+ {
+ detail: {
+ frontComponentId: callerId,
+ confirmationResult,
+ },
+ },
+ ),
+ );
+
+ setCommandMenuItemConfirmationModalConfig(null);
+ };
+
+ if (!commandMenuItemConfirmationModalConfig || !isModalOpened) {
+ return null;
+ }
+
+ return (
+ emitConfirmationResult('confirm')}
+ onClose={() => emitConfirmationResult('cancel')}
+ confirmButtonText={
+ commandMenuItemConfirmationModalConfig.confirmButtonText
+ }
+ confirmButtonAccent={
+ commandMenuItemConfirmationModalConfig.confirmButtonAccent
+ }
+ />
+ );
+};
diff --git a/packages/twenty-front/src/modules/command-menu-item/confirmation-modal/constants/CommandMenuItemConfirmationModalId.ts b/packages/twenty-front/src/modules/command-menu-item/confirmation-modal/constants/CommandMenuItemConfirmationModalId.ts
new file mode 100644
index 0000000000..5bae5b755a
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/confirmation-modal/constants/CommandMenuItemConfirmationModalId.ts
@@ -0,0 +1,2 @@
+export const COMMAND_MENU_CONFIRMATION_MODAL_INSTANCE_ID =
+ 'command-menu-item-confirmation-modal';
diff --git a/packages/twenty-front/src/modules/command-menu-item/confirmation-modal/constants/CommandMenuItemConfirmationModalResultBrowserEventName.ts b/packages/twenty-front/src/modules/command-menu-item/confirmation-modal/constants/CommandMenuItemConfirmationModalResultBrowserEventName.ts
new file mode 100644
index 0000000000..fd545d5e58
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/confirmation-modal/constants/CommandMenuItemConfirmationModalResultBrowserEventName.ts
@@ -0,0 +1,2 @@
+export const COMMAND_MENU_CONFIRMATION_MODAL_RESULT_BROWSER_EVENT_NAME =
+ 'command-menu-item-confirmation-modal-result';
diff --git a/packages/twenty-front/src/modules/command-menu-item/confirmation-modal/hooks/useCommandMenuConfirmationModal.ts b/packages/twenty-front/src/modules/command-menu-item/confirmation-modal/hooks/useCommandMenuConfirmationModal.ts
new file mode 100644
index 0000000000..11a56bb921
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/confirmation-modal/hooks/useCommandMenuConfirmationModal.ts
@@ -0,0 +1,48 @@
+import { useStore } from 'jotai';
+import { useCallback } from 'react';
+
+import { COMMAND_MENU_CONFIRMATION_MODAL_INSTANCE_ID } from '@/command-menu-item/confirmation-modal/constants/CommandMenuItemConfirmationModalId';
+import {
+ type CommandMenuItemConfirmationModalConfig,
+ commandMenuItemConfirmationModalConfigState,
+} from '@/command-menu-item/confirmation-modal/states/commandMenuItemConfirmationModalState';
+import { useModal } from '@/ui/layout/modal/hooks/useModal';
+import { isModalOpenedComponentState } from '@/ui/layout/modal/states/isModalOpenedComponentState';
+import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
+
+export const useCommandMenuConfirmationModal = () => {
+ const store = useStore();
+ const setCommandMenuItemConfirmationModalConfig = useSetAtomState(
+ commandMenuItemConfirmationModalConfigState,
+ );
+ const { openModal } = useModal();
+
+ const openConfirmationModal = useCallback(
+ (config: CommandMenuItemConfirmationModalConfig) => {
+ const existingCommandMenuItemConfirmationModalConfig = store.get(
+ commandMenuItemConfirmationModalConfigState.atom,
+ );
+ const isCommandMenuItemConfirmationModalOpened = store.get(
+ isModalOpenedComponentState.atomFamily({
+ instanceId: COMMAND_MENU_CONFIRMATION_MODAL_INSTANCE_ID,
+ }),
+ );
+
+ if (
+ existingCommandMenuItemConfirmationModalConfig !== null ||
+ isCommandMenuItemConfirmationModalOpened
+ ) {
+ throw new Error(
+ 'Command menu item confirmation modal is already active for another front component',
+ );
+ }
+
+ setCommandMenuItemConfirmationModalConfig(config);
+
+ openModal(COMMAND_MENU_CONFIRMATION_MODAL_INSTANCE_ID);
+ },
+ [store, setCommandMenuItemConfirmationModalConfig, openModal],
+ );
+
+ return { openConfirmationModal };
+};
diff --git a/packages/twenty-front/src/modules/action-menu/confirmation-modal/states/actionMenuConfirmationModalState.ts b/packages/twenty-front/src/modules/command-menu-item/confirmation-modal/states/commandMenuItemConfirmationModalState.ts
similarity index 59%
rename from packages/twenty-front/src/modules/action-menu/confirmation-modal/states/actionMenuConfirmationModalState.ts
rename to packages/twenty-front/src/modules/command-menu-item/confirmation-modal/states/commandMenuItemConfirmationModalState.ts
index 14583169ba..b6f3448810 100644
--- a/packages/twenty-front/src/modules/action-menu/confirmation-modal/states/actionMenuConfirmationModalState.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/confirmation-modal/states/commandMenuItemConfirmationModalState.ts
@@ -3,7 +3,7 @@ import { type ReactNode } from 'react';
import { createAtomState } from '@/ui/utilities/state/jotai/utils/createAtomState';
import { type ButtonAccent } from 'twenty-ui/input';
-export type ActionMenuConfirmationModalConfig = {
+export type CommandMenuItemConfirmationModalConfig = {
frontComponentId: string;
title: string;
subtitle: ReactNode;
@@ -11,8 +11,8 @@ export type ActionMenuConfirmationModalConfig = {
confirmButtonAccent?: ButtonAccent;
};
-export const actionMenuConfirmationModalConfigState =
- createAtomState({
- key: 'actionMenuConfirmationModalConfigState',
+export const commandMenuItemConfirmationModalConfigState =
+ createAtomState({
+ key: 'commandMenuItemConfirmationModalConfigState',
defaultValue: null,
});
diff --git a/packages/twenty-front/src/modules/command-menu-item/confirmation-modal/types/CommandMenuConfirmationModalResultBrowserEventDetail.ts b/packages/twenty-front/src/modules/command-menu-item/confirmation-modal/types/CommandMenuConfirmationModalResultBrowserEventDetail.ts
new file mode 100644
index 0000000000..e5030c7ae1
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/confirmation-modal/types/CommandMenuConfirmationModalResultBrowserEventDetail.ts
@@ -0,0 +1,6 @@
+export type CommandMenuConfirmationModalResult = 'confirm' | 'cancel';
+
+export type CommandMenuConfirmationModalResultBrowserEventDetail = {
+ frontComponentId: string;
+ confirmationResult: CommandMenuConfirmationModalResult;
+};
diff --git a/packages/twenty-front/src/modules/command-menu-item/constants/CommandMenuDropdownClickOutsideId.ts b/packages/twenty-front/src/modules/command-menu-item/constants/CommandMenuDropdownClickOutsideId.ts
new file mode 100644
index 0000000000..ba54968dc8
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/constants/CommandMenuDropdownClickOutsideId.ts
@@ -0,0 +1 @@
+export const COMMAND_MENU_DROPDOWN_CLICK_OUTSIDE_ID = 'command-menu-dropdown';
diff --git a/packages/twenty-front/src/modules/command-menu-item/contexts/CommandConfigContext.tsx b/packages/twenty-front/src/modules/command-menu-item/contexts/CommandConfigContext.tsx
new file mode 100644
index 0000000000..9efde55ba8
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/contexts/CommandConfigContext.tsx
@@ -0,0 +1,6 @@
+import { type CommandMenuItemConfig } from '@/command-menu-item/types/CommandMenuItemConfig';
+import { createContext } from 'react';
+
+export const CommandConfigContext = createContext(
+ null,
+);
diff --git a/packages/twenty-front/src/modules/command-menu-item/contexts/CommandMenuContext.ts b/packages/twenty-front/src/modules/command-menu-item/contexts/CommandMenuContext.ts
new file mode 100644
index 0000000000..ab85985573
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/contexts/CommandMenuContext.ts
@@ -0,0 +1,17 @@
+import { type CommandMenuItemConfig } from '@/command-menu-item/types/CommandMenuItemConfig';
+import { type CommandMenuItemContainerType } from '@/command-menu-item/types/CommandMenuItemContainerType';
+import { createContext } from 'react';
+
+export type CommandMenuContextType = {
+ isInSidePanel: boolean;
+ displayType: 'button' | 'listItem' | 'dropdownItem';
+ containerType: CommandMenuItemContainerType;
+ commandMenuItems: CommandMenuItemConfig[];
+};
+
+export const CommandMenuContext = createContext({
+ isInSidePanel: false,
+ containerType: 'command-menu-list',
+ displayType: 'button',
+ commandMenuItems: [],
+});
diff --git a/packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContextProvider.tsx b/packages/twenty-front/src/modules/command-menu-item/contexts/CommandMenuContextProvider.tsx
similarity index 71%
rename from packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContextProvider.tsx
rename to packages/twenty-front/src/modules/command-menu-item/contexts/CommandMenuContextProvider.tsx
index da801fed98..0d6205c684 100644
--- a/packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContextProvider.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/contexts/CommandMenuContextProvider.tsx
@@ -1,6 +1,6 @@
-import { type ActionMenuContextType } from '@/action-menu/contexts/ActionMenuContext';
-import { ActionMenuContextProviderDefault } from '@/action-menu/contexts/ActionMenuContextProviderDefault';
-import { ActionMenuContextProviderWorkflowObjects } from '@/action-menu/contexts/ActionMenuContextProviderWorkflowObjects';
+import { type CommandMenuContextType } from '@/command-menu-item/contexts/CommandMenuContext';
+import { CommandMenuContextProviderDefault } from '@/command-menu-item/contexts/CommandMenuContextProviderDefault';
+import { CommandMenuContextProviderWorkflowObjects } from '@/command-menu-item/contexts/CommandMenuContextProviderWorkflowObjects';
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
import { objectMetadataItemsState } from '@/object-metadata/states/objectMetadataItemsState';
import { CoreObjectNameSingular } from 'twenty-shared/types';
@@ -9,13 +9,13 @@ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/use
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
import { isDefined } from 'twenty-shared/utils';
-export const ActionMenuContextProvider = ({
+export const CommandMenuContextProvider = ({
children,
isInSidePanel,
displayType,
- actionMenuType,
+ containerType,
objectMetadataItemOverride,
-}: Omit & {
+}: Omit & {
children: React.ReactNode;
objectMetadataItemOverride?: ObjectMetadataItem;
}) => {
@@ -45,25 +45,25 @@ export const ActionMenuContextProvider = ({
if (isWorkflowObject) {
return (
-
{children}
-
+
);
}
return (
-
{children}
-
+
);
};
diff --git a/packages/twenty-front/src/modules/command-menu-item/contexts/CommandMenuContextProviderDefault.tsx b/packages/twenty-front/src/modules/command-menu-item/contexts/CommandMenuContextProviderDefault.tsx
new file mode 100644
index 0000000000..17841ccf45
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/contexts/CommandMenuContextProviderDefault.tsx
@@ -0,0 +1,78 @@
+import { useRunWorkflowRecordCommands } from '@/command-menu-item/record/workflow/hooks/useRunWorkflowRecordCommands';
+import { useRunWorkflowRecordAgnosticCommands } from '@/command-menu-item/record-agnostic/workflow/hooks/useRunWorkflowRecordAgnosticCommands';
+import {
+ CommandMenuContext,
+ type CommandMenuContextType,
+} from '@/command-menu-item/contexts/CommandMenuContext';
+import { useRegisteredCommandMenuItems } from '@/command-menu-item/hooks/useRegisteredCommandMenuItems';
+import { useShouldCommandMenuItemBeRegisteredParams } from '@/command-menu-item/hooks/useShouldCommandMenuItemBeRegisteredParams';
+import { useCommandMenuContextApi } from '@/command-menu-item/hooks/useCommandMenuContextApi';
+import { useCommandMenuItemFrontComponentActions } from '@/command-menu-item/hooks/useCommandMenuItemFrontComponentActions';
+import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
+import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
+import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
+
+export const CommandMenuContextProviderDefault = ({
+ objectMetadataItem,
+ isInSidePanel,
+ displayType,
+ containerType,
+ children,
+}: {
+ objectMetadataItem: ObjectMetadataItem;
+ isInSidePanel: CommandMenuContextType['isInSidePanel'];
+ displayType: CommandMenuContextType['displayType'];
+ containerType: CommandMenuContextType['containerType'];
+ children: React.ReactNode;
+}) => {
+ const params = useShouldCommandMenuItemBeRegisteredParams({
+ objectMetadataItem,
+ });
+
+ const shouldBeRegisteredParams = {
+ ...params,
+ };
+
+ const commandMenuItems = useRegisteredCommandMenuItems(
+ shouldBeRegisteredParams,
+ );
+
+ const contextStoreTargetedRecordsRule = useAtomComponentStateValue(
+ contextStoreTargetedRecordsRuleComponentState,
+ );
+
+ const isRecordSelection =
+ contextStoreTargetedRecordsRule.mode === 'selection' &&
+ contextStoreTargetedRecordsRule.selectedRecordIds.length > 0;
+
+ const runWorkflowRecordCommands = useRunWorkflowRecordCommands({
+ objectMetadataItem,
+ skip: !isRecordSelection,
+ });
+
+ const runWorkflowRecordAgnosticCommands =
+ useRunWorkflowRecordAgnosticCommands();
+
+ const commandMenuContextApi = useCommandMenuContextApi();
+
+ const commandMenuItemFrontComponentActions =
+ useCommandMenuItemFrontComponentActions(commandMenuContextApi);
+
+ return (
+
+ {children}
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContextProviderWorkflowObjects.tsx b/packages/twenty-front/src/modules/command-menu-item/contexts/CommandMenuContextProviderWorkflowObjects.tsx
similarity index 57%
rename from packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContextProviderWorkflowObjects.tsx
rename to packages/twenty-front/src/modules/command-menu-item/contexts/CommandMenuContextProviderWorkflowObjects.tsx
index fdbf5293d6..6622ef048d 100644
--- a/packages/twenty-front/src/modules/action-menu/contexts/ActionMenuContextProviderWorkflowObjects.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/contexts/CommandMenuContextProviderWorkflowObjects.tsx
@@ -1,11 +1,11 @@
-import { useRunWorkflowRecordAgnosticActions } from '@/action-menu/actions/record-agnostic-actions/run-workflow-actions/hooks/useRunWorkflowRecordAgnosticActions';
+import { useRunWorkflowRecordAgnosticCommands } from '@/command-menu-item/record-agnostic/workflow/hooks/useRunWorkflowRecordAgnosticCommands';
import {
- ActionMenuContext,
- type ActionMenuContextType,
-} from '@/action-menu/contexts/ActionMenuContext';
-import { useRegisteredActions } from '@/action-menu/hooks/useRegisteredActions';
-import { useShouldActionBeRegisteredParams } from '@/action-menu/hooks/useShouldActionBeRegisteredParams';
-import { useCommandMenuContextApi } from '@/action-menu/hooks/useCommandMenuContextApi';
+ CommandMenuContext,
+ type CommandMenuContextType,
+} from '@/command-menu-item/contexts/CommandMenuContext';
+import { useRegisteredCommandMenuItems } from '@/command-menu-item/hooks/useRegisteredCommandMenuItems';
+import { useShouldCommandMenuItemBeRegisteredParams } from '@/command-menu-item/hooks/useShouldCommandMenuItemBeRegisteredParams';
+import { useCommandMenuContextApi } from '@/command-menu-item/hooks/useCommandMenuContextApi';
import { useCommandMenuItemFrontComponentActions } from '@/command-menu-item/hooks/useCommandMenuItemFrontComponentActions';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
@@ -16,25 +16,25 @@ import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithC
import { type WorkflowWithCurrentVersion } from '@/workflow/types/Workflow';
import { isDefined } from 'twenty-shared/utils';
-type ActionMenuContextProviderWorkflowObjectsProps = {
+type CommandMenuContextProviderWorkflowObjectsProps = {
objectMetadataItem: ObjectMetadataItem;
- isInSidePanel: ActionMenuContextType['isInSidePanel'];
- displayType: ActionMenuContextType['displayType'];
- actionMenuType: ActionMenuContextType['actionMenuType'];
+ isInSidePanel: CommandMenuContextType['isInSidePanel'];
+ displayType: CommandMenuContextType['displayType'];
+ containerType: CommandMenuContextType['containerType'];
children: React.ReactNode;
};
-const ActionMenuContextProviderWorkflowObjectsContent = ({
+const CommandMenuContextProviderWorkflowObjectsContent = ({
objectMetadataItem,
isInSidePanel,
displayType,
- actionMenuType,
+ containerType,
children,
selectedRecordId,
-}: ActionMenuContextProviderWorkflowObjectsProps & {
+}: CommandMenuContextProviderWorkflowObjectsProps & {
selectedRecordId: string;
}) => {
- const params = useShouldActionBeRegisteredParams({
+ const params = useShouldCommandMenuItemBeRegisteredParams({
objectMetadataItem,
});
@@ -46,10 +46,12 @@ const ActionMenuContextProviderWorkflowObjectsContent = ({
workflowWithCurrentVersion,
};
- const actions = useRegisteredActions(shouldBeRegisteredParams);
+ const commandMenuItems = useRegisteredCommandMenuItems(
+ shouldBeRegisteredParams,
+ );
- const runWorkflowRecordAgnosticActions =
- useRunWorkflowRecordAgnosticActions();
+ const runWorkflowRecordAgnosticCommands =
+ useRunWorkflowRecordAgnosticCommands();
const commandMenuContextApi = useCommandMenuContextApi();
@@ -57,33 +59,33 @@ const ActionMenuContextProviderWorkflowObjectsContent = ({
useCommandMenuItemFrontComponentActions(commandMenuContextApi);
return (
-
{children}
-
+
);
};
-const ActionMenuContextProviderWorkflowObjectsWithoutWorkflow = ({
+const CommandMenuContextProviderWorkflowObjectsWithoutWorkflow = ({
objectMetadataItem,
isInSidePanel,
displayType,
- actionMenuType,
+ containerType,
children,
-}: ActionMenuContextProviderWorkflowObjectsProps & {
+}: CommandMenuContextProviderWorkflowObjectsProps & {
workflowWithCurrentVersion: WorkflowWithCurrentVersion | undefined;
}) => {
- const params = useShouldActionBeRegisteredParams({
+ const params = useShouldCommandMenuItemBeRegisteredParams({
objectMetadataItem,
});
@@ -92,10 +94,12 @@ const ActionMenuContextProviderWorkflowObjectsWithoutWorkflow = ({
workflowWithCurrentVersion: undefined,
};
- const actions = useRegisteredActions(shouldBeRegisteredParams);
+ const commandMenuItems = useRegisteredCommandMenuItems(
+ shouldBeRegisteredParams,
+ );
- const runWorkflowRecordAgnosticActions =
- useRunWorkflowRecordAgnosticActions();
+ const runWorkflowRecordAgnosticCommands =
+ useRunWorkflowRecordAgnosticCommands();
const commandMenuContextApi = useCommandMenuContextApi();
@@ -103,30 +107,30 @@ const ActionMenuContextProviderWorkflowObjectsWithoutWorkflow = ({
useCommandMenuItemFrontComponentActions(commandMenuContextApi);
return (
-
{children}
-
+
);
};
-export const ActionMenuContextProviderWorkflowObjects = ({
+export const CommandMenuContextProviderWorkflowObjects = ({
objectMetadataItem,
isInSidePanel,
displayType,
- actionMenuType,
+ containerType,
children,
-}: ActionMenuContextProviderWorkflowObjectsProps) => {
+}: CommandMenuContextProviderWorkflowObjectsProps) => {
const contextStoreTargetedRecordsRule = useAtomComponentStateValue(
contextStoreTargetedRecordsRuleComponentState,
);
@@ -143,27 +147,27 @@ export const ActionMenuContextProviderWorkflowObjects = ({
if (isDefined(selectedRecord?.id)) {
return (
-
{children}
-
+
);
}
return (
-
{children}
-
+
);
};
diff --git a/packages/twenty-front/src/modules/command-menu-item/display/components/Command.tsx b/packages/twenty-front/src/modules/command-menu-item/display/components/Command.tsx
new file mode 100644
index 0000000000..ca4a88f4dc
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/display/components/Command.tsx
@@ -0,0 +1,32 @@
+import { CommandConfigContext } from '@/command-menu-item/contexts/CommandConfigContext';
+import { CommandMenuItemDisplay } from '@/command-menu-item/display/components/CommandMenuItemDisplay';
+import { useCloseCommandMenu } from '@/command-menu-item/hooks/useCloseCommandMenu';
+import { useContext } from 'react';
+
+export const Command = ({
+ onClick,
+ closeSidePanelOnShowPageOptionsExecution = false,
+ closeSidePanelOnCommandMenuListExecution = true,
+}: {
+ onClick: () => void;
+ closeSidePanelOnShowPageOptionsExecution?: boolean;
+ closeSidePanelOnCommandMenuListExecution?: boolean;
+}) => {
+ const commandMenuItemConfig = useContext(CommandConfigContext);
+
+ const { closeCommandMenu } = useCloseCommandMenu({
+ closeSidePanelOnShowPageOptionsExecution,
+ closeSidePanelOnCommandMenuListExecution,
+ });
+
+ if (!commandMenuItemConfig) {
+ return null;
+ }
+
+ const handleClick = () => {
+ closeCommandMenu();
+ onClick();
+ };
+
+ return ;
+};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/display/components/ActionDropdownItem.tsx b/packages/twenty-front/src/modules/command-menu-item/display/components/CommandDropdownItem.tsx
similarity index 81%
rename from packages/twenty-front/src/modules/action-menu/actions/display/components/ActionDropdownItem.tsx
rename to packages/twenty-front/src/modules/command-menu-item/display/components/CommandDropdownItem.tsx
index 539374d895..ca37270f0c 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/display/components/ActionDropdownItem.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/display/components/CommandDropdownItem.tsx
@@ -1,5 +1,5 @@
-import { type ActionDisplayProps } from '@/action-menu/actions/display/components/ActionDisplay';
-import { getActionLabel } from '@/action-menu/utils/getActionLabel';
+import { type CommandMenuItemDisplayProps } from '@/command-menu-item/display/components/CommandMenuItemDisplay';
+import { getCommandMenuItemLabel } from '@/command-menu-item/utils/getCommandMenuItemLabel';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext';
import { isSelectedItemIdComponentFamilyState } from '@/ui/layout/selectable-list/states/isSelectedItemIdComponentFamilyState';
@@ -9,12 +9,12 @@ import { useNavigate } from 'react-router-dom';
import { isDefined } from 'twenty-shared/utils';
import { MenuItem } from 'twenty-ui/navigation';
-export const ActionDropdownItem = ({
+export const CommandDropdownItem = ({
action,
onClick,
to,
}: {
- action: ActionDisplayProps;
+ action: CommandMenuItemDisplayProps;
onClick?: () => void;
to?: string;
}) => {
@@ -44,7 +44,7 @@ export const ActionDropdownItem = ({
key={action.key}
LeftIcon={action.Icon}
onClick={handleClick}
- text={getActionLabel(action.label)}
+ text={getCommandMenuItemLabel(action.label)}
/>
);
diff --git a/packages/twenty-front/src/modules/command-menu-item/display/components/CommandLink.tsx b/packages/twenty-front/src/modules/command-menu-item/display/components/CommandLink.tsx
new file mode 100644
index 0000000000..ec62ee542d
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/display/components/CommandLink.tsx
@@ -0,0 +1,21 @@
+import { CommandMenuItemDisplay } from '@/command-menu-item/display/components/CommandMenuItemDisplay';
+import { useCloseCommandMenu } from '@/command-menu-item/hooks/useCloseCommandMenu';
+import { type PathParam } from 'react-router-dom';
+import { type AppPath } from 'twenty-shared/types';
+import { getAppPath } from 'twenty-shared/utils';
+
+export const CommandLink = ({
+ to,
+ params,
+ queryParams,
+}: {
+ to: T;
+ params?: { [key in PathParam]: string | null };
+ queryParams?: Record;
+}) => {
+ const { closeCommandMenu } = useCloseCommandMenu();
+
+ const path = getAppPath(to, params, queryParams);
+
+ return ;
+};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/display/components/ActionListItem.tsx b/packages/twenty-front/src/modules/command-menu-item/display/components/CommandListItem.tsx
similarity index 71%
rename from packages/twenty-front/src/modules/action-menu/actions/display/components/ActionListItem.tsx
rename to packages/twenty-front/src/modules/command-menu-item/display/components/CommandListItem.tsx
index d1327b60e0..f99c0da071 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/display/components/ActionListItem.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/display/components/CommandListItem.tsx
@@ -1,18 +1,18 @@
-import { type ActionDisplayProps } from '@/action-menu/actions/display/components/ActionDisplay';
-import { getActionLabel } from '@/action-menu/utils/getActionLabel';
+import { type CommandMenuItemDisplayProps } from '@/command-menu-item/display/components/CommandMenuItemDisplay';
+import { getCommandMenuItemLabel } from '@/command-menu-item/utils/getCommandMenuItemLabel';
import { CommandMenuItem } from '@/command-menu/components/CommandMenuItem';
import { SelectableListItem } from '@/ui/layout/selectable-list/components/SelectableListItem';
import { useNavigate } from 'react-router-dom';
import { isDefined } from 'twenty-shared/utils';
import { Loader } from 'twenty-ui/feedback';
-export const ActionListItem = ({
+export const CommandListItem = ({
action,
onClick,
to,
disabled = false,
}: {
- action: ActionDisplayProps;
+ action: CommandMenuItemDisplayProps;
onClick?: () => void;
to?: string;
disabled?: boolean;
@@ -35,8 +35,8 @@ export const ActionListItem = ({
) => void;
+ to?: string;
+}) => {
+ return ;
+};
diff --git a/packages/twenty-front/src/modules/command-menu-item/display/components/CommandMenuItemComponent.tsx b/packages/twenty-front/src/modules/command-menu-item/display/components/CommandMenuItemComponent.tsx
new file mode 100644
index 0000000000..0b9bc213ad
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/display/components/CommandMenuItemComponent.tsx
@@ -0,0 +1,14 @@
+import { type CommandMenuItemConfig } from '@/command-menu-item/types/CommandMenuItemConfig';
+import { CommandConfigContext } from '@/command-menu-item/contexts/CommandConfigContext';
+
+export const CommandMenuItemComponent = ({
+ action,
+}: {
+ action: CommandMenuItemConfig;
+}) => {
+ return (
+
+ {action.component}
+
+ );
+};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/display/components/ActionDisplay.tsx b/packages/twenty-front/src/modules/command-menu-item/display/components/CommandMenuItemDisplay.tsx
similarity index 54%
rename from packages/twenty-front/src/modules/action-menu/actions/display/components/ActionDisplay.tsx
rename to packages/twenty-front/src/modules/command-menu-item/display/components/CommandMenuItemDisplay.tsx
index 90885d1dd9..80e9fa78db 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/display/components/ActionDisplay.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/display/components/CommandMenuItemDisplay.tsx
@@ -1,15 +1,15 @@
-import { ActionButton } from '@/action-menu/actions/display/components/ActionButton';
-import { ActionDropdownItem } from '@/action-menu/actions/display/components/ActionDropdownItem';
-import { ActionListItem } from '@/action-menu/actions/display/components/ActionListItem';
-import { ActionConfigContext } from '@/action-menu/contexts/ActionConfigContext';
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
+import { CommandMenuItemButton } from '@/command-menu-item/display/components/CommandMenuItemButton';
+import { CommandDropdownItem } from '@/command-menu-item/display/components/CommandDropdownItem';
+import { CommandListItem } from '@/command-menu-item/display/components/CommandListItem';
+import { CommandConfigContext } from '@/command-menu-item/contexts/CommandConfigContext';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
import { type MessageDescriptor } from '@lingui/core';
import { useContext } from 'react';
import { assertUnreachable } from 'twenty-shared/utils';
import { type IconComponent } from 'twenty-ui/display';
import { type MenuItemAccent } from 'twenty-ui/navigation';
-export type ActionDisplayProps = {
+export type CommandMenuItemDisplayProps = {
key: string;
label: MessageDescriptor | string;
shortLabel?: MessageDescriptor | string;
@@ -20,7 +20,7 @@ export type ActionDisplayProps = {
hotKeys?: string[];
};
-export const ActionDisplay = ({
+export const CommandMenuItemDisplay = ({
onClick,
to,
disabled,
@@ -29,20 +29,20 @@ export const ActionDisplay = ({
to?: string;
disabled?: boolean;
}) => {
- const action = useContext(ActionConfigContext);
- const { displayType } = useContext(ActionMenuContext);
+ const action = useContext(CommandConfigContext);
+ const { displayType } = useContext(CommandMenuContext);
if (!action) {
return null;
}
if (displayType === 'button') {
- return ;
+ return ;
}
if (displayType === 'listItem') {
return (
- ;
+ return ;
}
return assertUnreachable(displayType, 'Unsupported display type');
diff --git a/packages/twenty-front/src/modules/action-menu/actions/components/ActionOpenSidePanelPage.tsx b/packages/twenty-front/src/modules/command-menu-item/display/components/CommandMenuItemOpenSidePanelPage.tsx
similarity index 75%
rename from packages/twenty-front/src/modules/action-menu/actions/components/ActionOpenSidePanelPage.tsx
rename to packages/twenty-front/src/modules/command-menu-item/display/components/CommandMenuItemOpenSidePanelPage.tsx
index d75776a25c..6aa4232788 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/components/ActionOpenSidePanelPage.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/display/components/CommandMenuItemOpenSidePanelPage.tsx
@@ -1,5 +1,5 @@
-import { ActionDisplay } from '@/action-menu/actions/display/components/ActionDisplay';
-import { ActionConfigContext } from '@/action-menu/contexts/ActionConfigContext';
+import { CommandMenuItemDisplay } from '@/command-menu-item/display/components/CommandMenuItemDisplay';
+import { CommandConfigContext } from '@/command-menu-item/contexts/CommandConfigContext';
import { useNavigateSidePanel } from '@/side-panel/hooks/useNavigateSidePanel';
import { sidePanelSearchState } from '@/side-panel/states/sidePanelSearchState';
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
@@ -9,7 +9,7 @@ import { useContext } from 'react';
import { type SidePanelPages } from 'twenty-shared/types';
import { type IconComponent } from 'twenty-ui/display';
-export const ActionOpenSidePanelPage = ({
+export const CommandMenuItemOpenSidePanelPage = ({
page,
pageTitle,
pageIcon,
@@ -22,7 +22,7 @@ export const ActionOpenSidePanelPage = ({
onClick?: () => void;
shouldResetSearchState?: boolean;
}) => {
- const actionConfig = useContext(ActionConfigContext);
+ const actionConfig = useContext(CommandConfigContext);
const { navigateSidePanel } = useNavigateSidePanel();
@@ -46,5 +46,5 @@ export const ActionOpenSidePanelPage = ({
}
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/components/ActionModal.tsx b/packages/twenty-front/src/modules/command-menu-item/display/components/CommandModal.tsx
similarity index 56%
rename from packages/twenty-front/src/modules/action-menu/actions/components/ActionModal.tsx
rename to packages/twenty-front/src/modules/command-menu-item/display/components/CommandModal.tsx
index 01c119b3b2..cb934bb80d 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/components/ActionModal.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/display/components/CommandModal.tsx
@@ -1,60 +1,60 @@
import { type ReactNode, useContext } from 'react';
import { t } from '@lingui/core/macro';
-import { ActionDisplay } from '@/action-menu/actions/display/components/ActionDisplay';
-import { ActionConfigContext } from '@/action-menu/contexts/ActionConfigContext';
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
-import { useCloseActionMenu } from '@/action-menu/hooks/useCloseActionMenu';
+import { CommandMenuItemDisplay } from '@/command-menu-item/display/components/CommandMenuItemDisplay';
+import { CommandConfigContext } from '@/command-menu-item/contexts/CommandConfigContext';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
+import { useCloseCommandMenu } from '@/command-menu-item/hooks/useCloseCommandMenu';
import { ConfirmationModal } from '@/ui/layout/modal/components/ConfirmationModal';
import { useModal } from '@/ui/layout/modal/hooks/useModal';
import { isModalOpenedComponentState } from '@/ui/layout/modal/states/isModalOpenedComponentState';
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
import { type ButtonAccent } from 'twenty-ui/input';
-export type ActionModalProps = {
+export type CommandModalProps = {
title: string;
subtitle: ReactNode;
onConfirmClick: () => void | Promise;
confirmButtonText?: string;
confirmButtonAccent?: ButtonAccent;
isLoading?: boolean;
- closeSidePanelOnShowPageOptionsActionExecution?: boolean;
- closeSidePanelOnCommandMenuListActionExecution?: boolean;
+ closeSidePanelOnShowPageOptionsExecution?: boolean;
+ closeSidePanelOnCommandMenuListExecution?: boolean;
};
-export const ActionModal = ({
+export const CommandModal = ({
title,
subtitle,
onConfirmClick,
confirmButtonText = t`Confirm`,
confirmButtonAccent = 'danger',
isLoading = false,
- closeSidePanelOnShowPageOptionsActionExecution,
- closeSidePanelOnCommandMenuListActionExecution,
-}: ActionModalProps) => {
+ closeSidePanelOnShowPageOptionsExecution,
+ closeSidePanelOnCommandMenuListExecution,
+}: CommandModalProps) => {
const { openModal } = useModal();
- const { closeActionMenu } = useCloseActionMenu({
- closeSidePanelOnShowPageOptionsActionExecution,
- closeSidePanelOnCommandMenuListActionExecution,
+ const { closeCommandMenu } = useCloseCommandMenu({
+ closeSidePanelOnShowPageOptionsExecution,
+ closeSidePanelOnCommandMenuListExecution,
});
const handleConfirmClick = async () => {
await onConfirmClick();
- closeActionMenu();
+ closeCommandMenu();
};
- const actionConfig = useContext(ActionConfigContext);
- const { actionMenuType } = useContext(ActionMenuContext);
+ const commandMenuItemConfig = useContext(CommandConfigContext);
+ const { containerType } = useContext(CommandMenuContext);
- const modalId = `${actionConfig?.key}-action-modal-${actionMenuType}`;
+ const modalId = `${commandMenuItemConfig?.key}-command-menu-item-modal-${containerType}`;
const isModalOpened = useAtomComponentStateValue(
isModalOpenedComponentState,
modalId,
);
- if (!actionConfig) {
+ if (!commandMenuItemConfig) {
return null;
}
@@ -62,7 +62,7 @@ export const ActionModal = ({
return (
<>
-
+
{isModalOpened && (
void;
+}) => {
+ const commandMenuItemConfig = useContext(CommandConfigContext);
+
+ const { closeCommandMenu } = useCloseCommandMenu({
+ closeSidePanelOnShowPageOptionsExecution: false,
+ closeSidePanelOnCommandMenuListExecution: false,
+ });
+
+ const isMounted = useAtomFamilySelectorValue(
+ isHeadlessFrontComponentMountedFamilySelector,
+ frontComponentId,
+ );
+
+ if (!commandMenuItemConfig) {
+ return null;
+ }
+
+ const handleClick = () => {
+ if (isMounted) {
+ return;
+ }
+
+ closeCommandMenu();
+ onClick();
+ };
+
+ return ;
+};
diff --git a/packages/twenty-front/src/modules/command-menu-item/display/components/__stories__/CommandMenuItemButton.stories.tsx b/packages/twenty-front/src/modules/command-menu-item/display/components/__stories__/CommandMenuItemButton.stories.tsx
new file mode 100644
index 0000000000..62196af57f
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/display/components/__stories__/CommandMenuItemButton.stories.tsx
@@ -0,0 +1,67 @@
+import { CommandMenuItemButton } from '@/command-menu-item/display/components/CommandMenuItemButton';
+import { NoSelectionRecordCommandKeys } from '@/command-menu-item/record/no-selection/types/NoSelectionRecordCommandKeys';
+import { SingleRecordCommandKeys } from '@/command-menu-item/record/single-record/types/SingleRecordCommandKeys';
+import { createMockCommandMenuItems } from '@/command-menu-item/mock/command-menu-items.mock';
+import { getCommandMenuItemLabel } from '@/command-menu-item/utils/getCommandMenuItemLabel';
+import { type Meta, type StoryObj } from '@storybook/react-vite';
+import { expect, fn, userEvent, within } from 'storybook/test';
+import { ComponentDecorator, RouterDecorator } from 'twenty-ui/testing';
+
+const meta: Meta = {
+ title: 'Modules/CommandMenuItem/Display/CommandMenuItemButton',
+ component: CommandMenuItemButton,
+ decorators: [ComponentDecorator, RouterDecorator],
+};
+
+export default meta;
+
+type Story = StoryObj;
+
+const deleteMock = fn();
+const addToFavoritesMock = fn();
+
+const mockActions = createMockCommandMenuItems({
+ deleteMock,
+ addToFavoritesMock,
+});
+
+const addToFavoritesCommandMenuItem = mockActions.find(
+ (action) => action.key === SingleRecordCommandKeys.ADD_TO_FAVORITES,
+);
+
+const goToPeopleCommandMenuItem = mockActions.find(
+ (action) => action.key === NoSelectionRecordCommandKeys.GO_TO_PEOPLE,
+);
+
+export const Default: Story = {
+ args: {
+ action: addToFavoritesCommandMenuItem,
+ onClick: addToFavoritesMock,
+ },
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ await userEvent.click(
+ await canvas.findByText(
+ getCommandMenuItemLabel(
+ addToFavoritesCommandMenuItem?.shortLabel ?? '',
+ ),
+ ),
+ );
+ expect(addToFavoritesMock).toHaveBeenCalled();
+ },
+};
+
+export const WithLink: Story = {
+ args: {
+ action: goToPeopleCommandMenuItem,
+ to: '/objects/people',
+ },
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+ const menuItem = await canvas.findByText(
+ getCommandMenuItemLabel(goToPeopleCommandMenuItem?.shortLabel ?? ''),
+ );
+ expect(menuItem).toBeVisible();
+ expect(canvas.getByRole('link')).toHaveAttribute('href', '/objects/people');
+ },
+};
diff --git a/packages/twenty-front/src/modules/command-menu-item/display/components/__stories__/CommandMenuItemComponent.stories.tsx b/packages/twenty-front/src/modules/command-menu-item/display/components/__stories__/CommandMenuItemComponent.stories.tsx
new file mode 100644
index 0000000000..a96e98991c
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/display/components/__stories__/CommandMenuItemComponent.stories.tsx
@@ -0,0 +1,69 @@
+import { type Meta, type StoryObj } from '@storybook/react-vite';
+import { expect, within } from 'storybook/test';
+
+import { CommandMenuItemComponent } from '@/command-menu-item/display/components/CommandMenuItemComponent';
+import { SingleRecordCommandKeys } from '@/command-menu-item/record/single-record/types/SingleRecordCommandKeys';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
+import { createMockCommandMenuItems } from '@/command-menu-item/mock/command-menu-items.mock';
+import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
+import { getCommandMenuItemLabel } from '@/command-menu-item/utils/getCommandMenuItemLabel';
+import { ComponentDecorator } from 'twenty-ui/testing';
+
+const mockActions = createMockCommandMenuItems({});
+
+const addToFavoritesCommandMenuItem = mockActions.find(
+ (action) => action.key === SingleRecordCommandKeys.ADD_TO_FAVORITES,
+);
+
+if (!addToFavoritesCommandMenuItem) {
+ throw new Error('Add to favorites action not found');
+}
+
+const meta: Meta = {
+ title: 'Modules/CommandMenuItem/Display/CommandMenuItemComponent',
+ component: CommandMenuItemComponent,
+ decorators: [
+ ComponentDecorator,
+ (Story) => (
+
+
+
+
+
+ ),
+ ],
+ args: {
+ action: addToFavoritesCommandMenuItem,
+ },
+ parameters: {
+ container: {
+ width: 'auto',
+ },
+ },
+};
+
+export default meta;
+type Story = StoryObj;
+
+export const Default: Story = {
+ play: async ({ canvasElement }) => {
+ const canvas = within(canvasElement);
+
+ expect(
+ await canvas.findByText(
+ getCommandMenuItemLabel(
+ addToFavoritesCommandMenuItem?.shortLabel ?? '',
+ ),
+ ),
+ ).toBeVisible();
+ },
+};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/display/components/__stories__/ActionDisplay.stories.tsx b/packages/twenty-front/src/modules/command-menu-item/display/components/__stories__/CommandMenuItemDisplay.stories.tsx
similarity index 55%
rename from packages/twenty-front/src/modules/action-menu/actions/display/components/__stories__/ActionDisplay.stories.tsx
rename to packages/twenty-front/src/modules/command-menu-item/display/components/__stories__/CommandMenuItemDisplay.stories.tsx
index aa42053f42..075c92efc0 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/display/components/__stories__/ActionDisplay.stories.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/display/components/__stories__/CommandMenuItemDisplay.stories.tsx
@@ -1,40 +1,40 @@
-import { ActionDisplay } from '@/action-menu/actions/display/components/ActionDisplay';
-import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey';
-import { ActionConfigContext } from '@/action-menu/contexts/ActionConfigContext';
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
-import { createMockActionMenuActions } from '@/action-menu/mock/action-menu-actions.mock';
-import { getActionLabel } from '@/action-menu/utils/getActionLabel';
+import { CommandMenuItemDisplay } from '@/command-menu-item/display/components/CommandMenuItemDisplay';
+import { SingleRecordCommandKeys } from '@/command-menu-item/record/single-record/types/SingleRecordCommandKeys';
+import { CommandConfigContext } from '@/command-menu-item/contexts/CommandConfigContext';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
+import { createMockCommandMenuItems } from '@/command-menu-item/mock/command-menu-items.mock';
+import { getCommandMenuItemLabel } from '@/command-menu-item/utils/getCommandMenuItemLabel';
import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext';
import { type Meta, type StoryObj } from '@storybook/react-vite';
import { expect, fn, userEvent, within } from 'storybook/test';
import { ComponentDecorator, RouterDecorator } from 'twenty-ui/testing';
-type Story = StoryObj;
+type Story = StoryObj;
const deleteMock = fn();
const addToFavoritesMock = fn();
-const mockActions = createMockActionMenuActions({
+const mockActions = createMockCommandMenuItems({
deleteMock,
addToFavoritesMock,
});
-const addToFavoritesAction = mockActions.find(
- (action) => action.key === SingleRecordActionKeys.ADD_TO_FAVORITES,
+const addToFavoritesCommandMenuItem = mockActions.find(
+ (action) => action.key === SingleRecordCommandKeys.ADD_TO_FAVORITES,
);
-if (!addToFavoritesAction) {
- throw new Error('addToFavoritesAction not found');
+if (!addToFavoritesCommandMenuItem) {
+ throw new Error('addToFavoritesCommandMenuItem not found');
}
-const meta: Meta = {
- title: 'Modules/ActionMenu/Actions/Display/ActionDisplay',
- component: ActionDisplay,
+const meta: Meta = {
+ title: 'Modules/CommandMenuItem/Display/CommandMenuItemDisplay',
+ component: CommandMenuItemDisplay,
decorators: [
(Story) => (
-
+
-
+
),
ComponentDecorator,
RouterDecorator,
@@ -49,23 +49,25 @@ export const AsButton: Story = {
},
decorators: [
(Story) => (
-
-
+
),
],
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await userEvent.click(
await canvas.findByText(
- getActionLabel(addToFavoritesAction?.shortLabel ?? ''),
+ getCommandMenuItemLabel(
+ addToFavoritesCommandMenuItem?.shortLabel ?? '',
+ ),
),
);
expect(addToFavoritesMock).toHaveBeenCalled();
@@ -85,23 +87,23 @@ export const AsListItem: Story = {
),
(Story) => (
-
-
+
),
],
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await userEvent.click(
await canvas.findByText(
- getActionLabel(addToFavoritesAction?.label ?? ''),
+ getCommandMenuItemLabel(addToFavoritesCommandMenuItem?.label ?? ''),
),
);
expect(addToFavoritesMock).toHaveBeenCalled();
@@ -121,23 +123,23 @@ export const AsDropdownItem: Story = {
),
(Story) => (
-
-
+
),
],
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await userEvent.click(
await canvas.findByText(
- getActionLabel(addToFavoritesAction?.label ?? ''),
+ getCommandMenuItemLabel(addToFavoritesCommandMenuItem?.label ?? ''),
),
);
expect(addToFavoritesMock).toHaveBeenCalled();
diff --git a/packages/twenty-front/src/modules/action-menu/actions/display/components/__stories__/ActionDropdownItem.stories.tsx b/packages/twenty-front/src/modules/command-menu-item/display/components/__stories__/CommandMenuItemDropdownItem.stories.tsx
similarity index 51%
rename from packages/twenty-front/src/modules/action-menu/actions/display/components/__stories__/ActionDropdownItem.stories.tsx
rename to packages/twenty-front/src/modules/command-menu-item/display/components/__stories__/CommandMenuItemDropdownItem.stories.tsx
index 728806da33..4d16a7be80 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/display/components/__stories__/ActionDropdownItem.stories.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/display/components/__stories__/CommandMenuItemDropdownItem.stories.tsx
@@ -1,16 +1,16 @@
-import { ActionDropdownItem } from '@/action-menu/actions/display/components/ActionDropdownItem';
-import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys';
-import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey';
-import { createMockActionMenuActions } from '@/action-menu/mock/action-menu-actions.mock';
-import { getActionLabel } from '@/action-menu/utils/getActionLabel';
+import { CommandDropdownItem } from '@/command-menu-item/display/components/CommandDropdownItem';
+import { NoSelectionRecordCommandKeys } from '@/command-menu-item/record/no-selection/types/NoSelectionRecordCommandKeys';
+import { SingleRecordCommandKeys } from '@/command-menu-item/record/single-record/types/SingleRecordCommandKeys';
+import { createMockCommandMenuItems } from '@/command-menu-item/mock/command-menu-items.mock';
+import { getCommandMenuItemLabel } from '@/command-menu-item/utils/getCommandMenuItemLabel';
import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext';
import { type Meta, type StoryObj } from '@storybook/react-vite';
import { expect, fn, userEvent, within } from 'storybook/test';
import { ComponentDecorator, RouterDecorator } from 'twenty-ui/testing';
-const meta: Meta = {
- title: 'Modules/ActionMenu/Actions/Display/ActionDropdownItem',
- component: ActionDropdownItem,
+const meta: Meta = {
+ title: 'Modules/CommandMenuItem/Display/CommandDropdownItem',
+ component: CommandDropdownItem,
decorators: [
(Story) => (
= {
export default meta;
-type Story = StoryObj;
+type Story = StoryObj;
const deleteMock = fn();
const addToFavoritesMock = fn();
-const mockActions = createMockActionMenuActions({
+const mockActions = createMockCommandMenuItems({
deleteMock,
addToFavoritesMock,
});
-const addToFavoritesAction = mockActions.find(
- (action) => action.key === SingleRecordActionKeys.ADD_TO_FAVORITES,
+const addToFavoritesCommandMenuItem = mockActions.find(
+ (action) => action.key === SingleRecordCommandKeys.ADD_TO_FAVORITES,
);
-const goToPeopleAction = mockActions.find(
- (action) => action.key === NoSelectionRecordActionKeys.GO_TO_PEOPLE,
+const goToPeopleCommandMenuItem = mockActions.find(
+ (action) => action.key === NoSelectionRecordCommandKeys.GO_TO_PEOPLE,
);
export const Default: Story = {
args: {
- action: addToFavoritesAction,
+ action: addToFavoritesCommandMenuItem,
onClick: addToFavoritesMock,
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
await userEvent.click(
await canvas.findByText(
- getActionLabel(addToFavoritesAction?.label ?? ''),
+ getCommandMenuItemLabel(addToFavoritesCommandMenuItem?.label ?? ''),
),
);
expect(addToFavoritesMock).toHaveBeenCalled();
@@ -62,13 +62,13 @@ export const Default: Story = {
export const WithLink: Story = {
args: {
- action: goToPeopleAction,
+ action: goToPeopleCommandMenuItem,
to: '/objects/people',
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const dropdownItem = await canvas.findByText(
- getActionLabel(goToPeopleAction?.label ?? ''),
+ getCommandMenuItemLabel(goToPeopleCommandMenuItem?.label ?? ''),
);
expect(dropdownItem).toBeVisible();
},
diff --git a/packages/twenty-front/src/modules/action-menu/actions/display/components/__stories__/ActionListItem.stories.tsx b/packages/twenty-front/src/modules/command-menu-item/display/components/__stories__/CommandMenuItemListItem.stories.tsx
similarity index 51%
rename from packages/twenty-front/src/modules/action-menu/actions/display/components/__stories__/ActionListItem.stories.tsx
rename to packages/twenty-front/src/modules/command-menu-item/display/components/__stories__/CommandMenuItemListItem.stories.tsx
index 4e869ba547..76c1fd85eb 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/display/components/__stories__/ActionListItem.stories.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/display/components/__stories__/CommandMenuItemListItem.stories.tsx
@@ -1,34 +1,34 @@
-import { ActionListItem } from '@/action-menu/actions/display/components/ActionListItem';
-import { NoSelectionRecordActionKeys } from '@/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys';
-import { SingleRecordActionKeys } from '@/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey';
-import { createMockActionMenuActions } from '@/action-menu/mock/action-menu-actions.mock';
-import { getActionLabel } from '@/action-menu/utils/getActionLabel';
+import { CommandListItem } from '@/command-menu-item/display/components/CommandListItem';
+import { NoSelectionRecordCommandKeys } from '@/command-menu-item/record/no-selection/types/NoSelectionRecordCommandKeys';
+import { SingleRecordCommandKeys } from '@/command-menu-item/record/single-record/types/SingleRecordCommandKeys';
+import { createMockCommandMenuItems } from '@/command-menu-item/mock/command-menu-items.mock';
+import { getCommandMenuItemLabel } from '@/command-menu-item/utils/getCommandMenuItemLabel';
import { SelectableListComponentInstanceContext } from '@/ui/layout/selectable-list/states/contexts/SelectableListComponentInstanceContext';
import { type Meta, type StoryObj } from '@storybook/react-vite';
import { expect, fn, userEvent, within } from 'storybook/test';
import { ComponentDecorator, RouterDecorator } from 'twenty-ui/testing';
-type Story = StoryObj;
+type Story = StoryObj;
const deleteMock = fn();
const addToFavoritesMock = fn();
-const mockActions = createMockActionMenuActions({
+const mockActions = createMockCommandMenuItems({
deleteMock,
addToFavoritesMock,
});
-const addToFavoritesAction = mockActions.find(
- (action) => action.key === SingleRecordActionKeys.ADD_TO_FAVORITES,
+const addToFavoritesCommandMenuItem = mockActions.find(
+ (action) => action.key === SingleRecordCommandKeys.ADD_TO_FAVORITES,
);
-const goToPeopleAction = mockActions.find(
- (action) => action.key === NoSelectionRecordActionKeys.GO_TO_PEOPLE,
+const goToPeopleCommandMenuItem = mockActions.find(
+ (action) => action.key === NoSelectionRecordCommandKeys.GO_TO_PEOPLE,
);
-const meta: Meta = {
- title: 'Modules/ActionMenu/Actions/Display/ActionListItem',
- component: ActionListItem,
+const meta: Meta = {
+ title: 'Modules/CommandMenuItem/Display/CommandListItem',
+ component: CommandListItem,
decorators: [
(Story) => (
{
const canvas = within(canvasElement);
await userEvent.click(
await canvas.findByText(
- getActionLabel(addToFavoritesAction?.label ?? ''),
+ getCommandMenuItemLabel(addToFavoritesCommandMenuItem?.label ?? ''),
),
);
expect(addToFavoritesMock).toHaveBeenCalled();
@@ -62,13 +62,13 @@ export const Default: Story = {
export const WithLink: Story = {
args: {
- action: goToPeopleAction,
+ action: goToPeopleCommandMenuItem,
to: '/objects/people',
},
play: async ({ canvasElement }) => {
const canvas = within(canvasElement);
const listItem = await canvas.findByText(
- getActionLabel(goToPeopleAction?.label ?? ''),
+ getCommandMenuItemLabel(goToPeopleCommandMenuItem?.label ?? ''),
);
expect(listItem).toBeVisible();
},
diff --git a/packages/twenty-front/src/modules/command-menu-item/hooks/useCloseCommandMenu.ts b/packages/twenty-front/src/modules/command-menu-item/hooks/useCloseCommandMenu.ts
new file mode 100644
index 0000000000..1834f69e1f
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/hooks/useCloseCommandMenu.ts
@@ -0,0 +1,60 @@
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
+import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
+import { getCommandMenuDropdownIdFromCommandMenuId } from '@/command-menu-item/utils/getCommandMenuDropdownIdFromCommandMenuId';
+import { getSidePanelCommandMenuDropdownIdFromCommandMenuId } from '@/command-menu-item/utils/getSidePanelCommandMenuDropdownIdFromCommandMenuId';
+import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
+import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
+import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
+import { useContext } from 'react';
+import { isDefined } from 'twenty-shared/utils';
+
+export const useCloseCommandMenu = ({
+ closeSidePanelOnShowPageOptionsExecution = false,
+ closeSidePanelOnCommandMenuListExecution = true,
+}: {
+ closeSidePanelOnShowPageOptionsExecution?: boolean;
+ closeSidePanelOnCommandMenuListExecution?: boolean;
+} = {}) => {
+ const { containerType, isInSidePanel } = useContext(CommandMenuContext);
+
+ const { closeSidePanelMenu } = useSidePanelMenu();
+
+ const { closeDropdown } = useCloseDropdown();
+
+ const commandMenuId = useAvailableComponentInstanceIdOrThrow(
+ CommandMenuComponentInstanceContext,
+ );
+
+ const dropdownId = isInSidePanel
+ ? getSidePanelCommandMenuDropdownIdFromCommandMenuId(commandMenuId)
+ : getCommandMenuDropdownIdFromCommandMenuId(commandMenuId);
+
+ const closeCommandMenu = () => {
+ if (containerType === 'command-menu-list') {
+ if (
+ isDefined(closeSidePanelOnCommandMenuListExecution) &&
+ !closeSidePanelOnCommandMenuListExecution
+ ) {
+ return;
+ }
+ closeSidePanelMenu();
+ }
+
+ if (
+ containerType === 'index-page-dropdown' ||
+ containerType === 'command-menu-show-page-dropdown'
+ ) {
+ closeDropdown(dropdownId);
+ }
+
+ if (
+ containerType === 'command-menu-show-page-dropdown' &&
+ isDefined(closeSidePanelOnShowPageOptionsExecution) &&
+ closeSidePanelOnShowPageOptionsExecution
+ ) {
+ closeSidePanelMenu();
+ }
+ };
+
+ return { closeCommandMenu };
+};
diff --git a/packages/twenty-front/src/modules/action-menu/hooks/useCommandMenuContextApi.ts b/packages/twenty-front/src/modules/command-menu-item/hooks/useCommandMenuContextApi.ts
similarity index 97%
rename from packages/twenty-front/src/modules/action-menu/hooks/useCommandMenuContextApi.ts
rename to packages/twenty-front/src/modules/command-menu-item/hooks/useCommandMenuContextApi.ts
index 5a3e431515..d6a4d6e70a 100644
--- a/packages/twenty-front/src/modules/action-menu/hooks/useCommandMenuContextApi.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/hooks/useCommandMenuContextApi.ts
@@ -1,4 +1,4 @@
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { objectPermissionsFamilySelector } from '@/auth/states/objectPermissionsFamilySelector';
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
@@ -30,7 +30,7 @@ import { FeatureFlagKey } from '~/generated-metadata/graphql';
export const useCommandMenuContextApi = (): CommandMenuContextApi => {
const store = useStore();
- const { isInSidePanel } = useContext(ActionMenuContext);
+ const { isInSidePanel } = useContext(CommandMenuContext);
const contextStoreCurrentObjectMetadataItemId = useAtomComponentStateValue(
contextStoreCurrentObjectMetadataItemIdComponentState,
diff --git a/packages/twenty-front/src/modules/command-menu-item/hooks/useCommandMenuItemFrontComponentActions.tsx b/packages/twenty-front/src/modules/command-menu-item/hooks/useCommandMenuItemFrontComponentActions.tsx
index 4a7a789cdd..55bcaaa8db 100644
--- a/packages/twenty-front/src/modules/command-menu-item/hooks/useCommandMenuItemFrontComponentActions.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/hooks/useCommandMenuItemFrontComponentActions.tsx
@@ -1,8 +1,8 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { HeadlessFrontComponentAction } from '@/action-menu/actions/display/components/HeadlessFrontComponentAction';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionType } from '@/action-menu/actions/types/ActionType';
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { HeadlessFrontComponentCommandMenuItem } from '@/command-menu-item/display/components/HeadlessFrontComponentCommandMenuItem';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
import { useOpenFrontComponentInSidePanel } from '@/side-panel/hooks/useOpenFrontComponentInSidePanel';
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
import { contextStoreIsPageInEditModeComponentState } from '@/context-store/states/contextStoreIsPageInEditModeComponentState';
@@ -34,9 +34,9 @@ type CommandMenuItemWithFrontComponent = CommandMenuItemFieldsFragment & {
conditionalAvailabilityExpression?: string | null;
};
-type BuildActionFromItemParams = {
+type BuildCommandMenuItemFromFrontComponentParams = {
item: CommandMenuItemWithFrontComponent;
- scope: ActionScope;
+ scope: CommandMenuItemScope;
index: number;
isPinned: boolean;
getIcon: ReturnType['getIcon'];
@@ -59,7 +59,7 @@ type BuildActionFromItemParams = {
// TODO: we should remove this backward compatibility logic in the future
// once we have migrated all command menu items
-const buildActionFromItem = ({
+const buildCommandMenuItemFromFrontComponent = ({
item,
scope,
index,
@@ -69,7 +69,7 @@ const buildActionFromItem = ({
mountHeadlessFrontComponent,
mountContext,
commandMenuContextApi,
-}: BuildActionFromItemParams) => {
+}: BuildCommandMenuItemFromFrontComponentParams) => {
const displayLabel = item.label;
const Icon = getIcon(item.icon, COMMAND_MENU_DEFAULT_ICON);
@@ -95,7 +95,7 @@ const buildActionFromItem = ({
};
return {
- type: ActionType.FrontComponent,
+ type: CommandMenuItemType.FrontComponent,
key: `command-menu-item-front-component-${item.id}`,
scope,
label: displayLabel,
@@ -109,12 +109,12 @@ const buildActionFromItem = ({
commandMenuContextApi,
),
component: isHeadless ? (
-
) : (
-
+
),
};
};
@@ -130,7 +130,7 @@ export const useCommandMenuItemFrontComponentActions = (
contextStoreIsPageInEditModeComponentState,
);
- const { actionMenuType } = useContext(ActionMenuContext);
+ const { containerType } = useContext(CommandMenuContext);
const contextStoreCurrentObjectMetadataItemId = useAtomComponentStateValue(
contextStoreCurrentObjectMetadataItemIdComponentState,
@@ -166,8 +166,8 @@ export const useCommandMenuItemFrontComponentActions = (
const { data } = useFindManyCommandMenuItemsQuery({
skip:
!isCommandMenuItemEnabled ||
- (actionMenuType !== 'command-menu' &&
- actionMenuType !== 'command-menu-show-page-action-menu-dropdown'),
+ (containerType !== 'command-menu-list' &&
+ containerType !== 'command-menu-show-page-dropdown'),
});
const frontComponentItems =
@@ -200,10 +200,10 @@ export const useCommandMenuItemFrontComponentActions = (
);
});
- const globalActions = globalItems.map((item, index) =>
- buildActionFromItem({
+ const globalCommandMenuItems = globalItems.map((item, index) =>
+ buildCommandMenuItemFromFrontComponent({
item,
- scope: ActionScope.Global,
+ scope: CommandMenuItemScope.Global,
index,
isPinned: !contextStoreIsPageInEditMode && item.isPinned,
getIcon,
@@ -213,10 +213,10 @@ export const useCommandMenuItemFrontComponentActions = (
}),
);
- const recordScopedActions = recordScopedItems.map((item, index) =>
- buildActionFromItem({
+ const recordScopedCommandMenuItems = recordScopedItems.map((item, index) =>
+ buildCommandMenuItemFromFrontComponent({
item,
- scope: ActionScope.RecordSelection,
+ scope: CommandMenuItemScope.RecordSelection,
index,
isPinned: !contextStoreIsPageInEditMode && item.isPinned,
getIcon,
@@ -227,5 +227,5 @@ export const useCommandMenuItemFrontComponentActions = (
}),
);
- return [...globalActions, ...recordScopedActions];
+ return [...globalCommandMenuItems, ...recordScopedCommandMenuItems];
};
diff --git a/packages/twenty-front/src/modules/command-menu-item/hooks/useRegisteredCommandMenuItems.ts b/packages/twenty-front/src/modules/command-menu-item/hooks/useRegisteredCommandMenuItems.ts
new file mode 100644
index 0000000000..5308bbd3be
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/hooks/useRegisteredCommandMenuItems.ts
@@ -0,0 +1,96 @@
+import { useRecordAgnosticCommands } from '@/command-menu-item/record-agnostic/hooks/useRecordAgnosticCommands';
+import { useRelatedRecordCommands } from '@/command-menu-item/record-agnostic/hooks/useRelatedRecordCommands';
+import { CommandMenuItemViewType } from 'twenty-shared/types';
+import { type ShouldBeRegisteredFunctionParams } from '@/command-menu-item/types/ShouldBeRegisteredFunctionParams';
+import { getCommandMenuItemConfig } from '@/command-menu-item/utils/getCommandMenuItemConfig';
+import { getCommandMenuItemViewType } from '@/command-menu-item/utils/getCommandMenuItemViewType';
+import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
+import { contextStoreIsPageInEditModeComponentState } from '@/context-store/states/contextStoreIsPageInEditModeComponentState';
+import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
+import { usePermissionFlagMap } from '@/settings/roles/hooks/usePermissionFlagMap';
+import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
+import { isDefined } from 'twenty-shared/utils';
+import { useIcons } from 'twenty-ui/display';
+
+export const useRegisteredCommandMenuItems = (
+ shouldBeRegisteredParams: ShouldBeRegisteredFunctionParams,
+) => {
+ const { objectMetadataItem } = shouldBeRegisteredParams;
+
+ const { getIcon } = useIcons();
+
+ const contextStoreTargetedRecordsRule = useAtomComponentStateValue(
+ contextStoreTargetedRecordsRuleComponentState,
+ );
+
+ const contextStoreCurrentViewType = useAtomComponentStateValue(
+ contextStoreCurrentViewTypeComponentState,
+ );
+
+ const contextStoreIsPageInEditMode = useAtomComponentStateValue(
+ contextStoreIsPageInEditModeComponentState,
+ );
+
+ const viewType = getCommandMenuItemViewType(
+ contextStoreCurrentViewType,
+ contextStoreTargetedRecordsRule,
+ );
+
+ const recordCommandMenuItemsConfig = getCommandMenuItemConfig({
+ objectMetadataItem,
+ });
+
+ const relatedRecordCommandMenuItemsConfig = useRelatedRecordCommands({
+ sourceObjectMetadataItem: objectMetadataItem,
+ getIcon,
+ startPosition: Object.keys(recordCommandMenuItemsConfig).length + 1,
+ });
+
+ const recordAgnosticCommandMenuItemsConfig = useRecordAgnosticCommands();
+
+ const commandMenuItemsConfig = {
+ ...recordCommandMenuItemsConfig,
+ ...relatedRecordCommandMenuItemsConfig,
+ ...recordAgnosticCommandMenuItemsConfig,
+ };
+
+ const permissionMap = usePermissionFlagMap();
+
+ const commandMenuItemsToRegister = Object.values(
+ commandMenuItemsConfig,
+ ).filter((commandMenuItem) => {
+ if (contextStoreIsPageInEditMode) {
+ return (
+ isDefined(commandMenuItem.availableOn) &&
+ commandMenuItem.availableOn.includes(
+ CommandMenuItemViewType.PAGE_EDIT_MODE,
+ )
+ );
+ }
+
+ if (isDefined(viewType)) {
+ return (
+ commandMenuItem.availableOn?.includes(viewType) ||
+ commandMenuItem.availableOn?.includes(CommandMenuItemViewType.GLOBAL)
+ );
+ }
+
+ return commandMenuItem.availableOn?.includes(
+ CommandMenuItemViewType.GLOBAL,
+ );
+ });
+
+ const commandMenuItems = commandMenuItemsToRegister
+ .filter((commandMenuItem) => {
+ if (
+ isDefined(commandMenuItem.requiredPermissionFlag) &&
+ !permissionMap[commandMenuItem.requiredPermissionFlag]
+ ) {
+ return false;
+ }
+ return commandMenuItem.shouldBeRegistered(shouldBeRegisteredParams);
+ })
+ .sort((a, b) => a.position - b.position);
+
+ return commandMenuItems;
+};
diff --git a/packages/twenty-front/src/modules/action-menu/hooks/useShouldActionBeRegisteredParams.ts b/packages/twenty-front/src/modules/command-menu-item/hooks/useShouldCommandMenuItemBeRegisteredParams.ts
similarity index 92%
rename from packages/twenty-front/src/modules/action-menu/hooks/useShouldActionBeRegisteredParams.ts
rename to packages/twenty-front/src/modules/command-menu-item/hooks/useShouldCommandMenuItemBeRegisteredParams.ts
index 41012f1805..efad4feef3 100644
--- a/packages/twenty-front/src/modules/action-menu/hooks/useShouldActionBeRegisteredParams.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/hooks/useShouldCommandMenuItemBeRegisteredParams.ts
@@ -1,6 +1,6 @@
-import { type ShouldBeRegisteredFunctionParams } from '@/action-menu/actions/types/ShouldBeRegisteredFunctionParams';
-import { getActionViewType } from '@/action-menu/actions/utils/getActionViewType';
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
+import { type ShouldBeRegisteredFunctionParams } from '@/command-menu-item/types/ShouldBeRegisteredFunctionParams';
+import { getCommandMenuItemViewType } from '@/command-menu-item/utils/getCommandMenuItemViewType';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
import { currentWorkspaceState } from '@/auth/states/currentWorkspaceState';
import { objectPermissionsFamilySelector } from '@/auth/states/objectPermissionsFamilySelector';
import { contextStoreCurrentViewTypeComponentState } from '@/context-store/states/contextStoreCurrentViewTypeComponentState';
@@ -25,7 +25,7 @@ import { useCallback, useContext, useMemo } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { FeatureFlagKey } from '~/generated-metadata/graphql';
-export const useShouldActionBeRegisteredParams = ({
+export const useShouldCommandMenuItemBeRegisteredParams = ({
objectMetadataItem,
}: {
objectMetadataItem?: ObjectMetadataItem;
@@ -84,7 +84,7 @@ export const useShouldActionBeRegisteredParams = ({
objectMetadataItem?.nameSingular === CoreObjectNameSingular.Note ||
objectMetadataItem?.nameSingular === CoreObjectNameSingular.Task;
- const { isInSidePanel } = useContext(ActionMenuContext);
+ const { isInSidePanel } = useContext(CommandMenuContext);
const { recordIndexId } = useRecordIndexIdFromCurrentContextStore();
@@ -105,7 +105,7 @@ export const useShouldActionBeRegisteredParams = ({
contextStoreCurrentViewTypeComponentState,
);
- const viewType = getActionViewType(
+ const viewType = getCommandMenuItemViewType(
contextStoreCurrentViewType,
contextStoreTargetedRecordsRule,
);
diff --git a/packages/twenty-front/src/modules/command-menu-item/mock/command-menu-items.mock.tsx b/packages/twenty-front/src/modules/command-menu-item/mock/command-menu-items.mock.tsx
new file mode 100644
index 0000000000..0eae11ebc2
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/mock/command-menu-items.mock.tsx
@@ -0,0 +1,104 @@
+import { Command } from '@/command-menu-item/display/components/Command';
+import { CommandLink } from '@/command-menu-item/display/components/CommandLink';
+import { NoSelectionRecordCommandKeys } from '@/command-menu-item/record/no-selection/types/NoSelectionRecordCommandKeys';
+import { SingleRecordCommandKeys } from '@/command-menu-item/record/single-record/types/SingleRecordCommandKeys';
+import { type CommandMenuItemConfig } from '@/command-menu-item/types/CommandMenuItemConfig';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
+import {
+ CommandMenuItemViewType,
+ CoreObjectNameSingular,
+ AppPath,
+} from 'twenty-shared/types';
+import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
+import { msg } from '@lingui/core/macro';
+import {
+ IconFileExport,
+ IconHeart,
+ IconTrash,
+ IconUser,
+} from 'twenty-ui/display';
+
+export const createMockCommandMenuItems = ({
+ deleteMock = () => {},
+ addToFavoritesMock = () => {},
+ exportMock = () => {},
+}: {
+ deleteMock?: () => void;
+ addToFavoritesMock?: () => void;
+ exportMock?: () => void;
+}): CommandMenuItemConfig[] => [
+ {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: SingleRecordCommandKeys.ADD_TO_FAVORITES,
+ label: msg`Add to favorites`,
+ shortLabel: msg`Add to favorites`,
+ position: 2,
+ isPinned: true,
+ Icon: IconHeart,
+ shouldBeRegistered: () => true,
+ availableOn: [
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ ],
+ component: ,
+ },
+ {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: SingleRecordCommandKeys.EXPORT_FROM_RECORD_INDEX,
+ label: msg`Export`,
+ shortLabel: msg`Export`,
+ position: 4,
+ Icon: IconFileExport,
+ accent: 'default',
+ isPinned: false,
+ shouldBeRegistered: () => true,
+ availableOn: [CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION],
+ component: ,
+ },
+ {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: SingleRecordCommandKeys.DELETE,
+ label: msg`Delete`,
+ shortLabel: msg`Delete`,
+ position: 7,
+ Icon: IconTrash,
+ accent: 'default',
+ isPinned: true,
+ shouldBeRegistered: () => true,
+ availableOn: [
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ ],
+ component: ,
+ },
+ {
+ type: CommandMenuItemType.Navigation,
+ scope: CommandMenuItemScope.Global,
+ key: NoSelectionRecordCommandKeys.GO_TO_PEOPLE,
+ label: msg`Go to People`,
+ shortLabel: msg`People`,
+ position: 19,
+ Icon: IconUser,
+ isPinned: false,
+ availableOn: [
+ CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ ],
+ shouldBeRegistered: ({ objectMetadataItem, viewType }) =>
+ objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Person ||
+ viewType === CommandMenuItemViewType.SHOW_PAGE,
+ component: (
+
+ ),
+ hotKeys: ['G', 'P'],
+ },
+];
diff --git a/packages/twenty-front/src/modules/command-menu-item/record-agnostic/constants/RecordAgnosticCommandMenuItemsConfig.tsx b/packages/twenty-front/src/modules/command-menu-item/record-agnostic/constants/RecordAgnosticCommandMenuItemsConfig.tsx
new file mode 100644
index 0000000000..f2a6cb34e0
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/record-agnostic/constants/RecordAgnosticCommandMenuItemsConfig.tsx
@@ -0,0 +1,117 @@
+import { CommandMenuItemOpenSidePanelPage } from '@/command-menu-item/display/components/CommandMenuItemOpenSidePanelPage';
+import { RecordAgnosticCommandKeys } from '@/command-menu-item/record-agnostic/types/RecordAgnosticCommandKeys';
+import { EditNavigationSidebarNoSelectionRecordCommand } from '@/command-menu-item/record/no-selection/components/EditNavigationSidebarNoSelectionRecordCommand';
+import { type CommandMenuItemConfig } from '@/command-menu-item/types/CommandMenuItemConfig';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
+import { CommandMenuItemViewType, SidePanelPages } from 'twenty-shared/types';
+import { msg } from '@lingui/core/macro';
+import {
+ IconHistory,
+ IconLayout,
+ IconSearch,
+ IconSparkles,
+} from 'twenty-ui/display';
+import { FeatureFlagKey } from '~/generated-metadata/graphql';
+
+export const RECORD_AGNOSTIC_COMMAND_MENU_ITEMS_CONFIG: Record<
+ string,
+ CommandMenuItemConfig
+> = {
+ [RecordAgnosticCommandKeys.SEARCH_RECORDS]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.Global,
+ key: RecordAgnosticCommandKeys.SEARCH_RECORDS,
+ label: msg`Search records`,
+ shortLabel: msg`Search`,
+ position: 0,
+ isPinned: false,
+ Icon: IconSearch,
+ availableOn: [CommandMenuItemViewType.GLOBAL],
+ component: (
+
+ ),
+ hotKeys: ['/'],
+ shouldBeRegistered: () => true,
+ },
+ [RecordAgnosticCommandKeys.SEARCH_RECORDS_FALLBACK]: {
+ type: CommandMenuItemType.Fallback,
+ scope: CommandMenuItemScope.Global,
+ key: RecordAgnosticCommandKeys.SEARCH_RECORDS_FALLBACK,
+ label: msg`Search records`,
+ shortLabel: msg`Search`,
+ position: 1,
+ isPinned: false,
+ Icon: IconSearch,
+ availableOn: [CommandMenuItemViewType.GLOBAL],
+ component: (
+
+ ),
+ hotKeys: ['/'],
+ shouldBeRegistered: () => true,
+ },
+ [RecordAgnosticCommandKeys.ASK_AI]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.Global,
+ key: RecordAgnosticCommandKeys.ASK_AI,
+ label: msg`Ask AI`,
+ shortLabel: msg`Ask AI`,
+ position: 2,
+ isPinned: false,
+ Icon: IconSparkles,
+ availableOn: [CommandMenuItemViewType.GLOBAL],
+ component: (
+
+ ),
+ hotKeys: ['@'],
+ shouldBeRegistered: () => true,
+ },
+ [RecordAgnosticCommandKeys.VIEW_PREVIOUS_AI_CHATS]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.Global,
+ key: RecordAgnosticCommandKeys.VIEW_PREVIOUS_AI_CHATS,
+ label: msg`View Previous AI Chats`,
+ shortLabel: msg`Previous AI Chats`,
+ position: 3,
+ isPinned: false,
+ Icon: IconHistory,
+ availableOn: [CommandMenuItemViewType.GLOBAL],
+ component: (
+
+ ),
+ shouldBeRegistered: () => true,
+ },
+ [RecordAgnosticCommandKeys.EDIT_NAVIGATION_SIDEBAR]: {
+ type: CommandMenuItemType.Navigation,
+ scope: CommandMenuItemScope.Global,
+ key: RecordAgnosticCommandKeys.EDIT_NAVIGATION_SIDEBAR,
+ label: msg`Edit navigation sidebar`,
+ shortLabel: msg`Edit sidebar`,
+ position: 4,
+ Icon: IconLayout,
+ isPinned: false,
+ availableOn: [CommandMenuItemViewType.GLOBAL],
+ shouldBeRegistered: ({ isFeatureFlagEnabled }) =>
+ isFeatureFlagEnabled(
+ FeatureFlagKey.IS_NAVIGATION_MENU_ITEM_EDITING_ENABLED,
+ ),
+ component: ,
+ },
+};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/hooks/__tests__/useRelatedRecordActions.test.tsx b/packages/twenty-front/src/modules/command-menu-item/record-agnostic/hooks/__tests__/useRelatedRecordCommands.test.tsx
similarity index 94%
rename from packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/hooks/__tests__/useRelatedRecordActions.test.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record-agnostic/hooks/__tests__/useRelatedRecordCommands.test.tsx
index 95da8fa872..f11e54b03c 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/hooks/__tests__/useRelatedRecordActions.test.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record-agnostic/hooks/__tests__/useRelatedRecordCommands.test.tsx
@@ -1,7 +1,7 @@
import { CoreObjectNameSingular } from 'twenty-shared/types';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { renderHook } from '@testing-library/react';
-import { useRelatedRecordActions } from '@/action-menu/actions/record-agnostic-actions/hooks/useRelatedRecordActions';
+import { useRelatedRecordCommands } from '@/command-menu-item/record-agnostic/hooks/useRelatedRecordCommands';
jest.mock('@/object-metadata/hooks/useObjectMetadataItems', () => ({
useObjectMetadataItems: () => ({
@@ -22,7 +22,7 @@ jest.mock('@/object-metadata/hooks/useObjectMetadataItems', () => ({
}),
}));
-describe('useRelatedRecordActions', () => {
+describe('useRelatedRecordCommands', () => {
const mockGetIcon = jest.fn();
beforeEach(() => {
@@ -37,7 +37,7 @@ describe('useRelatedRecordActions', () => {
} as unknown as ObjectMetadataItem;
const { result } = renderHook(() =>
- useRelatedRecordActions({
+ useRelatedRecordCommands({
sourceObjectMetadataItem: objectMetadataItem,
getIcon: mockGetIcon,
startPosition: 18,
@@ -51,7 +51,7 @@ describe('useRelatedRecordActions', () => {
const objectMetadataItem = undefined as unknown as ObjectMetadataItem;
const { result } = renderHook(() =>
- useRelatedRecordActions({
+ useRelatedRecordCommands({
sourceObjectMetadataItem: objectMetadataItem,
getIcon: mockGetIcon,
startPosition: 18,
@@ -95,7 +95,7 @@ describe('useRelatedRecordActions', () => {
} as unknown as ObjectMetadataItem;
const { result } = renderHook(() =>
- useRelatedRecordActions({
+ useRelatedRecordCommands({
sourceObjectMetadataItem: objectMetadataItem,
getIcon: mockGetIcon,
startPosition: 18,
@@ -145,7 +145,7 @@ describe('useRelatedRecordActions', () => {
} as unknown as ObjectMetadataItem;
const { result } = renderHook(() =>
- useRelatedRecordActions({
+ useRelatedRecordCommands({
sourceObjectMetadataItem: objectMetadataItem,
getIcon: mockGetIcon,
startPosition: 18,
@@ -191,7 +191,7 @@ describe('useRelatedRecordActions', () => {
} as unknown as ObjectMetadataItem;
const { result } = renderHook(() =>
- useRelatedRecordActions({
+ useRelatedRecordCommands({
sourceObjectMetadataItem: objectMetadataItem,
getIcon: mockGetIcon,
startPosition: 18,
@@ -237,7 +237,7 @@ describe('useRelatedRecordActions', () => {
} as unknown as ObjectMetadataItem;
const { result } = renderHook(() =>
- useRelatedRecordActions({
+ useRelatedRecordCommands({
sourceObjectMetadataItem: objectMetadataItem,
getIcon: mockGetIcon,
startPosition: 18,
diff --git a/packages/twenty-front/src/modules/command-menu-item/record-agnostic/hooks/useRecordAgnosticCommands.ts b/packages/twenty-front/src/modules/command-menu-item/record-agnostic/hooks/useRecordAgnosticCommands.ts
new file mode 100644
index 0000000000..ddfbec5b76
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/record-agnostic/hooks/useRecordAgnosticCommands.ts
@@ -0,0 +1,37 @@
+import { RECORD_AGNOSTIC_COMMAND_MENU_ITEMS_CONFIG } from '@/command-menu-item/record-agnostic/constants/RecordAgnosticCommandMenuItemsConfig';
+import { RecordAgnosticCommandKeys } from '@/command-menu-item/record-agnostic/types/RecordAgnosticCommandKeys';
+import { type CommandMenuItemConfig } from '@/command-menu-item/types/CommandMenuItemConfig';
+import { useIsFeatureEnabled } from '@/workspace/hooks/useIsFeatureEnabled';
+import { FeatureFlagKey } from '~/generated-metadata/graphql';
+
+export const useRecordAgnosticCommands = () => {
+ const isAiEnabled = useIsFeatureEnabled(FeatureFlagKey.IS_AI_ENABLED);
+
+ const commandMenuItems: Record = {
+ [RecordAgnosticCommandKeys.SEARCH_RECORDS]:
+ RECORD_AGNOSTIC_COMMAND_MENU_ITEMS_CONFIG[
+ RecordAgnosticCommandKeys.SEARCH_RECORDS
+ ],
+ [RecordAgnosticCommandKeys.SEARCH_RECORDS_FALLBACK]:
+ RECORD_AGNOSTIC_COMMAND_MENU_ITEMS_CONFIG[
+ RecordAgnosticCommandKeys.SEARCH_RECORDS_FALLBACK
+ ],
+ [RecordAgnosticCommandKeys.EDIT_NAVIGATION_SIDEBAR]:
+ RECORD_AGNOSTIC_COMMAND_MENU_ITEMS_CONFIG[
+ RecordAgnosticCommandKeys.EDIT_NAVIGATION_SIDEBAR
+ ],
+ };
+
+ if (isAiEnabled) {
+ commandMenuItems[RecordAgnosticCommandKeys.ASK_AI] =
+ RECORD_AGNOSTIC_COMMAND_MENU_ITEMS_CONFIG[
+ RecordAgnosticCommandKeys.ASK_AI
+ ];
+ commandMenuItems[RecordAgnosticCommandKeys.VIEW_PREVIOUS_AI_CHATS] =
+ RECORD_AGNOSTIC_COMMAND_MENU_ITEMS_CONFIG[
+ RecordAgnosticCommandKeys.VIEW_PREVIOUS_AI_CHATS
+ ];
+ }
+
+ return commandMenuItems;
+};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/hooks/useRelatedRecordActions.ts b/packages/twenty-front/src/modules/command-menu-item/record-agnostic/hooks/useRelatedRecordCommands.ts
similarity index 75%
rename from packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/hooks/useRelatedRecordActions.ts
rename to packages/twenty-front/src/modules/command-menu-item/record-agnostic/hooks/useRelatedRecordCommands.ts
index 2175137271..d91a488244 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/hooks/useRelatedRecordActions.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/record-agnostic/hooks/useRelatedRecordCommands.ts
@@ -1,8 +1,11 @@
-import { CreateRelatedRecordAction } from '@/action-menu/actions/record-actions/single-record/components/CreateRelatedRecordAction';
-import { type ActionConfig } from '@/action-menu/actions/types/ActionConfig';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionType } from '@/action-menu/actions/types/ActionType';
-import { ActionViewType, CoreObjectNameSingular } from 'twenty-shared/types';
+import { CreateRelatedRecordCommand } from '@/command-menu-item/record/single-record/components/CreateRelatedRecordCommand';
+import { type CommandMenuItemConfig } from '@/command-menu-item/types/CommandMenuItemConfig';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
+import {
+ CommandMenuItemViewType,
+ CoreObjectNameSingular,
+} from 'twenty-shared/types';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { isHiddenSystemField } from '@/object-metadata/utils/isHiddenSystemField';
@@ -12,23 +15,26 @@ import React from 'react';
import { isDefined } from 'twenty-shared/utils';
import { type IconComponent, IconPlus } from 'twenty-ui/display';
-interface GenerateRelatedRecordActionsParams {
+interface GenerateRelatedRecordCommandsParams {
sourceObjectMetadataItem?: ObjectMetadataItem;
getIcon: (iconKey: string) => IconComponent;
startPosition: number;
}
-export const useRelatedRecordActions = ({
+export const useRelatedRecordCommands = ({
sourceObjectMetadataItem,
getIcon,
startPosition,
-}: GenerateRelatedRecordActionsParams): Record => {
- const relatedActions: Record = {};
+}: GenerateRelatedRecordCommandsParams): Record<
+ string,
+ CommandMenuItemConfig
+> => {
+ const relatedCommands: Record = {};
const { objectMetadataItems } = useObjectMetadataItems();
if (!sourceObjectMetadataItem?.fields) {
- return relatedActions;
+ return relatedCommands;
}
const oneToManyFields = sourceObjectMetadataItem.readableFields.filter(
@@ -67,9 +73,9 @@ export const useRelatedRecordActions = ({
const actionKey = `create-related-${targetObjectLabelSingular}`;
- relatedActions[actionKey] = {
- type: ActionType.Standard,
- scope: ActionScope.CreateRelatedRecord,
+ relatedCommands[actionKey] = {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.CreateRelatedRecord,
key: actionKey,
label: msg`Create ${targetObjectLabelSingular}`,
shortLabel: msg`Create ${targetObjectLabelSingular}`,
@@ -103,10 +109,10 @@ export const useRelatedRecordActions = ({
)) ??
false,
availableOn: [
- ActionViewType.SHOW_PAGE,
- ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
],
- component: React.createElement(CreateRelatedRecordAction, {
+ component: React.createElement(CreateRelatedRecordCommand, {
targetFieldMetadataItemRelation: field.relation,
}),
};
@@ -114,5 +120,5 @@ export const useRelatedRecordActions = ({
currentPosition++;
}
- return relatedActions;
+ return relatedCommands;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/types/RecordAgnosticActionsKeys.ts b/packages/twenty-front/src/modules/command-menu-item/record-agnostic/types/RecordAgnosticCommandKeys.ts
similarity index 84%
rename from packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/types/RecordAgnosticActionsKeys.ts
rename to packages/twenty-front/src/modules/command-menu-item/record-agnostic/types/RecordAgnosticCommandKeys.ts
index f6881f71a8..188fd96709 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/types/RecordAgnosticActionsKeys.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/record-agnostic/types/RecordAgnosticCommandKeys.ts
@@ -1,4 +1,4 @@
-export enum RecordAgnosticActionsKeys {
+export enum RecordAgnosticCommandKeys {
SEARCH_RECORDS = 'search-records',
SEARCH_RECORDS_FALLBACK = 'search-records-fallback',
ASK_AI = 'ask-ai',
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/run-workflow-actions/hooks/useRunWorkflowRecordAgnosticActions.tsx b/packages/twenty-front/src/modules/command-menu-item/record-agnostic/workflow/hooks/useRunWorkflowRecordAgnosticCommands.tsx
similarity index 73%
rename from packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/run-workflow-actions/hooks/useRunWorkflowRecordAgnosticActions.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record-agnostic/workflow/hooks/useRunWorkflowRecordAgnosticCommands.tsx
index 7a4332f1ec..99e9fd753b 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-agnostic-actions/run-workflow-actions/hooks/useRunWorkflowRecordAgnosticActions.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record-agnostic/workflow/hooks/useRunWorkflowRecordAgnosticCommands.tsx
@@ -1,7 +1,7 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionType } from '@/action-menu/actions/types/ActionType';
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
import { contextStoreIsPageInEditModeComponentState } from '@/context-store/states/contextStoreIsPageInEditModeComponentState';
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
import { useActiveWorkflowVersionsWithManualTrigger } from '@/workflow/hooks/useActiveWorkflowVersionsWithManualTrigger';
@@ -11,20 +11,20 @@ import { useContext } from 'react';
import { capitalize, isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
-export const useRunWorkflowRecordAgnosticActions = () => {
+export const useRunWorkflowRecordAgnosticCommands = () => {
const { getIcon } = useIcons();
const contextStoreIsPageInEditMode = useAtomComponentStateValue(
contextStoreIsPageInEditModeComponentState,
);
- const { actionMenuType } = useContext(ActionMenuContext);
+ const { containerType } = useContext(CommandMenuContext);
const { records: activeWorkflowVersions } =
useActiveWorkflowVersionsWithManualTrigger({
skip:
- actionMenuType !== 'command-menu' &&
- actionMenuType !== 'command-menu-show-page-action-menu-dropdown',
+ containerType !== 'command-menu-list' &&
+ containerType !== 'command-menu-show-page-dropdown',
});
const { runWorkflowVersion } = useRunWorkflowVersion();
@@ -43,9 +43,9 @@ export const useRunWorkflowRecordAgnosticActions = () => {
);
return {
- type: ActionType.WorkflowRun,
+ type: CommandMenuItemType.WorkflowRun,
key: `workflow-run-${activeWorkflowVersion.id}`,
- scope: ActionScope.Global,
+ scope: CommandMenuItemScope.Global,
label: name,
shortLabel: name,
position: index,
@@ -55,14 +55,14 @@ export const useRunWorkflowRecordAgnosticActions = () => {
Icon,
shouldBeRegistered: () => true,
component: (
- {
runWorkflowVersion({
workflowVersionId: activeWorkflowVersion.id,
workflowId: activeWorkflowVersion.workflowId,
});
}}
- closeSidePanelOnCommandMenuListActionExecution={false}
+ closeSidePanelOnCommandMenuListExecution={false}
/>
),
};
diff --git a/packages/twenty-front/src/modules/command-menu-item/record/constants/DashboardCommandMenuItemsConfig.tsx b/packages/twenty-front/src/modules/command-menu-item/record/constants/DashboardCommandMenuItemsConfig.tsx
new file mode 100644
index 0000000000..a1a30f716f
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/record/constants/DashboardCommandMenuItemsConfig.tsx
@@ -0,0 +1,204 @@
+import { MultipleRecordsCommandKeys } from '@/command-menu-item/record/multiple-records/types/MultipleRecordsCommandKeys';
+import { NoSelectionRecordCommandKeys } from '@/command-menu-item/record/no-selection/types/NoSelectionRecordCommandKeys';
+import { CancelDashboardSingleRecordCommand } from '@/command-menu-item/record/single-record/dashboard/components/CancelDashboardSingleRecordCommand';
+import { DuplicateDashboardSingleRecordCommand } from '@/command-menu-item/record/single-record/dashboard/components/DuplicateDashboardSingleRecordCommand';
+import { EditDashboardSingleRecordCommand } from '@/command-menu-item/record/single-record/dashboard/components/EditDashboardSingleRecordCommand';
+import { SaveDashboardSingleRecordCommand } from '@/command-menu-item/record/single-record/dashboard/components/SaveDashboardSingleRecordCommand';
+import { DashboardSingleRecordCommandKeys } from '@/command-menu-item/record/single-record/dashboard/types/DashboardSingleRecordCommandKeys';
+import { SingleRecordCommandKeys } from '@/command-menu-item/record/single-record/types/SingleRecordCommandKeys';
+import { inheritCommandMenuItemsFromDefaultConfig } from '@/command-menu-item/record/utils/inheritCommandMenuItemsFromDefaultConfig';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
+import { CommandMenuItemViewType } from 'twenty-shared/types';
+import { PageLayoutSingleRecordActionKeys } from '@/page-layout/actions/PageLayoutSingleRecordActionKeys';
+import { msg } from '@lingui/core/macro';
+import { isDefined } from 'twenty-shared/utils';
+import {
+ IconCancel,
+ IconCopyPlus,
+ IconDeviceFloppy,
+ IconPencil,
+} from 'twenty-ui/display';
+
+export const DASHBOARD_COMMAND_MENU_ITEMS_CONFIG =
+ inheritCommandMenuItemsFromDefaultConfig({
+ config: {
+ [PageLayoutSingleRecordActionKeys.EDIT_LAYOUT]: {
+ key: PageLayoutSingleRecordActionKeys.EDIT_LAYOUT,
+ label: msg`Edit Dashboard`,
+ shortLabel: msg`Edit`,
+ isPinned: true,
+ position: 3,
+ Icon: IconPencil,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ shouldBeRegistered: ({ selectedRecord, objectPermissions }) =>
+ isDefined(selectedRecord) &&
+ !selectedRecord?.isRemote &&
+ !isDefined(selectedRecord?.deletedAt) &&
+ isDefined(selectedRecord?.pageLayoutId) &&
+ objectPermissions.canUpdateObjectRecords,
+ availableOn: [CommandMenuItemViewType.SHOW_PAGE],
+ component: ,
+ },
+ [PageLayoutSingleRecordActionKeys.SAVE_LAYOUT]: {
+ key: PageLayoutSingleRecordActionKeys.SAVE_LAYOUT,
+ label: msg`Save Dashboard`,
+ shortLabel: msg`Save`,
+ isPinned: true,
+ isPrimaryCTA: true,
+ position: 4,
+ Icon: IconDeviceFloppy,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ shouldBeRegistered: ({ selectedRecord, objectPermissions }) =>
+ isDefined(selectedRecord) &&
+ !selectedRecord?.isRemote &&
+ !isDefined(selectedRecord?.deletedAt) &&
+ isDefined(selectedRecord?.pageLayoutId) &&
+ objectPermissions.canUpdateObjectRecords,
+ availableOn: [CommandMenuItemViewType.PAGE_EDIT_MODE],
+ component: ,
+ },
+ [PageLayoutSingleRecordActionKeys.CANCEL_LAYOUT_EDITION]: {
+ key: PageLayoutSingleRecordActionKeys.CANCEL_LAYOUT_EDITION,
+ label: msg`Cancel Edition`,
+ shortLabel: msg`Cancel`,
+ isPinned: true,
+ position: 5,
+ Icon: IconCancel,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ shouldBeRegistered: ({ selectedRecord, objectPermissions }) =>
+ isDefined(selectedRecord) &&
+ !selectedRecord?.isRemote &&
+ !isDefined(selectedRecord?.deletedAt) &&
+ isDefined(selectedRecord?.pageLayoutId) &&
+ objectPermissions.canUpdateObjectRecords,
+ availableOn: [CommandMenuItemViewType.PAGE_EDIT_MODE],
+ component: ,
+ },
+ [DashboardSingleRecordCommandKeys.DUPLICATE_DASHBOARD]: {
+ key: DashboardSingleRecordCommandKeys.DUPLICATE_DASHBOARD,
+ label: msg`Duplicate Dashboard`,
+ shortLabel: msg`Duplicate`,
+ isPinned: false,
+ position: 6,
+ Icon: IconCopyPlus,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ shouldBeRegistered: ({ selectedRecord, objectPermissions }) =>
+ isDefined(selectedRecord) &&
+ !selectedRecord?.isRemote &&
+ !isDefined(selectedRecord?.deletedAt) &&
+ objectPermissions.canUpdateObjectRecords,
+ availableOn: [
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ ],
+ component: ,
+ },
+ },
+ commandKeys: [
+ NoSelectionRecordCommandKeys.CREATE_NEW_RECORD,
+ SingleRecordCommandKeys.ADD_TO_FAVORITES,
+ SingleRecordCommandKeys.REMOVE_FROM_FAVORITES,
+ SingleRecordCommandKeys.DELETE,
+ SingleRecordCommandKeys.DESTROY,
+ SingleRecordCommandKeys.RESTORE,
+ MultipleRecordsCommandKeys.DELETE,
+ MultipleRecordsCommandKeys.DESTROY,
+ MultipleRecordsCommandKeys.RESTORE,
+ NoSelectionRecordCommandKeys.SEE_DELETED_RECORDS,
+ NoSelectionRecordCommandKeys.HIDE_DELETED_RECORDS,
+ SingleRecordCommandKeys.EXPORT_FROM_RECORD_SHOW,
+ SingleRecordCommandKeys.NAVIGATE_TO_PREVIOUS_RECORD,
+ SingleRecordCommandKeys.NAVIGATE_TO_NEXT_RECORD,
+ NoSelectionRecordCommandKeys.GO_TO_WORKFLOWS,
+ NoSelectionRecordCommandKeys.GO_TO_PEOPLE,
+ NoSelectionRecordCommandKeys.GO_TO_COMPANIES,
+ NoSelectionRecordCommandKeys.GO_TO_OPPORTUNITIES,
+ NoSelectionRecordCommandKeys.GO_TO_SETTINGS,
+ NoSelectionRecordCommandKeys.GO_TO_TASKS,
+ NoSelectionRecordCommandKeys.GO_TO_NOTES,
+ ],
+ propertiesToOverwrite: {
+ [SingleRecordCommandKeys.NAVIGATE_TO_NEXT_RECORD]: {
+ position: 0,
+ label: msg`Navigate to next dashboard`,
+ },
+ [SingleRecordCommandKeys.NAVIGATE_TO_PREVIOUS_RECORD]: {
+ position: 1,
+ label: msg`Navigate to previous dashboard`,
+ },
+ [NoSelectionRecordCommandKeys.CREATE_NEW_RECORD]: {
+ position: 2,
+ label: msg`Create new dashboard`,
+ },
+ [SingleRecordCommandKeys.DELETE]: {
+ position: 7,
+ label: msg`Delete dashboard`,
+ },
+ [MultipleRecordsCommandKeys.DELETE]: {
+ position: 12,
+ label: msg`Delete dashboards`,
+ },
+ [SingleRecordCommandKeys.ADD_TO_FAVORITES]: {
+ position: 8,
+ isPinned: true,
+ },
+ [SingleRecordCommandKeys.REMOVE_FROM_FAVORITES]: {
+ position: 9,
+ isPinned: true,
+ },
+ [SingleRecordCommandKeys.EXPORT_FROM_RECORD_SHOW]: {
+ position: 10,
+ label: msg`Export dashboard`,
+ },
+ [SingleRecordCommandKeys.DESTROY]: {
+ position: 11,
+ label: msg`Permanently destroy dashboard`,
+ },
+ [MultipleRecordsCommandKeys.DESTROY]: {
+ position: 13,
+ label: msg`Permanently destroy dashboards`,
+ },
+ [SingleRecordCommandKeys.RESTORE]: {
+ position: 14,
+ label: msg`Restore dashboard`,
+ },
+ [MultipleRecordsCommandKeys.RESTORE]: {
+ position: 15,
+ label: msg`Restore dashboards`,
+ },
+ [NoSelectionRecordCommandKeys.SEE_DELETED_RECORDS]: {
+ position: 22,
+ label: msg`See deleted dashboards`,
+ },
+ [NoSelectionRecordCommandKeys.HIDE_DELETED_RECORDS]: {
+ position: 23,
+ label: msg`Hide deleted dashboards`,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_WORKFLOWS]: {
+ position: 24,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_PEOPLE]: {
+ position: 25,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_COMPANIES]: {
+ position: 26,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_OPPORTUNITIES]: {
+ position: 27,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_SETTINGS]: {
+ position: 28,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_TASKS]: {
+ position: 29,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_NOTES]: {
+ position: 30,
+ },
+ },
+ });
diff --git a/packages/twenty-front/src/modules/command-menu-item/record/constants/DefaultRecordCommandMenuItemsConfig.tsx b/packages/twenty-front/src/modules/command-menu-item/record/constants/DefaultRecordCommandMenuItemsConfig.tsx
new file mode 100644
index 0000000000..7bc3b12b5a
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/record/constants/DefaultRecordCommandMenuItemsConfig.tsx
@@ -0,0 +1,843 @@
+import { CommandLink } from '@/command-menu-item/display/components/CommandLink';
+import { DeleteMultipleRecordsCommand } from '@/command-menu-item/record/multiple-records/components/DeleteMultipleRecordsCommand';
+import { DestroyMultipleRecordsCommand } from '@/command-menu-item/record/multiple-records/components/DestroyMultipleRecordsCommand';
+import { ExportMultipleRecordsCommand } from '@/command-menu-item/record/multiple-records/components/ExportMultipleRecordsCommand';
+import { MergeMultipleRecordsCommand } from '@/command-menu-item/record/multiple-records/components/MergeMultipleRecordsCommand';
+import { RestoreMultipleRecordsCommand } from '@/command-menu-item/record/multiple-records/components/RestoreMultipleRecordsCommand';
+import { UpdateMultipleRecordsCommand } from '@/command-menu-item/record/multiple-records/components/UpdateMultipleRecordsCommand';
+import { MultipleRecordsCommandKeys } from '@/command-menu-item/record/multiple-records/types/MultipleRecordsCommandKeys';
+import { CreateNewIndexRecordNoSelectionRecordCommand } from '@/command-menu-item/record/no-selection/components/CreateNewIndexRecordNoSelectionRecordCommand';
+import { CreateNewViewNoSelectionRecordCommand } from '@/command-menu-item/record/no-selection/components/CreateNewViewNoSelectionRecordCommand';
+import { HideDeletedRecordsNoSelectionRecordCommand } from '@/command-menu-item/record/no-selection/components/HideDeletedRecordsNoSelectionRecordCommand';
+import { ImportRecordsNoSelectionRecordCommand } from '@/command-menu-item/record/no-selection/components/ImportRecordsNoSelectionRecordCommand';
+import { SeeDeletedRecordsNoSelectionRecordCommand } from '@/command-menu-item/record/no-selection/components/SeeDeletedRecordsNoSelectionRecordCommand';
+import { NoSelectionRecordCommandKeys } from '@/command-menu-item/record/no-selection/types/NoSelectionRecordCommandKeys';
+import { AddToFavoritesSingleRecordCommand } from '@/command-menu-item/record/single-record/components/AddToFavoritesSingleRecordCommand';
+import { DeleteSingleRecordCommand } from '@/command-menu-item/record/single-record/components/DeleteSingleRecordCommand';
+import { DestroySingleRecordCommand } from '@/command-menu-item/record/single-record/components/DestroySingleRecordCommand';
+import { ExportNoteSingleRecordCommand } from '@/command-menu-item/record/single-record/components/ExportNoteSingleRecordCommand';
+import { ExportSingleRecordCommand } from '@/command-menu-item/record/single-record/components/ExportSingleRecordCommand';
+import { NavigateToNextRecordSingleRecordCommand } from '@/command-menu-item/record/single-record/components/NavigateToNextRecordSingleRecordCommand';
+import { NavigateToPreviousRecordSingleRecordCommand } from '@/command-menu-item/record/single-record/components/NavigateToPreviousRecordSingleRecordCommand';
+import { RemoveFromFavoritesSingleRecordCommand } from '@/command-menu-item/record/single-record/components/RemoveFromFavoritesSingleRecordCommand';
+import { RestoreSingleRecordCommand } from '@/command-menu-item/record/single-record/components/RestoreSingleRecordCommand';
+import { CancelRecordPageLayoutSingleRecordCommand } from '@/command-menu-item/record/single-record/record-page-layout/components/CancelRecordPageLayoutSingleRecordCommand';
+import { EditRecordPageLayoutSingleRecordCommand } from '@/command-menu-item/record/single-record/record-page-layout/components/EditRecordPageLayoutSingleRecordCommand';
+import { SaveRecordPageLayoutSingleRecordCommand } from '@/command-menu-item/record/single-record/record-page-layout/components/SaveRecordPageLayoutSingleRecordCommand';
+import { RecordPageLayoutSingleRecordCommandKeys } from '@/command-menu-item/record/single-record/record-page-layout/types/RecordPageLayoutSingleRecordCommandKeys';
+import { SingleRecordCommandKeys } from '@/command-menu-item/record/single-record/types/SingleRecordCommandKeys';
+import { type CommandMenuItemConfig } from '@/command-menu-item/types/CommandMenuItemConfig';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
+import {
+ CommandMenuItemViewType,
+ CoreObjectNameSingular,
+ AppPath,
+ SettingsPath,
+} from 'twenty-shared/types';
+import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
+import {
+ BACKEND_BATCH_REQUEST_MAX_COUNT,
+ MUTATION_MAX_MERGE_RECORDS,
+} from 'twenty-shared/constants';
+import { msg } from '@lingui/core/macro';
+import { isNonEmptyString } from '@sniptt/guards';
+import {
+ IconArrowMerge,
+ IconBuildingSkyscraper,
+ IconCancel,
+ IconCheckbox,
+ IconChevronDown,
+ IconChevronUp,
+ IconDeviceFloppy,
+ IconEdit,
+ IconEyeOff,
+ IconFileExport,
+ IconFileImport,
+ IconHeart,
+ IconHeartOff,
+ IconLayout,
+ IconLayoutDashboard,
+ IconPencil,
+ IconPlus,
+ IconRefresh,
+ IconRotate2,
+ IconSettings,
+ IconSettingsAutomation,
+ IconTargetArrow,
+ IconTrash,
+ IconTrashX,
+ IconUser,
+} from 'twenty-ui/display';
+
+import { isDefined } from 'twenty-shared/utils';
+import {
+ PermissionFlagType,
+ FeatureFlagKey,
+} from '~/generated-metadata/graphql';
+
+export const DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG: Record<
+ | NoSelectionRecordCommandKeys
+ | SingleRecordCommandKeys
+ | MultipleRecordsCommandKeys
+ | RecordPageLayoutSingleRecordCommandKeys,
+ CommandMenuItemConfig
+> = {
+ [SingleRecordCommandKeys.NAVIGATE_TO_NEXT_RECORD]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: SingleRecordCommandKeys.NAVIGATE_TO_NEXT_RECORD,
+ label: msg`Navigate to next record`,
+ position: 0,
+ isPinned: true,
+ Icon: IconChevronDown,
+ shouldBeRegistered: ({ isInSidePanel }) => !isInSidePanel,
+ availableOn: [CommandMenuItemViewType.SHOW_PAGE],
+ component: ,
+ },
+ [SingleRecordCommandKeys.NAVIGATE_TO_PREVIOUS_RECORD]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: SingleRecordCommandKeys.NAVIGATE_TO_PREVIOUS_RECORD,
+ label: msg`Navigate to previous record`,
+ position: 1,
+ isPinned: true,
+ Icon: IconChevronUp,
+ shouldBeRegistered: ({ isInSidePanel }) => !isInSidePanel,
+ availableOn: [CommandMenuItemViewType.SHOW_PAGE],
+ component: ,
+ },
+ [NoSelectionRecordCommandKeys.CREATE_NEW_RECORD]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.Object,
+ key: NoSelectionRecordCommandKeys.CREATE_NEW_RECORD,
+ label: msg`Create new record`,
+ shortLabel: msg`New record`,
+ position: 2,
+ isPinned: true,
+ Icon: IconPlus,
+ shouldBeRegistered: ({ objectPermissions, hasAnySoftDeleteFilterOnView }) =>
+ (objectPermissions.canUpdateObjectRecords &&
+ !hasAnySoftDeleteFilterOnView) ??
+ false,
+ availableOn: [CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION],
+ component: ,
+ },
+ [SingleRecordCommandKeys.DELETE]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: SingleRecordCommandKeys.DELETE,
+ label: msg`Delete`,
+ shortLabel: msg`Delete`,
+ position: 3,
+ Icon: IconTrash,
+ accent: 'default',
+ isPinned: true,
+ shouldBeRegistered: ({
+ selectedRecord,
+ hasAnySoftDeleteFilterOnView,
+ objectPermissions,
+ }) =>
+ (isDefined(selectedRecord) &&
+ !selectedRecord.isRemote &&
+ !hasAnySoftDeleteFilterOnView &&
+ objectPermissions.canSoftDeleteObjectRecords &&
+ !isDefined(selectedRecord?.deletedAt)) ??
+ false,
+ availableOn: [
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ ],
+ component: ,
+ },
+ [MultipleRecordsCommandKeys.DELETE]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: MultipleRecordsCommandKeys.DELETE,
+ label: msg`Delete records`,
+ shortLabel: msg`Delete`,
+ position: 4,
+ Icon: IconTrash,
+ accent: 'default',
+ isPinned: true,
+ shouldBeRegistered: ({
+ objectPermissions,
+ isRemote,
+ hasAnySoftDeleteFilterOnView,
+ numberOfSelectedRecords,
+ }) =>
+ (objectPermissions.canSoftDeleteObjectRecords &&
+ !isRemote &&
+ !hasAnySoftDeleteFilterOnView &&
+ isDefined(numberOfSelectedRecords) &&
+ numberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT) ??
+ false,
+ availableOn: [CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION],
+ component: ,
+ },
+ [SingleRecordCommandKeys.RESTORE]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: SingleRecordCommandKeys.RESTORE,
+ label: msg`Restore record`,
+ shortLabel: msg`Restore`,
+ position: 5,
+ Icon: IconRefresh,
+ accent: 'default',
+ isPinned: true,
+ shouldBeRegistered: ({
+ selectedRecord,
+ objectPermissions,
+ isRemote,
+ isShowPage,
+ hasAnySoftDeleteFilterOnView,
+ }) =>
+ (!isRemote &&
+ isDefined(selectedRecord?.deletedAt) &&
+ objectPermissions.canSoftDeleteObjectRecords &&
+ ((isDefined(isShowPage) && isShowPage) ||
+ (isDefined(hasAnySoftDeleteFilterOnView) &&
+ hasAnySoftDeleteFilterOnView))) ??
+ false,
+ availableOn: [
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ ],
+ component: ,
+ },
+ [MultipleRecordsCommandKeys.RESTORE]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: MultipleRecordsCommandKeys.RESTORE,
+ label: msg`Restore records`,
+ shortLabel: msg`Restore`,
+ position: 6,
+ Icon: IconRefresh,
+ accent: 'default',
+ isPinned: true,
+ shouldBeRegistered: ({
+ objectPermissions,
+ isRemote,
+ hasAnySoftDeleteFilterOnView,
+ numberOfSelectedRecords,
+ }) =>
+ (objectPermissions.canSoftDeleteObjectRecords &&
+ !isRemote &&
+ isDefined(hasAnySoftDeleteFilterOnView) &&
+ hasAnySoftDeleteFilterOnView &&
+ isDefined(numberOfSelectedRecords) &&
+ numberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT) ??
+ false,
+ availableOn: [CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION],
+ component: ,
+ },
+ [SingleRecordCommandKeys.DESTROY]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: SingleRecordCommandKeys.DESTROY,
+ label: msg`Permanently destroy record`,
+ shortLabel: msg`Destroy`,
+ position: 7,
+ Icon: IconTrashX,
+ accent: 'danger',
+ isPinned: true,
+ shouldBeRegistered: ({ selectedRecord, objectPermissions, isRemote }) =>
+ (objectPermissions.canDestroyObjectRecords &&
+ !isRemote &&
+ isDefined(selectedRecord?.deletedAt)) ??
+ false,
+ availableOn: [
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ ],
+ component: ,
+ },
+ [MultipleRecordsCommandKeys.DESTROY]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: MultipleRecordsCommandKeys.DESTROY,
+ label: msg`Permanently destroy records`,
+ shortLabel: msg`Destroy`,
+ position: 8,
+ Icon: IconTrashX,
+ accent: 'danger',
+ isPinned: true,
+ shouldBeRegistered: ({
+ objectPermissions,
+ isRemote,
+ hasAnySoftDeleteFilterOnView,
+ numberOfSelectedRecords,
+ }) =>
+ (objectPermissions.canDestroyObjectRecords &&
+ !isRemote &&
+ isDefined(hasAnySoftDeleteFilterOnView) &&
+ hasAnySoftDeleteFilterOnView &&
+ isDefined(numberOfSelectedRecords) &&
+ numberOfSelectedRecords < BACKEND_BATCH_REQUEST_MAX_COUNT) ??
+ false,
+ availableOn: [CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION],
+ component: ,
+ },
+
+ [SingleRecordCommandKeys.ADD_TO_FAVORITES]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: SingleRecordCommandKeys.ADD_TO_FAVORITES,
+ label: msg`Add to favorites`,
+ shortLabel: msg`Add to favorites`,
+ position: 9,
+ isPinned: true,
+ Icon: IconHeart,
+ shouldBeRegistered: ({
+ selectedRecord,
+ isFavorite,
+ hasAnySoftDeleteFilterOnView,
+ }) =>
+ !selectedRecord?.isRemote &&
+ !isFavorite &&
+ !isDefined(selectedRecord?.deletedAt) &&
+ !hasAnySoftDeleteFilterOnView,
+ availableOn: [
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ ],
+ component: ,
+ },
+ [SingleRecordCommandKeys.REMOVE_FROM_FAVORITES]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: SingleRecordCommandKeys.REMOVE_FROM_FAVORITES,
+ label: msg`Remove from favorites`,
+ shortLabel: msg`Remove from favorites`,
+ isPinned: true,
+ position: 10,
+ Icon: IconHeartOff,
+ shouldBeRegistered: ({
+ selectedRecord,
+ isFavorite,
+ hasAnySoftDeleteFilterOnView,
+ }) =>
+ isDefined(selectedRecord) &&
+ !selectedRecord?.isRemote &&
+ isDefined(isFavorite) &&
+ isFavorite &&
+ !isDefined(selectedRecord?.deletedAt) &&
+ !hasAnySoftDeleteFilterOnView,
+ availableOn: [
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ ],
+ component: ,
+ },
+ [SingleRecordCommandKeys.EXPORT_NOTE_TO_PDF]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: SingleRecordCommandKeys.EXPORT_NOTE_TO_PDF,
+ label: msg`Export to PDF`,
+ shortLabel: msg`Export`,
+ position: 11,
+ isPinned: false,
+ Icon: IconFileExport,
+ shouldBeRegistered: ({ selectedRecord, isNoteOrTask }) =>
+ isDefined(isNoteOrTask) &&
+ isNoteOrTask &&
+ isNonEmptyString(selectedRecord?.bodyV2?.blocknote),
+ availableOn: [CommandMenuItemViewType.SHOW_PAGE],
+ component: ,
+ },
+ [SingleRecordCommandKeys.EXPORT_FROM_RECORD_INDEX]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: SingleRecordCommandKeys.EXPORT_FROM_RECORD_INDEX,
+ label: msg`Export`,
+ shortLabel: msg`Export`,
+ position: 12,
+ Icon: IconFileExport,
+ accent: 'default',
+ isPinned: false,
+ shouldBeRegistered: ({ selectedRecord }) =>
+ isDefined(selectedRecord) && !selectedRecord.isRemote,
+ availableOn: [CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION],
+ component: ,
+ requiredPermissionFlag: PermissionFlagType.EXPORT_CSV,
+ },
+ [SingleRecordCommandKeys.EXPORT_FROM_RECORD_SHOW]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: SingleRecordCommandKeys.EXPORT_FROM_RECORD_SHOW,
+ label: msg`Export`,
+ shortLabel: msg`Export`,
+ position: 13,
+ Icon: IconFileExport,
+ accent: 'default',
+ isPinned: false,
+ shouldBeRegistered: ({ selectedRecord }) =>
+ isDefined(selectedRecord) && !selectedRecord.isRemote,
+ availableOn: [CommandMenuItemViewType.SHOW_PAGE],
+ component: ,
+ requiredPermissionFlag: PermissionFlagType.EXPORT_CSV,
+ },
+ [MultipleRecordsCommandKeys.UPDATE]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: MultipleRecordsCommandKeys.UPDATE,
+ label: msg`Update records`,
+ shortLabel: msg`Update`,
+ position: 14,
+ Icon: IconEdit,
+ accent: 'default',
+ isPinned: true,
+ shouldBeRegistered: ({ objectPermissions, isRemote }) =>
+ objectPermissions.canUpdateObjectRecords && !isRemote,
+ availableOn: [CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION],
+ component: ,
+ },
+ [MultipleRecordsCommandKeys.MERGE]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: MultipleRecordsCommandKeys.MERGE,
+ label: msg`Merge records`,
+ shortLabel: msg`Merge`,
+ position: 15,
+ Icon: IconArrowMerge,
+ accent: 'default',
+ isPinned: false,
+ shouldBeRegistered: ({
+ objectMetadataItem,
+ numberOfSelectedRecords,
+ objectPermissions,
+ }) =>
+ isDefined(objectMetadataItem?.duplicateCriteria) &&
+ isDefined(numberOfSelectedRecords) &&
+ Boolean(objectPermissions.canUpdateObjectRecords) &&
+ Boolean(objectPermissions.canDestroyObjectRecords) &&
+ numberOfSelectedRecords <= MUTATION_MAX_MERGE_RECORDS,
+ availableOn: [CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION],
+ component: ,
+ },
+ [MultipleRecordsCommandKeys.EXPORT]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: MultipleRecordsCommandKeys.EXPORT,
+ label: msg`Export records`,
+ shortLabel: msg`Export`,
+ position: 16,
+ Icon: IconFileExport,
+ accent: 'default',
+ isPinned: false,
+ shouldBeRegistered: () => true,
+ availableOn: [CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION],
+ component: ,
+ requiredPermissionFlag: PermissionFlagType.EXPORT_CSV,
+ },
+ [NoSelectionRecordCommandKeys.IMPORT_RECORDS]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.Object,
+ key: NoSelectionRecordCommandKeys.IMPORT_RECORDS,
+ label: msg`Import records`,
+ shortLabel: msg`Import`,
+ position: 17,
+ Icon: IconFileImport,
+ accent: 'default',
+ isPinned: false,
+ shouldBeRegistered: ({ hasAnySoftDeleteFilterOnView }) =>
+ !hasAnySoftDeleteFilterOnView,
+ availableOn: [CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION],
+ component: ,
+ requiredPermissionFlag: PermissionFlagType.IMPORT_CSV,
+ },
+ [NoSelectionRecordCommandKeys.EXPORT_VIEW]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.Object,
+ key: NoSelectionRecordCommandKeys.EXPORT_VIEW,
+ label: msg`Export view`,
+ shortLabel: msg`Export`,
+ position: 18,
+ Icon: IconFileExport,
+ accent: 'default',
+ isPinned: false,
+ shouldBeRegistered: () => true,
+ availableOn: [CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION],
+ component: ,
+ requiredPermissionFlag: PermissionFlagType.EXPORT_CSV,
+ },
+ [NoSelectionRecordCommandKeys.SEE_DELETED_RECORDS]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.Object,
+ key: NoSelectionRecordCommandKeys.SEE_DELETED_RECORDS,
+ label: msg`See deleted records`,
+ shortLabel: msg`Deleted records`,
+ position: 19,
+ Icon: IconRotate2,
+ accent: 'default',
+ isPinned: false,
+ shouldBeRegistered: ({ hasAnySoftDeleteFilterOnView }) =>
+ !hasAnySoftDeleteFilterOnView,
+ availableOn: [CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION],
+ component: ,
+ },
+ [NoSelectionRecordCommandKeys.CREATE_NEW_VIEW]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.Object,
+ key: NoSelectionRecordCommandKeys.CREATE_NEW_VIEW,
+ label: msg`Create View`,
+ shortLabel: msg`Create View`,
+ position: 20,
+ Icon: IconLayout,
+ accent: 'default',
+ isPinned: false,
+ shouldBeRegistered: ({ hasAnySoftDeleteFilterOnView }) =>
+ !hasAnySoftDeleteFilterOnView,
+ availableOn: [CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION],
+ component: ,
+ },
+ [NoSelectionRecordCommandKeys.HIDE_DELETED_RECORDS]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.Object,
+ key: NoSelectionRecordCommandKeys.HIDE_DELETED_RECORDS,
+ label: msg`Hide deleted records`,
+ shortLabel: msg`Hide deleted`,
+ position: 21,
+ Icon: IconEyeOff,
+ accent: 'default',
+ isPinned: false,
+ shouldBeRegistered: ({ hasAnySoftDeleteFilterOnView }) =>
+ isDefined(hasAnySoftDeleteFilterOnView) && hasAnySoftDeleteFilterOnView,
+ availableOn: [CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION],
+ component: ,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_WORKFLOWS]: {
+ type: CommandMenuItemType.Navigation,
+ scope: CommandMenuItemScope.Global,
+ key: NoSelectionRecordCommandKeys.GO_TO_WORKFLOWS,
+ label: msg`Go to Workflows`,
+ shortLabel: msg`See Workflows`,
+ position: 22,
+ Icon: IconSettingsAutomation,
+ accent: 'default',
+ isPinned: false,
+ shouldBeRegistered: ({
+ objectMetadataItem,
+ viewType,
+ getTargetObjectReadPermission,
+ }) =>
+ getTargetObjectReadPermission(CoreObjectNameSingular.Workflow) &&
+ (objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Workflow ||
+ viewType === CommandMenuItemViewType.SHOW_PAGE),
+ availableOn: [
+ CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.PAGE_EDIT_MODE,
+ ],
+ component: (
+
+ ),
+ hotKeys: ['G', 'W'],
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_PEOPLE]: {
+ type: CommandMenuItemType.Navigation,
+ scope: CommandMenuItemScope.Global,
+ key: NoSelectionRecordCommandKeys.GO_TO_PEOPLE,
+ label: msg`Go to People`,
+ shortLabel: msg`People`,
+ position: 23,
+ Icon: IconUser,
+ isPinned: false,
+ availableOn: [
+ CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.PAGE_EDIT_MODE,
+ ],
+ shouldBeRegistered: ({
+ objectMetadataItem,
+ viewType,
+ getTargetObjectReadPermission,
+ }) =>
+ getTargetObjectReadPermission(CoreObjectNameSingular.Person) &&
+ (objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Person ||
+ viewType === CommandMenuItemViewType.SHOW_PAGE),
+ component: (
+
+ ),
+ hotKeys: ['G', 'P'],
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_COMPANIES]: {
+ type: CommandMenuItemType.Navigation,
+ scope: CommandMenuItemScope.Global,
+ key: NoSelectionRecordCommandKeys.GO_TO_COMPANIES,
+ label: msg`Go to Companies`,
+ shortLabel: msg`Companies`,
+ position: 24,
+ Icon: IconBuildingSkyscraper,
+ isPinned: false,
+ availableOn: [
+ CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.PAGE_EDIT_MODE,
+ ],
+ shouldBeRegistered: ({
+ objectMetadataItem,
+ viewType,
+ getTargetObjectReadPermission,
+ }) =>
+ getTargetObjectReadPermission(CoreObjectNameSingular.Company) &&
+ (objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Company ||
+ viewType === CommandMenuItemViewType.SHOW_PAGE),
+ component: (
+
+ ),
+ hotKeys: ['G', 'C'],
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_DASHBOARDS]: {
+ type: CommandMenuItemType.Navigation,
+ scope: CommandMenuItemScope.Global,
+ key: NoSelectionRecordCommandKeys.GO_TO_DASHBOARDS,
+ label: msg`Go to Dashboards`,
+ shortLabel: msg`Dashboards`,
+ position: 25,
+ Icon: IconLayoutDashboard,
+ isPinned: false,
+ availableOn: [
+ CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ ],
+ shouldBeRegistered: ({
+ objectMetadataItem,
+ viewType,
+ getTargetObjectReadPermission,
+ }) =>
+ getTargetObjectReadPermission(CoreObjectNameSingular.Dashboard) &&
+ (objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Dashboard ||
+ viewType === CommandMenuItemViewType.SHOW_PAGE),
+ component: (
+
+ ),
+ hotKeys: ['G', 'D'],
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_OPPORTUNITIES]: {
+ type: CommandMenuItemType.Navigation,
+ scope: CommandMenuItemScope.Global,
+ key: NoSelectionRecordCommandKeys.GO_TO_OPPORTUNITIES,
+ label: msg`Go to Opportunities`,
+ shortLabel: msg`Opportunities`,
+ position: 26,
+ Icon: IconTargetArrow,
+ isPinned: false,
+ availableOn: [
+ CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.PAGE_EDIT_MODE,
+ ],
+ shouldBeRegistered: ({
+ objectMetadataItem,
+ viewType,
+ getTargetObjectReadPermission,
+ }) =>
+ getTargetObjectReadPermission(CoreObjectNameSingular.Opportunity) &&
+ (objectMetadataItem?.nameSingular !==
+ CoreObjectNameSingular.Opportunity ||
+ viewType === CommandMenuItemViewType.SHOW_PAGE),
+ component: (
+
+ ),
+ hotKeys: ['G', 'O'],
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_SETTINGS]: {
+ type: CommandMenuItemType.Navigation,
+ scope: CommandMenuItemScope.Global,
+ key: NoSelectionRecordCommandKeys.GO_TO_SETTINGS,
+ label: msg`Go to Settings`,
+ shortLabel: msg`Settings`,
+ position: 27,
+ Icon: IconSettings,
+ isPinned: false,
+ availableOn: [
+ CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ ],
+ shouldBeRegistered: () => true,
+ component: (
+
+ ),
+ hotKeys: ['G', 'S'],
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_TASKS]: {
+ type: CommandMenuItemType.Navigation,
+ scope: CommandMenuItemScope.Global,
+ key: NoSelectionRecordCommandKeys.GO_TO_TASKS,
+ label: msg`Go to Tasks`,
+ shortLabel: msg`Tasks`,
+ position: 28,
+ Icon: IconCheckbox,
+ isPinned: false,
+ availableOn: [
+ CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.PAGE_EDIT_MODE,
+ ],
+ shouldBeRegistered: ({
+ objectMetadataItem,
+ viewType,
+ getTargetObjectReadPermission,
+ }) =>
+ getTargetObjectReadPermission(CoreObjectNameSingular.Task) &&
+ (objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Task ||
+ viewType === CommandMenuItemViewType.SHOW_PAGE),
+ component: (
+
+ ),
+ hotKeys: ['G', 'T'],
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_NOTES]: {
+ type: CommandMenuItemType.Navigation,
+ scope: CommandMenuItemScope.Global,
+ key: NoSelectionRecordCommandKeys.GO_TO_NOTES,
+ label: msg`Go to Notes`,
+ shortLabel: msg`Notes`,
+ position: 29,
+ Icon: IconCheckbox,
+ isPinned: false,
+ availableOn: [
+ CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.PAGE_EDIT_MODE,
+ ],
+ shouldBeRegistered: ({
+ objectMetadataItem,
+ viewType,
+ getTargetObjectReadPermission,
+ }) =>
+ getTargetObjectReadPermission(CoreObjectNameSingular.Note) &&
+ (objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Note ||
+ viewType === CommandMenuItemViewType.SHOW_PAGE),
+ component: (
+
+ ),
+ hotKeys: ['G', 'N'],
+ },
+
+ [RecordPageLayoutSingleRecordCommandKeys.EDIT_RECORD_PAGE_LAYOUT]: {
+ key: RecordPageLayoutSingleRecordCommandKeys.EDIT_RECORD_PAGE_LAYOUT,
+ label: msg`Edit Page Layout`,
+ shortLabel: msg`Edit Layout`,
+ isPinned: true,
+ position: 30,
+ Icon: IconPencil,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ requiredPermissionFlag: PermissionFlagType.LAYOUTS,
+ shouldBeRegistered: ({
+ selectedRecord,
+ objectPermissions,
+ objectMetadataItem,
+ isFeatureFlagEnabled,
+ }) =>
+ isFeatureFlagEnabled(
+ FeatureFlagKey.IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED,
+ ) &&
+ isDefined(selectedRecord) &&
+ !selectedRecord?.isRemote &&
+ !isDefined(selectedRecord?.deletedAt) &&
+ objectPermissions.canUpdateObjectRecords &&
+ objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Dashboard,
+ availableOn: [CommandMenuItemViewType.SHOW_PAGE],
+ component: ,
+ },
+ [RecordPageLayoutSingleRecordCommandKeys.SAVE_RECORD_PAGE_LAYOUT]: {
+ key: RecordPageLayoutSingleRecordCommandKeys.SAVE_RECORD_PAGE_LAYOUT,
+ label: msg`Save Page Layout`,
+ shortLabel: msg`Save`,
+ isPinned: true,
+ isPrimaryCTA: true,
+ position: 31,
+ Icon: IconDeviceFloppy,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ requiredPermissionFlag: PermissionFlagType.LAYOUTS,
+ shouldBeRegistered: ({
+ selectedRecord,
+ objectPermissions,
+ objectMetadataItem,
+ isFeatureFlagEnabled,
+ }) =>
+ isFeatureFlagEnabled(
+ FeatureFlagKey.IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED,
+ ) &&
+ isDefined(selectedRecord) &&
+ !selectedRecord?.isRemote &&
+ !isDefined(selectedRecord?.deletedAt) &&
+ objectPermissions.canUpdateObjectRecords &&
+ objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Dashboard,
+ availableOn: [CommandMenuItemViewType.PAGE_EDIT_MODE],
+ component: ,
+ },
+ [RecordPageLayoutSingleRecordCommandKeys.CANCEL_RECORD_PAGE_LAYOUT_EDITION]: {
+ key: RecordPageLayoutSingleRecordCommandKeys.CANCEL_RECORD_PAGE_LAYOUT_EDITION,
+ label: msg`Cancel Edition`,
+ shortLabel: msg`Cancel`,
+ isPinned: true,
+ position: 32,
+ Icon: IconCancel,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ requiredPermissionFlag: PermissionFlagType.LAYOUTS,
+ shouldBeRegistered: ({
+ selectedRecord,
+ objectPermissions,
+ objectMetadataItem,
+ isFeatureFlagEnabled,
+ }) =>
+ isFeatureFlagEnabled(
+ FeatureFlagKey.IS_RECORD_PAGE_LAYOUT_EDITING_ENABLED,
+ ) &&
+ isDefined(selectedRecord) &&
+ !selectedRecord?.isRemote &&
+ !isDefined(selectedRecord?.deletedAt) &&
+ objectPermissions.canUpdateObjectRecords &&
+ objectMetadataItem?.nameSingular !== CoreObjectNameSingular.Dashboard,
+ availableOn: [CommandMenuItemViewType.PAGE_EDIT_MODE],
+ component: ,
+ },
+};
diff --git a/packages/twenty-front/src/modules/command-menu-item/record/constants/WorkflowCommandMenuItemsConfig.tsx b/packages/twenty-front/src/modules/command-menu-item/record/constants/WorkflowCommandMenuItemsConfig.tsx
new file mode 100644
index 0000000000..72b037f297
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/record/constants/WorkflowCommandMenuItemsConfig.tsx
@@ -0,0 +1,390 @@
+import { CommandLink } from '@/command-menu-item/display/components/CommandLink';
+import { MultipleRecordsCommandKeys } from '@/command-menu-item/record/multiple-records/types/MultipleRecordsCommandKeys';
+import { NoSelectionRecordCommandKeys } from '@/command-menu-item/record/no-selection/types/NoSelectionRecordCommandKeys';
+import { NoSelectionWorkflowRecordCommandKeys } from '@/command-menu-item/record/no-selection/workflow/types/NoSelectionWorkflowRecordCommandKeys';
+import { SingleRecordCommandKeys } from '@/command-menu-item/record/single-record/types/SingleRecordCommandKeys';
+import { ActivateWorkflowSingleRecordCommand } from '@/command-menu-item/record/single-record/workflow/components/ActivateWorkflowSingleRecordCommand';
+import { AddNodeWorkflowSingleRecordCommand } from '@/command-menu-item/record/single-record/workflow/components/AddNodeWorkflowSingleRecordCommand';
+import { DeactivateWorkflowSingleRecordCommand } from '@/command-menu-item/record/single-record/workflow/components/DeactivateWorkflowSingleRecordCommand';
+import { DiscardDraftWorkflowSingleRecordCommand } from '@/command-menu-item/record/single-record/workflow/components/DiscardDraftWorkflowSingleRecordCommand';
+import { DuplicateWorkflowSingleRecordCommand } from '@/command-menu-item/record/single-record/workflow/components/DuplicateWorkflowSingleRecordCommand';
+import { SeeActiveVersionWorkflowSingleRecordCommand } from '@/command-menu-item/record/single-record/workflow/components/SeeActiveVersionWorkflowSingleRecordCommand';
+import { SeeRunsWorkflowSingleRecordCommand } from '@/command-menu-item/record/single-record/workflow/components/SeeRunsWorkflowSingleRecordCommand';
+import { SeeVersionsWorkflowSingleRecordCommand } from '@/command-menu-item/record/single-record/workflow/components/SeeVersionsWorkflowSingleRecordCommand';
+import { TestWorkflowSingleRecordCommand } from '@/command-menu-item/record/single-record/workflow/components/TestWorkflowSingleRecordCommand';
+import { TidyUpWorkflowSingleRecordCommand } from '@/command-menu-item/record/single-record/workflow/components/TidyUpWorkflowSingleRecordCommand';
+import { WorkflowSingleRecordCommandKeys } from '@/command-menu-item/record/single-record/workflow/types/WorkflowSingleRecordCommandKeys';
+import { inheritCommandMenuItemsFromDefaultConfig } from '@/command-menu-item/record/utils/inheritCommandMenuItemsFromDefaultConfig';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
+import { CommandMenuItemViewType, AppPath } from 'twenty-shared/types';
+import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
+import {
+ type WorkflowStep,
+ type WorkflowTrigger,
+ type WorkflowWithCurrentVersion,
+} from '@/workflow/types/Workflow';
+import { msg } from '@lingui/core/macro';
+import { isDefined } from 'twenty-shared/utils';
+import {
+ IconCopy,
+ IconHistoryToggle,
+ IconNoteOff,
+ IconPlayerPause,
+ IconPlayerPlay,
+ IconPlus,
+ IconPower,
+ IconReorder,
+ IconVersions,
+} from 'twenty-ui/display';
+
+const areWorkflowTriggerAndStepsDefined = (
+ workflowWithCurrentVersion: WorkflowWithCurrentVersion | undefined,
+): workflowWithCurrentVersion is WorkflowWithCurrentVersion & {
+ currentVersion: {
+ trigger: WorkflowTrigger;
+ steps: Array;
+ };
+} => {
+ return (
+ isDefined(workflowWithCurrentVersion?.currentVersion?.trigger) &&
+ isDefined(workflowWithCurrentVersion.currentVersion?.steps) &&
+ workflowWithCurrentVersion.currentVersion.steps.length > 0
+ );
+};
+
+export const WORKFLOW_COMMAND_MENU_ITEMS_CONFIG =
+ inheritCommandMenuItemsFromDefaultConfig({
+ config: {
+ [WorkflowSingleRecordCommandKeys.ACTIVATE]: {
+ key: WorkflowSingleRecordCommandKeys.ACTIVATE,
+ label: msg`Activate Workflow`,
+ shortLabel: msg`Activate`,
+ isPinned: true,
+ isPrimaryCTA: true,
+ position: 3,
+ Icon: IconPower,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
+ areWorkflowTriggerAndStepsDefined(workflowWithCurrentVersion) &&
+ (workflowWithCurrentVersion.currentVersion.status === 'DRAFT' ||
+ !workflowWithCurrentVersion.versions?.some(
+ (version) => version.status === 'ACTIVE',
+ )) &&
+ !isDefined(selectedRecord?.deletedAt),
+ availableOn: [
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ ],
+ component: ,
+ },
+ [WorkflowSingleRecordCommandKeys.DEACTIVATE]: {
+ key: WorkflowSingleRecordCommandKeys.DEACTIVATE,
+ label: msg`Deactivate Workflow`,
+ shortLabel: msg`Deactivate`,
+ isPinned: true,
+ position: 4,
+ Icon: IconPlayerPause,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
+ isDefined(workflowWithCurrentVersion) &&
+ workflowWithCurrentVersion.currentVersion.status === 'ACTIVE' &&
+ !isDefined(selectedRecord?.deletedAt),
+ availableOn: [
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ ],
+ component: ,
+ },
+ [WorkflowSingleRecordCommandKeys.DISCARD_DRAFT]: {
+ key: WorkflowSingleRecordCommandKeys.DISCARD_DRAFT,
+ label: msg`Discard Draft`,
+ shortLabel: msg`Discard Draft`,
+ isPinned: true,
+ position: 5,
+ Icon: IconNoteOff,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
+ isDefined(workflowWithCurrentVersion) &&
+ workflowWithCurrentVersion.versions.length > 1 &&
+ workflowWithCurrentVersion.currentVersion.status === 'DRAFT' &&
+ !isDefined(selectedRecord?.deletedAt),
+ availableOn: [
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ ],
+ component: ,
+ },
+ [WorkflowSingleRecordCommandKeys.TEST]: {
+ key: WorkflowSingleRecordCommandKeys.TEST,
+ label: msg`Test Workflow`,
+ shortLabel: msg`Test`,
+ isPinned: true,
+ position: 6,
+ Icon: IconPlayerPlay,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
+ areWorkflowTriggerAndStepsDefined(workflowWithCurrentVersion) &&
+ ((workflowWithCurrentVersion.currentVersion.trigger.type ===
+ 'MANUAL' &&
+ !isDefined(
+ workflowWithCurrentVersion.currentVersion.trigger.settings
+ .objectType,
+ )) ||
+ workflowWithCurrentVersion.currentVersion.trigger.type ===
+ 'WEBHOOK' ||
+ workflowWithCurrentVersion.currentVersion.trigger.type ===
+ 'CRON') &&
+ !isDefined(selectedRecord?.deletedAt),
+ availableOn: [
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ ],
+ component: ,
+ },
+
+ [WorkflowSingleRecordCommandKeys.SEE_ACTIVE_VERSION]: {
+ key: WorkflowSingleRecordCommandKeys.SEE_ACTIVE_VERSION,
+ label: msg`See active version`,
+ shortLabel: msg`See active version`,
+ isPinned: false,
+ position: 7,
+ Icon: IconVersions,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ shouldBeRegistered: ({ workflowWithCurrentVersion, selectedRecord }) =>
+ (workflowWithCurrentVersion?.statuses?.includes('ACTIVE') || false) &&
+ (workflowWithCurrentVersion?.statuses?.includes('DRAFT') || false) &&
+ !isDefined(selectedRecord?.deletedAt),
+ availableOn: [
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ ],
+ component: ,
+ },
+ [WorkflowSingleRecordCommandKeys.SEE_RUNS]: {
+ key: WorkflowSingleRecordCommandKeys.SEE_RUNS,
+ label: msg`See runs`,
+ shortLabel: msg`See runs`,
+ isPinned: true,
+ position: 8,
+ Icon: IconHistoryToggle,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
+ isDefined(workflowWithCurrentVersion) &&
+ !isDefined(selectedRecord?.deletedAt),
+ availableOn: [
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ ],
+ component: ,
+ },
+ [WorkflowSingleRecordCommandKeys.SEE_VERSIONS]: {
+ key: WorkflowSingleRecordCommandKeys.SEE_VERSIONS,
+ label: msg`See versions history`,
+ shortLabel: msg`See versions`,
+ isPinned: false,
+ position: 9,
+ Icon: IconVersions,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
+ isDefined(workflowWithCurrentVersion) &&
+ !isDefined(selectedRecord?.deletedAt),
+ availableOn: [
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ ],
+ component: ,
+ },
+
+ [WorkflowSingleRecordCommandKeys.ADD_NODE]: {
+ key: WorkflowSingleRecordCommandKeys.ADD_NODE,
+ label: msg`Add a node`,
+ shortLabel: msg`Add a node`,
+ isPinned: true,
+ position: 10,
+ Icon: IconPlus,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
+ areWorkflowTriggerAndStepsDefined(workflowWithCurrentVersion) &&
+ !isDefined(selectedRecord?.deletedAt),
+ availableOn: [CommandMenuItemViewType.SHOW_PAGE],
+ component: ,
+ },
+ [WorkflowSingleRecordCommandKeys.TIDY_UP]: {
+ key: WorkflowSingleRecordCommandKeys.TIDY_UP,
+ label: msg`Tidy up workflow`,
+ shortLabel: msg`Tidy up`,
+ isPinned: false,
+ position: 11,
+ Icon: IconReorder,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
+ areWorkflowTriggerAndStepsDefined(workflowWithCurrentVersion) &&
+ !isDefined(selectedRecord?.deletedAt),
+ availableOn: [CommandMenuItemViewType.SHOW_PAGE],
+ component: ,
+ },
+ [WorkflowSingleRecordCommandKeys.DUPLICATE_WORKFLOW]: {
+ key: WorkflowSingleRecordCommandKeys.DUPLICATE_WORKFLOW,
+ label: msg`Duplicate Workflow`,
+ shortLabel: msg`Duplicate`,
+ isPinned: false,
+ position: 12,
+ Icon: IconCopy,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ shouldBeRegistered: ({ selectedRecord, workflowWithCurrentVersion }) =>
+ isDefined(workflowWithCurrentVersion) &&
+ isDefined(workflowWithCurrentVersion.currentVersion) &&
+ !isDefined(selectedRecord?.deletedAt),
+ availableOn: [
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ ],
+ component: ,
+ },
+ [NoSelectionWorkflowRecordCommandKeys.GO_TO_RUNS]: {
+ type: CommandMenuItemType.Navigation,
+ scope: CommandMenuItemScope.Global,
+ key: NoSelectionWorkflowRecordCommandKeys.GO_TO_RUNS,
+ label: msg`Go to runs`,
+ shortLabel: msg`See runs`,
+ position: 22,
+ Icon: IconHistoryToggle,
+ accent: 'default',
+ isPinned: true,
+ shouldBeRegistered: ({ hasAnySoftDeleteFilterOnView }) =>
+ !hasAnySoftDeleteFilterOnView,
+ availableOn: [CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION],
+ component: (
+
+ ),
+ },
+ },
+ commandKeys: [
+ NoSelectionRecordCommandKeys.CREATE_NEW_RECORD,
+ SingleRecordCommandKeys.NAVIGATE_TO_PREVIOUS_RECORD,
+ SingleRecordCommandKeys.NAVIGATE_TO_NEXT_RECORD,
+ SingleRecordCommandKeys.ADD_TO_FAVORITES,
+ SingleRecordCommandKeys.REMOVE_FROM_FAVORITES,
+ SingleRecordCommandKeys.DELETE,
+ SingleRecordCommandKeys.DESTROY,
+ SingleRecordCommandKeys.RESTORE,
+ SingleRecordCommandKeys.EXPORT_FROM_RECORD_INDEX,
+ SingleRecordCommandKeys.EXPORT_FROM_RECORD_SHOW,
+ MultipleRecordsCommandKeys.DELETE,
+ MultipleRecordsCommandKeys.DESTROY,
+ MultipleRecordsCommandKeys.RESTORE,
+ MultipleRecordsCommandKeys.EXPORT,
+ NoSelectionRecordCommandKeys.SEE_DELETED_RECORDS,
+ NoSelectionRecordCommandKeys.HIDE_DELETED_RECORDS,
+ NoSelectionRecordCommandKeys.GO_TO_PEOPLE,
+ NoSelectionRecordCommandKeys.GO_TO_COMPANIES,
+ NoSelectionRecordCommandKeys.GO_TO_OPPORTUNITIES,
+ NoSelectionRecordCommandKeys.GO_TO_DASHBOARDS,
+ NoSelectionRecordCommandKeys.GO_TO_SETTINGS,
+ NoSelectionRecordCommandKeys.GO_TO_TASKS,
+ NoSelectionRecordCommandKeys.GO_TO_NOTES,
+ ],
+ propertiesToOverwrite: {
+ [SingleRecordCommandKeys.NAVIGATE_TO_NEXT_RECORD]: {
+ position: 0,
+ label: msg`Navigate to next workflow`,
+ },
+ [SingleRecordCommandKeys.NAVIGATE_TO_PREVIOUS_RECORD]: {
+ position: 1,
+ label: msg`Navigate to previous workflow`,
+ },
+ [NoSelectionRecordCommandKeys.CREATE_NEW_RECORD]: {
+ position: 2,
+ label: msg`Create new workflow`,
+ },
+ [SingleRecordCommandKeys.DELETE]: {
+ position: 12,
+ label: msg`Delete workflow`,
+ },
+ [MultipleRecordsCommandKeys.DELETE]: {
+ position: 13,
+ label: msg`Delete workflows`,
+ },
+ [SingleRecordCommandKeys.ADD_TO_FAVORITES]: {
+ position: 14,
+ isPinned: false,
+ },
+ [SingleRecordCommandKeys.REMOVE_FROM_FAVORITES]: {
+ position: 15,
+ isPinned: false,
+ },
+ [SingleRecordCommandKeys.DESTROY]: {
+ position: 16,
+ label: msg`Permanently destroy workflow`,
+ },
+ [SingleRecordCommandKeys.EXPORT_FROM_RECORD_INDEX]: {
+ position: 17,
+ label: msg`Export workflow`,
+ shouldBeRegistered: ({ selectedRecord }) =>
+ !isDefined(selectedRecord?.deletedAt),
+ },
+ [SingleRecordCommandKeys.EXPORT_FROM_RECORD_SHOW]: {
+ position: 18,
+ label: msg`Export workflow`,
+ },
+ [MultipleRecordsCommandKeys.EXPORT]: {
+ position: 19,
+ label: msg`Export workflows`,
+ },
+ [NoSelectionRecordCommandKeys.EXPORT_VIEW]: {
+ position: 20,
+ label: msg`Export view`,
+ },
+ [MultipleRecordsCommandKeys.DESTROY]: {
+ position: 21,
+ label: msg`Permanently destroy workflows`,
+ },
+ [NoSelectionRecordCommandKeys.SEE_DELETED_RECORDS]: {
+ position: 22,
+ label: msg`See deleted workflows`,
+ },
+ [NoSelectionRecordCommandKeys.HIDE_DELETED_RECORDS]: {
+ position: 23,
+ label: msg`Hide deleted workflows`,
+ },
+ [NoSelectionRecordCommandKeys.IMPORT_RECORDS]: {
+ position: 24,
+ label: msg`Import workflows`,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_PEOPLE]: {
+ position: 25,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_COMPANIES]: {
+ position: 26,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_OPPORTUNITIES]: {
+ position: 27,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_DASHBOARDS]: {
+ position: 28,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_SETTINGS]: {
+ position: 29,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_TASKS]: {
+ position: 30,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_NOTES]: {
+ position: 31,
+ },
+ },
+ });
diff --git a/packages/twenty-front/src/modules/command-menu-item/record/constants/WorkflowRunsCommandMenuItemsConfig.tsx b/packages/twenty-front/src/modules/command-menu-item/record/constants/WorkflowRunsCommandMenuItemsConfig.tsx
new file mode 100644
index 0000000000..6ad315176a
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/record/constants/WorkflowRunsCommandMenuItemsConfig.tsx
@@ -0,0 +1,165 @@
+import { MultipleRecordsCommandKeys } from '@/command-menu-item/record/multiple-records/types/MultipleRecordsCommandKeys';
+import { NoSelectionRecordCommandKeys } from '@/command-menu-item/record/no-selection/types/NoSelectionRecordCommandKeys';
+import { SingleRecordCommandKeys } from '@/command-menu-item/record/single-record/types/SingleRecordCommandKeys';
+import { SeeVersionWorkflowRunSingleRecordCommand } from '@/command-menu-item/record/single-record/workflow-runs/components/SeeVersionWorkflowRunSingleRecordCommand';
+import { SeeWorkflowWorkflowRunSingleRecordCommand } from '@/command-menu-item/record/single-record/workflow-runs/components/SeeWorkflowWorkflowRunSingleRecordCommand';
+import { StopWorkflowRunSingleRecordCommand } from '@/command-menu-item/record/single-record/workflow-runs/components/StopWorkflowRunSingleRecordCommand';
+import { WorkflowRunSingleRecordCommandKeys } from '@/command-menu-item/record/single-record/workflow-runs/types/WorkflowRunSingleRecordCommandKeys';
+import { inheritCommandMenuItemsFromDefaultConfig } from '@/command-menu-item/record/utils/inheritCommandMenuItemsFromDefaultConfig';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
+import { CommandMenuItemViewType } from 'twenty-shared/types';
+import { msg } from '@lingui/core/macro';
+import {
+ IconPlayerStop,
+ IconSettingsAutomation,
+ IconVersions,
+} from 'twenty-ui/display';
+
+export const WORKFLOW_RUNS_COMMAND_MENU_ITEMS_CONFIG =
+ inheritCommandMenuItemsFromDefaultConfig({
+ config: {
+ [WorkflowRunSingleRecordCommandKeys.SEE_VERSION]: {
+ key: WorkflowRunSingleRecordCommandKeys.SEE_VERSION,
+ label: msg`See version`,
+ shortLabel: msg`See version`,
+ position: 0,
+ isPinned: true,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ Icon: IconVersions,
+ shouldBeRegistered: () => true,
+ availableOn: [
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ ],
+ component: ,
+ },
+
+ [WorkflowRunSingleRecordCommandKeys.SEE_WORKFLOW]: {
+ key: WorkflowRunSingleRecordCommandKeys.SEE_WORKFLOW,
+ label: msg`See workflow`,
+ shortLabel: msg`See workflow`,
+ position: 1,
+ isPinned: true,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ Icon: IconSettingsAutomation,
+ shouldBeRegistered: () => true,
+ availableOn: [
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ ],
+ component: ,
+ },
+ [WorkflowRunSingleRecordCommandKeys.STOP]: {
+ key: WorkflowRunSingleRecordCommandKeys.STOP,
+ label: msg`Stop`,
+ shortLabel: msg`Stop`,
+ position: 2,
+ isPinned: true,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ Icon: IconPlayerStop,
+ shouldBeRegistered: ({ selectedRecord, isSelectAll }) => {
+ if (isSelectAll === true) {
+ return true;
+ }
+
+ const stoppableStatuses = ['NOT_STARTED', 'ENQUEUED', 'RUNNING'];
+ return stoppableStatuses.includes(selectedRecord?.status);
+ },
+ availableOn: [
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION,
+ ],
+ component: ,
+ },
+ },
+ commandKeys: [
+ SingleRecordCommandKeys.ADD_TO_FAVORITES,
+ SingleRecordCommandKeys.REMOVE_FROM_FAVORITES,
+ SingleRecordCommandKeys.NAVIGATE_TO_PREVIOUS_RECORD,
+ SingleRecordCommandKeys.NAVIGATE_TO_NEXT_RECORD,
+ SingleRecordCommandKeys.EXPORT_FROM_RECORD_INDEX,
+ SingleRecordCommandKeys.EXPORT_FROM_RECORD_SHOW,
+ MultipleRecordsCommandKeys.EXPORT,
+ NoSelectionRecordCommandKeys.EXPORT_VIEW,
+ NoSelectionRecordCommandKeys.SEE_DELETED_RECORDS,
+ NoSelectionRecordCommandKeys.HIDE_DELETED_RECORDS,
+ NoSelectionRecordCommandKeys.GO_TO_WORKFLOWS,
+ NoSelectionRecordCommandKeys.GO_TO_PEOPLE,
+ NoSelectionRecordCommandKeys.GO_TO_COMPANIES,
+ NoSelectionRecordCommandKeys.GO_TO_OPPORTUNITIES,
+ NoSelectionRecordCommandKeys.GO_TO_DASHBOARDS,
+ NoSelectionRecordCommandKeys.GO_TO_SETTINGS,
+ NoSelectionRecordCommandKeys.GO_TO_TASKS,
+ NoSelectionRecordCommandKeys.GO_TO_NOTES,
+ ],
+ propertiesToOverwrite: {
+ [SingleRecordCommandKeys.ADD_TO_FAVORITES]: {
+ isPinned: false,
+ position: 3,
+ },
+ [SingleRecordCommandKeys.REMOVE_FROM_FAVORITES]: {
+ isPinned: false,
+ position: 4,
+ },
+ [SingleRecordCommandKeys.EXPORT_FROM_RECORD_INDEX]: {
+ position: 5,
+ label: msg`Export run`,
+ },
+ [SingleRecordCommandKeys.EXPORT_FROM_RECORD_SHOW]: {
+ position: 5,
+ label: msg`Export run`,
+ },
+ [MultipleRecordsCommandKeys.EXPORT]: {
+ position: 6,
+ label: msg`Export runs`,
+ },
+ [NoSelectionRecordCommandKeys.EXPORT_VIEW]: {
+ position: 7,
+ label: msg`Export view`,
+ },
+ [NoSelectionRecordCommandKeys.SEE_DELETED_RECORDS]: {
+ position: 8,
+ label: msg`See deleted runs`,
+ },
+ [NoSelectionRecordCommandKeys.HIDE_DELETED_RECORDS]: {
+ position: 9,
+ label: msg`Hide deleted runs`,
+ },
+ [SingleRecordCommandKeys.NAVIGATE_TO_PREVIOUS_RECORD]: {
+ position: 10,
+ },
+ [SingleRecordCommandKeys.NAVIGATE_TO_NEXT_RECORD]: {
+ position: 11,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_WORKFLOWS]: {
+ position: 12,
+ isPinned: true,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_PEOPLE]: {
+ position: 13,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_COMPANIES]: {
+ position: 14,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_OPPORTUNITIES]: {
+ position: 15,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_DASHBOARDS]: {
+ position: 16,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_SETTINGS]: {
+ position: 17,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_TASKS]: {
+ position: 18,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_NOTES]: {
+ position: 19,
+ },
+ },
+ });
diff --git a/packages/twenty-front/src/modules/command-menu-item/record/constants/WorkflowVersionsCommandMenuItemsConfig.tsx b/packages/twenty-front/src/modules/command-menu-item/record/constants/WorkflowVersionsCommandMenuItemsConfig.tsx
new file mode 100644
index 0000000000..00c886e849
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/record/constants/WorkflowVersionsCommandMenuItemsConfig.tsx
@@ -0,0 +1,199 @@
+import { CommandLink } from '@/command-menu-item/display/components/CommandLink';
+import { MultipleRecordsCommandKeys } from '@/command-menu-item/record/multiple-records/types/MultipleRecordsCommandKeys';
+import { NoSelectionRecordCommandKeys } from '@/command-menu-item/record/no-selection/types/NoSelectionRecordCommandKeys';
+import { NoSelectionWorkflowRecordCommandKeys } from '@/command-menu-item/record/no-selection/workflow/types/NoSelectionWorkflowRecordCommandKeys';
+import { SingleRecordCommandKeys } from '@/command-menu-item/record/single-record/types/SingleRecordCommandKeys';
+import { SeeRunsWorkflowVersionSingleRecordCommand } from '@/command-menu-item/record/single-record/workflow-versions/components/SeeRunsWorkflowVersionSingleRecordCommand';
+import { SeeVersionsWorkflowVersionSingleRecordCommand } from '@/command-menu-item/record/single-record/workflow-versions/components/SeeVersionsWorkflowVersionSingleRecordCommand';
+import { SeeWorkflowWorkflowVersionSingleRecordCommand } from '@/command-menu-item/record/single-record/workflow-versions/components/SeeWorkflowWorkflowVersionSingleRecordCommand';
+import { UseAsDraftWorkflowVersionSingleRecordCommand } from '@/command-menu-item/record/single-record/workflow-versions/components/UseAsDraftWorkflowVersionSingleRecordCommand';
+import { WorkflowVersionSingleRecordCommandKeys } from '@/command-menu-item/record/single-record/workflow-versions/types/WorkflowVersionSingleRecordCommandKeys';
+import { inheritCommandMenuItemsFromDefaultConfig } from '@/command-menu-item/record/utils/inheritCommandMenuItemsFromDefaultConfig';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
+import { CommandMenuItemViewType, AppPath } from 'twenty-shared/types';
+import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
+import { msg } from '@lingui/core/macro';
+import { isDefined } from 'twenty-shared/utils';
+import {
+ IconHistoryToggle,
+ IconPencil,
+ IconSettingsAutomation,
+ IconVersions,
+} from 'twenty-ui/display';
+
+export const WORKFLOW_VERSIONS_COMMAND_MENU_ITEMS_CONFIG =
+ inheritCommandMenuItemsFromDefaultConfig({
+ config: {
+ [WorkflowVersionSingleRecordCommandKeys.SEE_RUNS]: {
+ key: WorkflowVersionSingleRecordCommandKeys.SEE_RUNS,
+ label: msg`See runs`,
+ shortLabel: msg`See runs`,
+ position: 1,
+ isPinned: true,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ Icon: IconHistoryToggle,
+ shouldBeRegistered: ({ workflowWithCurrentVersion }) =>
+ isDefined(workflowWithCurrentVersion),
+ availableOn: [
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ ],
+ component: ,
+ },
+ [WorkflowVersionSingleRecordCommandKeys.SEE_WORKFLOW]: {
+ key: WorkflowVersionSingleRecordCommandKeys.SEE_WORKFLOW,
+ label: msg`See workflow`,
+ shortLabel: msg`See workflow`,
+ position: 2,
+ isPinned: true,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ Icon: IconSettingsAutomation,
+ shouldBeRegistered: ({ selectedRecord }) =>
+ isDefined(selectedRecord?.workflow?.id),
+ availableOn: [
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ ],
+ component: ,
+ },
+ [WorkflowVersionSingleRecordCommandKeys.USE_AS_DRAFT]: {
+ key: WorkflowVersionSingleRecordCommandKeys.USE_AS_DRAFT,
+ label: msg`Use as draft`,
+ shortLabel: msg`Use as draft`,
+ position: 3,
+ isPinned: true,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ Icon: IconPencil,
+ shouldBeRegistered: ({ selectedRecord }) =>
+ isDefined(selectedRecord) && selectedRecord.status !== 'DRAFT',
+ availableOn: [
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ ],
+ component: ,
+ },
+ [WorkflowVersionSingleRecordCommandKeys.SEE_VERSIONS]: {
+ key: WorkflowVersionSingleRecordCommandKeys.SEE_VERSIONS,
+ label: msg`See versions history`,
+ shortLabel: msg`See versions`,
+ position: 4,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ Icon: IconVersions,
+ shouldBeRegistered: ({ workflowWithCurrentVersion }) =>
+ isDefined(workflowWithCurrentVersion),
+ availableOn: [
+ CommandMenuItemViewType.SHOW_PAGE,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ ],
+ component: ,
+ },
+ [NoSelectionWorkflowRecordCommandKeys.GO_TO_RUNS]: {
+ type: CommandMenuItemType.Navigation,
+ scope: CommandMenuItemScope.Global,
+ key: NoSelectionWorkflowRecordCommandKeys.GO_TO_RUNS,
+ label: msg`Go to runs`,
+ shortLabel: msg`See runs`,
+ position: 14,
+ Icon: IconHistoryToggle,
+ accent: 'default',
+ isPinned: true,
+ shouldBeRegistered: () => true,
+ availableOn: [CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION],
+ component: (
+
+ ),
+ },
+ },
+ commandKeys: [
+ SingleRecordCommandKeys.NAVIGATE_TO_PREVIOUS_RECORD,
+ SingleRecordCommandKeys.NAVIGATE_TO_NEXT_RECORD,
+ SingleRecordCommandKeys.ADD_TO_FAVORITES,
+ SingleRecordCommandKeys.REMOVE_FROM_FAVORITES,
+ SingleRecordCommandKeys.EXPORT_FROM_RECORD_INDEX,
+ SingleRecordCommandKeys.EXPORT_FROM_RECORD_SHOW,
+ MultipleRecordsCommandKeys.EXPORT,
+ NoSelectionRecordCommandKeys.EXPORT_VIEW,
+ NoSelectionRecordCommandKeys.SEE_DELETED_RECORDS,
+ NoSelectionRecordCommandKeys.HIDE_DELETED_RECORDS,
+ NoSelectionRecordCommandKeys.GO_TO_WORKFLOWS,
+ NoSelectionRecordCommandKeys.GO_TO_PEOPLE,
+ NoSelectionRecordCommandKeys.GO_TO_COMPANIES,
+ NoSelectionRecordCommandKeys.GO_TO_OPPORTUNITIES,
+ NoSelectionRecordCommandKeys.GO_TO_DASHBOARDS,
+ NoSelectionRecordCommandKeys.GO_TO_SETTINGS,
+ NoSelectionRecordCommandKeys.GO_TO_TASKS,
+ NoSelectionRecordCommandKeys.GO_TO_NOTES,
+ ],
+ propertiesToOverwrite: {
+ [SingleRecordCommandKeys.ADD_TO_FAVORITES]: {
+ position: 5,
+ isPinned: false,
+ },
+ [SingleRecordCommandKeys.REMOVE_FROM_FAVORITES]: {
+ position: 6,
+ isPinned: false,
+ },
+ [SingleRecordCommandKeys.EXPORT_FROM_RECORD_INDEX]: {
+ position: 7,
+ label: msg`Export version`,
+ },
+ [SingleRecordCommandKeys.EXPORT_FROM_RECORD_SHOW]: {
+ position: 7,
+ label: msg`Export version`,
+ },
+ [MultipleRecordsCommandKeys.EXPORT]: {
+ position: 8,
+ label: msg`Export versions`,
+ },
+ [NoSelectionRecordCommandKeys.EXPORT_VIEW]: {
+ position: 9,
+ },
+ [NoSelectionRecordCommandKeys.SEE_DELETED_RECORDS]: {
+ position: 10,
+ },
+ [NoSelectionRecordCommandKeys.HIDE_DELETED_RECORDS]: {
+ position: 11,
+ },
+ [SingleRecordCommandKeys.NAVIGATE_TO_PREVIOUS_RECORD]: {
+ position: 12,
+ label: msg`Navigate to previous version`,
+ },
+ [SingleRecordCommandKeys.NAVIGATE_TO_NEXT_RECORD]: {
+ position: 13,
+ label: msg`Navigate to next version`,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_WORKFLOWS]: {
+ position: 15,
+ isPinned: true,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_PEOPLE]: {
+ position: 16,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_COMPANIES]: {
+ position: 17,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_OPPORTUNITIES]: {
+ position: 18,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_DASHBOARDS]: {
+ position: 19,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_SETTINGS]: {
+ position: 20,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_TASKS]: {
+ position: 21,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_NOTES]: {
+ position: 22,
+ },
+ },
+ });
diff --git a/packages/twenty-front/src/modules/command-menu-item/record/constants/WorkspaceMembersCommandMenuItemsConfig.tsx b/packages/twenty-front/src/modules/command-menu-item/record/constants/WorkspaceMembersCommandMenuItemsConfig.tsx
new file mode 100644
index 0000000000..25bc8192c7
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/record/constants/WorkspaceMembersCommandMenuItemsConfig.tsx
@@ -0,0 +1,126 @@
+import { CommandLink } from '@/command-menu-item/display/components/CommandLink';
+import { MultipleRecordsCommandKeys } from '@/command-menu-item/record/multiple-records/types/MultipleRecordsCommandKeys';
+import { NoSelectionRecordCommandKeys } from '@/command-menu-item/record/no-selection/types/NoSelectionRecordCommandKeys';
+import { SingleRecordCommandKeys } from '@/command-menu-item/record/single-record/types/SingleRecordCommandKeys';
+import { inheritCommandMenuItemsFromDefaultConfig } from '@/command-menu-item/record/utils/inheritCommandMenuItemsFromDefaultConfig';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
+import {
+ CommandMenuItemViewType,
+ AppPath,
+ SettingsPath,
+} from 'twenty-shared/types';
+import { msg } from '@lingui/core/macro';
+import { IconSettings } from 'twenty-ui/display';
+
+export const WORKSPACE_MEMBERS_COMMAND_MENU_ITEMS_CONFIG =
+ inheritCommandMenuItemsFromDefaultConfig({
+ config: {
+ [NoSelectionRecordCommandKeys.GO_TO_SETTINGS]: {
+ type: CommandMenuItemType.Navigation,
+ scope: CommandMenuItemScope.Global,
+ key: NoSelectionRecordCommandKeys.GO_TO_SETTINGS,
+ label: msg`Manage members in settings`,
+ shortLabel: msg`Manage in settings`,
+ position: 14,
+ Icon: IconSettings,
+ isPinned: true,
+ availableOn: [
+ CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION,
+ CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION,
+ CommandMenuItemViewType.SHOW_PAGE,
+ ],
+ shouldBeRegistered: () => true,
+ component: (
+
+ ),
+ hotKeys: ['G', 'S'],
+ },
+ },
+ commandKeys: [
+ SingleRecordCommandKeys.ADD_TO_FAVORITES,
+ SingleRecordCommandKeys.REMOVE_FROM_FAVORITES,
+ SingleRecordCommandKeys.NAVIGATE_TO_PREVIOUS_RECORD,
+ SingleRecordCommandKeys.NAVIGATE_TO_NEXT_RECORD,
+ SingleRecordCommandKeys.EXPORT_FROM_RECORD_INDEX,
+ SingleRecordCommandKeys.EXPORT_FROM_RECORD_SHOW,
+ MultipleRecordsCommandKeys.EXPORT,
+ NoSelectionRecordCommandKeys.EXPORT_VIEW,
+ NoSelectionRecordCommandKeys.SEE_DELETED_RECORDS,
+ NoSelectionRecordCommandKeys.HIDE_DELETED_RECORDS,
+ NoSelectionRecordCommandKeys.GO_TO_WORKFLOWS,
+ NoSelectionRecordCommandKeys.GO_TO_PEOPLE,
+ NoSelectionRecordCommandKeys.GO_TO_COMPANIES,
+ NoSelectionRecordCommandKeys.GO_TO_OPPORTUNITIES,
+ NoSelectionRecordCommandKeys.GO_TO_DASHBOARDS,
+ NoSelectionRecordCommandKeys.GO_TO_TASKS,
+ NoSelectionRecordCommandKeys.GO_TO_NOTES,
+ ],
+ propertiesToOverwrite: {
+ [SingleRecordCommandKeys.ADD_TO_FAVORITES]: {
+ isPinned: false,
+ position: 0,
+ },
+ [SingleRecordCommandKeys.REMOVE_FROM_FAVORITES]: {
+ isPinned: false,
+ position: 1,
+ },
+ [SingleRecordCommandKeys.EXPORT_FROM_RECORD_INDEX]: {
+ position: 2,
+ label: msg`Export member`,
+ },
+ [SingleRecordCommandKeys.EXPORT_FROM_RECORD_SHOW]: {
+ position: 2,
+ label: msg`Export member`,
+ },
+ [MultipleRecordsCommandKeys.EXPORT]: {
+ position: 3,
+ label: msg`Export members`,
+ },
+ [NoSelectionRecordCommandKeys.EXPORT_VIEW]: {
+ position: 4,
+ label: msg`Export view`,
+ },
+ [NoSelectionRecordCommandKeys.SEE_DELETED_RECORDS]: {
+ position: 5,
+ label: msg`See deleted members`,
+ },
+ [NoSelectionRecordCommandKeys.HIDE_DELETED_RECORDS]: {
+ position: 6,
+ label: msg`Hide deleted members`,
+ },
+ [SingleRecordCommandKeys.NAVIGATE_TO_PREVIOUS_RECORD]: {
+ position: 7,
+ },
+ [SingleRecordCommandKeys.NAVIGATE_TO_NEXT_RECORD]: {
+ position: 8,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_WORKFLOWS]: {
+ position: 9,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_PEOPLE]: {
+ position: 10,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_COMPANIES]: {
+ position: 11,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_OPPORTUNITIES]: {
+ position: 12,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_DASHBOARDS]: {
+ position: 13,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_TASKS]: {
+ position: 15,
+ },
+ [NoSelectionRecordCommandKeys.GO_TO_NOTES]: {
+ position: 16,
+ },
+ },
+ });
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/DeleteMultipleRecordsAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/multiple-records/components/DeleteMultipleRecordsCommand.tsx
similarity index 82%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/DeleteMultipleRecordsAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/multiple-records/components/DeleteMultipleRecordsCommand.tsx
index 14d463ca03..2c69b09690 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/DeleteMultipleRecordsAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/multiple-records/components/DeleteMultipleRecordsCommand.tsx
@@ -1,7 +1,7 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { ActionConfigContext } from '@/action-menu/contexts/ActionConfigContext';
-import { computeProgressText } from '@/action-menu/utils/computeProgressText';
-import { getActionLabel } from '@/action-menu/utils/getActionLabel';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { CommandConfigContext } from '@/command-menu-item/contexts/CommandConfigContext';
+import { computeProgressText } from '@/command-menu-item/utils/computeProgressText';
+import { getCommandMenuItemLabel } from '@/command-menu-item/utils/getCommandMenuItemLabel';
import { contextStoreAnyFieldFilterValueComponentState } from '@/context-store/states/contextStoreAnyFieldFilterValueComponentState';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState';
@@ -18,7 +18,7 @@ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/use
import { useContext } from 'react';
import { isDefined } from 'twenty-shared/utils';
-export const DeleteMultipleRecordsAction = () => {
+export const DeleteMultipleRecordsCommand = () => {
const { recordIndexId, objectMetadataItem } =
useRecordIndexIdFromCurrentContextStore();
@@ -70,15 +70,17 @@ export const DeleteMultipleRecordsAction = () => {
delayInMsBetweenMutations: 50,
});
- const actionConfig = useContext(ActionConfigContext);
+ const actionConfig = useContext(CommandConfigContext);
if (!isDefined(actionConfig)) {
return null;
}
- const originalLabel = getActionLabel(actionConfig.label);
+ const originalLabel = getCommandMenuItemLabel(actionConfig.label);
- const originalShortLabel = getActionLabel(actionConfig.shortLabel ?? '');
+ const originalShortLabel = getCommandMenuItemLabel(
+ actionConfig.shortLabel ?? '',
+ );
const progressText = computeProgressText(progress);
@@ -95,8 +97,8 @@ export const DeleteMultipleRecordsAction = () => {
};
return (
-
-
-
+
+
+
);
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/DestroyMultipleRecordsAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/multiple-records/components/DestroyMultipleRecordsCommand.tsx
similarity index 84%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/DestroyMultipleRecordsAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/multiple-records/components/DestroyMultipleRecordsCommand.tsx
index e464985be7..aabce7ce26 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/DestroyMultipleRecordsAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/multiple-records/components/DestroyMultipleRecordsCommand.tsx
@@ -1,7 +1,7 @@
-import { ActionModal } from '@/action-menu/actions/components/ActionModal';
-import { ActionConfigContext } from '@/action-menu/contexts/ActionConfigContext';
-import { computeProgressText } from '@/action-menu/utils/computeProgressText';
-import { getActionLabel } from '@/action-menu/utils/getActionLabel';
+import { CommandModal } from '@/command-menu-item/display/components/CommandModal';
+import { CommandConfigContext } from '@/command-menu-item/contexts/CommandConfigContext';
+import { computeProgressText } from '@/command-menu-item/utils/computeProgressText';
+import { getCommandMenuItemLabel } from '@/command-menu-item/utils/getCommandMenuItemLabel';
import { contextStoreAnyFieldFilterValueComponentState } from '@/context-store/states/contextStoreAnyFieldFilterValueComponentState';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState';
@@ -20,7 +20,7 @@ import { useContext } from 'react';
import { type RecordGqlOperationFilter } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
-export const DestroyMultipleRecordsAction = () => {
+export const DestroyMultipleRecordsCommand = () => {
const { recordIndexId, objectMetadataItem } =
useRecordIndexIdFromCurrentContextStore();
@@ -77,15 +77,17 @@ export const DestroyMultipleRecordsAction = () => {
delayInMsBetweenMutations: 50,
});
- const actionConfig = useContext(ActionConfigContext);
+ const actionConfig = useContext(CommandConfigContext);
if (!isDefined(actionConfig)) {
return null;
}
- const originalLabel = getActionLabel(actionConfig.label);
+ const originalLabel = getCommandMenuItemLabel(actionConfig.label);
- const originalShortLabel = getActionLabel(actionConfig.shortLabel ?? '');
+ const originalShortLabel = getCommandMenuItemLabel(
+ actionConfig.shortLabel ?? '',
+ );
const progressText = computeProgressText(progress);
@@ -102,13 +104,13 @@ export const DestroyMultipleRecordsAction = () => {
};
return (
-
-
+
-
+
);
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/ExportMultipleRecordsAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/multiple-records/components/ExportMultipleRecordsCommand.tsx
similarity index 65%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/ExportMultipleRecordsAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/multiple-records/components/ExportMultipleRecordsCommand.tsx
index af0553b5d8..317e85f0a0 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/ExportMultipleRecordsAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/multiple-records/components/ExportMultipleRecordsCommand.tsx
@@ -1,8 +1,8 @@
-import { ActionDisplay } from '@/action-menu/actions/display/components/ActionDisplay';
-import { ActionConfigContext } from '@/action-menu/contexts/ActionConfigContext';
-import { useCloseActionMenu } from '@/action-menu/hooks/useCloseActionMenu';
-import { computeProgressText } from '@/action-menu/utils/computeProgressText';
-import { getActionLabel } from '@/action-menu/utils/getActionLabel';
+import { CommandMenuItemDisplay } from '@/command-menu-item/display/components/CommandMenuItemDisplay';
+import { CommandConfigContext } from '@/command-menu-item/contexts/CommandConfigContext';
+import { useCloseCommandMenu } from '@/command-menu-item/hooks/useCloseCommandMenu';
+import { computeProgressText } from '@/command-menu-item/utils/computeProgressText';
+import { getCommandMenuItemLabel } from '@/command-menu-item/utils/getCommandMenuItemLabel';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { useRecordIndexExportRecords } from '@/object-record/record-index/export/hooks/useRecordIndexExportRecords';
@@ -11,7 +11,7 @@ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/use
import { useContext } from 'react';
import { isDefined } from 'twenty-shared/utils';
-export const ExportMultipleRecordsAction = () => {
+export const ExportMultipleRecordsCommand = () => {
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const contextStoreCurrentViewId = useAtomComponentStateValue(
@@ -32,7 +32,7 @@ export const ExportMultipleRecordsAction = () => {
filename: `${objectMetadataItem.nameSingular}.csv`,
});
- const { closeActionMenu } = useCloseActionMenu({});
+ const { closeCommandMenu } = useCloseCommandMenu({});
const exportProgress = isDefined(progress)
? {
@@ -41,15 +41,17 @@ export const ExportMultipleRecordsAction = () => {
}
: undefined;
- const actionConfig = useContext(ActionConfigContext);
+ const actionConfig = useContext(CommandConfigContext);
if (!isDefined(actionConfig)) {
return null;
}
- const originalLabel = getActionLabel(actionConfig.label);
+ const originalLabel = getCommandMenuItemLabel(actionConfig.label);
- const originalShortLabel = getActionLabel(actionConfig.shortLabel ?? '');
+ const originalShortLabel = getCommandMenuItemLabel(
+ actionConfig.shortLabel ?? '',
+ );
const progressText = computeProgressText(exportProgress);
@@ -62,16 +64,16 @@ export const ExportMultipleRecordsAction = () => {
const handleClick = async () => {
try {
await download();
- closeActionMenu();
+ closeCommandMenu();
} catch (error) {
- closeActionMenu();
+ closeCommandMenu();
throw error;
}
};
return (
-
-
-
+
+
+
);
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/MergeMultipleRecordsAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/multiple-records/components/MergeMultipleRecordsCommand.tsx
similarity index 76%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/MergeMultipleRecordsAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/multiple-records/components/MergeMultipleRecordsCommand.tsx
index 6840cd20b8..d5baf93e84 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/MergeMultipleRecordsAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/multiple-records/components/MergeMultipleRecordsCommand.tsx
@@ -1,11 +1,11 @@
-import { ActionDisplay } from '@/action-menu/actions/display/components/ActionDisplay';
-import { useSelectedRecordIds } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIds';
+import { CommandMenuItemDisplay } from '@/command-menu-item/display/components/CommandMenuItemDisplay';
+import { useSelectedRecordIds } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIds';
import { useOpenMergeRecordsPageInSidePanel } from '@/side-panel/hooks/useOpenMergeRecordsPageInSidePanel';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
-export const MergeMultipleRecordsAction = () => {
+export const MergeMultipleRecordsCommand = () => {
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const contextStoreCurrentViewId = useAtomComponentStateValue(
@@ -27,5 +27,5 @@ export const MergeMultipleRecordsAction = () => {
openMergeRecordsPageInSidePanel();
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/RestoreMultipleRecordsAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/multiple-records/components/RestoreMultipleRecordsCommand.tsx
similarity index 96%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/RestoreMultipleRecordsAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/multiple-records/components/RestoreMultipleRecordsCommand.tsx
index 93257cae5f..1905208920 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/components/RestoreMultipleRecordsAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/multiple-records/components/RestoreMultipleRecordsCommand.tsx
@@ -1,4 +1,4 @@
-import { ActionModal } from '@/action-menu/actions/components/ActionModal';
+import { CommandModal } from '@/command-menu-item/display/components/CommandModal';
import { contextStoreAnyFieldFilterValueComponentState } from '@/context-store/states/contextStoreAnyFieldFilterValueComponentState';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState';
@@ -16,7 +16,7 @@ import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/use
import { t } from '@lingui/core/macro';
import { type RecordGqlOperationFilter } from 'twenty-shared/types';
-export const RestoreMultipleRecordsAction = () => {
+export const RestoreMultipleRecordsCommand = () => {
const { recordIndexId, objectMetadataItem } =
useRecordIndexIdFromCurrentContextStore();
@@ -90,7 +90,7 @@ export const RestoreMultipleRecordsAction = () => {
};
return (
- {
+export const UpdateMultipleRecordsCommand = () => {
const contextStoreInstanceId = useAvailableComponentInstanceIdOrThrow(
ContextStoreComponentInstanceContext,
);
@@ -17,5 +17,5 @@ export const UpdateMultipleRecordsAction = () => {
openUpdateMultipleRecordsPageInSidePanel();
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys.ts b/packages/twenty-front/src/modules/command-menu-item/record/multiple-records/types/MultipleRecordsCommandKeys.ts
similarity index 84%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys.ts
rename to packages/twenty-front/src/modules/command-menu-item/record/multiple-records/types/MultipleRecordsCommandKeys.ts
index 52079f2806..bd60395b84 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/record/multiple-records/types/MultipleRecordsCommandKeys.ts
@@ -1,4 +1,4 @@
-export enum MultipleRecordsActionKeys {
+export enum MultipleRecordsCommandKeys {
UPDATE = 'update-multiple-records',
DELETE = 'delete-multiple-records',
EXPORT = 'export-multiple-records',
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/CreateNewIndexRecordNoSelectionRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/CreateNewIndexRecordNoSelectionRecordCommand.tsx
similarity index 69%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/CreateNewIndexRecordNoSelectionRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/CreateNewIndexRecordNoSelectionRecordCommand.tsx
index 2008016df3..855bbbedba 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/CreateNewIndexRecordNoSelectionRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/CreateNewIndexRecordNoSelectionRecordCommand.tsx
@@ -1,8 +1,8 @@
-import { Action } from '@/action-menu/actions/components/Action';
+import { Command } from '@/command-menu-item/display/components/Command';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { useCreateNewIndexRecord } from '@/object-record/record-table/hooks/useCreateNewIndexRecord';
-export const CreateNewIndexRecordNoSelectionRecordAction = () => {
+export const CreateNewIndexRecordNoSelectionRecordCommand = () => {
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const { createNewIndexRecord } = useCreateNewIndexRecord({
@@ -10,9 +10,9 @@ export const CreateNewIndexRecordNoSelectionRecordAction = () => {
});
return (
- createNewIndexRecord({ position: 'first' })}
- closeSidePanelOnCommandMenuListActionExecution={false}
+ closeSidePanelOnCommandMenuListExecution={false}
/>
);
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/CreateNewViewNoSelectionRecord.tsx b/packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/CreateNewViewNoSelectionRecordCommand.tsx
similarity index 90%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/CreateNewViewNoSelectionRecord.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/CreateNewViewNoSelectionRecordCommand.tsx
index 548bd69f7f..3e66886c2c 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/CreateNewViewNoSelectionRecord.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/CreateNewViewNoSelectionRecordCommand.tsx
@@ -1,4 +1,4 @@
-import { Action } from '@/action-menu/actions/components/Action';
+import { Command } from '@/command-menu-item/display/components/Command';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId';
@@ -9,7 +9,7 @@ import { VIEW_PICKER_DROPDOWN_ID } from '@/views/view-picker/constants/ViewPicke
import { useViewPickerMode } from '@/views/view-picker/hooks/useViewPickerMode';
import { viewPickerReferenceViewIdComponentState } from '@/views/view-picker/states/viewPickerReferenceViewIdComponentState';
-export const CreateNewViewNoSelectionRecord = () => {
+export const CreateNewViewNoSelectionRecordCommand = () => {
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const { openDropdown } = useOpenDropdown();
@@ -41,5 +41,5 @@ export const CreateNewViewNoSelectionRecord = () => {
});
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/EditNavigationSidebarNoSelectionRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/EditNavigationSidebarNoSelectionRecordCommand.tsx
similarity index 65%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/EditNavigationSidebarNoSelectionRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/EditNavigationSidebarNoSelectionRecordCommand.tsx
index d7eba36271..57e13744fa 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/EditNavigationSidebarNoSelectionRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/EditNavigationSidebarNoSelectionRecordCommand.tsx
@@ -1,16 +1,16 @@
-import { Action } from '@/action-menu/actions/components/Action';
+import { Command } from '@/command-menu-item/display/components/Command';
import { isNavigationMenuInEditModeState } from '@/navigation-menu-item/states/isNavigationMenuInEditModeState';
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
-export const EditNavigationSidebarNoSelectionRecordAction = () => {
+export const EditNavigationSidebarNoSelectionRecordCommand = () => {
const setIsNavigationMenuInEditMode = useSetAtomState(
isNavigationMenuInEditModeState,
);
return (
- setIsNavigationMenuInEditMode(true)}
- closeSidePanelOnCommandMenuListActionExecution
+ closeSidePanelOnCommandMenuListExecution
/>
);
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/HideDeletedRecordsNoSelectionRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/HideDeletedRecordsNoSelectionRecordCommand.tsx
similarity index 92%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/HideDeletedRecordsNoSelectionRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/HideDeletedRecordsNoSelectionRecordCommand.tsx
index ed425948ef..32056cd8be 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/HideDeletedRecordsNoSelectionRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/HideDeletedRecordsNoSelectionRecordCommand.tsx
@@ -1,4 +1,4 @@
-import { Action } from '@/action-menu/actions/components/Action';
+import { Command } from '@/command-menu-item/display/components/Command';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { useCheckIsSoftDeleteFilter } from '@/object-record/record-filter/hooks/useCheckIsSoftDeleteFilter';
@@ -9,7 +9,7 @@ import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/u
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
import { isDefined } from 'twenty-shared/utils';
-export const HideDeletedRecordsNoSelectionRecordAction = () => {
+export const HideDeletedRecordsNoSelectionRecordCommand = () => {
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const contextStoreCurrentViewId = useAtomComponentStateValue(
@@ -52,5 +52,5 @@ export const HideDeletedRecordsNoSelectionRecordAction = () => {
toggleSoftDeleteFilterState(false);
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/ImportRecordsNoSelectionRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/ImportRecordsNoSelectionRecordCommand.tsx
similarity index 70%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/ImportRecordsNoSelectionRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/ImportRecordsNoSelectionRecordCommand.tsx
index 0c709d185d..9005584ff4 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/ImportRecordsNoSelectionRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/ImportRecordsNoSelectionRecordCommand.tsx
@@ -1,8 +1,8 @@
-import { Action } from '@/action-menu/actions/components/Action';
+import { Command } from '@/command-menu-item/display/components/Command';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { useOpenObjectRecordsSpreadsheetImportDialog } from '@/object-record/spreadsheet-import/hooks/useOpenObjectRecordsSpreadsheetImportDialog';
-export const ImportRecordsNoSelectionRecordAction = () => {
+export const ImportRecordsNoSelectionRecordCommand = () => {
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const { openObjectRecordsSpreadsheetImportDialog } =
@@ -10,5 +10,5 @@ export const ImportRecordsNoSelectionRecordAction = () => {
objectMetadataItem.nameSingular,
);
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/SeeDeletedRecordsNoSelectionRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/SeeDeletedRecordsNoSelectionRecordCommand.tsx
similarity index 90%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/SeeDeletedRecordsNoSelectionRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/SeeDeletedRecordsNoSelectionRecordCommand.tsx
index 8f079b0c50..8603d73cc6 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/components/SeeDeletedRecordsNoSelectionRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/no-selection/components/SeeDeletedRecordsNoSelectionRecordCommand.tsx
@@ -1,11 +1,11 @@
-import { Action } from '@/action-menu/actions/components/Action';
+import { Command } from '@/command-menu-item/display/components/Command';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { useHandleToggleTrashColumnFilter } from '@/object-record/record-index/hooks/useHandleToggleTrashColumnFilter';
import { getRecordIndexIdFromObjectNamePluralAndViewId } from '@/object-record/utils/getRecordIndexIdFromObjectNamePluralAndViewId';
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
-export const SeeDeletedRecordsNoSelectionRecordAction = () => {
+export const SeeDeletedRecordsNoSelectionRecordCommand = () => {
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const contextStoreCurrentViewId = useAtomComponentStateValue(
@@ -28,7 +28,7 @@ export const SeeDeletedRecordsNoSelectionRecordAction = () => {
});
return (
- {
handleToggleTrashColumnFilter();
toggleSoftDeleteFilterState(true);
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys.ts b/packages/twenty-front/src/modules/command-menu-item/record/no-selection/types/NoSelectionRecordCommandKeys.ts
similarity index 92%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys.ts
rename to packages/twenty-front/src/modules/command-menu-item/record/no-selection/types/NoSelectionRecordCommandKeys.ts
index 51506d7a55..3a0f4e8975 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/no-selection/types/NoSelectionRecordActionsKeys.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/record/no-selection/types/NoSelectionRecordCommandKeys.ts
@@ -1,4 +1,4 @@
-export enum NoSelectionRecordActionKeys {
+export enum NoSelectionRecordCommandKeys {
EXPORT_VIEW = 'export-view',
CREATE_NEW_RECORD = 'create-new-record',
SEE_DELETED_RECORDS = 'see-deleted-records',
diff --git a/packages/twenty-front/src/modules/command-menu-item/record/no-selection/workflow/types/NoSelectionWorkflowRecordCommandKeys.ts b/packages/twenty-front/src/modules/command-menu-item/record/no-selection/workflow/types/NoSelectionWorkflowRecordCommandKeys.ts
new file mode 100644
index 0000000000..2f8d1af84a
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/record/no-selection/workflow/types/NoSelectionWorkflowRecordCommandKeys.ts
@@ -0,0 +1,3 @@
+export enum NoSelectionWorkflowRecordCommandKeys {
+ GO_TO_RUNS = 'go-to-runs',
+}
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/AddToFavoritesSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/AddToFavoritesSingleRecordCommand.tsx
similarity index 74%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/AddToFavoritesSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/components/AddToFavoritesSingleRecordCommand.tsx
index ea30d8916d..c8222f8024 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/AddToFavoritesSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/AddToFavoritesSingleRecordCommand.tsx
@@ -1,12 +1,12 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { useCreateFavorite } from '@/favorites/hooks/useCreateFavorite';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
import { isDefined } from 'twenty-shared/utils';
-export const AddToFavoritesSingleRecordAction = () => {
+export const AddToFavoritesSingleRecordCommand = () => {
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const recordId = useSelectedRecordIdOrThrow();
@@ -23,5 +23,5 @@ export const AddToFavoritesSingleRecordAction = () => {
createFavorite(recordStore, objectMetadataItem.nameSingular);
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/CreateRelatedRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/CreateRelatedRecordCommand.tsx
similarity index 89%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/CreateRelatedRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/components/CreateRelatedRecordCommand.tsx
index 6d986036c3..ceef716f06 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/CreateRelatedRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/CreateRelatedRecordCommand.tsx
@@ -1,5 +1,5 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { useOpenRecordInSidePanel } from '@/side-panel/hooks/useOpenRecordInSidePanel';
import { useObjectMetadataItem } from '@/object-metadata/hooks/useObjectMetadataItem';
import { CoreObjectNameSingular } from 'twenty-shared/types';
@@ -8,13 +8,13 @@ import { useCreateOneRecord } from '@/object-record/hooks/useCreateOneRecord';
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
import { getForeignKeyNameFromRelationFieldName } from '@/object-record/utils/getForeignKeyNameFromRelationFieldName';
-interface CreateRelatedRecordActionProps {
+interface CreateRelatedRecordCommandProps {
targetFieldMetadataItemRelation: FieldMetadataItemRelation;
}
-export const CreateRelatedRecordAction = ({
+export const CreateRelatedRecordCommand = ({
targetFieldMetadataItemRelation,
-}: CreateRelatedRecordActionProps) => {
+}: CreateRelatedRecordCommandProps) => {
const sourceRecordId = useSelectedRecordIdOrThrow();
const { objectMetadataItem: targetObjectMetadataItem } =
@@ -95,9 +95,9 @@ export const CreateRelatedRecordAction = ({
};
return (
-
);
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/DeleteSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/DeleteSingleRecordCommand.tsx
similarity index 88%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/DeleteSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/components/DeleteSingleRecordCommand.tsx
index dc6e8b51b2..7811e6f4d1 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/DeleteSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/DeleteSingleRecordCommand.tsx
@@ -1,5 +1,5 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { useDeleteFavorite } from '@/favorites/hooks/useDeleteFavorite';
import { useFavorites } from '@/favorites/hooks/useFavorites';
import { usePrefetchedNavigationMenuItemsData } from '@/navigation-menu-item/hooks/usePrefetchedNavigationMenuItemsData';
@@ -10,7 +10,7 @@ import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-
import { useResetTableRowSelection } from '@/object-record/record-table/hooks/internal/useResetTableRowSelection';
import { isDefined } from 'twenty-shared/utils';
-export const DeleteSingleRecordAction = () => {
+export const DeleteSingleRecordCommand = () => {
const { recordIndexId, objectMetadataItem } =
useRecordIndexIdFromCurrentContextStore();
@@ -58,5 +58,5 @@ export const DeleteSingleRecordAction = () => {
await deleteOneRecord(recordId);
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/DestroySingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/DestroySingleRecordCommand.tsx
similarity index 83%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/DestroySingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/components/DestroySingleRecordCommand.tsx
index 0f59ffe752..1ca7dd63bb 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/DestroySingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/DestroySingleRecordCommand.tsx
@@ -1,5 +1,5 @@
-import { ActionModal } from '@/action-menu/actions/components/ActionModal';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { CommandModal } from '@/command-menu-item/display/components/CommandModal';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { useDestroyOneRecord } from '@/object-record/hooks/useDestroyOneRecord';
import { useRemoveSelectedRecordsFromRecordBoard } from '@/object-record/record-board/hooks/useRemoveSelectedRecordsFromRecordBoard';
import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore';
@@ -8,7 +8,7 @@ import { t } from '@lingui/core/macro';
import { AppPath } from 'twenty-shared/types';
import { useNavigateApp } from '~/hooks/useNavigateApp';
-export const DestroySingleRecordAction = () => {
+export const DestroySingleRecordCommand = () => {
const { recordIndexId, objectMetadataItem } =
useRecordIndexIdFromCurrentContextStore();
@@ -36,12 +36,12 @@ export const DestroySingleRecordAction = () => {
};
return (
-
);
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/ExportNoteActionSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/ExportNoteSingleRecordCommand.tsx
similarity index 73%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/ExportNoteActionSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/components/ExportNoteSingleRecordCommand.tsx
index e50bc1b766..b2104d25ff 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/ExportNoteActionSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/ExportNoteSingleRecordCommand.tsx
@@ -1,10 +1,10 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
import { isDefined } from 'twenty-shared/utils';
-export const ExportNoteActionSingleRecordAction = () => {
+export const ExportNoteSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
@@ -33,17 +33,17 @@ export const ExportNoteActionSingleRecordAction = () => {
}
const { exportBlockNoteEditorToPdf } = await import(
- '@/action-menu/actions/record-actions/single-record/utils/exportBlockNoteEditorToPdf'
+ '@/command-menu-item/record/single-record/utils/exportBlockNoteEditorToPdf'
);
await exportBlockNoteEditorToPdf(parsedBody, filename);
// TODO later: implement DOCX export
// const { exportBlockNoteEditorToDocx } = await import(
- // '@/action-menu/actions/record-actions/single-record/utils/exportBlockNoteEditorToDocx'
+ // '@/command-menu-item/record/single-record/utils/exportBlockNoteEditorToDocx'
// );
// await exportBlockNoteEditorToDocx(editor, filename);
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/ExportSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/ExportSingleRecordCommand.tsx
similarity index 77%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/ExportSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/components/ExportSingleRecordCommand.tsx
index 1f341c6e19..379066b68b 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/ExportSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/ExportSingleRecordCommand.tsx
@@ -1,12 +1,12 @@
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { useExportSingleRecord } from '@/object-record/record-show/hooks/useExportSingleRecord';
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
-import { Action } from '@/action-menu/actions/components/Action';
+import { Command } from '@/command-menu-item/display/components/Command';
-export const ExportSingleRecordAction = () => {
+export const ExportSingleRecordCommand = () => {
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const contextStoreCurrentViewId = useAtomComponentStateValue(
@@ -26,5 +26,5 @@ export const ExportSingleRecordAction = () => {
recordId,
});
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/NavigateToNextRecordSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/NavigateToNextRecordSingleRecordCommand.tsx
similarity index 61%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/NavigateToNextRecordSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/components/NavigateToNextRecordSingleRecordCommand.tsx
index 7a10f97092..682e00a437 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/NavigateToNextRecordSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/NavigateToNextRecordSingleRecordCommand.tsx
@@ -1,9 +1,9 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { useRecordShowPagePagination } from '@/object-record/record-show/hooks/useRecordShowPagePagination';
-export const NavigateToNextRecordSingleRecordAction = () => {
+export const NavigateToNextRecordSingleRecordCommand = () => {
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const recordId = useSelectedRecordIdOrThrow();
@@ -13,5 +13,5 @@ export const NavigateToNextRecordSingleRecordAction = () => {
recordId,
);
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/NavigateToPreviousRecordSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/NavigateToPreviousRecordSingleRecordCommand.tsx
similarity index 60%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/NavigateToPreviousRecordSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/components/NavigateToPreviousRecordSingleRecordCommand.tsx
index eb87858ffd..15b7e7d0f9 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/NavigateToPreviousRecordSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/NavigateToPreviousRecordSingleRecordCommand.tsx
@@ -1,9 +1,9 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { useRecordShowPagePagination } from '@/object-record/record-show/hooks/useRecordShowPagePagination';
-export const NavigateToPreviousRecordSingleRecordAction = () => {
+export const NavigateToPreviousRecordSingleRecordCommand = () => {
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const recordId = useSelectedRecordIdOrThrow();
@@ -13,5 +13,5 @@ export const NavigateToPreviousRecordSingleRecordAction = () => {
recordId,
);
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/RemoveFromFavoritesSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/RemoveFromFavoritesSingleRecordCommand.tsx
similarity index 83%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/RemoveFromFavoritesSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/components/RemoveFromFavoritesSingleRecordCommand.tsx
index 0510ab0139..a3e4d540c7 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/RemoveFromFavoritesSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/RemoveFromFavoritesSingleRecordCommand.tsx
@@ -1,5 +1,5 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { useDeleteFavorite } from '@/favorites/hooks/useDeleteFavorite';
import { useFavorites } from '@/favorites/hooks/useFavorites';
@@ -7,7 +7,7 @@ import { useDeleteNavigationMenuItem } from '@/navigation-menu-item/hooks/useDel
import { usePrefetchedNavigationMenuItemsData } from '@/navigation-menu-item/hooks/usePrefetchedNavigationMenuItemsData';
import { isDefined } from 'twenty-shared/utils';
-export const RemoveFromFavoritesSingleRecordAction = () => {
+export const RemoveFromFavoritesSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
@@ -40,5 +40,5 @@ export const RemoveFromFavoritesSingleRecordAction = () => {
deleteFavorite(foundFavorite.id);
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/RestoreSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/RestoreSingleRecordCommand.tsx
similarity index 83%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/RestoreSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/components/RestoreSingleRecordCommand.tsx
index 2cf123bc5c..c8ff9eea86 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/components/RestoreSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/components/RestoreSingleRecordCommand.tsx
@@ -1,12 +1,12 @@
-import { ActionModal } from '@/action-menu/actions/components/ActionModal';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { CommandModal } from '@/command-menu-item/display/components/CommandModal';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { useRestoreManyRecords } from '@/object-record/hooks/useRestoreManyRecords';
import { useRemoveSelectedRecordsFromRecordBoard } from '@/object-record/record-board/hooks/useRemoveSelectedRecordsFromRecordBoard';
import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore';
import { useResetTableRowSelection } from '@/object-record/record-table/hooks/internal/useResetTableRowSelection';
import { t } from '@lingui/core/macro';
-export const RestoreSingleRecordAction = () => {
+export const RestoreSingleRecordCommand = () => {
const { recordIndexId, objectMetadataItem } =
useRecordIndexIdFromCurrentContextStore();
@@ -30,7 +30,7 @@ export const RestoreSingleRecordAction = () => {
};
return (
- {
+export const CancelDashboardSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
@@ -28,5 +28,5 @@ export const CancelDashboardSingleRecordAction = () => {
setIsPageLayoutInEditMode(false);
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/dashboard-actions/components/DuplicateDashboardSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/dashboard/components/DuplicateDashboardSingleRecordCommand.tsx
similarity index 80%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/dashboard-actions/components/DuplicateDashboardSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/dashboard/components/DuplicateDashboardSingleRecordCommand.tsx
index 8028c2aaf0..bd9f264385 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/dashboard-actions/components/DuplicateDashboardSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/dashboard/components/DuplicateDashboardSingleRecordCommand.tsx
@@ -1,5 +1,5 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { useDuplicateDashboard } from '@/dashboards/hooks/useDuplicateDashboard';
import { CoreObjectNameSingular, AppPath } from 'twenty-shared/types';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
@@ -8,7 +8,7 @@ import { isNonEmptyString } from '@sniptt/guards';
import { isDefined } from 'twenty-shared/utils';
import { useNavigateApp } from '~/hooks/useNavigateApp';
-export const DuplicateDashboardSingleRecordAction = () => {
+export const DuplicateDashboardSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const { duplicateDashboard } = useDuplicateDashboard();
const navigate = useNavigateApp();
@@ -33,5 +33,5 @@ export const DuplicateDashboardSingleRecordAction = () => {
}
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/dashboard-actions/components/EditDashboardSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/dashboard/components/EditDashboardSingleRecordCommand.tsx
similarity index 72%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/dashboard-actions/components/EditDashboardSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/dashboard/components/EditDashboardSingleRecordCommand.tsx
index 2c77a80ee9..2b4f332985 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/dashboard-actions/components/EditDashboardSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/dashboard/components/EditDashboardSingleRecordCommand.tsx
@@ -1,11 +1,11 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useSetIsPageLayoutInEditMode } from '@/page-layout/hooks/useSetIsPageLayoutInEditMode';
import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
import { useResetLocationHash } from 'twenty-ui/utilities';
-export const EditDashboardSingleRecordAction = () => {
+export const EditDashboardSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
@@ -22,5 +22,5 @@ export const EditDashboardSingleRecordAction = () => {
resetLocationHash();
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/dashboard-actions/components/SaveDashboardSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/dashboard/components/SaveDashboardSingleRecordCommand.tsx
similarity index 77%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/dashboard-actions/components/SaveDashboardSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/dashboard/components/SaveDashboardSingleRecordCommand.tsx
index 725072e049..cd49d80d1a 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/dashboard-actions/components/SaveDashboardSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/dashboard/components/SaveDashboardSingleRecordCommand.tsx
@@ -1,12 +1,12 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useSavePageLayout } from '@/page-layout/hooks/useSavePageLayout';
import { useSetIsPageLayoutInEditMode } from '@/page-layout/hooks/useSetIsPageLayoutInEditMode';
import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
-export const SaveDashboardSingleRecordAction = () => {
+export const SaveDashboardSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
@@ -29,5 +29,5 @@ export const SaveDashboardSingleRecordAction = () => {
}
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/dashboard-actions/types/DashboardSingleRecordActionKeys.ts b/packages/twenty-front/src/modules/command-menu-item/record/single-record/dashboard/types/DashboardSingleRecordCommandKeys.ts
similarity index 57%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/dashboard-actions/types/DashboardSingleRecordActionKeys.ts
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/dashboard/types/DashboardSingleRecordCommandKeys.ts
index e411eabac6..10a298ecf8 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/dashboard-actions/types/DashboardSingleRecordActionKeys.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/dashboard/types/DashboardSingleRecordCommandKeys.ts
@@ -1,3 +1,3 @@
-export enum DashboardSingleRecordActionKeys {
+export enum DashboardSingleRecordCommandKeys {
DUPLICATE_DASHBOARD = 'duplicate-dashboard-single-record',
}
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow.tsx
similarity index 100%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow.tsx
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIds.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/hooks/useSelectedRecordIds.tsx
similarity index 100%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIds.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/hooks/useSelectedRecordIds.tsx
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/CancelRecordPageLayoutSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/record-page-layout/components/CancelRecordPageLayoutSingleRecordCommand.tsx
similarity index 86%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/CancelRecordPageLayoutSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/record-page-layout/components/CancelRecordPageLayoutSingleRecordCommand.tsx
index 808fc60d82..f5762b8340 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/CancelRecordPageLayoutSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/record-page-layout/components/CancelRecordPageLayoutSingleRecordCommand.tsx
@@ -1,11 +1,11 @@
-import { Action } from '@/action-menu/actions/components/Action';
+import { Command } from '@/command-menu-item/display/components/Command';
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { useRecordPageLayoutIdFromRecordStoreOrThrow } from '@/page-layout/hooks/useRecordPageLayoutIdFromRecordStoreOrThrow';
import { useResetDraftPageLayoutToPersistedPageLayout } from '@/page-layout/hooks/useResetDraftPageLayoutToPersistedPageLayout';
import { useSetIsPageLayoutInEditMode } from '@/page-layout/hooks/useSetIsPageLayoutInEditMode';
-export const CancelRecordPageLayoutSingleRecordAction = () => {
+export const CancelRecordPageLayoutSingleRecordCommand = () => {
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const { pageLayoutId } = useRecordPageLayoutIdFromRecordStoreOrThrow({
@@ -27,5 +27,5 @@ export const CancelRecordPageLayoutSingleRecordAction = () => {
setIsPageLayoutInEditMode(false);
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/EditRecordPageLayoutSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/record-page-layout/components/EditRecordPageLayoutSingleRecordCommand.tsx
similarity index 82%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/EditRecordPageLayoutSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/record-page-layout/components/EditRecordPageLayoutSingleRecordCommand.tsx
index 3aff9fcb9b..2ed6606bfe 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/EditRecordPageLayoutSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/record-page-layout/components/EditRecordPageLayoutSingleRecordCommand.tsx
@@ -1,10 +1,10 @@
-import { Action } from '@/action-menu/actions/components/Action';
+import { Command } from '@/command-menu-item/display/components/Command';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { useRecordPageLayoutIdFromRecordStoreOrThrow } from '@/page-layout/hooks/useRecordPageLayoutIdFromRecordStoreOrThrow';
import { useSetIsPageLayoutInEditMode } from '@/page-layout/hooks/useSetIsPageLayoutInEditMode';
import { useResetLocationHash } from 'twenty-ui/utilities';
-export const EditRecordPageLayoutSingleRecordAction = () => {
+export const EditRecordPageLayoutSingleRecordCommand = () => {
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const { pageLayoutId } = useRecordPageLayoutIdFromRecordStoreOrThrow({
@@ -21,5 +21,5 @@ export const EditRecordPageLayoutSingleRecordAction = () => {
resetLocationHash();
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/SaveRecordPageLayoutSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/record-page-layout/components/SaveRecordPageLayoutSingleRecordCommand.tsx
similarity index 88%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/SaveRecordPageLayoutSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/record-page-layout/components/SaveRecordPageLayoutSingleRecordCommand.tsx
index b1cca98682..689978c381 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/components/SaveRecordPageLayoutSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/record-page-layout/components/SaveRecordPageLayoutSingleRecordCommand.tsx
@@ -1,4 +1,4 @@
-import { Action } from '@/action-menu/actions/components/Action';
+import { Command } from '@/command-menu-item/display/components/Command';
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { useRecordPageLayoutIdFromRecordStoreOrThrow } from '@/page-layout/hooks/useRecordPageLayoutIdFromRecordStoreOrThrow';
@@ -6,7 +6,7 @@ import { useSaveFieldsWidgetGroups } from '@/page-layout/hooks/useSaveFieldsWidg
import { useSavePageLayout } from '@/page-layout/hooks/useSavePageLayout';
import { useSetIsPageLayoutInEditMode } from '@/page-layout/hooks/useSetIsPageLayoutInEditMode';
-export const SaveRecordPageLayoutSingleRecordAction = () => {
+export const SaveRecordPageLayoutSingleRecordCommand = () => {
const { objectMetadataItem } = useContextStoreObjectMetadataItemOrThrow();
const { pageLayoutId } = useRecordPageLayoutIdFromRecordStoreOrThrow({
@@ -34,5 +34,5 @@ export const SaveRecordPageLayoutSingleRecordAction = () => {
}
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/types/RecordPageLayoutSingleRecordActionKeys.ts b/packages/twenty-front/src/modules/command-menu-item/record/single-record/record-page-layout/types/RecordPageLayoutSingleRecordCommandKeys.ts
similarity index 80%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/types/RecordPageLayoutSingleRecordActionKeys.ts
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/record-page-layout/types/RecordPageLayoutSingleRecordCommandKeys.ts
index e8dbde1654..8869732e61 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/record-page-layout-actions/types/RecordPageLayoutSingleRecordActionKeys.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/record-page-layout/types/RecordPageLayoutSingleRecordCommandKeys.ts
@@ -1,4 +1,4 @@
-export enum RecordPageLayoutSingleRecordActionKeys {
+export enum RecordPageLayoutSingleRecordCommandKeys {
EDIT_RECORD_PAGE_LAYOUT = 'edit-record-page-layout-single-record',
SAVE_RECORD_PAGE_LAYOUT = 'save-record-page-layout-single-record',
CANCEL_RECORD_PAGE_LAYOUT_EDITION = 'cancel-record-page-layout-edition-single-record',
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey.ts b/packages/twenty-front/src/modules/command-menu-item/record/single-record/types/SingleRecordCommandKeys.ts
similarity index 93%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey.ts
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/types/SingleRecordCommandKeys.ts
index 229ca24fb7..c8ab553602 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/types/SingleRecordActionsKey.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/types/SingleRecordCommandKeys.ts
@@ -1,4 +1,4 @@
-export enum SingleRecordActionKeys {
+export enum SingleRecordCommandKeys {
DELETE = 'delete-single-record',
DESTROY = 'destroy-single-record',
ADD_TO_FAVORITES = 'add-to-favorites-single-record',
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/utils/exportBlockNoteEditorToDocx.ts b/packages/twenty-front/src/modules/command-menu-item/record/single-record/utils/exportBlockNoteEditorToDocx.ts
similarity index 100%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/utils/exportBlockNoteEditorToDocx.ts
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/utils/exportBlockNoteEditorToDocx.ts
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/utils/exportBlockNoteEditorToPdf.ts b/packages/twenty-front/src/modules/command-menu-item/record/single-record/utils/exportBlockNoteEditorToPdf.ts
similarity index 100%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/utils/exportBlockNoteEditorToPdf.ts
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/utils/exportBlockNoteEditorToPdf.ts
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-run-actions/components/SeeVersionWorkflowRunSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-runs/components/SeeVersionWorkflowRunSingleRecordCommand.tsx
similarity index 72%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-run-actions/components/SeeVersionWorkflowRunSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-runs/components/SeeVersionWorkflowRunSingleRecordCommand.tsx
index df10b96e0e..61ec3bfc86 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-run-actions/components/SeeVersionWorkflowRunSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-runs/components/SeeVersionWorkflowRunSingleRecordCommand.tsx
@@ -1,11 +1,11 @@
-import { ActionLink } from '@/action-menu/actions/components/ActionLink';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { CommandLink } from '@/command-menu-item/display/components/CommandLink';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { CoreObjectNameSingular, AppPath } from 'twenty-shared/types';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
import { isDefined } from 'twenty-shared/utils';
-export const SeeVersionWorkflowRunSingleRecordAction = () => {
+export const SeeVersionWorkflowRunSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
@@ -14,7 +14,7 @@ export const SeeVersionWorkflowRunSingleRecordAction = () => {
}
return (
- {
+export const SeeWorkflowWorkflowRunSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
@@ -14,7 +14,7 @@ export const SeeWorkflowWorkflowRunSingleRecordAction = () => {
}
return (
- {
+export const StopWorkflowRunSingleRecordCommand = () => {
const { objectMetadataItem } = useRecordIndexIdFromCurrentContextStore();
const contextStoreTargetedRecordsRule = useAtomComponentStateValue(
@@ -65,5 +65,5 @@ export const StopWorkflowRunSingleRecordAction = () => {
}
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-run-actions/types/WorkflowRunSingleRecordActionsKeys.ts b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-runs/types/WorkflowRunSingleRecordCommandKeys.ts
similarity index 76%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-run-actions/types/WorkflowRunSingleRecordActionsKeys.ts
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-runs/types/WorkflowRunSingleRecordCommandKeys.ts
index ad84a02da3..8d3654eddf 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-run-actions/types/WorkflowRunSingleRecordActionsKeys.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-runs/types/WorkflowRunSingleRecordCommandKeys.ts
@@ -1,4 +1,4 @@
-export enum WorkflowRunSingleRecordActionKeys {
+export enum WorkflowRunSingleRecordCommandKeys {
STOP = 'stop-workflow-run-single-record',
SEE_WORKFLOW = 'see-workflow-workflow-run-single-record',
SEE_VERSION = 'see-version-workflow-run-single-record',
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/components/SeeRunsWorkflowVersionSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-versions/components/SeeRunsWorkflowVersionSingleRecordCommand.tsx
similarity index 78%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/components/SeeRunsWorkflowVersionSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-versions/components/SeeRunsWorkflowVersionSingleRecordCommand.tsx
index 4eb73199fd..adc6271486 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/components/SeeRunsWorkflowVersionSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-versions/components/SeeRunsWorkflowVersionSingleRecordCommand.tsx
@@ -1,5 +1,5 @@
-import { ActionLink } from '@/action-menu/actions/components/ActionLink';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { CommandLink } from '@/command-menu-item/display/components/CommandLink';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
@@ -7,7 +7,7 @@ import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithC
import { AppPath, ViewFilterOperand } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
-const SeeRunsWorkflowVersionSingleRecordActionContent = ({
+const SeeRunsWorkflowVersionSingleRecordCommandContent = ({
workflowId,
recordId,
}: {
@@ -17,7 +17,7 @@ const SeeRunsWorkflowVersionSingleRecordActionContent = ({
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(workflowId);
return (
- {
+export const SeeRunsWorkflowVersionSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
@@ -49,7 +49,7 @@ export const SeeRunsWorkflowVersionSingleRecordAction = () => {
}
return (
-
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/components/SeeVersionsWorkflowVersionSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-versions/components/SeeVersionsWorkflowVersionSingleRecordCommand.tsx
similarity index 75%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/components/SeeVersionsWorkflowVersionSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-versions/components/SeeVersionsWorkflowVersionSingleRecordCommand.tsx
index c2621c3814..cb2d6a6a23 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/components/SeeVersionsWorkflowVersionSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-versions/components/SeeVersionsWorkflowVersionSingleRecordCommand.tsx
@@ -1,5 +1,5 @@
-import { ActionLink } from '@/action-menu/actions/components/ActionLink';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { CommandLink } from '@/command-menu-item/display/components/CommandLink';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { CoreObjectNamePlural } from '@/object-metadata/types/CoreObjectNamePlural';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
@@ -7,7 +7,7 @@ import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAto
import { AppPath, ViewFilterOperand } from 'twenty-shared/types';
import { isDefined } from 'twenty-shared/utils';
-const SeeVersionsWorkflowVersionSingleRecordActionContent = ({
+const SeeVersionsWorkflowVersionSingleRecordCommandContent = ({
workflowId,
}: {
workflowId: string;
@@ -15,7 +15,7 @@ const SeeVersionsWorkflowVersionSingleRecordActionContent = ({
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(workflowId);
return (
- {
+export const SeeVersionsWorkflowVersionSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
@@ -40,7 +40,7 @@ export const SeeVersionsWorkflowVersionSingleRecordAction = () => {
}
return (
-
);
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/components/SeeWorkflowWorkflowVersionSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-versions/components/SeeWorkflowWorkflowVersionSingleRecordCommand.tsx
similarity index 67%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/components/SeeWorkflowWorkflowVersionSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-versions/components/SeeWorkflowWorkflowVersionSingleRecordCommand.tsx
index 6400c824a4..24cb2699d7 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/components/SeeWorkflowWorkflowVersionSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-versions/components/SeeWorkflowWorkflowVersionSingleRecordCommand.tsx
@@ -1,15 +1,15 @@
-import { ActionLink } from '@/action-menu/actions/components/ActionLink';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { CommandLink } from '@/command-menu-item/display/components/CommandLink';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { CoreObjectNameSingular, AppPath } from 'twenty-shared/types';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useAtomFamilyStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomFamilyStateValue';
-export const SeeWorkflowWorkflowVersionSingleRecordAction = () => {
+export const SeeWorkflowWorkflowVersionSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const recordStore = useAtomFamilyStateValue(recordStoreFamilyState, recordId);
return (
- {
+ const executeCommandWithoutWaiting = async () => {
await createDraftFromWorkflowVersion({
workflowId,
workflowVersionIdToCopy: workflowVersionId,
@@ -50,13 +50,13 @@ const UseAsDraftWorkflowVersionSingleRecordActionContent = ({
setHasNavigated(true);
};
- executeActionWithoutWaiting();
+ executeCommandWithoutWaiting();
}
};
return (
<>
-
+
{
+export const UseAsDraftWorkflowVersionSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const workflowVersion = useWorkflowVersion(recordId);
@@ -74,7 +74,7 @@ export const UseAsDraftWorkflowVersionSingleRecordAction = () => {
}
return (
-
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/types/WorkflowVersionSingleRecordActionsKeys.ts b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-versions/types/WorkflowVersionSingleRecordCommandKeys.ts
similarity index 82%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/types/WorkflowVersionSingleRecordActionsKeys.ts
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-versions/types/WorkflowVersionSingleRecordCommandKeys.ts
index 293b2af66b..1001095a7a 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-version-actions/types/WorkflowVersionSingleRecordActionsKeys.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow-versions/types/WorkflowVersionSingleRecordCommandKeys.ts
@@ -1,4 +1,4 @@
-export enum WorkflowVersionSingleRecordActionKeys {
+export enum WorkflowVersionSingleRecordCommandKeys {
SEE_RUNS = 'see-runs-workflow-version-single-record',
SEE_VERSIONS = 'see-versions-workflow-version-single-record',
USE_AS_DRAFT = 'use-as-draft-workflow-version-single-record',
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/ActivateWorkflowSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/ActivateWorkflowSingleRecordCommand.tsx
similarity index 70%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/ActivateWorkflowSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/ActivateWorkflowSingleRecordCommand.tsx
index fe4773279a..772c551f57 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/ActivateWorkflowSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/ActivateWorkflowSingleRecordCommand.tsx
@@ -1,10 +1,10 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { useActivateWorkflowVersion } from '@/workflow/hooks/useActivateWorkflowVersion';
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
import { isDefined } from 'twenty-shared/utils';
-export const ActivateWorkflowSingleRecordAction = () => {
+export const ActivateWorkflowSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const { activateWorkflowVersion } = useActivateWorkflowVersion();
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(recordId);
@@ -20,5 +20,5 @@ export const ActivateWorkflowSingleRecordAction = () => {
});
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/AddNodeWorkflowSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/AddNodeWorkflowSingleRecordCommand.tsx
similarity index 69%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/AddNodeWorkflowSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/AddNodeWorkflowSingleRecordCommand.tsx
index f0d59fc762..07b06d0314 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/AddNodeWorkflowSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/AddNodeWorkflowSingleRecordCommand.tsx
@@ -1,10 +1,10 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { useSidePanelWorkflowNavigation } from '@/side-panel/pages/workflow/hooks/useSidePanelWorkflowNavigation';
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
import { isDefined } from 'twenty-shared/utils';
-export const AddNodeWorkflowSingleRecordAction = () => {
+export const AddNodeWorkflowSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(recordId);
const { openWorkflowCreateStepInSidePanel } =
@@ -18,5 +18,5 @@ export const AddNodeWorkflowSingleRecordAction = () => {
openWorkflowCreateStepInSidePanel(workflowWithCurrentVersion.id);
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/DeactivateWorkflowSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/DeactivateWorkflowSingleRecordCommand.tsx
similarity index 69%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/DeactivateWorkflowSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/DeactivateWorkflowSingleRecordCommand.tsx
index f2184da058..54ac6267ba 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/DeactivateWorkflowSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/DeactivateWorkflowSingleRecordCommand.tsx
@@ -1,10 +1,10 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { useDeactivateWorkflowVersion } from '@/workflow/hooks/useDeactivateWorkflowVersion';
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
import { isDefined } from 'twenty-shared/utils';
-export const DeactivateWorkflowSingleRecordAction = () => {
+export const DeactivateWorkflowSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const { deactivateWorkflowVersion } = useDeactivateWorkflowVersion();
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(recordId);
@@ -19,5 +19,5 @@ export const DeactivateWorkflowSingleRecordAction = () => {
});
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/DiscardDraftWorkflowSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/DiscardDraftWorkflowSingleRecordCommand.tsx
similarity index 68%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/DiscardDraftWorkflowSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/DiscardDraftWorkflowSingleRecordCommand.tsx
index 462dae6051..2484b6aafa 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/DiscardDraftWorkflowSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/DiscardDraftWorkflowSingleRecordCommand.tsx
@@ -1,10 +1,10 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { useDeleteOneWorkflowVersion } from '@/workflow/hooks/useDeleteOneWorkflowVersion';
import { useWorkflowWithCurrentVersion } from '@/workflow/hooks/useWorkflowWithCurrentVersion';
import { isDefined } from 'twenty-shared/utils';
-export const DiscardDraftWorkflowSingleRecordAction = () => {
+export const DiscardDraftWorkflowSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const { deleteOneWorkflowVersion } = useDeleteOneWorkflowVersion();
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(recordId);
@@ -19,5 +19,5 @@ export const DiscardDraftWorkflowSingleRecordAction = () => {
});
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/DuplicateWorkflowSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/DuplicateWorkflowSingleRecordCommand.tsx
similarity index 82%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/DuplicateWorkflowSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/DuplicateWorkflowSingleRecordCommand.tsx
index 9ada90f3a9..a3ca2b6fa6 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/DuplicateWorkflowSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/DuplicateWorkflowSingleRecordCommand.tsx
@@ -1,5 +1,5 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { CoreObjectNameSingular, AppPath } from 'twenty-shared/types';
import { useSnackBar } from '@/ui/feedback/snack-bar-manager/hooks/useSnackBar';
import { useDuplicateWorkflow } from '@/workflow/hooks/useDuplicateWorkflow';
@@ -9,7 +9,7 @@ import { isNonEmptyString } from '@sniptt/guards';
import { isDefined } from 'twenty-shared/utils';
import { useNavigateApp } from '~/hooks/useNavigateApp';
-export const DuplicateWorkflowSingleRecordAction = () => {
+export const DuplicateWorkflowSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const workflow = useWorkflowWithCurrentVersion(recordId);
const { duplicateWorkflow } = useDuplicateWorkflow();
@@ -42,5 +42,5 @@ export const DuplicateWorkflowSingleRecordAction = () => {
}
};
- return isDefined(workflow) ? : null;
+ return isDefined(workflow) ? : null;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/SeeActiveVersionWorkflowSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/SeeActiveVersionWorkflowSingleRecordCommand.tsx
similarity index 55%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/SeeActiveVersionWorkflowSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/SeeActiveVersionWorkflowSingleRecordCommand.tsx
index 10e174205f..2e370f6328 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/SeeActiveVersionWorkflowSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/SeeActiveVersionWorkflowSingleRecordCommand.tsx
@@ -1,10 +1,10 @@
-import { ActionLink } from '@/action-menu/actions/components/ActionLink';
-import { ActionDisplay } from '@/action-menu/actions/display/components/ActionDisplay';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { CommandLink } from '@/command-menu-item/display/components/CommandLink';
+import { CommandMenuItemDisplay } from '@/command-menu-item/display/components/CommandMenuItemDisplay';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { CoreObjectNameSingular, AppPath } from 'twenty-shared/types';
import { useActiveWorkflowVersion } from '@/workflow/hooks/useActiveWorkflowVersion';
-export const SeeActiveVersionWorkflowSingleRecordAction = () => {
+export const SeeActiveVersionWorkflowSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const { workflowVersion, loading } = useActiveWorkflowVersion({
@@ -12,11 +12,11 @@ export const SeeActiveVersionWorkflowSingleRecordAction = () => {
});
if (loading) {
- return ;
+ return ;
}
return (
- {
+export const SeeRunsWorkflowSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(recordId);
return (
- {
+export const SeeVersionsWorkflowSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(recordId);
return (
- {
+export const TestWorkflowSingleRecordCommand = () => {
const recordId = useSelectedRecordIdOrThrow();
const { runWorkflowVersion } = useRunWorkflowVersion();
const workflowWithCurrentVersion = useWorkflowWithCurrentVersion(recordId);
@@ -20,5 +20,5 @@ export const TestWorkflowSingleRecordAction = () => {
});
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/TidyUpWorkflowSingleRecordAction.tsx b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/TidyUpWorkflowSingleRecordCommand.tsx
similarity index 81%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/TidyUpWorkflowSingleRecordAction.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/TidyUpWorkflowSingleRecordCommand.tsx
index 9bbc355527..7c00fe385c 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/components/TidyUpWorkflowSingleRecordAction.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/components/TidyUpWorkflowSingleRecordCommand.tsx
@@ -1,5 +1,5 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { useSelectedRecordIdOrThrow } from '@/action-menu/actions/record-actions/single-record/hooks/useSelectedRecordIdOrThrow';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { useSelectedRecordIdOrThrow } from '@/command-menu-item/record/single-record/hooks/useSelectedRecordIdOrThrow';
import { useGetUpdatableWorkflowVersionOrThrow } from '@/workflow/hooks/useGetUpdatableWorkflowVersionOrThrow';
import { getWorkflowVisualizerComponentInstanceId } from '@/workflow/utils/getWorkflowVisualizerComponentInstanceId';
import { workflowDiagramComponentState } from '@/workflow/workflow-diagram/states/workflowDiagramComponentState';
@@ -7,7 +7,7 @@ import { useTidyUpWorkflowVersion } from '@/workflow/workflow-version/hooks/useT
import { isDefined } from 'twenty-shared/utils';
import { useStore } from 'jotai';
-export const TidyUpWorkflowSingleRecordAction = () => {
+export const TidyUpWorkflowSingleRecordCommand = () => {
const store = useStore();
const recordId = useSelectedRecordIdOrThrow();
const { tidyUpWorkflowVersion } = useTidyUpWorkflowVersion();
@@ -32,5 +32,5 @@ export const TidyUpWorkflowSingleRecordAction = () => {
await tidyUpWorkflowVersion(workflowVersionId, workflowDiagram);
};
- return ;
+ return ;
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/types/WorkflowSingleRecordActionsKeys.ts b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/types/WorkflowSingleRecordCommandKeys.ts
similarity index 91%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/types/WorkflowSingleRecordActionsKeys.ts
rename to packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/types/WorkflowSingleRecordCommandKeys.ts
index d8d6f3490a..43ccd977f3 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/single-record/workflow-actions/types/WorkflowSingleRecordActionsKeys.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/record/single-record/workflow/types/WorkflowSingleRecordCommandKeys.ts
@@ -1,4 +1,4 @@
-export enum WorkflowSingleRecordActionKeys {
+export enum WorkflowSingleRecordCommandKeys {
ACTIVATE = 'activate-workflow-single-record',
DEACTIVATE = 'deactivate-workflow-single-record',
DISCARD_DRAFT = 'discard-draft-workflow-single-record',
diff --git a/packages/twenty-front/src/modules/command-menu-item/record/types/DefaultRecordCommandKeys.ts b/packages/twenty-front/src/modules/command-menu-item/record/types/DefaultRecordCommandKeys.ts
new file mode 100644
index 0000000000..61129793d7
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/record/types/DefaultRecordCommandKeys.ts
@@ -0,0 +1,8 @@
+import { type MultipleRecordsCommandKeys } from '@/command-menu-item/record/multiple-records/types/MultipleRecordsCommandKeys';
+import { type NoSelectionRecordCommandKeys } from '@/command-menu-item/record/no-selection/types/NoSelectionRecordCommandKeys';
+import { type SingleRecordCommandKeys } from '@/command-menu-item/record/single-record/types/SingleRecordCommandKeys';
+
+export type DefaultRecordCommandKeys =
+ | NoSelectionRecordCommandKeys
+ | SingleRecordCommandKeys
+ | MultipleRecordsCommandKeys;
diff --git a/packages/twenty-front/src/modules/command-menu-item/record/utils/__tests__/inheritCommandMenuItemsFromDefaultConfig.test.tsx b/packages/twenty-front/src/modules/command-menu-item/record/utils/__tests__/inheritCommandMenuItemsFromDefaultConfig.test.tsx
new file mode 100644
index 0000000000..5000398ec1
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/record/utils/__tests__/inheritCommandMenuItemsFromDefaultConfig.test.tsx
@@ -0,0 +1,330 @@
+import { DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG } from '@/command-menu-item/record/constants/DefaultRecordCommandMenuItemsConfig';
+import { NoSelectionRecordCommandKeys } from '@/command-menu-item/record/no-selection/types/NoSelectionRecordCommandKeys';
+import { SingleRecordCommandKeys } from '@/command-menu-item/record/single-record/types/SingleRecordCommandKeys';
+import { type CommandMenuItemConfig } from '@/command-menu-item/types/CommandMenuItemConfig';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
+import { type DefaultRecordCommandKeys } from '@/command-menu-item/record/types/DefaultRecordCommandKeys';
+import { IconHeart, IconPlus } from 'twenty-ui/display';
+import { inheritCommandMenuItemsFromDefaultConfig } from '@/command-menu-item/record/utils/inheritCommandMenuItemsFromDefaultConfig';
+
+const MockComponent = Mock Component
;
+
+describe('inheritCommandMenuItemsFromDefaultConfig', () => {
+ it('should return empty object when no action keys are provided', () => {
+ const result = inheritCommandMenuItemsFromDefaultConfig({
+ config: {},
+ commandKeys: [],
+ propertiesToOverwrite: {},
+ });
+
+ expect(result).toEqual({});
+ });
+
+ it('should return only provided config when no default action keys are specified', () => {
+ const customConfig: Record = {
+ 'custom-action': {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.Object,
+ key: 'custom-action',
+ label: 'Custom Action',
+ position: 100,
+ Icon: IconPlus,
+ shouldBeRegistered: () => true,
+ component: MockComponent,
+ },
+ };
+
+ const result = inheritCommandMenuItemsFromDefaultConfig({
+ config: customConfig,
+ commandKeys: [],
+ propertiesToOverwrite: {},
+ });
+
+ expect(result).toEqual(customConfig);
+ });
+
+ it('should inherit actions from default config', () => {
+ const commandKeys: DefaultRecordCommandKeys[] = [
+ NoSelectionRecordCommandKeys.CREATE_NEW_RECORD,
+ SingleRecordCommandKeys.ADD_TO_FAVORITES,
+ ];
+
+ const result = inheritCommandMenuItemsFromDefaultConfig({
+ config: {},
+ commandKeys,
+ propertiesToOverwrite: {},
+ });
+
+ expect(result).toEqual({
+ [NoSelectionRecordCommandKeys.CREATE_NEW_RECORD]:
+ DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG[
+ NoSelectionRecordCommandKeys.CREATE_NEW_RECORD
+ ],
+ [SingleRecordCommandKeys.ADD_TO_FAVORITES]:
+ DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG[
+ SingleRecordCommandKeys.ADD_TO_FAVORITES
+ ],
+ });
+ });
+
+ it('should overwrite specific properties of inherited actions', () => {
+ const commandKeys: DefaultRecordCommandKeys[] = [
+ NoSelectionRecordCommandKeys.CREATE_NEW_RECORD,
+ ];
+
+ const propertiesToOverwrite = {
+ [NoSelectionRecordCommandKeys.CREATE_NEW_RECORD]: {
+ label: 'Custom Create Label',
+ position: 999,
+ isPinned: false,
+ },
+ };
+
+ const result = inheritCommandMenuItemsFromDefaultConfig({
+ config: {},
+ commandKeys,
+ propertiesToOverwrite,
+ });
+
+ const expectedCommandMenuItem = {
+ ...DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG[
+ NoSelectionRecordCommandKeys.CREATE_NEW_RECORD
+ ],
+ label: 'Custom Create Label',
+ position: 999,
+ isPinned: false,
+ };
+
+ expect(result).toEqual({
+ [NoSelectionRecordCommandKeys.CREATE_NEW_RECORD]: expectedCommandMenuItem,
+ });
+ });
+
+ it('should overwrite properties for multiple actions', () => {
+ const commandKeys: DefaultRecordCommandKeys[] = [
+ NoSelectionRecordCommandKeys.CREATE_NEW_RECORD,
+ SingleRecordCommandKeys.ADD_TO_FAVORITES,
+ ];
+
+ const propertiesToOverwrite = {
+ [NoSelectionRecordCommandKeys.CREATE_NEW_RECORD]: {
+ position: 10,
+ },
+ [SingleRecordCommandKeys.ADD_TO_FAVORITES]: {
+ label: 'Custom Favorite Label',
+ Icon: IconHeart,
+ },
+ };
+
+ const result = inheritCommandMenuItemsFromDefaultConfig({
+ config: {},
+ commandKeys,
+ propertiesToOverwrite,
+ });
+
+ expect(result[NoSelectionRecordCommandKeys.CREATE_NEW_RECORD]).toEqual({
+ ...DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG[
+ NoSelectionRecordCommandKeys.CREATE_NEW_RECORD
+ ],
+ position: 10,
+ });
+
+ expect(result[SingleRecordCommandKeys.ADD_TO_FAVORITES]).toEqual({
+ ...DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG[
+ SingleRecordCommandKeys.ADD_TO_FAVORITES
+ ],
+ label: 'Custom Favorite Label',
+ Icon: IconHeart,
+ });
+ });
+
+ it('should only overwrite properties for specified actions', () => {
+ const commandKeys: DefaultRecordCommandKeys[] = [
+ NoSelectionRecordCommandKeys.CREATE_NEW_RECORD,
+ SingleRecordCommandKeys.ADD_TO_FAVORITES,
+ ];
+
+ const propertiesToOverwrite = {
+ [NoSelectionRecordCommandKeys.CREATE_NEW_RECORD]: {
+ position: 10,
+ },
+ };
+
+ const result = inheritCommandMenuItemsFromDefaultConfig({
+ config: {},
+ commandKeys,
+ propertiesToOverwrite,
+ });
+
+ expect(result[NoSelectionRecordCommandKeys.CREATE_NEW_RECORD]).toEqual({
+ ...DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG[
+ NoSelectionRecordCommandKeys.CREATE_NEW_RECORD
+ ],
+ position: 10,
+ });
+
+ expect(result[SingleRecordCommandKeys.ADD_TO_FAVORITES]).toEqual(
+ DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG[
+ SingleRecordCommandKeys.ADD_TO_FAVORITES
+ ],
+ );
+ });
+
+ it('should merge inherited actions with provided config', () => {
+ const customConfig: Record = {
+ 'custom-action': {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.Object,
+ key: 'custom-action',
+ label: 'Custom Action',
+ position: 100,
+ Icon: IconPlus,
+ shouldBeRegistered: () => true,
+ component: MockComponent,
+ },
+ };
+
+ const commandKeys: DefaultRecordCommandKeys[] = [
+ NoSelectionRecordCommandKeys.CREATE_NEW_RECORD,
+ ];
+
+ const result = inheritCommandMenuItemsFromDefaultConfig({
+ config: customConfig,
+ commandKeys,
+ propertiesToOverwrite: {},
+ });
+
+ expect(result).toEqual({
+ [NoSelectionRecordCommandKeys.CREATE_NEW_RECORD]:
+ DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG[
+ NoSelectionRecordCommandKeys.CREATE_NEW_RECORD
+ ],
+ 'custom-action': customConfig['custom-action'],
+ });
+ });
+
+ it('should prioritize provided config over inherited actions when keys conflict', () => {
+ const customConfig: Record = {
+ [NoSelectionRecordCommandKeys.CREATE_NEW_RECORD]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.Object,
+ key: NoSelectionRecordCommandKeys.CREATE_NEW_RECORD,
+ label: 'Overridden Create Action',
+ position: 999,
+ Icon: IconHeart,
+ shouldBeRegistered: () => false,
+ component: MockComponent,
+ },
+ };
+
+ const commandKeys: DefaultRecordCommandKeys[] = [
+ NoSelectionRecordCommandKeys.CREATE_NEW_RECORD,
+ ];
+
+ const result = inheritCommandMenuItemsFromDefaultConfig({
+ config: customConfig,
+ commandKeys,
+ propertiesToOverwrite: {},
+ });
+
+ expect(result[NoSelectionRecordCommandKeys.CREATE_NEW_RECORD]).toEqual(
+ customConfig[NoSelectionRecordCommandKeys.CREATE_NEW_RECORD],
+ );
+ expect(result[NoSelectionRecordCommandKeys.CREATE_NEW_RECORD].label).toBe(
+ 'Overridden Create Action',
+ );
+ });
+
+ it('should handle complex scenario with inheritance, overrides, and custom config', () => {
+ const customConfig: Record = {
+ 'custom-action-1': {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.Object,
+ key: 'custom-action-1',
+ label: 'Custom Action 1',
+ position: 50,
+ Icon: IconPlus,
+ shouldBeRegistered: () => true,
+ component: MockComponent,
+ },
+ [SingleRecordCommandKeys.ADD_TO_FAVORITES]: {
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
+ key: SingleRecordCommandKeys.ADD_TO_FAVORITES,
+ label: 'Completely Custom Favorites',
+ position: 1000,
+ Icon: IconHeart,
+ shouldBeRegistered: () => false,
+ component: MockComponent,
+ },
+ };
+
+ const commandKeys: DefaultRecordCommandKeys[] = [
+ NoSelectionRecordCommandKeys.CREATE_NEW_RECORD,
+ SingleRecordCommandKeys.ADD_TO_FAVORITES,
+ SingleRecordCommandKeys.REMOVE_FROM_FAVORITES,
+ ];
+
+ const propertiesToOverwrite = {
+ [NoSelectionRecordCommandKeys.CREATE_NEW_RECORD]: {
+ label: 'Modified Create Label',
+ position: 5,
+ },
+ [SingleRecordCommandKeys.REMOVE_FROM_FAVORITES]: {
+ isPinned: false,
+ },
+ };
+
+ const result = inheritCommandMenuItemsFromDefaultConfig({
+ config: customConfig,
+ commandKeys,
+ propertiesToOverwrite,
+ });
+
+ expect(Object.keys(result)).toHaveLength(4);
+
+ expect(result['custom-action-1']).toEqual(customConfig['custom-action-1']);
+
+ expect(result[NoSelectionRecordCommandKeys.CREATE_NEW_RECORD]).toEqual({
+ ...DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG[
+ NoSelectionRecordCommandKeys.CREATE_NEW_RECORD
+ ],
+ label: 'Modified Create Label',
+ position: 5,
+ });
+
+ expect(result[SingleRecordCommandKeys.ADD_TO_FAVORITES]).toEqual(
+ customConfig[SingleRecordCommandKeys.ADD_TO_FAVORITES],
+ );
+
+ expect(result[SingleRecordCommandKeys.REMOVE_FROM_FAVORITES]).toEqual({
+ ...DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG[
+ SingleRecordCommandKeys.REMOVE_FROM_FAVORITES
+ ],
+ isPinned: false,
+ });
+ });
+
+ it('should handle empty overrides gracefully', () => {
+ const commandKeys: DefaultRecordCommandKeys[] = [
+ NoSelectionRecordCommandKeys.CREATE_NEW_RECORD,
+ ];
+
+ const propertiesToOverwrite = {
+ [NoSelectionRecordCommandKeys.CREATE_NEW_RECORD]: {},
+ };
+
+ const result = inheritCommandMenuItemsFromDefaultConfig({
+ config: {},
+ commandKeys,
+ propertiesToOverwrite,
+ });
+
+ expect(result[NoSelectionRecordCommandKeys.CREATE_NEW_RECORD]).toEqual(
+ DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG[
+ NoSelectionRecordCommandKeys.CREATE_NEW_RECORD
+ ],
+ );
+ });
+});
diff --git a/packages/twenty-front/src/modules/command-menu-item/record/utils/inheritCommandMenuItemsFromDefaultConfig.ts b/packages/twenty-front/src/modules/command-menu-item/record/utils/inheritCommandMenuItemsFromDefaultConfig.ts
new file mode 100644
index 0000000000..d7fa3cd8a5
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/record/utils/inheritCommandMenuItemsFromDefaultConfig.ts
@@ -0,0 +1,31 @@
+import { DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG } from '@/command-menu-item/record/constants/DefaultRecordCommandMenuItemsConfig';
+import { type CommandMenuItemConfig } from '@/command-menu-item/types/CommandMenuItemConfig';
+import { type DefaultRecordCommandKeys } from '@/command-menu-item/record/types/DefaultRecordCommandKeys';
+
+export const inheritCommandMenuItemsFromDefaultConfig = ({
+ config,
+ commandKeys,
+ propertiesToOverwrite,
+}: {
+ config: Record;
+ commandKeys: DefaultRecordCommandKeys[];
+ propertiesToOverwrite: Partial<
+ Record>
+ >;
+}): Record => {
+ const commandMenuItemsFromDefaultConfig = commandKeys.reduce(
+ (acc, key) => ({
+ ...acc,
+ [key]: {
+ ...DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG[key],
+ ...propertiesToOverwrite[key],
+ },
+ }),
+ {} as Record,
+ );
+
+ return {
+ ...commandMenuItemsFromDefaultConfig,
+ ...config,
+ };
+};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/utils/isBulkRecordsManualTrigger.ts b/packages/twenty-front/src/modules/command-menu-item/record/utils/isBulkRecordsManualTrigger.ts
similarity index 100%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/utils/isBulkRecordsManualTrigger.ts
rename to packages/twenty-front/src/modules/command-menu-item/record/utils/isBulkRecordsManualTrigger.ts
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/utils/isGlobalManualTrigger.ts b/packages/twenty-front/src/modules/command-menu-item/record/utils/isGlobalManualTrigger.ts
similarity index 100%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/utils/isGlobalManualTrigger.ts
rename to packages/twenty-front/src/modules/command-menu-item/record/utils/isGlobalManualTrigger.ts
diff --git a/packages/twenty-front/src/modules/action-menu/actions/record-actions/run-workflow-actions/hooks/useRunWorkflowRecordActions.tsx b/packages/twenty-front/src/modules/command-menu-item/record/workflow/hooks/useRunWorkflowRecordCommands.tsx
similarity index 90%
rename from packages/twenty-front/src/modules/action-menu/actions/record-actions/run-workflow-actions/hooks/useRunWorkflowRecordActions.tsx
rename to packages/twenty-front/src/modules/command-menu-item/record/workflow/hooks/useRunWorkflowRecordCommands.tsx
index c5fdb79e6c..74b15870ac 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/record-actions/run-workflow-actions/hooks/useRunWorkflowRecordActions.tsx
+++ b/packages/twenty-front/src/modules/command-menu-item/record/workflow/hooks/useRunWorkflowRecordCommands.tsx
@@ -1,7 +1,7 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { isBulkRecordsManualTrigger } from '@/action-menu/actions/record-actions/utils/isBulkRecordsManualTrigger';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionType } from '@/action-menu/actions/types/ActionType';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { isBulkRecordsManualTrigger } from '@/command-menu-item/record/utils/isBulkRecordsManualTrigger';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
import { contextStoreIsPageInEditModeComponentState } from '@/context-store/states/contextStoreIsPageInEditModeComponentState';
import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
@@ -20,7 +20,7 @@ import { capitalize, isDefined } from 'twenty-shared/utils';
import { useIcons } from 'twenty-ui/display';
import { useStore } from 'jotai';
-export const useRunWorkflowRecordActions = ({
+export const useRunWorkflowRecordCommands = ({
objectMetadataItem,
skip,
}: {
@@ -130,9 +130,9 @@ export const useRunWorkflowRecordActions = ({
);
return {
- type: ActionType.WorkflowRun,
+ type: CommandMenuItemType.WorkflowRun,
key: `workflow-run-${activeWorkflowVersion.id}`,
- scope: ActionScope.RecordSelection,
+ scope: CommandMenuItemScope.RecordSelection,
label: name,
shortLabel: name,
position: index,
@@ -142,7 +142,7 @@ export const useRunWorkflowRecordActions = ({
activeWorkflowVersion.trigger?.settings?.isPinned,
shouldBeRegistered: () => true,
component: (
- {
if (!isDefined(selectedRecordIds)) {
return;
@@ -153,7 +153,7 @@ export const useRunWorkflowRecordActions = ({
activeWorkflowVersion,
);
}}
- closeSidePanelOnCommandMenuListActionExecution={false}
+ closeSidePanelOnCommandMenuListExecution={false}
/>
),
};
diff --git a/packages/twenty-front/src/modules/command-menu-item/states/recordIndexCommandMenuDropdownPositionComponentState.ts b/packages/twenty-front/src/modules/command-menu-item/states/recordIndexCommandMenuDropdownPositionComponentState.ts
new file mode 100644
index 0000000000..d2ca78721a
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/states/recordIndexCommandMenuDropdownPositionComponentState.ts
@@ -0,0 +1,13 @@
+import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
+import { type PositionType } from '@/command-menu-item/types/PositionType';
+import { createAtomComponentState } from '@/ui/utilities/state/jotai/utils/createAtomComponentState';
+
+export const recordIndexCommandMenuDropdownPositionComponentState =
+ createAtomComponentState({
+ key: 'recordIndexCommandMenuDropdownPositionComponentState',
+ defaultValue: {
+ x: null,
+ y: null,
+ },
+ componentInstanceContext: CommandMenuComponentInstanceContext,
+ });
diff --git a/packages/twenty-front/src/modules/action-menu/actions/types/ActionConfig.ts b/packages/twenty-front/src/modules/command-menu-item/types/CommandMenuItemConfig.ts
similarity index 57%
rename from packages/twenty-front/src/modules/action-menu/actions/types/ActionConfig.ts
rename to packages/twenty-front/src/modules/command-menu-item/types/CommandMenuItemConfig.ts
index 913866670f..d767aeb76a 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/types/ActionConfig.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/types/CommandMenuItemConfig.ts
@@ -1,15 +1,15 @@
-import { type ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { type ActionType } from '@/action-menu/actions/types/ActionType';
-import { type ActionViewType } from 'twenty-shared/types';
-import { type ShouldBeRegisteredFunctionParams } from '@/action-menu/actions/types/ShouldBeRegisteredFunctionParams';
+import { type CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { type CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
+import { type CommandMenuItemViewType } from 'twenty-shared/types';
+import { type ShouldBeRegisteredFunctionParams } from '@/command-menu-item/types/ShouldBeRegisteredFunctionParams';
import { type MessageDescriptor } from '@lingui/core';
import { type IconComponent } from 'twenty-ui/display';
import { type MenuItemAccent } from 'twenty-ui/navigation';
import { type PermissionFlagType } from '~/generated-metadata/graphql';
-export type ActionConfig = {
- type: ActionType;
- scope: ActionScope;
+export type CommandMenuItemConfig = {
+ type: CommandMenuItemType;
+ scope: CommandMenuItemScope;
key: string;
label: MessageDescriptor | string;
shortLabel?: MessageDescriptor | string;
@@ -19,7 +19,7 @@ export type ActionConfig = {
isPinned?: boolean;
isPrimaryCTA?: boolean;
accent?: MenuItemAccent;
- availableOn?: ActionViewType[];
+ availableOn?: CommandMenuItemViewType[];
shouldBeRegistered: (params: ShouldBeRegisteredFunctionParams) => boolean;
component: React.ReactNode;
hotKeys?: string[];
diff --git a/packages/twenty-front/src/modules/command-menu-item/types/CommandMenuItemContainerType.ts b/packages/twenty-front/src/modules/command-menu-item/types/CommandMenuItemContainerType.ts
new file mode 100644
index 0000000000..08bda5bd3e
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/types/CommandMenuItemContainerType.ts
@@ -0,0 +1,6 @@
+export type CommandMenuItemContainerType =
+ | 'command-menu-list'
+ | 'index-page-header'
+ | 'index-page-dropdown'
+ | 'show-page-header'
+ | 'command-menu-show-page-dropdown';
diff --git a/packages/twenty-front/src/modules/action-menu/actions/types/ActionScope.ts b/packages/twenty-front/src/modules/command-menu-item/types/CommandMenuItemScope.ts
similarity index 78%
rename from packages/twenty-front/src/modules/action-menu/actions/types/ActionScope.ts
rename to packages/twenty-front/src/modules/command-menu-item/types/CommandMenuItemScope.ts
index 259a35e266..1c00826e95 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/types/ActionScope.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/types/CommandMenuItemScope.ts
@@ -1,4 +1,4 @@
-export enum ActionScope {
+export enum CommandMenuItemScope {
Global = 'Global',
RecordSelection = 'RecordSelection',
CreateRelatedRecord = 'CreateRelatedRecord',
diff --git a/packages/twenty-front/src/modules/action-menu/actions/types/ActionType.ts b/packages/twenty-front/src/modules/command-menu-item/types/CommandMenuItemType.ts
similarity index 81%
rename from packages/twenty-front/src/modules/action-menu/actions/types/ActionType.ts
rename to packages/twenty-front/src/modules/command-menu-item/types/CommandMenuItemType.ts
index 9f1b978932..f9f78bd99a 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/types/ActionType.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/types/CommandMenuItemType.ts
@@ -1,4 +1,4 @@
-export enum ActionType {
+export enum CommandMenuItemType {
Standard = 'Standard',
WorkflowRun = 'WorkflowRun',
FrontComponent = 'FrontComponent',
diff --git a/packages/twenty-front/src/modules/action-menu/types/PositionType.ts b/packages/twenty-front/src/modules/command-menu-item/types/PositionType.ts
similarity index 100%
rename from packages/twenty-front/src/modules/action-menu/types/PositionType.ts
rename to packages/twenty-front/src/modules/command-menu-item/types/PositionType.ts
diff --git a/packages/twenty-front/src/modules/action-menu/actions/types/ShouldBeRegisteredFunctionParams.ts b/packages/twenty-front/src/modules/command-menu-item/types/ShouldBeRegisteredFunctionParams.ts
similarity index 94%
rename from packages/twenty-front/src/modules/action-menu/actions/types/ShouldBeRegisteredFunctionParams.ts
rename to packages/twenty-front/src/modules/command-menu-item/types/ShouldBeRegisteredFunctionParams.ts
index bae8d83cc3..b4f00e2921 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/types/ShouldBeRegisteredFunctionParams.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/types/ShouldBeRegisteredFunctionParams.ts
@@ -3,7 +3,7 @@ import { type RecordFilter } from '@/object-record/record-filter/types/RecordFil
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
import { type WorkflowWithCurrentVersion } from '@/workflow/types/Workflow';
import {
- type ActionViewType,
+ type CommandMenuItemViewType,
type ObjectPermissions,
} from 'twenty-shared/types';
import { type FeatureFlagKey } from '~/generated-metadata/graphql';
@@ -23,7 +23,7 @@ export type ShouldBeRegisteredFunctionParams = {
selectedRecord?: ObjectRecord;
numberOfSelectedRecords?: number;
workflowWithCurrentVersion?: WorkflowWithCurrentVersion;
- viewType?: ActionViewType;
+ viewType?: CommandMenuItemViewType;
getTargetObjectReadPermission: (
objectMetadataItemNameSingular: string,
) => boolean;
diff --git a/packages/twenty-front/src/modules/command-menu-item/utils/__tests__/getCommandMenuDropdownIdFromCommandMenuId.test.ts b/packages/twenty-front/src/modules/command-menu-item/utils/__tests__/getCommandMenuDropdownIdFromCommandMenuId.test.ts
new file mode 100644
index 0000000000..d6d27bcfc2
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/utils/__tests__/getCommandMenuDropdownIdFromCommandMenuId.test.ts
@@ -0,0 +1,9 @@
+import { getCommandMenuDropdownIdFromCommandMenuId } from '@/command-menu-item/utils/getCommandMenuDropdownIdFromCommandMenuId';
+
+describe('getCommandMenuDropdownIdFromCommandMenuId', () => {
+ it('should return the correct action menu dropdown id', () => {
+ expect(getCommandMenuDropdownIdFromCommandMenuId('command-menu-id')).toBe(
+ 'command-menu-dropdown-command-menu-id',
+ );
+ });
+});
diff --git a/packages/twenty-front/src/modules/command-menu-item/utils/__tests__/getCommandMenuIdFromRecordIndexId.test.ts b/packages/twenty-front/src/modules/command-menu-item/utils/__tests__/getCommandMenuIdFromRecordIndexId.test.ts
new file mode 100644
index 0000000000..9758afde4b
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/utils/__tests__/getCommandMenuIdFromRecordIndexId.test.ts
@@ -0,0 +1,9 @@
+import { getCommandMenuIdFromRecordIndexId } from '@/command-menu-item/utils/getCommandMenuIdFromRecordIndexId';
+
+describe('getCommandMenuIdFromRecordIndexId', () => {
+ it('should return the correct action menu id', () => {
+ expect(getCommandMenuIdFromRecordIndexId('record-index-id')).toBe(
+ 'command-menu-record-index-record-index-id',
+ );
+ });
+});
diff --git a/packages/twenty-front/src/modules/command-menu-item/utils/__tests__/getSidePanelCommandMenuDropdownIdFromCommandMenuId.test.ts b/packages/twenty-front/src/modules/command-menu-item/utils/__tests__/getSidePanelCommandMenuDropdownIdFromCommandMenuId.test.ts
new file mode 100644
index 0000000000..f6ffb0c8d5
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/utils/__tests__/getSidePanelCommandMenuDropdownIdFromCommandMenuId.test.ts
@@ -0,0 +1,9 @@
+import { getSidePanelCommandMenuDropdownIdFromCommandMenuId } from '@/command-menu-item/utils/getSidePanelCommandMenuDropdownIdFromCommandMenuId';
+
+describe('getSidePanelCommandMenuDropdownIdFromCommandMenuId', () => {
+ it('should return the side panel action menu dropdown id', () => {
+ expect(
+ getSidePanelCommandMenuDropdownIdFromCommandMenuId('command-menu-id'),
+ ).toBe('side-panel-command-menu-dropdown-command-menu-id');
+ });
+});
diff --git a/packages/twenty-front/src/modules/action-menu/utils/computeProgressText.ts b/packages/twenty-front/src/modules/command-menu-item/utils/computeProgressText.ts
similarity index 100%
rename from packages/twenty-front/src/modules/action-menu/utils/computeProgressText.ts
rename to packages/twenty-front/src/modules/command-menu-item/utils/computeProgressText.ts
diff --git a/packages/twenty-front/src/modules/command-menu-item/utils/getCommandMenuDropdownIdFromCommandMenuId.ts b/packages/twenty-front/src/modules/command-menu-item/utils/getCommandMenuDropdownIdFromCommandMenuId.ts
new file mode 100644
index 0000000000..d72b94d439
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/utils/getCommandMenuDropdownIdFromCommandMenuId.ts
@@ -0,0 +1,5 @@
+export const getCommandMenuDropdownIdFromCommandMenuId = (
+ commandMenuId: string,
+) => {
+ return `command-menu-dropdown-${commandMenuId}`;
+};
diff --git a/packages/twenty-front/src/modules/command-menu-item/utils/getCommandMenuIdFromRecordIndexId.ts b/packages/twenty-front/src/modules/command-menu-item/utils/getCommandMenuIdFromRecordIndexId.ts
new file mode 100644
index 0000000000..ff1bdf85e4
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/utils/getCommandMenuIdFromRecordIndexId.ts
@@ -0,0 +1,3 @@
+export const getCommandMenuIdFromRecordIndexId = (recordIndexId: string) => {
+ return `command-menu-record-index-${recordIndexId}`;
+};
diff --git a/packages/twenty-front/src/modules/command-menu-item/utils/getCommandMenuItemConfig.ts b/packages/twenty-front/src/modules/command-menu-item/utils/getCommandMenuItemConfig.ts
new file mode 100644
index 0000000000..ab42f46718
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/utils/getCommandMenuItemConfig.ts
@@ -0,0 +1,44 @@
+import { DASHBOARD_COMMAND_MENU_ITEMS_CONFIG } from '@/command-menu-item/record/constants/DashboardCommandMenuItemsConfig';
+import { DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG } from '@/command-menu-item/record/constants/DefaultRecordCommandMenuItemsConfig';
+import { WORKFLOW_COMMAND_MENU_ITEMS_CONFIG } from '@/command-menu-item/record/constants/WorkflowCommandMenuItemsConfig';
+import { WORKFLOW_RUNS_COMMAND_MENU_ITEMS_CONFIG } from '@/command-menu-item/record/constants/WorkflowRunsCommandMenuItemsConfig';
+import { WORKFLOW_VERSIONS_COMMAND_MENU_ITEMS_CONFIG } from '@/command-menu-item/record/constants/WorkflowVersionsCommandMenuItemsConfig';
+import { WORKSPACE_MEMBERS_COMMAND_MENU_ITEMS_CONFIG } from '@/command-menu-item/record/constants/WorkspaceMembersCommandMenuItemsConfig';
+import { type CommandMenuItemConfig } from '@/command-menu-item/types/CommandMenuItemConfig';
+import { CoreObjectNameSingular } from 'twenty-shared/types';
+import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
+import { isDefined } from 'twenty-shared/utils';
+
+export const getCommandMenuItemConfig = ({
+ objectMetadataItem,
+}: {
+ objectMetadataItem?: ObjectMetadataItem;
+}): Record => {
+ if (!isDefined(objectMetadataItem)) {
+ return {};
+ }
+
+ switch (objectMetadataItem.nameSingular) {
+ case CoreObjectNameSingular.Dashboard: {
+ return DASHBOARD_COMMAND_MENU_ITEMS_CONFIG;
+ }
+ case CoreObjectNameSingular.Workflow: {
+ return WORKFLOW_COMMAND_MENU_ITEMS_CONFIG;
+ }
+ case CoreObjectNameSingular.WorkflowVersion: {
+ return WORKFLOW_VERSIONS_COMMAND_MENU_ITEMS_CONFIG;
+ }
+ case CoreObjectNameSingular.WorkflowRun: {
+ return WORKFLOW_RUNS_COMMAND_MENU_ITEMS_CONFIG;
+ }
+ case CoreObjectNameSingular.WorkspaceMember: {
+ return WORKSPACE_MEMBERS_COMMAND_MENU_ITEMS_CONFIG;
+ }
+ case CoreObjectNameSingular.Company: {
+ return DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG;
+ }
+ default: {
+ return DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG;
+ }
+ }
+};
diff --git a/packages/twenty-front/src/modules/action-menu/utils/getActionLabel.ts b/packages/twenty-front/src/modules/command-menu-item/utils/getCommandMenuItemLabel.ts
similarity index 68%
rename from packages/twenty-front/src/modules/action-menu/utils/getActionLabel.ts
rename to packages/twenty-front/src/modules/command-menu-item/utils/getCommandMenuItemLabel.ts
index 55487b22e4..8b2518de4a 100644
--- a/packages/twenty-front/src/modules/action-menu/utils/getActionLabel.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/utils/getCommandMenuItemLabel.ts
@@ -1,6 +1,8 @@
import { i18n, type MessageDescriptor } from '@lingui/core';
import { isString } from '@sniptt/guards';
-export const getActionLabel = (label: string | MessageDescriptor): string => {
+export const getCommandMenuItemLabel = (
+ label: string | MessageDescriptor,
+): string => {
return isString(label) ? label : i18n._(label);
};
diff --git a/packages/twenty-front/src/modules/action-menu/actions/utils/getActionViewType.ts b/packages/twenty-front/src/modules/command-menu-item/utils/getCommandMenuItemViewType.ts
similarity index 69%
rename from packages/twenty-front/src/modules/action-menu/actions/utils/getActionViewType.ts
rename to packages/twenty-front/src/modules/command-menu-item/utils/getCommandMenuItemViewType.ts
index 4846065a09..67d1a75816 100644
--- a/packages/twenty-front/src/modules/action-menu/actions/utils/getActionViewType.ts
+++ b/packages/twenty-front/src/modules/command-menu-item/utils/getCommandMenuItemViewType.ts
@@ -1,8 +1,8 @@
-import { ActionViewType } from 'twenty-shared/types';
+import { CommandMenuItemViewType } from 'twenty-shared/types';
import { type ContextStoreTargetedRecordsRule } from '@/context-store/states/contextStoreTargetedRecordsRuleComponentState';
import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType';
-export const getActionViewType = (
+export const getCommandMenuItemViewType = (
contextStoreCurrentViewType: ContextStoreViewType | null,
contextStoreTargetedRecordsRule: ContextStoreTargetedRecordsRule,
) => {
@@ -11,22 +11,22 @@ export const getActionViewType = (
}
if (contextStoreCurrentViewType === ContextStoreViewType.ShowPage) {
- return ActionViewType.SHOW_PAGE;
+ return CommandMenuItemViewType.SHOW_PAGE;
}
if (
contextStoreTargetedRecordsRule.mode === 'selection' &&
contextStoreTargetedRecordsRule.selectedRecordIds.length === 0
) {
- return ActionViewType.INDEX_PAGE_NO_SELECTION;
+ return CommandMenuItemViewType.INDEX_PAGE_NO_SELECTION;
}
if (
contextStoreTargetedRecordsRule.mode === 'selection' &&
contextStoreTargetedRecordsRule.selectedRecordIds.length === 1
) {
- return ActionViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION;
+ return CommandMenuItemViewType.INDEX_PAGE_SINGLE_RECORD_SELECTION;
}
- return ActionViewType.INDEX_PAGE_BULK_SELECTION;
+ return CommandMenuItemViewType.INDEX_PAGE_BULK_SELECTION;
};
diff --git a/packages/twenty-front/src/modules/command-menu-item/utils/getSidePanelCommandMenuDropdownIdFromCommandMenuId.ts b/packages/twenty-front/src/modules/command-menu-item/utils/getSidePanelCommandMenuDropdownIdFromCommandMenuId.ts
new file mode 100644
index 0000000000..64e0b82255
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu-item/utils/getSidePanelCommandMenuDropdownIdFromCommandMenuId.ts
@@ -0,0 +1,5 @@
+export const getSidePanelCommandMenuDropdownIdFromCommandMenuId = (
+ commandMenuId: string,
+) => {
+ return `side-panel-command-menu-dropdown-${commandMenuId}`;
+};
diff --git a/packages/twenty-front/src/modules/command-menu/components/CommandMenuButton.tsx b/packages/twenty-front/src/modules/command-menu/components/CommandMenuButton.tsx
new file mode 100644
index 0000000000..a1738d976f
--- /dev/null
+++ b/packages/twenty-front/src/modules/command-menu/components/CommandMenuButton.tsx
@@ -0,0 +1,88 @@
+import { styled } from '@linaria/react';
+import { i18n, type MessageDescriptor } from '@lingui/core';
+import { isString } from '@sniptt/guards';
+import { type MouseEvent } from 'react';
+import {
+ AppTooltip,
+ type IconComponent,
+ TooltipDelay,
+ TooltipPosition,
+} from 'twenty-ui/display';
+import { Button, IconButton } from 'twenty-ui/input';
+import { themeCssVariables } from 'twenty-ui/theme-constants';
+
+const StyledWrapper = styled.div`
+ font-size: ${themeCssVariables.font.size.md};
+`;
+
+export type CommandMenuButtonProps = {
+ command: {
+ key: string;
+ label: string | MessageDescriptor;
+ shortLabel?: string | MessageDescriptor;
+ Icon: IconComponent;
+ isPrimaryCTA?: boolean;
+ };
+ onClick?: (event?: MouseEvent) => void;
+ to?: string;
+};
+
+const getCommandMenuButtonLabel = (
+ label: string | MessageDescriptor,
+): string => {
+ return isString(label) ? label : i18n._(label);
+};
+
+export const CommandMenuButton = ({
+ command,
+ onClick,
+ to,
+}: CommandMenuButtonProps) => {
+ const resolvedLabel = getCommandMenuButtonLabel(command.label);
+
+ const resolvedShortLabel =
+ command.shortLabel === undefined
+ ? undefined
+ : getCommandMenuButtonLabel(command.shortLabel);
+
+ const buttonAccent = command.isPrimaryCTA ? 'blue' : 'default';
+
+ return (
+ <>
+ {resolvedShortLabel !== undefined ? (
+
+ ) : (
+
+ )}
+ >
+ );
+};
diff --git a/packages/twenty-front/src/modules/command-menu/components/__stories__/CommandMenu.stories.tsx b/packages/twenty-front/src/modules/command-menu/components/__stories__/CommandMenu.stories.tsx
index 341172035a..65f7104362 100644
--- a/packages/twenty-front/src/modules/command-menu/components/__stories__/CommandMenu.stories.tsx
+++ b/packages/twenty-front/src/modules/command-menu/components/__stories__/CommandMenu.stories.tsx
@@ -20,7 +20,7 @@ import {
} from '~/testing/mock-data/users';
import { sleep } from '~/utils/sleep';
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
+import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
import { currentUserWorkspaceState } from '@/auth/states/currentUserWorkspaceState';
import { SidePanelRouter } from '@/side-panel/components/SidePanelRouter';
import { SIDE_PANEL_COMPONENT_INSTANCE_ID } from '@/side-panel/constants/SidePanelComponentInstanceId';
@@ -55,7 +55,7 @@ const ContextStoreDecorator: Decorator = (Story) => {
-
{
>
-
+
diff --git a/packages/twenty-front/src/modules/command-menu/hooks/__tests__/useSetGlobalCommandMenuContext.test.tsx b/packages/twenty-front/src/modules/command-menu/hooks/__tests__/useSetGlobalCommandMenuContext.test.tsx
index 7ef95acdd1..2fab803af6 100644
--- a/packages/twenty-front/src/modules/command-menu/hooks/__tests__/useSetGlobalCommandMenuContext.test.tsx
+++ b/packages/twenty-front/src/modules/command-menu/hooks/__tests__/useSetGlobalCommandMenuContext.test.tsx
@@ -15,7 +15,7 @@ import { contextStoreTargetedRecordsRuleComponentState } from '@/context-store/s
import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType';
import { recordStoreFamilyState } from '@/object-record/record-store/states/recordStoreFamilyState';
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
-import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper';
+import { getJestMetadataAndApolloMocksAndCommandMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper';
import { mockedPersonRecords } from '~/testing/mock-data/generated/data/people/mock-people-data';
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
import { contextStoreFilterGroupsComponentState } from '@/context-store/states/contextStoreFilterGroupsComponentState';
@@ -35,7 +35,7 @@ jotaiStore.set(
peopleMock[1],
);
-const wrapper = getJestMetadataAndApolloMocksAndActionMenuWrapper({
+const wrapper = getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: SIDE_PANEL_COMPONENT_INSTANCE_ID,
contextStoreCurrentObjectMetadataNameSingular:
diff --git a/packages/twenty-front/src/modules/command-menu/hooks/__tests__/useWorkflowCommandMenu.test.tsx b/packages/twenty-front/src/modules/command-menu/hooks/__tests__/useWorkflowCommandMenu.test.tsx
index 84674f6cc4..fb7ac618d0 100644
--- a/packages/twenty-front/src/modules/command-menu/hooks/__tests__/useWorkflowCommandMenu.test.tsx
+++ b/packages/twenty-front/src/modules/command-menu/hooks/__tests__/useWorkflowCommandMenu.test.tsx
@@ -15,7 +15,7 @@ import { t } from '@lingui/core/macro';
import { act } from 'react';
import { SidePanelPages } from 'twenty-shared/types';
import { IconBolt, IconSettingsAutomation, useIcons } from 'twenty-ui/display';
-import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper';
+import { getJestMetadataAndApolloMocksAndCommandMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper';
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
jest.mock('uuid', () => ({
@@ -39,7 +39,7 @@ jest.mock('@/object-metadata/hooks/useObjectMetadataItem', () => ({
})),
}));
-const wrapper = getJestMetadataAndApolloMocksAndActionMenuWrapper({
+const wrapper = getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: SIDE_PANEL_COMPONENT_INSTANCE_ID,
contextStoreCurrentObjectMetadataNameSingular:
diff --git a/packages/twenty-front/src/modules/command-menu/hooks/useCopyContextStoreAndActionMenuStates.ts b/packages/twenty-front/src/modules/command-menu/hooks/useCopyContextStoreAndCommandMenuStates.ts
similarity index 100%
rename from packages/twenty-front/src/modules/command-menu/hooks/useCopyContextStoreAndActionMenuStates.ts
rename to packages/twenty-front/src/modules/command-menu/hooks/useCopyContextStoreAndCommandMenuStates.ts
diff --git a/packages/twenty-front/src/modules/action-menu/states/contexts/ActionMenuComponentInstanceContext.ts b/packages/twenty-front/src/modules/command-menu/states/contexts/CommandMenuComponentInstanceContext.ts
similarity index 75%
rename from packages/twenty-front/src/modules/action-menu/states/contexts/ActionMenuComponentInstanceContext.ts
rename to packages/twenty-front/src/modules/command-menu/states/contexts/CommandMenuComponentInstanceContext.ts
index 1e64690c74..a5bf9d53f4 100644
--- a/packages/twenty-front/src/modules/action-menu/states/contexts/ActionMenuComponentInstanceContext.ts
+++ b/packages/twenty-front/src/modules/command-menu/states/contexts/CommandMenuComponentInstanceContext.ts
@@ -1,4 +1,4 @@
import { createComponentInstanceContext } from '@/ui/utilities/state/component-state/utils/createComponentInstanceContext';
-export const ActionMenuComponentInstanceContext =
+export const CommandMenuComponentInstanceContext =
createComponentInstanceContext();
diff --git a/packages/twenty-front/src/modules/front-components/hooks/useFrontComponentExecutionContext.ts b/packages/twenty-front/src/modules/front-components/hooks/useFrontComponentExecutionContext.ts
index 6b5e0b5de7..346cb6b26c 100644
--- a/packages/twenty-front/src/modules/front-components/hooks/useFrontComponentExecutionContext.ts
+++ b/packages/twenty-front/src/modules/front-components/hooks/useFrontComponentExecutionContext.ts
@@ -5,7 +5,7 @@ import {
} from 'twenty-sdk/front-component-renderer';
import { type AppPath, type EnqueueSnackbarParams } from 'twenty-shared/types';
-import { useActionMenuConfirmationModal } from '@/action-menu/confirmation-modal/hooks/useActionMenuConfirmationModal';
+import { useCommandMenuConfirmationModal } from '@/command-menu-item/confirmation-modal/hooks/useCommandMenuConfirmationModal';
import { currentUserState } from '@/auth/states/currentUserState';
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
import { useNavigateSidePanel } from '@/side-panel/hooks/useNavigateSidePanel';
@@ -32,7 +32,7 @@ export const useFrontComponentExecutionContext = ({
const { requestAccessTokenRefresh } = useRequestApplicationTokenRefresh({
frontComponentId,
});
- const { openConfirmationModal } = useActionMenuConfirmationModal();
+ const { openConfirmationModal } = useCommandMenuConfirmationModal();
const { navigateSidePanel } = useNavigateSidePanel();
const setSidePanelSearch = useSetAtomState(sidePanelSearchState);
const { getIcon } = useIcons();
@@ -72,7 +72,7 @@ export const useFrontComponentExecutionContext = ({
}
};
- const openActionConfirmationModal: FrontComponentHostCommunicationApi['openActionConfirmationModal'] =
+ const openCommandConfirmationModal: FrontComponentHostCommunicationApi['openCommandConfirmationModal'] =
async ({ title, subtitle, confirmButtonText, confirmButtonAccent }) => {
openConfirmationModal({
frontComponentId,
@@ -138,7 +138,7 @@ export const useFrontComponentExecutionContext = ({
navigate,
requestAccessTokenRefresh,
openSidePanelPage,
- openActionConfirmationModal,
+ openCommandConfirmationModal,
enqueueSnackbar,
unmountFrontComponent,
closeSidePanel,
diff --git a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useColumnDefinitionsFromObjectMetadata.test.ts b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useColumnDefinitionsFromObjectMetadata.test.ts
index cbb717d617..95fa2f7273 100644
--- a/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useColumnDefinitionsFromObjectMetadata.test.ts
+++ b/packages/twenty-front/src/modules/object-metadata/hooks/__tests__/useColumnDefinitionsFromObjectMetadata.test.ts
@@ -12,10 +12,10 @@ import {
SubscriptionStatus,
WorkspaceActivationStatus,
} from '~/generated-metadata/graphql';
-import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper';
+import { getJestMetadataAndApolloMocksAndCommandMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper';
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
-const Wrapper = getJestMetadataAndApolloMocksAndActionMenuWrapper({
+const Wrapper = getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: 'instanceId',
contextStoreCurrentObjectMetadataNameSingular: 'company',
diff --git a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterAddFilterRuleSelect.tsx b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterAddFilterRuleSelect.tsx
index c854e2caa2..9386aff959 100644
--- a/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterAddFilterRuleSelect.tsx
+++ b/packages/twenty-front/src/modules/object-record/advanced-filter/components/AdvancedFilterAddFilterRuleSelect.tsx
@@ -1,4 +1,4 @@
-import { ActionButton } from '@/action-menu/actions/display/components/ActionButton';
+import { CommandMenuButton } from '@/command-menu/components/CommandMenuButton';
import { useChildRecordFiltersAndRecordFilterGroups } from '@/object-record/advanced-filter/hooks/useChildRecordFiltersAndRecordFilterGroups';
import { useGetDefaultFieldMetadataItemForFilter } from '@/object-record/advanced-filter/hooks/useGetDefaultFieldMetadataItemForFilter';
import { useSetRecordFilterUsedInAdvancedFilterDropdownRow } from '@/object-record/advanced-filter/hooks/useSetRecordFilterUsedInAdvancedFilterDropdownRow';
@@ -147,8 +147,8 @@ export const AdvancedFilterAddFilterRuleSelect = ({
if (!isFilterRuleGroupOptionVisible) {
return (
- {
useListenClickOutside({
excludedClickOutsideIds: [
- ACTION_MENU_DROPDOWN_CLICK_OUTSIDE_ID,
+ COMMAND_MENU_DROPDOWN_CLICK_OUTSIDE_ID,
COMMAND_MENU_CLICK_OUTSIDE_ID,
MODAL_BACKDROP_CLICK_OUTSIDE_ID,
PAGE_ACTION_CONTAINER_CLICK_OUTSIDE_ID,
diff --git a/packages/twenty-front/src/modules/object-record/record-board/hooks/useRecordBoardSelection.ts b/packages/twenty-front/src/modules/object-record/record-board/hooks/useRecordBoardSelection.ts
index d5d82eeb8a..a33f3c1434 100644
--- a/packages/twenty-front/src/modules/object-record/record-board/hooks/useRecordBoardSelection.ts
+++ b/packages/twenty-front/src/modules/object-record/record-board/hooks/useRecordBoardSelection.ts
@@ -1,5 +1,5 @@
-import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
-import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
+import { getCommandMenuDropdownIdFromCommandMenuId } from '@/command-menu-item/utils/getCommandMenuDropdownIdFromCommandMenuId';
+import { getCommandMenuIdFromRecordIndexId } from '@/command-menu-item/utils/getCommandMenuIdFromRecordIndexId';
import { RecordBoardComponentInstanceContext } from '@/object-record/record-board/states/contexts/RecordBoardComponentInstanceContext';
import { isRecordBoardCardSelectedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardSelectedComponentFamilyState';
import { recordBoardSelectedRecordIdsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardSelectedRecordIdsComponentSelector';
@@ -30,8 +30,8 @@ export const useRecordBoardSelection = (recordBoardId?: string) => {
const { closeDropdown } = useCloseDropdown();
const store = useStore();
- const dropdownId = getActionMenuDropdownIdFromActionMenuId(
- getActionMenuIdFromRecordIndexId(instanceIdFromProps),
+ const dropdownId = getCommandMenuDropdownIdFromCommandMenuId(
+ getCommandMenuIdFromRecordIndexId(instanceIdFromProps),
);
const setRecordAsSelected = useCallback(
diff --git a/packages/twenty-front/src/modules/object-record/record-board/hooks/useResetRecordBoardSelection.ts b/packages/twenty-front/src/modules/object-record/record-board/hooks/useResetRecordBoardSelection.ts
index d280bc0ae4..1e80753227 100644
--- a/packages/twenty-front/src/modules/object-record/record-board/hooks/useResetRecordBoardSelection.ts
+++ b/packages/twenty-front/src/modules/object-record/record-board/hooks/useResetRecordBoardSelection.ts
@@ -1,5 +1,5 @@
-import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
-import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
+import { getCommandMenuDropdownIdFromCommandMenuId } from '@/command-menu-item/utils/getCommandMenuDropdownIdFromCommandMenuId';
+import { getCommandMenuIdFromRecordIndexId } from '@/command-menu-item/utils/getCommandMenuIdFromRecordIndexId';
import { RecordBoardComponentInstanceContext } from '@/object-record/record-board/states/contexts/RecordBoardComponentInstanceContext';
import { isRecordBoardCardSelectedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardSelectedComponentFamilyState';
import { recordBoardSelectedRecordIdsComponentSelector } from '@/object-record/record-board/states/selectors/recordBoardSelectedRecordIdsComponentSelector';
@@ -30,8 +30,8 @@ export const useResetRecordBoardSelection = (recordBoardId?: string) => {
const { closeDropdown } = useCloseDropdown();
const store = useStore();
- const dropdownId = getActionMenuDropdownIdFromActionMenuId(
- getActionMenuIdFromRecordIndexId(instanceIdFromProps),
+ const dropdownId = getCommandMenuDropdownIdFromCommandMenuId(
+ getCommandMenuIdFromRecordIndexId(instanceIdFromProps),
);
const resetRecordBoardSelection = useCallback(() => {
diff --git a/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx b/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx
index 95541ea088..beb5153035 100644
--- a/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-board/record-board-card/components/RecordBoardCard.tsx
@@ -1,6 +1,6 @@
-import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-menu/states/recordIndexActionMenuDropdownPositionComponentState';
-import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
-import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
+import { recordIndexCommandMenuDropdownPositionComponentState } from '@/command-menu-item/states/recordIndexCommandMenuDropdownPositionComponentState';
+import { getCommandMenuDropdownIdFromCommandMenuId } from '@/command-menu-item/utils/getCommandMenuDropdownIdFromCommandMenuId';
+import { getCommandMenuIdFromRecordIndexId } from '@/command-menu-item/utils/getCommandMenuIdFromRecordIndexId';
import { RecordBoardCardContext } from '@/object-record/record-board/record-board-card/contexts/RecordBoardCardContext';
import { isRecordBoardCardActiveComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardActiveComponentFamilyState';
import { isRecordBoardCardFocusedComponentFamilyState } from '@/object-record/record-board/states/isRecordBoardCardFocusedComponentFamilyState';
@@ -99,14 +99,14 @@ export const RecordBoardCard = () => {
},
);
- const actionMenuId = getActionMenuIdFromRecordIndexId(recordBoardId);
+ const commandMenuId = getCommandMenuIdFromRecordIndexId(recordBoardId);
- const actionMenuDropdownId =
- getActionMenuDropdownIdFromActionMenuId(actionMenuId);
+ const commandMenuDropdownId =
+ getCommandMenuDropdownIdFromCommandMenuId(commandMenuId);
- const setRecordIndexActionMenuDropdownPosition = useSetAtomComponentState(
- recordIndexActionMenuDropdownPositionComponentState,
- actionMenuDropdownId,
+ const setRecordIndexCommandMenuDropdownPosition = useSetAtomComponentState(
+ recordIndexCommandMenuDropdownPositionComponentState,
+ commandMenuDropdownId,
);
const { openDropdown } = useOpenDropdown();
@@ -118,12 +118,12 @@ export const RecordBoardCard = () => {
const handleContextMenuOpen = (event: React.MouseEvent) => {
event.preventDefault();
setIsRecordBoardCardSelected(true);
- setRecordIndexActionMenuDropdownPosition({
+ setRecordIndexCommandMenuDropdownPosition({
x: event.clientX,
y: event.clientY,
});
openDropdown({
- dropdownComponentInstanceIdFromProps: actionMenuDropdownId,
+ dropdownComponentInstanceIdFromProps: commandMenuDropdownId,
globalHotkeysConfig: {
enableGlobalHotkeysWithModifiers: true,
enableGlobalHotkeysConflictingWithKeyboard: false,
diff --git a/packages/twenty-front/src/modules/object-record/record-calendar/components/RecordCalendar.tsx b/packages/twenty-front/src/modules/object-record/record-calendar/components/RecordCalendar.tsx
index 7982ab4b43..2857f59fcd 100644
--- a/packages/twenty-front/src/modules/object-record/record-calendar/components/RecordCalendar.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-calendar/components/RecordCalendar.tsx
@@ -1,6 +1,6 @@
import { styled } from '@linaria/react';
-import { ACTION_MENU_DROPDOWN_CLICK_OUTSIDE_ID } from '@/action-menu/constants/ActionMenuDropdownClickOutsideId';
+import { COMMAND_MENU_DROPDOWN_CLICK_OUTSIDE_ID } from '@/command-menu-item/constants/CommandMenuDropdownClickOutsideId';
import { COMMAND_MENU_CLICK_OUTSIDE_ID } from '@/command-menu/constants/CommandMenuClickOutsideId';
import { RecordCalendarTopBar } from '@/object-record/record-calendar/components/RecordCalendarTopBar';
import { RECORD_CALENDAR_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-calendar/constants/RecordCalendarClickOutsideListenerId';
@@ -35,7 +35,7 @@ export const RecordCalendar = () => {
useListenClickOutside({
excludedClickOutsideIds: [
- ACTION_MENU_DROPDOWN_CLICK_OUTSIDE_ID,
+ COMMAND_MENU_DROPDOWN_CLICK_OUTSIDE_ID,
COMMAND_MENU_CLICK_OUTSIDE_ID,
MODAL_BACKDROP_CLICK_OUTSIDE_ID,
PAGE_ACTION_CONTAINER_CLICK_OUTSIDE_ID,
diff --git a/packages/twenty-front/src/modules/object-record/record-calendar/record-calendar-card/components/RecordCalendarCard.tsx b/packages/twenty-front/src/modules/object-record/record-calendar/record-calendar-card/components/RecordCalendarCard.tsx
index 6a1eccd558..2685945cfd 100644
--- a/packages/twenty-front/src/modules/object-record/record-calendar/record-calendar-card/components/RecordCalendarCard.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-calendar/record-calendar-card/components/RecordCalendarCard.tsx
@@ -1,6 +1,6 @@
-import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-menu/states/recordIndexActionMenuDropdownPositionComponentState';
-import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
-import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
+import { recordIndexCommandMenuDropdownPositionComponentState } from '@/command-menu-item/states/recordIndexCommandMenuDropdownPositionComponentState';
+import { getCommandMenuDropdownIdFromCommandMenuId } from '@/command-menu-item/utils/getCommandMenuDropdownIdFromCommandMenuId';
+import { getCommandMenuIdFromRecordIndexId } from '@/command-menu-item/utils/getCommandMenuIdFromRecordIndexId';
import { RecordCalendarCardCellEditModePortal } from '@/object-record/record-calendar/record-calendar-card/anchored-portal/components/RecordCalendarCardCellEditModePortal';
import { RecordCalendarCardCellHoveredPortal } from '@/object-record/record-calendar/record-calendar-card/anchored-portal/components/RecordCalendarCardCellHoveredPortal';
import { RecordCalendarCardBody } from '@/object-record/record-calendar/record-calendar-card/components/RecordCalendarCardBody';
@@ -46,14 +46,14 @@ export const RecordCalendarCard = ({ recordId }: RecordCalendarCardProps) => {
RecordCalendarComponentInstanceContext,
);
- const actionMenuId = getActionMenuIdFromRecordIndexId(recordCalendarId);
+ const commandMenuId = getCommandMenuIdFromRecordIndexId(recordCalendarId);
- const actionMenuDropdownId =
- getActionMenuDropdownIdFromActionMenuId(actionMenuId);
+ const commandMenuDropdownId =
+ getCommandMenuDropdownIdFromCommandMenuId(commandMenuId);
- const setRecordIndexActionMenuDropdownPosition = useSetAtomComponentState(
- recordIndexActionMenuDropdownPositionComponentState,
- actionMenuDropdownId,
+ const setRecordIndexCommandMenuDropdownPosition = useSetAtomComponentState(
+ recordIndexCommandMenuDropdownPositionComponentState,
+ commandMenuDropdownId,
);
const { openDropdown } = useOpenDropdown();
@@ -61,12 +61,12 @@ export const RecordCalendarCard = ({ recordId }: RecordCalendarCardProps) => {
const handleContextMenuOpen = (event: React.MouseEvent) => {
event.preventDefault();
setIsRecordCalendarCardSelected(true);
- setRecordIndexActionMenuDropdownPosition({
+ setRecordIndexCommandMenuDropdownPosition({
x: event.clientX,
y: event.clientY,
});
openDropdown({
- dropdownComponentInstanceIdFromProps: actionMenuDropdownId,
+ dropdownComponentInstanceIdFromProps: commandMenuDropdownId,
globalHotkeysConfig: {
enableGlobalHotkeysWithModifiers: true,
enableGlobalHotkeysConflictingWithKeyboard: false,
diff --git a/packages/twenty-front/src/modules/object-record/record-calendar/states/selectors/useRecordCalendarSelection.ts b/packages/twenty-front/src/modules/object-record/record-calendar/states/selectors/useRecordCalendarSelection.ts
index 94692e359c..979635bd72 100644
--- a/packages/twenty-front/src/modules/object-record/record-calendar/states/selectors/useRecordCalendarSelection.ts
+++ b/packages/twenty-front/src/modules/object-record/record-calendar/states/selectors/useRecordCalendarSelection.ts
@@ -1,7 +1,7 @@
import { useCallback } from 'react';
-import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
-import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
+import { getCommandMenuDropdownIdFromCommandMenuId } from '@/command-menu-item/utils/getCommandMenuDropdownIdFromCommandMenuId';
+import { getCommandMenuIdFromRecordIndexId } from '@/command-menu-item/utils/getCommandMenuIdFromRecordIndexId';
import { useCloseDropdown } from '@/ui/layout/dropdown/hooks/useCloseDropdown';
import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/component-state/hooks/useAvailableComponentInstanceIdOrThrow';
import { useAtomComponentFamilyStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateCallbackState';
@@ -31,8 +31,8 @@ export const useRecordCalendarSelection = (recordCalendarId?: string) => {
const { closeDropdown } = useCloseDropdown();
const store = useStore();
- const dropdownId = getActionMenuDropdownIdFromActionMenuId(
- getActionMenuIdFromRecordIndexId(instanceIdFromProps),
+ const dropdownId = getCommandMenuDropdownIdFromCommandMenuId(
+ getCommandMenuIdFromRecordIndexId(instanceIdFromProps),
);
const resetRecordSelection = useCallback(() => {
diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx
index 4eafa3f74c..05876aab0b 100644
--- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexContainerGater.tsx
@@ -1,7 +1,7 @@
import { RecordIndexContextProvider } from '@/object-record/record-index/contexts/RecordIndexContext';
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
-import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
+import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
+import { getCommandMenuIdFromRecordIndexId } from '@/command-menu-item/utils/getCommandMenuIdFromRecordIndexId';
import { getObjectPermissionsForObject } from '@/object-metadata/utils/getObjectPermissionsForObject';
import { MainContainerLayoutWithSidePanel } from '@/object-record/components/MainContainerLayoutWithSidePanel';
import { RecordComponentInstanceContextsWrapper } from '@/object-record/components/RecordComponentInstanceContextsWrapper';
@@ -88,9 +88,9 @@ export const RecordIndexContainerGater = () => {
-
@@ -103,7 +103,7 @@ export const RecordIndexContainerGater = () => {
-
+
diff --git a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexPageHeader.tsx b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexPageHeader.tsx
index 0778086a91..0e7d919c8b 100644
--- a/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexPageHeader.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-index/components/RecordIndexPageHeader.tsx
@@ -1,4 +1,4 @@
-import { RecordIndexActionMenu } from '@/action-menu/components/RecordIndexActionMenu';
+import { RecordIndexCommandMenu } from '@/command-menu-item/components/RecordIndexCommandMenu';
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { contextStoreNumberOfSelectedRecordsComponentState } from '@/context-store/states/contextStoreNumberOfSelectedRecordsComponentState';
@@ -71,7 +71,7 @@ export const RecordIndexPageHeader = () => {
>
{isDefined(contextStoreCurrentViewId) && (
<>
-
+
>
)}
diff --git a/packages/twenty-front/src/modules/object-record/record-index/export/hooks/__tests__/useRecordIndexLazyFetchRecords.test.ts b/packages/twenty-front/src/modules/object-record/record-index/export/hooks/__tests__/useRecordIndexLazyFetchRecords.test.ts
index 8f9c4609f7..436b0bca91 100644
--- a/packages/twenty-front/src/modules/object-record/record-index/export/hooks/__tests__/useRecordIndexLazyFetchRecords.test.ts
+++ b/packages/twenty-front/src/modules/object-record/record-index/export/hooks/__tests__/useRecordIndexLazyFetchRecords.test.ts
@@ -8,7 +8,7 @@ import {
import { useLazyFetchAllRecords } from '@/object-record/hooks/useLazyFetchAllRecords';
import { ViewType } from '@/views/types/ViewType';
-import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper';
+import { getJestMetadataAndApolloMocksAndCommandMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper';
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
const mockPerson = {
@@ -61,7 +61,7 @@ const mockPerson = {
},
};
-const Wrapper = getJestMetadataAndApolloMocksAndActionMenuWrapper({
+const Wrapper = getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: 'recordIndexId',
contextStoreTargetedRecordsRule: {
diff --git a/packages/twenty-front/src/modules/object-record/record-index/hooks/__tests__/useRecordIndexIdFromCurrentContextStore.test.tsx b/packages/twenty-front/src/modules/object-record/record-index/hooks/__tests__/useRecordIndexIdFromCurrentContextStore.test.tsx
index 276cc736ad..acf53bb2a3 100644
--- a/packages/twenty-front/src/modules/object-record/record-index/hooks/__tests__/useRecordIndexIdFromCurrentContextStore.test.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-index/hooks/__tests__/useRecordIndexIdFromCurrentContextStore.test.tsx
@@ -1,14 +1,14 @@
import { useRecordIndexIdFromCurrentContextStore } from '@/object-record/record-index/hooks/useRecordIndexIdFromCurrentContextStore';
import { renderHook } from '@testing-library/react';
import { JestObjectMetadataItemSetter } from '~/testing/jest/JestObjectMetadataItemSetter';
-import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper';
+import { getJestMetadataAndApolloMocksAndCommandMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper';
const testComponentInstanceId = 'test';
const testCurrentViewId = 'view-id';
const testObjectMetadataItemNameSingular = 'person';
const testObjectMetadataItemNamePlural = 'people';
-const Wrapper = getJestMetadataAndApolloMocksAndActionMenuWrapper({
+const Wrapper = getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: testComponentInstanceId,
contextStoreCurrentObjectMetadataNameSingular:
diff --git a/packages/twenty-front/src/modules/object-record/record-show/components/PageLayoutRecordPageRenderer.tsx b/packages/twenty-front/src/modules/object-record/record-show/components/PageLayoutRecordPageRenderer.tsx
index 8558e453b5..feba2185d5 100644
--- a/packages/twenty-front/src/modules/object-record/record-show/components/PageLayoutRecordPageRenderer.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-show/components/PageLayoutRecordPageRenderer.tsx
@@ -1,5 +1,5 @@
-import { RecordShowSidePanelActionMenu } from '@/action-menu/components/RecordShowSidePanelActionMenu';
-import { RecordShowSidePanelOpenRecordButton } from '@/action-menu/components/RecordShowSidePanelOpenRecordButton';
+import { RecordPageSidePanelCommandMenu } from '@/command-menu-item/components/RecordPageSidePanelCommandMenu';
+import { RecordShowSidePanelOpenRecordButton } from '@/command-menu-item/components/RecordShowSidePanelOpenRecordButton';
import { InformationBannerDeletedRecord } from '@/information-banner/components/deleted-record/InformationBannerDeletedRecord';
import { CoreObjectNameSingular } from 'twenty-shared/types';
import { RecordShowContainerContextStoreTargetedRecordsEffect } from '@/object-record/record-show/components/RecordShowContainerContextStoreTargetedRecordsEffect';
@@ -103,7 +103,7 @@ export const PageLayoutRecordPageRenderer = ({
{isInSidePanel && (
,
+ ,
{
- triggerActionMenuDropdown(event, recordId);
+ triggerCommandMenuDropdown(event, recordId);
};
const hasUserSelectedAllRows = useAtomComponentStateValue(
@@ -70,7 +70,7 @@ export const RecordTableNoRecordGroupBodyContextProvider = ({
onMoveFocus: handleMoveFocus,
onCloseTableCell: handleCloseTableCell,
onMoveHoverToCurrentCell: handleMoveHoverToCurrentCell,
- onActionMenuDropdownOpened: handleActionMenuDropdown,
+ onCommandMenuDropdownOpened: handleCommandMenuDropdown,
hasUserSelectedAllRows,
}}
>
diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRecordGroupBodyContextProvider.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRecordGroupBodyContextProvider.tsx
index 83c0c8587e..57ceb05163 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRecordGroupBodyContextProvider.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/components/RecordTableRecordGroupBodyContextProvider.tsx
@@ -7,7 +7,7 @@ import {
type OpenTableCellArgs,
useOpenRecordTableCell,
} from '@/object-record/record-table/record-table-cell/hooks/useOpenRecordTableCell';
-import { useTriggerActionMenuDropdown } from '@/object-record/record-table/record-table-cell/hooks/useTriggerActionMenuDropdown';
+import { useTriggerCommandMenuDropdown } from '@/object-record/record-table/record-table-cell/hooks/useTriggerCommandMenuDropdown';
import { type MoveFocusDirection } from '@/object-record/record-table/types/MoveFocusDirection';
import { type TableCellPosition } from '@/object-record/record-table/types/TableCellPosition';
import { type ReactNode } from 'react';
@@ -46,15 +46,15 @@ export const RecordTableRecordGroupBodyContextProvider = ({
moveHoverToCurrentCell(cellPosition);
};
- const { triggerActionMenuDropdown } = useTriggerActionMenuDropdown({
+ const { triggerCommandMenuDropdown } = useTriggerCommandMenuDropdown({
recordTableId,
});
- const handleActionMenuDropdown = (
+ const handleCommandMenuDropdown = (
event: React.MouseEvent,
recordId: string,
) => {
- triggerActionMenuDropdown(event, recordId);
+ triggerCommandMenuDropdown(event, recordId);
};
return (
@@ -64,7 +64,7 @@ export const RecordTableRecordGroupBodyContextProvider = ({
onMoveFocus: handleMoveFocus,
onCloseTableCell: handlecloseTableCellInGroup,
onMoveHoverToCurrentCell: handleMoveHoverToCurrentCell,
- onActionMenuDropdownOpened: handleActionMenuDropdown,
+ onCommandMenuDropdownOpened: handleCommandMenuDropdown,
}}
>
{children}
diff --git a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx
index 10291fe071..c5c576e13c 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/components/__stories__/perf/RecordTableCell.perf.stories.tsx
@@ -181,7 +181,7 @@ const meta: Meta = {
onMoveFocus: () => {},
onCloseTableCell: () => {},
onMoveHoverToCurrentCell: () => {},
- onActionMenuDropdownOpened: () => {},
+ onCommandMenuDropdownOpened: () => {},
}}
>
void;
onCloseTableCell: () => void;
onMoveHoverToCurrentCell: (cellPosition: TableCellPosition) => void;
- onActionMenuDropdownOpened: (
+ onCommandMenuDropdownOpened: (
event: React.MouseEvent,
recordId: string,
) => void;
diff --git a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useResetTableRowSelection.ts b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useResetTableRowSelection.ts
index 94b45fd82f..fc76c0b15d 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useResetTableRowSelection.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/hooks/internal/useResetTableRowSelection.ts
@@ -1,8 +1,8 @@
import { useCallback } from 'react';
import { useStore } from 'jotai';
-import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
-import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
+import { getCommandMenuDropdownIdFromCommandMenuId } from '@/command-menu-item/utils/getCommandMenuDropdownIdFromCommandMenuId';
+import { getCommandMenuIdFromRecordIndexId } from '@/command-menu-item/utils/getCommandMenuIdFromRecordIndexId';
import { recordIndexAllRecordIdsComponentSelector } from '@/object-record/record-index/states/selectors/recordIndexAllRecordIdsComponentSelector';
import { hasUserSelectedAllRowsComponentState } from '@/object-record/record-table/record-table-row/states/hasUserSelectedAllRowsFamilyState';
import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState';
@@ -55,8 +55,8 @@ export const useResetTableRowSelection = (recordTableId?: string) => {
store.set(lastSelectedRowIndexComponentCallbackState, null);
closeDropdown(
- getActionMenuDropdownIdFromActionMenuId(
- getActionMenuIdFromRecordIndexId(recordTableIdFromContext),
+ getCommandMenuDropdownIdFromCommandMenuId(
+ getCommandMenuIdFromRecordIndexId(recordTableIdFromContext),
),
);
}, [
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyFocusClickOutsideEffect.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyFocusClickOutsideEffect.tsx
index 2f6412acdb..bd4e0c964f 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyFocusClickOutsideEffect.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-body/components/RecordTableBodyFocusClickOutsideEffect.tsx
@@ -1,4 +1,4 @@
-import { ACTION_MENU_DROPDOWN_CLICK_OUTSIDE_ID } from '@/action-menu/constants/ActionMenuDropdownClickOutsideId';
+import { COMMAND_MENU_DROPDOWN_CLICK_OUTSIDE_ID } from '@/command-menu-item/constants/CommandMenuDropdownClickOutsideId';
import { COMMAND_MENU_CLICK_OUTSIDE_ID } from '@/command-menu/constants/CommandMenuClickOutsideId';
import { RECORD_TABLE_CLICK_OUTSIDE_LISTENER_ID } from '@/object-record/record-table/constants/RecordTableClickOutsideListenerId';
import { useRecordTableContextOrThrow } from '@/object-record/record-table/contexts/RecordTableContext';
@@ -26,7 +26,7 @@ export const RecordTableBodyFocusClickOutsideEffect = ({
useListenClickOutside({
excludedClickOutsideIds: [
- ACTION_MENU_DROPDOWN_CLICK_OUTSIDE_ID,
+ COMMAND_MENU_DROPDOWN_CLICK_OUTSIDE_ID,
COMMAND_MENU_CLICK_OUTSIDE_ID,
PAGE_ACTION_CONTAINER_CLICK_OUTSIDE_ID,
MODAL_BACKDROP_CLICK_OUTSIDE_ID,
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayMode.tsx b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayMode.tsx
index a4876f78bf..8a15b1e369 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayMode.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/components/RecordTableCellDisplayMode.tsx
@@ -13,14 +13,14 @@ export const RecordTableCellDisplayMode = ({
const { recordId, isRecordFieldReadOnly: isReadOnly } =
useContext(FieldContext);
- const { onActionMenuDropdownOpened } = useRecordTableBodyContextOrThrow();
+ const { onCommandMenuDropdownOpened } = useRecordTableBodyContextOrThrow();
const { openTableCell } = useOpenRecordTableCellFromCell();
const isFieldInputOnly = useIsFieldInputOnly();
- const handleActionMenuDropdown = (event: React.MouseEvent) => {
- onActionMenuDropdownOpened(event, recordId);
+ const handleCommandMenuDropdown = (event: React.MouseEvent) => {
+ onCommandMenuDropdownOpened(event, recordId);
};
const handleClick = (event: React.MouseEvent) => {
@@ -32,7 +32,7 @@ export const RecordTableCellDisplayMode = ({
return (
{children}
diff --git a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useTriggerActionMenuDropdown.ts b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useTriggerCommandMenuDropdown.ts
similarity index 59%
rename from packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useTriggerActionMenuDropdown.ts
rename to packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useTriggerCommandMenuDropdown.ts
index c7c8ffcc97..ab2e7117d9 100644
--- a/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useTriggerActionMenuDropdown.ts
+++ b/packages/twenty-front/src/modules/object-record/record-table/record-table-cell/hooks/useTriggerCommandMenuDropdown.ts
@@ -1,9 +1,9 @@
import { useCallback } from 'react';
import { useStore } from 'jotai';
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
-import { recordIndexActionMenuDropdownPositionComponentState } from '@/action-menu/states/recordIndexActionMenuDropdownPositionComponentState';
-import { getActionMenuDropdownIdFromActionMenuId } from '@/action-menu/utils/getActionMenuDropdownIdFromActionMenuId';
+import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
+import { recordIndexCommandMenuDropdownPositionComponentState } from '@/command-menu-item/states/recordIndexCommandMenuDropdownPositionComponentState';
+import { getCommandMenuDropdownIdFromCommandMenuId } from '@/command-menu-item/utils/getCommandMenuDropdownIdFromCommandMenuId';
import { useSidePanelMenu } from '@/side-panel/hooks/useSidePanelMenu';
import { isRowSelectedComponentFamilyState } from '@/object-record/record-table/record-table-row/states/isRowSelectedComponentFamilyState';
import { useOpenDropdown } from '@/ui/layout/dropdown/hooks/useOpenDropdown';
@@ -11,13 +11,13 @@ import { useAvailableComponentInstanceIdOrThrow } from '@/ui/utilities/state/com
import { useAtomComponentStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateCallbackState';
import { useAtomComponentFamilyStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentFamilyStateCallbackState';
-export const useTriggerActionMenuDropdown = ({
+export const useTriggerCommandMenuDropdown = ({
recordTableId,
}: {
recordTableId: string;
}) => {
- const actionMenuInstanceId = useAvailableComponentInstanceIdOrThrow(
- ActionMenuComponentInstanceContext,
+ const commandMenuInstanceId = useAvailableComponentInstanceIdOrThrow(
+ CommandMenuComponentInstanceContext,
);
const isRowSelectedFamilyState = useAtomComponentFamilyStateCallbackState(
@@ -25,24 +25,25 @@ export const useTriggerActionMenuDropdown = ({
recordTableId,
);
- const actionMenuDropdownId =
- getActionMenuDropdownIdFromActionMenuId(actionMenuInstanceId);
+ const commandMenuDropdownId = getCommandMenuDropdownIdFromCommandMenuId(
+ commandMenuInstanceId,
+ );
- const recordIndexActionMenuDropdownPositionCallbackState =
+ const recordIndexCommandMenuDropdownPositionCallbackState =
useAtomComponentStateCallbackState(
- recordIndexActionMenuDropdownPositionComponentState,
- actionMenuDropdownId,
+ recordIndexCommandMenuDropdownPositionComponentState,
+ commandMenuDropdownId,
);
const { openDropdown } = useOpenDropdown();
const { closeSidePanelMenu } = useSidePanelMenu();
const store = useStore();
- const triggerActionMenuDropdown = useCallback(
+ const triggerCommandMenuDropdown = useCallback(
(event: React.MouseEvent, recordId: string) => {
event.preventDefault();
- store.set(recordIndexActionMenuDropdownPositionCallbackState, {
+ store.set(recordIndexCommandMenuDropdownPositionCallbackState, {
x: event.pageX,
y: event.pageY,
});
@@ -56,18 +57,18 @@ export const useTriggerActionMenuDropdown = ({
closeSidePanelMenu();
openDropdown({
- dropdownComponentInstanceIdFromProps: actionMenuDropdownId,
+ dropdownComponentInstanceIdFromProps: commandMenuDropdownId,
});
},
[
- recordIndexActionMenuDropdownPositionCallbackState,
+ recordIndexCommandMenuDropdownPositionCallbackState,
isRowSelectedFamilyState,
closeSidePanelMenu,
openDropdown,
- actionMenuDropdownId,
+ commandMenuDropdownId,
store,
],
);
- return { triggerActionMenuDropdown };
+ return { triggerCommandMenuDropdown };
};
diff --git a/packages/twenty-front/src/modules/object-record/record-update-multiple/components/UpdateMultipleRecordsFooter.tsx b/packages/twenty-front/src/modules/object-record/record-update-multiple/components/UpdateMultipleRecordsFooter.tsx
index 457272e9a9..0bcc5a99f8 100644
--- a/packages/twenty-front/src/modules/object-record/record-update-multiple/components/UpdateMultipleRecordsFooter.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-update-multiple/components/UpdateMultipleRecordsFooter.tsx
@@ -1,4 +1,4 @@
-import { computeProgressText } from '@/action-menu/utils/computeProgressText';
+import { computeProgressText } from '@/command-menu-item/utils/computeProgressText';
import { SIDE_PANEL_FOCUS_ID } from '@/side-panel/constants/SidePanelFocusId';
import { type ObjectRecordQueryProgress } from '@/object-record/types/ObjectRecordQueryProgress';
import { useHotkeysOnFocusedElement } from '@/ui/utilities/hotkey/hooks/useHotkeysOnFocusedElement';
diff --git a/packages/twenty-front/src/modules/object-record/record-update-multiple/components/__stories__/UpdateMultipleRecordsContainer.stories.tsx b/packages/twenty-front/src/modules/object-record/record-update-multiple/components/__stories__/UpdateMultipleRecordsContainer.stories.tsx
index 3ccb716ca5..482966ccf7 100644
--- a/packages/twenty-front/src/modules/object-record/record-update-multiple/components/__stories__/UpdateMultipleRecordsContainer.stories.tsx
+++ b/packages/twenty-front/src/modules/object-record/record-update-multiple/components/__stories__/UpdateMultipleRecordsContainer.stories.tsx
@@ -1,4 +1,4 @@
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
import { ApolloCoreClientContext } from '@/object-metadata/contexts/ApolloCoreClientContext';
import { UpdateMultipleRecordsContainer } from '@/object-record/record-update-multiple/components/UpdateMultipleRecordsContainer';
@@ -53,16 +53,16 @@ const meta: Meta = {
decorators: [
(Story) => (
-
-
+
),
ContextStoreDecorator,
diff --git a/packages/twenty-front/src/modules/settings/roles/role-permissions/object-level-permissions/record-level-permissions/components/SettingsRolePermissionsObjectLevelRecordLevelPermissionFilterBuilderContent.tsx b/packages/twenty-front/src/modules/settings/roles/role-permissions/object-level-permissions/record-level-permissions/components/SettingsRolePermissionsObjectLevelRecordLevelPermissionFilterBuilderContent.tsx
index 36aea9e687..d0a4fbe1cb 100644
--- a/packages/twenty-front/src/modules/settings/roles/role-permissions/object-level-permissions/record-level-permissions/components/SettingsRolePermissionsObjectLevelRecordLevelPermissionFilterBuilderContent.tsx
+++ b/packages/twenty-front/src/modules/settings/roles/role-permissions/object-level-permissions/record-level-permissions/components/SettingsRolePermissionsObjectLevelRecordLevelPermissionFilterBuilderContent.tsx
@@ -7,7 +7,7 @@ import { IconFilter, IconPlus } from 'twenty-ui/display';
import { Button } from 'twenty-ui/input';
import { themeCssVariables } from 'twenty-ui/theme-constants';
-import { ActionButton } from '@/action-menu/actions/display/components/ActionButton';
+import { CommandMenuButton } from '@/command-menu/components/CommandMenuButton';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useChildRecordFiltersAndRecordFilterGroups } from '@/object-record/advanced-filter/hooks/useChildRecordFiltersAndRecordFilterGroups';
import { useSetRecordFilterUsedInAdvancedFilterDropdownRow } from '@/object-record/advanced-filter/hooks/useSetRecordFilterUsedInAdvancedFilterDropdownRow';
@@ -137,8 +137,8 @@ export const SettingsRolePermissionsObjectLevelRecordLevelPermissionFilterBuilde
))}
- {
-
{children}
-
+
);
diff --git a/packages/twenty-front/src/modules/side-panel/components/SidePanelList.tsx b/packages/twenty-front/src/modules/side-panel/components/SidePanelList.tsx
index f5e367abce..c80a8c0ae3 100644
--- a/packages/twenty-front/src/modules/side-panel/components/SidePanelList.tsx
+++ b/packages/twenty-front/src/modules/side-panel/components/SidePanelList.tsx
@@ -1,4 +1,4 @@
-import { ActionComponent } from '@/action-menu/actions/display/components/ActionComponent';
+import { CommandMenuItemComponent } from '@/command-menu-item/display/components/CommandMenuItemComponent';
import { SidePanelGroup } from '@/side-panel/components/SidePanelGroup';
import { SidePanelDefaultSelectionEffect } from '@/side-panel/components/SidePanelDefaultSelectionEffect';
import { SIDE_PANEL_SELECTABLE_LIST_ID } from '@/side-panel/constants/SidePanelSelectableListId';
@@ -6,7 +6,7 @@ import { SIDE_PANEL_TOP_BAR_HEIGHT } from '@/side-panel/constants/SidePanelTopBa
import { SIDE_PANEL_LIST_PADDING } from '@/side-panel/constants/SidePanelListPadding';
import { SIDE_PANEL_FOCUS_ID } from '@/side-panel/constants/SidePanelFocusId';
import { hasUserSelectedSidePanelListItemState } from '@/side-panel/states/hasUserSelectedSidePanelListItemState';
-import { type SidePanelActionGroupConfig } from '@/side-panel/types/SidePanelActionGroupConfig';
+import { type SidePanelCommandMenuItemGroupConfig } from '@/side-panel/types/SidePanelCommandMenuItemGroupConfig';
import { SelectableList } from '@/ui/layout/selectable-list/components/SelectableList';
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
import { ScrollWrapper } from '@/ui/utilities/scroll/components/ScrollWrapper';
@@ -15,7 +15,7 @@ import { t } from '@lingui/core/macro';
import { MOBILE_VIEWPORT, themeCssVariables } from 'twenty-ui/theme-constants';
export type SidePanelListProps = {
- commandGroups: SidePanelActionGroupConfig[];
+ commandGroups: SidePanelCommandMenuItemGroupConfig[];
selectableItemIds: string[];
children?: React.ReactNode;
loading?: boolean;
@@ -83,7 +83,7 @@ export const SidePanelList = ({
items?.length ? (
{items.map((item) => (
-
+
))}
) : null,
diff --git a/packages/twenty-front/src/modules/side-panel/components/SidePanelMultipleRecordsInfo.tsx b/packages/twenty-front/src/modules/side-panel/components/SidePanelMultipleRecordsInfo.tsx
index 1215f23fb8..27d53ff94d 100644
--- a/packages/twenty-front/src/modules/side-panel/components/SidePanelMultipleRecordsInfo.tsx
+++ b/packages/twenty-front/src/modules/side-panel/components/SidePanelMultipleRecordsInfo.tsx
@@ -1,6 +1,6 @@
-import { DEFAULT_RECORD_ACTIONS_CONFIG } from '@/action-menu/actions/record-actions/constants/DefaultRecordActionsConfig';
-import { MultipleRecordsActionKeys } from '@/action-menu/actions/record-actions/multiple-records/types/MultipleRecordsActionKeys';
-import { getActionLabel } from '@/action-menu/utils/getActionLabel';
+import { DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG } from '@/command-menu-item/record/constants/DefaultRecordCommandMenuItemsConfig';
+import { MultipleRecordsCommandKeys } from '@/command-menu-item/record/multiple-records/types/MultipleRecordsCommandKeys';
+import { getCommandMenuItemLabel } from '@/command-menu-item/utils/getCommandMenuItemLabel';
import { SidePanelPageInfoLayout } from '@/side-panel/components/SidePanelPageInfoLayout';
import { useFindManyRecordsSelectedInContextStore } from '@/context-store/hooks/useFindManyRecordsSelectedInContextStore';
import { t } from '@lingui/core/macro';
@@ -21,13 +21,13 @@ export const SidePanelMultipleRecordsInfo = ({
});
const { Icon, label } =
- DEFAULT_RECORD_ACTIONS_CONFIG[MultipleRecordsActionKeys.UPDATE];
+ DEFAULT_RECORD_COMMAND_MENU_ITEMS_CONFIG[MultipleRecordsCommandKeys.UPDATE];
return (
}
iconColor={theme.font.color.tertiary}
- title={getActionLabel(label)}
+ title={getCommandMenuItemLabel(label)}
label={t`${totalCount} selected`}
/>
);
diff --git a/packages/twenty-front/src/modules/side-panel/components/SidePanelRouter.tsx b/packages/twenty-front/src/modules/side-panel/components/SidePanelRouter.tsx
index 10a2383e2b..3ffbea57a4 100644
--- a/packages/twenty-front/src/modules/side-panel/components/SidePanelRouter.tsx
+++ b/packages/twenty-front/src/modules/side-panel/components/SidePanelRouter.tsx
@@ -1,4 +1,4 @@
-import { ActionMenuContextProvider } from '@/action-menu/contexts/ActionMenuContextProvider';
+import { CommandMenuContextProvider } from '@/command-menu-item/contexts/CommandMenuContextProvider';
import { SidePanelContainer } from '@/side-panel/components/SidePanelContainer';
import { SidePanelTopBar } from '@/side-panel/components/SidePanelTopBar';
import { SIDE_PANEL_PAGES_CONFIG } from '@/side-panel/constants/SidePanelPagesConfig';
@@ -51,13 +51,13 @@ export const SidePanelRouter = () => {
-
{sidePanelPageComponent}
-
+
diff --git a/packages/twenty-front/src/modules/side-panel/components/__stories__/SidePanelContextRecordChip.stories.tsx b/packages/twenty-front/src/modules/side-panel/components/__stories__/SidePanelContextRecordChip.stories.tsx
index 5b4df07104..c5e66f3fa7 100644
--- a/packages/twenty-front/src/modules/side-panel/components/__stories__/SidePanelContextRecordChip.stories.tsx
+++ b/packages/twenty-front/src/modules/side-panel/components/__stories__/SidePanelContextRecordChip.stories.tsx
@@ -12,7 +12,7 @@ import { recordStoreFamilyState } from '@/object-record/record-store/states/reco
import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { type ObjectRecord } from '@/object-record/types/ObjectRecord';
import { ComponentDecorator } from 'twenty-ui/testing';
-import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper';
+import { getJestMetadataAndApolloMocksAndCommandMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper';
import { mockedCompanyRecords } from '~/testing/mock-data/generated/data/companies/mock-companies-data';
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
@@ -145,7 +145,7 @@ const createContextStoreWrapper = ({
companies: typeof mockedCompanyRecords;
componentInstanceId: string;
}) => {
- return getJestMetadataAndApolloMocksAndActionMenuWrapper({
+ return getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [
{
request: {
diff --git a/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useNavigateSidePanel.test.tsx b/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useNavigateSidePanel.test.tsx
index 0e152c249f..5483aec1ba 100644
--- a/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useNavigateSidePanel.test.tsx
+++ b/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useNavigateSidePanel.test.tsx
@@ -10,7 +10,7 @@ import { jotaiStore } from '@/ui/utilities/state/jotai/jotaiStore';
import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType';
import { SidePanelPages } from 'twenty-shared/types';
import { Icon123, useIcons } from 'twenty-ui/display';
-import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper';
+import { getJestMetadataAndApolloMocksAndCommandMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper';
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
jest.mock('uuid', () => ({
@@ -21,7 +21,7 @@ const personMockObjectMetadataItem = generatedMockObjectMetadataItems.find(
(item) => item.nameSingular === 'person',
)!;
-const wrapper = getJestMetadataAndApolloMocksAndActionMenuWrapper({
+const wrapper = getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: SIDE_PANEL_COMPONENT_INSTANCE_ID,
contextStoreCurrentObjectMetadataNameSingular:
diff --git a/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useOpenCalendarEventInSidePanel.test.tsx b/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useOpenCalendarEventInSidePanel.test.tsx
index 0cc1e96670..21cc918d3d 100644
--- a/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useOpenCalendarEventInSidePanel.test.tsx
+++ b/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useOpenCalendarEventInSidePanel.test.tsx
@@ -8,7 +8,7 @@ import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
import { SidePanelPages } from 'twenty-shared/types';
import { IconCalendarEvent } from 'twenty-ui/display';
-import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper';
+import { getJestMetadataAndApolloMocksAndCommandMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper';
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
jest.mock('uuid', () => ({
@@ -26,7 +26,7 @@ const personMockObjectMetadataItem = generatedMockObjectMetadataItems.find(
(item) => item.nameSingular === 'person',
)!;
-const wrapper = getJestMetadataAndApolloMocksAndActionMenuWrapper({
+const wrapper = getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: SIDE_PANEL_COMPONENT_INSTANCE_ID,
contextStoreCurrentObjectMetadataNameSingular:
diff --git a/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useOpenEmailThreadInSidePanel.test.tsx b/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useOpenEmailThreadInSidePanel.test.tsx
index c2c038ced9..4f72fa53ef 100644
--- a/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useOpenEmailThreadInSidePanel.test.tsx
+++ b/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useOpenEmailThreadInSidePanel.test.tsx
@@ -8,7 +8,7 @@ import { ContextStoreViewType } from '@/context-store/types/ContextStoreViewType
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
import { SidePanelPages } from 'twenty-shared/types';
import { IconMail } from 'twenty-ui/display';
-import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper';
+import { getJestMetadataAndApolloMocksAndCommandMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper';
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
jest.mock('uuid', () => ({
@@ -26,7 +26,7 @@ const personMockObjectMetadataItem = generatedMockObjectMetadataItems.find(
(item) => item.nameSingular === 'person',
)!;
-const wrapper = getJestMetadataAndApolloMocksAndActionMenuWrapper({
+const wrapper = getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: SIDE_PANEL_COMPONENT_INSTANCE_ID,
contextStoreCurrentObjectMetadataNameSingular:
diff --git a/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useOpenRecordInSidePanel.test.tsx b/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useOpenRecordInSidePanel.test.tsx
index 6e1de6c49c..6d95cbce1b 100644
--- a/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useOpenRecordInSidePanel.test.tsx
+++ b/packages/twenty-front/src/modules/side-panel/hooks/__tests__/useOpenRecordInSidePanel.test.tsx
@@ -16,7 +16,7 @@ import { getLabelIdentifierFieldMetadataItem } from '@/object-metadata/utils/get
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
import { SidePanelPages } from 'twenty-shared/types';
import { useIcons } from 'twenty-ui/display';
-import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper';
+import { getJestMetadataAndApolloMocksAndCommandMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper';
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
jest.mock('uuid', () => ({
@@ -44,7 +44,7 @@ const personMockObjectMetadataItem = generatedMockObjectMetadataItems.find(
(item) => item.nameSingular === 'person',
)!;
-const wrapper = getJestMetadataAndApolloMocksAndActionMenuWrapper({
+const wrapper = getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: SIDE_PANEL_COMPONENT_INSTANCE_ID,
contextStoreCurrentObjectMetadataNameSingular:
diff --git a/packages/twenty-front/src/modules/side-panel/hooks/useNavigateSidePanel.ts b/packages/twenty-front/src/modules/side-panel/hooks/useNavigateSidePanel.ts
index a1ca5011bc..8ee88b0d69 100644
--- a/packages/twenty-front/src/modules/side-panel/hooks/useNavigateSidePanel.ts
+++ b/packages/twenty-front/src/modules/side-panel/hooks/useNavigateSidePanel.ts
@@ -1,7 +1,7 @@
import { SIDE_PANEL_COMPONENT_INSTANCE_ID } from '@/side-panel/constants/SidePanelComponentInstanceId';
import { SIDE_PANEL_FOCUS_ID } from '@/side-panel/constants/SidePanelFocusId';
import { useSidePanelCloseAnimationCompleteCleanup } from '@/side-panel/hooks/useSidePanelCloseAnimationCompleteCleanup';
-import { useCopyContextStoreStates } from '@/command-menu/hooks/useCopyContextStoreAndActionMenuStates';
+import { useCopyContextStoreStates } from '@/command-menu/hooks/useCopyContextStoreAndCommandMenuStates';
import { sidePanelNavigationMorphItemsByPageState } from '@/side-panel/states/sidePanelNavigationMorphItemsByPageState';
import { sidePanelNavigationStackState } from '@/side-panel/states/sidePanelNavigationStackState';
import { sidePanelPageInfoState } from '@/side-panel/states/sidePanelPageInfoState';
diff --git a/packages/twenty-front/src/modules/side-panel/pages/record-page/components/SidePanelMergeRecordPage.tsx b/packages/twenty-front/src/modules/side-panel/pages/record-page/components/SidePanelMergeRecordPage.tsx
index e9811383ee..9786610b0f 100644
--- a/packages/twenty-front/src/modules/side-panel/pages/record-page/components/SidePanelMergeRecordPage.tsx
+++ b/packages/twenty-front/src/modules/side-panel/pages/record-page/components/SidePanelMergeRecordPage.tsx
@@ -1,4 +1,4 @@
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
+import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
import { SidePanelPageComponentInstanceContext } from '@/side-panel/states/contexts/SidePanelPageComponentInstanceContext';
import { useContextStoreObjectMetadataItemOrThrow } from '@/context-store/hooks/useContextStoreObjectMetadataItemOrThrow';
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
@@ -33,7 +33,7 @@ export const SidePanelMergeRecordPage = () => {
instanceId: sidePanelPageInstanceId,
}}
>
-
@@ -41,7 +41,7 @@ export const SidePanelMergeRecordPage = () => {
objectNameSingular={objectMetadataItem.nameSingular}
/>
-
+
);
diff --git a/packages/twenty-front/src/modules/side-panel/pages/record-page/components/SidePanelRecordPage.tsx b/packages/twenty-front/src/modules/side-panel/pages/record-page/components/SidePanelRecordPage.tsx
index fda2b13be3..18c85e3388 100644
--- a/packages/twenty-front/src/modules/side-panel/pages/record-page/components/SidePanelRecordPage.tsx
+++ b/packages/twenty-front/src/modules/side-panel/pages/record-page/components/SidePanelRecordPage.tsx
@@ -1,4 +1,4 @@
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
+import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
import { TimelineActivityContext } from '@/activities/timeline-activities/contexts/TimelineActivityContext';
import { viewableRecordIdComponentState } from '@/side-panel/pages/record-page/states/viewableRecordIdComponentState';
import { viewableRecordNameSingularComponentState } from '@/side-panel/pages/record-page/states/viewableRecordNameSingularComponentState';
@@ -72,7 +72,7 @@ export const SidePanelRecordPage = () => {
instanceId: sidePanelPageInstanceId,
}}
>
-
@@ -90,7 +90,7 @@ export const SidePanelRecordPage = () => {
/>
-
+
);
diff --git a/packages/twenty-front/src/modules/side-panel/pages/root/components/SidePanelRootPage.tsx b/packages/twenty-front/src/modules/side-panel/pages/root/components/SidePanelRootPage.tsx
index 94d40a26af..64154037f7 100644
--- a/packages/twenty-front/src/modules/side-panel/pages/root/components/SidePanelRootPage.tsx
+++ b/packages/twenty-front/src/modules/side-panel/pages/root/components/SidePanelRootPage.tsx
@@ -3,7 +3,7 @@ import { SidePanelList } from '@/side-panel/components/SidePanelList';
import { SIDE_PANEL_PREVIOUS_COMPONENT_INSTANCE_ID } from '@/side-panel/constants/SidePanelPreviousComponentInstanceId';
import { SIDE_PANEL_RESET_CONTEXT_TO_SELECTION } from '@/side-panel/constants/SidePanelResetContextToSelection';
import { sidePanelSearchState } from '@/side-panel/states/sidePanelSearchState';
-import { type SidePanelActionGroupConfig } from '@/side-panel/types/SidePanelActionGroupConfig';
+import { type SidePanelCommandMenuItemGroupConfig } from '@/side-panel/types/SidePanelCommandMenuItemGroupConfig';
import { contextStoreCurrentObjectMetadataItemIdComponentState } from '@/context-store/states/contextStoreCurrentObjectMetadataItemIdComponentState';
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
import { SidePanelResetContextToSelectionButton } from '@/side-panel/pages/root/components/SidePanelResetContextToSelectionButton';
@@ -49,7 +49,7 @@ export const SidePanelRootPage = () => {
(item) => item.id === contextStoreCurrentObjectMetadataItemId,
);
- const commandGroups: SidePanelActionGroupConfig[] = [
+ const commandGroups: SidePanelCommandMenuItemGroupConfig[] = [
{
heading: t`Record Selection`,
items: matchingStandardActionRecordSelectionActions
diff --git a/packages/twenty-front/src/modules/side-panel/pages/root/hooks/__tests__/useFilterActionsWithSidePanelSearch.test.tsx b/packages/twenty-front/src/modules/side-panel/pages/root/hooks/__tests__/useFilterActionsWithSidePanelSearch.test.tsx
index 2fb9dc2e16..76c4e5ac25 100644
--- a/packages/twenty-front/src/modules/side-panel/pages/root/hooks/__tests__/useFilterActionsWithSidePanelSearch.test.tsx
+++ b/packages/twenty-front/src/modules/side-panel/pages/root/hooks/__tests__/useFilterActionsWithSidePanelSearch.test.tsx
@@ -1,6 +1,6 @@
-import { type ActionConfig } from '@/action-menu/actions/types/ActionConfig';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionType } from '@/action-menu/actions/types/ActionType';
+import { type CommandMenuItemConfig } from '@/command-menu-item/types/CommandMenuItemConfig';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
import { renderHook } from '@testing-library/react';
import { IconPlus } from 'twenty-ui/display';
import { useFilterActionsWithSidePanelSearch } from '@/side-panel/pages/root/hooks/useFilterActionsWithSidePanelSearch';
@@ -8,12 +8,12 @@ import { useFilterActionsWithSidePanelSearch } from '@/side-panel/pages/root/hoo
const MockComponent = Mock Component
;
describe('useFilterActionsWithSidePanelSearch', () => {
- const mockActions: ActionConfig[] = [
+ const mockActions: CommandMenuItemConfig[] = [
{
key: 'action-1',
label: 'Create Record',
- type: ActionType.Standard,
- scope: ActionScope.Global,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.Global,
position: 1,
Icon: IconPlus,
shouldBeRegistered: () => true,
@@ -23,8 +23,8 @@ describe('useFilterActionsWithSidePanelSearch', () => {
{
key: 'action-2',
label: 'Delete Record',
- type: ActionType.Standard,
- scope: ActionScope.RecordSelection,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.RecordSelection,
position: 2,
Icon: IconPlus,
shouldBeRegistered: () => true,
@@ -34,8 +34,8 @@ describe('useFilterActionsWithSidePanelSearch', () => {
{
key: 'action-3',
label: 'Update Record',
- type: ActionType.Standard,
- scope: ActionScope.Object,
+ type: CommandMenuItemType.Standard,
+ scope: CommandMenuItemScope.Object,
position: 3,
Icon: IconPlus,
shouldBeRegistered: () => true,
diff --git a/packages/twenty-front/src/modules/side-panel/pages/root/hooks/useFilterActionsWithSidePanelSearch.ts b/packages/twenty-front/src/modules/side-panel/pages/root/hooks/useFilterActionsWithSidePanelSearch.ts
index 66364e5946..ee7e56487e 100644
--- a/packages/twenty-front/src/modules/side-panel/pages/root/hooks/useFilterActionsWithSidePanelSearch.ts
+++ b/packages/twenty-front/src/modules/side-panel/pages/root/hooks/useFilterActionsWithSidePanelSearch.ts
@@ -1,17 +1,17 @@
-import { type ActionConfig } from '@/action-menu/actions/types/ActionConfig';
-import { getActionLabel } from '@/action-menu/utils/getActionLabel';
+import { type CommandMenuItemConfig } from '@/command-menu-item/types/CommandMenuItemConfig';
+import { getCommandMenuItemLabel } from '@/command-menu-item/utils/getCommandMenuItemLabel';
import { isNonEmptyString } from '@sniptt/guards';
import { useCallback } from 'react';
import { normalizeSearchText } from '~/utils/normalizeSearchText';
-const checkInShortcuts = (action: ActionConfig, search: string) => {
+const checkInShortcuts = (action: CommandMenuItemConfig, search: string) => {
const concatenatedString = action.hotKeys?.join('') ?? '';
const searchNormalized = normalizeSearchText(search.trim());
return normalizeSearchText(concatenatedString).includes(searchNormalized);
};
-const checkInLabels = (action: ActionConfig, search: string) => {
- const actionLabel = getActionLabel(action.label);
+const checkInLabels = (action: CommandMenuItemConfig, search: string) => {
+ const actionLabel = getCommandMenuItemLabel(action.label);
if (isNonEmptyString(actionLabel)) {
const searchNormalized = normalizeSearchText(search);
return normalizeSearchText(actionLabel).includes(searchNormalized);
@@ -27,7 +27,7 @@ export const useFilterActionsWithSidePanelSearch = ({
sidePanelSearch,
}: UseFilterActionsWithSidePanelSearchProps) => {
const filterActionsWithSidePanelSearch = useCallback(
- (actions: ActionConfig[]) => {
+ (actions: CommandMenuItemConfig[]) => {
return actions.filter((action) =>
sidePanelSearch.length > 0
? checkInShortcuts(action, sidePanelSearch) ||
diff --git a/packages/twenty-front/src/modules/side-panel/pages/root/hooks/useResetPreviousSidePanelContext.ts b/packages/twenty-front/src/modules/side-panel/pages/root/hooks/useResetPreviousSidePanelContext.ts
index 0bb145a7ec..d50ee02fb9 100644
--- a/packages/twenty-front/src/modules/side-panel/pages/root/hooks/useResetPreviousSidePanelContext.ts
+++ b/packages/twenty-front/src/modules/side-panel/pages/root/hooks/useResetPreviousSidePanelContext.ts
@@ -1,6 +1,6 @@
import { SIDE_PANEL_COMPONENT_INSTANCE_ID } from '@/side-panel/constants/SidePanelComponentInstanceId';
import { SIDE_PANEL_PREVIOUS_COMPONENT_INSTANCE_ID } from '@/side-panel/constants/SidePanelPreviousComponentInstanceId';
-import { useCopyContextStoreStates } from '@/command-menu/hooks/useCopyContextStoreAndActionMenuStates';
+import { useCopyContextStoreStates } from '@/command-menu/hooks/useCopyContextStoreAndCommandMenuStates';
import { useResetContextStoreStates } from '@/command-menu/hooks/useResetContextStoreStates';
export const useResetPreviousSidePanelContext = () => {
diff --git a/packages/twenty-front/src/modules/side-panel/pages/root/hooks/useSidePanelActions.tsx b/packages/twenty-front/src/modules/side-panel/pages/root/hooks/useSidePanelActions.tsx
index c7ef18b527..383acc5b5a 100644
--- a/packages/twenty-front/src/modules/side-panel/pages/root/hooks/useSidePanelActions.tsx
+++ b/packages/twenty-front/src/modules/side-panel/pages/root/hooks/useSidePanelActions.tsx
@@ -1,67 +1,73 @@
-import { type ActionConfig } from '@/action-menu/actions/types/ActionConfig';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionType } from '@/action-menu/actions/types/ActionType';
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
+import { type CommandMenuItemConfig } from '@/command-menu-item/types/CommandMenuItemConfig';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
import { useContext } from 'react';
export const useSidePanelActions = () => {
- const { actions } = useContext(ActionMenuContext);
+ const { commandMenuItems } = useContext(CommandMenuContext);
- const navigateActions = actions?.filter(
- (action) => action.type === ActionType.Navigation,
+ const navigateActions = commandMenuItems?.filter(
+ (action) => action.type === CommandMenuItemType.Navigation,
);
- const actionRecordSelectionActions: ActionConfig[] = actions?.filter(
+ const actionRecordSelectionActions: CommandMenuItemConfig[] =
+ commandMenuItems?.filter(
+ (action) =>
+ action.type === CommandMenuItemType.Standard &&
+ action.scope === CommandMenuItemScope.RecordSelection,
+ );
+
+ const actionObjectActions: CommandMenuItemConfig[] = commandMenuItems?.filter(
(action) =>
- action.type === ActionType.Standard &&
- action.scope === ActionScope.RecordSelection,
+ action.type === CommandMenuItemType.Standard &&
+ action.scope === CommandMenuItemScope.Object,
);
- const actionObjectActions: ActionConfig[] = actions?.filter(
+ const actionGlobalActions: CommandMenuItemConfig[] = commandMenuItems?.filter(
(action) =>
- action.type === ActionType.Standard &&
- action.scope === ActionScope.Object,
+ action.type === CommandMenuItemType.Standard &&
+ action.scope === CommandMenuItemScope.Global,
);
- const actionGlobalActions: ActionConfig[] = actions?.filter(
- (action) =>
- action.type === ActionType.Standard &&
- action.scope === ActionScope.Global,
+ const workflowRunRecordSelectionActions: CommandMenuItemConfig[] =
+ commandMenuItems?.filter(
+ (action) =>
+ action.type === CommandMenuItemType.WorkflowRun &&
+ action.scope === CommandMenuItemScope.RecordSelection,
+ );
+
+ const workflowRunGlobalActions: CommandMenuItemConfig[] =
+ commandMenuItems?.filter(
+ (action) =>
+ action.type === CommandMenuItemType.WorkflowRun &&
+ action.scope === CommandMenuItemScope.Global,
+ );
+
+ const frontComponentGlobalActions: CommandMenuItemConfig[] =
+ commandMenuItems?.filter(
+ (action) =>
+ action.type === CommandMenuItemType.FrontComponent &&
+ action.scope === CommandMenuItemScope.Global,
+ );
+
+ const frontComponentRecordSelectionActions: CommandMenuItemConfig[] =
+ commandMenuItems?.filter(
+ (action) =>
+ action.type === CommandMenuItemType.FrontComponent &&
+ action.scope === CommandMenuItemScope.RecordSelection,
+ );
+
+ const fallbackActions: CommandMenuItemConfig[] = commandMenuItems?.filter(
+ (action) => action.type === CommandMenuItemType.Fallback,
);
- const workflowRunRecordSelectionActions: ActionConfig[] = actions?.filter(
- (action) =>
- action.type === ActionType.WorkflowRun &&
- action.scope === ActionScope.RecordSelection,
- );
-
- const workflowRunGlobalActions: ActionConfig[] = actions?.filter(
- (action) =>
- action.type === ActionType.WorkflowRun &&
- action.scope === ActionScope.Global,
- );
-
- const frontComponentGlobalActions: ActionConfig[] = actions?.filter(
- (action) =>
- action.type === ActionType.FrontComponent &&
- action.scope === ActionScope.Global,
- );
-
- const frontComponentRecordSelectionActions: ActionConfig[] = actions?.filter(
- (action) =>
- action.type === ActionType.FrontComponent &&
- action.scope === ActionScope.RecordSelection,
- );
-
- const fallbackActions: ActionConfig[] = actions?.filter(
- (action) => action.type === ActionType.Fallback,
- );
-
- const createRelatedRecordActions: ActionConfig[] = actions?.filter(
- (action) =>
- action.type === ActionType.Standard &&
- action.scope === ActionScope.CreateRelatedRecord,
- );
+ const createRelatedRecordActions: CommandMenuItemConfig[] =
+ commandMenuItems?.filter(
+ (action) =>
+ action.type === CommandMenuItemType.Standard &&
+ action.scope === CommandMenuItemScope.CreateRelatedRecord,
+ );
return {
navigateActions,
diff --git a/packages/twenty-front/src/modules/side-panel/pages/search/hooks/useSidePanelSearchRecords.tsx b/packages/twenty-front/src/modules/side-panel/pages/search/hooks/useSidePanelSearchRecords.tsx
index a681070318..a44d08c5dc 100644
--- a/packages/twenty-front/src/modules/side-panel/pages/search/hooks/useSidePanelSearchRecords.tsx
+++ b/packages/twenty-front/src/modules/side-panel/pages/search/hooks/useSidePanelSearchRecords.tsx
@@ -1,7 +1,7 @@
-import { Action } from '@/action-menu/actions/components/Action';
-import { ActionLink } from '@/action-menu/actions/components/ActionLink';
-import { ActionScope } from '@/action-menu/actions/types/ActionScope';
-import { ActionType } from '@/action-menu/actions/types/ActionType';
+import { Command } from '@/command-menu-item/display/components/Command';
+import { CommandLink } from '@/command-menu-item/display/components/CommandLink';
+import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
+import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
import { MAX_SEARCH_RESULTS } from '@/command-menu/constants/MaxSearchResults';
import { useOpenRecordInSidePanel } from '@/side-panel/hooks/useOpenRecordInSidePanel';
import { sidePanelSearchState } from '@/side-panel/states/sidePanelSearchState';
@@ -56,8 +56,8 @@ export const useSidePanelSearchRecords = () => {
return (searchData?.search.edges.map((edge) => edge.node) ?? []).map(
(searchRecord, index) => {
const baseAction = {
- type: ActionType.Navigation,
- scope: ActionScope.Global,
+ type: CommandMenuItemType.Navigation,
+ scope: CommandMenuItemScope.Global,
key: searchRecord.recordId,
label: searchRecord.label,
position: index,
@@ -89,7 +89,7 @@ export const useSidePanelSearchRecords = () => {
return {
...baseAction,
component: (
- {
searchRecord.objectNameSingular === 'task'
? openRecordInSidePanel({
@@ -101,7 +101,7 @@ export const useSidePanelSearchRecords = () => {
objectNameSingular: CoreObjectNameSingular.Note,
});
}}
- closeSidePanelOnCommandMenuListActionExecution={false}
+ closeSidePanelOnCommandMenuListExecution={false}
/>
),
};
@@ -110,7 +110,7 @@ export const useSidePanelSearchRecords = () => {
return {
...baseAction,
component: (
- {
recordTableId={recordIndexId}
viewId={viewBarId}
/>
-
{isDefined(objectMetadataItem) && (
@@ -103,7 +103,7 @@ export const SignInBackgroundMockContainer = () => {
/>
>
)}
-
+
diff --git a/packages/twenty-front/src/modules/ui/utilities/hotkey/utils/__tests__/isNonTextWritingKey.test.ts b/packages/twenty-front/src/modules/ui/utilities/hotkey/utils/__tests__/isNonTextWritingKey.test.ts
index 58f5d4a2f1..3079320ac9 100644
--- a/packages/twenty-front/src/modules/ui/utilities/hotkey/utils/__tests__/isNonTextWritingKey.test.ts
+++ b/packages/twenty-front/src/modules/ui/utilities/hotkey/utils/__tests__/isNonTextWritingKey.test.ts
@@ -3,6 +3,7 @@ import { isNonTextWritingKey } from '@/ui/utilities/hotkey/utils/isNonTextWritin
describe('isNonTextWritingKey', () => {
it('should determine non-text-writing keys', () => {
expect(isNonTextWritingKey('Tab')).toBe(true);
+ expect(isNonTextWritingKey('ContextMenu')).toBe(true);
expect(isNonTextWritingKey('a')).toBe(false);
});
});
diff --git a/packages/twenty-front/src/modules/ui/utilities/hotkey/utils/isNonTextWritingKey.ts b/packages/twenty-front/src/modules/ui/utilities/hotkey/utils/isNonTextWritingKey.ts
index 6c3a0f96ab..8c1bd4be4b 100644
--- a/packages/twenty-front/src/modules/ui/utilities/hotkey/utils/isNonTextWritingKey.ts
+++ b/packages/twenty-front/src/modules/ui/utilities/hotkey/utils/isNonTextWritingKey.ts
@@ -35,7 +35,7 @@ export const isNonTextWritingKey = (key: string) => {
'Delete',
'End',
'PageDown',
- 'ActionMenuDropdown',
+ 'ContextMenu',
'PrintScreen',
'BrowserBack',
'BrowserForward',
diff --git a/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups.test.tsx b/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups.test.tsx
index 08b294b4f9..6fadc35c2c 100644
--- a/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups.test.tsx
+++ b/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups.test.tsx
@@ -15,7 +15,7 @@ import { mapViewFilterGroupLogicalOperatorToRecordFilterGroupLogicalOperator } f
import { act } from 'react';
import { isDefined } from 'twenty-shared/utils';
import { type CoreViewFilterGroup } from '~/generated-metadata/graphql';
-import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper';
+import { getJestMetadataAndApolloMocksAndCommandMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper';
import { mockedCoreViews } from '~/testing/mock-data/generated/metadata/views/mock-views-data';
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
@@ -87,7 +87,7 @@ describe('useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups', () => {
};
},
{
- wrapper: getJestMetadataAndApolloMocksAndActionMenuWrapper({
+ wrapper: getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: 'instanceId',
contextStoreCurrentViewId: mockView.id,
@@ -139,7 +139,7 @@ describe('useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups', () => {
};
},
{
- wrapper: getJestMetadataAndApolloMocksAndActionMenuWrapper({
+ wrapper: getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: 'instanceId',
contextStoreCurrentObjectMetadataNameSingular:
@@ -180,7 +180,7 @@ describe('useApplyCurrentViewFilterGroupsToCurrentRecordFilterGroups', () => {
};
},
{
- wrapper: getJestMetadataAndApolloMocksAndActionMenuWrapper({
+ wrapper: getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: 'instanceId',
contextStoreCurrentObjectMetadataNameSingular:
diff --git a/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFiltersToCurrentRecordFilters.test.tsx b/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFiltersToCurrentRecordFilters.test.tsx
index 97fcfdd296..d2d31d120d 100644
--- a/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFiltersToCurrentRecordFilters.test.tsx
+++ b/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewFiltersToCurrentRecordFilters.test.tsx
@@ -16,7 +16,7 @@ import {
type CoreViewFilter,
ViewFilterOperand as CoreViewFilterOperand,
} from '~/generated-metadata/graphql';
-import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper';
+import { getJestMetadataAndApolloMocksAndCommandMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper';
import { mockedCoreViews } from '~/testing/mock-data/generated/metadata/views/mock-views-data';
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
import { useApplyCurrentViewFiltersToCurrentRecordFilters } from '@/views/hooks/useApplyCurrentViewFiltersToCurrentRecordFilters';
@@ -98,7 +98,7 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
};
},
{
- wrapper: getJestMetadataAndApolloMocksAndActionMenuWrapper({
+ wrapper: getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: 'instanceId',
contextStoreCurrentObjectMetadataNameSingular:
@@ -148,7 +148,7 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
};
},
{
- wrapper: getJestMetadataAndApolloMocksAndActionMenuWrapper({
+ wrapper: getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: 'instanceId',
contextStoreCurrentObjectMetadataNameSingular:
@@ -189,7 +189,7 @@ describe('useApplyCurrentViewFiltersToCurrentRecordFilters', () => {
};
},
{
- wrapper: getJestMetadataAndApolloMocksAndActionMenuWrapper({
+ wrapper: getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: 'instanceId',
contextStoreCurrentObjectMetadataNameSingular:
diff --git a/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewSortsToCurrentRecordSorts.test.tsx b/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewSortsToCurrentRecordSorts.test.tsx
index a8b5adf62a..d383703529 100644
--- a/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewSortsToCurrentRecordSorts.test.tsx
+++ b/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyCurrentViewSortsToCurrentRecordSorts.test.tsx
@@ -12,7 +12,7 @@ import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations'
import { type View } from '@/views/types/View';
import { isDefined } from 'twenty-shared/utils';
import { ViewSortDirection } from '~/generated-metadata/graphql';
-import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper';
+import { getJestMetadataAndApolloMocksAndCommandMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper';
import { mockedCoreViews } from '~/testing/mock-data/generated/metadata/views/mock-views-data';
import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockObjectMetadataItems';
import { useApplyCurrentViewSortsToCurrentRecordSorts } from '@/views/hooks/useApplyCurrentViewSortsToCurrentRecordSorts';
@@ -86,7 +86,7 @@ describe('useApplyCurrentViewSortsToCurrentRecordSorts', () => {
};
},
{
- wrapper: getJestMetadataAndApolloMocksAndActionMenuWrapper({
+ wrapper: getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: 'instanceId',
contextStoreCurrentObjectMetadataNameSingular:
@@ -130,7 +130,7 @@ describe('useApplyCurrentViewSortsToCurrentRecordSorts', () => {
};
},
{
- wrapper: getJestMetadataAndApolloMocksAndActionMenuWrapper({
+ wrapper: getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: 'instanceId',
contextStoreCurrentObjectMetadataNameSingular:
@@ -176,7 +176,7 @@ describe('useApplyCurrentViewSortsToCurrentRecordSorts', () => {
};
},
{
- wrapper: getJestMetadataAndApolloMocksAndActionMenuWrapper({
+ wrapper: getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: 'instanceId',
contextStoreCurrentObjectMetadataNameSingular:
diff --git a/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyViewSortsToCurrentRecordSorts.test.tsx b/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyViewSortsToCurrentRecordSorts.test.tsx
index 53274867cb..684f0a8681 100644
--- a/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyViewSortsToCurrentRecordSorts.test.tsx
+++ b/packages/twenty-front/src/modules/views/hooks/__tests__/useApplyViewSortsToCurrentRecordSorts.test.tsx
@@ -8,7 +8,7 @@ import { generatedMockObjectMetadataItems } from '~/testing/utils/generatedMockO
import { type CoreViewSortEssential } from '@/views/types/CoreViewSortEssential';
import { isDefined } from 'twenty-shared/utils';
import { ViewSortDirection } from '~/generated-metadata/graphql';
-import { getJestMetadataAndApolloMocksAndActionMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper';
+import { getJestMetadataAndApolloMocksAndCommandMenuWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper';
import { useApplyViewSortsToCurrentRecordSorts } from '@/views/hooks/useApplyViewSortsToCurrentRecordSorts';
const mockObjectMetadataItemNameSingular = 'company';
@@ -52,7 +52,7 @@ describe('useApplyViewSortsToCurrentRecordSorts', () => {
return { applyViewSortsToCurrentRecordSorts, currentRecordSorts };
},
{
- wrapper: getJestMetadataAndApolloMocksAndActionMenuWrapper({
+ wrapper: getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: 'instanceId',
contextStoreCurrentObjectMetadataNameSingular:
@@ -87,7 +87,7 @@ describe('useApplyViewSortsToCurrentRecordSorts', () => {
return { applyViewSortsToCurrentRecordSorts, currentRecordSorts };
},
{
- wrapper: getJestMetadataAndApolloMocksAndActionMenuWrapper({
+ wrapper: getJestMetadataAndApolloMocksAndCommandMenuWrapper({
apolloMocks: [],
componentInstanceId: 'instanceId',
contextStoreCurrentObjectMetadataNameSingular:
diff --git a/packages/twenty-front/src/modules/workflow/hooks/useActiveWorkflowVersionsWithManualTrigger.ts b/packages/twenty-front/src/modules/workflow/hooks/useActiveWorkflowVersionsWithManualTrigger.ts
index 089468c50b..814c951227 100644
--- a/packages/twenty-front/src/modules/workflow/hooks/useActiveWorkflowVersionsWithManualTrigger.ts
+++ b/packages/twenty-front/src/modules/workflow/hooks/useActiveWorkflowVersionsWithManualTrigger.ts
@@ -1,4 +1,4 @@
-import { isGlobalManualTrigger } from '@/action-menu/actions/record-actions/utils/isGlobalManualTrigger';
+import { isGlobalManualTrigger } from '@/command-menu-item/record/utils/isGlobalManualTrigger';
import { CoreObjectNameSingular } from 'twenty-shared/types';
import { type ObjectMetadataItem } from '@/object-metadata/types/ObjectMetadataItem';
import { useFindManyRecords } from '@/object-record/hooks/useFindManyRecords';
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 043e522c0b..1a0038da9e 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,4 @@
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
import { sidePanelWidthState } from '@/side-panel/states/sidePanelWidthState';
import { isSidePanelOpenedState } from '@/side-panel/states/isSidePanelOpenedState';
import { useListenToSidePanelClosing } from '@/ui/layout/side-panel/hooks/useListenToSidePanelClosing';
@@ -256,7 +256,7 @@ export const WorkflowDiagramCanvasBase = ({
}, [workflowDiagram, workflowInsertStepIds]);
const isSidePanelOpened = useAtomStateValue(isSidePanelOpenedState);
- const { isInSidePanel } = useContext(ActionMenuContext);
+ const { isInSidePanel } = useContext(CommandMenuContext);
const handleEdgesChange = (
edgeChanges: Array>,
diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunVisualizerEffect.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunVisualizerEffect.tsx
index b7d71a0761..24da3ceaa4 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunVisualizerEffect.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/components/WorkflowRunVisualizerEffect.tsx
@@ -1,4 +1,4 @@
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
import { useSidePanelWorkflowNavigation } from '@/side-panel/pages/workflow/hooks/useSidePanelWorkflowNavigation';
import { useAtomComponentStateCallbackState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateCallbackState';
import { useSetAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useSetAtomComponentState';
@@ -68,7 +68,7 @@ export const WorkflowRunVisualizerEffect = ({
const { populateStepsOutputSchema } = useStepsOutputSchema();
- const { isInSidePanel } = useContext(ActionMenuContext);
+ const { isInSidePanel } = useContext(CommandMenuContext);
const store = useStore();
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 e5475da357..361166ca98 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,4 +1,4 @@
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
import { useSidePanelWorkflowNavigation } from '@/side-panel/pages/workflow/hooks/useSidePanelWorkflowNavigation';
import { sidePanelNavigationStackState } from '@/side-panel/states/sidePanelNavigationStackState';
import { useAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentState';
@@ -13,7 +13,7 @@ import { useCallback, useContext } from 'react';
import { isDefined } from 'twenty-shared/utils';
export const useStartNodeCreation = () => {
- const { isInSidePanel } = useContext(ActionMenuContext);
+ const { isInSidePanel } = useContext(CommandMenuContext);
const [workflowInsertStepIds, setWorkflowInsertStepIds] =
useAtomComponentState(workflowInsertStepIdsComponentState);
diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramEmptyTriggerEditable.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramEmptyTriggerEditable.tsx
index 043554c3ae..a122ff357d 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramEmptyTriggerEditable.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramEmptyTriggerEditable.tsx
@@ -1,4 +1,4 @@
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
import { useSidePanelWorkflowNavigation } from '@/side-panel/pages/workflow/hooks/useSidePanelWorkflowNavigation';
import { sidePanelNavigationStackState } from '@/side-panel/states/sidePanelNavigationStackState';
import { useAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentState';
@@ -32,7 +32,7 @@ export const WorkflowDiagramEmptyTriggerEditable = ({ id }: { id: string }) => {
workflowSelectedNodeComponentState,
);
- const { isInSidePanel } = useContext(ActionMenuContext);
+ const { isInSidePanel } = useContext(CommandMenuContext);
const setSidePanelNavigationStack = useSetAtomState(
sidePanelNavigationStackState,
diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramEmptyTriggerReadonly.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramEmptyTriggerReadonly.tsx
index 72ca2c8b38..9f28a3ff35 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramEmptyTriggerReadonly.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramEmptyTriggerReadonly.tsx
@@ -1,4 +1,4 @@
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
import { useSidePanelWorkflowNavigation } from '@/side-panel/pages/workflow/hooks/useSidePanelWorkflowNavigation';
import { sidePanelNavigationStackState } from '@/side-panel/states/sidePanelNavigationStackState';
import { useAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentState';
@@ -35,7 +35,7 @@ export const WorkflowDiagramEmptyTriggerReadonly = ({ id }: { id: string }) => {
workflowSelectedNodeComponentState,
);
- const { isInSidePanel } = useContext(ActionMenuContext);
+ const { isInSidePanel } = useContext(CommandMenuContext);
const { openWorkflowViewStepInSidePanel } = useSidePanelWorkflowNavigation();
diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditable.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditable.tsx
index 16a82e2b72..82c810a224 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditable.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeEditable.tsx
@@ -1,4 +1,4 @@
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
import { useSidePanelWorkflowNavigation } from '@/side-panel/pages/workflow/hooks/useSidePanelWorkflowNavigation';
import { sidePanelNavigationStackState } from '@/side-panel/states/sidePanelNavigationStackState';
import { useAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentState';
@@ -37,7 +37,7 @@ export const WorkflowDiagramStepNodeEditable = ({
const { resetWorkflowInsertStepIds } = useResetWorkflowInsertStepIds();
- const { isInSidePanel } = useContext(ActionMenuContext);
+ const { isInSidePanel } = useContext(CommandMenuContext);
const setSidePanelNavigationStack = useSetAtomState(
sidePanelNavigationStackState,
diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeReadonly.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeReadonly.tsx
index 95fa7580c5..bf71e9399b 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeReadonly.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowDiagramStepNodeReadonly.tsx
@@ -1,4 +1,4 @@
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
import { useSidePanelWorkflowNavigation } from '@/side-panel/pages/workflow/hooks/useSidePanelWorkflowNavigation';
import { sidePanelNavigationStackState } from '@/side-panel/states/sidePanelNavigationStackState';
import { useAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentState';
@@ -50,7 +50,7 @@ export const WorkflowDiagramStepNodeReadonly = ({
const { openWorkflowViewStepInSidePanel } = useSidePanelWorkflowNavigation();
- const { isInSidePanel } = useContext(ActionMenuContext);
+ const { isInSidePanel } = useContext(CommandMenuContext);
const setSidePanelNavigationStack = useSetAtomState(
sidePanelNavigationStackState,
diff --git a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowRunDiagramStepNode.tsx b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowRunDiagramStepNode.tsx
index 7b50a752fc..19f3a219c8 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowRunDiagramStepNode.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-diagram/workflow-nodes/components/WorkflowRunDiagramStepNode.tsx
@@ -1,4 +1,4 @@
-import { ActionMenuContext } from '@/action-menu/contexts/ActionMenuContext';
+import { CommandMenuContext } from '@/command-menu-item/contexts/CommandMenuContext';
import { useSidePanelWorkflowNavigation } from '@/side-panel/pages/workflow/hooks/useSidePanelWorkflowNavigation';
import { sidePanelNavigationStackState } from '@/side-panel/states/sidePanelNavigationStackState';
import { useAtomComponentState } from '@/ui/utilities/state/jotai/hooks/useAtomComponentState';
@@ -100,7 +100,7 @@ export const WorkflowRunDiagramStepNode = ({
const { openWorkflowRunViewStepInSidePanel } =
useSidePanelWorkflowNavigation();
- const { isInSidePanel } = useContext(ActionMenuContext);
+ const { isInSidePanel } = useContext(CommandMenuContext);
const setSidePanelNavigationStack = useSetAtomState(
sidePanelNavigationStackState,
diff --git a/packages/twenty-front/src/modules/action-menu/components/CmdEnterActionButton.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowStepCmdEnterButton.tsx
similarity index 95%
rename from packages/twenty-front/src/modules/action-menu/components/CmdEnterActionButton.tsx
rename to packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowStepCmdEnterButton.tsx
index 0d55389deb..ec265f106a 100644
--- a/packages/twenty-front/src/modules/action-menu/components/CmdEnterActionButton.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-steps/components/WorkflowStepCmdEnterButton.tsx
@@ -4,7 +4,7 @@ import { Key } from 'ts-key-enum';
import { Button } from 'twenty-ui/input';
import { getOsControlSymbol } from 'twenty-ui/utilities';
-export const CmdEnterActionButton = ({
+export const WorkflowStepCmdEnterButton = ({
title,
onClick,
disabled = false,
diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/filters/components/WorkflowStepFilterAddFilterRuleSelect.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/filters/components/WorkflowStepFilterAddFilterRuleSelect.tsx
index 79d1dfbb22..6584a9b745 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-steps/filters/components/WorkflowStepFilterAddFilterRuleSelect.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-steps/filters/components/WorkflowStepFilterAddFilterRuleSelect.tsx
@@ -1,4 +1,4 @@
-import { ActionButton } from '@/action-menu/actions/display/components/ActionButton';
+import { CommandMenuButton } from '@/command-menu/components/CommandMenuButton';
import { getAdvancedFilterAddFilterRuleSelectDropdownId } from '@/object-record/advanced-filter/utils/getAdvancedFilterAddFilterRuleSelectDropdownId';
import { Dropdown } from '@/ui/layout/dropdown/components/Dropdown';
import { DropdownContent } from '@/ui/layout/dropdown/components/DropdownContent';
@@ -95,8 +95,8 @@ export const WorkflowStepFilterAddFilterRuleSelect = ({
if (!isFilterRuleGroupOptionVisible) {
return (
- setWorkflowAiAgentPermissionsIsAddingPermission(true)}
diff --git a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionCode.tsx b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionCode.tsx
index 9e44744ab9..b41da8dcdb 100644
--- a/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionCode.tsx
+++ b/packages/twenty-front/src/modules/workflow/workflow-steps/workflow-actions/code-action/components/WorkflowEditActionCode.tsx
@@ -8,7 +8,7 @@ import { workflowVisualizerWorkflowIdComponentState } from '@/workflow/states/wo
import { type WorkflowCodeAction } from '@/workflow/types/Workflow';
import { setNestedValue } from '@/workflow/workflow-steps/workflow-actions/code-action/utils/setNestedValue';
-import { CmdEnterActionButton } from '@/action-menu/components/CmdEnterActionButton';
+import { WorkflowStepCmdEnterButton } from '@/workflow/workflow-steps/components/WorkflowStepCmdEnterButton';
import { LogicFunctionExecutionResult } from '@/logic-functions/components/LogicFunctionExecutionResult';
import { LogicFunctionLogs } from '@/logic-functions/components/LogicFunctionLogs';
import { mergeDefaultFunctionInputAndFunctionInput } from '@/workflow/workflow-steps/workflow-actions/code-action/utils/mergeDefaultFunctionInputAndFunctionInput';
@@ -434,7 +434,7 @@ export const WorkflowEditActionCode = ({
additionalActions={
activeTabId === WorkflowLogicFunctionTabId.TEST
? [
- {
-
@@ -49,7 +49,7 @@ export const RecordShowPage = () => {
objectNameSingular={objectNameSingular}
objectRecordId={objectRecordId}
>
-
+
@@ -72,7 +72,7 @@ export const RecordShowPage = () => {
-
+
);
diff --git a/packages/twenty-front/src/testing/decorators/RecordTableDecorator.tsx b/packages/twenty-front/src/testing/decorators/RecordTableDecorator.tsx
index dc309c840a..71f8bb5acc 100644
--- a/packages/twenty-front/src/testing/decorators/RecordTableDecorator.tsx
+++ b/packages/twenty-front/src/testing/decorators/RecordTableDecorator.tsx
@@ -1,8 +1,8 @@
import { type Decorator } from '@storybook/react-vite';
import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState';
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
-import { getActionMenuIdFromRecordIndexId } from '@/action-menu/utils/getActionMenuIdFromRecordIndexId';
+import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
+import { getCommandMenuIdFromRecordIndexId } from '@/command-menu-item/utils/getCommandMenuIdFromRecordIndexId';
import { MAIN_CONTEXT_STORE_INSTANCE_ID } from '@/context-store/constants/MainContextStoreInstanceId';
import { contextStoreCurrentViewIdComponentState } from '@/context-store/states/contextStoreCurrentViewIdComponentState';
import { labelIdentifierFieldMetadataItemSelector } from '@/object-metadata/states/labelIdentifierFieldMetadataItemSelector';
@@ -191,7 +191,7 @@ const InternalTableContextProviders = ({
value={{
onCloseTableCell: () => {},
onOpenTableCell: () => {},
- onActionMenuDropdownOpened: () => {},
+ onCommandMenuDropdownOpened: () => {},
onMoveFocus: () => {},
onMoveHoverToCurrentCell: () => {},
}}
@@ -235,9 +235,9 @@ export const RecordTableDecorator: Decorator = (Story, context) => {
-
{
/>
-
+
diff --git a/packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper.tsx b/packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper.tsx
similarity index 86%
rename from packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper.tsx
rename to packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper.tsx
index 7bdcea9340..813f294eba 100644
--- a/packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndActionMenuWrapper.tsx
+++ b/packages/twenty-front/src/testing/jest/getJestMetadataAndApolloMocksAndCommandMenuWrapper.tsx
@@ -1,4 +1,4 @@
-import { ActionMenuComponentInstanceContext } from '@/action-menu/states/contexts/ActionMenuComponentInstanceContext';
+import { CommandMenuComponentInstanceContext } from '@/command-menu/states/contexts/CommandMenuComponentInstanceContext';
import { ContextStoreComponentInstanceContext } from '@/context-store/states/contexts/ContextStoreComponentInstanceContext';
import { type MockedResponse } from '@apollo/client/testing';
import { type ReactNode } from 'react';
@@ -12,7 +12,7 @@ import { JestRecordIndexContextProviderWrapper } from '~/testing/jest/JestRecord
import { getJestMetadataAndApolloMocksWrapper } from '~/testing/jest/getJestMetadataAndApolloMocksWrapper';
import { getMockObjectMetadataItemOrThrow } from '~/testing/utils/getMockObjectMetadataItemOrThrow';
-export type GetJestMetadataAndApolloMocksAndActionMenuWrapperProps = {
+export type GetJestMetadataAndApolloMocksAndCommandMenuWrapperProps = {
apolloMocks:
| readonly MockedResponse, Record>[]
| undefined;
@@ -20,7 +20,7 @@ export type GetJestMetadataAndApolloMocksAndActionMenuWrapperProps = {
componentInstanceId: string;
} & JestContextStoreSetterMocks;
-export const getJestMetadataAndApolloMocksAndActionMenuWrapper = ({
+export const getJestMetadataAndApolloMocksAndCommandMenuWrapper = ({
apolloMocks,
onInitializeJotaiStore,
contextStoreTargetedRecordsRule,
@@ -30,7 +30,7 @@ export const getJestMetadataAndApolloMocksAndActionMenuWrapper = ({
contextStoreCurrentObjectMetadataNameSingular,
contextStoreFilters,
componentInstanceId,
-}: GetJestMetadataAndApolloMocksAndActionMenuWrapperProps) => {
+}: GetJestMetadataAndApolloMocksAndCommandMenuWrapperProps) => {
const Wrapper = getJestMetadataAndApolloMocksWrapper({
apolloMocks,
onInitializeJotaiStore,
@@ -51,7 +51,7 @@ export const getJestMetadataAndApolloMocksAndActionMenuWrapper = ({
-
-
+
);
diff --git a/packages/twenty-sdk/src/front-component-renderer/remote/components/FrontComponentWorkerEffect.tsx b/packages/twenty-sdk/src/front-component-renderer/remote/components/FrontComponentWorkerEffect.tsx
index fbebbbe7ec..341baa0e95 100644
--- a/packages/twenty-sdk/src/front-component-renderer/remote/components/FrontComponentWorkerEffect.tsx
+++ b/packages/twenty-sdk/src/front-component-renderer/remote/components/FrontComponentWorkerEffect.tsx
@@ -1,18 +1,18 @@
import { ThreadWebWorker, release, retain } from '@quilted/threads';
import { RemoteReceiver } from '@remote-dom/core/receivers';
import { useEffect, useRef } from 'react';
-import { type ActionConfirmationModalResult } from '../../../sdk/front-component-api/globals/frontComponentHostCommunicationApi';
+import { type CommandConfirmationModalResult } from '../../../sdk/front-component-api/globals/frontComponentHostCommunicationApi';
import { type FrontComponentHostCommunicationApi } from '../../types/FrontComponentHostCommunicationApi';
import { type WorkerExports } from '../../types/WorkerExports';
import { createRemoteWorker } from '../worker/utils/createRemoteWorker';
-// Must match ACTION_MENU_CONFIRMATION_MODAL_RESULT_BROWSER_EVENT_NAME in twenty-front
-const ACTION_MENU_CONFIRMATION_MODAL_RESULT_BROWSER_EVENT_NAME =
- 'action-menu-confirmation-modal-result';
+// Must match COMMAND_MENU_ITEM_CONFIRMATION_MODAL_RESULT_BROWSER_EVENT_NAME in twenty-front
+const COMMAND_MENU_ITEM_CONFIRMATION_MODAL_RESULT_BROWSER_EVENT_NAME =
+ 'command-menu-item-confirmation-modal-result';
-type ActionMenuConfirmationModalResultBrowserEventDetail = {
+type CommandMenuItemConfirmationModalResultBrowserEventDetail = {
frontComponentId: string;
- confirmationResult: ActionConfirmationModalResult;
+ confirmationResult: CommandConfirmationModalResult;
};
type FrontComponentWorkerEffectProps = {
@@ -67,13 +67,14 @@ export const FrontComponentWorkerEffect = ({
exports: frontComponentHostCommunicationApi,
});
- const handleActionMenuConfirmationModalResultBrowserEvent = (
- event: CustomEvent,
+ const handleCommandMenuItemConfirmationModalResultBrowserEvent = (
+ event: CustomEvent,
) => {
- const actionMenuConfirmationModalResultBrowserEventDetail = event.detail;
+ const commandMenuItemConfirmationModalResultBrowserEventDetail =
+ event.detail;
if (
- actionMenuConfirmationModalResultBrowserEventDetail.frontComponentId !==
+ commandMenuItemConfirmationModalResultBrowserEventDetail.frontComponentId !==
frontComponentId
) {
return;
@@ -81,7 +82,7 @@ export const FrontComponentWorkerEffect = ({
thread.imports
.onConfirmationModalResult(
- actionMenuConfirmationModalResultBrowserEventDetail.confirmationResult,
+ commandMenuItemConfirmationModalResultBrowserEventDetail.confirmationResult,
)
.catch((error: Error) => {
setError(error);
@@ -89,8 +90,8 @@ export const FrontComponentWorkerEffect = ({
};
window.addEventListener(
- ACTION_MENU_CONFIRMATION_MODAL_RESULT_BROWSER_EVENT_NAME,
- handleActionMenuConfirmationModalResultBrowserEvent as EventListener,
+ COMMAND_MENU_ITEM_CONFIRMATION_MODAL_RESULT_BROWSER_EVENT_NAME,
+ handleCommandMenuItemConfirmationModalResultBrowserEvent as EventListener,
);
setThread(thread);
@@ -110,8 +111,8 @@ export const FrontComponentWorkerEffect = ({
return () => {
window.removeEventListener(
- ACTION_MENU_CONFIRMATION_MODAL_RESULT_BROWSER_EVENT_NAME,
- handleActionMenuConfirmationModalResultBrowserEvent as EventListener,
+ COMMAND_MENU_ITEM_CONFIRMATION_MODAL_RESULT_BROWSER_EVENT_NAME,
+ handleCommandMenuItemConfirmationModalResultBrowserEvent as EventListener,
);
setThread(null);
worker.terminate();
diff --git a/packages/twenty-sdk/src/front-component-renderer/remote/worker/remote-worker.ts b/packages/twenty-sdk/src/front-component-renderer/remote/worker/remote-worker.ts
index 63de3ad72a..59ffb7d092 100644
--- a/packages/twenty-sdk/src/front-component-renderer/remote/worker/remote-worker.ts
+++ b/packages/twenty-sdk/src/front-component-renderer/remote/worker/remote-worker.ts
@@ -25,9 +25,9 @@ import { type HostToWorkerRenderContext } from '../../types/HostToWorkerRenderCo
import { type WorkerExports } from '../../types/WorkerExports';
import { exposeGlobals } from '../utils/exposeGlobals';
import {
- createOpenActionConfirmationModalAdapter,
- handleActionConfirmationModalResult,
-} from './utils/createActionConfirmationModalBridge';
+ createOpenCommandConfirmationModalAdapter,
+ handleCommandConfirmationModalResult,
+} from './utils/createCommandConfirmationModalBridge';
import { setWorkerEnv } from './utils/setWorkerEnv';
installStylePropertyOnRemoteElements();
@@ -101,8 +101,8 @@ const initializeHostCommunicationApi: WorkerExports['initializeHostCommunication
hostApi.requestAccessTokenRefresh;
frontComponentHostCommunicationApi.openSidePanelPage =
hostApi.openSidePanelPage;
- frontComponentHostCommunicationApi.openActionConfirmationModal =
- createOpenActionConfirmationModalAdapter(hostApi);
+ frontComponentHostCommunicationApi.openCommandConfirmationModal =
+ createOpenCommandConfirmationModalAdapter(hostApi);
frontComponentHostCommunicationApi.unmountFrontComponent =
hostApi.unmountFrontComponent;
frontComponentHostCommunicationApi.enqueueSnackbar =
@@ -112,7 +112,7 @@ const initializeHostCommunicationApi: WorkerExports['initializeHostCommunication
const onConfirmationModalResult: WorkerExports['onConfirmationModalResult'] =
async (result) => {
- await handleActionConfirmationModalResult(result);
+ await handleCommandConfirmationModalResult(result);
};
const updateContext: WorkerExports['updateContext'] = async (
diff --git a/packages/twenty-sdk/src/front-component-renderer/remote/worker/utils/createActionConfirmationModalBridge.ts b/packages/twenty-sdk/src/front-component-renderer/remote/worker/utils/createActionConfirmationModalBridge.ts
deleted file mode 100644
index 9802a5a9b7..0000000000
--- a/packages/twenty-sdk/src/front-component-renderer/remote/worker/utils/createActionConfirmationModalBridge.ts
+++ /dev/null
@@ -1,65 +0,0 @@
-import {
- type ActionConfirmationModalResult,
- type OpenActionConfirmationModalFunction,
-} from '@/sdk/front-component-api/globals/frontComponentHostCommunicationApi';
-import { type FrontComponentHostCommunicationApi } from '../../../types/FrontComponentHostCommunicationApi';
-
-type ActionConfirmationModalPromiseCallbacks = {
- resolve: (result: ActionConfirmationModalResult) => void;
- reject: (error: Error) => void;
-};
-
-let pendingActionConfirmationModalPromiseCallbacks: ActionConfirmationModalPromiseCallbacks | null =
- null;
-
-const clearPendingActionConfirmationModalPromiseCallbacks = () => {
- pendingActionConfirmationModalPromiseCallbacks = null;
-};
-
-export const createOpenActionConfirmationModalAdapter = (
- hostApi: Pick<
- FrontComponentHostCommunicationApi,
- 'openActionConfirmationModal'
- >,
-): OpenActionConfirmationModalFunction => {
- return async (params) => {
- if (pendingActionConfirmationModalPromiseCallbacks !== null) {
- throw new Error(
- 'A confirmation modal is already pending for this front component',
- );
- }
-
- let rejectActionConfirmationModalPromise: (error: Error) => void = () => {};
-
- const actionConfirmationModalResultPromise =
- new Promise((resolve, reject) => {
- rejectActionConfirmationModalPromise = reject;
- pendingActionConfirmationModalPromiseCallbacks = { resolve, reject };
- });
-
- try {
- await hostApi.openActionConfirmationModal(params);
- } catch (error) {
- clearPendingActionConfirmationModalPromiseCallbacks();
-
- rejectActionConfirmationModalPromise(
- error instanceof Error ? error : new Error(String(error)),
- );
- }
-
- return actionConfirmationModalResultPromise;
- };
-};
-
-export const handleActionConfirmationModalResult = async (
- result: ActionConfirmationModalResult,
-) => {
- if (pendingActionConfirmationModalPromiseCallbacks === null) {
- return;
- }
-
- const currentActionConfirmationModalPromiseCallbacks =
- pendingActionConfirmationModalPromiseCallbacks;
- clearPendingActionConfirmationModalPromiseCallbacks();
- currentActionConfirmationModalPromiseCallbacks.resolve(result);
-};
diff --git a/packages/twenty-sdk/src/front-component-renderer/remote/worker/utils/createCommandConfirmationModalBridge.ts b/packages/twenty-sdk/src/front-component-renderer/remote/worker/utils/createCommandConfirmationModalBridge.ts
new file mode 100644
index 0000000000..1adbeb7a7e
--- /dev/null
+++ b/packages/twenty-sdk/src/front-component-renderer/remote/worker/utils/createCommandConfirmationModalBridge.ts
@@ -0,0 +1,67 @@
+import {
+ type CommandConfirmationModalResult,
+ type OpenCommandConfirmationModalFunction,
+} from '@/sdk/front-component-api/globals/frontComponentHostCommunicationApi';
+import { type FrontComponentHostCommunicationApi } from '../../../types/FrontComponentHostCommunicationApi';
+
+type CommandConfirmationModalPromiseCallbacks = {
+ resolve: (result: CommandConfirmationModalResult) => void;
+ reject: (error: Error) => void;
+};
+
+let pendingCommandConfirmationModalPromiseCallbacks: CommandConfirmationModalPromiseCallbacks | null =
+ null;
+
+const clearPendingCommandConfirmationModalPromiseCallbacks = () => {
+ pendingCommandConfirmationModalPromiseCallbacks = null;
+};
+
+export const createOpenCommandConfirmationModalAdapter = (
+ hostApi: Pick<
+ FrontComponentHostCommunicationApi,
+ 'openCommandConfirmationModal'
+ >,
+): OpenCommandConfirmationModalFunction => {
+ return async (params) => {
+ if (pendingCommandConfirmationModalPromiseCallbacks !== null) {
+ throw new Error(
+ 'A confirmation modal is already pending for this front component',
+ );
+ }
+
+ let rejectCommandConfirmationModalPromise: (
+ error: Error,
+ ) => void = () => {};
+
+ const commandConfirmationModalResultPromise =
+ new Promise((resolve, reject) => {
+ rejectCommandConfirmationModalPromise = reject;
+ pendingCommandConfirmationModalPromiseCallbacks = { resolve, reject };
+ });
+
+ try {
+ await hostApi.openCommandConfirmationModal(params);
+ } catch (error) {
+ clearPendingCommandConfirmationModalPromiseCallbacks();
+
+ rejectCommandConfirmationModalPromise(
+ error instanceof Error ? error : new Error(String(error)),
+ );
+ }
+
+ return commandConfirmationModalResultPromise;
+ };
+};
+
+export const handleCommandConfirmationModalResult = async (
+ result: CommandConfirmationModalResult,
+) => {
+ if (pendingCommandConfirmationModalPromiseCallbacks === null) {
+ return;
+ }
+
+ const currentCommandConfirmationModalPromiseCallbacks =
+ pendingCommandConfirmationModalPromiseCallbacks;
+ clearPendingCommandConfirmationModalPromiseCallbacks();
+ currentCommandConfirmationModalPromiseCallbacks.resolve(result);
+};
diff --git a/packages/twenty-sdk/src/front-component-renderer/types/FrontComponentHostCommunicationApi.ts b/packages/twenty-sdk/src/front-component-renderer/types/FrontComponentHostCommunicationApi.ts
index 8ec3b11ae4..a24027cb46 100644
--- a/packages/twenty-sdk/src/front-component-renderer/types/FrontComponentHostCommunicationApi.ts
+++ b/packages/twenty-sdk/src/front-component-renderer/types/FrontComponentHostCommunicationApi.ts
@@ -2,7 +2,7 @@ import {
type CloseSidePanelFunction,
type EnqueueSnackbarFunction,
type NavigateFunction,
- type OpenActionConfirmationModalHostFunction,
+ type OpenCommandConfirmationModalHostFunction,
type OpenSidePanelPageFunction,
type RequestAccessTokenRefreshFunction,
type UnmountFrontComponentFunction,
@@ -12,7 +12,7 @@ export type FrontComponentHostCommunicationApi = {
navigate: NavigateFunction;
requestAccessTokenRefresh: RequestAccessTokenRefreshFunction;
openSidePanelPage: OpenSidePanelPageFunction;
- openActionConfirmationModal: OpenActionConfirmationModalHostFunction;
+ openCommandConfirmationModal: OpenCommandConfirmationModalHostFunction;
unmountFrontComponent: UnmountFrontComponentFunction;
enqueueSnackbar: EnqueueSnackbarFunction;
closeSidePanel: CloseSidePanelFunction;
diff --git a/packages/twenty-sdk/src/sdk/action/index.ts b/packages/twenty-sdk/src/sdk/action/index.ts
deleted file mode 100644
index e026fd5c1e..0000000000
--- a/packages/twenty-sdk/src/sdk/action/index.ts
+++ /dev/null
@@ -1,8 +0,0 @@
-export { Action } from './Action';
-export type { ActionProps } from './Action';
-export { ActionLink } from './ActionLink';
-export type { ActionLinkProps } from './ActionLink';
-export { ActionOpenSidePanelPage } from './ActionOpenSidePanelPage';
-export type { ActionOpenSidePanelPageProps } from './ActionOpenSidePanelPage';
-export { ActionModal } from './ActionModal';
-export type { ActionModalProps } from './ActionModal';
diff --git a/packages/twenty-sdk/src/sdk/action/Action.tsx b/packages/twenty-sdk/src/sdk/command/Command.tsx
similarity index 76%
rename from packages/twenty-sdk/src/sdk/action/Action.tsx
rename to packages/twenty-sdk/src/sdk/command/Command.tsx
index 9e39e26536..beff14490e 100644
--- a/packages/twenty-sdk/src/sdk/action/Action.tsx
+++ b/packages/twenty-sdk/src/sdk/command/Command.tsx
@@ -2,16 +2,16 @@ import { useEffect, useState } from 'react';
import {
enqueueSnackbar,
- getFrontComponentActionErrorDedupeKey,
+ getFrontComponentCommandErrorDedupeKey,
unmountFrontComponent,
useFrontComponentId,
} from '../front-component-api';
-export type ActionProps = {
+export type CommandProps = {
execute: () => void | Promise;
};
-export const Action = ({ execute }: ActionProps) => {
+export const Command = ({ execute }: CommandProps) => {
const [hasExecuted, setHasExecuted] = useState(false);
const frontComponentId = useFrontComponentId();
@@ -29,10 +29,10 @@ export const Action = ({ execute }: ActionProps) => {
} catch (error) {
if (error instanceof Error) {
await enqueueSnackbar({
- message: 'Action failed',
+ message: 'Command failed',
detailedMessage: error.message,
variant: 'error',
- dedupeKey: getFrontComponentActionErrorDedupeKey(frontComponentId),
+ dedupeKey: getFrontComponentCommandErrorDedupeKey(frontComponentId),
});
}
} finally {
diff --git a/packages/twenty-sdk/src/sdk/action/ActionLink.tsx b/packages/twenty-sdk/src/sdk/command/CommandLink.tsx
similarity index 80%
rename from packages/twenty-sdk/src/sdk/action/ActionLink.tsx
rename to packages/twenty-sdk/src/sdk/command/CommandLink.tsx
index 5099274a58..8c25e45314 100644
--- a/packages/twenty-sdk/src/sdk/action/ActionLink.tsx
+++ b/packages/twenty-sdk/src/sdk/command/CommandLink.tsx
@@ -5,25 +5,25 @@ import { type AppPath } from 'twenty-shared/types';
import { type getAppPath } from 'twenty-shared/utils';
import {
enqueueSnackbar,
- getFrontComponentActionErrorDedupeKey,
+ getFrontComponentCommandErrorDedupeKey,
navigate,
unmountFrontComponent,
useFrontComponentId,
} from '../front-component-api';
-export type ActionLinkProps = {
+export type CommandLinkProps = {
to: T;
params?: Parameters>[1];
queryParams?: Record;
options?: NavigateOptions;
};
-export const ActionLink = ({
+export const CommandLink = ({
to,
params,
queryParams,
options,
-}: ActionLinkProps) => {
+}: CommandLinkProps) => {
const [hasExecuted, setHasExecuted] = useState(false);
const frontComponentId = useFrontComponentId();
@@ -41,10 +41,10 @@ export const ActionLink = ({
} catch (error) {
if (error instanceof Error) {
await enqueueSnackbar({
- message: 'Action failed',
+ message: 'Command failed',
detailedMessage: error.message,
variant: 'error',
- dedupeKey: getFrontComponentActionErrorDedupeKey(frontComponentId),
+ dedupeKey: getFrontComponentCommandErrorDedupeKey(frontComponentId),
});
}
} finally {
diff --git a/packages/twenty-sdk/src/sdk/action/ActionModal.tsx b/packages/twenty-sdk/src/sdk/command/CommandModal.tsx
similarity index 68%
rename from packages/twenty-sdk/src/sdk/action/ActionModal.tsx
rename to packages/twenty-sdk/src/sdk/command/CommandModal.tsx
index b298a90e4f..94f4423301 100644
--- a/packages/twenty-sdk/src/sdk/action/ActionModal.tsx
+++ b/packages/twenty-sdk/src/sdk/command/CommandModal.tsx
@@ -2,28 +2,28 @@ import { useEffect, useState } from 'react';
import {
enqueueSnackbar,
- getFrontComponentActionErrorDedupeKey,
- openActionConfirmationModal,
+ getFrontComponentCommandErrorDedupeKey,
+ openCommandConfirmationModal,
unmountFrontComponent,
useFrontComponentId,
- type ActionConfirmationModalAccent,
+ type CommandConfirmationModalAccent,
} from '../front-component-api';
-export type ActionModalProps = {
+export type CommandModalProps = {
title: string;
subtitle: string;
execute: () => void | Promise;
confirmButtonText?: string;
- confirmButtonAccent?: ActionConfirmationModalAccent;
+ confirmButtonAccent?: CommandConfirmationModalAccent;
};
-export const ActionModal = ({
+export const CommandModal = ({
title,
subtitle,
execute,
confirmButtonText,
confirmButtonAccent,
-}: ActionModalProps) => {
+}: CommandModalProps) => {
const [hasExecuted, setHasExecuted] = useState(false);
const frontComponentId = useFrontComponentId();
@@ -37,26 +37,25 @@ export const ActionModal = ({
const run = async () => {
try {
- const actionConfirmationModalResult = await openActionConfirmationModal(
- {
+ const commandConfirmationModalResult =
+ await openCommandConfirmationModal({
title,
subtitle,
confirmButtonText,
confirmButtonAccent,
- },
- );
+ });
- if (actionConfirmationModalResult === 'confirm') {
+ if (commandConfirmationModalResult === 'confirm') {
await execute();
}
} catch (error) {
const message = error instanceof Error ? error.message : String(error);
await enqueueSnackbar({
- message: 'Action failed',
+ message: 'Command failed',
detailedMessage: message,
variant: 'error',
- dedupeKey: getFrontComponentActionErrorDedupeKey(frontComponentId),
+ dedupeKey: getFrontComponentCommandErrorDedupeKey(frontComponentId),
});
} finally {
await unmountFrontComponent();
diff --git a/packages/twenty-sdk/src/sdk/action/ActionOpenSidePanelPage.tsx b/packages/twenty-sdk/src/sdk/command/CommandOpenSidePanelPage.tsx
similarity index 81%
rename from packages/twenty-sdk/src/sdk/action/ActionOpenSidePanelPage.tsx
rename to packages/twenty-sdk/src/sdk/command/CommandOpenSidePanelPage.tsx
index 0e47c15363..ae96c4b77b 100644
--- a/packages/twenty-sdk/src/sdk/action/ActionOpenSidePanelPage.tsx
+++ b/packages/twenty-sdk/src/sdk/command/CommandOpenSidePanelPage.tsx
@@ -1,6 +1,6 @@
import {
enqueueSnackbar,
- getFrontComponentActionErrorDedupeKey,
+ getFrontComponentCommandErrorDedupeKey,
openSidePanelPage,
unmountFrontComponent,
useFrontComponentId,
@@ -9,7 +9,7 @@ import { useEffect, useState } from 'react';
import { type SidePanelPages } from 'twenty-shared/types';
-export type ActionOpenSidePanelPageProps = {
+export type CommandOpenSidePanelPageProps = {
page: SidePanelPages;
pageTitle: string;
pageIcon: string;
@@ -17,13 +17,13 @@ export type ActionOpenSidePanelPageProps = {
shouldResetSearchState?: boolean;
};
-export const ActionOpenSidePanelPage = ({
+export const CommandOpenSidePanelPage = ({
page,
pageTitle,
pageIcon,
onClick,
shouldResetSearchState = false,
-}: ActionOpenSidePanelPageProps) => {
+}: CommandOpenSidePanelPageProps) => {
const [hasExecuted, setHasExecuted] = useState(false);
const frontComponentId = useFrontComponentId();
@@ -48,10 +48,10 @@ export const ActionOpenSidePanelPage = ({
} catch (error) {
if (error instanceof Error) {
await enqueueSnackbar({
- message: 'Action failed',
+ message: 'Command failed',
detailedMessage: error.message,
variant: 'error',
- dedupeKey: getFrontComponentActionErrorDedupeKey(frontComponentId),
+ dedupeKey: getFrontComponentCommandErrorDedupeKey(frontComponentId),
});
}
} finally {
diff --git a/packages/twenty-sdk/src/sdk/command/index.ts b/packages/twenty-sdk/src/sdk/command/index.ts
new file mode 100644
index 0000000000..1b9b3441e3
--- /dev/null
+++ b/packages/twenty-sdk/src/sdk/command/index.ts
@@ -0,0 +1,8 @@
+export { Command } from './Command';
+export type { CommandProps } from './Command';
+export { CommandLink } from './CommandLink';
+export type { CommandLinkProps } from './CommandLink';
+export { CommandOpenSidePanelPage } from './CommandOpenSidePanelPage';
+export type { CommandOpenSidePanelPageProps } from './CommandOpenSidePanelPage';
+export { CommandModal } from './CommandModal';
+export type { CommandModalProps } from './CommandModal';
diff --git a/packages/twenty-sdk/src/sdk/front-component-api/functions/openActionConfirmationModal.ts b/packages/twenty-sdk/src/sdk/front-component-api/functions/openActionConfirmationModal.ts
deleted file mode 100644
index 8e4b02c93f..0000000000
--- a/packages/twenty-sdk/src/sdk/front-component-api/functions/openActionConfirmationModal.ts
+++ /dev/null
@@ -1,18 +0,0 @@
-import { isDefined } from 'twenty-shared/utils';
-
-import {
- frontComponentHostCommunicationApi,
- type OpenActionConfirmationModalFunction,
-} from '../globals/frontComponentHostCommunicationApi';
-
-export const openActionConfirmationModal: OpenActionConfirmationModalFunction =
- (params) => {
- const openActionConfirmationModalFunction =
- frontComponentHostCommunicationApi.openActionConfirmationModal;
-
- if (!isDefined(openActionConfirmationModalFunction)) {
- throw new Error('openActionConfirmationModalFunction is not set');
- }
-
- return openActionConfirmationModalFunction(params);
- };
diff --git a/packages/twenty-sdk/src/sdk/front-component-api/functions/openCommandConfirmationModal.ts b/packages/twenty-sdk/src/sdk/front-component-api/functions/openCommandConfirmationModal.ts
new file mode 100644
index 0000000000..c48bf5ecce
--- /dev/null
+++ b/packages/twenty-sdk/src/sdk/front-component-api/functions/openCommandConfirmationModal.ts
@@ -0,0 +1,18 @@
+import { isDefined } from 'twenty-shared/utils';
+
+import {
+ frontComponentHostCommunicationApi,
+ type OpenCommandConfirmationModalFunction,
+} from '../globals/frontComponentHostCommunicationApi';
+
+export const openCommandConfirmationModal: OpenCommandConfirmationModalFunction =
+ (params) => {
+ const openCommandConfirmationModalFunction =
+ frontComponentHostCommunicationApi.openCommandConfirmationModal;
+
+ if (!isDefined(openCommandConfirmationModalFunction)) {
+ throw new Error('openCommandConfirmationModalFunction is not set');
+ }
+
+ return openCommandConfirmationModalFunction(params);
+ };
diff --git a/packages/twenty-sdk/src/sdk/front-component-api/globals/frontComponentHostCommunicationApi.ts b/packages/twenty-sdk/src/sdk/front-component-api/globals/frontComponentHostCommunicationApi.ts
index 72bada6bf2..2bfcaf93fe 100644
--- a/packages/twenty-sdk/src/sdk/front-component-api/globals/frontComponentHostCommunicationApi.ts
+++ b/packages/twenty-sdk/src/sdk/front-component-api/globals/frontComponentHostCommunicationApi.ts
@@ -20,16 +20,16 @@ export type OpenSidePanelPageFunction = (params: {
shouldResetSearchState?: boolean;
}) => Promise;
-export type ActionConfirmationModalResult = 'confirm' | 'cancel';
+export type CommandConfirmationModalResult = 'confirm' | 'cancel';
-export type ActionConfirmationModalAccent = 'default' | 'blue' | 'danger';
+export type CommandConfirmationModalAccent = 'default' | 'blue' | 'danger';
-export type OpenActionConfirmationModalFunction = (params: {
+export type OpenCommandConfirmationModalFunction = (params: {
title: string;
subtitle: string;
confirmButtonText?: string;
- confirmButtonAccent?: ActionConfirmationModalAccent;
-}) => Promise;
+ confirmButtonAccent?: CommandConfirmationModalAccent;
+}) => Promise;
export type UnmountFrontComponentFunction = () => Promise;
@@ -41,15 +41,15 @@ export type CloseSidePanelFunction = () => Promise;
export type RequestAccessTokenRefreshFunction = () => Promise;
-export type OpenActionConfirmationModalHostFunction = (
- params: Parameters[0],
+export type OpenCommandConfirmationModalHostFunction = (
+ params: Parameters[0],
) => Promise;
export type FrontComponentHostCommunicationApiStore = {
navigate?: NavigateFunction;
requestAccessTokenRefresh?: RequestAccessTokenRefreshFunction;
openSidePanelPage?: OpenSidePanelPageFunction;
- openActionConfirmationModal?: OpenActionConfirmationModalFunction;
+ openCommandConfirmationModal?: OpenCommandConfirmationModalFunction;
unmountFrontComponent?: UnmountFrontComponentFunction;
enqueueSnackbar?: EnqueueSnackbarFunction;
closeSidePanel?: CloseSidePanelFunction;
diff --git a/packages/twenty-sdk/src/sdk/front-component-api/index.ts b/packages/twenty-sdk/src/sdk/front-component-api/index.ts
index 1ba878e427..b49530ec48 100644
--- a/packages/twenty-sdk/src/sdk/front-component-api/index.ts
+++ b/packages/twenty-sdk/src/sdk/front-component-api/index.ts
@@ -19,7 +19,7 @@ export { setFrontComponentExecutionContext } from './context/frontComponentConte
export { closeSidePanel } from './functions/closeSidePanel';
export { enqueueSnackbar } from './functions/enqueueSnackbar';
export { navigate } from './functions/navigate';
-export { openActionConfirmationModal } from './functions/openActionConfirmationModal';
+export { openCommandConfirmationModal } from './functions/openCommandConfirmationModal';
export { openSidePanelPage } from './functions/openSidePanelPage';
export { unmountFrontComponent } from './functions/unmountFrontComponent';
export { useFrontComponentExecutionContext } from './hooks/useFrontComponentExecutionContext';
@@ -27,10 +27,10 @@ export { useFrontComponentId } from './hooks/useFrontComponentId';
export { useRecordId } from './hooks/useRecordId';
export { useUserId } from './hooks/useUserId';
export type { FrontComponentExecutionContext } from './types/FrontComponentExecutionContext';
-export { getFrontComponentActionErrorDedupeKey } from './utils/getFrontComponentActionErrorDedupeKey';
+export { getFrontComponentCommandErrorDedupeKey } from './utils/getFrontComponentCommandErrorDedupeKey';
export type {
- ActionConfirmationModalAccent,
- ActionConfirmationModalResult,
+ CommandConfirmationModalAccent,
+ CommandConfirmationModalResult,
} from './globals/frontComponentHostCommunicationApi';
export { ALLOWED_HTML_ELEMENTS } from './constants/AllowedHtmlElements';
diff --git a/packages/twenty-sdk/src/sdk/front-component-api/utils/getFrontComponentActionErrorDedupeKey.ts b/packages/twenty-sdk/src/sdk/front-component-api/utils/getFrontComponentActionErrorDedupeKey.ts
deleted file mode 100644
index 63923f0e7e..0000000000
--- a/packages/twenty-sdk/src/sdk/front-component-api/utils/getFrontComponentActionErrorDedupeKey.ts
+++ /dev/null
@@ -1,3 +0,0 @@
-export const getFrontComponentActionErrorDedupeKey = (
- frontComponentId: string,
-): string => `${frontComponentId}-action-error`;
diff --git a/packages/twenty-sdk/src/sdk/front-component-api/utils/getFrontComponentCommandErrorDedupeKey.ts b/packages/twenty-sdk/src/sdk/front-component-api/utils/getFrontComponentCommandErrorDedupeKey.ts
new file mode 100644
index 0000000000..4b68a2a150
--- /dev/null
+++ b/packages/twenty-sdk/src/sdk/front-component-api/utils/getFrontComponentCommandErrorDedupeKey.ts
@@ -0,0 +1,3 @@
+export const getFrontComponentCommandErrorDedupeKey = (
+ frontComponentId: string,
+): string => `${frontComponentId}-command-error`;
diff --git a/packages/twenty-sdk/src/sdk/index.ts b/packages/twenty-sdk/src/sdk/index.ts
index 2f841cc466..5f5f341d89 100644
--- a/packages/twenty-sdk/src/sdk/index.ts
+++ b/packages/twenty-sdk/src/sdk/index.ts
@@ -74,19 +74,19 @@ export { defineView } from './views/define-view';
export type { ViewConfig } from './views/view-config';
export { ViewKey } from './views/view-key';
-// Action components for front components
+// Command components for front components
export {
- Action,
- ActionLink,
- ActionModal,
- ActionOpenSidePanelPage,
-} from './action';
+ Command,
+ CommandLink,
+ CommandModal,
+ CommandOpenSidePanelPage,
+} from './command';
export type {
- ActionLinkProps,
- ActionModalProps,
- ActionOpenSidePanelPageProps,
- ActionProps,
-} from './action';
+ CommandLinkProps,
+ CommandModalProps,
+ CommandOpenSidePanelPageProps,
+ CommandProps,
+} from './command';
// Conditional availability typed variables for command menu items
export {
@@ -111,9 +111,9 @@ export {
export {
closeSidePanel,
enqueueSnackbar,
- getFrontComponentActionErrorDedupeKey,
+ getFrontComponentCommandErrorDedupeKey,
navigate,
- openActionConfirmationModal,
+ openCommandConfirmationModal,
openSidePanelPage,
unmountFrontComponent,
useFrontComponentExecutionContext,
@@ -122,8 +122,8 @@ export {
useUserId,
} from './front-component-api';
export type {
- ActionConfirmationModalAccent,
- ActionConfirmationModalResult,
+ CommandConfirmationModalAccent,
+ CommandConfirmationModalResult,
FrontComponentExecutionContext,
} from './front-component-api';
diff --git a/packages/twenty-shared/src/types/ActionViewType.ts b/packages/twenty-shared/src/types/CommandMenuItemViewType.ts
similarity index 87%
rename from packages/twenty-shared/src/types/ActionViewType.ts
rename to packages/twenty-shared/src/types/CommandMenuItemViewType.ts
index 19fd1d2d22..ec255f560e 100644
--- a/packages/twenty-shared/src/types/ActionViewType.ts
+++ b/packages/twenty-shared/src/types/CommandMenuItemViewType.ts
@@ -1,4 +1,4 @@
-export enum ActionViewType {
+export enum CommandMenuItemViewType {
GLOBAL = 'GLOBAL',
INDEX_PAGE_BULK_SELECTION = 'INDEX_PAGE_BULK_SELECTION',
INDEX_PAGE_SINGLE_RECORD_SELECTION = 'INDEX_PAGE_SINGLE_RECORD_SELECTION',
diff --git a/packages/twenty-shared/src/types/index.ts b/packages/twenty-shared/src/types/index.ts
index d5c9cbd803..aec3a7397b 100644
--- a/packages/twenty-shared/src/types/index.ts
+++ b/packages/twenty-shared/src/types/index.ts
@@ -7,7 +7,6 @@
* |___/
*/
-export { ActionViewType } from './ActionViewType';
export type { AllowedAddressSubField } from './AddressFieldsType';
export { ALLOWED_ADDRESS_SUBFIELDS } from './AddressFieldsType';
export { AggregateOperations } from './AggregateOperations';
@@ -16,6 +15,7 @@ export { AppPath } from './AppPath';
export type { Arrayable } from './Arrayable';
export type { ArraySortDirection } from './ArraySortDirection';
export type { CommandMenuContextApi } from './CommandMenuContextApi';
+export { CommandMenuItemViewType } from './CommandMenuItemViewType';
export type { ActorMetadata } from './composite-types/actor.composite-type';
export {
FieldActorSource,