diff --git a/changes/conf-6385-host-policy-table-fixes b/changes/conf-6385-host-policy-table-fixes new file mode 100644 index 0000000000..c61124d153 --- /dev/null +++ b/changes/conf-6385-host-policy-table-fixes @@ -0,0 +1 @@ +- Host policy table can be sortable by response and View all host link preserves the team diff --git a/frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx b/frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx index b052371d50..ed2d8ad85c 100644 --- a/frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx +++ b/frontend/pages/hosts/details/DeviceUserPage/DeviceUserPage.tsx @@ -471,6 +471,7 @@ const DeviceUserPage = ({ deviceUser togglePolicyDetailsModal={togglePolicyDetailsModal} hostPlatform={host?.platform || ""} + router={router} /> )} diff --git a/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx b/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx index 91ddf98ef4..d19575211f 100644 --- a/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx +++ b/frontend/pages/hosts/details/HostDetailsPage/HostDetailsPage.tsx @@ -903,6 +903,8 @@ const HostDetailsPage = ({ isLoading={isLoadingHost} togglePolicyDetailsModal={togglePolicyDetailsModal} hostPlatform={host.platform} + router={router} + currentTeamId={currentTeam?.id} /> diff --git a/frontend/pages/hosts/details/cards/Policies/HostPolicies.tsx b/frontend/pages/hosts/details/cards/Policies/HostPolicies.tsx index 53f91b5a9b..e3bb3550eb 100644 --- a/frontend/pages/hosts/details/cards/Policies/HostPolicies.tsx +++ b/frontend/pages/hosts/details/cards/Policies/HostPolicies.tsx @@ -1,7 +1,11 @@ -import React from "react"; +import React, { useCallback } from "react"; +import { InjectedRouter } from "react-router"; +import { Row } from "react-table"; +import { noop } from "lodash"; import { IHostPolicy } from "interfaces/policy"; -import { SUPPORT_LINK } from "utilities/constants"; +import { PolicyResponse, SUPPORT_LINK } from "utilities/constants"; +import { createHostsByPolicyPath } from "utilities/helpers"; import TableContainer from "components/TableContainer"; import EmptyTable from "components/EmptyTable"; import Card from "components/Card"; @@ -21,6 +25,15 @@ interface IPoliciesProps { deviceUser?: boolean; togglePolicyDetailsModal: (policy: IHostPolicy) => void; hostPlatform: string; + router: InjectedRouter; + currentTeamId?: number; +} + +interface IHostPoliciesRowProps extends Row { + original: { + id: number; + response: "pass" | "fail"; + }; } const Policies = ({ @@ -29,8 +42,13 @@ const Policies = ({ deviceUser, togglePolicyDetailsModal, hostPlatform, + router, + currentTeamId, }: IPoliciesProps): JSX.Element => { - const tableHeaders = generatePolicyTableHeaders(togglePolicyDetailsModal); + const tableHeaders = generatePolicyTableHeaders( + togglePolicyDetailsModal, + currentTeamId + ); if (deviceUser) { // Remove view all hosts link tableHeaders.pop(); @@ -38,6 +56,23 @@ const Policies = ({ const failingResponses: IHostPolicy[] = policies.filter((policy: IHostPolicy) => policy.response === "fail") || []; + const onClickRow = useCallback( + (row: IHostPoliciesRowProps) => { + const { id: policyId, response: policyResponse } = row.original; + + const viewAllHostPath = createHostsByPolicyPath( + policyId, + policyResponse === "pass" + ? PolicyResponse.PASSING + : PolicyResponse.FAILING, + currentTeamId + ); + + router.push(viewAllHostPath); + }, + [router] + ); + const renderHostPolicies = () => { if (hostPlatform === "ios" || hostPlatform === "ipados") { return ( @@ -83,14 +118,16 @@ const Policies = ({ columnConfigs={tableHeaders} data={generatePolicyDataSet(policies)} isLoading={isLoading} - manualSortBy - resultsTitle="policy items" + defaultSortHeader="response" + defaultSortDirection="asc" + resultsTitle="policies" emptyComponent={() => <>} showMarkAllPages={false} isAllPagesSelected={false} - disablePagination disableCount - disableMultiRowSelect + disableMultiRowSelect={!deviceUser} // Removes hover/click state if deviceUser + isClientSidePagination + onClickRow={deviceUser ? noop : onClickRow} /> ); diff --git a/frontend/pages/hosts/details/cards/Policies/HostPoliciesTable/HostPoliciesTableConfig.tsx b/frontend/pages/hosts/details/cards/Policies/HostPoliciesTable/HostPoliciesTableConfig.tsx index 5b2d19c6e7..96455ddad7 100644 --- a/frontend/pages/hosts/details/cards/Policies/HostPoliciesTable/HostPoliciesTableConfig.tsx +++ b/frontend/pages/hosts/details/cards/Policies/HostPoliciesTable/HostPoliciesTableConfig.tsx @@ -1,8 +1,11 @@ import React from "react"; -import StatusIndicatorWithIcon from "components/StatusIndicatorWithIcon"; -import Button from "components/buttons/Button"; + import { IHostPolicy } from "interfaces/policy"; import { PolicyResponse, DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants"; + +import StatusIndicatorWithIcon from "components/StatusIndicatorWithIcon"; +import Button from "components/buttons/Button"; +import HeaderCell from "components/TableContainer/DataTable/HeaderCell"; import ViewAllHostsLink from "components/ViewAllHostsLink"; import { IndicatorStatus } from "components/StatusIndicatorWithIcon/StatusIndicatorWithIcon"; @@ -42,7 +45,8 @@ interface IDataColumn { // NOTE: cellProps come from react-table // more info here https://react-table.tanstack.com/docs/api/useTable#cell-properties const generatePolicyTableHeaders = ( - togglePolicyDetails: (policy: IHostPolicy, teamId?: number) => void + togglePolicyDetails: (policy: IHostPolicy, teamId?: number) => void, + currentTeamId?: number ): IDataColumn[] => { const STATUS_CELL_VALUES: Record = { pass: { @@ -65,12 +69,17 @@ const generatePolicyTableHeaders = ( disableSortBy: true, Cell: (cellProps) => { const { name } = cellProps.row.original; + + const onClickPolicyName = (e: React.MouseEvent) => { + // Allows for button to be clickable in a clickable row + e.stopPropagation(); + togglePolicyDetails(cellProps.row.original); + }; + return (