Refactor navigation commands to use NAVIGATION engine key with payload (#19303)
- Adds a payload JSON column to `CommandMenuItem` and introduces a unified `NAVIGATION` engine component key that replaces all individual GO_TO_* keys - Navigation commands now use the payload to determine their target (either an objectMetadataItemId or a path), making navigation commands dynamic and eliminating the need for a hardcoded engine key per object - Includes a 1.21 upgrade command (refactor-navigation-commands) that migrates existing GO_TO_* items to NAVIGATION items with the appropriate payload, and applies a CHECK constraint enforcing payload coherence https://github.com/user-attachments/assets/4d305ba2-ae0b-4556-bb0e-e9d899777350 TODO: In a second PR, create the sync between object metadata items and the navigation command menu items - Object metadata item created or enabled -> Create navigation command - Object metadata item deleted or disabled -> Delete associated navigation command In another PR: - Allow `label`, `shortLabel` and `icon` to resolve the `navigateToObjectMetadataItem` dynamically in their interpolation instead of being hardcoded in the command menu item - Make the icon dynamic in the command menu items as the label so that we can resolve ${navigateToObjectMetadataItem.icon} at runTime -> This way we won't need to keep update the command menu item icon when we update the objectMetadataItem icon
This commit is contained in:
+5
@@ -10,6 +10,7 @@ import {
|
||||
IsString,
|
||||
IsUUID,
|
||||
} from 'class-validator';
|
||||
import { GraphQLJSON } from 'graphql-type-json';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { CommandMenuItemAvailabilityType } from 'src/engine/metadata-modules/command-menu-item/enums/command-menu-item-availability-type.enum';
|
||||
@@ -68,6 +69,10 @@ export class CommandMenuItemDTO {
|
||||
@Field(() => CommandMenuItemAvailabilityType)
|
||||
availabilityType: CommandMenuItemAvailabilityType;
|
||||
|
||||
@IsOptional()
|
||||
@Field(() => GraphQLJSON, { nullable: true })
|
||||
payload?: Record<string, unknown>;
|
||||
|
||||
@IsString({ each: true })
|
||||
@IsOptional()
|
||||
@Field(() => [String], { nullable: true })
|
||||
|
||||
+7
@@ -5,10 +5,12 @@ import {
|
||||
IsEnum,
|
||||
IsNotEmpty,
|
||||
IsNumber,
|
||||
IsObject,
|
||||
IsOptional,
|
||||
IsString,
|
||||
IsUUID,
|
||||
} from 'class-validator';
|
||||
import GraphQLJSON from 'graphql-type-json';
|
||||
|
||||
import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars';
|
||||
import { CommandMenuItemAvailabilityType } from 'src/engine/metadata-modules/command-menu-item/enums/command-menu-item-availability-type.enum';
|
||||
@@ -75,4 +77,9 @@ export class CreateCommandMenuItemInput {
|
||||
@IsOptional()
|
||||
@Field(() => UUIDScalarType, { nullable: true })
|
||||
availabilityObjectMetadataId?: string;
|
||||
|
||||
@IsObject()
|
||||
@IsOptional()
|
||||
@Field(() => GraphQLJSON, { nullable: true })
|
||||
payload?: Record<string, unknown>;
|
||||
}
|
||||
|
||||
+4
-1
@@ -31,7 +31,7 @@ import { SyncableEntity } from 'src/engine/workspace-manager/types/syncable-enti
|
||||
])
|
||||
@Check(
|
||||
'CHK_CMD_MENU_ITEM_ENGINE_KEY_COHERENCE',
|
||||
`("engineComponentKey" = 'TRIGGER_WORKFLOW_VERSION' AND "workflowVersionId" IS NOT NULL AND "frontComponentId" IS NULL) OR ("engineComponentKey" = 'FRONT_COMPONENT_RENDERER' AND "frontComponentId" IS NOT NULL AND "workflowVersionId" IS NULL) OR ("engineComponentKey" NOT IN ('TRIGGER_WORKFLOW_VERSION', 'FRONT_COMPONENT_RENDERER') AND "workflowVersionId" IS NULL AND "frontComponentId" IS NULL)`,
|
||||
`("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)`,
|
||||
)
|
||||
export class CommandMenuItemEntity
|
||||
extends SyncableEntity
|
||||
@@ -79,6 +79,9 @@ export class CommandMenuItemEntity
|
||||
})
|
||||
availabilityType: CommandMenuItemAvailabilityType;
|
||||
|
||||
@Column({ type: 'jsonb', nullable: true })
|
||||
payload: Record<string, unknown> | null;
|
||||
|
||||
@Column({ type: 'text', array: true, nullable: true })
|
||||
hotKeys: string[] | null;
|
||||
|
||||
|
||||
+13
-9
@@ -18,19 +18,11 @@ export enum EngineComponentKey {
|
||||
SEE_DELETED_RECORDS = 'SEE_DELETED_RECORDS',
|
||||
CREATE_NEW_VIEW = 'CREATE_NEW_VIEW',
|
||||
HIDE_DELETED_RECORDS = 'HIDE_DELETED_RECORDS',
|
||||
GO_TO_PEOPLE = 'GO_TO_PEOPLE',
|
||||
GO_TO_COMPANIES = 'GO_TO_COMPANIES',
|
||||
GO_TO_DASHBOARDS = 'GO_TO_DASHBOARDS',
|
||||
GO_TO_OPPORTUNITIES = 'GO_TO_OPPORTUNITIES',
|
||||
GO_TO_SETTINGS = 'GO_TO_SETTINGS',
|
||||
GO_TO_TASKS = 'GO_TO_TASKS',
|
||||
GO_TO_NOTES = 'GO_TO_NOTES',
|
||||
EDIT_RECORD_PAGE_LAYOUT = 'EDIT_RECORD_PAGE_LAYOUT',
|
||||
EDIT_DASHBOARD_LAYOUT = 'EDIT_DASHBOARD_LAYOUT',
|
||||
SAVE_DASHBOARD_LAYOUT = 'SAVE_DASHBOARD_LAYOUT',
|
||||
CANCEL_DASHBOARD_LAYOUT = 'CANCEL_DASHBOARD_LAYOUT',
|
||||
DUPLICATE_DASHBOARD = 'DUPLICATE_DASHBOARD',
|
||||
GO_TO_WORKFLOWS = 'GO_TO_WORKFLOWS',
|
||||
ACTIVATE_WORKFLOW = 'ACTIVATE_WORKFLOW',
|
||||
DEACTIVATE_WORKFLOW = 'DEACTIVATE_WORKFLOW',
|
||||
DISCARD_DRAFT_WORKFLOW = 'DISCARD_DRAFT_WORKFLOW',
|
||||
@@ -41,7 +33,6 @@ export enum EngineComponentKey {
|
||||
ADD_NODE_WORKFLOW = 'ADD_NODE_WORKFLOW',
|
||||
TIDY_UP_WORKFLOW = 'TIDY_UP_WORKFLOW',
|
||||
DUPLICATE_WORKFLOW = 'DUPLICATE_WORKFLOW',
|
||||
GO_TO_RUNS = 'GO_TO_RUNS',
|
||||
SEE_VERSION_WORKFLOW_RUN = 'SEE_VERSION_WORKFLOW_RUN',
|
||||
SEE_WORKFLOW_WORKFLOW_RUN = 'SEE_WORKFLOW_WORKFLOW_RUN',
|
||||
STOP_WORKFLOW_RUN = 'STOP_WORKFLOW_RUN',
|
||||
@@ -53,11 +44,24 @@ export enum EngineComponentKey {
|
||||
SEARCH_RECORDS_FALLBACK = 'SEARCH_RECORDS_FALLBACK',
|
||||
ASK_AI = 'ASK_AI',
|
||||
VIEW_PREVIOUS_AI_CHATS = 'VIEW_PREVIOUS_AI_CHATS',
|
||||
NAVIGATION = 'NAVIGATION',
|
||||
TRIGGER_WORKFLOW_VERSION = 'TRIGGER_WORKFLOW_VERSION',
|
||||
FRONT_COMPONENT_RENDERER = 'FRONT_COMPONENT_RENDERER',
|
||||
REPLY_TO_EMAIL_THREAD = 'REPLY_TO_EMAIL_THREAD',
|
||||
COMPOSE_EMAIL = 'COMPOSE_EMAIL',
|
||||
|
||||
// TODO: Remove deprecated keys once upgrade:1-21:refactor-navigation-commands has run on all workspaces
|
||||
// Deprecated: replaced by NAVIGATION engine key with payload
|
||||
GO_TO_PEOPLE = 'GO_TO_PEOPLE',
|
||||
GO_TO_COMPANIES = 'GO_TO_COMPANIES',
|
||||
GO_TO_DASHBOARDS = 'GO_TO_DASHBOARDS',
|
||||
GO_TO_OPPORTUNITIES = 'GO_TO_OPPORTUNITIES',
|
||||
GO_TO_SETTINGS = 'GO_TO_SETTINGS',
|
||||
GO_TO_TASKS = 'GO_TO_TASKS',
|
||||
GO_TO_NOTES = 'GO_TO_NOTES',
|
||||
GO_TO_WORKFLOWS = 'GO_TO_WORKFLOWS',
|
||||
GO_TO_RUNS = 'GO_TO_RUNS',
|
||||
|
||||
// Deprecated keys kept for backward compatibility until migration runs
|
||||
DELETE_SINGLE_RECORD = 'DELETE_SINGLE_RECORD',
|
||||
DELETE_MULTIPLE_RECORDS = 'DELETE_MULTIPLE_RECORDS',
|
||||
|
||||
Reference in New Issue
Block a user