From 651ab184a725d4db8d032a95dfca5eebb5c6769b Mon Sep 17 00:00:00 2001 From: Paul Rastoin <45004772+prastoin@users.noreply.github.com> Date: Fri, 10 Oct 2025 15:02:14 +0200 Subject: [PATCH] `[GQL_VIEW_FILTER_API_BREAKING_CHANGE][WHEN_RELEASED_REQUIRES_CACHE_FLUSH]` `ViewFilter` migration to workspace migration v2 (#15010) # Introduction Migrating `viewFilter` to v2 in order to migrate later the field update side effect on view to v2 too ## What's done - Created flat-view-filter - flat view filter runner - flat view filter builder - create view filter service v2 and input transpilers - refactor the existing view filter resolver to fix standard ( BREAKING_CHANGE on graphql api update especially ) REST stays the same - refactored the front to consume the mutations autogenerated ## New generic tools ### Compare two flat entity Introducing a new util to compare two flat entity, it's strictly typed and will be added to the generic builder in a following PR This will ease flat entity addition as won't required to create a specific abstraction for comparison Generic builder will expect specific constant: properties to compare and properties to stringify ### Transform flat entity for comparison Forked and refactor the initial existing method for flat entity business scope and type safety ## Coverage Migrated existing integration tests to fit new contract API This PR does not add strong coverage on validation exceptions Deadlines are too short close https://github.com/twentyhq/core-team-issues/issues/1666 --- .../src/generated-metadata/graphql.ts | 87 +++-- .../twenty-front/src/generated/graphql.ts | 87 +++-- .../graphql/fragments/viewFilterFragment.ts | 3 + .../graphql/mutations/deleteCoreViewFilter.ts | 8 +- .../mutations/destroyCoreViewFilter.ts | 8 +- .../graphql/mutations/updateCoreViewFilter.ts | 4 +- .../internal/usePersistViewFilterRecords.ts | 195 +++++------ .../hooks/useCreateViewFromCurrentView.ts | 16 +- .../useRefreshCoreViewsByObjectMetadataId.ts | 12 +- .../useSaveRecordFiltersToViewFilters.ts | 44 ++- .../useTriggerViewFilterOptimisticEffect.ts | 144 ++++++++ ...ll-flat-entity-maps-properties.constant.ts | 1 + .../empty-all-flat-entity-maps.constant.ts | 1 + ...t-entities-by-metadata-engine-name.type.ts | 2 + .../utils/compare-two-flat-entity.util.ts | 77 +++++ ...ansform-flat-entity-for-comparison.util.ts | 40 +++ ...n-field-input-transpilations-error.util.ts | 1 + .../utils/compare-two-flat-view-field.util.ts | 47 +-- ...iew-filter-editable-properties.constant.ts | 10 + ...t-view-filter-jsonb-properties.constant.ts | 5 + ...w-filter-properties-to-compare.constant.ts | 8 + ...ter-entity-relation-properties.constant.ts | 8 + ...pace-flat-view-filter-map-cache.service.ts | 51 +++ .../types/flat-view-filter-maps.type.ts | 4 + ...-view-filter-properties-to-compare.type.ts | 4 + .../types/flat-view-filter.type.ts | 19 + .../compare-two-flat-view-filter.util.ts | 23 ++ ...nput-to-flat-view-filter-to-create.util.ts | 47 +++ ...input-to-flat-view-filter-or-throw.util.ts | 40 +++ ...input-to-flat-view-filter-or-throw.util.ts | 37 ++ ...lat-view-filter-to-update-or-throw.util.ts | 51 +++ ...-filter-entity-to-flat-view-filter.util.ts | 21 ++ .../workspace-flat-view-map-cache.service.ts | 5 +- .../flat-view/types/flat-view.type.ts | 1 + ...-view-input-to-flat-view-to-create.util.ts | 1 + ...-view-to-flat-view-to-with-default.util.ts | 38 -- .../from-view-entity-to-flat-view.util.ts | 3 +- .../controllers/view-filter.controller.ts | 9 +- .../dtos/inputs/create-view-filter.input.ts | 21 ++ .../dtos/inputs/delete-view-filter.input.ts | 15 + .../dtos/inputs/destroy-view-filter.input.ts | 15 + .../dtos/inputs/update-view-filter.input.ts | 66 +++- .../entities/view-filter.entity.ts | 11 +- .../resolvers/view-filter.resolver.ts | 116 +++++-- .../tests/view-filter.service.spec.ts | 2 +- .../services/view-filter-v2.service.ts | 326 ++++++++++++++++++ .../services/view-filter.service.ts | 4 +- .../view-filter/view-filter.module.ts | 14 +- .../workspace-flat-map-cache.module.ts | 5 + ...ty-orchestrator-actions-report.constant.ts | 1 + ...ption-to-validation-response-error.util.ts | 2 + ...ce-migration-build-orchestrator.service.ts | 37 ++ ...ew-filter-related-flat-entity-maps.type.ts | 6 + ...-v2-view-filter-actions-builder.service.ts | 197 +++++++++++ .../workspace-migration-action-common-v2.ts | 2 + ...ace-migration-view-field-action-v2.type.ts | 22 +- ...ce-migration-view-filter-action-v2.type.ts | 34 ++ .../flat-view-filter-validator.service.ts | 158 +++++++++ ...ace-migration-builder-validators.module.ts | 3 + .../workspace-migration-builder-v2.module.ts | 3 + ...eate-view-filter-action-handler.service.ts | 55 +++ ...lete-view-filter-action-handler.service.ts | 61 ++++ ...date-view-filter-action-handler.service.ts | 70 ++++ ...migration-runner-action-handlers.module.ts | 7 + .../utils/order-object-properties.util.ts | 5 +- .../group-by-resolvers.integration-spec.ts | 27 +- ...r-settings-permissions.integration-spec.ts | 81 +++-- ...w-filter-resolver.integration-spec.ts.snap | 34 ++ ...ate-view-field-v2.integration-spec.ts.snap | 6 + ...ect-on-view-field.integration-spec.ts.snap | 10 + .../view-filter-resolver.integration-spec.ts | 266 +++++++------- ...eate-view-filter-operation-factory.util.ts | 25 -- ...lete-view-filter-operation-factory.util.ts | 16 - ...troy-view-filter-operation-factory.util.ts | 16 - ...date-view-filter-operation-factory.util.ts | 24 -- ...ne-field-metadata.integration-spec.ts.snap | 2 + ...ne-field-metadata.integration-spec.ts.snap | 4 + ...-metadata-enum-v2.integration-spec.ts.snap | 140 ++++++++ ...field-metadata-v2.integration-spec.ts.snap | 136 ++++++++ ...morph-relation-v2.integration-spec.ts.snap | 34 ++ ...relation-creation.integration-spec.ts.snap | 40 +++ ...a-relation-update.integration-spec.ts.snap | 4 + ...bject-metadata-v2.integration-spec.ts.snap | 42 +++ ...e-object-metadata.integration-spec.ts.snap | 6 + ...ate-core-view-filter-query-factory.util.ts | 21 ++ .../utils/create-one-core-view-filter.util.ts | 40 +++ ...ete-core-view-filter-query-factory.util.ts | 21 ++ .../utils/delete-one-core-view-filter.util.ts | 40 +++ ...roy-core-view-filter-query-factory.util.ts | 21 ++ .../destroy-one-core-view-filter.util.ts | 40 +++ ...d-core-view-filters-query-factory.util.ts} | 6 +- .../utils/find-core-view-filters.util.ts | 42 +++ ...ate-core-view-filter-query-factory.util.ts | 21 ++ .../utils/update-one-core-view-filter.util.ts | 40 +++ .../MultiItemFieldDefaultMaxValues.ts | 1 - .../constants/MultiItemFieldMinMaxValues.ts | 1 - .../src/utils/__tests__/parseJson.test.ts | 5 + 97 files changed, 3012 insertions(+), 620 deletions(-) create mode 100644 packages/twenty-front/src/modules/views/optimistic-effects/hooks/useTriggerViewFilterOptimisticEffect.ts create mode 100644 packages/twenty-server/src/engine/core-modules/common/utils/compare-two-flat-entity.util.ts create mode 100644 packages/twenty-server/src/engine/core-modules/common/utils/transform-flat-entity-for-comparison.util.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-editable-properties.constant.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-jsonb-properties.constant.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-properties-to-compare.constant.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-view-filter/constants/view-filter-entity-relation-properties.constant.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-view-filter/services/workspace-flat-view-filter-map-cache.service.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-maps.type.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-properties-to-compare.type.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/compare-two-flat-view-filter.util.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-create-view-filter-input-to-flat-view-filter-to-create.util.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-delete-view-filter-input-to-flat-view-filter-or-throw.util.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-destroy-view-filter-input-to-flat-view-filter-or-throw.util.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-update-view-filter-input-to-flat-view-filter-to-update-or-throw.util.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-view-filter-entity-to-flat-view-filter.util.ts delete mode 100644 packages/twenty-server/src/engine/metadata-modules/flat-view/utils/from-partial-flat-view-to-flat-view-to-with-default.util.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/view-filter/dtos/inputs/delete-view-filter.input.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/view-filter/dtos/inputs/destroy-view-filter.input.ts create mode 100644 packages/twenty-server/src/engine/metadata-modules/view-filter/services/view-filter-v2.service.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/types/view-filter-related-flat-entity-maps.type.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/workspace-migration-v2-view-filter-actions-builder.service.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-filter-action-v2.type.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-filter-validator.service.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/create-view-filter-action-handler.service.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/delete-view-filter-action-handler.service.ts create mode 100644 packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/update-view-filter-action-handler.service.ts create mode 100644 packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/view-filter-resolver.integration-spec.ts.snap delete mode 100644 packages/twenty-server/test/integration/graphql/utils/create-view-filter-operation-factory.util.ts delete mode 100644 packages/twenty-server/test/integration/graphql/utils/delete-view-filter-operation-factory.util.ts delete mode 100644 packages/twenty-server/test/integration/graphql/utils/destroy-view-filter-operation-factory.util.ts delete mode 100644 packages/twenty-server/test/integration/graphql/utils/update-view-filter-operation-factory.util.ts create mode 100644 packages/twenty-server/test/integration/metadata/suites/view-filter/utils/create-core-view-filter-query-factory.util.ts create mode 100644 packages/twenty-server/test/integration/metadata/suites/view-filter/utils/create-one-core-view-filter.util.ts create mode 100644 packages/twenty-server/test/integration/metadata/suites/view-filter/utils/delete-core-view-filter-query-factory.util.ts create mode 100644 packages/twenty-server/test/integration/metadata/suites/view-filter/utils/delete-one-core-view-filter.util.ts create mode 100644 packages/twenty-server/test/integration/metadata/suites/view-filter/utils/destroy-core-view-filter-query-factory.util.ts create mode 100644 packages/twenty-server/test/integration/metadata/suites/view-filter/utils/destroy-one-core-view-filter.util.ts rename packages/twenty-server/test/integration/{graphql/utils/find-view-filters-operation-factory.util.ts => metadata/suites/view-filter/utils/find-core-view-filters-query-factory.util.ts} (74%) create mode 100644 packages/twenty-server/test/integration/metadata/suites/view-filter/utils/find-core-view-filters.util.ts create mode 100644 packages/twenty-server/test/integration/metadata/suites/view-filter/utils/update-core-view-filter-query-factory.util.ts create mode 100644 packages/twenty-server/test/integration/metadata/suites/view-filter/utils/update-one-core-view-filter.util.ts diff --git a/packages/twenty-front/src/generated-metadata/graphql.ts b/packages/twenty-front/src/generated-metadata/graphql.ts index a5b02037ea0..0b1b4ace051 100644 --- a/packages/twenty-front/src/generated-metadata/graphql.ts +++ b/packages/twenty-front/src/generated-metadata/graphql.ts @@ -1048,6 +1048,11 @@ export type DeleteViewFieldInput = { id: Scalars['UUID']; }; +export type DeleteViewFilterInput = { + /** The id of the view filter to delete. */ + id: Scalars['UUID']; +}; + export type DeleteWebhookDto = { id: Scalars['UUID']; }; @@ -1073,6 +1078,11 @@ export type DestroyViewFieldInput = { id: Scalars['UUID']; }; +export type DestroyViewFilterInput = { + /** The id of the view filter to destroy. */ + id: Scalars['UUID']; +}; + /** Schema update on a table */ export enum DistantTableUpdate { COLUMNS_ADDED = 'COLUMNS_ADDED', @@ -1702,7 +1712,7 @@ export type Mutation = { deleteApprovedAccessDomain: Scalars['Boolean']; deleteCoreView: Scalars['Boolean']; deleteCoreViewField: CoreViewField; - deleteCoreViewFilter: Scalars['Boolean']; + deleteCoreViewFilter: CoreViewFilter; deleteCoreViewFilterGroup: Scalars['Boolean']; deleteCoreViewGroup: Scalars['Boolean']; deleteCoreViewSort: Scalars['Boolean']; @@ -1732,7 +1742,7 @@ export type Mutation = { deleteWorkspaceInvitation: Scalars['String']; destroyCoreView: Scalars['Boolean']; destroyCoreViewField: CoreViewField; - destroyCoreViewFilter: Scalars['Boolean']; + destroyCoreViewFilter: CoreViewFilter; destroyCoreViewFilterGroup: Scalars['Boolean']; destroyCoreViewGroup: Scalars['Boolean']; destroyCoreViewSort: Scalars['Boolean']; @@ -2083,7 +2093,7 @@ export type MutationDeleteCoreViewFieldArgs = { export type MutationDeleteCoreViewFilterArgs = { - id: Scalars['String']; + input: DeleteViewFilterInput; }; @@ -2223,7 +2233,7 @@ export type MutationDestroyCoreViewFieldArgs = { export type MutationDestroyCoreViewFilterArgs = { - id: Scalars['String']; + input: DestroyViewFilterInput; }; @@ -2496,7 +2506,6 @@ export type MutationUpdateCoreViewFieldArgs = { export type MutationUpdateCoreViewFilterArgs = { - id: Scalars['String']; input: UpdateViewFilterInput; }; @@ -4109,14 +4118,19 @@ export type UpdateViewFilterGroupInput = { }; export type UpdateViewFilterInput = { + /** The id of the view filter to update */ + id: Scalars['UUID']; + /** The view filter to update */ + update: UpdateViewFilterInputUpdates; +}; + +export type UpdateViewFilterInputUpdates = { fieldMetadataId?: InputMaybe; - id?: InputMaybe; operand?: InputMaybe; positionInViewFilterGroup?: InputMaybe; subFieldName?: InputMaybe; value?: InputMaybe; viewFilterGroupId?: InputMaybe; - viewId?: InputMaybe; }; export type UpdateViewGroupInput = { @@ -5586,11 +5600,11 @@ export type GetCurrentUserQuery = { __typename?: 'Query', currentUser: { __typen export type ViewFieldFragmentFragment = { __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }; -export type ViewFilterFragmentFragment = { __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string }; +export type ViewFilterFragmentFragment = { __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }; export type ViewFilterGroupFragmentFragment = { __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }; -export type ViewFragmentFragment = { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, fieldMetadataId: string, isVisible: boolean, fieldValue: string, position: number, viewId: string }> }; +export type ViewFragmentFragment = { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, fieldMetadataId: string, isVisible: boolean, fieldValue: string, position: number, viewId: string }> }; export type ViewGroupFragmentFragment = { __typename?: 'CoreViewGroup', id: string, fieldMetadataId: string, isVisible: boolean, fieldValue: string, position: number, viewId: string }; @@ -5601,7 +5615,7 @@ export type CreateCoreViewMutationVariables = Exact<{ }>; -export type CreateCoreViewMutation = { __typename?: 'Mutation', createCoreView: { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, fieldMetadataId: string, isVisible: boolean, fieldValue: string, position: number, viewId: string }> } }; +export type CreateCoreViewMutation = { __typename?: 'Mutation', createCoreView: { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, fieldMetadataId: string, isVisible: boolean, fieldValue: string, position: number, viewId: string }> } }; export type CreateCoreViewFieldMutationVariables = Exact<{ input: CreateViewFieldInput; @@ -5615,7 +5629,7 @@ export type CreateCoreViewFilterMutationVariables = Exact<{ }>; -export type CreateCoreViewFilterMutation = { __typename?: 'Mutation', createCoreViewFilter: { __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string } }; +export type CreateCoreViewFilterMutation = { __typename?: 'Mutation', createCoreViewFilter: { __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null } }; export type CreateCoreViewFilterGroupMutationVariables = Exact<{ input: CreateViewFilterGroupInput; @@ -5653,11 +5667,11 @@ export type DeleteCoreViewFieldMutationVariables = Exact<{ export type DeleteCoreViewFieldMutation = { __typename?: 'Mutation', deleteCoreViewField: { __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null } }; export type DeleteCoreViewFilterMutationVariables = Exact<{ - id: Scalars['String']; + input: DeleteViewFilterInput; }>; -export type DeleteCoreViewFilterMutation = { __typename?: 'Mutation', deleteCoreViewFilter: boolean }; +export type DeleteCoreViewFilterMutation = { __typename?: 'Mutation', deleteCoreViewFilter: { __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null } }; export type DeleteCoreViewFilterGroupMutationVariables = Exact<{ id: Scalars['String']; @@ -5695,11 +5709,11 @@ export type DestroyCoreViewFieldMutationVariables = Exact<{ export type DestroyCoreViewFieldMutation = { __typename?: 'Mutation', destroyCoreViewField: { __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null } }; export type DestroyCoreViewFilterMutationVariables = Exact<{ - id: Scalars['String']; + input: DestroyViewFilterInput; }>; -export type DestroyCoreViewFilterMutation = { __typename?: 'Mutation', destroyCoreViewFilter: boolean }; +export type DestroyCoreViewFilterMutation = { __typename?: 'Mutation', destroyCoreViewFilter: { __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null } }; export type DestroyCoreViewFilterGroupMutationVariables = Exact<{ id: Scalars['String']; @@ -5728,7 +5742,7 @@ export type UpdateCoreViewMutationVariables = Exact<{ }>; -export type UpdateCoreViewMutation = { __typename?: 'Mutation', updateCoreView: { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, fieldMetadataId: string, isVisible: boolean, fieldValue: string, position: number, viewId: string }> } }; +export type UpdateCoreViewMutation = { __typename?: 'Mutation', updateCoreView: { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, fieldMetadataId: string, isVisible: boolean, fieldValue: string, position: number, viewId: string }> } }; export type UpdateCoreViewFieldMutationVariables = Exact<{ input: UpdateViewFieldInput; @@ -5738,12 +5752,11 @@ export type UpdateCoreViewFieldMutationVariables = Exact<{ export type UpdateCoreViewFieldMutation = { __typename?: 'Mutation', updateCoreViewField: { __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null } }; export type UpdateCoreViewFilterMutationVariables = Exact<{ - id: Scalars['String']; input: UpdateViewFilterInput; }>; -export type UpdateCoreViewFilterMutation = { __typename?: 'Mutation', updateCoreViewFilter: { __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string } }; +export type UpdateCoreViewFilterMutation = { __typename?: 'Mutation', updateCoreViewFilter: { __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null } }; export type UpdateCoreViewFilterGroupMutationVariables = Exact<{ id: Scalars['String']; @@ -5772,7 +5785,7 @@ export type UpdateCoreViewSortMutation = { __typename?: 'Mutation', updateCoreVi export type FindAllCoreViewsQueryVariables = Exact<{ [key: string]: never; }>; -export type FindAllCoreViewsQuery = { __typename?: 'Query', getCoreViews: Array<{ __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, fieldMetadataId: string, isVisible: boolean, fieldValue: string, position: number, viewId: string }> }> }; +export type FindAllCoreViewsQuery = { __typename?: 'Query', getCoreViews: Array<{ __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, fieldMetadataId: string, isVisible: boolean, fieldValue: string, position: number, viewId: string }> }> }; export type FindManyCoreViewFieldsQueryVariables = Exact<{ viewId: Scalars['String']; @@ -5793,7 +5806,7 @@ export type FindManyCoreViewFiltersQueryVariables = Exact<{ }>; -export type FindManyCoreViewFiltersQuery = { __typename?: 'Query', getCoreViewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string }> }; +export type FindManyCoreViewFiltersQuery = { __typename?: 'Query', getCoreViewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }> }; export type FindManyCoreViewGroupsQueryVariables = Exact<{ viewId?: InputMaybe; @@ -5814,14 +5827,14 @@ export type FindManyCoreViewsQueryVariables = Exact<{ }>; -export type FindManyCoreViewsQuery = { __typename?: 'Query', getCoreViews: Array<{ __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, fieldMetadataId: string, isVisible: boolean, fieldValue: string, position: number, viewId: string }> }> }; +export type FindManyCoreViewsQuery = { __typename?: 'Query', getCoreViews: Array<{ __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, fieldMetadataId: string, isVisible: boolean, fieldValue: string, position: number, viewId: string }> }> }; export type FindOneCoreViewQueryVariables = Exact<{ id: Scalars['String']; }>; -export type FindOneCoreViewQuery = { __typename?: 'Query', getCoreView?: { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, fieldMetadataId: string, isVisible: boolean, fieldValue: string, position: number, viewId: string }> } | null }; +export type FindOneCoreViewQuery = { __typename?: 'Query', getCoreView?: { __typename?: 'CoreView', id: string, name: string, objectMetadataId: string, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: string | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: string | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: string, fieldMetadataId: string, viewId: string, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: string, parentViewFilterGroupId?: string | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: string }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: string, fieldMetadataId: string, direction: ViewSortDirection, viewId: string }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: string, fieldMetadataId: string, isVisible: boolean, fieldValue: string, position: number, viewId: string }> } | null }; export type FindOneCoreViewFieldQueryVariables = Exact<{ id: Scalars['String']; @@ -5835,7 +5848,7 @@ export type FindOneCoreViewFilterQueryVariables = Exact<{ }>; -export type FindOneCoreViewFilterQuery = { __typename?: 'Query', getCoreViewFilter?: { __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string } | null }; +export type FindOneCoreViewFilterQuery = { __typename?: 'Query', getCoreViewFilter?: { __typename?: 'CoreViewFilter', id: string, fieldMetadataId: string, operand: ViewFilterOperand, value: any, viewFilterGroupId?: string | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: string, createdAt: string, updatedAt: string, deletedAt?: string | null } | null }; export type FindOneCoreViewFilterGroupQueryVariables = Exact<{ id: Scalars['String']; @@ -6441,6 +6454,9 @@ export const ViewFilterFragmentFragmentDoc = gql` positionInViewFilterGroup subFieldName viewId + createdAt + updatedAt + deletedAt } `; export const ViewFilterGroupFragmentFragmentDoc = gql` @@ -11997,10 +12013,12 @@ export type DeleteCoreViewFieldMutationHookResult = ReturnType; export type DeleteCoreViewFieldMutationOptions = Apollo.BaseMutationOptions; export const DeleteCoreViewFilterDocument = gql` - mutation DeleteCoreViewFilter($id: String!) { - deleteCoreViewFilter(id: $id) + mutation DeleteCoreViewFilter($input: DeleteViewFilterInput!) { + deleteCoreViewFilter(input: $input) { + ...ViewFilterFragment + } } - `; + ${ViewFilterFragmentFragmentDoc}`; export type DeleteCoreViewFilterMutationFn = Apollo.MutationFunction; /** @@ -12016,7 +12034,7 @@ export type DeleteCoreViewFilterMutationFn = Apollo.MutationFunction; export type DestroyCoreViewFieldMutationOptions = Apollo.BaseMutationOptions; export const DestroyCoreViewFilterDocument = gql` - mutation DestroyCoreViewFilter($id: String!) { - destroyCoreViewFilter(id: $id) + mutation DestroyCoreViewFilter($input: DestroyViewFilterInput!) { + destroyCoreViewFilter(input: $input) { + ...ViewFilterFragment + } } - `; + ${ViewFilterFragmentFragmentDoc}`; export type DestroyCoreViewFilterMutationFn = Apollo.MutationFunction; /** @@ -12204,7 +12224,7 @@ export type DestroyCoreViewFilterMutationFn = Apollo.MutationFunction; export type UpdateCoreViewFieldMutationOptions = Apollo.BaseMutationOptions; export const UpdateCoreViewFilterDocument = gql` - mutation UpdateCoreViewFilter($id: String!, $input: UpdateViewFilterInput!) { - updateCoreViewFilter(id: $id, input: $input) { + mutation UpdateCoreViewFilter($input: UpdateViewFilterInput!) { + updateCoreViewFilter(input: $input) { ...ViewFilterFragment } } @@ -12397,7 +12417,6 @@ export type UpdateCoreViewFilterMutationFn = Apollo.MutationFunction; - id?: InputMaybe; operand?: InputMaybe; positionInViewFilterGroup?: InputMaybe; subFieldName?: InputMaybe; value?: InputMaybe; viewFilterGroupId?: InputMaybe; - viewId?: InputMaybe; }; export type UpdateViewGroupInput = { @@ -4450,11 +4464,11 @@ export type OnDbEventSubscription = { __typename?: 'Subscription', onDbEvent: { export type ViewFieldFragmentFragment = { __typename?: 'CoreViewField', id: any, fieldMetadataId: any, viewId: any, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }; -export type ViewFilterFragmentFragment = { __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any }; +export type ViewFilterFragmentFragment = { __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any, createdAt: string, updatedAt: string, deletedAt?: string | null }; export type ViewFilterGroupFragmentFragment = { __typename?: 'CoreViewFilterGroup', id: any, parentViewFilterGroupId?: any | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: any }; -export type ViewFragmentFragment = { __typename?: 'CoreView', id: any, name: string, objectMetadataId: any, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: any | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: any | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: any, fieldMetadataId: any, viewId: any, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: any, parentViewFilterGroupId?: any | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: any }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: any, fieldMetadataId: any, direction: ViewSortDirection, viewId: any }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: any, fieldMetadataId: any, isVisible: boolean, fieldValue: string, position: number, viewId: any }> }; +export type ViewFragmentFragment = { __typename?: 'CoreView', id: any, name: string, objectMetadataId: any, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: any | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: any | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: any, fieldMetadataId: any, viewId: any, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: any, parentViewFilterGroupId?: any | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: any }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: any, fieldMetadataId: any, direction: ViewSortDirection, viewId: any }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: any, fieldMetadataId: any, isVisible: boolean, fieldValue: string, position: number, viewId: any }> }; export type ViewGroupFragmentFragment = { __typename?: 'CoreViewGroup', id: any, fieldMetadataId: any, isVisible: boolean, fieldValue: string, position: number, viewId: any }; @@ -4465,7 +4479,7 @@ export type CreateCoreViewMutationVariables = Exact<{ }>; -export type CreateCoreViewMutation = { __typename?: 'Mutation', createCoreView: { __typename?: 'CoreView', id: any, name: string, objectMetadataId: any, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: any | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: any | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: any, fieldMetadataId: any, viewId: any, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: any, parentViewFilterGroupId?: any | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: any }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: any, fieldMetadataId: any, direction: ViewSortDirection, viewId: any }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: any, fieldMetadataId: any, isVisible: boolean, fieldValue: string, position: number, viewId: any }> } }; +export type CreateCoreViewMutation = { __typename?: 'Mutation', createCoreView: { __typename?: 'CoreView', id: any, name: string, objectMetadataId: any, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: any | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: any | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: any, fieldMetadataId: any, viewId: any, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: any, parentViewFilterGroupId?: any | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: any }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: any, fieldMetadataId: any, direction: ViewSortDirection, viewId: any }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: any, fieldMetadataId: any, isVisible: boolean, fieldValue: string, position: number, viewId: any }> } }; export type CreateCoreViewFieldMutationVariables = Exact<{ input: CreateViewFieldInput; @@ -4479,7 +4493,7 @@ export type CreateCoreViewFilterMutationVariables = Exact<{ }>; -export type CreateCoreViewFilterMutation = { __typename?: 'Mutation', createCoreViewFilter: { __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any } }; +export type CreateCoreViewFilterMutation = { __typename?: 'Mutation', createCoreViewFilter: { __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any, createdAt: string, updatedAt: string, deletedAt?: string | null } }; export type CreateCoreViewFilterGroupMutationVariables = Exact<{ input: CreateViewFilterGroupInput; @@ -4517,11 +4531,11 @@ export type DeleteCoreViewFieldMutationVariables = Exact<{ export type DeleteCoreViewFieldMutation = { __typename?: 'Mutation', deleteCoreViewField: { __typename?: 'CoreViewField', id: any, fieldMetadataId: any, viewId: any, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null } }; export type DeleteCoreViewFilterMutationVariables = Exact<{ - id: Scalars['String']; + input: DeleteViewFilterInput; }>; -export type DeleteCoreViewFilterMutation = { __typename?: 'Mutation', deleteCoreViewFilter: boolean }; +export type DeleteCoreViewFilterMutation = { __typename?: 'Mutation', deleteCoreViewFilter: { __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any, createdAt: string, updatedAt: string, deletedAt?: string | null } }; export type DeleteCoreViewFilterGroupMutationVariables = Exact<{ id: Scalars['String']; @@ -4559,11 +4573,11 @@ export type DestroyCoreViewFieldMutationVariables = Exact<{ export type DestroyCoreViewFieldMutation = { __typename?: 'Mutation', destroyCoreViewField: { __typename?: 'CoreViewField', id: any, fieldMetadataId: any, viewId: any, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null } }; export type DestroyCoreViewFilterMutationVariables = Exact<{ - id: Scalars['String']; + input: DestroyViewFilterInput; }>; -export type DestroyCoreViewFilterMutation = { __typename?: 'Mutation', destroyCoreViewFilter: boolean }; +export type DestroyCoreViewFilterMutation = { __typename?: 'Mutation', destroyCoreViewFilter: { __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any, createdAt: string, updatedAt: string, deletedAt?: string | null } }; export type DestroyCoreViewFilterGroupMutationVariables = Exact<{ id: Scalars['String']; @@ -4592,7 +4606,7 @@ export type UpdateCoreViewMutationVariables = Exact<{ }>; -export type UpdateCoreViewMutation = { __typename?: 'Mutation', updateCoreView: { __typename?: 'CoreView', id: any, name: string, objectMetadataId: any, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: any | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: any | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: any, fieldMetadataId: any, viewId: any, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: any, parentViewFilterGroupId?: any | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: any }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: any, fieldMetadataId: any, direction: ViewSortDirection, viewId: any }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: any, fieldMetadataId: any, isVisible: boolean, fieldValue: string, position: number, viewId: any }> } }; +export type UpdateCoreViewMutation = { __typename?: 'Mutation', updateCoreView: { __typename?: 'CoreView', id: any, name: string, objectMetadataId: any, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: any | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: any | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: any, fieldMetadataId: any, viewId: any, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: any, parentViewFilterGroupId?: any | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: any }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: any, fieldMetadataId: any, direction: ViewSortDirection, viewId: any }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: any, fieldMetadataId: any, isVisible: boolean, fieldValue: string, position: number, viewId: any }> } }; export type UpdateCoreViewFieldMutationVariables = Exact<{ input: UpdateViewFieldInput; @@ -4602,12 +4616,11 @@ export type UpdateCoreViewFieldMutationVariables = Exact<{ export type UpdateCoreViewFieldMutation = { __typename?: 'Mutation', updateCoreViewField: { __typename?: 'CoreViewField', id: any, fieldMetadataId: any, viewId: any, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null } }; export type UpdateCoreViewFilterMutationVariables = Exact<{ - id: Scalars['String']; input: UpdateViewFilterInput; }>; -export type UpdateCoreViewFilterMutation = { __typename?: 'Mutation', updateCoreViewFilter: { __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any } }; +export type UpdateCoreViewFilterMutation = { __typename?: 'Mutation', updateCoreViewFilter: { __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any, createdAt: string, updatedAt: string, deletedAt?: string | null } }; export type UpdateCoreViewFilterGroupMutationVariables = Exact<{ id: Scalars['String']; @@ -4636,7 +4649,7 @@ export type UpdateCoreViewSortMutation = { __typename?: 'Mutation', updateCoreVi export type FindAllCoreViewsQueryVariables = Exact<{ [key: string]: never; }>; -export type FindAllCoreViewsQuery = { __typename?: 'Query', getCoreViews: Array<{ __typename?: 'CoreView', id: any, name: string, objectMetadataId: any, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: any | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: any | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: any, fieldMetadataId: any, viewId: any, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: any, parentViewFilterGroupId?: any | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: any }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: any, fieldMetadataId: any, direction: ViewSortDirection, viewId: any }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: any, fieldMetadataId: any, isVisible: boolean, fieldValue: string, position: number, viewId: any }> }> }; +export type FindAllCoreViewsQuery = { __typename?: 'Query', getCoreViews: Array<{ __typename?: 'CoreView', id: any, name: string, objectMetadataId: any, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: any | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: any | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: any, fieldMetadataId: any, viewId: any, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: any, parentViewFilterGroupId?: any | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: any }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: any, fieldMetadataId: any, direction: ViewSortDirection, viewId: any }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: any, fieldMetadataId: any, isVisible: boolean, fieldValue: string, position: number, viewId: any }> }> }; export type FindManyCoreViewFieldsQueryVariables = Exact<{ viewId: Scalars['String']; @@ -4657,7 +4670,7 @@ export type FindManyCoreViewFiltersQueryVariables = Exact<{ }>; -export type FindManyCoreViewFiltersQuery = { __typename?: 'Query', getCoreViewFilters: Array<{ __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any }> }; +export type FindManyCoreViewFiltersQuery = { __typename?: 'Query', getCoreViewFilters: Array<{ __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any, createdAt: string, updatedAt: string, deletedAt?: string | null }> }; export type FindManyCoreViewGroupsQueryVariables = Exact<{ viewId?: InputMaybe; @@ -4678,14 +4691,14 @@ export type FindManyCoreViewsQueryVariables = Exact<{ }>; -export type FindManyCoreViewsQuery = { __typename?: 'Query', getCoreViews: Array<{ __typename?: 'CoreView', id: any, name: string, objectMetadataId: any, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: any | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: any | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: any, fieldMetadataId: any, viewId: any, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: any, parentViewFilterGroupId?: any | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: any }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: any, fieldMetadataId: any, direction: ViewSortDirection, viewId: any }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: any, fieldMetadataId: any, isVisible: boolean, fieldValue: string, position: number, viewId: any }> }> }; +export type FindManyCoreViewsQuery = { __typename?: 'Query', getCoreViews: Array<{ __typename?: 'CoreView', id: any, name: string, objectMetadataId: any, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: any | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: any | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: any, fieldMetadataId: any, viewId: any, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: any, parentViewFilterGroupId?: any | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: any }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: any, fieldMetadataId: any, direction: ViewSortDirection, viewId: any }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: any, fieldMetadataId: any, isVisible: boolean, fieldValue: string, position: number, viewId: any }> }> }; export type FindOneCoreViewQueryVariables = Exact<{ id: Scalars['String']; }>; -export type FindOneCoreViewQuery = { __typename?: 'Query', getCoreView?: { __typename?: 'CoreView', id: any, name: string, objectMetadataId: any, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: any | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: any | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: any, fieldMetadataId: any, viewId: any, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: any, parentViewFilterGroupId?: any | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: any }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: any, fieldMetadataId: any, direction: ViewSortDirection, viewId: any }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: any, fieldMetadataId: any, isVisible: boolean, fieldValue: string, position: number, viewId: any }> } | null }; +export type FindOneCoreViewQuery = { __typename?: 'Query', getCoreView?: { __typename?: 'CoreView', id: any, name: string, objectMetadataId: any, type: ViewType, key?: ViewKey | null, icon: string, position: number, isCompact: boolean, openRecordIn: ViewOpenRecordIn, kanbanAggregateOperation?: AggregateOperations | null, kanbanAggregateOperationFieldMetadataId?: any | null, anyFieldFilterValue?: string | null, calendarFieldMetadataId?: any | null, calendarLayout?: ViewCalendarLayout | null, viewFields: Array<{ __typename?: 'CoreViewField', id: any, fieldMetadataId: any, viewId: any, isVisible: boolean, position: number, size: number, aggregateOperation?: AggregateOperations | null, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilters: Array<{ __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any, createdAt: string, updatedAt: string, deletedAt?: string | null }>, viewFilterGroups: Array<{ __typename?: 'CoreViewFilterGroup', id: any, parentViewFilterGroupId?: any | null, logicalOperator: ViewFilterGroupLogicalOperator, positionInViewFilterGroup?: number | null, viewId: any }>, viewSorts: Array<{ __typename?: 'CoreViewSort', id: any, fieldMetadataId: any, direction: ViewSortDirection, viewId: any }>, viewGroups: Array<{ __typename?: 'CoreViewGroup', id: any, fieldMetadataId: any, isVisible: boolean, fieldValue: string, position: number, viewId: any }> } | null }; export type FindOneCoreViewFieldQueryVariables = Exact<{ id: Scalars['String']; @@ -4699,7 +4712,7 @@ export type FindOneCoreViewFilterQueryVariables = Exact<{ }>; -export type FindOneCoreViewFilterQuery = { __typename?: 'Query', getCoreViewFilter?: { __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any } | null }; +export type FindOneCoreViewFilterQuery = { __typename?: 'Query', getCoreViewFilter?: { __typename?: 'CoreViewFilter', id: any, fieldMetadataId: any, operand: ViewFilterOperand, value: any, viewFilterGroupId?: any | null, positionInViewFilterGroup?: number | null, subFieldName?: string | null, viewId: any, createdAt: string, updatedAt: string, deletedAt?: string | null } | null }; export type FindOneCoreViewFilterGroupQueryVariables = Exact<{ id: Scalars['String']; @@ -4836,6 +4849,9 @@ export const ViewFilterFragmentFragmentDoc = gql` positionInViewFilterGroup subFieldName viewId + createdAt + updatedAt + deletedAt } `; export const ViewFilterGroupFragmentFragmentDoc = gql` @@ -5311,10 +5327,12 @@ export type DeleteCoreViewFieldMutationHookResult = ReturnType; export type DeleteCoreViewFieldMutationOptions = Apollo.BaseMutationOptions; export const DeleteCoreViewFilterDocument = gql` - mutation DeleteCoreViewFilter($id: String!) { - deleteCoreViewFilter(id: $id) + mutation DeleteCoreViewFilter($input: DeleteViewFilterInput!) { + deleteCoreViewFilter(input: $input) { + ...ViewFilterFragment + } } - `; + ${ViewFilterFragmentFragmentDoc}`; export type DeleteCoreViewFilterMutationFn = Apollo.MutationFunction; /** @@ -5330,7 +5348,7 @@ export type DeleteCoreViewFilterMutationFn = Apollo.MutationFunction; export type DestroyCoreViewFieldMutationOptions = Apollo.BaseMutationOptions; export const DestroyCoreViewFilterDocument = gql` - mutation DestroyCoreViewFilter($id: String!) { - destroyCoreViewFilter(id: $id) + mutation DestroyCoreViewFilter($input: DestroyViewFilterInput!) { + destroyCoreViewFilter(input: $input) { + ...ViewFilterFragment + } } - `; + ${ViewFilterFragmentFragmentDoc}`; export type DestroyCoreViewFilterMutationFn = Apollo.MutationFunction; /** @@ -5518,7 +5538,7 @@ export type DestroyCoreViewFilterMutationFn = Apollo.MutationFunction; export type UpdateCoreViewFieldMutationOptions = Apollo.BaseMutationOptions; export const UpdateCoreViewFilterDocument = gql` - mutation UpdateCoreViewFilter($id: String!, $input: UpdateViewFilterInput!) { - updateCoreViewFilter(id: $id, input: $input) { + mutation UpdateCoreViewFilter($input: UpdateViewFilterInput!) { + updateCoreViewFilter(input: $input) { ...ViewFilterFragment } } @@ -5711,7 +5731,6 @@ export type UpdateCoreViewFilterMutationFn = Apollo.MutationFunction { - const { objectMetadataItem } = useObjectMetadataItem({ - objectNameSingular: CoreObjectNameSingular.ViewFilter, - }); - - const getRecordFromCache = useGetRecordFromCache({ - objectNameSingular: CoreObjectNameSingular.ViewFilter, - }); - - const { objectMetadataItems } = useObjectMetadataItems(); - const { objectPermissionsByObjectMetadataId } = useObjectPermissions(); - const apolloClient = useApolloClient(); + const { triggerViewFilterOptimisticEffect } = + useTriggerViewFilterOptimisticEffect(); + const [createCoreViewFilterMutation] = useCreateCoreViewFilterMutation(); + const [updateCoreViewFilterMutation] = useUpdateCoreViewFilterMutation(); + const [deleteCoreViewFilterMutation] = useDeleteCoreViewFilterMutation(); + const [destroyCoreViewFilterMutation] = useDestroyCoreViewFilterMutation(); const createCoreViewFilterRecords = useCallback( - (viewFiltersToCreate: ViewFilter[], view: Pick) => { - if (viewFiltersToCreate.length === 0) return; + (createCoreViewFilterInputs: CreateCoreViewFilterMutationVariables[]) => { + if (createCoreViewFilterInputs.length === 0) { + return; + } return Promise.all( - viewFiltersToCreate.map((viewFilter) => - apolloClient.mutate({ - mutation: CREATE_CORE_VIEW_FILTER, - variables: { - input: { - id: viewFilter.id, - fieldMetadataId: viewFilter.fieldMetadataId, - viewId: view.id, - value: viewFilter.value, - operand: viewFilter.operand, - viewFilterGroupId: viewFilter.viewFilterGroupId, - positionInViewFilterGroup: viewFilter.positionInViewFilterGroup, - subFieldName: viewFilter.subFieldName ?? null, - } satisfies Partial, - }, - update: (cache, { data }) => { - const record = data?.['createCoreViewFilter']; - if (!isDefined(record)) return; + createCoreViewFilterInputs.map((variables) => + createCoreViewFilterMutation({ + variables, + update: (_cache, { data }) => { + const createdViewFilter = data?.createCoreViewFilter; + if (!isDefined(createdViewFilter)) { + return; + } - triggerCreateRecordsOptimisticEffect({ - cache, - objectMetadataItem, - recordsToCreate: [record], - objectMetadataItems, - objectPermissionsByObjectMetadataId, + triggerViewFilterOptimisticEffect({ + createdViewFilters: [createdViewFilter], }); }, }), ), ); }, - [ - apolloClient, - objectMetadataItem, - objectMetadataItems, - objectPermissionsByObjectMetadataId, - ], + [triggerViewFilterOptimisticEffect, createCoreViewFilterMutation], ); const updateCoreViewFilterRecords = useCallback( - (viewFiltersToUpdate: ViewFilter[]) => { - if (!viewFiltersToUpdate.length) return; + (updateCoreViewFilterInputs: UpdateCoreViewFilterMutationVariables[]) => { + if (updateCoreViewFilterInputs.length === 0) { + return; + } + return Promise.all( - viewFiltersToUpdate.map((viewFilter) => - apolloClient.mutate({ - mutation: UPDATE_CORE_VIEW_FILTER, - variables: { - id: viewFilter.id, - input: { - value: viewFilter.value, - operand: viewFilter.operand, - positionInViewFilterGroup: viewFilter.positionInViewFilterGroup, - viewFilterGroupId: viewFilter.viewFilterGroupId, - subFieldName: viewFilter.subFieldName ?? null, - } satisfies Partial, - }, - update: (cache, { data }) => { - const record = data?.['updateCoreViewFilter']; - if (!isDefined(record)) return; + updateCoreViewFilterInputs.map((variables) => + updateCoreViewFilterMutation({ + variables, + update: (_cache, { data }) => { + const updatedViewFilter = data?.updateCoreViewFilter; + if (!isDefined(updatedViewFilter)) { + return; + } - const cachedRecord = getRecordFromCache( - record.id, - cache, - ); - if (isNull(cachedRecord)) return; - - triggerUpdateRecordOptimisticEffect({ - cache, - objectMetadataItem, - currentRecord: cachedRecord, - updatedRecord: record, - objectMetadataItems, + triggerViewFilterOptimisticEffect({ + updatedViewFilters: [updatedViewFilter], }); }, }), ), ); }, - [apolloClient, getRecordFromCache, objectMetadataItem, objectMetadataItems], + [triggerViewFilterOptimisticEffect, updateCoreViewFilterMutation], ); const deleteCoreViewFilterRecords = useCallback( - (viewFilterIdsToDelete: string[]) => { - if (!viewFilterIdsToDelete.length) return; + (deleteCoreViewFilterInputs: DeleteCoreViewFilterMutationVariables[]) => { + if (deleteCoreViewFilterInputs.length === 0) { + return; + } + return Promise.all( - viewFilterIdsToDelete.map((viewFilterId) => - apolloClient.mutate({ - mutation: DESTROY_CORE_VIEW_FILTER, - variables: { - id: viewFilterId, - }, - update: (cache, { data }) => { - const record = data?.['destroyCoreViewFilter']; - if (!isDefined(record)) return; + deleteCoreViewFilterInputs.map((variables) => + deleteCoreViewFilterMutation({ + variables, + update: (_cache, { data }) => { + const deletedViewFilter = data?.deleteCoreViewFilter; + if (!isDefined(deletedViewFilter)) { + return; + } - const cachedRecord = getRecordFromCache( - record.id, - cache, - ); - if (isNull(cachedRecord)) return; - - triggerDestroyRecordsOptimisticEffect({ - cache, - objectMetadataItem, - recordsToDestroy: [cachedRecord], - objectMetadataItems, + triggerViewFilterOptimisticEffect({ + deletedViewFilters: [deletedViewFilter], }); }, }), ), ); }, - [apolloClient, getRecordFromCache, objectMetadataItem, objectMetadataItems], + [triggerViewFilterOptimisticEffect, deleteCoreViewFilterMutation], + ); + + const destroyCoreViewFilterRecords = useCallback( + (destroyCoreViewFilterInputs: DestroyCoreViewFilterMutationVariables[]) => { + if (destroyCoreViewFilterInputs.length === 0) { + return; + } + + return Promise.all( + destroyCoreViewFilterInputs.map((variables) => + destroyCoreViewFilterMutation({ + variables, + }), + ), + ); + }, + [destroyCoreViewFilterMutation], ); return { createViewFilterRecords: createCoreViewFilterRecords, updateViewFilterRecords: updateCoreViewFilterRecords, deleteViewFilterRecords: deleteCoreViewFilterRecords, + destroyViewFilterRecords: destroyCoreViewFilterRecords, }; }; diff --git a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts index eb4ea9b4b02..14b03f3d28a 100644 --- a/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts +++ b/packages/twenty-front/src/modules/views/hooks/useCreateViewFromCurrentView.ts @@ -231,7 +231,21 @@ export const useCreateViewFromCurrentView = (viewBarComponentId?: string) => { await createViewFilterGroupRecords(viewFilterGroupsToCreate, { id: newViewId, }); - await createViewFilterRecords(viewFiltersToCreate, { id: newViewId }); + const createViewFilterInputs = viewFiltersToCreate.map( + (viewFilter) => ({ + input: { + id: viewFilter.id, + fieldMetadataId: viewFilter.fieldMetadataId, + viewId: newViewId, + value: viewFilter.value, + operand: viewFilter.operand, + viewFilterGroupId: viewFilter.viewFilterGroupId, + positionInViewFilterGroup: viewFilter.positionInViewFilterGroup, + subFieldName: viewFilter.subFieldName ?? null, + }, + }), + ); + await createViewFilterRecords(createViewFilterInputs); await createViewSortRecords(viewSortsToCreate, { id: newViewId }); } diff --git a/packages/twenty-front/src/modules/views/hooks/useRefreshCoreViewsByObjectMetadataId.ts b/packages/twenty-front/src/modules/views/hooks/useRefreshCoreViewsByObjectMetadataId.ts index 7d159794a44..b041814f3a4 100644 --- a/packages/twenty-front/src/modules/views/hooks/useRefreshCoreViewsByObjectMetadataId.ts +++ b/packages/twenty-front/src/modules/views/hooks/useRefreshCoreViewsByObjectMetadataId.ts @@ -95,7 +95,17 @@ export const useRefreshCoreViewsByObjectMetadataId = () => { ); } - if (!isDeeplyEqual(coreView.viewFilters, existingView.viewFilters)) { + if ( + !isDeeplyEqual( + coreView.viewFilters.map((viewFilter) => + removePropertiesFromRecord(viewFilter, [ + 'createdAt', + 'updatedAt', + ]), + ), + existingView.viewFilters, + ) + ) { const view = convertCoreViewToView(coreView); set( currentRecordFiltersComponentState.atomFamily({ diff --git a/packages/twenty-front/src/modules/views/hooks/useSaveRecordFiltersToViewFilters.ts b/packages/twenty-front/src/modules/views/hooks/useSaveRecordFiltersToViewFilters.ts index 66e26831a7d..261a4784498 100644 --- a/packages/twenty-front/src/modules/views/hooks/useSaveRecordFiltersToViewFilters.ts +++ b/packages/twenty-front/src/modules/views/hooks/useSaveRecordFiltersToViewFilters.ts @@ -56,13 +56,47 @@ export const useSaveRecordFiltersToViewFilters = () => { newViewFilters, ); - const viewFilterIdsToDelete = viewFiltersToDelete.map( - (viewFilter) => viewFilter.id, + const createViewFilterInputs = viewFiltersToCreate.map( + (viewFilter) => ({ + input: { + id: viewFilter.id, + fieldMetadataId: viewFilter.fieldMetadataId, + viewId: currentView.id, + value: viewFilter.value, + operand: viewFilter.operand, + viewFilterGroupId: viewFilter.viewFilterGroupId, + positionInViewFilterGroup: viewFilter.positionInViewFilterGroup, + subFieldName: viewFilter.subFieldName ?? null, + }, + }), ); - await createViewFilterRecords(viewFiltersToCreate, currentView); - await updateViewFilterRecords(viewFiltersToUpdate); - await deleteViewFilterRecords(viewFilterIdsToDelete); + const updateViewFilterInputs = viewFiltersToUpdate.map( + (viewFilter) => ({ + input: { + id: viewFilter.id, + update: { + value: viewFilter.value, + operand: viewFilter.operand, + positionInViewFilterGroup: viewFilter.positionInViewFilterGroup, + viewFilterGroupId: viewFilter.viewFilterGroupId, + subFieldName: viewFilter.subFieldName ?? null, + }, + }, + }), + ); + + const deleteViewFilterInputs = viewFiltersToDelete.map( + (viewFilter) => ({ + input: { + id: viewFilter.id, + }, + }), + ); + + await createViewFilterRecords(createViewFilterInputs); + await updateViewFilterRecords(updateViewFilterInputs); + await deleteViewFilterRecords(deleteViewFilterInputs); }, [ currentView, diff --git a/packages/twenty-front/src/modules/views/optimistic-effects/hooks/useTriggerViewFilterOptimisticEffect.ts b/packages/twenty-front/src/modules/views/optimistic-effects/hooks/useTriggerViewFilterOptimisticEffect.ts new file mode 100644 index 00000000000..0f535a6d736 --- /dev/null +++ b/packages/twenty-front/src/modules/views/optimistic-effects/hooks/useTriggerViewFilterOptimisticEffect.ts @@ -0,0 +1,144 @@ +import { getSnapshotValue } from '@/ui/utilities/state/utils/getSnapshotValue'; +import { coreViewsState } from '@/views/states/coreViewState'; +import { type CoreViewWithRelations } from '@/views/types/CoreViewWithRelations'; +import { useApolloClient } from '@apollo/client'; +import { useRecoilCallback } from 'recoil'; +import { isDefined } from 'twenty-shared/utils'; +import { type CoreViewFilter } from '~/generated/graphql'; +import { isDeeplyEqual } from '~/utils/isDeeplyEqual'; +type UpdatedDeletedCoreViewFilter = { + createdViewFilters?: Omit[]; + updatedViewFilters?: Omit[]; + deletedViewFilters?: Pick[]; +}; +export const useTriggerViewFilterOptimisticEffect = () => { + const apolloClient = useApolloClient(); + + const cache = apolloClient.cache; + + const triggerViewFilterOptimisticEffect = useRecoilCallback( + ({ set, snapshot }) => + ({ + createdViewFilters = [], + updatedViewFilters = [], + deletedViewFilters = [], + }: UpdatedDeletedCoreViewFilter) => { + const coreViews = getSnapshotValue(snapshot, coreViewsState); + let newCoreViews = [...coreViews]; + + createdViewFilters.forEach((createdViewFilter) => { + cache.modify({ + id: cache.identify({ + __typename: 'CoreView', + id: createdViewFilter.viewId, + }), + fields: { + viewFilters: (existingViewFilters, { toReference }) => [ + ...(existingViewFilters ?? []), + toReference(createdViewFilter), + ], + }, + }); + const toBeModifiedCoreView = newCoreViews.find( + (coreView) => coreView.id === createdViewFilter.viewId, + ); + if (isDefined(toBeModifiedCoreView)) { + newCoreViews = [ + ...newCoreViews.filter( + (coreView) => coreView.id !== createdViewFilter.viewId, + ), + { + ...toBeModifiedCoreView, + viewFilters: [ + ...toBeModifiedCoreView.viewFilters, + createdViewFilter, + ], + }, + ]; + } + }); + + updatedViewFilters.forEach((updatedViewFilter) => { + cache.modify({ + id: cache.identify({ + __typename: 'CoreView', + id: updatedViewFilter.viewId, + }), + fields: { + viewFilters: (existingViewFilters, { readField, toReference }) => + existingViewFilters.map((viewFilter) => { + const viewFilterId = readField('id', viewFilter); + if (viewFilterId === updatedViewFilter.id) { + return toReference(updatedViewFilter); + } + return viewFilter; + }), + }, + }); + const toBeModifiedCoreView = newCoreViews.find( + (coreView) => coreView.id === updatedViewFilter.viewId, + ); + if (isDefined(toBeModifiedCoreView)) { + newCoreViews = [ + ...newCoreViews.filter( + (coreView) => coreView.id !== updatedViewFilter.viewId, + ), + { + ...toBeModifiedCoreView, + viewFilters: [ + ...toBeModifiedCoreView.viewFilters.filter( + (viewFilter) => viewFilter.id !== updatedViewFilter.id, + ), + updatedViewFilter, + ], + }, + ]; + } + }); + + deletedViewFilters.forEach( + (deletedViewFilter: Pick) => { + cache.modify({ + id: cache.identify({ + __typename: 'CoreView', + id: deletedViewFilter.viewId, + }), + fields: { + viewFilters: (existingViewFilters, { readField }) => + existingViewFilters.filter( + (viewFilter) => + readField('id', viewFilter) !== deletedViewFilter.id, + ), + }, + }); + const toBeModifiedCoreView = newCoreViews.find( + (coreView) => coreView.id === deletedViewFilter.viewId, + ); + + if (isDefined(toBeModifiedCoreView)) { + newCoreViews = [ + ...newCoreViews.filter( + (coreView) => coreView.id !== deletedViewFilter.viewId, + ), + { + ...toBeModifiedCoreView, + viewFilters: toBeModifiedCoreView.viewFilters.filter( + (viewFilter) => viewFilter.id !== deletedViewFilter.id, + ), + }, + ]; + } + }, + ); + + if (!isDeeplyEqual(coreViews, newCoreViews)) { + set(coreViewsState, newCoreViews); + } + }, + [cache], + ); + + return { + triggerViewFilterOptimisticEffect, + }; +}; diff --git a/packages/twenty-server/src/engine/core-modules/common/constant/all-flat-entity-maps-properties.constant.ts b/packages/twenty-server/src/engine/core-modules/common/constant/all-flat-entity-maps-properties.constant.ts index 7a7aa753136..a50dda43291 100644 --- a/packages/twenty-server/src/engine/core-modules/common/constant/all-flat-entity-maps-properties.constant.ts +++ b/packages/twenty-server/src/engine/core-modules/common/constant/all-flat-entity-maps-properties.constant.ts @@ -10,4 +10,5 @@ export const ALL_FLAT_ENTITY_MAPS_PROPERTIES = [ 'flatCronTriggerMaps', 'flatRouteTriggerMaps', 'flatFieldMetadataMaps', + 'flatViewFilterMaps', ] as const satisfies (keyof AllFlatEntityMaps)[]; diff --git a/packages/twenty-server/src/engine/core-modules/common/constant/empty-all-flat-entity-maps.constant.ts b/packages/twenty-server/src/engine/core-modules/common/constant/empty-all-flat-entity-maps.constant.ts index 7e7605fa4fe..5f83a16bf8b 100644 --- a/packages/twenty-server/src/engine/core-modules/common/constant/empty-all-flat-entity-maps.constant.ts +++ b/packages/twenty-server/src/engine/core-modules/common/constant/empty-all-flat-entity-maps.constant.ts @@ -11,4 +11,5 @@ export const EMPTY_ALL_FLAT_ENTITY_MAPS = { flatCronTriggerMaps: EMPTY_FLAT_ENTITY_MAPS, flatDatabaseEventTriggerMaps: EMPTY_FLAT_ENTITY_MAPS, flatRouteTriggerMaps: EMPTY_FLAT_ENTITY_MAPS, + flatViewFilterMaps: EMPTY_FLAT_ENTITY_MAPS, } as const satisfies AllFlatEntityMaps; diff --git a/packages/twenty-server/src/engine/core-modules/common/types/all-flat-entities-by-metadata-engine-name.type.ts b/packages/twenty-server/src/engine/core-modules/common/types/all-flat-entities-by-metadata-engine-name.type.ts index 190fc4e9837..df06605d1bb 100644 --- a/packages/twenty-server/src/engine/core-modules/common/types/all-flat-entities-by-metadata-engine-name.type.ts +++ b/packages/twenty-server/src/engine/core-modules/common/types/all-flat-entities-by-metadata-engine-name.type.ts @@ -4,6 +4,7 @@ import { type FlatFieldMetadata } from 'src/engine/metadata-modules/flat-field-m import { type FlatIndexMetadata } from 'src/engine/metadata-modules/flat-index-metadata/types/flat-index-metadata.type'; import { type FlatObjectMetadata } from 'src/engine/metadata-modules/flat-object-metadata/types/flat-object-metadata.type'; import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type'; +import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type'; import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type'; import { type FlatRouteTrigger } from 'src/engine/metadata-modules/route-trigger/types/flat-route-trigger.type'; import { type FlatServerlessFunction } from 'src/engine/metadata-modules/serverless-function/types/flat-serverless-function.type'; @@ -18,4 +19,5 @@ export type AllFlatEntitiesByMetadataEngineName = { cronTrigger: FlatCronTrigger; databaseEventTrigger: FlatDatabaseEventTrigger; routeTrigger: FlatRouteTrigger; + viewFilter: FlatViewFilter; }; diff --git a/packages/twenty-server/src/engine/core-modules/common/utils/compare-two-flat-entity.util.ts b/packages/twenty-server/src/engine/core-modules/common/utils/compare-two-flat-entity.util.ts new file mode 100644 index 00000000000..cbd32a323d3 --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/common/utils/compare-two-flat-entity.util.ts @@ -0,0 +1,77 @@ +import diff from 'microdiff'; +import { type FromTo } from 'twenty-shared/types'; +import { parseJson } from 'twenty-shared/utils'; + +import { type AllFlatEntities } from 'src/engine/core-modules/common/types/all-flat-entities.type'; +import { transformFlatEntityForComparison } from 'src/engine/core-modules/common/utils/transform-flat-entity-for-comparison.util'; +import { type PropertyUpdate } from 'src/engine/workspace-manager/workspace-migration-v2/types/property-update.type'; + +export const compareTwoFlatEntity = < + TFlatEntity extends AllFlatEntities, + PToCompare extends keyof TFlatEntity, + PJsonB extends keyof TFlatEntity, +>({ + fromFlatEntity, + toFlatEntity, + propertiesToCompare, + propertiesToStringify, +}: { + propertiesToCompare: PToCompare[]; + propertiesToStringify: PJsonB[]; +} & FromTo) => { + const [transformedFromFlatEntity, transformedToFlatEntity] = [ + fromFlatEntity, + toFlatEntity, + ].map((flatEntity) => + transformFlatEntityForComparison({ + flatEntity, + options: { + propertiesToCompare, + propertiesToStringify, + }, + }), + ); + + const flatEntityDifferences = diff( + transformedFromFlatEntity, + transformedToFlatEntity, + ); + + return flatEntityDifferences.flatMap< + Array< + { + [P in PToCompare]: PropertyUpdate; + }[PToCompare] + >[number] + >((difference) => { + switch (difference.type) { + case 'CHANGE': { + const { oldValue, path, value } = difference; + const property = path[0] as PToCompare; + const isJsonb = propertiesToStringify.includes( + property as unknown as PJsonB, + ); + + if (isJsonb) { + return { + from: parseJson(oldValue), + to: parseJson(value), + property, + }; + } + + return { + from: oldValue, + to: value, + property, + }; + } + case 'CREATE': + case 'REMOVE': + default: { + // Should never occurs, we should only provide null never undefined and so on + return []; + } + } + }); +}; diff --git a/packages/twenty-server/src/engine/core-modules/common/utils/transform-flat-entity-for-comparison.util.ts b/packages/twenty-server/src/engine/core-modules/common/utils/transform-flat-entity-for-comparison.util.ts new file mode 100644 index 00000000000..aa696ef797c --- /dev/null +++ b/packages/twenty-server/src/engine/core-modules/common/utils/transform-flat-entity-for-comparison.util.ts @@ -0,0 +1,40 @@ +import { type AllFlatEntities } from 'src/engine/core-modules/common/types/all-flat-entities.type'; +import { orderObjectProperties } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/order-object-properties.util'; + +export function transformFlatEntityForComparison< + TFlatEntity extends AllFlatEntities, + PToCompare extends keyof TFlatEntity, + PJsonB extends keyof TFlatEntity, +>({ + flatEntity, + options: { propertiesToCompare, propertiesToStringify }, +}: { + flatEntity: TFlatEntity; + options: { + propertiesToCompare: PToCompare[]; + propertiesToStringify: PJsonB[]; + }; +}) { + return propertiesToCompare.reduce( + (flatEntityAccumulator, propertyToCompare) => { + const currentValue = flatEntity[propertyToCompare]; + + if ( + propertiesToStringify.includes(propertyToCompare as unknown as PJsonB) + ) { + const orderedValue = orderObjectProperties(currentValue); + + return { + ...flatEntityAccumulator, + [propertyToCompare]: JSON.stringify(orderedValue), + }; + } + + return { + ...flatEntityAccumulator, + [propertyToCompare]: currentValue, + }; + }, + {} as Pick, + ); +} diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util.ts index 7feac8c3cfa..225d65755a5 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-field-metadata/utils/throw-on-field-input-transpilations-error.util.ts @@ -24,6 +24,7 @@ export const throwOnFieldInputTranspilationsError: ThrowOnFieldInputTranspilatio throw new WorkspaceMigrationBuilderExceptionV2( { report: { + viewFilter: [], fieldMetadata: [], index: [], view: [], diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-field/utils/compare-two-flat-view-field.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-field/utils/compare-two-flat-view-field.util.ts index 5aced1eafa7..89cc12b45a6 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-view-field/utils/compare-two-flat-view-field.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-field/utils/compare-two-flat-view-field.util.ts @@ -1,11 +1,8 @@ -import diff from 'microdiff'; import { type FromTo } from 'twenty-shared/types'; +import { compareTwoFlatEntity } from 'src/engine/core-modules/common/utils/compare-two-flat-entity.util'; import { FLAT_VIEW_FIELD_PROPERTIES_TO_COMPARE } from 'src/engine/metadata-modules/flat-view-field/constants/flat-view-field-properties-to-compare.constant'; -import { type FlatViewFieldPropertiesToCompare } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field-properties-to-compare.type'; import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type'; -import { type UpdateViewFieldAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-field-action-v2.type'; -import { transformMetadataForComparison } from 'src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/transform-metadata-for-comparison.util'; type GetWorkspaceMigrationUpdateViewFieldActionArgs = FromTo< FlatViewField, @@ -16,44 +13,10 @@ export const compareTwoFlatViewField = ({ fromFlatViewField, toFlatViewField, }: GetWorkspaceMigrationUpdateViewFieldActionArgs) => { - const transformMetadataForComparisonParameters = { - shouldIgnoreProperty: (property: string) => - !FLAT_VIEW_FIELD_PROPERTIES_TO_COMPARE.includes( - property as FlatViewFieldPropertiesToCompare, - ), + return compareTwoFlatEntity({ + fromFlatEntity: fromFlatViewField, + toFlatEntity: toFlatViewField, propertiesToStringify: [], - }; - const fromCompare = transformMetadataForComparison( - fromFlatViewField, - transformMetadataForComparisonParameters, - ); - const toCompare = transformMetadataForComparison( - toFlatViewField, - transformMetadataForComparisonParameters, - ); - - const flatViewFieldDifferences = diff(fromCompare, toCompare); - - return flatViewFieldDifferences.flatMap< - UpdateViewFieldAction['updates'][number] - >((difference) => { - switch (difference.type) { - case 'CHANGE': { - const { oldValue, path, value } = difference; - const property = path[0] as FlatViewFieldPropertiesToCompare; - - return { - from: oldValue, - to: value, - property, - }; - } - case 'CREATE': - case 'REMOVE': - default: { - // Should never occurs, we should only provide null never undefined and so on - return []; - } - } + propertiesToCompare: FLAT_VIEW_FIELD_PROPERTIES_TO_COMPARE, }); }; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-editable-properties.constant.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-editable-properties.constant.ts new file mode 100644 index 00000000000..81b30a955a7 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-editable-properties.constant.ts @@ -0,0 +1,10 @@ +import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type'; + +export const FLAT_VIEW_FILTER_EDITABLE_PROPERTIES = [ + 'fieldMetadataId', + 'operand', + 'value', + 'viewFilterGroupId', + 'positionInViewFilterGroup', + 'subFieldName', +] as const satisfies (keyof FlatViewFilter)[]; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-jsonb-properties.constant.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-jsonb-properties.constant.ts new file mode 100644 index 00000000000..fa04eb772e2 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-jsonb-properties.constant.ts @@ -0,0 +1,5 @@ +import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type'; + +export const FLAT_VIEW_FILTER_JSONB_PROPERTIES = [ + 'value', +] as const satisfies (keyof FlatViewFilter)[]; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-properties-to-compare.constant.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-properties-to-compare.constant.ts new file mode 100644 index 00000000000..0642208a62d --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-properties-to-compare.constant.ts @@ -0,0 +1,8 @@ +import { FLAT_VIEW_FILTER_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-editable-properties.constant'; +import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type'; + +export const FLAT_VIEW_FILTER_PROPERTIES_TO_COMPARE = [ + 'viewId', + 'deletedAt', + ...FLAT_VIEW_FILTER_EDITABLE_PROPERTIES, +] as const satisfies (keyof FlatViewFilter)[]; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/constants/view-filter-entity-relation-properties.constant.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/constants/view-filter-entity-relation-properties.constant.ts new file mode 100644 index 00000000000..ddddee89638 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/constants/view-filter-entity-relation-properties.constant.ts @@ -0,0 +1,8 @@ +import { type ViewFilterEntityRelationProperties } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type'; + +export const VIEW_FILTER_ENTITY_RELATION_PROPERTIES = [ + 'fieldMetadata', + 'view', + 'viewFilterGroup', + 'workspace', +] as const satisfies ViewFilterEntityRelationProperties[]; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/services/workspace-flat-view-filter-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/services/workspace-flat-view-filter-map-cache.service.ts new file mode 100644 index 00000000000..cee58eaf93f --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/services/workspace-flat-view-filter-map-cache.service.ts @@ -0,0 +1,51 @@ +import { Injectable } from '@nestjs/common'; +import { InjectRepository } from '@nestjs/typeorm'; + +import { Repository } from 'typeorm'; + +import { InjectCacheStorage } from 'src/engine/core-modules/cache-storage/decorators/cache-storage.decorator'; +import { CacheStorageService } from 'src/engine/core-modules/cache-storage/services/cache-storage.service'; +import { CacheStorageNamespace } from 'src/engine/core-modules/cache-storage/types/cache-storage-namespace.enum'; +import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/core-modules/common/constant/empty-flat-entity-maps.constant'; +import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; +import { type FlatViewFilterMaps } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-maps.type'; +import { fromViewFilterEntityToFlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/utils/from-view-filter-entity-to-flat-view-filter.util'; +import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity'; +import { WorkspaceFlatMapCache } from 'src/engine/workspace-flat-map-cache/decorators/workspace-flat-map-cache.decorator'; +import { WorkspaceFlatMapCacheService } from 'src/engine/workspace-flat-map-cache/services/workspace-flat-map-cache.service'; + +@Injectable() +@WorkspaceFlatMapCache('flatViewFilterMaps') +export class WorkspaceFlatViewFilterMapCacheService extends WorkspaceFlatMapCacheService { + constructor( + @InjectCacheStorage(CacheStorageNamespace.EngineWorkspace) + cacheStorageService: CacheStorageService, + @InjectRepository(ViewFilterEntity) + private readonly viewFilterRepository: Repository, + ) { + super(cacheStorageService); + } + + protected async computeFlatMap({ + workspaceId, + }: { + workspaceId: string; + }): Promise { + const viewFilters = await this.viewFilterRepository.find({ + where: { + workspaceId, + }, + withDeleted: true, + }); + + return viewFilters.reduce((flatViewFilterMaps, viewFilterEntity) => { + const flatViewFilter = + fromViewFilterEntityToFlatViewFilter(viewFilterEntity); + + return addFlatEntityToFlatEntityMapsOrThrow({ + flatEntity: flatViewFilter, + flatEntityMaps: flatViewFilterMaps, + }); + }, EMPTY_FLAT_ENTITY_MAPS); + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-maps.type.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-maps.type.ts new file mode 100644 index 00000000000..0fe50cb6f78 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-maps.type.ts @@ -0,0 +1,4 @@ +import { type FlatEntityMaps } from 'src/engine/core-modules/common/types/flat-entity-maps.type'; +import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type'; + +export type FlatViewFilterMaps = FlatEntityMaps; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-properties-to-compare.type.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-properties-to-compare.type.ts new file mode 100644 index 00000000000..a006868b6c9 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-properties-to-compare.type.ts @@ -0,0 +1,4 @@ +import { type FLAT_VIEW_FILTER_PROPERTIES_TO_COMPARE } from 'src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-properties-to-compare.constant'; + +export type FlatViewFilterPropertiesToCompare = + (typeof FLAT_VIEW_FILTER_PROPERTIES_TO_COMPARE)[number]; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type.ts new file mode 100644 index 00000000000..9644f7636b0 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type.ts @@ -0,0 +1,19 @@ +import { type Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { type FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; +import { type ViewFilterGroupEntity } from 'src/engine/metadata-modules/view-filter-group/entities/view-filter-group.entity'; +import { type ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity'; +import { type ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity'; +import { type ExtractRecordTypeOrmRelationProperties } from 'src/engine/workspace-manager/workspace-migration-v2/types/extract-record-typeorm-relation-properties.type'; + +export type ViewFilterEntityRelationProperties = + ExtractRecordTypeOrmRelationProperties< + ViewFilterEntity, + FieldMetadataEntity | ViewEntity | ViewFilterGroupEntity | Workspace + >; + +export type FlatViewFilter = Omit< + ViewFilterEntity, + ViewFilterEntityRelationProperties +> & { + universalIdentifier: string; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/compare-two-flat-view-filter.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/compare-two-flat-view-filter.util.ts new file mode 100644 index 00000000000..f0decdf5b14 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/compare-two-flat-view-filter.util.ts @@ -0,0 +1,23 @@ +import { type FromTo } from 'twenty-shared/types'; + +import { compareTwoFlatEntity } from 'src/engine/core-modules/common/utils/compare-two-flat-entity.util'; +import { FLAT_VIEW_FILTER_JSONB_PROPERTIES } from 'src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-jsonb-properties.constant'; +import { FLAT_VIEW_FILTER_PROPERTIES_TO_COMPARE } from 'src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-properties-to-compare.constant'; +import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type'; + +type GetWorkspaceMigrationUpdateViewFilterActionArgs = FromTo< + FlatViewFilter, + 'FlatViewFilter' +>; + +export const compareTwoFlatViewFilter = ({ + fromFlatViewFilter, + toFlatViewFilter, +}: GetWorkspaceMigrationUpdateViewFilterActionArgs) => { + return compareTwoFlatEntity({ + fromFlatEntity: fromFlatViewFilter, + toFlatEntity: toFlatViewFilter, + propertiesToStringify: FLAT_VIEW_FILTER_JSONB_PROPERTIES, + propertiesToCompare: FLAT_VIEW_FILTER_PROPERTIES_TO_COMPARE, + }); +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-create-view-filter-input-to-flat-view-filter-to-create.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-create-view-filter-input-to-flat-view-filter-to-create.util.ts new file mode 100644 index 00000000000..c6b0250beeb --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-create-view-filter-input-to-flat-view-filter-to-create.util.ts @@ -0,0 +1,47 @@ +import { ViewFilterOperand } from 'twenty-shared/types'; +import { trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties } from 'twenty-shared/utils'; +import { v4 } from 'uuid'; + +import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type'; +import { type CreateViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/create-view-filter.input'; + +export const fromCreateViewFilterInputToFlatViewFilterToCreate = ({ + createViewFilterInput: rawCreateViewFilterInput, + workspaceId, +}: { + createViewFilterInput: CreateViewFilterInput; + workspaceId: string; +}): FlatViewFilter => { + const { fieldMetadataId, viewId, value, ...createViewFilterInput } = + trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties( + rawCreateViewFilterInput, + [ + 'fieldMetadataId', + 'id', + 'viewId', + 'viewFilterGroupId', + 'operand', + 'subFieldName', + ], + ); + + const createdAt = new Date(); + const viewFilterId = createViewFilterInput.id ?? v4(); + + return { + id: viewFilterId, + fieldMetadataId, + viewId, + workspaceId, + createdAt: createdAt, + updatedAt: createdAt, + deletedAt: null, + universalIdentifier: viewFilterId, + operand: createViewFilterInput.operand ?? ViewFilterOperand.CONTAINS, + value: value, + viewFilterGroupId: createViewFilterInput.viewFilterGroupId ?? null, + positionInViewFilterGroup: + createViewFilterInput.positionInViewFilterGroup ?? null, + subFieldName: createViewFilterInput.subFieldName ?? null, + }; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-delete-view-filter-input-to-flat-view-filter-or-throw.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-delete-view-filter-input-to-flat-view-filter-or-throw.util.ts new file mode 100644 index 00000000000..17a70411739 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-delete-view-filter-input-to-flat-view-filter-or-throw.util.ts @@ -0,0 +1,40 @@ +import { t } from '@lingui/core/macro'; +import { + extractAndSanitizeObjectStringFields, + isDefined, +} from 'twenty-shared/utils'; + +import { type FlatViewFilterMaps } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-maps.type'; +import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type'; +import { type DeleteViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/delete-view-filter.input'; +import { + ViewFilterException, + ViewFilterExceptionCode, +} from 'src/engine/metadata-modules/view-filter/exceptions/view-filter.exception'; + +export const fromDeleteViewFilterInputToFlatViewFilterOrThrow = ({ + deleteViewFilterInput: rawDeleteViewFilterInput, + flatViewFilterMaps, +}: { + deleteViewFilterInput: DeleteViewFilterInput; + flatViewFilterMaps: FlatViewFilterMaps; +}): FlatViewFilter => { + const { id: viewFilterId } = extractAndSanitizeObjectStringFields( + rawDeleteViewFilterInput, + ['id'], + ); + + const existingFlatViewFilterToDelete = flatViewFilterMaps.byId[viewFilterId]; + + if (!isDefined(existingFlatViewFilterToDelete)) { + throw new ViewFilterException( + t`View filter to delete not found`, + ViewFilterExceptionCode.VIEW_FILTER_NOT_FOUND, + ); + } + + return { + ...existingFlatViewFilterToDelete, + deletedAt: new Date(), + }; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-destroy-view-filter-input-to-flat-view-filter-or-throw.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-destroy-view-filter-input-to-flat-view-filter-or-throw.util.ts new file mode 100644 index 00000000000..b2cc19fc3cb --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-destroy-view-filter-input-to-flat-view-filter-or-throw.util.ts @@ -0,0 +1,37 @@ +import { t } from '@lingui/core/macro'; +import { + extractAndSanitizeObjectStringFields, + isDefined, +} from 'twenty-shared/utils'; + +import { type FlatViewFilterMaps } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-maps.type'; +import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type'; +import { type DestroyViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/destroy-view-filter.input'; +import { + ViewFilterException, + ViewFilterExceptionCode, +} from 'src/engine/metadata-modules/view-filter/exceptions/view-filter.exception'; + +export const fromDestroyViewFilterInputToFlatViewFilterOrThrow = ({ + destroyViewFilterInput, + flatViewFilterMaps, +}: { + destroyViewFilterInput: DestroyViewFilterInput; + flatViewFilterMaps: FlatViewFilterMaps; +}): FlatViewFilter => { + const { id: viewFilterId } = extractAndSanitizeObjectStringFields( + destroyViewFilterInput, + ['id'], + ); + + const existingFlatViewFilterToDestroy = flatViewFilterMaps.byId[viewFilterId]; + + if (!isDefined(existingFlatViewFilterToDestroy)) { + throw new ViewFilterException( + t`View filter to destroy not found`, + ViewFilterExceptionCode.VIEW_FILTER_NOT_FOUND, + ); + } + + return existingFlatViewFilterToDestroy; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-update-view-filter-input-to-flat-view-filter-to-update-or-throw.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-update-view-filter-input-to-flat-view-filter-to-update-or-throw.util.ts new file mode 100644 index 00000000000..e55a20bc3ad --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-update-view-filter-input-to-flat-view-filter-to-update-or-throw.util.ts @@ -0,0 +1,51 @@ +import { t } from '@lingui/core/macro'; +import { + extractAndSanitizeObjectStringFields, + isDefined, + trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties, +} from 'twenty-shared/utils'; + +import { FLAT_VIEW_FILTER_EDITABLE_PROPERTIES } from 'src/engine/metadata-modules/flat-view-filter/constants/flat-view-filter-editable-properties.constant'; +import { type FlatViewFilterMaps } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-maps.type'; +import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type'; +import { type UpdateViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/update-view-filter.input'; +import { + ViewFilterException, + ViewFilterExceptionCode, +} from 'src/engine/metadata-modules/view-filter/exceptions/view-filter.exception'; +import { mergeUpdateInExistingRecord } from 'src/utils/merge-update-in-existing-record.util'; + +export const fromUpdateViewFilterInputToFlatViewFilterToUpdateOrThrow = ({ + updateViewFilterInput: rawUpdateViewFilterInput, + flatViewFilterMaps, +}: { + updateViewFilterInput: UpdateViewFilterInput; + flatViewFilterMaps: FlatViewFilterMaps; +}): FlatViewFilter => { + const { id: viewFilterToUpdateId } = + trimAndRemoveDuplicatedWhitespacesFromObjectStringProperties( + rawUpdateViewFilterInput, + ['id'], + ); + + const existingFlatViewFilterToUpdate = + flatViewFilterMaps.byId[viewFilterToUpdateId]; + + if (!isDefined(existingFlatViewFilterToUpdate)) { + throw new ViewFilterException( + t`View filter to update not found`, + ViewFilterExceptionCode.VIEW_FILTER_NOT_FOUND, + ); + } + + const updatedEditableFieldProperties = extractAndSanitizeObjectStringFields( + rawUpdateViewFilterInput.update, + FLAT_VIEW_FILTER_EDITABLE_PROPERTIES, + ); + + return mergeUpdateInExistingRecord({ + existing: existingFlatViewFilterToUpdate, + properties: FLAT_VIEW_FILTER_EDITABLE_PROPERTIES, + update: updatedEditableFieldProperties, + }); +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-view-filter-entity-to-flat-view-filter.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-view-filter-entity-to-flat-view-filter.util.ts new file mode 100644 index 00000000000..95377c53d92 --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view-filter/utils/from-view-filter-entity-to-flat-view-filter.util.ts @@ -0,0 +1,21 @@ +import { removePropertiesFromRecord } from 'twenty-shared/utils'; + +import { VIEW_FILTER_ENTITY_RELATION_PROPERTIES } from 'src/engine/metadata-modules/flat-view-filter/constants/view-filter-entity-relation-properties.constant'; +import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type'; +import { type ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity'; + +export const fromViewFilterEntityToFlatViewFilter = ( + viewFilterEntity: ViewFilterEntity, +): FlatViewFilter => { + const viewFilterEntityWithoutRelations = removePropertiesFromRecord( + viewFilterEntity, + VIEW_FILTER_ENTITY_RELATION_PROPERTIES, + ); + + return { + ...viewFilterEntityWithoutRelations, + universalIdentifier: + viewFilterEntityWithoutRelations.universalIdentifier ?? + viewFilterEntityWithoutRelations.id, + }; +}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view/services/workspace-flat-view-map-cache.service.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view/services/workspace-flat-view-map-cache.service.ts index b30dd9290fe..8797123e990 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-view/services/workspace-flat-view-map-cache.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view/services/workspace-flat-view-map-cache.service.ts @@ -39,8 +39,11 @@ export class WorkspaceFlatViewMapCacheService extends WorkspaceFlatMapCacheServi viewFields: { id: true, }, + viewFilters: { + id: true, + }, }, - relations: ['viewFields'], + relations: ['viewFields', 'viewFilters'], withDeleted: true, }); diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view/types/flat-view.type.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view/types/flat-view.type.ts index a150b015762..e0cde363079 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-view/types/flat-view.type.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view/types/flat-view.type.ts @@ -23,4 +23,5 @@ export type ViewEntityRelationProperties = export type FlatView = Omit & { universalIdentifier: string; viewFieldIds: string[]; + viewFilterIds: string[]; }; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view/utils/from-create-view-input-to-flat-view-to-create.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view/utils/from-create-view-input-to-flat-view-to-create.util.ts index 3b8cff81361..ca60edc0f5f 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-view/utils/from-create-view-input-to-flat-view-to-create.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view/utils/from-create-view-input-to-flat-view-to-create.util.ts @@ -44,5 +44,6 @@ export const fromCreateViewInputToFlatViewToCreate = ({ type: createViewInput.type ?? ViewType.TABLE, universalIdentifier: v4(), viewFieldIds: [], + viewFilterIds: [], }; }; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view/utils/from-partial-flat-view-to-flat-view-to-with-default.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view/utils/from-partial-flat-view-to-flat-view-to-with-default.util.ts deleted file mode 100644 index 80a8ef54e73..00000000000 --- a/packages/twenty-server/src/engine/metadata-modules/flat-view/utils/from-partial-flat-view-to-flat-view-to-with-default.util.ts +++ /dev/null @@ -1,38 +0,0 @@ -import { v4 } from 'uuid'; - -import { type FlatView } from 'src/engine/metadata-modules/flat-view/types/flat-view.type'; -import { ViewOpenRecordIn } from 'src/engine/metadata-modules/view/enums/view-open-record-in'; -import { ViewType } from 'src/engine/metadata-modules/view/enums/view-type.enum'; - -export const fromPartialFlatViewToFlatViewWithDefault = ( - partialFlatView: Partial, -): FlatView => { - const createdAt = new Date(); - const viewId = partialFlatView.id ?? v4(); - - return { - ...partialFlatView, - id: viewId, - name: partialFlatView.name ?? '', - objectMetadataId: partialFlatView.objectMetadataId ?? '', - type: partialFlatView.type ?? ViewType.TABLE, - key: partialFlatView.key ?? null, - icon: partialFlatView.icon ?? '', - position: partialFlatView.position ?? 0, - isCompact: partialFlatView.isCompact ?? false, - isCustom: partialFlatView.isCustom ?? false, - openRecordIn: partialFlatView.openRecordIn ?? ViewOpenRecordIn.SIDE_PANEL, - kanbanAggregateOperation: partialFlatView.kanbanAggregateOperation ?? null, - kanbanAggregateOperationFieldMetadataId: - partialFlatView.kanbanAggregateOperationFieldMetadataId ?? null, - workspaceId: partialFlatView.workspaceId ?? '', - createdAt: createdAt, - updatedAt: createdAt, - deletedAt: null, - anyFieldFilterValue: partialFlatView.anyFieldFilterValue ?? null, - universalIdentifier: partialFlatView.universalIdentifier ?? viewId, - viewFieldIds: partialFlatView.viewFieldIds ?? [], - calendarLayout: partialFlatView.calendarLayout ?? null, - calendarFieldMetadataId: partialFlatView.calendarFieldMetadataId ?? null, - }; -}; diff --git a/packages/twenty-server/src/engine/metadata-modules/flat-view/utils/from-view-entity-to-flat-view.util.ts b/packages/twenty-server/src/engine/metadata-modules/flat-view/utils/from-view-entity-to-flat-view.util.ts index d3943c15019..704df22f0c5 100644 --- a/packages/twenty-server/src/engine/metadata-modules/flat-view/utils/from-view-entity-to-flat-view.util.ts +++ b/packages/twenty-server/src/engine/metadata-modules/flat-view/utils/from-view-entity-to-flat-view.util.ts @@ -15,6 +15,7 @@ export const fromViewEntityToFlatView = (viewEntity: ViewEntity): FlatView => { universalIdentifier: viewEntityWithoutRelations.universalIdentifier ?? viewEntityWithoutRelations.id, - viewFieldIds: viewEntity.viewFields.map((viewField) => viewField.id) ?? [], + viewFieldIds: viewEntity.viewFields.map((viewField) => viewField.id), + viewFilterIds: viewEntity.viewFilters.map((viewFilter) => viewFilter.id), }; }; diff --git a/packages/twenty-server/src/engine/metadata-modules/view-filter/controllers/view-filter.controller.ts b/packages/twenty-server/src/engine/metadata-modules/view-filter/controllers/view-filter.controller.ts index eb23493561e..593a3042956 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-filter/controllers/view-filter.controller.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-filter/controllers/view-filter.controller.ts @@ -89,10 +89,15 @@ export class ViewFilterController { @Body() input: UpdateViewFilterInput, @AuthWorkspace() workspace: Workspace, ): Promise { - const updatedViewFilter = await this.viewFilterService.update( + const updateInput: UpdateViewFilterInput = { id, + update: input.update ?? input, + }; + + const updatedViewFilter = await this.viewFilterService.update( + updateInput.id, workspace.id, - input, + updateInput.update, ); return updatedViewFilter; diff --git a/packages/twenty-server/src/engine/metadata-modules/view-filter/dtos/inputs/create-view-filter.input.ts b/packages/twenty-server/src/engine/metadata-modules/view-filter/dtos/inputs/create-view-filter.input.ts index a970be2c662..5885377cd53 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-filter/dtos/inputs/create-view-filter.input.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-filter/dtos/inputs/create-view-filter.input.ts @@ -2,33 +2,54 @@ import { Field, InputType } from '@nestjs/graphql'; import GraphQLJSON from 'graphql-type-json'; import { ViewFilterOperand } from 'twenty-shared/types'; +import { + IsDefined, + IsEnum, + IsNumber, + IsOptional, + IsString, + IsUUID, +} from 'class-validator'; import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; import { ViewFilterValue } from 'src/engine/metadata-modules/view-filter/types/view-filter-value.type'; @InputType() export class CreateViewFilterInput { + @IsOptional() + @IsUUID() @Field(() => UUIDScalarType, { nullable: true }) id?: string; + @IsUUID() @Field(() => UUIDScalarType, { nullable: false }) fieldMetadataId: string; + @IsOptional() + @IsEnum(ViewFilterOperand) @Field({ nullable: true, defaultValue: ViewFilterOperand.CONTAINS }) operand?: ViewFilterOperand; + @IsDefined() @Field(() => GraphQLJSON, { nullable: false }) value: ViewFilterValue; + @IsOptional() + @IsUUID() @Field(() => UUIDScalarType, { nullable: true }) viewFilterGroupId?: string; + @IsOptional() + @IsNumber() @Field({ nullable: true }) positionInViewFilterGroup?: number; + @IsOptional() + @IsString() @Field({ nullable: true }) subFieldName?: string; + @IsUUID() @Field(() => UUIDScalarType, { nullable: false }) viewId: string; } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-filter/dtos/inputs/delete-view-filter.input.ts b/packages/twenty-server/src/engine/metadata-modules/view-filter/dtos/inputs/delete-view-filter.input.ts new file mode 100644 index 00000000000..ea5ad02bfae --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/view-filter/dtos/inputs/delete-view-filter.input.ts @@ -0,0 +1,15 @@ +import { InputType } from '@nestjs/graphql'; + +import { IDField } from '@ptc-org/nestjs-query-graphql'; +import { IsUUID } from 'class-validator'; + +import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; + +@InputType() +export class DeleteViewFilterInput { + @IDField(() => UUIDScalarType, { + description: 'The id of the view filter to delete.', + }) + @IsUUID() + id: string; +} diff --git a/packages/twenty-server/src/engine/metadata-modules/view-filter/dtos/inputs/destroy-view-filter.input.ts b/packages/twenty-server/src/engine/metadata-modules/view-filter/dtos/inputs/destroy-view-filter.input.ts new file mode 100644 index 00000000000..4b785b8794a --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/view-filter/dtos/inputs/destroy-view-filter.input.ts @@ -0,0 +1,15 @@ +import { InputType } from '@nestjs/graphql'; + +import { IDField } from '@ptc-org/nestjs-query-graphql'; +import { IsUUID } from 'class-validator'; + +import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; + +@InputType() +export class DestroyViewFilterInput { + @IDField(() => UUIDScalarType, { + description: 'The id of the view filter to destroy.', + }) + @IsUUID() + id: string; +} diff --git a/packages/twenty-server/src/engine/metadata-modules/view-filter/dtos/inputs/update-view-filter.input.ts b/packages/twenty-server/src/engine/metadata-modules/view-filter/dtos/inputs/update-view-filter.input.ts index 6dd2c798f0f..ec5bd719b2d 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-filter/dtos/inputs/update-view-filter.input.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-filter/dtos/inputs/update-view-filter.input.ts @@ -1,6 +1,66 @@ -import { InputType, PartialType } from '@nestjs/graphql'; +import { Field, InputType } from '@nestjs/graphql'; -import { CreateViewFilterInput } from './create-view-filter.input'; +import { + IsEnum, + IsNotEmpty, + IsNumber, + IsOptional, + IsString, + IsUUID, + ValidateNested, +} from 'class-validator'; +import GraphQLJSON from 'graphql-type-json'; +import { ViewFilterOperand } from 'twenty-shared/types'; +import { Type } from 'class-transformer'; + +import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; +import { ViewFilterValue } from 'src/engine/metadata-modules/view-filter/types/view-filter-value.type'; @InputType() -export class UpdateViewFilterInput extends PartialType(CreateViewFilterInput) {} +class UpdateViewFilterInputUpdates { + @IsOptional() + @IsUUID() + @Field(() => UUIDScalarType, { nullable: true }) + fieldMetadataId?: string; + + @IsOptional() + @IsEnum(ViewFilterOperand) + @Field({ nullable: true }) + operand?: ViewFilterOperand; + + @IsOptional() + @Field(() => GraphQLJSON, { nullable: true }) + value?: ViewFilterValue; + + @IsOptional() + @IsUUID() + @Field(() => UUIDScalarType, { nullable: true }) + viewFilterGroupId?: string; + + @IsOptional() + @IsNumber() + @Field({ nullable: true }) + positionInViewFilterGroup?: number; + + @IsOptional() + @IsString() + @Field({ nullable: true }) + subFieldName?: string; +} + +@InputType() +export class UpdateViewFilterInput { + @IsUUID() + @IsNotEmpty() + @Field(() => UUIDScalarType, { + description: 'The id of the view filter to update', + }) + id: string; + + @Type(() => UpdateViewFilterInputUpdates) + @ValidateNested() + @Field(() => UpdateViewFilterInputUpdates, { + description: 'The view filter to update', + }) + update: UpdateViewFilterInputUpdates; +} diff --git a/packages/twenty-server/src/engine/metadata-modules/view-filter/entities/view-filter.entity.ts b/packages/twenty-server/src/engine/metadata-modules/view-filter/entities/view-filter.entity.ts index 32371d3a13c..adb28a117b4 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-filter/entities/view-filter.entity.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-filter/entities/view-filter.entity.ts @@ -26,7 +26,10 @@ import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entit where: '"deletedAt" IS NULL', }) @Index('IDX_VIEW_FILTER_FIELD_METADATA_ID', ['fieldMetadataId']) -export class ViewFilterEntity extends SyncableEntity { +export class ViewFilterEntity + extends SyncableEntity + implements Required +{ @PrimaryGeneratedColumn('uuid') id: string; @@ -51,13 +54,13 @@ export class ViewFilterEntity extends SyncableEntity { value: ViewFilterValue; @Column({ nullable: true, type: 'uuid' }) - viewFilterGroupId?: string | null; + viewFilterGroupId: string | null; @Column({ nullable: true, type: 'double precision' }) positionInViewFilterGroup: number | null; @Column({ nullable: true, type: 'text', default: null }) - subFieldName?: string | null; + subFieldName: string | null; @Column({ nullable: false, type: 'uuid' }) viewId: string; @@ -72,7 +75,7 @@ export class ViewFilterEntity extends SyncableEntity { updatedAt: Date; @DeleteDateColumn({ type: 'timestamptz' }) - deletedAt?: Date | null; + deletedAt: Date | null; @ManyToOne(() => Workspace, { onDelete: 'CASCADE', diff --git a/packages/twenty-server/src/engine/metadata-modules/view-filter/resolvers/view-filter.resolver.ts b/packages/twenty-server/src/engine/metadata-modules/view-filter/resolvers/view-filter.resolver.ts index e9bb7e012f4..5750fa36692 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-filter/resolvers/view-filter.resolver.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-filter/resolvers/view-filter.resolver.ts @@ -1,14 +1,17 @@ import { UseFilters, UseGuards } from '@nestjs/common'; import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; -import { isDefined } from 'twenty-shared/utils'; - +import { FeatureFlagKey } from 'src/engine/core-modules/feature-flag/enums/feature-flag-key.enum'; +import { FeatureFlagService } from 'src/engine/core-modules/feature-flag/services/feature-flag.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; import { AuthWorkspace } from 'src/engine/decorators/auth/auth-workspace.decorator'; import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { CreateViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/create-view-filter.input'; +import { DeleteViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/delete-view-filter.input'; +import { DestroyViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/destroy-view-filter.input'; import { UpdateViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/update-view-filter.input'; import { ViewFilterDTO } from 'src/engine/metadata-modules/view-filter/dtos/view-filter.dto'; +import { ViewFilterV2Service } from 'src/engine/metadata-modules/view-filter/services/view-filter-v2.service'; import { ViewFilterService } from 'src/engine/metadata-modules/view-filter/services/view-filter.service'; import { ViewGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/view/utils/view-graphql-api-exception.filter'; @@ -16,7 +19,11 @@ import { ViewGraphqlApiExceptionFilter } from 'src/engine/metadata-modules/view/ @UseFilters(ViewGraphqlApiExceptionFilter) @UseGuards(WorkspaceAuthGuard) export class ViewFilterResolver { - constructor(private readonly viewFilterService: ViewFilterService) {} + constructor( + private readonly viewFilterService: ViewFilterService, + private readonly featureFlagService: FeatureFlagService, + private readonly viewFilterV2Service: ViewFilterV2Service, + ) {} @Query(() => [ViewFilterDTO]) async getCoreViewFilters( @@ -41,47 +48,104 @@ export class ViewFilterResolver { @Mutation(() => ViewFilterDTO) async createCoreViewFilter( - @Args('input') input: CreateViewFilterInput, - @AuthWorkspace() workspace: Workspace, + @Args('input') createViewFilterInput: CreateViewFilterInput, + @AuthWorkspace() { id: workspaceId }: Workspace, ): Promise { + const isWorkspaceMigrationV2Enabled = + await this.featureFlagService.isFeatureEnabled( + FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED, + workspaceId, + ); + + if (isWorkspaceMigrationV2Enabled) { + return await this.viewFilterV2Service.createOne({ + createViewFilterInput, + workspaceId, + }); + } + return this.viewFilterService.create({ - ...input, - workspaceId: workspace.id, + ...createViewFilterInput, + workspaceId, }); } @Mutation(() => ViewFilterDTO) async updateCoreViewFilter( - @Args('id', { type: () => String }) id: string, - @Args('input') input: UpdateViewFilterInput, - @AuthWorkspace() workspace: Workspace, + @Args('input') updateViewFilterInput: UpdateViewFilterInput, + @AuthWorkspace() { id: workspaceId }: Workspace, ): Promise { - return this.viewFilterService.update(id, workspace.id, input); + const isWorkspaceMigrationV2Enabled = + await this.featureFlagService.isFeatureEnabled( + FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED, + workspaceId, + ); + + if (isWorkspaceMigrationV2Enabled) { + return await this.viewFilterV2Service.updateOne({ + updateViewFilterInput, + workspaceId, + }); + } + + return this.viewFilterService.update( + updateViewFilterInput.id, + workspaceId, + updateViewFilterInput.update, + ); } - @Mutation(() => Boolean) + @Mutation(() => ViewFilterDTO) async deleteCoreViewFilter( - @Args('id', { type: () => String }) id: string, - @AuthWorkspace() workspace: Workspace, - ): Promise { + @Args('input') deleteViewFilterInput: DeleteViewFilterInput, + @AuthWorkspace() { id: workspaceId }: Workspace, + ): Promise { + const isWorkspaceMigrationV2Enabled = + await this.featureFlagService.isFeatureEnabled( + FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED, + workspaceId, + ); + + if (isWorkspaceMigrationV2Enabled) { + return await this.viewFilterV2Service.deleteOne({ + deleteViewFilterInput, + workspaceId, + }); + } + const deletedViewFilter = await this.viewFilterService.delete( - id, - workspace.id, + deleteViewFilterInput.id, + workspaceId, ); - return isDefined(deletedViewFilter); + return deletedViewFilter; } - @Mutation(() => Boolean) + @Mutation(() => ViewFilterDTO) async destroyCoreViewFilter( - @Args('id', { type: () => String }) id: string, - @AuthWorkspace() workspace: Workspace, - ): Promise { - const deletedViewFilter = await this.viewFilterService.destroy( - id, - workspace.id, + @Args('input') destroyViewFilterInput: DestroyViewFilterInput, + @AuthWorkspace() { id: workspaceId }: Workspace, + ): Promise { + const isWorkspaceMigrationV2Enabled = + await this.featureFlagService.isFeatureEnabled( + FeatureFlagKey.IS_WORKSPACE_MIGRATION_V2_ENABLED, + workspaceId, + ); + + if (isWorkspaceMigrationV2Enabled) { + const destroyedViewFilter = await this.viewFilterV2Service.destroyOne({ + destroyViewFilterInput, + workspaceId, + }); + + return destroyedViewFilter; + } + + const destroyedViewFilter = await this.viewFilterService.destroy( + destroyViewFilterInput.id, + workspaceId, ); - return isDefined(deletedViewFilter); + return destroyedViewFilter; } } diff --git a/packages/twenty-server/src/engine/metadata-modules/view-filter/services/tests/view-filter.service.spec.ts b/packages/twenty-server/src/engine/metadata-modules/view-filter/services/tests/view-filter.service.spec.ts index e9c76ba29eb..c9939053a6c 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-filter/services/tests/view-filter.service.spec.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-filter/services/tests/view-filter.service.spec.ts @@ -333,7 +333,7 @@ describe('ViewFilterService', () => { expect(viewFilterService.findById).toHaveBeenCalledWith(id, workspaceId); expect(viewFilterRepository.delete).toHaveBeenCalledWith(id); - expect(result).toEqual(true); + expect(result).toEqual(mockViewFilter); }); }); }); diff --git a/packages/twenty-server/src/engine/metadata-modules/view-filter/services/view-filter-v2.service.ts b/packages/twenty-server/src/engine/metadata-modules/view-filter/services/view-filter-v2.service.ts new file mode 100644 index 00000000000..5c528a68b3f --- /dev/null +++ b/packages/twenty-server/src/engine/metadata-modules/view-filter/services/view-filter-v2.service.ts @@ -0,0 +1,326 @@ +import { Injectable } from '@nestjs/common'; + +import { isDefined } from 'twenty-shared/utils'; + +import { EMPTY_FLAT_ENTITY_MAPS } from 'src/engine/core-modules/common/constant/empty-flat-entity-maps.constant'; +import { WorkspaceManyOrAllFlatEntityMapsCacheService } from 'src/engine/core-modules/common/services/workspace-many-or-all-flat-entity-maps-cache.service'; +import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; +import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util'; +import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; +import { getSubFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/get-sub-flat-entity-maps-or-throw.util'; +import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util'; +import { fromCreateViewFilterInputToFlatViewFilterToCreate } from 'src/engine/metadata-modules/flat-view-filter/utils/from-create-view-filter-input-to-flat-view-filter-to-create.util'; +import { fromDeleteViewFilterInputToFlatViewFilterOrThrow } from 'src/engine/metadata-modules/flat-view-filter/utils/from-delete-view-filter-input-to-flat-view-filter-or-throw.util'; +import { fromDestroyViewFilterInputToFlatViewFilterOrThrow } from 'src/engine/metadata-modules/flat-view-filter/utils/from-destroy-view-filter-input-to-flat-view-filter-or-throw.util'; +import { fromUpdateViewFilterInputToFlatViewFilterToUpdateOrThrow } from 'src/engine/metadata-modules/flat-view-filter/utils/from-update-view-filter-input-to-flat-view-filter-to-update-or-throw.util'; +import { CreateViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/create-view-filter.input'; +import { DeleteViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/delete-view-filter.input'; +import { DestroyViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/destroy-view-filter.input'; +import { UpdateViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/update-view-filter.input'; +import { ViewFilterDTO } from 'src/engine/metadata-modules/view-filter/dtos/view-filter.dto'; +import { WorkspaceMigrationBuilderExceptionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/exceptions/workspace-migration-builder-exception-v2'; +import { WorkspaceMigrationValidateBuildAndRunService } from 'src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-validate-build-and-run-service'; + +@Injectable() +export class ViewFilterV2Service { + constructor( + private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService, + private readonly flatEntityMapsCacheService: WorkspaceManyOrAllFlatEntityMapsCacheService, + ) {} + + async createOne({ + createViewFilterInput, + workspaceId, + }: { + createViewFilterInput: CreateViewFilterInput; + workspaceId: string; + }): Promise { + const { + flatViewFilterMaps: existingFlatViewFilterMaps, + flatViewMaps, + flatFieldMetadataMaps, + flatObjectMetadataMaps, + } = await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: [ + 'flatViewFilterMaps', + 'flatViewMaps', + 'flatFieldMetadataMaps', + 'flatObjectMetadataMaps', + ], + }, + ); + + const flatViewFilterToCreate = + fromCreateViewFilterInputToFlatViewFilterToCreate({ + createViewFilterInput, + workspaceId, + }); + + const toFlatViewFilterMaps = addFlatEntityToFlatEntityMapsOrThrow({ + flatEntity: flatViewFilterToCreate, + flatEntityMaps: existingFlatViewFilterMaps, + }); + + const validateAndBuildResult = + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + { + fromToAllFlatEntityMaps: { + flatViewFilterMaps: { + from: existingFlatViewFilterMaps, + to: toFlatViewFilterMaps, + }, + }, + dependencyAllFlatEntityMaps: { + flatFieldMetadataMaps, + flatViewMaps, + flatObjectMetadataMaps, + }, + buildOptions: { + isSystemBuild: false, + inferDeletionFromMissingEntities: false, + }, + workspaceId, + }, + ); + + if (isDefined(validateAndBuildResult)) { + throw new WorkspaceMigrationBuilderExceptionV2( + validateAndBuildResult, + 'Multiple validation errors occurred while creating view filter', + ); + } + + const { flatViewFilterMaps: recomputedExistingFlatViewFilterMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: ['flatViewFilterMaps'], + }, + ); + + return findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: flatViewFilterToCreate.id, + flatEntityMaps: recomputedExistingFlatViewFilterMaps, + }); + } + + async updateOne({ + updateViewFilterInput, + workspaceId, + }: { + workspaceId: string; + updateViewFilterInput: UpdateViewFilterInput; + }): Promise { + const { + flatViewFilterMaps: existingFlatViewFilterMaps, + flatViewMaps, + flatFieldMetadataMaps, + } = await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: [ + 'flatViewFilterMaps', + 'flatViewMaps', + 'flatFieldMetadataMaps', + ], + }, + ); + + const optimisticallyUpdatedFlatViewFilter = + fromUpdateViewFilterInputToFlatViewFilterToUpdateOrThrow({ + flatViewFilterMaps: existingFlatViewFilterMaps, + updateViewFilterInput, + }); + + const toFlatViewFilterMaps = addFlatEntityToFlatEntityMapsOrThrow({ + flatEntity: optimisticallyUpdatedFlatViewFilter, + flatEntityMaps: EMPTY_FLAT_ENTITY_MAPS, + }); + + const validateAndBuildResult = + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + { + fromToAllFlatEntityMaps: { + flatViewFilterMaps: { + from: existingFlatViewFilterMaps, + to: toFlatViewFilterMaps, + }, + }, + dependencyAllFlatEntityMaps: { + flatViewMaps, + flatFieldMetadataMaps, + }, + buildOptions: { + isSystemBuild: false, + inferDeletionFromMissingEntities: false, + }, + workspaceId, + }, + ); + + if (isDefined(validateAndBuildResult)) { + throw new WorkspaceMigrationBuilderExceptionV2( + validateAndBuildResult, + 'Multiple validation errors occurred while updating view filter', + ); + } + + const { flatViewFilterMaps: recomputedExistingFlatViewFilterMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: ['flatViewFilterMaps'], + }, + ); + + return findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: optimisticallyUpdatedFlatViewFilter.id, + flatEntityMaps: recomputedExistingFlatViewFilterMaps, + }); + } + + async deleteOne({ + deleteViewFilterInput, + workspaceId, + }: { + deleteViewFilterInput: DeleteViewFilterInput; + workspaceId: string; + }): Promise { + const { + flatViewFilterMaps: existingFlatViewFilterMaps, + flatViewMaps, + flatFieldMetadataMaps, + } = await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: [ + 'flatViewFilterMaps', + 'flatViewMaps', + 'flatFieldMetadataMaps', + ], + }, + ); + + const optimisticallyUpdatedFlatViewFilterWithDeletedAt = + fromDeleteViewFilterInputToFlatViewFilterOrThrow({ + flatViewFilterMaps: existingFlatViewFilterMaps, + deleteViewFilterInput, + }); + + const toFlatViewFilterMaps = replaceFlatEntityInFlatEntityMapsOrThrow({ + flatEntity: optimisticallyUpdatedFlatViewFilterWithDeletedAt, + flatEntityMaps: existingFlatViewFilterMaps, + }); + + const validateAndBuildResult = + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + { + fromToAllFlatEntityMaps: { + flatViewFilterMaps: { + from: existingFlatViewFilterMaps, + to: toFlatViewFilterMaps, + }, + }, + dependencyAllFlatEntityMaps: { + flatFieldMetadataMaps, + flatViewMaps, + }, + buildOptions: { + isSystemBuild: false, + inferDeletionFromMissingEntities: false, + }, + workspaceId, + }, + ); + + if (isDefined(validateAndBuildResult)) { + throw new WorkspaceMigrationBuilderExceptionV2( + validateAndBuildResult, + 'Multiple validation errors occurred while deleting view filter', + ); + } + + const { flatViewFilterMaps: recomputedExistingFlatViewFilterMaps } = + await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: ['flatViewFilterMaps'], + }, + ); + + return findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: optimisticallyUpdatedFlatViewFilterWithDeletedAt.id, + flatEntityMaps: recomputedExistingFlatViewFilterMaps, + }); + } + + async destroyOne({ + destroyViewFilterInput, + workspaceId, + }: { + destroyViewFilterInput: DestroyViewFilterInput; + workspaceId: string; + }): Promise { + const { + flatViewFilterMaps: existingFlatViewFilterMaps, + flatViewMaps: existingFlatViewMaps, + flatFieldMetadataMaps: existingFlatFieldMetadataMaps, + } = await this.flatEntityMapsCacheService.getOrRecomputeManyOrAllFlatEntityMaps( + { + workspaceId, + flatMapsKeys: [ + 'flatViewFilterMaps', + 'flatViewMaps', + 'flatFieldMetadataMaps', + ], + }, + ); + + const existingViewFilterToDelete = + fromDestroyViewFilterInputToFlatViewFilterOrThrow({ + destroyViewFilterInput, + flatViewFilterMaps: existingFlatViewFilterMaps, + }); + + const fromFlatViewFilterMaps = getSubFlatEntityMapsOrThrow({ + flatEntityIds: [existingViewFilterToDelete.id], + flatEntityMaps: existingFlatViewFilterMaps, + }); + const toFlatViewFilterMaps = deleteFlatEntityFromFlatEntityMapsOrThrow({ + flatEntityMaps: fromFlatViewFilterMaps, + entityToDeleteId: existingViewFilterToDelete.id, + }); + + const validateAndBuildResult = + await this.workspaceMigrationValidateBuildAndRunService.validateBuildAndRunWorkspaceMigration( + { + fromToAllFlatEntityMaps: { + flatViewFilterMaps: { + from: fromFlatViewFilterMaps, + to: toFlatViewFilterMaps, + }, + }, + dependencyAllFlatEntityMaps: { + flatViewMaps: existingFlatViewMaps, + flatFieldMetadataMaps: existingFlatFieldMetadataMaps, + }, + buildOptions: { + isSystemBuild: false, + inferDeletionFromMissingEntities: true, + }, + workspaceId, + }, + ); + + if (isDefined(validateAndBuildResult)) { + throw new WorkspaceMigrationBuilderExceptionV2( + validateAndBuildResult, + 'Multiple validation errors occurred while destroying view filter', + ); + } + + return existingViewFilterToDelete; + } +} diff --git a/packages/twenty-server/src/engine/metadata-modules/view-filter/services/view-filter.service.ts b/packages/twenty-server/src/engine/metadata-modules/view-filter/services/view-filter.service.ts index 2808372c672..dc4eb472f14 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-filter/services/view-filter.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-filter/services/view-filter.service.ts @@ -168,7 +168,7 @@ export class ViewFilterService { return viewFilter; } - async destroy(id: string, workspaceId: string): Promise { + async destroy(id: string, workspaceId: string): Promise { const viewFilter = await this.findById(id, workspaceId); if (!isDefined(viewFilter)) { @@ -185,7 +185,7 @@ export class ViewFilterService { await this.flushGraphQLCache(workspaceId); - return true; + return viewFilter; } private async flushGraphQLCache(workspaceId: string): Promise { diff --git a/packages/twenty-server/src/engine/metadata-modules/view-filter/view-filter.module.ts b/packages/twenty-server/src/engine/metadata-modules/view-filter/view-filter.module.ts index b4c5954eedf..04b6e89ca9a 100644 --- a/packages/twenty-server/src/engine/metadata-modules/view-filter/view-filter.module.ts +++ b/packages/twenty-server/src/engine/metadata-modules/view-filter/view-filter.module.ts @@ -1,19 +1,27 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; +import { WorkspaceManyOrAllFlatEntityMapsCacheModule } from 'src/engine/core-modules/common/services/workspace-many-or-all-flat-entity-maps-cache.module'; +import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; import { ViewFilterController } from 'src/engine/metadata-modules/view-filter/controllers/view-filter.controller'; import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity'; import { ViewFilterResolver } from 'src/engine/metadata-modules/view-filter/resolvers/view-filter.resolver'; +import { ViewFilterV2Service } from 'src/engine/metadata-modules/view-filter/services/view-filter-v2.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 { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/workspace-cache-storage.module'; +import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-v2.module'; @Module({ imports: [ - TypeOrmModule.forFeature([ViewFilterEntity]), + TypeOrmModule.forFeature([ViewFilterEntity, ViewEntity]), WorkspaceCacheStorageModule, + FeatureFlagModule, + WorkspaceMigrationV2Module, + WorkspaceManyOrAllFlatEntityMapsCacheModule, ], controllers: [ViewFilterController], - providers: [ViewFilterService, ViewFilterResolver], - exports: [ViewFilterService], + providers: [ViewFilterService, ViewFilterResolver, ViewFilterV2Service], + exports: [ViewFilterService, ViewFilterV2Service], }) export class ViewFilterModule {} diff --git a/packages/twenty-server/src/engine/workspace-flat-map-cache/workspace-flat-map-cache.module.ts b/packages/twenty-server/src/engine/workspace-flat-map-cache/workspace-flat-map-cache.module.ts index 13c6f45d829..a18221e2d9c 100644 --- a/packages/twenty-server/src/engine/workspace-flat-map-cache/workspace-flat-map-cache.module.ts +++ b/packages/twenty-server/src/engine/workspace-flat-map-cache/workspace-flat-map-cache.module.ts @@ -7,10 +7,12 @@ import { WorkspaceFlatFieldMetadataMapCacheService } from 'src/engine/metadata-m import { WorkspaceFlatIndexMapCacheService } from 'src/engine/metadata-modules/flat-index-metadata/services/workspace-flat-index-map-cache.service'; import { WorkspaceFlatObjectMetadataMapCacheService } from 'src/engine/metadata-modules/flat-object-metadata/services/workspace-flat-object-metadata-map-cache.service'; import { WorkspaceFlatViewFieldMapCacheService } from 'src/engine/metadata-modules/flat-view-field/services/workspace-flat-view-field-map-cache.service'; +import { WorkspaceFlatViewFilterMapCacheService } from 'src/engine/metadata-modules/flat-view-filter/services/workspace-flat-view-filter-map-cache.service'; import { WorkspaceFlatViewMapCacheService } from 'src/engine/metadata-modules/flat-view/services/workspace-flat-view-map-cache.service'; import { IndexMetadataEntity } from 'src/engine/metadata-modules/index-metadata/index-metadata.entity'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity'; +import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity'; import { ViewEntity } from 'src/engine/metadata-modules/view/entities/view.entity'; import { WorkspaceMetadataCacheModule } from 'src/engine/metadata-modules/workspace-metadata-cache/workspace-metadata-cache.module'; import { WorkspaceMetadataVersionModule } from 'src/engine/metadata-modules/workspace-metadata-version/workspace-metadata-version.module'; @@ -26,6 +28,7 @@ import { WorkspaceFlatMapCacheRegistryService } from 'src/engine/workspace-flat- TypeOrmModule.forFeature([ ViewEntity, ViewFieldEntity, + ViewFilterEntity, IndexMetadataEntity, FieldMetadataEntity, ObjectMetadataEntity, @@ -36,6 +39,7 @@ import { WorkspaceFlatMapCacheRegistryService } from 'src/engine/workspace-flat- WorkspaceFlatObjectMetadataMapCacheService, WorkspaceFlatViewMapCacheService, WorkspaceFlatViewFieldMapCacheService, + WorkspaceFlatViewFilterMapCacheService, WorkspaceFlatIndexMapCacheService, WorkspaceFlatFieldMetadataMapCacheService, ], @@ -44,6 +48,7 @@ import { WorkspaceFlatMapCacheRegistryService } from 'src/engine/workspace-flat- WorkspaceFlatObjectMetadataMapCacheService, WorkspaceFlatViewMapCacheService, WorkspaceFlatViewFieldMapCacheService, + WorkspaceFlatViewFilterMapCacheService, WorkspaceFlatIndexMapCacheService, WorkspaceFlatFieldMetadataMapCacheService, ], diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant.ts index c2826a08805..9b73fb3da4a 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/constant/empty-orchestrator-actions-report.constant.ts @@ -19,4 +19,5 @@ export const EMPTY_ORCHESTRATOR_ACTIONS_REPORT = { databaseEventTrigger: emptyCreatedDeletedUpdated, cronTrigger: emptyCreatedDeletedUpdated, routeTrigger: emptyCreatedDeletedUpdated, + viewFilter: emptyCreatedDeletedUpdated, } as const satisfies OrchestratorActionsReport; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/interceptors/utils/from-workspace-migration-builder-exception-to-validation-response-error.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/interceptors/utils/from-workspace-migration-builder-exception-to-validation-response-error.util.ts index eb6e646073b..0525c8814ff 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/interceptors/utils/from-workspace-migration-builder-exception-to-validation-response-error.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/interceptors/utils/from-workspace-migration-builder-exception-to-validation-response-error.util.ts @@ -10,6 +10,7 @@ export const fromWorkspaceMigrationBuilderExceptionToValidationResponseError = ( ): ValidationErrorResponse => { const emptyResponseError: ValidationErrorResponse = { summary: { + invalidViewFilter: 0, invalidObjectMetadata: 0, invalidView: 0, invalidViewField: 0, @@ -31,6 +32,7 @@ export const fromWorkspaceMigrationBuilderExceptionToValidationResponseError = ( databaseEventTrigger: [], cronTrigger: [], routeTrigger: [], + viewFilter: [], }, }; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts index 9a38dde550b..1b42f45430f 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/services/workspace-migration-build-orchestrator.service.ts @@ -20,6 +20,7 @@ import { WorkspaceMigrationV2ObjectActionsBuilderService } from 'src/engine/work import { WorkspaceMigrationV2RouteTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/route-trigger/workspace-migration-v2-route-trigger-actions-builder.service'; import { WorkspaceMigrationV2ServerlessFunctionActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service'; import { WorkspaceMigrationV2ViewFieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service'; +import { WorkspaceMigrationV2ViewFilterActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/workspace-migration-v2-view-filter-actions-builder.service'; import { WorkspaceMigrationV2ViewActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service'; @Injectable() export class WorkspaceMigrationBuildOrchestratorService { @@ -28,6 +29,7 @@ export class WorkspaceMigrationBuildOrchestratorService { private readonly workspaceMigrationV2IndexActionsBuilderService: WorkspaceMigrationV2IndexActionsBuilderService, private readonly workspaceMigrationV2ViewActionsBuilderService: WorkspaceMigrationV2ViewActionsBuilderService, private readonly workspaceMigrationV2ViewFieldActionsBuilderService: WorkspaceMigrationV2ViewFieldActionsBuilderService, + private readonly workspaceMigrationV2ViewFilterActionsBuilderService: WorkspaceMigrationV2ViewFilterActionsBuilderService, private readonly workspaceMigrationV2ServerlessFunctionActionsBuilderService: WorkspaceMigrationV2ServerlessFunctionActionsBuilderService, private readonly workspaceMigrationV2DatabaseEventTriggerActionsBuilderService: WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService, private readonly workspaceMigrationV2CronTriggerActionsBuilderService: WorkspaceMigrationV2CronTriggerActionsBuilderService, @@ -88,6 +90,7 @@ export class WorkspaceMigrationBuildOrchestratorService { cronTrigger: [], routeTrigger: [], fieldMetadata: [], + viewFilter: [], }; const optimisticAllFlatEntityMaps = this.setupOptimisticCache({ @@ -104,6 +107,7 @@ export class WorkspaceMigrationBuildOrchestratorService { flatCronTriggerMaps, flatRouteTriggerMaps, flatFieldMetadataMaps, + flatViewFilterMaps, } = fromToAllFlatEntityMaps; if (isDefined(flatObjectMetadataMaps)) { @@ -268,6 +272,36 @@ export class WorkspaceMigrationBuildOrchestratorService { } } + if (isDefined(flatViewFilterMaps)) { + const { from: fromFlatViewFilterMaps, to: toFlatViewFilterMaps } = + flatViewFilterMaps; + const viewFilterResult = + await this.workspaceMigrationV2ViewFilterActionsBuilderService.validateAndBuild( + { + from: fromFlatViewFilterMaps, + to: toFlatViewFilterMaps, + buildOptions, + dependencyOptimisticFlatEntityMaps: { + flatFieldMetadataMaps: + optimisticAllFlatEntityMaps.flatFieldMetadataMaps, + flatViewMaps: optimisticAllFlatEntityMaps.flatViewMaps, + }, + workspaceId, + }, + ); + + optimisticAllFlatEntityMaps.flatViewFilterMaps = + viewFilterResult.optimisticFlatEntityMaps; + optimisticAllFlatEntityMaps.flatViewMaps = + viewFilterResult.dependencyOptimisticFlatEntityMaps.flatViewMaps; + + if (viewFilterResult.status === 'fail') { + orchestratorFailureReport.viewFilter.push(...viewFilterResult.errors); + } else { + orchestratorActionsReport.viewFilter = viewFilterResult.actions; + } + } + if (isDefined(flatServerlessFunctionMaps)) { const { from: fromFlatServerlessFunctionMaps, @@ -434,6 +468,9 @@ export class WorkspaceMigrationBuildOrchestratorService { ...aggregatedOrchestratorActionsReport.viewField.deleted, ...aggregatedOrchestratorActionsReport.viewField.created, ...aggregatedOrchestratorActionsReport.viewField.updated, + ...aggregatedOrchestratorActionsReport.viewFilter.deleted, + ...aggregatedOrchestratorActionsReport.viewFilter.created, + ...aggregatedOrchestratorActionsReport.viewFilter.updated, /// // Serverless functions diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/types/view-filter-related-flat-entity-maps.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/types/view-filter-related-flat-entity-maps.type.ts new file mode 100644 index 00000000000..463e27c238b --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/types/view-filter-related-flat-entity-maps.type.ts @@ -0,0 +1,6 @@ +import { type AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; + +export type ViewFilterRelatedFlatEntityMaps = Pick< + AllFlatEntityMaps, + 'flatViewMaps' | 'flatFieldMetadataMaps' +>; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/workspace-migration-v2-view-filter-actions-builder.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/workspace-migration-v2-view-filter-actions-builder.service.ts new file mode 100644 index 00000000000..55f5385fadd --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/workspace-migration-v2-view-filter-actions-builder.service.ts @@ -0,0 +1,197 @@ +import { Injectable } from '@nestjs/common'; + +import { isDefined } from 'twenty-shared/utils'; + +import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; +import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; +import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util'; +import { FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type'; +import { compareTwoFlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/utils/compare-two-flat-view-filter.util'; +import { ViewFilterRelatedFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/types/view-filter-related-flat-entity-maps.type'; +import { + FlatEntityUpdateValidationArgs, + FlatEntityValidationArgs, + FlatEntityValidationReturnType, + WorkspaceEntityMigrationBuilderV2Service, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/services/workspace-entity-migration-builder-v2.service'; +import { + UpdateViewFilterAction, + WorkspaceMigrationViewFilterActionV2, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-filter-action-v2.type'; +import { FlatViewFilterValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-filter-validator.service'; + +@Injectable() +export class WorkspaceMigrationV2ViewFilterActionsBuilderService extends WorkspaceEntityMigrationBuilderV2Service< + 'viewFilter', + FlatViewFilter, + WorkspaceMigrationViewFilterActionV2, + ViewFilterRelatedFlatEntityMaps +> { + constructor( + private readonly flatViewFilterValidatorService: FlatViewFilterValidatorService, + ) { + super('viewFilter'); + } + + protected async validateFlatEntityCreation({ + dependencyOptimisticFlatEntityMaps, + flatEntityToValidate: flatViewFilterToValidate, + optimisticFlatEntityMaps: optimisticFlatViewFilterMaps, + }: FlatEntityValidationArgs< + FlatViewFilter, + ViewFilterRelatedFlatEntityMaps + >): Promise< + FlatEntityValidationReturnType< + WorkspaceMigrationViewFilterActionV2, + FlatViewFilter, + ViewFilterRelatedFlatEntityMaps + > + > { + const validationResult = + this.flatViewFilterValidatorService.validateFlatViewFilterCreation({ + dependencyOptimisticFlatEntityMaps, + flatViewFilterToValidate, + optimisticFlatViewFilterMaps, + }); + + if (validationResult.errors.length > 0) { + return { + status: 'fail', + ...validationResult, + }; + } + + const flatView = findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: flatViewFilterToValidate.viewId, + flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, + }); + + const updatedFlatViewMaps = replaceFlatEntityInFlatEntityMapsOrThrow({ + flatEntity: { + ...flatView, + viewFilterIds: [...flatView.viewFilterIds, flatViewFilterToValidate.id], + }, + flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, + }); + + return { + status: 'success', + action: { + type: 'create_view_filter', + viewFilter: flatViewFilterToValidate, + }, + dependencyOptimisticFlatEntityMaps: { + ...dependencyOptimisticFlatEntityMaps, + flatViewMaps: updatedFlatViewMaps, + }, + }; + } + + protected async validateFlatEntityDeletion({ + dependencyOptimisticFlatEntityMaps, + flatEntityToValidate: flatViewFilterToValidate, + optimisticFlatEntityMaps: optimisticFlatViewFilterMaps, + }: FlatEntityValidationArgs< + FlatViewFilter, + ViewFilterRelatedFlatEntityMaps + >): Promise< + FlatEntityValidationReturnType< + WorkspaceMigrationViewFilterActionV2, + FlatViewFilter, + ViewFilterRelatedFlatEntityMaps + > + > { + const validationResult = + this.flatViewFilterValidatorService.validateFlatViewFilterDeletion({ + flatViewFilterToValidate, + optimisticFlatViewFilterMaps, + }); + + if (validationResult.errors.length > 0) { + return { + status: 'fail', + ...validationResult, + }; + } + + const flatView = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: flatViewFilterToValidate.viewId, + flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, + }); + + const updatedFlatViewMaps = isDefined(flatView) + ? replaceFlatEntityInFlatEntityMapsOrThrow({ + flatEntity: { + ...flatView, + viewFilterIds: flatView.viewFilterIds.filter( + (id) => id !== flatViewFilterToValidate.id, + ), + }, + flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, + }) + : dependencyOptimisticFlatEntityMaps.flatViewMaps; + + return { + status: 'success', + action: { + type: 'delete_view_filter', + viewFilterId: flatViewFilterToValidate.id, + }, + dependencyOptimisticFlatEntityMaps: { + ...dependencyOptimisticFlatEntityMaps, + flatViewMaps: updatedFlatViewMaps, + }, + }; + } + + protected async validateFlatEntityUpdate({ + dependencyOptimisticFlatEntityMaps, + flatEntityUpdate: { from: fromFlatViewFilter, to: toFlatViewFilter }, + optimisticFlatEntityMaps: optimisticFlatViewFilterMaps, + }: FlatEntityUpdateValidationArgs< + FlatViewFilter, + ViewFilterRelatedFlatEntityMaps + >): Promise< + | FlatEntityValidationReturnType< + WorkspaceMigrationViewFilterActionV2, + FlatViewFilter, + ViewFilterRelatedFlatEntityMaps + > + | undefined + > { + const viewFilterUpdatedProperties = compareTwoFlatViewFilter({ + fromFlatViewFilter, + toFlatViewFilter, + }); + + if (viewFilterUpdatedProperties.length === 0) { + return undefined; + } + + const validationResult = + this.flatViewFilterValidatorService.validateFlatViewFilterUpdate({ + dependencyOptimisticFlatEntityMaps, + flatViewFilterToValidate: toFlatViewFilter, + optimisticFlatViewFilterMaps, + }); + + if (validationResult.errors.length > 0) { + return { + status: 'fail', + ...validationResult, + }; + } + + const updateViewFilterAction: UpdateViewFilterAction = { + type: 'update_view_filter', + viewFilterId: toFlatViewFilter.id, + updates: viewFilterUpdatedProperties, + }; + + return { + status: 'success', + action: updateViewFilterAction, + dependencyOptimisticFlatEntityMaps, + }; + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2.ts index 96df25af220..9a62dd8b59f 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-action-common-v2.ts @@ -7,6 +7,7 @@ import { type WorkspaceMigrationRouteTriggerActionV2 } from 'src/engine/workspac import { type WorkspaceMigrationServerlessFunctionActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-serverless-function-action-v2.type'; import { type WorkspaceMigrationViewActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-action-v2.type'; import { type WorkspaceMigrationViewFieldActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-field-action-v2.type'; +import { type WorkspaceMigrationViewFilterActionV2 } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-filter-action-v2.type'; export type WorkspaceMigrationActionV2 = | WorkspaceMigrationObjectActionV2 @@ -14,6 +15,7 @@ export type WorkspaceMigrationActionV2 = | WorkspaceMigrationIndexActionV2 | WorkspaceMigrationViewActionV2 | WorkspaceMigrationViewFieldActionV2 + | WorkspaceMigrationViewFilterActionV2 | WorkspaceMigrationServerlessFunctionActionV2 | WorkspaceMigrationDatabaseEventTriggerActionV2 | WorkspaceMigrationCronTriggerActionV2 diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-field-action-v2.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-field-action-v2.type.ts index a17912377e5..064b290c757 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-field-action-v2.type.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-field-action-v2.type.ts @@ -1,30 +1,20 @@ -import { type FromTo } from 'twenty-shared/types'; - import { type FlatViewFieldPropertiesToCompare } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field-properties-to-compare.type'; import { type FlatViewField } from 'src/engine/metadata-modules/flat-view-field/types/flat-view-field.type'; -import { type ViewFieldEntity } from 'src/engine/metadata-modules/view-field/entities/view-field.entity'; - -export type FlatViewFieldPropertyUpdate< - P extends FlatViewFieldPropertiesToCompare, -> = { - property: P; -} & FromTo; +import { type PropertyUpdate } from 'src/engine/workspace-manager/workspace-migration-v2/types/property-update.type'; export type CreateViewFieldAction = { type: 'create_view_field'; viewField: FlatViewField; }; -export type FlatViewFieldPropertiesUpdates = Array< - { - [P in FlatViewFieldPropertiesToCompare]: FlatViewFieldPropertyUpdate

; - }[FlatViewFieldPropertiesToCompare] ->; - export type UpdateViewFieldAction = { type: 'update_view_field'; viewFieldId: string; - updates: FlatViewFieldPropertiesUpdates; + updates: Array< + { + [P in FlatViewFieldPropertiesToCompare]: PropertyUpdate; + }[FlatViewFieldPropertiesToCompare] + >; }; export type DeleteViewFieldAction = { diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-filter-action-v2.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-filter-action-v2.type.ts new file mode 100644 index 00000000000..36905b544e7 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-filter-action-v2.type.ts @@ -0,0 +1,34 @@ +import { type FlatViewFilterPropertiesToCompare } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-properties-to-compare.type'; +import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type'; +import { type PropertyUpdate } from 'src/engine/workspace-manager/workspace-migration-v2/types/property-update.type'; + +export type CreateViewFilterAction = { + type: 'create_view_filter'; + viewFilter: FlatViewFilter; +}; + +export type UpdateViewFilterAction = { + type: 'update_view_filter'; + viewFilterId: string; + updates: Array< + { + [P in FlatViewFilterPropertiesToCompare]: PropertyUpdate< + FlatViewFilter, + P + >; + }[FlatViewFilterPropertiesToCompare] + >; +}; + +export type DeleteViewFilterAction = { + type: 'delete_view_filter'; + viewFilterId: string; +}; + +export type WorkspaceMigrationViewFilterActionV2 = + | CreateViewFilterAction + | UpdateViewFilterAction + | DeleteViewFilterAction; + +export type WorkspaceMigrationViewFilterActionTypeV2 = + WorkspaceMigrationViewFilterActionV2['type']; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-filter-validator.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-filter-validator.service.ts new file mode 100644 index 00000000000..dab6588854b --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-filter-validator.service.ts @@ -0,0 +1,158 @@ +import { Injectable } from '@nestjs/common'; + +import { msg, t } from '@lingui/core/macro'; +import { isDefined } from 'twenty-shared/utils'; + +import { findFlatEntityByIdInFlatEntityMaps } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps.util'; +import { type FlatViewFilterMaps } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter-maps.type'; +import { type FlatViewFilter } from 'src/engine/metadata-modules/flat-view-filter/types/flat-view-filter.type'; +import { ViewFilterExceptionCode } from 'src/engine/metadata-modules/view-filter/exceptions/view-filter.exception'; +import { FailedFlatEntityValidation } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/types/failed-flat-entity-validation.type'; +import { ViewFilterRelatedFlatEntityMaps } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/types/view-filter-related-flat-entity-maps.type'; + +@Injectable() +export class FlatViewFilterValidatorService { + constructor() {} + + validateFlatViewFilterCreation({ + flatViewFilterToValidate, + dependencyOptimisticFlatEntityMaps, + optimisticFlatViewFilterMaps, + }: { + flatViewFilterToValidate: FlatViewFilter; + dependencyOptimisticFlatEntityMaps: ViewFilterRelatedFlatEntityMaps; + optimisticFlatViewFilterMaps: FlatViewFilterMaps; + }): FailedFlatEntityValidation { + const validationResult: FailedFlatEntityValidation = { + type: 'create_view_filter', + errors: [], + flatEntityMinimalInformation: { + id: flatViewFilterToValidate.id, + }, + }; + + const existingViewFilter = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: flatViewFilterToValidate.id, + flatEntityMaps: optimisticFlatViewFilterMaps, + }); + + if (isDefined(existingViewFilter)) { + validationResult.errors.push({ + code: ViewFilterExceptionCode.INVALID_VIEW_FILTER_DATA, + message: t`View filter with this id already exists`, + userFriendlyMessage: msg`View filter with this id already exists`, + }); + } + + const referencedView = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: flatViewFilterToValidate.viewId, + flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatViewMaps, + }); + + if (!isDefined(referencedView)) { + validationResult.errors.push({ + code: ViewFilterExceptionCode.INVALID_VIEW_FILTER_DATA, + message: t`View not found`, + userFriendlyMessage: msg`View not found`, + }); + } + + const referencedFieldMetadata = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: flatViewFilterToValidate.fieldMetadataId, + flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + }); + + if (!isDefined(referencedFieldMetadata)) { + validationResult.errors.push({ + code: ViewFilterExceptionCode.INVALID_VIEW_FILTER_DATA, + message: t`Field metadata not found`, + userFriendlyMessage: msg`Field metadata not found`, + }); + } + + return validationResult; + } + + validateFlatViewFilterDeletion({ + flatViewFilterToValidate, + optimisticFlatViewFilterMaps, + }: { + flatViewFilterToValidate: FlatViewFilter; + optimisticFlatViewFilterMaps: FlatViewFilterMaps; + }): FailedFlatEntityValidation { + const validationResult: FailedFlatEntityValidation = { + type: 'delete_view_filter', + errors: [], + flatEntityMinimalInformation: { + id: flatViewFilterToValidate.id, + }, + }; + + const existingViewFilter = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: flatViewFilterToValidate.id, + flatEntityMaps: optimisticFlatViewFilterMaps, + }); + + if (!isDefined(existingViewFilter)) { + validationResult.errors.push({ + code: ViewFilterExceptionCode.VIEW_FILTER_NOT_FOUND, + message: t`View filter not found`, + userFriendlyMessage: msg`View filter not found`, + }); + } else if (!isDefined(existingViewFilter.deletedAt)) { + validationResult.errors.push({ + code: ViewFilterExceptionCode.INVALID_VIEW_FILTER_DATA, + message: t`View filter has to be soft deleted first`, + userFriendlyMessage: msg`View filter has to be soft deleted first`, + }); + } + + return validationResult; + } + + validateFlatViewFilterUpdate({ + flatViewFilterToValidate, + dependencyOptimisticFlatEntityMaps, + optimisticFlatViewFilterMaps, + }: { + flatViewFilterToValidate: FlatViewFilter; + dependencyOptimisticFlatEntityMaps: ViewFilterRelatedFlatEntityMaps; + optimisticFlatViewFilterMaps: FlatViewFilterMaps; + }): FailedFlatEntityValidation { + const validationResult: FailedFlatEntityValidation = { + type: 'update_view_filter', + errors: [], + flatEntityMinimalInformation: { + id: flatViewFilterToValidate.id, + }, + }; + + const existingViewFilter = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: flatViewFilterToValidate.id, + flatEntityMaps: optimisticFlatViewFilterMaps, + }); + + if (!isDefined(existingViewFilter)) { + validationResult.errors.push({ + code: ViewFilterExceptionCode.VIEW_FILTER_NOT_FOUND, + message: t`View filter not found`, + userFriendlyMessage: msg`View filter not found`, + }); + } + + const referencedFieldMetadata = findFlatEntityByIdInFlatEntityMaps({ + flatEntityId: flatViewFilterToValidate.fieldMetadataId, + flatEntityMaps: dependencyOptimisticFlatEntityMaps.flatFieldMetadataMaps, + }); + + if (!isDefined(referencedFieldMetadata)) { + validationResult.errors.push({ + code: ViewFilterExceptionCode.INVALID_VIEW_FILTER_DATA, + message: t`Field metadata not found`, + userFriendlyMessage: msg`Field metadata not found`, + }); + } + + return validationResult; + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/workspace-migration-builder-validators.module.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/workspace-migration-builder-validators.module.ts index 14f624fed1a..a214fab1b02 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/workspace-migration-builder-validators.module.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/workspace-migration-builder-validators.module.ts @@ -10,6 +10,7 @@ import { FlatObjectMetadataValidatorService } from 'src/engine/workspace-manager import { FlatRouteTriggerValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-route-trigger-validator.service'; import { FlatServerlessFunctionValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-serverless-function-validator.service'; import { FlatViewFieldValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-field-validator.service'; +import { FlatViewFilterValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-filter-validator.service'; import { FlatViewValidatorService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/services/flat-view-validator.service'; @Module({ @@ -17,6 +18,7 @@ import { FlatViewValidatorService } from 'src/engine/workspace-manager/workspace providers: [ FlatViewValidatorService, FlatViewFieldValidatorService, + FlatViewFilterValidatorService, FlatIndexValidatorService, FlatFieldMetadataValidatorService, FlatObjectMetadataValidatorService, @@ -29,6 +31,7 @@ import { FlatViewValidatorService } from 'src/engine/workspace-manager/workspace exports: [ FlatViewValidatorService, FlatViewFieldValidatorService, + FlatViewFilterValidatorService, FlatIndexValidatorService, FlatFieldMetadataValidatorService, FlatObjectMetadataValidatorService, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts index cd283e87401..f4761aa3c29 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/workspace-migration-builder-v2.module.ts @@ -10,6 +10,7 @@ import { WorkspaceMigrationV2ObjectActionsBuilderService } from 'src/engine/work import { WorkspaceMigrationV2RouteTriggerActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/route-trigger/workspace-migration-v2-route-trigger-actions-builder.service'; import { WorkspaceMigrationV2ServerlessFunctionActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/serverless-function/workspace-migration-v2-serverless-function-actions-builder.service'; import { WorkspaceMigrationV2ViewFieldActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-field/workspace-migration-v2-view-field-actions-builder.service'; +import { WorkspaceMigrationV2ViewFilterActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view-filter/workspace-migration-v2-view-filter-actions-builder.service'; import { WorkspaceMigrationV2ViewActionsBuilderService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/builders/view/workspace-migration-v2-view-actions-builder.service'; import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/validators/workspace-migration-builder-validators.module'; @@ -20,6 +21,7 @@ import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace- WorkspaceMigrationV2ObjectActionsBuilderService, WorkspaceMigrationV2ViewActionsBuilderService, WorkspaceMigrationV2ViewFieldActionsBuilderService, + WorkspaceMigrationV2ViewFilterActionsBuilderService, WorkspaceMigrationV2IndexActionsBuilderService, WorkspaceMigrationV2ServerlessFunctionActionsBuilderService, WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService, @@ -32,6 +34,7 @@ import { WorkspaceMigrationBuilderValidatorsModule } from 'src/engine/workspace- WorkspaceMigrationV2IndexActionsBuilderService, WorkspaceMigrationV2ObjectActionsBuilderService, WorkspaceMigrationV2ViewFieldActionsBuilderService, + WorkspaceMigrationV2ViewFilterActionsBuilderService, WorkspaceMigrationV2FieldActionsBuilderService, WorkspaceMigrationV2ServerlessFunctionActionsBuilderService, WorkspaceMigrationV2DatabaseEventTriggerActionsBuilderService, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/create-view-filter-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/create-view-filter-action-handler.service.ts new file mode 100644 index 00000000000..63d1fd9ae14 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/create-view-filter-action-handler.service.ts @@ -0,0 +1,55 @@ +import { Injectable } from '@nestjs/common'; + +import { + OptimisticallyApplyActionOnAllFlatEntityMapsArgs, + WorkspaceMigrationRunnerActionHandler, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface'; + +import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; +import { addFlatEntityToFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/add-flat-entity-to-flat-entity-maps-or-throw.util'; +import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity'; +import { CreateViewFilterAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-filter-action-v2.type'; +import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type'; + +@Injectable() +export class CreateViewFilterActionHandlerService extends WorkspaceMigrationRunnerActionHandler( + 'create_view_filter', +) { + optimisticallyApplyActionOnAllFlatEntityMaps({ + action, + allFlatEntityMaps, + }: OptimisticallyApplyActionOnAllFlatEntityMapsArgs): Partial { + const { flatViewFilterMaps } = allFlatEntityMaps; + const { viewFilter } = action; + + const updatedFlatViewFilterMaps = addFlatEntityToFlatEntityMapsOrThrow({ + flatEntity: viewFilter, + flatEntityMaps: flatViewFilterMaps, + }); + + return { + flatViewFilterMaps: updatedFlatViewFilterMaps, + }; + } + + async executeForMetadata( + context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + const { action, queryRunner, workspaceId } = context; + const { viewFilter } = action; + + const viewFilterRepository = + queryRunner.manager.getRepository(ViewFilterEntity); + + await viewFilterRepository.insert({ + ...viewFilter, + workspaceId, + }); + } + + async executeForWorkspaceSchema( + _context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + return; + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/delete-view-filter-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/delete-view-filter-action-handler.service.ts new file mode 100644 index 00000000000..d45c6c8c738 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/delete-view-filter-action-handler.service.ts @@ -0,0 +1,61 @@ +import { Injectable } from '@nestjs/common'; + +import { + OptimisticallyApplyActionOnAllFlatEntityMapsArgs, + WorkspaceMigrationRunnerActionHandler, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface'; + +import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; +import { deleteFlatEntityFromFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/delete-flat-entity-from-flat-entity-maps-or-throw.util'; +import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity'; +import { DeleteViewFilterAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-filter-action-v2.type'; +import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type'; + +@Injectable() +export class DeleteViewFilterActionHandlerService extends WorkspaceMigrationRunnerActionHandler( + 'delete_view_filter', +) { + constructor() { + super(); + } + + optimisticallyApplyActionOnAllFlatEntityMaps({ + action, + allFlatEntityMaps, + }: OptimisticallyApplyActionOnAllFlatEntityMapsArgs): Partial { + const { flatViewFilterMaps } = allFlatEntityMaps; + const { viewFilterId } = action; + + const updatedFlatViewFilterMaps = deleteFlatEntityFromFlatEntityMapsOrThrow( + { + entityToDeleteId: viewFilterId, + flatEntityMaps: flatViewFilterMaps, + }, + ); + + return { + flatViewFilterMaps: updatedFlatViewFilterMaps, + }; + } + + async executeForMetadata( + context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + const { action, queryRunner, workspaceId } = context; + const { viewFilterId } = action; + + const viewFilterRepository = + queryRunner.manager.getRepository(ViewFilterEntity); + + await viewFilterRepository.delete({ + id: viewFilterId, + workspaceId, + }); + } + + async executeForWorkspaceSchema( + _context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + return; + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/update-view-filter-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/update-view-filter-action-handler.service.ts new file mode 100644 index 00000000000..c3dd04c2436 --- /dev/null +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/update-view-filter-action-handler.service.ts @@ -0,0 +1,70 @@ +import { Injectable } from '@nestjs/common'; + +import { + OptimisticallyApplyActionOnAllFlatEntityMapsArgs, + WorkspaceMigrationRunnerActionHandler, +} from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface'; + +import { AllFlatEntityMaps } from 'src/engine/core-modules/common/types/all-flat-entity-maps.type'; +import { findFlatEntityByIdInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/find-flat-entity-by-id-in-flat-entity-maps-or-throw.util'; +import { replaceFlatEntityInFlatEntityMapsOrThrow } from 'src/engine/core-modules/common/utils/replace-flat-entity-in-flat-entity-maps-or-throw.util'; +import { ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity'; +import { UpdateViewFilterAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-filter-action-v2.type'; +import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type'; +import { fromWorkspaceMigrationUpdateActionToPartialEntity } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/utils/from-workspace-migration-update-action-to-partial-field-or-object-entity.util'; + +@Injectable() +export class UpdateViewFilterActionHandlerService extends WorkspaceMigrationRunnerActionHandler( + 'update_view_filter', +) { + constructor() { + super(); + } + + optimisticallyApplyActionOnAllFlatEntityMaps({ + action, + allFlatEntityMaps, + }: OptimisticallyApplyActionOnAllFlatEntityMapsArgs): Partial { + const { flatViewFilterMaps } = allFlatEntityMaps; + const { viewFilterId } = action; + + const existingViewFilter = findFlatEntityByIdInFlatEntityMapsOrThrow({ + flatEntityId: viewFilterId, + flatEntityMaps: flatViewFilterMaps, + }); + + const updatedViewFilter = { + ...existingViewFilter, + ...fromWorkspaceMigrationUpdateActionToPartialEntity(action), + }; + + const updatedFlatViewFilterMaps = replaceFlatEntityInFlatEntityMapsOrThrow({ + flatEntity: updatedViewFilter, + flatEntityMaps: flatViewFilterMaps, + }); + + return { + flatViewFilterMaps: updatedFlatViewFilterMaps, + }; + } + + async executeForMetadata( + context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + const { action, queryRunner } = context; + const { viewFilterId } = action; + + const viewFilterRepository = + queryRunner.manager.getRepository(ViewFilterEntity); + + const update = fromWorkspaceMigrationUpdateActionToPartialEntity(action); + + await viewFilterRepository.update(viewFilterId, update); + } + + async executeForWorkspaceSchema( + _context: WorkspaceMigrationActionRunnerArgs, + ): Promise { + return; + } +} diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/workspace-schema-migration-runner-action-handlers.module.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/workspace-schema-migration-runner-action-handlers.module.ts index f30d33deefc..0f8f6699eb3 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/workspace-schema-migration-runner-action-handlers.module.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/workspace-schema-migration-runner-action-handlers.module.ts @@ -24,6 +24,9 @@ import { UpdateServerlessFunctionActionHandlerService } from 'src/engine/workspa import { CreateViewFieldActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-field/services/create-view-field-action-handler.service'; import { DeleteViewFieldActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-field/services/delete-view-field-action-handler.service'; import { UpdateViewFieldActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-field/services/update-view-field-action-handler.service'; +import { CreateViewFilterActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/create-view-filter-action-handler.service'; +import { DeleteViewFilterActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/delete-view-filter-action-handler.service'; +import { UpdateViewFilterActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view-filter/services/update-view-filter-action-handler.service'; import { CreateViewActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view/services/create-view-action-handler.service'; import { DeleteViewActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view/services/delete-view-action-handler.service'; import { UpdateViewActionHandlerService } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view/services/update-view-action-handler.service'; @@ -50,6 +53,10 @@ import { UpdateViewActionHandlerService } from 'src/engine/workspace-manager/wor UpdateViewFieldActionHandlerService, DeleteViewFieldActionHandlerService, + CreateViewFilterActionHandlerService, + UpdateViewFilterActionHandlerService, + DeleteViewFilterActionHandlerService, + CreateServerlessFunctionActionHandlerService, DeleteServerlessFunctionActionHandlerService, UpdateServerlessFunctionActionHandlerService, diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/order-object-properties.util.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/order-object-properties.util.ts index e3a40529f0f..dc9065582e0 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/order-object-properties.util.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-sync-metadata/comparators/utils/order-object-properties.util.ts @@ -1,7 +1,4 @@ -// eslint-disable-next-line @typescript-eslint/no-explicit-any -export function orderObjectProperties | object>( - data: T, -): T { +export function orderObjectProperties(data: T): T { if (Array.isArray(data)) { return data.map(orderObjectProperties) as T; } diff --git a/packages/twenty-server/test/integration/graphql/suites/group-by-resolvers.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/group-by-resolvers.integration-spec.ts index c73e4b68bfe..408eb316f51 100644 --- a/packages/twenty-server/test/integration/graphql/suites/group-by-resolvers.integration-spec.ts +++ b/packages/twenty-server/test/integration/graphql/suites/group-by-resolvers.integration-spec.ts @@ -3,13 +3,14 @@ import { randomUUID } from 'crypto'; import { PERSON_GQL_FIELDS } from 'test/integration/constants/person-gql-fields.constants'; import { createOneOperationFactory } from 'test/integration/graphql/utils/create-one-operation-factory.util'; import { createViewFilterGroupOperationFactory } from 'test/integration/graphql/utils/create-view-filter-group-operation-factory.util'; -import { createViewFilterOperationFactory } from 'test/integration/graphql/utils/create-view-filter-operation-factory.util'; import { createViewOperationFactory } from 'test/integration/graphql/utils/create-view-operation-factory.util'; import { destroyOneOperationFactory } from 'test/integration/graphql/utils/destroy-one-operation-factory.util'; import { groupByOperationFactory } from 'test/integration/graphql/utils/group-by-operation-factory.util'; import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util'; import { findManyObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/find-many-object-metadata.util'; import { ViewFilterOperand } from 'twenty-shared/types'; +import { createOneCoreViewFilter } from 'test/integration/metadata/suites/view-filter/utils/create-one-core-view-filter.util'; +import { jestExpectToBeDefined } from 'test/utils/expect-to-be-defined.util.test'; import { type FieldMetadataDTO } from 'src/engine/metadata-modules/field-metadata/dtos/field-metadata.dto'; import { type ObjectMetadataDTO } from 'src/engine/metadata-modules/object-metadata/dtos/object-metadata.dto'; @@ -443,18 +444,18 @@ describe('group-by resolvers (integration)', () => { const viewFilterGroupId = viewFilterGroupResponse.body.data .createCoreViewFilterGroup.id as string; - await makeGraphqlAPIRequest( - createViewFilterOperationFactory({ - data: { - viewId, - viewFilterGroupId, - fieldMetadataId: cityFieldMetadataId, - operand: ViewFilterOperand.CONTAINS, - value: cityToKeep, - positionInViewFilterGroup: 0, - }, - }), - ); + jestExpectToBeDefined(cityFieldMetadataId); + await createOneCoreViewFilter({ + input: { + viewId, + viewFilterGroupId, + fieldMetadataId: cityFieldMetadataId, + operand: ViewFilterOperand.CONTAINS, + value: cityToKeep, + positionInViewFilterGroup: 0, + }, + expectToFail: false, + }); const response = await makeGraphqlAPIRequest( groupByOperationFactory({ diff --git a/packages/twenty-server/test/integration/graphql/suites/settings-permissions/granular-settings-permissions.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/settings-permissions/granular-settings-permissions.integration-spec.ts index 33ad84e1e6e..e8999a8d299 100644 --- a/packages/twenty-server/test/integration/graphql/suites/settings-permissions/granular-settings-permissions.integration-spec.ts +++ b/packages/twenty-server/test/integration/graphql/suites/settings-permissions/granular-settings-permissions.integration-spec.ts @@ -1,10 +1,10 @@ -import { print } from 'graphql'; import request from 'supertest'; import { deleteOneRoleOperationFactory } from 'test/integration/graphql/utils/delete-one-role-operation-factory.util'; import { destroyOneOperationFactory } from 'test/integration/graphql/utils/destroy-one-operation-factory.util'; import { updateWorkspaceMemberRole } from 'test/integration/graphql/utils/update-workspace-member-role.util'; -import { createOneObjectMetadataQueryFactory } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata-query-factory.util'; -import { deleteOneObjectMetadataQueryFactory } from 'test/integration/metadata/suites/object-metadata/utils/delete-one-object-metadata-query-factory.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 { createOneObjectMetadata } from 'test/integration/metadata/suites/object-metadata/utils/create-one-object-metadata.util'; import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; import { PermissionFlagType } from 'src/engine/metadata-modules/permissions/constants/permission-flag-type.constants'; @@ -16,6 +16,7 @@ const client = request(`http://localhost:${APP_PORT}`); describe('Granular settings permissions', () => { let customRoleId: string; let originalMemberRoleId: string; + const createdObjectMetadataIds: string[] = []; beforeAll(async () => { // Get the original Member role ID for restoration later @@ -123,54 +124,50 @@ describe('Granular settings permissions', () => { .post('/graphql') .set('Authorization', `Bearer ${APPLE_JANE_ADMIN_ACCESS_TOKEN}`) .send(deleteRoleQuery); + + for (const objectMetadataId of createdObjectMetadataIds) { + await updateOneObjectMetadata({ + expectToFail: false, + input: { + idToUpdate: objectMetadataId, + updatePayload: { + isActive: false, + }, + }, + }); + + await deleteOneObjectMetadata({ + input: { + idToDelete: objectMetadataId, + }, + expectToFail: false, + }); + } }); describe('Data Model Permissions', () => { it('should allow access to data model operations when user has DATA_MODEL setting permission', async () => { - // Test creating an object metadata (requires DATA_MODEL permission) - const { query: createObjectQuery, variables } = - createOneObjectMetadataQueryFactory({ - input: { - labelSingular: 'House', - labelPlural: 'Houses', - nameSingular: 'house', - namePlural: 'houses', - description: 'a house', - icon: 'IconHome', - }, - gqlFields: ` + const { data, errors } = await createOneObjectMetadata({ + input: { + labelSingular: 'House', + labelPlural: 'Houses', + nameSingular: 'house', + namePlural: 'houses', + description: 'a house', + icon: 'IconHome', + }, + gqlFields: ` id labelSingular labelPlural `, - }); + expectToFail: false, + }); - const response = await client - .post('/metadata') - .set('Authorization', `Bearer ${APPLE_JONY_MEMBER_ACCESS_TOKEN}`) - .send({ query: print(createObjectQuery), variables }); - - expect(response.status).toBe(200); - expect(response.body.errors).toBeUndefined(); - expect(response.body.data.createOneObject).toBeDefined(); - expect(response.body.data.createOneObject.labelSingular).toBe('House'); - - // Clean up - delete the created object - const { query: deleteObjectQuery, variables: deleteObjectVariables } = - deleteOneObjectMetadataQueryFactory({ - input: { - idToDelete: response.body.data.createOneObject.id, - }, - gqlFields: 'id', - }); - - await client - .post('/graphql') - .set('Authorization', `Bearer ${APPLE_JANE_ADMIN_ACCESS_TOKEN}`) - .send({ - query: print(deleteObjectQuery), - variables: deleteObjectVariables, - }); + createdObjectMetadataIds.push(data.createOneObject.id); + expect(errors).toBeUndefined(); + expect(data.createOneObject).toBeDefined(); + expect(data.createOneObject.labelSingular).toBe('House'); }); }); diff --git a/packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/view-filter-resolver.integration-spec.ts.snap b/packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/view-filter-resolver.integration-spec.ts.snap new file mode 100644 index 00000000000..e55fd2e4396 --- /dev/null +++ b/packages/twenty-server/test/integration/graphql/suites/view/__snapshots__/view-filter-resolver.integration-spec.ts.snap @@ -0,0 +1,34 @@ +// Jest Snapshot v1, https://goo.gl/fbAQLP + +exports[`View Filter Resolver deleteCoreViewFilter should throw an error when deleting non-existent view filter 1`] = ` +{ + "extensions": { + "code": "NOT_FOUND", + "userFriendlyMessage": "An error occurred.", + }, + "message": "View filter to delete not found", + "name": "NotFoundError", +} +`; + +exports[`View Filter Resolver destroyCoreViewFilter should throw an error when destroying non-existent view filter 1`] = ` +{ + "extensions": { + "code": "NOT_FOUND", + "userFriendlyMessage": "An error occurred.", + }, + "message": "View filter to destroy not found", + "name": "NotFoundError", +} +`; + +exports[`View Filter Resolver updateCoreViewFilter should throw an error when updating non-existent view filter 1`] = ` +{ + "extensions": { + "code": "NOT_FOUND", + "userFriendlyMessage": "An error occurred.", + }, + "message": "View filter to update not found", + "name": "NotFoundError", +} +`; diff --git a/packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap index 71b69241c45..9b9128a3ad5 100644 --- a/packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/failing-create-view-field-v2.integration-spec.ts.snap @@ -31,6 +31,7 @@ exports[`View Field Resolver - Failing Create Operation - v2 Should fail to crea "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -43,6 +44,7 @@ exports[`View Field Resolver - Failing Create Operation - v2 Should fail to crea "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -83,6 +85,7 @@ exports[`View Field Resolver - Failing Create Operation - v2 should fail to crea "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -95,6 +98,7 @@ exports[`View Field Resolver - Failing Create Operation - v2 should fail to crea "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -135,6 +139,7 @@ exports[`View Field Resolver - Failing Create Operation - v2 should fail to crea "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -147,6 +152,7 @@ exports[`View Field Resolver - Failing Create Operation - v2 should fail to crea "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", diff --git a/packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/object-identifier-update-side-effect-on-view-field.integration-spec.ts.snap b/packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/object-identifier-update-side-effect-on-view-field.integration-spec.ts.snap index 78621d30469..bae0827e700 100644 --- a/packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/object-identifier-update-side-effect-on-view-field.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/graphql/suites/view/view-field/__snapshots__/object-identifier-update-side-effect-on-view-field.integration-spec.ts.snap @@ -31,6 +31,7 @@ exports[`View Field Resolver - Successful object metadata identifier update side "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -43,6 +44,7 @@ exports[`View Field Resolver - Successful object metadata identifier update side "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -83,6 +85,7 @@ exports[`View Field Resolver - Successful object metadata identifier update side "type": "update_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -95,6 +98,7 @@ exports[`View Field Resolver - Successful object metadata identifier update side "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -133,6 +137,7 @@ exports[`View Field Resolver - Successful object metadata identifier update side "type": "delete_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -145,6 +150,7 @@ exports[`View Field Resolver - Successful object metadata identifier update side "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -185,6 +191,7 @@ exports[`View Field Resolver - Successful object metadata identifier update side "type": "update_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -197,6 +204,7 @@ exports[`View Field Resolver - Successful object metadata identifier update side "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -237,6 +245,7 @@ exports[`View Field Resolver - Successful object metadata identifier update side "type": "update_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -249,6 +258,7 @@ exports[`View Field Resolver - Successful object metadata identifier update side "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", diff --git a/packages/twenty-server/test/integration/graphql/suites/view/view-filter-resolver.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/view/view-filter-resolver.integration-spec.ts index e5df161eaab..a0a9dae58d4 100644 --- a/packages/twenty-server/test/integration/graphql/suites/view/view-filter-resolver.integration-spec.ts +++ b/packages/twenty-server/test/integration/graphql/suites/view/view-filter-resolver.integration-spec.ts @@ -1,31 +1,18 @@ -import { TEST_NOT_EXISTING_VIEW_FILTER_ID } from 'test/integration/constants/test-view-ids.constants'; -import { createViewFilterOperationFactory } from 'test/integration/graphql/utils/create-view-filter-operation-factory.util'; -import { deleteViewFilterOperationFactory } from 'test/integration/graphql/utils/delete-view-filter-operation-factory.util'; -import { destroyViewFilterOperationFactory } from 'test/integration/graphql/utils/destroy-view-filter-operation-factory.util'; -import { findViewFiltersOperationFactory } from 'test/integration/graphql/utils/find-view-filters-operation-factory.util'; -import { - assertGraphQLErrorResponse, - assertGraphQLSuccessfulResponse, -} from 'test/integration/graphql/utils/graphql-test-assertions.util'; -import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util'; -import { updateViewFilterOperationFactory } from 'test/integration/graphql/utils/update-view-filter-operation-factory.util'; -import { createViewFilterData } from 'test/integration/graphql/utils/view-data-factory.util'; +import { expectOneNotInternalServerErrorSnapshot } from 'test/integration/graphql/utils/expect-one-not-internal-server-error-snapshot.util'; import { createTestViewWithGraphQL } from 'test/integration/graphql/utils/view-graphql.util'; import { createOneFieldMetadata } from 'test/integration/metadata/suites/field-metadata/utils/create-one-field-metadata.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 { - assertViewFilterStructure, - cleanupViewRecords, -} from 'test/integration/utils/view-test.util'; +import { createOneCoreViewFilter } from 'test/integration/metadata/suites/view-filter/utils/create-one-core-view-filter.util'; +import { deleteOneCoreViewFilter } from 'test/integration/metadata/suites/view-filter/utils/delete-one-core-view-filter.util'; +import { destroyOneCoreViewFilter } from 'test/integration/metadata/suites/view-filter/utils/destroy-one-core-view-filter.util'; +import { findCoreViewFilters } from 'test/integration/metadata/suites/view-filter/utils/find-core-view-filters.util'; +import { updateOneCoreViewFilter } from 'test/integration/metadata/suites/view-filter/utils/update-one-core-view-filter.util'; +import { cleanupViewRecords } from 'test/integration/utils/view-test.util'; import { FieldMetadataType, ViewFilterOperand } from 'twenty-shared/types'; -import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; -import { - generateViewFilterExceptionMessage, - ViewFilterExceptionMessageKey, -} from 'src/engine/metadata-modules/view-filter/exceptions/view-filter.exception'; +const TEST_NOT_EXISTING_VIEW_FILTER_ID = '20202020-52c5-4152-8c09-76a845fb8ece'; describe('View Filter Resolver', () => { let testViewId: string; @@ -98,33 +85,34 @@ describe('View Filter Resolver', () => { describe('getCoreViewFilters', () => { it('should return empty array when no view filters exist', async () => { - const operation = findViewFiltersOperationFactory({ viewId: testViewId }); - const response = await makeGraphqlAPIRequest(operation); + const { data, errors } = await findCoreViewFilters({ + viewId: testViewId, + expectToFail: false, + }); - assertGraphQLSuccessfulResponse(response); - expect(response.body.data.getCoreViewFilters).toEqual([]); + expect(errors).toBeUndefined(); + expect(data.getCoreViewFilters).toEqual([]); }); it('should return view filters for a specific view', async () => { - const filterData = createViewFilterData(testViewId, { - operand: ViewFilterOperand.CONTAINS, - value: 'test', - fieldMetadataId: testFieldMetadataId, - }); - const createOperation = createViewFilterOperationFactory({ - data: filterData, + await createOneCoreViewFilter({ + input: { + fieldMetadataId: testFieldMetadataId, + viewId: testViewId, + operand: ViewFilterOperand.CONTAINS, + value: 'test', + }, + expectToFail: false, }); - await makeGraphqlAPIRequest(createOperation); - - const getOperation = findViewFiltersOperationFactory({ + const { data, errors } = await findCoreViewFilters({ viewId: testViewId, + expectToFail: false, }); - const response = await makeGraphqlAPIRequest(getOperation); - assertGraphQLSuccessfulResponse(response); - expect(response.body.data.getCoreViewFilters).toHaveLength(1); - assertViewFilterStructure(response.body.data.getCoreViewFilters[0], { + expect(errors).toBeUndefined(); + expect(data.getCoreViewFilters).toHaveLength(1); + expect(data.getCoreViewFilters[0]).toMatchObject({ fieldMetadataId: testFieldMetadataId, operand: ViewFilterOperand.CONTAINS, value: 'test', @@ -135,17 +123,18 @@ describe('View Filter Resolver', () => { describe('createCoreViewFilter', () => { it('should create a new view filter with string value', async () => { - const filterData = createViewFilterData(testViewId, { - operand: ViewFilterOperand.IS, - value: 'test value', - fieldMetadataId: testFieldMetadataId, + const { data, errors } = await createOneCoreViewFilter({ + input: { + fieldMetadataId: testFieldMetadataId, + viewId: testViewId, + operand: ViewFilterOperand.IS, + value: 'test value', + }, + expectToFail: false, }); - const operation = createViewFilterOperationFactory({ data: filterData }); - const response = await makeGraphqlAPIRequest(operation); - - assertGraphQLSuccessfulResponse(response); - assertViewFilterStructure(response.body.data.createCoreViewFilter, { + expect(errors).toBeUndefined(); + expect(data.createCoreViewFilter).toMatchObject({ fieldMetadataId: testFieldMetadataId, operand: ViewFilterOperand.IS, value: 'test value', @@ -154,17 +143,18 @@ describe('View Filter Resolver', () => { }); it('should create a view filter with numeric value', async () => { - const filterData = createViewFilterData(testViewId, { - operand: ViewFilterOperand.GREATER_THAN_OR_EQUAL, - value: 100, - fieldMetadataId: testFieldMetadataId, + const { data, errors } = await createOneCoreViewFilter({ + input: { + fieldMetadataId: testFieldMetadataId, + viewId: testViewId, + operand: ViewFilterOperand.GREATER_THAN_OR_EQUAL, + value: 100, + }, + expectToFail: false, }); - const operation = createViewFilterOperationFactory({ data: filterData }); - const response = await makeGraphqlAPIRequest(operation); - - assertGraphQLSuccessfulResponse(response); - assertViewFilterStructure(response.body.data.createCoreViewFilter, { + expect(errors).toBeUndefined(); + expect(data.createCoreViewFilter).toMatchObject({ fieldMetadataId: testFieldMetadataId, operand: ViewFilterOperand.GREATER_THAN_OR_EQUAL, value: 100, @@ -173,18 +163,18 @@ describe('View Filter Resolver', () => { }); it('should create a view filter with boolean value', async () => { - const operation = createViewFilterOperationFactory({ - data: createViewFilterData(testViewId, { + const { data, errors } = await createOneCoreViewFilter({ + input: { + fieldMetadataId: testFieldMetadataId, + viewId: testViewId, operand: ViewFilterOperand.IS, value: true, - fieldMetadataId: testFieldMetadataId, - }), + }, + expectToFail: false, }); - const response = await makeGraphqlAPIRequest(operation); - - assertGraphQLSuccessfulResponse(response); - assertViewFilterStructure(response.body.data.createCoreViewFilter, { + expect(errors).toBeUndefined(); + expect(data.createCoreViewFilter).toMatchObject({ fieldMetadataId: testFieldMetadataId, operand: ViewFilterOperand.IS, value: true, @@ -195,30 +185,31 @@ describe('View Filter Resolver', () => { describe('updateCoreViewFilter', () => { it('should update an existing view filter', async () => { - const createOperation = createViewFilterOperationFactory({ - data: createViewFilterData(testViewId, { + const { data: createData } = await createOneCoreViewFilter({ + input: { + fieldMetadataId: testFieldMetadataId, + viewId: testViewId, operand: ViewFilterOperand.CONTAINS, value: 'original', - fieldMetadataId: testFieldMetadataId, - }), - }); - - const createResponse = await makeGraphqlAPIRequest(createOperation); - - const viewFilterId = createResponse.body.data.createCoreViewFilter.id; - - const updateOperation = updateViewFilterOperationFactory({ - viewFilterId: viewFilterId, - data: { - operand: ViewFilterOperand.DOES_NOT_CONTAIN, - value: 'updated', }, + expectToFail: false, }); - const response = await makeGraphqlAPIRequest(updateOperation); + const viewFilterId = createData.createCoreViewFilter.id; - assertGraphQLSuccessfulResponse(response); - assertViewFilterStructure(response.body.data.updateCoreViewFilter, { + const { data, errors } = await updateOneCoreViewFilter({ + input: { + id: viewFilterId, + update: { + operand: ViewFilterOperand.DOES_NOT_CONTAIN, + value: 'updated', + }, + }, + expectToFail: false, + }); + + expect(errors).toBeUndefined(); + expect(data.updateCoreViewFilter).toMatchObject({ id: viewFilterId, operand: ViewFilterOperand.DOES_NOT_CONTAIN, value: 'updated', @@ -226,101 +217,92 @@ describe('View Filter Resolver', () => { }); it('should throw an error when updating non-existent view filter', async () => { - const operation = updateViewFilterOperationFactory({ - viewFilterId: TEST_NOT_EXISTING_VIEW_FILTER_ID, + const { errors } = await updateOneCoreViewFilter({ + input: { + id: TEST_NOT_EXISTING_VIEW_FILTER_ID, + update: {}, + }, + expectToFail: true, }); - const response = await makeGraphqlAPIRequest(operation); - assertGraphQLErrorResponse( - response, - ErrorCode.NOT_FOUND, - generateViewFilterExceptionMessage( - ViewFilterExceptionMessageKey.VIEW_FILTER_NOT_FOUND, - TEST_NOT_EXISTING_VIEW_FILTER_ID, - ), - ); + expectOneNotInternalServerErrorSnapshot({ errors }); }); }); describe('deleteCoreViewFilter', () => { it('should delete an existing view filter', async () => { - const createOperation = createViewFilterOperationFactory({ - data: createViewFilterData(testViewId, { + const { data: createData } = await createOneCoreViewFilter({ + input: { + fieldMetadataId: testFieldMetadataId, + viewId: testViewId, operand: ViewFilterOperand.CONTAINS, value: 'to delete', - fieldMetadataId: testFieldMetadataId, - }), + }, + expectToFail: false, }); - const createResponse = await makeGraphqlAPIRequest(createOperation); + const viewFilterId = createData.createCoreViewFilter.id; - const viewFilterId = createResponse.body.data.createCoreViewFilter.id; - - const deleteOperation = deleteViewFilterOperationFactory({ - viewFilterId: viewFilterId, + const { data, errors } = await deleteOneCoreViewFilter({ + input: { id: viewFilterId }, + expectToFail: false, }); - const response = await makeGraphqlAPIRequest(deleteOperation); - - assertGraphQLSuccessfulResponse(response); - expect(response.body.data.deleteCoreViewFilter).toBe(true); + expect(errors).toBeUndefined(); + expect(data.deleteCoreViewFilter).toMatchObject({ + id: viewFilterId, + }); + expect(data.deleteCoreViewFilter.deletedAt).toBeDefined(); }); it('should throw an error when deleting non-existent view filter', async () => { - const operation = deleteViewFilterOperationFactory({ - viewFilterId: TEST_NOT_EXISTING_VIEW_FILTER_ID, + const { errors } = await deleteOneCoreViewFilter({ + input: { id: TEST_NOT_EXISTING_VIEW_FILTER_ID }, + expectToFail: true, }); - const response = await makeGraphqlAPIRequest(operation); - assertGraphQLErrorResponse( - response, - ErrorCode.NOT_FOUND, - generateViewFilterExceptionMessage( - ViewFilterExceptionMessageKey.VIEW_FILTER_NOT_FOUND, - TEST_NOT_EXISTING_VIEW_FILTER_ID, - ), - ); + expectOneNotInternalServerErrorSnapshot({ errors }); }); }); describe('destroyCoreViewFilter', () => { it('should destroy an existing view filter', async () => { - const createOperation = createViewFilterOperationFactory({ - data: createViewFilterData(testViewId, { + const { data: createData } = await createOneCoreViewFilter({ + input: { + fieldMetadataId: testFieldMetadataId, + viewId: testViewId, operand: ViewFilterOperand.CONTAINS, value: 'to destroy', - fieldMetadataId: testFieldMetadataId, - }), + }, + expectToFail: false, }); - const createResponse = await makeGraphqlAPIRequest(createOperation); + const viewFilterId = createData.createCoreViewFilter.id; - const viewFilterId = createResponse.body.data.createCoreViewFilter.id; - - const destroyOperation = destroyViewFilterOperationFactory({ - viewFilterId: viewFilterId, + await deleteOneCoreViewFilter({ + input: { + id: viewFilterId, + }, + expectToFail: false, + }); + const { data, errors } = await destroyOneCoreViewFilter({ + input: { id: viewFilterId }, + expectToFail: false, }); - const response = await makeGraphqlAPIRequest(destroyOperation); - - assertGraphQLSuccessfulResponse(response); - expect(response.body.data.destroyCoreViewFilter).toBe(true); + expect(errors).toBeUndefined(); + expect(data.destroyCoreViewFilter).toMatchObject({ + id: viewFilterId, + }); }); it('should throw an error when destroying non-existent view filter', async () => { - const operation = destroyViewFilterOperationFactory({ - viewFilterId: TEST_NOT_EXISTING_VIEW_FILTER_ID, + const { errors } = await destroyOneCoreViewFilter({ + input: { id: TEST_NOT_EXISTING_VIEW_FILTER_ID }, + expectToFail: true, }); - const response = await makeGraphqlAPIRequest(operation); - assertGraphQLErrorResponse( - response, - ErrorCode.NOT_FOUND, - generateViewFilterExceptionMessage( - ViewFilterExceptionMessageKey.VIEW_FILTER_NOT_FOUND, - TEST_NOT_EXISTING_VIEW_FILTER_ID, - ), - ); + expectOneNotInternalServerErrorSnapshot({ errors }); }); }); }); diff --git a/packages/twenty-server/test/integration/graphql/utils/create-view-filter-operation-factory.util.ts b/packages/twenty-server/test/integration/graphql/utils/create-view-filter-operation-factory.util.ts deleted file mode 100644 index d76db26f401..00000000000 --- a/packages/twenty-server/test/integration/graphql/utils/create-view-filter-operation-factory.util.ts +++ /dev/null @@ -1,25 +0,0 @@ -import gql from 'graphql-tag'; -import { VIEW_FILTER_GQL_FIELDS } from 'test/integration/constants/view-gql-fields.constants'; - -import { type ViewFilterEntity } from 'src/engine/metadata-modules/view-filter/entities/view-filter.entity'; - -type CreateViewFilterOperationFactoryParams = { - gqlFields?: string; - data?: Partial; -}; - -export const createViewFilterOperationFactory = ({ - gqlFields = VIEW_FILTER_GQL_FIELDS, - data = {}, -}: CreateViewFilterOperationFactoryParams = {}) => ({ - query: gql` - mutation CreateCoreViewFilter($input: CreateViewFilterInput!) { - createCoreViewFilter(input: $input) { - ${gqlFields} - } - } - `, - variables: { - input: data, - }, -}); diff --git a/packages/twenty-server/test/integration/graphql/utils/delete-view-filter-operation-factory.util.ts b/packages/twenty-server/test/integration/graphql/utils/delete-view-filter-operation-factory.util.ts deleted file mode 100644 index 12e585e8b2d..00000000000 --- a/packages/twenty-server/test/integration/graphql/utils/delete-view-filter-operation-factory.util.ts +++ /dev/null @@ -1,16 +0,0 @@ -import gql from 'graphql-tag'; - -export const deleteViewFilterOperationFactory = ({ - viewFilterId, -}: { - viewFilterId: string; -}) => ({ - query: gql` - mutation DeleteCoreViewFilter($id: String!) { - deleteCoreViewFilter(id: $id) - } - `, - variables: { - id: viewFilterId, - }, -}); diff --git a/packages/twenty-server/test/integration/graphql/utils/destroy-view-filter-operation-factory.util.ts b/packages/twenty-server/test/integration/graphql/utils/destroy-view-filter-operation-factory.util.ts deleted file mode 100644 index 90b12fce247..00000000000 --- a/packages/twenty-server/test/integration/graphql/utils/destroy-view-filter-operation-factory.util.ts +++ /dev/null @@ -1,16 +0,0 @@ -import gql from 'graphql-tag'; - -export const destroyViewFilterOperationFactory = ({ - viewFilterId, -}: { - viewFilterId: string; -}) => ({ - query: gql` - mutation DestroyCoreViewFilter($id: String!) { - destroyCoreViewFilter(id: $id) - } - `, - variables: { - id: viewFilterId, - }, -}); diff --git a/packages/twenty-server/test/integration/graphql/utils/update-view-filter-operation-factory.util.ts b/packages/twenty-server/test/integration/graphql/utils/update-view-filter-operation-factory.util.ts deleted file mode 100644 index de4a4e9adc0..00000000000 --- a/packages/twenty-server/test/integration/graphql/utils/update-view-filter-operation-factory.util.ts +++ /dev/null @@ -1,24 +0,0 @@ -import gql from 'graphql-tag'; -import { VIEW_FILTER_GQL_FIELDS } from 'test/integration/constants/view-gql-fields.constants'; - -export const updateViewFilterOperationFactory = ({ - gqlFields = VIEW_FILTER_GQL_FIELDS, - viewFilterId, - data = {}, -}: { - gqlFields?: string; - viewFilterId: string; - data?: object; -}) => ({ - query: gql` - mutation UpdateCoreViewFilter($id: String!, $input: UpdateViewFilterInput!) { - updateCoreViewFilter(id: $id, input: $input) { - ${gqlFields} - } - } - `, - variables: { - id: viewFilterId, - input: data, - }, -}); diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/create-one-field-metadata.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/create-one-field-metadata.integration-spec.ts.snap index 30fdb2e1d3f..02f8d57d3ef 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/create-one-field-metadata.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/create-one-field-metadata.integration-spec.ts.snap @@ -32,6 +32,7 @@ exports[`createOne FieldMetadataService name/label sync should return an error w "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -44,6 +45,7 @@ exports[`createOne FieldMetadataService name/label sync should return an error w "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/update-one-field-metadata.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/update-one-field-metadata.integration-spec.ts.snap index c183049e28a..2ee263edd31 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/update-one-field-metadata.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/__snapshots__/update-one-field-metadata.integration-spec.ts.snap @@ -32,6 +32,7 @@ exports[`updateOne failing update should not update a field name if it is not sy "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -44,6 +45,7 @@ exports[`updateOne failing update should not update a field name if it is not sy "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -92,6 +94,7 @@ exports[`updateOne failing update should throw if the field name is not availabl "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -104,6 +107,7 @@ exports[`updateOne failing update should throw if the field name is not availabl "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-create-one-field-metadata-enum-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-create-one-field-metadata-enum-v2.integration-spec.ts.snap index e43814b19d9..2d74fc2b225 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-create-one-field-metadata-enum-v2.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-create-one-field-metadata-enum-v2.integration-spec.ts.snap @@ -33,6 +33,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -45,6 +46,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -88,6 +90,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -100,6 +103,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -142,6 +146,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -154,6 +159,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -211,6 +217,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -223,6 +230,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -280,6 +288,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -292,6 +301,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -349,6 +359,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -361,6 +372,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -418,6 +430,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -430,6 +443,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -472,6 +486,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -484,6 +499,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -527,6 +543,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -539,6 +556,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -586,6 +604,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -598,6 +617,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -640,6 +660,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -652,6 +673,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -695,6 +717,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -707,6 +730,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -749,6 +773,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -761,6 +786,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -818,6 +844,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -830,6 +857,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -872,6 +900,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -884,6 +913,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -926,6 +956,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -938,6 +969,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -981,6 +1013,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -993,6 +1026,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1036,6 +1070,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1048,6 +1083,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1090,6 +1126,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1102,6 +1139,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1145,6 +1183,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1157,6 +1196,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1199,6 +1239,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1211,6 +1252,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1258,6 +1300,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1270,6 +1313,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1312,6 +1356,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1324,6 +1369,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1367,6 +1413,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1379,6 +1426,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1421,6 +1469,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1433,6 +1482,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1480,6 +1530,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1492,6 +1543,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1534,6 +1586,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1546,6 +1599,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1589,6 +1643,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1601,6 +1656,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1643,6 +1699,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1655,6 +1712,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1702,6 +1760,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1714,6 +1773,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1756,6 +1816,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1768,6 +1829,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1810,6 +1872,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1822,6 +1885,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1869,6 +1933,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1881,6 +1946,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1923,6 +1989,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1935,6 +2002,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1977,6 +2045,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1989,6 +2058,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2032,6 +2102,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2044,6 +2115,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2086,6 +2158,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2098,6 +2171,7 @@ exports[`Failing create field metadata MULTI_SELECT tests suite v2 Create should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2145,6 +2219,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2157,6 +2232,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2199,6 +2275,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2211,6 +2288,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2253,6 +2331,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2265,6 +2344,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2322,6 +2402,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2334,6 +2415,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2391,6 +2473,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2403,6 +2486,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2460,6 +2544,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2472,6 +2557,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2529,6 +2615,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2541,6 +2628,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2584,6 +2672,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2596,6 +2685,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2643,6 +2733,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2655,6 +2746,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2697,6 +2789,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2709,6 +2802,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2752,6 +2846,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2764,6 +2859,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2806,6 +2902,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2818,6 +2915,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2860,6 +2958,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2872,6 +2971,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2914,6 +3014,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2926,6 +3027,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2969,6 +3071,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2981,6 +3084,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3023,6 +3127,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3035,6 +3140,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3078,6 +3184,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3090,6 +3197,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3132,6 +3240,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3144,6 +3253,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3191,6 +3301,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3203,6 +3314,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3245,6 +3357,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3257,6 +3370,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3300,6 +3414,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3312,6 +3427,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3354,6 +3470,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3366,6 +3483,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3413,6 +3531,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3425,6 +3544,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3467,6 +3587,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3479,6 +3600,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3522,6 +3644,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3534,6 +3657,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3576,6 +3700,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3588,6 +3713,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3635,6 +3761,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3647,6 +3774,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3689,6 +3817,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3701,6 +3830,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3743,6 +3873,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3755,6 +3886,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3802,6 +3934,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3814,6 +3947,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3856,6 +3990,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3868,6 +4003,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3910,6 +4046,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3922,6 +4059,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3965,6 +4103,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3977,6 +4116,7 @@ exports[`Failing create field metadata SELECT tests suite v2 Create should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-update-one-enum-field-metadata-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-update-one-enum-field-metadata-v2.integration-spec.ts.snap index d4eb844a58b..e73bb229dd1 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-update-one-enum-field-metadata-v2.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/enum/__snapshots__/failing-update-one-enum-field-metadata-v2.integration-spec.ts.snap @@ -33,6 +33,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -45,6 +46,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -88,6 +90,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -100,6 +103,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -142,6 +146,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -154,6 +159,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -211,6 +217,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -223,6 +230,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -280,6 +288,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -292,6 +301,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -349,6 +359,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -361,6 +372,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -418,6 +430,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -430,6 +443,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -472,6 +486,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -484,6 +499,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -527,6 +543,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -539,6 +556,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -586,6 +604,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -598,6 +617,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -640,6 +660,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -652,6 +673,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -695,6 +717,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -707,6 +730,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -749,6 +773,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -761,6 +786,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -818,6 +844,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -830,6 +857,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -872,6 +900,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -884,6 +913,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -926,6 +956,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -938,6 +969,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -981,6 +1013,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -993,6 +1026,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1036,6 +1070,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1048,6 +1083,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1090,6 +1126,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1102,6 +1139,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1145,6 +1183,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1157,6 +1196,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1199,6 +1239,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1211,6 +1252,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1258,6 +1300,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1270,6 +1313,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1312,6 +1356,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1324,6 +1369,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1366,6 +1412,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1378,6 +1425,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1425,6 +1473,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1437,6 +1486,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1479,6 +1529,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1491,6 +1542,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1534,6 +1586,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1546,6 +1599,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1588,6 +1642,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1600,6 +1655,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1647,6 +1703,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1659,6 +1716,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1701,6 +1759,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1713,6 +1772,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1755,6 +1815,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1767,6 +1828,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1814,6 +1876,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1826,6 +1889,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1868,6 +1932,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1880,6 +1945,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1922,6 +1988,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1934,6 +2001,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1976,6 +2044,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1988,6 +2057,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2030,6 +2100,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2042,6 +2113,7 @@ exports[`Failing update field metadata MULTI_SELECT tests suite v2 Update should "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2089,6 +2161,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2101,6 +2174,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2143,6 +2217,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2155,6 +2230,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2197,6 +2273,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2209,6 +2286,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2266,6 +2344,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2278,6 +2357,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2335,6 +2415,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2347,6 +2428,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2404,6 +2486,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2416,6 +2499,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2473,6 +2557,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2485,6 +2570,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2528,6 +2614,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2540,6 +2627,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2587,6 +2675,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2599,6 +2688,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2641,6 +2731,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2653,6 +2744,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2696,6 +2788,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2708,6 +2801,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2750,6 +2844,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2762,6 +2857,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2804,6 +2900,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2816,6 +2913,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2858,6 +2956,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2870,6 +2969,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2913,6 +3013,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2925,6 +3026,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2967,6 +3069,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2979,6 +3082,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3022,6 +3126,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3034,6 +3139,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3076,6 +3182,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3088,6 +3195,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3135,6 +3243,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3147,6 +3256,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3189,6 +3299,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3201,6 +3312,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3243,6 +3355,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3255,6 +3368,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3302,6 +3416,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3314,6 +3429,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3356,6 +3472,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3368,6 +3485,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3411,6 +3529,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3423,6 +3542,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3465,6 +3585,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3477,6 +3598,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3524,6 +3646,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3536,6 +3659,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3578,6 +3702,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3590,6 +3715,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3632,6 +3758,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3644,6 +3771,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3691,6 +3819,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3703,6 +3832,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3745,6 +3875,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3757,6 +3888,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3799,6 +3931,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3811,6 +3944,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3853,6 +3987,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3865,6 +4000,7 @@ exports[`Failing update field metadata SELECT tests suite v2 Update should fail "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/morph-relation/__snapshots__/failing-create-one-field-metadata-morph-relation-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/morph-relation/__snapshots__/failing-create-one-field-metadata-morph-relation-v2.integration-spec.ts.snap index 88f83a5f657..d579b718c61 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/morph-relation/__snapshots__/failing-create-one-field-metadata-morph-relation-v2.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/morph-relation/__snapshots__/failing-create-one-field-metadata-morph-relation-v2.integration-spec.ts.snap @@ -80,6 +80,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 Morh re "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -92,6 +93,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 Morh re "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -133,6 +135,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 Morh re "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -145,6 +148,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 Morh re "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -180,6 +184,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -192,6 +197,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -227,6 +233,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -239,6 +246,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -302,6 +310,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -314,6 +323,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -371,6 +381,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -383,6 +394,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -440,6 +452,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -452,6 +465,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -515,6 +529,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -527,6 +542,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -570,6 +586,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -582,6 +599,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -625,6 +643,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -637,6 +656,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -679,6 +699,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -691,6 +712,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -726,6 +748,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -738,6 +761,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -773,6 +797,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -785,6 +810,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -820,6 +846,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -832,6 +859,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -870,6 +898,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -882,6 +911,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -918,6 +948,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -930,6 +961,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -965,6 +997,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -977,6 +1010,7 @@ exports[`failing createOne FieldMetadataService morph relation fields v2 it shou "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/__snapshots__/failing-field-metadata-relation-creation.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/__snapshots__/failing-field-metadata-relation-creation.integration-spec.ts.snap index 789bab43bee..0e0b3a2fcc7 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/__snapshots__/failing-field-metadata-relation-creation.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/__snapshots__/failing-field-metadata-relation-creation.integration-spec.ts.snap @@ -33,6 +33,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -45,6 +46,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -88,6 +90,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -100,6 +103,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -149,6 +153,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -161,6 +166,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -204,6 +210,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -216,6 +223,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -265,6 +273,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -277,6 +286,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -320,6 +330,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -332,6 +343,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -375,6 +387,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -387,6 +400,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -429,6 +443,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -441,6 +456,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE (rela "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -516,6 +532,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE when "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -528,6 +545,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE when "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -571,6 +589,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE when "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -583,6 +602,7 @@ exports[`Field metadata relation creation should fail relation MANY_TO_ONE when "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -642,6 +662,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -654,6 +675,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -713,6 +735,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -725,6 +748,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -790,6 +814,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -802,6 +827,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -861,6 +887,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -873,6 +900,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -938,6 +966,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -950,6 +979,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -993,6 +1023,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1005,6 +1036,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1048,6 +1080,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1060,6 +1093,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1102,6 +1136,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1114,6 +1149,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY (rela "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1189,6 +1225,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY when "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1201,6 +1238,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY when "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1244,6 +1282,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY when "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1256,6 +1295,7 @@ exports[`Field metadata relation creation should fail relation ONE_TO_MANY when "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", diff --git a/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/__snapshots__/failing-field-metadata-relation-update.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/__snapshots__/failing-field-metadata-relation-update.integration-spec.ts.snap index 65553b4cc3b..0a4a420e70f 100644 --- a/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/__snapshots__/failing-field-metadata-relation-update.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/field-metadata/relation/__snapshots__/failing-field-metadata-relation-update.integration-spec.ts.snap @@ -48,6 +48,7 @@ exports[`Field metadata relation update should fail relation when name is change "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -60,6 +61,7 @@ exports[`Field metadata relation update should fail relation when name is change "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -142,6 +144,7 @@ exports[`Field metadata relation update should fail relation when name is not in "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -154,6 +157,7 @@ exports[`Field metadata relation update should fail relation when name is not in "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-create-one-object-metadata-v2.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-create-one-object-metadata-v2.integration-spec.ts.snap index 26db3207ee7..ed4b661d8b8 100644 --- a/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-create-one-object-metadata-v2.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-create-one-object-metadata-v2.integration-spec.ts.snap @@ -588,6 +588,7 @@ exports[`Object metadata creation should fail v2 when labelPlural contains only "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -600,6 +601,7 @@ exports[`Object metadata creation should fail v2 when labelPlural contains only "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1197,6 +1199,7 @@ exports[`Object metadata creation should fail v2 when labelPlural exceeds maximu "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1209,6 +1212,7 @@ exports[`Object metadata creation should fail v2 when labelPlural exceeds maximu "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -1806,6 +1810,7 @@ exports[`Object metadata creation should fail v2 when labelPlural is empty 1`] = "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -1818,6 +1823,7 @@ exports[`Object metadata creation should fail v2 when labelPlural is empty 1`] = "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -2415,6 +2421,7 @@ exports[`Object metadata creation should fail v2 when labelSingular contains onl "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -2427,6 +2434,7 @@ exports[`Object metadata creation should fail v2 when labelSingular contains onl "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3024,6 +3032,7 @@ exports[`Object metadata creation should fail v2 when labelSingular exceeds maxi "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3036,6 +3045,7 @@ exports[`Object metadata creation should fail v2 when labelSingular exceeds maxi "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -3633,6 +3643,7 @@ exports[`Object metadata creation should fail v2 when labelSingular is empty 1`] "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -3645,6 +3656,7 @@ exports[`Object metadata creation should fail v2 when labelSingular is empty 1`] "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -4243,6 +4255,7 @@ exports[`Object metadata creation should fail v2 when labels are identical 1`] = "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -4255,6 +4268,7 @@ exports[`Object metadata creation should fail v2 when labels are identical 1`] = "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -4853,6 +4867,7 @@ exports[`Object metadata creation should fail v2 when labels with whitespaces re "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -4865,6 +4880,7 @@ exports[`Object metadata creation should fail v2 when labels with whitespaces re "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -5492,6 +5508,7 @@ exports[`Object metadata creation should fail v2 when name exceeds maximum lengt "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -5504,6 +5521,7 @@ exports[`Object metadata creation should fail v2 when name exceeds maximum lengt "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -6101,6 +6119,7 @@ exports[`Object metadata creation should fail v2 when namePlural has invalid cha "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -6113,6 +6132,7 @@ exports[`Object metadata creation should fail v2 when namePlural has invalid cha "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -6710,6 +6730,7 @@ exports[`Object metadata creation should fail v2 when namePlural is a reserved k "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -6722,6 +6743,7 @@ exports[`Object metadata creation should fail v2 when namePlural is a reserved k "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -7324,6 +7346,7 @@ exports[`Object metadata creation should fail v2 when namePlural is an empty str "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -7336,6 +7359,7 @@ exports[`Object metadata creation should fail v2 when namePlural is an empty str "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -7938,6 +7962,7 @@ exports[`Object metadata creation should fail v2 when namePlural is not camelCas "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -7950,6 +7975,7 @@ exports[`Object metadata creation should fail v2 when namePlural is not camelCas "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -8612,6 +8638,7 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -8624,6 +8651,7 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -9286,6 +9314,7 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -9298,6 +9327,7 @@ exports[`Object metadata creation should fail v2 when nameSingular contains only "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -9925,6 +9955,7 @@ exports[`Object metadata creation should fail v2 when nameSingular has invalid c "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -9937,6 +9968,7 @@ exports[`Object metadata creation should fail v2 when nameSingular has invalid c "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -10564,6 +10596,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is a reserved "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -10576,6 +10609,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is a reserved "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -11238,6 +11272,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is an empty s "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -11250,6 +11285,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is an empty s "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -11912,6 +11948,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is not camelC "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -11924,6 +11961,7 @@ exports[`Object metadata creation should fail v2 when nameSingular is not camelC "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -12522,6 +12560,7 @@ exports[`Object metadata creation should fail v2 when names are identical 1`] = "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -12534,6 +12573,7 @@ exports[`Object metadata creation should fail v2 when names are identical 1`] = "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -13132,6 +13172,7 @@ exports[`Object metadata creation should fail v2 when names with whitespaces res "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -13144,6 +13185,7 @@ exports[`Object metadata creation should fail v2 when names with whitespaces res "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", diff --git a/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-update-one-object-metadata.integration-spec.ts.snap b/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-update-one-object-metadata.integration-spec.ts.snap index f4c9cafd7c6..797c3e14605 100644 --- a/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-update-one-object-metadata.integration-spec.ts.snap +++ b/packages/twenty-server/test/integration/metadata/suites/object-metadata/__snapshots__/failing-update-one-object-metadata.integration-spec.ts.snap @@ -49,6 +49,7 @@ exports[`Object metadata update should fail when labelIdentifier is not a TEXT o "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -61,6 +62,7 @@ exports[`Object metadata update should fail when labelIdentifier is not a TEXT o "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -125,6 +127,7 @@ exports[`Object metadata update should fail when labelIdentifier is not a known "type": "create_view_field", }, ], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -137,6 +140,7 @@ exports[`Object metadata update should fail when labelIdentifier is not a known "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", @@ -195,6 +199,7 @@ exports[`Object metadata update should fail when labelIdentifier is null 1`] = ` "serverlessFunction": [], "view": [], "viewField": [], + "viewFilter": [], }, "message": "Validation failed for 0 object(s) and 0 field(s)", "summary": { @@ -207,6 +212,7 @@ exports[`Object metadata update should fail when labelIdentifier is null 1`] = ` "invalidServerlessFunction": 0, "invalidView": 0, "invalidViewField": 0, + "invalidViewFilter": 0, "totalErrors": 0, }, "userFriendlyMessage": "Validation failed for 0 object(s) and 0 field(s)", diff --git a/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/create-core-view-filter-query-factory.util.ts b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/create-core-view-filter-query-factory.util.ts new file mode 100644 index 00000000000..c7020584cc3 --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/create-core-view-filter-query-factory.util.ts @@ -0,0 +1,21 @@ +import gql from 'graphql-tag'; +import { VIEW_FILTER_GQL_FIELDS } from 'test/integration/constants/view-gql-fields.constants'; +import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type'; + +import { type CreateViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/create-view-filter.input'; + +export const createCoreViewFilterQueryFactory = ({ + gqlFields = VIEW_FILTER_GQL_FIELDS, + input, +}: PerformMetadataQueryParams) => ({ + query: gql` + mutation CreateCoreViewFilter($input: CreateViewFilterInput!) { + createCoreViewFilter(input: $input) { + ${gqlFields} + } + } + `, + variables: { + input, + }, +}); diff --git a/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/create-one-core-view-filter.util.ts b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/create-one-core-view-filter.util.ts new file mode 100644 index 00000000000..86c97b22b7f --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/create-one-core-view-filter.util.ts @@ -0,0 +1,40 @@ +import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util'; +import { createCoreViewFilterQueryFactory } from 'test/integration/metadata/suites/view-filter/utils/create-core-view-filter-query-factory.util'; +import { type CommonResponseBody } from 'test/integration/metadata/types/common-response-body.type'; +import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.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 CreateViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/create-view-filter.input'; +import { type ViewFilterDTO } from 'src/engine/metadata-modules/view-filter/dtos/view-filter.dto'; + +export const createOneCoreViewFilter = async ({ + input, + gqlFields, + expectToFail, +}: PerformMetadataQueryParams): CommonResponseBody<{ + createCoreViewFilter: ViewFilterDTO; +}> => { + const graphqlOperation = createCoreViewFilterQueryFactory({ + input, + gqlFields, + }); + + const response = await makeMetadataAPIRequest(graphqlOperation); + + if (expectToFail === true) { + warnIfNoErrorButExpectedToFail({ + response, + errorMessage: 'View Filter creation should have failed but did not', + }); + } + + if (expectToFail === false) { + warnIfErrorButNotExpectedToFail({ + response, + errorMessage: 'View Filter creation has failed but should not', + }); + } + + return { data: response.body.data, errors: response.body.errors }; +}; diff --git a/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/delete-core-view-filter-query-factory.util.ts b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/delete-core-view-filter-query-factory.util.ts new file mode 100644 index 00000000000..289798fdeed --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/delete-core-view-filter-query-factory.util.ts @@ -0,0 +1,21 @@ +import gql from 'graphql-tag'; +import { VIEW_FILTER_GQL_FIELDS } from 'test/integration/constants/view-gql-fields.constants'; +import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type'; + +import { type DeleteViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/delete-view-filter.input'; + +export const deleteCoreViewFilterQueryFactory = ({ + gqlFields = VIEW_FILTER_GQL_FIELDS, + input, +}: PerformMetadataQueryParams) => ({ + query: gql` + mutation DeleteCoreViewFilter($input: DeleteViewFilterInput!) { + deleteCoreViewFilter(input: $input) { + ${gqlFields} + } + } + `, + variables: { + input, + }, +}); diff --git a/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/delete-one-core-view-filter.util.ts b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/delete-one-core-view-filter.util.ts new file mode 100644 index 00000000000..ad0dffe2ff6 --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/delete-one-core-view-filter.util.ts @@ -0,0 +1,40 @@ +import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util'; +import { deleteCoreViewFilterQueryFactory } from 'test/integration/metadata/suites/view-filter/utils/delete-core-view-filter-query-factory.util'; +import { type CommonResponseBody } from 'test/integration/metadata/types/common-response-body.type'; +import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.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 DeleteViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/delete-view-filter.input'; +import { type ViewFilterDTO } from 'src/engine/metadata-modules/view-filter/dtos/view-filter.dto'; + +export const deleteOneCoreViewFilter = async ({ + input, + gqlFields, + expectToFail, +}: PerformMetadataQueryParams): CommonResponseBody<{ + deleteCoreViewFilter: ViewFilterDTO; +}> => { + const graphqlOperation = deleteCoreViewFilterQueryFactory({ + input, + gqlFields, + }); + + const response = await makeMetadataAPIRequest(graphqlOperation); + + if (expectToFail === true) { + warnIfNoErrorButExpectedToFail({ + response, + errorMessage: 'View Filter deletion should have failed but did not', + }); + } + + if (expectToFail === false) { + warnIfErrorButNotExpectedToFail({ + response, + errorMessage: 'View Filter deletion has failed but should not', + }); + } + + return { data: response.body.data, errors: response.body.errors }; +}; diff --git a/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/destroy-core-view-filter-query-factory.util.ts b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/destroy-core-view-filter-query-factory.util.ts new file mode 100644 index 00000000000..95e6eac6248 --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/destroy-core-view-filter-query-factory.util.ts @@ -0,0 +1,21 @@ +import gql from 'graphql-tag'; +import { VIEW_FILTER_GQL_FIELDS } from 'test/integration/constants/view-gql-fields.constants'; +import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type'; + +import { type DestroyViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/destroy-view-filter.input'; + +export const destroyCoreViewFilterQueryFactory = ({ + gqlFields = VIEW_FILTER_GQL_FIELDS, + input, +}: PerformMetadataQueryParams) => ({ + query: gql` + mutation DestroyCoreViewFilter($input: DestroyViewFilterInput!) { + destroyCoreViewFilter(input: $input) { + ${gqlFields} + } + } + `, + variables: { + input, + }, +}); diff --git a/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/destroy-one-core-view-filter.util.ts b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/destroy-one-core-view-filter.util.ts new file mode 100644 index 00000000000..f565135a7d1 --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/destroy-one-core-view-filter.util.ts @@ -0,0 +1,40 @@ +import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util'; +import { destroyCoreViewFilterQueryFactory } from 'test/integration/metadata/suites/view-filter/utils/destroy-core-view-filter-query-factory.util'; +import { type CommonResponseBody } from 'test/integration/metadata/types/common-response-body.type'; +import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.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 DestroyViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/destroy-view-filter.input'; +import { type ViewFilterDTO } from 'src/engine/metadata-modules/view-filter/dtos/view-filter.dto'; + +export const destroyOneCoreViewFilter = async ({ + input, + gqlFields, + expectToFail, +}: PerformMetadataQueryParams): CommonResponseBody<{ + destroyCoreViewFilter: ViewFilterDTO; +}> => { + const graphqlOperation = destroyCoreViewFilterQueryFactory({ + input, + gqlFields, + }); + + const response = await makeMetadataAPIRequest(graphqlOperation); + + if (expectToFail === true) { + warnIfNoErrorButExpectedToFail({ + response, + errorMessage: 'View Filter destruction should have failed but did not', + }); + } + + if (expectToFail === false) { + warnIfErrorButNotExpectedToFail({ + response, + errorMessage: 'View Filter destruction has failed but should not', + }); + } + + return { data: response.body.data, errors: response.body.errors }; +}; diff --git a/packages/twenty-server/test/integration/graphql/utils/find-view-filters-operation-factory.util.ts b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/find-core-view-filters-query-factory.util.ts similarity index 74% rename from packages/twenty-server/test/integration/graphql/utils/find-view-filters-operation-factory.util.ts rename to packages/twenty-server/test/integration/metadata/suites/view-filter/utils/find-core-view-filters-query-factory.util.ts index c93dc6f2a80..fe87a41b4f7 100644 --- a/packages/twenty-server/test/integration/graphql/utils/find-view-filters-operation-factory.util.ts +++ b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/find-core-view-filters-query-factory.util.ts @@ -1,15 +1,15 @@ import gql from 'graphql-tag'; import { VIEW_FILTER_GQL_FIELDS } from 'test/integration/constants/view-gql-fields.constants'; -export const findViewFiltersOperationFactory = ({ +export const findCoreViewFiltersQueryFactory = ({ gqlFields = VIEW_FILTER_GQL_FIELDS, viewId, }: { gqlFields?: string; - viewId: string; + viewId?: string; }) => ({ query: gql` - query GetCoreViewFilters($viewId: String!) { + query GetCoreViewFilters($viewId: String) { getCoreViewFilters(viewId: $viewId) { ${gqlFields} } diff --git a/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/find-core-view-filters.util.ts b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/find-core-view-filters.util.ts new file mode 100644 index 00000000000..03fae24c7e7 --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/find-core-view-filters.util.ts @@ -0,0 +1,42 @@ +import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util'; +import { findCoreViewFiltersQueryFactory } from 'test/integration/metadata/suites/view-filter/utils/find-core-view-filters-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 ViewFilterDTO } from 'src/engine/metadata-modules/view-filter/dtos/view-filter.dto'; + +export const findCoreViewFilters = async ({ + viewId, + gqlFields, + expectToFail, +}: { + viewId?: string; + gqlFields?: string; + expectToFail?: boolean; +}): CommonResponseBody<{ + getCoreViewFilters: ViewFilterDTO[]; +}> => { + const graphqlOperation = findCoreViewFiltersQueryFactory({ + viewId, + gqlFields, + }); + + const response = await makeMetadataAPIRequest(graphqlOperation); + + if (expectToFail === true) { + warnIfNoErrorButExpectedToFail({ + response, + errorMessage: 'View Filter search should have failed but did not', + }); + } + + if (expectToFail === false) { + warnIfErrorButNotExpectedToFail({ + response, + errorMessage: 'View Filter search has failed but should not', + }); + } + + return { data: response.body.data, errors: response.body.errors }; +}; diff --git a/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/update-core-view-filter-query-factory.util.ts b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/update-core-view-filter-query-factory.util.ts new file mode 100644 index 00000000000..d4abceeea9f --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/update-core-view-filter-query-factory.util.ts @@ -0,0 +1,21 @@ +import gql from 'graphql-tag'; +import { VIEW_FILTER_GQL_FIELDS } from 'test/integration/constants/view-gql-fields.constants'; +import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.type'; + +import { type UpdateViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/update-view-filter.input'; + +export const updateCoreViewFilterQueryFactory = ({ + gqlFields = VIEW_FILTER_GQL_FIELDS, + input, +}: PerformMetadataQueryParams) => ({ + query: gql` + mutation UpdateCoreViewFilter($input: UpdateViewFilterInput!) { + updateCoreViewFilter(input: $input) { + ${gqlFields} + } + } + `, + variables: { + input, + }, +}); diff --git a/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/update-one-core-view-filter.util.ts b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/update-one-core-view-filter.util.ts new file mode 100644 index 00000000000..2512350dba5 --- /dev/null +++ b/packages/twenty-server/test/integration/metadata/suites/view-filter/utils/update-one-core-view-filter.util.ts @@ -0,0 +1,40 @@ +import { makeMetadataAPIRequest } from 'test/integration/metadata/suites/utils/make-metadata-api-request.util'; +import { updateCoreViewFilterQueryFactory } from 'test/integration/metadata/suites/view-filter/utils/update-core-view-filter-query-factory.util'; +import { type CommonResponseBody } from 'test/integration/metadata/types/common-response-body.type'; +import { type PerformMetadataQueryParams } from 'test/integration/metadata/types/perform-metadata-query.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 UpdateViewFilterInput } from 'src/engine/metadata-modules/view-filter/dtos/inputs/update-view-filter.input'; +import { type ViewFilterDTO } from 'src/engine/metadata-modules/view-filter/dtos/view-filter.dto'; + +export const updateOneCoreViewFilter = async ({ + input, + gqlFields, + expectToFail, +}: PerformMetadataQueryParams): CommonResponseBody<{ + updateCoreViewFilter: ViewFilterDTO; +}> => { + const graphqlOperation = updateCoreViewFilterQueryFactory({ + input, + gqlFields, + }); + + const response = await makeMetadataAPIRequest(graphqlOperation); + + if (expectToFail === true) { + warnIfNoErrorButExpectedToFail({ + response, + errorMessage: 'View Filter update should have failed but did not', + }); + } + + if (expectToFail === false) { + warnIfErrorButNotExpectedToFail({ + response, + errorMessage: 'View Filter update has failed but should not', + }); + } + + return { data: response.body.data, errors: response.body.errors }; +}; diff --git a/packages/twenty-shared/src/constants/MultiItemFieldDefaultMaxValues.ts b/packages/twenty-shared/src/constants/MultiItemFieldDefaultMaxValues.ts index b0c9f54ebce..5c78d00e6e5 100644 --- a/packages/twenty-shared/src/constants/MultiItemFieldDefaultMaxValues.ts +++ b/packages/twenty-shared/src/constants/MultiItemFieldDefaultMaxValues.ts @@ -1,2 +1 @@ export const MULTI_ITEM_FIELD_DEFAULT_MAX_VALUES = 10; - diff --git a/packages/twenty-shared/src/constants/MultiItemFieldMinMaxValues.ts b/packages/twenty-shared/src/constants/MultiItemFieldMinMaxValues.ts index 4257e54b014..e3f97b3baea 100644 --- a/packages/twenty-shared/src/constants/MultiItemFieldMinMaxValues.ts +++ b/packages/twenty-shared/src/constants/MultiItemFieldMinMaxValues.ts @@ -1,2 +1 @@ export const MULTI_ITEM_FIELD_MIN_MAX_VALUES = 1; - diff --git a/packages/twenty-shared/src/utils/__tests__/parseJson.test.ts b/packages/twenty-shared/src/utils/__tests__/parseJson.test.ts index e5c10dc1733..05dbd744f79 100644 --- a/packages/twenty-shared/src/utils/__tests__/parseJson.test.ts +++ b/packages/twenty-shared/src/utils/__tests__/parseJson.test.ts @@ -6,6 +6,11 @@ describe('parseJson', () => { expect(result).toBeNull(); }); + it('if value is raw string', () => { + const result = parseJson('t'); + expect(result).toBeNull(); + }); + it('if value is undefined', () => { const result = parseJson(undefined); expect(result).toBeNull();