diff --git a/frontend/pages/ManageControlsPage/ManageControlsPage.tsx b/frontend/pages/ManageControlsPage/ManageControlsPage.tsx
index 5d95de538c..32d9613b11 100644
--- a/frontend/pages/ManageControlsPage/ManageControlsPage.tsx
+++ b/frontend/pages/ManageControlsPage/ManageControlsPage.tsx
@@ -9,6 +9,7 @@ import useTeamIdParam from "hooks/useTeamIdParam";
import TabsWrapper from "components/TabsWrapper";
import MainContent from "components/MainContent";
import TeamsDropdown from "components/TeamsDropdown";
+import { parseOSUpdatesCurrentVersionsQueryParams } from "./OSUpdates/components/CurrentVersionSection/CurrentVersionSection";
interface IControlsSubNavItem {
name: string;
@@ -43,6 +44,8 @@ interface IManageControlsPageProps {
query: {
team_id?: string;
page?: string;
+ order_key?: string;
+ order_direction?: "asc" | "desc";
};
};
router: InjectedRouter; // v3
@@ -121,7 +124,11 @@ const ManageControlsPage = ({
- {React.cloneElement(children, { teamIdForApi, currentPage: page })}
+ {React.cloneElement(children, {
+ teamIdForApi,
+ currentPage: page,
+ queryParams: parseOSUpdatesCurrentVersionsQueryParams(location.query),
+ })}
);
};
diff --git a/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/_styles.scss b/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/_styles.scss
index cb9b50f1f0..81c563065c 100644
--- a/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/_styles.scss
+++ b/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/_styles.scss
@@ -101,10 +101,6 @@
gap: $pad-small;
}
- &__profile-graphic--message {
- text-align: center;
- }
-
&__button-wrap {
display: flex;
justify-content: flex-end;
diff --git a/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/components/ProfileUploader/components/AddProfileModal/_styles.scss b/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/components/ProfileUploader/components/AddProfileModal/_styles.scss
index 261799fe73..222268e7db 100644
--- a/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/components/ProfileUploader/components/AddProfileModal/_styles.scss
+++ b/frontend/pages/ManageControlsPage/OSSettings/cards/CustomSettings/components/ProfileUploader/components/AddProfileModal/_styles.scss
@@ -59,6 +59,10 @@
gap: $pad-small;
}
+ &__profile-graphic--message {
+ text-align: center;
+ }
+
&__button-wrap {
display: flex;
justify-content: flex-end;
diff --git a/frontend/pages/ManageControlsPage/OSSettings/cards/DiskEncryption/components/DiskEncryptionTable/_styles.scss b/frontend/pages/ManageControlsPage/OSSettings/cards/DiskEncryption/components/DiskEncryptionTable/_styles.scss
index 4b9fe65d32..74a24f3ac2 100644
--- a/frontend/pages/ManageControlsPage/OSSettings/cards/DiskEncryption/components/DiskEncryptionTable/_styles.scss
+++ b/frontend/pages/ManageControlsPage/OSSettings/cards/DiskEncryption/components/DiskEncryptionTable/_styles.scss
@@ -9,7 +9,7 @@
border-right: none;
}
- @media (max-width: $break-md) {
+ @media (max-width: 1120px) {
.view-hosts-link {
span {
display: none;
diff --git a/frontend/pages/ManageControlsPage/OSUpdates/OSUpdates.tsx b/frontend/pages/ManageControlsPage/OSUpdates/OSUpdates.tsx
index e18a4afca2..e56450775a 100644
--- a/frontend/pages/ManageControlsPage/OSUpdates/OSUpdates.tsx
+++ b/frontend/pages/ManageControlsPage/OSUpdates/OSUpdates.tsx
@@ -17,6 +17,7 @@ import NudgePreview from "./components/NudgePreview";
import TurnOnMdmMessage from "../components/TurnOnMdmMessage/TurnOnMdmMessage";
import CurrentVersionSection from "./components/CurrentVersionSection";
import TargetSection from "./components/TargetSection";
+import { parseOSUpdatesCurrentVersionsQueryParams } from "./components/CurrentVersionSection/CurrentVersionSection";
export type OSUpdatesSupportedPlatform =
| "darwin"
@@ -42,9 +43,10 @@ const getSelectedPlatform = (
interface IOSUpdates {
router: InjectedRouter;
teamIdForApi: number;
+ queryParams: ReturnType;
}
-const OSUpdates = ({ router, teamIdForApi }: IOSUpdates) => {
+const OSUpdates = ({ router, teamIdForApi, queryParams }: IOSUpdates) => {
const { isPremiumTier, config, setConfig } = useContext(AppContext);
const [
@@ -113,7 +115,11 @@ const OSUpdates = ({ router, teamIdForApi }: IOSUpdates) => {
-
+
;
}
+const DEFAULT_SORT_DIRECTION = "desc";
+const DEFAULT_SORT_HEADER = "hosts_count";
+const DEFAULT_PAGE = 0;
+const DEFAULT_PAGE_SIZE = 8;
+
+export const parseOSUpdatesCurrentVersionsQueryParams = (queryParams: {
+ page?: string;
+ order_key?: string;
+ order_direction?: "asc" | "desc";
+}) => {
+ const sortHeader = queryParams?.order_key ?? DEFAULT_SORT_HEADER;
+ const sortDirection = queryParams?.order_direction ?? DEFAULT_SORT_DIRECTION;
+ const page = queryParams?.page
+ ? parseInt(queryParams.page, 10)
+ : DEFAULT_PAGE;
+ const pageSize = DEFAULT_PAGE_SIZE;
+
+ return {
+ page,
+ order_key: sortHeader,
+ order_direction: sortDirection,
+ per_page: pageSize,
+ };
+};
+
const CurrentVersionSection = ({
+ router,
currentTeamId,
+ queryParams,
}: ICurrentVersionSectionProps) => {
const { data, isError, isLoading: isLoadingOsVersions } = useQuery<
IOSVersionsResponse,
AxiosError
>(
- ["os_versions", currentTeamId],
- () => getOSVersions({ teamId: currentTeamId }),
+ ["os_versions", currentTeamId, queryParams],
+ () => getOSVersions({ teamId: currentTeamId, ...queryParams }),
{
retry: false,
refetchOnWindowFocus: false,
@@ -91,9 +121,11 @@ const CurrentVersionSection = ({
return (
);
};
diff --git a/frontend/pages/ManageControlsPage/OSUpdates/components/OSVersionTable/OSVersionTable.tsx b/frontend/pages/ManageControlsPage/OSUpdates/components/OSVersionTable/OSVersionTable.tsx
index 372430e0c0..b71e546fd0 100644
--- a/frontend/pages/ManageControlsPage/OSUpdates/components/OSVersionTable/OSVersionTable.tsx
+++ b/frontend/pages/ManageControlsPage/OSUpdates/components/OSVersionTable/OSVersionTable.tsx
@@ -1,30 +1,92 @@
-import React from "react";
+import React, { useCallback } from "react";
+import { InjectedRouter } from "react-router";
+import PATHS from "router/paths";
import { IOperatingSystemVersion } from "interfaces/operating_system";
+import { getNextLocationPath } from "utilities/helpers";
+import { ITableQueryData } from "components/TableContainer/TableContainer";
import TableContainer from "components/TableContainer";
import { generateTableHeaders } from "./OSVersionTableConfig";
import OSVersionsEmptyState from "../OSVersionsEmptyState";
+import { parseOSUpdatesCurrentVersionsQueryParams } from "../CurrentVersionSection/CurrentVersionSection";
const baseClass = "os-version-table";
interface IOSVersionTableProps {
+ router: InjectedRouter;
osVersionData: IOperatingSystemVersion[];
currentTeamId: number;
isLoading: boolean;
+ queryParams: ReturnType;
}
-const DEFAULT_SORT_HEADER = "hosts_count";
-const DEFAULT_SORT_DIRECTION = "desc";
-
const OSVersionTable = ({
+ router,
osVersionData,
currentTeamId,
isLoading,
+ queryParams,
}: IOSVersionTableProps) => {
const columns = generateTableHeaders(currentTeamId);
+ const determineQueryParamChange = useCallback(
+ (newTableQuery: ITableQueryData) => {
+ const changedEntry = Object.entries(newTableQuery).find(([key, val]) => {
+ switch (key) {
+ case "sortDirection":
+ return val !== queryParams.order_direction;
+ case "sortHeader":
+ return val !== queryParams.order_key;
+ case "pageIndex":
+ return val !== queryParams.page;
+ default:
+ return false;
+ }
+ });
+ return changedEntry?.[0] ?? "";
+ },
+ [queryParams.order_direction, queryParams.order_key, queryParams.page]
+ );
+
+ const generateNewQueryParams = useCallback(
+ (newTableQuery: ITableQueryData, changedParam: string) => {
+ const newQueryParam: Record = {
+ team_id: currentTeamId,
+ order_direction: newTableQuery.sortDirection,
+ order_key: newTableQuery.sortHeader,
+ page: changedParam === "pageIndex" ? newTableQuery.pageIndex : 0,
+ };
+
+ return newQueryParam;
+ },
+ [currentTeamId]
+ );
+ // NOTE: this is called once on initial render and every time the query changes
+ const onQueryChange = useCallback(
+ (newTableQuery: ITableQueryData) => {
+ // we want to determine which query param has changed in order to
+ // reset the page index to 0 if any other param has changed.
+ const changedParam = determineQueryParamChange(newTableQuery);
+
+ // if nothing has changed, don't update the route. this can happen when
+ // this handler is called on the inital render. Can also happen when
+ // the filter dropdown is changed. That is handled on the onChange handler
+ // for the dropdown.
+ if (changedParam === "") return;
+
+ const newRoute = getNextLocationPath({
+ pathPrefix: PATHS.CONTROLS_OS_UPDATES,
+ routeTemplate: "",
+ queryParams: generateNewQueryParams(newTableQuery, changedParam),
+ });
+
+ router.replace(newRoute);
+ },
+ [determineQueryParamChange, generateNewQueryParams, router]
+ );
+
return (
);