feat: saved board views and richer board filters

The board now filters by text, type, priority and unassigned tickets as
well. Any combination can be saved as a named view, private or shared with
the project, and opened again with one click.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 14:14:38 +02:00
parent 0606f53026
commit 298383f19f
46 changed files with 2922 additions and 26 deletions

View File

@@ -181,6 +181,57 @@ export class ChangeIssueStatusInput {
reason?: string | null;
}
@InputType()
export class SavedFilterCriteriaInput {
@Field(() => [String], { nullable: true })
@IsOptional()
@Matches(SETTING_ID, { each: true })
types?: string[];
@Field(() => [String], { nullable: true })
@IsOptional()
@Matches(SETTING_ID, { each: true })
areas?: string[];
@Field(() => [IssuePriority], { nullable: true })
@IsOptional()
@IsEnum(IssuePriority, { each: true })
priorities?: IssuePriority[];
@Field(() => ID, { nullable: true })
@IsOptional()
@IsString()
assigneeId?: string | null;
@Field({ nullable: true }) @IsOptional() @IsBoolean() unassigned?: boolean;
@Field(() => ID, { nullable: true })
@IsOptional()
@IsUUID()
releaseId?: string | null;
@Field(() => [String], { nullable: true })
@IsOptional()
@ArrayMaxSize(20)
@IsString({ each: true })
labels?: string[];
@Field(() => String, { nullable: true })
@IsOptional()
@IsString()
@MaxLength(200)
search?: string | null;
}
@InputType()
export class SaveFilterInput {
@Field(() => ID) @IsUUID() projectId!: string;
@Field() @IsString() @MinLength(1) @MaxLength(60) name!: string;
@Field({
defaultValue: false,
description: 'Visible to the whole project (members, not viewers, share)',
})
@IsBoolean()
shared!: boolean;
@Field(() => SavedFilterCriteriaInput)
@ValidateNested()
@Type(() => SavedFilterCriteriaInput)
criteria!: SavedFilterCriteriaInput;
}
@InputType()
export class RankIssueInput {
@Field(() => ID) @IsUUID() issueId!: string;