feat: what is new since my last visit, and turning a comment into a ticket

Opening a ticket notes the visit and answers the one before (issue_visits),
so the page marks others' comments and changes since. A comment can become
a ticket of its own, as a subtask or linked; it remembers where it went.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-10-21 21:05:44 +02:00
parent 429b52e6f5
commit 285bd5c454
50 changed files with 1953 additions and 79 deletions

View File

@@ -110,6 +110,12 @@ export const issuePageEvents = eventGroup({
resolved: boolean;
conclusion: string | null;
}>(),
commentToIssueRequested: type<{
commentId: string;
title: string;
type: string;
asSubtask: 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 }>(),

View File

@@ -316,6 +316,21 @@ export class IssueFacade {
});
}
/** Makes a ticket of a comment: a subtask of this one, or linked to it. */
turnCommentIntoIssue(
commentId: string,
title: string,
type: string,
asSubtask: boolean,
): void {
this.dispatch.commentToIssueRequested({
commentId,
title: title.trim(),
type,
asSubtask,
});
}
/** Marks a comment as a decision of the ticket (`on`) or unmarks it. */
markDecision(commentId: string, on: boolean): void {
this.dispatch.decisionRequested({ commentId, on });

View File

@@ -608,6 +608,28 @@ export const IssueStore = signalStore(
),
),
),
events.on(issuePageEvents.commentToIssueRequested).pipe(
mergeMap(({ payload }) =>
comments
.turnIntoIssue(
payload.commentId,
payload.title,
payload.type,
payload.asSubtask,
)
.pipe(
mapResponse({
next: (result) =>
done(
result.key
? `Creado ${result.key}`
: 'Ticket creado',
),
error: (error) => failed(describeError(error)),
}),
),
),
),
events.on(issuePageEvents.reactRequested).pipe(
mergeMap(({ payload }) =>
comments.react(payload.commentId, payload.emoji, payload.on).pipe(