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>
This commit is contained in:
+23
-9
@@ -97,11 +97,19 @@ export class CommandMenuItemService {
|
||||
input: CreateCommandMenuItemInput,
|
||||
workspaceId: string,
|
||||
): Promise<CommandMenuItemDTO> {
|
||||
const { flatObjectMetadataMaps, flatFrontComponentMaps } =
|
||||
const {
|
||||
flatObjectMetadataMaps,
|
||||
flatFrontComponentMaps,
|
||||
flatPageLayoutMaps,
|
||||
} =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatObjectMetadataMaps', 'flatFrontComponentMaps'],
|
||||
flatMapsKeys: [
|
||||
'flatObjectMetadataMaps',
|
||||
'flatFrontComponentMaps',
|
||||
'flatPageLayoutMaps',
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
@@ -117,6 +125,7 @@ export class CommandMenuItemService {
|
||||
flatApplication: workspaceCustomFlatApplication,
|
||||
flatObjectMetadataMaps,
|
||||
flatFrontComponentMaps,
|
||||
flatPageLayoutMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
@@ -171,19 +180,24 @@ export class CommandMenuItemService {
|
||||
const {
|
||||
flatCommandMenuItemMaps: existingFlatCommandMenuItemMaps,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
} =
|
||||
await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: ['flatCommandMenuItemMaps', 'flatObjectMetadataMaps'],
|
||||
},
|
||||
);
|
||||
flatPageLayoutMaps: existingFlatPageLayoutMaps,
|
||||
} = await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps(
|
||||
{
|
||||
workspaceId,
|
||||
flatMapsKeys: [
|
||||
'flatCommandMenuItemMaps',
|
||||
'flatObjectMetadataMaps',
|
||||
'flatPageLayoutMaps',
|
||||
],
|
||||
},
|
||||
);
|
||||
|
||||
const flatCommandMenuItemToUpdate =
|
||||
fromUpdateCommandMenuItemInputToFlatCommandMenuItemToUpdateOrThrow({
|
||||
flatCommandMenuItemMaps: existingFlatCommandMenuItemMaps,
|
||||
updateCommandMenuItemInput: input,
|
||||
flatObjectMetadataMaps: existingFlatObjectMetadataMaps,
|
||||
flatPageLayoutMaps: existingFlatPageLayoutMaps,
|
||||
});
|
||||
|
||||
const validateAndBuildResult =
|
||||
|
||||
+5
@@ -91,6 +91,11 @@ export class CommandMenuItemDTO {
|
||||
@Field(() => UUIDScalarType, { nullable: true })
|
||||
availabilityObjectMetadataId?: string;
|
||||
|
||||
@IsUUID()
|
||||
@IsOptional()
|
||||
@Field(() => UUIDScalarType, { nullable: true })
|
||||
pageLayoutId?: string;
|
||||
|
||||
@HideField()
|
||||
workspaceId: string;
|
||||
|
||||
|
||||
+5
@@ -83,4 +83,9 @@ export class CreateCommandMenuItemInput {
|
||||
@IsOptional()
|
||||
@Field(() => GraphQLJSON, { nullable: true })
|
||||
payload?: CommandMenuItemPayload;
|
||||
|
||||
@IsUUID()
|
||||
@IsOptional()
|
||||
@Field(() => UUIDScalarType, { nullable: true })
|
||||
pageLayoutId?: string;
|
||||
}
|
||||
|
||||
+5
@@ -65,4 +65,9 @@ export class UpdateCommandMenuItemInput {
|
||||
@IsOptional()
|
||||
@Field(() => [String], { nullable: true })
|
||||
hotKeys?: string[];
|
||||
|
||||
@IsUUID()
|
||||
@IsOptional()
|
||||
@Field(() => UUIDScalarType, { nullable: true })
|
||||
pageLayoutId?: string;
|
||||
}
|
||||
|
||||
+15
@@ -16,6 +16,7 @@ import { CommandMenuItemAvailabilityType } from 'src/engine/metadata-modules/com
|
||||
import { EngineComponentKey } from 'src/engine/metadata-modules/command-menu-item/enums/engine-component-key.enum';
|
||||
import { FrontComponentEntity } from 'src/engine/metadata-modules/front-component/entities/front-component.entity';
|
||||
import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity';
|
||||
import { PageLayoutEntity } from 'src/engine/metadata-modules/page-layout/entities/page-layout.entity';
|
||||
import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-entity.interface';
|
||||
|
||||
@Entity({ name: 'commandMenuItem', schema: 'core' })
|
||||
@@ -30,6 +31,10 @@ import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-enti
|
||||
@Index('IDX_COMMAND_MENU_ITEM_AVAILABILITY_OBJECT_METADATA_ID', [
|
||||
'availabilityObjectMetadataId',
|
||||
])
|
||||
@Index('IDX_COMMAND_MENU_ITEM_PAGE_LAYOUT_ID_WORKSPACE_ID', [
|
||||
'pageLayoutId',
|
||||
'workspaceId',
|
||||
])
|
||||
@Check(
|
||||
'CHK_CMD_MENU_ITEM_ENGINE_KEY_COHERENCE',
|
||||
`("engineComponentKey" = 'TRIGGER_WORKFLOW_VERSION' AND "workflowVersionId" IS NOT NULL AND "frontComponentId" IS NULL AND "payload" IS NULL) OR ("engineComponentKey" = 'FRONT_COMPONENT_RENDERER' AND "frontComponentId" IS NOT NULL AND "workflowVersionId" IS NULL AND "payload" IS NULL) OR ("engineComponentKey" = 'NAVIGATION' AND "payload" IS NOT NULL AND "workflowVersionId" IS NULL AND "frontComponentId" IS NULL) OR ("engineComponentKey" NOT IN ('TRIGGER_WORKFLOW_VERSION', 'FRONT_COMPONENT_RENDERER', 'NAVIGATION') AND "workflowVersionId" IS NULL AND "frontComponentId" IS NULL AND "payload" IS NULL)`,
|
||||
@@ -99,6 +104,16 @@ export class CommandMenuItemEntity
|
||||
@JoinColumn({ name: 'availabilityObjectMetadataId' })
|
||||
availabilityObjectMetadata: Relation<ObjectMetadataEntity> | null;
|
||||
|
||||
@Column({ nullable: true, type: 'uuid' })
|
||||
pageLayoutId: string | null;
|
||||
|
||||
@ManyToOne(() => PageLayoutEntity, {
|
||||
onDelete: 'CASCADE',
|
||||
nullable: true,
|
||||
})
|
||||
@JoinColumn({ name: 'pageLayoutId' })
|
||||
pageLayout: Relation<PageLayoutEntity> | null;
|
||||
|
||||
@CreateDateColumn({ type: 'timestamptz' })
|
||||
createdAt: Date;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user