From a82739cdb1987f0e4db184d2430f72846f660ee6 Mon Sep 17 00:00:00 2001 From: Charles Bochet Date: Tue, 17 Mar 2026 23:18:07 +0100 Subject: [PATCH] feat: optimistic metadata store updates for navigation menu items (#18710) ## Summary - **Optimistic metadata store updates**: Replace `refetchQueries` with direct `addToDraft`/`applyChanges` calls in create, update, and delete navigation menu item mutation hooks for instant UI feedback. Client-side UUID generation enables optimistic creates before the server responds. - **SSE event enrichment with `targetRecordIdentifier`**: Introduce `NavigationMenuItemRecordIdentifierService` to resolve record display info (label, image) and enrich SSE metadata events at emission time, so the sidebar shows record names immediately without a page refresh. - **Centralized role permission resolution**: Add `resolveRolePermissionConfigFromAuthContext` to `PermissionsService`, removing duplicated role resolution logic from individual services. - **Mutation fragments include `targetRecordIdentifier`**: Switch create/update/delete mutations from `NavigationMenuItemFields` to `NavigationMenuItemQueryFields` so the mutation response includes `targetRecordIdentifier`, preventing a brief gap where RECORD favorites are invisible in the sidebar. - **Folder UI fixes**: Remove transparent border on `StyledFolderContainer` that caused a 1px size inconsistency between folder and non-folder items in Favorites. Make the folder kebab menu hover-only instead of always visible. --- .../src/generated-metadata/graphql.ts | 13 +- .../mutations/createNavigationMenuItem.ts | 6 +- .../mutations/deleteNavigationMenuItem.ts | 6 +- .../mutations/updateNavigationMenuItem.ts | 6 +- .../hooks/useCreateNavigationMenuItem.ts | 137 +- .../hooks/useDeleteNavigationMenuItem.ts | 10 +- .../hooks/useUpdateNavigationMenuItem.ts | 26 +- .../states/navigationMenuItemsSelector.ts | 3 +- .../common/utils/computeDndReorderPosition.ts | 36 + .../useHandleNavigationMenuItemDragAndDrop.ts | 255 ++-- ...eWorkspaceNavigationMenuItemDragAndDrop.ts | 177 --- .../dnd/hooks/useNavigationMenuItemDndKit.ts | 27 +- .../NavigationMenuItemFolderDnd.tsx | 3 +- .../useCreateNavigationMenuItemFolder.ts | 21 +- .../hooks/useSaveNavigationMenuItemsDraft.ts | 3 - .../clients/generated/metadata/schema.graphql | 221 +-- .../src/clients/generated/metadata/schema.ts | 318 ++--- .../src/clients/generated/metadata/types.ts | 1225 +++++++++-------- ...lat-navigation-menu-item-to-create.util.ts | 2 +- .../dtos/create-navigation-menu-item.input.ts | 5 + .../navigation-menu-item.module.ts | 11 +- .../navigation-menu-item.service.ts | 152 +- ...ion-menu-item-record-identifier.service.ts | 134 ++ .../permissions/permissions.service.ts | 47 + .../workspace-event-emitter.service.spec.ts | 9 + .../workspace-event-emitter.module.ts | 2 + .../workspace-event-emitter.service.ts | 57 + 27 files changed, 1496 insertions(+), 1416 deletions(-) create mode 100644 packages/twenty-front/src/modules/navigation-menu-item/common/utils/computeDndReorderPosition.ts delete mode 100644 packages/twenty-front/src/modules/navigation-menu-item/display/dnd/hooks/useHandleWorkspaceNavigationMenuItemDragAndDrop.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/navigation-menu-item/services/navigation-menu-item-record-identifier.service.ts diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index 4ce18bc75d..81293fcf23 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -1075,6 +1075,7 @@ export type CreateNavigationMenuItemInput = { color?: InputMaybe; folderId?: InputMaybe; icon?: InputMaybe; + id?: InputMaybe; link?: InputMaybe; name?: InputMaybe; position?: InputMaybe; @@ -6453,21 +6454,21 @@ export type CreateNavigationMenuItemMutationVariables = Exact<{ }>; -export type CreateNavigationMenuItemMutation = { __typename?: 'Mutation', createNavigationMenuItem: { __typename?: 'NavigationMenuItem', id: string, type: NavigationMenuItemType, userWorkspaceId?: string | null, targetRecordId?: string | null, targetObjectMetadataId?: string | null, viewId?: string | null, folderId?: string | null, name?: string | null, link?: string | null, icon?: string | null, color?: string | null, position: number, applicationId?: string | null, createdAt: string, updatedAt: string } }; +export type CreateNavigationMenuItemMutation = { __typename?: 'Mutation', createNavigationMenuItem: { __typename?: 'NavigationMenuItem', id: string, type: NavigationMenuItemType, userWorkspaceId?: string | null, targetRecordId?: string | null, targetObjectMetadataId?: string | null, viewId?: string | null, folderId?: string | null, name?: string | null, link?: string | null, icon?: string | null, color?: string | null, position: number, applicationId?: string | null, createdAt: string, updatedAt: string, targetRecordIdentifier?: { __typename?: 'RecordIdentifier', id: string, labelIdentifier: string, imageIdentifier?: string | null } | null } }; export type DeleteNavigationMenuItemMutationVariables = Exact<{ id: Scalars['UUID']; }>; -export type DeleteNavigationMenuItemMutation = { __typename?: 'Mutation', deleteNavigationMenuItem: { __typename?: 'NavigationMenuItem', id: string, type: NavigationMenuItemType, userWorkspaceId?: string | null, targetRecordId?: string | null, targetObjectMetadataId?: string | null, viewId?: string | null, folderId?: string | null, name?: string | null, link?: string | null, icon?: string | null, color?: string | null, position: number, applicationId?: string | null, createdAt: string, updatedAt: string } }; +export type DeleteNavigationMenuItemMutation = { __typename?: 'Mutation', deleteNavigationMenuItem: { __typename?: 'NavigationMenuItem', id: string, type: NavigationMenuItemType, userWorkspaceId?: string | null, targetRecordId?: string | null, targetObjectMetadataId?: string | null, viewId?: string | null, folderId?: string | null, name?: string | null, link?: string | null, icon?: string | null, color?: string | null, position: number, applicationId?: string | null, createdAt: string, updatedAt: string, targetRecordIdentifier?: { __typename?: 'RecordIdentifier', id: string, labelIdentifier: string, imageIdentifier?: string | null } | null } }; export type UpdateNavigationMenuItemMutationVariables = Exact<{ input: UpdateOneNavigationMenuItemInput; }>; -export type UpdateNavigationMenuItemMutation = { __typename?: 'Mutation', updateNavigationMenuItem: { __typename?: 'NavigationMenuItem', id: string, type: NavigationMenuItemType, userWorkspaceId?: string | null, targetRecordId?: string | null, targetObjectMetadataId?: string | null, viewId?: string | null, folderId?: string | null, name?: string | null, link?: string | null, icon?: string | null, color?: string | null, position: number, applicationId?: string | null, createdAt: string, updatedAt: string } }; +export type UpdateNavigationMenuItemMutation = { __typename?: 'Mutation', updateNavigationMenuItem: { __typename?: 'NavigationMenuItem', id: string, type: NavigationMenuItemType, userWorkspaceId?: string | null, targetRecordId?: string | null, targetObjectMetadataId?: string | null, viewId?: string | null, folderId?: string | null, name?: string | null, link?: string | null, icon?: string | null, color?: string | null, position: number, applicationId?: string | null, createdAt: string, updatedAt: string, targetRecordIdentifier?: { __typename?: 'RecordIdentifier', id: string, labelIdentifier: string, imageIdentifier?: string | null } | null } }; export type FindManyNavigationMenuItemsQueryVariables = Exact<{ [key: string]: never; }>; @@ -7698,9 +7699,9 @@ export const InstallMarketplaceAppDocument = {"kind":"Document","definitions":[{ export const UpgradeApplicationDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpgradeApplication"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"appRegistrationId"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"targetVersion"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"upgradeApplication"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"appRegistrationId"},"value":{"kind":"Variable","name":{"kind":"Name","value":"appRegistrationId"}}},{"kind":"Argument","name":{"kind":"Name","value":"targetVersion"},"value":{"kind":"Variable","name":{"kind":"Name","value":"targetVersion"}}}]}]}}]} as unknown as DocumentNode; export const FindManyMarketplaceAppsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindManyMarketplaceApps"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"findManyMarketplaceApps"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"MarketplaceAppFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"MarketplaceAppFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"MarketplaceApp"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"author"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"screenshots"}},{"kind":"Field","name":{"kind":"Name","value":"aboutDescription"}},{"kind":"Field","name":{"kind":"Name","value":"providers"}},{"kind":"Field","name":{"kind":"Name","value":"websiteUrl"}},{"kind":"Field","name":{"kind":"Name","value":"termsUrl"}},{"kind":"Field","name":{"kind":"Name","value":"objects"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"universalIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"fields"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"universalIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"fields"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"objectUniversalIdentifier"}}]}},{"kind":"Field","name":{"kind":"Name","value":"logicFunctions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"timeoutSeconds"}}]}},{"kind":"Field","name":{"kind":"Name","value":"frontComponents"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sourcePackage"}},{"kind":"Field","name":{"kind":"Name","value":"isFeatured"}},{"kind":"Field","name":{"kind":"Name","value":"defaultRole"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"canReadAllObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canUpdateAllObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canSoftDeleteAllObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canDestroyAllObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canUpdateAllSettings"}},{"kind":"Field","name":{"kind":"Name","value":"canAccessAllTools"}},{"kind":"Field","name":{"kind":"Name","value":"objectPermissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"objectUniversalIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"canReadObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canUpdateObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canSoftDeleteObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canDestroyObjectRecords"}}]}},{"kind":"Field","name":{"kind":"Name","value":"fieldPermissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"objectUniversalIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"fieldUniversalIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"canReadFieldValue"}},{"kind":"Field","name":{"kind":"Name","value":"canUpdateFieldValue"}}]}},{"kind":"Field","name":{"kind":"Name","value":"permissionFlags"}}]}}]}}]} as unknown as DocumentNode; export const FindOneMarketplaceAppDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindOneMarketplaceApp"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"universalIdentifier"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"findOneMarketplaceApp"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"universalIdentifier"},"value":{"kind":"Variable","name":{"kind":"Name","value":"universalIdentifier"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"MarketplaceAppFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"MarketplaceAppFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"MarketplaceApp"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"version"}},{"kind":"Field","name":{"kind":"Name","value":"author"}},{"kind":"Field","name":{"kind":"Name","value":"category"}},{"kind":"Field","name":{"kind":"Name","value":"logo"}},{"kind":"Field","name":{"kind":"Name","value":"screenshots"}},{"kind":"Field","name":{"kind":"Name","value":"aboutDescription"}},{"kind":"Field","name":{"kind":"Name","value":"providers"}},{"kind":"Field","name":{"kind":"Name","value":"websiteUrl"}},{"kind":"Field","name":{"kind":"Name","value":"termsUrl"}},{"kind":"Field","name":{"kind":"Name","value":"objects"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"universalIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"fields"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"universalIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"fields"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"objectUniversalIdentifier"}}]}},{"kind":"Field","name":{"kind":"Name","value":"logicFunctions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"timeoutSeconds"}}]}},{"kind":"Field","name":{"kind":"Name","value":"frontComponents"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"description"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sourcePackage"}},{"kind":"Field","name":{"kind":"Name","value":"isFeatured"}},{"kind":"Field","name":{"kind":"Name","value":"defaultRole"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"canReadAllObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canUpdateAllObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canSoftDeleteAllObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canDestroyAllObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canUpdateAllSettings"}},{"kind":"Field","name":{"kind":"Name","value":"canAccessAllTools"}},{"kind":"Field","name":{"kind":"Name","value":"objectPermissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"objectUniversalIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"canReadObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canUpdateObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canSoftDeleteObjectRecords"}},{"kind":"Field","name":{"kind":"Name","value":"canDestroyObjectRecords"}}]}},{"kind":"Field","name":{"kind":"Name","value":"fieldPermissions"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"objectUniversalIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"fieldUniversalIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"canReadFieldValue"}},{"kind":"Field","name":{"kind":"Name","value":"canUpdateFieldValue"}}]}},{"kind":"Field","name":{"kind":"Name","value":"permissionFlags"}}]}}]}}]} as unknown as DocumentNode; -export const CreateNavigationMenuItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateNavigationMenuItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateNavigationMenuItemInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createNavigationMenuItem"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"userWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordId"}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"folderId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"link"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; -export const DeleteNavigationMenuItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteNavigationMenuItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteNavigationMenuItem"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"userWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordId"}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"folderId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"link"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; -export const UpdateNavigationMenuItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateNavigationMenuItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateOneNavigationMenuItemInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateNavigationMenuItem"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"userWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordId"}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"folderId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"link"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}}]} as unknown as DocumentNode; +export const CreateNavigationMenuItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateNavigationMenuItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateNavigationMenuItemInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createNavigationMenuItem"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemQueryFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"userWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordId"}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"folderId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"link"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemQueryFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemFields"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordIdentifier"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifier"}}]}}]}}]} as unknown as DocumentNode; +export const DeleteNavigationMenuItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DeleteNavigationMenuItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"deleteNavigationMenuItem"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemQueryFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"userWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordId"}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"folderId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"link"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemQueryFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemFields"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordIdentifier"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifier"}}]}}]}}]} as unknown as DocumentNode; +export const UpdateNavigationMenuItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateNavigationMenuItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateOneNavigationMenuItemInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateNavigationMenuItem"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemQueryFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"userWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordId"}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"folderId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"link"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemQueryFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemFields"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordIdentifier"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifier"}}]}}]}}]} as unknown as DocumentNode; export const FindManyNavigationMenuItemsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindManyNavigationMenuItems"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"navigationMenuItems"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemQueryFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"userWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordId"}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"folderId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"link"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemQueryFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemFields"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordIdentifier"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifier"}}]}}]}}]} as unknown as DocumentNode; export const FindOneNavigationMenuItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"query","name":{"kind":"Name","value":"FindOneNavigationMenuItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UUID"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"navigationMenuItem"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemQueryFields"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"userWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordId"}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"folderId"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"link"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"NavigationMenuItemQueryFields"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"NavigationMenuItem"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"NavigationMenuItemFields"}},{"kind":"Field","name":{"kind":"Name","value":"targetRecordIdentifier"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifier"}}]}}]}}]} as unknown as DocumentNode; export const CreateOneObjectMetadataItemDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"CreateOneObjectMetadataItem"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"CreateOneObjectInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"createOneObject"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}},{"kind":"Field","name":{"kind":"Name","value":"labelSingular"}},{"kind":"Field","name":{"kind":"Name","value":"labelPlural"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"color"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isSearchable"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"labelIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"imageIdentifierFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"isLabelSyncedWithName"}},{"kind":"Field","name":{"kind":"Name","value":"fieldsList"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"universalIdentifier"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"label"}},{"kind":"Field","name":{"kind":"Name","value":"description"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"isCustom"}},{"kind":"Field","name":{"kind":"Name","value":"isActive"}},{"kind":"Field","name":{"kind":"Name","value":"isSystem"}},{"kind":"Field","name":{"kind":"Name","value":"isUIReadOnly"}},{"kind":"Field","name":{"kind":"Name","value":"isNullable"}},{"kind":"Field","name":{"kind":"Name","value":"isUnique"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"defaultValue"}},{"kind":"Field","name":{"kind":"Name","value":"options"}},{"kind":"Field","name":{"kind":"Name","value":"settings"}},{"kind":"Field","name":{"kind":"Name","value":"isLabelSyncedWithName"}},{"kind":"Field","name":{"kind":"Name","value":"morphId"}},{"kind":"Field","name":{"kind":"Name","value":"applicationId"}},{"kind":"Field","name":{"kind":"Name","value":"relation"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"sourceObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sourceFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}},{"kind":"Field","name":{"kind":"Name","value":"morphRelations"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"sourceObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetObjectMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"nameSingular"}},{"kind":"Field","name":{"kind":"Name","value":"namePlural"}}]}},{"kind":"Field","name":{"kind":"Name","value":"sourceFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}},{"kind":"Field","name":{"kind":"Name","value":"targetFieldMetadata"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}}]}}]}}]}}]}}]}}]} as unknown as DocumentNode; diff --git a/packages/twenty-front/src/modules/navigation-menu-item/common/graphql/mutations/createNavigationMenuItem.ts b/packages/twenty-front/src/modules/navigation-menu-item/common/graphql/mutations/createNavigationMenuItem.ts index f9c5188f9c..fd05f7eb34 100644 --- a/packages/twenty-front/src/modules/navigation-menu-item/common/graphql/mutations/createNavigationMenuItem.ts +++ b/packages/twenty-front/src/modules/navigation-menu-item/common/graphql/mutations/createNavigationMenuItem.ts @@ -1,11 +1,11 @@ import { gql } from '@apollo/client'; -import { NAVIGATION_MENU_ITEM_FRAGMENT } from '@/navigation-menu-item/common/graphql/fragments/navigationMenuItemFragment'; +import { NAVIGATION_MENU_ITEM_QUERY_FRAGMENT } from '@/navigation-menu-item/common/graphql/fragments/navigationMenuItemQueryFragment'; export const CREATE_NAVIGATION_MENU_ITEM = gql` - ${NAVIGATION_MENU_ITEM_FRAGMENT} + ${NAVIGATION_MENU_ITEM_QUERY_FRAGMENT} mutation CreateNavigationMenuItem($input: CreateNavigationMenuItemInput!) { createNavigationMenuItem(input: $input) { - ...NavigationMenuItemFields + ...NavigationMenuItemQueryFields } } `; diff --git a/packages/twenty-front/src/modules/navigation-menu-item/common/graphql/mutations/deleteNavigationMenuItem.ts b/packages/twenty-front/src/modules/navigation-menu-item/common/graphql/mutations/deleteNavigationMenuItem.ts index e8fcf3d608..2ac307764b 100644 --- a/packages/twenty-front/src/modules/navigation-menu-item/common/graphql/mutations/deleteNavigationMenuItem.ts +++ b/packages/twenty-front/src/modules/navigation-menu-item/common/graphql/mutations/deleteNavigationMenuItem.ts @@ -1,11 +1,11 @@ import { gql } from '@apollo/client'; -import { NAVIGATION_MENU_ITEM_FRAGMENT } from '@/navigation-menu-item/common/graphql/fragments/navigationMenuItemFragment'; +import { NAVIGATION_MENU_ITEM_QUERY_FRAGMENT } from '@/navigation-menu-item/common/graphql/fragments/navigationMenuItemQueryFragment'; export const DELETE_NAVIGATION_MENU_ITEM = gql` - ${NAVIGATION_MENU_ITEM_FRAGMENT} + ${NAVIGATION_MENU_ITEM_QUERY_FRAGMENT} mutation DeleteNavigationMenuItem($id: UUID!) { deleteNavigationMenuItem(id: $id) { - ...NavigationMenuItemFields + ...NavigationMenuItemQueryFields } } `; diff --git a/packages/twenty-front/src/modules/navigation-menu-item/common/graphql/mutations/updateNavigationMenuItem.ts b/packages/twenty-front/src/modules/navigation-menu-item/common/graphql/mutations/updateNavigationMenuItem.ts index 448f45afa1..6a2d18fb04 100644 --- a/packages/twenty-front/src/modules/navigation-menu-item/common/graphql/mutations/updateNavigationMenuItem.ts +++ b/packages/twenty-front/src/modules/navigation-menu-item/common/graphql/mutations/updateNavigationMenuItem.ts @@ -1,11 +1,11 @@ import { gql } from '@apollo/client'; -import { NAVIGATION_MENU_ITEM_FRAGMENT } from '@/navigation-menu-item/common/graphql/fragments/navigationMenuItemFragment'; +import { NAVIGATION_MENU_ITEM_QUERY_FRAGMENT } from '@/navigation-menu-item/common/graphql/fragments/navigationMenuItemQueryFragment'; export const UPDATE_NAVIGATION_MENU_ITEM = gql` - ${NAVIGATION_MENU_ITEM_FRAGMENT} + ${NAVIGATION_MENU_ITEM_QUERY_FRAGMENT} mutation UpdateNavigationMenuItem($input: UpdateOneNavigationMenuItemInput!) { updateNavigationMenuItem(input: $input) { - ...NavigationMenuItemFields + ...NavigationMenuItemQueryFields } } `; diff --git a/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useCreateNavigationMenuItem.ts b/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useCreateNavigationMenuItem.ts index c81d04e1b6..ece747fb59 100644 --- a/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useCreateNavigationMenuItem.ts +++ b/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useCreateNavigationMenuItem.ts @@ -1,23 +1,47 @@ import { useMutation } from '@apollo/client/react'; import { NavigationMenuItemType } from 'twenty-shared/types'; import { isDefined } from 'twenty-shared/utils'; -import { CreateNavigationMenuItemDocument } from '~/generated-metadata/graphql'; +import { v4 as uuidv4 } from 'uuid'; +import { + type CreateNavigationMenuItemInput, + CreateNavigationMenuItemDocument, + type NavigationMenuItem, +} from '~/generated-metadata/graphql'; +import { useMetadataStore } from '@/metadata-store/hooks/useMetadataStore'; import { useNavigationMenuItemsData } from '@/navigation-menu-item/display/hooks/useNavigationMenuItemsData'; import { objectMetadataItemsSelector } from '@/object-metadata/states/objectMetadataItemsSelector'; import { type ObjectRecord } from '@/object-record/types/ObjectRecord'; import { useAtomStateValue } from '@/ui/utilities/state/jotai/hooks/useAtomStateValue'; +const buildOptimisticNavigationMenuItem = ( + input: CreateNavigationMenuItemInput & { id: string }, +): NavigationMenuItem => ({ + id: input.id, + type: input.type, + position: input.position ?? 0, + userWorkspaceId: input.userWorkspaceId ?? null, + targetRecordId: input.targetRecordId ?? null, + targetObjectMetadataId: input.targetObjectMetadataId ?? null, + viewId: input.viewId ?? null, + folderId: input.folderId ?? null, + name: input.name ?? null, + link: input.link ?? null, + icon: input.icon ?? null, + color: input.color ?? null, + applicationId: null, + createdAt: new Date().toISOString(), + updatedAt: new Date().toISOString(), +}); + export const useCreateNavigationMenuItem = () => { const { navigationMenuItems, currentWorkspaceMemberId } = useNavigationMenuItemsData(); const objectMetadataItems = useAtomStateValue(objectMetadataItemsSelector); + const { addToDraft, applyChanges } = useMetadataStore(); const [createNavigationMenuItemMutation] = useMutation( CreateNavigationMenuItemDocument, - { - refetchQueries: ['FindManyNavigationMenuItems'], - }, ); const createNavigationMenuItem = async ( @@ -26,31 +50,48 @@ export const useCreateNavigationMenuItem = () => { folderId?: string, ) => { const isView = targetObjectNameSingular === 'view'; + const id = uuidv4(); + + const relevantItems = folderId + ? navigationMenuItems.filter((item) => item.folderId === folderId) + : navigationMenuItems.filter( + (item) => + !isDefined(item.folderId) && isDefined(item.userWorkspaceId), + ); + + const maxPosition = Math.max( + ...relevantItems.map((item) => item.position), + 0, + ); + + const position = maxPosition + 1; if (isView) { - const relevantItems = folderId - ? navigationMenuItems.filter((item) => item.folderId === folderId) - : navigationMenuItems.filter( - (item) => - !isDefined(item.folderId) && isDefined(item.userWorkspaceId), - ); + const input: CreateNavigationMenuItemInput = { + id, + type: NavigationMenuItemType.VIEW, + viewId: targetRecord.id, + userWorkspaceId: currentWorkspaceMemberId, + folderId, + position, + }; - const maxPosition = Math.max( - ...relevantItems.map((item) => item.position), - 0, - ); - - await createNavigationMenuItemMutation({ - variables: { - input: { - type: NavigationMenuItemType.VIEW, - viewId: targetRecord.id, - userWorkspaceId: currentWorkspaceMemberId, - folderId, - position: maxPosition + 1, - }, - }, + addToDraft({ + key: 'navigationMenuItems', + items: [buildOptimisticNavigationMenuItem({ ...input, id })], }); + applyChanges(); + + const result = await createNavigationMenuItemMutation({ + variables: { input }, + }); + + const created = result.data?.createNavigationMenuItem; + + if (isDefined(created)) { + addToDraft({ key: 'navigationMenuItems', items: [created] }); + applyChanges(); + } } else { const objectMetadataItem = objectMetadataItems.find( (item) => item.nameSingular === targetObjectNameSingular, @@ -62,30 +103,32 @@ export const useCreateNavigationMenuItem = () => { ); } - const relevantItems = folderId - ? navigationMenuItems.filter((item) => item.folderId === folderId) - : navigationMenuItems.filter( - (item) => - !isDefined(item.folderId) && isDefined(item.userWorkspaceId), - ); + const input: CreateNavigationMenuItemInput = { + id, + type: NavigationMenuItemType.RECORD, + targetRecordId: targetRecord.id, + targetObjectMetadataId: objectMetadataItem.id, + userWorkspaceId: currentWorkspaceMemberId, + folderId, + position, + }; - const maxPosition = Math.max( - ...relevantItems.map((item) => item.position), - 0, - ); - - await createNavigationMenuItemMutation({ - variables: { - input: { - type: NavigationMenuItemType.RECORD, - targetRecordId: targetRecord.id, - targetObjectMetadataId: objectMetadataItem.id, - userWorkspaceId: currentWorkspaceMemberId, - folderId, - position: maxPosition + 1, - }, - }, + addToDraft({ + key: 'navigationMenuItems', + items: [buildOptimisticNavigationMenuItem({ ...input, id })], }); + applyChanges(); + + const result = await createNavigationMenuItemMutation({ + variables: { input }, + }); + + const created = result.data?.createNavigationMenuItem; + + if (isDefined(created)) { + addToDraft({ key: 'navigationMenuItems', items: [created] }); + applyChanges(); + } } }; diff --git a/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useDeleteNavigationMenuItem.ts b/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useDeleteNavigationMenuItem.ts index 2330f5ec5e..c6a2d670db 100644 --- a/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useDeleteNavigationMenuItem.ts +++ b/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useDeleteNavigationMenuItem.ts @@ -1,15 +1,19 @@ import { useMutation } from '@apollo/client/react'; import { DeleteNavigationMenuItemDocument } from '~/generated-metadata/graphql'; +import { useMetadataStore } from '@/metadata-store/hooks/useMetadataStore'; + export const useDeleteNavigationMenuItem = () => { + const { removeFromDraft, applyChanges } = useMetadataStore(); + const [deleteNavigationMenuItemMutation] = useMutation( DeleteNavigationMenuItemDocument, - { - refetchQueries: ['FindManyNavigationMenuItems'], - }, ); const deleteNavigationMenuItem = async (id: string) => { + removeFromDraft({ key: 'navigationMenuItems', itemIds: [id] }); + applyChanges(); + await deleteNavigationMenuItemMutation({ variables: { id }, }); diff --git a/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useUpdateNavigationMenuItem.ts b/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useUpdateNavigationMenuItem.ts index 9d764442ca..7a953d8ca2 100644 --- a/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useUpdateNavigationMenuItem.ts +++ b/packages/twenty-front/src/modules/navigation-menu-item/common/hooks/useUpdateNavigationMenuItem.ts @@ -1,31 +1,47 @@ import { useMutation } from '@apollo/client/react'; +import { isDefined } from 'twenty-shared/utils'; import { + type NavigationMenuItem, type UpdateNavigationMenuItemInput, type UpdateOneNavigationMenuItemInput, UpdateNavigationMenuItemDocument, } from '~/generated-metadata/graphql'; +import { useMetadataStore } from '@/metadata-store/hooks/useMetadataStore'; + export const useUpdateNavigationMenuItem = () => { + const { addToDraft, applyChanges } = useMetadataStore(); + const [updateNavigationMenuItemMutation] = useMutation( UpdateNavigationMenuItemDocument, - { - refetchQueries: ['FindManyNavigationMenuItems'], - awaitRefetchQueries: false, - }, ); const updateNavigationMenuItem = async ( input: UpdateNavigationMenuItemInput & { id: string }, ) => { const { id, ...update } = input; + + addToDraft({ + key: 'navigationMenuItems', + items: [{ id, ...update } as NavigationMenuItem], + }); + applyChanges(); + const updateOneInput: UpdateOneNavigationMenuItemInput = { id, update, }; - await updateNavigationMenuItemMutation({ + const result = await updateNavigationMenuItemMutation({ variables: { input: updateOneInput }, }); + + const updated = result.data?.updateNavigationMenuItem; + + if (isDefined(updated)) { + addToDraft({ key: 'navigationMenuItems', items: [updated] }); + applyChanges(); + } }; return { updateNavigationMenuItem }; diff --git a/packages/twenty-front/src/modules/navigation-menu-item/common/states/navigationMenuItemsSelector.ts b/packages/twenty-front/src/modules/navigation-menu-item/common/states/navigationMenuItemsSelector.ts index ba9e53b9f0..95cac810e0 100644 --- a/packages/twenty-front/src/modules/navigation-menu-item/common/states/navigationMenuItemsSelector.ts +++ b/packages/twenty-front/src/modules/navigation-menu-item/common/states/navigationMenuItemsSelector.ts @@ -8,7 +8,8 @@ export const navigationMenuItemsSelector = createAtomSelector< key: 'navigationMenuItemsSelector', get: ({ get }) => { const entry = get(metadataStoreState, 'navigationMenuItems'); + const items = entry.current as unknown as NavigationMenuItem[]; - return entry.current as unknown as NavigationMenuItem[]; + return items; }, }); diff --git a/packages/twenty-front/src/modules/navigation-menu-item/common/utils/computeDndReorderPosition.ts b/packages/twenty-front/src/modules/navigation-menu-item/common/utils/computeDndReorderPosition.ts new file mode 100644 index 0000000000..5c8b6e76f9 --- /dev/null +++ b/packages/twenty-front/src/modules/navigation-menu-item/common/utils/computeDndReorderPosition.ts @@ -0,0 +1,36 @@ +import { getPositionBetween } from '@/navigation-menu-item/common/utils/getPositionBetween'; + +export const computeDndReorderPosition = ({ + sortedList, + draggableId, + destinationIndex, +}: { + sortedList: Array<{ id: string; position: number }>; + draggableId: string; + destinationIndex: number; +}): number => { + const sourceIndexInList = sortedList.findIndex( + (item) => item.id === draggableId, + ); + const isSameList = sourceIndexInList >= 0; + + if (isSameList) { + const listWithoutDragged = sortedList.filter( + (item) => item.id !== draggableId, + ); + const adjustedIndex = + sourceIndexInList < destinationIndex && + destinationIndex <= listWithoutDragged.length + ? destinationIndex - 1 + : destinationIndex; + const prevItem = listWithoutDragged[adjustedIndex - 1]; + const nextItem = listWithoutDragged[adjustedIndex]; + + return getPositionBetween(prevItem?.position, nextItem?.position); + } + + const prevItem = sortedList[destinationIndex - 1]; + const nextItem = sortedList[destinationIndex]; + + return getPositionBetween(prevItem?.position, nextItem?.position); +}; diff --git a/packages/twenty-front/src/modules/navigation-menu-item/display/dnd/hooks/useHandleNavigationMenuItemDragAndDrop.ts b/packages/twenty-front/src/modules/navigation-menu-item/display/dnd/hooks/useHandleNavigationMenuItemDragAndDrop.ts index 51178691e3..a29848af9a 100644 --- a/packages/twenty-front/src/modules/navigation-menu-item/display/dnd/hooks/useHandleNavigationMenuItemDragAndDrop.ts +++ b/packages/twenty-front/src/modules/navigation-menu-item/display/dnd/hooks/useHandleNavigationMenuItemDragAndDrop.ts @@ -1,45 +1,127 @@ import { type OnDragEndResponder } from '@hello-pangea/dnd'; +import { useStore } from 'jotai'; +import { type NavigationMenuItem } from '~/generated-metadata/graphql'; +import { isDefined } from 'twenty-shared/utils'; -import { NavigationMenuItemDroppableIds } from '@/navigation-menu-item/common/constants/NavigationMenuItemDroppableIds'; -import { canNavigationMenuItemBeDroppedIn } from '@/navigation-menu-item/common/utils/canNavigationMenuItemBeDroppedIn'; -import { useSortedNavigationMenuItems } from '@/navigation-menu-item/display/hooks/useSortedNavigationMenuItems'; +import { isLayoutCustomizationModeEnabledState } from '@/layout-customization/states/isLayoutCustomizationModeEnabledState'; import { useUpdateNavigationMenuItem } from '@/navigation-menu-item/common/hooks/useUpdateNavigationMenuItem'; +import { NAVIGATION_MENU_ITEM_SECTION_DROPPABLE_CONFIG } from '@/navigation-menu-item/common/constants/NavigationMenuItemSectionDroppableConfig'; +import { navigationMenuItemsDraftState } from '@/navigation-menu-item/common/states/navigationMenuItemsDraftState'; import { openNavigationMenuItemFolderIdsState } from '@/navigation-menu-item/common/states/openNavigationMenuItemFolderIdsState'; -import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState'; -import { calculateNewPosition } from '@/ui/layout/draggable-list/utils/calculateNewPosition'; +import type { NavigationMenuItemSection } from '@/navigation-menu-item/common/types/NavigationMenuItemSection'; +import { canNavigationMenuItemBeDroppedIn } from '@/navigation-menu-item/common/utils/canNavigationMenuItemBeDroppedIn'; +import { computeDndReorderPosition } from '@/navigation-menu-item/common/utils/computeDndReorderPosition'; import { extractFolderIdFromDroppableId } from '@/navigation-menu-item/common/utils/extractFolderIdFromDroppableId'; - +import { isNavigationMenuItemFolder } from '@/navigation-menu-item/common/utils/isNavigationMenuItemFolder'; import { useNavigationMenuItemsData } from '@/navigation-menu-item/display/hooks/useNavigationMenuItemsData'; +import { useSortedNavigationMenuItems } from '@/navigation-menu-item/display/hooks/useSortedNavigationMenuItems'; +import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState'; -export const useHandleNavigationMenuItemDragAndDrop = () => { - const { navigationMenuItems } = useNavigationMenuItemsData(); +const matchesFolderId = ( + item: { folderId?: string | null }, + folderId: string | null, +): boolean => (item.folderId ?? null) === folderId; + +export const useHandleNavigationMenuItemDragAndDrop = ( + section: NavigationMenuItemSection, +) => { + const store = useStore(); + const { navigationMenuItems, workspaceNavigationMenuItems } = + useNavigationMenuItemsData(); const { navigationMenuItemsSorted } = useSortedNavigationMenuItems(); const { updateNavigationMenuItem } = useUpdateNavigationMenuItem(); + const setNavigationMenuItemsDraft = useSetAtomState( + navigationMenuItemsDraftState, + ); const setOpenNavigationMenuItemFolderIds = useSetAtomState( openNavigationMenuItemFolderIdsState, ); - const openDestinationFolder = (folderId: string | null) => { - if (!folderId) { - return; + const isDraftMode = section === 'workspace'; + const config = NAVIGATION_MENU_ITEM_SECTION_DROPPABLE_CONFIG[section]; + const allItems = isDraftMode + ? workspaceNavigationMenuItems + : navigationMenuItems; + + const getSortedItems = (): Array<{ + id: string; + position: number; + folderId?: string | null; + }> => + isDraftMode + ? (store.get(navigationMenuItemsDraftState.atom) ?? []).sort( + (a, b) => a.position - b.position, + ) + : navigationMenuItemsSorted; + + const applyReorder = async ( + draggableId: string, + newPosition: number, + newFolderId?: string | null, + ) => { + const folderUpdate = + newFolderId !== undefined ? { folderId: newFolderId } : {}; + + if (isDraftMode) { + const draft = store.get(navigationMenuItemsDraftState.atom); + if (!draft) return; + + setNavigationMenuItemsDraft( + draft.map((item): NavigationMenuItem => { + if (item.id !== draggableId) return item; + return { ...item, position: newPosition, ...folderUpdate }; + }), + ); + } else { + await updateNavigationMenuItem({ + id: draggableId, + position: newPosition, + ...folderUpdate, + }); + } + }; + + const computeAndApplyReorder = async ( + draggableId: string, + list: Array<{ id: string; position: number }>, + destinationIndex: number, + newFolderId?: string | null, + ) => { + const newPosition = computeDndReorderPosition({ + sortedList: list, + draggableId, + destinationIndex, + }); + await applyReorder(draggableId, newPosition, newFolderId); + }; + + const isDropAllowed = ( + sourceDroppableId: string, + destinationDroppableId: string, + ): boolean => { + if (isDraftMode) { + return ( + sourceDroppableId.startsWith('workspace-') && + destinationDroppableId.startsWith('workspace-') && + store.get(isLayoutCustomizationModeEnabledState.atom) && + isDefined(store.get(navigationMenuItemsDraftState.atom)) + ); } - setOpenNavigationMenuItemFolderIds((current) => { - if (!current.includes(folderId)) { - return [...current, folderId]; - } - return current; + return !canNavigationMenuItemBeDroppedIn({ + navigationMenuItemSection: 'workspace', + droppableId: destinationDroppableId, }); }; const handleNavigationMenuItemDragAndDrop: OnDragEndResponder = async ( - result, + result: Parameters[0] & { + insertBeforeItemId?: string | null; + }, ) => { const { destination, source, draggableId } = result; - if (!destination) { - return; - } + if (!destination) return; if ( destination.droppableId === source.droppableId && @@ -48,104 +130,83 @@ export const useHandleNavigationMenuItemDragAndDrop = () => { return; } - if ( - canNavigationMenuItemBeDroppedIn({ - navigationMenuItemSection: 'workspace', - droppableId: destination.droppableId, - }) - ) { - return; - } + if (!isDropAllowed(source.droppableId, destination.droppableId)) return; - const draggedNavigationMenuItem = navigationMenuItems.find( - (item) => item.id === draggableId, - ); - if (!draggedNavigationMenuItem) { - return; - } + const draggedItem = allItems.find((item) => item.id === draggableId); + if (!draggedItem) return; const destinationFolderId = extractFolderIdFromDroppableId( destination.droppableId, - 'favorite', + section, ); const sourceFolderId = extractFolderIdFromDroppableId( source.droppableId, - 'favorite', + section, ); if ( - destination.droppableId.startsWith( - NavigationMenuItemDroppableIds.FAVORITE_FOLDER_HEADER_PREFIX, - ) + isDraftMode && + isNavigationMenuItemFolder(draggedItem) && + isDefined(destinationFolderId) ) { - if (destinationFolderId === null) - throw new Error('Invalid folder header ID'); - - const folderNavigationMenuItems = navigationMenuItemsSorted.filter( - (item) => item.folderId === destinationFolderId, - ); - - const newPosition = - folderNavigationMenuItems.length === 0 - ? 1 - : folderNavigationMenuItems[folderNavigationMenuItems.length - 1] - .position + 1; - - await updateNavigationMenuItem({ - id: draggableId, - folderId: destinationFolderId, - position: newPosition, - }); - - openDestinationFolder(destinationFolderId); return; } - if (destination.droppableId !== source.droppableId) { - const destinationNavigationMenuItems = navigationMenuItemsSorted.filter( - (item) => item.folderId === destinationFolderId, - ); - - let newPosition; - if (destinationNavigationMenuItems.length === 0) { - newPosition = 1; - } else if (destination.index === 0) { - newPosition = destinationNavigationMenuItems[0].position - 1; - } else if (destination.index >= destinationNavigationMenuItems.length) { - newPosition = - destinationNavigationMenuItems[ - destinationNavigationMenuItems.length - 1 - ].position + 1; - } else { - newPosition = calculateNewPosition({ - destinationIndex: destination.index, - sourceIndex: -1, - items: destinationNavigationMenuItems, - }); + if (destination.droppableId.startsWith(config.folderHeaderPrefix)) { + if (destinationFolderId === null) { + throw new Error('Invalid folder header ID'); } - await updateNavigationMenuItem({ - id: draggableId, - folderId: destinationFolderId ?? null, - position: newPosition, - }); + const folderList = getSortedItems().filter((item) => + matchesFolderId(item, destinationFolderId), + ); + + await computeAndApplyReorder( + draggableId, + folderList, + folderList.length, + destinationFolderId, + ); + setOpenNavigationMenuItemFolderIds((current) => + current.includes(destinationFolderId) + ? current + : [...current, destinationFolderId], + ); return; } - const navigationMenuItemsInSameList = navigationMenuItemsSorted - .filter((item) => item.folderId === sourceFolderId) - .filter((item) => item.id !== draggableId); + if (sourceFolderId === destinationFolderId) { + const sourceList = getSortedItems().filter((item) => + matchesFolderId(item, sourceFolderId), + ); - const newPosition = calculateNewPosition({ - destinationIndex: destination.index, - sourceIndex: source.index, - items: navigationMenuItemsInSameList, - }); + if (!sourceList.some((item) => item.id === draggableId)) return; - await updateNavigationMenuItem({ - id: draggableId, - position: newPosition, - }); + const insertBeforeIndex = + result.insertBeforeItemId != null + ? sourceList.findIndex( + (item) => item.id === result.insertBeforeItemId, + ) + : -1; + + await computeAndApplyReorder( + draggableId, + sourceList, + insertBeforeIndex >= 0 ? insertBeforeIndex : destination.index, + ); + return; + } + + const destinationList = getSortedItems().filter((item) => + matchesFolderId(item, destinationFolderId), + ); + + await computeAndApplyReorder( + draggableId, + destinationList, + destination.index, + destinationFolderId ?? null, + ); }; return { handleNavigationMenuItemDragAndDrop }; diff --git a/packages/twenty-front/src/modules/navigation-menu-item/display/dnd/hooks/useHandleWorkspaceNavigationMenuItemDragAndDrop.ts b/packages/twenty-front/src/modules/navigation-menu-item/display/dnd/hooks/useHandleWorkspaceNavigationMenuItemDragAndDrop.ts deleted file mode 100644 index 7782d899fc..0000000000 --- a/packages/twenty-front/src/modules/navigation-menu-item/display/dnd/hooks/useHandleWorkspaceNavigationMenuItemDragAndDrop.ts +++ /dev/null @@ -1,177 +0,0 @@ -import { type OnDragEndResponder } from '@hello-pangea/dnd'; -import { useStore } from 'jotai'; -import { type NavigationMenuItem } from '~/generated-metadata/graphql'; - -import { isLayoutCustomizationModeEnabledState } from '@/layout-customization/states/isLayoutCustomizationModeEnabledState'; -import { NavigationMenuItemDroppableIds } from '@/navigation-menu-item/common/constants/NavigationMenuItemDroppableIds'; -import { navigationMenuItemsDraftState } from '@/navigation-menu-item/common/states/navigationMenuItemsDraftState'; -import { openNavigationMenuItemFolderIdsState } from '@/navigation-menu-item/common/states/openNavigationMenuItemFolderIdsState'; -import { getPositionBetween } from '@/navigation-menu-item/common/utils/getPositionBetween'; -import { isNavigationMenuItemFolder } from '@/navigation-menu-item/common/utils/isNavigationMenuItemFolder'; -import { - matchesWorkspaceFolderId, - validateAndExtractWorkspaceFolderId, -} from '@/navigation-menu-item/common/utils/validateAndExtractWorkspaceFolderId'; -import { useSetAtomState } from '@/ui/utilities/state/jotai/hooks/useSetAtomState'; - -import { isDefined } from 'twenty-shared/utils'; -import { useNavigationMenuItemsData } from '@/navigation-menu-item/display/hooks/useNavigationMenuItemsData'; - -export const useHandleWorkspaceNavigationMenuItemDragAndDrop = () => { - const store = useStore(); - const { workspaceNavigationMenuItems } = useNavigationMenuItemsData(); - const setNavigationMenuItemsDraft = useSetAtomState( - navigationMenuItemsDraftState, - ); - const setOpenNavigationMenuItemFolderIds = useSetAtomState( - openNavigationMenuItemFolderIdsState, - ); - - const openDestinationFolder = (folderId: string | null) => { - if (!folderId) { - return; - } - - setOpenNavigationMenuItemFolderIds((current) => { - if (!current.includes(folderId)) { - return [...current, folderId]; - } - return current; - }); - }; - - const handleWorkspaceNavigationMenuItemDragAndDrop: OnDragEndResponder = ( - result: Parameters[0] & { - insertBeforeItemId?: string | null; - }, - ) => { - const { destination, source, draggableId } = result; - - if (!destination) { - return; - } - - if ( - destination.droppableId === source.droppableId && - destination.index === source.index - ) { - return; - } - - const isWorkspaceDrop = - source.droppableId.startsWith('workspace-') && - destination.droppableId.startsWith('workspace-'); - - if (!isWorkspaceDrop) { - return; - } - - const navigationMenuItemsDraft = store.get( - navigationMenuItemsDraftState.atom, - ); - const isLayoutCustomizationModeEnabled = store.get( - isLayoutCustomizationModeEnabledState.atom, - ); - if (!isLayoutCustomizationModeEnabled || !navigationMenuItemsDraft) { - return; - } - - const draggedItem = workspaceNavigationMenuItems.find( - (item) => item.id === draggableId, - ); - - if (!draggedItem) { - return; - } - - const destinationFolderId = validateAndExtractWorkspaceFolderId( - destination.droppableId, - ); - - if ( - isNavigationMenuItemFolder(draggedItem) && - isDefined(destinationFolderId) - ) { - return; - } - const sourceFolderId = validateAndExtractWorkspaceFolderId( - source.droppableId, - ); - - const isDropOnFolderHeader = destination.droppableId.startsWith( - NavigationMenuItemDroppableIds.WORKSPACE_FOLDER_HEADER_PREFIX, - ); - - if (isDropOnFolderHeader && isDefined(destinationFolderId)) { - openDestinationFolder(destinationFolderId); - } - - const sourceList = (navigationMenuItemsDraft ?? []) - .filter((item) => matchesWorkspaceFolderId(item, sourceFolderId)) - .sort((a, b) => a.position - b.position); - - const destinationList = (navigationMenuItemsDraft ?? []) - .filter((item) => matchesWorkspaceFolderId(item, destinationFolderId)) - .sort((a, b) => a.position - b.position); - - if (!sourceList.some((item) => item.id === draggableId)) { - return; - } - - const isSameList = sourceFolderId === destinationFolderId; - - if (isSameList) { - const listWithoutDragged = sourceList.filter( - (item) => item.id !== draggableId, - ); - const sourceIndexInList = sourceList.findIndex( - (item) => item.id === draggableId, - ); - const insertBeforeIndex = - result.insertBeforeItemId != null - ? sourceList.findIndex( - (item) => item.id === result.insertBeforeItemId, - ) - : -1; - const destinationIndexInFullList = - insertBeforeIndex >= 0 ? insertBeforeIndex : destination.index; - const destIndexInListWithoutDragged = - sourceIndexInList < destinationIndexInFullList && - destinationIndexInFullList <= listWithoutDragged.length - ? destinationIndexInFullList - 1 - : destinationIndexInFullList; - const prevItem = listWithoutDragged[destIndexInListWithoutDragged - 1]; - const nextItem = listWithoutDragged[destIndexInListWithoutDragged]; - const newPosition = getPositionBetween( - prevItem?.position, - nextItem?.position, - ); - const updatedDraft = navigationMenuItemsDraft.map( - (item): NavigationMenuItem => - item.id === draggableId ? { ...item, position: newPosition } : item, - ); - setNavigationMenuItemsDraft(updatedDraft); - return; - } - - const prevItem = destinationList[destination.index - 1]; - const nextItem = destinationList[destination.index]; - const newPosition = getPositionBetween( - prevItem?.position, - nextItem?.position, - ); - const updatedDraft = navigationMenuItemsDraft.map( - (item): NavigationMenuItem => { - if (item.id !== draggableId) return item; - return { - ...item, - position: newPosition, - folderId: destinationFolderId, - }; - }, - ); - setNavigationMenuItemsDraft(updatedDraft); - }; - - return { handleWorkspaceNavigationMenuItemDragAndDrop }; -}; diff --git a/packages/twenty-front/src/modules/navigation-menu-item/display/dnd/hooks/useNavigationMenuItemDndKit.ts b/packages/twenty-front/src/modules/navigation-menu-item/display/dnd/hooks/useNavigationMenuItemDndKit.ts index ab93fa622d..b9f5440298 100644 --- a/packages/twenty-front/src/modules/navigation-menu-item/display/dnd/hooks/useNavigationMenuItemDndKit.ts +++ b/packages/twenty-front/src/modules/navigation-menu-item/display/dnd/hooks/useNavigationMenuItemDndKit.ts @@ -18,7 +18,6 @@ import { isNavigationMenuItemFolder } from '@/navigation-menu-item/common/utils/ import { DROP_RESULT_OPTIONS } from '@/navigation-menu-item/display/dnd/constants/navigationMenuItemDndKitDropResultOptions'; import { useHandleAddToNavigationDrop } from '@/navigation-menu-item/display/dnd/hooks/useHandleAddToNavigationDrop'; import { useHandleNavigationMenuItemDragAndDrop } from '@/navigation-menu-item/display/dnd/hooks/useHandleNavigationMenuItemDragAndDrop'; -import { useHandleWorkspaceNavigationMenuItemDragAndDrop } from '@/navigation-menu-item/display/dnd/hooks/useHandleWorkspaceNavigationMenuItemDragAndDrop'; import { resolveDropTarget } from '@/navigation-menu-item/display/dnd/utils/navigationMenuItemDndKitResolveDropTarget'; import { toDropResult } from '@/navigation-menu-item/display/dnd/utils/navigationMenuItemDndKitToDropResult'; import { useNavigationMenuItemsData } from '@/navigation-menu-item/display/hooks/useNavigationMenuItemsData'; @@ -92,9 +91,7 @@ export const useNavigationMenuItemDndKit = ( const { workspaceNavigationMenuItems } = useNavigationMenuItemsDraftState(); const { handleAddToNavigationDrop } = useHandleAddToNavigationDrop(); const { handleNavigationMenuItemDragAndDrop } = - useHandleNavigationMenuItemDragAndDrop(); - const { handleWorkspaceNavigationMenuItemDragAndDrop } = - useHandleWorkspaceNavigationMenuItemDragAndDrop(); + useHandleNavigationMenuItemDragAndDrop(sectionType); const items = isWorkspaceSection ? workspaceNavigationMenuItems @@ -169,25 +166,13 @@ export const useNavigationMenuItemDndKit = ( [sectionType, getAddToNavPayload, isSourceFolderDrag], ); - const applyWorkspaceReorderIfAllowed = useCallback( + const applyWorkspaceReorder = useCallback( ( id: string, source: DropDestination, destination: DropDestination, insertBeforeItemId?: string | null, ) => { - const draggedItem = getNavItemById(id); - const destFolderId = extractFolderIdFromDroppableId( - destination.droppableId, - 'workspace', - ); - if ( - isDefined(destFolderId) && - isDefined(draggedItem) && - isNavigationMenuItemFolder(draggedItem) - ) { - return; - } const result = toDropResult( id, { @@ -197,7 +182,7 @@ export const useNavigationMenuItemDndKit = ( destination, ); const provided: ResponderProvided = { announce: () => {} }; - handleWorkspaceNavigationMenuItemDragAndDrop( + handleNavigationMenuItemDragAndDrop( { ...result, ...DROP_RESULT_OPTIONS, @@ -206,7 +191,7 @@ export const useNavigationMenuItemDndKit = ( provided, ); }, - [getNavItemById, handleWorkspaceNavigationMenuItemDragAndDrop], + [handleNavigationMenuItemDragAndDrop], ); const handleDragStart = (event: DragStartPayload) => { @@ -344,7 +329,7 @@ export const useNavigationMenuItemDndKit = ( const insertBeforeItemId = resolved.isTargetFolder ? null : String(target?.id ?? ''); - applyWorkspaceReorderIfAllowed( + applyWorkspaceReorder( draggableId, { droppableId: initialGroup, index: initialIndex }, resolved.destination, @@ -388,7 +373,7 @@ export const useNavigationMenuItemDndKit = ( droppableId: destination.droppableId, }) ) { - applyWorkspaceReorderIfAllowed( + applyWorkspaceReorder( draggableId, { droppableId: data?.sourceDroppableId ?? '', diff --git a/packages/twenty-front/src/modules/navigation-menu-item/display/folder/components/NavigationMenuItemFolderDnd.tsx b/packages/twenty-front/src/modules/navigation-menu-item/display/folder/components/NavigationMenuItemFolderDnd.tsx index 8492214273..2081c4d1fe 100644 --- a/packages/twenty-front/src/modules/navigation-menu-item/display/folder/components/NavigationMenuItemFolderDnd.tsx +++ b/packages/twenty-front/src/modules/navigation-menu-item/display/folder/components/NavigationMenuItemFolderDnd.tsx @@ -58,7 +58,7 @@ const StyledFolderContainer = styled.div<{ border: ${({ $isSelectedInEditMode }) => $isSelectedInEditMode ? `1px solid ${themeCssVariables.color.blue}` - : '1px solid transparent'}; + : 'none'}; border-radius: ${themeCssVariables.border.radius.sm}; transition: background-color 150ms ease-in-out; @@ -240,7 +240,6 @@ export const NavigationMenuItemFolderDnd = ({ triggerEvent="CLICK" preventCollapseOnMobile={isMobile} isDragging={isDragging} - alwaysShowRightOptions /> ); diff --git a/packages/twenty-front/src/modules/navigation-menu-item/display/folder/hooks/useCreateNavigationMenuItemFolder.ts b/packages/twenty-front/src/modules/navigation-menu-item/display/folder/hooks/useCreateNavigationMenuItemFolder.ts index 650c58c3d2..dee68c6a6c 100644 --- a/packages/twenty-front/src/modules/navigation-menu-item/display/folder/hooks/useCreateNavigationMenuItemFolder.ts +++ b/packages/twenty-front/src/modules/navigation-menu-item/display/folder/hooks/useCreateNavigationMenuItemFolder.ts @@ -11,9 +11,6 @@ export const useCreateNavigationMenuItemFolder = () => { const [createNavigationMenuItemMutation] = useMutation( CreateNavigationMenuItemDocument, - { - refetchQueries: ['FindManyNavigationMenuItems'], - }, ); const createNewNavigationMenuItemFolder = async ( @@ -23,20 +20,16 @@ export const useCreateNavigationMenuItemFolder = () => { return; } - const folderNavigationMenuItems = navigationMenuItems.filter( + const topLevelItems = navigationMenuItems.filter( (item) => - isDefined(item.name) && - !item.folderId && - !item.targetRecordId && - !item.targetObjectMetadataId && - !item.viewId && + !isDefined(item.folderId) && item.userWorkspaceId === currentWorkspaceMemberId, ); - const maxPosition = Math.max( - ...folderNavigationMenuItems.map((item) => item.position), - 0, - ); + const minPosition = + topLevelItems.length > 0 + ? Math.min(...topLevelItems.map((item) => item.position)) + : 1; await createNavigationMenuItemMutation({ variables: { @@ -47,7 +40,7 @@ export const useCreateNavigationMenuItemFolder = () => { targetObjectMetadataId: null, userWorkspaceId: currentWorkspaceMemberId, folderId: null, - position: maxPosition + 1, + position: minPosition - 1, }, }, }); diff --git a/packages/twenty-front/src/modules/navigation-menu-item/edit/hooks/useSaveNavigationMenuItemsDraft.ts b/packages/twenty-front/src/modules/navigation-menu-item/edit/hooks/useSaveNavigationMenuItemsDraft.ts index d427e0d082..c217dc01e9 100644 --- a/packages/twenty-front/src/modules/navigation-menu-item/edit/hooks/useSaveNavigationMenuItemsDraft.ts +++ b/packages/twenty-front/src/modules/navigation-menu-item/edit/hooks/useSaveNavigationMenuItemsDraft.ts @@ -23,9 +23,6 @@ export const useSaveNavigationMenuItemsDraft = () => { const { deleteNavigationMenuItem } = useDeleteNavigationMenuItem(); const [createNavigationMenuItemMutation] = useMutation( CreateNavigationMenuItemDocument, - { - refetchQueries: ['FindManyNavigationMenuItems'], - }, ); const { updateOneObjectMetadataItem } = useUpdateOneObjectMetadataItem(); diff --git a/packages/twenty-sdk/src/clients/generated/metadata/schema.graphql b/packages/twenty-sdk/src/clients/generated/metadata/schema.graphql index e44873e0ec..3f2fead812 100644 --- a/packages/twenty-sdk/src/clients/generated/metadata/schema.graphql +++ b/packages/twenty-sdk/src/clients/generated/metadata/schema.graphql @@ -1236,6 +1236,47 @@ enum PageLayoutType { DASHBOARD } +type FileWithSignedUrl { + id: UUID! + path: String! + size: Float! + createdAt: DateTime! + url: String! +} + +type RecordIdentifier { + id: UUID! + labelIdentifier: String! + imageIdentifier: String +} + +type NavigationMenuItem { + id: UUID! + userWorkspaceId: UUID + targetRecordId: UUID + targetObjectMetadataId: UUID + viewId: UUID + type: NavigationMenuItemType! + name: String + link: String + icon: String + color: String + folderId: UUID + position: Float! + applicationId: UUID + createdAt: DateTime! + updatedAt: DateTime! + targetRecordIdentifier: RecordIdentifier +} + +enum NavigationMenuItemType { + VIEW + FOLDER + LINK + OBJECT + RECORD +} + type ObjectRecordEventProperties { updatedFields: [String!] before: JSON @@ -1482,14 +1523,6 @@ type ApprovedAccessDomain { createdAt: DateTime! } -type FileWithSignedUrl { - id: UUID! - path: String! - size: Float! - createdAt: DateTime! - url: String! -} - type WorkspaceInvitation { id: UUID! email: String! @@ -1924,39 +1957,6 @@ type WorkspaceInviteHashValid { isValid: Boolean! } -type RecordIdentifier { - id: UUID! - labelIdentifier: String! - imageIdentifier: String -} - -type NavigationMenuItem { - id: UUID! - userWorkspaceId: UUID - targetRecordId: UUID - targetObjectMetadataId: UUID - viewId: UUID - type: NavigationMenuItemType! - name: String - link: String - icon: String - color: String - folderId: UUID - position: Float! - applicationId: UUID - createdAt: DateTime! - updatedAt: DateTime! - targetRecordIdentifier: RecordIdentifier -} - -enum NavigationMenuItemType { - VIEW - FOLDER - LINK - OBJECT - RECORD -} - type LogicFunctionExecutionResult { """Execution result in JSON format""" data: JSON @@ -2925,6 +2925,8 @@ type EventLogQueryResult { } type Query { + navigationMenuItems: [NavigationMenuItem!]! + navigationMenuItem(id: UUID!): NavigationMenuItem getPageLayoutWidgets(pageLayoutTabId: String!): [PageLayoutWidget!]! getPageLayoutWidget(id: String!): PageLayoutWidget! getPageLayoutTabs(pageLayoutId: String!): [PageLayoutTab!]! @@ -2978,13 +2980,11 @@ type Query { enterprisePortalSession(returnUrlPath: String): String enterpriseCheckoutSession(billingInterval: String): String enterpriseSubscriptionStatus: EnterpriseSubscriptionStatusDTO - navigationMenuItems: [NavigationMenuItem!]! - navigationMenuItem(id: UUID!): NavigationMenuItem - apiKeys: [ApiKey!]! - apiKey(input: GetApiKeyInput!): ApiKey getRoles: [Role!]! findWorkspaceInvitations: [WorkspaceInvitation!]! getApprovedAccessDomains: [ApprovedAccessDomain!]! + apiKeys: [ApiKey!]! + apiKey(input: GetApiKeyInput!): ApiKey getToolIndex: [ToolIndexEntry!]! getToolInputSchema(toolName: String!): JSON field( @@ -3171,6 +3171,15 @@ input BarChartDataInput { type Mutation { addQueryToEventStream(input: AddQuerySubscriptionInput!): Boolean! removeQueryFromEventStream(input: RemoveQueryFromEventStreamInput!): Boolean! + createNavigationMenuItem(input: CreateNavigationMenuItemInput!): NavigationMenuItem! + updateNavigationMenuItem(input: UpdateOneNavigationMenuItemInput!): NavigationMenuItem! + deleteNavigationMenuItem(id: UUID!): NavigationMenuItem! + uploadAIChatFile(file: Upload!): FileWithSignedUrl! + uploadWorkflowFile(file: Upload!): FileWithSignedUrl! + uploadWorkspaceLogo(file: Upload!): FileWithSignedUrl! + uploadWorkspaceMemberProfilePicture(file: Upload!): FileWithSignedUrl! + uploadFilesFieldFile(file: Upload!, fieldMetadataId: String!): FileWithSignedUrl! + uploadFilesFieldFileByUniversalIdentifier(file: Upload!, fieldMetadataUniversalIdentifier: String!): FileWithSignedUrl! createObjectEvent(event: String!, recordId: UUID!, objectMetadataId: UUID!, properties: JSON): Analytics! trackAnalytics(type: AnalyticsType!, name: String, event: String, properties: JSON): Analytics! createPageLayoutWidget(input: CreatePageLayoutWidgetInput!): PageLayoutWidget! @@ -3218,12 +3227,6 @@ type Mutation { createOneAgent(input: CreateAgentInput!): Agent! updateOneAgent(input: UpdateAgentInput!): Agent! deleteOneAgent(input: AgentIdInput!): Agent! - uploadAIChatFile(file: Upload!): FileWithSignedUrl! - uploadWorkflowFile(file: Upload!): FileWithSignedUrl! - uploadWorkspaceLogo(file: Upload!): FileWithSignedUrl! - uploadWorkspaceMemberProfilePicture(file: Upload!): FileWithSignedUrl! - uploadFilesFieldFile(file: Upload!, fieldMetadataId: String!): FileWithSignedUrl! - uploadFilesFieldFileByUniversalIdentifier(file: Upload!, fieldMetadataUniversalIdentifier: String!): FileWithSignedUrl! checkoutSession(recurringInterval: SubscriptionInterval!, plan: BillingPlanKey! = PRO, requirePaymentMethod: Boolean! = true, successUrlPath: String): BillingSession! switchSubscriptionInterval: BillingUpdate! switchBillingPlan: BillingUpdate! @@ -3234,13 +3237,6 @@ type Mutation { cancelSwitchMeteredPrice: BillingUpdate! refreshEnterpriseValidityToken: Boolean! setEnterpriseKey(enterpriseKey: String!): EnterpriseLicenseInfoDTO! - createNavigationMenuItem(input: CreateNavigationMenuItemInput!): NavigationMenuItem! - updateNavigationMenuItem(input: UpdateOneNavigationMenuItemInput!): NavigationMenuItem! - deleteNavigationMenuItem(id: UUID!): NavigationMenuItem! - createApiKey(input: CreateApiKeyInput!): ApiKey! - updateApiKey(input: UpdateApiKeyInput!): ApiKey - revokeApiKey(input: RevokeApiKeyInput!): ApiKey - assignRoleToApiKey(apiKeyId: UUID!, roleId: UUID!): Boolean! updateWorkspaceMemberRole(workspaceMemberId: UUID!, roleId: UUID!): WorkspaceMember! createOneRole(createRoleInput: CreateRoleInput!): Role! updateOneRole(updateRoleInput: UpdateRoleInput!): Role! @@ -3259,6 +3255,10 @@ type Mutation { createApprovedAccessDomain(input: CreateApprovedAccessDomainInput!): ApprovedAccessDomain! deleteApprovedAccessDomain(input: DeleteApprovedAccessDomainInput!): Boolean! validateApprovedAccessDomain(input: ValidateApprovedAccessDomainInput!): ApprovedAccessDomain! + createApiKey(input: CreateApiKeyInput!): ApiKey! + updateApiKey(input: UpdateApiKeyInput!): ApiKey + revokeApiKey(input: RevokeApiKeyInput!): ApiKey + assignRoleToApiKey(apiKeyId: UUID!, roleId: UUID!): Boolean! createOneField(input: CreateOneFieldMetadataInput!): Field! updateOneField(input: UpdateOneFieldMetadataInput!): Field! deleteOneField(input: DeleteOneFieldInput!): Field! @@ -3373,6 +3373,41 @@ input RemoveQueryFromEventStreamInput { queryId: String! } +input CreateNavigationMenuItemInput { + id: UUID + userWorkspaceId: UUID + targetRecordId: UUID + targetObjectMetadataId: UUID + viewId: UUID + type: NavigationMenuItemType! + name: String + link: String + icon: String + color: String + folderId: UUID + position: Float +} + +input UpdateOneNavigationMenuItemInput { + """The id of the record to update""" + id: UUID! + + """The record to update""" + update: UpdateNavigationMenuItemInput! +} + +input UpdateNavigationMenuItemInput { + folderId: UUID + position: Float + name: String + link: String + icon: String + color: String +} + +"""The `Upload` scalar type represents a file upload.""" +scalar Upload + enum AnalyticsType { PAGEVIEW TRACK @@ -3793,58 +3828,6 @@ input UpdateAgentInput { evaluationInputs: [String!] } -"""The `Upload` scalar type represents a file upload.""" -scalar Upload - -input CreateNavigationMenuItemInput { - userWorkspaceId: UUID - targetRecordId: UUID - targetObjectMetadataId: UUID - viewId: UUID - type: NavigationMenuItemType! - name: String - link: String - icon: String - color: String - folderId: UUID - position: Float -} - -input UpdateOneNavigationMenuItemInput { - """The id of the record to update""" - id: UUID! - - """The record to update""" - update: UpdateNavigationMenuItemInput! -} - -input UpdateNavigationMenuItemInput { - folderId: UUID - position: Float - name: String - link: String - icon: String - color: String -} - -input CreateApiKeyInput { - name: String! - expiresAt: String! - revokedAt: String - roleId: UUID! -} - -input UpdateApiKeyInput { - id: UUID! - name: String - expiresAt: String - revokedAt: String -} - -input RevokeApiKeyInput { - id: UUID! -} - input CreateRoleInput { id: String label: String! @@ -3954,6 +3937,24 @@ input ValidateApprovedAccessDomainInput { approvedAccessDomainId: UUID! } +input CreateApiKeyInput { + name: String! + expiresAt: String! + revokedAt: String + roleId: UUID! +} + +input UpdateApiKeyInput { + id: UUID! + name: String + expiresAt: String + revokedAt: String +} + +input RevokeApiKeyInput { + id: UUID! +} + input CreateOneFieldMetadataInput { """The record to create""" field: CreateFieldInput! diff --git a/packages/twenty-sdk/src/clients/generated/metadata/schema.ts b/packages/twenty-sdk/src/clients/generated/metadata/schema.ts index ffcfb748d2..212c4b415e 100644 --- a/packages/twenty-sdk/src/clients/generated/metadata/schema.ts +++ b/packages/twenty-sdk/src/clients/generated/metadata/schema.ts @@ -963,6 +963,44 @@ export interface PageLayout { export type PageLayoutType = 'RECORD_INDEX' | 'RECORD_PAGE' | 'DASHBOARD' +export interface FileWithSignedUrl { + id: Scalars['UUID'] + path: Scalars['String'] + size: Scalars['Float'] + createdAt: Scalars['DateTime'] + url: Scalars['String'] + __typename: 'FileWithSignedUrl' +} + +export interface RecordIdentifier { + id: Scalars['UUID'] + labelIdentifier: Scalars['String'] + imageIdentifier?: Scalars['String'] + __typename: 'RecordIdentifier' +} + +export interface NavigationMenuItem { + id: Scalars['UUID'] + userWorkspaceId?: Scalars['UUID'] + targetRecordId?: Scalars['UUID'] + targetObjectMetadataId?: Scalars['UUID'] + viewId?: Scalars['UUID'] + type: NavigationMenuItemType + name?: Scalars['String'] + link?: Scalars['String'] + icon?: Scalars['String'] + color?: Scalars['String'] + folderId?: Scalars['UUID'] + position: Scalars['Float'] + applicationId?: Scalars['UUID'] + createdAt: Scalars['DateTime'] + updatedAt: Scalars['DateTime'] + targetRecordIdentifier?: RecordIdentifier + __typename: 'NavigationMenuItem' +} + +export type NavigationMenuItemType = 'VIEW' | 'FOLDER' | 'LINK' | 'OBJECT' | 'RECORD' + export interface ObjectRecordEventProperties { updatedFields?: Scalars['String'][] before?: Scalars['JSON'] @@ -1203,15 +1241,6 @@ export interface ApprovedAccessDomain { __typename: 'ApprovedAccessDomain' } -export interface FileWithSignedUrl { - id: Scalars['UUID'] - path: Scalars['String'] - size: Scalars['Float'] - createdAt: Scalars['DateTime'] - url: Scalars['String'] - __typename: 'FileWithSignedUrl' -} - export interface WorkspaceInvitation { id: Scalars['UUID'] email: Scalars['String'] @@ -1658,35 +1687,6 @@ export interface WorkspaceInviteHashValid { __typename: 'WorkspaceInviteHashValid' } -export interface RecordIdentifier { - id: Scalars['UUID'] - labelIdentifier: Scalars['String'] - imageIdentifier?: Scalars['String'] - __typename: 'RecordIdentifier' -} - -export interface NavigationMenuItem { - id: Scalars['UUID'] - userWorkspaceId?: Scalars['UUID'] - targetRecordId?: Scalars['UUID'] - targetObjectMetadataId?: Scalars['UUID'] - viewId?: Scalars['UUID'] - type: NavigationMenuItemType - name?: Scalars['String'] - link?: Scalars['String'] - icon?: Scalars['String'] - color?: Scalars['String'] - folderId?: Scalars['UUID'] - position: Scalars['Float'] - applicationId?: Scalars['UUID'] - createdAt: Scalars['DateTime'] - updatedAt: Scalars['DateTime'] - targetRecordIdentifier?: RecordIdentifier - __typename: 'NavigationMenuItem' -} - -export type NavigationMenuItemType = 'VIEW' | 'FOLDER' | 'LINK' | 'OBJECT' | 'RECORD' - export interface LogicFunctionExecutionResult { /** Execution result in JSON format */ data?: Scalars['JSON'] @@ -2565,6 +2565,8 @@ export interface EventLogQueryResult { } export interface Query { + navigationMenuItems: NavigationMenuItem[] + navigationMenuItem?: NavigationMenuItem getPageLayoutWidgets: PageLayoutWidget[] getPageLayoutWidget: PageLayoutWidget getPageLayoutTabs: PageLayoutTab[] @@ -2600,13 +2602,11 @@ export interface Query { enterprisePortalSession?: Scalars['String'] enterpriseCheckoutSession?: Scalars['String'] enterpriseSubscriptionStatus?: EnterpriseSubscriptionStatusDTO - navigationMenuItems: NavigationMenuItem[] - navigationMenuItem?: NavigationMenuItem - apiKeys: ApiKey[] - apiKey?: ApiKey getRoles: Role[] findWorkspaceInvitations: WorkspaceInvitation[] getApprovedAccessDomains: ApprovedAccessDomain[] + apiKeys: ApiKey[] + apiKey?: ApiKey getToolIndex: ToolIndexEntry[] getToolInputSchema?: Scalars['JSON'] field: Field @@ -2683,6 +2683,15 @@ export type EventLogTable = 'WORKSPACE_EVENT' | 'PAGEVIEW' | 'OBJECT_EVENT' export interface Mutation { addQueryToEventStream: Scalars['Boolean'] removeQueryFromEventStream: Scalars['Boolean'] + createNavigationMenuItem: NavigationMenuItem + updateNavigationMenuItem: NavigationMenuItem + deleteNavigationMenuItem: NavigationMenuItem + uploadAIChatFile: FileWithSignedUrl + uploadWorkflowFile: FileWithSignedUrl + uploadWorkspaceLogo: FileWithSignedUrl + uploadWorkspaceMemberProfilePicture: FileWithSignedUrl + uploadFilesFieldFile: FileWithSignedUrl + uploadFilesFieldFileByUniversalIdentifier: FileWithSignedUrl createObjectEvent: Analytics trackAnalytics: Analytics createPageLayoutWidget: PageLayoutWidget @@ -2730,12 +2739,6 @@ export interface Mutation { createOneAgent: Agent updateOneAgent: Agent deleteOneAgent: Agent - uploadAIChatFile: FileWithSignedUrl - uploadWorkflowFile: FileWithSignedUrl - uploadWorkspaceLogo: FileWithSignedUrl - uploadWorkspaceMemberProfilePicture: FileWithSignedUrl - uploadFilesFieldFile: FileWithSignedUrl - uploadFilesFieldFileByUniversalIdentifier: FileWithSignedUrl checkoutSession: BillingSession switchSubscriptionInterval: BillingUpdate switchBillingPlan: BillingUpdate @@ -2746,13 +2749,6 @@ export interface Mutation { cancelSwitchMeteredPrice: BillingUpdate refreshEnterpriseValidityToken: Scalars['Boolean'] setEnterpriseKey: EnterpriseLicenseInfoDTO - createNavigationMenuItem: NavigationMenuItem - updateNavigationMenuItem: NavigationMenuItem - deleteNavigationMenuItem: NavigationMenuItem - createApiKey: ApiKey - updateApiKey?: ApiKey - revokeApiKey?: ApiKey - assignRoleToApiKey: Scalars['Boolean'] updateWorkspaceMemberRole: WorkspaceMember createOneRole: Role updateOneRole: Role @@ -2771,6 +2767,10 @@ export interface Mutation { createApprovedAccessDomain: ApprovedAccessDomain deleteApprovedAccessDomain: Scalars['Boolean'] validateApprovedAccessDomain: ApprovedAccessDomain + createApiKey: ApiKey + updateApiKey?: ApiKey + revokeApiKey?: ApiKey + assignRoleToApiKey: Scalars['Boolean'] createOneField: Field updateOneField: Field deleteOneField: Field @@ -3898,6 +3898,45 @@ export interface PageLayoutGenqlSelection{ __scalar?: boolean | number } +export interface FileWithSignedUrlGenqlSelection{ + id?: boolean | number + path?: boolean | number + size?: boolean | number + createdAt?: boolean | number + url?: boolean | number + __typename?: boolean | number + __scalar?: boolean | number +} + +export interface RecordIdentifierGenqlSelection{ + id?: boolean | number + labelIdentifier?: boolean | number + imageIdentifier?: boolean | number + __typename?: boolean | number + __scalar?: boolean | number +} + +export interface NavigationMenuItemGenqlSelection{ + id?: boolean | number + userWorkspaceId?: boolean | number + targetRecordId?: boolean | number + targetObjectMetadataId?: boolean | number + viewId?: boolean | number + type?: boolean | number + name?: boolean | number + link?: boolean | number + icon?: boolean | number + color?: boolean | number + folderId?: boolean | number + position?: boolean | number + applicationId?: boolean | number + createdAt?: boolean | number + updatedAt?: boolean | number + targetRecordIdentifier?: RecordIdentifierGenqlSelection + __typename?: boolean | number + __scalar?: boolean | number +} + export interface ObjectRecordEventPropertiesGenqlSelection{ updatedFields?: boolean | number before?: boolean | number @@ -4143,16 +4182,6 @@ export interface ApprovedAccessDomainGenqlSelection{ __scalar?: boolean | number } -export interface FileWithSignedUrlGenqlSelection{ - id?: boolean | number - path?: boolean | number - size?: boolean | number - createdAt?: boolean | number - url?: boolean | number - __typename?: boolean | number - __scalar?: boolean | number -} - export interface WorkspaceInvitationGenqlSelection{ id?: boolean | number email?: boolean | number @@ -4648,35 +4677,6 @@ export interface WorkspaceInviteHashValidGenqlSelection{ __scalar?: boolean | number } -export interface RecordIdentifierGenqlSelection{ - id?: boolean | number - labelIdentifier?: boolean | number - imageIdentifier?: boolean | number - __typename?: boolean | number - __scalar?: boolean | number -} - -export interface NavigationMenuItemGenqlSelection{ - id?: boolean | number - userWorkspaceId?: boolean | number - targetRecordId?: boolean | number - targetObjectMetadataId?: boolean | number - viewId?: boolean | number - type?: boolean | number - name?: boolean | number - link?: boolean | number - icon?: boolean | number - color?: boolean | number - folderId?: boolean | number - position?: boolean | number - applicationId?: boolean | number - createdAt?: boolean | number - updatedAt?: boolean | number - targetRecordIdentifier?: RecordIdentifierGenqlSelection - __typename?: boolean | number - __scalar?: boolean | number -} - export interface LogicFunctionExecutionResultGenqlSelection{ /** Execution result in JSON format */ data?: boolean | number @@ -5607,6 +5607,8 @@ export interface EventLogQueryResultGenqlSelection{ } export interface QueryGenqlSelection{ + navigationMenuItems?: NavigationMenuItemGenqlSelection + navigationMenuItem?: (NavigationMenuItemGenqlSelection & { __args: {id: Scalars['UUID']} }) getPageLayoutWidgets?: (PageLayoutWidgetGenqlSelection & { __args: {pageLayoutTabId: Scalars['String']} }) getPageLayoutWidget?: (PageLayoutWidgetGenqlSelection & { __args: {id: Scalars['String']} }) getPageLayoutTabs?: (PageLayoutTabGenqlSelection & { __args: {pageLayoutId: Scalars['String']} }) @@ -5654,13 +5656,11 @@ export interface QueryGenqlSelection{ enterprisePortalSession?: { __args: {returnUrlPath?: (Scalars['String'] | null)} } | boolean | number enterpriseCheckoutSession?: { __args: {billingInterval?: (Scalars['String'] | null)} } | boolean | number enterpriseSubscriptionStatus?: EnterpriseSubscriptionStatusDTOGenqlSelection - navigationMenuItems?: NavigationMenuItemGenqlSelection - navigationMenuItem?: (NavigationMenuItemGenqlSelection & { __args: {id: Scalars['UUID']} }) - apiKeys?: ApiKeyGenqlSelection - apiKey?: (ApiKeyGenqlSelection & { __args: {input: GetApiKeyInput} }) getRoles?: RoleGenqlSelection findWorkspaceInvitations?: WorkspaceInvitationGenqlSelection getApprovedAccessDomains?: ApprovedAccessDomainGenqlSelection + apiKeys?: ApiKeyGenqlSelection + apiKey?: (ApiKeyGenqlSelection & { __args: {input: GetApiKeyInput} }) getToolIndex?: ToolIndexEntryGenqlSelection getToolInputSchema?: { __args: {toolName: Scalars['String']} } field?: (FieldGenqlSelection & { __args: { @@ -5768,6 +5768,15 @@ export interface BarChartDataInput {objectMetadataId: Scalars['UUID'],configurat export interface MutationGenqlSelection{ addQueryToEventStream?: { __args: {input: AddQuerySubscriptionInput} } removeQueryFromEventStream?: { __args: {input: RemoveQueryFromEventStreamInput} } + createNavigationMenuItem?: (NavigationMenuItemGenqlSelection & { __args: {input: CreateNavigationMenuItemInput} }) + updateNavigationMenuItem?: (NavigationMenuItemGenqlSelection & { __args: {input: UpdateOneNavigationMenuItemInput} }) + deleteNavigationMenuItem?: (NavigationMenuItemGenqlSelection & { __args: {id: Scalars['UUID']} }) + uploadAIChatFile?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload']} }) + uploadWorkflowFile?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload']} }) + uploadWorkspaceLogo?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload']} }) + uploadWorkspaceMemberProfilePicture?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload']} }) + uploadFilesFieldFile?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload'], fieldMetadataId: Scalars['String']} }) + uploadFilesFieldFileByUniversalIdentifier?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload'], fieldMetadataUniversalIdentifier: Scalars['String']} }) createObjectEvent?: (AnalyticsGenqlSelection & { __args: {event: Scalars['String'], recordId: Scalars['UUID'], objectMetadataId: Scalars['UUID'], properties?: (Scalars['JSON'] | null)} }) trackAnalytics?: (AnalyticsGenqlSelection & { __args: {type: AnalyticsType, name?: (Scalars['String'] | null), event?: (Scalars['String'] | null), properties?: (Scalars['JSON'] | null)} }) createPageLayoutWidget?: (PageLayoutWidgetGenqlSelection & { __args: {input: CreatePageLayoutWidgetInput} }) @@ -5815,12 +5824,6 @@ export interface MutationGenqlSelection{ createOneAgent?: (AgentGenqlSelection & { __args: {input: CreateAgentInput} }) updateOneAgent?: (AgentGenqlSelection & { __args: {input: UpdateAgentInput} }) deleteOneAgent?: (AgentGenqlSelection & { __args: {input: AgentIdInput} }) - uploadAIChatFile?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload']} }) - uploadWorkflowFile?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload']} }) - uploadWorkspaceLogo?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload']} }) - uploadWorkspaceMemberProfilePicture?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload']} }) - uploadFilesFieldFile?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload'], fieldMetadataId: Scalars['String']} }) - uploadFilesFieldFileByUniversalIdentifier?: (FileWithSignedUrlGenqlSelection & { __args: {file: Scalars['Upload'], fieldMetadataUniversalIdentifier: Scalars['String']} }) checkoutSession?: (BillingSessionGenqlSelection & { __args: {recurringInterval: SubscriptionInterval, plan: BillingPlanKey, requirePaymentMethod: Scalars['Boolean'], successUrlPath?: (Scalars['String'] | null)} }) switchSubscriptionInterval?: BillingUpdateGenqlSelection switchBillingPlan?: BillingUpdateGenqlSelection @@ -5831,13 +5834,6 @@ export interface MutationGenqlSelection{ cancelSwitchMeteredPrice?: BillingUpdateGenqlSelection refreshEnterpriseValidityToken?: boolean | number setEnterpriseKey?: (EnterpriseLicenseInfoDTOGenqlSelection & { __args: {enterpriseKey: Scalars['String']} }) - createNavigationMenuItem?: (NavigationMenuItemGenqlSelection & { __args: {input: CreateNavigationMenuItemInput} }) - updateNavigationMenuItem?: (NavigationMenuItemGenqlSelection & { __args: {input: UpdateOneNavigationMenuItemInput} }) - deleteNavigationMenuItem?: (NavigationMenuItemGenqlSelection & { __args: {id: Scalars['UUID']} }) - createApiKey?: (ApiKeyGenqlSelection & { __args: {input: CreateApiKeyInput} }) - updateApiKey?: (ApiKeyGenqlSelection & { __args: {input: UpdateApiKeyInput} }) - revokeApiKey?: (ApiKeyGenqlSelection & { __args: {input: RevokeApiKeyInput} }) - assignRoleToApiKey?: { __args: {apiKeyId: Scalars['UUID'], roleId: Scalars['UUID']} } updateWorkspaceMemberRole?: (WorkspaceMemberGenqlSelection & { __args: {workspaceMemberId: Scalars['UUID'], roleId: Scalars['UUID']} }) createOneRole?: (RoleGenqlSelection & { __args: {createRoleInput: CreateRoleInput} }) updateOneRole?: (RoleGenqlSelection & { __args: {updateRoleInput: UpdateRoleInput} }) @@ -5856,6 +5852,10 @@ export interface MutationGenqlSelection{ createApprovedAccessDomain?: (ApprovedAccessDomainGenqlSelection & { __args: {input: CreateApprovedAccessDomainInput} }) deleteApprovedAccessDomain?: { __args: {input: DeleteApprovedAccessDomainInput} } validateApprovedAccessDomain?: (ApprovedAccessDomainGenqlSelection & { __args: {input: ValidateApprovedAccessDomainInput} }) + createApiKey?: (ApiKeyGenqlSelection & { __args: {input: CreateApiKeyInput} }) + updateApiKey?: (ApiKeyGenqlSelection & { __args: {input: UpdateApiKeyInput} }) + revokeApiKey?: (ApiKeyGenqlSelection & { __args: {input: RevokeApiKeyInput} }) + assignRoleToApiKey?: { __args: {apiKeyId: Scalars['UUID'], roleId: Scalars['UUID']} } createOneField?: (FieldGenqlSelection & { __args: {input: CreateOneFieldMetadataInput} }) updateOneField?: (FieldGenqlSelection & { __args: {input: UpdateOneFieldMetadataInput} }) deleteOneField?: (FieldGenqlSelection & { __args: {input: DeleteOneFieldInput} }) @@ -5965,6 +5965,16 @@ export interface AddQuerySubscriptionInput {eventStreamId: Scalars['String'],que export interface RemoveQueryFromEventStreamInput {eventStreamId: Scalars['String'],queryId: Scalars['String']} +export interface CreateNavigationMenuItemInput {id?: (Scalars['UUID'] | null),userWorkspaceId?: (Scalars['UUID'] | null),targetRecordId?: (Scalars['UUID'] | null),targetObjectMetadataId?: (Scalars['UUID'] | null),viewId?: (Scalars['UUID'] | null),type: NavigationMenuItemType,name?: (Scalars['String'] | null),link?: (Scalars['String'] | null),icon?: (Scalars['String'] | null),color?: (Scalars['String'] | null),folderId?: (Scalars['UUID'] | null),position?: (Scalars['Float'] | null)} + +export interface UpdateOneNavigationMenuItemInput { +/** The id of the record to update */ +id: Scalars['UUID'], +/** The record to update */ +update: UpdateNavigationMenuItemInput} + +export interface UpdateNavigationMenuItemInput {folderId?: (Scalars['UUID'] | null),position?: (Scalars['Float'] | null),name?: (Scalars['String'] | null),link?: (Scalars['String'] | null),icon?: (Scalars['String'] | null),color?: (Scalars['String'] | null)} + export interface CreatePageLayoutWidgetInput {pageLayoutTabId: Scalars['UUID'],title: Scalars['String'],type: WidgetType,objectMetadataId?: (Scalars['UUID'] | null),gridPosition: GridPositionInput,position?: (Scalars['JSON'] | null),configuration: Scalars['JSON']} export interface GridPositionInput {row: Scalars['Float'],column: Scalars['Float'],rowSpan: Scalars['Float'],columnSpan: Scalars['Float']} @@ -6107,22 +6117,6 @@ export interface CreateAgentInput {name?: (Scalars['String'] | null),label: Scal export interface UpdateAgentInput {id: Scalars['UUID'],name?: (Scalars['String'] | null),label?: (Scalars['String'] | null),icon?: (Scalars['String'] | null),description?: (Scalars['String'] | null),prompt?: (Scalars['String'] | null),modelId?: (Scalars['String'] | null),roleId?: (Scalars['UUID'] | null),responseFormat?: (Scalars['JSON'] | null),modelConfiguration?: (Scalars['JSON'] | null),evaluationInputs?: (Scalars['String'][] | null)} -export interface CreateNavigationMenuItemInput {userWorkspaceId?: (Scalars['UUID'] | null),targetRecordId?: (Scalars['UUID'] | null),targetObjectMetadataId?: (Scalars['UUID'] | null),viewId?: (Scalars['UUID'] | null),type: NavigationMenuItemType,name?: (Scalars['String'] | null),link?: (Scalars['String'] | null),icon?: (Scalars['String'] | null),color?: (Scalars['String'] | null),folderId?: (Scalars['UUID'] | null),position?: (Scalars['Float'] | null)} - -export interface UpdateOneNavigationMenuItemInput { -/** The id of the record to update */ -id: Scalars['UUID'], -/** The record to update */ -update: UpdateNavigationMenuItemInput} - -export interface UpdateNavigationMenuItemInput {folderId?: (Scalars['UUID'] | null),position?: (Scalars['Float'] | null),name?: (Scalars['String'] | null),link?: (Scalars['String'] | null),icon?: (Scalars['String'] | null),color?: (Scalars['String'] | null)} - -export interface CreateApiKeyInput {name: Scalars['String'],expiresAt: Scalars['String'],revokedAt?: (Scalars['String'] | null),roleId: Scalars['UUID']} - -export interface UpdateApiKeyInput {id: Scalars['UUID'],name?: (Scalars['String'] | null),expiresAt?: (Scalars['String'] | null),revokedAt?: (Scalars['String'] | null)} - -export interface RevokeApiKeyInput {id: Scalars['UUID']} - export interface CreateRoleInput {id?: (Scalars['String'] | null),label: Scalars['String'],description?: (Scalars['String'] | null),icon?: (Scalars['String'] | null),canUpdateAllSettings?: (Scalars['Boolean'] | null),canAccessAllTools?: (Scalars['Boolean'] | null),canReadAllObjectRecords?: (Scalars['Boolean'] | null),canUpdateAllObjectRecords?: (Scalars['Boolean'] | null),canSoftDeleteAllObjectRecords?: (Scalars['Boolean'] | null),canDestroyAllObjectRecords?: (Scalars['Boolean'] | null),canBeAssignedToUsers?: (Scalars['Boolean'] | null),canBeAssignedToAgents?: (Scalars['Boolean'] | null),canBeAssignedToApiKeys?: (Scalars['Boolean'] | null)} export interface UpdateRoleInput {update: UpdateRolePayload, @@ -6153,6 +6147,12 @@ export interface DeleteApprovedAccessDomainInput {id: Scalars['UUID']} export interface ValidateApprovedAccessDomainInput {validationToken: Scalars['String'],approvedAccessDomainId: Scalars['UUID']} +export interface CreateApiKeyInput {name: Scalars['String'],expiresAt: Scalars['String'],revokedAt?: (Scalars['String'] | null),roleId: Scalars['UUID']} + +export interface UpdateApiKeyInput {id: Scalars['UUID'],name?: (Scalars['String'] | null),expiresAt?: (Scalars['String'] | null),revokedAt?: (Scalars['String'] | null)} + +export interface RevokeApiKeyInput {id: Scalars['UUID']} + export interface CreateOneFieldMetadataInput { /** The record to create */ field: CreateFieldInput} @@ -6824,6 +6824,30 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null + const FileWithSignedUrl_possibleTypes: string[] = ['FileWithSignedUrl'] + export const isFileWithSignedUrl = (obj?: { __typename?: any } | null): obj is FileWithSignedUrl => { + if (!obj?.__typename) throw new Error('__typename is missing in "isFileWithSignedUrl"') + return FileWithSignedUrl_possibleTypes.includes(obj.__typename) + } + + + + const RecordIdentifier_possibleTypes: string[] = ['RecordIdentifier'] + export const isRecordIdentifier = (obj?: { __typename?: any } | null): obj is RecordIdentifier => { + if (!obj?.__typename) throw new Error('__typename is missing in "isRecordIdentifier"') + return RecordIdentifier_possibleTypes.includes(obj.__typename) + } + + + + const NavigationMenuItem_possibleTypes: string[] = ['NavigationMenuItem'] + export const isNavigationMenuItem = (obj?: { __typename?: any } | null): obj is NavigationMenuItem => { + if (!obj?.__typename) throw new Error('__typename is missing in "isNavigationMenuItem"') + return NavigationMenuItem_possibleTypes.includes(obj.__typename) + } + + + const ObjectRecordEventProperties_possibleTypes: string[] = ['ObjectRecordEventProperties'] export const isObjectRecordEventProperties = (obj?: { __typename?: any } | null): obj is ObjectRecordEventProperties => { if (!obj?.__typename) throw new Error('__typename is missing in "isObjectRecordEventProperties"') @@ -7040,14 +7064,6 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null - const FileWithSignedUrl_possibleTypes: string[] = ['FileWithSignedUrl'] - export const isFileWithSignedUrl = (obj?: { __typename?: any } | null): obj is FileWithSignedUrl => { - if (!obj?.__typename) throw new Error('__typename is missing in "isFileWithSignedUrl"') - return FileWithSignedUrl_possibleTypes.includes(obj.__typename) - } - - - const WorkspaceInvitation_possibleTypes: string[] = ['WorkspaceInvitation'] export const isWorkspaceInvitation = (obj?: { __typename?: any } | null): obj is WorkspaceInvitation => { if (!obj?.__typename) throw new Error('__typename is missing in "isWorkspaceInvitation"') @@ -7536,22 +7552,6 @@ export interface LogicFunctionLogsInput {applicationId?: (Scalars['UUID'] | null - const RecordIdentifier_possibleTypes: string[] = ['RecordIdentifier'] - export const isRecordIdentifier = (obj?: { __typename?: any } | null): obj is RecordIdentifier => { - if (!obj?.__typename) throw new Error('__typename is missing in "isRecordIdentifier"') - return RecordIdentifier_possibleTypes.includes(obj.__typename) - } - - - - const NavigationMenuItem_possibleTypes: string[] = ['NavigationMenuItem'] - export const isNavigationMenuItem = (obj?: { __typename?: any } | null): obj is NavigationMenuItem => { - if (!obj?.__typename) throw new Error('__typename is missing in "isNavigationMenuItem"') - return NavigationMenuItem_possibleTypes.includes(obj.__typename) - } - - - const LogicFunctionExecutionResult_possibleTypes: string[] = ['LogicFunctionExecutionResult'] export const isLogicFunctionExecutionResult = (obj?: { __typename?: any } | null): obj is LogicFunctionExecutionResult => { if (!obj?.__typename) throw new Error('__typename is missing in "isLogicFunctionExecutionResult"') @@ -8593,6 +8593,14 @@ export const enumPageLayoutType = { DASHBOARD: 'DASHBOARD' as const } +export const enumNavigationMenuItemType = { + VIEW: 'VIEW' as const, + FOLDER: 'FOLDER' as const, + LINK: 'LINK' as const, + OBJECT: 'OBJECT' as const, + RECORD: 'RECORD' as const +} + export const enumMetadataEventAction = { CREATED: 'CREATED' as const, UPDATED: 'UPDATED' as const, @@ -8685,14 +8693,6 @@ export const enumRelationType = { MANY_TO_ONE: 'MANY_TO_ONE' as const } -export const enumNavigationMenuItemType = { - VIEW: 'VIEW' as const, - FOLDER: 'FOLDER' as const, - LINK: 'LINK' as const, - OBJECT: 'OBJECT' as const, - RECORD: 'RECORD' as const -} - export const enumLogicFunctionExecutionStatus = { IDLE: 'IDLE' as const, SUCCESS: 'SUCCESS' as const, diff --git a/packages/twenty-sdk/src/clients/generated/metadata/types.ts b/packages/twenty-sdk/src/clients/generated/metadata/types.ts index 5125e822aa..ab4b012503 100644 --- a/packages/twenty-sdk/src/clients/generated/metadata/types.ts +++ b/packages/twenty-sdk/src/clients/generated/metadata/types.ts @@ -38,19 +38,19 @@ export default { 94, 95, 112, - 115, - 117, - 125, - 126, - 127, + 116, + 119, + 121, 129, - 137, - 153, - 154, - 159, - 163, - 187, - 216, + 130, + 131, + 133, + 141, + 156, + 157, + 162, + 166, + 190, 218, 226, 227, @@ -73,8 +73,8 @@ export default { 334, 335, 337, - 346, - 393, + 349, + 350, 456, 457 ], @@ -90,13 +90,13 @@ export default { 1 ], "metadata": [ - 124 + 128 ], "on_BillingLicensedProduct": [ - 133 + 137 ], "on_BillingMeteredProduct": [ - 134 + 138 ], "__typename": [ 1 @@ -780,10 +780,10 @@ export default { 3 ], "relation": [ - 186 + 189 ], "morphRelations": [ - 186 + 189 ], "object": [ 46 @@ -842,7 +842,7 @@ export default { 36 ], "objectMetadata": [ - 174, + 177, { "paging": [ 39, @@ -855,7 +855,7 @@ export default { } ], "indexFieldMetadatas": [ - 172, + 175, { "paging": [ 39, @@ -1100,7 +1100,7 @@ export default { 37 ], "fields": [ - 179, + 182, { "paging": [ 39, @@ -1113,7 +1113,7 @@ export default { } ], "indexMetadatas": [ - 177, + 180, { "paging": [ 39, @@ -1691,16 +1691,16 @@ export default { 49 ], "featureFlags": [ - 162 + 165 ], "billingSubscriptions": [ - 136 + 140 ], "currentBillingSubscription": [ - 136 + 140 ], "billingEntitlements": [ - 158 + 161 ], "hasValidEnterpriseKey": [ 6 @@ -1712,7 +1712,7 @@ export default { 6 ], "workspaceUrls": [ - 151 + 154 ], "workspaceCustomApplicationId": [ 1 @@ -1804,7 +1804,7 @@ export default { 20 ], "deletedWorkspaceMembers": [ - 157 + 160 ], "hasPassword": [ 6 @@ -1816,7 +1816,7 @@ export default { 17 ], "availableWorkspaces": [ - 156 + 159 ], "__typename": [ 1 @@ -2566,6 +2566,94 @@ export default { ] }, "PageLayoutType": {}, + "FileWithSignedUrl": { + "id": [ + 3 + ], + "path": [ + 1 + ], + "size": [ + 11 + ], + "createdAt": [ + 4 + ], + "url": [ + 1 + ], + "__typename": [ + 1 + ] + }, + "RecordIdentifier": { + "id": [ + 3 + ], + "labelIdentifier": [ + 1 + ], + "imageIdentifier": [ + 1 + ], + "__typename": [ + 1 + ] + }, + "NavigationMenuItem": { + "id": [ + 3 + ], + "userWorkspaceId": [ + 3 + ], + "targetRecordId": [ + 3 + ], + "targetObjectMetadataId": [ + 3 + ], + "viewId": [ + 3 + ], + "type": [ + 116 + ], + "name": [ + 1 + ], + "link": [ + 1 + ], + "icon": [ + 1 + ], + "color": [ + 1 + ], + "folderId": [ + 3 + ], + "position": [ + 11 + ], + "applicationId": [ + 3 + ], + "createdAt": [ + 4 + ], + "updatedAt": [ + 4 + ], + "targetRecordIdentifier": [ + 114 + ], + "__typename": [ + 1 + ] + }, + "NavigationMenuItemType": {}, "ObjectRecordEventProperties": { "updatedFields": [ 1 @@ -2585,7 +2673,7 @@ export default { }, "MetadataEvent": { "type": [ - 115 + 119 ], "metadataName": [ 1 @@ -2594,7 +2682,7 @@ export default { 1 ], "properties": [ - 113 + 117 ], "updatedCollectionHash": [ 1 @@ -2606,7 +2694,7 @@ export default { "MetadataEventAction": {}, "ObjectRecordEvent": { "action": [ - 117 + 121 ], "objectNameSingular": [ 1 @@ -2621,7 +2709,7 @@ export default { 1 ], "properties": [ - 113 + 117 ], "__typename": [ 1 @@ -2633,7 +2721,7 @@ export default { 1 ], "objectRecordEvent": [ - 116 + 120 ], "__typename": [ 1 @@ -2644,10 +2732,10 @@ export default { 1 ], "objectRecordEventsWithQueryIds": [ - 118 + 122 ], "metadataEvents": [ - 114 + 118 ], "__typename": [ 1 @@ -2655,7 +2743,7 @@ export default { }, "OnDbEvent": { "action": [ - 117 + 121 ], "objectNameSingular": [ 1 @@ -2700,7 +2788,7 @@ export default { 11 ], "items": [ - 122 + 126 ], "__typename": [ 1 @@ -2708,13 +2796,13 @@ export default { }, "BillingProductMetadata": { "planKey": [ - 125 + 129 ], "priceUsageBased": [ - 126 + 130 ], "productKey": [ - 127 + 131 ], "__typename": [ 1 @@ -2725,7 +2813,7 @@ export default { "BillingProductKey": {}, "BillingPriceLicensed": { "recurringInterval": [ - 129 + 133 ], "unitAmount": [ 11 @@ -2734,7 +2822,7 @@ export default { 1 ], "priceUsageType": [ - 126 + 130 ], "__typename": [ 1 @@ -2757,16 +2845,16 @@ export default { }, "BillingPriceMetered": { "tiers": [ - 130 + 134 ], "recurringInterval": [ - 129 + 133 ], "stripePriceId": [ 1 ], "priceUsageType": [ - 126 + 130 ], "__typename": [ 1 @@ -2783,7 +2871,7 @@ export default { 1 ], "metadata": [ - 124 + 128 ], "__typename": [ 1 @@ -2800,10 +2888,10 @@ export default { 1 ], "metadata": [ - 124 + 128 ], "prices": [ - 128 + 132 ], "__typename": [ 1 @@ -2820,10 +2908,10 @@ export default { 1 ], "metadata": [ - 124 + 128 ], "prices": [ - 131 + 135 ], "__typename": [ 1 @@ -2854,13 +2942,13 @@ export default { 3 ], "status": [ - 137 + 141 ], "interval": [ - 129 + 133 ], "billingSubscriptionItems": [ - 135 + 139 ], "currentPeriodEnd": [ 4 @@ -2869,7 +2957,7 @@ export default { 15 ], "phases": [ - 123 + 127 ], "__typename": [ 1 @@ -2878,7 +2966,7 @@ export default { "SubscriptionStatus": {}, "BillingEndTrialPeriod": { "status": [ - 137 + 141 ], "hasPaymentMethod": [ 6 @@ -2892,7 +2980,7 @@ export default { }, "BillingMeteredProductUsage": { "productKey": [ - 127 + 131 ], "periodStart": [ 4 @@ -2921,13 +3009,13 @@ export default { }, "BillingPlan": { "planKey": [ - 125 + 129 ], "licensedProducts": [ - 133 + 137 ], "meteredProducts": [ - 134 + 138 ], "__typename": [ 1 @@ -2943,10 +3031,10 @@ export default { }, "BillingUpdate": { "currentBillingSubscription": [ - 136 + 140 ], "billingSubscriptions": [ - 136 + 140 ], "__typename": [ 1 @@ -3017,26 +3105,6 @@ export default { 1 ] }, - "FileWithSignedUrl": { - "id": [ - 3 - ], - "path": [ - 1 - ], - "size": [ - 11 - ], - "createdAt": [ - 4 - ], - "url": [ - 1 - ], - "__typename": [ - 1 - ] - }, "WorkspaceInvitation": { "id": [ 3 @@ -3062,7 +3130,7 @@ export default { 1 ], "result": [ - 148 + 151 ], "__typename": [ 1 @@ -3089,7 +3157,7 @@ export default { }, "SSOConnection": { "type": [ - 153 + 156 ], "id": [ 3 @@ -3101,7 +3169,7 @@ export default { 1 ], "status": [ - 154 + 157 ], "__typename": [ 1 @@ -3126,13 +3194,13 @@ export default { 1 ], "workspaceUrls": [ - 151 + 154 ], "logo": [ 1 ], "sso": [ - 152 + 155 ], "__typename": [ 1 @@ -3140,10 +3208,10 @@ export default { }, "AvailableWorkspaces": { "availableWorkspacesForSignIn": [ - 155 + 158 ], "availableWorkspacesForSignUp": [ - 155 + 158 ], "__typename": [ 1 @@ -3171,7 +3239,7 @@ export default { }, "BillingEntitlement": { "key": [ - 159 + 162 ], "value": [ 6 @@ -3209,7 +3277,7 @@ export default { 1 ], "records": [ - 160 + 163 ], "__typename": [ 1 @@ -3217,7 +3285,7 @@ export default { }, "FeatureFlag": { "key": [ - 163 + 166 ], "value": [ 6 @@ -3235,10 +3303,10 @@ export default { 1 ], "type": [ - 153 + 156 ], "status": [ - 154 + 157 ], "issuer": [ 1 @@ -3249,7 +3317,7 @@ export default { }, "AuthProviders": { "sso": [ - 164 + 167 ], "google": [ 6 @@ -3286,10 +3354,10 @@ export default { 3 ], "authProviders": [ - 165 + 168 ], "authBypassProviders": [ - 166 + 169 ], "logo": [ 1 @@ -3298,7 +3366,7 @@ export default { 1 ], "workspaceUrls": [ - 151 + 154 ], "__typename": [ 1 @@ -3334,10 +3402,10 @@ export default { }, "IndexConnection": { "pageInfo": [ - 169 + 172 ], "edges": [ - 168 + 171 ], "__typename": [ 1 @@ -3356,10 +3424,10 @@ export default { }, "IndexIndexFieldMetadatasConnection": { "pageInfo": [ - 169 + 172 ], "edges": [ - 171 + 174 ], "__typename": [ 1 @@ -3378,10 +3446,10 @@ export default { }, "IndexObjectMetadataConnection": { "pageInfo": [ - 169 + 172 ], "edges": [ - 173 + 176 ], "__typename": [ 1 @@ -3400,10 +3468,10 @@ export default { }, "ObjectConnection": { "pageInfo": [ - 169 + 172 ], "edges": [ - 173 + 176 ], "__typename": [ 1 @@ -3411,10 +3479,10 @@ export default { }, "ObjectIndexMetadatasConnection": { "pageInfo": [ - 169 + 172 ], "edges": [ - 168 + 171 ], "__typename": [ 1 @@ -3433,10 +3501,10 @@ export default { }, "ObjectFieldsConnection": { "pageInfo": [ - 169 + 172 ], "edges": [ - 178 + 181 ], "__typename": [ 1 @@ -3472,7 +3540,7 @@ export default { 1 ], "versionDistribution": [ - 181 + 184 ], "__typename": [ 1 @@ -3519,7 +3587,7 @@ export default { }, "Relation": { "type": [ - 187 + 190 ], "sourceObjectMetadata": [ 46 @@ -3540,10 +3608,10 @@ export default { "RelationType": {}, "FieldConnection": { "pageInfo": [ - 169 + 172 ], "edges": [ - 178 + 181 ], "__typename": [ 1 @@ -3562,7 +3630,7 @@ export default { 3 ], "type": [ - 153 + 156 ], "issuer": [ 1 @@ -3571,7 +3639,7 @@ export default { 1 ], "status": [ - 154 + 157 ], "__typename": [ 1 @@ -3590,7 +3658,7 @@ export default { }, "FindAvailableSSOIDP": { "type": [ - 153 + 156 ], "id": [ 3 @@ -3602,10 +3670,10 @@ export default { 1 ], "status": [ - 154 + 157 ], "workspace": [ - 191 + 194 ], "__typename": [ 1 @@ -3616,7 +3684,7 @@ export default { 3 ], "type": [ - 153 + 156 ], "issuer": [ 1 @@ -3625,7 +3693,7 @@ export default { 1 ], "status": [ - 154 + 157 ], "__typename": [ 1 @@ -3676,10 +3744,10 @@ export default { }, "AuthTokenPair": { "accessOrWorkspaceAgnosticToken": [ - 198 + 201 ], "refreshToken": [ - 198 + 201 ], "__typename": [ 1 @@ -3687,10 +3755,10 @@ export default { }, "AvailableWorkspacesAndAccessTokens": { "tokens": [ - 199 + 202 ], "availableWorkspaces": [ - 156 + 159 ], "__typename": [ 1 @@ -3728,7 +3796,7 @@ export default { }, "WorkspaceUrlsAndId": { "workspaceUrls": [ - 151 + 154 ], "id": [ 3 @@ -3739,10 +3807,10 @@ export default { }, "SignUp": { "loginToken": [ - 198 + 201 ], "workspace": [ - 204 + 207 ], "__typename": [ 1 @@ -3750,7 +3818,7 @@ export default { }, "TransientToken": { "transientToken": [ - 198 + 201 ], "__typename": [ 1 @@ -3772,10 +3840,10 @@ export default { }, "VerifyEmailAndGetLoginToken": { "loginToken": [ - 198 + 201 ], "workspaceUrls": [ - 151 + 154 ], "__typename": [ 1 @@ -3791,7 +3859,7 @@ export default { }, "AuthTokens": { "tokens": [ - 199 + 202 ], "__typename": [ 1 @@ -3799,7 +3867,7 @@ export default { }, "LoginToken": { "loginToken": [ - 198 + 201 ], "__typename": [ 1 @@ -3827,74 +3895,6 @@ export default { 1 ] }, - "RecordIdentifier": { - "id": [ - 3 - ], - "labelIdentifier": [ - 1 - ], - "imageIdentifier": [ - 1 - ], - "__typename": [ - 1 - ] - }, - "NavigationMenuItem": { - "id": [ - 3 - ], - "userWorkspaceId": [ - 3 - ], - "targetRecordId": [ - 3 - ], - "targetObjectMetadataId": [ - 3 - ], - "viewId": [ - 3 - ], - "type": [ - 216 - ], - "name": [ - 1 - ], - "link": [ - 1 - ], - "icon": [ - 1 - ], - "color": [ - 1 - ], - "folderId": [ - 3 - ], - "position": [ - 11 - ], - "applicationId": [ - 3 - ], - "createdAt": [ - 4 - ], - "updatedAt": [ - 4 - ], - "targetRecordIdentifier": [ - 214 - ], - "__typename": [ - 1 - ] - }, - "NavigationMenuItemType": {}, "LogicFunctionExecutionResult": { "data": [ 15 @@ -4067,10 +4067,10 @@ export default { }, "ApplicationTokenPair": { "applicationAccessToken": [ - 198 + 201 ], "applicationRefreshToken": [ - 198 + 201 ], "__typename": [ 1 @@ -4277,7 +4277,7 @@ export default { }, "AgentChatThreadConnection": { "pageInfo": [ - 169 + 172 ], "edges": [ 232 @@ -4614,7 +4614,7 @@ export default { }, "PublicFeatureFlag": { "key": [ - 163 + 166 ], "metadata": [ 256 @@ -4628,7 +4628,7 @@ export default { 1 ], "authProviders": [ - 165 + 168 ], "billing": [ 249 @@ -4942,13 +4942,13 @@ export default { 11 ], "workspaceUrls": [ - 151 + 154 ], "users": [ 276 ], "featureFlags": [ - 162 + 165 ], "__typename": [ 1 @@ -5090,10 +5090,10 @@ export default { "QueueMetricsTimeRange": {}, "Impersonate": { "loginToken": [ - 198 + 201 ], "workspace": [ - 204 + 207 ], "__typename": [ 1 @@ -5770,6 +5770,18 @@ export default { ] }, "Query": { + "navigationMenuItems": [ + 115 + ], + "navigationMenuItem": [ + 115, + { + "id": [ + 3, + "UUID!" + ] + } + ], "getPageLayoutWidgets": [ 75, { @@ -5857,7 +5869,7 @@ export default { } ], "objectRecordCounts": [ - 175 + 178 ], "object": [ 46, @@ -5869,7 +5881,7 @@ export default { } ], "objects": [ - 176, + 179, { "paging": [ 39, @@ -5965,7 +5977,7 @@ export default { } ], "indexMetadatas": [ - 170, + 173, { "paging": [ 39, @@ -6014,7 +6026,7 @@ export default { } ], "billingPortalSession": [ - 141, + 145, { "returnUrlPath": [ 1 @@ -6022,10 +6034,10 @@ export default { } ], "listPlans": [ - 140 + 144 ], "getMeteredProductsUsage": [ - 139 + 143 ], "enterprisePortalSession": [ 1, @@ -6044,19 +6056,16 @@ export default { } ], "enterpriseSubscriptionStatus": [ - 144 + 148 ], - "navigationMenuItems": [ - 215 + "getRoles": [ + 29 ], - "navigationMenuItem": [ - 215, - { - "id": [ - 3, - "UUID!" - ] - } + "findWorkspaceInvitations": [ + 151 + ], + "getApprovedAccessDomains": [ + 150 ], "apiKeys": [ 2 @@ -6070,15 +6079,6 @@ export default { ] } ], - "getRoles": [ - 29 - ], - "findWorkspaceInvitations": [ - 148 - ], - "getApprovedAccessDomains": [ - 146 - ], "getToolIndex": [ 220 ], @@ -6101,7 +6101,7 @@ export default { } ], "fields": [ - 188, + 191, { "paging": [ 39, @@ -6171,7 +6171,7 @@ export default { 66 ], "getPublicWorkspaceDataByDomain": [ - 167, + 170, { "origin": [ 1 @@ -6179,7 +6179,7 @@ export default { } ], "findApplicationRegistrationByClientId": [ - 184, + 187, { "clientId": [ 1, @@ -6209,7 +6209,7 @@ export default { } ], "findApplicationRegistrationStats": [ - 182, + 185, { "id": [ 1, @@ -6236,7 +6236,7 @@ export default { } ], "checkUserExists": [ - 212, + 215, { "email": [ 1, @@ -6248,7 +6248,7 @@ export default { } ], "checkWorkspaceInviteHashIsValid": [ - 213, + 216, { "inviteHash": [ 1, @@ -6266,7 +6266,7 @@ export default { } ], "validatePasswordResetToken": [ - 207, + 210, { "passwordResetToken": [ 1, @@ -6275,7 +6275,7 @@ export default { } ], "getSSOIdentityProviders": [ - 192 + 195 ], "webhooks": [ 241 @@ -6743,8 +6743,97 @@ export default { ] } ], + "createNavigationMenuItem": [ + 115, + { + "input": [ + 346, + "CreateNavigationMenuItemInput!" + ] + } + ], + "updateNavigationMenuItem": [ + 115, + { + "input": [ + 347, + "UpdateOneNavigationMenuItemInput!" + ] + } + ], + "deleteNavigationMenuItem": [ + 115, + { + "id": [ + 3, + "UUID!" + ] + } + ], + "uploadAIChatFile": [ + 113, + { + "file": [ + 349, + "Upload!" + ] + } + ], + "uploadWorkflowFile": [ + 113, + { + "file": [ + 349, + "Upload!" + ] + } + ], + "uploadWorkspaceLogo": [ + 113, + { + "file": [ + 349, + "Upload!" + ] + } + ], + "uploadWorkspaceMemberProfilePicture": [ + 113, + { + "file": [ + 349, + "Upload!" + ] + } + ], + "uploadFilesFieldFile": [ + 113, + { + "file": [ + 349, + "Upload!" + ], + "fieldMetadataId": [ + 1, + "String!" + ] + } + ], + "uploadFilesFieldFileByUniversalIdentifier": [ + 113, + { + "file": [ + 349, + "Upload!" + ], + "fieldMetadataUniversalIdentifier": [ + 1, + "String!" + ] + } + ], "createObjectEvent": [ - 121, + 125, { "event": [ 1, @@ -6764,10 +6853,10 @@ export default { } ], "trackAnalytics": [ - 121, + 125, { "type": [ - 346, + 350, "AnalyticsType!" ], "name": [ @@ -6785,7 +6874,7 @@ export default { 75, { "input": [ - 347, + 351, "CreatePageLayoutWidgetInput!" ] } @@ -6798,7 +6887,7 @@ export default { "String!" ], "input": [ - 349, + 353, "UpdatePageLayoutWidgetInput!" ] } @@ -6816,7 +6905,7 @@ export default { 110, { "input": [ - 350, + 354, "CreatePageLayoutTabInput!" ] } @@ -6829,7 +6918,7 @@ export default { "String!" ], "input": [ - 351, + 355, "UpdatePageLayoutTabInput!" ] } @@ -6847,7 +6936,7 @@ export default { 111, { "input": [ - 352, + 356, "CreatePageLayoutInput!" ] } @@ -6860,7 +6949,7 @@ export default { "String!" ], "input": [ - 353, + 357, "UpdatePageLayoutInput!" ] } @@ -6882,7 +6971,7 @@ export default { "String!" ], "input": [ - 354, + 358, "UpdatePageLayoutWithTabsInput!" ] } @@ -6900,7 +6989,7 @@ export default { 32, { "input": [ - 357, + 361, "CreateLogicFunctionFromSourceInput!" ] } @@ -6909,7 +6998,7 @@ export default { 217, { "input": [ - 358, + 362, "ExecuteOneLogicFunctionInput!" ] } @@ -6918,7 +7007,7 @@ export default { 6, { "input": [ - 359, + 363, "UpdateLogicFunctionFromSourceInput!" ] } @@ -6927,7 +7016,7 @@ export default { 46, { "input": [ - 361, + 365, "CreateOneObjectInput!" ] } @@ -6936,7 +7025,7 @@ export default { 46, { "input": [ - 363, + 367, "DeleteOneObjectInput!" ] } @@ -6945,7 +7034,7 @@ export default { 46, { "input": [ - 364, + 368, "UpdateOneObjectInput!" ] } @@ -6954,7 +7043,7 @@ export default { 50, { "input": [ - 366, + 370, "UpdateViewFieldInput!" ] } @@ -6963,7 +7052,7 @@ export default { 50, { "input": [ - 368, + 372, "CreateViewFieldInput!" ] } @@ -6972,7 +7061,7 @@ export default { 50, { "inputs": [ - 368, + 372, "[CreateViewFieldInput!]!" ] } @@ -6981,7 +7070,7 @@ export default { 50, { "input": [ - 369, + 373, "DeleteViewFieldInput!" ] } @@ -6990,7 +7079,7 @@ export default { 50, { "input": [ - 370, + 374, "DestroyViewFieldInput!" ] } @@ -6999,7 +7088,7 @@ export default { 60, { "input": [ - 371, + 375, "CreateViewInput!" ] } @@ -7012,7 +7101,7 @@ export default { "String!" ], "input": [ - 372, + 376, "UpdateViewInput!" ] } @@ -7039,7 +7128,7 @@ export default { 57, { "input": [ - 373, + 377, "CreateViewSortInput!" ] } @@ -7048,7 +7137,7 @@ export default { 57, { "input": [ - 374, + 378, "UpdateViewSortInput!" ] } @@ -7057,7 +7146,7 @@ export default { 6, { "input": [ - 376, + 380, "DeleteViewSortInput!" ] } @@ -7066,7 +7155,7 @@ export default { 6, { "input": [ - 377, + 381, "DestroyViewSortInput!" ] } @@ -7075,7 +7164,7 @@ export default { 59, { "input": [ - 378, + 382, "UpdateViewFieldGroupInput!" ] } @@ -7084,7 +7173,7 @@ export default { 59, { "input": [ - 380, + 384, "CreateViewFieldGroupInput!" ] } @@ -7093,7 +7182,7 @@ export default { 59, { "inputs": [ - 380, + 384, "[CreateViewFieldGroupInput!]!" ] } @@ -7102,7 +7191,7 @@ export default { 59, { "input": [ - 381, + 385, "DeleteViewFieldGroupInput!" ] } @@ -7111,7 +7200,7 @@ export default { 59, { "input": [ - 382, + 386, "DestroyViewFieldGroupInput!" ] } @@ -7120,7 +7209,7 @@ export default { 60, { "input": [ - 383, + 387, "UpsertFieldsWidgetInput!" ] } @@ -7129,7 +7218,7 @@ export default { 225, { "input": [ - 386, + 390, "CreateCommandMenuItemInput!" ] } @@ -7138,7 +7227,7 @@ export default { 225, { "input": [ - 387, + 391, "UpdateCommandMenuItemInput!" ] } @@ -7156,7 +7245,7 @@ export default { 224, { "input": [ - 388, + 392, "CreateFrontComponentInput!" ] } @@ -7165,7 +7254,7 @@ export default { 224, { "input": [ - 389, + 393, "UpdateFrontComponentInput!" ] } @@ -7183,7 +7272,7 @@ export default { 25, { "input": [ - 391, + 395, "CreateAgentInput!" ] } @@ -7192,7 +7281,7 @@ export default { 25, { "input": [ - 392, + 396, "UpdateAgentInput!" ] } @@ -7206,77 +7295,15 @@ export default { ] } ], - "uploadAIChatFile": [ - 147, - { - "file": [ - 393, - "Upload!" - ] - } - ], - "uploadWorkflowFile": [ - 147, - { - "file": [ - 393, - "Upload!" - ] - } - ], - "uploadWorkspaceLogo": [ - 147, - { - "file": [ - 393, - "Upload!" - ] - } - ], - "uploadWorkspaceMemberProfilePicture": [ - 147, - { - "file": [ - 393, - "Upload!" - ] - } - ], - "uploadFilesFieldFile": [ - 147, - { - "file": [ - 393, - "Upload!" - ], - "fieldMetadataId": [ - 1, - "String!" - ] - } - ], - "uploadFilesFieldFileByUniversalIdentifier": [ - 147, - { - "file": [ - 393, - "Upload!" - ], - "fieldMetadataUniversalIdentifier": [ - 1, - "String!" - ] - } - ], "checkoutSession": [ - 141, + 145, { "recurringInterval": [ - 129, + 133, "SubscriptionInterval!" ], "plan": [ - 125, + 129, "BillingPlanKey!" ], "requirePaymentMethod": [ @@ -7289,19 +7316,19 @@ export default { } ], "switchSubscriptionInterval": [ - 142 + 146 ], "switchBillingPlan": [ - 142 + 146 ], "cancelSwitchBillingPlan": [ - 142 + 146 ], "cancelSwitchBillingInterval": [ - 142 + 146 ], "setMeteredSubscriptionPrice": [ - 142, + 146, { "priceId": [ 1, @@ -7310,16 +7337,16 @@ export default { } ], "endSubscriptionTrialPeriod": [ - 138 + 142 ], "cancelSwitchMeteredPrice": [ - 142 + 146 ], "refreshEnterpriseValidityToken": [ 6 ], "setEnterpriseKey": [ - 143, + 147, { "enterpriseKey": [ 1, @@ -7327,73 +7354,6 @@ export default { ] } ], - "createNavigationMenuItem": [ - 215, - { - "input": [ - 394, - "CreateNavigationMenuItemInput!" - ] - } - ], - "updateNavigationMenuItem": [ - 215, - { - "input": [ - 395, - "UpdateOneNavigationMenuItemInput!" - ] - } - ], - "deleteNavigationMenuItem": [ - 215, - { - "id": [ - 3, - "UUID!" - ] - } - ], - "createApiKey": [ - 2, - { - "input": [ - 397, - "CreateApiKeyInput!" - ] - } - ], - "updateApiKey": [ - 2, - { - "input": [ - 398, - "UpdateApiKeyInput!" - ] - } - ], - "revokeApiKey": [ - 2, - { - "input": [ - 399, - "RevokeApiKeyInput!" - ] - } - ], - "assignRoleToApiKey": [ - 6, - { - "apiKeyId": [ - 3, - "UUID!" - ], - "roleId": [ - 3, - "UUID!" - ] - } - ], "updateWorkspaceMemberRole": [ 20, { @@ -7411,7 +7371,7 @@ export default { 29, { "createRoleInput": [ - 400, + 397, "CreateRoleInput!" ] } @@ -7420,7 +7380,7 @@ export default { 29, { "updateRoleInput": [ - 401, + 398, "UpdateRoleInput!" ] } @@ -7438,7 +7398,7 @@ export default { 16, { "upsertObjectPermissionsInput": [ - 403, + 400, "UpsertObjectPermissionsInput!" ] } @@ -7447,7 +7407,7 @@ export default { 27, { "upsertPermissionFlagsInput": [ - 405, + 402, "UpsertPermissionFlagsInput!" ] } @@ -7456,16 +7416,16 @@ export default { 26, { "upsertFieldPermissionsInput": [ - 406, + 403, "UpsertFieldPermissionsInput!" ] } ], "upsertRowLevelPermissionPredicates": [ - 180, + 183, { "input": [ - 408, + 405, "UpsertRowLevelPermissionPredicatesInput!" ] } @@ -7493,10 +7453,10 @@ export default { } ], "skipSyncEmailOnboardingStep": [ - 145 + 149 ], "skipBookOnboardingStep": [ - 145 + 149 ], "deleteWorkspaceInvitation": [ 1, @@ -7508,7 +7468,7 @@ export default { } ], "resendWorkspaceInvitation": [ - 149, + 152, { "appTokenId": [ 1, @@ -7517,7 +7477,7 @@ export default { } ], "sendInvitations": [ - 149, + 152, { "emails": [ 1, @@ -7529,10 +7489,10 @@ export default { } ], "createApprovedAccessDomain": [ - 146, + 150, { "input": [ - 411, + 408, "CreateApprovedAccessDomainInput!" ] } @@ -7541,17 +7501,57 @@ export default { 6, { "input": [ - 412, + 409, "DeleteApprovedAccessDomainInput!" ] } ], "validateApprovedAccessDomain": [ - 146, + 150, + { + "input": [ + 410, + "ValidateApprovedAccessDomainInput!" + ] + } + ], + "createApiKey": [ + 2, + { + "input": [ + 411, + "CreateApiKeyInput!" + ] + } + ], + "updateApiKey": [ + 2, + { + "input": [ + 412, + "UpdateApiKeyInput!" + ] + } + ], + "revokeApiKey": [ + 2, { "input": [ 413, - "ValidateApprovedAccessDomainInput!" + "RevokeApiKeyInput!" + ] + } + ], + "assignRoleToApiKey": [ + 6, + { + "apiKeyId": [ + 3, + "UUID!" + ], + "roleId": [ + 3, + "UUID!" ] } ], @@ -7728,7 +7728,7 @@ export default { } ], "resendEmailVerificationToken": [ - 150, + 153, { "email": [ 1, @@ -7762,10 +7762,10 @@ export default { 66 ], "checkCustomDomainValidRecords": [ - 161 + 164 ], "createApplicationRegistration": [ - 183, + 186, { "input": [ 433, @@ -7792,7 +7792,7 @@ export default { } ], "rotateApplicationRegistrationClientSecret": [ - 185, + 188, { "id": [ 1, @@ -7831,7 +7831,7 @@ export default { 7, { "file": [ - 393, + 349, "Upload!" ], "universalIdentifier": [ @@ -7853,7 +7853,7 @@ export default { } ], "getAuthorizationUrlForSSO": [ - 202, + 205, { "input": [ 439, @@ -7862,7 +7862,7 @@ export default { } ], "getLoginTokenFromCredentials": [ - 211, + 214, { "email": [ 1, @@ -7888,7 +7888,7 @@ export default { } ], "signIn": [ - 200, + 203, { "email": [ 1, @@ -7910,7 +7910,7 @@ export default { } ], "verifyEmailAndGetLoginToken": [ - 208, + 211, { "emailVerificationToken": [ 1, @@ -7930,7 +7930,7 @@ export default { } ], "verifyEmailAndGetWorkspaceAgnosticToken": [ - 200, + 203, { "emailVerificationToken": [ 1, @@ -7946,7 +7946,7 @@ export default { } ], "getAuthTokensFromOTP": [ - 210, + 213, { "otp": [ 1, @@ -7966,7 +7966,7 @@ export default { } ], "signUp": [ - 200, + 203, { "email": [ 1, @@ -7988,7 +7988,7 @@ export default { } ], "signUpInWorkspace": [ - 205, + 208, { "email": [ 1, @@ -8019,13 +8019,13 @@ export default { } ], "signUpInNewWorkspace": [ - 205 + 208 ], "generateTransientToken": [ - 206 + 209 ], "getAuthTokensFromLoginToken": [ - 210, + 213, { "loginToken": [ 1, @@ -8038,7 +8038,7 @@ export default { } ], "authorizeApp": [ - 197, + 200, { "clientId": [ 1, @@ -8060,7 +8060,7 @@ export default { } ], "renewToken": [ - 210, + 213, { "appToken": [ 1, @@ -8069,7 +8069,7 @@ export default { } ], "generateApiKeyToken": [ - 209, + 212, { "apiKeyId": [ 3, @@ -8082,7 +8082,7 @@ export default { } ], "emailPasswordResetLink": [ - 201, + 204, { "email": [ 1, @@ -8094,7 +8094,7 @@ export default { } ], "updatePasswordViaResetToken": [ - 203, + 206, { "passwordResetToken": [ 1, @@ -8107,7 +8107,7 @@ export default { } ], "initiateOTPProvisioning": [ - 195, + 198, { "loginToken": [ 1, @@ -8120,10 +8120,10 @@ export default { } ], "initiateOTPProvisioningForAuthenticatedUser": [ - 195 + 198 ], "deleteTwoFactorAuthenticationMethod": [ - 194, + 197, { "twoFactorAuthenticationMethodId": [ 3, @@ -8132,7 +8132,7 @@ export default { } ], "verifyTwoFactorAuthenticationMethodForAuthenticatedUser": [ - 196, + 199, { "otp": [ 1, @@ -8141,7 +8141,7 @@ export default { } ], "createOIDCIdentityProvider": [ - 193, + 196, { "input": [ 440, @@ -8150,7 +8150,7 @@ export default { } ], "createSAMLIdentityProvider": [ - 193, + 196, { "input": [ 441, @@ -8159,7 +8159,7 @@ export default { } ], "deleteSSOIdentityProvider": [ - 189, + 192, { "input": [ 442, @@ -8168,7 +8168,7 @@ export default { } ], "editSSOIdentityProvider": [ - 190, + 193, { "input": [ 443, @@ -8325,7 +8325,7 @@ export default { } ], "updateLabPublicFeatureFlag": [ - 162, + 165, { "input": [ 451, @@ -8458,7 +8458,7 @@ export default { } ], "checkPublicDomainValidRecords": [ - 161, + 164, { "domain": [ 1, @@ -8600,7 +8600,7 @@ export default { 290, { "file": [ - 393, + 349, "Upload!" ], "applicationUniversalIdentifier": [ @@ -8668,6 +8668,82 @@ export default { 1 ] }, + "CreateNavigationMenuItemInput": { + "id": [ + 3 + ], + "userWorkspaceId": [ + 3 + ], + "targetRecordId": [ + 3 + ], + "targetObjectMetadataId": [ + 3 + ], + "viewId": [ + 3 + ], + "type": [ + 116 + ], + "name": [ + 1 + ], + "link": [ + 1 + ], + "icon": [ + 1 + ], + "color": [ + 1 + ], + "folderId": [ + 3 + ], + "position": [ + 11 + ], + "__typename": [ + 1 + ] + }, + "UpdateOneNavigationMenuItemInput": { + "id": [ + 3 + ], + "update": [ + 348 + ], + "__typename": [ + 1 + ] + }, + "UpdateNavigationMenuItemInput": { + "folderId": [ + 3 + ], + "position": [ + 11 + ], + "name": [ + 1 + ], + "link": [ + 1 + ], + "icon": [ + 1 + ], + "color": [ + 1 + ], + "__typename": [ + 1 + ] + }, + "Upload": {}, "AnalyticsType": {}, "CreatePageLayoutWidgetInput": { "pageLayoutTabId": [ @@ -8683,7 +8759,7 @@ export default { 3 ], "gridPosition": [ - 348 + 352 ], "position": [ 15 @@ -8723,7 +8799,7 @@ export default { 3 ], "gridPosition": [ - 348 + 352 ], "position": [ 15 @@ -8805,7 +8881,7 @@ export default { 3 ], "tabs": [ - 355 + 359 ], "__typename": [ 1 @@ -8825,7 +8901,7 @@ export default { 1 ], "widgets": [ - 356 + 360 ], "__typename": [ 1 @@ -8848,7 +8924,7 @@ export default { 3 ], "gridPosition": [ - 348 + 352 ], "position": [ 15 @@ -8917,7 +8993,7 @@ export default { 3 ], "update": [ - 360 + 364 ], "__typename": [ 1 @@ -8963,7 +9039,7 @@ export default { }, "CreateOneObjectInput": { "object": [ - 362 + 366 ], "__typename": [ 1 @@ -9023,7 +9099,7 @@ export default { }, "UpdateOneObjectInput": { "update": [ - 365 + 369 ], "id": [ 3 @@ -9078,7 +9154,7 @@ export default { 3 ], "update": [ - 367 + 371 ], "__typename": [ 1 @@ -9277,7 +9353,7 @@ export default { 3 ], "update": [ - 375 + 379 ], "__typename": [ 1 @@ -9312,7 +9388,7 @@ export default { 3 ], "update": [ - 379 + 383 ], "__typename": [ 1 @@ -9376,10 +9452,10 @@ export default { 3 ], "groups": [ - 384 + 388 ], "fields": [ - 385 + 389 ], "__typename": [ 1 @@ -9399,7 +9475,7 @@ export default { 6 ], "fields": [ - 385 + 389 ], "__typename": [ 1 @@ -9526,7 +9602,7 @@ export default { 3 ], "update": [ - 390 + 394 ], "__typename": [ 1 @@ -9616,121 +9692,6 @@ export default { 1 ] }, - "Upload": {}, - "CreateNavigationMenuItemInput": { - "userWorkspaceId": [ - 3 - ], - "targetRecordId": [ - 3 - ], - "targetObjectMetadataId": [ - 3 - ], - "viewId": [ - 3 - ], - "type": [ - 216 - ], - "name": [ - 1 - ], - "link": [ - 1 - ], - "icon": [ - 1 - ], - "color": [ - 1 - ], - "folderId": [ - 3 - ], - "position": [ - 11 - ], - "__typename": [ - 1 - ] - }, - "UpdateOneNavigationMenuItemInput": { - "id": [ - 3 - ], - "update": [ - 396 - ], - "__typename": [ - 1 - ] - }, - "UpdateNavigationMenuItemInput": { - "folderId": [ - 3 - ], - "position": [ - 11 - ], - "name": [ - 1 - ], - "link": [ - 1 - ], - "icon": [ - 1 - ], - "color": [ - 1 - ], - "__typename": [ - 1 - ] - }, - "CreateApiKeyInput": { - "name": [ - 1 - ], - "expiresAt": [ - 1 - ], - "revokedAt": [ - 1 - ], - "roleId": [ - 3 - ], - "__typename": [ - 1 - ] - }, - "UpdateApiKeyInput": { - "id": [ - 3 - ], - "name": [ - 1 - ], - "expiresAt": [ - 1 - ], - "revokedAt": [ - 1 - ], - "__typename": [ - 1 - ] - }, - "RevokeApiKeyInput": { - "id": [ - 3 - ], - "__typename": [ - 1 - ] - }, "CreateRoleInput": { "id": [ 1 @@ -9777,7 +9738,7 @@ export default { }, "UpdateRoleInput": { "update": [ - 402 + 399 ], "id": [ 3 @@ -9832,7 +9793,7 @@ export default { 3 ], "objectPermissions": [ - 404 + 401 ], "__typename": [ 1 @@ -9874,7 +9835,7 @@ export default { 3 ], "fieldPermissions": [ - 407 + 404 ], "__typename": [ 1 @@ -9905,10 +9866,10 @@ export default { 3 ], "predicates": [ - 409 + 406 ], "predicateGroups": [ - 410 + 407 ], "__typename": [ 1 @@ -9996,6 +9957,48 @@ export default { 1 ] }, + "CreateApiKeyInput": { + "name": [ + 1 + ], + "expiresAt": [ + 1 + ], + "revokedAt": [ + 1 + ], + "roleId": [ + 3 + ], + "__typename": [ + 1 + ] + }, + "UpdateApiKeyInput": { + "id": [ + 3 + ], + "name": [ + 1 + ], + "expiresAt": [ + 1 + ], + "revokedAt": [ + 1 + ], + "__typename": [ + 1 + ] + }, + "RevokeApiKeyInput": { + "id": [ + 3 + ], + "__typename": [ + 1 + ] + }, "CreateOneFieldMetadataInput": { "field": [ 415 @@ -10587,7 +10590,7 @@ export default { 3 ], "status": [ - 154 + 157 ], "__typename": [ 1 @@ -10777,7 +10780,7 @@ export default { "FileFolder": {}, "Subscription": { "onDbEvent": [ - 120, + 124, { "input": [ 459, @@ -10786,7 +10789,7 @@ export default { } ], "onEventSubscription": [ - 119, + 123, { "eventStreamId": [ 1, @@ -10809,7 +10812,7 @@ export default { }, "OnDbEventInput": { "action": [ - 117 + 121 ], "objectNameSingular": [ 1 diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-navigation-menu-item/utils/from-create-navigation-menu-item-input-to-flat-navigation-menu-item-to-create.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-navigation-menu-item/utils/from-create-navigation-menu-item-input-to-flat-navigation-menu-item-to-create.util.ts index 9b4b6778f9..97395b11a7 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-navigation-menu-item/utils/from-create-navigation-menu-item-input-to-flat-navigation-menu-item-to-create.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-navigation-menu-item/utils/from-create-navigation-menu-item-input-to-flat-navigation-menu-item-to-create.util.ts @@ -25,7 +25,7 @@ export const fromCreateNavigationMenuItemInputToFlatNavigationMenuItemToCreate = AllFlatEntityMaps, 'flatObjectMetadataMaps' | 'flatViewMaps' >): FlatNavigationMenuItem => { - const id = uuidv4(); + const id = createNavigationMenuItemInput.id ?? uuidv4(); const now = new Date().toISOString(); let position = createNavigationMenuItemInput.position; diff --git a/packages/twenty-server/src/engine/metadata-modules/navigation-menu-item/dtos/create-navigation-menu-item.input.ts b/packages/twenty-server/src/engine/metadata-modules/navigation-menu-item/dtos/create-navigation-menu-item.input.ts index 81e98ff871..b073157c3a 100644 --- a/packages/twenty-server/src/engine/metadata-modules/navigation-menu-item/dtos/create-navigation-menu-item.input.ts +++ b/packages/twenty-server/src/engine/metadata-modules/navigation-menu-item/dtos/create-navigation-menu-item.input.ts @@ -13,6 +13,11 @@ import { NavigationMenuItemType } from 'src/engine/metadata-modules/navigation-m @InputType() export class CreateNavigationMenuItemInput { + @IsUUID() + @IsOptional() + @Field(() => UUIDScalarType, { nullable: true }) + id?: string; + @IsUUID() @IsOptional() @Field(() => UUIDScalarType, { nullable: true }) diff --git a/packages/twenty-server/src/engine/metadata-modules/navigation-menu-item/navigation-menu-item.module.ts b/packages/twenty-server/src/engine/metadata-modules/navigation-menu-item/navigation-menu-item.module.ts index 4ca5f68aac..4c432b1550 100644 --- a/packages/twenty-server/src/engine/metadata-modules/navigation-menu-item/navigation-menu-item.module.ts +++ b/packages/twenty-server/src/engine/metadata-modules/navigation-menu-item/navigation-menu-item.module.ts @@ -1,6 +1,5 @@ import { Module } from '@nestjs/common'; -import { ApiKeyModule } from 'src/engine/core-modules/api-key/api-key.module'; import { ApplicationModule } from 'src/engine/core-modules/application/application.module'; import { FileModule } from 'src/engine/core-modules/file/file.module'; import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module'; @@ -12,8 +11,8 @@ import { NavigationMenuItemResolver } from 'src/engine/metadata-modules/navigati import { NavigationMenuItemService } from 'src/engine/metadata-modules/navigation-menu-item/navigation-menu-item.service'; import { NavigationMenuItemAccessService } from 'src/engine/metadata-modules/navigation-menu-item/services/navigation-menu-item-access.service'; import { NavigationMenuItemDeletionService } from 'src/engine/metadata-modules/navigation-menu-item/services/navigation-menu-item-deletion.service'; +import { NavigationMenuItemRecordIdentifierService } from 'src/engine/metadata-modules/navigation-menu-item/services/navigation-menu-item-record-identifier.service'; import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module'; -import { UserRoleModule } from 'src/engine/metadata-modules/user-role/user-role.module'; import { WorkspaceMigrationGraphqlApiExceptionInterceptor } from 'src/engine/workspace-manager/workspace-migration/interceptors/workspace-migration-graphql-api-exception.interceptor'; import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace-migration/workspace-migration.module'; @@ -25,8 +24,6 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace FlatNavigationMenuItemModule, PermissionsModule, FileModule, - UserRoleModule, - ApiKeyModule, ], providers: [ NavigationMenuItemService, @@ -35,9 +32,13 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace NavigationMenuItemDeletionListener, NavigationMenuItemDeletionJob, NavigationMenuItemResolver, + NavigationMenuItemRecordIdentifierService, NavigationMenuItemGraphqlApiExceptionInterceptor, WorkspaceMigrationGraphqlApiExceptionInterceptor, ], - exports: [NavigationMenuItemService], + exports: [ + NavigationMenuItemService, + NavigationMenuItemRecordIdentifierService, + ], }) export class NavigationMenuItemModule {} diff --git a/packages/twenty-server/src/engine/metadata-modules/navigation-menu-item/navigation-menu-item.service.ts b/packages/twenty-server/src/engine/metadata-modules/navigation-menu-item/navigation-menu-item.service.ts index 9dcc757831..f47aa8686b 100644 --- a/packages/twenty-server/src/engine/metadata-modules/navigation-menu-item/navigation-menu-item.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/navigation-menu-item/navigation-menu-item.service.ts @@ -2,15 +2,8 @@ import { Injectable } from '@nestjs/common'; import { isDefined } from 'twenty-shared/utils'; -import { ApiKeyRoleService } from 'src/engine/core-modules/api-key/services/api-key-role.service'; import { ApplicationService } from 'src/engine/core-modules/application/application.service'; -import { isApiKeyAuthContext } from 'src/engine/core-modules/auth/guards/is-api-key-auth-context.guard'; -import { isApplicationAuthContext } from 'src/engine/core-modules/auth/guards/is-application-auth-context.guard'; -import { isUserAuthContext } from 'src/engine/core-modules/auth/guards/is-user-auth-context.guard'; import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type'; -import { FileService } from 'src/engine/core-modules/file/services/file.service'; -import { getRecordDisplayName } from 'src/engine/core-modules/record-crud/utils/get-record-display-name.util'; -import { getRecordImageIdentifier } from 'src/engine/core-modules/record-crud/utils/get-record-image-identifier.util'; import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service'; import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; @@ -27,12 +20,8 @@ import { NavigationMenuItemExceptionCode, } from 'src/engine/metadata-modules/navigation-menu-item/navigation-menu-item.exception'; import { NavigationMenuItemAccessService } from 'src/engine/metadata-modules/navigation-menu-item/services/navigation-menu-item-access.service'; -import { getMinimalSelectForRecordIdentifier } from 'src/engine/metadata-modules/navigation-menu-item/utils/get-minimal-select-for-record-identifier.util'; +import { NavigationMenuItemRecordIdentifierService } from 'src/engine/metadata-modules/navigation-menu-item/services/navigation-menu-item-record-identifier.service'; import { PermissionsException } from 'src/engine/metadata-modules/permissions/permissions.exception'; -import { UserRoleService } from 'src/engine/metadata-modules/user-role/user-role.service'; -import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager'; -import { type RolePermissionConfig } from 'src/engine/twenty-orm/types/role-permission-config'; -import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; import { WorkspaceMigrationBuilderException } from 'src/engine/workspace-manager/workspace-migration/exceptions/workspace-migration-builder-exception'; import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration/services/workspace-migration-validate-build-and-run-service'; @@ -43,10 +32,7 @@ export class NavigationMenuItemService { private readonly workspaceManyOrAllFlatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService, private readonly applicationService: ApplicationService, private readonly navigationMenuItemAccessService: NavigationMenuItemAccessService, - private readonly globalWorkspaceOrmManager: GlobalWorkspaceOrmManager, - private readonly fileService: FileService, - private readonly userRoleService: UserRoleService, - private readonly apiKeyRoleService: ApiKeyRoleService, + private readonly navigationMenuItemRecordIdentifierService: NavigationMenuItemRecordIdentifierService, ) {} async findAll({ @@ -379,41 +365,6 @@ export class NavigationMenuItemService { ); } - private async getRoleId( - authContext: WorkspaceAuthContext, - workspaceId: string, - ): Promise { - if (isApiKeyAuthContext(authContext)) { - return this.apiKeyRoleService.getRoleIdForApiKeyId( - authContext.apiKey.id, - workspaceId, - ); - } - - if ( - isApplicationAuthContext(authContext) && - isDefined(authContext.application.defaultRoleId) - ) { - return authContext.application.defaultRoleId; - } - - if (isUserAuthContext(authContext)) { - try { - return await this.userRoleService.getRoleIdForUserWorkspace({ - userWorkspaceId: authContext.userWorkspaceId, - workspaceId, - }); - } catch (error: unknown) { - if (error instanceof PermissionsException) { - return undefined; - } - throw error; - } - } - - return undefined; - } - async findTargetRecord({ targetRecordId, targetObjectMetadataId, @@ -425,104 +376,15 @@ export class NavigationMenuItemService { workspaceId: string; authContext: WorkspaceAuthContext; }): Promise { - const { flatObjectMetadataMaps, flatFieldMetadataMaps } = - await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + try { + return await this.navigationMenuItemRecordIdentifierService.resolveRecordIdentifier( { + targetRecordId, + targetObjectMetadataId, workspaceId, - flatMapsKeys: ['flatObjectMetadataMaps', 'flatFieldMetadataMaps'], + authContext, }, ); - - const objectMetadata = findFlatEntityByIdInFlatEntityMaps({ - flatEntityId: targetObjectMetadataId, - flatEntityMaps: flatObjectMetadataMaps, - }); - - if (!isDefined(objectMetadata)) { - return null; - } - - try { - const roleId = await this.getRoleId(authContext, workspaceId); - - if (!isDefined(roleId)) { - return null; - } - - const rolePermissionConfig: RolePermissionConfig = { - unionOf: [roleId], - }; - - const minimalSelectColumns = getMinimalSelectForRecordIdentifier({ - flatObjectMetadata: objectMetadata, - flatFieldMetadataMaps, - }); - - const record = - await this.globalWorkspaceOrmManager.executeInWorkspaceContext( - async () => { - const repository = - await this.globalWorkspaceOrmManager.getRepository( - workspaceId, - objectMetadata.nameSingular, - rolePermissionConfig, - ); - - const alias = objectMetadata.nameSingular; - const queryBuilder = repository.createQueryBuilder(alias); - - queryBuilder.select([]); - - for (const column of minimalSelectColumns) { - queryBuilder.addSelect(`"${alias}"."${column}"`, column); - } - - const rawResult = await queryBuilder - .where(`${alias}.id = :id`, { id: targetRecordId }) - .getRawOne(); - - if (!isDefined(rawResult)) { - return null; - } - - const formattedRecord = formatResult>( - rawResult, - objectMetadata, - flatObjectMetadataMaps, - flatFieldMetadataMaps, - ); - - return formattedRecord; - }, - authContext, - ); - - if (!isDefined(record)) { - return null; - } - - const labelIdentifier = getRecordDisplayName( - record, - objectMetadata, - flatFieldMetadataMaps, - ); - - const imageIdentifier = getRecordImageIdentifier({ - record, - flatObjectMetadata: objectMetadata, - flatFieldMetadataMaps, - signUrl: (url: string) => - this.fileService.signFileUrl({ - url, - workspaceId, - }), - }); - - return { - id: record.id as string, - labelIdentifier, - imageIdentifier, - }; } catch (error: unknown) { if (error instanceof PermissionsException) { return null; diff --git a/packages/twenty-server/src/engine/metadata-modules/navigation-menu-item/services/navigation-menu-item-record-identifier.service.ts b/packages/twenty-server/src/engine/metadata-modules/navigation-menu-item/services/navigation-menu-item-record-identifier.service.ts new file mode 100644 index 0000000000..3d873ff503 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/navigation-menu-item/services/navigation-menu-item-record-identifier.service.ts @@ -0,0 +1,134 @@ +import { Injectable } from '@nestjs/common'; + +import { isDefined } from 'twenty-shared/utils'; + +import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type'; +import { FileService } from 'src/engine/core-modules/file/services/file.service'; +import { getRecordDisplayName } from 'src/engine/core-modules/record-crud/utils/get-record-display-name.util'; +import { getRecordImageIdentifier } from 'src/engine/core-modules/record-crud/utils/get-record-image-identifier.util'; +import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.service'; +import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; +import { RecordIdentifierDTO } from 'src/engine/metadata-modules/navigation-menu-item/dtos/record-identifier.dto'; +import { getMinimalSelectForRecordIdentifier } from 'src/engine/metadata-modules/navigation-menu-item/utils/get-minimal-select-for-record-identifier.util'; +import { PermissionsService } from 'src/engine/metadata-modules/permissions/permissions.service'; +import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager'; +import { formatResult } from 'src/engine/twenty-orm/utils/format-result.util'; + +@Injectable() +export class NavigationMenuItemRecordIdentifierService { + constructor( + private readonly workspaceManyOrAllFlatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService, + private readonly globalWorkspaceOrmManager: GlobalWorkspaceOrmManager, + private readonly fileService: FileService, + private readonly permissionsService: PermissionsService, + ) {} + + async resolveRecordIdentifier({ + targetRecordId, + targetObjectMetadataId, + workspaceId, + authContext, + }: { + targetRecordId: string; + targetObjectMetadataId: string; + workspaceId: string; + authContext?: WorkspaceAuthContext; + }): Promise { + const { flatObjectMetadataMaps, flatFieldMetadataMaps } = + await this.workspaceManyOrAllFlatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: ['flatObjectMetadataMaps', 'flatFieldMetadataMaps'], + }, + ); + + const objectMetadata = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: targetObjectMetadataId, + flatEntityMaps: flatObjectMetadataMaps, + }); + + if (!isDefined(objectMetadata)) { + return null; + } + + const minimalSelectColumns = getMinimalSelectForRecordIdentifier({ + flatObjectMetadata: objectMetadata, + flatFieldMetadataMaps, + }); + + const resolvedAuthContext: WorkspaceAuthContext = + authContext ?? + ({ + type: 'system', + workspace: { id: workspaceId }, + } as WorkspaceAuthContext); + + const rolePermissionConfig = + await this.permissionsService.resolveRolePermissionConfigFromAuthContext( + resolvedAuthContext, + ); + + const record = + await this.globalWorkspaceOrmManager.executeInWorkspaceContext( + async () => { + const repository = await this.globalWorkspaceOrmManager.getRepository( + workspaceId, + objectMetadata.nameSingular, + rolePermissionConfig ?? { shouldBypassPermissionChecks: true }, + ); + + const alias = objectMetadata.nameSingular; + const queryBuilder = repository.createQueryBuilder(alias); + + queryBuilder.select([]); + + for (const column of minimalSelectColumns) { + queryBuilder.addSelect(`"${alias}"."${column}"`, column); + } + + const rawResult = await queryBuilder + .where(`${alias}.id = :id`, { id: targetRecordId }) + .getRawOne(); + + if (!isDefined(rawResult)) { + return null; + } + + return formatResult>( + rawResult, + objectMetadata, + flatObjectMetadataMaps, + flatFieldMetadataMaps, + ); + }, + resolvedAuthContext, + ); + + if (!isDefined(record)) { + return null; + } + + const labelIdentifier = getRecordDisplayName( + record, + objectMetadata, + flatFieldMetadataMaps, + ); + + const imageIdentifier = getRecordImageIdentifier({ + record, + flatObjectMetadata: objectMetadata, + flatFieldMetadataMaps, + signUrl: (url: string) => + this.fileService.signFileUrl({ + url, + workspaceId, + }), + }); + + return { + id: record.id as string, + labelIdentifier, + imageIdentifier, + }; + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/permissions/permissions.service.ts b/packages/twenty-server/src/engine/metadata-modules/permissions/permissions.service.ts index 9fb0566c86..adeabc5660 100644 --- a/packages/twenty-server/src/engine/metadata-modules/permissions/permissions.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/permissions/permissions.service.ts @@ -12,6 +12,11 @@ import { ApplicationException, ApplicationExceptionCode, } from 'src/engine/core-modules/application/application.exception'; +import { isApiKeyAuthContext } from 'src/engine/core-modules/auth/guards/is-api-key-auth-context.guard'; +import { isApplicationAuthContext } from 'src/engine/core-modules/auth/guards/is-application-auth-context.guard'; +import { isSystemAuthContext } from 'src/engine/core-modules/auth/guards/is-system-auth-context.guard'; +import { isUserAuthContext } from 'src/engine/core-modules/auth/guards/is-user-auth-context.guard'; +import { type WorkspaceAuthContext } from 'src/engine/core-modules/auth/types/workspace-auth-context.type'; import { TOOL_PERMISSION_FLAGS } from 'src/engine/metadata-modules/permissions/constants/tool-permission-flags'; import { PermissionsException, @@ -129,6 +134,48 @@ export class PermissionsService { objectsPermissions: {}, }) as const satisfies UserWorkspacePermissions; + // TODO: this could likely be handled in the ORM layer + public async resolveRolePermissionConfigFromAuthContext( + authContext: WorkspaceAuthContext, + ): Promise { + const workspaceId = authContext.workspace.id; + + if (isSystemAuthContext(authContext)) { + return { shouldBypassPermissionChecks: true }; + } + + if (isApiKeyAuthContext(authContext)) { + const roleId = await this.apiKeyRoleService.getRoleIdForApiKeyId( + authContext.apiKey.id, + workspaceId, + ); + + return { intersectionOf: [roleId] }; + } + + if ( + isApplicationAuthContext(authContext) && + isDefined(authContext.application.defaultRoleId) + ) { + return { intersectionOf: [authContext.application.defaultRoleId] }; + } + + if (isUserAuthContext(authContext)) { + const roleId = await this.userRoleService.getRoleIdForUserWorkspace({ + userWorkspaceId: authContext.userWorkspaceId, + workspaceId, + }); + + if (!isDefined(roleId)) { + return null; + } + + return { intersectionOf: [roleId] }; + } + + return null; + } + public async userHasWorkspaceSettingPermission({ userWorkspaceId, workspaceId, diff --git a/packages/twenty-server/src/engine/workspace-event-emitter/__tests__/workspace-event-emitter.service.spec.ts b/packages/twenty-server/src/engine/workspace-event-emitter/__tests__/workspace-event-emitter.service.spec.ts index 65ed9a8340..c1a5845208 100644 --- a/packages/twenty-server/src/engine/workspace-event-emitter/__tests__/workspace-event-emitter.service.spec.ts +++ b/packages/twenty-server/src/engine/workspace-event-emitter/__tests__/workspace-event-emitter.service.spec.ts @@ -22,6 +22,7 @@ import { type EventStreamData } from 'src/engine/subscriptions/types/event-strea import { GlobalWorkspaceOrmManager } from 'src/engine/twenty-orm/global-workspace-datasource/global-workspace-orm.manager'; import { WorkspaceCacheService } from 'src/engine/workspace-cache/services/workspace-cache.service'; import { type WorkspaceEventBatch } from 'src/engine/workspace-event-emitter/types/workspace-event-batch.type'; +import { NavigationMenuItemRecordIdentifierService } from 'src/engine/metadata-modules/navigation-menu-item/services/navigation-menu-item-record-identifier.service'; import { WorkspaceEventEmitterService } from 'src/engine/workspace-event-emitter/workspace-event-emitter.service'; jest.mock( @@ -301,6 +302,14 @@ describe('WorkspaceEventEmitterService', () => { provide: CommonSelectFieldsHelper, useValue: new CommonSelectFieldsHelper(), }, + { + provide: NavigationMenuItemRecordIdentifierService, + useValue: { + enrichNavigationMenuItemEventsWithRecordIdentifiers: jest + .fn() + .mockResolvedValue(undefined), + }, + }, ], }).compile(); diff --git a/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.module.ts b/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.module.ts index f4f67e3b60..12fa9fa451 100644 --- a/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.module.ts +++ b/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.module.ts @@ -4,6 +4,7 @@ import { ProcessNestedRelationsV2Helper } from 'src/engine/api/common/common-nes import { ProcessNestedRelationsHelper } from 'src/engine/api/common/common-nested-relations-processor/process-nested-relations.helper'; import { CommonSelectFieldsHelper } from 'src/engine/api/common/common-select-fields/common-select-fields-helper'; import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/metadata-modules/flat-entity/services/workspace-many-or-all-flat-entity-maps-cache.module'; +import { NavigationMenuItemModule } from 'src/engine/metadata-modules/navigation-menu-item/navigation-menu-item.module'; import { SubscriptionsModule } from 'src/engine/subscriptions/subscriptions.module'; import { WorkspaceCacheModule } from 'src/engine/workspace-cache/workspace-cache.module'; import { WorkspaceEventEmitter } from 'src/engine/workspace-event-emitter/workspace-event-emitter'; @@ -16,6 +17,7 @@ import { WorkspaceEventEmitterService } from 'src/engine/workspace-event-emitter SubscriptionsModule, WorkspaceCacheModule, WorkspaceManyOrAllFlatEntityMapsCacheModule, + NavigationMenuItemModule, ], providers: [ WorkspaceEventEmitter, diff --git a/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.service.ts b/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.service.ts index 7e80f1f7ff..06dacc2670 100644 --- a/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.service.ts +++ b/packages/twenty-server/src/engine/workspace-event-emitter/workspace-event-emitter.service.ts @@ -31,6 +31,7 @@ import { type FlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/typ import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-metadata/types/flat-field-metadata.type'; import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; +import { NavigationMenuItemRecordIdentifierService } from 'src/engine/metadata-modules/navigation-menu-item/services/navigation-menu-item-record-identifier.service'; import { enrichFieldMetadataEventWithRelations } from 'src/engine/workspace-event-emitter/utils/enrich-field-metadata-event-with-relations.util'; import { UserWorkspaceRoleMap } from 'src/engine/metadata-modules/role-target/types/user-workspace-role-map'; import { type FlatRowLevelPermissionPredicateGroupMaps } from 'src/engine/metadata-modules/row-level-permission-predicate/types/flat-row-level-permission-predicate-group-maps.type'; @@ -62,6 +63,7 @@ export class WorkspaceEventEmitterService { private readonly workspaceManyOrAllFlatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService, private readonly globalWorkspaceOrmManager: GlobalWorkspaceOrmManager, private readonly commonSelectFieldsHelper: CommonSelectFieldsHelper, + private readonly navigationMenuItemRecordIdentifierService: NavigationMenuItemRecordIdentifierService, ) {} async publish( @@ -134,6 +136,8 @@ export class WorkspaceEventEmitterService { const enrichedMetadataEventBatch = isMetadata ? await this.enrichFieldMetadataEventsWithRelations( eventBatch as MetadataEventBatch, + ).then((batch) => + this.enrichNavigationMenuItemEventsWithTargetRecordIdentifier(batch), ) : undefined; @@ -251,6 +255,59 @@ export class WorkspaceEventEmitterService { return { ...metadataEventBatch, events: enrichedEvents }; } + private async enrichNavigationMenuItemEventsWithTargetRecordIdentifier( + metadataEventBatch: MetadataEventBatch, + ): Promise { + if (metadataEventBatch.metadataName !== 'navigationMenuItem') { + return metadataEventBatch; + } + + const enrichedEvents = await Promise.all( + metadataEventBatch.events.map(async (event) => { + if ( + !('after' in event.properties) || + !isDefined(event.properties.after) + ) { + return event; + } + + const after = event.properties.after as Record; + const targetRecordId = after.targetRecordId as string | undefined; + const targetObjectMetadataId = after.targetObjectMetadataId as + | string + | undefined; + + if (!isDefined(targetRecordId) || !isDefined(targetObjectMetadataId)) { + return event; + } + + const targetRecordIdentifier = + await this.navigationMenuItemRecordIdentifierService.resolveRecordIdentifier( + { + targetRecordId, + targetObjectMetadataId, + workspaceId: metadataEventBatch.workspaceId, + }, + ); + + const enrichedAfter: Record = { + ...after, + targetRecordIdentifier, + }; + + return { + ...event, + properties: { + ...event.properties, + after: enrichedAfter, + }, + } as typeof event; + }), + ); + + return { ...metadataEventBatch, events: enrichedEvents }; + } + private async processObjectRecordStreamEvents( streamChannelId: string, streamData: EventStreamData,