import { ReviewVerdict } from '../issue/review'; import { DevLink } from '../issue/dev-link'; import { IssueLinkType, IssuePriority } from '../issue/issue.enums'; import { StatusCategory } from '../project/project-settings'; import { UserRefReadModel } from './user-ref.read-model'; export type LinkDirection = 'OUTWARD' | 'INWARD'; export class IssueLinkReadModel { type!: IssueLinkType; /** OUTWARD: this issue → other (e.g. "blocks"). INWARD: other → this ("is blocked by"). */ direction!: LinkDirection; issueId!: string; issueKey!: string; } export class AttachmentReadModel { id!: string; fileName!: string; mimeType!: string; size!: number; uploadedBy!: UserRefReadModel; uploadedAt!: string; /** Shown under this comment when set. */ commentId!: string | null; } export class ChecklistItemReadModel { id!: string; text!: string; done!: boolean; } /** The ticket another one hangs from. */ export class IssueParentReadModel { id!: string; key!: string; title!: string; } /** How far the tickets hanging from one have got. */ export class ChildProgressReadModel { total!: number; /** Done or cancelled. */ finished!: number; percent!: number; storyPoints!: number; finishedStoryPoints!: number; } /** A top-level ticket that groups others, with their progress. */ export class EpicReadModel { issue!: IssueReadModel; progress!: ChildProgressReadModel; } export class IssueReadModel { id!: string; projectId!: string; projectKey!: string; number!: number; key!: string; /** Ids from the project's settings. */ type!: string; area!: string | null; /** A team id of the project's settings. */ team!: string | null; title!: string; description!: string | null; status!: string; /** Category of `status` (kept in sync when the project's settings change). */ statusCategory!: StatusCategory; priority!: IssuePriority; reporter!: UserRefReadModel; assignee!: UserRefReadModel | null; release!: { id: string; name: string } | null; sprint!: { id: string; name: string } | null; labels!: string[]; figmaUrl!: string | null; storyPoints!: number | null; startDate!: string | null; dueDate!: string | null; /** The project's custom fields: field id → value (only those with one). */ customFields!: Record; links!: IssueLinkReadModel[]; attachments!: AttachmentReadModel[]; /** People following the ticket. */ watchers!: UserRefReadModel[]; /** Asked reviews, open and answered, oldest first. */ reviews!: IssueReviewReadModel[]; /** How many want it done. */ votes!: number; /** Who voted: to tell someone whether they did; never shown as a list. */ voterIds!: string[]; parent!: IssueParentReadModel | null; /** Place in the backlog (and in each board column): ascending. */ rank!: string; checklist!: ChecklistItemReadModel[]; /** Commits, branches and pull requests that mention it. */ devLinks!: DevLink[]; /** In the trash since then (null: not in it). */ trashedAt!: string | null; commentCount!: number; createdAt!: string; updatedAt!: string; /** Position of the last projected event. */ version!: number; } /** A review asked on a ticket, as the read side shows it. */ export class IssueReviewReadModel { id!: string; requester!: UserRefReadModel; reviewer!: UserRefReadModel; note!: string | null; requestedAt!: string; /** Null while waiting for an answer. */ verdict!: ReviewVerdict | null; answer!: string | null; answeredAt!: string | null; }