feat: admin dashboard — search, analytics, users, templates#6
Merged
Conversation
- Search box on the admin inbox view filters the message list client-side by from/subject/preview substrings. - New stats package exposes user, premium, active inbox, and message (24h/7d) counts via DynamoDB scans with paginated SelectCount. - GET /admin/stats returns the snapshot; AdminView renders a five-tile strip at the top so the operator sees platform health at a glance. Scan-based aggregation is fine at current volumes; if the table grows we will move to per-counter sentinel items or CloudWatch metrics.
Adds GET /admin/users returning every user with id, email, tier, role, webhook flag, and created_at. AdminView grew an INBOXES / USERS tab switcher under the stats strip; the USERS tab shows a sortable table with client-side search by id/email/tier/role. Sensitive fields (api key, webhook secret) are deliberately omitted from the admin view. Mutations (promote/demote, manual tier change) left out for v1 — they need confirmation UX and audit logging before shipping.
New template package persists per-admin compose presets in DynamoDB under PK __template__:<userID>. Admin endpoints GET/POST/DELETE /admin/templates list, create (max 25 per user), and remove templates. Compose form gets a 'Insert template' dropdown that fills subject and body, and a 'Save template' input next to SEND that captures the current draft under a name. Saved templates are listed below the form with inline delete buttons.
|
The latest updates on your projects. Learn more about Vercel for GitHub.
|
Stamp read_at on the first GetMessage call via a conditional UpdateItem (skips write if already set). MessageSummary now carries read_at so the list renders unread rows in bold with a brighter dot and a subtle border highlight; opening a message optimistically flips the row in the client before the next poll lands.
Owners (premium) can grant another account read access to one of their
inboxes by entering the recipient's account email. The recipient
authenticates with their own api key when fetching the inbox; backend
authenticateInbox now allows owner OR shared_with match.
New endpoints (premium-gated for add):
GET /inbox/{addr}/shares
POST /inbox/{addr}/shares { email }
DELETE /inbox/{addr}/shares/{userId}
Shares are persisted as a string list on the inbox sentinel item; the
recipient surfaces them via direct URL for now (a "Shared with you"
listing for the recipient is left for v2 — no reverse index yet).
Account page grew an inline Share section per active inbox with email
input, error states for unknown email or self-share, and an inline
list with per-row remove.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Phase 4 (Growth & Admin) work, all behind the existing admin role gate.
from,subject, orpreviewsubstring.Mutations on user records (promote/demote, manual tier change) are intentionally absent for v1 — they need confirmation UX and audit logging before shipping.
Scan-based aggregation is fine at current volumes; if the table grows we will move to per-counter sentinel items or CloudWatch metrics.
Test plan