Routing & Layouts
FT Configs UI uses TanStack Router with file-based routing. The route tree is generated at build time by @tanstack/router-plugin into src/routeTree.gen.ts from files under src/routes/**.
Layout hierarchy
Layouts are expressed as pathless layout routes (files prefixed with _).
-
src/routes/__root.tsx— root route created viacreateRootRoute(). Wraps children in<Suspense fallback={<FullPageSpinner/>}><Outlet/></Suspense>. Global providers (I18nProvider,QueryProvider,AuthProvider,RouterProvider,<Toaster/>) live insrc/main.tsx/App.tsx, not in the route file. -
src/routes/_auth.tsx—AuthLayoutfor public pages (flex-centered shell). -
src/routes/_protected.tsx—ProtectedLayout. Performs the auth guard viauseAuth(): if!isAuthenticated && !isLoading, it callsuseNavigate('/login', { replace: true }). It also blocks any route whose path matchesDISABLED_ROUTE_PREFIXESby redirecting to/. -
src/routes/_protected/settings/_admin.tsx— admin sub-layout. Wraps its children inAdminSettingsGuard(role check) and mountsAdminRolesProviderlocally (not globally).
The auth guard is implemented at the component level, not via TanStack Router’s beforeLoad. beforeLoad executes outside the React render tree against a frozen snapshot of context, so it cannot wait for AuthProvider to finish its initial refreshSession() call. The component-level guard is the standard SPA pattern documented in the migration plan and is the correct trade-off for this codebase.
|
beforeLoad is used for static redirects that do not depend on auth state — e.g. /dashboard → /, /settings → /settings/profile. Throw redirect({ to: '…' }) from beforeLoad for those cases.
|
Route tree
Source: src/routes/**. The following tree mirrors the generated routeTree.gen.ts.
src/routes/
├── __root.tsx # Root: Suspense + Outlet + FullPageSpinner
├── index.tsx # '/' — HomePage (application chooser, lazy)
│
├── _auth.tsx # Public layout
│ ├── _auth/login.tsx # '/login'
│ ├── _auth/register.tsx # '/register'
│ └── _auth/change-password.tsx # '/change-password'
│
└── _protected.tsx # Protected layout + auth guard
├── _protected/dashboard.tsx # '/dashboard' → beforeLoad redirects to '/'
│
├── _protected/settings/
│ ├── index.tsx # '/settings' → redirect to SETTINGS_PROFILE
│ ├── profile.tsx # '/settings/profile'
│ └── _admin.tsx # Admin sub-layout (AdminSettingsGuard + AdminRolesProvider)
│ ├── _admin/users.tsx # '/settings/users'
│ ├── _admin/security.tsx # '/settings/security'
│ └── _admin/audit-log.tsx # '/settings/audit-log'
│
├── _protected/acs/ # 11+ modules: bulk-data, configuration, dashboard,
│ # ctn-info, external-trace, fcc-config, force-qoe-stop,
│ # ftacs-task-config, ftacsws-access, hardcoded-event,
│ # parameter-names-cache, set-parameter-result-template
│
├── _protected/angular/ # 18+ modules: app-ports, columns, cube-dsl-parameters,
│ # custom-params, dashboard, device-activities,
│ # device-monitoring, frames, interface-items, mesh,
│ # neighboring-wifi-diagnostic-paths,
│ # network-device-param-mappings, network-map,
│ # replace-services, rpc-methods, simplified-view,
│ # snmp-configuration, tab-view, tabs, user-info, voip
│
├── _protected/provision-portal/ # 8 modules: index, configuration, csv-settings,
│ # custom-status, objects, params, replace-cpe, statuses
│
├── _protected/northbound.tsx # '/northbound'
└── _protected/service-api.tsx # '/service-api'
High-level route map
Route path constants are centralized in src/lib/constants.ts (APP_ROUTES).
-
/— home (application chooser) -
/login,/register,/change-password— public auth pages -
/dashboard— redirects to/(beforeLoadthrowsredirect) -
/acs/*— ACS configuration and bulk-data modules -
/angular/*— Angular Console dictionary modules -
/provision-portal/*— Provision Portal modules -
/northbound— Northbound Config editor -
/service-api— Service API configuration -
/settings/profile— user preferences -
/settings/users,/settings/security,/settings/audit-log— admin-only (ADMIN role)
Dynamic routes
TanStack Router uses $param.tsx for dynamic segments (e.g. _protected/replace-services/$id.tsx). Inside the route component, read params via Route.useParams(), typed search params via Route.useSearch() with a validateSearch schema.
| Some detail/edit routes are implemented as redirects to list pages with query parameters (example: Replace Services). This pattern is unchanged from the previous implementation — only the routing primitives differ. |