Commit Graph

24 Commits

Author SHA1 Message Date
josh d8785a964d Merge SERVICE role into AGENT
Build & Push / Test (client) (push) Successful in 31s
Build & Push / Test (server) (push) Successful in 38s
Build & Push / Build Client (push) Successful in 1m17s
Build & Push / Build Server (push) Successful in 1m18s
Every AGENT now gets an auto-generated API key on creation, shown once
in a modal. AGENTs log in with password and authenticate to the API
with X-Api-Key. pre-push.sql defensively migrates any residual SERVICE
rows to AGENT before Prisma rewrites the enum. Goddard is no longer
baked into the seed — create agents via Admin → Users.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 22:44:32 -04:00
josh b341c64b02 Install root deps in Docker build so shared schemas resolve zod
Build & Push / Test (client) (push) Successful in 21s
Build & Push / Test (server) (push) Successful in 35s
Build & Push / Build Client (push) Successful in 1m12s
Build & Push / Build Server (push) Successful in 1m8s
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 17:19:45 -04:00
josh 8c2139f6a6 Remove deprecated baseUrl from client tsconfig
Build & Push / Test (client) (push) Failing after 7m24s
Build & Push / Build Client (push) Has been skipped
Build & Push / Test (server) (push) Failing after 31s
Build & Push / Build Server (push) Has been skipped
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 16:45:09 -04:00
josh ef22e92ac8 Phase 4: power UX (palette, shortcuts, mentions, mobile, PWA)
Command palette (cmd+K) with fuzzy nav, ticket search, people lookup
and action entries (new ticket, logout, show shortcuts). Opens from
keyboard or user dropdown.

Global keyboard shortcuts via a small useShortcut/useLeaderShortcut
hook: `?` help overlay, `c` new ticket, `g d|t|m|n|s` leader nav.
Tickets list: j/k cursor, Enter open, x toggle select. TicketDetail:
`e` edit, `r` focus comment composer. All guarded against firing
inside text fields.

@mention autocomplete in the comment composer (MentionTextarea) with
arrow-key nav and Tab/Enter insert. Rendered comments and audit log
rewrite @username tokens to links pointing at that user's assignee
filter; unknown usernames left as plain text.

Mobile sweep: TicketDetail sidebar stacks below content on <md,
Settings profile grid collapses to one column, admin tables get
horizontal scroll with a 640px min width, CTI 3-column grid stacks
vertically on <md, New ticket severity/assignee grid same.

PWA: manifest.webmanifest, SVG icon, minimal network-first service
worker for the app shell (never caches /api/*), registered in
production builds only. Theme-color meta + manifest link in index.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 16:36:28 -04:00
josh 4bade22410 Phase 3: UI redesign (Gitea-issues aesthetic)
Top-nav Layout replaces side-nav: brand, primary nav, global search
(debounced /search), notifications bell (Popover + unread badge),
user avatar DropdownMenu. Mobile hamburger collapse.

New pages:
- /dashboard: analytics home (open-by-severity, age buckets, queue
  load, median resolution)
- /tickets: Gitea-style list with status tabs, severity/assignee/CTI
  filters, server pagination (25/page), multi-select bulk bar
  (reassign/close/severity), saved views CRUD
- /notifications: full list with mark-all-read
- /settings: profile, notification prefs grid, API key (SERVICE role)
- /admin/webhooks: CRUD + rotate-secret + active toggle,
  reveal-once secret dialog

TicketDetail: inline Popover editing for Status/Severity/Assignee
(replaces modal chain), AlertDialog delete confirmation, comment
draft autosave to localStorage per ticket.

Admin Users: window.confirm swapped for AlertDialog on delete +
rotate API key with toast feedback.

React Query hooks added for paged tickets, bulk actions,
notifications, webhooks, saved views, analytics, notification prefs.
ThemeProvider wired (v1.0 ships dark-only; toggle deferred).

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 16:20:28 -04:00
josh 77679922a8 Phase 1d: react-hook-form + zod on Login and NewTicket
- Both forms use useForm with zodResolver against shared schemas
  (loginSchema, createTicketSchema)
- Field-level errors rendered inline under inputs
- isSubmitting drives button disabled state
- NewTicket: severity registered with valueAsNumber; CTISelect wrapped in
  nested Controllers (one per categoryId/typeId/itemId) since it controls
  three form fields as a single compound input
- Admin forms stay on useState for now — they get redesigned with shadcn
  dialogs in Phase 3, RHF migration lands with that

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 15:35:29 -04:00
josh 17697ecf3b Phase 1c: shadcn/ui primitives + CSS-variable theme tokens
- components.json, @/* path alias in tsconfig + vite config
- Tailwind config: CSS-variable-backed color tokens, animation plugin
- index.css: :root (light) and .dark token blocks (slate base) — currently
  pinned to dark via class on <html> so visual appearance is unchanged
- src/lib/utils.ts: cn() helper (clsx + tailwind-merge)
- src/components/ui/: 16 primitives — button, input, label, textarea, badge,
  avatar, separator, skeleton, dialog, dropdown-menu, select, tabs, tooltip,
  sonner, alert-dialog, popover
- Nothing replaced yet; existing components still in place. Used in Phase 3.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 15:35:19 -04:00
josh 4eae11b5b0 Phase 1b: React Query + Vitest on client
- @tanstack/react-query v5 with QueryClientProvider at app root
- client/src/api/queries.ts: query-key factory, hooks for tickets, ticket, audit,
  comments, users, CTI tree + cascade, plus full mutation set
  (create/update/delete ticket, add/delete comment, CTI CRUD, user CRUD)
- All page-level useEffect + useState fetching replaced:
  Dashboard, MyTickets, TicketDetail, NewTicket, admin/CTI, admin/Users
- Dashboard preserves 300ms debounced search via separate debouncedSearch state
- CTISelect cascades via useCategories / useTypes(categoryId) / useItems(typeId);
  dependent hooks disabled until parent selected
- vitest + @testing-library/react + jsdom; 6 client tests cover SeverityBadge + StatusBadge

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
2026-04-18 15:35:09 -04:00
josh 27d2ab0f0d Add ESLint + Prettier + EditorConfig tooling at repo root
v1.0 Phase 1.1 — repo-wide lint/format baseline.

- eslint.config.mjs (flat config) lints server, client, shared
- .prettierrc.json, .prettierignore, .editorconfig, .nvmrc
- Root package.json holds shared devDeps; per-package scripts keep
  their typecheck + test runners
- Fix 7 lint issues surfaced by the baseline run:
  - TicketDetail.tsx: replace ternary-with-side-effects with if/else
  - admin/Users.tsx: escape apostrophe in JSX
  - errorHandler.ts: typed err as unknown with ErrorLike refinement
  - users.ts: Prisma.UserUpdateInput instead of Record<string, any>
  - seed.ts: drop unused goddard binding
- Run prettier across tracked sources for a clean formatting baseline
2026-04-18 14:47:34 -04:00
Josh Wright 2a6090e473 Redesign comments to GitHub/Gitea style
Build & Push / TypeScript Check (client) (push) Successful in 14s
Build & Push / Build Server (push) Successful in 36s
Build & Push / Build Client (push) Successful in 33s
- Each comment is a bordered card with a distinct header bar (author name,
  clickable relative timestamp, hover-to-reveal delete) and a body section
- Subtle spine line connects comments in the avatar column
- Composer matches card style: same header bar for Write/Preview tabs,
  transparent textarea inside, submit row with border-top
- Comment timestamps default to relative, click to toggle absolute
  (mirrors sidebar date toggle pattern)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 12:38:36 -04:00
Josh Wright 8bea999b93 Remove /tickets prefix from ticket detail URLs
Build & Push / TypeScript Check (client) (push) Successful in 15s
Build & Push / Build Server (push) Successful in 42s
Build & Push / Build Client (push) Successful in 35s
Routes and links now use /:id (e.g. /V675409888) instead of /tickets/:id.
API calls are unaffected as they go through /api/tickets/.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 12:30:10 -04:00
Josh Wright 8c86ad7bb8 Move edit pencil to title card top-right; hide Actions card for non-admins
Build & Push / TypeScript Check (client) (push) Successful in 14s
Build & Push / Build Server (push) Successful in 34s
Build & Push / Build Client (push) Successful in 33s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 12:24:53 -04:00
Josh Wright e6c2298ac2 Remove unused SidebarField; add CI typecheck job before client Docker build
Build & Push / Build Server (push) Has been cancelled
Build & Push / Build Client (push) Has been cancelled
Build & Push / TypeScript Check (client) (push) Has been cancelled
- Delete the now-unused SidebarField component from TicketDetail.tsx
- Add typecheck-client CI job that runs tsc --noEmit on the client before
  the Docker build, so TypeScript errors surface fast with a clear message
- build-client now depends on typecheck-client passing

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 12:14:48 -04:00
Josh Wright 618a9136f6 Toggle date fields between relative and absolute on click
Build & Push / Build Server (push) Successful in 34s
Build & Push / Build Client (push) Failing after 26s
Defaults to relative time (e.g. '5 hours ago'); clicking switches to
absolute timestamp and back.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 12:10:12 -04:00
Josh Wright 2638eb226b Remove unused selectClass constant
Build & Push / Build Server (push) Successful in 43s
Build & Push / Build Client (push) Successful in 36s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 12:06:41 -04:00
Josh Wright 402de82750 Unify sidebar fields: all editable fields use full-width clickable blocks
Build & Push / Build Server (push) Successful in 51s
Build & Push / Build Client (push) Failing after 26s
- Status and Severity now match CTI style (full-width button, hover bg, no chevron)
- Remove 'Change routing' hint text from CTI block
- Replace Assignee dropdown with clickable block that opens a modal picker with avatars
- Add Assignee modal consistent with Status/Severity modal pattern

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 12:03:39 -04:00
Josh Wright 44e5e2d373 Redesign ticket sidebar: modal pickers for status/severity, CTI as clickable unit
Build & Push / Build Server (push) Successful in 44s
Build & Push / Build Client (push) Successful in 37s
- Rename 'Details' card to 'Ticket Summary'
- Replace status/severity dropdowns with badge displays that open small modal pickers on click
- Show Category, Type, Issue as separate labeled rows that together act as one clickable unit opening the routing modal
- Reorganize into sections: status/severity, CTI routing, dates (created/modified/resolved), people (assignee + requester)
- Add Requester field showing the ticket creator with avatar

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-31 11:56:53 -04:00
josh 2b76ad27b1 Reroute ticket via modal instead of inline sidebar expansion
Build & Push / Build Client (push) Successful in 37s
Build & Push / Build Server (push) Successful in 51s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 23:40:28 -04:00
josh d751e36ae8 Fix My Tickets and queue filter
Build & Push / Build Server (push) Successful in 58s
Build & Push / Build Client (push) Successful in 41s
- My Tickets: exclude RESOLVED and CLOSED, show active tickets only
- Queue filter: cascading Category > Type > Item picker — each leaf is
  a distinct queue (e.g. TheWrightServer > Automation > Backup vs Sync)
- Server: support typeId and itemId as ticket list filter params

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 23:35:33 -04:00
josh 725f91578d Dark theme, roles overhaul, modal New Ticket, My Tickets page, and more
Build & Push / Build Server (push) Successful in 2m5s
Build & Push / Build Client (push) Successful in 41s
- Dark UI across all pages and components (gray-950/900/800 palette)
- New Ticket is now a centered modal (triggered from sidebar), not a separate page
- Add USER role: view and comment only; AGENT and SERVICE can create/edit tickets
- Only admins can set ticket status to CLOSED (enforced server + UI)
- Add My Tickets page (/my-tickets) showing tickets assigned to current user
- Add queue (category) filter to Dashboard
- Audit log entries are clickable to expand detail; comment body shown as markdown
- Resolved date now includes time (HH:mm) in ticket sidebar
- Store comment body in audit log detail for COMMENT_ADDED and COMMENT_DELETED
- Clarify role descriptions in Admin Users modal
- Remove CI/CD section from README; add full API reference documentation

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 23:17:14 -04:00
josh d8dc5b3ded Full-page ticket layout: two-column with sticky sidebar
Build & Push / Build Server (push) Successful in 1m26s
Build & Push / Build Client (push) Successful in 39s
Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 21:21:46 -04:00
josh f65c259a71 Ticket IDs, audit log, markdown comments, tabbed detail page
- Tickets get a random display ID (V + 9 digits, e.g. V325813929)
- Ticket detail page has Overview / Comments / Audit Log tabs
- Audit log records every action (create, status, assignee, severity,
  reroute, title/overview edit, comment add/delete) with who and when
- Comments redesigned: avatar (initials + color), markdown rendering
  via react-markdown + remark-gfm, Write/Preview toggle
- Dashboard shows displayId and assignee avatar
- URLs now use displayId (/tickets/V325813929)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 20:53:37 -04:00
josh e7ecf210e0 Add package-lock.json for reproducible Docker builds
Build & Push / Build Server (push) Failing after 24s
Build & Push / Build Client (push) Successful in 44s
npm ci in the Dockerfiles requires committed lockfiles.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 19:43:43 -04:00
josh 21894fad7a Initial commit: TicketingSystem
Build & Push / Build Client (push) Failing after 9s
Build & Push / Build Server (push) Failing after 28s
Internal ticketing app with CTI routing, severity levels, and n8n integration.

Stack: Express + TypeScript + Prisma + PostgreSQL / React + Vite + Tailwind
- JWT auth for users, API key auth for service accounts (Goddard/n8n)
- CTI hierarchy (Category > Type > Item) for ticket routing
- Severity 1-5, auto-close resolved tickets after 14 days
- Gitea Actions CI/CD building separate server/client images
- Production docker-compose.yml with Traefik integration

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-03-30 19:38:32 -04:00