first commit
This commit is contained in:
239
libs/api/tracker/presenters/src/lib/graphql/inputs.ts
Normal file
239
libs/api/tracker/presenters/src/lib/graphql/inputs.ts
Normal file
@@ -0,0 +1,239 @@
|
||||
import { Field, ID, InputType, Int } from '@nestjs/graphql';
|
||||
import {
|
||||
IssueArea,
|
||||
IssueLinkType,
|
||||
IssuePriority,
|
||||
IssueStatus,
|
||||
IssueType,
|
||||
ProjectRole,
|
||||
} from '@task-stream/api/tracker/domain';
|
||||
import {
|
||||
ArrayMaxSize,
|
||||
IsBoolean,
|
||||
IsEnum,
|
||||
IsInt,
|
||||
IsISO8601,
|
||||
IsOptional,
|
||||
IsString,
|
||||
IsUrl,
|
||||
IsUUID,
|
||||
Matches,
|
||||
Max,
|
||||
MaxLength,
|
||||
Min,
|
||||
MinLength,
|
||||
} from 'class-validator';
|
||||
|
||||
@InputType()
|
||||
export class CreateProjectInput {
|
||||
@Field({ description: '2-10 chars, e.g. "TS" → tickets TS-1, TS-2...' })
|
||||
@Matches(/^[A-Za-z][A-Za-z0-9]{1,9}$/)
|
||||
key!: string;
|
||||
|
||||
@Field() @IsString() @MinLength(1) @MaxLength(120) name!: string;
|
||||
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MaxLength(5000)
|
||||
description?: string | null;
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class UpdateProjectInput {
|
||||
@Field(() => ID) @IsUUID() projectId!: string;
|
||||
@Field({ nullable: true })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MinLength(1)
|
||||
@MaxLength(120)
|
||||
name?: string;
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MaxLength(5000)
|
||||
description?: string | null;
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class ProjectMemberInput {
|
||||
@Field(() => ID) @IsUUID() projectId!: string;
|
||||
@Field(() => ID, { description: 'Pireon user id' })
|
||||
@IsString()
|
||||
userId!: string;
|
||||
@Field(() => ProjectRole, { defaultValue: ProjectRole.MEMBER })
|
||||
@IsEnum(ProjectRole)
|
||||
role!: ProjectRole;
|
||||
}
|
||||
|
||||
@InputType({ isAbstract: true })
|
||||
abstract class IssueFieldsInput {
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MaxLength(50000)
|
||||
description?: string | null;
|
||||
|
||||
@Field(() => IssueArea, { nullable: true })
|
||||
@IsOptional()
|
||||
@IsEnum(IssueArea)
|
||||
area?: IssueArea | null;
|
||||
|
||||
@Field(() => IssuePriority, { nullable: true })
|
||||
@IsOptional()
|
||||
@IsEnum(IssuePriority)
|
||||
priority?: IssuePriority;
|
||||
|
||||
@Field(() => [String], { nullable: true })
|
||||
@IsOptional()
|
||||
@ArrayMaxSize(20)
|
||||
@IsString({ each: true })
|
||||
@MaxLength(40, { each: true })
|
||||
labels?: string[];
|
||||
|
||||
@Field(() => String, {
|
||||
nullable: true,
|
||||
description: 'Figma frame for UI changes',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsUrl({ protocols: ['https'] })
|
||||
figmaUrl?: string | null;
|
||||
|
||||
@Field(() => Int, { nullable: true })
|
||||
@IsOptional()
|
||||
@IsInt()
|
||||
@Min(0)
|
||||
@Max(100)
|
||||
storyPoints?: number | null;
|
||||
|
||||
@Field(() => String, { nullable: true }) @IsOptional() @IsISO8601() dueDate?:
|
||||
| string
|
||||
| null;
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class CreateIssueInput extends IssueFieldsInput {
|
||||
@Field(() => ID) @IsUUID() projectId!: string;
|
||||
@Field(() => IssueType) @IsEnum(IssueType) type!: IssueType;
|
||||
@Field() @IsString() @MinLength(1) @MaxLength(255) title!: string;
|
||||
@Field(() => ID, { nullable: true }) @IsOptional() @IsString() assigneeId?:
|
||||
| string
|
||||
| null;
|
||||
@Field(() => ID, { nullable: true }) @IsOptional() @IsUUID() releaseId?:
|
||||
| string
|
||||
| null;
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class UpdateIssueInput extends IssueFieldsInput {
|
||||
@Field(() => ID) @IsUUID() issueId!: string;
|
||||
@Field(() => IssueType, { nullable: true })
|
||||
@IsOptional()
|
||||
@IsEnum(IssueType)
|
||||
type?: IssueType;
|
||||
@Field({ nullable: true })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MinLength(1)
|
||||
@MaxLength(255)
|
||||
title?: string;
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class ChangeIssueStatusInput {
|
||||
@Field(() => ID) @IsUUID() issueId!: string;
|
||||
@Field(() => IssueStatus) @IsEnum(IssueStatus) status!: IssueStatus;
|
||||
@Field(() => String, {
|
||||
nullable: true,
|
||||
description: 'Required for QA_FAILED and CANCELLED',
|
||||
})
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MaxLength(5000)
|
||||
reason?: string | null;
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class LinkIssuesInput {
|
||||
@Field(() => ID) @IsUUID() issueId!: string;
|
||||
@Field(() => IssueLinkType) @IsEnum(IssueLinkType) type!: IssueLinkType;
|
||||
@Field(() => ID) @IsUUID() targetIssueId!: string;
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class IssueFilterInput {
|
||||
@Field(() => ID) @IsUUID() projectId!: string;
|
||||
@Field(() => [IssueStatus], { nullable: true })
|
||||
@IsOptional()
|
||||
@IsEnum(IssueStatus, { each: true })
|
||||
statuses?: IssueStatus[];
|
||||
@Field(() => [IssueType], { nullable: true })
|
||||
@IsOptional()
|
||||
@IsEnum(IssueType, { each: true })
|
||||
types?: IssueType[];
|
||||
@Field(() => [IssueArea], { nullable: true })
|
||||
@IsOptional()
|
||||
@IsEnum(IssueArea, { each: true })
|
||||
areas?: IssueArea[];
|
||||
@Field(() => [IssuePriority], { nullable: true })
|
||||
@IsOptional()
|
||||
@IsEnum(IssuePriority, { each: true })
|
||||
priorities?: IssuePriority[];
|
||||
@Field(() => ID, { nullable: true })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
assigneeId?: string;
|
||||
@Field({ nullable: true }) @IsOptional() @IsBoolean() unassigned?: boolean;
|
||||
@Field(() => ID, { nullable: true })
|
||||
@IsOptional()
|
||||
@IsUUID()
|
||||
releaseId?: string;
|
||||
@Field(() => [String], { nullable: true })
|
||||
@IsOptional()
|
||||
@IsString({ each: true })
|
||||
labels?: string[];
|
||||
@Field({ nullable: true, description: 'Matches key, title or description' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MaxLength(200)
|
||||
search?: string;
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class CreateReleaseInput {
|
||||
@Field(() => ID) @IsUUID() projectId!: string;
|
||||
@Field({ description: 'e.g. v1.4.0' })
|
||||
@IsString()
|
||||
@MinLength(1)
|
||||
@MaxLength(60)
|
||||
name!: string;
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MaxLength(5000)
|
||||
description?: string | null;
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsOptional()
|
||||
@IsISO8601()
|
||||
targetDate?: string | null;
|
||||
}
|
||||
|
||||
@InputType()
|
||||
export class UpdateReleaseInput {
|
||||
@Field(() => ID) @IsUUID() releaseId!: string;
|
||||
@Field({ nullable: true })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MinLength(1)
|
||||
@MaxLength(60)
|
||||
name?: string;
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
@MaxLength(5000)
|
||||
description?: string | null;
|
||||
@Field(() => String, { nullable: true })
|
||||
@IsOptional()
|
||||
@IsISO8601()
|
||||
targetDate?: string | null;
|
||||
}
|
||||
Reference in New Issue
Block a user