fleet/frontend/pages/admin/AdminWrapper.tsx
Scott Gress fe7be1833a
Update urls to use "fleets" and "reports" instead of "teams" and "queries" (#41084)
<!-- Add the related story/sub-task/bug number, like Resolves #123, or
remove if NA -->
**Related issue:** For #41030

# Details

This PR updates front-end routes and redirects the old routes to the new
ones.

While I typically have shied away from renaming vars and constants in
this phase of the renaming work, I chose to rename the path constants
here because they're a lot less useful when they have names that don't
correspond to the paths they're representing. I did the renames using
VSCode's "Rename Symbol" feature which automatically finds and fixes any
references. I then asked Claude to verify the changes and it didn't find
any dangling references (also the code would fail to compile unless all
the new names collided with old ones).

# Checklist for submitter

If some of the following don't apply, delete the relevant line.

- [ ] Changes file added for user-visible changes in `changes/`,
`orbit/changes/` or `ee/fleetd-chrome/changes`.
See [Changes
files](https://github.com/fleetdm/fleet/blob/main/docs/Contributing/guides/committing-changes.md#changes-files)
for more information.
n/a

## Testing

- [ ] Added/updated automated tests
no relevant tests exist
- [X] QA'd all new/changed functionality manually

## Reports (formerly Queries)

**New routes:**
- [x] /reports/manage — Reports list page
- [x] /reports/new — New report editor
- [x] /reports/new/live — New report live query
- [x] /reports/:id — Report details
- [x] /reports/:id/edit — Edit report
- [x] /reports/:id/live — Live report run

**Redirects from old routes:**
- [x] /queries → /reports
- [x] /queries/manage → /reports/manage
- [x] /queries/new → /reports/new
- [x] /queries/new/live → /reports/new/live
- [x] /queries/:id → /reports/:id
- [x] /queries/:id/edit → /reports/:id/edit
- [x] /queries/:id/live → /reports/:id/live

## Host Reports (formerly Host Queries)

**New routes:**
- [x] /hosts/:host_id/reports/:query_id — Host report results

**Redirects from old routes:**
- [ ] ~/hosts/:host_id/schedule → /hosts/:host_id/reports~ <- this is
not a real URL; removed current broken redirect
- [x] /hosts/:host_id/queries/:query_id →
/hosts/:host_id/reports/:query_id

## Fleets (formerly Teams)

**New routes:**
- [x] /settings/fleets — Fleets list page
- [x] /settings/fleets/users?fleet_id=:id — Fleet users
- [x] /settings/fleets/options?fleet_id=:id — Fleet agent options
- [x] /settings/fleets/settings?fleet_id=:id — Fleet settings

**Redirects from old routes:**
- [x] /settings/teams → /settings/fleets
- [x] /settings/teams/users → /settings/fleets/users
- [x] /settings/teams/options → /settings/fleets/options
- [x] /settings/teams/settings → /settings/fleets/settings
- [x] /settings/teams/:team_id → /settings/fleets
- [x] /settings/teams/:team_id/users → /settings/fleets
- [x] /settings/teams/:team_id/options → /settings/fleets

**Navigation & Links**

- [x] Top nav "Reports" link goes to /reports/manage
- [x] User menu team switcher navigates to
/settings/fleets/users?fleet_id=:id
- [x] Admin sidebar "Fleets" tab goes to /settings/fleets
- [x] "Create a fleet" links (user form, transfer host modal) go to
/settings/fleets
- [x] "Back to fleets" button on fleet details goes to /settings/fleets
- [x] Fleet table name links go to /settings/fleets/users?fleet_id=:id
- [x] Host details "Add query" button goes to /reports/new
- [x] Select query modal links go to /reports/new and /reports/:id/edit
- [x] Query report "full report" link goes to /reports/:id
- [x] Browser tab titles show correct names for report pages

**Query params preserved through redirects**

- [x] /queries/:id?fleet_id=1 → /reports/:id?fleet_id=1
- [x] /settings/teams/users?fleet_id=1 →
/settings/fleets/users?fleet_id=1

For unreleased bug fixes in a release candidate, one of:

- [X] Confirmed that the fix is not expected to adversely impact load
test results
2026-03-06 08:24:50 -06:00

107 lines
2.8 KiB
TypeScript

import React, { useContext } from "react";
import { Tab, Tabs, TabList } from "react-tabs";
import { InjectedRouter } from "react-router";
import PATHS from "router/paths";
import { AppContext } from "context/app";
import TabNav from "components/TabNav";
import MainContent from "components/MainContent";
import TabText from "components/TabText";
import classnames from "classnames";
interface ISettingSubNavItem {
name: string;
pathname: string;
exclude?: boolean;
}
interface ISettingsWrapperProp {
children: JSX.Element;
location: {
pathname: string;
};
router: InjectedRouter; // v3
}
const baseClass = "admin-wrapper";
const AdminWrapper = ({
children,
location: { pathname },
router,
}: ISettingsWrapperProp): JSX.Element => {
const { isPremiumTier, isSandboxMode } = useContext(AppContext);
const settingsSubNav: ISettingSubNavItem[] = [
{
name: "Organization settings",
pathname: PATHS.ADMIN_ORGANIZATION,
exclude: isSandboxMode,
},
{
name: "Integrations",
pathname: PATHS.ADMIN_INTEGRATIONS,
},
{
name: "Users",
pathname: PATHS.ADMIN_USERS,
exclude: isSandboxMode,
},
{
name: "Fleets",
pathname: PATHS.ADMIN_FLEETS,
exclude: !isPremiumTier,
},
];
const filteredSettingsSubNav = settingsSubNav.filter((navItem) => {
return !navItem.exclude;
});
const navigateToNav = (i: number): void => {
const navPath = filteredSettingsSubNav[i].pathname;
router.push(navPath);
};
const getTabIndex = (path: string): number => {
return filteredSettingsSubNav.findIndex((navItem) => {
// tab stays highlighted for paths that start with same pathname
return path.startsWith(navItem.pathname);
});
};
// we add a conditional sandbox-mode class here as we will need to make some
// styling changes on the settings page to have the sticky elements work
// with the sandbox mode expiry message
const classNames = classnames(baseClass, { "sandbox-mode": isSandboxMode });
return (
<MainContent className={classNames}>
<>
<h1 className="page-header">Settings</h1>
<TabNav>
<Tabs
selectedIndex={getTabIndex(pathname)}
onSelect={(i) => navigateToNav(i)}
>
<TabList>
{filteredSettingsSubNav.map((navItem) => {
// Bolding text when the tab is active causes a layout shift
// so we add a hidden pseudo element with the same text string
return (
<Tab key={navItem.name} data-text={navItem.name}>
<TabText>{navItem.name}</TabText>
</Tab>
);
})}
</TabList>
</Tabs>
</TabNav>
{children}
</>
</MainContent>
);
};
export default AdminWrapper;