feat: bulk edit tickets
Select several tickets in the backlog and change their status, assignee, sprint, priority or labels at once. Each ticket goes through the normal rules and may refuse on its own; the result says which did. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -789,6 +789,51 @@ export class ImportQueryDto {
|
||||
dryRun = false;
|
||||
}
|
||||
|
||||
export class BulkUpdateIssuesDto {
|
||||
@ApiProperty({ type: [String], format: 'uuid', maxItems: 100 })
|
||||
@IsArray()
|
||||
@ArrayMaxSize(100)
|
||||
@IsUUID('all', { each: true })
|
||||
issueIds!: string[];
|
||||
@ApiPropertyOptional({ example: 'IN_PROGRESS' })
|
||||
@IsOptional()
|
||||
@Matches(SETTING_ID)
|
||||
status?: string;
|
||||
@ApiPropertyOptional({ description: 'Unassign everything' })
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
unassign?: boolean;
|
||||
@ApiPropertyOptional({ description: 'Pireon user id of a member' })
|
||||
@IsOptional()
|
||||
@IsString()
|
||||
assigneeId?: string;
|
||||
@ApiPropertyOptional({ description: 'Back to the backlog' })
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
noSprint?: boolean;
|
||||
@ApiPropertyOptional({ format: 'uuid' })
|
||||
@IsOptional()
|
||||
@IsUUID()
|
||||
sprintId?: string;
|
||||
@ApiPropertyOptional({ description: 'Out of their release' })
|
||||
@IsOptional()
|
||||
@IsBoolean()
|
||||
noRelease?: boolean;
|
||||
@ApiPropertyOptional({ format: 'uuid' })
|
||||
@IsOptional()
|
||||
@IsUUID()
|
||||
releaseId?: string;
|
||||
@ApiPropertyOptional({ enum: IssuePriority, enumName: 'IssuePriority' })
|
||||
@IsOptional()
|
||||
@IsEnum(IssuePriority)
|
||||
priority?: IssuePriority;
|
||||
@ApiPropertyOptional({ type: [String] })
|
||||
@IsOptional()
|
||||
@ArrayMaxSize(10)
|
||||
@IsString({ each: true })
|
||||
addLabels?: string[];
|
||||
}
|
||||
|
||||
export class RankIssueDto {
|
||||
@ApiPropertyOptional({
|
||||
type: String,
|
||||
|
||||
@@ -223,6 +223,17 @@ export class ImportReportDto {
|
||||
@ApiProperty({ type: [ImportLineDto] }) warnings!: ImportLineDto[];
|
||||
}
|
||||
|
||||
export class BulkIssueResultDto {
|
||||
@ApiProperty({ format: 'uuid' }) issueId!: string;
|
||||
@ApiProperty() ok!: boolean;
|
||||
@ApiProperty({ type: String, nullable: true }) error!: string | null;
|
||||
}
|
||||
|
||||
export class BulkResultDto {
|
||||
@ApiProperty() updated!: number;
|
||||
@ApiProperty({ type: [BulkIssueResultDto] }) results!: BulkIssueResultDto[];
|
||||
}
|
||||
|
||||
export class GitDeliveryResultDto {
|
||||
@ApiProperty({ description: 'Tickets that got something new' })
|
||||
recorded!: number;
|
||||
|
||||
@@ -3,6 +3,7 @@ import {
|
||||
Controller,
|
||||
Delete,
|
||||
Get,
|
||||
HttpCode,
|
||||
Param,
|
||||
ParseUUIDPipe,
|
||||
Patch,
|
||||
@@ -35,6 +36,7 @@ import { IssueLinkType } from '@task-stream/api/tracker/domain';
|
||||
import { withoutNulls } from '../common/issue-input';
|
||||
import {
|
||||
AssignIssueDto,
|
||||
BulkUpdateIssuesDto,
|
||||
ChangeStatusDto,
|
||||
ChecklistItemBodyDto,
|
||||
CommentBodyDto,
|
||||
@@ -52,6 +54,7 @@ import {
|
||||
} from './dto/requests.dto';
|
||||
import {
|
||||
ActivityDto,
|
||||
BulkResultDto,
|
||||
CommandResultDto,
|
||||
CommentPageDto,
|
||||
EpicDto,
|
||||
@@ -59,6 +62,7 @@ import {
|
||||
IssuePageDto,
|
||||
} from './dto/responses.dto';
|
||||
import { viewerOf } from '../common/viewer';
|
||||
import { toBulkChange } from '../common/bulk';
|
||||
import { Refs } from './refs';
|
||||
|
||||
const PROJECT = ApiParam({
|
||||
@@ -306,6 +310,19 @@ export class IssuesController {
|
||||
);
|
||||
}
|
||||
|
||||
@Post('issues/bulk')
|
||||
@HttpCode(200)
|
||||
@ApiOperation({
|
||||
summary: 'The same change on up to 100 tickets',
|
||||
description:
|
||||
'Each ticket goes through the normal rules (permissions, workflow, open sprints and releases) and may refuse on its own; the answer says which.',
|
||||
})
|
||||
@ApiOkResponse({ type: BulkResultDto })
|
||||
@ApiCommandErrors()
|
||||
bulkUpdate(@CurrentUser() me: User, @Body() body: BulkUpdateIssuesDto) {
|
||||
return this.issues.bulkUpdate(me.id, body.issueIds, toBulkChange(body));
|
||||
}
|
||||
|
||||
@Put('issues/:issue/parent')
|
||||
@ISSUE
|
||||
@ApiOperation({
|
||||
|
||||
Reference in New Issue
Block a user