cd2efe3587
Phase 1 of frontend_tasks.md - stop showing fabricated/broken UI:
- Dashboard now fetches real stats (projects, tasks, users, pending
approvals, API keys, developer stats, pending reviews, admin
activity) instead of hardcoded numbers. Added services/developer.ts
and services/review.ts wrappers for previously-unused backend
endpoints.
- Wired ActivityFeed into every project's Overview page in place of
the "coming soon" placeholder.
- Registered the missing /projects/:id/technical-specs route (view
and service already existed, just unreachable).
- Fixed AssetDeleteConfirmDialog's raw styled divs to use the shared
Alert component and wired it into AssetBrowser, matching
ShotBrowser's impact-summary + type-to-confirm safety pattern
(asset deletion was previously less safe than shot deletion).
- Fixed a shared bug in both delete dialogs where the impact-summary
section never rendered (watch on the open prop needed
{ immediate: true }).
- Replaced native confirm()/alert() with styled AlertDialog/Dialog in
NoteItem, TaskAttachments, and UserMenu's keyboard-shortcuts item.
- Removed dead-end UI: Google OAuth stub buttons, UserMenu items
pointing at non-existent routes, the /developer/docs dead link, and
the no-op action button on the API Keys placeholder page.
- Removed leftover debug console logging across 8 files.
Added frontend_report.md (full audit) and frontend_tasks.md (phased
checklist) as the reference for this and future phases.
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
95 lines
9.7 KiB
Markdown
95 lines
9.7 KiB
Markdown
# Frontend Improvement Tasks
|
||
|
||
Derived from `frontend_report.md`. Checklist form for tracking progress — check items off as they land. Ordered by phase (do Phase 1 before Phase 2, etc.); within a phase, order doesn't matter much.
|
||
|
||
---
|
||
|
||
## Phase 1 — Truth-in-UI & dead code ✅ (done)
|
||
|
||
- [x] Wire `views/DashboardView.vue` stats to real API data where an endpoint exists (projects, active projects, overdue tasks, total users, pending approvals, API keys, developer stats, pending reviews, admin system activity). Added `services/developer.ts` and `services/review.ts` wrappers.
|
||
- [ ] Replace fixed-lookup episode progress with real computed progress — `components/episode/EpisodeCard.vue:117-128` and `components/episode/EpisodeList.vue:267-278` — **deferred**: backend has no `completed_shots`/`progress` field yet (`backend/schemas/episode.py`, `backend/routers/episodes.py`)
|
||
- [ ] Fix task-status usage counts always showing 0 — `components/settings/CustomTaskStatusManager.vue:275-295` — **deferred**: needs a new `GET /projects/{id}/task-statuses/counts` backend endpoint
|
||
- [x] Register the missing route: `/projects/:projectId/technical-specs` in `router/index.ts`
|
||
- [x] Delete confirmed-dead files (or finish wiring them in):
|
||
- [x] `components/shot/ShotColumnVisibilityControl.vue` — deleted
|
||
- [x] `components/asset/ColumnVisibilityControl.vue` — deleted
|
||
- [x] `components/project/ShotsTable.vue` — deleted
|
||
- [x] `components/examples/FileUploadExample.vue` — deleted
|
||
- [x] `views/GlobalSettingsView.vue` — deleted
|
||
- [x] `views/HomeView.vue` — deleted
|
||
- [x] `components/asset/AssetDeleteConfirmDialog.vue` — fixed (raw divs → shared `Alert` component) and wired into `AssetBrowser.vue`, mirroring `ShotBrowser.vue`'s pattern
|
||
- [x] `components/activity/ActivityFeed.vue` — wired into `ProjectOverviewView.vue` in place of "coming soon" text; `TaskActivityTimeline.vue` — deleted (no `taskId` available at that call site)
|
||
- [x] Replace native `confirm()`/`alert()` with styled dialogs:
|
||
- [x] `components/task/NoteItem.vue:178` → `AlertDialog`
|
||
- [x] `components/task/TaskAttachments.vue:201` → `AlertDialog`
|
||
- [x] `components/layout/UserMenu.vue` keyboard-shortcuts `alert()` → `Dialog`
|
||
- [x] Remove leftover debug logging (all 8 files/line-ranges)
|
||
- [x] Removed Google OAuth stub buttons (`LoginView.vue`, `RegisterView.vue`) — no OAuth backend exists, so the buttons were pure dead ends
|
||
- [ ] `/developer/api-keys`, `/developer/projects`, `/developer/tasks`, `/developer/analytics`, `views/ReviewsView.vue` — **left as-is**: their empty states are honest ("No API keys" etc.), not misleading, so out of scope for a truth-in-UI pass. Only fixed the one dead action button on `APIKeysView.vue` (removed `action-text`/`@action` since it did nothing).
|
||
- [x] Removed dead-end UserMenu items (`/settings/preferences`, `/help`, notifications toggle) and the `/developer/docs` dead link (`AppSidebar.vue`, `DashboardView.vue`) — no real destination existed for any of them
|
||
|
||
**Bonus fixes surfaced during verification (approved mid-implementation):**
|
||
- Fixed two pre-existing backend bugs that 500'd once real data was wired up: `backend/routers/reviews.py` (`joinedload("reviewer")` string → `joinedload(Review.reviewer)`) and `backend/utils/activity.py` (wrong `models.submission` import path → `models.task`).
|
||
- Fixed a pre-existing bug shared by both `ShotDeleteConfirmDialog.vue` and `AssetDeleteConfirmDialog.vue`: their `watch(() => props.open, ...)` lacked `{ immediate: true }`, so the impact-summary section never rendered since the dialog only mounts once already open. Deletion itself worked fine either way — this was purely cosmetic, but it was the whole point of the "impact summary" safety feature.
|
||
|
||
## Phase 2 — Close feature gaps (asset vs. shot parity)
|
||
|
||
- [ ] Add user-assignment popover to `components/asset/EditableTaskStatus.vue` (shot version at `components/shot/EditableTaskStatus.vue` is the reference)
|
||
- [ ] Add column-locking toggle to `components/asset/AssetTableToolbar.vue` (shot version has `Lock`/`Unlock` toggle)
|
||
- [ ] Add row-actions ("…") menu to `components/task/columns.ts` (shot/asset already have one)
|
||
- [ ] Implement the six stubbed asset detail-panel actions in `components/asset/AssetBrowser.vue:571-574, 680-703`: create task, select task, create note, upload reference, publish version — or hide the affordances until built
|
||
- [ ] Implement shot detail-panel task stubs in `components/shot/ShotBrowser.vue:848-856`: create task, select task
|
||
- [ ] Consolidate `components/project/ProjectMembersManager.vue` and `components/project/ProjectMemberManagement.vue` into one component
|
||
- [ ] Wire the consolidated member-management component into `ProjectDetailView.vue:149-151` ("Manage Members" is currently a no-op)
|
||
|
||
## Phase 3 — Unify controls
|
||
|
||
- [ ] Extract `ColumnToggleList` component (built on `DropdownMenuCheckboxItem`, not hand-rolled div+Check) and point at it from:
|
||
- [ ] `components/ui/sidebar/SidebarColumnSwitch.vue`
|
||
- [ ] `components/shot/ShotTableToolbar.vue`
|
||
- [ ] `components/asset/AssetTableToolbar.vue`
|
||
- [ ] `components/task/TaskTableToolbar.vue`
|
||
- [ ] Extract shared `EntityTableToolbar` (search, column-visibility trigger, detail-panel toggle, clear-filters) to de-duplicate the three toolbar files
|
||
- [ ] Extract `SegmentedToggle` component for the three hand-built view-mode switches (shot grid/list/table, asset grid/list, task all/shots/assets)
|
||
- [ ] Standardize delete confirmation on the shot pattern (`Dialog` + `Alert` + impact summary + type-to-confirm) for any cascading delete; fix asset's dialog to match or consciously keep it lighter
|
||
- [ ] Swap hand-rolled checkbox-divs for real `Checkbox`/`DropdownMenuCheckboxItem` in:
|
||
- [ ] `SidebarColumnSwitch.vue`
|
||
- [ ] `ShotTableToolbar.vue`
|
||
- [ ] `AssetTableToolbar.vue`
|
||
- [ ] `TaskTableToolbar.vue`
|
||
- [ ] `ShotTaskStatusFilter.vue`
|
||
- [ ] `asset/TaskStatusFilter.vue`
|
||
- [ ] Replace ad hoc `size="sm" class="h-8 w-8 p-0"` with `size="icon-sm"` across toolbar/browser icon buttons
|
||
- [ ] Decide one convention (icon+label vs. icon-only+tooltip) for primary "create" CTAs and apply consistently (shot/asset create buttons currently lack tooltips project/episode create buttons have)
|
||
- [ ] Standardize row-actions/bulk-actions on `DropdownMenu`/`DropdownMenuItem`; replace ad hoc `<button>` list in `components/task/TaskBulkActionsMenu.vue`
|
||
- [ ] Extract `DetailPanelShell` (header/close button, loading state, error state, Tabs scaffold, slide-in transition) for `ShotDetailPanel.vue`, `AssetDetailPanel.vue`, `TaskDetailPanel.vue` to share; add missing error state to Task's panel
|
||
|
||
## Phase 4 — Architecture & tooling investment
|
||
|
||
- [ ] Add a shared `useAsyncAction`-style composable (`isLoading`/`error`/`run(fn)`) and adopt it across `stores/*.ts` to cut repeated try/catch/finally boilerplate
|
||
- [ ] Replace `stores/taskStatuses.ts`'s polling-based in-flight request de-dup (100ms `setInterval` loop, lines 96-117) with promise memoization
|
||
- [ ] Extend a similar TTL/cache strategy to `stores/assets.ts`, `stores/tasks.ts`, `stores/projects.ts`, `stores/episodes.ts` (currently no caching — every view re-fetches on mount)
|
||
- [ ] De-duplicate `assets.ts`'s optimistic-update/rollback logic between single (`lines 156-234`) and bulk (`lines 236-356`) task-status updates into one parameterized function
|
||
- [ ] Add `markRaw()` around icon components stored in reactive state — `stores/projects.ts` `assignProjectIcon`
|
||
- [ ] Audit `deep: true` watchers, especially `views/ProjectsView.vue:770` (watches the full, non-`markRaw`'d projects array)
|
||
- [ ] Fix N+1 project-member fetch: hoist `getProjectMembers()` call out of `EditableTaskStatus.vue` (mounted per row × task-type column) into a shared store/cache or parent-passed prop
|
||
- [ ] Add table virtualization (e.g. `@tanstack/vue-virtual`) to `ShotsDataTable.vue`, `AssetsDataTable.vue`, `TasksDataTable.vue`
|
||
- [ ] Introduce a shared `EmptyState` component and standardize on `Skeleton` for loading states (currently: 5 files use `Skeleton`, 62 use ad hoc spinners; 31 files hand-roll empty-state text)
|
||
- [ ] Add toast-on-error for currently-silent secondary loads: episodes/task-types/task-statuses/project-context in `ShotBrowser.vue` (lines 474-508), `stores/notifications.ts:fetchStats`, router auth-init failure (`router/index.ts:190-196`)
|
||
- [ ] Centralize a `usePermission()`/`can()` composable to consolidate role/admin checks currently duplicated across ~20 components outside the router guard
|
||
- [ ] Consider splitting the largest files into smaller pieces: `views/project/ShotDetailView.vue` (1658 lines), `views/admin/DeletedItemsManagementView.vue` (1279 lines), and evaluate a shared "entity browser" composable for `ShotBrowser.vue`/`AssetBrowser.vue`'s ~70% structural overlap
|
||
- [ ] Move ad hoc domain types out of `services/*.ts` into `types/` for discoverability (currently only `auth.ts`, `notification.ts`, `activity.ts` live in `types/`)
|
||
|
||
## Phase 5 — Testing & quality gates
|
||
|
||
- [ ] Add Vitest + Vue Test Utils
|
||
- [ ] Write first tests for the highest-risk untested logic: `stores/assets.ts` optimistic-update/rollback, `stores/auth.ts` token lifecycle
|
||
- [ ] Add an ESLint config (flag `any`, unused locals, enforce consistent import/style rules)
|
||
- [ ] Re-enable `noUnusedLocals` in `tsconfig.json` (currently explicitly disabled)
|
||
- [ ] Introduce a typed `ApiError` helper to replace ad hoc `err.response?.data?.detail` access at the 104 `catch (err: any)` sites (fix incrementally as files are touched, not all at once)
|
||
- [ ] Accessibility fixes: remove checkbox-inside-`SelectItem` anti-pattern (also fixes the double-toggle bug), add keyboard support to hand-rolled clickable `<div>`s (`SubmissionCard.vue`, `EditableTaskStatus.vue`)
|
||
|
||
---
|
||
|
||
*Full context, rationale, and file-by-file findings for every item above are in `frontend_report.md`.*
|