Refactor: Unify command menu item execution (#18908)

- Makes engineComponentKey non-nullable on CommandMenuItem. Adds two new
engine component keys: TRIGGER_WORKFLOW_VERSION and
FRONT_COMPONENT_RENDERER to cover the former standalone cases.
- Unifies the previously separated engine, front component and workflow
runners into a single `CommandRunner` component with a unified
`useMountCommand` hook that handles all command types.
This commit is contained in:
Raphaël Bosi
2026-03-24 16:59:52 +01:00
committed by GitHub
parent 27c0ca975f
commit 49afe5dbc4
103 changed files with 1296 additions and 1131 deletions
@@ -1,7 +1,5 @@
import { EngineCommandMenuItem } from '@/command-menu-item/display/components/EngineCommandMenuItem';
import { FrontComponentCommandMenuItem } from '@/command-menu-item/display/components/FrontComponentCommandMenuItem';
import { HeadlessFrontComponentCommandMenuItem } from '@/command-menu-item/display/components/HeadlessFrontComponentCommandMenuItem';
import { WorkflowCommandMenuItem } from '@/command-menu-item/display/components/WorkflowCommandMenuItem';
import { HeadlessCommandMenuItem } from '@/command-menu-item/display/components/HeadlessCommandMenuItem';
import { CommandMenuItemScope } from '@/command-menu-item/types/CommandMenuItemScope';
import { CommandMenuItemType } from '@/command-menu-item/types/CommandMenuItemType';
import { contextStoreIsPageInEditModeComponentState } from '@/context-store/states/contextStoreIsPageInEditModeComponentState';
@@ -19,6 +17,7 @@ import { useIcons } from 'twenty-ui/display';
import {
CommandMenuItemAvailabilityType,
type CommandMenuItemFieldsFragment,
EngineComponentKey,
} from '~/generated-metadata/graphql';
const resolveScope = (
@@ -36,16 +35,15 @@ const resolveType = (
if (item.availabilityType === CommandMenuItemAvailabilityType.FALLBACK) {
return CommandMenuItemType.Fallback;
}
if (isDefined(item.engineComponentKey)) {
return CommandMenuItemType.Standard;
switch (item.engineComponentKey) {
case EngineComponentKey.FRONT_COMPONENT_RENDERER:
return CommandMenuItemType.FrontComponent;
case EngineComponentKey.TRIGGER_WORKFLOW_VERSION:
return CommandMenuItemType.WorkflowRun;
default:
return CommandMenuItemType.Standard;
}
if (isDefined(item.frontComponentId)) {
return CommandMenuItemType.FrontComponent;
}
if (isDefined(item.workflowVersionId)) {
return CommandMenuItemType.WorkflowRun;
}
return CommandMenuItemType.Standard;
};
// TODO: Remove this hook once we finish refactoring and we use
@@ -101,33 +99,22 @@ export const useConvertBackendItemToCommandMenuItemConfig = () => {
context: commandMenuContextApi,
});
const component = isDefined(item.engineComponentKey) ? (
<EngineCommandMenuItem
commandMenuItemId={item.id}
engineComponentKey={item.engineComponentKey}
/>
) : isDefined(item.frontComponentId) ? (
item.frontComponent?.isHeadless === true ? (
<HeadlessFrontComponentCommandMenuItem
frontComponentId={item.frontComponentId}
commandMenuItemId={item.id}
/>
) : (
<FrontComponentCommandMenuItem
frontComponentId={item.frontComponentId}
/>
)
) : isDefined(item.workflowVersionId) ? (
<WorkflowCommandMenuItem
workflowVersionId={item.workflowVersionId}
availabilityType={item.availabilityType}
availabilityObjectMetadataId={item.availabilityObjectMetadataId}
/>
) : null;
const component = (() => {
if (
item.engineComponentKey ===
EngineComponentKey.FRONT_COMPONENT_RENDERER &&
isDefined(item.frontComponentId) &&
item.frontComponent?.isHeadless !== true
) {
return (
<FrontComponentCommandMenuItem
frontComponentId={item.frontComponentId}
/>
);
}
if (!isDefined(component)) {
return;
}
return <HeadlessCommandMenuItem item={item} />;
})();
return {
type: resolveType(item),