From 90197d83ae3c3e13353264c1daec3c03e33c3e1d Mon Sep 17 00:00:00 2001 From: Juan Fernandez Date: Tue, 6 Jun 2023 06:46:46 -0400 Subject: [PATCH] Bug 11525: Fixed navigation issues on 'My Device' page (#12102) Fixed navigation on DeviceUserPage Tab components. --- changes/11525-bug-software-table-device-page | 1 + .../DeviceUserPage/DeviceUserPage.tests.tsx | 36 ++++++++++++++++- .../details/DeviceUserPage/DeviceUserPage.tsx | 40 +++++++++++++++++-- .../HostDetailsPage/HostDetailsPage.tsx | 2 +- .../hosts/details/cards/Software/Software.tsx | 30 +++++++------- frontend/router/index.tsx | 11 ++++- frontend/router/paths.ts | 6 +++ 7 files changed, 103 insertions(+), 23 deletions(-) create mode 100644 changes/11525-bug-software-table-device-page diff --git a/changes/11525-bug-software-table-device-page b/changes/11525-bug-software-table-device-page new file mode 100644 index 0000000000..184a8d2a70 --- /dev/null +++ b/changes/11525-bug-software-table-device-page @@ -0,0 +1 @@ +- Fixed bug with page navigation inside 'My Device' page. diff --git a/frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tests.tsx b/frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tests.tsx index 17098ae14a..facfb4b2c1 100644 --- a/frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tests.tsx +++ b/frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tests.tsx @@ -8,6 +8,30 @@ import { createCustomRenderer } from "test/test-utils"; import { customDeviceHandler } from "test/handlers/device-handler"; import DeviceUserPage from "./DeviceUserPage"; +const mockRouter = { + push: jest.fn(), + replace: jest.fn(), + goBack: jest.fn(), + goForward: jest.fn(), + go: jest.fn(), + setRouteLeaveHook: jest.fn(), + isActive: jest.fn(), + createHref: jest.fn(), + createPath: jest.fn(), +}; + +const mockLocation = { + pathname: "", + query: { + vulnerable: undefined, + page: undefined, + query: undefined, + order_key: undefined, + order_direction: undefined, + }, + search: undefined, +}; + describe("Device User Page", () => { it("renders the software empty message if the device has no software", async () => { const render = createCustomRenderer({ @@ -16,7 +40,11 @@ describe("Device User Page", () => { // TODO: fix return type from render const { user } = render( - + ); // waiting for the device data to render @@ -37,7 +65,11 @@ describe("Device User Page", () => { }); const { user } = await render( - + ); // waiting for the device data to render diff --git a/frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx b/frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx index 41e41c1c7e..4136810aa7 100644 --- a/frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx +++ b/frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx @@ -1,9 +1,9 @@ import React, { useState, useContext, useCallback } from "react"; -import { Params } from "react-router/lib/Router"; +import { InjectedRouter, Params } from "react-router/lib/Router"; import { useQuery } from "react-query"; import { Tab, Tabs, TabList, TabPanel } from "react-tabs"; -import { pick } from "lodash"; +import { pick, findIndex } from "lodash"; import { NotificationContext } from "context/notification"; import deviceUserAPI from "services/entities/device_user"; @@ -28,6 +28,7 @@ import { wrapFleetHelper, humanHostDiskEncryptionEnabled, } from "utilities/helpers"; +import PATHS from "router/paths"; import HostSummaryCard from "../cards/HostSummary"; import AboutCard from "../cards/About"; @@ -47,6 +48,18 @@ import BootstrapPackageModal from "../HostDetailsPage/modals/BootstrapPackageMod const baseClass = "device-user"; interface IDeviceUserPageProps { + location: { + pathname: string; + query: { + vulnerable?: string; + page?: string; + query?: string; + order_key?: string; + order_direction?: "asc" | "desc"; + }; + search?: string; + }; + router: InjectedRouter; params: Params; } @@ -56,9 +69,12 @@ interface IHostDiskEncryptionProps { } const DeviceUserPage = ({ + location, + router, params: { device_auth_token }, }: IDeviceUserPageProps): JSX.Element => { const deviceAuthToken = device_auth_token; + const queryParams = location.query; const { renderFlash } = useContext(NotificationContext); const [isPremiumTier, setIsPremiumTier] = useState(false); @@ -347,6 +363,15 @@ const DeviceUserPage = ({ host?.mdm.macos_settings?.disk_encryption === "action_required" && host?.mdm.macos_settings?.action_required === "rotate_key"; + const tabPaths = [ + PATHS.DEVICE_USER_DETAILS(deviceAuthToken), + PATHS.DEVICE_USER_DETAILS_SOFTWARE(deviceAuthToken), + PATHS.DEVICE_USER_DETAILS_POLICIES(deviceAuthToken), + ]; + + const findSelectedTab = (pathname: string) => + findIndex(tabPaths, (x) => x.startsWith(pathname.split("?")[0])); + return (
{isLoadingHost ? ( @@ -394,7 +419,10 @@ const DeviceUserPage = ({ deviceUser /> - + router.push(tabPaths[i])} + > Details Software @@ -419,11 +447,15 @@ const DeviceUserPage = ({ {isPremiumTier && ( diff --git a/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx b/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx index d157aee2fc..f3fd4f5f78 100644 --- a/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx +++ b/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx @@ -746,8 +746,8 @@ const HostDetailsPage = ({ router={router} queryParams={queryParams} routeTemplate={routeTemplate} - hostId={host?.id || 0} pathname={pathname} + pathPrefix={PATHS.HOST_SOFTWARE(host?.id || 0)} /> {host?.platform === "darwin" && macadmins && ( { const { isSandboxMode, setFilteredSoftwarePath } = useContext(AppContext); @@ -118,8 +118,9 @@ const SoftwareTable = ({ ) { newQueryParams.page = 0; } + const locationPath = getNextLocationPath({ - pathPrefix: PATHS.HOST_SOFTWARE(hostId), + pathPrefix, routeTemplate, queryParams: newQueryParams, }); @@ -132,7 +133,7 @@ const SoftwareTable = ({ const onClientSidePaginationChange = useCallback( (pageIndex: number) => { const locationPath = getNextLocationPath({ - pathPrefix: PATHS.HOST_SOFTWARE(hostId), + pathPrefix, routeTemplate, queryParams: { ...queryParams, @@ -163,17 +164,16 @@ const SoftwareTable = ({ ); const handleVulnFilterDropdownChange = (isFilterVulnerable: string) => { - router?.replace( - getNextLocationPath({ - pathPrefix: PATHS.HOST_SOFTWARE(hostId), - routeTemplate, - queryParams: { - ...queryParams, - page: 0, - vulnerable: isFilterVulnerable, - }, - }) - ); + const nextPath = getNextLocationPath({ + pathPrefix, + routeTemplate, + queryParams: { + ...queryParams, + page: 0, + vulnerable: isFilterVulnerable, + }, + }); + router?.replace(nextPath); }; const handleRowSelect = (row: IRowProps) => { diff --git a/frontend/router/index.tsx b/frontend/router/index.tsx index be7c931329..9c4013adfa 100644 --- a/frontend/router/index.tsx +++ b/frontend/router/index.tsx @@ -231,7 +231,16 @@ const routes = ( /> - + + + + + + + + + + diff --git a/frontend/router/paths.ts b/frontend/router/paths.ts index 949a00182c..15d899a916 100644 --- a/frontend/router/paths.ts +++ b/frontend/router/paths.ts @@ -75,6 +75,12 @@ export default { DEVICE_USER_DETAILS: (deviceAuthToken: any): string => { return `${URL_PREFIX}/device/${deviceAuthToken}`; }, + DEVICE_USER_DETAILS_SOFTWARE: (deviceAuthToken: string): string => { + return `${URL_PREFIX}/device/${deviceAuthToken}/software`; + }, + DEVICE_USER_DETAILS_POLICIES: (deviceAuthToken: string): string => { + return `${URL_PREFIX}/device/${deviceAuthToken}/policies`; + }, MANAGE_SOFTWARE: `${URL_PREFIX}/software/manage`, SOFTWARE_DETAILS: (id: string): string => { return `${URL_PREFIX}/software/${id}`;