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}`;