diff --git a/front/.nvmrc b/front/.nvmrc index 807e541706..3c79f30eca 100644 --- a/front/.nvmrc +++ b/front/.nvmrc @@ -1 +1 @@ -18.6.0 \ No newline at end of file +18.16.0 \ No newline at end of file diff --git a/front/src/generated/graphql.tsx b/front/src/generated/graphql.tsx index 30bfc9c056..b4573e790c 100644 --- a/front/src/generated/graphql.tsx +++ b/front/src/generated/graphql.tsx @@ -293,7 +293,7 @@ export type CommentThreadTarget = { createdAt: Scalars['DateTime']; id: Scalars['ID']; updatedAt: Scalars['DateTime']; - workspace: Workspace; + workspace?: Maybe; }; export type CommentThreadTargetCreateManyCommentThreadInput = { @@ -712,6 +712,17 @@ export enum FileFolder { WorkspaceLogo = 'WorkspaceLogo' } +export type IntFilter = { + equals?: InputMaybe; + gt?: InputMaybe; + gte?: InputMaybe; + in?: InputMaybe>; + lt?: InputMaybe; + lte?: InputMaybe; + not?: InputMaybe; + notIn?: InputMaybe>; +}; + export type IntNullableFilter = { equals?: InputMaybe; gt?: InputMaybe; @@ -765,6 +776,7 @@ export type Mutation = { updateOnePerson?: Maybe; updateOnePipelineProgress?: Maybe; updateOnePipelineStage?: Maybe; + updateOneViewField: ViewField; updateUser: User; updateWorkspace: Workspace; uploadAttachment: Scalars['String']; @@ -880,6 +892,12 @@ export type MutationUpdateOnePipelineStageArgs = { }; +export type MutationUpdateOneViewFieldArgs = { + data: ViewFieldUpdateInput; + where: ViewFieldWhereUniqueInput; +}; + + export type MutationUpdateUserArgs = { data: UserUpdateInput; where: UserWhereUniqueInput; @@ -985,6 +1003,17 @@ export type NestedEnumPipelineProgressableTypeFilter = { notIn?: InputMaybe>; }; +export type NestedIntFilter = { + equals?: InputMaybe; + gt?: InputMaybe; + gte?: InputMaybe; + in?: InputMaybe>; + lt?: InputMaybe; + lte?: InputMaybe; + not?: InputMaybe; + notIn?: InputMaybe>; +}; + export type NestedIntNullableFilter = { equals?: InputMaybe; gt?: InputMaybe; @@ -1500,6 +1529,7 @@ export type Query = { findManyPipelineProgress: Array; findManyPipelineStage: Array; findManyUser: Array; + findManyViewField: Array; findManyWorkspaceMember: Array; findUniqueCompany: Company; findUniquePerson: Person; @@ -1586,6 +1616,16 @@ export type QueryFindManyUserArgs = { }; +export type QueryFindManyViewFieldArgs = { + cursor?: InputMaybe; + distinct?: InputMaybe>; + orderBy?: InputMaybe>; + skip?: InputMaybe; + take?: InputMaybe; + where?: InputMaybe; +}; + + export type QueryFindManyWorkspaceMemberArgs = { cursor?: InputMaybe; distinct?: InputMaybe>; @@ -1867,6 +1907,66 @@ export type Verify = { user: User; }; +export type ViewField = { + __typename?: 'ViewField'; + fieldName: Scalars['String']; + id: Scalars['ID']; + index: Scalars['Int']; + isVisible: Scalars['Boolean']; + objectName: Scalars['String']; + sizeInPx: Scalars['Int']; +}; + +export type ViewFieldOrderByWithRelationInput = { + fieldName?: InputMaybe; + id?: InputMaybe; + index?: InputMaybe; + isVisible?: InputMaybe; + objectName?: InputMaybe; + sizeInPx?: InputMaybe; +}; + +export enum ViewFieldScalarFieldEnum { + FieldName = 'fieldName', + Id = 'id', + Index = 'index', + IsVisible = 'isVisible', + ObjectName = 'objectName', + SizeInPx = 'sizeInPx', + WorkspaceId = 'workspaceId' +} + +export type ViewFieldUpdateInput = { + fieldName?: InputMaybe; + id?: InputMaybe; + index?: InputMaybe; + isVisible?: InputMaybe; + objectName?: InputMaybe; + sizeInPx?: InputMaybe; +}; + +export type ViewFieldUpdateManyWithoutWorkspaceNestedInput = { + connect?: InputMaybe>; + disconnect?: InputMaybe>; + set?: InputMaybe>; +}; + +export type ViewFieldWhereInput = { + AND?: InputMaybe>; + NOT?: InputMaybe>; + OR?: InputMaybe>; + fieldName?: InputMaybe; + id?: InputMaybe; + index?: InputMaybe; + isVisible?: InputMaybe; + objectName?: InputMaybe; + sizeInPx?: InputMaybe; +}; + +export type ViewFieldWhereUniqueInput = { + id?: InputMaybe; +}; + export type Workspace = { __typename?: 'Workspace'; Attachment?: Maybe>; @@ -1885,6 +1985,7 @@ export type Workspace = { pipelineStages?: Maybe>; pipelines?: Maybe>; updatedAt: Scalars['DateTime']; + viewFields?: Maybe>; workspaceMember?: Maybe>; }; @@ -1959,6 +2060,7 @@ export type WorkspaceUpdateInput = { pipelineStages?: InputMaybe; pipelines?: InputMaybe; updatedAt?: InputMaybe; + viewFields?: InputMaybe; workspaceMember?: InputMaybe; }; @@ -2342,6 +2444,21 @@ export type RemoveProfilePictureMutationVariables = Exact<{ export type RemoveProfilePictureMutation = { __typename?: 'Mutation', updateUser: { __typename?: 'User', id: string, avatarUrl?: string | null } }; +export type GetViewFieldsQueryVariables = Exact<{ + where?: InputMaybe; +}>; + + +export type GetViewFieldsQuery = { __typename?: 'Query', viewFields: Array<{ __typename?: 'ViewField', id: string, fieldName: string, isVisible: boolean, sizeInPx: number, index: number }> }; + +export type UpdateViewFieldMutationVariables = Exact<{ + data: ViewFieldUpdateInput; + where: ViewFieldWhereUniqueInput; +}>; + + +export type UpdateViewFieldMutation = { __typename?: 'Mutation', updateOneViewField: { __typename?: 'ViewField', id: string, fieldName: string, isVisible: boolean, sizeInPx: number, index: number } }; + export type GetWorkspaceMembersQueryVariables = Exact<{ [key: string]: never; }>; @@ -4470,6 +4587,83 @@ export function useRemoveProfilePictureMutation(baseOptions?: Apollo.MutationHoo export type RemoveProfilePictureMutationHookResult = ReturnType; export type RemoveProfilePictureMutationResult = Apollo.MutationResult; export type RemoveProfilePictureMutationOptions = Apollo.BaseMutationOptions; +export const GetViewFieldsDocument = gql` + query GetViewFields($where: ViewFieldWhereInput) { + viewFields: findManyViewField(where: $where) { + id + fieldName + isVisible + sizeInPx + index + } +} + `; + +/** + * __useGetViewFieldsQuery__ + * + * To run a query within a React component, call `useGetViewFieldsQuery` and pass it any options that fit your needs. + * When your component renders, `useGetViewFieldsQuery` returns an object from Apollo Client that contains loading, error, and data properties + * you can use to render your UI. + * + * @param baseOptions options that will be passed into the query, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options; + * + * @example + * const { data, loading, error } = useGetViewFieldsQuery({ + * variables: { + * where: // value for 'where' + * }, + * }); + */ +export function useGetViewFieldsQuery(baseOptions?: Apollo.QueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useQuery(GetViewFieldsDocument, options); + } +export function useGetViewFieldsLazyQuery(baseOptions?: Apollo.LazyQueryHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useLazyQuery(GetViewFieldsDocument, options); + } +export type GetViewFieldsQueryHookResult = ReturnType; +export type GetViewFieldsLazyQueryHookResult = ReturnType; +export type GetViewFieldsQueryResult = Apollo.QueryResult; +export const UpdateViewFieldDocument = gql` + mutation UpdateViewField($data: ViewFieldUpdateInput!, $where: ViewFieldWhereUniqueInput!) { + updateOneViewField(data: $data, where: $where) { + id + fieldName + isVisible + sizeInPx + index + } +} + `; +export type UpdateViewFieldMutationFn = Apollo.MutationFunction; + +/** + * __useUpdateViewFieldMutation__ + * + * To run a mutation, you first call `useUpdateViewFieldMutation` within a React component and pass it any options that fit your needs. + * When your component renders, `useUpdateViewFieldMutation` returns a tuple that includes: + * - A mutate function that you can call at any time to execute the mutation + * - An object with fields that represent the current status of the mutation's execution + * + * @param baseOptions options that will be passed into the mutation, supported options are listed on: https://www.apollographql.com/docs/react/api/react-hooks/#options-2; + * + * @example + * const [updateViewFieldMutation, { data, loading, error }] = useUpdateViewFieldMutation({ + * variables: { + * data: // value for 'data' + * where: // value for 'where' + * }, + * }); + */ +export function useUpdateViewFieldMutation(baseOptions?: Apollo.MutationHookOptions) { + const options = {...defaultOptions, ...baseOptions} + return Apollo.useMutation(UpdateViewFieldDocument, options); + } +export type UpdateViewFieldMutationHookResult = ReturnType; +export type UpdateViewFieldMutationResult = Apollo.MutationResult; +export type UpdateViewFieldMutationOptions = Apollo.BaseMutationOptions; export const GetWorkspaceMembersDocument = gql` query GetWorkspaceMembers { workspaceMembers: findManyWorkspaceMember { diff --git a/front/src/modules/views/queries/select.ts b/front/src/modules/views/queries/select.ts new file mode 100644 index 0000000000..2341c0722c --- /dev/null +++ b/front/src/modules/views/queries/select.ts @@ -0,0 +1,13 @@ +import { gql } from '@apollo/client'; + +export const GET_VIEW_FIELDS = gql` + query GetViewFields($where: ViewFieldWhereInput) { + viewFields: findManyViewField(where: $where) { + id + fieldName + isVisible + sizeInPx + index + } + } +`; diff --git a/front/src/modules/views/queries/update.ts b/front/src/modules/views/queries/update.ts new file mode 100644 index 0000000000..c270d7a6b7 --- /dev/null +++ b/front/src/modules/views/queries/update.ts @@ -0,0 +1,16 @@ +import { gql } from '@apollo/client'; + +export const UPDATE_VIEW_FIELD = gql` + mutation UpdateViewField( + $data: ViewFieldUpdateInput! + $where: ViewFieldWhereUniqueInput! + ) { + updateOneViewField(data: $data, where: $where) { + id + fieldName + isVisible + sizeInPx + index + } + } +`; diff --git a/server/.nvmrc b/server/.nvmrc index 5036cb7c07..6d80269a4f 100644 --- a/server/.nvmrc +++ b/server/.nvmrc @@ -1 +1 @@ -18.10.0 +18.16.0 diff --git a/server/src/ability/ability.factory.ts b/server/src/ability/ability.factory.ts index a4c1662f45..6b927f3286 100644 --- a/server/src/ability/ability.factory.ts +++ b/server/src/ability/ability.factory.ts @@ -17,6 +17,7 @@ import { PipelineProgress, Attachment, UserSettings, + ViewField, } from '@prisma/client'; import { AbilityAction } from './ability.action'; @@ -36,6 +37,7 @@ type SubjectsAbility = Subjects<{ PipelineProgress: PipelineProgress; Attachment: Attachment; UserSettings: UserSettings; + ViewField: ViewField; }>; export type AppAbility = PureAbility< @@ -128,6 +130,10 @@ export class AbilityFactory { workspaceId: workspace.id, }); + // ViewField + can(AbilityAction.Read, 'ViewField', { workspaceId: workspace.id }); + can(AbilityAction.Update, 'ViewField', { workspaceId: workspace.id }); + return build(); } } diff --git a/server/src/ability/ability.module.ts b/server/src/ability/ability.module.ts index 5b4607c464..72ccb3e603 100644 --- a/server/src/ability/ability.module.ts +++ b/server/src/ability/ability.module.ts @@ -94,6 +94,10 @@ import { ReadAttachmentAbilityHandler, UpdateAttachmentAbilityHandler, } from './handlers/attachment.ability-handler'; +import { + ReadViewFieldAbilityHandler, + UpdateViewFieldAbilityHandler, +} from './handlers/view-field.ability-handler'; @Global() @Module({ @@ -178,6 +182,9 @@ import { CreatePipelineProgressAbilityHandler, UpdatePipelineProgressAbilityHandler, DeletePipelineProgressAbilityHandler, + // ViewField + ReadViewFieldAbilityHandler, + UpdateViewFieldAbilityHandler, ], exports: [ AbilityFactory, @@ -259,6 +266,9 @@ import { CreatePipelineProgressAbilityHandler, UpdatePipelineProgressAbilityHandler, DeletePipelineProgressAbilityHandler, + // ViewField + ReadViewFieldAbilityHandler, + UpdateViewFieldAbilityHandler, ], }) export class AbilityModule {} diff --git a/server/src/ability/handlers/view-field.ability-handler.ts b/server/src/ability/handlers/view-field.ability-handler.ts new file mode 100644 index 0000000000..4a4380cbbe --- /dev/null +++ b/server/src/ability/handlers/view-field.ability-handler.ts @@ -0,0 +1,56 @@ +import { + ExecutionContext, + Injectable, + NotFoundException, +} from '@nestjs/common'; +import { GqlExecutionContext } from '@nestjs/graphql'; + +import { subject } from '@casl/ability'; + +import { IAbilityHandler } from 'src/ability/interfaces/ability-handler.interface'; + +import { AbilityAction } from 'src/ability/ability.action'; +import { AppAbility } from 'src/ability/ability.factory'; +import { relationAbilityChecker } from 'src/ability/ability.util'; +import { ViewFieldWhereInput } from 'src/core/@generated/view-field/view-field-where.input'; +import { PrismaService } from 'src/database/prisma.service'; +import { assert } from 'src/utils/assert'; + +class ViewFieldArgs { + where?: ViewFieldWhereInput; + [key: string]: any; +} + +@Injectable() +export class ReadViewFieldAbilityHandler implements IAbilityHandler { + handle(ability: AppAbility) { + return ability.can(AbilityAction.Read, 'ViewField'); + } +} + +@Injectable() +export class UpdateViewFieldAbilityHandler implements IAbilityHandler { + constructor(private readonly prismaService: PrismaService) {} + + async handle(ability: AppAbility, context: ExecutionContext) { + const gqlContext = GqlExecutionContext.create(context); + const args = gqlContext.getArgs(); + const viewField = await this.prismaService.client.viewField.findFirst({ + where: args.where, + }); + assert(viewField, '', NotFoundException); + + const allowed = await relationAbilityChecker( + 'ViewField', + ability, + this.prismaService.client, + args, + ); + + if (!allowed) { + return false; + } + + return ability.can(AbilityAction.Update, subject('ViewField', viewField)); + } +} diff --git a/server/src/core/core.module.ts b/server/src/core/core.module.ts index 5ddf91f0ca..4832e4409c 100644 --- a/server/src/core/core.module.ts +++ b/server/src/core/core.module.ts @@ -11,6 +11,7 @@ import { AnalyticsModule } from './analytics/analytics.module'; import { FileModule } from './file/file.module'; import { ClientConfigModule } from './client-config/client-config.module'; import { AttachmentModule } from './attachment/attachment.module'; +import { ViewModule } from './view/view.module'; @Module({ imports: [ @@ -25,6 +26,7 @@ import { AttachmentModule } from './attachment/attachment.module'; FileModule, ClientConfigModule, AttachmentModule, + ViewModule, ], exports: [ AuthModule, diff --git a/server/src/core/view/resolvers/view-field.resolver.spec.ts b/server/src/core/view/resolvers/view-field.resolver.spec.ts new file mode 100644 index 0000000000..2084cedb46 --- /dev/null +++ b/server/src/core/view/resolvers/view-field.resolver.spec.ts @@ -0,0 +1,32 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { ViewFieldService } from 'src/core/view/services/view-field.service'; + +import { ViewFieldResolver } from './view-field.resolver'; +import { AbilityFactory } from 'src/ability/ability.factory'; + +describe('ViewFieldResolver', () => { + let resolver: ViewFieldResolver; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + ViewFieldResolver, + { + provide: ViewFieldService, + useValue: {}, + }, + { + provide: AbilityFactory, + useValue: {}, + }, + ], + }).compile(); + + resolver = module.get(ViewFieldResolver); + }); + + it('should be defined', () => { + expect(resolver).toBeDefined(); + }); +}); diff --git a/server/src/core/view/resolvers/view-field.resolver.ts b/server/src/core/view/resolvers/view-field.resolver.ts new file mode 100644 index 0000000000..2ac1be3e77 --- /dev/null +++ b/server/src/core/view/resolvers/view-field.resolver.ts @@ -0,0 +1,68 @@ +import { UseGuards } from '@nestjs/common'; +import { Args, Mutation, Query, Resolver } from '@nestjs/graphql'; + +import { accessibleBy } from '@casl/prisma'; +import { Prisma } from '@prisma/client'; + +import { AppAbility } from 'src/ability/ability.factory'; +import { + ReadViewFieldAbilityHandler, + UpdateViewFieldAbilityHandler, +} from 'src/ability/handlers/view-field.ability-handler'; +import { FindManyViewFieldArgs } from 'src/core/@generated/view-field/find-many-view-field.args'; +import { UpdateOneViewFieldArgs } from 'src/core/@generated/view-field/update-one-view-field.args'; +import { ViewField } from 'src/core/@generated/view-field/view-field.model'; +import { ViewFieldService } from 'src/core/view/services/view-field.service'; +import { CheckAbilities } from 'src/decorators/check-abilities.decorator'; +import { + PrismaSelect, + PrismaSelector, +} from 'src/decorators/prisma-select.decorator'; +import { UserAbility } from 'src/decorators/user-ability.decorator'; +import { AbilityGuard } from 'src/guards/ability.guard'; +import { JwtAuthGuard } from 'src/guards/jwt.auth.guard'; + +@UseGuards(JwtAuthGuard) +@Resolver(() => ViewField) +export class ViewFieldResolver { + constructor(private readonly viewFieldService: ViewFieldService) {} + + @Query(() => [ViewField]) + @UseGuards(AbilityGuard) + @CheckAbilities(ReadViewFieldAbilityHandler) + async findManyViewField( + @Args() args: FindManyViewFieldArgs, + @UserAbility() ability: AppAbility, + @PrismaSelector({ modelName: 'ViewField' }) + prismaSelect: PrismaSelect<'ViewField'>, + ): Promise[]> { + return this.viewFieldService.findMany({ + where: args.where + ? { + AND: [args.where, accessibleBy(ability).ViewField], + } + : accessibleBy(ability).ViewField, + orderBy: args.orderBy, + cursor: args.cursor, + take: args.take, + skip: args.skip, + distinct: args.distinct, + select: prismaSelect.value, + }); + } + + @Mutation(() => ViewField) + @UseGuards(AbilityGuard) + @CheckAbilities(UpdateViewFieldAbilityHandler) + async updateOneViewField( + @Args() args: UpdateOneViewFieldArgs, + @PrismaSelector({ modelName: 'ViewField' }) + prismaSelect: PrismaSelect<'ViewField'>, + ) { + return this.viewFieldService.update({ + where: args.where, + data: args.data, + select: prismaSelect.value, + } as Prisma.ViewFieldUpdateArgs); + } +} diff --git a/server/src/core/view/services/view-field.service.spec.ts b/server/src/core/view/services/view-field.service.spec.ts new file mode 100644 index 0000000000..6f3eeea520 --- /dev/null +++ b/server/src/core/view/services/view-field.service.spec.ts @@ -0,0 +1,28 @@ +import { Test, TestingModule } from '@nestjs/testing'; + +import { PrismaService } from 'src/database/prisma.service'; +import { prismaMock } from 'src/database/client-mock/jest-prisma-singleton'; + +import { ViewFieldService } from './view-field.service'; + +describe('ViewFieldService', () => { + let service: ViewFieldService; + + beforeEach(async () => { + const module: TestingModule = await Test.createTestingModule({ + providers: [ + ViewFieldService, + { + provide: PrismaService, + useValue: prismaMock, + }, + ], + }).compile(); + + service = module.get(ViewFieldService); + }); + + it('should be defined', () => { + expect(service).toBeDefined(); + }); +}); diff --git a/server/src/core/view/services/view-field.service.ts b/server/src/core/view/services/view-field.service.ts new file mode 100644 index 0000000000..e55f6ad217 --- /dev/null +++ b/server/src/core/view/services/view-field.service.ts @@ -0,0 +1,39 @@ +import { Injectable } from '@nestjs/common'; + +import { PrismaService } from 'src/database/prisma.service'; + +@Injectable() +export class ViewFieldService { + constructor(private readonly prismaService: PrismaService) {} + + // Find + findFirst = this.prismaService.client.viewField.findFirst; + findFirstOrThrow = this.prismaService.client.viewField.findFirstOrThrow; + + findUnique = this.prismaService.client.viewField.findUnique; + findUniqueOrThrow = this.prismaService.client.viewField.findUniqueOrThrow; + + findMany = this.prismaService.client.viewField.findMany; + + // Create + create = this.prismaService.client.viewField.create; + createMany = this.prismaService.client.viewField.createMany; + + // Update + update = this.prismaService.client.viewField.update; + upsert = this.prismaService.client.viewField.upsert; + updateMany = this.prismaService.client.viewField.updateMany; + + // Delete + delete = this.prismaService.client.viewField.delete; + deleteMany = this.prismaService.client.viewField.deleteMany; + + // Aggregate + aggregate = this.prismaService.client.viewField.aggregate; + + // Count + count = this.prismaService.client.viewField.count; + + // GroupBy + groupBy = this.prismaService.client.viewField.groupBy; +} diff --git a/server/src/core/view/view.module.ts b/server/src/core/view/view.module.ts new file mode 100644 index 0000000000..f22071866c --- /dev/null +++ b/server/src/core/view/view.module.ts @@ -0,0 +1,9 @@ +import { Module } from '@nestjs/common'; + +import { ViewFieldService } from './services/view-field.service'; +import { ViewFieldResolver } from './resolvers/view-field.resolver'; + +@Module({ + providers: [ViewFieldService, ViewFieldResolver], +}) +export class ViewModule {} diff --git a/server/src/database/migrations/20230727124244_add_view_fields_table/migration.sql b/server/src/database/migrations/20230727124244_add_view_fields_table/migration.sql new file mode 100644 index 0000000000..178c90ce81 --- /dev/null +++ b/server/src/database/migrations/20230727124244_add_view_fields_table/migration.sql @@ -0,0 +1,15 @@ +-- CreateTable +CREATE TABLE "viewFields" ( + "id" TEXT NOT NULL, + "fieldName" TEXT NOT NULL, + "index" INTEGER NOT NULL, + "isVisible" BOOLEAN NOT NULL, + "objectName" TEXT NOT NULL, + "sizeInPx" INTEGER NOT NULL, + "workspaceId" TEXT NOT NULL, + + CONSTRAINT "viewFields_pkey" PRIMARY KEY ("id") +); + +-- AddForeignKey +ALTER TABLE "viewFields" ADD CONSTRAINT "viewFields_workspaceId_fkey" FOREIGN KEY ("workspaceId") REFERENCES "workspaces"("id") ON DELETE RESTRICT ON UPDATE CASCADE; diff --git a/server/src/database/schema.prisma b/server/src/database/schema.prisma index c4b922939e..a45e76d7de 100644 --- a/server/src/database/schema.prisma +++ b/server/src/database/schema.prisma @@ -169,6 +169,7 @@ model Workspace { pipelines Pipeline[] pipelineStages PipelineStage[] pipelineProgresses PipelineProgress[] + viewFields ViewField[] /// @TypeGraphQL.omit(input: true, output: true) deletedAt DateTime? @@ -532,3 +533,22 @@ model Attachment { @@map("attachments") } + +model ViewField { + /// @Validator.IsString() + /// @Validator.IsOptional() + id String @id @default(uuid()) + + fieldName String + index Int + isVisible Boolean + objectName String + sizeInPx Int + + /// @TypeGraphQL.omit(input: true, output: true) + workspace Workspace @relation(fields: [workspaceId], references: [id]) + /// @TypeGraphQL.omit(input: true, output: true) + workspaceId String + + @@map("viewFields") +} diff --git a/server/src/utils/prisma-select/model-select-map.ts b/server/src/utils/prisma-select/model-select-map.ts index e8779a3a3a..bb286ef78c 100644 --- a/server/src/utils/prisma-select/model-select-map.ts +++ b/server/src/utils/prisma-select/model-select-map.ts @@ -16,4 +16,5 @@ export type ModelSelectMap = { PipelineStage: Prisma.PipelineStageSelect; PipelineProgress: Prisma.PipelineProgressSelect; Attachment: Prisma.AttachmentSelect; + ViewField: Prisma.ViewFieldSelect; };