Change overflow-hidden to overflow-auto in table wrapper classNames
across all list pages (rules, tunnels, nodes, limits, groups, users,
monitor views). Also add table-fixed min-w to forward all-rules table
and fix unescaped entities in dashboard.
* docs: add announcement popup design spec
* docs: add announcement popup implementation plan
* fix(ui): change modal scroll behavior to inside for mobile screens
Fixes layout issue where modal footer and action buttons are pushed off screen on mobile devices.
- Add NodeMetric/TunnelMetric/ServiceMonitor models and repository methods
- Implement metrics ingestion service with per-minute bucket aggregation
- Add health checker for node connectivity monitoring
- Wire node metrics from WebSocket SystemInfo messages
- Add tunnel metrics ingestion from flow upload endpoint
- Create monitoring REST API endpoints for nodes, tunnels, services
- Implement service monitor CRUD and execution (TCP/ICMP checks)
- Add MonitorPermission for non-admin access control
- Create frontend monitor page with node/tunnel/service views
- Add tunnel metrics ingestion from agent flow reports
- Include schema migration for tunnel_metric unique index
- Fix tunnel entry port conflict validation to use transaction
Entire-Checkpoint: 030821a7c8e3
Restore the 2.1.8-beta9 style of displaying node remark and renewal
info via an info button (ℹ️) in the CardHeader with a hover popover,
instead of inline display in the CardBody.
- Add infoPopoverPlacement state and updateInfoPopoverPlacement callback
- Add info button with hover popover showing expiry reminder and remark
- Restore drag handle with touch support and responsive visibility
- Remove inline info display from CardBody
- Add isIndeterminate support to Checkbox component
- Use showAddressModal in SortableTableRow for multi-address display
- Remove unused onClose parameter in search modal
- Remove unused infoPopoverPlacement and related code in node.tsx
- Move {...props} before onCloseAutoFocus to prevent override
- Simplify handler to just e.preventDefault()
- Apply fix to both dialog.tsx and modal.tsx
Changed info popover position calculation to use the card container
as reference instead of viewport, ensuring consistent placement within
card boundaries.
* feat(nodes): add renewal cycle and auto-advance scheduling
- Add renewal_cycle field to nodes for tracking paid vs free cycles
- Implement auto-advance scheduling when renewal is processed
- Add migration test for renewal_cycle column
- Update dashboard to show renewal cycle count
- Add renewal status display on node detail page
* fix(frontend): show rule count in compact view mode for forward pages
* style(frontend): format code and improve node card layout
Entire-Checkpoint: 08b760b76538
* fix: restore renewal.ts from main to resolve build errors
- Add renewal_cycle field to nodes for tracking paid vs free cycles
- Implement auto-advance scheduling when renewal is processed
- Add migration test for renewal_cycle column
- Update dashboard to show renewal cycle count
- Add renewal status display on node detail page
- Add extra_ips field to nodes for multi-IP servers
- Add connect_ip field to chain_tunnel for specifying connection address
- Add in_ip field to forward_port for specifying listen address
- Frontend: add UI controls for extra IPs on node form
- Frontend: add connect IP input for tunnel chain nodes
- Frontend: add listen IP input for forward form
- Backend: resolve forward ingress with custom listen IP priority
Entire-Checkpoint: 557563462c16
Use an overflow wrapper with an inner min-w-full flex row so controls stay visually right-aligned when space is sufficient, while Android can still horizontally swipe when the toolbar overflows.
Switch mobile batch toolbar alignment to start and enable horizontal pan gestures so overflow actions remain reachable on Android while desktop right alignment stays unchanged.
Switching batch controls to the top-right action bar with stable single-row layout improves clarity and prevents visual jumps while entering batch mode.
* feat(frontend): persist filter state across page reloads
Add useLocalStorageState hook to persist filter/search state in
forward, node, tunnel, user, and limit pages. Reset filter clears
the persisted value from localStorage.
* feat(ui): add collapsible sidebar and smooth animations