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

@@ -69,6 +69,10 @@ fragment IssueSummaryFields on Issue {
id
name
}
sprint {
id
name
}
parent {
id
key

File diff suppressed because it is too large Load Diff

View File

@@ -8,6 +8,7 @@ query Board(
$labels: [String!]
$search: String
$unassigned: Boolean
$sprintId: ID
) {
project(idOrKey: $idOrKey) {
id
@@ -20,6 +21,7 @@ query Board(
labels: $labels
search: $search
unassigned: $unassigned
sprintId: $sprintId
perColumn: 100
) {
status

View File

@@ -0,0 +1,81 @@
fragment SprintFields on Sprint {
id
projectId
name
goal
startDate
endDate
status
startedAt
closedAt
progress {
total
finished
percent
storyPoints
finishedStoryPoints
}
}
query Sprints($projectId: ID!) {
sprints(projectId: $projectId) {
...SprintFields
}
}
query SprintBurndown($id: ID!) {
sprint(id: $id) {
id
burndown {
sprintId
dates
scope
remaining
remainingPoints
ideal
}
}
}
mutation CreateSprint($input: CreateSprintInput!) {
createSprint(input: $input) {
...CommandResultFields
}
}
mutation UpdateSprint($input: UpdateSprintInput!) {
updateSprint(input: $input) {
...CommandResultFields
}
}
mutation StartSprint($sprintId: ID!) {
startSprint(sprintId: $sprintId) {
...CommandResultFields
}
}
mutation CloseSprint($sprintId: ID!, $carryOverToSprintId: ID) {
closeSprint(sprintId: $sprintId, carryOverToSprintId: $carryOverToSprintId) {
...CommandResultFields
}
}
mutation DeleteSprint($sprintId: ID!) {
deleteSprint(sprintId: $sprintId) {
...CommandResultFields
}
}
mutation SetIssueSprint($issueId: ID!, $sprintId: ID) {
setIssueSprint(issueId: $issueId, sprintId: $sprintId) {
...CommandResultFields
}
}
subscription SprintChanged($projectId: ID!) {
sprintChanged(projectId: $projectId) {
action
sprintId
}
}