feat: sprints with burndown and carry-over
Plan sprints with dates and a goal, run one at a time per project, and put tickets in them from the ticket page. The Sprints tab follows the one under way with its progress and a burndown in tickets or points against the ideal line. Closing a sprint sends what was left to the next one or back to the backlog; the board can be filtered by sprint. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,85 @@
|
||||
import { Command } from '@nestjs/cqrs';
|
||||
import { SprintDetails } from '@task-stream/api/tracker/domain';
|
||||
import { CommandResult } from './command-result';
|
||||
|
||||
export class CreateSprintCommand extends Command<CommandResult> {
|
||||
constructor(
|
||||
public readonly actorId: string,
|
||||
public readonly projectId: string,
|
||||
public readonly name: string,
|
||||
public readonly startDate: string,
|
||||
public readonly endDate: string,
|
||||
public readonly goal: string | null = null,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
export class UpdateSprintCommand extends Command<CommandResult> {
|
||||
constructor(
|
||||
public readonly actorId: string,
|
||||
public readonly sprintId: string,
|
||||
public readonly changes: SprintDetails,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
export class StartSprintCommand extends Command<CommandResult> {
|
||||
constructor(
|
||||
public readonly actorId: string,
|
||||
public readonly sprintId: string,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
/** Ends a sprint; unfinished tickets go to `carryOverTo` (null: backlog). */
|
||||
export class CloseSprintCommand extends Command<CommandResult> {
|
||||
constructor(
|
||||
public readonly actorId: string,
|
||||
public readonly sprintId: string,
|
||||
public readonly carryOverTo: string | null,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
/** A planned sprint (people), or any sprint of a deleted project (`cascade`, saga). */
|
||||
export class DeleteSprintCommand extends Command<CommandResult | void> {
|
||||
constructor(
|
||||
public readonly actorId: string,
|
||||
public readonly sprintId: string,
|
||||
public readonly cascade = false,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
/** Puts a ticket in a sprint (null: back to the backlog). */
|
||||
export class SetIssueSprintCommand extends Command<CommandResult> {
|
||||
constructor(
|
||||
public readonly actorId: string,
|
||||
public readonly issueId: string,
|
||||
public readonly sprintId: string | null,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* Saga only: a sprint closed (or was deleted), so a ticket of it moves to
|
||||
* `toSprintId` (null: backlog). With `onlyUnfinished`, finished ones stay as
|
||||
* the record of what the sprint achieved.
|
||||
*/
|
||||
export class CarryOverIssueCommand extends Command<void> {
|
||||
constructor(
|
||||
public readonly actorId: string,
|
||||
public readonly issueId: string,
|
||||
public readonly fromSprintId: string,
|
||||
public readonly toSprintId: string | null,
|
||||
public readonly onlyUnfinished: boolean,
|
||||
) {
|
||||
super();
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user