From f06786d6037ae27b4d945f938406c831297c8a55 Mon Sep 17 00:00:00 2001 From: Weiko Date: Tue, 26 Aug 2025 18:59:20 +0200 Subject: [PATCH] Add missing FK on view tables (#14084) ## Context View tables were missing some FK, we are also introducing delete cascade on those tables when needed to leverage pg cascade deletion instead of having to implement it. Also renaming those classes with Entity suffix to follow repo guidelines. --- .../migrate-views-to-core.command.ts | 40 +++++----- .../1756209145695-addMissingFkOnViewTables.ts | 43 ++++++++++ .../view/controllers/view-field.controller.ts | 10 +-- .../view/entities/view-field.entity.ts | 18 +++-- .../view/entities/view-filter-group.entity.ts | 25 +++--- .../view/entities/view-filter.entity.ts | 24 +++--- .../view/entities/view-group.entity.ts | 18 +++-- .../view/entities/view-sort.entity.ts | 18 +++-- .../core-modules/view/entities/view.entity.ts | 45 ++++++----- .../view/resolvers/view-field.resolver.ts | 10 +-- .../services/tests/view-field.service.spec.ts | 12 +-- .../tests/view-filter-group.service.spec.ts | 12 +-- .../tests/view-filter.service.spec.ts | 12 +-- .../services/tests/view-group.service.spec.ts | 12 +-- .../services/tests/view-sort.service.spec.ts | 12 +-- .../view/services/tests/view.service.spec.ts | 12 +-- .../view/services/view-field.service.ts | 25 +++--- .../services/view-filter-group.service.ts | 27 ++++--- .../view/services/view-filter.service.ts | 25 +++--- .../view/services/view-group.service.ts | 25 +++--- .../view/services/view-sort.service.ts | 26 +++--- .../view/services/view.service.ts | 20 ++--- .../engine/core-modules/view/view.module.ts | 21 +++-- .../workspace/workspace.entity.ts | 36 ++++----- .../object-metadata-v2.service.ts | 6 +- .../object-metadata/object-metadata.module.ts | 4 +- .../prefill-core-views.ts | 45 ++++++----- .../types/flat-view-field.type.ts | 4 +- .../types/flat-view.type.ts | 4 +- .../create-view-action-handler.service.ts | 9 ++- .../view/services/view-field-sync.service.ts | 12 +-- .../view-filter-group-sync.service.ts | 12 +-- .../view/services/view-filter-sync.service.ts | 12 +-- .../view/services/view-group-sync.service.ts | 12 +-- .../view/services/view-sort-sync.service.ts | 12 +-- .../view/services/view-sync.service.ts | 12 +-- .../src/modules/view/view.module.ts | 21 +++-- .../view-field-resolver.integration-spec.ts | 79 ++++++++++++++++--- ...-filter-group-resolver.integration-spec.ts | 29 +++++++ .../view-filter-resolver.integration-spec.ts | 67 ++++++++++++++-- .../view-group-resolver.integration-spec.ts | 65 +++++++++++++-- .../view/view-resolver.integration-spec.ts | 71 ++++++++++++++--- .../view-sort-resolver.integration-spec.ts | 70 +++++++++++++--- ...reate-view-field-operation-factory.util.ts | 4 +- ...iew-filter-group-operation-factory.util.ts | 4 +- ...eate-view-filter-operation-factory.util.ts | 4 +- ...reate-view-group-operation-factory.util.ts | 4 +- .../create-view-operation-factory.util.ts | 4 +- ...create-view-sort-operation-factory.util.ts | 4 +- .../graphql/utils/view-data-factory.util.ts | 54 ++++++------- .../graphql/utils/view-graphql.util.ts | 8 +- .../suites/view-field.integration-spec.ts | 73 +++++++++++++++-- .../view-filter-group.integration-spec.ts | 43 ++++++++++ .../suites/view-filter.integration-spec.ts | 76 ++++++++++++++++-- .../suites/view-group.integration-spec.ts | 79 +++++++++++++++++-- .../rest/suites/view-sort.integration-spec.ts | 73 +++++++++++++++-- .../rest/suites/view.integration-spec.ts | 47 +++++++++-- .../rest/utils/view-rest-api.util.ts | 36 ++++----- .../test/integration/utils/view-test.util.ts | 36 ++++----- 59 files changed, 1171 insertions(+), 452 deletions(-) create mode 100644 packages/twenty-server/src/database/typeorm/core/migrations/common/1756209145695-addMissingFkOnViewTables.ts diff --git a/packages/twenty-server/src/database/commands/views-migration/migrate-views-to-core.command.ts b/packages/twenty-server/src/database/commands/views-migration/migrate-views-to-core.command.ts index 4f46e49624..b8a2222fc0 100644 --- a/packages/twenty-server/src/database/commands/views-migration/migrate-views-to-core.command.ts +++ b/packages/twenty-server/src/database/commands/views-migration/migrate-views-to-core.command.ts @@ -10,12 +10,12 @@ import { } from 'src/database/commands/command-runners/active-or-suspended-workspaces-migration.command-runner'; 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 { ViewField } from 'src/engine/core-modules/view/entities/view-field.entity'; -import { ViewFilterGroup } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; -import { ViewFilter } from 'src/engine/core-modules/view/entities/view-filter.entity'; -import { ViewGroup } from 'src/engine/core-modules/view/entities/view-group.entity'; -import { ViewSort } from 'src/engine/core-modules/view/entities/view-sort.entity'; -import { View } from 'src/engine/core-modules/view/entities/view.entity'; +import { ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; +import { ViewFilterGroupEntity } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; +import { ViewFilterEntity } from 'src/engine/core-modules/view/entities/view-filter.entity'; +import { ViewGroupEntity } from 'src/engine/core-modules/view/entities/view-group.entity'; +import { ViewSortEntity } from 'src/engine/core-modules/view/entities/view-sort.entity'; +import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { type ViewFilterGroupLogicalOperator } from 'src/engine/core-modules/view/enums/view-filter-group-logical-operator'; import { ViewKey } from 'src/engine/core-modules/view/enums/view-key.enum'; import { ViewOpenRecordIn } from 'src/engine/core-modules/view/enums/view-open-record-in'; @@ -208,7 +208,7 @@ export class MigrateViewsToCoreCommand extends ActiveOrSuspendedWorkspacesMigrat queryRunner: QueryRunner, dryRun: boolean, ): Promise { - const viewRepository = queryRunner.manager.getRepository(View); + const viewRepository = queryRunner.manager.getRepository(ViewEntity); const existingViews = await viewRepository.find({ where: { workspaceId }, select: ['id'], @@ -253,7 +253,7 @@ export class MigrateViewsToCoreCommand extends ActiveOrSuspendedWorkspacesMigrat viewName = 'All {objectLabelPlural}'; } - const coreView: Partial = { + const coreView: Partial = { id: workspaceView.id, name: viewName, objectMetadataId: workspaceView.objectMetadataId, @@ -282,7 +282,7 @@ export class MigrateViewsToCoreCommand extends ActiveOrSuspendedWorkspacesMigrat anyFieldFilterValue: workspaceView.anyFieldFilterValue, }; - const repository = queryRunner.manager.getRepository(View); + const repository = queryRunner.manager.getRepository(ViewEntity); await repository.insert(coreView); } @@ -293,7 +293,7 @@ export class MigrateViewsToCoreCommand extends ActiveOrSuspendedWorkspacesMigrat queryRunner: QueryRunner, ): Promise { for (const field of workspaceViewFields) { - const coreViewField: Partial = { + const coreViewField: Partial = { id: field.id, fieldMetadataId: field.fieldMetadataId, viewId: field.viewId, @@ -306,7 +306,7 @@ export class MigrateViewsToCoreCommand extends ActiveOrSuspendedWorkspacesMigrat deletedAt: field.deletedAt ? new Date(field.deletedAt) : null, }; - const repository = queryRunner.manager.getRepository(ViewField); + const repository = queryRunner.manager.getRepository(ViewFieldEntity); await repository.insert(coreViewField); } @@ -325,7 +325,7 @@ export class MigrateViewsToCoreCommand extends ActiveOrSuspendedWorkspacesMigrat continue; } - const coreViewFilter: Partial = { + const coreViewFilter: Partial = { id: filter.id, fieldMetadataId: filter.fieldMetadataId, viewId: filter.viewId, @@ -340,7 +340,7 @@ export class MigrateViewsToCoreCommand extends ActiveOrSuspendedWorkspacesMigrat deletedAt: filter.deletedAt ? new Date(filter.deletedAt) : null, }; - const repository = queryRunner.manager.getRepository(ViewFilter); + const repository = queryRunner.manager.getRepository(ViewFilterEntity); await repository.insert(coreViewFilter); } @@ -361,7 +361,7 @@ export class MigrateViewsToCoreCommand extends ActiveOrSuspendedWorkspacesMigrat const direction = sort.direction.toUpperCase() as ViewSortDirection; - const coreViewSort: Partial = { + const coreViewSort: Partial = { id: sort.id, fieldMetadataId: sort.fieldMetadataId, viewId: sort.viewId, @@ -372,7 +372,7 @@ export class MigrateViewsToCoreCommand extends ActiveOrSuspendedWorkspacesMigrat deletedAt: sort.deletedAt ? new Date(sort.deletedAt) : null, }; - const repository = queryRunner.manager.getRepository(ViewSort); + const repository = queryRunner.manager.getRepository(ViewSortEntity); await repository.insert(coreViewSort); } @@ -391,7 +391,7 @@ export class MigrateViewsToCoreCommand extends ActiveOrSuspendedWorkspacesMigrat continue; } - const coreViewGroup: Partial = { + const coreViewGroup: Partial = { id: group.id, fieldMetadataId: group.fieldMetadataId, viewId: group.viewId, @@ -404,7 +404,7 @@ export class MigrateViewsToCoreCommand extends ActiveOrSuspendedWorkspacesMigrat deletedAt: group.deletedAt ? new Date(group.deletedAt) : null, }; - const repository = queryRunner.manager.getRepository(ViewGroup); + const repository = queryRunner.manager.getRepository(ViewGroupEntity); await repository.insert(coreViewGroup); } @@ -416,7 +416,7 @@ export class MigrateViewsToCoreCommand extends ActiveOrSuspendedWorkspacesMigrat queryRunner: QueryRunner, ): Promise { for (const filterGroup of workspaceViewFilterGroups) { - const coreViewFilterGroup: Partial = { + const coreViewFilterGroup: Partial = { id: filterGroup.id, viewId: filterGroup.viewId, logicalOperator: @@ -431,7 +431,9 @@ export class MigrateViewsToCoreCommand extends ActiveOrSuspendedWorkspacesMigrat : null, }; - const repository = queryRunner.manager.getRepository(ViewFilterGroup); + const repository = queryRunner.manager.getRepository( + ViewFilterGroupEntity, + ); await repository.insert(coreViewFilterGroup); } diff --git a/packages/twenty-server/src/database/typeorm/core/migrations/common/1756209145695-addMissingFkOnViewTables.ts b/packages/twenty-server/src/database/typeorm/core/migrations/common/1756209145695-addMissingFkOnViewTables.ts new file mode 100644 index 0000000000..aa440dbb49 --- /dev/null +++ b/packages/twenty-server/src/database/typeorm/core/migrations/common/1756209145695-addMissingFkOnViewTables.ts @@ -0,0 +1,43 @@ +import { type MigrationInterface, type QueryRunner } from 'typeorm'; + +export class AddMissingFkOnViewTables1756209145695 + implements MigrationInterface +{ + name = 'AddMissingFkOnViewTables1756209145695'; + + public async up(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "core"."viewFilter" ADD CONSTRAINT "FK_193548db5abc45713087f7d1af6" FOREIGN KEY ("fieldMetadataId") REFERENCES "core"."fieldMetadata"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE "core"."viewGroup" ADD CONSTRAINT "FK_b3aa7ec58cdd9e83729f2232591" FOREIGN KEY ("fieldMetadataId") REFERENCES "core"."fieldMetadata"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE "core"."viewSort" ADD CONSTRAINT "FK_818522b962a9b756accb5b3149d" FOREIGN KEY ("fieldMetadataId") REFERENCES "core"."fieldMetadata"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE "core"."view" ADD CONSTRAINT "FK_3e5ea41c239ef1b75b0d42bef99" FOREIGN KEY ("objectMetadataId") REFERENCES "core"."objectMetadata"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + await queryRunner.query( + `ALTER TABLE "core"."viewField" ADD CONSTRAINT "FK_0a48a0b66daedac1314437be5eb" FOREIGN KEY ("fieldMetadataId") REFERENCES "core"."fieldMetadata"("id") ON DELETE CASCADE ON UPDATE NO ACTION`, + ); + } + + public async down(queryRunner: QueryRunner): Promise { + await queryRunner.query( + `ALTER TABLE "core"."viewField" DROP CONSTRAINT "FK_0a48a0b66daedac1314437be5eb"`, + ); + await queryRunner.query( + `ALTER TABLE "core"."view" DROP CONSTRAINT "FK_3e5ea41c239ef1b75b0d42bef99"`, + ); + await queryRunner.query( + `ALTER TABLE "core"."viewSort" DROP CONSTRAINT "FK_818522b962a9b756accb5b3149d"`, + ); + await queryRunner.query( + `ALTER TABLE "core"."viewGroup" DROP CONSTRAINT "FK_b3aa7ec58cdd9e83729f2232591"`, + ); + await queryRunner.query( + `ALTER TABLE "core"."viewFilter" DROP CONSTRAINT "FK_193548db5abc45713087f7d1af6"`, + ); + } +} diff --git a/packages/twenty-server/src/engine/core-modules/view/controllers/view-field.controller.ts b/packages/twenty-server/src/engine/core-modules/view/controllers/view-field.controller.ts index 0e869dd46d..dfb1cd0e30 100644 --- a/packages/twenty-server/src/engine/core-modules/view/controllers/view-field.controller.ts +++ b/packages/twenty-server/src/engine/core-modules/view/controllers/view-field.controller.ts @@ -15,7 +15,7 @@ import { isDefined } from 'twenty-shared/utils'; import { CreateViewFieldInput } from 'src/engine/core-modules/view/dtos/inputs/create-view-field.input'; import { UpdateViewFieldInput } from 'src/engine/core-modules/view/dtos/inputs/update-view-field.input'; -import { type ViewField } from 'src/engine/core-modules/view/entities/view-field.entity'; +import { type ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; import { ViewFieldRestApiExceptionFilter } from 'src/engine/core-modules/view/filters/view-field-rest-api-exception.filter'; import { ViewFieldService } from 'src/engine/core-modules/view/services/view-field.service'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @@ -32,7 +32,7 @@ export class ViewFieldController { async findMany( @AuthWorkspace() workspace: Workspace, @Query('viewId') viewId?: string, - ): Promise { + ): Promise { if (viewId) { return this.viewFieldService.findByViewId(workspace.id, viewId); } @@ -44,7 +44,7 @@ export class ViewFieldController { async findOne( @Param('id') id: string, @AuthWorkspace() workspace: Workspace, - ): Promise { + ): Promise { return this.viewFieldService.findById(id, workspace.id); } @@ -53,7 +53,7 @@ export class ViewFieldController { @Param('id') id: string, @Body() input: UpdateViewFieldInput, @AuthWorkspace() workspace: Workspace, - ): Promise { + ): Promise { const updatedViewField = await this.viewFieldService.update( id, workspace.id, @@ -67,7 +67,7 @@ export class ViewFieldController { async create( @Body() input: CreateViewFieldInput, @AuthWorkspace() workspace: Workspace, - ): Promise { + ): Promise { return this.viewFieldService.create({ ...input, workspaceId: workspace.id, diff --git a/packages/twenty-server/src/engine/core-modules/view/entities/view-field.entity.ts b/packages/twenty-server/src/engine/core-modules/view/entities/view-field.entity.ts index 74de692a15..be23f0db82 100644 --- a/packages/twenty-server/src/engine/core-modules/view/entities/view-field.entity.ts +++ b/packages/twenty-server/src/engine/core-modules/view/entities/view-field.entity.ts @@ -1,4 +1,3 @@ -import { IDField } from '@ptc-org/nestjs-query-graphql'; import { Column, CreateDateColumn, @@ -13,9 +12,9 @@ import { } from 'typeorm'; import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant'; -import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; -import { View } from 'src/engine/core-modules/view/entities/view.entity'; +import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; @Entity({ name: 'viewField', schema: 'core' }) @Index('IDX_VIEW_FIELD_WORKSPACE_ID_VIEW_ID', ['workspaceId', 'viewId']) @@ -27,14 +26,19 @@ import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; where: '"deletedAt" IS NULL', }, ) -export class ViewField { - @IDField(() => UUIDScalarType) +export class ViewFieldEntity { @PrimaryGeneratedColumn('uuid') id: string; @Column({ nullable: false, type: 'uuid' }) fieldMetadataId: string; + @ManyToOne(() => FieldMetadataEntity, { + onDelete: 'CASCADE', + }) + @JoinColumn({ name: 'fieldMetadataId' }) + fieldMetadata: Relation; + @Column({ nullable: false, default: true }) isVisible: boolean; @@ -73,9 +77,9 @@ export class ViewField { @JoinColumn({ name: 'workspaceId' }) workspace: Relation; - @ManyToOne(() => View, (view) => view.viewFields, { + @ManyToOne(() => ViewEntity, (view) => view.viewFields, { onDelete: 'CASCADE', }) @JoinColumn({ name: 'viewId' }) - view: Relation; + view: Relation; } diff --git a/packages/twenty-server/src/engine/core-modules/view/entities/view-filter-group.entity.ts b/packages/twenty-server/src/engine/core-modules/view/entities/view-filter-group.entity.ts index 04c691e87c..bca2ae821f 100644 --- a/packages/twenty-server/src/engine/core-modules/view/entities/view-filter-group.entity.ts +++ b/packages/twenty-server/src/engine/core-modules/view/entities/view-filter-group.entity.ts @@ -1,4 +1,3 @@ -import { IDField } from '@ptc-org/nestjs-query-graphql'; import { Column, CreateDateColumn, @@ -13,16 +12,14 @@ import { UpdateDateColumn, } from 'typeorm'; -import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; -import { ViewFilter } from 'src/engine/core-modules/view/entities/view-filter.entity'; -import { View } from 'src/engine/core-modules/view/entities/view.entity'; +import { ViewFilterEntity } from 'src/engine/core-modules/view/entities/view-filter.entity'; +import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { ViewFilterGroupLogicalOperator } from 'src/engine/core-modules/view/enums/view-filter-group-logical-operator'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @Entity({ name: 'viewFilterGroup', schema: 'core' }) @Index('IDX_VIEW_FILTER_GROUP_WORKSPACE_ID_VIEW_ID', ['workspaceId', 'viewId']) -export class ViewFilterGroup { - @IDField(() => UUIDScalarType) +export class ViewFilterGroupEntity { @PrimaryGeneratedColumn('uuid') id: string; @@ -61,28 +58,28 @@ export class ViewFilterGroup { @JoinColumn({ name: 'workspaceId' }) workspace: Relation; - @ManyToOne(() => View, (view) => view.viewFilterGroups, { + @ManyToOne(() => ViewEntity, (view) => view.viewFilterGroups, { onDelete: 'CASCADE', }) @JoinColumn({ name: 'viewId' }) - view: Relation; + view: Relation; - @OneToMany(() => ViewFilter, (viewFilter) => viewFilter.viewFilterGroup) - viewFilters: Relation[]; + @OneToMany(() => ViewFilterEntity, (viewFilter) => viewFilter.viewFilterGroup) + viewFilters: Relation[]; @ManyToOne( - () => ViewFilterGroup, + () => ViewFilterGroupEntity, (viewFilterGroup) => viewFilterGroup.childViewFilterGroups, { onDelete: 'CASCADE', }, ) @JoinColumn({ name: 'parentViewFilterGroupId' }) - parentViewFilterGroup: Relation; + parentViewFilterGroup: Relation; @OneToMany( - () => ViewFilterGroup, + () => ViewFilterGroupEntity, (viewFilterGroup) => viewFilterGroup.parentViewFilterGroup, ) - childViewFilterGroups: Relation[]; + childViewFilterGroups: Relation[]; } diff --git a/packages/twenty-server/src/engine/core-modules/view/entities/view-filter.entity.ts b/packages/twenty-server/src/engine/core-modules/view/entities/view-filter.entity.ts index 908b4351cc..70b9d7fc99 100644 --- a/packages/twenty-server/src/engine/core-modules/view/entities/view-filter.entity.ts +++ b/packages/twenty-server/src/engine/core-modules/view/entities/view-filter.entity.ts @@ -1,4 +1,3 @@ -import { IDField } from '@ptc-org/nestjs-query-graphql'; import { Column, CreateDateColumn, @@ -12,24 +11,29 @@ import { UpdateDateColumn, } from 'typeorm'; -import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; -import { ViewFilterGroup } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; -import { View } from 'src/engine/core-modules/view/entities/view.entity'; +import { ViewFilterGroupEntity } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; +import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { ViewFilterOperand } from 'src/engine/core-modules/view/enums/view-filter-operand'; import { ViewFilterValue } from 'src/engine/core-modules/view/types/view-filter-value.type'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; @Entity({ name: 'viewFilter', schema: 'core' }) @Index('IDX_VIEW_FILTER_WORKSPACE_ID_VIEW_ID', ['workspaceId', 'viewId']) @Index('IDX_VIEW_FILTER_FIELD_METADATA_ID', ['fieldMetadataId']) -export class ViewFilter { - @IDField(() => UUIDScalarType) +export class ViewFilterEntity { @PrimaryGeneratedColumn('uuid') id: string; @Column({ nullable: false, type: 'uuid' }) fieldMetadataId: string; + @ManyToOne(() => FieldMetadataEntity, { + onDelete: 'CASCADE', + }) + @JoinColumn({ name: 'fieldMetadataId' }) + fieldMetadata: Relation; + @Column({ nullable: false, type: 'enum', @@ -71,19 +75,19 @@ export class ViewFilter { @JoinColumn({ name: 'workspaceId' }) workspace: Relation; - @ManyToOne(() => View, (view) => view.viewFilters, { + @ManyToOne(() => ViewEntity, (view) => view.viewFilters, { onDelete: 'CASCADE', }) @JoinColumn({ name: 'viewId' }) - view: Relation; + view: Relation; @ManyToOne( - () => ViewFilterGroup, + () => ViewFilterGroupEntity, (viewFilterGroup) => viewFilterGroup.viewFilters, { onDelete: 'CASCADE', }, ) @JoinColumn({ name: 'viewFilterGroupId' }) - viewFilterGroup: Relation; + viewFilterGroup: Relation; } diff --git a/packages/twenty-server/src/engine/core-modules/view/entities/view-group.entity.ts b/packages/twenty-server/src/engine/core-modules/view/entities/view-group.entity.ts index b9f9252e35..f40b080540 100644 --- a/packages/twenty-server/src/engine/core-modules/view/entities/view-group.entity.ts +++ b/packages/twenty-server/src/engine/core-modules/view/entities/view-group.entity.ts @@ -1,4 +1,3 @@ -import { IDField } from '@ptc-org/nestjs-query-graphql'; import { Column, CreateDateColumn, @@ -12,20 +11,25 @@ import { UpdateDateColumn, } from 'typeorm'; -import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; -import { View } from 'src/engine/core-modules/view/entities/view.entity'; +import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; @Entity({ name: 'viewGroup', schema: 'core' }) @Index('IDX_VIEW_GROUP_WORKSPACE_ID_VIEW_ID', ['workspaceId', 'viewId']) -export class ViewGroup { - @IDField(() => UUIDScalarType) +export class ViewGroupEntity { @PrimaryGeneratedColumn('uuid') id: string; @Column({ nullable: false, type: 'uuid' }) fieldMetadataId: string; + @ManyToOne(() => FieldMetadataEntity, { + onDelete: 'CASCADE', + }) + @JoinColumn({ name: 'fieldMetadataId' }) + fieldMetadata: Relation; + @Column({ nullable: false, default: true }) isVisible: boolean; @@ -56,9 +60,9 @@ export class ViewGroup { @JoinColumn({ name: 'workspaceId' }) workspace: Relation; - @ManyToOne(() => View, (view) => view.viewGroups, { + @ManyToOne(() => ViewEntity, (view) => view.viewGroups, { onDelete: 'CASCADE', }) @JoinColumn({ name: 'viewId' }) - view: Relation; + view: Relation; } diff --git a/packages/twenty-server/src/engine/core-modules/view/entities/view-sort.entity.ts b/packages/twenty-server/src/engine/core-modules/view/entities/view-sort.entity.ts index 358defbbcd..1e984cd238 100644 --- a/packages/twenty-server/src/engine/core-modules/view/entities/view-sort.entity.ts +++ b/packages/twenty-server/src/engine/core-modules/view/entities/view-sort.entity.ts @@ -1,4 +1,3 @@ -import { IDField } from '@ptc-org/nestjs-query-graphql'; import { Column, CreateDateColumn, @@ -12,10 +11,10 @@ import { UpdateDateColumn, } from 'typeorm'; -import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; -import { View } from 'src/engine/core-modules/view/entities/view.entity'; +import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { ViewSortDirection } from 'src/engine/core-modules/view/enums/view-sort-direction'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { FieldMetadataEntity } from 'src/engine/metadata-modules/field-metadata/field-metadata.entity'; @Entity({ name: 'viewSort', schema: 'core' }) @Index('IDX_VIEW_SORT_WORKSPACE_ID_VIEW_ID', ['workspaceId', 'viewId']) @@ -27,14 +26,19 @@ import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; where: '"deletedAt" IS NULL', }, ) -export class ViewSort { - @IDField(() => UUIDScalarType) +export class ViewSortEntity { @PrimaryGeneratedColumn('uuid') id: string; @Column({ nullable: false, type: 'uuid' }) fieldMetadataId: string; + @ManyToOne(() => FieldMetadataEntity, { + onDelete: 'CASCADE', + }) + @JoinColumn({ name: 'fieldMetadataId' }) + fieldMetadata: Relation; + @Column({ nullable: false, type: 'enum', @@ -64,9 +68,9 @@ export class ViewSort { @JoinColumn({ name: 'workspaceId' }) workspace: Relation; - @ManyToOne(() => View, (view) => view.viewSorts, { + @ManyToOne(() => ViewEntity, (view) => view.viewSorts, { onDelete: 'CASCADE', }) @JoinColumn({ name: 'viewId' }) - view: Relation; + view: Relation; } diff --git a/packages/twenty-server/src/engine/core-modules/view/entities/view.entity.ts b/packages/twenty-server/src/engine/core-modules/view/entities/view.entity.ts index 2ad67f6b0c..625751ce78 100644 --- a/packages/twenty-server/src/engine/core-modules/view/entities/view.entity.ts +++ b/packages/twenty-server/src/engine/core-modules/view/entities/view.entity.ts @@ -1,4 +1,3 @@ -import { IDField } from '@ptc-org/nestjs-query-graphql'; import { Column, CreateDateColumn, @@ -14,24 +13,23 @@ import { } from 'typeorm'; import { AggregateOperations } from 'src/engine/api/graphql/graphql-query-runner/constants/aggregate-operations.constant'; -import { UUIDScalarType } from 'src/engine/api/graphql/workspace-schema-builder/graphql-types/scalars'; -import { ViewField } from 'src/engine/core-modules/view/entities/view-field.entity'; -import { ViewFilterGroup } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; -import { ViewFilter } from 'src/engine/core-modules/view/entities/view-filter.entity'; -import { ViewGroup } from 'src/engine/core-modules/view/entities/view-group.entity'; -import { ViewSort } from 'src/engine/core-modules/view/entities/view-sort.entity'; +import { ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; +import { ViewFilterGroupEntity } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; +import { ViewFilterEntity } from 'src/engine/core-modules/view/entities/view-filter.entity'; +import { ViewGroupEntity } from 'src/engine/core-modules/view/entities/view-group.entity'; +import { ViewSortEntity } from 'src/engine/core-modules/view/entities/view-sort.entity'; import { ViewKey } from 'src/engine/core-modules/view/enums/view-key.enum'; import { ViewOpenRecordIn } from 'src/engine/core-modules/view/enums/view-open-record-in'; import { ViewType } from 'src/engine/core-modules/view/enums/view-type.enum'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; +import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; @Entity({ name: 'view', schema: 'core' }) @Index('IDX_VIEW_WORKSPACE_ID_OBJECT_METADATA_ID', [ 'workspaceId', 'objectMetadataId', ]) -export class View { - @IDField(() => UUIDScalarType) +export class ViewEntity { @PrimaryGeneratedColumn('uuid') id: string; @@ -41,6 +39,12 @@ export class View { @Column({ nullable: false, type: 'uuid' }) objectMetadataId: string; + @ManyToOne(() => ObjectMetadataEntity, { + onDelete: 'CASCADE', + }) + @JoinColumn({ name: 'objectMetadataId' }) + objectMetadata: Relation; + @Column({ type: 'enum', enum: Object.values(ViewType), @@ -109,18 +113,21 @@ export class View { @JoinColumn({ name: 'workspaceId' }) workspace: Relation; - @OneToMany(() => ViewField, (viewField) => viewField.view) - viewFields: Relation; + @OneToMany(() => ViewFieldEntity, (viewField) => viewField.view) + viewFields: Relation; - @OneToMany(() => ViewFilter, (viewFilter) => viewFilter.view) - viewFilters: Relation; + @OneToMany(() => ViewFilterEntity, (viewFilter) => viewFilter.view) + viewFilters: Relation; - @OneToMany(() => ViewSort, (viewSort) => viewSort.view) - viewSorts: Relation; + @OneToMany(() => ViewSortEntity, (viewSort) => viewSort.view) + viewSorts: Relation; - @OneToMany(() => ViewGroup, (viewGroup) => viewGroup.view) - viewGroups: Relation; + @OneToMany(() => ViewGroupEntity, (viewGroup) => viewGroup.view) + viewGroups: Relation; - @OneToMany(() => ViewFilterGroup, (viewFilterGroup) => viewFilterGroup.view) - viewFilterGroups: Relation; + @OneToMany( + () => ViewFilterGroupEntity, + (viewFilterGroup) => viewFilterGroup.view, + ) + viewFilterGroups: Relation; } diff --git a/packages/twenty-server/src/engine/core-modules/view/resolvers/view-field.resolver.ts b/packages/twenty-server/src/engine/core-modules/view/resolvers/view-field.resolver.ts index 81742e530b..0c5ed785a4 100644 --- a/packages/twenty-server/src/engine/core-modules/view/resolvers/view-field.resolver.ts +++ b/packages/twenty-server/src/engine/core-modules/view/resolvers/view-field.resolver.ts @@ -6,7 +6,7 @@ import { isDefined } from 'twenty-shared/utils'; import { CreateViewFieldInput } from 'src/engine/core-modules/view/dtos/inputs/create-view-field.input'; import { UpdateViewFieldInput } from 'src/engine/core-modules/view/dtos/inputs/update-view-field.input'; import { ViewFieldDTO } from 'src/engine/core-modules/view/dtos/view-field.dto'; -import { type ViewField } from 'src/engine/core-modules/view/entities/view-field.entity'; +import { type ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; import { ViewFieldService } from 'src/engine/core-modules/view/services/view-field.service'; import { ViewGraphqlApiExceptionFilter } from 'src/engine/core-modules/view/utils/view-graphql-api-exception.filter'; import { Workspace } from 'src/engine/core-modules/workspace/workspace.entity'; @@ -23,7 +23,7 @@ export class ViewFieldResolver { async getCoreViewFields( @Args('viewId', { type: () => String }) viewId: string, @AuthWorkspace() workspace: Workspace, - ): Promise { + ): Promise { return this.viewFieldService.findByViewId(workspace.id, viewId); } @@ -31,7 +31,7 @@ export class ViewFieldResolver { async getCoreViewField( @Args('id', { type: () => String }) id: string, @AuthWorkspace() workspace: Workspace, - ): Promise { + ): Promise { return this.viewFieldService.findById(id, workspace.id); } @@ -40,7 +40,7 @@ export class ViewFieldResolver { @Args('id', { type: () => String }) id: string, @Args('input') input: UpdateViewFieldInput, @AuthWorkspace() workspace: Workspace, - ): Promise { + ): Promise { return this.viewFieldService.update(id, workspace.id, input); } @@ -48,7 +48,7 @@ export class ViewFieldResolver { async createCoreViewField( @Args('input') input: CreateViewFieldInput, @AuthWorkspace() workspace: Workspace, - ): Promise { + ): Promise { return this.viewFieldService.create({ ...input, workspaceId: workspace.id, diff --git a/packages/twenty-server/src/engine/core-modules/view/services/tests/view-field.service.spec.ts b/packages/twenty-server/src/engine/core-modules/view/services/tests/view-field.service.spec.ts index aceb104c07..8ae651152f 100644 --- a/packages/twenty-server/src/engine/core-modules/view/services/tests/view-field.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/view/services/tests/view-field.service.spec.ts @@ -3,7 +3,7 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { type Repository } from 'typeorm'; -import { ViewField } from 'src/engine/core-modules/view/entities/view-field.entity'; +import { ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; import { ViewFieldException, ViewFieldExceptionCode, @@ -15,7 +15,7 @@ import { ViewFieldService } from 'src/engine/core-modules/view/services/view-fie describe('ViewFieldService', () => { let viewFieldService: ViewFieldService; - let viewFieldRepository: Repository; + let viewFieldRepository: Repository; const mockViewField = { id: 'view-field-id', @@ -28,14 +28,14 @@ describe('ViewFieldService', () => { createdAt: new Date(), updatedAt: new Date(), deletedAt: null, - } as ViewField; + } as ViewFieldEntity; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ ViewFieldService, { - provide: getRepositoryToken(ViewField, 'core'), + provide: getRepositoryToken(ViewFieldEntity, 'core'), useValue: { find: jest.fn(), findOne: jest.fn(), @@ -49,8 +49,8 @@ describe('ViewFieldService', () => { }).compile(); viewFieldService = module.get(ViewFieldService); - viewFieldRepository = module.get>( - getRepositoryToken(ViewField, 'core'), + viewFieldRepository = module.get>( + getRepositoryToken(ViewFieldEntity, 'core'), ); }); diff --git a/packages/twenty-server/src/engine/core-modules/view/services/tests/view-filter-group.service.spec.ts b/packages/twenty-server/src/engine/core-modules/view/services/tests/view-filter-group.service.spec.ts index 3ccc81fee2..d55324a9ae 100644 --- a/packages/twenty-server/src/engine/core-modules/view/services/tests/view-filter-group.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/view/services/tests/view-filter-group.service.spec.ts @@ -3,7 +3,7 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { type Repository } from 'typeorm'; -import { ViewFilterGroup } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; +import { ViewFilterGroupEntity } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; import { ViewFilterGroupLogicalOperator } from 'src/engine/core-modules/view/enums/view-filter-group-logical-operator'; import { ViewFilterGroupException, @@ -16,7 +16,7 @@ import { ViewFilterGroupService } from 'src/engine/core-modules/view/services/vi describe('ViewFilterGroupService', () => { let viewFilterGroupService: ViewFilterGroupService; - let viewFilterGroupRepository: Repository; + let viewFilterGroupRepository: Repository; const mockViewFilterGroup = { id: 'view-filter-group-id', @@ -27,14 +27,14 @@ describe('ViewFilterGroupService', () => { createdAt: new Date(), updatedAt: new Date(), deletedAt: null, - } as ViewFilterGroup; + } as ViewFilterGroupEntity; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ ViewFilterGroupService, { - provide: getRepositoryToken(ViewFilterGroup, 'core'), + provide: getRepositoryToken(ViewFilterGroupEntity, 'core'), useValue: { find: jest.fn(), findOne: jest.fn(), @@ -50,8 +50,8 @@ describe('ViewFilterGroupService', () => { viewFilterGroupService = module.get( ViewFilterGroupService, ); - viewFilterGroupRepository = module.get>( - getRepositoryToken(ViewFilterGroup, 'core'), + viewFilterGroupRepository = module.get>( + getRepositoryToken(ViewFilterGroupEntity, 'core'), ); }); diff --git a/packages/twenty-server/src/engine/core-modules/view/services/tests/view-filter.service.spec.ts b/packages/twenty-server/src/engine/core-modules/view/services/tests/view-filter.service.spec.ts index 14fe3dbf09..6a7f9925eb 100644 --- a/packages/twenty-server/src/engine/core-modules/view/services/tests/view-filter.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/view/services/tests/view-filter.service.spec.ts @@ -3,7 +3,7 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { type Repository } from 'typeorm'; -import { ViewFilter } from 'src/engine/core-modules/view/entities/view-filter.entity'; +import { ViewFilterEntity } from 'src/engine/core-modules/view/entities/view-filter.entity'; import { ViewFilterOperand } from 'src/engine/core-modules/view/enums/view-filter-operand'; import { ViewFilterException, @@ -16,7 +16,7 @@ import { ViewFilterService } from 'src/engine/core-modules/view/services/view-fi describe('ViewFilterService', () => { let viewFilterService: ViewFilterService; - let viewFilterRepository: Repository; + let viewFilterRepository: Repository; const mockViewFilter = { id: 'view-filter-id', @@ -29,14 +29,14 @@ describe('ViewFilterService', () => { createdAt: new Date(), updatedAt: new Date(), deletedAt: null, - } as ViewFilter; + } as ViewFilterEntity; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ ViewFilterService, { - provide: getRepositoryToken(ViewFilter, 'core'), + provide: getRepositoryToken(ViewFilterEntity, 'core'), useValue: { find: jest.fn(), findOne: jest.fn(), @@ -50,8 +50,8 @@ describe('ViewFilterService', () => { }).compile(); viewFilterService = module.get(ViewFilterService); - viewFilterRepository = module.get>( - getRepositoryToken(ViewFilter, 'core'), + viewFilterRepository = module.get>( + getRepositoryToken(ViewFilterEntity, 'core'), ); }); diff --git a/packages/twenty-server/src/engine/core-modules/view/services/tests/view-group.service.spec.ts b/packages/twenty-server/src/engine/core-modules/view/services/tests/view-group.service.spec.ts index f383a1da7d..062d4dc7ec 100644 --- a/packages/twenty-server/src/engine/core-modules/view/services/tests/view-group.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/view/services/tests/view-group.service.spec.ts @@ -3,7 +3,7 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { type Repository } from 'typeorm'; -import { ViewGroup } from 'src/engine/core-modules/view/entities/view-group.entity'; +import { ViewGroupEntity } from 'src/engine/core-modules/view/entities/view-group.entity'; import { ViewGroupException, ViewGroupExceptionCode, @@ -15,7 +15,7 @@ import { ViewGroupService } from 'src/engine/core-modules/view/services/view-gro describe('ViewGroupService', () => { let viewGroupService: ViewGroupService; - let viewGroupRepository: Repository; + let viewGroupRepository: Repository; const mockViewGroup = { id: 'view-group-id', @@ -28,14 +28,14 @@ describe('ViewGroupService', () => { createdAt: new Date(), updatedAt: new Date(), deletedAt: null, - } as ViewGroup; + } as ViewGroupEntity; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ ViewGroupService, { - provide: getRepositoryToken(ViewGroup, 'core'), + provide: getRepositoryToken(ViewGroupEntity, 'core'), useValue: { find: jest.fn(), findOne: jest.fn(), @@ -49,8 +49,8 @@ describe('ViewGroupService', () => { }).compile(); viewGroupService = module.get(ViewGroupService); - viewGroupRepository = module.get>( - getRepositoryToken(ViewGroup, 'core'), + viewGroupRepository = module.get>( + getRepositoryToken(ViewGroupEntity, 'core'), ); }); diff --git a/packages/twenty-server/src/engine/core-modules/view/services/tests/view-sort.service.spec.ts b/packages/twenty-server/src/engine/core-modules/view/services/tests/view-sort.service.spec.ts index 0a3dc4613e..207bc39523 100644 --- a/packages/twenty-server/src/engine/core-modules/view/services/tests/view-sort.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/view/services/tests/view-sort.service.spec.ts @@ -3,7 +3,7 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { type Repository } from 'typeorm'; -import { ViewSort } from 'src/engine/core-modules/view/entities/view-sort.entity'; +import { ViewSortEntity } from 'src/engine/core-modules/view/entities/view-sort.entity'; import { ViewSortDirection } from 'src/engine/core-modules/view/enums/view-sort-direction'; import { ViewSortException, @@ -16,7 +16,7 @@ import { ViewSortService } from 'src/engine/core-modules/view/services/view-sort describe('ViewSortService', () => { let viewSortService: ViewSortService; - let viewSortRepository: Repository; + let viewSortRepository: Repository; const mockViewSort = { id: 'view-sort-id', @@ -27,14 +27,14 @@ describe('ViewSortService', () => { createdAt: new Date(), updatedAt: new Date(), deletedAt: null, - } as ViewSort; + } as ViewSortEntity; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ ViewSortService, { - provide: getRepositoryToken(ViewSort, 'core'), + provide: getRepositoryToken(ViewSortEntity, 'core'), useValue: { find: jest.fn(), findOne: jest.fn(), @@ -48,8 +48,8 @@ describe('ViewSortService', () => { }).compile(); viewSortService = module.get(ViewSortService); - viewSortRepository = module.get>( - getRepositoryToken(ViewSort, 'core'), + viewSortRepository = module.get>( + getRepositoryToken(ViewSortEntity, 'core'), ); }); diff --git a/packages/twenty-server/src/engine/core-modules/view/services/tests/view.service.spec.ts b/packages/twenty-server/src/engine/core-modules/view/services/tests/view.service.spec.ts index 1dda2644c4..99875db609 100644 --- a/packages/twenty-server/src/engine/core-modules/view/services/tests/view.service.spec.ts +++ b/packages/twenty-server/src/engine/core-modules/view/services/tests/view.service.spec.ts @@ -3,7 +3,7 @@ import { getRepositoryToken } from '@nestjs/typeorm'; import { type Repository } from 'typeorm'; -import { View } from 'src/engine/core-modules/view/entities/view.entity'; +import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { ViewOpenRecordIn } from 'src/engine/core-modules/view/enums/view-open-record-in'; import { ViewType } from 'src/engine/core-modules/view/enums/view-type.enum'; import { @@ -17,7 +17,7 @@ import { ViewService } from 'src/engine/core-modules/view/services/view.service' describe('ViewService', () => { let viewService: ViewService; - let viewRepository: Repository; + let viewRepository: Repository; const mockView = { id: 'view-id', @@ -37,14 +37,14 @@ describe('ViewService', () => { createdAt: new Date(), updatedAt: new Date(), deletedAt: null, - } as View; + } as ViewEntity; beforeEach(async () => { const module: TestingModule = await Test.createTestingModule({ providers: [ ViewService, { - provide: getRepositoryToken(View, 'core'), + provide: getRepositoryToken(ViewEntity, 'core'), useValue: { find: jest.fn(), findOne: jest.fn(), @@ -58,8 +58,8 @@ describe('ViewService', () => { }).compile(); viewService = module.get(ViewService); - viewRepository = module.get>( - getRepositoryToken(View, 'core'), + viewRepository = module.get>( + getRepositoryToken(ViewEntity, 'core'), ); }); diff --git a/packages/twenty-server/src/engine/core-modules/view/services/view-field.service.ts b/packages/twenty-server/src/engine/core-modules/view/services/view-field.service.ts index 20d8dc69b7..aabdd54ded 100644 --- a/packages/twenty-server/src/engine/core-modules/view/services/view-field.service.ts +++ b/packages/twenty-server/src/engine/core-modules/view/services/view-field.service.ts @@ -4,7 +4,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { isDefined } from 'twenty-shared/utils'; import { IsNull, Repository } from 'typeorm'; -import { ViewField } from 'src/engine/core-modules/view/entities/view-field.entity'; +import { ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; import { ViewFieldException, ViewFieldExceptionCode, @@ -16,11 +16,11 @@ import { @Injectable() export class ViewFieldService { constructor( - @InjectRepository(ViewField, 'core') - private readonly viewFieldRepository: Repository, + @InjectRepository(ViewFieldEntity, 'core') + private readonly viewFieldRepository: Repository, ) {} - async findByWorkspaceId(workspaceId: string): Promise { + async findByWorkspaceId(workspaceId: string): Promise { return this.viewFieldRepository.find({ where: { workspaceId, @@ -34,7 +34,7 @@ export class ViewFieldService { async findByViewId( workspaceId: string, viewId: string, - ): Promise { + ): Promise { return this.viewFieldRepository.find({ where: { workspaceId, @@ -46,7 +46,10 @@ export class ViewFieldService { }); } - async findById(id: string, workspaceId: string): Promise { + async findById( + id: string, + workspaceId: string, + ): Promise { const viewField = await this.viewFieldRepository.findOne({ where: { id, @@ -59,7 +62,9 @@ export class ViewFieldService { return viewField || null; } - async create(viewFieldData: Partial): Promise { + async create( + viewFieldData: Partial, + ): Promise { if (!isDefined(viewFieldData.workspaceId)) { throw new ViewFieldException( generateViewFieldExceptionMessage( @@ -110,8 +115,8 @@ export class ViewFieldService { async update( id: string, workspaceId: string, - updateData: Partial, - ): Promise { + updateData: Partial, + ): Promise { const existingViewField = await this.findById(id, workspaceId); if (!isDefined(existingViewField)) { @@ -132,7 +137,7 @@ export class ViewFieldService { return { ...existingViewField, ...updatedViewField }; } - async delete(id: string, workspaceId: string): Promise { + async delete(id: string, workspaceId: string): Promise { const viewField = await this.findById(id, workspaceId); if (!isDefined(viewField)) { diff --git a/packages/twenty-server/src/engine/core-modules/view/services/view-filter-group.service.ts b/packages/twenty-server/src/engine/core-modules/view/services/view-filter-group.service.ts index 3632fce0c5..a8035a6a71 100644 --- a/packages/twenty-server/src/engine/core-modules/view/services/view-filter-group.service.ts +++ b/packages/twenty-server/src/engine/core-modules/view/services/view-filter-group.service.ts @@ -4,7 +4,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { isDefined } from 'twenty-shared/utils'; import { IsNull, Repository } from 'typeorm'; -import { ViewFilterGroup } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; +import { ViewFilterGroupEntity } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; import { ViewFilterGroupException, ViewFilterGroupExceptionCode, @@ -16,11 +16,13 @@ import { @Injectable() export class ViewFilterGroupService { constructor( - @InjectRepository(ViewFilterGroup, 'core') - private readonly viewFilterGroupRepository: Repository, + @InjectRepository(ViewFilterGroupEntity, 'core') + private readonly viewFilterGroupRepository: Repository, ) {} - async findByWorkspaceId(workspaceId: string): Promise { + async findByWorkspaceId( + workspaceId: string, + ): Promise { return this.viewFilterGroupRepository.find({ where: { workspaceId, @@ -40,7 +42,7 @@ export class ViewFilterGroupService { async findByViewId( workspaceId: string, viewId: string, - ): Promise { + ): Promise { return this.viewFilterGroupRepository.find({ where: { workspaceId, @@ -61,7 +63,7 @@ export class ViewFilterGroupService { async findById( id: string, workspaceId: string, - ): Promise { + ): Promise { const viewFilterGroup = await this.viewFilterGroupRepository.findOne({ where: { id, @@ -81,8 +83,8 @@ export class ViewFilterGroupService { } async create( - viewFilterGroupData: Partial, - ): Promise { + viewFilterGroupData: Partial, + ): Promise { if (!isDefined(viewFilterGroupData.workspaceId)) { throw new ViewFilterGroupException( generateViewFilterGroupExceptionMessage( @@ -122,8 +124,8 @@ export class ViewFilterGroupService { async update( id: string, workspaceId: string, - updateData: Partial, - ): Promise { + updateData: Partial, + ): Promise { const existingViewFilterGroup = await this.findById(id, workspaceId); if (!isDefined(existingViewFilterGroup)) { @@ -144,7 +146,10 @@ export class ViewFilterGroupService { return { ...existingViewFilterGroup, ...updatedViewFilterGroup }; } - async delete(id: string, workspaceId: string): Promise { + async delete( + id: string, + workspaceId: string, + ): Promise { const viewFilterGroup = await this.findById(id, workspaceId); if (!isDefined(viewFilterGroup)) { diff --git a/packages/twenty-server/src/engine/core-modules/view/services/view-filter.service.ts b/packages/twenty-server/src/engine/core-modules/view/services/view-filter.service.ts index 2ec90823e1..faf4d3c6e4 100644 --- a/packages/twenty-server/src/engine/core-modules/view/services/view-filter.service.ts +++ b/packages/twenty-server/src/engine/core-modules/view/services/view-filter.service.ts @@ -4,7 +4,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { isDefined } from 'twenty-shared/utils'; import { IsNull, Repository } from 'typeorm'; -import { ViewFilter } from 'src/engine/core-modules/view/entities/view-filter.entity'; +import { ViewFilterEntity } from 'src/engine/core-modules/view/entities/view-filter.entity'; import { ViewFilterException, ViewFilterExceptionCode, @@ -16,11 +16,11 @@ import { @Injectable() export class ViewFilterService { constructor( - @InjectRepository(ViewFilter, 'core') - private readonly viewFilterRepository: Repository, + @InjectRepository(ViewFilterEntity, 'core') + private readonly viewFilterRepository: Repository, ) {} - async findByWorkspaceId(workspaceId: string): Promise { + async findByWorkspaceId(workspaceId: string): Promise { return this.viewFilterRepository.find({ where: { workspaceId, @@ -34,7 +34,7 @@ export class ViewFilterService { async findByViewId( workspaceId: string, viewId: string, - ): Promise { + ): Promise { return this.viewFilterRepository.find({ where: { workspaceId, @@ -46,7 +46,10 @@ export class ViewFilterService { }); } - async findById(id: string, workspaceId: string): Promise { + async findById( + id: string, + workspaceId: string, + ): Promise { const viewFilter = await this.viewFilterRepository.findOne({ where: { id, @@ -59,7 +62,9 @@ export class ViewFilterService { return viewFilter || null; } - async create(viewFilterData: Partial): Promise { + async create( + viewFilterData: Partial, + ): Promise { if (!isDefined(viewFilterData.workspaceId)) { throw new ViewFilterException( generateViewFilterExceptionMessage( @@ -110,8 +115,8 @@ export class ViewFilterService { async update( id: string, workspaceId: string, - updateData: Partial, - ): Promise { + updateData: Partial, + ): Promise { const existingViewFilter = await this.findById(id, workspaceId); if (!isDefined(existingViewFilter)) { @@ -132,7 +137,7 @@ export class ViewFilterService { return { ...existingViewFilter, ...updatedViewFilter }; } - async delete(id: string, workspaceId: string): Promise { + async delete(id: string, workspaceId: string): Promise { const viewFilter = await this.findById(id, workspaceId); if (!isDefined(viewFilter)) { diff --git a/packages/twenty-server/src/engine/core-modules/view/services/view-group.service.ts b/packages/twenty-server/src/engine/core-modules/view/services/view-group.service.ts index 85d95b5cbf..4419557915 100644 --- a/packages/twenty-server/src/engine/core-modules/view/services/view-group.service.ts +++ b/packages/twenty-server/src/engine/core-modules/view/services/view-group.service.ts @@ -4,7 +4,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { isDefined } from 'twenty-shared/utils'; import { IsNull, Repository } from 'typeorm'; -import { ViewGroup } from 'src/engine/core-modules/view/entities/view-group.entity'; +import { ViewGroupEntity } from 'src/engine/core-modules/view/entities/view-group.entity'; import { ViewGroupException, ViewGroupExceptionCode, @@ -16,11 +16,11 @@ import { @Injectable() export class ViewGroupService { constructor( - @InjectRepository(ViewGroup, 'core') - private readonly viewGroupRepository: Repository, + @InjectRepository(ViewGroupEntity, 'core') + private readonly viewGroupRepository: Repository, ) {} - async findByWorkspaceId(workspaceId: string): Promise { + async findByWorkspaceId(workspaceId: string): Promise { return this.viewGroupRepository.find({ where: { workspaceId, @@ -34,7 +34,7 @@ export class ViewGroupService { async findByViewId( workspaceId: string, viewId: string, - ): Promise { + ): Promise { return this.viewGroupRepository.find({ where: { workspaceId, @@ -46,7 +46,10 @@ export class ViewGroupService { }); } - async findById(id: string, workspaceId: string): Promise { + async findById( + id: string, + workspaceId: string, + ): Promise { const viewGroup = await this.viewGroupRepository.findOne({ where: { id, @@ -59,7 +62,9 @@ export class ViewGroupService { return viewGroup || null; } - async create(viewGroupData: Partial): Promise { + async create( + viewGroupData: Partial, + ): Promise { if (!isDefined(viewGroupData.workspaceId)) { throw new ViewGroupException( generateViewGroupExceptionMessage( @@ -110,8 +115,8 @@ export class ViewGroupService { async update( id: string, workspaceId: string, - updateData: Partial, - ): Promise { + updateData: Partial, + ): Promise { const existingViewGroup = await this.findById(id, workspaceId); if (!isDefined(existingViewGroup)) { @@ -132,7 +137,7 @@ export class ViewGroupService { return { ...existingViewGroup, ...updatedViewGroup }; } - async delete(id: string, workspaceId: string): Promise { + async delete(id: string, workspaceId: string): Promise { const viewGroup = await this.findById(id, workspaceId); if (!isDefined(viewGroup)) { diff --git a/packages/twenty-server/src/engine/core-modules/view/services/view-sort.service.ts b/packages/twenty-server/src/engine/core-modules/view/services/view-sort.service.ts index ac4fb052ea..de0a2d2a97 100644 --- a/packages/twenty-server/src/engine/core-modules/view/services/view-sort.service.ts +++ b/packages/twenty-server/src/engine/core-modules/view/services/view-sort.service.ts @@ -4,7 +4,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { isDefined } from 'twenty-shared/utils'; import { IsNull, Repository } from 'typeorm'; -import { ViewSort } from 'src/engine/core-modules/view/entities/view-sort.entity'; +import { ViewSortEntity } from 'src/engine/core-modules/view/entities/view-sort.entity'; import { ViewSortException, ViewSortExceptionCode, @@ -16,11 +16,11 @@ import { @Injectable() export class ViewSortService { constructor( - @InjectRepository(ViewSort, 'core') - private readonly viewSortRepository: Repository, + @InjectRepository(ViewSortEntity, 'core') + private readonly viewSortRepository: Repository, ) {} - async findByWorkspaceId(workspaceId: string): Promise { + async findByWorkspaceId(workspaceId: string): Promise { return this.viewSortRepository.find({ where: { workspaceId, @@ -30,7 +30,10 @@ export class ViewSortService { }); } - async findByViewId(workspaceId: string, viewId: string): Promise { + async findByViewId( + workspaceId: string, + viewId: string, + ): Promise { return this.viewSortRepository.find({ where: { workspaceId, @@ -41,7 +44,10 @@ export class ViewSortService { }); } - async findById(id: string, workspaceId: string): Promise { + async findById( + id: string, + workspaceId: string, + ): Promise { const viewSort = await this.viewSortRepository.findOne({ where: { id, @@ -54,7 +60,7 @@ export class ViewSortService { return viewSort || null; } - async create(viewSortData: Partial): Promise { + async create(viewSortData: Partial): Promise { if (!isDefined(viewSortData.workspaceId)) { throw new ViewSortException( generateViewSortExceptionMessage( @@ -105,8 +111,8 @@ export class ViewSortService { async update( id: string, workspaceId: string, - updateData: Partial, - ): Promise { + updateData: Partial, + ): Promise { const existingViewSort = await this.findById(id, workspaceId); if (!isDefined(existingViewSort)) { @@ -127,7 +133,7 @@ export class ViewSortService { return { ...existingViewSort, ...updatedViewSort }; } - async delete(id: string, workspaceId: string): Promise { + async delete(id: string, workspaceId: string): Promise { const viewSort = await this.findById(id, workspaceId); if (!isDefined(viewSort)) { diff --git a/packages/twenty-server/src/engine/core-modules/view/services/view.service.ts b/packages/twenty-server/src/engine/core-modules/view/services/view.service.ts index 9f406e6417..536efdd274 100644 --- a/packages/twenty-server/src/engine/core-modules/view/services/view.service.ts +++ b/packages/twenty-server/src/engine/core-modules/view/services/view.service.ts @@ -4,7 +4,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { isDefined } from 'twenty-shared/utils'; import { IsNull, Repository } from 'typeorm'; -import { View } from 'src/engine/core-modules/view/entities/view.entity'; +import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { ViewException, ViewExceptionCode, @@ -16,11 +16,11 @@ import { @Injectable() export class ViewService { constructor( - @InjectRepository(View, 'core') - private readonly viewRepository: Repository, + @InjectRepository(ViewEntity, 'core') + private readonly viewRepository: Repository, ) {} - async findByWorkspaceId(workspaceId: string): Promise { + async findByWorkspaceId(workspaceId: string): Promise { return this.viewRepository.find({ where: { workspaceId, @@ -41,7 +41,7 @@ export class ViewService { async findByObjectMetadataId( workspaceId: string, objectMetadataId: string, - ): Promise { + ): Promise { return this.viewRepository.find({ where: { workspaceId, @@ -60,7 +60,7 @@ export class ViewService { }); } - async findById(id: string, workspaceId: string): Promise { + async findById(id: string, workspaceId: string): Promise { const view = await this.viewRepository.findOne({ where: { id, @@ -80,7 +80,7 @@ export class ViewService { return view || null; } - async create(viewData: Partial): Promise { + async create(viewData: Partial): Promise { if (!isDefined(viewData.workspaceId)) { throw new ViewException( generateViewExceptionMessage( @@ -120,8 +120,8 @@ export class ViewService { async update( id: string, workspaceId: string, - updateData: Partial, - ): Promise { + updateData: Partial, + ): Promise { const existingView = await this.findById(id, workspaceId); if (!isDefined(existingView)) { @@ -142,7 +142,7 @@ export class ViewService { return { ...existingView, ...updatedView }; } - async delete(id: string, workspaceId: string): Promise { + async delete(id: string, workspaceId: string): Promise { const view = await this.findById(id, workspaceId); if (!isDefined(view)) { diff --git a/packages/twenty-server/src/engine/core-modules/view/view.module.ts b/packages/twenty-server/src/engine/core-modules/view/view.module.ts index 6b7ad10f31..854e9ce353 100644 --- a/packages/twenty-server/src/engine/core-modules/view/view.module.ts +++ b/packages/twenty-server/src/engine/core-modules/view/view.module.ts @@ -8,12 +8,12 @@ import { ViewFilterController } from 'src/engine/core-modules/view/controllers/v import { ViewGroupController } from 'src/engine/core-modules/view/controllers/view-group.controller'; import { ViewSortController } from 'src/engine/core-modules/view/controllers/view-sort.controller'; import { ViewController } from 'src/engine/core-modules/view/controllers/view.controller'; -import { ViewField } from 'src/engine/core-modules/view/entities/view-field.entity'; -import { ViewFilterGroup } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; -import { ViewFilter } from 'src/engine/core-modules/view/entities/view-filter.entity'; -import { ViewGroup } from 'src/engine/core-modules/view/entities/view-group.entity'; -import { ViewSort } from 'src/engine/core-modules/view/entities/view-sort.entity'; -import { View } from 'src/engine/core-modules/view/entities/view.entity'; +import { ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; +import { ViewFilterGroupEntity } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; +import { ViewFilterEntity } from 'src/engine/core-modules/view/entities/view-filter.entity'; +import { ViewGroupEntity } from 'src/engine/core-modules/view/entities/view-group.entity'; +import { ViewSortEntity } from 'src/engine/core-modules/view/entities/view-sort.entity'; +import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { ViewFieldResolver } from 'src/engine/core-modules/view/resolvers/view-field.resolver'; import { ViewFilterGroupResolver } from 'src/engine/core-modules/view/resolvers/view-filter-group.resolver'; import { ViewFilterResolver } from 'src/engine/core-modules/view/resolvers/view-filter.resolver'; @@ -32,7 +32,14 @@ import { WorkspaceCacheStorageModule } from 'src/engine/workspace-cache-storage/ @Module({ imports: [ TypeOrmModule.forFeature( - [View, ViewField, ViewFilter, ViewFilterGroup, ViewGroup, ViewSort], + [ + ViewEntity, + ViewFieldEntity, + ViewFilterEntity, + ViewFilterGroupEntity, + ViewGroupEntity, + ViewSortEntity, + ], 'core', ), I18nModule, diff --git a/packages/twenty-server/src/engine/core-modules/workspace/workspace.entity.ts b/packages/twenty-server/src/engine/core-modules/workspace/workspace.entity.ts index 30f8d25bae..193a87ab3a 100644 --- a/packages/twenty-server/src/engine/core-modules/workspace/workspace.entity.ts +++ b/packages/twenty-server/src/engine/core-modules/workspace/workspace.entity.ts @@ -30,12 +30,12 @@ import { ViewFilterDTO } from 'src/engine/core-modules/view/dtos/view-filter.dto import { ViewGroupDTO } from 'src/engine/core-modules/view/dtos/view-group.dto'; import { ViewSortDTO } from 'src/engine/core-modules/view/dtos/view-sort.dto'; import { ViewDTO } from 'src/engine/core-modules/view/dtos/view.dto'; -import { ViewField } from 'src/engine/core-modules/view/entities/view-field.entity'; -import { ViewFilterGroup } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; -import { ViewFilter } from 'src/engine/core-modules/view/entities/view-filter.entity'; -import { ViewGroup } from 'src/engine/core-modules/view/entities/view-group.entity'; -import { ViewSort } from 'src/engine/core-modules/view/entities/view-sort.entity'; -import { View } from 'src/engine/core-modules/view/entities/view.entity'; +import { ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; +import { ViewFilterGroupEntity } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; +import { ViewFilterEntity } from 'src/engine/core-modules/view/entities/view-filter.entity'; +import { ViewGroupEntity } from 'src/engine/core-modules/view/entities/view-group.entity'; +import { ViewSortEntity } from 'src/engine/core-modules/view/entities/view-sort.entity'; +import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { Webhook } from 'src/engine/core-modules/webhook/webhook.entity'; import { AgentHandoffEntity } from 'src/engine/metadata-modules/agent/agent-handoff.entity'; import { AgentEntity } from 'src/engine/metadata-modules/agent/agent.entity'; @@ -157,31 +157,31 @@ export class Workspace { apiKeys: Relation; @Field(() => [ViewDTO], { nullable: true }) - @OneToMany(() => View, (view) => view.workspace) - views: Relation; + @OneToMany(() => ViewEntity, (view) => view.workspace) + views: Relation; @Field(() => [ViewFieldDTO], { nullable: true }) - @OneToMany(() => ViewField, (viewField) => viewField.workspace) - viewFields: Relation; + @OneToMany(() => ViewFieldEntity, (viewField) => viewField.workspace) + viewFields: Relation; @Field(() => [ViewFilterDTO], { nullable: true }) - @OneToMany(() => ViewFilter, (viewFilter) => viewFilter.workspace) - viewFilters: Relation; + @OneToMany(() => ViewFilterEntity, (viewFilter) => viewFilter.workspace) + viewFilters: Relation; @Field(() => [ViewFilterGroupDTO], { nullable: true }) @OneToMany( - () => ViewFilterGroup, + () => ViewFilterGroupEntity, (viewFilterGroup) => viewFilterGroup.workspace, ) - viewFilterGroups: Relation; + viewFilterGroups: Relation; @Field(() => [ViewGroupDTO], { nullable: true }) - @OneToMany(() => ViewGroup, (viewGroup) => viewGroup.workspace) - viewGroups: Relation; + @OneToMany(() => ViewGroupEntity, (viewGroup) => viewGroup.workspace) + viewGroups: Relation; @Field(() => [ViewSortDTO], { nullable: true }) - @OneToMany(() => ViewSort, (viewSort) => viewSort.workspace) - viewSorts: Relation; + @OneToMany(() => ViewSortEntity, (viewSort) => viewSort.workspace) + viewSorts: Relation; @Field() @Column({ default: 1 }) diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata-v2.service.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata-v2.service.ts index 3b8b0d8fda..1bf8e6da86 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata-v2.service.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata-v2.service.ts @@ -4,7 +4,7 @@ import { InjectRepository } from '@nestjs/typeorm'; import { isDefined } from 'twenty-shared/utils'; import { Repository } from 'typeorm'; -import { View } from 'src/engine/core-modules/view/entities/view.entity'; +import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { ViewKey } from 'src/engine/core-modules/view/enums/view-key.enum'; import { addFlatFieldMetadataInFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-field-metadata-in-flat-object-metadata-maps-or-throw.util'; import { addFlatObjectMetadataToFlatObjectMetadataMapsOrThrow } from 'src/engine/metadata-modules/flat-object-metadata-maps/utils/add-flat-object-metadata-to-flat-object-metadata-maps-or-throw.util'; @@ -37,8 +37,8 @@ export class ObjectMetadataServiceV2 { private readonly workspaceMetadataCacheService: WorkspaceMetadataCacheService, private readonly workspaceMigrationValidateBuildAndRunService: WorkspaceMigrationValidateBuildAndRunService, private readonly objectMetadataRelatedRecordsService: ObjectMetadataRelatedRecordsService, - @InjectRepository(View, 'core') - private readonly viewRepository: Repository, + @InjectRepository(ViewEntity, 'core') + private readonly viewRepository: Repository, ) {} async updateOne({ diff --git a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.module.ts b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.module.ts index 4554d56501..6ead17a489 100644 --- a/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.module.ts +++ b/packages/twenty-server/src/engine/metadata-modules/object-metadata/object-metadata.module.ts @@ -11,7 +11,7 @@ import { NestjsQueryTypeOrmModule } from '@ptc-org/nestjs-query-typeorm'; import { TypeORMModule } from 'src/database/typeorm/typeorm.module'; import { FeatureFlag } from 'src/engine/core-modules/feature-flag/feature-flag.entity'; import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; -import { View } from 'src/engine/core-modules/view/entities/view.entity'; +import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { SettingsPermissionsGuard } from 'src/engine/guards/settings-permissions.guard'; import { WorkspaceAuthGuard } from 'src/engine/guards/workspace-auth.guard'; import { DataSourceModule } from 'src/engine/metadata-modules/data-source/data-source.module'; @@ -56,7 +56,7 @@ import { WorkspaceMigrationV2Module } from 'src/engine/workspace-manager/workspa [ObjectMetadataEntity, FieldMetadataEntity], 'core', ), - TypeOrmModule.forFeature([FeatureFlag, View], 'core'), + TypeOrmModule.forFeature([FeatureFlag, ViewEntity], 'core'), DataSourceModule, WorkspaceMigrationModule, WorkspaceMigrationRunnerModule, diff --git a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-core-views.ts b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-core-views.ts index fc35a399c1..d243cbd901 100644 --- a/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-core-views.ts +++ b/packages/twenty-server/src/engine/workspace-manager/standard-objects-prefill-data/prefill-core-views.ts @@ -3,10 +3,10 @@ import { type ViewFilterOperand as SharedViewFilterOperand } from 'twenty-shared import { type DataSource, type QueryRunner } from 'typeorm'; import { v4 } from 'uuid'; -import { ViewField } from 'src/engine/core-modules/view/entities/view-field.entity'; -import { ViewFilter } from 'src/engine/core-modules/view/entities/view-filter.entity'; -import { ViewGroup } from 'src/engine/core-modules/view/entities/view-group.entity'; -import { View } from 'src/engine/core-modules/view/entities/view.entity'; +import { ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; +import { ViewFilterEntity } from 'src/engine/core-modules/view/entities/view-filter.entity'; +import { ViewGroupEntity } from 'src/engine/core-modules/view/entities/view-group.entity'; +import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { ViewKey } from 'src/engine/core-modules/view/enums/view-key.enum'; import { ViewOpenRecordIn } from 'src/engine/core-modules/view/enums/view-open-record-in'; import { ViewType } from 'src/engine/core-modules/view/enums/view-type.enum'; @@ -30,7 +30,7 @@ export const prefillCoreViews = async ( dataSource: DataSource, workspaceId: string, objectMetadataItems: ObjectMetadataEntity[], -): Promise => { +): Promise => { const views = [ companiesAllView(objectMetadataItems, true), peopleAllView(objectMetadataItems, true), @@ -71,13 +71,13 @@ const createCoreViews = async ( queryRunner: QueryRunner, workspaceId: string, viewDefinitions: ViewDefinition[], -): Promise => { +): Promise => { const viewDefinitionsWithId = viewDefinitions.map((viewDefinition) => ({ ...viewDefinition, id: v4(), })); - const coreViews: Partial[] = viewDefinitionsWithId.map( + const coreViews: Partial[] = viewDefinitionsWithId.map( ({ id, name, @@ -111,30 +111,30 @@ const createCoreViews = async ( }), ); - const viewRepository = queryRunner.manager.getRepository(View); + const viewRepository = queryRunner.manager.getRepository(ViewEntity); const createdViews = await viewRepository.save(coreViews); for (const viewDefinition of viewDefinitionsWithId) { if (viewDefinition.fields && viewDefinition.fields.length > 0) { - const coreViewFields: Partial[] = viewDefinition.fields.map( - (field) => ({ + const coreViewFields: Partial[] = + viewDefinition.fields.map((field) => ({ fieldMetadataId: field.fieldMetadataId, position: field.position, isVisible: field.isVisible, size: field.size, viewId: viewDefinition.id, workspaceId, - }), - ); + })); - const viewFieldRepository = queryRunner.manager.getRepository(ViewField); + const viewFieldRepository = + queryRunner.manager.getRepository(ViewFieldEntity); await viewFieldRepository.save(coreViewFields); } if (viewDefinition.filters && viewDefinition.filters.length > 0) { - const coreViewFilters: Partial[] = viewDefinition.filters.map( - (filter) => ({ + const coreViewFilters: Partial[] = + viewDefinition.filters.map((filter) => ({ fieldMetadataId: filter.fieldMetadataId, viewId: viewDefinition.id, operand: convertViewFilterOperandToCoreOperand( @@ -142,11 +142,10 @@ const createCoreViews = async ( ), value: filter.value, workspaceId, - }), - ); + })); const viewFilterRepository = - queryRunner.manager.getRepository(ViewFilter); + queryRunner.manager.getRepository(ViewFilterEntity); await viewFilterRepository.save(coreViewFilters); } @@ -156,18 +155,18 @@ const createCoreViews = async ( viewDefinition.groups && viewDefinition.groups.length > 0 ) { - const coreViewGroups: Partial[] = viewDefinition.groups.map( - (group) => ({ + const coreViewGroups: Partial[] = + viewDefinition.groups.map((group) => ({ fieldMetadataId: group.fieldMetadataId, isVisible: group.isVisible, fieldValue: group.fieldValue, position: group.position, viewId: viewDefinition.id, workspaceId, - }), - ); + })); - const viewGroupRepository = queryRunner.manager.getRepository(ViewGroup); + const viewGroupRepository = + queryRunner.manager.getRepository(ViewGroupEntity); await viewGroupRepository.save(coreViewGroups); } diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/types/flat-view-field.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/types/flat-view-field.type.ts index 547a9420fe..6d65839fba 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/types/flat-view-field.type.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/types/flat-view-field.type.ts @@ -1,6 +1,6 @@ -import { type ViewField } from 'src/engine/core-modules/view/entities/view-field.entity'; +import { type ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; export type FlatViewField = Pick< - ViewField, + ViewFieldEntity, 'fieldMetadataId' | 'position' | 'isVisible' | 'size' >; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/types/flat-view.type.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/types/flat-view.type.ts index ba26137371..d81b0502b0 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/types/flat-view.type.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/types/flat-view.type.ts @@ -1,8 +1,8 @@ -import { type View } from 'src/engine/core-modules/view/entities/view.entity'; +import { type ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { type FlatViewField } from 'src/engine/workspace-manager/workspace-migration-v2/types/flat-view-field.type'; export type FlatView = Pick< - View, + ViewEntity, 'name' | 'objectMetadataId' | 'type' | 'isCustom' | 'key' | 'icon' > & { viewFields: FlatViewField[]; diff --git a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view/services/create-view-action-handler.service.ts b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view/services/create-view-action-handler.service.ts index b9b90ea255..fe80a6628a 100644 --- a/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view/services/create-view-action-handler.service.ts +++ b/packages/twenty-server/src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/action-handlers/view/services/create-view-action-handler.service.ts @@ -2,8 +2,8 @@ import { Injectable } from '@nestjs/common'; import { WorkspaceMigrationRunnerActionHandler } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/interfaces/workspace-migration-runner-action-handler-service.interface'; -import { ViewField } from 'src/engine/core-modules/view/entities/view-field.entity'; -import { View } from 'src/engine/core-modules/view/entities/view.entity'; +import { ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; +import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { CreateViewAction } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-builder-v2/types/workspace-migration-view-action-v2.type'; import { WorkspaceMigrationActionRunnerArgs } from 'src/engine/workspace-manager/workspace-migration-v2/workspace-migration-runner-v2/types/workspace-migration-action-runner-args.type'; @@ -23,9 +23,10 @@ export class CreateViewActionHandlerService extends WorkspaceMigrationRunnerActi const { viewFields } = view; - const viewRepository = queryRunner.manager.getRepository(View); + const viewRepository = + queryRunner.manager.getRepository(ViewEntity); const viewFieldRepository = - queryRunner.manager.getRepository(ViewField); + queryRunner.manager.getRepository(ViewFieldEntity); const createdView = await viewRepository.save({ ...view, diff --git a/packages/twenty-server/src/modules/view/services/view-field-sync.service.ts b/packages/twenty-server/src/modules/view/services/view-field-sync.service.ts index 6425072cf4..b4dfc2f33d 100644 --- a/packages/twenty-server/src/modules/view/services/view-field-sync.service.ts +++ b/packages/twenty-server/src/modules/view/services/view-field-sync.service.ts @@ -5,19 +5,19 @@ import { isDefined } from 'twenty-shared/utils'; import { Repository } from 'typeorm'; import { type ObjectRecordDiff } from 'src/engine/core-modules/event-emitter/types/object-record-diff'; -import { ViewField } from 'src/engine/core-modules/view/entities/view-field.entity'; +import { ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; import { type ViewFieldWorkspaceEntity } from 'src/modules/view/standard-objects/view-field.workspace-entity'; @Injectable() export class ViewFieldSyncService { constructor( - @InjectRepository(ViewField, 'core') - private readonly coreViewFieldRepository: Repository, + @InjectRepository(ViewFieldEntity, 'core') + private readonly coreViewFieldRepository: Repository, ) {} private parseUpdateDataFromDiff( diff: Partial>, - ): Partial { + ): Partial { const updateData: Record = {}; for (const key of Object.keys(diff)) { @@ -28,14 +28,14 @@ export class ViewFieldSyncService { } } - return updateData as Partial; + return updateData as Partial; } public async createCoreViewField( workspaceId: string, workspaceViewField: ViewFieldWorkspaceEntity, ): Promise { - const coreViewField: Partial = { + const coreViewField: Partial = { id: workspaceViewField.id, fieldMetadataId: workspaceViewField.fieldMetadataId, viewId: workspaceViewField.viewId, diff --git a/packages/twenty-server/src/modules/view/services/view-filter-group-sync.service.ts b/packages/twenty-server/src/modules/view/services/view-filter-group-sync.service.ts index c92a97dc63..1c352feebc 100644 --- a/packages/twenty-server/src/modules/view/services/view-filter-group-sync.service.ts +++ b/packages/twenty-server/src/modules/view/services/view-filter-group-sync.service.ts @@ -5,20 +5,20 @@ import { isDefined } from 'twenty-shared/utils'; import { Repository } from 'typeorm'; import { type ObjectRecordDiff } from 'src/engine/core-modules/event-emitter/types/object-record-diff'; -import { ViewFilterGroup } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; +import { ViewFilterGroupEntity } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; import { type ViewFilterGroupLogicalOperator } from 'src/engine/core-modules/view/enums/view-filter-group-logical-operator'; import { type ViewFilterGroupWorkspaceEntity } from 'src/modules/view/standard-objects/view-filter-group.workspace-entity'; @Injectable() export class ViewFilterGroupSyncService { constructor( - @InjectRepository(ViewFilterGroup, 'core') - private readonly coreViewFilterGroupRepository: Repository, + @InjectRepository(ViewFilterGroupEntity, 'core') + private readonly coreViewFilterGroupRepository: Repository, ) {} private parseUpdateDataFromDiff( diff: Partial>, - ): Partial { + ): Partial { const updateData: Record = {}; for (const key of Object.keys(diff)) { @@ -33,14 +33,14 @@ export class ViewFilterGroupSyncService { } } - return updateData as Partial; + return updateData as Partial; } public async createCoreViewFilterGroup( workspaceId: string, workspaceViewFilterGroup: ViewFilterGroupWorkspaceEntity, ): Promise { - const coreViewFilterGroup: Partial = { + const coreViewFilterGroup: Partial = { id: workspaceViewFilterGroup.id, viewId: workspaceViewFilterGroup.viewId, logicalOperator: diff --git a/packages/twenty-server/src/modules/view/services/view-filter-sync.service.ts b/packages/twenty-server/src/modules/view/services/view-filter-sync.service.ts index d5bac4dd9b..00dce42933 100644 --- a/packages/twenty-server/src/modules/view/services/view-filter-sync.service.ts +++ b/packages/twenty-server/src/modules/view/services/view-filter-sync.service.ts @@ -6,7 +6,7 @@ import { isDefined } from 'twenty-shared/utils'; import { Repository } from 'typeorm'; import { type ObjectRecordDiff } from 'src/engine/core-modules/event-emitter/types/object-record-diff'; -import { ViewFilter } from 'src/engine/core-modules/view/entities/view-filter.entity'; +import { ViewFilterEntity } from 'src/engine/core-modules/view/entities/view-filter.entity'; import { type ViewFilterWorkspaceEntity } from 'src/modules/view/standard-objects/view-filter.workspace-entity'; import { convertViewFilterOperandToCoreOperand } from 'src/modules/view/utils/convert-view-filter-operand-to-core-operand.util'; import { convertViewFilterWorkspaceValueToCoreValue } from 'src/modules/view/utils/convert-view-filter-workspace-value-to-core-value'; @@ -14,13 +14,13 @@ import { convertViewFilterWorkspaceValueToCoreValue } from 'src/modules/view/uti @Injectable() export class ViewFilterSyncService { constructor( - @InjectRepository(ViewFilter, 'core') - private readonly coreViewFilterRepository: Repository, + @InjectRepository(ViewFilterEntity, 'core') + private readonly coreViewFilterRepository: Repository, ) {} private parseUpdateDataFromDiff( diff: Partial>, - ): Partial { + ): Partial { const updateData: Record = {}; for (const key of Object.keys(diff)) { @@ -45,7 +45,7 @@ export class ViewFilterSyncService { } } - return updateData as Partial; + return updateData as Partial; } public async createCoreViewFilter( @@ -56,7 +56,7 @@ export class ViewFilterSyncService { return; } - const coreViewFilter: Partial = { + const coreViewFilter: Partial = { id: workspaceViewFilter.id, fieldMetadataId: workspaceViewFilter.fieldMetadataId, viewId: workspaceViewFilter.viewId, diff --git a/packages/twenty-server/src/modules/view/services/view-group-sync.service.ts b/packages/twenty-server/src/modules/view/services/view-group-sync.service.ts index 0fcc07c026..d7df690e26 100644 --- a/packages/twenty-server/src/modules/view/services/view-group-sync.service.ts +++ b/packages/twenty-server/src/modules/view/services/view-group-sync.service.ts @@ -5,19 +5,19 @@ import { isDefined } from 'twenty-shared/utils'; import { Repository } from 'typeorm'; import { type ObjectRecordDiff } from 'src/engine/core-modules/event-emitter/types/object-record-diff'; -import { ViewGroup } from 'src/engine/core-modules/view/entities/view-group.entity'; +import { ViewGroupEntity } from 'src/engine/core-modules/view/entities/view-group.entity'; import { type ViewGroupWorkspaceEntity } from 'src/modules/view/standard-objects/view-group.workspace-entity'; @Injectable() export class ViewGroupSyncService { constructor( - @InjectRepository(ViewGroup, 'core') - private readonly coreViewGroupRepository: Repository, + @InjectRepository(ViewGroupEntity, 'core') + private readonly coreViewGroupRepository: Repository, ) {} private parseUpdateDataFromDiff( diff: Partial>, - ): Partial { + ): Partial { const updateData: Record = {}; for (const key of Object.keys(diff)) { @@ -28,7 +28,7 @@ export class ViewGroupSyncService { } } - return updateData as Partial; + return updateData as Partial; } public async createCoreViewGroup( @@ -39,7 +39,7 @@ export class ViewGroupSyncService { return; } - const coreViewGroup: Partial = { + const coreViewGroup: Partial = { id: workspaceViewGroup.id, fieldMetadataId: workspaceViewGroup.fieldMetadataId, viewId: workspaceViewGroup.viewId, diff --git a/packages/twenty-server/src/modules/view/services/view-sort-sync.service.ts b/packages/twenty-server/src/modules/view/services/view-sort-sync.service.ts index 36930b50b7..6e3b509190 100644 --- a/packages/twenty-server/src/modules/view/services/view-sort-sync.service.ts +++ b/packages/twenty-server/src/modules/view/services/view-sort-sync.service.ts @@ -5,20 +5,20 @@ import { isDefined } from 'twenty-shared/utils'; import { Repository } from 'typeorm'; import { type ObjectRecordDiff } from 'src/engine/core-modules/event-emitter/types/object-record-diff'; -import { ViewSort } from 'src/engine/core-modules/view/entities/view-sort.entity'; +import { ViewSortEntity } from 'src/engine/core-modules/view/entities/view-sort.entity'; import { type ViewSortDirection } from 'src/engine/core-modules/view/enums/view-sort-direction'; import { type ViewSortWorkspaceEntity } from 'src/modules/view/standard-objects/view-sort.workspace-entity'; @Injectable() export class ViewSortSyncService { constructor( - @InjectRepository(ViewSort, 'core') - private readonly coreViewSortRepository: Repository, + @InjectRepository(ViewSortEntity, 'core') + private readonly coreViewSortRepository: Repository, ) {} private parseUpdateDataFromDiff( diff: Partial>, - ): Partial { + ): Partial { const updateData: Record = {}; for (const key of Object.keys(diff)) { @@ -35,7 +35,7 @@ export class ViewSortSyncService { } } - return updateData as Partial; + return updateData as Partial; } public async createCoreViewSort( @@ -49,7 +49,7 @@ export class ViewSortSyncService { const direction = workspaceViewSort.direction.toUpperCase() as ViewSortDirection; - const coreViewSort: Partial = { + const coreViewSort: Partial = { id: workspaceViewSort.id, fieldMetadataId: workspaceViewSort.fieldMetadataId, viewId: workspaceViewSort.viewId, diff --git a/packages/twenty-server/src/modules/view/services/view-sync.service.ts b/packages/twenty-server/src/modules/view/services/view-sync.service.ts index 048316cb90..773db34454 100644 --- a/packages/twenty-server/src/modules/view/services/view-sync.service.ts +++ b/packages/twenty-server/src/modules/view/services/view-sync.service.ts @@ -5,7 +5,7 @@ import { isDefined } from 'twenty-shared/utils'; import { Repository } from 'typeorm'; import { type ObjectRecordDiff } from 'src/engine/core-modules/event-emitter/types/object-record-diff'; -import { View } from 'src/engine/core-modules/view/entities/view.entity'; +import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { ViewKey } from 'src/engine/core-modules/view/enums/view-key.enum'; import { ViewOpenRecordIn } from 'src/engine/core-modules/view/enums/view-open-record-in'; import { ViewType } from 'src/engine/core-modules/view/enums/view-type.enum'; @@ -14,13 +14,13 @@ import { type ViewWorkspaceEntity } from 'src/modules/view/standard-objects/view @Injectable() export class ViewSyncService { constructor( - @InjectRepository(View, 'core') - private readonly coreViewRepository: Repository, + @InjectRepository(ViewEntity, 'core') + private readonly coreViewRepository: Repository, ) {} private parseUpdateDataFromDiff( diff: Partial>, - ): Partial { + ): Partial { const updateData: Record = {}; for (const key of Object.keys(diff)) { @@ -50,7 +50,7 @@ export class ViewSyncService { } } - return updateData as Partial; + return updateData as Partial; } public async createCoreView( @@ -64,7 +64,7 @@ export class ViewSyncService { viewName = 'All {objectLabelPlural}'; } - const coreView: Partial = { + const coreView: Partial = { id: workspaceView.id, name: viewName, objectMetadataId: workspaceView.objectMetadataId, diff --git a/packages/twenty-server/src/modules/view/view.module.ts b/packages/twenty-server/src/modules/view/view.module.ts index f483a2dfea..491fee2286 100644 --- a/packages/twenty-server/src/modules/view/view.module.ts +++ b/packages/twenty-server/src/modules/view/view.module.ts @@ -2,12 +2,12 @@ import { Module } from '@nestjs/common'; import { TypeOrmModule } from '@nestjs/typeorm'; import { FeatureFlagModule } from 'src/engine/core-modules/feature-flag/feature-flag.module'; -import { ViewField } from 'src/engine/core-modules/view/entities/view-field.entity'; -import { ViewFilterGroup } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; -import { ViewFilter } from 'src/engine/core-modules/view/entities/view-filter.entity'; -import { ViewGroup } from 'src/engine/core-modules/view/entities/view-group.entity'; -import { ViewSort } from 'src/engine/core-modules/view/entities/view-sort.entity'; -import { View } from 'src/engine/core-modules/view/entities/view.entity'; +import { ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; +import { ViewFilterGroupEntity } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; +import { ViewFilterEntity } from 'src/engine/core-modules/view/entities/view-filter.entity'; +import { ViewGroupEntity } from 'src/engine/core-modules/view/entities/view-group.entity'; +import { ViewSortEntity } from 'src/engine/core-modules/view/entities/view-sort.entity'; +import { ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { ObjectMetadataEntity } from 'src/engine/metadata-modules/object-metadata/object-metadata.entity'; import { ViewFieldListener } from 'src/modules/view/listeners/view-field.listener'; import { ViewFilterGroupListener } from 'src/modules/view/listeners/view-filter-group.listener'; @@ -27,7 +27,14 @@ import { ViewService } from 'src/modules/view/services/view.service'; @Module({ imports: [ TypeOrmModule.forFeature( - [View, ViewField, ViewFilter, ViewFilterGroup, ViewGroup, ViewSort], + [ + ViewEntity, + ViewFieldEntity, + ViewFilterEntity, + ViewFilterGroupEntity, + ViewGroupEntity, + ViewSortEntity, + ], 'core', ), TypeOrmModule.forFeature([ObjectMetadataEntity], 'core'), diff --git a/packages/twenty-server/test/integration/graphql/suites/view/view-field-resolver.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/view/view-field-resolver.integration-spec.ts index 7b94c34282..d89b4e86ea 100644 --- a/packages/twenty-server/test/integration/graphql/suites/view/view-field-resolver.integration-spec.ts +++ b/packages/twenty-server/test/integration/graphql/suites/view/view-field-resolver.integration-spec.ts @@ -1,7 +1,4 @@ -import { - TEST_FIELD_METADATA_1_ID, - TEST_NOT_EXISTING_VIEW_FIELD_ID, -} from 'test/integration/constants/test-view-ids.constants'; +import { TEST_NOT_EXISTING_VIEW_FIELD_ID } from 'test/integration/constants/test-view-ids.constants'; import { createViewFieldOperationFactory } from 'test/integration/graphql/utils/create-view-field-operation-factory.util'; import { deleteViewFieldOperationFactory } from 'test/integration/graphql/utils/delete-view-field-operation-factory.util'; import { destroyViewFieldOperationFactory } from 'test/integration/graphql/utils/destroy-view-field-operation-factory.util'; @@ -17,10 +14,14 @@ import { updateViewFieldData, } from 'test/integration/graphql/utils/view-data-factory.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 { assertViewFieldStructure, cleanupViewRecords, } from 'test/integration/utils/view-test.util'; +import { FieldMetadataType } from 'twenty-shared/types'; import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; import { @@ -30,12 +31,63 @@ import { describe('View Field Resolver', () => { let testViewId: string; + let testObjectMetadataId: string; + let testFieldMetadataId: string; + + beforeAll(async () => { + const { + data: { + createOneObject: { id: objectMetadataId }, + }, + } = await createOneObjectMetadata({ + input: { + nameSingular: 'myTestObject', + namePlural: 'myTestObjects', + labelSingular: 'My Test Object', + labelPlural: 'My Test Objects', + icon: 'Icon123', + }, + }); + + testObjectMetadataId = objectMetadataId; + + const createFieldInput = { + name: 'testField', + label: 'Test Field', + type: FieldMetadataType.TEXT, + objectMetadataId: testObjectMetadataId, + isLabelSyncedWithName: true, + }; + + const { + data: { + createOneField: { id: fieldMetadataId }, + }, + } = await createOneFieldMetadata({ + input: createFieldInput, + gqlFields: ` + id + name + label + isLabelSyncedWithName + `, + }); + + testFieldMetadataId = fieldMetadataId; + }); + + afterAll(async () => { + await deleteOneObjectMetadata({ + input: { idToDelete: testObjectMetadataId }, + }); + }); beforeEach(async () => { await cleanupViewRecords(); const view = await createTestViewWithGraphQL({ name: 'Test View for Fields', + objectMetadataId: testObjectMetadataId, }); testViewId = view.id; @@ -59,6 +111,7 @@ describe('View Field Resolver', () => { position: 0, isVisible: true, size: 150, + fieldMetadataId: testFieldMetadataId, }); const createOperation = createViewFieldOperationFactory({ data: fieldData, @@ -74,7 +127,7 @@ describe('View Field Resolver', () => { assertGraphQLSuccessfulResponse(response); expect(response.body.data.getCoreViewFields).toHaveLength(1); assertViewFieldStructure(response.body.data.getCoreViewFields[0], { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, position: 0, isVisible: true, size: 150, @@ -89,6 +142,7 @@ describe('View Field Resolver', () => { position: 1, isVisible: true, size: 200, + fieldMetadataId: testFieldMetadataId, }); const operation = createViewFieldOperationFactory({ data: fieldData }); @@ -96,7 +150,7 @@ describe('View Field Resolver', () => { assertGraphQLSuccessfulResponse(response); assertViewFieldStructure(response.body.data.createCoreViewField, { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, position: 1, isVisible: true, size: 200, @@ -106,7 +160,7 @@ describe('View Field Resolver', () => { it('should create a hidden view field', async () => { const fieldData = { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, position: 2, isVisible: false, size: 100, @@ -118,7 +172,7 @@ describe('View Field Resolver', () => { assertGraphQLSuccessfulResponse(response); assertViewFieldStructure(response.body.data.createCoreViewField, { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, position: 2, isVisible: false, size: 100, @@ -133,6 +187,7 @@ describe('View Field Resolver', () => { position: 0, isVisible: true, size: 150, + fieldMetadataId: testFieldMetadataId, }); const createOperation = createViewFieldOperationFactory({ data: fieldData, @@ -179,7 +234,9 @@ describe('View Field Resolver', () => { describe('deleteCoreViewField', () => { it('should delete an existing view field', async () => { - const fieldData = createViewFieldData(testViewId); + const fieldData = createViewFieldData(testViewId, { + fieldMetadataId: testFieldMetadataId, + }); const createOperation = createViewFieldOperationFactory({ data: fieldData, }); @@ -214,7 +271,9 @@ describe('View Field Resolver', () => { describe('destroyCoreViewField', () => { it('should destroy an existing view field', async () => { - const fieldData = createViewFieldData(testViewId); + const fieldData = createViewFieldData(testViewId, { + fieldMetadataId: testFieldMetadataId, + }); const createOperation = createViewFieldOperationFactory({ data: fieldData, }); diff --git a/packages/twenty-server/test/integration/graphql/suites/view/view-filter-group-resolver.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/view/view-filter-group-resolver.integration-spec.ts index b2d49b5b60..55c304d876 100644 --- a/packages/twenty-server/test/integration/graphql/suites/view/view-filter-group-resolver.integration-spec.ts +++ b/packages/twenty-server/test/integration/graphql/suites/view/view-filter-group-resolver.integration-spec.ts @@ -15,6 +15,8 @@ import { updateViewFilterGroupData, } from 'test/integration/graphql/utils/view-data-factory.util'; import { createTestViewWithGraphQL } from 'test/integration/graphql/utils/view-graphql.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 { assertViewFilterGroupStructure, cleanupViewRecords, @@ -30,11 +32,38 @@ import { describe('View Filter Group Resolver', () => { let testViewId: string; + let testObjectMetadataId: string; + + beforeAll(async () => { + const { + data: { + createOneObject: { id: objectMetadataId }, + }, + } = await createOneObjectMetadata({ + input: { + nameSingular: 'myTestObject', + namePlural: 'myTestObjects', + labelSingular: 'My Test Object', + labelPlural: 'My Test Objects', + icon: 'Icon123', + }, + }); + + testObjectMetadataId = objectMetadataId; + }); + + afterAll(async () => { + await deleteOneObjectMetadata({ + input: { idToDelete: testObjectMetadataId }, + }); + }); + beforeEach(async () => { await cleanupViewRecords(); const view = await createTestViewWithGraphQL({ name: 'Test View for Filter Groups', + objectMetadataId: testObjectMetadataId, }); testViewId = view.id; 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 74dae0812e..70d962da87 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,7 +1,4 @@ -import { - TEST_FIELD_METADATA_1_ID, - TEST_NOT_EXISTING_VIEW_FILTER_ID, -} from 'test/integration/constants/test-view-ids.constants'; +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'; @@ -14,10 +11,14 @@ import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graph 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 { 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 { assertViewFilterStructure, cleanupViewRecords, } from 'test/integration/utils/view-test.util'; +import { FieldMetadataType } from 'twenty-shared/types'; import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; import { ViewFilterOperand } from 'src/engine/core-modules/view/enums/view-filter-operand'; @@ -28,12 +29,55 @@ import { describe('View Filter Resolver', () => { let testViewId: string; + let testObjectMetadataId: string; + let testFieldMetadataId: string; + + beforeAll(async () => { + const { + data: { + createOneObject: { id: objectMetadataId }, + }, + } = await createOneObjectMetadata({ + input: { + nameSingular: 'myTestObject', + namePlural: 'myTestObjects', + labelSingular: 'My Test Object', + labelPlural: 'My Test Objects', + icon: 'Icon123', + }, + }); + + testObjectMetadataId = objectMetadataId; + + const { + data: { + createOneField: { id: fieldMetadataId }, + }, + } = await createOneFieldMetadata({ + input: { + name: 'testField', + label: 'Test Field', + type: FieldMetadataType.TEXT, + objectMetadataId: testObjectMetadataId, + isLabelSyncedWithName: true, + }, + }); + + testFieldMetadataId = fieldMetadataId; + }); + + afterAll(async () => { + await deleteOneObjectMetadata({ + input: { idToDelete: testObjectMetadataId }, + }); + }); beforeEach(async () => { await cleanupViewRecords(); const view = await createTestViewWithGraphQL({ name: 'Test View for Filters', + objectMetadataId: testObjectMetadataId, }); testViewId = view.id; @@ -56,6 +100,7 @@ describe('View Filter Resolver', () => { const filterData = createViewFilterData(testViewId, { operand: ViewFilterOperand.CONTAINS, value: 'test', + fieldMetadataId: testFieldMetadataId, }); const createOperation = createViewFilterOperationFactory({ data: filterData, @@ -71,7 +116,7 @@ describe('View Filter Resolver', () => { assertGraphQLSuccessfulResponse(response); expect(response.body.data.getCoreViewFilters).toHaveLength(1); assertViewFilterStructure(response.body.data.getCoreViewFilters[0], { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, operand: ViewFilterOperand.CONTAINS, value: 'test', viewId: testViewId, @@ -84,6 +129,7 @@ describe('View Filter Resolver', () => { const filterData = createViewFilterData(testViewId, { operand: ViewFilterOperand.IS, value: 'test value', + fieldMetadataId: testFieldMetadataId, }); const operation = createViewFilterOperationFactory({ data: filterData }); @@ -91,7 +137,7 @@ describe('View Filter Resolver', () => { assertGraphQLSuccessfulResponse(response); assertViewFilterStructure(response.body.data.createCoreViewFilter, { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, operand: ViewFilterOperand.IS, value: 'test value', viewId: testViewId, @@ -102,6 +148,7 @@ describe('View Filter Resolver', () => { const filterData = createViewFilterData(testViewId, { operand: ViewFilterOperand.GREATER_THAN_OR_EQUAL, value: 100, + fieldMetadataId: testFieldMetadataId, }); const operation = createViewFilterOperationFactory({ data: filterData }); @@ -109,7 +156,7 @@ describe('View Filter Resolver', () => { assertGraphQLSuccessfulResponse(response); assertViewFilterStructure(response.body.data.createCoreViewFilter, { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, operand: ViewFilterOperand.GREATER_THAN_OR_EQUAL, value: 100, viewId: testViewId, @@ -121,6 +168,7 @@ describe('View Filter Resolver', () => { data: createViewFilterData(testViewId, { operand: ViewFilterOperand.IS, value: true, + fieldMetadataId: testFieldMetadataId, }), }); @@ -128,7 +176,7 @@ describe('View Filter Resolver', () => { assertGraphQLSuccessfulResponse(response); assertViewFilterStructure(response.body.data.createCoreViewFilter, { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, operand: ViewFilterOperand.IS, value: true, viewId: testViewId, @@ -142,6 +190,7 @@ describe('View Filter Resolver', () => { data: createViewFilterData(testViewId, { operand: ViewFilterOperand.CONTAINS, value: 'original', + fieldMetadataId: testFieldMetadataId, }), }); @@ -190,6 +239,7 @@ describe('View Filter Resolver', () => { data: createViewFilterData(testViewId, { operand: ViewFilterOperand.CONTAINS, value: 'to delete', + fieldMetadataId: testFieldMetadataId, }), }); @@ -230,6 +280,7 @@ describe('View Filter Resolver', () => { data: createViewFilterData(testViewId, { operand: ViewFilterOperand.CONTAINS, value: 'to destroy', + fieldMetadataId: testFieldMetadataId, }), }); diff --git a/packages/twenty-server/test/integration/graphql/suites/view/view-group-resolver.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/view/view-group-resolver.integration-spec.ts index 7f85744838..134e0c171f 100644 --- a/packages/twenty-server/test/integration/graphql/suites/view/view-group-resolver.integration-spec.ts +++ b/packages/twenty-server/test/integration/graphql/suites/view/view-group-resolver.integration-spec.ts @@ -1,7 +1,4 @@ -import { - TEST_FIELD_METADATA_1_ID, - TEST_NOT_EXISTING_VIEW_GROUP_ID, -} from 'test/integration/constants/test-view-ids.constants'; +import { TEST_NOT_EXISTING_VIEW_GROUP_ID } from 'test/integration/constants/test-view-ids.constants'; import { createViewGroupOperationFactory } from 'test/integration/graphql/utils/create-view-group-operation-factory.util'; import { deleteViewGroupOperationFactory } from 'test/integration/graphql/utils/delete-view-group-operation-factory.util'; import { destroyViewGroupOperationFactory } from 'test/integration/graphql/utils/destroy-view-group-operation-factory.util'; @@ -17,10 +14,14 @@ import { updateViewGroupData, } from 'test/integration/graphql/utils/view-data-factory.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 { assertViewGroupStructure, cleanupViewRecords, } from 'test/integration/utils/view-test.util'; +import { FieldMetadataType } from 'twenty-shared/types'; import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; import { @@ -30,12 +31,55 @@ import { describe('View Group Resolver', () => { let testViewId: string; + let testObjectMetadataId: string; + let testFieldMetadataId: string; + + beforeAll(async () => { + const { + data: { + createOneObject: { id: objectMetadataId }, + }, + } = await createOneObjectMetadata({ + input: { + nameSingular: 'myTestObject', + namePlural: 'myTestObjects', + labelSingular: 'My Test Object', + labelPlural: 'My Test Objects', + icon: 'Icon123', + }, + }); + + testObjectMetadataId = objectMetadataId; + + const { + data: { + createOneField: { id: fieldMetadataId }, + }, + } = await createOneFieldMetadata({ + input: { + name: 'testField', + label: 'Test Field', + type: FieldMetadataType.TEXT, + objectMetadataId: testObjectMetadataId, + isLabelSyncedWithName: true, + }, + }); + + testFieldMetadataId = fieldMetadataId; + }); + + afterAll(async () => { + await deleteOneObjectMetadata({ + input: { idToDelete: testObjectMetadataId }, + }); + }); beforeEach(async () => { await cleanupViewRecords(); const view = await createTestViewWithGraphQL({ name: 'Test View for Groups', + objectMetadataId: testObjectMetadataId, }); testViewId = view.id; @@ -59,6 +103,7 @@ describe('View Group Resolver', () => { isVisible: true, fieldValue: 'active', position: 0, + fieldMetadataId: testFieldMetadataId, }); const createOperation = createViewGroupOperationFactory({ data: groupData, @@ -74,7 +119,7 @@ describe('View Group Resolver', () => { assertGraphQLSuccessfulResponse(response); expect(response.body.data.getCoreViewGroups).toHaveLength(1); assertViewGroupStructure(response.body.data.getCoreViewGroups[0], { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, isVisible: true, fieldValue: 'active', position: 0, @@ -89,6 +134,7 @@ describe('View Group Resolver', () => { isVisible: false, fieldValue: 'inactive', position: 1, + fieldMetadataId: testFieldMetadataId, }); const operation = createViewGroupOperationFactory({ @@ -98,7 +144,7 @@ describe('View Group Resolver', () => { assertGraphQLSuccessfulResponse(response); assertViewGroupStructure(response.body.data.createCoreViewGroup, { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, isVisible: false, fieldValue: 'inactive', position: 1, @@ -111,6 +157,7 @@ describe('View Group Resolver', () => { isVisible: true, fieldValue: '', position: 2, + fieldMetadataId: testFieldMetadataId, }); const operation = createViewGroupOperationFactory({ @@ -120,7 +167,7 @@ describe('View Group Resolver', () => { assertGraphQLSuccessfulResponse(response); assertViewGroupStructure(response.body.data.createCoreViewGroup, { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, isVisible: true, fieldValue: '', position: 2, @@ -134,6 +181,7 @@ describe('View Group Resolver', () => { isVisible: true, fieldValue: 'original', position: 0, + fieldMetadataId: testFieldMetadataId, }); const createOperation = createViewGroupOperationFactory({ data: groupData, @@ -145,6 +193,7 @@ describe('View Group Resolver', () => { isVisible: false, fieldValue: 'updated', position: 5, + fieldMetadataId: testFieldMetadataId, }); const updateOperation = updateViewGroupOperationFactory({ viewGroupId: viewGroup.id, @@ -184,6 +233,7 @@ describe('View Group Resolver', () => { isVisible: true, fieldValue: 'to delete', position: 0, + fieldMetadataId: testFieldMetadataId, }); const createOperation = createViewGroupOperationFactory({ data: groupData, @@ -223,6 +273,7 @@ describe('View Group Resolver', () => { isVisible: true, fieldValue: 'to destroy', position: 0, + fieldMetadataId: testFieldMetadataId, }); const createOperation = createViewGroupOperationFactory({ data: groupData, diff --git a/packages/twenty-server/test/integration/graphql/suites/view/view-resolver.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/view/view-resolver.integration-spec.ts index 07549166ad..b9c080c8ea 100644 --- a/packages/twenty-server/test/integration/graphql/suites/view/view-resolver.integration-spec.ts +++ b/packages/twenty-server/test/integration/graphql/suites/view/view-resolver.integration-spec.ts @@ -1,8 +1,4 @@ -import { - TEST_NOT_EXISTING_VIEW_ID, - TEST_OBJECT_METADATA_1_ID, - TEST_OBJECT_METADATA_2_ID, -} from 'test/integration/constants/test-view-ids.constants'; +import { TEST_NOT_EXISTING_VIEW_ID } from 'test/integration/constants/test-view-ids.constants'; import { createViewOperationFactory } from 'test/integration/graphql/utils/create-view-operation-factory.util'; import { deleteViewOperationFactory } from 'test/integration/graphql/utils/delete-view-operation-factory.util'; import { destroyViewOperationFactory } from 'test/integration/graphql/utils/destroy-view-operation-factory.util'; @@ -19,6 +15,8 @@ import { updateViewData, } from 'test/integration/graphql/utils/view-data-factory.util'; import { createTestViewWithGraphQL } from 'test/integration/graphql/utils/view-graphql.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 { assertViewStructure, cleanupViewRecords, @@ -33,6 +31,32 @@ import { } from 'src/engine/core-modules/view/exceptions/view.exception'; describe('View Resolver', () => { + let testObjectMetadataId: string; + + beforeAll(async () => { + const { + data: { + createOneObject: { id: objectMetadataId }, + }, + } = await createOneObjectMetadata({ + input: { + nameSingular: 'myTestObject', + namePlural: 'myTestObjects', + labelSingular: 'My Test Object', + labelPlural: 'My Test Objects', + icon: 'Icon123', + }, + }); + + testObjectMetadataId = objectMetadataId; + }); + + afterAll(async () => { + await deleteOneObjectMetadata({ + input: { idToDelete: testObjectMetadataId }, + }); + }); + beforeEach(async () => { await cleanupViewRecords(); }); @@ -55,10 +79,12 @@ describe('View Resolver', () => { await createTestViewWithGraphQL({ name: viewName, + objectMetadataId: testObjectMetadataId, }); const viewData = createViewData({ name: viewName, + objectMetadataId: testObjectMetadataId, }); const operation = findViewsOperationFactory(); @@ -73,19 +99,33 @@ describe('View Resolver', () => { const object1ViewName = 'View for Object 1'; const object2ViewName = 'View for Object 2'; + const { + data: { + createOneObject: { id: objectMetadata2Id }, + }, + } = await createOneObjectMetadata({ + input: { + nameSingular: 'myTestObject2', + namePlural: 'myTestObjects2', + labelSingular: 'My Test Object 2', + labelPlural: 'My Test Objects 2', + icon: 'Icon123', + }, + }); + await Promise.all([ createTestViewWithGraphQL({ name: object1ViewName, - objectMetadataId: TEST_OBJECT_METADATA_1_ID, + objectMetadataId: testObjectMetadataId, }), createTestViewWithGraphQL({ name: object2ViewName, - objectMetadataId: TEST_OBJECT_METADATA_2_ID, + objectMetadataId: objectMetadata2Id, }), ]); const operation = findViewsOperationFactory({ - objectMetadataId: TEST_OBJECT_METADATA_1_ID, + objectMetadataId: testObjectMetadataId, }); const response = await makeGraphqlAPIRequest(operation); @@ -94,6 +134,10 @@ describe('View Resolver', () => { expect(response.body.data.getCoreViews[0]).toMatchObject({ name: object1ViewName, }); + + await deleteOneObjectMetadata({ + input: { idToDelete: objectMetadata2Id }, + }); }); }); @@ -113,6 +157,7 @@ describe('View Resolver', () => { const view = await createTestViewWithGraphQL({ name: viewName, + objectMetadataId: testObjectMetadataId, }); const operation = findViewOperationFactory({ viewId: view.id }); @@ -122,7 +167,7 @@ describe('View Resolver', () => { assertViewStructure(response.body.data.getCoreView, { id: view.id, name: viewName, - objectMetadataId: TEST_OBJECT_METADATA_1_ID, + objectMetadataId: testObjectMetadataId, }); }); }); @@ -131,7 +176,7 @@ describe('View Resolver', () => { it('should create a new view with all properties', async () => { const input = { name: 'Kanban View', - objectMetadataId: TEST_OBJECT_METADATA_1_ID, + objectMetadataId: testObjectMetadataId, icon: 'IconDeal', type: ViewType.KANBAN, key: null, @@ -159,7 +204,7 @@ describe('View Resolver', () => { it('should create a view with minimum required fields', async () => { const input = { name: 'Minimal View', - objectMetadataId: TEST_OBJECT_METADATA_1_ID, + objectMetadataId: testObjectMetadataId, icon: 'IconList', }; @@ -186,12 +231,14 @@ describe('View Resolver', () => { name: 'Original View', type: ViewType.TABLE, isCompact: false, + objectMetadataId: testObjectMetadataId, }); const updateInput = updateViewData({ name: 'Updated View', type: ViewType.KANBAN, isCompact: true, + objectMetadataId: testObjectMetadataId, }); const operation = updateViewOperationFactory({ @@ -229,6 +276,7 @@ describe('View Resolver', () => { it('should delete an existing view', async () => { const view = await createTestViewWithGraphQL({ name: 'View to Delete', + objectMetadataId: testObjectMetadataId, }); const deleteOperation = deleteViewOperationFactory({ viewId: view.id }); @@ -264,6 +312,7 @@ describe('View Resolver', () => { it('should destroy an existing view', async () => { const view = await createTestViewWithGraphQL({ name: 'View to Destroy', + objectMetadataId: testObjectMetadataId, }); const destroyOperation = destroyViewOperationFactory({ viewId: view.id }); diff --git a/packages/twenty-server/test/integration/graphql/suites/view/view-sort-resolver.integration-spec.ts b/packages/twenty-server/test/integration/graphql/suites/view/view-sort-resolver.integration-spec.ts index 26d221af70..575887385c 100644 --- a/packages/twenty-server/test/integration/graphql/suites/view/view-sort-resolver.integration-spec.ts +++ b/packages/twenty-server/test/integration/graphql/suites/view/view-sort-resolver.integration-spec.ts @@ -1,7 +1,4 @@ -import { - TEST_FIELD_METADATA_1_ID, - TEST_NOT_EXISTING_VIEW_SORT_ID, -} from 'test/integration/constants/test-view-ids.constants'; +import { TEST_NOT_EXISTING_VIEW_SORT_ID } from 'test/integration/constants/test-view-ids.constants'; import { createViewSortOperationFactory } from 'test/integration/graphql/utils/create-view-sort-operation-factory.util'; import { deleteViewSortOperationFactory } from 'test/integration/graphql/utils/delete-view-sort-operation-factory.util'; import { destroyViewSortOperationFactory } from 'test/integration/graphql/utils/destroy-view-sort-operation-factory.util'; @@ -17,10 +14,14 @@ import { updateViewSortData, } from 'test/integration/graphql/utils/view-data-factory.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 { assertViewSortStructure, cleanupViewRecords, } from 'test/integration/utils/view-test.util'; +import { FieldMetadataType } from 'twenty-shared/types'; import { ErrorCode } from 'src/engine/core-modules/graphql/utils/graphql-errors.util'; import { ViewSortDirection } from 'src/engine/core-modules/view/enums/view-sort-direction'; @@ -31,12 +32,55 @@ import { describe('View Sort Resolver', () => { let testViewId: string; + let testObjectMetadataId: string; + let testFieldMetadataId: string; + + beforeAll(async () => { + const { + data: { + createOneObject: { id: objectMetadataId }, + }, + } = await createOneObjectMetadata({ + input: { + nameSingular: 'myTestObject', + namePlural: 'myTestObjects', + labelSingular: 'My Test Object', + labelPlural: 'My Test Objects', + icon: 'Icon123', + }, + }); + + testObjectMetadataId = objectMetadataId; + + const { + data: { + createOneField: { id: fieldMetadataId }, + }, + } = await createOneFieldMetadata({ + input: { + name: 'testField', + label: 'Test Field', + type: FieldMetadataType.TEXT, + objectMetadataId: testObjectMetadataId, + isLabelSyncedWithName: true, + }, + }); + + testFieldMetadataId = fieldMetadataId; + }); + + afterAll(async () => { + await deleteOneObjectMetadata({ + input: { idToDelete: testObjectMetadataId }, + }); + }); beforeEach(async () => { await cleanupViewRecords(); const view = await createTestViewWithGraphQL({ name: 'Test View for Sorts', + objectMetadataId: testObjectMetadataId, }); testViewId = view.id; @@ -58,6 +102,7 @@ describe('View Sort Resolver', () => { it('should return view sorts for a specific view', async () => { const sortData = createViewSortData(testViewId, { direction: ViewSortDirection.ASC, + fieldMetadataId: testFieldMetadataId, }); const createOperation = createViewSortOperationFactory({ data: sortData, @@ -73,7 +118,7 @@ describe('View Sort Resolver', () => { assertGraphQLSuccessfulResponse(response); expect(response.body.data.getCoreViewSorts).toHaveLength(1); assertViewSortStructure(response.body.data.getCoreViewSorts[0], { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, direction: ViewSortDirection.ASC, viewId: testViewId, }); @@ -84,6 +129,7 @@ describe('View Sort Resolver', () => { it('should create a new view sort with ASC direction', async () => { const sortData = createViewSortData(testViewId, { direction: ViewSortDirection.ASC, + fieldMetadataId: testFieldMetadataId, }); const operation = createViewSortOperationFactory({ data: sortData }); @@ -91,7 +137,7 @@ describe('View Sort Resolver', () => { assertGraphQLSuccessfulResponse(response); assertViewSortStructure(response.body.data.createCoreViewSort, { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, direction: ViewSortDirection.ASC, viewId: testViewId, }); @@ -100,6 +146,7 @@ describe('View Sort Resolver', () => { it('should create a view sort with DESC direction', async () => { const sortData = createViewSortData(testViewId, { direction: ViewSortDirection.DESC, + fieldMetadataId: testFieldMetadataId, }); const operation = createViewSortOperationFactory({ data: sortData }); @@ -107,7 +154,7 @@ describe('View Sort Resolver', () => { assertGraphQLSuccessfulResponse(response); assertViewSortStructure(response.body.data.createCoreViewSort, { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, direction: ViewSortDirection.DESC, viewId: testViewId, }); @@ -118,6 +165,7 @@ describe('View Sort Resolver', () => { it('should update an existing view sort', async () => { const sortData = createViewSortData(testViewId, { direction: ViewSortDirection.ASC, + fieldMetadataId: testFieldMetadataId, }); const createOperation = createViewSortOperationFactory({ data: sortData, @@ -160,7 +208,9 @@ describe('View Sort Resolver', () => { describe('deleteCoreViewSort', () => { it('should delete an existing view sort', async () => { - const sortData = createViewSortData(testViewId); + const sortData = createViewSortData(testViewId, { + fieldMetadataId: testFieldMetadataId, + }); const createOperation = createViewSortOperationFactory({ data: sortData, }); @@ -195,7 +245,9 @@ describe('View Sort Resolver', () => { describe('destroyCoreViewSort', () => { it('should destroy an existing view sort', async () => { - const sortData = createViewSortData(testViewId); + const sortData = createViewSortData(testViewId, { + fieldMetadataId: testFieldMetadataId, + }); const createOperation = createViewSortOperationFactory({ data: sortData, }); diff --git a/packages/twenty-server/test/integration/graphql/utils/create-view-field-operation-factory.util.ts b/packages/twenty-server/test/integration/graphql/utils/create-view-field-operation-factory.util.ts index cb01e55a7e..87ccaabf9a 100644 --- a/packages/twenty-server/test/integration/graphql/utils/create-view-field-operation-factory.util.ts +++ b/packages/twenty-server/test/integration/graphql/utils/create-view-field-operation-factory.util.ts @@ -1,11 +1,11 @@ import gql from 'graphql-tag'; import { VIEW_FIELD_GQL_FIELDS } from 'test/integration/constants/view-gql-fields.constants'; -import { type ViewField } from 'src/engine/core-modules/view/entities/view-field.entity'; +import { type ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; type CreateViewFieldOperationFactoryParams = { gqlFields?: string; - data?: Partial; + data?: Partial; }; export const createViewFieldOperationFactory = ({ diff --git a/packages/twenty-server/test/integration/graphql/utils/create-view-filter-group-operation-factory.util.ts b/packages/twenty-server/test/integration/graphql/utils/create-view-filter-group-operation-factory.util.ts index 542bd3e8fb..d3cb75584e 100644 --- a/packages/twenty-server/test/integration/graphql/utils/create-view-filter-group-operation-factory.util.ts +++ b/packages/twenty-server/test/integration/graphql/utils/create-view-filter-group-operation-factory.util.ts @@ -1,11 +1,11 @@ import gql from 'graphql-tag'; import { VIEW_FILTER_GROUP_GQL_FIELDS } from 'test/integration/constants/view-gql-fields.constants'; -import { type ViewFilterGroup } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; +import { type ViewFilterGroupEntity } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; type CreateViewFilterGroupOperationFactoryParams = { gqlFields?: string; - data?: Partial; + data?: Partial; }; export const createViewFilterGroupOperationFactory = ({ 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 index cb626fe530..22c6e42718 100644 --- 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 @@ -1,11 +1,11 @@ import gql from 'graphql-tag'; import { VIEW_FILTER_GQL_FIELDS } from 'test/integration/constants/view-gql-fields.constants'; -import { type ViewFilter } from 'src/engine/core-modules/view/entities/view-filter.entity'; +import { type ViewFilterEntity } from 'src/engine/core-modules/view/entities/view-filter.entity'; type CreateViewFilterOperationFactoryParams = { gqlFields?: string; - data?: Partial; + data?: Partial; }; export const createViewFilterOperationFactory = ({ diff --git a/packages/twenty-server/test/integration/graphql/utils/create-view-group-operation-factory.util.ts b/packages/twenty-server/test/integration/graphql/utils/create-view-group-operation-factory.util.ts index 423e175c19..e849e4895c 100644 --- a/packages/twenty-server/test/integration/graphql/utils/create-view-group-operation-factory.util.ts +++ b/packages/twenty-server/test/integration/graphql/utils/create-view-group-operation-factory.util.ts @@ -1,11 +1,11 @@ import gql from 'graphql-tag'; import { VIEW_GROUP_GQL_FIELDS } from 'test/integration/constants/view-gql-fields.constants'; -import { type ViewGroup } from 'src/engine/core-modules/view/entities/view-group.entity'; +import { type ViewGroupEntity } from 'src/engine/core-modules/view/entities/view-group.entity'; type CreateViewGroupOperationFactoryParams = { gqlFields?: string; - data?: Partial; + data?: Partial; }; export const createViewGroupOperationFactory = ({ diff --git a/packages/twenty-server/test/integration/graphql/utils/create-view-operation-factory.util.ts b/packages/twenty-server/test/integration/graphql/utils/create-view-operation-factory.util.ts index 9d63ec200b..16576f722f 100644 --- a/packages/twenty-server/test/integration/graphql/utils/create-view-operation-factory.util.ts +++ b/packages/twenty-server/test/integration/graphql/utils/create-view-operation-factory.util.ts @@ -1,11 +1,11 @@ import gql from 'graphql-tag'; import { VIEW_GQL_FIELDS } from 'test/integration/constants/view-gql-fields.constants'; -import { type View } from 'src/engine/core-modules/view/entities/view.entity'; +import { type ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; type CreateViewOperationFactoryParams = { gqlFields?: string; - data?: Partial; + data?: Partial; }; export const createViewOperationFactory = ({ diff --git a/packages/twenty-server/test/integration/graphql/utils/create-view-sort-operation-factory.util.ts b/packages/twenty-server/test/integration/graphql/utils/create-view-sort-operation-factory.util.ts index 22504a8261..c4efb2801a 100644 --- a/packages/twenty-server/test/integration/graphql/utils/create-view-sort-operation-factory.util.ts +++ b/packages/twenty-server/test/integration/graphql/utils/create-view-sort-operation-factory.util.ts @@ -1,11 +1,11 @@ import gql from 'graphql-tag'; import { VIEW_SORT_GQL_FIELDS } from 'test/integration/constants/view-gql-fields.constants'; -import { type ViewSort } from 'src/engine/core-modules/view/entities/view-sort.entity'; +import { type ViewSortEntity } from 'src/engine/core-modules/view/entities/view-sort.entity'; type CreateViewSortOperationFactoryParams = { gqlFields?: string; - data?: Partial; + data?: Partial; }; export const createViewSortOperationFactory = ({ diff --git a/packages/twenty-server/test/integration/graphql/utils/view-data-factory.util.ts b/packages/twenty-server/test/integration/graphql/utils/view-data-factory.util.ts index f52b649ba2..405082c772 100644 --- a/packages/twenty-server/test/integration/graphql/utils/view-data-factory.util.ts +++ b/packages/twenty-server/test/integration/graphql/utils/view-data-factory.util.ts @@ -1,23 +1,17 @@ -import { - TEST_FIELD_METADATA_1_ID, - TEST_OBJECT_METADATA_1_ID, -} from 'test/integration/constants/test-view-ids.constants'; - -import { type ViewField } from 'src/engine/core-modules/view/entities/view-field.entity'; -import { type ViewFilterGroup } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; -import { type ViewFilter } from 'src/engine/core-modules/view/entities/view-filter.entity'; -import { type ViewGroup } from 'src/engine/core-modules/view/entities/view-group.entity'; -import { type ViewSort } from 'src/engine/core-modules/view/entities/view-sort.entity'; -import { type View } from 'src/engine/core-modules/view/entities/view.entity'; +import { type ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; +import { type ViewFilterGroupEntity } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; +import { type ViewFilterEntity } from 'src/engine/core-modules/view/entities/view-filter.entity'; +import { type ViewGroupEntity } from 'src/engine/core-modules/view/entities/view-group.entity'; +import { type ViewSortEntity } from 'src/engine/core-modules/view/entities/view-sort.entity'; +import { type ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { ViewFilterGroupLogicalOperator } from 'src/engine/core-modules/view/enums/view-filter-group-logical-operator'; import { ViewFilterOperand } from 'src/engine/core-modules/view/enums/view-filter-operand'; import { ViewOpenRecordIn } from 'src/engine/core-modules/view/enums/view-open-record-in'; import { ViewSortDirection } from 'src/engine/core-modules/view/enums/view-sort-direction'; import { ViewType } from 'src/engine/core-modules/view/enums/view-type.enum'; -export const createViewData = (overrides: Partial = {}) => ({ +export const createViewData = (overrides: Partial = {}) => ({ name: 'Test View', - objectMetadataId: TEST_OBJECT_METADATA_1_ID, icon: 'IconTable', type: ViewType.TABLE, key: null, @@ -27,7 +21,7 @@ export const createViewData = (overrides: Partial = {}) => ({ ...overrides, }); -export const updateViewData = (overrides: Partial = {}) => ({ +export const updateViewData = (overrides: Partial = {}) => ({ name: 'Updated View', type: ViewType.KANBAN, isCompact: true, @@ -36,17 +30,18 @@ export const updateViewData = (overrides: Partial = {}) => ({ export const createViewFieldData = ( viewId: string, - overrides: Partial = {}, + overrides: Partial = {}, ) => ({ viewId, - fieldMetadataId: TEST_FIELD_METADATA_1_ID, position: 0, isVisible: true, size: 150, ...overrides, }); -export const updateViewFieldData = (overrides: Partial = {}) => ({ +export const updateViewFieldData = ( + overrides: Partial = {}, +) => ({ position: 5, isVisible: false, size: 300, @@ -55,31 +50,33 @@ export const updateViewFieldData = (overrides: Partial = {}) => ({ export const createViewSortData = ( viewId: string, - overrides: Partial = {}, + overrides: Partial = {}, ) => ({ viewId, - fieldMetadataId: TEST_FIELD_METADATA_1_ID, direction: ViewSortDirection.ASC, ...overrides, }); -export const updateViewSortData = (overrides: Partial = {}) => ({ +export const updateViewSortData = ( + overrides: Partial = {}, +) => ({ direction: ViewSortDirection.DESC, ...overrides, }); export const createViewFilterData = ( viewId: string, - overrides: Partial = {}, + overrides: Partial = {}, ) => ({ viewId, - fieldMetadataId: TEST_FIELD_METADATA_1_ID, operand: ViewFilterOperand.IS, value: 'test-value', ...overrides, }); -export const updateViewFilterData = (overrides: Partial = {}) => ({ +export const updateViewFilterData = ( + overrides: Partial = {}, +) => ({ operand: ViewFilterOperand.IS_NOT, value: 'updated-value', ...overrides, @@ -87,17 +84,18 @@ export const updateViewFilterData = (overrides: Partial = {}) => ({ export const createViewGroupData = ( viewId: string, - overrides: Partial = {}, + overrides: Partial = {}, ) => ({ viewId, - fieldMetadataId: TEST_FIELD_METADATA_1_ID, fieldValue: 'test-group-value', isVisible: true, position: 0, ...overrides, }); -export const updateViewGroupData = (overrides: Partial = {}) => ({ +export const updateViewGroupData = ( + overrides: Partial = {}, +) => ({ fieldValue: 'updated-group-value', isVisible: false, position: 1, @@ -106,7 +104,7 @@ export const updateViewGroupData = (overrides: Partial = {}) => ({ export const createViewFilterGroupData = ( viewId: string, - overrides: Partial = {}, + overrides: Partial = {}, ) => ({ viewId, logicalOperator: ViewFilterGroupLogicalOperator.AND, @@ -114,7 +112,7 @@ export const createViewFilterGroupData = ( }); export const updateViewFilterGroupData = ( - overrides: Partial = {}, + overrides: Partial = {}, ) => ({ logicalOperator: ViewFilterGroupLogicalOperator.OR, ...overrides, diff --git a/packages/twenty-server/test/integration/graphql/utils/view-graphql.util.ts b/packages/twenty-server/test/integration/graphql/utils/view-graphql.util.ts index f8509cfc60..82ccad1041 100644 --- a/packages/twenty-server/test/integration/graphql/utils/view-graphql.util.ts +++ b/packages/twenty-server/test/integration/graphql/utils/view-graphql.util.ts @@ -1,18 +1,18 @@ import { type GraphQLResponse } from 'test/integration/graphql/utils/graphql-test-assertions.util'; import { makeGraphqlAPIRequest } from 'test/integration/graphql/utils/make-graphql-api-request.util'; -import { type View } from 'src/engine/core-modules/view/entities/view.entity'; +import { type ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { createViewOperationFactory } from './create-view-operation-factory.util'; import { createViewData } from './view-data-factory.util'; interface CreateViewResponse extends Record { - createCoreView: View; + createCoreView: ViewEntity; } export const createTestViewWithGraphQL = async ( - overrides: Partial = {}, -): Promise => { + overrides: Partial = {}, +): Promise => { const input = createViewData(overrides); const operation = createViewOperationFactory({ data: input }); diff --git a/packages/twenty-server/test/integration/rest/suites/view-field.integration-spec.ts b/packages/twenty-server/test/integration/rest/suites/view-field.integration-spec.ts index 726c85326e..ffa441e73b 100644 --- a/packages/twenty-server/test/integration/rest/suites/view-field.integration-spec.ts +++ b/packages/twenty-server/test/integration/rest/suites/view-field.integration-spec.ts @@ -1,8 +1,10 @@ import { - TEST_FIELD_METADATA_1_ID, TEST_NOT_EXISTING_VIEW_FIELD_ID, TEST_VIEW_1_ID, } from 'test/integration/constants/test-view-ids.constants'; +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 { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util'; import { assertRestApiErrorResponse, @@ -17,6 +19,7 @@ import { assertViewFieldStructure, cleanupViewRecords, } from 'test/integration/utils/view-test.util'; +import { FieldMetadataType } from 'twenty-shared/types'; import { generateViewFieldExceptionMessage, @@ -24,11 +27,63 @@ import { } from 'src/engine/core-modules/view/exceptions/view-field.exception'; describe('View Field REST API', () => { + let testObjectMetadataId: string; + let testFieldMetadataId: string; + + beforeAll(async () => { + const { + data: { + createOneObject: { id: objectMetadataId }, + }, + } = await createOneObjectMetadata({ + input: { + nameSingular: 'myTestObject', + namePlural: 'myTestObjects', + labelSingular: 'My Test Object', + labelPlural: 'My Test Objects', + icon: 'Icon123', + }, + }); + + testObjectMetadataId = objectMetadataId; + + const createFieldInput = { + name: 'testField', + label: 'Test Field', + type: FieldMetadataType.TEXT, + objectMetadataId: testObjectMetadataId, + isLabelSyncedWithName: true, + }; + + const { + data: { + createOneField: { id: fieldMetadataId }, + }, + } = await createOneFieldMetadata({ + input: createFieldInput, + gqlFields: ` + id + name + label + isLabelSyncedWithName + `, + }); + + testFieldMetadataId = fieldMetadataId; + }); + + afterAll(async () => { + await deleteOneObjectMetadata({ + input: { idToDelete: testObjectMetadataId }, + }); + }); + beforeEach(async () => { await cleanupViewRecords(); await createTestViewWithRestApi({ name: 'Test View for Fields', + objectMetadataId: testObjectMetadataId, }); }); @@ -64,6 +119,7 @@ describe('View Field REST API', () => { position: 0, isVisible: true, size: 150, + fieldMetadataId: testFieldMetadataId, }); const response = await makeRestAPIRequest({ @@ -80,7 +136,7 @@ describe('View Field REST API', () => { assertViewFieldStructure(returnedViewField, { id: viewField.id, - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, viewId: TEST_VIEW_1_ID, position: 0, isVisible: true, @@ -97,10 +153,11 @@ describe('View Field REST API', () => { position: 1, isVisible: true, size: 200, + fieldMetadataId: testFieldMetadataId, }); assertViewFieldStructure(viewField, { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, viewId: TEST_VIEW_1_ID, position: 1, isVisible: true, @@ -115,10 +172,11 @@ describe('View Field REST API', () => { position: 2, isVisible: false, size: 100, + fieldMetadataId: testFieldMetadataId, }); assertViewFieldStructure(hiddenField, { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, viewId: TEST_VIEW_1_ID, position: 2, isVisible: false, @@ -135,6 +193,7 @@ describe('View Field REST API', () => { position: 0, isVisible: true, size: 150, + fieldMetadataId: testFieldMetadataId, }); const response = await makeRestAPIRequest({ @@ -146,7 +205,7 @@ describe('View Field REST API', () => { assertRestApiSuccessfulResponse(response); assertViewFieldStructure(response.body, { id: viewField.id, - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, viewId: TEST_VIEW_1_ID, }); @@ -171,6 +230,7 @@ describe('View Field REST API', () => { position: 0, isVisible: true, size: 150, + fieldMetadataId: testFieldMetadataId, }); const updateData = { @@ -192,7 +252,7 @@ describe('View Field REST API', () => { position: 5, isVisible: false, size: 300, - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, viewId: TEST_VIEW_1_ID, }); @@ -230,6 +290,7 @@ describe('View Field REST API', () => { position: 0, isVisible: true, size: 150, + fieldMetadataId: testFieldMetadataId, }); const deleteResponse = await makeRestAPIRequest({ diff --git a/packages/twenty-server/test/integration/rest/suites/view-filter-group.integration-spec.ts b/packages/twenty-server/test/integration/rest/suites/view-filter-group.integration-spec.ts index e5a0fde717..7715c6a717 100644 --- a/packages/twenty-server/test/integration/rest/suites/view-filter-group.integration-spec.ts +++ b/packages/twenty-server/test/integration/rest/suites/view-filter-group.integration-spec.ts @@ -2,6 +2,8 @@ import { TEST_NOT_EXISTING_VIEW_FILTER_GROUP_ID, TEST_VIEW_1_ID, } from 'test/integration/constants/test-view-ids.constants'; +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 { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util'; import { assertRestApiErrorResponse, @@ -25,11 +27,42 @@ import { } from 'src/engine/core-modules/view/exceptions/view-filter-group.exception'; describe('View Filter Group REST API', () => { + let testObjectMetadataId: string; + + beforeAll(async () => { + await deleteOneObjectMetadata({ + input: { idToDelete: testObjectMetadataId }, + }); + + const { + data: { + createOneObject: { id: objectMetadataId }, + }, + } = await createOneObjectMetadata({ + input: { + nameSingular: 'myTestObject', + namePlural: 'myTestObjects', + labelSingular: 'My Test Object', + labelPlural: 'My Test Objects', + icon: 'Icon123', + }, + }); + + testObjectMetadataId = objectMetadataId; + }); + + afterAll(async () => { + await deleteOneObjectMetadata({ + input: { idToDelete: testObjectMetadataId }, + }); + }); + beforeEach(async () => { await cleanupViewRecords(); await createTestViewWithRestApi({ name: generateRecordName('Test View for Filter Groups'), + objectMetadataId: testObjectMetadataId, }); }); @@ -90,6 +123,7 @@ describe('View Filter Group REST API', () => { const parentData = { viewId: TEST_VIEW_1_ID, logicalOperator: 'AND', + objectMetadataId: testObjectMetadataId, }; const parentResponse = await makeRestAPIRequest({ @@ -105,6 +139,7 @@ describe('View Filter Group REST API', () => { viewId: TEST_VIEW_1_ID, parentViewFilterGroupId: parentId, logicalOperator: 'OR', + objectMetadataId: testObjectMetadataId, }; const childResponse = await makeRestAPIRequest({ @@ -214,6 +249,7 @@ describe('View Filter Group REST API', () => { const parentData = { viewId: TEST_VIEW_1_ID, logicalOperator: 'AND', + objectMetadataId: testObjectMetadataId, }; const parentResponse = await makeRestAPIRequest({ @@ -229,6 +265,7 @@ describe('View Filter Group REST API', () => { viewId: TEST_VIEW_1_ID, parentViewFilterGroupId: parentId, logicalOperator: 'OR', + objectMetadataId: testObjectMetadataId, }; const childGroupResponse = await makeRestAPIRequest({ @@ -247,6 +284,7 @@ describe('View Filter Group REST API', () => { const viewFilterGroupData = { viewId: TEST_VIEW_1_ID, logicalOperator: 'NOT', + objectMetadataId: testObjectMetadataId, }; const createResponse = await makeRestAPIRequest({ @@ -288,6 +326,7 @@ describe('View Filter Group REST API', () => { const viewFilterGroupData = { viewId: TEST_VIEW_1_ID, logicalOperator: 'AND', + objectMetadataId: testObjectMetadataId, }; const createResponse = await makeRestAPIRequest({ @@ -301,6 +340,7 @@ describe('View Filter Group REST API', () => { const updateData = { logicalOperator: 'OR', + objectMetadataId: testObjectMetadataId, }; const response = await makeRestAPIRequest({ @@ -321,6 +361,7 @@ describe('View Filter Group REST API', () => { const parentData = { viewId: TEST_VIEW_1_ID, logicalOperator: 'AND', + objectMetadataId: testObjectMetadataId, }; const parentResponse = await makeRestAPIRequest({ @@ -335,6 +376,7 @@ describe('View Filter Group REST API', () => { const childData = { viewId: TEST_VIEW_1_ID, logicalOperator: 'OR', + objectMetadataId: testObjectMetadataId, }; const childResponse = await makeRestAPIRequest({ @@ -394,6 +436,7 @@ describe('View Filter Group REST API', () => { const viewFilterGroupData = { viewId: TEST_VIEW_1_ID, logicalOperator: 'AND', + objectMetadataId: testObjectMetadataId, }; const createResponse = await makeRestAPIRequest({ diff --git a/packages/twenty-server/test/integration/rest/suites/view-filter.integration-spec.ts b/packages/twenty-server/test/integration/rest/suites/view-filter.integration-spec.ts index 2ce686afe3..bc9f5f0a2f 100644 --- a/packages/twenty-server/test/integration/rest/suites/view-filter.integration-spec.ts +++ b/packages/twenty-server/test/integration/rest/suites/view-filter.integration-spec.ts @@ -1,8 +1,10 @@ import { - TEST_FIELD_METADATA_1_ID, TEST_NOT_EXISTING_VIEW_FILTER_ID, TEST_VIEW_1_ID, } from 'test/integration/constants/test-view-ids.constants'; +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 { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util'; import { assertRestApiErrorResponse, @@ -17,6 +19,7 @@ import { assertViewFilterStructure, cleanupViewRecords, } from 'test/integration/utils/view-test.util'; +import { FieldMetadataType } from 'twenty-shared/types'; import { ViewFilterOperand } from 'src/engine/core-modules/view/enums/view-filter-operand'; import { @@ -25,11 +28,63 @@ import { } from 'src/engine/core-modules/view/exceptions/view-filter.exception'; describe('View Filter REST API', () => { + let testObjectMetadataId: string; + let testFieldMetadataId: string; + + beforeAll(async () => { + const { + data: { + createOneObject: { id: objectMetadataId }, + }, + } = await createOneObjectMetadata({ + input: { + nameSingular: 'myTestObject', + namePlural: 'myTestObjects', + labelSingular: 'My Test Object', + labelPlural: 'My Test Objects', + icon: 'Icon123', + }, + }); + + testObjectMetadataId = objectMetadataId; + + const createFieldInput = { + name: 'testField', + label: 'Test Field', + type: FieldMetadataType.TEXT, + objectMetadataId: testObjectMetadataId, + isLabelSyncedWithName: true, + }; + + const { + data: { + createOneField: { id: fieldMetadataId }, + }, + } = await createOneFieldMetadata({ + input: createFieldInput, + gqlFields: ` + id + name + label + isLabelSyncedWithName + `, + }); + + testFieldMetadataId = fieldMetadataId; + }); + + afterAll(async () => { + await deleteOneObjectMetadata({ + input: { idToDelete: testObjectMetadataId }, + }); + }); + beforeEach(async () => { await cleanupViewRecords(); await createTestViewWithRestApi({ name: 'Test View for Filters', + objectMetadataId: testObjectMetadataId, }); }); @@ -64,6 +119,7 @@ describe('View Filter REST API', () => { const viewFilter = await createTestViewFilterWithRestApi({ operand: ViewFilterOperand.CONTAINS, value: 'test', + fieldMetadataId: testFieldMetadataId, }); const response = await makeRestAPIRequest({ @@ -80,7 +136,7 @@ describe('View Filter REST API', () => { assertViewFilterStructure(returnedViewFilter, { id: viewFilter.id, - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, viewId: TEST_VIEW_1_ID, operand: ViewFilterOperand.CONTAINS, value: 'test', @@ -95,10 +151,11 @@ describe('View Filter REST API', () => { const viewFilter = await createTestViewFilterWithRestApi({ operand: ViewFilterOperand.IS, value: 'test value', + fieldMetadataId: testFieldMetadataId, }); assertViewFilterStructure(viewFilter, { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, viewId: TEST_VIEW_1_ID, operand: ViewFilterOperand.IS, value: 'test value', @@ -111,10 +168,11 @@ describe('View Filter REST API', () => { const numericFilter = await createTestViewFilterWithRestApi({ operand: ViewFilterOperand.GREATER_THAN_OR_EQUAL, value: '100', + fieldMetadataId: testFieldMetadataId, }); assertViewFilterStructure(numericFilter, { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, viewId: TEST_VIEW_1_ID, operand: ViewFilterOperand.GREATER_THAN_OR_EQUAL, value: '100', @@ -127,10 +185,11 @@ describe('View Filter REST API', () => { const booleanFilter = await createTestViewFilterWithRestApi({ operand: ViewFilterOperand.IS, value: 'true', + fieldMetadataId: testFieldMetadataId, }); assertViewFilterStructure(booleanFilter, { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, viewId: TEST_VIEW_1_ID, operand: ViewFilterOperand.IS, value: 'true', @@ -145,6 +204,7 @@ describe('View Filter REST API', () => { const viewFilter = await createTestViewFilterWithRestApi({ operand: ViewFilterOperand.IS, value: 'test', + fieldMetadataId: testFieldMetadataId, }); const response = await makeRestAPIRequest({ @@ -156,7 +216,7 @@ describe('View Filter REST API', () => { assertRestApiSuccessfulResponse(response); assertViewFilterStructure(response.body, { id: viewFilter.id, - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, viewId: TEST_VIEW_1_ID, operand: ViewFilterOperand.IS, value: 'test', @@ -182,6 +242,7 @@ describe('View Filter REST API', () => { const viewFilter = await createTestViewFilterWithRestApi({ operand: ViewFilterOperand.IS, value: 'original', + fieldMetadataId: testFieldMetadataId, }); const updateData = { @@ -201,7 +262,7 @@ describe('View Filter REST API', () => { id: viewFilter.id, operand: ViewFilterOperand.IS_NOT, value: 'updated', - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, viewId: TEST_VIEW_1_ID, }); @@ -237,6 +298,7 @@ describe('View Filter REST API', () => { const viewFilter = await createTestViewFilterWithRestApi({ operand: ViewFilterOperand.IS, value: 'to delete', + fieldMetadataId: testFieldMetadataId, }); const deleteResponse = await makeRestAPIRequest({ diff --git a/packages/twenty-server/test/integration/rest/suites/view-group.integration-spec.ts b/packages/twenty-server/test/integration/rest/suites/view-group.integration-spec.ts index 7871c58269..2b3b53f7a3 100644 --- a/packages/twenty-server/test/integration/rest/suites/view-group.integration-spec.ts +++ b/packages/twenty-server/test/integration/rest/suites/view-group.integration-spec.ts @@ -1,8 +1,10 @@ import { - TEST_FIELD_METADATA_1_ID, TEST_NOT_EXISTING_VIEW_GROUP_ID, TEST_VIEW_1_ID, } from 'test/integration/constants/test-view-ids.constants'; +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 { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util'; import { assertRestApiErrorResponse, @@ -18,19 +20,76 @@ import { assertViewGroupStructure, cleanupViewRecords, } from 'test/integration/utils/view-test.util'; +import { FieldMetadataType } from 'twenty-shared/types'; -import { type ViewGroup } from 'src/engine/core-modules/view/entities/view-group.entity'; +import { type ViewGroupEntity } from 'src/engine/core-modules/view/entities/view-group.entity'; import { generateViewGroupExceptionMessage, ViewGroupExceptionMessageKey, } from 'src/engine/core-modules/view/exceptions/view-group.exception'; describe('View Group REST API', () => { + let testObjectMetadataId: string; + let testFieldMetadataId: string; + + beforeAll(async () => { + await deleteOneObjectMetadata({ + input: { idToDelete: testObjectMetadataId }, + }); + + const { + data: { + createOneObject: { id: objectMetadataId }, + }, + } = await createOneObjectMetadata({ + input: { + nameSingular: 'myTestObject', + namePlural: 'myTestObjects', + labelSingular: 'My Test Object', + labelPlural: 'My Test Objects', + icon: 'Icon123', + }, + }); + + testObjectMetadataId = objectMetadataId; + + const createFieldInput = { + name: 'testField', + label: 'Test Field', + type: FieldMetadataType.TEXT, + objectMetadataId: testObjectMetadataId, + isLabelSyncedWithName: true, + }; + + const { + data: { + createOneField: { id: fieldMetadataId }, + }, + } = await createOneFieldMetadata({ + input: createFieldInput, + gqlFields: ` + id + name + label + isLabelSyncedWithName + `, + }); + + testFieldMetadataId = fieldMetadataId; + }); + + afterAll(async () => { + await deleteOneObjectMetadata({ + input: { idToDelete: testObjectMetadataId }, + }); + }); + beforeEach(async () => { await cleanupViewRecords(); await createTestViewWithRestApi({ name: generateRecordName('Test View for Groups'), + objectMetadataId: testObjectMetadataId, }); }); @@ -66,6 +125,7 @@ describe('View Group REST API', () => { fieldValue: 'test-field-value', isVisible: true, position: 0, + fieldMetadataId: testFieldMetadataId, }); const response = await makeRestAPIRequest({ @@ -95,11 +155,13 @@ describe('View Group REST API', () => { const viewGroup1 = await createTestViewGroupWithRestApi({ fieldValue: 'group-1', position: 0, + fieldMetadataId: testFieldMetadataId, }); const viewGroup2 = await createTestViewGroupWithRestApi({ fieldValue: 'group-2', position: 1, + fieldMetadataId: testFieldMetadataId, }); const response = await makeRestAPIRequest({ @@ -113,10 +175,10 @@ describe('View Group REST API', () => { expect(response.body).toHaveLength(2); const group1 = response.body.find( - (group: ViewGroup) => group.id === viewGroup1.id, + (group: ViewGroupEntity) => group.id === viewGroup1.id, ); const group2 = response.body.find( - (group: ViewGroup) => group.id === viewGroup2.id, + (group: ViewGroupEntity) => group.id === viewGroup2.id, ); assertViewGroupStructure(group1, { @@ -139,6 +201,7 @@ describe('View Group REST API', () => { const viewGroup = await createTestViewGroupWithRestApi({ fieldValue: 'specific-group', isVisible: false, + fieldMetadataId: testFieldMetadataId, }); const response = await makeRestAPIRequest({ @@ -163,7 +226,7 @@ describe('View Group REST API', () => { it('should create a new view group', async () => { const viewGroupData = { viewId: TEST_VIEW_1_ID, - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, fieldValue: 'new-group-value', isVisible: true, position: 5, @@ -190,7 +253,7 @@ describe('View Group REST API', () => { it('should create view group with minimal required fields', async () => { const viewGroupData = { viewId: TEST_VIEW_1_ID, - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, fieldValue: 'minimal-group', }; @@ -240,6 +303,7 @@ describe('View Group REST API', () => { fieldValue: 'original-value', isVisible: true, position: 1, + fieldMetadataId: testFieldMetadataId, }); const updateData = { @@ -272,6 +336,7 @@ describe('View Group REST API', () => { fieldValue: 'original-value', isVisible: true, position: 1, + fieldMetadataId: testFieldMetadataId, }); const updateData = { @@ -323,6 +388,7 @@ describe('View Group REST API', () => { it('should delete an existing view group', async () => { const viewGroup = await createTestViewGroupWithRestApi({ fieldValue: 'to-be-deleted', + fieldMetadataId: testFieldMetadataId, }); const deleteResponse = await makeRestAPIRequest({ @@ -355,6 +421,7 @@ describe('View Group REST API', () => { it('should return success even when group is already deleted', async () => { const viewGroup = await createTestViewGroupWithRestApi({ fieldValue: 'double-delete-test', + fieldMetadataId: testFieldMetadataId, }); const deleteResponse = await makeRestAPIRequest({ diff --git a/packages/twenty-server/test/integration/rest/suites/view-sort.integration-spec.ts b/packages/twenty-server/test/integration/rest/suites/view-sort.integration-spec.ts index 0c37e5cbaa..d99d704abc 100644 --- a/packages/twenty-server/test/integration/rest/suites/view-sort.integration-spec.ts +++ b/packages/twenty-server/test/integration/rest/suites/view-sort.integration-spec.ts @@ -1,8 +1,10 @@ import { - TEST_FIELD_METADATA_1_ID, TEST_NOT_EXISTING_VIEW_SORT_ID, TEST_VIEW_1_ID, } from 'test/integration/constants/test-view-ids.constants'; +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 { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util'; import { assertRestApiErrorResponse, @@ -17,6 +19,7 @@ import { assertViewSortStructure, cleanupViewRecords, } from 'test/integration/utils/view-test.util'; +import { FieldMetadataType } from 'twenty-shared/types'; import { ViewSortDirection } from 'src/engine/core-modules/view/enums/view-sort-direction'; import { @@ -25,11 +28,63 @@ import { } from 'src/engine/core-modules/view/exceptions/view-sort.exception'; describe('View Sort REST API', () => { + let testObjectMetadataId: string; + let testFieldMetadataId: string; + + beforeAll(async () => { + const { + data: { + createOneObject: { id: objectMetadataId }, + }, + } = await createOneObjectMetadata({ + input: { + nameSingular: 'myTestObject', + namePlural: 'myTestObjects', + labelSingular: 'My Test Object', + labelPlural: 'My Test Objects', + icon: 'Icon123', + }, + }); + + testObjectMetadataId = objectMetadataId; + + const createFieldInput = { + name: 'testField', + label: 'Test Field', + type: FieldMetadataType.TEXT, + objectMetadataId: testObjectMetadataId, + isLabelSyncedWithName: true, + }; + + const { + data: { + createOneField: { id: fieldMetadataId }, + }, + } = await createOneFieldMetadata({ + input: createFieldInput, + gqlFields: ` + id + name + label + isLabelSyncedWithName + `, + }); + + testFieldMetadataId = fieldMetadataId; + }); + + afterAll(async () => { + await deleteOneObjectMetadata({ + input: { idToDelete: testObjectMetadataId }, + }); + }); + beforeEach(async () => { await cleanupViewRecords(); await createTestViewWithRestApi({ name: generateRecordName('Test View for Sorts'), + objectMetadataId: testObjectMetadataId, }); }); @@ -63,6 +118,7 @@ describe('View Sort REST API', () => { it('should return view sorts for a specific view after creating one', async () => { const viewSort = await createTestViewSortWithRestApi({ direction: ViewSortDirection.ASC, + fieldMetadataId: testFieldMetadataId, }); const response = await makeRestAPIRequest({ @@ -79,7 +135,7 @@ describe('View Sort REST API', () => { assertViewSortStructure(returnedViewSort, { id: viewSort.id, - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, viewId: TEST_VIEW_1_ID, direction: ViewSortDirection.ASC, }); @@ -90,10 +146,11 @@ describe('View Sort REST API', () => { it('should create a new view sort with ASC direction', async () => { const viewSort = await createTestViewSortWithRestApi({ direction: ViewSortDirection.ASC, + fieldMetadataId: testFieldMetadataId, }); assertViewSortStructure(viewSort, { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, viewId: TEST_VIEW_1_ID, direction: ViewSortDirection.ASC, }); @@ -102,10 +159,11 @@ describe('View Sort REST API', () => { it('should create a view sort with DESC direction', async () => { const descSort = await createTestViewSortWithRestApi({ direction: ViewSortDirection.DESC, + fieldMetadataId: testFieldMetadataId, }); assertViewSortStructure(descSort, { - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, viewId: TEST_VIEW_1_ID, direction: ViewSortDirection.DESC, }); @@ -116,6 +174,7 @@ describe('View Sort REST API', () => { it('should return a view sort by id', async () => { const viewSort = await createTestViewSortWithRestApi({ direction: ViewSortDirection.ASC, + fieldMetadataId: testFieldMetadataId, }); const response = await makeRestAPIRequest({ @@ -127,7 +186,7 @@ describe('View Sort REST API', () => { assertRestApiSuccessfulResponse(response); assertViewSortStructure(response.body, { id: viewSort.id, - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, viewId: TEST_VIEW_1_ID, direction: ViewSortDirection.ASC, }); @@ -149,6 +208,7 @@ describe('View Sort REST API', () => { it('should update an existing view sort', async () => { const viewSort = await createTestViewSortWithRestApi({ direction: ViewSortDirection.ASC, + fieldMetadataId: testFieldMetadataId, }); const updateData = { @@ -166,7 +226,7 @@ describe('View Sort REST API', () => { assertViewSortStructure(response.body, { id: viewSort.id, direction: ViewSortDirection.DESC, - fieldMetadataId: TEST_FIELD_METADATA_1_ID, + fieldMetadataId: testFieldMetadataId, viewId: TEST_VIEW_1_ID, }); }); @@ -198,6 +258,7 @@ describe('View Sort REST API', () => { it('should delete an existing view sort', async () => { const viewSort = await createTestViewSortWithRestApi({ direction: ViewSortDirection.ASC, + fieldMetadataId: testFieldMetadataId, }); const deleteResponse = await makeRestAPIRequest({ diff --git a/packages/twenty-server/test/integration/rest/suites/view.integration-spec.ts b/packages/twenty-server/test/integration/rest/suites/view.integration-spec.ts index 3b3a4981d1..b3b1e47d59 100644 --- a/packages/twenty-server/test/integration/rest/suites/view.integration-spec.ts +++ b/packages/twenty-server/test/integration/rest/suites/view.integration-spec.ts @@ -1,7 +1,6 @@ -import { - TEST_NOT_EXISTING_VIEW_ID, - TEST_OBJECT_METADATA_1_ID, -} from 'test/integration/constants/test-view-ids.constants'; +import { TEST_NOT_EXISTING_VIEW_ID } from 'test/integration/constants/test-view-ids.constants'; +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 { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util'; import { assertRestApiErrorResponse, @@ -26,6 +25,32 @@ import { } from 'src/engine/core-modules/view/exceptions/view.exception'; describe('View REST API', () => { + let testObjectMetadataId: string; + + beforeAll(async () => { + const { + data: { + createOneObject: { id: objectMetadataId }, + }, + } = await createOneObjectMetadata({ + input: { + nameSingular: 'myTestObject', + namePlural: 'myTestObjects', + labelSingular: 'My Test Object', + labelPlural: 'My Test Objects', + icon: 'Icon123', + }, + }); + + testObjectMetadataId = objectMetadataId; + }); + + afterAll(async () => { + await deleteOneObjectMetadata({ + input: { idToDelete: testObjectMetadataId }, + }); + }); + beforeEach(async () => { await cleanupViewRecords(); }); @@ -49,7 +74,7 @@ describe('View REST API', () => { it('should return views filtered by objectMetadataId', async () => { const response = await makeRestAPIRequest({ method: 'get', - path: `/metadata/views?objectMetadataId=${TEST_OBJECT_METADATA_1_ID}`, + path: `/metadata/views?objectMetadataId=${testObjectMetadataId}`, bearer: APPLE_JANE_ADMIN_ACCESS_TOKEN, }); @@ -73,11 +98,12 @@ describe('View REST API', () => { position: 0, isCompact: false, openRecordIn: ViewOpenRecordIn.SIDE_PANEL, + objectMetadataId: testObjectMetadataId, }); assertViewStructure(view, { name: viewName, - objectMetadataId: TEST_OBJECT_METADATA_1_ID, + objectMetadataId: testObjectMetadataId, icon: 'IconTable', type: ViewType.TABLE, key: ViewKey.INDEX, @@ -97,6 +123,7 @@ describe('View REST API', () => { position: 1, isCompact: true, openRecordIn: ViewOpenRecordIn.SIDE_PANEL, + objectMetadataId: testObjectMetadataId, }); assertViewStructure(kanbanView, { @@ -104,6 +131,7 @@ describe('View REST API', () => { type: ViewType.KANBAN, isCompact: true, openRecordIn: ViewOpenRecordIn.SIDE_PANEL, + objectMetadataId: testObjectMetadataId, }); await deleteTestViewWithRestApi(kanbanView.id); @@ -121,6 +149,7 @@ describe('View REST API', () => { position: 0, isCompact: false, openRecordIn: ViewOpenRecordIn.SIDE_PANEL, + objectMetadataId: testObjectMetadataId, }); const response = await makeRestAPIRequest({ @@ -133,7 +162,7 @@ describe('View REST API', () => { assertViewStructure(response.body, { id: view.id, name: viewName, - objectMetadataId: TEST_OBJECT_METADATA_1_ID, + objectMetadataId: testObjectMetadataId, }); }); @@ -160,6 +189,7 @@ describe('View REST API', () => { position: 0, isCompact: false, openRecordIn: ViewOpenRecordIn.SIDE_PANEL, + objectMetadataId: testObjectMetadataId, }); const updatedName = generateRecordName('Updated View'); @@ -184,7 +214,7 @@ describe('View REST API', () => { type: ViewType.KANBAN, isCompact: true, openRecordIn: ViewOpenRecordIn.SIDE_PANEL, - objectMetadataId: TEST_OBJECT_METADATA_1_ID, + objectMetadataId: testObjectMetadataId, }); }); @@ -223,6 +253,7 @@ describe('View REST API', () => { position: 0, isCompact: false, openRecordIn: ViewOpenRecordIn.SIDE_PANEL, + objectMetadataId: testObjectMetadataId, }); const deleteResponse = await makeRestAPIRequest({ diff --git a/packages/twenty-server/test/integration/rest/utils/view-rest-api.util.ts b/packages/twenty-server/test/integration/rest/utils/view-rest-api.util.ts index 98585e1586..851c7447a3 100644 --- a/packages/twenty-server/test/integration/rest/utils/view-rest-api.util.ts +++ b/packages/twenty-server/test/integration/rest/utils/view-rest-api.util.ts @@ -6,18 +6,18 @@ import { import { makeRestAPIRequest } from 'test/integration/rest/utils/make-rest-api-request.util'; import { generateRecordName } from 'test/integration/utils/generate-record-name'; -import { type ViewField } from 'src/engine/core-modules/view/entities/view-field.entity'; -import { type ViewFilterGroup } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; -import { type ViewFilter } from 'src/engine/core-modules/view/entities/view-filter.entity'; -import { type ViewGroup } from 'src/engine/core-modules/view/entities/view-group.entity'; -import { type ViewSort } from 'src/engine/core-modules/view/entities/view-sort.entity'; -import { type View } from 'src/engine/core-modules/view/entities/view.entity'; +import { type ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; +import { type ViewFilterGroupEntity } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; +import { type ViewFilterEntity } from 'src/engine/core-modules/view/entities/view-filter.entity'; +import { type ViewGroupEntity } from 'src/engine/core-modules/view/entities/view-group.entity'; +import { type ViewSortEntity } from 'src/engine/core-modules/view/entities/view-sort.entity'; +import { type ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { ViewOpenRecordIn } from 'src/engine/core-modules/view/enums/view-open-record-in'; import { ViewType } from 'src/engine/core-modules/view/enums/view-type.enum'; export const createTestViewWithRestApi = async ( - overrides: Partial = {}, -): Promise => { + overrides: Partial = {}, +): Promise => { const viewData = { id: TEST_VIEW_1_ID, name: generateRecordName('Test View'), @@ -48,8 +48,8 @@ export const createTestViewWithRestApi = async ( }; export const createTestViewFieldWithRestApi = async ( - overrides: Partial = {}, -): Promise => { + overrides: Partial = {}, +): Promise => { const viewFieldData = { viewId: TEST_VIEW_1_ID, fieldMetadataId: TEST_FIELD_METADATA_1_ID, @@ -76,8 +76,8 @@ export const createTestViewFieldWithRestApi = async ( }; export const createTestViewFilterWithRestApi = async ( - overrides: Partial = {}, -): Promise => { + overrides: Partial = {}, +): Promise => { const viewFilterData = { viewId: TEST_VIEW_1_ID, fieldMetadataId: TEST_FIELD_METADATA_1_ID, @@ -103,8 +103,8 @@ export const createTestViewFilterWithRestApi = async ( }; export const createTestViewSortWithRestApi = async ( - overrides: Partial = {}, -): Promise => { + overrides: Partial = {}, +): Promise => { const viewSortData = { viewId: TEST_VIEW_1_ID, fieldMetadataId: TEST_FIELD_METADATA_1_ID, @@ -129,8 +129,8 @@ export const createTestViewSortWithRestApi = async ( }; export const createTestViewGroupWithRestApi = async ( - overrides: Partial = {}, -): Promise => { + overrides: Partial = {}, +): Promise => { const viewGroupData = { viewId: TEST_VIEW_1_ID, fieldMetadataId: TEST_FIELD_METADATA_1_ID, @@ -157,8 +157,8 @@ export const createTestViewGroupWithRestApi = async ( }; export const createTestViewFilterGroupWithRestApi = async ( - overrides: Partial = {}, -): Promise => { + overrides: Partial = {}, +): Promise => { const viewFilterGroupData = { viewId: TEST_VIEW_1_ID, logicalOperator: 'AND', diff --git a/packages/twenty-server/test/integration/utils/view-test.util.ts b/packages/twenty-server/test/integration/utils/view-test.util.ts index 4c7f244ce1..9c0c6339be 100644 --- a/packages/twenty-server/test/integration/utils/view-test.util.ts +++ b/packages/twenty-server/test/integration/utils/view-test.util.ts @@ -1,9 +1,9 @@ -import { type ViewField } from 'src/engine/core-modules/view/entities/view-field.entity'; -import { type ViewFilterGroup } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; -import { type ViewFilter } from 'src/engine/core-modules/view/entities/view-filter.entity'; -import { type ViewGroup } from 'src/engine/core-modules/view/entities/view-group.entity'; -import { type ViewSort } from 'src/engine/core-modules/view/entities/view-sort.entity'; -import { type View } from 'src/engine/core-modules/view/entities/view.entity'; +import { type ViewFieldEntity } from 'src/engine/core-modules/view/entities/view-field.entity'; +import { type ViewFilterGroupEntity } from 'src/engine/core-modules/view/entities/view-filter-group.entity'; +import { type ViewFilterEntity } from 'src/engine/core-modules/view/entities/view-filter.entity'; +import { type ViewGroupEntity } from 'src/engine/core-modules/view/entities/view-group.entity'; +import { type ViewSortEntity } from 'src/engine/core-modules/view/entities/view-sort.entity'; +import { type ViewEntity } from 'src/engine/core-modules/view/entities/view.entity'; import { ViewFilterGroupLogicalOperator } from 'src/modules/view/standard-objects/view-filter-group.workspace-entity'; export const cleanupViewRecords = async (): Promise => { @@ -12,8 +12,8 @@ export const cleanupViewRecords = async (): Promise => { }; export const assertViewStructure = ( - view: View, - expectedFields?: Partial, + view: ViewEntity, + expectedFields?: Partial, ) => { expect(view).toBeDefined(); expect(view.id).toBeDefined(); @@ -29,8 +29,8 @@ export const assertViewStructure = ( }; export const assertViewFieldStructure = ( - viewField: ViewField, - expectedFields?: Partial, + viewField: ViewFieldEntity, + expectedFields?: Partial, ) => { expect(viewField).toBeDefined(); expect(viewField.id).toBeDefined(); @@ -46,8 +46,8 @@ export const assertViewFieldStructure = ( }; export const assertViewSortStructure = ( - viewSort: ViewSort, - expectedFields?: Partial, + viewSort: ViewSortEntity, + expectedFields?: Partial, ) => { expect(viewSort).toBeDefined(); expect(viewSort.id).toBeDefined(); @@ -62,8 +62,8 @@ export const assertViewSortStructure = ( }; export const assertViewFilterStructure = ( - viewFilter: ViewFilter, - expectedFields?: Partial, + viewFilter: ViewFilterEntity, + expectedFields?: Partial, ) => { expect(viewFilter).toBeDefined(); expect(viewFilter.id).toBeDefined(); @@ -78,8 +78,8 @@ export const assertViewFilterStructure = ( }; export const assertViewGroupStructure = ( - viewGroup: ViewGroup, - expectedFields?: Partial, + viewGroup: ViewGroupEntity, + expectedFields?: Partial, ) => { expect(viewGroup).toBeDefined(); expect(viewGroup.id).toBeDefined(); @@ -95,8 +95,8 @@ export const assertViewGroupStructure = ( }; export const assertViewFilterGroupStructure = ( - viewFilterGroup: ViewFilterGroup, - expectedFields?: Partial, + viewFilterGroup: ViewFilterGroupEntity, + expectedFields?: Partial, validLogicalOperators: string[] = [ ViewFilterGroupLogicalOperator.AND, ViewFilterGroupLogicalOperator.OR,