Each person pins up to 20 tickets from the ticket's page («Fijar»). They
show as a strip under the projects on the home page and in the search
palette before typing. Private and without history, like the views of
«my work» (Mongo `pinned_issues`); tickets in the trash or out of reach
are left out, and when the list is full the unreadable ones are dropped
first.
API: GET /api/me/pins, PUT/DELETE /api/issues/{issue}/pin; GraphQL
myPins, pinIssue, unpinIssue and Issue.pinned.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
106 lines
3.5 KiB
TypeScript
106 lines
3.5 KiB
TypeScript
import { type } from '@ngrx/signals';
|
|
import { eventGroup } from '@ngrx/signals/events';
|
|
import {
|
|
Activity,
|
|
ChangeStatusInput,
|
|
Comment,
|
|
CommentChanged,
|
|
Issue,
|
|
IssueSummary,
|
|
LinkIssuesInput,
|
|
UpdateIssueInput,
|
|
} from '@task-stream/web/tracker/domain';
|
|
|
|
export const issuePageEvents = eventGroup({
|
|
source: 'Issue Page',
|
|
events: {
|
|
opened: type<{ idOrKey: string }>(),
|
|
statusChangeRequested: type<ChangeStatusInput>(),
|
|
assignRequested: type<{ issueId: string; assigneeId: string | null }>(),
|
|
updateRequested: type<UpdateIssueInput>(),
|
|
linkRequested: type<LinkIssuesInput>(),
|
|
/** Relate by the other ticket's key (e.g. BE-3), resolved to its id first. */
|
|
linkByKeyRequested: type<{
|
|
issueId: string;
|
|
type: LinkIssuesInput['type'];
|
|
targetKey: string;
|
|
}>(),
|
|
unlinkRequested: type<LinkIssuesInput>(),
|
|
sprintChangeRequested: type<{
|
|
issueId: string;
|
|
sprintId: string | null;
|
|
}>(),
|
|
releaseChangeRequested: type<{
|
|
issueId: string;
|
|
releaseId: string | null;
|
|
}>(),
|
|
commentAddRequested: type<{
|
|
issueId: string;
|
|
body: string;
|
|
/** Uploaded under the new comment once it exists. */
|
|
files?: File[];
|
|
/** Comment it answers (one level of replies). */
|
|
replyTo?: string | null;
|
|
}>(),
|
|
watchRequested: type<{ issueId: string; watching: boolean }>(),
|
|
pinRequested: type<{ issueId: string; pinned: boolean }>(),
|
|
trashRequested: type<{ issueId: string; trashed: boolean }>(),
|
|
/** Place the ticket under another one by its key (e.g. WEB-3); null: out. */
|
|
parentRequested: type<{ issueId: string; parentKey: string | null }>(),
|
|
subtaskCreateRequested: type<{
|
|
projectId: string;
|
|
parentId: string;
|
|
type: string;
|
|
title: string;
|
|
}>(),
|
|
checklistAddRequested: type<{ issueId: string; text: string }>(),
|
|
checklistUpdateRequested: type<{
|
|
issueId: string;
|
|
itemId: string;
|
|
changes: { text?: string; done?: boolean };
|
|
}>(),
|
|
checklistRemoveRequested: type<{ issueId: string; itemId: string }>(),
|
|
attachRequested: type<{
|
|
issueId: string;
|
|
files: File[];
|
|
commentId?: string | null;
|
|
}>(),
|
|
attachmentRemoveRequested: type<{
|
|
issueId: string;
|
|
attachmentId: string;
|
|
}>(),
|
|
commentEditRequested: type<{ commentId: string; body: string }>(),
|
|
reactRequested: type<{ commentId: string; emoji: string; on: boolean }>(),
|
|
voteRequested: type<{ issueId: string; on: boolean }>(),
|
|
/** An image pasted into a text was uploaded (it joins the ticket's files). */
|
|
imagePasted: type<{ issueId: string }>(),
|
|
commentDeleteRequested: type<{ commentId: string }>(),
|
|
},
|
|
});
|
|
|
|
export const issueApiEvents = eventGroup({
|
|
source: 'Issue API',
|
|
events: {
|
|
loaded: type<Issue>(),
|
|
loadFailed: type<string>(),
|
|
commentsLoaded: type<Comment[]>(),
|
|
historyLoaded: type<Activity[]>(),
|
|
childrenLoaded: type<IssueSummary[]>(),
|
|
commandSucceeded: type<string>(),
|
|
/** A checklist step was saved (no toast for something so small). */
|
|
checklistSaved: type<void>(),
|
|
commandFailed: type<string>(),
|
|
},
|
|
});
|
|
|
|
export const issueRealtimeEvents = eventGroup({
|
|
source: 'Issue Realtime',
|
|
events: {
|
|
/** Something about this ticket changed: refetch it. */
|
|
issueTouched: type<{ issueId: string; version: number }>(),
|
|
/** A ticket under this one changed, arrived or left: reload them. */
|
|
childrenTouched: type<{ issueId: string }>(),
|
|
commentChanged: type<CommentChanged>(),
|
|
},
|
|
});
|