first commit
This commit is contained in:
101
libs/web/tracker/application/src/lib/facades/issue.facade.ts
Normal file
101
libs/web/tracker/application/src/lib/facades/issue.facade.ts
Normal file
@@ -0,0 +1,101 @@
|
||||
import { inject, Injectable, Provider } from '@angular/core';
|
||||
import { injectDispatch } from '@ngrx/signals/events';
|
||||
import {
|
||||
IssueLink,
|
||||
IssueLinkType,
|
||||
IssueStatus,
|
||||
UpdateIssueInput,
|
||||
} from '@task-stream/web/tracker/domain';
|
||||
import { issuePageEvents } from '../events/issue.events';
|
||||
import { IssueStore } from '../stores/issue.store';
|
||||
|
||||
/**
|
||||
* One ticket for presenters: details, comments and history, live. Commands act
|
||||
* on the open ticket, so pages don't pass its id.
|
||||
*/
|
||||
@Injectable()
|
||||
export class IssueFacade {
|
||||
private readonly store = inject(IssueStore);
|
||||
private readonly dispatch = injectDispatch(issuePageEvents);
|
||||
|
||||
readonly issue = this.store.issue;
|
||||
readonly comments = this.store.comments;
|
||||
readonly history = this.store.history;
|
||||
readonly outwardLinks = this.store.outwardLinks;
|
||||
readonly inwardLinks = this.store.inwardLinks;
|
||||
readonly loading = this.store.loading;
|
||||
readonly error = this.store.error;
|
||||
/** Signed-in user's id (authors can edit their comments). */
|
||||
readonly me = this.store.me;
|
||||
|
||||
/** Loads the ticket (by id or key, e.g. BE-3) and follows its changes. */
|
||||
open(idOrKey: string): void {
|
||||
this.dispatch.opened({ idOrKey });
|
||||
}
|
||||
|
||||
/** QA_FAILED and CANCELLED need a reason. */
|
||||
changeStatus(status: IssueStatus, reason?: string | null): void {
|
||||
this.withIssue((issueId) =>
|
||||
this.dispatch.statusChangeRequested({ issueId, status, reason }),
|
||||
);
|
||||
}
|
||||
|
||||
assign(assigneeId: string | null): void {
|
||||
this.withIssue((issueId) =>
|
||||
this.dispatch.assignRequested({ issueId, assigneeId }),
|
||||
);
|
||||
}
|
||||
|
||||
update(changes: Omit<UpdateIssueInput, 'issueId'>): void {
|
||||
this.withIssue((issueId) =>
|
||||
this.dispatch.updateRequested({ issueId, ...changes }),
|
||||
);
|
||||
}
|
||||
|
||||
/** Relates this ticket with another one by its key (e.g. BE-3). */
|
||||
link(type: IssueLinkType, targetKey: string): void {
|
||||
this.withIssue((issueId) =>
|
||||
this.dispatch.linkByKeyRequested({ issueId, type, targetKey }),
|
||||
);
|
||||
}
|
||||
|
||||
unlink(link: IssueLink): void {
|
||||
this.withIssue((issueId) =>
|
||||
this.dispatch.unlinkRequested({
|
||||
issueId,
|
||||
type: link.type,
|
||||
targetIssueId: link.issueId,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
setRelease(releaseId: string | null): void {
|
||||
this.withIssue((issueId) =>
|
||||
this.dispatch.releaseChangeRequested({ issueId, releaseId }),
|
||||
);
|
||||
}
|
||||
|
||||
addComment(body: string): void {
|
||||
this.withIssue((issueId) =>
|
||||
this.dispatch.commentAddRequested({ issueId, body }),
|
||||
);
|
||||
}
|
||||
|
||||
editComment(commentId: string, body: string): void {
|
||||
this.dispatch.commentEditRequested({ commentId, body });
|
||||
}
|
||||
|
||||
deleteComment(commentId: string): void {
|
||||
this.dispatch.commentDeleteRequested({ commentId });
|
||||
}
|
||||
|
||||
private withIssue(command: (issueId: string) => void): void {
|
||||
const issueId = this.store.issue()?.id;
|
||||
if (issueId) command(issueId);
|
||||
}
|
||||
}
|
||||
|
||||
/** Store + facade of a ticket, for the issue route's component. */
|
||||
export function provideIssueFacade(): Provider[] {
|
||||
return [IssueStore, IssueFacade];
|
||||
}
|
||||
Reference in New Issue
Block a user