feat: estimate tickets and see the team's velocity

Story points can be set on the ticket page and when creating a ticket,
and show on cards, column headers, subtasks and the backlog. The Sprints
tab charts the points finished per closed sprint and warns when a planned
sprint holds more than the recent average.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-08 15:04:11 +02:00
parent 50d3ffd1dd
commit 6aec774c92
16 changed files with 304 additions and 20 deletions

View File

@@ -168,6 +168,24 @@ export const RELEASE_STATUS: Record<
[ReleaseStatus.ARCHIVED]: { label: 'Archivada', color: 'grey' },
};
/** "Sin estimar" + the usual scale (+ `current` if it is off the scale). */
export function pointOptions(
scale: readonly number[],
current: number | null = null,
): { value: string; label: string }[] {
const values = [...scale];
if (current !== null && !values.includes(current)) values.push(current);
return [
{ value: '', label: 'Sin estimar' },
...values
.sort((a, b) => a - b)
.map((v) => ({
value: String(v),
label: v === 1 ? '1 punto' : `${v} puntos`,
})),
];
}
export const options = <T extends string>(
record: Record<T, string | { label: string }>,
) =>

View File

@@ -45,6 +45,11 @@ import { initials, PRIORITY, PRIORITY_LEVEL, typeLook } from './copy';
>↑ {{ parent.key }}</span
>
}
@if (issue().storyPoints !== null) {
<span class="ts-card__points" title="Estimación">{{
issue().storyPoints
}}</span>
}
@if (issue().release; as release) {
<span class="ts-card__meta" title="Release"
>◆ {{ release.name }}</span
@@ -73,6 +78,18 @@ import { initials, PRIORITY, PRIORITY_LEVEL, typeLook } from './copy';
:host {
display: block;
}
.ts-card__points {
display: inline-grid;
place-items: center;
min-width: 1.25rem;
height: 1.25rem;
padding: 0 0.3rem;
border-radius: 999px;
background: var(--ts-line);
color: var(--ts-ink-soft);
font-size: 0.6875rem;
font-weight: 600;
}
.ts-card {
--type: var(--ts-muted);
position: relative;