- table-layout: fixed with minWidth instead of width:100% to avoid
browser recalculating explicit column widths
- Wider resize handles (w-3, 12px) for easier grabbing
- Better visibility on hover
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- table-layout: fixed on the table wrapper so browser respects explicit widths
- All cells (header + rows) now use the same col.width consistently
- Subject column no longer special-cased for width
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Left column gets wider, right column gets narrower by same amount.
Subject column now has fixed width (not flexible) so the table
doesn't redistribute space unpredictably.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Handle on the left edge resizes the PREVIOUS column, not itself.
This matches the mental model: dragging the boundary between Subject
and Status changes Subject's width. First column has no handle.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Handles now sit on the left edge (the boundary between columns).
Dragging feels natural — you pull the dividing line between two columns.
Wider hit area (w-2) for easier grabbing.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Replaced flex containers with display: table/table-row/table-cell.
This guarantees column widths are shared between header and all rows,
fixing the misalignment. Subject column gets remaining width, all
others use fixed pixel widths. Resize handles on header cells still work.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Column header was missing the w-9 spacer that ticket rows have
for the batch checkbox. Added spacer so columns align properly.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Checkbox column on every ticket row
- Select multiple tickets via checkboxes
- Floating sticky action bar at bottom when tickets selected:
- Shows count: "3 selected" with Clear button
- Quick status change buttons
- Assign to me button
- Checkbox click stops propagation (doesn't select ticket for triage panel)
- Batch operations run sequentially via API
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Column config saves to localStorage on every change
- Load from localStorage on mount (survive reloads without saved view)
- Custom fields appear as column options in picker
- Custom field values render in ticket rows
- Backend now always includes custom_fields in GET /tickets response
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Column picker dropdown (grid icon next to sort/density)
- Check/uncheck columns: ID, Subject, Status, Queue, Owner, Created, Updated
- Subject column auto-expands (flex), others have fixed width
- Column resize handles: drag right edge of any column header
- Min 50px, max 800px, body gets select-none during drag
- Columns persist with saved views (columns jsonb field)
- Reset to defaults when navigating away from a saved view
- Sticky column header row with muted background
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Fix sidebar All tickets link: /?view=all instead of / (avoids dashboard redirect)
- Replace useless side panel with triage command center:
- Quick status change buttons (click to transition inline)
- Assign to me button (appears when unassigned)
- Mini activity feed showing last 8 transactions with type labels,
status badges, old→new values, and comment previews
- Relative timestamps
- Open full view button
- Fetches ticket transactions on selection
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Backend:
- team_id column on tickets table
- team_id filter in GET /tickets (resolves team members)
- team_id in UpdateTicketSchema + PATCH handler
- SetTeam transaction type
Frontend:
- Team selector in ticket detail properties sidebar
- My team's tickets in sidebar (when user belongs to a team)
- team_id passed through to API from ticket list page
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Popover now renders via createPortal into document.body with z-index 9999
- This avoids the header backdrop-blur stacking context trapping it
- Add + button in Dashboards sidebar section to create dashboards
- Inline input on Dashboards section header, Enter to create/Escape to cancel
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Add demo dashboard with 7 widgets to seed script
- Dashboard is_default=true — appears as home page on fresh seed
- Add views/dashboards/dashboardWidgets to seed reset
- Fix My tickets: now filters by first non-system user (not any owner)
- Pass owner param in sidebar My tickets link
- Update page.tsx view=my to respect owner URL param
- Scrip engine already sorts by sort_order (verified)
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Move ticket filtering from in-memory to SQL WHERE clauses
(queue_id, status, owner use Drizzle eq/isNull; text search uses ilike;
custom field filters use EXISTS subqueries)
- Add limit param to GET /tickets
- Add POST/PATCH/DELETE /users routes
- Add Users tab to admin page with create/edit/delete
- Smart widget positioning in dashboard (3-column grid fill)
- Show pattern hint below CF inputs in New Ticket dialog
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Fixed popover z-index: uses fixed positioning with z-50 above backdrop
- Stepped flow: select field → set operator (is/is_not) → choose/write value → Apply
- Removed old inline CF value inputs (handled inline in the new flow)
- Fixed filter persistence: clear filters when navigating away from saved view
- Fixed home redirect: check for default dashboard on load
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- POST /tickets now returns { ticket, scrip_results } matching PATCH pattern
- createTicket API function returns UpdateResult instead of Ticket
- Update call site to use data.ticket.id
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Remove three-column layout, inline detail panel, and properties sidebar
- Click a ticket navigates to /tickets/[id] via router.push
- Redesign TicketRow as inbox-style: status dot, bold subject on top line,
muted ID/queue/owner meta on second line, time right-aligned
- Cleaner visual hierarchy with increased padding and gap
Backend returns PascalCase (Create, StatusChange, SetOwner, Comment, Correspond).
Frontend was checking lowercase, causing transaction rendering to fall through to raw type strings.