5.7 KiB
5.7 KiB
13 — Frontend (Vue 3 SPA)
Vue 3 + TypeScript + Vite + Pinia + Vue Router + Tailwind, pnpm, in web/. Styling authority is 14-design-system.md. All API access through one typed client; all live updates through one SSE module.
Structure
web/src/api/client.ts— typed fetch wrapper (base/api/v1, JSON, error envelope → typedApiError, cookie credentials)web/src/api/sse.ts— EventSource wrapper: connect after login, auto-reconnect with backoff, dispatch frames to therealtimestore, exposeonReconnecthooks (pages refetch)web/src/router/index.ts— routes below; global guard redirects unauthenticated →/login(bootstraps viaGET /me)- Layout:
AppShell(fixed sidebar + navbar +<router-view>), auth pages bare - Vite dev proxy:
/api,/files,/webhooks→ Go server port
Routes & pages
/login— email/password + OAuth buttons (hidden per config)/register— sign-up (notes that first user becomes admin)/oauth/callback— post-OAuth landing, bootstraps session, redirects/— Dashboard: favorite + recent projects, "assigned to me" issue list, cross-project activity feed/inbox— notification inbox (unread filter, mark read/all)/search— full search page (type tabs)/projects— project cards (favorites first, status/priority badges, favorite toggle)/projects/:id— Project overview: description (markdown), members, links, attachments, dependencies (both directions), activity feed/projects/:id/issues— Issue table: sortable columns, FilterBar, URL-synced filters/sort, row click → detail/projects/:id/board— Kanban: 7 fixed status columns, drag-and-drop (optimistic), card =#N, title, labels, assignee avatar, points badge, blocked indicator, epic color strip/projects/:id/issues/:num— Issue detail: editable title/description, sidebar (status, priority, points, assignee, epic, dates, labels, watchers, watch toggle), sub-issues list (+create), blockers list, attachments, links, activity feed ∪ comments with resolve, MarkdownEditor for comments/projects/:id/epics— epic list with progress bars (counts + points), status filter/projects/:id/epics/:epicId— epic detail: description, status, color, ordered issue list (drag to reorder, attach existing / create new)/projects/:id/wiki— page list;/projects/:id/wiki/:slug— view;/projects/:id/wiki/:slug/edit+/projects/:id/wiki/new— edit/create with preview/projects/:id/settings— tabs: general (fields, status, git URL, transfer, delete) | members | labels | webhooks (incoming secret, outgoing CRUD + delivery log) | export | danger zone — owner-gated tabs hidden for members/settings— tabs: profile | security (password) | tokens (PAT create/reveal-once/revoke) | notifications (email_mode)/admin/users— admin only: user list, admin toggle, delete- 404 page; project-scope 404s render "not found or no access"
Pinia stores
auth— me, bootstrap, login/logout, guardsprojects— list + current project (members, labels, dependencies)issues— table query state (filters/sort/page, URL-synced), detail cacheboard— per-status ordered lists, optimistic move (rank computed client-side between neighbors, PATCH sent, rollback on error)epics— list + detail + orderingcomments— per-issue comments + resolve statewiki— page list + current pagenotifications— unread count, inbox, mark-readrealtime— SSE connection state; routesdataframes: if the pointed-at resource is in an active store (current board/table/detail/feed), patch or refetch it;notificationframes →notificationsstore + toastsearch— palette state, recents (localStorage)ui— toasts, modals, sidebar collapse
Shared components
KanbanBoard/KanbanColumn/IssueCard— drag via vuedraggable or a small pointer-events implementation; column headers show countIssueTable+FilterBar(status/assignee/label/priority/epic pickers + text search) +SortHeaderMarkdownEditor— textarea + write/preview tabs,@mention autocomplete (project members),#issue autocomplete, paste/drop image → attachment uploadMarkdownView— markdown-it + DOMPurify, mention chips,#Nrouter-links, code highlightActivityFeed— renders audit entries (icon + actor + verb + target + relative time)NotificationBell— unread badge, dropdown of latest 10, link to/inboxCommandPalette— Cmd/Ctrl+K overlay (10-search.md)- Badges/pills:
StatusBadge(per-status colors),PriorityBadge,PointsBadge,LabelPill(label color),EpicPill(epic color) UserAvatar(initials fallback) +AssigneePicker+MemberPickerEpicProgressBar(counts + points tooltip)WatchButton,FavoriteStarAttachmentUploader(drag-drop zone) +AttachmentList(image preview, download, delete)DatePicker,ConfirmDialog,ToastHost,EmptyState(illustrated, per design system)
Behaviors
- Optimistic updates for board drags and inline status/assignee edits; rollback + toast on API error
- URL is the source of truth for table filters/sort (shareable, refresh-safe)
- SSE reconnect → refetch active page data + unread count (09-notifications-realtime.md)
- Keyboard: Cmd/Ctrl+K palette;
cnew issue on board/table pages; Esc closes modals - Every list has loading skeletons + designed empty states; destructive actions use
ConfirmDialog - Route titles set per page (
SoloPM — {project} — {page})