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:
2026-10-08 14:59:01 +02:00
parent d2e31789a7
commit 50d3ffd1dd
104 changed files with 7209 additions and 33 deletions

View File

@@ -26,6 +26,10 @@ export const issuePageEvents = eventGroup({
targetKey: string;
}>(),
unlinkRequested: type<LinkIssuesInput>(),
sprintChangeRequested: type<{
issueId: string;
sprintId: string | null;
}>(),
releaseChangeRequested: type<{
issueId: string;
releaseId: string | null;

View File

@@ -10,6 +10,10 @@ import {
ProjectStats,
Release,
ReleaseBurnup,
CreateSprintInput,
Sprint,
SprintBurndown,
UpdateSprintInput,
UserDirectoryEntry,
} from '@task-stream/web/tracker/domain';
@@ -23,6 +27,15 @@ export const projectPageEvents = eventGroup({
releaseCreateRequested: type<CreateReleaseInput>(),
releasePublishRequested: type<{ releaseId: string; force: boolean }>(),
releaseArchiveRequested: type<{ releaseId: string }>(),
sprintCreateRequested: type<CreateSprintInput>(),
sprintUpdateRequested: type<UpdateSprintInput>(),
sprintStartRequested: type<{ sprintId: string }>(),
sprintCloseRequested: type<{
sprintId: string;
carryOverTo: string | null;
}>(),
sprintDeleteRequested: type<{ sprintId: string }>(),
burndownRequested: type<{ sprintId: string }>(),
userSearchRequested: type<string>(),
settingsSaveRequested: type<{
projectId: string;
@@ -42,6 +55,8 @@ export const projectApiEvents = eventGroup({
loadFailed: type<string>(),
statsLoaded: type<ProjectStats>(),
releasesLoaded: type<Release[]>(),
sprintsLoaded: type<Sprint[]>(),
burndownLoaded: type<SprintBurndown>(),
activityLoaded: type<Activity[]>(),
commandSucceeded: type<string>(),
commandFailed: type<string>(),
@@ -63,5 +78,6 @@ export const projectRealtimeEvents = eventGroup({
projectDeleted: type<Project>(),
activityAdded: type<Activity>(),
releaseChanged: type<Release>(),
sprintChanged: type<{ sprintId: string }>(),
},
});