import { Observable } from 'rxjs'; import { Activity, Attachment, BoardColumn, Comment, Epic, SavedFilter, SavedFilterCriteria, CommandResult, Issue, IssuePage, IssueSummary, Notification, NotificationSettings, Project, ProjectAnalytics, ProjectStats, Release, ReleaseBurnup, UserDirectoryEntry, } from '../models/models'; import { ProjectSettings } from '../models/workflow'; import { BoardFilter, ChangeStatusInput, CreateIssueInput, CreateProjectInput, CreateReleaseInput, LinkIssuesInput, MemberInput, MyIssuesFilter, UpdateIssueInput, UpdateProjectInput, } from '../models/inputs'; /* * Outbound ports of the tracker. The application layer depends on these * abstract classes; the infrastructure layer implements them over GraphQL. */ export abstract class ProjectsGateway { abstract myProjects(): Observable; /** Projects anyone can read (no sign-in needed). */ abstract publicProjects(): Observable; abstract project(idOrKey: string): Observable; abstract stats(projectId: string): Observable; /** Statistics of the last `days` days. */ abstract analytics( projectId: string, days: number, ): Observable; /** Replaces statuses, transitions, types and areas (owners and admins). */ abstract updateSettings( projectId: string, settings: ProjectSettings, ): Observable; abstract create(input: CreateProjectInput): Observable; /** Name, description or visibility (owners and admins). */ abstract update(input: UpdateProjectInput): Observable; /** Owner only; `confirmKey` must be the project key. */ abstract delete( projectId: string, confirmKey: string, ): Observable; abstract addMember(input: MemberInput): Observable; abstract changeMemberRole(input: MemberInput): Observable; abstract removeMember( projectId: string, userId: string, ): Observable; } export abstract class IssuesGateway { abstract board(filter: BoardFilter): Observable; abstract issue(idOrKey: string): Observable; abstract search(projectId: string, text: string): Observable; /** Tickets across all my projects (most recently updated first). */ abstract mine(filter: MyIssuesFilter): Observable; abstract create(input: CreateIssueInput): Observable; abstract update(input: UpdateIssueInput): Observable; abstract changeStatus(input: ChangeStatusInput): Observable; abstract assign( issueId: string, assigneeId: string | null, ): Observable; abstract link(input: LinkIssuesInput): Observable; abstract unlink(input: LinkIssuesInput): Observable; abstract setRelease( issueId: string, releaseId: string | null, ): Observable; /** The signed-in person follows (or stops following) the ticket. */ abstract watch(issueId: string, watching: boolean): Observable; /** Tickets hanging from `issueId`. */ abstract children( projectId: string, issueId: string, ): Observable; /** Places the ticket under `parentId` (null: back to the top). */ abstract setParent( issueId: string, parentId: string | null, ): Observable; abstract epics(projectId: string): Observable; /** Tickets still to start (TODO category), in backlog order. */ abstract backlog(projectId: string): Observable; /** Moves a ticket between two others of the backlog (null: an end). */ abstract rank( issueId: string, aboveIssueId: string | null, belowIssueId: string | null, ): Observable; abstract addChecklistItem( issueId: string, text: string, ): Observable; abstract updateChecklistItem( issueId: string, itemId: string, changes: { text?: string; done?: boolean }, ): Observable; abstract removeChecklistItem( issueId: string, itemId: string, ): Observable; } /** Saved views of a project's board (mine and the shared ones). */ export abstract class SavedFiltersGateway { abstract list(projectId: string): Observable; abstract save(input: { projectId: string; name: string; shared: boolean; criteria: SavedFilterCriteria; }): Observable; abstract remove(id: string): Observable; } export abstract class CommentsGateway { abstract list(issueId: string): Observable; abstract add(issueId: string, body: string): Observable; abstract edit(commentId: string, body: string): Observable; abstract remove(commentId: string): Observable; } /** A ticket's files. Uploads and downloads go through the REST API. */ export abstract class AttachmentsGateway { abstract upload( issueId: string, file: File, commentId?: string | null, ): Observable; /** The file's bytes, to show (images) or save. */ abstract download(issueId: string, attachment: Attachment): Observable; abstract remove( issueId: string, attachmentId: string, ): Observable; } export abstract class ReleasesGateway { abstract list(projectId: string): Observable; /** Planned releases of all my projects, soonest target date first. */ abstract upcoming(limit: number): Observable; abstract create(input: CreateReleaseInput): Observable; abstract publish( releaseId: string, force: boolean, ): Observable; abstract archive(releaseId: string): Observable; abstract burnup(releaseId: string): Observable; } export abstract class ActivityGateway { abstract list(projectId: string, issueId?: string): Observable; } export abstract class UsersGateway { abstract search(term: string): Observable; } /** The signed-in person's notifications. */ export abstract class NotificationsGateway { abstract mine( unreadOnly: boolean, limit: number, ): Observable<{ items: Notification[]; unread: number }>; /** Without ids: all of them. */ abstract markRead(ids?: string[]): Observable; abstract settings(): Observable; abstract updateSettings(email: boolean): Observable; } /** Realtime (GraphQL subscriptions over WebSocket). */ export interface IssueChanged { action: string; version: number; actorId: string; issue: IssueSummary; } export interface CommentChanged { action: string; commentId: string; comment: Comment | null; } /** A project changed, or was deleted (then `project` is its last state). */ export interface ProjectChanged { project: Project; deleted: boolean; } /** Realtime needs a session: without one, these streams stay silent. */ export abstract class TrackerRealtimeGateway { abstract issueChanges(projectId: string): Observable; abstract commentChanges(issueId: string): Observable; abstract activity(projectId: string): Observable; abstract releaseChanges(projectId: string): Observable; abstract projectChanges(projectId: string): Observable; abstract myProjectsChanges(): Observable; abstract notifications(): Observable; }