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:
@@ -2651,6 +2651,7 @@ type CommandMenuItem {
|
||||
hotKeys: [String!]
|
||||
conditionalAvailabilityExpression: String
|
||||
availabilityObjectMetadataId: UUID
|
||||
pageLayoutId: UUID
|
||||
applicationId: UUID
|
||||
createdAt: DateTime!
|
||||
updatedAt: DateTime!
|
||||
@@ -4183,6 +4184,7 @@ input CreateCommandMenuItemInput {
|
||||
conditionalAvailabilityExpression: String
|
||||
availabilityObjectMetadataId: UUID
|
||||
payload: JSON
|
||||
pageLayoutId: UUID
|
||||
}
|
||||
|
||||
input UpdateCommandMenuItemInput {
|
||||
@@ -4196,6 +4198,7 @@ input UpdateCommandMenuItemInput {
|
||||
availabilityObjectMetadataId: UUID
|
||||
engineComponentKey: EngineComponentKey
|
||||
hotKeys: [String!]
|
||||
pageLayoutId: UUID
|
||||
}
|
||||
|
||||
input CreateFrontComponentInput {
|
||||
|
||||
@@ -2368,6 +2368,7 @@ export interface CommandMenuItem {
|
||||
hotKeys?: Scalars['String'][]
|
||||
conditionalAvailabilityExpression?: Scalars['String']
|
||||
availabilityObjectMetadataId?: Scalars['UUID']
|
||||
pageLayoutId?: Scalars['UUID']
|
||||
applicationId?: Scalars['UUID']
|
||||
createdAt: Scalars['DateTime']
|
||||
updatedAt: Scalars['DateTime']
|
||||
@@ -5706,6 +5707,7 @@ export interface CommandMenuItemGenqlSelection{
|
||||
hotKeys?: boolean | number
|
||||
conditionalAvailabilityExpression?: boolean | number
|
||||
availabilityObjectMetadataId?: boolean | number
|
||||
pageLayoutId?: boolean | number
|
||||
applicationId?: boolean | number
|
||||
createdAt?: boolean | number
|
||||
updatedAt?: boolean | number
|
||||
@@ -6742,9 +6744,9 @@ update: UpdateLogicFunctionFromSourceInputUpdates}
|
||||
|
||||
export interface UpdateLogicFunctionFromSourceInputUpdates {name?: (Scalars['String'] | null),description?: (Scalars['String'] | null),timeoutSeconds?: (Scalars['Float'] | null),sourceHandlerCode?: (Scalars['String'] | null),toolInputSchema?: (Scalars['JSON'] | null),handlerName?: (Scalars['String'] | null),sourceHandlerPath?: (Scalars['String'] | null),isTool?: (Scalars['Boolean'] | null),cronTriggerSettings?: (Scalars['JSON'] | null),databaseEventTriggerSettings?: (Scalars['JSON'] | null),httpRouteTriggerSettings?: (Scalars['JSON'] | null)}
|
||||
|
||||
export interface CreateCommandMenuItemInput {workflowVersionId?: (Scalars['UUID'] | null),frontComponentId?: (Scalars['UUID'] | null),engineComponentKey: EngineComponentKey,label: Scalars['String'],icon?: (Scalars['String'] | null),shortLabel?: (Scalars['String'] | null),position?: (Scalars['Float'] | null),isPinned?: (Scalars['Boolean'] | null),availabilityType?: (CommandMenuItemAvailabilityType | null),hotKeys?: (Scalars['String'][] | null),conditionalAvailabilityExpression?: (Scalars['String'] | null),availabilityObjectMetadataId?: (Scalars['UUID'] | null),payload?: (Scalars['JSON'] | null)}
|
||||
export interface CreateCommandMenuItemInput {workflowVersionId?: (Scalars['UUID'] | null),frontComponentId?: (Scalars['UUID'] | null),engineComponentKey: EngineComponentKey,label: Scalars['String'],icon?: (Scalars['String'] | null),shortLabel?: (Scalars['String'] | null),position?: (Scalars['Float'] | null),isPinned?: (Scalars['Boolean'] | null),availabilityType?: (CommandMenuItemAvailabilityType | null),hotKeys?: (Scalars['String'][] | null),conditionalAvailabilityExpression?: (Scalars['String'] | null),availabilityObjectMetadataId?: (Scalars['UUID'] | null),payload?: (Scalars['JSON'] | null),pageLayoutId?: (Scalars['UUID'] | null)}
|
||||
|
||||
export interface UpdateCommandMenuItemInput {id: Scalars['UUID'],label?: (Scalars['String'] | null),icon?: (Scalars['String'] | null),shortLabel?: (Scalars['String'] | null),position?: (Scalars['Float'] | null),isPinned?: (Scalars['Boolean'] | null),availabilityType?: (CommandMenuItemAvailabilityType | null),availabilityObjectMetadataId?: (Scalars['UUID'] | null),engineComponentKey?: (EngineComponentKey | null),hotKeys?: (Scalars['String'][] | null)}
|
||||
export interface UpdateCommandMenuItemInput {id: Scalars['UUID'],label?: (Scalars['String'] | null),icon?: (Scalars['String'] | null),shortLabel?: (Scalars['String'] | null),position?: (Scalars['Float'] | null),isPinned?: (Scalars['Boolean'] | null),availabilityType?: (CommandMenuItemAvailabilityType | null),availabilityObjectMetadataId?: (Scalars['UUID'] | null),engineComponentKey?: (EngineComponentKey | null),hotKeys?: (Scalars['String'][] | null),pageLayoutId?: (Scalars['UUID'] | null)}
|
||||
|
||||
export interface CreateFrontComponentInput {id?: (Scalars['UUID'] | null),name: Scalars['String'],description?: (Scalars['String'] | null),sourceComponentPath: Scalars['String'],builtComponentPath: Scalars['String'],componentName: Scalars['String'],builtComponentChecksum: Scalars['String']}
|
||||
|
||||
|
||||
@@ -5334,6 +5334,9 @@ export default {
|
||||
"availabilityObjectMetadataId": [
|
||||
3
|
||||
],
|
||||
"pageLayoutId": [
|
||||
3
|
||||
],
|
||||
"applicationId": [
|
||||
3
|
||||
],
|
||||
@@ -10666,6 +10669,9 @@ export default {
|
||||
"payload": [
|
||||
15
|
||||
],
|
||||
"pageLayoutId": [
|
||||
3
|
||||
],
|
||||
"__typename": [
|
||||
1
|
||||
]
|
||||
@@ -10701,6 +10707,9 @@ export default {
|
||||
"hotKeys": [
|
||||
1
|
||||
],
|
||||
"pageLayoutId": [
|
||||
3
|
||||
],
|
||||
"__typename": [
|
||||
1
|
||||
]
|
||||
|
||||
File diff suppressed because one or more lines are too long
@@ -32,6 +32,7 @@ import { useResetFocusStackToFocusItem } from '@/ui/utilities/focus/hooks/useRes
|
||||
import { FocusComponentType } from '@/ui/utilities/focus/types/FocusComponentType';
|
||||
import { useAtomComponentStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomComponentStateValue';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { currentPageLayoutIdState } from '@/page-layout/states/currentPageLayoutIdState';
|
||||
import { useStore } from 'jotai';
|
||||
import { useCallback, useEffect, useState } from 'react';
|
||||
import {
|
||||
@@ -44,6 +45,7 @@ import { AppBasePath, AppPath, SidePanelPages } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { AnalyticsType } from '~/generated-metadata/graphql';
|
||||
import { usePageChangeEffectNavigateLocation } from '~/hooks/usePageChangeEffectNavigateLocation';
|
||||
import { getPageLayoutIdForLocation } from '~/modules/app/utils/getPageLayoutIdForLocation';
|
||||
import { useInitializeQueryParamState } from '~/modules/app/hooks/useInitializeQueryParamState';
|
||||
import { isMatchingLocation } from '~/utils/isMatchingLocation';
|
||||
import { getPageTitleFromPath } from '~/utils/title-utils';
|
||||
@@ -146,10 +148,15 @@ export const PageChangeEffect = () => {
|
||||
if (!previousLocation || previousLocation !== location.pathname) {
|
||||
setPreviousLocation(location.pathname);
|
||||
executeTasksOnAnyLocationChange();
|
||||
} else {
|
||||
return;
|
||||
|
||||
const newPageLayoutId = getPageLayoutIdForLocation({
|
||||
location,
|
||||
store,
|
||||
});
|
||||
|
||||
store.set(currentPageLayoutIdState.atom, newPageLayoutId);
|
||||
}
|
||||
}, [location, previousLocation, executeTasksOnAnyLocationChange]);
|
||||
}, [location, previousLocation, executeTasksOnAnyLocationChange, store]);
|
||||
|
||||
useEffect(() => {
|
||||
initializeQueryParamState();
|
||||
|
||||
@@ -0,0 +1,59 @@
|
||||
import { type getDefaultStore } from 'jotai';
|
||||
import { type Location, matchPath } from 'react-router-dom';
|
||||
import { AppPath, CoreObjectNameSingular } from 'twenty-shared/types';
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
|
||||
import { objectMetadataItemFamilySelector } from '@/object-metadata/states/objectMetadataItemFamilySelector';
|
||||
import { recordPageLayoutByObjectMetadataIdFamilySelector } from '@/page-layout/states/selectors/recordPageLayoutByObjectMetadataIdFamilySelector';
|
||||
import { getDefaultRecordPageLayoutId } from '@/page-layout/utils/getDefaultRecordPageLayoutId';
|
||||
|
||||
const DASHBOARD_NAME_SINGULAR = CoreObjectNameSingular.Dashboard;
|
||||
|
||||
export const getPageLayoutIdForLocation = ({
|
||||
location,
|
||||
store,
|
||||
}: {
|
||||
location: Location;
|
||||
store: ReturnType<typeof getDefaultStore>;
|
||||
}): string | null => {
|
||||
const recordShowMatch = matchPath(AppPath.RecordShowPage, location.pathname);
|
||||
|
||||
if (isDefined(recordShowMatch?.params.objectNameSingular)) {
|
||||
const objectNameSingular = recordShowMatch.params.objectNameSingular;
|
||||
|
||||
if (objectNameSingular === DASHBOARD_NAME_SINGULAR) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const objectMetadataItem = store.get(
|
||||
objectMetadataItemFamilySelector.selectorFamily({
|
||||
objectName: objectNameSingular,
|
||||
objectNameType: 'singular',
|
||||
}),
|
||||
);
|
||||
|
||||
if (!isDefined(objectMetadataItem)) {
|
||||
return null;
|
||||
}
|
||||
|
||||
const recordPageLayout = store.get(
|
||||
recordPageLayoutByObjectMetadataIdFamilySelector.selectorFamily({
|
||||
objectMetadataId: objectMetadataItem.id,
|
||||
}),
|
||||
);
|
||||
|
||||
return isDefined(recordPageLayout)
|
||||
? recordPageLayout.id
|
||||
: getDefaultRecordPageLayoutId({
|
||||
targetObjectNameSingular: objectNameSingular,
|
||||
});
|
||||
}
|
||||
|
||||
const pageLayoutMatch = matchPath(AppPath.PageLayoutPage, location.pathname);
|
||||
|
||||
if (isDefined(pageLayoutMatch?.params.pageLayoutId)) {
|
||||
return pageLayoutMatch.params.pageLayoutId;
|
||||
}
|
||||
|
||||
return null;
|
||||
};
|
||||
+5
-1
@@ -5,7 +5,9 @@ import { PinnedCommandMenuItemButtons } from '@/command-menu-item/display/compon
|
||||
import { CommandMenuItemEditButton } from '@/command-menu-item/edit/components/CommandMenuItemEditButton';
|
||||
import { commandMenuItemsSelector } from '@/command-menu-item/states/commandMenuItemsSelector';
|
||||
import { doesCommandMenuItemMatchObjectMetadataId } from '@/command-menu-item/utils/doesCommandMenuItemMatchObjectMetadataId';
|
||||
import { doesCommandMenuItemMatchPageLayoutId } from '@/command-menu-item/utils/doesCommandMenuItemMatchPageLayoutId';
|
||||
import { useObjectMetadataItems } from '@/object-metadata/hooks/useObjectMetadataItems';
|
||||
import { currentPageLayoutIdState } from '@/page-layout/states/currentPageLayoutIdState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useStore } from 'jotai';
|
||||
import { useMemo } from 'react';
|
||||
@@ -22,6 +24,7 @@ export const StandalonePageCommandMenu = () => {
|
||||
const isMobile = useIsMobile();
|
||||
const commandMenuItems = useAtomStateValue(commandMenuItemsSelector);
|
||||
const currentWorkspace = useAtomStateValue(currentWorkspaceState);
|
||||
const currentPageLayoutId = useAtomStateValue(currentPageLayoutIdState);
|
||||
const { objectMetadataItems } = useObjectMetadataItems();
|
||||
|
||||
const commandMenuContextApi = useMemo<CommandMenuContextApi>(() => {
|
||||
@@ -83,6 +86,7 @@ export const StandalonePageCommandMenu = () => {
|
||||
item.availabilityType !==
|
||||
CommandMenuItemAvailabilityType.GLOBAL_OBJECT_CONTEXT,
|
||||
)
|
||||
.filter(doesCommandMenuItemMatchPageLayoutId(currentPageLayoutId))
|
||||
.filter((item) =>
|
||||
evaluateConditionalAvailabilityExpression(
|
||||
item.conditionalAvailabilityExpression,
|
||||
@@ -92,7 +96,7 @@ export const StandalonePageCommandMenu = () => {
|
||||
.sort(
|
||||
(firstItem, secondItem) => firstItem.position - secondItem.position,
|
||||
);
|
||||
}, [commandMenuItems, commandMenuContextApi]);
|
||||
}, [commandMenuItems, commandMenuContextApi, currentPageLayoutId]);
|
||||
|
||||
return (
|
||||
<CommandMenuContext.Provider
|
||||
|
||||
+5
-1
@@ -4,7 +4,9 @@ import {
|
||||
} from '@/command-menu-item/contexts/CommandMenuContext';
|
||||
import { commandMenuItemsSelector } from '@/command-menu-item/states/commandMenuItemsSelector';
|
||||
import { doesCommandMenuItemMatchObjectMetadataId } from '@/command-menu-item/utils/doesCommandMenuItemMatchObjectMetadataId';
|
||||
import { doesCommandMenuItemMatchPageLayoutId } from '@/command-menu-item/utils/doesCommandMenuItemMatchPageLayoutId';
|
||||
import { doesCommandMenuItemMatchPageType } from '@/command-menu-item/utils/doesCommandMenuItemMatchPageType';
|
||||
import { currentPageLayoutIdState } from '@/page-layout/states/currentPageLayoutIdState';
|
||||
import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue';
|
||||
import { useMemo } from 'react';
|
||||
import { type CommandMenuContextApi } from 'twenty-shared/types';
|
||||
@@ -24,6 +26,7 @@ export const CommandMenuContextProviderContent = ({
|
||||
commandMenuContextApi,
|
||||
}: CommandMenuContextProviderContentProps) => {
|
||||
const commandMenuItems = useAtomStateValue(commandMenuItemsSelector);
|
||||
const currentPageLayoutId = useAtomStateValue(currentPageLayoutIdState);
|
||||
|
||||
const filteredCommandMenuItems = useMemo(() => {
|
||||
const currentObjectMetadataItemId =
|
||||
@@ -34,6 +37,7 @@ export const CommandMenuContextProviderContent = ({
|
||||
doesCommandMenuItemMatchObjectMetadataId(currentObjectMetadataItemId),
|
||||
)
|
||||
.filter(doesCommandMenuItemMatchPageType(commandMenuContextApi.pageType))
|
||||
.filter(doesCommandMenuItemMatchPageLayoutId(currentPageLayoutId))
|
||||
.filter((item) =>
|
||||
evaluateConditionalAvailabilityExpression(
|
||||
item.conditionalAvailabilityExpression,
|
||||
@@ -43,7 +47,7 @@ export const CommandMenuContextProviderContent = ({
|
||||
.sort(
|
||||
(firstItem, secondItem) => firstItem.position - secondItem.position,
|
||||
);
|
||||
}, [commandMenuItems, commandMenuContextApi]);
|
||||
}, [commandMenuItems, commandMenuContextApi, currentPageLayoutId]);
|
||||
|
||||
return (
|
||||
<CommandMenuContext.Provider
|
||||
|
||||
+1
@@ -28,5 +28,6 @@ export const COMMAND_MENU_ITEM_FRAGMENT = gql`
|
||||
conditionalAvailabilityExpression
|
||||
availabilityType
|
||||
availabilityObjectMetadataId
|
||||
pageLayoutId
|
||||
}
|
||||
`;
|
||||
|
||||
+6
@@ -0,0 +1,6 @@
|
||||
import { isDefined } from 'twenty-shared/utils';
|
||||
import { type CommandMenuItemFieldsFragment } from '~/generated-metadata/graphql';
|
||||
|
||||
export const doesCommandMenuItemMatchPageLayoutId =
|
||||
(pageLayoutId: string | null) => (item: CommandMenuItemFieldsFragment) =>
|
||||
!isDefined(item.pageLayoutId) || item.pageLayoutId === pageLayoutId;
|
||||
@@ -95,7 +95,9 @@ export const useSetIsPageLayoutInEditMode = (pageLayoutIdFromProps: string) => {
|
||||
|
||||
store.set(contextStoreIsFullTabWidgetInEditModeState, value);
|
||||
|
||||
store.set(currentPageLayoutIdState.atom, value ? pageLayoutId : null);
|
||||
if (value) {
|
||||
store.set(currentPageLayoutIdState.atom, pageLayoutId);
|
||||
}
|
||||
},
|
||||
[
|
||||
isDashboardInEditModeState,
|
||||
|
||||
+2
@@ -238,6 +238,8 @@ export class RefactorNavigationCommandsCommand extends ActiveOrSuspendedWorkspac
|
||||
workflowVersionId: null,
|
||||
availabilityObjectMetadataId: null,
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
pageLayoutId: null,
|
||||
pageLayoutUniversalIdentifier: null,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
});
|
||||
|
||||
+33
@@ -0,0 +1,33 @@
|
||||
import { QueryRunner } from 'typeorm';
|
||||
|
||||
import { RegisteredInstanceCommand } from 'src/engine/core-modules/upgrade/decorators/registered-instance-command.decorator';
|
||||
import { FastInstanceCommand } from 'src/engine/core-modules/upgrade/interfaces/fast-instance-command.interface';
|
||||
|
||||
@RegisteredInstanceCommand('1.23.0', 1776168404836)
|
||||
export class AddPageLayoutIdToCommandMenuItemFastInstanceCommand
|
||||
implements FastInstanceCommand
|
||||
{
|
||||
public async up(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'ALTER TABLE "core"."commandMenuItem" ADD "pageLayoutId" uuid',
|
||||
);
|
||||
await queryRunner.query(
|
||||
'CREATE INDEX "IDX_COMMAND_MENU_ITEM_PAGE_LAYOUT_ID_WORKSPACE_ID" ON "core"."commandMenuItem" ("pageLayoutId", "workspaceId") ',
|
||||
);
|
||||
await queryRunner.query(
|
||||
'ALTER TABLE "core"."commandMenuItem" ADD CONSTRAINT "FK_8577be6253969364b6725b807b4" FOREIGN KEY ("pageLayoutId") REFERENCES "core"."pageLayout"("id") ON DELETE CASCADE ON UPDATE NO ACTION',
|
||||
);
|
||||
}
|
||||
|
||||
public async down(queryRunner: QueryRunner): Promise<void> {
|
||||
await queryRunner.query(
|
||||
'ALTER TABLE "core"."commandMenuItem" DROP CONSTRAINT "FK_8577be6253969364b6725b807b4"',
|
||||
);
|
||||
await queryRunner.query(
|
||||
'DROP INDEX "core"."IDX_COMMAND_MENU_ITEM_PAGE_LAYOUT_ID_WORKSPACE_ID"',
|
||||
);
|
||||
await queryRunner.query(
|
||||
'ALTER TABLE "core"."commandMenuItem" DROP COLUMN "pageLayoutId"',
|
||||
);
|
||||
}
|
||||
}
|
||||
+2
@@ -13,6 +13,7 @@ import { AddCreditBalanceToBillingCustomerFastInstanceCommand } from 'src/databa
|
||||
import { BackfillWorkspaceIdOnIndirectEntitiesSlowInstanceCommand } from 'src/database/commands/upgrade-version-command/1-22/1-22-instance-command-slow-1775758621018-backfill-workspace-id-on-indirect-entities';
|
||||
import { DropWorkspaceVersionColumnFastInstanceCommand } from 'src/database/commands/upgrade-version-command/1-23/1-23-instance-command-fast-1785000000000-drop-workspace-version-column';
|
||||
import { AddGlobalObjectContextToCommandMenuItemAvailabilityTypeFastInstanceCommand } from 'src/database/commands/upgrade-version-command/1-23/1-23-instance-command-fast-1776090711153-add-global-object-context-to-command-menu-item-availability-type';
|
||||
import { AddPageLayoutIdToCommandMenuItemFastInstanceCommand } from 'src/database/commands/upgrade-version-command/1-23/1-23-instance-command-fast-1776168404836-add-page-layout-id-to-command-menu-item';
|
||||
|
||||
export const INSTANCE_COMMANDS = [
|
||||
AddViewFieldGroupIdIndexOnViewFieldFastInstanceCommand,
|
||||
@@ -28,4 +29,5 @@ export const INSTANCE_COMMANDS = [
|
||||
AddCreditBalanceToBillingCustomerFastInstanceCommand,
|
||||
DropWorkspaceVersionColumnFastInstanceCommand,
|
||||
AddGlobalObjectContextToCommandMenuItemAvailabilityTypeFastInstanceCommand,
|
||||
AddPageLayoutIdToCommandMenuItemFastInstanceCommand,
|
||||
];
|
||||
|
||||
+1
@@ -44,6 +44,7 @@ export const fromCommandMenuItemManifestToUniversalFlatCommandMenuItem = ({
|
||||
payload: null,
|
||||
hotKeys: null,
|
||||
workflowVersionId: null,
|
||||
pageLayoutUniversalIdentifier: null,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
+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;
|
||||
|
||||
|
||||
+1
@@ -10,4 +10,5 @@ export const FLAT_COMMAND_MENU_ITEM_EDITABLE_PROPERTIES = [
|
||||
'availabilityType',
|
||||
'availabilityObjectMetadataId',
|
||||
'engineComponentKey',
|
||||
'pageLayoutId',
|
||||
] as const satisfies MetadataEntityPropertyName<'commandMenuItem'>[];
|
||||
|
||||
+2
@@ -7,6 +7,7 @@ import { WorkspaceFlatCommandMenuItemMapCacheService } from 'src/engine/metadata
|
||||
import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module';
|
||||
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';
|
||||
|
||||
@Module({
|
||||
imports: [
|
||||
@@ -15,6 +16,7 @@ import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadat
|
||||
ApplicationEntity,
|
||||
ObjectMetadataEntity,
|
||||
FrontComponentEntity,
|
||||
PageLayoutEntity,
|
||||
]),
|
||||
WorkspaceManyOrAllFlatEntityMapsCacheModule,
|
||||
],
|
||||
|
||||
+38
-22
@@ -12,6 +12,7 @@ import { fromCommandMenuItemEntityToFlatCommandMenuItem } from 'src/engine/metad
|
||||
import { createEmptyFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/constant/create-empty-flat-entity-maps.constant';
|
||||
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 { WorkspaceCache } from 'src/engine/workspace-cache/decorators/workspace-cache.decorator';
|
||||
import { createIdToUniversalIdentifierMap } from 'src/engine/workspace-cache/utils/create-id-to-universal-identifier-map.util';
|
||||
import { addFlatEntityToFlatEntityMapsThroughMutationOrThrow } from 'src/engine/workspace-manager/workspace-migration/utils/add-flat-entity-to-flat-entity-maps-through-mutation-or-throw.util';
|
||||
@@ -28,33 +29,45 @@ export class WorkspaceFlatCommandMenuItemMapCacheService extends WorkspaceCacheP
|
||||
private readonly objectMetadataRepository: Repository<ObjectMetadataEntity>,
|
||||
@InjectRepository(FrontComponentEntity)
|
||||
private readonly frontComponentRepository: Repository<FrontComponentEntity>,
|
||||
@InjectRepository(PageLayoutEntity)
|
||||
private readonly pageLayoutRepository: Repository<PageLayoutEntity>,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
|
||||
async computeForCache(workspaceId: string): Promise<FlatCommandMenuItemMaps> {
|
||||
const [commandMenuItems, applications, objectMetadatas, frontComponents] =
|
||||
await Promise.all([
|
||||
this.commandMenuItemRepository.find({
|
||||
where: { workspaceId },
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.applicationRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.objectMetadataRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.frontComponentRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
]);
|
||||
const [
|
||||
commandMenuItems,
|
||||
applications,
|
||||
objectMetadatas,
|
||||
frontComponents,
|
||||
pageLayouts,
|
||||
] = await Promise.all([
|
||||
this.commandMenuItemRepository.find({
|
||||
where: { workspaceId },
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.applicationRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.objectMetadataRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.frontComponentRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
this.pageLayoutRepository.find({
|
||||
where: { workspaceId },
|
||||
select: ['id', 'universalIdentifier'],
|
||||
withDeleted: true,
|
||||
}),
|
||||
]);
|
||||
|
||||
const applicationIdToUniversalIdentifierMap =
|
||||
createIdToUniversalIdentifierMap(applications);
|
||||
@@ -62,6 +75,8 @@ export class WorkspaceFlatCommandMenuItemMapCacheService extends WorkspaceCacheP
|
||||
createIdToUniversalIdentifierMap(objectMetadatas);
|
||||
const frontComponentIdToUniversalIdentifierMap =
|
||||
createIdToUniversalIdentifierMap(frontComponents);
|
||||
const pageLayoutIdToUniversalIdentifierMap =
|
||||
createIdToUniversalIdentifierMap(pageLayouts);
|
||||
|
||||
const flatCommandMenuItemMaps = createEmptyFlatEntityMaps();
|
||||
|
||||
@@ -72,6 +87,7 @@ export class WorkspaceFlatCommandMenuItemMapCacheService extends WorkspaceCacheP
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
objectMetadataIdToUniversalIdentifierMap,
|
||||
frontComponentIdToUniversalIdentifierMap,
|
||||
pageLayoutIdToUniversalIdentifierMap,
|
||||
});
|
||||
|
||||
addFlatEntityToFlatEntityMapsThroughMutationOrThrow({
|
||||
|
||||
+2
@@ -65,6 +65,8 @@ export const buildNavigationFlatCommandMenuItem = ({
|
||||
workflowVersionId: null,
|
||||
availabilityObjectMetadataId: null,
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
pageLayoutId: null,
|
||||
pageLayoutUniversalIdentifier: null,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
+19
@@ -12,6 +12,7 @@ export const fromCommandMenuItemEntityToFlatCommandMenuItem = ({
|
||||
applicationIdToUniversalIdentifierMap,
|
||||
objectMetadataIdToUniversalIdentifierMap,
|
||||
frontComponentIdToUniversalIdentifierMap,
|
||||
pageLayoutIdToUniversalIdentifierMap,
|
||||
}: FromEntityToFlatEntityArgs<'commandMenuItem'>): FlatCommandMenuItem => {
|
||||
const applicationUniversalIdentifier =
|
||||
applicationIdToUniversalIdentifierMap.get(
|
||||
@@ -57,6 +58,22 @@ export const fromCommandMenuItemEntityToFlatCommandMenuItem = ({
|
||||
}
|
||||
}
|
||||
|
||||
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,
|
||||
@@ -82,5 +99,7 @@ export const fromCommandMenuItemEntityToFlatCommandMenuItem = ({
|
||||
commandMenuItemEntity.conditionalAvailabilityExpression,
|
||||
availabilityObjectMetadataUniversalIdentifier,
|
||||
frontComponentUniversalIdentifier,
|
||||
pageLayoutId: commandMenuItemEntity.pageLayoutId,
|
||||
pageLayoutUniversalIdentifier,
|
||||
};
|
||||
};
|
||||
|
||||
+11
-2
@@ -14,13 +14,14 @@ export const fromCreateCommandMenuItemInputToFlatCommandMenuItemToCreate = ({
|
||||
flatApplication,
|
||||
flatObjectMetadataMaps,
|
||||
flatFrontComponentMaps,
|
||||
flatPageLayoutMaps,
|
||||
}: {
|
||||
createCommandMenuItemInput: CreateCommandMenuItemInput;
|
||||
workspaceId: string;
|
||||
flatApplication: FlatApplication;
|
||||
} & Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatObjectMetadataMaps' | 'flatFrontComponentMaps'
|
||||
'flatObjectMetadataMaps' | 'flatFrontComponentMaps' | 'flatPageLayoutMaps'
|
||||
>): FlatCommandMenuItem => {
|
||||
const id = uuidv4();
|
||||
const now = new Date().toISOString();
|
||||
@@ -28,14 +29,20 @@ export const fromCreateCommandMenuItemInputToFlatCommandMenuItemToCreate = ({
|
||||
const {
|
||||
availabilityObjectMetadataUniversalIdentifier,
|
||||
frontComponentUniversalIdentifier,
|
||||
pageLayoutUniversalIdentifier,
|
||||
} = resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'commandMenuItem',
|
||||
foreignKeyValues: {
|
||||
availabilityObjectMetadataId:
|
||||
createCommandMenuItemInput.availabilityObjectMetadataId,
|
||||
frontComponentId: createCommandMenuItemInput.frontComponentId,
|
||||
pageLayoutId: createCommandMenuItemInput.pageLayoutId,
|
||||
},
|
||||
flatEntityMaps: {
|
||||
flatObjectMetadataMaps,
|
||||
flatFrontComponentMaps,
|
||||
flatPageLayoutMaps,
|
||||
},
|
||||
flatEntityMaps: { flatObjectMetadataMaps, flatFrontComponentMaps },
|
||||
});
|
||||
|
||||
return {
|
||||
@@ -64,6 +71,8 @@ export const fromCreateCommandMenuItemInputToFlatCommandMenuItemToCreate = ({
|
||||
conditionalAvailabilityExpression:
|
||||
createCommandMenuItemInput.conditionalAvailabilityExpression ?? null,
|
||||
availabilityObjectMetadataUniversalIdentifier,
|
||||
pageLayoutId: createCommandMenuItemInput.pageLayoutId ?? null,
|
||||
pageLayoutUniversalIdentifier,
|
||||
workspaceId,
|
||||
applicationId: flatApplication.id,
|
||||
applicationUniversalIdentifier: flatApplication.universalIdentifier,
|
||||
|
||||
+1
@@ -20,6 +20,7 @@ export const fromFlatCommandMenuItemToCommandMenuItemDto = (
|
||||
flatCommandMenuItem.conditionalAvailabilityExpression ?? undefined,
|
||||
availabilityObjectMetadataId:
|
||||
flatCommandMenuItem.availabilityObjectMetadataId ?? undefined,
|
||||
pageLayoutId: flatCommandMenuItem.pageLayoutId ?? undefined,
|
||||
workspaceId: flatCommandMenuItem.workspaceId,
|
||||
applicationId: flatCommandMenuItem.applicationId ?? undefined,
|
||||
createdAt: new Date(flatCommandMenuItem.createdAt),
|
||||
|
||||
+16
-1
@@ -18,12 +18,13 @@ export const fromUpdateCommandMenuItemInputToFlatCommandMenuItemToUpdateOrThrow
|
||||
flatCommandMenuItemMaps,
|
||||
updateCommandMenuItemInput,
|
||||
flatObjectMetadataMaps,
|
||||
flatPageLayoutMaps,
|
||||
}: {
|
||||
flatCommandMenuItemMaps: FlatCommandMenuItemMaps;
|
||||
updateCommandMenuItemInput: UpdateCommandMenuItemInput;
|
||||
} & Pick<
|
||||
AllFlatEntityMaps,
|
||||
'flatObjectMetadataMaps'
|
||||
'flatObjectMetadataMaps' | 'flatPageLayoutMaps'
|
||||
>): FlatCommandMenuItem => {
|
||||
const existingFlatCommandMenuItem = findFlatEntityByIdInFlatEntityMaps({
|
||||
flatEntityId: updateCommandMenuItemInput.id,
|
||||
@@ -63,5 +64,19 @@ export const fromUpdateCommandMenuItemInputToFlatCommandMenuItemToUpdateOrThrow
|
||||
availabilityObjectMetadataUniversalIdentifier;
|
||||
}
|
||||
|
||||
if (updates.pageLayoutId !== undefined) {
|
||||
const { pageLayoutUniversalIdentifier } =
|
||||
resolveEntityRelationUniversalIdentifiers({
|
||||
metadataName: 'commandMenuItem',
|
||||
foreignKeyValues: {
|
||||
pageLayoutId: flatCommandMenuItemToUpdate.pageLayoutId,
|
||||
},
|
||||
flatEntityMaps: { flatPageLayoutMaps },
|
||||
});
|
||||
|
||||
flatCommandMenuItemToUpdate.pageLayoutUniversalIdentifier =
|
||||
pageLayoutUniversalIdentifier;
|
||||
}
|
||||
|
||||
return flatCommandMenuItemToUpdate;
|
||||
};
|
||||
|
||||
+5
@@ -1114,6 +1114,11 @@ export const ALL_ENTITY_PROPERTIES_CONFIGURATION_BY_METADATA_NAME = {
|
||||
toStringify: false,
|
||||
universalProperty: undefined,
|
||||
},
|
||||
pageLayoutId: {
|
||||
toCompare: false,
|
||||
toStringify: false,
|
||||
universalProperty: 'pageLayoutUniversalIdentifier',
|
||||
},
|
||||
},
|
||||
navigationMenuItem: {
|
||||
type: {
|
||||
|
||||
+3
@@ -50,6 +50,9 @@ export const ALL_MANY_TO_ONE_METADATA_FOREIGN_KEY = {
|
||||
frontComponent: {
|
||||
foreignKey: 'frontComponentId',
|
||||
},
|
||||
pageLayout: {
|
||||
foreignKey: 'pageLayoutId',
|
||||
},
|
||||
},
|
||||
navigationMenuItem: {
|
||||
workspace: null,
|
||||
|
||||
+7
@@ -86,6 +86,13 @@ export const ALL_MANY_TO_ONE_METADATA_RELATIONS = {
|
||||
isNullable: true,
|
||||
universalForeignKey: 'frontComponentUniversalIdentifier',
|
||||
},
|
||||
pageLayout: {
|
||||
metadataName: 'pageLayout',
|
||||
foreignKey: 'pageLayoutId',
|
||||
inverseOneToManyProperty: null,
|
||||
isNullable: true,
|
||||
universalForeignKey: 'pageLayoutUniversalIdentifier',
|
||||
},
|
||||
},
|
||||
navigationMenuItem: {
|
||||
workspace: null,
|
||||
|
||||
+1
@@ -69,6 +69,7 @@ export const ALL_METADATA_REQUIRED_METADATA_FOR_VALIDATION = {
|
||||
commandMenuItem: {
|
||||
objectMetadata: true,
|
||||
frontComponent: true,
|
||||
pageLayout: true,
|
||||
},
|
||||
navigationMenuItem: {
|
||||
objectMetadata: true,
|
||||
|
||||
+1
@@ -6,6 +6,7 @@ exports[`getMetadataRelatedMetadataNames should return related metadata names fo
|
||||
[
|
||||
"objectMetadata",
|
||||
"frontComponent",
|
||||
"pageLayout",
|
||||
]
|
||||
`;
|
||||
|
||||
|
||||
+1
-1
@@ -4,10 +4,10 @@ exports[`sortMetadataNamesChildrenFirst should return metadata names sorted with
|
||||
[
|
||||
"rowLevelPermissionPredicate",
|
||||
"navigationMenuItem",
|
||||
"commandMenuItem",
|
||||
"fieldPermission",
|
||||
"viewField",
|
||||
"viewFilter",
|
||||
"commandMenuItem",
|
||||
"objectPermission",
|
||||
"pageLayoutWidget",
|
||||
"viewSort",
|
||||
|
||||
+3
-1
@@ -82,13 +82,15 @@ export const prefillFrontComponentCommandMenuItems = async ({
|
||||
icon: definition.icon,
|
||||
shortLabel: definition.label,
|
||||
position: definition.position,
|
||||
isPinned: false,
|
||||
isPinned: definition.isPinned ?? false,
|
||||
availabilityType: CommandMenuItemAvailabilityType.GLOBAL,
|
||||
conditionalAvailabilityExpression: null,
|
||||
availabilityObjectMetadataId: null,
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
payload: null,
|
||||
hotKeys: null,
|
||||
pageLayoutId: definition.pageLayoutId ?? null,
|
||||
pageLayoutUniversalIdentifier: definition.pageLayoutId ?? null,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
+20
@@ -1,5 +1,8 @@
|
||||
import { v5 as uuidv5 } from 'uuid';
|
||||
|
||||
import { PAGE_LAYOUT_SEEDS } from 'src/engine/workspace-manager/dev-seeder/core/constants/page-layout-seeds.constant';
|
||||
import { generateSeedId } from 'src/engine/workspace-manager/dev-seeder/core/utils/generate-seed-id.util';
|
||||
|
||||
const SEED_FRONT_COMPONENT_ID_NAMESPACE =
|
||||
'e7a3b1c4-f5d6-4e8a-9b2c-3d4e5f6a7b8c';
|
||||
|
||||
@@ -20,6 +23,8 @@ export type SeedFrontComponentCommandMenuItemDefinition = {
|
||||
label: string;
|
||||
icon: string;
|
||||
position: number;
|
||||
isPinned?: boolean;
|
||||
pageLayoutId?: string | null;
|
||||
};
|
||||
|
||||
export const getSeedFrontComponentIds = (workspaceId: string) => ({
|
||||
@@ -98,5 +103,20 @@ export const getSeedFrontComponentCommandMenuItemDefinitions = (
|
||||
icon: 'IconBell',
|
||||
position: 201,
|
||||
},
|
||||
{
|
||||
universalIdentifier: uuidv5(
|
||||
`${workspaceId}:seed-front-component-command:standalone-page-show-notification`,
|
||||
SEED_FRONT_COMPONENT_ID_NAMESPACE,
|
||||
),
|
||||
frontComponentId: showNotificationId,
|
||||
label: 'Show Notification',
|
||||
icon: 'IconStar',
|
||||
position: 202,
|
||||
isPinned: true,
|
||||
pageLayoutId: generateSeedId(
|
||||
workspaceId,
|
||||
PAGE_LAYOUT_SEEDS.DOCUMENTATION_STANDALONE_PAGE,
|
||||
),
|
||||
},
|
||||
];
|
||||
};
|
||||
|
||||
+2
@@ -68,6 +68,8 @@ export const prefillWorkflowCommandMenuItems = async ({
|
||||
availabilityObjectMetadataUniversalIdentifier: null,
|
||||
payload: null,
|
||||
hotKeys: null,
|
||||
pageLayoutId: null,
|
||||
pageLayoutUniversalIdentifier: null,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
+2
@@ -74,6 +74,8 @@ export const createStandardCommandMenuItemFlatMetadata = ({
|
||||
availabilityObjectMetadataId: resolvedObjectMetadataId,
|
||||
availabilityObjectMetadataUniversalIdentifier:
|
||||
resolvedObjectMetadataUniversalIdentifier,
|
||||
pageLayoutId: null,
|
||||
pageLayoutUniversalIdentifier: null,
|
||||
createdAt: now,
|
||||
updatedAt: now,
|
||||
};
|
||||
|
||||
+2
-1
@@ -30,7 +30,7 @@ export class CreateCommandMenuItemActionHandlerService extends WorkspaceMigratio
|
||||
flatApplication,
|
||||
workspaceId,
|
||||
}: WorkspaceMigrationActionRunnerArgs<UniversalCreateCommandMenuItemAction>): Promise<FlatCreateCommandMenuItemAction> {
|
||||
const { availabilityObjectMetadataId, frontComponentId } =
|
||||
const { availabilityObjectMetadataId, frontComponentId, pageLayoutId } =
|
||||
resolveUniversalRelationIdentifiersToIds({
|
||||
flatEntityMaps: allFlatEntityMaps,
|
||||
metadataName: action.metadataName,
|
||||
@@ -48,6 +48,7 @@ export class CreateCommandMenuItemActionHandlerService extends WorkspaceMigratio
|
||||
...action.flatEntity,
|
||||
availabilityObjectMetadataId,
|
||||
frontComponentId,
|
||||
pageLayoutId,
|
||||
applicationId: flatApplication.id,
|
||||
id: action.id ?? v4(),
|
||||
workspaceId,
|
||||
|
||||
Reference in New Issue
Block a user