reminders: add ListReminders IPC + /reminders web page
Store layer: ListReminders returns the n most recent reminders (newest first). IPC: new MethodListReminders wired through server, client, and lockedAPI. Web: /reminders page with table of created time, fire time, status badge, and payload text; empty state with prompt to ask maven for a reminder. Sidebar entry under Automation.
This commit is contained in:
@@ -221,6 +221,7 @@ type CoreAPI interface {
|
||||
Presence(ctx context.Context) (Presence, error)
|
||||
CreateReminder(ctx context.Context, fire time.Time, payload, cron string) (int64, error)
|
||||
MarkReminder(ctx context.Context, id int64, status string) error
|
||||
ListReminders(ctx context.Context, n int) ([]Reminder, error)
|
||||
RecordNudge(ctx context.Context, rule, channel, message string, ts time.Time) (int64, error)
|
||||
ResolveNudge(ctx context.Context, id int64, outcome string, ts time.Time) error
|
||||
RecentOutcomes(ctx context.Context, rule string, n int) ([]string, error)
|
||||
|
||||
@@ -249,6 +249,14 @@ func (c *Client) MarkReminder(ctx context.Context, id int64, status string) erro
|
||||
return c.call(ctx, MethodMarkReminder, markReminderReq{ID: id, Status: status}, nil)
|
||||
}
|
||||
|
||||
func (c *Client) ListReminders(ctx context.Context, n int) ([]Reminder, error) {
|
||||
var out []Reminder
|
||||
if err := c.call(ctx, MethodListReminders, nReq{N: n}, &out); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (c *Client) RecordNudge(ctx context.Context, rule, channel, message string, ts time.Time) (int64, error) {
|
||||
var r idResp
|
||||
if err := c.call(ctx, MethodRecordNudge, recordNudgeReq{Rule: rule, Channel: channel, Message: message, Ts: ts}, &r); err != nil {
|
||||
|
||||
@@ -78,6 +78,18 @@ func (a *storeAPI) MarkReminder(ctx context.Context, id int64, status string) er
|
||||
return mapErr(a.s.MarkReminder(ctx, id, status))
|
||||
}
|
||||
|
||||
func (a *storeAPI) ListReminders(ctx context.Context, n int) ([]Reminder, error) {
|
||||
rs, err := a.s.ListReminders(ctx, n)
|
||||
if err != nil {
|
||||
return nil, mapErr(err)
|
||||
}
|
||||
out := make([]Reminder, len(rs))
|
||||
for i, r := range rs {
|
||||
out[i] = toReminder(r)
|
||||
}
|
||||
return out, nil
|
||||
}
|
||||
|
||||
func (a *storeAPI) RescheduleReminder(ctx context.Context, id int64, now time.Time) error {
|
||||
return mapErr(a.s.RescheduleReminder(ctx, id, now))
|
||||
}
|
||||
@@ -210,6 +222,18 @@ func toTool(t store.Tool) Tool {
|
||||
}
|
||||
}
|
||||
|
||||
func toReminder(r store.Reminder) Reminder {
|
||||
return Reminder{
|
||||
ID: r.ID,
|
||||
CreatedTs: r.CreatedTs,
|
||||
FireTs: r.FireTs,
|
||||
NextFireTs: r.NextFireTs,
|
||||
Payload: r.Payload,
|
||||
Status: r.Status,
|
||||
Cron: r.Cron,
|
||||
}
|
||||
}
|
||||
|
||||
func toNote(n store.Note) Note {
|
||||
return Note{ID: n.ID, Ts: n.Ts, Text: n.Text, Source: n.Source, Score: n.Score}
|
||||
}
|
||||
@@ -516,6 +540,20 @@ func (s *Server) dispatch(ctx context.Context, req Request) (json.RawMessage, er
|
||||
err := api.MarkReminder(ctx, p.ID, p.Status)
|
||||
return marshalResult(nil), err
|
||||
|
||||
case MethodListReminders:
|
||||
var p nReq
|
||||
if err := unmarshalParams(req.Params, &p); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out, err := api.ListReminders(ctx, p.N)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if out == nil {
|
||||
out = []Reminder{}
|
||||
}
|
||||
return marshalResult(out), nil
|
||||
|
||||
case MethodRecordNudge:
|
||||
var p recordNudgeReq
|
||||
if err := unmarshalParams(req.Params, &p); err != nil {
|
||||
|
||||
@@ -20,6 +20,7 @@ const (
|
||||
MethodPresence Method = "presence"
|
||||
MethodCreateReminder Method = "create_reminder"
|
||||
MethodMarkReminder Method = "mark_reminder"
|
||||
MethodListReminders Method = "list_reminders"
|
||||
MethodRecordNudge Method = "record_nudge"
|
||||
MethodResolveNudge Method = "resolve_nudge"
|
||||
MethodRecentOutcomes Method = "recent_outcomes"
|
||||
|
||||
@@ -115,6 +115,26 @@ func (s *Store) MarkReminder(ctx context.Context, id int64, status string) error
|
||||
return err
|
||||
}
|
||||
|
||||
// ListReminders returns the n most recent reminders, newest first.
|
||||
func (s *Store) ListReminders(ctx context.Context, n int) ([]Reminder, error) {
|
||||
rows, err := s.db.QueryContext(ctx, `
|
||||
SELECT id, created_ts, fire_ts, next_fire_ts, payload, status, cron
|
||||
FROM reminders ORDER BY created_ts DESC, id DESC LIMIT ?`, n)
|
||||
if err != nil {
|
||||
return nil, fmt.Errorf("list reminders: %w", err)
|
||||
}
|
||||
defer rows.Close()
|
||||
var out []Reminder
|
||||
for rows.Next() {
|
||||
r, err := scanReminder(rows)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
out = append(out, r)
|
||||
}
|
||||
return out, rows.Err()
|
||||
}
|
||||
|
||||
// RescheduleReminder computes the next fire time for a recurring reminder and
|
||||
// updates next_fire_ts. Returns ErrReminderState if the reminder is not
|
||||
// recurring or not pending. If no more valid fire times exist, marks it fired.
|
||||
|
||||
Reference in New Issue
Block a user