Files
LinkDesk/frontend_tasks.md
T
indigo cd2efe3587 Truth-in-UI cleanup: wire real dashboard data, fix delete/dialog gaps
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>
2026-07-17 04:47:26 +08:00

9.7 KiB
Raw Blame History

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)

  • 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-278deferred: 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-295deferred: needs a new GET /projects/{id}/task-statuses/counts backend endpoint
  • Register the missing route: /projects/:projectId/technical-specs in router/index.ts
  • Delete confirmed-dead files (or finish wiring them in):
    • components/shot/ShotColumnVisibilityControl.vue — deleted
    • components/asset/ColumnVisibilityControl.vue — deleted
    • components/project/ShotsTable.vue — deleted
    • components/examples/FileUploadExample.vue — deleted
    • views/GlobalSettingsView.vue — deleted
    • views/HomeView.vue — deleted
    • components/asset/AssetDeleteConfirmDialog.vue — fixed (raw divs → shared Alert component) and wired into AssetBrowser.vue, mirroring ShotBrowser.vue's pattern
    • components/activity/ActivityFeed.vue — wired into ProjectOverviewView.vue in place of "coming soon" text; TaskActivityTimeline.vue — deleted (no taskId available at that call site)
  • Replace native confirm()/alert() with styled dialogs:
    • components/task/NoteItem.vue:178AlertDialog
    • components/task/TaskAttachments.vue:201AlertDialog
    • components/layout/UserMenu.vue keyboard-shortcuts alert()Dialog
  • Remove leftover debug logging (all 8 files/line-ranges)
  • 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.vueleft 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).
  • 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.