Files
twenty/packages/twenty-server/src/engine/metadata-modules/flat-command-menu-item/utils/from-command-menu-item-entity-to-flat-command-menu-item.util.ts
T
2b5b8a8b13 Link command menu items to specific page layout (#19706)
- Add a `pageLayoutId` foreign key to `CommandMenuItem`, allowing
command menu items to be scoped to a specific page layout instead of
being globally available
- Filter command menu items by the current page layout on the frontend.
Items with a `pageLayoutId` only appear when viewing that layout, while
items without one remain globally visible
- Create an effect to track the current page layout ID
- Include a seed example: a "Show Notification" command pinned to the
Star history standalone page layout

---------

Co-authored-by: Charles Bochet <charles@twenty.com>
2026-04-16 12:07:36 +00:00

106 lines
4.2 KiB
TypeScript

import { isDefined } from 'twenty-shared/utils';
import { type FlatCommandMenuItem } from 'src/engine/metadata-modules/flat-command-menu-item/types/flat-command-menu-item.type';
import {
FlatEntityMapsException,
FlatEntityMapsExceptionCode,
} from 'src/engine/metadata-modules/flat-entity/exceptions/flat-entity-maps.exception';
import { type FromEntityToFlatEntityArgs } from 'src/engine/workspace-cache/types/from-entity-to-flat-entity-args.type';
export const fromCommandMenuItemEntityToFlatCommandMenuItem = ({
entity: commandMenuItemEntity,
applicationIdToUniversalIdentifierMap,
objectMetadataIdToUniversalIdentifierMap,
frontComponentIdToUniversalIdentifierMap,
pageLayoutIdToUniversalIdentifierMap,
}: FromEntityToFlatEntityArgs<'commandMenuItem'>): FlatCommandMenuItem => {
const applicationUniversalIdentifier =
applicationIdToUniversalIdentifierMap.get(
commandMenuItemEntity.applicationId,
);
if (!isDefined(applicationUniversalIdentifier)) {
throw new FlatEntityMapsException(
`Application with id ${commandMenuItemEntity.applicationId} not found for commandMenuItem ${commandMenuItemEntity.id}`,
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
);
}
let availabilityObjectMetadataUniversalIdentifier: string | null = null;
if (isDefined(commandMenuItemEntity.availabilityObjectMetadataId)) {
availabilityObjectMetadataUniversalIdentifier =
objectMetadataIdToUniversalIdentifierMap.get(
commandMenuItemEntity.availabilityObjectMetadataId,
) ?? null;
if (!isDefined(availabilityObjectMetadataUniversalIdentifier)) {
throw new FlatEntityMapsException(
`ObjectMetadata with id ${commandMenuItemEntity.availabilityObjectMetadataId} not found for commandMenuItem ${commandMenuItemEntity.id}`,
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
);
}
}
let frontComponentUniversalIdentifier: string | null = null;
if (isDefined(commandMenuItemEntity.frontComponentId)) {
frontComponentUniversalIdentifier =
frontComponentIdToUniversalIdentifierMap.get(
commandMenuItemEntity.frontComponentId,
) ?? null;
if (!isDefined(frontComponentUniversalIdentifier)) {
throw new FlatEntityMapsException(
`FrontComponent with id ${commandMenuItemEntity.frontComponentId} not found for commandMenuItem ${commandMenuItemEntity.id}`,
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
);
}
}
let pageLayoutUniversalIdentifier: string | null = null;
if (isDefined(commandMenuItemEntity.pageLayoutId)) {
pageLayoutUniversalIdentifier =
pageLayoutIdToUniversalIdentifierMap.get(
commandMenuItemEntity.pageLayoutId,
) ?? null;
if (!isDefined(pageLayoutUniversalIdentifier)) {
throw new FlatEntityMapsException(
`PageLayout with id ${commandMenuItemEntity.pageLayoutId} not found for commandMenuItem ${commandMenuItemEntity.id}`,
FlatEntityMapsExceptionCode.ENTITY_NOT_FOUND,
);
}
}
return {
id: commandMenuItemEntity.id,
workflowVersionId: commandMenuItemEntity.workflowVersionId,
frontComponentId: commandMenuItemEntity.frontComponentId,
engineComponentKey: commandMenuItemEntity.engineComponentKey,
label: commandMenuItemEntity.label,
icon: commandMenuItemEntity.icon,
shortLabel: commandMenuItemEntity.shortLabel,
position: commandMenuItemEntity.position,
isPinned: commandMenuItemEntity.isPinned,
payload: commandMenuItemEntity.payload,
hotKeys: commandMenuItemEntity.hotKeys,
availabilityType: commandMenuItemEntity.availabilityType,
availabilityObjectMetadataId:
commandMenuItemEntity.availabilityObjectMetadataId,
workspaceId: commandMenuItemEntity.workspaceId,
universalIdentifier: commandMenuItemEntity.universalIdentifier,
applicationId: commandMenuItemEntity.applicationId,
createdAt: commandMenuItemEntity.createdAt.toISOString(),
updatedAt: commandMenuItemEntity.updatedAt.toISOString(),
applicationUniversalIdentifier,
conditionalAvailabilityExpression:
commandMenuItemEntity.conditionalAvailabilityExpression,
availabilityObjectMetadataUniversalIdentifier,
frontComponentUniversalIdentifier,
pageLayoutId: commandMenuItemEntity.pageLayoutId,
pageLayoutUniversalIdentifier,
};
};