feat: pinned tickets, at hand on the home page and in search

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>
This commit is contained in:
2026-10-17 10:15:28 +02:00
parent 423f82c1a3
commit dfa42a8a1a
32 changed files with 1612 additions and 46 deletions

View File

@@ -190,6 +190,8 @@ export interface Issue extends IssueSummary {
attachments: Attachment[];
/** People following the ticket. */
watchers: UserRef[];
/** Whether I keep it pinned (home page and search). */
pinned: boolean;
checklist: ChecklistItem[];
/** Commits, branches and pull requests that mention it. */
devLinks: DevLink[];

View File

@@ -140,6 +140,10 @@ export abstract class IssuesGateway {
): Observable<CommandResult>;
/** The signed-in person follows (or stops following) the ticket. */
abstract watch(issueId: string, watching: boolean): Observable<CommandResult>;
/** My pinned tickets, most recently pinned first. */
abstract pins(): Observable<IssueSummary[]>;
/** Pins the ticket for me (or unpins it): private, at most 20. */
abstract pin(issueId: string, pinned: boolean): Observable<void>;
/** Tickets hanging from `issueId`. */
abstract children(
projectId: string,