The insights reading adds quality (open bugs per priority, bugs created and closed per week for 8 weeks, QA returns and passes per area over 90 days, bugs reported in the 14 days after each of the last three releases) and, for each list custom field, open tickets per option. The dashboard shows both; the field to split by can be picked. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
192 lines
5.9 KiB
TypeScript
192 lines
5.9 KiB
TypeScript
import { UserRefReadModel } from './user-ref.read-model';
|
|
|
|
/** A ticket named by the dashboard, with the number that put it there. */
|
|
export class InsightIssueReadModel {
|
|
id!: string;
|
|
key!: string;
|
|
title!: string;
|
|
/** Status id of the project's settings. */
|
|
status!: string;
|
|
assignee!: UserRefReadModel | null;
|
|
/** Days in its current status (aging, stuck) or past/to its due date. */
|
|
days!: number;
|
|
dueDate!: string | null;
|
|
}
|
|
|
|
/** The sprint under way: time gone against work done. */
|
|
export class SprintPulseReadModel {
|
|
sprintId!: string;
|
|
name!: string;
|
|
startDate!: string;
|
|
endDate!: string;
|
|
/** Days of the sprint, both ends included. */
|
|
totalDays!: number;
|
|
/** Days left after today (0 on the last day; negative once it is over). */
|
|
daysLeft!: number;
|
|
tickets!: number;
|
|
doneTickets!: number;
|
|
points!: number;
|
|
donePoints!: number;
|
|
/** Points closed per day so far (null on the first day). */
|
|
pacePerDay!: number | null;
|
|
/** Points per day still needed to finish (null when nothing is left). */
|
|
neededPerDay!: number | null;
|
|
/** At this pace, what is open would not be closed in time. */
|
|
behind!: boolean;
|
|
}
|
|
|
|
/** Tickets to look at now. Lists are the worst first, a few at most. */
|
|
export class RiskReadModel {
|
|
overdue!: InsightIssueReadModel[];
|
|
overdueCount!: number;
|
|
/** Due within the next 7 days. */
|
|
dueSoon!: InsightIssueReadModel[];
|
|
dueSoonCount!: number;
|
|
/** Waiting for an open ticket that blocks them (or they depend on). */
|
|
blocked!: InsightIssueReadModel[];
|
|
blockedCount!: number;
|
|
/** In progress or in QA for `stuckDays` or more without moving. */
|
|
stuck!: InsightIssueReadModel[];
|
|
stuckCount!: number;
|
|
stuckDays!: number;
|
|
}
|
|
|
|
/** How long the work under way has been where it is. */
|
|
export class AgingReadModel {
|
|
issues!: InsightIssueReadModel[];
|
|
/** 85% of the tickets finished lately took at most this (cycle time). */
|
|
thresholdDays!: number | null;
|
|
}
|
|
|
|
/** Time tickets spend in a status of the flow, and how many are there. */
|
|
export class StatusTimeReadModel {
|
|
status!: string;
|
|
/** Average stay of the tickets that left it in the last 90 days. */
|
|
averageDays!: number | null;
|
|
/** Stays measured. */
|
|
samples!: number;
|
|
open!: number;
|
|
wipLimit!: number | null;
|
|
overLimit!: boolean;
|
|
}
|
|
|
|
/** When a planned release would be finished, at the team's real pace. */
|
|
export class ReleaseForecastReadModel {
|
|
releaseId!: string;
|
|
name!: string;
|
|
targetDate!: string | null;
|
|
/** Tickets in it (cancelled ones aside). */
|
|
total!: number;
|
|
finished!: number;
|
|
/** Half of the simulated futures finish by then (null: no pace yet). */
|
|
likelyDate!: string | null;
|
|
/** 85% of them do. */
|
|
safeDate!: string | null;
|
|
/**
|
|
* DONE: nothing left. NO_DATE: no target to compare. UNKNOWN: nothing
|
|
* finished lately to measure a pace. ON_TRACK: 85% in time. AT_RISK: half
|
|
* in time. LATE: less than half.
|
|
*/
|
|
verdict!: 'DONE' | 'NO_DATE' | 'UNKNOWN' | 'ON_TRACK' | 'AT_RISK' | 'LATE';
|
|
}
|
|
|
|
/** What has happened since a moment (the viewer's last visit). */
|
|
export class ChangesSinceReadModel {
|
|
since!: string;
|
|
created!: InsightIssueReadModel[];
|
|
createdCount!: number;
|
|
finished!: InsightIssueReadModel[];
|
|
finishedCount!: number;
|
|
/** Sent back from QA. */
|
|
returned!: InsightIssueReadModel[];
|
|
returnedCount!: number;
|
|
/** Times the viewer was mentioned in this project. */
|
|
mentions!: number;
|
|
}
|
|
|
|
/** One person's open work against what they usually close. */
|
|
export class TeamLoadReadModel {
|
|
user!: UserRefReadModel;
|
|
openTickets!: number;
|
|
openPoints!: number;
|
|
/** Their open tickets waiting for another open one. */
|
|
blocked!: number;
|
|
/** Points they closed per sprint, over the last three closed sprints. */
|
|
pointsPerSprint!: number | null;
|
|
/** More open points than they usually close in a sprint. */
|
|
overloaded!: boolean;
|
|
}
|
|
|
|
/** Open tickets missing what planning needs. */
|
|
export class BacklogHealthReadModel {
|
|
open!: number;
|
|
unestimated!: number;
|
|
noArea!: number;
|
|
unassigned!: number;
|
|
/** Not updated in `staleDays` days. */
|
|
stale!: number;
|
|
staleDays!: number;
|
|
}
|
|
|
|
/** Bugs created and closed in one week (Monday, UTC). */
|
|
export class BugWeekReadModel {
|
|
week!: string;
|
|
created!: number;
|
|
closed!: number;
|
|
}
|
|
|
|
/** What QA sent back, and let through, per area (last 90 days). */
|
|
export class QaByAreaReadModel {
|
|
/** Area id; null: tickets with no area. */
|
|
area!: string | null;
|
|
returned!: number;
|
|
passed!: number;
|
|
}
|
|
|
|
/** Bugs reported in the 14 days after a release shipped. */
|
|
export class EscapedBugsReadModel {
|
|
releaseId!: string;
|
|
name!: string;
|
|
releasedAt!: string;
|
|
bugs!: number;
|
|
}
|
|
|
|
/** Bugs (types drawn with the bug icon) and QA. */
|
|
export class QualityReadModel {
|
|
/** Open bugs per priority (all five, most urgent first). */
|
|
openBugsByPriority!: { priority: string; count: number }[];
|
|
/** The last 8 weeks, oldest first. */
|
|
bugWeeks!: BugWeekReadModel[];
|
|
qaByArea!: QaByAreaReadModel[];
|
|
/** The last three shipped releases, newest first. */
|
|
escaped!: EscapedBugsReadModel[];
|
|
}
|
|
|
|
/** Open tickets per option of a list custom field. */
|
|
export class FieldBreakdownReadModel {
|
|
fieldId!: string;
|
|
counts!: { value: string; count: number }[];
|
|
/** Open tickets with no value in it. */
|
|
none!: number;
|
|
}
|
|
|
|
/** What the project dashboard reads beyond the counts. */
|
|
export class ProjectInsightsReadModel {
|
|
generatedAt!: string;
|
|
sprint!: SprintPulseReadModel | null;
|
|
risks!: RiskReadModel;
|
|
aging!: AgingReadModel;
|
|
/** In-progress and QA statuses, in board order. */
|
|
bottlenecks!: StatusTimeReadModel[];
|
|
/** Planned releases, by target date. */
|
|
releases!: ReleaseForecastReadModel[];
|
|
/** Null unless asked with a `since`. */
|
|
changes!: ChangesSinceReadModel | null;
|
|
/** Members (and others with open tickets), busiest first. */
|
|
team!: TeamLoadReadModel[];
|
|
backlog!: BacklogHealthReadModel;
|
|
quality!: QualityReadModel;
|
|
/** One per active list (SELECT) custom field. */
|
|
fields!: FieldBreakdownReadModel[];
|
|
}
|