mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
Macos settings hosts filter (#10385)
## Addresses #9597 <img width="1121" alt="Screenshot 2023-03-09 at 2 03 58 PM" src="https://user-images.githubusercontent.com/61553566/224170878-00a1ba60-6477-4c4b-8582-d1711e8b0181.png"> ## Notes The UI for "No teams" filtered state will be implemented in the **Frontend** portion of #10409 ## Checklist - [x] Manual QA - [x] Updated testing inventory or added tests - [x] Change file --------- Co-authored-by: Jacob Shandling <jacob@fleetdm.com>
This commit is contained in:
parent
c4fa0393af
commit
81c732f34d
5 changed files with 106 additions and 10 deletions
3
changes/9567-macos_settings-hosts-filter
Normal file
3
changes/9567-macos_settings-hosts-filter
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
* Add ability to filter data under the Hosts tab by the aggregate status of hosts' MDM-managed macos
|
||||
settings. This filter is used when clicking Controls > macOS settings > "# hosts" under Latest,
|
||||
Pending, or Failing.
|
||||
|
|
@ -13,6 +13,7 @@ import globalPoliciesAPI from "services/entities/global_policies";
|
|||
import hostsAPI, {
|
||||
ILoadHostsOptions,
|
||||
ISortOption,
|
||||
MacSettingsStatusQueryParam,
|
||||
} from "services/entities/hosts";
|
||||
import hostCountAPI, {
|
||||
IHostCountLoadOptions,
|
||||
|
|
@ -73,6 +74,7 @@ import {
|
|||
DEFAULT_SORT_DIRECTION,
|
||||
DEFAULT_PAGE_SIZE,
|
||||
HOST_SELECT_STATUSES,
|
||||
MAC_SETTINGS_FILTER_OPTIONS,
|
||||
} from "./constants";
|
||||
import { isAcceptableStatus, getNextLocationPath } from "./helpers";
|
||||
import DeleteSecretModal from "../../../components/EnrollSecrets/DeleteSecretModal";
|
||||
|
|
@ -242,6 +244,7 @@ const ManageHostsPage = ({
|
|||
const routeTemplate = route?.path ?? "";
|
||||
const policyId = queryParams?.policy_id;
|
||||
const policyResponse: PolicyResponse = queryParams?.policy_response;
|
||||
const macSettingsStatus = queryParams?.macos_settings;
|
||||
const softwareId =
|
||||
queryParams?.software_id !== undefined
|
||||
? parseInt(queryParams.software_id, 10)
|
||||
|
|
@ -421,25 +424,20 @@ const ManageHostsPage = ({
|
|||
setIsHostsLoading(true);
|
||||
options = {
|
||||
...options,
|
||||
teamId: currentTeam?.id,
|
||||
teamId: queryParams.team_id ? queryParams.team_id : currentTeam?.id,
|
||||
};
|
||||
|
||||
if (queryParams.team_id) {
|
||||
options.teamId = queryParams.team_id;
|
||||
}
|
||||
|
||||
try {
|
||||
const {
|
||||
hosts: returnedHosts,
|
||||
software,
|
||||
mobile_device_management_solution,
|
||||
munki_issue,
|
||||
mobile_device_management_solution: mdmSolution,
|
||||
munki_issue: munkiIssue,
|
||||
} = await hostsAPI.loadHosts(options);
|
||||
setHosts(returnedHosts);
|
||||
software && setSoftwareDetails(software);
|
||||
mobile_device_management_solution &&
|
||||
setMDMSolutionDetails(mobile_device_management_solution);
|
||||
munki_issue && setMunkiIssueDetails(munki_issue);
|
||||
mdmSolution && setMDMSolutionDetails(mdmSolution);
|
||||
munkiIssue && setMunkiIssueDetails(munkiIssue);
|
||||
} catch (error) {
|
||||
console.error(error);
|
||||
setHasHostErrors(true);
|
||||
|
|
@ -514,6 +512,7 @@ const ManageHostsPage = ({
|
|||
teamId: selectedTeam?.id,
|
||||
policyId,
|
||||
policyResponse,
|
||||
macSettingsStatus,
|
||||
softwareId,
|
||||
status,
|
||||
mdmId,
|
||||
|
|
@ -632,6 +631,10 @@ const ManageHostsPage = ({
|
|||
handleClearFilter(["os_id", "os_name", "os_version"]);
|
||||
};
|
||||
|
||||
const handleClearMacSettingsStatusFilter = () => {
|
||||
handleClearFilter(["macos_settings"]);
|
||||
};
|
||||
|
||||
const handleClearSoftwareFilter = () => {
|
||||
handleClearFilter(["software_id"]);
|
||||
};
|
||||
|
|
@ -687,6 +690,21 @@ const ManageHostsPage = ({
|
|||
);
|
||||
};
|
||||
|
||||
const handleMacSettingsStatusDropdownChange = (
|
||||
newMacSettingsStatus: MacSettingsStatusQueryParam
|
||||
) => {
|
||||
handleResetPageIndex();
|
||||
|
||||
router.replace(
|
||||
getNextLocationPath({
|
||||
pathPrefix: PATHS.MANAGE_HOSTS,
|
||||
routeTemplate,
|
||||
routeParams,
|
||||
queryParams: { ...queryParams, macos_settings: newMacSettingsStatus },
|
||||
})
|
||||
);
|
||||
};
|
||||
|
||||
const onAddLabelClick = () => {
|
||||
router.push(`${PATHS.NEW_LABEL}`);
|
||||
};
|
||||
|
|
@ -764,6 +782,8 @@ const ManageHostsPage = ({
|
|||
if (policyId && policyResponse) {
|
||||
newQueryParams.policy_id = policyId;
|
||||
newQueryParams.policy_response = policyResponse;
|
||||
} else if (macSettingsStatus) {
|
||||
newQueryParams.macos_settings = macSettingsStatus;
|
||||
} else if (softwareId) {
|
||||
newQueryParams.software_id = softwareId;
|
||||
} else if (mdmId) {
|
||||
|
|
@ -801,6 +821,7 @@ const ManageHostsPage = ({
|
|||
currentUser,
|
||||
policyId,
|
||||
queryParams,
|
||||
macSettingsStatus,
|
||||
softwareId,
|
||||
status,
|
||||
mdmId,
|
||||
|
|
@ -989,6 +1010,7 @@ const ManageHostsPage = ({
|
|||
teamId: currentTeam?.id,
|
||||
policyId,
|
||||
policyResponse,
|
||||
macSettingsStatus,
|
||||
softwareId,
|
||||
status,
|
||||
mdmId,
|
||||
|
|
@ -1044,6 +1066,7 @@ const ManageHostsPage = ({
|
|||
teamId: currentTeam?.id,
|
||||
policyId,
|
||||
policyResponse,
|
||||
macSettingsStatus,
|
||||
softwareId,
|
||||
status,
|
||||
mdmId,
|
||||
|
|
@ -1168,6 +1191,24 @@ const ManageHostsPage = ({
|
|||
</>
|
||||
);
|
||||
|
||||
const renderMacSettingsStatusFilterBlock = () => {
|
||||
const label = "macOS settings";
|
||||
return (
|
||||
<>
|
||||
<Dropdown
|
||||
value={macSettingsStatus}
|
||||
className={`${baseClass}__macsettings-dropdown`}
|
||||
options={MAC_SETTINGS_FILTER_OPTIONS}
|
||||
onChange={handleMacSettingsStatusDropdownChange}
|
||||
/>
|
||||
<FilterPill
|
||||
label={label}
|
||||
onClear={handleClearMacSettingsStatusFilter}
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
const renderSoftwareFilterBlock = () => {
|
||||
if (!softwareDetails) return null;
|
||||
|
||||
|
|
@ -1464,6 +1505,7 @@ const ManageHostsPage = ({
|
|||
teamId: currentTeam?.id,
|
||||
policyId,
|
||||
policyResponse,
|
||||
macSettingsStatus,
|
||||
softwareId,
|
||||
status,
|
||||
mdmId,
|
||||
|
|
@ -1534,6 +1576,7 @@ const ManageHostsPage = ({
|
|||
if (
|
||||
showSelectedLabel ||
|
||||
policyId ||
|
||||
macSettingsStatus ||
|
||||
softwareId ||
|
||||
showSelectedLabel ||
|
||||
mdmId ||
|
||||
|
|
@ -1570,6 +1613,8 @@ const ManageHostsPage = ({
|
|||
return renderLabelFilterPill();
|
||||
case !!policyId:
|
||||
return renderPoliciesFilterBlock();
|
||||
case !!macSettingsStatus:
|
||||
return renderMacSettingsStatusFilterBlock();
|
||||
case !!softwareId:
|
||||
return renderSoftwareFilterBlock();
|
||||
case !!mdmId:
|
||||
|
|
|
|||
|
|
@ -248,6 +248,23 @@
|
|||
margin-left: $pad-small;
|
||||
}
|
||||
|
||||
&__macsettings-dropdown {
|
||||
width: 137px;
|
||||
|
||||
.Select-value {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
||||
&::before {
|
||||
position: relative;
|
||||
content: url(../assets/images/icon-filter-v2-black-16x16@2x.png);
|
||||
transform: scale(0.5);
|
||||
left: -8px;
|
||||
top: 4px;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
&__labels-active-filter-wrap {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
|
|
|
|||
|
|
@ -36,3 +36,21 @@ export const HOST_SELECT_STATUSES = [
|
|||
helpText: "Hosts added to Fleet in the last 24 hours.",
|
||||
},
|
||||
];
|
||||
|
||||
export const MAC_SETTINGS_FILTER_OPTIONS = [
|
||||
{
|
||||
disabled: false,
|
||||
label: "Latest",
|
||||
value: "latest",
|
||||
},
|
||||
{
|
||||
disabled: false,
|
||||
label: "Pending",
|
||||
value: "pending",
|
||||
},
|
||||
{
|
||||
disabled: false,
|
||||
label: "Failing",
|
||||
value: "failing",
|
||||
},
|
||||
];
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ export interface ISortOption {
|
|||
direction: string;
|
||||
}
|
||||
|
||||
export type MacSettingsStatusQueryParam = "latest" | "pending" | "failing";
|
||||
|
||||
export interface ILoadHostsOptions {
|
||||
page?: number;
|
||||
perPage?: number;
|
||||
|
|
@ -23,6 +25,7 @@ export interface ILoadHostsOptions {
|
|||
teamId?: number;
|
||||
policyId?: number;
|
||||
policyResponse?: string;
|
||||
macSettingsStatus?: MacSettingsStatusQueryParam;
|
||||
softwareId?: number;
|
||||
status?: HostStatus;
|
||||
mdmId?: number;
|
||||
|
|
@ -46,6 +49,7 @@ export interface IExportHostsOptions {
|
|||
teamId?: number;
|
||||
policyId?: number;
|
||||
policyResponse?: string;
|
||||
macSettingsStatus?: MacSettingsStatusQueryParam;
|
||||
softwareId?: number;
|
||||
status?: HostStatus;
|
||||
mdmId?: number;
|
||||
|
|
@ -140,6 +144,7 @@ export default {
|
|||
const policyId = options?.policyId;
|
||||
const policyResponse = options?.policyResponse || "passing";
|
||||
const softwareId = options?.softwareId;
|
||||
const macSettingsStatus = options?.macSettingsStatus;
|
||||
const status = options?.status;
|
||||
const mdmId = options?.mdmId;
|
||||
const mdmEnrollmentStatus = options?.mdmEnrollmentStatus;
|
||||
|
|
@ -186,6 +191,7 @@ export default {
|
|||
teamId,
|
||||
policyId,
|
||||
policyResponse = "passing",
|
||||
macSettingsStatus,
|
||||
softwareId,
|
||||
status,
|
||||
mdmId,
|
||||
|
|
@ -202,6 +208,12 @@ export default {
|
|||
const label = getLabel(selectedLabels);
|
||||
const sortParams = getSortParams(sortBy);
|
||||
|
||||
// ensure macos_settings filter is always applied in
|
||||
// conjuction with a team_id, 0 (no teams) by default
|
||||
if (macSettingsStatus) {
|
||||
teamId = teamId ?? 0;
|
||||
}
|
||||
|
||||
const queryParams = {
|
||||
page,
|
||||
per_page: perPage,
|
||||
|
|
@ -211,6 +223,7 @@ export default {
|
|||
order_key: sortParams.order_key,
|
||||
order_direction: sortParams.order_direction,
|
||||
status,
|
||||
macos_settings: macSettingsStatus,
|
||||
...reconcileMutuallyExclusiveHostParams({
|
||||
label,
|
||||
policyId,
|
||||
|
|
|
|||
Loading…
Reference in a new issue