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:
@@ -28,6 +28,12 @@ import {
|
||||
ReleaseCreatedEvent,
|
||||
ReleaseShippedEvent,
|
||||
ReleaseUpdatedEvent,
|
||||
IssueSprintChangedEvent,
|
||||
SprintClosedEvent,
|
||||
SprintCreatedEvent,
|
||||
SprintDeletedEvent,
|
||||
SprintStartedEvent,
|
||||
SprintUpdatedEvent,
|
||||
TrackerEvent,
|
||||
} from '@task-stream/api/tracker/domain';
|
||||
|
||||
@@ -37,6 +43,8 @@ export interface SummaryContext {
|
||||
issueKey: string;
|
||||
projectKey: string;
|
||||
releaseName: string;
|
||||
/** '' when unknown (e.g. the sprint was deleted). */
|
||||
sprintName: string;
|
||||
/** The project's workflow: names of statuses and types. */
|
||||
workflow: ProjectWorkflow;
|
||||
}
|
||||
@@ -146,6 +154,12 @@ export function describeEvent(
|
||||
if (event instanceof IssueAttachmentRemovedEvent)
|
||||
return `${actor} quitó el adjunto ${event.fileName} de ${issueKey}`;
|
||||
|
||||
if (event instanceof IssueSprintChangedEvent) {
|
||||
const sprint = ctx.sprintName ? `el sprint ${ctx.sprintName}` : 'un sprint';
|
||||
return event.sprintId
|
||||
? `${actor} metió ${issueKey} en ${sprint}`
|
||||
: `${actor} sacó ${issueKey} de ${sprint}`;
|
||||
}
|
||||
if (event instanceof IssueParentChangedEvent) {
|
||||
return event.parentKey
|
||||
? `${actor} colocó ${issueKey} bajo ${event.parentKey}`
|
||||
@@ -178,5 +192,20 @@ export function describeEvent(
|
||||
return `${actor} publicó la release ${ctx.releaseName} 🚀`;
|
||||
if (event instanceof ReleaseArchivedEvent)
|
||||
return `${actor} archivó la release ${ctx.releaseName}`;
|
||||
const sprint = ctx.sprintName || 'un sprint';
|
||||
if (event instanceof SprintCreatedEvent)
|
||||
return `${actor} planificó el sprint ${event.sprint.name}`;
|
||||
if (event instanceof SprintUpdatedEvent)
|
||||
return `${actor} actualizó el sprint ${sprint}`;
|
||||
if (event instanceof SprintStartedEvent)
|
||||
return `${actor} empezó el sprint ${sprint} 🏁`;
|
||||
if (event instanceof SprintClosedEvent) {
|
||||
const left = event.unfinishedIssues
|
||||
? `; ${event.unfinishedIssues} ticket(s) sin terminar pasan ${event.carryOverTo ? 'al siguiente sprint' : 'al backlog'}`
|
||||
: '';
|
||||
return `${actor} cerró el sprint ${sprint}${left}`;
|
||||
}
|
||||
if (event instanceof SprintDeletedEvent)
|
||||
return `${actor} borró el sprint ${sprint}`;
|
||||
return `${actor}: ${event.constructor.name}`;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user