mirror of
https://github.com/kikootwo/ReadMeABook.git
synced 2026-06-03 12:50:09 +00:00
eef6ae3462
Introduce a complete admin System Logs feature: adds frontend components (filters, date picker, active filter chips, rows, detail panel, skeletons, pagination, toolbar, user typeahead, and styles) under src/app/admin/logs/components, plus hooks (useAutoRefreshControl, useLogsUrlState, useUserSearch) and types. Add constants for job labels and log filters, wire URL-driven filters/search/date-range/hasError/user/audiobookQuery with pause-on-interact behavior and page-size options. Update API route (/api/admin/logs) to support the expanded query params and exported where-builder. Update documentation (TABLEOFCONTENTS and admin-dashboard) and add/adjust tests for the new admin logs UI and API behavior.
146 lines
7.0 KiB
Markdown
146 lines
7.0 KiB
Markdown
# Admin Dashboard
|
|
|
|
**Status:** ✅ Implemented
|
|
|
|
Comprehensive overview of system metrics, active requests, download monitoring, and quick access to settings.
|
|
|
|
## Sections
|
|
|
|
- **Metrics:** Total requests, active downloads, completed/failed requests, total users, system health
|
|
- **Requests Awaiting Approval:** Grid of requests pending admin approval (approve/deny buttons, auto-refresh)
|
|
- **Active Downloads:** Real-time table with title, progress, speed, ETA
|
|
- **Request Management:** Full-featured table with filtering, sorting, pagination
|
|
- **Quick Actions:** Links to settings, users, scheduled jobs, system logs
|
|
|
|
## Data Sources
|
|
|
|
**GET /api/admin/metrics**
|
|
- Total requests (all time)
|
|
- Active downloads (status: 'downloading')
|
|
- Completed requests (status: 'downloaded' or 'available', last 30 days)
|
|
- Failed requests (status: 'failed', last 30 days)
|
|
- Total users
|
|
- System health indicators
|
|
|
|
**GET /api/admin/downloads/active**
|
|
- Request ID, title, progress %, speed, ETA, user
|
|
|
|
**GET /api/admin/requests** (Paginated)
|
|
- Query params: `page`, `pageSize` (10|25|50|100), `search`, `status`, `userId`, `sortBy`, `sortOrder`
|
|
- Returns: `requests[]`, `total`, `page`, `pageSize`, `totalPages`
|
|
- Sorting: createdAt (default), completedAt, title, user, status
|
|
- Filtering: by status, by user, text search (title/author)
|
|
|
|
**GET /api/admin/requests/recent** (Legacy)
|
|
- Request ID, title, user, status, created/completed dates
|
|
- Limited to 50 entries, no filtering
|
|
|
|
**GET /api/admin/requests/pending-approval**
|
|
- Requests with status 'awaiting_approval', includes audiobook + user details
|
|
- Returns: requests array, count
|
|
|
|
**POST /api/admin/requests/[id]/approve**
|
|
- Action: 'approve' (set status to 'pending', trigger search) or 'deny' (set status to 'denied')
|
|
- Validates request is in 'awaiting_approval' status
|
|
|
|
**GET /api/admin/users**
|
|
- User ID, Plex ID, username, email, role, avatar, created/updated dates, last login, request count, autoApproveRequests
|
|
|
|
**PUT /api/admin/users/[id]**
|
|
- Update user role (user/admin), autoApproveRequests (true/false/null)
|
|
- Prevents self-demotion
|
|
|
|
**GET /api/admin/settings/auto-approve**
|
|
- Get global auto-approve setting (boolean)
|
|
|
|
**PATCH /api/admin/settings/auto-approve**
|
|
- Update global auto-approve setting (boolean)
|
|
|
|
**GET /api/admin/logs**
|
|
- Query params: page, limit, status, type, search, dateFrom, dateTo, hasError, userId, audiobookQuery
|
|
- limit: one of 25/50/100 (default 50; invalid values clamp to 50)
|
|
- status: 'all' or one of pending/active/completed/failed/delayed/stuck
|
|
- type: 'all' or any job type key
|
|
- dateFrom / dateTo: ISO UTC strings; invalid dates silently dropped
|
|
- hasError: 'true' or '1' → `status in (failed, stuck) OR errorMessage IS NOT NULL`
|
|
- userId: uuid → filters via `request.userId`
|
|
- audiobookQuery: free text → OR-contains (case-insensitive) on `request.audiobook.{title,author}`
|
|
- search: free text → 6-column OR: bullJobId (startsWith, case-sensitive), errorMessage (contains-i), events.some.message (contains-i), request.audiobook.title/author (contains-i), request.user.plexUsername (contains-i)
|
|
- hasError + search combine under top-level `AND`; other filters compose via AND on `where`
|
|
- Where-builder: exported `buildLogsWhere(params)` in route file (pure, testable)
|
|
- Returns: `{ logs, pagination: { page, limit, total, totalPages } }`
|
|
|
|
## Request Management Features
|
|
|
|
- **Filter Bar:**
|
|
- Text search (title/author, 300ms debounce)
|
|
- Status dropdown (all statuses)
|
|
- User dropdown (all users)
|
|
- Clear filters button
|
|
- **Sortable Columns:** Click headers to sort by title, user, status, requested, completed
|
|
- **Pagination:** Page navigation, page size selector (10/25/50/100), results count
|
|
- **URL State:** Filters/sort/page stored in URL query params (shareable, bookmarkable)
|
|
- **Actions:** Delete, cancel, manual search, fetch ebook (via dropdown)
|
|
|
|
## Features
|
|
|
|
- Auto-refresh every 10 seconds (SWR)
|
|
- Back to Home button in header
|
|
- Admin role required
|
|
- Real-time progress updates
|
|
- **Requests Awaiting Approval Section:**
|
|
- Only visible when pending approval requests exist
|
|
- Grid layout (3 columns on desktop)
|
|
- Book cards with cover, title, author, user info, timestamp
|
|
- Approve (green) and Deny (red) buttons
|
|
- Loading states during approval/denial actions
|
|
- Toast notifications for success/errors
|
|
- Mutates pending-approval, recent requests, metrics caches on action
|
|
|
|
## Navigation
|
|
|
|
- `/admin/jobs` - Scheduled jobs management (trigger, edit schedule, enable/disable)
|
|
- `/admin/settings` - System settings (Plex, Prowlarr, paths)
|
|
- `/admin/users` - User management (view users, change roles)
|
|
- `/admin/logs` - System logs (view job history, errors, filter by status/type)
|
|
|
|
## User Management Features
|
|
|
|
- List all users with avatar, email, role, request count, last login, autoApproveRequests
|
|
- Edit user roles (user/admin)
|
|
- Cannot change own role (security)
|
|
- Shows request count per user
|
|
- Role badges (purple for admin, gray for user)
|
|
- **Global Auto-Approve Toggle:**
|
|
- Checkbox at top: "Auto-approve all requests by default"
|
|
- Updates Configuration.auto_approve_requests
|
|
- **Per-User Auto-Approve Control:**
|
|
- Dropdown: Use Global (null), Always Auto-Approve (true), Always Require Approval (false)
|
|
- Updates User.autoApproveRequests
|
|
- Shows effective setting (considers global + per-user)
|
|
|
|
## System Logs Features
|
|
|
|
- Real-time job monitoring (10s SWR refresh; pauses on interact)
|
|
- **Filter row (5 pickers):** Status · Job Type · Date Range · User typeahead · Audiobook free-text
|
|
- Status: dropdown over VALID_STATUSES (from `src/app/admin/logs/types.ts`); labels via `STATUS_OPTIONS` in `src/lib/constants/log-filters.ts`
|
|
- Job Type: dropdown over `JOB_TYPE_LABELS` insertion order (`src/lib/constants/job-labels.ts`)
|
|
- Date Range: presets (Last hour / 24h / 7d / 30d / Custom / All time) — default = Last 7 days (Zach #1); Custom uses `<input type="datetime-local">` rendered as local time, wired as UTC ISO
|
|
- User: typeahead via `useUserSearch` (fetch-once from `/api/admin/users`, SWR-cached, in-memory filter, max 10 suggestions); selection sets `userId = User.id`
|
|
- Audiobook: free-text → server-side OR-contains on title/author (Zach #4 — no picker)
|
|
- **Active filter chips:** dismissable `<button aria-label="Remove filter: X">` strip; NOT sticky (Zach #6 — scrolls with content). Errors-only renders as a chip when active.
|
|
- **Clear all filters:** visible only when ≥1 filter or the search input is non-default
|
|
- **Pause-on-interact reasons (registered to `useAutoRefreshControl`):**
|
|
- `logs-status-dropdown`, `logs-type-dropdown`, `logs-date-picker`, `logs-user-typeahead`, `logs-book-input`
|
|
- **URL = source of truth** via `useLogsUrlState` (`src/app/admin/logs/hooks/`); param names exported as `LOG_PARAMS`; same names used by `/api/admin/logs`
|
|
- Shows related audiobook/user for request jobs
|
|
- Expandable error messages, duration calc, attempt tracking, Bull job ID
|
|
- Pagination: page-size selector (25 / 50 / 100), default 50
|
|
|
|
## Tech Stack
|
|
|
|
- React Server Components + SWR
|
|
- Tailwind CSS
|
|
- Prisma aggregations for metrics
|
|
- Database queries with indexing
|