feat(approvals): My Approvals page with inline approve/reject (PMS-481) #329
No reviewers
Labels
No labels
No milestone
No project
No assignees
1 participant
Notifications
Due date
No due date set.
Dependencies
No dependencies set
Reference
psa-systems/mokosh-apps!329
Loading…
Reference in a new issue
No description provided.
Delete branch "feat/PMS-481-approvals-page"
Deleting a branch is permanent. Although the deleted branch may continue to exist for a short time before it actually gets removed, it CANNOT be undone in most cases. Continue?
PMS-451 shipped the ticket-approvals server surface; PMS-470 widened it to polymorphic approvals across tickets / time_entries / change_requests / quotes. The SPA had no consumer for
/approvals/pending- every approver had to read the column directly. PMS-481 lands the highest-leverage slice: a new/approvalspage that lists every pending decision the signed-in user can decide and accepts approve / reject inline.What landed:
New
pages/approvals.rs::ApprovalsPage, registered at the/approvalsroute. FetchesGET /api/v1/approvals/pendingviause_resourcewith aversionsignal that bumps after each successful decision so the queue refreshes without a page reload.Each row carries a per-target badge (
Ticket/Time entry/Change request/Quote, with unknown targets falling through to the raw string so a future server-side surface still renders), a clickable entity chip that links to the parent (only for tickets today - non-ticket entity routes don't exist client-side yet, so those render the id verbatim), the requester name, the approver scope ("To: name" or "Role: role"), the requested-at timestamp, and the optional notes.Approve / Reject buttons POST
{ "decision": "approve" | "reject" }to/api/v1/approvals/{id}/decision. On success a toast confirms the action and the queue refetches; on failure the inline error chip surfaces the message without dropping the rest of the queue.The DTO tolerates both the PMS-451-phase-1 ticket-only payload and the PMS-470 polymorphic shape:
targetdefaults to"ticket",entity_idfalls back toticket_idwhen absent, so a tenant running an older server still gets a functional page.Follow-up filed as PMS-486 for the ticket-detail "Approvals" tab + "Request approval" modal + top-bar pending-decisions badge. Each of those touches existing high-traffic surfaces (the ticket-detail tabbed section + the AppLayout chrome) so they land separately; the standalone
/approvalspage is the surface every other approval flow eventually links to.#PMS-481
PMS-451 shipped the ticket-approvals server surface; PMS-470 widened it to polymorphic approvals across tickets / time_entries / change_requests / quotes. The SPA had no consumer for `/approvals/pending` - every approver had to read the column directly. PMS-481 lands the highest-leverage slice: a new `/approvals` page that lists every pending decision the signed-in user can decide and accepts approve / reject inline. What landed: * New `pages/approvals.rs::ApprovalsPage`, registered at the `/approvals` route. Fetches `GET /api/v1/approvals/pending` via `use_resource` with a `version` signal that bumps after each successful decision so the queue refreshes without a page reload. * Each row carries a per-target badge (`Ticket` / `Time entry` / `Change request` / `Quote`, with unknown targets falling through to the raw string so a future server-side surface still renders), a clickable entity chip that links to the parent (only for tickets today - non-ticket entity routes don't exist client-side yet, so those render the id verbatim), the requester name, the approver scope ("To: name" or "Role: role"), the requested-at timestamp, and the optional notes. * Approve / Reject buttons POST `{ "decision": "approve" | "reject" }` to `/api/v1/approvals/{id}/decision`. On success a toast confirms the action and the queue refetches; on failure the inline error chip surfaces the message without dropping the rest of the queue. * The DTO tolerates both the PMS-451-phase-1 ticket-only payload and the PMS-470 polymorphic shape: `target` defaults to `"ticket"`, `entity_id` falls back to `ticket_id` when absent, so a tenant running an older server still gets a functional page. Follow-up filed as PMS-486 for the ticket-detail "Approvals" tab + "Request approval" modal + top-bar pending-decisions badge. Each of those touches existing high-traffic surfaces (the ticket-detail tabbed section + the AppLayout chrome) so they land separately; the standalone `/approvals` page is the surface every other approval flow eventually links to. #PMS-481