diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql index 543ca8b32f..51489facfc 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.graphql +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.graphql @@ -3501,6 +3501,7 @@ type Mutation { createViewGroup(input: CreateViewGroupInput!): ViewGroup! createManyViewGroups(inputs: [CreateViewGroupInput!]!): [ViewGroup!]! updateViewGroup(input: UpdateViewGroupInput!): ViewGroup! + updateManyViewGroups(inputs: [UpdateViewGroupInput!]!): [ViewGroup!]! deleteViewGroup(input: DeleteViewGroupInput!): ViewGroup! destroyViewGroup(input: DestroyViewGroupInput!): ViewGroup! updateMessageFolder(input: UpdateMessageFolderInput!): MessageFolder! diff --git a/packages/twenty-client-sdk/src/metadata/generated/schema.ts b/packages/twenty-client-sdk/src/metadata/generated/schema.ts index a0b70417f8..52fd7b1c52 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/schema.ts +++ b/packages/twenty-client-sdk/src/metadata/generated/schema.ts @@ -2954,6 +2954,7 @@ export interface Mutation { createViewGroup: ViewGroup createManyViewGroups: ViewGroup[] updateViewGroup: ViewGroup + updateManyViewGroups: ViewGroup[] deleteViewGroup: ViewGroup destroyViewGroup: ViewGroup updateMessageFolder: MessageFolder @@ -6207,6 +6208,7 @@ export interface MutationGenqlSelection{ createViewGroup?: (ViewGroupGenqlSelection & { __args: {input: CreateViewGroupInput} }) createManyViewGroups?: (ViewGroupGenqlSelection & { __args: {inputs: CreateViewGroupInput[]} }) updateViewGroup?: (ViewGroupGenqlSelection & { __args: {input: UpdateViewGroupInput} }) + updateManyViewGroups?: (ViewGroupGenqlSelection & { __args: {inputs: UpdateViewGroupInput[]} }) deleteViewGroup?: (ViewGroupGenqlSelection & { __args: {input: DeleteViewGroupInput} }) destroyViewGroup?: (ViewGroupGenqlSelection & { __args: {input: DestroyViewGroupInput} }) updateMessageFolder?: (MessageFolderGenqlSelection & { __args: {input: UpdateMessageFolderInput} }) diff --git a/packages/twenty-client-sdk/src/metadata/generated/types.ts b/packages/twenty-client-sdk/src/metadata/generated/types.ts index ada7e65f35..3b47795bc8 100644 --- a/packages/twenty-client-sdk/src/metadata/generated/types.ts +++ b/packages/twenty-client-sdk/src/metadata/generated/types.ts @@ -8130,6 +8130,15 @@ export default { ] } ], + "updateManyViewGroups": [ + 56, + { + "inputs": [ + 450, + "[UpdateViewGroupInput!]!" + ] + } + ], "deleteViewGroup": [ 56, { diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index 65017e3869..b8526b98fa 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -2703,6 +2703,7 @@ export type Mutation = { updateFrontComponent: FrontComponent; updateLabPublicFeatureFlag: FeatureFlag; updateManyNavigationMenuItems: Array; + updateManyViewGroups: Array; updateMessageChannel: MessageChannel; updateMessageFolder: MessageFolder; updateMessageFolders: Array; @@ -3513,6 +3514,11 @@ export type MutationUpdateManyNavigationMenuItemsArgs = { }; +export type MutationUpdateManyViewGroupsArgs = { + inputs: Array; +}; + + export type MutationUpdateMessageChannelArgs = { input: UpdateMessageChannelInput; }; @@ -7862,6 +7868,13 @@ export type DestroyViewSortMutationVariables = Exact<{ export type DestroyViewSortMutation = { __typename?: 'Mutation', destroyViewSort: boolean }; +export type UpdateManyViewGroupsMutationVariables = Exact<{ + inputs: Array | UpdateViewGroupInput; +}>; + + +export type UpdateManyViewGroupsMutation = { __typename?: 'Mutation', updateManyViewGroups: Array<{ __typename?: 'ViewGroup', id: string, isVisible: boolean, fieldValue: string, position: number, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> }; + export type UpdateViewMutationVariables = Exact<{ id: Scalars['String']; input: UpdateViewInput; @@ -8361,6 +8374,7 @@ export const DestroyViewFilterDocument = {"kind":"Document","definitions":[{"kin export const DestroyViewFilterGroupDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DestroyViewFilterGroup"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"destroyViewFilterGroup"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}}]}]}}]} as unknown as DocumentNode; export const DestroyViewGroupDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DestroyViewGroup"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DestroyViewGroupInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"destroyViewGroup"},"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":"ViewGroupFragment"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewGroupFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewGroup"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"isVisible"}},{"kind":"Field","name":{"kind":"Name","value":"fieldValue"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}}]}}]} as unknown as DocumentNode; export const DestroyViewSortDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"DestroyViewSort"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"DestroyViewSortInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"destroyViewSort"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"input"},"value":{"kind":"Variable","name":{"kind":"Name","value":"input"}}}]}]}}]} as unknown as DocumentNode; +export const UpdateManyViewGroupsDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateManyViewGroups"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"inputs"}},"type":{"kind":"NonNullType","type":{"kind":"ListType","type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateViewGroupInput"}}}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateManyViewGroups"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"inputs"},"value":{"kind":"Variable","name":{"kind":"Name","value":"inputs"}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewGroupFragment"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewGroupFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewGroup"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"isVisible"}},{"kind":"Field","name":{"kind":"Name","value":"fieldValue"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}}]}}]} as unknown as DocumentNode; export const UpdateViewDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateView"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"id"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"String"}}}},{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateViewInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateView"},"arguments":[{"kind":"Argument","name":{"kind":"Name","value":"id"},"value":{"kind":"Variable","name":{"kind":"Name","value":"id"}}},{"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":"ViewFragment"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewFieldFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewField"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"fieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"isVisible"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"size"}},{"kind":"Field","name":{"kind":"Name","value":"aggregateOperation"}},{"kind":"Field","name":{"kind":"Name","value":"viewFieldGroupId"}},{"kind":"Field","name":{"kind":"Name","value":"isOverridden"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewFieldGroupFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewFieldGroup"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"isVisible"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"isOverridden"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}},{"kind":"Field","name":{"kind":"Name","value":"viewFields"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewFieldFragment"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewFilterFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewFilter"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"fieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"operand"}},{"kind":"Field","name":{"kind":"Name","value":"value"}},{"kind":"Field","name":{"kind":"Name","value":"viewFilterGroupId"}},{"kind":"Field","name":{"kind":"Name","value":"positionInViewFilterGroup"}},{"kind":"Field","name":{"kind":"Name","value":"subFieldName"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewFilterGroupFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewFilterGroup"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"parentViewFilterGroupId"}},{"kind":"Field","name":{"kind":"Name","value":"logicalOperator"}},{"kind":"Field","name":{"kind":"Name","value":"positionInViewFilterGroup"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewSortFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewSort"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"fieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"direction"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewGroupFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewGroup"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"isVisible"}},{"kind":"Field","name":{"kind":"Name","value":"fieldValue"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"View"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"objectMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"type"}},{"kind":"Field","name":{"kind":"Name","value":"key"}},{"kind":"Field","name":{"kind":"Name","value":"icon"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"isCompact"}},{"kind":"Field","name":{"kind":"Name","value":"openRecordIn"}},{"kind":"Field","name":{"kind":"Name","value":"kanbanAggregateOperation"}},{"kind":"Field","name":{"kind":"Name","value":"kanbanAggregateOperationFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"mainGroupByFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"shouldHideEmptyGroups"}},{"kind":"Field","name":{"kind":"Name","value":"anyFieldFilterValue"}},{"kind":"Field","name":{"kind":"Name","value":"calendarFieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"calendarLayout"}},{"kind":"Field","name":{"kind":"Name","value":"visibility"}},{"kind":"Field","name":{"kind":"Name","value":"createdByUserWorkspaceId"}},{"kind":"Field","name":{"kind":"Name","value":"viewFields"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewFieldFragment"}}]}},{"kind":"Field","name":{"kind":"Name","value":"viewFieldGroups"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewFieldGroupFragment"}}]}},{"kind":"Field","name":{"kind":"Name","value":"viewFilters"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewFilterFragment"}}]}},{"kind":"Field","name":{"kind":"Name","value":"viewFilterGroups"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewFilterGroupFragment"}}]}},{"kind":"Field","name":{"kind":"Name","value":"viewSorts"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewSortFragment"}}]}},{"kind":"Field","name":{"kind":"Name","value":"viewGroups"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewGroupFragment"}}]}}]}}]} as unknown as DocumentNode; export const UpdateViewFieldDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateViewField"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateViewFieldInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateViewField"},"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":"ViewFieldFragment"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewFieldFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewField"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"fieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"isVisible"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"size"}},{"kind":"Field","name":{"kind":"Name","value":"aggregateOperation"}},{"kind":"Field","name":{"kind":"Name","value":"viewFieldGroupId"}},{"kind":"Field","name":{"kind":"Name","value":"isOverridden"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}}]}}]} as unknown as DocumentNode; export const UpdateViewFieldGroupDocument = {"kind":"Document","definitions":[{"kind":"OperationDefinition","operation":"mutation","name":{"kind":"Name","value":"UpdateViewFieldGroup"},"variableDefinitions":[{"kind":"VariableDefinition","variable":{"kind":"Variable","name":{"kind":"Name","value":"input"}},"type":{"kind":"NonNullType","type":{"kind":"NamedType","name":{"kind":"Name","value":"UpdateViewFieldGroupInput"}}}}],"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"updateViewFieldGroup"},"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":"ViewFieldGroupFragment"}}]}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewFieldFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewField"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"fieldMetadataId"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"isVisible"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"size"}},{"kind":"Field","name":{"kind":"Name","value":"aggregateOperation"}},{"kind":"Field","name":{"kind":"Name","value":"viewFieldGroupId"}},{"kind":"Field","name":{"kind":"Name","value":"isOverridden"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}}]}},{"kind":"FragmentDefinition","name":{"kind":"Name","value":"ViewFieldGroupFragment"},"typeCondition":{"kind":"NamedType","name":{"kind":"Name","value":"ViewFieldGroup"}},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"Field","name":{"kind":"Name","value":"id"}},{"kind":"Field","name":{"kind":"Name","value":"name"}},{"kind":"Field","name":{"kind":"Name","value":"position"}},{"kind":"Field","name":{"kind":"Name","value":"isVisible"}},{"kind":"Field","name":{"kind":"Name","value":"viewId"}},{"kind":"Field","name":{"kind":"Name","value":"isOverridden"}},{"kind":"Field","name":{"kind":"Name","value":"createdAt"}},{"kind":"Field","name":{"kind":"Name","value":"updatedAt"}},{"kind":"Field","name":{"kind":"Name","value":"deletedAt"}},{"kind":"Field","name":{"kind":"Name","value":"viewFields"},"selectionSet":{"kind":"SelectionSet","selections":[{"kind":"FragmentSpread","name":{"kind":"Name","value":"ViewFieldFragment"}}]}}]}}]} as unknown as DocumentNode; diff --git a/packages/twenty-front/src/modules/views/graphql/mutations/updateManyViewGroups.ts b/packages/twenty-front/src/modules/views/graphql/mutations/updateManyViewGroups.ts new file mode 100644 index 0000000000..7697e1ab5c --- /dev/null +++ b/packages/twenty-front/src/modules/views/graphql/mutations/updateManyViewGroups.ts @@ -0,0 +1,11 @@ +import { VIEW_GROUP_FRAGMENT } from '@/views/graphql/fragments/viewGroupFragment'; +import { gql } from '@apollo/client'; + +export const UPDATE_MANY_VIEW_GROUPS = gql` + ${VIEW_GROUP_FRAGMENT} + mutation UpdateManyViewGroups($inputs: [UpdateViewGroupInput!]!) { + updateManyViewGroups(inputs: $inputs) { + ...ViewGroupFragment + } + } +`; diff --git a/packages/twenty-front/src/modules/views/hooks/internal/usePerformViewGroupAPIPersist.ts b/packages/twenty-front/src/modules/views/hooks/internal/usePerformViewGroupAPIPersist.ts index ad366f45a6..fdff739098 100644 --- a/packages/twenty-front/src/modules/views/hooks/internal/usePerformViewGroupAPIPersist.ts +++ b/packages/twenty-front/src/modules/views/hooks/internal/usePerformViewGroupAPIPersist.ts @@ -8,43 +8,44 @@ import { t } from '@lingui/core/macro'; import { CrudOperationType } from 'twenty-shared/types'; import { useMutation } from '@apollo/client/react'; import { - type UpdateViewGroupMutationVariables, - UpdateViewGroupDocument, + type UpdateManyViewGroupsMutationVariables, + UpdateManyViewGroupsDocument, } from '~/generated-metadata/graphql'; export const usePerformViewGroupAPIPersist = () => { - const [updateViewGroupMutation] = useMutation(UpdateViewGroupDocument); + const [updateManyViewGroupsMutation] = useMutation( + UpdateManyViewGroupsDocument, + ); const { handleMetadataError } = useMetadataErrorHandler(); const { enqueueErrorSnackBar } = useSnackBar(); const performViewGroupAPIUpdate = useCallback( async ( - updateViewGroupInputs: UpdateViewGroupMutationVariables[], + updateViewGroupInputs: UpdateManyViewGroupsMutationVariables, ): Promise< - MetadataRequestResult< - Awaited>[] - > + MetadataRequestResult + > | null> > => { - if (updateViewGroupInputs.length === 0) { + if ( + !Array.isArray(updateViewGroupInputs.inputs) || + updateViewGroupInputs.inputs.length === 0 + ) { return { status: 'successful', - response: [], + response: null, }; } try { - const results = await Promise.all( - updateViewGroupInputs.map((variables) => - updateViewGroupMutation({ - variables, - }), - ), - ); + const result = await updateManyViewGroupsMutation({ + variables: updateViewGroupInputs, + }); return { status: 'successful', - response: results, + response: result, }; } catch (error) { if (CombinedGraphQLErrors.is(error)) { @@ -62,7 +63,7 @@ export const usePerformViewGroupAPIPersist = () => { }; } }, - [updateViewGroupMutation, handleMetadataError, enqueueErrorSnackBar], + [updateManyViewGroupsMutation, handleMetadataError, enqueueErrorSnackBar], ); return { diff --git a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts index c4a78d2ba5..fc3f349eb5 100644 --- a/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts +++ b/packages/twenty-front/src/modules/views/hooks/useSaveCurrentViewGroups.ts @@ -67,9 +67,9 @@ export const useSaveCurrentViewGroups = () => { return; } - await performViewGroupAPIUpdate([ - { - input: { + await performViewGroupAPIUpdate({ + inputs: [ + { id: existingField.id, update: { isVisible: viewGroupToSave.isVisible, @@ -77,8 +77,8 @@ export const useSaveCurrentViewGroups = () => { fieldValue: viewGroupToSave.fieldValue, }, }, - }, - ]); + ], + }); }, [ store, @@ -109,7 +109,7 @@ export const useSaveCurrentViewGroups = () => { const currentViewGroups = view.viewGroups; - const viewGroupsToUpdate = viewGroupsToSave + const viewGroupInputsToUpdate = viewGroupsToSave .map((viewGroupToSave) => { const existingField = currentViewGroups.find( (currentViewGroup) => @@ -136,13 +136,11 @@ export const useSaveCurrentViewGroups = () => { } return { - input: { - id: existingField.id, - update: { - isVisible: viewGroupToSave.isVisible, - position: viewGroupToSave.position, - fieldValue: viewGroupToSave.fieldValue, - }, + id: existingField.id, + update: { + isVisible: viewGroupToSave.isVisible, + position: viewGroupToSave.position, + fieldValue: viewGroupToSave.fieldValue, }, }; }) @@ -152,7 +150,7 @@ export const useSaveCurrentViewGroups = () => { throw new Error('mainGroupByFieldMetadataId is required'); } - await performViewGroupAPIUpdate(viewGroupsToUpdate); + await performViewGroupAPIUpdate({ inputs: viewGroupInputsToUpdate }); }, [ store, diff --git a/packages/twenty-server/src/engine/metadata-modules/view-group/resolvers/view-group.resolver.ts b/packages/twenty-server/src/engine/metadata-modules/view-group/resolvers/view-group.resolver.ts index f9b5e05167..2b93c17352 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-group/resolvers/view-group.resolver.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-group/resolvers/view-group.resolver.ts @@ -84,6 +84,19 @@ export class ViewGroupResolver { }); } + @Mutation(() => [ViewGroupDTO]) + @UseGuards(UpdateViewGroupPermissionGuard) + async updateManyViewGroups( + @Args('inputs', { type: () => [UpdateViewGroupInput] }) + updateViewGroupInputs: UpdateViewGroupInput[], + @AuthWorkspace() { id: workspaceId }: WorkspaceEntity, + ): Promise { + return await this.viewGroupService.updateMany({ + updateViewGroupInputs, + workspaceId, + }); + } + @Mutation(() => ViewGroupDTO) @UseGuards(DeleteViewGroupPermissionGuard) async deleteViewGroup( diff --git a/packages/twenty-server/src/engine/metadata-modules/view-group/services/view-group.service.ts b/packages/twenty-server/src/engine/metadata-modules/view-group/services/view-group.service.ts index 3c134a6e7d..e2f1570781 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-group/services/view-group.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-group/services/view-group.service.ts @@ -7,6 +7,7 @@ import { IsNull, Repository } from 'typeorm'; import { ApplicationService } from 'src/engine/core-modules/application/application.service'; 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 { findManyFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/metadata-modules/flat-entity/utils/find-many-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; import { fromCreateViewGroupInputToFlatViewGroupToCreate } from 'src/engine/metadata-modules/flat-view-group/utils/from-create-view-group-input-to-flat-view-group-to-create.util'; @@ -152,6 +153,32 @@ export class ViewGroupService { workspaceId: string; updateViewGroupInput: UpdateViewGroupInput; }): Promise { + const [updatedViewGroup] = await this.updateMany({ + updateViewGroupInputs: [updateViewGroupInput], + workspaceId, + }); + + if (!isDefined(updatedViewGroup)) { + throw new ViewGroupException( + 'Failed to update view group', + ViewGroupExceptionCode.INVALID_VIEW_GROUP_DATA, + ); + } + + return updatedViewGroup; + } + + async updateMany({ + updateViewGroupInputs, + workspaceId, + }: { + updateViewGroupInputs: UpdateViewGroupInput[]; + workspaceId: string; + }): Promise { + if (updateViewGroupInputs.length === 0) { + return []; + } + const { workspaceCustomFlatApplication } = await this.applicationService.findWorkspaceTwentyStandardAndCustomApplicationOrThrow( { @@ -167,11 +194,13 @@ export class ViewGroupService { }, ); - const optimisticallyUpdatedFlatViewGroup = - fromUpdateViewGroupInputToFlatViewGroupToUpdateOrThrow({ - flatViewGroupMaps: existingFlatViewGroupMaps, - updateViewGroupInput, - }); + const flatViewGroupsToUpdate = updateViewGroupInputs.map( + (updateViewGroupInput) => + fromUpdateViewGroupInputToFlatViewGroupToUpdateOrThrow({ + flatViewGroupMaps: existingFlatViewGroupMaps, + updateViewGroupInput, + }), + ); const validateAndBuildResult = await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( @@ -180,7 +209,7 @@ export class ViewGroupService { viewGroup: { flatEntityToCreate: [], flatEntityToDelete: [], - flatEntityToUpdate: [optimisticallyUpdatedFlatViewGroup], + flatEntityToUpdate: flatViewGroupsToUpdate, }, }, workspaceId, @@ -193,7 +222,7 @@ export class ViewGroupService { if (validateAndBuildResult.status === 'fail') { throw new WorkspaceMigrationBuilderException( validateAndBuildResult, - 'Multiple validation errors occurred while updating view group', + 'Multiple validation errors occurred while updating view groups', ); } @@ -205,12 +234,13 @@ export class ViewGroupService { }, ); - return fromFlatViewGroupToViewGroupDto( - findFlatEntityByUniversalIdentifierOrThrow({ - universalIdentifier: - optimisticallyUpdatedFlatViewGroup.universalIdentifier, - flatEntityMaps: recomputedExistingFlatViewGroupMaps, - }), + return updateViewGroupInputs.map(({ id }) => + fromFlatViewGroupToViewGroupDto( + findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: id, + flatEntityMaps: recomputedExistingFlatViewGroupMaps, + }), + ), ); } diff --git a/packages/twenty-server/test/integration/graphql/suites/view/view-group/successful-update-many-view-groups-v2.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/view/view-group/successful-update-many-view-groups-v2.integration-spec.ts new file mode 100644 index 0000000000..02450ff6b1 --- /dev/null +++ b/packages/twenty-server/test/integration/graphql/suites/view/view-group/successful-update-many-view-groups-v2.integration-spec.ts @@ -0,0 +1,235 @@ +import { createOneSelectFieldMetadataForIntegrationTests } from 'test/integration/metadata/suites/field-metadata/utils/create-one-select-field-metadata-for-integration-tests.util'; +import { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util'; +import { deleteOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata.util'; +import { updateOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/update-one-object-metadata.util'; +import { createManyViewGroups } from 'test/integration/metadata/suites/view-group/utils/create-many-view-groups.util'; +import { deleteOneViewGroup } from 'test/integration/metadata/suites/view-group/utils/delete-one-view-group.util'; +import { destroyOneViewGroup } from 'test/integration/metadata/suites/view-group/utils/destroy-one-view-group.util'; +import { updateManyViewGroups } from 'test/integration/metadata/suites/view-group/utils/update-many-view-groups.util'; +import { createOneView } from 'test/integration/metadata/suites/view/utils/create-one-view.util'; +import { isDefined } from 'twenty-shared/utils'; + +import { type CreateViewGroupInput } from 'src/engine/metadata-modules/view-group/dtos/inputs/create-view-group.input'; + +describe('View Group Resolver - Successful Update Many Operations - v2', () => { + let testSetup: { + testViewId: string; + testObjectMetadataId: string; + }; + let createdViewGroupIds: string[] = []; + + beforeAll(async () => { + const { + data: { + createOneObject: { id: objectMetadataId }, + }, + } = await createOneObjectMetadata({ + expectToFail: false, + input: { + nameSingular: 'myUpdateManyGroupTestObjectV2', + namePlural: 'myUpdateManyGroupTestObjectsV2', + labelSingular: 'My Update Many Group Test Object v2', + labelPlural: 'My Update Many Group Test Objects v2', + icon: 'Icon123', + }, + }); + + const { selectFieldMetadataId } = + await createOneSelectFieldMetadataForIntegrationTests({ + input: { + objectMetadataId, + }, + }); + + const { + data: { + createView: { id: testViewId }, + }, + } = await createOneView({ + input: { + icon: 'icon123', + objectMetadataId, + name: 'TestViewForUpdateManyGroups', + mainGroupByFieldMetadataId: selectFieldMetadataId, + }, + expectToFail: false, + }); + + testSetup = { + testViewId, + testObjectMetadataId: objectMetadataId, + }; + }); + + afterAll(async () => { + await updateOneObjectMetadata({ + input: { + idToUpdate: testSetup.testObjectMetadataId, + updatePayload: { + isActive: false, + }, + }, + }); + await deleteOneObjectMetadata({ + expectToFail: false, + input: { idToDelete: testSetup.testObjectMetadataId }, + }); + }); + + afterEach(async () => { + for (const viewGroupId of createdViewGroupIds) { + if (isDefined(viewGroupId)) { + const { + data: { deleteViewGroup }, + } = await deleteOneViewGroup({ + expectToFail: false, + input: { + id: viewGroupId, + }, + }); + + expect(deleteViewGroup.deletedAt).not.toBeNull(); + await destroyOneViewGroup({ + expectToFail: false, + input: { + id: viewGroupId, + }, + }); + } + } + createdViewGroupIds = []; + }); + + it('should batch-update positions of multiple view groups at once', async () => { + const createInputs: CreateViewGroupInput[] = [ + { + viewId: testSetup.testViewId, + position: 0, + isVisible: true, + fieldValue: 'Group A', + }, + { + viewId: testSetup.testViewId, + position: 1, + isVisible: true, + fieldValue: 'Group B', + }, + { + viewId: testSetup.testViewId, + position: 2, + isVisible: true, + fieldValue: 'Group C', + }, + ]; + + const { + data: { createManyViewGroups: createdGroups }, + } = await createManyViewGroups({ + inputs: createInputs, + expectToFail: false, + }); + + createdViewGroupIds = createdGroups.map( + (viewGroup: { id: string }) => viewGroup.id, + ); + + const { + data: { updateManyViewGroups: updatedGroups }, + errors, + } = await updateManyViewGroups({ + inputs: [ + { id: createdGroups[0].id, update: { position: 2 } }, + { id: createdGroups[1].id, update: { position: 0 } }, + { id: createdGroups[2].id, update: { position: 1 } }, + ], + expectToFail: false, + }); + + expect(errors).toBeUndefined(); + expect(updatedGroups).toBeDefined(); + expect(updatedGroups).toHaveLength(3); + + expect(updatedGroups[0]).toMatchObject({ + id: createdGroups[0].id, + position: 2, + }); + expect(updatedGroups[1]).toMatchObject({ + id: createdGroups[1].id, + position: 0, + }); + expect(updatedGroups[2]).toMatchObject({ + id: createdGroups[2].id, + position: 1, + }); + }); + + it('should batch-update visibility of multiple view groups at once', async () => { + const createInputs: CreateViewGroupInput[] = [ + { + viewId: testSetup.testViewId, + position: 0, + isVisible: true, + fieldValue: 'Visible Group', + }, + { + viewId: testSetup.testViewId, + position: 1, + isVisible: true, + fieldValue: 'To Be Hidden Group', + }, + ]; + + const { + data: { createManyViewGroups: createdGroups }, + } = await createManyViewGroups({ + inputs: createInputs, + expectToFail: false, + }); + + createdViewGroupIds = createdGroups.map( + (viewGroup: { id: string }) => viewGroup.id, + ); + + const { + data: { updateManyViewGroups: updatedGroups }, + errors, + } = await updateManyViewGroups({ + inputs: [ + { id: createdGroups[0].id, update: { isVisible: false } }, + { + id: createdGroups[1].id, + update: { isVisible: false, position: 5 }, + }, + ], + expectToFail: false, + }); + + expect(errors).toBeUndefined(); + expect(updatedGroups).toBeDefined(); + expect(updatedGroups).toHaveLength(2); + + expect(updatedGroups[0]).toMatchObject({ + id: createdGroups[0].id, + isVisible: false, + }); + expect(updatedGroups[1]).toMatchObject({ + id: createdGroups[1].id, + isVisible: false, + position: 5, + }); + }); + + it('should return empty array for empty inputs', async () => { + const { + data: { updateManyViewGroups: updatedGroups }, + errors, + } = await updateManyViewGroups({ + inputs: [], + expectToFail: false, + }); + + expect(errors).toBeUndefined(); + expect(updatedGroups).toBeDefined(); + expect(updatedGroups).toHaveLength(0); + }); +}); diff --git a/packages/twenty-server/test/integration/metadata/suites/view-group/utils/update-many-view-groups-query-factory.util.ts b/packages/twenty-server/test/integration/metadata/suites/view-group/utils/update-many-view-groups-query-factory.util.ts new file mode 100644 index 0000000000..ed2a262758 --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/view-group/utils/update-many-view-groups-query-factory.util.ts @@ -0,0 +1,23 @@ +import gql from 'graphql-tag'; +import { VIEW_GROUP_GQL_FIELDS } from 'test/integration/constants/view-gql-fields.constants'; + +import { type UpdateViewGroupInput } from 'src/engine/metadata-modules/view-group/dtos/inputs/update-view-group.input'; + +export const updateManyViewGroupsQueryFactory = ({ + gqlFields = VIEW_GROUP_GQL_FIELDS, + inputs, +}: { + gqlFields?: string; + inputs: UpdateViewGroupInput[]; +}) => ({ + query: gql` + mutation UpdateManyViewGroups($inputs: [UpdateViewGroupInput!]!) { + updateManyViewGroups(inputs: $inputs) { + ${gqlFields} + } + } + `, + variables: { + inputs, + }, +}); diff --git a/packages/twenty-server/test/integration/metadata/suites/view-group/utils/update-many-view-groups.util.ts b/packages/twenty-server/test/integration/metadata/suites/view-group/utils/update-many-view-groups.util.ts new file mode 100644 index 0000000000..cc70fee379 --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/view-group/utils/update-many-view-groups.util.ts @@ -0,0 +1,45 @@ +import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util'; +import { updateManyViewGroupsQueryFactory } from 'test/integration/metadata/suites/view-group/utils/update-many-view-groups-query-factory.util'; +import { type CommonResponseBody } from 'test/integration/metadata/types/common-response-body.type'; +import { warnIfErrorButNotExpectedToFail } from 'test/integration/metadata/utils/warn-if-error-but-not-expected-to-fail.util'; +import { warnIfNoErrorButExpectedToFail } from 'test/integration/metadata/utils/warn-if-no-error-but-expected-to-fail.util'; + +import { type UpdateViewGroupInput } from 'src/engine/metadata-modules/view-group/dtos/inputs/update-view-group.input'; +import { type ViewGroupEntity } from 'src/engine/metadata-modules/view-group/entities/view-group.entity'; + +export const updateManyViewGroups = async ({ + inputs, + gqlFields, + expectToFail, +}: { + inputs: UpdateViewGroupInput[]; + gqlFields?: string; + expectToFail?: boolean; +}): CommonResponseBody<{ + updateManyViewGroups: ViewGroupEntity[]; +}> => { + const graphqlOperation = updateManyViewGroupsQueryFactory({ + inputs, + gqlFields, + }); + + const response = await makeMetadataAPIRequest(graphqlOperation); + + if (expectToFail === true) { + warnIfNoErrorButExpectedToFail({ + response, + errorMessage: + 'View Groups batch update should have failed but did not', + }); + } + + if (expectToFail === false) { + warnIfErrorButNotExpectedToFail({ + response, + errorMessage: + 'View Groups batch update has failed but should not', + }); + } + + return { data: response.body.data, errors: response.body.errors }; +};