diff --git a/packages/twenty-sdk/src/clients/generated/metadata/schema.graphql b/packages/twenty-sdk/src/clients/generated/metadata/schema.graphql index 6010a889b2..514a40c0bb 100644 --- a/packages/twenty-sdk/src/clients/generated/metadata/schema.graphql +++ b/packages/twenty-sdk/src/clients/generated/metadata/schema.graphql @@ -2885,12 +2885,6 @@ type Query { getCoreView(id: String!): CoreView getCoreViewSorts(viewId: String): [CoreViewSort!]! getCoreViewSort(id: String!): CoreViewSort - getCoreViewGroups(viewId: String): [CoreViewGroup!]! - getCoreViewGroup(id: String!): CoreViewGroup - getCoreViewFilterGroups(viewId: String): [CoreViewFilterGroup!]! - getCoreViewFilterGroup(id: String!): CoreViewFilterGroup - getCoreViewFilters(viewId: String): [CoreViewFilter!]! - getCoreViewFilter(id: String!): CoreViewFilter getCoreViewFieldGroups(viewId: String!): [CoreViewFieldGroup!]! getCoreViewFieldGroup(id: String!): CoreViewFieldGroup index( @@ -2936,6 +2930,12 @@ type Query { """Specify to filter the records returned.""" filter: FieldFilter! = {} ): FieldConnection! + getCoreViewGroups(viewId: String): [CoreViewGroup!]! + getCoreViewGroup(id: String!): CoreViewGroup + getCoreViewFilters(viewId: String): [CoreViewFilter!]! + getCoreViewFilter(id: String!): CoreViewFilter + getCoreViewFilterGroups(viewId: String): [CoreViewFilterGroup!]! + getCoreViewFilterGroup(id: String!): CoreViewFilterGroup currentUser: User! currentWorkspace: Workspace! getPublicWorkspaceDataByDomain(origin: String): PublicWorkspaceData! @@ -3134,19 +3134,6 @@ type Mutation { updateCoreViewSort(input: UpdateViewSortInput!): CoreViewSort! deleteCoreViewSort(input: DeleteViewSortInput!): Boolean! destroyCoreViewSort(input: DestroyViewSortInput!): Boolean! - createCoreViewGroup(input: CreateViewGroupInput!): CoreViewGroup! - createManyCoreViewGroups(inputs: [CreateViewGroupInput!]!): [CoreViewGroup!]! - updateCoreViewGroup(input: UpdateViewGroupInput!): CoreViewGroup! - deleteCoreViewGroup(input: DeleteViewGroupInput!): CoreViewGroup! - destroyCoreViewGroup(input: DestroyViewGroupInput!): CoreViewGroup! - createCoreViewFilterGroup(input: CreateViewFilterGroupInput!): CoreViewFilterGroup! - updateCoreViewFilterGroup(id: String!, input: UpdateViewFilterGroupInput!): CoreViewFilterGroup! - deleteCoreViewFilterGroup(id: String!): Boolean! - destroyCoreViewFilterGroup(id: String!): Boolean! - createCoreViewFilter(input: CreateViewFilterInput!): CoreViewFilter! - updateCoreViewFilter(input: UpdateViewFilterInput!): CoreViewFilter! - deleteCoreViewFilter(input: DeleteViewFilterInput!): CoreViewFilter! - destroyCoreViewFilter(input: DestroyViewFilterInput!): CoreViewFilter! updateCoreViewFieldGroup(input: UpdateViewFieldGroupInput!): CoreViewFieldGroup! createCoreViewFieldGroup(input: CreateViewFieldGroupInput!): CoreViewFieldGroup! createManyCoreViewFieldGroups(inputs: [CreateViewFieldGroupInput!]!): [CoreViewFieldGroup!]! @@ -3206,6 +3193,19 @@ type Mutation { createOneField(input: CreateOneFieldMetadataInput!): Field! updateOneField(input: UpdateOneFieldMetadataInput!): Field! deleteOneField(input: DeleteOneFieldInput!): Field! + createCoreViewGroup(input: CreateViewGroupInput!): CoreViewGroup! + createManyCoreViewGroups(inputs: [CreateViewGroupInput!]!): [CoreViewGroup!]! + updateCoreViewGroup(input: UpdateViewGroupInput!): CoreViewGroup! + deleteCoreViewGroup(input: DeleteViewGroupInput!): CoreViewGroup! + destroyCoreViewGroup(input: DestroyViewGroupInput!): CoreViewGroup! + createCoreViewFilter(input: CreateViewFilterInput!): CoreViewFilter! + updateCoreViewFilter(input: UpdateViewFilterInput!): CoreViewFilter! + deleteCoreViewFilter(input: DeleteViewFilterInput!): CoreViewFilter! + destroyCoreViewFilter(input: DestroyViewFilterInput!): CoreViewFilter! + createCoreViewFilterGroup(input: CreateViewFilterGroupInput!): CoreViewFilterGroup! + updateCoreViewFilterGroup(id: String!, input: UpdateViewFilterGroupInput!): CoreViewFilterGroup! + deleteCoreViewFilterGroup(id: String!): Boolean! + destroyCoreViewFilterGroup(id: String!): Boolean! deleteUser: User! deleteUserFromWorkspace(workspaceMemberIdToDelete: String!): UserWorkspace! updateUserEmail(newEmail: String!, verifyEmailRedirectPath: String): Boolean! @@ -3581,93 +3581,6 @@ input DestroyViewSortInput { id: UUID! } -input CreateViewGroupInput { - id: UUID - isVisible: Boolean = true - fieldValue: String! - position: Float = 0 - viewId: UUID! -} - -input UpdateViewGroupInput { - """The id of the view group to update""" - id: UUID! - - """The view group to update""" - update: UpdateViewGroupInputUpdates! -} - -input UpdateViewGroupInputUpdates { - fieldMetadataId: UUID - isVisible: Boolean - fieldValue: String - position: Float -} - -input DeleteViewGroupInput { - """The id of the view group to delete.""" - id: UUID! -} - -input DestroyViewGroupInput { - """The id of the view group to destroy.""" - id: UUID! -} - -input CreateViewFilterGroupInput { - id: UUID - parentViewFilterGroupId: UUID - logicalOperator: ViewFilterGroupLogicalOperator = AND - positionInViewFilterGroup: Float - viewId: UUID! -} - -input UpdateViewFilterGroupInput { - id: UUID - parentViewFilterGroupId: UUID - logicalOperator: ViewFilterGroupLogicalOperator = AND - positionInViewFilterGroup: Float - viewId: UUID -} - -input CreateViewFilterInput { - id: UUID - fieldMetadataId: UUID! - operand: ViewFilterOperand = CONTAINS - value: JSON! - viewFilterGroupId: UUID - positionInViewFilterGroup: Float - subFieldName: String - viewId: UUID! -} - -input UpdateViewFilterInput { - """The id of the view filter to update""" - id: UUID! - - """The view filter to update""" - update: UpdateViewFilterInputUpdates! -} - -input UpdateViewFilterInputUpdates { - fieldMetadataId: UUID - operand: ViewFilterOperand - value: JSON - viewFilterGroupId: UUID - positionInViewFilterGroup: Float - subFieldName: String -} - -input DeleteViewFilterInput { - """The id of the view filter to delete.""" - id: UUID! -} - -input DestroyViewFilterInput { - """The id of the view filter to destroy.""" - id: UUID! -} - input UpdateViewFieldGroupInput { """The id of the view field group to update""" id: UUID! @@ -4025,6 +3938,93 @@ input DeleteOneFieldInput { id: UUID! } +input CreateViewGroupInput { + id: UUID + isVisible: Boolean = true + fieldValue: String! + position: Float = 0 + viewId: UUID! +} + +input UpdateViewGroupInput { + """The id of the view group to update""" + id: UUID! + + """The view group to update""" + update: UpdateViewGroupInputUpdates! +} + +input UpdateViewGroupInputUpdates { + fieldMetadataId: UUID + isVisible: Boolean + fieldValue: String + position: Float +} + +input DeleteViewGroupInput { + """The id of the view group to delete.""" + id: UUID! +} + +input DestroyViewGroupInput { + """The id of the view group to destroy.""" + id: UUID! +} + +input CreateViewFilterInput { + id: UUID + fieldMetadataId: UUID! + operand: ViewFilterOperand = CONTAINS + value: JSON! + viewFilterGroupId: UUID + positionInViewFilterGroup: Float + subFieldName: String + viewId: UUID! +} + +input UpdateViewFilterInput { + """The id of the view filter to update""" + id: UUID! + + """The view filter to update""" + update: UpdateViewFilterInputUpdates! +} + +input UpdateViewFilterInputUpdates { + fieldMetadataId: UUID + operand: ViewFilterOperand + value: JSON + viewFilterGroupId: UUID + positionInViewFilterGroup: Float + subFieldName: String +} + +input DeleteViewFilterInput { + """The id of the view filter to delete.""" + id: UUID! +} + +input DestroyViewFilterInput { + """The id of the view filter to destroy.""" + id: UUID! +} + +input CreateViewFilterGroupInput { + id: UUID + parentViewFilterGroupId: UUID + logicalOperator: ViewFilterGroupLogicalOperator = AND + positionInViewFilterGroup: Float + viewId: UUID! +} + +input UpdateViewFilterGroupInput { + id: UUID + parentViewFilterGroupId: UUID + logicalOperator: ViewFilterGroupLogicalOperator = AND + positionInViewFilterGroup: Float + viewId: UUID +} + input ActivateWorkspaceInput { displayName: String } diff --git a/packages/twenty-sdk/src/clients/generated/metadata/schema.ts b/packages/twenty-sdk/src/clients/generated/metadata/schema.ts index 701e5d9348..b3781806b1 100644 --- a/packages/twenty-sdk/src/clients/generated/metadata/schema.ts +++ b/packages/twenty-sdk/src/clients/generated/metadata/schema.ts @@ -2543,12 +2543,6 @@ export interface Query { getCoreView?: CoreView getCoreViewSorts: CoreViewSort[] getCoreViewSort?: CoreViewSort - getCoreViewGroups: CoreViewGroup[] - getCoreViewGroup?: CoreViewGroup - getCoreViewFilterGroups: CoreViewFilterGroup[] - getCoreViewFilterGroup?: CoreViewFilterGroup - getCoreViewFilters: CoreViewFilter[] - getCoreViewFilter?: CoreViewFilter getCoreViewFieldGroups: CoreViewFieldGroup[] getCoreViewFieldGroup?: CoreViewFieldGroup index: Index @@ -2576,6 +2570,12 @@ export interface Query { getToolInputSchema?: Scalars['JSON'] field: Field fields: FieldConnection + getCoreViewGroups: CoreViewGroup[] + getCoreViewGroup?: CoreViewGroup + getCoreViewFilters: CoreViewFilter[] + getCoreViewFilter?: CoreViewFilter + getCoreViewFilterGroups: CoreViewFilterGroup[] + getCoreViewFilterGroup?: CoreViewFilterGroup currentUser: User currentWorkspace: Workspace getPublicWorkspaceDataByDomain: PublicWorkspaceData @@ -2673,19 +2673,6 @@ export interface Mutation { updateCoreViewSort: CoreViewSort deleteCoreViewSort: Scalars['Boolean'] destroyCoreViewSort: Scalars['Boolean'] - createCoreViewGroup: CoreViewGroup - createManyCoreViewGroups: CoreViewGroup[] - updateCoreViewGroup: CoreViewGroup - deleteCoreViewGroup: CoreViewGroup - destroyCoreViewGroup: CoreViewGroup - createCoreViewFilterGroup: CoreViewFilterGroup - updateCoreViewFilterGroup: CoreViewFilterGroup - deleteCoreViewFilterGroup: Scalars['Boolean'] - destroyCoreViewFilterGroup: Scalars['Boolean'] - createCoreViewFilter: CoreViewFilter - updateCoreViewFilter: CoreViewFilter - deleteCoreViewFilter: CoreViewFilter - destroyCoreViewFilter: CoreViewFilter updateCoreViewFieldGroup: CoreViewFieldGroup createCoreViewFieldGroup: CoreViewFieldGroup createManyCoreViewFieldGroups: CoreViewFieldGroup[] @@ -2745,6 +2732,19 @@ export interface Mutation { createOneField: Field updateOneField: Field deleteOneField: Field + createCoreViewGroup: CoreViewGroup + createManyCoreViewGroups: CoreViewGroup[] + updateCoreViewGroup: CoreViewGroup + deleteCoreViewGroup: CoreViewGroup + destroyCoreViewGroup: CoreViewGroup + createCoreViewFilter: CoreViewFilter + updateCoreViewFilter: CoreViewFilter + deleteCoreViewFilter: CoreViewFilter + destroyCoreViewFilter: CoreViewFilter + createCoreViewFilterGroup: CoreViewFilterGroup + updateCoreViewFilterGroup: CoreViewFilterGroup + deleteCoreViewFilterGroup: Scalars['Boolean'] + destroyCoreViewFilterGroup: Scalars['Boolean'] deleteUser: User deleteUserFromWorkspace: UserWorkspace updateUserEmail: Scalars['Boolean'] @@ -5552,12 +5552,6 @@ export interface QueryGenqlSelection{ getCoreView?: (CoreViewGenqlSelection & { __args: {id: Scalars['String']} }) getCoreViewSorts?: (CoreViewSortGenqlSelection & { __args?: {viewId?: (Scalars['String'] | null)} }) getCoreViewSort?: (CoreViewSortGenqlSelection & { __args: {id: Scalars['String']} }) - getCoreViewGroups?: (CoreViewGroupGenqlSelection & { __args?: {viewId?: (Scalars['String'] | null)} }) - getCoreViewGroup?: (CoreViewGroupGenqlSelection & { __args: {id: Scalars['String']} }) - getCoreViewFilterGroups?: (CoreViewFilterGroupGenqlSelection & { __args?: {viewId?: (Scalars['String'] | null)} }) - getCoreViewFilterGroup?: (CoreViewFilterGroupGenqlSelection & { __args: {id: Scalars['String']} }) - getCoreViewFilters?: (CoreViewFilterGenqlSelection & { __args?: {viewId?: (Scalars['String'] | null)} }) - getCoreViewFilter?: (CoreViewFilterGenqlSelection & { __args: {id: Scalars['String']} }) getCoreViewFieldGroups?: (CoreViewFieldGroupGenqlSelection & { __args: {viewId: Scalars['String']} }) getCoreViewFieldGroup?: (CoreViewFieldGroupGenqlSelection & { __args: {id: Scalars['String']} }) index?: (IndexGenqlSelection & { __args: { @@ -5597,6 +5591,12 @@ export interface QueryGenqlSelection{ paging: CursorPaging, /** Specify to filter the records returned. */ filter: FieldFilter} }) + getCoreViewGroups?: (CoreViewGroupGenqlSelection & { __args?: {viewId?: (Scalars['String'] | null)} }) + getCoreViewGroup?: (CoreViewGroupGenqlSelection & { __args: {id: Scalars['String']} }) + getCoreViewFilters?: (CoreViewFilterGenqlSelection & { __args?: {viewId?: (Scalars['String'] | null)} }) + getCoreViewFilter?: (CoreViewFilterGenqlSelection & { __args: {id: Scalars['String']} }) + getCoreViewFilterGroups?: (CoreViewFilterGroupGenqlSelection & { __args?: {viewId?: (Scalars['String'] | null)} }) + getCoreViewFilterGroup?: (CoreViewFilterGroupGenqlSelection & { __args: {id: Scalars['String']} }) currentUser?: UserGenqlSelection currentWorkspace?: WorkspaceGenqlSelection getPublicWorkspaceDataByDomain?: (PublicWorkspaceDataGenqlSelection & { __args?: {origin?: (Scalars['String'] | null)} }) @@ -5719,19 +5719,6 @@ export interface MutationGenqlSelection{ updateCoreViewSort?: (CoreViewSortGenqlSelection & { __args: {input: UpdateViewSortInput} }) deleteCoreViewSort?: { __args: {input: DeleteViewSortInput} } destroyCoreViewSort?: { __args: {input: DestroyViewSortInput} } - createCoreViewGroup?: (CoreViewGroupGenqlSelection & { __args: {input: CreateViewGroupInput} }) - createManyCoreViewGroups?: (CoreViewGroupGenqlSelection & { __args: {inputs: CreateViewGroupInput[]} }) - updateCoreViewGroup?: (CoreViewGroupGenqlSelection & { __args: {input: UpdateViewGroupInput} }) - deleteCoreViewGroup?: (CoreViewGroupGenqlSelection & { __args: {input: DeleteViewGroupInput} }) - destroyCoreViewGroup?: (CoreViewGroupGenqlSelection & { __args: {input: DestroyViewGroupInput} }) - createCoreViewFilterGroup?: (CoreViewFilterGroupGenqlSelection & { __args: {input: CreateViewFilterGroupInput} }) - updateCoreViewFilterGroup?: (CoreViewFilterGroupGenqlSelection & { __args: {id: Scalars['String'], input: UpdateViewFilterGroupInput} }) - deleteCoreViewFilterGroup?: { __args: {id: Scalars['String']} } - destroyCoreViewFilterGroup?: { __args: {id: Scalars['String']} } - createCoreViewFilter?: (CoreViewFilterGenqlSelection & { __args: {input: CreateViewFilterInput} }) - updateCoreViewFilter?: (CoreViewFilterGenqlSelection & { __args: {input: UpdateViewFilterInput} }) - deleteCoreViewFilter?: (CoreViewFilterGenqlSelection & { __args: {input: DeleteViewFilterInput} }) - destroyCoreViewFilter?: (CoreViewFilterGenqlSelection & { __args: {input: DestroyViewFilterInput} }) updateCoreViewFieldGroup?: (CoreViewFieldGroupGenqlSelection & { __args: {input: UpdateViewFieldGroupInput} }) createCoreViewFieldGroup?: (CoreViewFieldGroupGenqlSelection & { __args: {input: CreateViewFieldGroupInput} }) createManyCoreViewFieldGroups?: (CoreViewFieldGroupGenqlSelection & { __args: {inputs: CreateViewFieldGroupInput[]} }) @@ -5791,6 +5778,19 @@ export interface MutationGenqlSelection{ createOneField?: (FieldGenqlSelection & { __args: {input: CreateOneFieldMetadataInput} }) updateOneField?: (FieldGenqlSelection & { __args: {input: UpdateOneFieldMetadataInput} }) deleteOneField?: (FieldGenqlSelection & { __args: {input: DeleteOneFieldInput} }) + createCoreViewGroup?: (CoreViewGroupGenqlSelection & { __args: {input: CreateViewGroupInput} }) + createManyCoreViewGroups?: (CoreViewGroupGenqlSelection & { __args: {inputs: CreateViewGroupInput[]} }) + updateCoreViewGroup?: (CoreViewGroupGenqlSelection & { __args: {input: UpdateViewGroupInput} }) + deleteCoreViewGroup?: (CoreViewGroupGenqlSelection & { __args: {input: DeleteViewGroupInput} }) + destroyCoreViewGroup?: (CoreViewGroupGenqlSelection & { __args: {input: DestroyViewGroupInput} }) + createCoreViewFilter?: (CoreViewFilterGenqlSelection & { __args: {input: CreateViewFilterInput} }) + updateCoreViewFilter?: (CoreViewFilterGenqlSelection & { __args: {input: UpdateViewFilterInput} }) + deleteCoreViewFilter?: (CoreViewFilterGenqlSelection & { __args: {input: DeleteViewFilterInput} }) + destroyCoreViewFilter?: (CoreViewFilterGenqlSelection & { __args: {input: DestroyViewFilterInput} }) + createCoreViewFilterGroup?: (CoreViewFilterGroupGenqlSelection & { __args: {input: CreateViewFilterGroupInput} }) + updateCoreViewFilterGroup?: (CoreViewFilterGroupGenqlSelection & { __args: {id: Scalars['String'], input: UpdateViewFilterGroupInput} }) + deleteCoreViewFilterGroup?: { __args: {id: Scalars['String']} } + destroyCoreViewFilterGroup?: { __args: {id: Scalars['String']} } deleteUser?: UserGenqlSelection deleteUserFromWorkspace?: (UserWorkspaceGenqlSelection & { __args: {workspaceMemberIdToDelete: Scalars['String']} }) updateUserEmail?: { __args: {newEmail: Scalars['String'], verifyEmailRedirectPath?: (Scalars['String'] | null)} } @@ -5976,46 +5976,6 @@ export interface DestroyViewSortInput { /** The id of the view sort to destroy. */ id: Scalars['UUID']} -export interface CreateViewGroupInput {id?: (Scalars['UUID'] | null),isVisible?: (Scalars['Boolean'] | null),fieldValue: Scalars['String'],position?: (Scalars['Float'] | null),viewId: Scalars['UUID']} - -export interface UpdateViewGroupInput { -/** The id of the view group to update */ -id: Scalars['UUID'], -/** The view group to update */ -update: UpdateViewGroupInputUpdates} - -export interface UpdateViewGroupInputUpdates {fieldMetadataId?: (Scalars['UUID'] | null),isVisible?: (Scalars['Boolean'] | null),fieldValue?: (Scalars['String'] | null),position?: (Scalars['Float'] | null)} - -export interface DeleteViewGroupInput { -/** The id of the view group to delete. */ -id: Scalars['UUID']} - -export interface DestroyViewGroupInput { -/** The id of the view group to destroy. */ -id: Scalars['UUID']} - -export interface CreateViewFilterGroupInput {id?: (Scalars['UUID'] | null),parentViewFilterGroupId?: (Scalars['UUID'] | null),logicalOperator?: (ViewFilterGroupLogicalOperator | null),positionInViewFilterGroup?: (Scalars['Float'] | null),viewId: Scalars['UUID']} - -export interface UpdateViewFilterGroupInput {id?: (Scalars['UUID'] | null),parentViewFilterGroupId?: (Scalars['UUID'] | null),logicalOperator?: (ViewFilterGroupLogicalOperator | null),positionInViewFilterGroup?: (Scalars['Float'] | null),viewId?: (Scalars['UUID'] | null)} - -export interface CreateViewFilterInput {id?: (Scalars['UUID'] | null),fieldMetadataId: Scalars['UUID'],operand?: (ViewFilterOperand | null),value: Scalars['JSON'],viewFilterGroupId?: (Scalars['UUID'] | null),positionInViewFilterGroup?: (Scalars['Float'] | null),subFieldName?: (Scalars['String'] | null),viewId: Scalars['UUID']} - -export interface UpdateViewFilterInput { -/** The id of the view filter to update */ -id: Scalars['UUID'], -/** The view filter to update */ -update: UpdateViewFilterInputUpdates} - -export interface UpdateViewFilterInputUpdates {fieldMetadataId?: (Scalars['UUID'] | null),operand?: (ViewFilterOperand | null),value?: (Scalars['JSON'] | null),viewFilterGroupId?: (Scalars['UUID'] | null),positionInViewFilterGroup?: (Scalars['Float'] | null),subFieldName?: (Scalars['String'] | null)} - -export interface DeleteViewFilterInput { -/** The id of the view filter to delete. */ -id: Scalars['UUID']} - -export interface DestroyViewFilterInput { -/** The id of the view filter to destroy. */ -id: Scalars['UUID']} - export interface UpdateViewFieldGroupInput { /** The id of the view field group to update */ id: Scalars['UUID'], @@ -6130,6 +6090,46 @@ export interface DeleteOneFieldInput { /** The id of the field to delete. */ id: Scalars['UUID']} +export interface CreateViewGroupInput {id?: (Scalars['UUID'] | null),isVisible?: (Scalars['Boolean'] | null),fieldValue: Scalars['String'],position?: (Scalars['Float'] | null),viewId: Scalars['UUID']} + +export interface UpdateViewGroupInput { +/** The id of the view group to update */ +id: Scalars['UUID'], +/** The view group to update */ +update: UpdateViewGroupInputUpdates} + +export interface UpdateViewGroupInputUpdates {fieldMetadataId?: (Scalars['UUID'] | null),isVisible?: (Scalars['Boolean'] | null),fieldValue?: (Scalars['String'] | null),position?: (Scalars['Float'] | null)} + +export interface DeleteViewGroupInput { +/** The id of the view group to delete. */ +id: Scalars['UUID']} + +export interface DestroyViewGroupInput { +/** The id of the view group to destroy. */ +id: Scalars['UUID']} + +export interface CreateViewFilterInput {id?: (Scalars['UUID'] | null),fieldMetadataId: Scalars['UUID'],operand?: (ViewFilterOperand | null),value: Scalars['JSON'],viewFilterGroupId?: (Scalars['UUID'] | null),positionInViewFilterGroup?: (Scalars['Float'] | null),subFieldName?: (Scalars['String'] | null),viewId: Scalars['UUID']} + +export interface UpdateViewFilterInput { +/** The id of the view filter to update */ +id: Scalars['UUID'], +/** The view filter to update */ +update: UpdateViewFilterInputUpdates} + +export interface UpdateViewFilterInputUpdates {fieldMetadataId?: (Scalars['UUID'] | null),operand?: (ViewFilterOperand | null),value?: (Scalars['JSON'] | null),viewFilterGroupId?: (Scalars['UUID'] | null),positionInViewFilterGroup?: (Scalars['Float'] | null),subFieldName?: (Scalars['String'] | null)} + +export interface DeleteViewFilterInput { +/** The id of the view filter to delete. */ +id: Scalars['UUID']} + +export interface DestroyViewFilterInput { +/** The id of the view filter to destroy. */ +id: Scalars['UUID']} + +export interface CreateViewFilterGroupInput {id?: (Scalars['UUID'] | null),parentViewFilterGroupId?: (Scalars['UUID'] | null),logicalOperator?: (ViewFilterGroupLogicalOperator | null),positionInViewFilterGroup?: (Scalars['Float'] | null),viewId: Scalars['UUID']} + +export interface UpdateViewFilterGroupInput {id?: (Scalars['UUID'] | null),parentViewFilterGroupId?: (Scalars['UUID'] | null),logicalOperator?: (ViewFilterGroupLogicalOperator | null),positionInViewFilterGroup?: (Scalars['Float'] | null),viewId?: (Scalars['UUID'] | null)} + export interface ActivateWorkspaceInput {displayName?: (Scalars['String'] | null)} export interface UpdateWorkspaceInput {subdomain?: (Scalars['String'] | null),customDomain?: (Scalars['String'] | null),displayName?: (Scalars['String'] | null),logo?: (Scalars['String'] | null),inviteHash?: (Scalars['String'] | null),isPublicInviteLinkEnabled?: (Scalars['Boolean'] | null),allowImpersonation?: (Scalars['Boolean'] | null),isGoogleAuthEnabled?: (Scalars['Boolean'] | null),isMicrosoftAuthEnabled?: (Scalars['Boolean'] | null),isPasswordAuthEnabled?: (Scalars['Boolean'] | null),isGoogleAuthBypassEnabled?: (Scalars['Boolean'] | null),isMicrosoftAuthBypassEnabled?: (Scalars['Boolean'] | null),isPasswordAuthBypassEnabled?: (Scalars['Boolean'] | null),defaultRoleId?: (Scalars['UUID'] | null),isTwoFactorAuthenticationEnforced?: (Scalars['Boolean'] | null),trashRetentionDays?: (Scalars['Float'] | null),eventLogRetentionDays?: (Scalars['Float'] | null),fastModel?: (Scalars['String'] | null),smartModel?: (Scalars['String'] | null),aiAdditionalInstructions?: (Scalars['String'] | null),editableProfileFields?: (Scalars['String'][] | null),autoEnableNewAiModels?: (Scalars['Boolean'] | null),disabledAiModelIds?: (Scalars['String'][] | null),enabledAiModelIds?: (Scalars['String'][] | null),useRecommendedModels?: (Scalars['Boolean'] | null)} diff --git a/packages/twenty-sdk/src/clients/generated/metadata/types.ts b/packages/twenty-sdk/src/clients/generated/metadata/types.ts index a5f31fcef5..d83a2cc4d7 100644 --- a/packages/twenty-sdk/src/clients/generated/metadata/types.ts +++ b/packages/twenty-sdk/src/clients/generated/metadata/types.ts @@ -72,7 +72,7 @@ export default { 330, 332, 341, - 400, + 388, 451, 452, 453 @@ -5844,57 +5844,6 @@ export default { ] } ], - "getCoreViewGroups": [ - 56, - { - "viewId": [ - 1 - ] - } - ], - "getCoreViewGroup": [ - 56, - { - "id": [ - 1, - "String!" - ] - } - ], - "getCoreViewFilterGroups": [ - 52, - { - "viewId": [ - 1 - ] - } - ], - "getCoreViewFilterGroup": [ - 52, - { - "id": [ - 1, - "String!" - ] - } - ], - "getCoreViewFilters": [ - 54, - { - "viewId": [ - 1 - ] - } - ], - "getCoreViewFilter": [ - 54, - { - "id": [ - 1, - "String!" - ] - } - ], "getCoreViewFieldGroups": [ 59, { @@ -6071,6 +6020,57 @@ export default { ] } ], + "getCoreViewGroups": [ + 56, + { + "viewId": [ + 1 + ] + } + ], + "getCoreViewGroup": [ + 56, + { + "id": [ + 1, + "String!" + ] + } + ], + "getCoreViewFilters": [ + 54, + { + "viewId": [ + 1 + ] + } + ], + "getCoreViewFilter": [ + 54, + { + "id": [ + 1, + "String!" + ] + } + ], + "getCoreViewFilterGroups": [ + 52, + { + "viewId": [ + 1 + ] + } + ], + "getCoreViewFilterGroup": [ + 52, + { + "id": [ + 1, + "String!" + ] + } + ], "currentUser": [ 69 ], @@ -6975,132 +6975,11 @@ export default { ] } ], - "createCoreViewGroup": [ - 56, - { - "input": [ - 373, - "CreateViewGroupInput!" - ] - } - ], - "createManyCoreViewGroups": [ - 56, - { - "inputs": [ - 373, - "[CreateViewGroupInput!]!" - ] - } - ], - "updateCoreViewGroup": [ - 56, - { - "input": [ - 374, - "UpdateViewGroupInput!" - ] - } - ], - "deleteCoreViewGroup": [ - 56, - { - "input": [ - 376, - "DeleteViewGroupInput!" - ] - } - ], - "destroyCoreViewGroup": [ - 56, - { - "input": [ - 377, - "DestroyViewGroupInput!" - ] - } - ], - "createCoreViewFilterGroup": [ - 52, - { - "input": [ - 378, - "CreateViewFilterGroupInput!" - ] - } - ], - "updateCoreViewFilterGroup": [ - 52, - { - "id": [ - 1, - "String!" - ], - "input": [ - 379, - "UpdateViewFilterGroupInput!" - ] - } - ], - "deleteCoreViewFilterGroup": [ - 6, - { - "id": [ - 1, - "String!" - ] - } - ], - "destroyCoreViewFilterGroup": [ - 6, - { - "id": [ - 1, - "String!" - ] - } - ], - "createCoreViewFilter": [ - 54, - { - "input": [ - 380, - "CreateViewFilterInput!" - ] - } - ], - "updateCoreViewFilter": [ - 54, - { - "input": [ - 381, - "UpdateViewFilterInput!" - ] - } - ], - "deleteCoreViewFilter": [ - 54, - { - "input": [ - 383, - "DeleteViewFilterInput!" - ] - } - ], - "destroyCoreViewFilter": [ - 54, - { - "input": [ - 384, - "DestroyViewFilterInput!" - ] - } - ], "updateCoreViewFieldGroup": [ 59, { "input": [ - 385, + 373, "UpdateViewFieldGroupInput!" ] } @@ -7109,7 +6988,7 @@ export default { 59, { "input": [ - 387, + 375, "CreateViewFieldGroupInput!" ] } @@ -7118,7 +6997,7 @@ export default { 59, { "inputs": [ - 387, + 375, "[CreateViewFieldGroupInput!]!" ] } @@ -7127,7 +7006,7 @@ export default { 59, { "input": [ - 388, + 376, "DeleteViewFieldGroupInput!" ] } @@ -7136,7 +7015,7 @@ export default { 59, { "input": [ - 389, + 377, "DestroyViewFieldGroupInput!" ] } @@ -7145,7 +7024,7 @@ export default { 60, { "input": [ - 390, + 378, "UpsertFieldsWidgetInput!" ] } @@ -7154,7 +7033,7 @@ export default { 225, { "input": [ - 393, + 381, "CreateCommandMenuItemInput!" ] } @@ -7163,7 +7042,7 @@ export default { 225, { "input": [ - 394, + 382, "UpdateCommandMenuItemInput!" ] } @@ -7181,7 +7060,7 @@ export default { 224, { "input": [ - 395, + 383, "CreateFrontComponentInput!" ] } @@ -7190,7 +7069,7 @@ export default { 224, { "input": [ - 396, + 384, "UpdateFrontComponentInput!" ] } @@ -7208,7 +7087,7 @@ export default { 25, { "input": [ - 398, + 386, "CreateAgentInput!" ] } @@ -7217,7 +7096,7 @@ export default { 25, { "input": [ - 399, + 387, "UpdateAgentInput!" ] } @@ -7235,7 +7114,7 @@ export default { 148, { "file": [ - 400, + 388, "Upload!" ] } @@ -7244,7 +7123,7 @@ export default { 148, { "file": [ - 400, + 388, "Upload!" ] } @@ -7253,7 +7132,7 @@ export default { 148, { "file": [ - 400, + 388, "Upload!" ] } @@ -7262,7 +7141,7 @@ export default { 148, { "file": [ - 400, + 388, "Upload!" ] } @@ -7271,7 +7150,7 @@ export default { 148, { "file": [ - 400, + 388, "Upload!" ], "fieldMetadataId": [ @@ -7284,7 +7163,7 @@ export default { 148, { "file": [ - 400, + 388, "Upload!" ], "fieldMetadataUniversalIdentifier": [ @@ -7356,7 +7235,7 @@ export default { 216, { "input": [ - 401, + 389, "CreateNavigationMenuItemInput!" ] } @@ -7365,7 +7244,7 @@ export default { 216, { "input": [ - 402, + 390, "UpdateOneNavigationMenuItemInput!" ] } @@ -7383,7 +7262,7 @@ export default { 2, { "input": [ - 404, + 392, "CreateApiKeyInput!" ] } @@ -7392,7 +7271,7 @@ export default { 2, { "input": [ - 405, + 393, "UpdateApiKeyInput!" ] } @@ -7401,7 +7280,7 @@ export default { 2, { "input": [ - 406, + 394, "RevokeApiKeyInput!" ] } @@ -7436,7 +7315,7 @@ export default { 29, { "createRoleInput": [ - 407, + 395, "CreateRoleInput!" ] } @@ -7445,7 +7324,7 @@ export default { 29, { "updateRoleInput": [ - 408, + 396, "UpdateRoleInput!" ] } @@ -7463,7 +7342,7 @@ export default { 16, { "upsertObjectPermissionsInput": [ - 410, + 398, "UpsertObjectPermissionsInput!" ] } @@ -7472,7 +7351,7 @@ export default { 27, { "upsertPermissionFlagsInput": [ - 412, + 400, "UpsertPermissionFlagsInput!" ] } @@ -7481,7 +7360,7 @@ export default { 26, { "upsertFieldPermissionsInput": [ - 413, + 401, "UpsertFieldPermissionsInput!" ] } @@ -7490,7 +7369,7 @@ export default { 181, { "input": [ - 415, + 403, "UpsertRowLevelPermissionPredicatesInput!" ] } @@ -7557,7 +7436,7 @@ export default { 147, { "input": [ - 418, + 406, "CreateApprovedAccessDomainInput!" ] } @@ -7566,7 +7445,7 @@ export default { 6, { "input": [ - 419, + 407, "DeleteApprovedAccessDomainInput!" ] } @@ -7575,7 +7454,7 @@ export default { 147, { "input": [ - 420, + 408, "ValidateApprovedAccessDomainInput!" ] } @@ -7584,7 +7463,7 @@ export default { 34, { "input": [ - 421, + 409, "CreateOneFieldMetadataInput!" ] } @@ -7593,7 +7472,7 @@ export default { 34, { "input": [ - 423, + 411, "UpdateOneFieldMetadataInput!" ] } @@ -7602,11 +7481,132 @@ export default { 34, { "input": [ - 425, + 413, "DeleteOneFieldInput!" ] } ], + "createCoreViewGroup": [ + 56, + { + "input": [ + 414, + "CreateViewGroupInput!" + ] + } + ], + "createManyCoreViewGroups": [ + 56, + { + "inputs": [ + 414, + "[CreateViewGroupInput!]!" + ] + } + ], + "updateCoreViewGroup": [ + 56, + { + "input": [ + 415, + "UpdateViewGroupInput!" + ] + } + ], + "deleteCoreViewGroup": [ + 56, + { + "input": [ + 417, + "DeleteViewGroupInput!" + ] + } + ], + "destroyCoreViewGroup": [ + 56, + { + "input": [ + 418, + "DestroyViewGroupInput!" + ] + } + ], + "createCoreViewFilter": [ + 54, + { + "input": [ + 419, + "CreateViewFilterInput!" + ] + } + ], + "updateCoreViewFilter": [ + 54, + { + "input": [ + 420, + "UpdateViewFilterInput!" + ] + } + ], + "deleteCoreViewFilter": [ + 54, + { + "input": [ + 422, + "DeleteViewFilterInput!" + ] + } + ], + "destroyCoreViewFilter": [ + 54, + { + "input": [ + 423, + "DestroyViewFilterInput!" + ] + } + ], + "createCoreViewFilterGroup": [ + 52, + { + "input": [ + 424, + "CreateViewFilterGroupInput!" + ] + } + ], + "updateCoreViewFilterGroup": [ + 52, + { + "id": [ + 1, + "String!" + ], + "input": [ + 425, + "UpdateViewFilterGroupInput!" + ] + } + ], + "deleteCoreViewFilterGroup": [ + 6, + { + "id": [ + 1, + "String!" + ] + } + ], + "destroyCoreViewFilterGroup": [ + 6, + { + "id": [ + 1, + "String!" + ] + } + ], "deleteUser": [ 69 ], @@ -7989,7 +7989,7 @@ export default { 7, { "file": [ - 400, + 388, "Upload!" ], "universalIdentifier": [ @@ -8504,7 +8504,7 @@ export default { 285, { "file": [ - 400, + 388, "Upload!" ], "applicationUniversalIdentifier": [ @@ -9205,195 +9205,12 @@ export default { 1 ] }, - "CreateViewGroupInput": { - "id": [ - 3 - ], - "isVisible": [ - 6 - ], - "fieldValue": [ - 1 - ], - "position": [ - 11 - ], - "viewId": [ - 3 - ], - "__typename": [ - 1 - ] - }, - "UpdateViewGroupInput": { - "id": [ - 3 - ], - "update": [ - 375 - ], - "__typename": [ - 1 - ] - }, - "UpdateViewGroupInputUpdates": { - "fieldMetadataId": [ - 3 - ], - "isVisible": [ - 6 - ], - "fieldValue": [ - 1 - ], - "position": [ - 11 - ], - "__typename": [ - 1 - ] - }, - "DeleteViewGroupInput": { - "id": [ - 3 - ], - "__typename": [ - 1 - ] - }, - "DestroyViewGroupInput": { - "id": [ - 3 - ], - "__typename": [ - 1 - ] - }, - "CreateViewFilterGroupInput": { - "id": [ - 3 - ], - "parentViewFilterGroupId": [ - 3 - ], - "logicalOperator": [ - 53 - ], - "positionInViewFilterGroup": [ - 11 - ], - "viewId": [ - 3 - ], - "__typename": [ - 1 - ] - }, - "UpdateViewFilterGroupInput": { - "id": [ - 3 - ], - "parentViewFilterGroupId": [ - 3 - ], - "logicalOperator": [ - 53 - ], - "positionInViewFilterGroup": [ - 11 - ], - "viewId": [ - 3 - ], - "__typename": [ - 1 - ] - }, - "CreateViewFilterInput": { - "id": [ - 3 - ], - "fieldMetadataId": [ - 3 - ], - "operand": [ - 55 - ], - "value": [ - 15 - ], - "viewFilterGroupId": [ - 3 - ], - "positionInViewFilterGroup": [ - 11 - ], - "subFieldName": [ - 1 - ], - "viewId": [ - 3 - ], - "__typename": [ - 1 - ] - }, - "UpdateViewFilterInput": { - "id": [ - 3 - ], - "update": [ - 382 - ], - "__typename": [ - 1 - ] - }, - "UpdateViewFilterInputUpdates": { - "fieldMetadataId": [ - 3 - ], - "operand": [ - 55 - ], - "value": [ - 15 - ], - "viewFilterGroupId": [ - 3 - ], - "positionInViewFilterGroup": [ - 11 - ], - "subFieldName": [ - 1 - ], - "__typename": [ - 1 - ] - }, - "DeleteViewFilterInput": { - "id": [ - 3 - ], - "__typename": [ - 1 - ] - }, - "DestroyViewFilterInput": { - "id": [ - 3 - ], - "__typename": [ - 1 - ] - }, "UpdateViewFieldGroupInput": { "id": [ 3 ], "update": [ - 386 + 374 ], "__typename": [ 1 @@ -9457,10 +9274,10 @@ export default { 3 ], "groups": [ - 391 + 379 ], "fields": [ - 392 + 380 ], "__typename": [ 1 @@ -9480,7 +9297,7 @@ export default { 6 ], "fields": [ - 392 + 380 ], "__typename": [ 1 @@ -9601,7 +9418,7 @@ export default { 3 ], "update": [ - 397 + 385 ], "__typename": [ 1 @@ -9732,7 +9549,7 @@ export default { 3 ], "update": [ - 403 + 391 ], "__typename": [ 1 @@ -9849,7 +9666,7 @@ export default { }, "UpdateRoleInput": { "update": [ - 409 + 397 ], "id": [ 3 @@ -9904,7 +9721,7 @@ export default { 3 ], "objectPermissions": [ - 411 + 399 ], "__typename": [ 1 @@ -9946,7 +9763,7 @@ export default { 3 ], "fieldPermissions": [ - 414 + 402 ], "__typename": [ 1 @@ -9977,10 +9794,10 @@ export default { 3 ], "predicates": [ - 416 + 404 ], "predicateGroups": [ - 417 + 405 ], "__typename": [ 1 @@ -10070,7 +9887,7 @@ export default { }, "CreateOneFieldMetadataInput": { "field": [ - 422 + 410 ], "__typename": [ 1 @@ -10143,7 +9960,7 @@ export default { 3 ], "update": [ - 424 + 412 ], "__typename": [ 1 @@ -10207,6 +10024,189 @@ export default { 1 ] }, + "CreateViewGroupInput": { + "id": [ + 3 + ], + "isVisible": [ + 6 + ], + "fieldValue": [ + 1 + ], + "position": [ + 11 + ], + "viewId": [ + 3 + ], + "__typename": [ + 1 + ] + }, + "UpdateViewGroupInput": { + "id": [ + 3 + ], + "update": [ + 416 + ], + "__typename": [ + 1 + ] + }, + "UpdateViewGroupInputUpdates": { + "fieldMetadataId": [ + 3 + ], + "isVisible": [ + 6 + ], + "fieldValue": [ + 1 + ], + "position": [ + 11 + ], + "__typename": [ + 1 + ] + }, + "DeleteViewGroupInput": { + "id": [ + 3 + ], + "__typename": [ + 1 + ] + }, + "DestroyViewGroupInput": { + "id": [ + 3 + ], + "__typename": [ + 1 + ] + }, + "CreateViewFilterInput": { + "id": [ + 3 + ], + "fieldMetadataId": [ + 3 + ], + "operand": [ + 55 + ], + "value": [ + 15 + ], + "viewFilterGroupId": [ + 3 + ], + "positionInViewFilterGroup": [ + 11 + ], + "subFieldName": [ + 1 + ], + "viewId": [ + 3 + ], + "__typename": [ + 1 + ] + }, + "UpdateViewFilterInput": { + "id": [ + 3 + ], + "update": [ + 421 + ], + "__typename": [ + 1 + ] + }, + "UpdateViewFilterInputUpdates": { + "fieldMetadataId": [ + 3 + ], + "operand": [ + 55 + ], + "value": [ + 15 + ], + "viewFilterGroupId": [ + 3 + ], + "positionInViewFilterGroup": [ + 11 + ], + "subFieldName": [ + 1 + ], + "__typename": [ + 1 + ] + }, + "DeleteViewFilterInput": { + "id": [ + 3 + ], + "__typename": [ + 1 + ] + }, + "DestroyViewFilterInput": { + "id": [ + 3 + ], + "__typename": [ + 1 + ] + }, + "CreateViewFilterGroupInput": { + "id": [ + 3 + ], + "parentViewFilterGroupId": [ + 3 + ], + "logicalOperator": [ + 53 + ], + "positionInViewFilterGroup": [ + 11 + ], + "viewId": [ + 3 + ], + "__typename": [ + 1 + ] + }, + "UpdateViewFilterGroupInput": { + "id": [ + 3 + ], + "parentViewFilterGroupId": [ + 3 + ], + "logicalOperator": [ + 53 + ], + "positionInViewFilterGroup": [ + 11 + ], + "viewId": [ + 3 + ], + "__typename": [ + 1 + ] + }, "ActivateWorkspaceInput": { "displayName": [ 1 diff --git a/packages/twenty-server/src/engine/api/common/common-query-runners/common-group-by-query-runner.service.ts b/packages/twenty-server/src/engine/api/common/common-query-runners/common-group-by-query-runner.service.ts index 6056e035bc..d4a8896bb2 100644 --- a/packages/twenty-server/src/engine/api/common/common-query-runners/common-group-by-query-runner.service.ts +++ b/packages/twenty-server/src/engine/api/common/common-query-runners/common-group-by-query-runner.service.ts @@ -11,6 +11,7 @@ import { computeRecordGqlOperationFilter, convertViewFilterValueToString, getFilterTypeFromFieldType, + isDefined, turnAnyFieldFilterIntoRecordGqlFilter, } from 'twenty-shared/utils'; import { ObjectLiteral } from 'typeorm'; @@ -23,8 +24,11 @@ import { CommonQueryRunnerExceptionCode, } from 'src/engine/api/common/common-query-runners/errors/common-query-runner.exception'; import { STANDARD_ERROR_MESSAGE } from 'src/engine/api/common/common-query-runners/errors/standard-error-message.constant'; +import { GroupByDefinition } from 'src/engine/api/common/common-query-runners/types/group-by-definition.type'; +import { GroupByField } from 'src/engine/api/common/common-query-runners/types/group-by-field.types'; import { getGroupByDefinitions } from 'src/engine/api/common/common-query-runners/utils/get-group-by-definitions.util'; import { getObjectAlias } from 'src/engine/api/common/common-query-runners/utils/get-object-alias-for-group-by.util'; +import { isGroupByRelationField } from 'src/engine/api/common/common-query-runners/utils/is-group-by-relation-field.util'; import { CommonBaseQueryRunnerContext } from 'src/engine/api/common/types/common-base-query-runner-context.type'; import { CommonExtendedQueryRunnerContext } from 'src/engine/api/common/types/common-extended-query-runner-context.type'; import { CommonGroupByOutputItem } from 'src/engine/api/common/types/common-group-by-output-item.type'; @@ -36,10 +40,7 @@ import { } from 'src/engine/api/common/types/common-query-args.type'; import { CommonSelectedFieldsResult } from 'src/engine/api/common/types/common-selected-fields-result.type'; import { GraphqlQueryParser } from 'src/engine/api/graphql/graphql-query-runner/graphql-query-parsers/graphql-query.parser'; -import { GroupByDefinition } from 'src/engine/api/common/common-query-runners/types/group-by-definition.type'; -import { GroupByField } from 'src/engine/api/common/common-query-runners/types/group-by-field.types'; import { formatResultWithGroupByDimensionValues } from 'src/engine/api/graphql/graphql-query-runner/group-by/resolvers/utils/format-result-with-group-by-dimension-values.util'; -import { isGroupByRelationField } from 'src/engine/api/common/common-query-runners/utils/is-group-by-relation-field.util'; import { parseGroupByArgs } from 'src/engine/api/graphql/graphql-query-runner/group-by/resolvers/utils/parse-group-by-args.util'; import { GroupByWithRecordsService } from 'src/engine/api/graphql/graphql-query-runner/group-by/services/group-by-with-records.service'; import { getGroupLimit } from 'src/engine/api/graphql/graphql-query-runner/group-by/utils/get-group-limit.util'; @@ -53,7 +54,6 @@ import { isMorphOrRelationFlatFieldMetadata } from 'src/engine/metadata-modules/ import { FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; import { ViewFilterGroupService } from 'src/engine/metadata-modules/view-filter-group/services/view-filter-group.service'; import { ViewFilterService } from 'src/engine/metadata-modules/view-filter/services/view-filter.service'; -import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity'; import { ViewService } from 'src/engine/metadata-modules/view/services/view.service'; import { WorkspaceSelectQueryBuilder } from 'src/engine/twenty-orm/repository/workspace-select-query-builder'; import { formatColumnNameForRelationField } from 'src/engine/twenty-orm/utils/format-column-name-for-relation-field.util'; @@ -263,16 +263,19 @@ export class CommonGroupByQueryRunnerService extends CommonBaseQueryRunnerServic }, }); - let view: ViewEntity | null = viewFilters[0]?.view; + const viewFromFilter = viewFilters[0]?.view; + let viewAnyFieldFilterValue = viewFromFilter?.anyFieldFilterValue; - if (!view) { - view = await this.viewService.findById(args.viewId, workspaceId); + if (!isDefined(viewFromFilter)) { + const view = await this.viewService.findById(args.viewId, workspaceId); + + viewAnyFieldFilterValue = view?.anyFieldFilterValue ?? null; } const { recordGqlOperationFilter: anyFieldFilter } = turnAnyFieldFilterIntoRecordGqlFilter({ fields, - filterValue: view?.anyFieldFilterValue ?? '', + filterValue: viewAnyFieldFilterValue ?? '', }); appliedFilters = combineFilters([ diff --git a/packages/twenty-server/src/engine/dataloaders/dataloader.interface.ts b/packages/twenty-server/src/engine/dataloaders/dataloader.interface.ts index 2e56b63b1b..8531c21fa1 100644 --- a/packages/twenty-server/src/engine/dataloaders/dataloader.interface.ts +++ b/packages/twenty-server/src/engine/dataloaders/dataloader.interface.ts @@ -9,6 +9,11 @@ import { type RelationLoaderPayload, type ViewFieldGroupsByViewIdLoaderPayload, type ViewFieldsByViewFieldGroupIdLoaderPayload, + type ViewFieldsByViewIdLoaderPayload, + type ViewFilterGroupsByViewIdLoaderPayload, + type ViewFiltersByViewIdLoaderPayload, + type ViewGroupsByViewIdLoaderPayload, + type ViewSortsByViewIdLoaderPayload, } from 'src/engine/dataloaders/dataloader.service'; import { type FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto'; import { type RelationDTO } from 'src/engine/metadata-modules/field-metadata/dtos/relation.dto'; @@ -17,6 +22,10 @@ import { type IndexMetadataDTO } from 'src/engine/metadata-modules/index-metadat import { type ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto'; import { type ViewFieldGroupDTO } from 'src/engine/metadata-modules/view-field-group/dtos/view-field-group.dto'; import { type ViewFieldDTO } from 'src/engine/metadata-modules/view-field/dtos/view-field.dto'; +import { type ViewFilterGroupDTO } from 'src/engine/metadata-modules/view-filter-group/dtos/view-filter-group.dto'; +import { type ViewFilterDTO } from 'src/engine/metadata-modules/view-filter/dtos/view-filter.dto'; +import { type ViewGroupDTO } from 'src/engine/metadata-modules/view-group/dtos/view-group.dto'; +import { type ViewSortDTO } from 'src/engine/metadata-modules/view-sort/dtos/view-sort.dto'; export interface IDataloaders { relationLoader: DataLoader; @@ -55,4 +64,29 @@ export interface IDataloaders { ViewFieldsByViewFieldGroupIdLoaderPayload, ViewFieldDTO[] >; + + viewFieldsByViewIdLoader: DataLoader< + ViewFieldsByViewIdLoaderPayload, + ViewFieldDTO[] + >; + + viewFiltersByViewIdLoader: DataLoader< + ViewFiltersByViewIdLoaderPayload, + ViewFilterDTO[] + >; + + viewSortsByViewIdLoader: DataLoader< + ViewSortsByViewIdLoaderPayload, + ViewSortDTO[] + >; + + viewGroupsByViewIdLoader: DataLoader< + ViewGroupsByViewIdLoaderPayload, + ViewGroupDTO[] + >; + + viewFilterGroupsByViewIdLoader: DataLoader< + ViewFilterGroupsByViewIdLoaderPayload, + ViewFilterGroupDTO[] + >; } diff --git a/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts b/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts index 2d06323fb5..5dd48d3124 100644 --- a/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts +++ b/packages/twenty-server/src/engine/dataloaders/dataloader.service.ts @@ -30,6 +30,10 @@ import { fromFlatObjectMetadataToObjectMetadataDto } from 'src/engine/metadata-m import { getMorphNameFromMorphFieldMetadataName } from 'src/engine/metadata-modules/flat-object-metadata/utils/get-morph-name-from-morph-field-metadata-name.util'; import { fromFlatViewFieldGroupToViewFieldGroupDto } from 'src/engine/metadata-modules/view-field-group/utils/from-flat-view-field-group-to-view-field-group-dto.util'; import { fromFlatViewFieldToViewFieldDto } from 'src/engine/metadata-modules/view-field/utils/from-flat-view-field-to-view-field-dto.util'; +import { fromFlatViewFilterToViewFilterDto } from 'src/engine/metadata-modules/view-filter/utils/from-flat-view-filter-to-view-filter-dto.util'; +import { fromFlatViewFilterGroupToViewFilterGroupDto } from 'src/engine/metadata-modules/view-filter-group/utils/from-flat-view-filter-group-to-view-filter-group-dto.util'; +import { fromFlatViewGroupToViewGroupDto } from 'src/engine/metadata-modules/view-group/utils/from-flat-view-group-to-view-group-dto.util'; +import { fromFlatViewSortToViewSortDto } from 'src/engine/metadata-modules/view-sort/utils/from-flat-view-sort-to-view-sort-dto.util'; import { type IndexFieldMetadataDTO } from 'src/engine/metadata-modules/index-metadata/dtos/index-field-metadata.dto'; import { type IndexMetadataDTO } from 'src/engine/metadata-modules/index-metadata/dtos/index-metadata.dto'; import { ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto'; @@ -84,6 +88,31 @@ export type ViewFieldsByViewFieldGroupIdLoaderPayload = { viewFieldGroupId: string; }; +export type ViewFieldsByViewIdLoaderPayload = { + workspaceId: string; + viewId: string; +}; + +export type ViewFiltersByViewIdLoaderPayload = { + workspaceId: string; + viewId: string; +}; + +export type ViewSortsByViewIdLoaderPayload = { + workspaceId: string; + viewId: string; +}; + +export type ViewGroupsByViewIdLoaderPayload = { + workspaceId: string; + viewId: string; +}; + +export type ViewFilterGroupsByViewIdLoaderPayload = { + workspaceId: string; + viewId: string; +}; + @Injectable() export class DataloaderService { constructor( @@ -102,6 +131,12 @@ export class DataloaderService { this.createViewFieldGroupsByViewIdLoader(); const viewFieldsByViewFieldGroupIdLoader = this.createViewFieldsByViewFieldGroupIdLoader(); + const viewFieldsByViewIdLoader = this.createViewFieldsByViewIdLoader(); + const viewFiltersByViewIdLoader = this.createViewFiltersByViewIdLoader(); + const viewSortsByViewIdLoader = this.createViewSortsByViewIdLoader(); + const viewGroupsByViewIdLoader = this.createViewGroupsByViewIdLoader(); + const viewFilterGroupsByViewIdLoader = + this.createViewFilterGroupsByViewIdLoader(); return { relationLoader, @@ -112,6 +147,11 @@ export class DataloaderService { objectMetadataLoader, viewFieldGroupsByViewIdLoader, viewFieldsByViewFieldGroupIdLoader, + viewFieldsByViewIdLoader, + viewFiltersByViewIdLoader, + viewSortsByViewIdLoader, + viewGroupsByViewIdLoader, + viewFilterGroupsByViewIdLoader, }; } @@ -609,4 +649,181 @@ export class DataloaderService { }); }); } + + private createViewFieldsByViewIdLoader() { + return new DataLoader< + ViewFieldsByViewIdLoaderPayload, + ReturnType[] + >(async (dataLoaderParams: ViewFieldsByViewIdLoaderPayload[]) => { + const workspaceId = dataLoaderParams[0].workspaceId; + + const { flatViewMaps, flatViewFieldMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: ['flatViewMaps', 'flatViewFieldMaps'], + }, + ); + + return dataLoaderParams.map(({ viewId }) => { + const flatView = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: viewId, + flatEntityMaps: flatViewMaps, + }); + + if (!isDefined(flatView)) { + return []; + } + + return findManyFlatEntityByIdInFlatEntityMaps({ + flatEntityIds: flatView.viewFieldIds, + flatEntityMaps: flatViewFieldMaps, + }) + .filter((flatViewField) => flatViewField.deletedAt === null) + .map(fromFlatViewFieldToViewFieldDto); + }); + }); + } + + private createViewFiltersByViewIdLoader() { + return new DataLoader< + ViewFiltersByViewIdLoaderPayload, + ReturnType[] + >(async (dataLoaderParams: ViewFiltersByViewIdLoaderPayload[]) => { + const workspaceId = dataLoaderParams[0].workspaceId; + + const { flatViewMaps, flatViewFilterMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: ['flatViewMaps', 'flatViewFilterMaps'], + }, + ); + + return dataLoaderParams.map(({ viewId }) => { + const flatView = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: viewId, + flatEntityMaps: flatViewMaps, + }); + + if (!isDefined(flatView)) { + return []; + } + + return findManyFlatEntityByIdInFlatEntityMaps({ + flatEntityIds: flatView.viewFilterIds, + flatEntityMaps: flatViewFilterMaps, + }) + .filter((flatViewFilter) => flatViewFilter.deletedAt === null) + .map(fromFlatViewFilterToViewFilterDto); + }); + }); + } + + private createViewSortsByViewIdLoader() { + return new DataLoader< + ViewSortsByViewIdLoaderPayload, + ReturnType[] + >(async (dataLoaderParams: ViewSortsByViewIdLoaderPayload[]) => { + const workspaceId = dataLoaderParams[0].workspaceId; + + const { flatViewMaps, flatViewSortMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: ['flatViewMaps', 'flatViewSortMaps'], + }, + ); + + return dataLoaderParams.map(({ viewId }) => { + const flatView = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: viewId, + flatEntityMaps: flatViewMaps, + }); + + if (!isDefined(flatView)) { + return []; + } + + return findManyFlatEntityByIdInFlatEntityMaps({ + flatEntityIds: flatView.viewSortIds, + flatEntityMaps: flatViewSortMaps, + }) + .filter((flatViewSort) => flatViewSort.deletedAt === null) + .map(fromFlatViewSortToViewSortDto); + }); + }); + } + + private createViewGroupsByViewIdLoader() { + return new DataLoader< + ViewGroupsByViewIdLoaderPayload, + ReturnType[] + >(async (dataLoaderParams: ViewGroupsByViewIdLoaderPayload[]) => { + const workspaceId = dataLoaderParams[0].workspaceId; + + const { flatViewMaps, flatViewGroupMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: ['flatViewMaps', 'flatViewGroupMaps'], + }, + ); + + return dataLoaderParams.map(({ viewId }) => { + const flatView = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: viewId, + flatEntityMaps: flatViewMaps, + }); + + if (!isDefined(flatView)) { + return []; + } + + return findManyFlatEntityByIdInFlatEntityMaps({ + flatEntityIds: flatView.viewGroupIds, + flatEntityMaps: flatViewGroupMaps, + }) + .filter((flatViewGroup) => flatViewGroup.deletedAt === null) + .map(fromFlatViewGroupToViewGroupDto); + }); + }); + } + + private createViewFilterGroupsByViewIdLoader() { + return new DataLoader< + ViewFilterGroupsByViewIdLoaderPayload, + ReturnType[] + >(async (dataLoaderParams: ViewFilterGroupsByViewIdLoaderPayload[]) => { + const workspaceId = dataLoaderParams[0].workspaceId; + + const { flatViewMaps, flatViewFilterGroupMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: ['flatViewMaps', 'flatViewFilterGroupMaps'], + }, + ); + + return dataLoaderParams.map(({ viewId }) => { + const flatView = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: viewId, + flatEntityMaps: flatViewMaps, + }); + + if (!isDefined(flatView)) { + return []; + } + + return findManyFlatEntityByIdInFlatEntityMaps({ + flatEntityIds: flatView.viewFilterGroupIds, + flatEntityMaps: flatViewFilterGroupMaps, + }) + .filter( + (flatViewFilterGroup) => flatViewFilterGroup.deletedAt === null, + ) + .map(fromFlatViewFilterGroupToViewFilterGroupDto); + }); + }); + } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view/controllers/view.controller.ts b/packages/twenty-server/src/engine/metadata-modules/view/controllers/view.controller.ts index ca33c02918..2b08025c4b 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view/controllers/view.controller.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view/controllers/view.controller.ts @@ -60,12 +60,15 @@ export class ViewController { @Query('objectMetadataId') objectMetadataId?: string, ): Promise { const views = objectMetadataId - ? await this.viewService.findByObjectMetadataId( + ? await this.viewService.findByObjectMetadataIdWithRelations( workspace.id, objectMetadataId, userWorkspaceId, ) - : await this.viewService.findByWorkspaceId(workspace.id, userWorkspaceId); + : await this.viewService.findByWorkspaceIdWithRelations( + workspace.id, + userWorkspaceId, + ); return this.processViewsWithTemplates(views, workspace.id, locale); } @@ -77,7 +80,7 @@ export class ViewController { @RequestLocale() locale: keyof typeof APP_LOCALES | undefined, @AuthWorkspace() workspace: WorkspaceEntity, ): Promise { - const view = await this.viewService.findById(id, workspace.id); + const view = await this.viewService.findByIdWithRelations(id, workspace.id); if (!isDefined(view)) { throw new ViewException( diff --git a/packages/twenty-server/src/engine/metadata-modules/view/resolvers/view.resolver.ts b/packages/twenty-server/src/engine/metadata-modules/view/resolvers/view.resolver.ts index c5dff90252..0a0fdcdc74 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view/resolvers/view.resolver.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view/resolvers/view.resolver.ts @@ -8,7 +8,6 @@ import { ResolveField, } from '@nestjs/graphql'; -import { isArray } from '@sniptt/guards'; import { ViewType, ViewVisibility } from 'twenty-shared/types'; import { isDefined } from 'twenty-shared/utils'; @@ -25,23 +24,17 @@ import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { resolveObjectMetadataStandardOverride } from 'src/engine/metadata-modules/object-metadata/utils/resolve-object-metadata-standard-override.util'; import { ViewFieldGroupDTO } from 'src/engine/metadata-modules/view-field-group/dtos/view-field-group.dto'; import { ViewFieldDTO } from 'src/engine/metadata-modules/view-field/dtos/view-field.dto'; -import { ViewFieldService } from 'src/engine/metadata-modules/view-field/services/view-field.service'; import { ViewFilterGroupDTO } from 'src/engine/metadata-modules/view-filter-group/dtos/view-filter-group.dto'; -import { ViewFilterGroupService } from 'src/engine/metadata-modules/view-filter-group/services/view-filter-group.service'; import { ViewFilterDTO } from 'src/engine/metadata-modules/view-filter/dtos/view-filter.dto'; -import { ViewFilterService } from 'src/engine/metadata-modules/view-filter/services/view-filter.service'; import { ViewGroupDTO } from 'src/engine/metadata-modules/view-group/dtos/view-group.dto'; -import { ViewGroupService } from 'src/engine/metadata-modules/view-group/services/view-group.service'; import { CreateViewPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/create-view-permission.guard'; import { DeleteViewPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/delete-view-permission.guard'; import { DestroyViewPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/destroy-view-permission.guard'; import { UpdateViewPermissionGuard } from 'src/engine/metadata-modules/view-permissions/guards/update-view-permission.guard'; import { ViewSortDTO } from 'src/engine/metadata-modules/view-sort/dtos/view-sort.dto'; -import { ViewSortService } from 'src/engine/metadata-modules/view-sort/services/view-sort.service'; import { CreateViewInput } from 'src/engine/metadata-modules/view/dtos/inputs/create-view.input'; import { UpdateViewInput } from 'src/engine/metadata-modules/view/dtos/inputs/update-view.input'; import { ViewDTO } from 'src/engine/metadata-modules/view/dtos/view.dto'; -import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity'; import { ViewService } from 'src/engine/metadata-modules/view/services/view.service'; import { ViewGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/view/utils/view-graphql-api-exception.filter'; @@ -51,13 +44,7 @@ import { ViewGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/view/ export class ViewResolver { constructor( private readonly viewService: ViewService, - private readonly viewFilterService: ViewFilterService, - private readonly viewFilterGroupService: ViewFilterGroupService, - private readonly viewSortService: ViewSortService, - private readonly viewGroupService: ViewGroupService, private readonly i18nService: I18nService, - - private readonly viewFieldService: ViewFieldService, ) {} @ResolveField(() => String) @@ -114,7 +101,7 @@ export class ViewResolver { objectMetadataId?: string, @Args('viewTypes', { type: () => [ViewType], nullable: true }) viewTypes?: ViewType[], - ): Promise { + ): Promise { if (objectMetadataId) { return this.viewService.findByObjectMetadataId( workspace.id, @@ -143,7 +130,6 @@ export class ViewResolver { return null; } - // Do not apply list visibility filtering here: unlisted views are accessible by link return view; } @@ -211,61 +197,61 @@ export class ViewResolver { @ResolveField(() => [ViewFieldDTO]) async viewFields( @Parent() view: ViewDTO, + @Context() context: { loaders: IDataloaders }, @AuthWorkspace() workspace: WorkspaceEntity, ) { - if (isArray(view.viewFields)) { - return view.viewFields; - } - - return this.viewFieldService.findByViewId(workspace.id, view.id); + return context.loaders.viewFieldsByViewIdLoader.load({ + workspaceId: workspace.id, + viewId: view.id, + }); } @ResolveField(() => [ViewFilterDTO]) async viewFilters( @Parent() view: ViewDTO, + @Context() context: { loaders: IDataloaders }, @AuthWorkspace() workspace: WorkspaceEntity, ) { - if (isArray(view.viewFilters)) { - return view.viewFilters; - } - - return this.viewFilterService.findByViewId(workspace.id, view.id); + return context.loaders.viewFiltersByViewIdLoader.load({ + workspaceId: workspace.id, + viewId: view.id, + }); } @ResolveField(() => [ViewFilterGroupDTO]) async viewFilterGroups( @Parent() view: ViewDTO, + @Context() context: { loaders: IDataloaders }, @AuthWorkspace() workspace: WorkspaceEntity, ) { - if (isArray(view.viewFilterGroups)) { - return view.viewFilterGroups; - } - - return this.viewFilterGroupService.findByViewId(workspace.id, view.id); + return context.loaders.viewFilterGroupsByViewIdLoader.load({ + workspaceId: workspace.id, + viewId: view.id, + }); } @ResolveField(() => [ViewSortDTO]) async viewSorts( @Parent() view: ViewDTO, + @Context() context: { loaders: IDataloaders }, @AuthWorkspace() workspace: WorkspaceEntity, ) { - if (isArray(view.viewSorts)) { - return view.viewSorts; - } - - return this.viewSortService.findByViewId(workspace.id, view.id); + return context.loaders.viewSortsByViewIdLoader.load({ + workspaceId: workspace.id, + viewId: view.id, + }); } @ResolveField(() => [ViewGroupDTO]) async viewGroups( @Parent() view: ViewDTO, + @Context() context: { loaders: IDataloaders }, @AuthWorkspace() workspace: WorkspaceEntity, ) { - if (isArray(view.viewGroups)) { - return view.viewGroups; - } - - return this.viewGroupService.findByViewId(workspace.id, view.id); + return context.loaders.viewGroupsByViewIdLoader.load({ + workspaceId: workspace.id, + viewId: view.id, + }); } @ResolveField(() => [ViewFieldGroupDTO]) @@ -274,10 +260,6 @@ export class ViewResolver { @Context() context: { loaders: IDataloaders }, @AuthWorkspace() workspace: WorkspaceEntity, ) { - if (isArray(view.viewFieldGroups)) { - return view.viewFieldGroups; - } - return context.loaders.viewFieldGroupsByViewIdLoader.load({ workspaceId: workspace.id, viewId: view.id, diff --git a/packages/twenty-server/src/engine/metadata-modules/view/services/__tests__/view-query-params.service.spec.ts b/packages/twenty-server/src/engine/metadata-modules/view/services/__tests__/view-query-params.service.spec.ts index 1198594b58..ee335b4bba 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view/services/__tests__/view-query-params.service.spec.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view/services/__tests__/view-query-params.service.spec.ts @@ -65,7 +65,7 @@ describe('ViewQueryParamsService', () => { { provide: ViewService, useValue: { - findById: jest.fn(), + findByIdWithRelations: jest.fn(), }, }, { @@ -98,7 +98,7 @@ describe('ViewQueryParamsService', () => { describe('resolveViewToQueryParams', () => { it('should throw error when view is not found', async () => { - viewService.findById.mockResolvedValue(null); + viewService.findByIdWithRelations.mockResolvedValue(null); await expect( viewQueryParamsService.resolveViewToQueryParams( @@ -120,7 +120,7 @@ describe('ViewQueryParamsService', () => { viewSorts: [], }; - viewService.findById.mockResolvedValue(mockView as any); + viewService.findByIdWithRelations.mockResolvedValue(mockView as any); flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps.mockResolvedValue( { flatObjectMetadataMaps: mockFlatObjectMetadataMaps, @@ -168,7 +168,7 @@ describe('ViewQueryParamsService', () => { viewSorts: [], }; - viewService.findById.mockResolvedValue(mockView as any); + viewService.findByIdWithRelations.mockResolvedValue(mockView as any); flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps.mockResolvedValue( { flatObjectMetadataMaps: mockFlatObjectMetadataMaps, @@ -204,7 +204,7 @@ describe('ViewQueryParamsService', () => { ], }; - viewService.findById.mockResolvedValue(mockView as any); + viewService.findByIdWithRelations.mockResolvedValue(mockView as any); flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps.mockResolvedValue( { flatObjectMetadataMaps: mockFlatObjectMetadataMaps, @@ -251,7 +251,7 @@ describe('ViewQueryParamsService', () => { viewSorts: [], }; - viewService.findById.mockResolvedValue(mockView as any); + viewService.findByIdWithRelations.mockResolvedValue(mockView as any); flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps.mockResolvedValue( { flatObjectMetadataMaps: mockFlatObjectMetadataMaps, diff --git a/packages/twenty-server/src/engine/metadata-modules/view/services/view-query-params.service.ts b/packages/twenty-server/src/engine/metadata-modules/view/services/view-query-params.service.ts index eaa9afeddf..7b99f773d7 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view/services/view-query-params.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view/services/view-query-params.service.ts @@ -46,7 +46,10 @@ export class ViewQueryParamsService { workspaceId: string, currentWorkspaceMemberId?: string, ): Promise { - const view = await this.viewService.findById(viewId, workspaceId); + const view = await this.viewService.findByIdWithRelations( + viewId, + workspaceId, + ); if (!view) { throw new Error(`View with id ${viewId} not found`); diff --git a/packages/twenty-server/src/engine/metadata-modules/view/services/view.service.ts b/packages/twenty-server/src/engine/metadata-modules/view/services/view.service.ts index 18453d0b7f..f9396588ce 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view/services/view.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view/services/view.service.ts @@ -4,18 +4,27 @@ import { InjectRepository } from '@nestjs/typeorm'; import { APP_LOCALES, SOURCE_LOCALE } from 'twenty-shared/translations'; import { ViewType, ViewVisibility } from 'twenty-shared/types'; import { isDefined } from 'twenty-shared/utils'; -import { In, IsNull, Repository } from 'typeorm'; +import { Repository } from 'typeorm'; import { ApplicationService } from 'src/engine/core-modules/application/application.service'; import { I18nService } from 'src/engine/core-modules/i18n/i18n.service'; import { generateMessageId } from 'src/engine/core-modules/i18n/utils/generateMessageId'; 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 { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { findFlatEntityByUniversalIdentifierOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-flat-entity-by-universal-identifier-or-throw.util'; +import { findManyFlatEntityByIdInFlatEntityMaps } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps.util'; +import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type'; import { fromCreateViewInputToFlatViewToCreate } from 'src/engine/metadata-modules/flat-view/utils/from-create-view-input-to-flat-view-to-create.util'; import { fromDeleteViewInputToFlatViewOrThrow } from 'src/engine/metadata-modules/flat-view/utils/from-delete-view-input-to-flat-view-or-throw.util'; import { fromDestroyViewInputToFlatViewOrThrow } from 'src/engine/metadata-modules/flat-view/utils/from-destroy-view-input-to-flat-view-or-throw.util'; import { fromUpdateViewInputToFlatViewToUpdateOrThrow } from 'src/engine/metadata-modules/flat-view/utils/from-update-view-input-to-flat-view-to-update-or-throw.util'; +import { fromFlatViewFieldGroupToViewFieldGroupDto } from 'src/engine/metadata-modules/view-field-group/utils/from-flat-view-field-group-to-view-field-group-dto.util'; +import { fromFlatViewFieldToViewFieldDto } from 'src/engine/metadata-modules/view-field/utils/from-flat-view-field-to-view-field-dto.util'; +import { fromFlatViewFilterGroupToViewFilterGroupDto } from 'src/engine/metadata-modules/view-filter-group/utils/from-flat-view-filter-group-to-view-filter-group-dto.util'; +import { fromFlatViewFilterToViewFilterDto } from 'src/engine/metadata-modules/view-filter/utils/from-flat-view-filter-to-view-filter-dto.util'; +import { fromFlatViewGroupToViewGroupDto } from 'src/engine/metadata-modules/view-group/utils/from-flat-view-group-to-view-group-dto.util'; +import { fromFlatViewSortToViewSortDto } from 'src/engine/metadata-modules/view-sort/utils/from-flat-view-sort-to-view-sort-dto.util'; import { CreateViewInput } from 'src/engine/metadata-modules/view/dtos/inputs/create-view.input'; import { DeleteViewInput } from 'src/engine/metadata-modules/view/dtos/inputs/delete-view.input'; import { DestroyViewInput } from 'src/engine/metadata-modules/view/dtos/inputs/destroy-view.input'; @@ -372,42 +381,73 @@ export class ViewService { return viewName; } + private isViewVisibleToUser( + view: { + visibility: ViewVisibility; + createdByUserWorkspaceId: string | null; + }, + userWorkspaceId?: string, + ): boolean { + if (view.visibility === ViewVisibility.WORKSPACE) { + return true; + } + + return ( + view.visibility === ViewVisibility.UNLISTED && + isDefined(userWorkspaceId) && + view.createdByUserWorkspaceId === userWorkspaceId + ); + } + + private async getFilteredFlatViews({ + workspaceId, + objectMetadataId, + userWorkspaceId, + viewTypes, + }: { + workspaceId: string; + objectMetadataId?: string; + userWorkspaceId?: string; + viewTypes?: ViewType[]; + }): Promise { + const { flatViewMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: ['flatViewMaps'], + }, + ); + + return Object.values(flatViewMaps.byUniversalIdentifier) + .filter(isDefined) + .filter((flatView) => flatView.workspaceId === workspaceId) + .filter( + (flatView) => + !objectMetadataId || flatView.objectMetadataId === objectMetadataId, + ) + .filter((flatView) => flatView.deletedAt === null) + .filter( + (flatView) => + !viewTypes || + viewTypes.length === 0 || + viewTypes.includes(flatView.type), + ) + .filter((flatView) => this.isViewVisibleToUser(flatView, userWorkspaceId)) + .sort((a, b) => a.position - b.position); + } + async findByWorkspaceId( workspaceId: string, userWorkspaceId?: string, viewTypes?: ViewType[], - ): Promise { - const views = await this.viewRepository.find({ - where: { - workspaceId, - deletedAt: IsNull(), - ...(viewTypes && viewTypes.length > 0 && { type: In(viewTypes) }), - }, - order: { position: 'ASC' }, - relations: [ - 'workspace', - 'viewFields', - 'viewFilters', - 'viewSorts', - 'viewGroups', - 'viewFilterGroups', - ], + ): Promise { + const flatViews = await this.getFilteredFlatViews({ + workspaceId, + userWorkspaceId, + viewTypes, }); - return views.filter((view) => { - if (view.visibility === ViewVisibility.WORKSPACE) { - return true; - } - if ( - view.visibility === ViewVisibility.UNLISTED && - isDefined(userWorkspaceId) && - view.createdByUserWorkspaceId === userWorkspaceId - ) { - return true; - } - - return false; - }); + return flatViews.map(fromFlatViewToViewDto); } async findByObjectMetadataId( @@ -415,60 +455,170 @@ export class ViewService { objectMetadataId: string, userWorkspaceId?: string, viewTypes?: ViewType[], - ): Promise { - const views = await this.viewRepository.find({ - where: { - workspaceId, - objectMetadataId, - deletedAt: IsNull(), - ...(viewTypes && viewTypes.length > 0 && { type: In(viewTypes) }), - }, - order: { position: 'ASC' }, - relations: [ - 'workspace', - 'viewFields', - 'viewFilters', - 'viewSorts', - 'viewGroups', - 'viewFilterGroups', - ], + ): Promise { + const flatViews = await this.getFilteredFlatViews({ + workspaceId, + objectMetadataId, + userWorkspaceId, + viewTypes, }); - // Apply visibility filtering - return views.filter((view) => { - if (view.visibility === ViewVisibility.WORKSPACE) { - return true; - } - if ( - view.visibility === ViewVisibility.UNLISTED && - isDefined(userWorkspaceId) && - view.createdByUserWorkspaceId === userWorkspaceId - ) { - return true; - } + return flatViews.map(fromFlatViewToViewDto); + } - return false; + async findById(id: string, workspaceId: string): Promise { + const { flatViewMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: ['flatViewMaps'], + }, + ); + + const flatView = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: id, + flatEntityMaps: flatViewMaps, + }); + + if (!isDefined(flatView) || flatView.deletedAt !== null) { + return null; + } + + return fromFlatViewToViewDto(flatView); + } + + async findManyWithRelationsFromCache( + flatViews: FlatView[], + workspaceId: string, + ): Promise { + const { + flatViewFieldMaps, + flatViewFieldGroupMaps, + flatViewFilterMaps, + flatViewFilterGroupMaps, + flatViewSortMaps, + flatViewGroupMaps, + } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: [ + 'flatViewFieldMaps', + 'flatViewFieldGroupMaps', + 'flatViewFilterMaps', + 'flatViewFilterGroupMaps', + 'flatViewSortMaps', + 'flatViewGroupMaps', + ], + }, + ); + + return flatViews.map((flatView) => { + const viewDto = fromFlatViewToViewDto(flatView); + + viewDto.viewFields = findManyFlatEntityByIdInFlatEntityMaps({ + flatEntityIds: flatView.viewFieldIds, + flatEntityMaps: flatViewFieldMaps, + }) + .filter((flatEntity) => flatEntity.deletedAt === null) + .map(fromFlatViewFieldToViewFieldDto); + + viewDto.viewFieldGroups = findManyFlatEntityByIdInFlatEntityMaps({ + flatEntityIds: flatView.viewFieldGroupIds, + flatEntityMaps: flatViewFieldGroupMaps, + }) + .filter((flatEntity) => flatEntity.deletedAt === null) + .map(fromFlatViewFieldGroupToViewFieldGroupDto); + + viewDto.viewFilters = findManyFlatEntityByIdInFlatEntityMaps({ + flatEntityIds: flatView.viewFilterIds, + flatEntityMaps: flatViewFilterMaps, + }) + .filter((flatEntity) => flatEntity.deletedAt === null) + .map(fromFlatViewFilterToViewFilterDto); + + viewDto.viewFilterGroups = findManyFlatEntityByIdInFlatEntityMaps({ + flatEntityIds: flatView.viewFilterGroupIds, + flatEntityMaps: flatViewFilterGroupMaps, + }) + .filter((flatEntity) => flatEntity.deletedAt === null) + .map(fromFlatViewFilterGroupToViewFilterGroupDto); + + viewDto.viewSorts = findManyFlatEntityByIdInFlatEntityMaps({ + flatEntityIds: flatView.viewSortIds, + flatEntityMaps: flatViewSortMaps, + }) + .filter((flatEntity) => flatEntity.deletedAt === null) + .map(fromFlatViewSortToViewSortDto); + + viewDto.viewGroups = findManyFlatEntityByIdInFlatEntityMaps({ + flatEntityIds: flatView.viewGroupIds, + flatEntityMaps: flatViewGroupMaps, + }) + .filter((flatEntity) => flatEntity.deletedAt === null) + .map(fromFlatViewGroupToViewGroupDto); + + return viewDto; }); } - async findById(id: string, workspaceId: string): Promise { - const view = await this.viewRepository.findOne({ - where: { - id, - workspaceId, - deletedAt: IsNull(), - }, - relations: [ - 'workspace', - 'viewFields', - 'viewFilters', - 'viewSorts', - 'viewGroups', - 'viewFilterGroups', - ], + async findByWorkspaceIdWithRelations( + workspaceId: string, + userWorkspaceId?: string, + viewTypes?: ViewType[], + ): Promise { + const flatViews = await this.getFilteredFlatViews({ + workspaceId, + userWorkspaceId, + viewTypes, }); - return view || null; + return this.findManyWithRelationsFromCache(flatViews, workspaceId); + } + + async findByObjectMetadataIdWithRelations( + workspaceId: string, + objectMetadataId: string, + userWorkspaceId?: string, + viewTypes?: ViewType[], + ): Promise { + const flatViews = await this.getFilteredFlatViews({ + workspaceId, + objectMetadataId, + userWorkspaceId, + viewTypes, + }); + + return this.findManyWithRelationsFromCache(flatViews, workspaceId); + } + + async findByIdWithRelations( + id: string, + workspaceId: string, + ): Promise { + const { flatViewMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: ['flatViewMaps'], + }, + ); + + const flatView = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: id, + flatEntityMaps: flatViewMaps, + }); + + if (!isDefined(flatView) || flatView.deletedAt !== null) { + return null; + } + + const results = await this.findManyWithRelationsFromCache( + [flatView], + workspaceId, + ); + + return results[0] ?? null; } async findByIdIncludingDeleted( diff --git a/packages/twenty-server/src/engine/metadata-modules/view/view.module.ts b/packages/twenty-server/src/engine/metadata-modules/view/view.module.ts index 03579f9b09..4032e3d93a 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view/view.module.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view/view.module.ts @@ -8,10 +8,6 @@ import { FlatViewModule } from 'src/engine/metadata-modules/flat-view/flat-view. import { PermissionsModule } from 'src/engine/metadata-modules/permissions/permissions.module'; import { UserRoleModule } from 'src/engine/metadata-modules/user-role/user-role.module'; import { ViewFieldGroupModule } from 'src/engine/metadata-modules/view-field-group/view-field-group.module'; -import { ViewFieldModule } from 'src/engine/metadata-modules/view-field/view-field.module'; -import { ViewFilterGroupModule } from 'src/engine/metadata-modules/view-filter-group/view-filter-group.module'; -import { ViewFilterModule } from 'src/engine/metadata-modules/view-filter/view-filter.module'; -import { ViewGroupModule } from 'src/engine/metadata-modules/view-group/view-group.module'; import { ViewPermissionsModule } from 'src/engine/metadata-modules/view-permissions/view-permissions.module'; import { ViewSortModule } from 'src/engine/metadata-modules/view-sort/view-sort.module'; import { ViewController } from 'src/engine/metadata-modules/view/controllers/view.controller'; @@ -27,11 +23,7 @@ import { WorkspaceMigrationModule } from 'src/engine/workspace-manager/workspace imports: [ TypeOrmModule.forFeature([ViewEntity]), ViewPermissionsModule, - ViewFieldModule, ViewFieldGroupModule, - ViewFilterModule, - ViewFilterGroupModule, - ViewGroupModule, ViewSortModule, I18nModule, ApplicationModule,