feat(paliadin/agent-glyph): t-paliad-161 Slice E — ✨ alongside 👀
When a pending row was drafted by Paliadin (requester_kind='agent' on its in-flight approval_request), surface a sparkle ✨ next to the existing eye-pill 👀. The two glyphs are orthogonal: 👀 = "needs approval", ✨ = "Paliadin drafted this". Either can change without the other, so the visual taxonomy stays decomposable for any future autopilot mode where 👀 disappears but ✨ stays. Read-path: - DeadlineService.ListVisibleForUser + AppointmentService.ListVisibleForUser LEFT JOIN paliad.approval_requests on pending_request_id and project ar.requester_kind into the row. NULL when no request is pending. - models.DeadlineWithProject + AppointmentWithProject grow RequesterKind *string. The list-projection helpers (projectDeadline / projectAppointment in event_service.go) carry it into EventListItem. - /api/events response now includes requester_kind on every pending row; /api/inbox already does (Slice D extended approvalRequestViewColumns). Render-path: - frontend/src/client/events.ts — new AGENT_PILL_GLYPH constant ("✨"), agentPill rendered into the title cell next to the existing pendingPill when item.approval_status='pending' AND item.requester_kind='agent'. EventListItem TS shape gains `requester_kind?: "user" | "agent"`. - frontend/src/client/agenda.ts — same pattern, agendaItem TS shape + agentPill rendered next to pendingPill in the headline span. - frontend/src/client/inbox.ts — ApprovalRequestView gains requester_kind + agent_turn_id; the meta line replaces the requester's plain name with "Anna ✨ Paliadin" when the request was drafted by the agent. CSS: new .approval-pill--agent modifier in global.css using only existing tokens (--color-bg-lime-tint / --color-surface-2 / --color-text), mirroring the .approval-pill--icon shape so the two glyphs sit side-by-side at the same baseline. i18n: 3 new keys × 2 langs (approvals.agent.label / approvals.agent.byline / approvals.agent.suggestion_pending) — total 1966 → 1969. Build clean (frontend + go), tests green. Refs: docs/design-paliadin-inline-2026-05-08.md §8.
This commit is contained in:
@@ -185,9 +185,11 @@ func (s *AppointmentService) ListVisibleForUser(ctx context.Context, userID uuid
|
||||
t.approval_status, t.pending_request_id, t.approved_by, t.approved_at,
|
||||
p.reference AS project_reference,
|
||||
p.title AS project_title,
|
||||
p.type AS project_type
|
||||
p.type AS project_type,
|
||||
ar.requester_kind AS requester_kind
|
||||
FROM paliad.appointments t
|
||||
LEFT JOIN paliad.projects p ON p.id = t.project_id
|
||||
LEFT JOIN paliad.approval_requests ar ON ar.id = t.pending_request_id
|
||||
WHERE ` + strings.Join(conds, " AND ") + `
|
||||
ORDER BY t.start_at ASC, t.created_at DESC`
|
||||
|
||||
|
||||
@@ -240,10 +240,12 @@ func (s *DeadlineService) ListVisibleForUser(ctx context.Context, userID uuid.UU
|
||||
p.title AS project_title,
|
||||
p.type AS project_type,
|
||||
r.name AS rule_name,
|
||||
r.name_en AS rule_name_en
|
||||
r.name_en AS rule_name_en,
|
||||
ar.requester_kind AS requester_kind
|
||||
FROM paliad.deadlines f
|
||||
JOIN paliad.projects p ON p.id = f.project_id
|
||||
LEFT JOIN paliad.deadline_rules r ON r.id = f.rule_id
|
||||
LEFT JOIN paliad.approval_requests ar ON ar.id = f.pending_request_id
|
||||
WHERE ` + strings.Join(conds, " AND ") + `
|
||||
ORDER BY f.due_date ASC, f.created_at DESC`
|
||||
|
||||
|
||||
@@ -97,6 +97,10 @@ type EventListItem struct {
|
||||
// (default), "pending" (in-flight 4-eye request — pill rendered on
|
||||
// every list surface), or "legacy" (pre-4-eye row, no pill).
|
||||
ApprovalStatus *string `json:"approval_status,omitempty"`
|
||||
// RequesterKind is the kind of the in-flight approval request when
|
||||
// approval_status='pending': 'user' or 'agent' (Paliadin-drafted —
|
||||
// t-paliad-161). NULL otherwise. Drives the ✨ glyph alongside 👀.
|
||||
RequesterKind *string `json:"requester_kind,omitempty"`
|
||||
|
||||
// Deadline-only.
|
||||
DueDate *string `json:"due_date,omitempty"` // YYYY-MM-DD
|
||||
@@ -223,6 +227,7 @@ func projectDeadline(d models.DeadlineWithProject) EventListItem {
|
||||
ProjectType: &ptype,
|
||||
CreatedBy: d.CreatedBy,
|
||||
ApprovalStatus: &approvalStatus,
|
||||
RequesterKind: d.RequesterKind,
|
||||
DueDate: &due,
|
||||
Status: &status,
|
||||
CompletedAt: d.CompletedAt,
|
||||
@@ -251,6 +256,7 @@ func projectAppointment(a models.AppointmentWithProject) EventListItem {
|
||||
ProjectType: a.ProjectType,
|
||||
CreatedBy: a.CreatedBy,
|
||||
ApprovalStatus: &approvalStatus,
|
||||
RequesterKind: a.RequesterKind,
|
||||
StartAt: &startCopy,
|
||||
EndAt: a.EndAt,
|
||||
Location: a.Location,
|
||||
|
||||
Reference in New Issue
Block a user