The onUp handler was capturing stale widgets from the render closure,
overwriting the resize dimensions. Now uses setWidgets(current => ...)
to read latest state and apply overlap resolution correctly.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
When resizing a widget, any widget that gets overlapped is automatically
pushed down to clear the collision. Multi-pass overlap detection ensures
cascading widgets are all resolved. Positions persisted to API.
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Edit/Done toggle button in header (pencil icon)
- Widget delete buttons only visible in edit mode
- Add widget button only visible in edit mode
- Empty state prompts to enter edit mode instead of adding directly
- Default is view mode — clean, no accidental deletes
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Dropdown to assign/unassign dashboard to a team
- Updates immediately via PATCH
- createDashboard and updateDashboard API now accept team_id
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
Schema:
- teams table (name unique, description)
- team_members table (team_id, user_id, unique constraint)
- team_id column on dashboards
API:
- GET/POST/PATCH/DELETE /teams
- POST /teams/:id/members (add user)
- DELETE /teams/:id/members/:userId (remove user)
- dashboards support team_id on create/update
Frontend:
- Teams tab in admin: CRUD + member management with add/remove
- Sidebar: dashboards filtered to user's teams
(unassigned dashboards visible to all)
- Compact dashboard picker dropdown in sidebar
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
- Single-line select dropdown instead of one list item per dashboard
- Scales to any number of teams without clutter
- "+ New dashboard" as last option in dropdown
- Preserves the create flow with inline name input
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>
- DELETE /templates/:id — backend route
- deleteTemplate() API client function
- Trash icon on each template list item (shows on hover)
- Confirms inline, no dialog needed
- Resets builder if the deleted template was being edited
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>
- Show CF values as read-only text with edit affordance (pencil icon on hover)
- Click to enter edit mode: inline input (free-text) or select (choice fields)
- Save on blur or Enter, cancel on Escape — reverts to original value
- Auto-save for select fields on change
- Loading spinner while saving
- Remove now-unused customFieldValue helper
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>
Backend:
- POST /:id/comment endpoint accepting {body, internal?, creator_id?}
- internal=false → Correspond (public reply), internal=true → Comment
- Runs scrip engine on the new transaction so notifications fire
- CommentSchema zod validation
Frontend:
- sendComment() API function in lib/api.ts
- Send button wired with onClick, sending spinner, disabled state
- Error display below reply box, clears on new typing
- Refreshes transaction list after successful send
- Reply/Internal note mode passed as internal flag
- 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.
- layout.tsx: ThemeProvider from next-themes, light mode DEFAULT, JetBrains_Mono font
- globals.css: font-mono pointing to correct variable, font-feature-settings cv01+ss03 on body
- next-themes package installed
- Build passes with zero errors