mirror of
https://github.com/Sagit-chu/flvx.git
synced 2026-09-28 07:36:38 +08:00
f1bdb2e2ef
- Add dashboard auto-refresh with 5s polling and visibility-aware pause - Harden node realtime reconnection with exponential backoff and polling fallback - Implement local state patching for forward/tunnel/user mutations - Add batch operation progress feedback UI - Add shared list-state helpers for replace/remove operations - Preserve derived UI state during server payload merges Closes #276 Entire-Checkpoint: 7d6188355d7f
11 KiB
11 KiB
020 AJAX No-refresh UX
Objective
- Implement issue
#276as a focused frontend UX improvement initiative, not a full data-layer rewrite. - Keep the existing
axios + local React state + custom hooksarchitecture, and extend it with polling, realtime hardening, and local state patching where it improves responsiveness. - Deliver the work in phases so the highest-value improvements ship first: dashboard auto-refresh and node realtime resilience, then local list updates after mutations, then batch progress and search/filter polish.
Non-goals
- Do not introduce
@tanstack/react-query, SWR, or other new frontend data libraries for this issue. - Do not rewrite page architecture, routing, or modal flows that already submit asynchronously without browser reloads.
- Do not require backend changes unless a batch-progress requirement cannot be met with the current API surface.
- Do not change the raw JWT auth convention used by
vite-frontend/src/api/network.ts.
Current State
vite-frontend/src/pages/node/use-node-realtime.tsandvite-frontend/src/pages/node.tsxalready provide websocket-driven node status, system info, and upgrade progress updates.vite-frontend/src/pages/forward.tsx,vite-frontend/src/pages/tunnel.tsx,vite-frontend/src/pages/user.tsx, andvite-frontend/src/pages/node.tsxalready submit forms asynchronously, so the main remaining gap is consistency of post-submit local refresh behavior.vite-frontend/src/pages/dashboard/use-dashboard-data.tscurrently fetches dashboard data only once on mount, so traffic charts and counters do not auto-refresh.- Several mutation handlers still rely on page-level reload functions such as
loadData(),loadUsers(), orloadNodes()instead of patching only the changed records. - Batch progress UI exists for node upgrade but not for other batch actions such as forward and tunnel operations.
Design Principles
- Prefer local state patching after successful mutations when the changed record set is known.
- Prefer targeted refetches over full-page refetches when the server is the source of truth for a small dependent dataset.
- Use polling only where realtime transport does not already exist.
- Pause or reduce background refresh work when the page is hidden to avoid unnecessary traffic.
- Keep UI feedback explicit: loading states, toast feedback, and visible progress for long-running batch actions.
Checklist
- Refactor dashboard data loading into reusable refresh callbacks in
vite-frontend/src/pages/dashboard/use-dashboard-data.ts. - Add dashboard traffic polling with visibility-aware pause/resume and safe notification deduplication.
- Harden node realtime reconnection behavior in
vite-frontend/src/pages/node/use-node-realtime.tsand define a fallback refresh path if websocket recovery fails. - Add shared local-list patch helpers for replace/remove/upsert patterns used by page-level mutation handlers.
- Convert forward create/edit/delete/service-toggle flows in
vite-frontend/src/pages/forward.tsxfrom whole-page refetches to local or targeted updates where safe. - Convert tunnel create/edit/delete flows in
vite-frontend/src/pages/tunnel.tsxfrom whole-page refetches to local or targeted updates where safe. - Convert user create/edit/delete and user-tunnel permission mutation flows in
vite-frontend/src/pages/user.tsxto local or targeted updates where safe. - Extend batch action UX to show visible progress or staged feedback for forward and tunnel batch operations.
- Normalize search/filter behavior and document where client-side instant filtering is appropriate versus where server-side pagination must remain authoritative.
- Run focused frontend verification and record the result in this plan after implementation.
Implementation Plan
Phase 1 - Dashboard auto-refresh and node realtime resilience
1. Dashboard traffic/statistics auto-refresh
- Extract
loadPackageData()andloadAnnouncement()invite-frontend/src/pages/dashboard/use-dashboard-data.tsinto stable callbacks so the hook can refresh data without re-running the whole mount sequence. - Add a 5-second polling loop for package, flow, and chart data returned by
getUserPackageInfo(). - Keep announcement loading low-frequency or first-load only unless the API contract clearly expects live updates.
- Pause polling when
document.visibilityState !== "visible", then trigger an immediate refresh when the tab becomes visible again. - Preserve current loading UX for first load, but use a silent refresh path for polling so the page does not flicker.
2. Dashboard notification safety
- Audit
checkExpirationNotifications()invite-frontend/src/pages/dashboard/use-dashboard-data.tsso polling does not repeatedly emit expiration warnings. - Continue using notification deduplication, but base it on stable expiration identifiers rather than every poll cycle.
- Ensure refreshes that only change traffic counters do not retrigger expiry toasts.
3. Node realtime hardening
- Review
vite-frontend/src/pages/node/use-node-realtime.tsreconnect logic, which currently stops after a fixed retry budget. - Replace the hard stop with controlled backoff reconnect behavior, or explicitly trigger a degraded polling fallback once retry exhaustion is reached.
- If a fallback list refresh is introduced, merge incoming node metadata with existing
systemInfo,connectionStatus, and upgrade-progress state so live metrics are not wiped during recovery. - Keep the existing offline debounce behavior in
vite-frontend/src/pages/node/use-node-offline-timers.ts.
Phase 2 - Local mutation updates and partial refreshes
4. Shared list-patching helpers
- Add small reusable helpers for common state operations such as:
- replace one item by
id - remove one or many items by
id - upsert a created or updated item into an ordered list
- preserve derived UI-only fields during server payload merges
- replace one item by
- Keep these helpers local to the frontend codebase and avoid introducing a generic state-management abstraction.
5. Forward page partial refresh conversion
- Target
vite-frontend/src/pages/forward.tsxmutation handlers first because the page already contains some optimistic/local patterns. - Preserve the current local behavior for service toggles, but review rollback handling so final UI state matches backend truth after success or failure.
- Change create/edit/delete flows to patch
forwardsstate directly when the response payload is sufficient. - Use targeted refetches only when an operation changes dependent datasets that are not reliably derivable from the local page state.
- Re-check grouped ordering, collapsed-state persistence, and selected-row state after local mutations.
6. Tunnel page partial refresh conversion
- Update
vite-frontend/src/pages/tunnel.tsxso create/edit/delete mutatetunnelsstate directly instead of always callingloadData(). - Keep node reference data refresh separate from tunnel list refresh so a tunnel mutation does not force a full page data reload.
- Preserve existing drag-sort behavior and ensure local patching keeps
inxand stored order consistent.
7. User page partial refresh conversion
- Update
vite-frontend/src/pages/user.tsxso create/edit/delete patch theuserslist when the current page can be updated safely. - Update user-tunnel permission flows to patch
userTunnelsdirectly after assign, edit, remove, and flow-reset operations. - Respect server-side pagination semantics for the user list; if the server response does not provide enough data for a safe local patch, use a targeted page refetch rather than a full multi-dataset refresh.
- Keep current modal and toast behavior unchanged unless the local update path exposes stale-state issues.
Phase 3 - Batch progress UX and search/filter polish
8. Batch progress UX
- Use the node upgrade progress model in
vite-frontend/src/pages/node.tsxas the UI reference for long-running operations. - Review
vite-frontend/src/pages/forward/batch-actions.tsand tunnel batch handlers to determine whether current APIs expose enough intermediate state for real progress. - If only final summary APIs are available, implement staged client-side progress feedback such as
processing X/Y, current action label, success count, and failure count. - If the UX requirement cannot be met without backend support, document the missing backend contract and split the work into frontend and backend follow-ups.
9. Search and filter responsiveness
- Preserve instant client-side filtering on pages that already hold the authoritative dataset locally, including node, tunnel, and forward pages.
- Audit the user page separately because it depends on server-side pagination and keyword search.
- If user-page instant filtering is desired, choose one of two explicit strategies:
- keep server-side pagination authoritative and add debounce for keyword-triggered requests, or
- load a larger local dataset only if product requirements accept the cost.
- Do not silently mix partial client filtering with incomplete paginated datasets.
Risks and Mitigations
- Repeated dashboard polling may spam expiry toasts.
- Mitigation: deduplicate notifications based on expiration identity and only emit on meaningful state changes.
- Node recovery refreshes may wipe websocket-derived metrics.
- Mitigation: merge fetched node metadata into existing live state instead of replacing the whole record blindly.
- Local mutation patching may desynchronize grouped, sorted, or selected views.
- Mitigation: patch canonical source arrays first, then recompute derived memoized groupings from state.
- Batch APIs may not expose progress details.
- Mitigation: implement client-side staged progress where possible and document backend gaps where not.
- User-page local updates may conflict with pagination semantics.
- Mitigation: prefer targeted page refetch over unsafe optimistic filtering or cross-page list mutation.
Verification Plan
- Dashboard:
- Open
dashboardand confirm traffic counters and chart data refresh at least once every 5 seconds without manual reload. - Confirm hidden-tab pause and visible-tab immediate refresh behavior.
- Confirm expiry toasts do not repeat on every polling cycle.
- Open
- Nodes:
- Confirm websocket-driven online/offline transitions still work.
- Simulate websocket interruption and verify reconnect or fallback refresh behavior.
- Confirm recovery does not clear existing live metrics unexpectedly.
- Forwards, tunnels, users:
- Create, edit, delete, enable, disable, and reset flows without browser reload.
- Confirm the affected rows update immediately and other unrelated rows stay stable.
- Confirm selection state, ordering, and modal close behavior remain correct after local patching.
- Batch actions:
- Confirm visible progress or staged status feedback exists during long-running operations.
- Confirm success and failure summaries remain accurate after completion.
- Build:
- Run
cd vite-frontend && npm run build.
- Run
Rollout Notes
- Ship Phase 1 first because it matches the issue approval priority and provides the clearest user-visible gain.
- Keep each phase in reviewable commits so regressions in local list patching can be isolated quickly.
- If backend support becomes necessary for real batch progress, land the frontend scaffolding separately and track the backend dependency explicitly.
Test Record
- Command:
cd vite-frontend && npm install - Result: passed.
- Command:
cd vite-frontend && npm run build - Result: passed.