feat: «Recordármelo», a reminder of a ticket only for me
On a ticket, «Recordármelo» offers in an hour, this evening, tomorrow or
next Monday at 9, in a week, or any date and time, with an optional note.
The ticket shows the waiting one («Te lo recordaré el mié 21 a las 9:00»)
to change or drop. Every minute a scheduler tells the ones whose time
came as a REMINDER notification (bell, push, e-mail), once, and forgets
those whose ticket went to the trash or out of reach. One per person and
ticket, private, no history (Mongo `issue_reminders`).
API: setReminder / clearReminder, Issue.myReminder, myReminders;
PUT/DELETE /api/issues/{issue}/reminder, GET /api/me/reminders. MCP:
remind_me.
Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -50,6 +50,12 @@ export const issuePageEvents = eventGroup({
|
||||
watchRequested: type<{ issueId: string; watching: boolean }>(),
|
||||
pinRequested: type<{ issueId: string; pinned: boolean }>(),
|
||||
followTreeRequested: type<{ issueId: string; on: boolean }>(),
|
||||
reminderRequested: type<{
|
||||
issueId: string;
|
||||
/** null: drop it. */
|
||||
at: string | null;
|
||||
note: string | null;
|
||||
}>(),
|
||||
trashRequested: type<{
|
||||
issueId: string;
|
||||
trashed: boolean;
|
||||
|
||||
@@ -120,6 +120,17 @@ export class IssueFacade {
|
||||
);
|
||||
}
|
||||
|
||||
/** Remind me of the ticket then (null: drop it); one per ticket. */
|
||||
setReminder(at: string | null, note: string | null = null): void {
|
||||
this.withIssue((issueId) =>
|
||||
this.dispatch.reminderRequested({
|
||||
issueId,
|
||||
at,
|
||||
note: note?.trim() || null,
|
||||
}),
|
||||
);
|
||||
}
|
||||
|
||||
/** Follow the ticket with everything under it (an epic), or stop. */
|
||||
setFollowingTree(on: boolean): void {
|
||||
this.withIssue((issueId) =>
|
||||
|
||||
@@ -22,6 +22,7 @@ import {
|
||||
IssueSummary,
|
||||
SprintsGateway,
|
||||
TrackerRealtimeGateway,
|
||||
whenLabel,
|
||||
} from '@task-stream/web/tracker/domain';
|
||||
import {
|
||||
concatMap,
|
||||
@@ -379,6 +380,26 @@ export const IssueStore = signalStore(
|
||||
),
|
||||
),
|
||||
),
|
||||
events
|
||||
.on(issuePageEvents.reminderRequested)
|
||||
.pipe(
|
||||
mergeMap(({ payload }) =>
|
||||
runCommand(
|
||||
payload.at
|
||||
? issues.setReminder(
|
||||
payload.issueId,
|
||||
payload.at,
|
||||
payload.note,
|
||||
)
|
||||
: issues.clearReminder(payload.issueId),
|
||||
payload.at
|
||||
? `Te lo recordaré ${whenLabel(payload.at)}`
|
||||
: 'Recordatorio quitado',
|
||||
done,
|
||||
failed,
|
||||
),
|
||||
),
|
||||
),
|
||||
events
|
||||
.on(issuePageEvents.followTreeRequested)
|
||||
.pipe(
|
||||
|
||||
Reference in New Issue
Block a user