Skip to content

Convert the Inventory screen route trees to react-router v6 Routes - #421

Merged
cigamit merged 10 commits into
ctrliq:mainfrom
blaipr:feature/react-router-inventory
Jun 16, 2026
Merged

Convert the Inventory screen route trees to react-router v6 Routes#421
cigamit merged 10 commits into
ctrliq:mainfrom
blaipr:feature/react-router-inventory

Conversation

@blaipr

@blaipr blaipr commented Jun 14, 2026

Copy link
Copy Markdown
Contributor
SUMMARY

Continues the react-router v5 → v6 route-tree migration. Converts the Inventory screen - the largest remaining screen family (16 nested route trees) - from the v5 <Switch>/<Route>/<Redirect> API to v6 <Routes>/<Route> via react-router-dom-v5-compat. Done as a single PR with several commits.

UI (no behavior change - same URLs, same panels). Each route tree keeps its absolute /inventories/... paths, so it resolves correctly regardless of conversion order; every route that delegates to a nested screen gets a trailing /*; useRouteMatch is replaced with useParams + an explicit base url; exact <Redirect>s (and the inventory-kind mismatch redirects) become <Navigate>.

Converted (15 of the 16 trees):

  • Hosts: AdvancedInventoryHost(s), InventoryHosts, InventoryHost, InventoryHostGroups
  • Groups: InventoryGroups, InventoryGroup, InventoryGroupHosts, InventoryRelatedGroups
  • Sources: InventorySources (the list)
  • Inventory-type details: Inventory, SmartInventory, ConstructedInventory, FederatedInventory
  • Dispatcher: Inventories.js (delegates each inventory-type detail with /*)

Deferred (1 tree):

  • InventorySource (the source detail) renders the shared Schedules component, so it stays on v5 here and is handled with the shared-Schedules cluster. Its v5 <Switch> keeps working under the now-v6 InventorySources parent because it matches the absolute location.
ISSUE TYPE
  • Bug, Docs Fix or other nominal change
COMPONENT NAME
  • UI
ADDITIONAL INFORMATION
  • Part of the incremental react-router v6 migration; converting the Inventory screen as one PR rather than many small PRs.
  • Tests: full screens/Inventory directory passes (76 suites / 345 tests). A couple of tests needed updates (drop conflicting hoisted useParams module mocks and mount under the real v6 route; stub the inventory list / mount at /inventories); the rest pass unchanged because the routes keep absolute paths. npm --prefix awx/ui run lint clean on the changed source.

blaipr added 5 commits June 14, 2026 17:17
First batch of the Inventory screen migration to react-router v6.

- AdvancedInventoryHost: <Switch> -> <Routes>; useRouteMatch is replaced
  with useParams (inventoryType, hostId) and an explicit hostBaseUrl;
  the exact <Redirect> becomes a <Route> that <Navigate>s to details;
  not-found kept as path="*".
- AdvancedInventoryHosts: <Switch> -> <Routes>; the host detail route
  gets a trailing /* so the nested <AdvancedInventoryHost> tree matches.

Both keep absolute /inventories/:inventoryType/:id/hosts paths, so they
resolve under the still-v5 Inventory parents; existing tests pass
unchanged.
Second batch of the Inventory screen migration: the standard inventory
host subtree.

- InventoryHosts: <Switch> -> <Routes>; host add/list use element; the
  host detail route gets /* to delegate to <InventoryHost>.
- InventoryHost: <Switch> -> <Routes>; useRouteMatch replaced with
  useParams (hostId) + an explicit hostBaseUrl; exact <Redirect> becomes
  a <Route> Navigate to details; the groups tab delegates with groups/*;
  not-found kept as path="*".
- InventoryHostGroups: <Switch> -> <Routes> keeping its absolute
  /inventories/inventory/:id/hosts/:hostId/groups path.

All keep absolute paths, so they resolve under the still-v5 Inventory
parents and existing tests pass unchanged.
Third batch of the Inventory screen migration: the inventory group
subtree.

- InventoryGroups: <Switch> -> <Routes>; group add/list use element; the
  group detail route gets /* to delegate to <InventoryGroup>.
- InventoryGroup: <Switch> -> <Routes>; exact <Redirect> becomes a
  <Route> Navigate to details (built from the useParams inventoryType/
  inventoryId/groupId); the nested_hosts and nested_groups tabs delegate
  with /*; not-found kept as path="*".
- InventoryGroupHosts / InventoryRelatedGroups: <Switch> -> <Routes>
  keeping their absolute nested_hosts / nested_groups paths.
- InventoryGroup.test.js: drop the conflicting hoisted useParams module
  mocks and mount under the real v6 /inventories/:inventoryType/:id/
  groups/:groupId/* route so params resolve from the URL.

All keep absolute paths, so they resolve under the still-v5 Inventory
parents.
…outes

Fourth batch of the Inventory screen migration: the standard inventory
detail and its sources subtree.

- Inventory.js: <Switch> -> <Routes>; useRouteMatch replaced with
  useParams (id) + an explicit inventoryBaseUrl; the exact <Redirect>
  and the kind-mismatch <Redirect> become <Navigate>; the groups/hosts/
  sources tabs delegate with /*; details/access/edit/jobs/job_templates
  use the element prop; not-found kept as path="*".
- InventorySources: <Switch> -> <Routes>; the source detail route gets
  /* to delegate to the (still-v5) <InventorySource> - its v5 Switch
  matches the absolute location, so it keeps working until it is
  converted with the shared Schedules cluster.

All keep absolute paths.
Final Inventory batch: the smart/constructed/federated inventory detail
screens and the top-level Inventories dispatcher.

- SmartInventory, ConstructedInventory, FederatedInventory: <Switch> ->
  <Routes>; useRouteMatch replaced with useParams + an explicit base
  url; the exact <Redirect> and the kind-mismatch <Redirect> become
  <Navigate>; the hosts and groups tabs delegate with /*; not-found
  kept as path="*".
- Inventories.js: <Switch> -> <Routes>; the add routes use the element
  prop; each inventory-type detail route gets /* so its nested <Routes>
  resolves.
- Inventories.test.js: mount at /inventories and stub InventoryList so
  the list route renders without an API call.

Only the InventorySource detail remains on v5 (it renders the shared
Schedules component and is handled with the Schedules cluster).

Copilot AI left a comment

Copy link
Copy Markdown
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pull request overview

Migrates the Inventory screen’s route trees from react-router v5 (<Switch>/<Route>/<Redirect>) to react-router v6-style routing (<Routes>/<Route>/<Navigate>) using react-router-dom-v5-compat, while preserving the existing absolute /inventories/... URL structure and nested route behavior.

Changes:

  • Converted Inventory detail screens (Inventory / Smart / Constructed / Federated) to <Routes> and replaced v5 redirects with <Navigate replace>.
  • Updated nested Inventory subtrees (hosts, groups, sources, related groups, etc.) to use v6 routing patterns, including /* where delegation to nested route trees is required.
  • Updated tests to mount components under real v6-compatible routes and to stub inventory listing where needed.

Reviewed changes

Copilot reviewed 17 out of 17 changed files in this pull request and generated 1 comment.

Show a summary per file
File Description
awx/ui/src/screens/Inventory/SmartInventory.js Converts Smart Inventory detail routing to <Routes>/<Navigate> and replaces useRouteMatch with useParams + explicit base URL.
awx/ui/src/screens/Inventory/InventorySources/InventorySources.js Converts sources route tree to <Routes>, adding /* delegation for the nested InventorySource subtree.
awx/ui/src/screens/Inventory/InventoryRelatedGroups/InventoryRelatedGroups.js Converts related-groups subtree routing to <Routes>.
awx/ui/src/screens/Inventory/InventoryHosts/InventoryHosts.js Converts hosts subtree routing to <Routes>, adding /* delegation for nested host detail routes.
awx/ui/src/screens/Inventory/InventoryHostGroups/InventoryHostGroups.js Converts host-groups subtree routing to <Routes>.
awx/ui/src/screens/Inventory/InventoryHost/InventoryHost.js Converts inventory host detail routing to <Routes>/<Navigate> and switches from useRouteMatch to useParams.
awx/ui/src/screens/Inventory/InventoryGroups/InventoryGroups.js Converts groups subtree routing to <Routes>, adding /* delegation for nested group detail routes.
awx/ui/src/screens/Inventory/InventoryGroupHosts/InventoryGroupHosts.js Converts group-hosts subtree routing to <Routes>.
awx/ui/src/screens/Inventory/InventoryGroup/InventoryGroup.test.js Updates tests to mount under a real v6-compatible route so useParams resolves from the URL.
awx/ui/src/screens/Inventory/InventoryGroup/InventoryGroup.js Converts group detail routing to <Routes>/<Navigate> and replaces v5 redirect behavior.
awx/ui/src/screens/Inventory/Inventory.js Converts standard Inventory detail routing to <Routes>/<Navigate> and switches from useRouteMatch to useParams.
awx/ui/src/screens/Inventory/Inventories.test.js Adjusts test mounting to /inventories and stubs the list so the route can render without API calls.
awx/ui/src/screens/Inventory/Inventories.js Converts the top-level Inventories dispatcher routing to <Routes> and adds /* delegation for each inventory detail screen.
awx/ui/src/screens/Inventory/FederatedInventory.js Converts Federated Inventory detail routing to <Routes>/<Navigate> and switches from useRouteMatch to useParams.
awx/ui/src/screens/Inventory/ConstructedInventory.js Converts Constructed Inventory detail routing to <Routes>/<Navigate> and switches from useRouteMatch to useParams.
awx/ui/src/screens/Inventory/AdvancedInventoryHosts/AdvancedInventoryHosts.js Converts advanced-hosts subtree routing to <Routes>, adding /* delegation for nested host detail routes.
awx/ui/src/screens/Inventory/AdvancedInventoryHost/AdvancedInventoryHost.js Converts advanced host detail routing to <Routes>/<Navigate> and replaces useRouteMatch with useParams + explicit base URL.

Comment thread awx/ui/src/screens/Inventory/InventoryGroup/InventoryGroup.js
The fallback 'View Inventory Details' link built a literal
'/inventories/:inventoryType/...' path, which navigates to a non-existent
URL. Interpolate inventoryType from useParams() so the link resolves.
@blaipr

blaipr commented Jun 14, 2026

Copy link
Copy Markdown
Contributor Author

Thanks for the review. Fixed in b5d5370139: the not-found link built a literal /inventories/:inventoryType/... segment; it now interpolates inventoryType from useParams so the link resolves.

@cigamit cigamit added the Needs triage When a Issue needs to be researched or a PR has an issue that needs fixing before merging label Jun 15, 2026
@cigamit

cigamit commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

There is an issue with this one. Clicking on an inventory, all tabs (Details, Access, Groups, etc..) throw the error
"The page you requested could not be found."

image

blaipr added 2 commits June 15, 2026 18:56
cigamit reported that clicking an inventory threw 'page not found' on every
tab. The dispatcher (Inventories.js) was converted to v6 (path "...:id/*"),
which makes each detail screen's <Routes> a descendant whose paths resolve
relative to the parent match. The screens used ABSOLUTE paths
(/inventories/inventory/:id/details), so nothing matched and everything fell
through to the not-found route.

- Convert the whole Inventory subtree to relative route paths (matching the
  merged Application screen), with index routes for the bare-:id redirects.
- Route inventory detail through a single /inventories/:inventoryType/:id/*
  entry so inventoryType is a real route param again (the nested group/host
  screens read it via useParams to build links); a small type-router picks
  the right detail screen by kind.
- Update the isolated tests to mount each screen under its v6 parent route
  (they were mounting top-level, which is exactly why the regression slipped
  through), and add a dispatcher-level test that a detail tab resolves rather
  than falling through to not-found.
InventorySource is mounted as a descendant of the v6 inventory route tree
(Inventory -> InventorySources via sources/* -> InventorySource via
:sourceId/*), but it was still a v5 <Switch> with relative path strings, which
v5 cannot match. Its tabs and the schedules sub-route fell through to the
not-found route. Convert it to v6 <Routes>: read :sourceId via useParams,
build URLs from inventory.id, use relative <Route> elements, and mount
<Schedules> under schedules/* so its nested route tree resolves.
@cigamit

cigamit commented Jun 15, 2026

Copy link
Copy Markdown
Contributor

Details and a few other pages now work, but still getting errors when clicking on Groups, Hosts, or Sources in an inventory

Page not found at /api/v2/inventories/undefined/ad_hoc_commands/
Page not found at /api/v2/inventories/undefined/hosts/
Page not found at /api/v2/inventories/undefined/inventory_sources/
Page not found at /api/v2/inventories/undefined/groups/

image

blaipr added 2 commits June 15, 2026 21:53
cigamit reported that opening a schedule's details fails. <Schedules> is
mounted by the parent screens via a ".../schedules/*" route, so it is a v6
descendant; it (and <Schedule>) built absolute baseUrl/pathRoot-derived
route paths, which do not match in that descendant context, so the
add/detail/edit routes never resolved.

Use relative route paths (add, :scheduleId/*, index in Schedules; index ->
details, details, edit in Schedule). The pathRoot-derived absolute values
are kept only for the tab/breadcrumb Links, not the route paths. Mount the
Schedules test under its parent route.

(cherry picked from commit 4dd8df0)
The Inventory route tree is now v6, but its leaf components (lists, detail,
add/edit, list items) still read :id / :inventoryType / :groupId / :hostId
through react-router v5 useParams, which returns nothing inside a v6 <Routes>
tree. As a result the Hosts, Groups and Sources tabs fetched
/api/v2/inventories/undefined/... and rendered a not-found error.

Read those params from react-router-dom-v5-compat in all 16 affected
components, and drop the now-empty useRouteMatch().url in InventoryList in
favor of the fixed /inventories base. Update the tests to mount each component
under a real v6 route that supplies the params instead of mocking the router,
so they exercise the actual routing.
@blaipr

blaipr commented Jun 15, 2026

Copy link
Copy Markdown
Contributor Author

Pushed a fix for the Groups/Hosts/Sources errors you hit (the /api/v2/inventories/undefined/... calls).

Root cause: the inventory route tree is v6 now, but its leaf components (the lists, detail, add/edit and list-item components) were still reading :id / :inventoryType / :groupId through react-router v5 useParams, which returns nothing inside a v6 Routes tree. So the id came through as undefined and the API calls 404'd.

Changes:

  • Read those params from react-router-dom-v5-compat in the 16 affected leaf components.
  • Also pulled in the v6 shared Schedule component so the inventory source Schedules tab resolves.
  • Reworked the tests to mount each component under a real v6 route instead of mocking the router, so they exercise the actual routing.

Verified in a local browser against real data: Details, Access, Groups, Hosts, Sources, the inventory list, and the inventory source Schedules list and detail all load correctly now.

@cigamit
cigamit merged commit 752823f into ctrliq:main Jun 16, 2026
@cigamit cigamit self-assigned this Jun 18, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

Needs triage When a Issue needs to be researched or a PR has an issue that needs fixing before merging

Development

Successfully merging this pull request may close these issues.

3 participants