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>
- 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>