mirror of
https://github.com/empayre/fleet.git
synced 2024-11-06 17:05:18 +00:00
Feat UI add verifying status to mdm (#11311)
This commit is contained in:
parent
4d1beef728
commit
4866bccb3f
1
changes/issue-11181-add-verifying-status-to-profiles
Normal file
1
changes/issue-11181-add-verifying-status-to-profiles
Normal file
@ -0,0 +1 @@
|
|||||||
|
- add verifying status for mdm profiles
|
@ -9,10 +9,15 @@ import { COLORS } from "styles/var/colors";
|
|||||||
|
|
||||||
const baseClass = "status-indicator-with-icon";
|
const baseClass = "status-indicator-with-icon";
|
||||||
|
|
||||||
type Status = "success" | "pending" | "error";
|
export type IndicatorStatus =
|
||||||
|
| "success"
|
||||||
|
| "successPartial"
|
||||||
|
| "pending"
|
||||||
|
| "pendingPartial"
|
||||||
|
| "error";
|
||||||
|
|
||||||
interface IStatusIndicatorWithIconProps {
|
interface IStatusIndicatorWithIconProps {
|
||||||
status: Status;
|
status: IndicatorStatus;
|
||||||
value: string;
|
value: string;
|
||||||
tooltip?: {
|
tooltip?: {
|
||||||
tooltipText: string | JSX.Element;
|
tooltipText: string | JSX.Element;
|
||||||
@ -21,9 +26,11 @@ interface IStatusIndicatorWithIconProps {
|
|||||||
className?: string;
|
className?: string;
|
||||||
}
|
}
|
||||||
|
|
||||||
const statusIconNameMapping: Record<Status, IconNames> = {
|
const statusIconNameMapping: Record<IndicatorStatus, IconNames> = {
|
||||||
success: "success",
|
success: "success",
|
||||||
|
successPartial: "success-partial",
|
||||||
pending: "pending",
|
pending: "pending",
|
||||||
|
pendingPartial: "pending-partial",
|
||||||
error: "error",
|
error: "error",
|
||||||
};
|
};
|
||||||
|
|
||||||
|
20
frontend/components/icons/PendingPartial.tsx
Normal file
20
frontend/components/icons/PendingPartial.tsx
Normal file
@ -0,0 +1,20 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const PendingPartial = () => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="18"
|
||||||
|
height="18"
|
||||||
|
viewBox="0 0 18 18"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<circle cx="9" cy="9" r="8" stroke="#8B8FA2" strokeWidth="2" />
|
||||||
|
<circle cx="5.6665" cy="9" r="1" fill="#8B8FA2" />
|
||||||
|
<circle cx="8.6665" cy="9" r="1" fill="#8B8FA2" />
|
||||||
|
<circle cx="11.6665" cy="9" r="1" fill="#8B8FA2" />
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default PendingPartial;
|
24
frontend/components/icons/SuccessPartial.tsx
Normal file
24
frontend/components/icons/SuccessPartial.tsx
Normal file
@ -0,0 +1,24 @@
|
|||||||
|
import React from "react";
|
||||||
|
|
||||||
|
const SuccessPartial = () => {
|
||||||
|
return (
|
||||||
|
<svg
|
||||||
|
width="18"
|
||||||
|
height="18"
|
||||||
|
viewBox="0 0 18 18"
|
||||||
|
fill="none"
|
||||||
|
xmlns="http://www.w3.org/2000/svg"
|
||||||
|
>
|
||||||
|
<ellipse cx="9" cy="9" rx="8" ry="8" stroke="#3DB67B" strokeWidth="2" />
|
||||||
|
<path
|
||||||
|
d="M6 10L8 12L12 6"
|
||||||
|
stroke="#3DB67B"
|
||||||
|
strokeWidth="1.5"
|
||||||
|
strokeLinecap="round"
|
||||||
|
strokeLinejoin="round"
|
||||||
|
/>
|
||||||
|
</svg>
|
||||||
|
);
|
||||||
|
};
|
||||||
|
|
||||||
|
export default SuccessPartial;
|
@ -16,7 +16,6 @@ import EmptyTeams from "./EmptyTeams";
|
|||||||
import ExternalLink from "./ExternalLink";
|
import ExternalLink from "./ExternalLink";
|
||||||
import Issue from "./Issue";
|
import Issue from "./Issue";
|
||||||
import Plus from "./Plus";
|
import Plus from "./Plus";
|
||||||
import Pending from "./Pending";
|
|
||||||
import PremiumFeature from "./PremiumFeature";
|
import PremiumFeature from "./PremiumFeature";
|
||||||
|
|
||||||
import LowDiskSpaceHosts from "./LowDiskSpaceHosts";
|
import LowDiskSpaceHosts from "./LowDiskSpaceHosts";
|
||||||
@ -37,8 +36,12 @@ import ApplePurple from "./ApplePurple";
|
|||||||
import LinuxGreen from "./LinuxGreen";
|
import LinuxGreen from "./LinuxGreen";
|
||||||
import WindowsBlue from "./WindowsBlue";
|
import WindowsBlue from "./WindowsBlue";
|
||||||
|
|
||||||
import Error from "./Error";
|
// Status Icons
|
||||||
import Success from "./Success";
|
import Success from "./Success";
|
||||||
|
import SuccessPartial from "./SuccessPartial";
|
||||||
|
import Pending from "./Pending";
|
||||||
|
import PendingPartial from "./PendingPartial";
|
||||||
|
import Error from "./Error";
|
||||||
|
|
||||||
import Clipboard from "./Clipboard";
|
import Clipboard from "./Clipboard";
|
||||||
import Eye from "./Eye";
|
import Eye from "./Eye";
|
||||||
@ -79,9 +82,11 @@ export const ICON_MAP = {
|
|||||||
clipboard: Clipboard,
|
clipboard: Clipboard,
|
||||||
eye: Eye,
|
eye: Eye,
|
||||||
pencil: Pencil,
|
pencil: Pencil,
|
||||||
pending: Pending,
|
|
||||||
trash: TrashCan,
|
trash: TrashCan,
|
||||||
success: Success,
|
success: Success,
|
||||||
|
"success-partial": SuccessPartial,
|
||||||
|
pending: Pending,
|
||||||
|
"pending-partial": PendingPartial,
|
||||||
error: Error,
|
error: Error,
|
||||||
darwin: Apple,
|
darwin: Apple,
|
||||||
macOS: Apple,
|
macOS: Apple,
|
||||||
|
@ -7,7 +7,7 @@ import softwareInterface, { ISoftware } from "./software";
|
|||||||
import hostQueryResult from "./campaign";
|
import hostQueryResult from "./campaign";
|
||||||
import queryStatsInterface, { IQueryStats } from "./query_stats";
|
import queryStatsInterface, { IQueryStats } from "./query_stats";
|
||||||
import { ILicense, IDeviceGlobalConfig } from "./config";
|
import { ILicense, IDeviceGlobalConfig } from "./config";
|
||||||
import { IMacSettings, MdmEnrollmentStatus } from "./mdm";
|
import { IHostMacMdmProfile, MdmEnrollmentStatus } from "./mdm";
|
||||||
|
|
||||||
export default PropTypes.shape({
|
export default PropTypes.shape({
|
||||||
created_at: PropTypes.string,
|
created_at: PropTypes.string,
|
||||||
@ -107,7 +107,7 @@ export interface IHostMdmData {
|
|||||||
name?: string;
|
name?: string;
|
||||||
server_url: string;
|
server_url: string;
|
||||||
id?: number;
|
id?: number;
|
||||||
profiles: IMacSettings;
|
profiles: IHostMacMdmProfile[];
|
||||||
macos_settings: IMdmMacOsSettings;
|
macos_settings: IMdmMacOsSettings;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -68,33 +68,38 @@ export interface IMdmProfilesResponse {
|
|||||||
profiles: IMdmProfile[] | null;
|
profiles: IMdmProfile[] | null;
|
||||||
}
|
}
|
||||||
|
|
||||||
export type MacMdmProfileStatus = "applied" | "pending" | "failed";
|
export enum MdmProfileStatus {
|
||||||
|
VERIFYING = "verifying",
|
||||||
|
PENDING = "pending",
|
||||||
|
FAILED = "failed",
|
||||||
|
}
|
||||||
|
|
||||||
export type MacMdmProfileOperationType = "remove" | "install";
|
export type MacMdmProfileOperationType = "remove" | "install";
|
||||||
|
|
||||||
export interface IHostMacMdmProfile {
|
export interface IHostMacMdmProfile {
|
||||||
profile_id: number;
|
profile_id: number;
|
||||||
name: string;
|
name: string;
|
||||||
operation_type: MacMdmProfileOperationType;
|
operation_type: MacMdmProfileOperationType;
|
||||||
status: MacMdmProfileStatus;
|
status: MdmProfileStatus;
|
||||||
detail: string;
|
detail: string;
|
||||||
}
|
}
|
||||||
export type IMacSettings = IHostMacMdmProfile[];
|
|
||||||
export type MacSettingsStatus = "Failing" | "Latest" | "Pending";
|
|
||||||
|
|
||||||
export interface IAggregateMacSettingsStatus {
|
export interface IFileVaultSummaryResponse {
|
||||||
latest: number;
|
verifying: number;
|
||||||
pending: number;
|
|
||||||
failing: number;
|
|
||||||
}
|
|
||||||
|
|
||||||
export interface IDiskEncryptionStatusAggregate {
|
|
||||||
applied: number;
|
|
||||||
action_required: number;
|
action_required: number;
|
||||||
enforcing: number;
|
enforcing: number;
|
||||||
failed: number;
|
failed: number;
|
||||||
removing_enforcement: number;
|
removing_enforcement: number;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export enum FileVaultProfileStatus {
|
||||||
|
VERIFYING = "verifying",
|
||||||
|
ACTION_REQUIRED = "action_required",
|
||||||
|
ENFORCING = "enforcing",
|
||||||
|
FAILED = "failed",
|
||||||
|
REMOVING_ENFORCEMENT = "removing_enforcement",
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: update when we have API
|
// TODO: update when we have API
|
||||||
export interface IMdmScript {
|
export interface IMdmScript {
|
||||||
id: number;
|
id: number;
|
||||||
|
@ -1,4 +1,5 @@
|
|||||||
import { IAggregateMacSettingsStatus } from "interfaces/mdm";
|
import { IconNames } from "components/icons";
|
||||||
|
import { MdmProfileStatus } from "interfaces/mdm";
|
||||||
import MacSettingsIndicator from "pages/hosts/details/MacSettingsIndicator";
|
import MacSettingsIndicator from "pages/hosts/details/MacSettingsIndicator";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import { useQuery } from "react-query";
|
import { useQuery } from "react-query";
|
||||||
@ -8,6 +9,39 @@ import { buildQueryStringFromParams } from "utilities/url";
|
|||||||
|
|
||||||
const baseClass = "aggregate-mac-settings-indicators";
|
const baseClass = "aggregate-mac-settings-indicators";
|
||||||
|
|
||||||
|
interface IAggregateDisplayOption {
|
||||||
|
value: MdmProfileStatus;
|
||||||
|
text: string;
|
||||||
|
iconName: IconNames;
|
||||||
|
tooltipText: string;
|
||||||
|
}
|
||||||
|
|
||||||
|
const AGGREGATE_STATUS_DISPLAY_OPTIONS: IAggregateDisplayOption[] = [
|
||||||
|
{
|
||||||
|
value: MdmProfileStatus.VERIFYING,
|
||||||
|
text: "Verifying",
|
||||||
|
iconName: "success-partial",
|
||||||
|
tooltipText:
|
||||||
|
"Hosts that told Fleet all settings are enforced. Fleet is verifying.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MdmProfileStatus.PENDING,
|
||||||
|
text: "Pending",
|
||||||
|
iconName: "pending-partial",
|
||||||
|
tooltipText:
|
||||||
|
"Hosts that will have settings enforced when the hosts come online.",
|
||||||
|
},
|
||||||
|
{
|
||||||
|
value: MdmProfileStatus.FAILED,
|
||||||
|
text: "Failed",
|
||||||
|
iconName: "error",
|
||||||
|
tooltipText:
|
||||||
|
"Hosts that failed to apply settings. Click on a host to view error(s).",
|
||||||
|
},
|
||||||
|
];
|
||||||
|
|
||||||
|
type ProfileSummaryResponse = Record<MdmProfileStatus, number>;
|
||||||
|
|
||||||
interface AggregateMacSettingsIndicatorsProps {
|
interface AggregateMacSettingsIndicatorsProps {
|
||||||
teamId: number;
|
teamId: number;
|
||||||
}
|
}
|
||||||
@ -15,52 +49,22 @@ interface AggregateMacSettingsIndicatorsProps {
|
|||||||
const AggregateMacSettingsIndicators = ({
|
const AggregateMacSettingsIndicators = ({
|
||||||
teamId,
|
teamId,
|
||||||
}: AggregateMacSettingsIndicatorsProps) => {
|
}: AggregateMacSettingsIndicatorsProps) => {
|
||||||
const AGGREGATE_STATUS_DISPLAY_OPTIONS = {
|
|
||||||
latest: {
|
|
||||||
text: "Latest",
|
|
||||||
iconName: "success",
|
|
||||||
tooltipText: "Hosts that applied the latest settings.",
|
|
||||||
},
|
|
||||||
pending: {
|
|
||||||
text: "Pending",
|
|
||||||
iconName: "pending",
|
|
||||||
tooltipText:
|
|
||||||
"Hosts that haven’t applied the latest settings because they are asleep, disconnected from the internet, or require action.",
|
|
||||||
},
|
|
||||||
failing: {
|
|
||||||
text: "Failing",
|
|
||||||
iconName: "error",
|
|
||||||
tooltipText:
|
|
||||||
"Hosts that failed to apply the latest settings. View hosts to see errors.",
|
|
||||||
},
|
|
||||||
} as const;
|
|
||||||
|
|
||||||
const {
|
const {
|
||||||
data: aggregateProfileStatusesResponse,
|
data: aggregateProfileStatusesResponse,
|
||||||
} = useQuery<IAggregateMacSettingsStatus>(
|
} = useQuery<ProfileSummaryResponse>(
|
||||||
["aggregateProfileStatuses", teamId],
|
["aggregateProfileStatuses", teamId],
|
||||||
() => mdmAPI.getAggregateProfileStatuses(teamId),
|
() => mdmAPI.getAggregateProfileStatuses(teamId),
|
||||||
{ refetchOnWindowFocus: false }
|
{ refetchOnWindowFocus: false }
|
||||||
);
|
);
|
||||||
|
|
||||||
const DISPLAY_ORDER = ["latest", "pending", "failing"] as const;
|
if (!aggregateProfileStatusesResponse) return null;
|
||||||
const orderedResponseKVArr: [
|
|
||||||
keyof IAggregateMacSettingsStatus,
|
|
||||||
number
|
|
||||||
][] = aggregateProfileStatusesResponse
|
|
||||||
? DISPLAY_ORDER.map((key) => {
|
|
||||||
return [key, aggregateProfileStatusesResponse[key]];
|
|
||||||
})
|
|
||||||
: [];
|
|
||||||
|
|
||||||
const indicators = orderedResponseKVArr.map(([status, count]) => {
|
const indicators = AGGREGATE_STATUS_DISPLAY_OPTIONS.map((status) => {
|
||||||
const { text, iconName, tooltipText } = AGGREGATE_STATUS_DISPLAY_OPTIONS[
|
const { value, text, iconName, tooltipText } = status;
|
||||||
status
|
const count = aggregateProfileStatusesResponse[value];
|
||||||
];
|
|
||||||
|
|
||||||
return (
|
return (
|
||||||
<div className="aggregate-mac-settings-indicator">
|
<div className="aggregate-mac-settings-indicator">
|
||||||
{/* NOTE - below will be renamed as a general component and moved into the components dir by Gabe */}
|
|
||||||
<MacSettingsIndicator
|
<MacSettingsIndicator
|
||||||
indicatorText={text}
|
indicatorText={text}
|
||||||
iconName={iconName}
|
iconName={iconName}
|
||||||
@ -69,7 +73,7 @@ const AggregateMacSettingsIndicators = ({
|
|||||||
<a
|
<a
|
||||||
href={`${paths.MANAGE_HOSTS}?${buildQueryStringFromParams({
|
href={`${paths.MANAGE_HOSTS}?${buildQueryStringFromParams({
|
||||||
team_id: teamId,
|
team_id: teamId,
|
||||||
macos_settings: status,
|
macos_settings: value,
|
||||||
})}`}
|
})}`}
|
||||||
>
|
>
|
||||||
{count} hosts
|
{count} hosts
|
||||||
|
@ -1,7 +1,7 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { useQuery } from "react-query";
|
import { useQuery } from "react-query";
|
||||||
|
|
||||||
import { IDiskEncryptionStatusAggregate } from "interfaces/mdm";
|
import { IFileVaultSummaryResponse } from "interfaces/mdm";
|
||||||
import mdmAPI from "services/entities/mdm";
|
import mdmAPI from "services/entities/mdm";
|
||||||
|
|
||||||
import TableContainer from "components/TableContainer";
|
import TableContainer from "components/TableContainer";
|
||||||
@ -24,9 +24,9 @@ const DEFAULT_SORT_DIRECTION = "asc";
|
|||||||
|
|
||||||
const DiskEncryptionTable = ({ currentTeamId }: IDiskEncryptionTableProps) => {
|
const DiskEncryptionTable = ({ currentTeamId }: IDiskEncryptionTableProps) => {
|
||||||
const { data, error } = useQuery<
|
const { data, error } = useQuery<
|
||||||
IDiskEncryptionStatusAggregate,
|
IFileVaultSummaryResponse,
|
||||||
Error,
|
Error,
|
||||||
IDiskEncryptionStatusAggregate
|
IFileVaultSummaryResponse
|
||||||
>(
|
>(
|
||||||
["disk-encryption-summary", currentTeamId],
|
["disk-encryption-summary", currentTeamId],
|
||||||
() => mdmAPI.getDiskEncryptionAggregate(currentTeamId),
|
() => mdmAPI.getDiskEncryptionAggregate(currentTeamId),
|
||||||
|
@ -1,17 +1,20 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { IDiskEncryptionStatusAggregate } from "interfaces/mdm";
|
import {
|
||||||
import { DiskEncryptionStatus } from "utilities/constants";
|
FileVaultProfileStatus,
|
||||||
|
IFileVaultSummaryResponse,
|
||||||
|
} from "interfaces/mdm";
|
||||||
|
|
||||||
import TextCell from "components/TableContainer/DataTable/TextCell";
|
import TextCell from "components/TableContainer/DataTable/TextCell";
|
||||||
import HeaderCell from "components/TableContainer/DataTable/HeaderCell";
|
import HeaderCell from "components/TableContainer/DataTable/HeaderCell";
|
||||||
import StatusIndicatorWithIcon from "components/StatusIndicatorWithIcon";
|
import StatusIndicatorWithIcon from "components/StatusIndicatorWithIcon";
|
||||||
import ViewAllHostsLink from "components/ViewAllHostsLink";
|
import ViewAllHostsLink from "components/ViewAllHostsLink";
|
||||||
|
import { IndicatorStatus } from "components/StatusIndicatorWithIcon/StatusIndicatorWithIcon";
|
||||||
|
|
||||||
interface IStatusCellValue {
|
interface IStatusCellValue {
|
||||||
displayName: string;
|
displayName: string;
|
||||||
statusName: "success" | "pending" | "error";
|
statusName: IndicatorStatus;
|
||||||
value: DiskEncryptionStatus;
|
value: FileVaultProfileStatus;
|
||||||
tooltip?: string | JSX.Element;
|
tooltip?: string | JSX.Element;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -100,7 +103,7 @@ const defaultTableHeaders: IDataColumn[] = [
|
|||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
type StatusNames = keyof IDiskEncryptionStatusAggregate;
|
type StatusNames = keyof IFileVaultSummaryResponse;
|
||||||
|
|
||||||
type StatusEntry = [StatusNames, number];
|
type StatusEntry = [StatusNames, number];
|
||||||
|
|
||||||
@ -108,17 +111,17 @@ export const generateTableHeaders = (): IDataColumn[] => {
|
|||||||
return defaultTableHeaders;
|
return defaultTableHeaders;
|
||||||
};
|
};
|
||||||
|
|
||||||
const STATUS_CELL_VALUES: Record<StatusNames, IStatusCellValue> = {
|
const STATUS_CELL_VALUES: Record<FileVaultProfileStatus, IStatusCellValue> = {
|
||||||
applied: {
|
verifying: {
|
||||||
displayName: "Applied",
|
displayName: "Verifying",
|
||||||
statusName: "success",
|
statusName: "successPartial",
|
||||||
value: DiskEncryptionStatus.APPLIED,
|
value: FileVaultProfileStatus.VERIFYING,
|
||||||
tooltip: "Disk encryption on and key stored in Fleet.",
|
tooltip: "Disk encryption on and key stored in Fleet. Fleet will verify.",
|
||||||
},
|
},
|
||||||
action_required: {
|
action_required: {
|
||||||
displayName: "Action required (pending)",
|
displayName: "Action required (pending)",
|
||||||
statusName: "pending",
|
statusName: "pendingPartial",
|
||||||
value: DiskEncryptionStatus.ACTION_REQUIRED,
|
value: FileVaultProfileStatus.ACTION_REQUIRED,
|
||||||
tooltip: (
|
tooltip: (
|
||||||
<>
|
<>
|
||||||
Ask the end user to follow <b>Disk encryption</b> instructions on their{" "}
|
Ask the end user to follow <b>Disk encryption</b> instructions on their{" "}
|
||||||
@ -128,25 +131,25 @@ const STATUS_CELL_VALUES: Record<StatusNames, IStatusCellValue> = {
|
|||||||
},
|
},
|
||||||
enforcing: {
|
enforcing: {
|
||||||
displayName: "Enforcing (pending)",
|
displayName: "Enforcing (pending)",
|
||||||
statusName: "pending",
|
statusName: "pendingPartial",
|
||||||
value: DiskEncryptionStatus.ENFORCING,
|
value: FileVaultProfileStatus.ENFORCING,
|
||||||
tooltip: "Setting will be enforced when the hosts come online.",
|
tooltip: "Setting will be enforced when the hosts come online.",
|
||||||
},
|
},
|
||||||
failed: {
|
failed: {
|
||||||
displayName: "Failed",
|
displayName: "Failed",
|
||||||
statusName: "error",
|
statusName: "error",
|
||||||
value: DiskEncryptionStatus.FAILED,
|
value: FileVaultProfileStatus.FAILED,
|
||||||
},
|
},
|
||||||
removing_enforcement: {
|
removing_enforcement: {
|
||||||
displayName: "Removing enforcement (pending)",
|
displayName: "Removing enforcement (pending)",
|
||||||
statusName: "pending",
|
statusName: "pendingPartial",
|
||||||
value: DiskEncryptionStatus.REMOVING_ENFORCEMENT,
|
value: FileVaultProfileStatus.REMOVING_ENFORCEMENT,
|
||||||
tooltip: "Enforcement will be removed when the hosts come online.",
|
tooltip: "Enforcement will be removed when the hosts come online.",
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
||||||
export const generateTableData = (
|
export const generateTableData = (
|
||||||
data?: IDiskEncryptionStatusAggregate,
|
data?: IFileVaultSummaryResponse,
|
||||||
currentTeamId?: number
|
currentTeamId?: number
|
||||||
) => {
|
) => {
|
||||||
if (!data) return [];
|
if (!data) return [];
|
||||||
|
@ -48,10 +48,10 @@ import { IOperatingSystemVersion } from "interfaces/operating_system";
|
|||||||
import { IPolicy, IStoredPolicyResponse } from "interfaces/policy";
|
import { IPolicy, IStoredPolicyResponse } from "interfaces/policy";
|
||||||
import { ITeam } from "interfaces/team";
|
import { ITeam } from "interfaces/team";
|
||||||
import { IEmptyTableProps } from "interfaces/empty_table";
|
import { IEmptyTableProps } from "interfaces/empty_table";
|
||||||
|
import { FileVaultProfileStatus } from "interfaces/mdm";
|
||||||
|
|
||||||
import sortUtils from "utilities/sort";
|
import sortUtils from "utilities/sort";
|
||||||
import {
|
import {
|
||||||
DiskEncryptionStatus,
|
|
||||||
HOSTS_SEARCH_BOX_PLACEHOLDER,
|
HOSTS_SEARCH_BOX_PLACEHOLDER,
|
||||||
HOSTS_SEARCH_BOX_TOOLTIP,
|
HOSTS_SEARCH_BOX_TOOLTIP,
|
||||||
PolicyResponse,
|
PolicyResponse,
|
||||||
@ -245,7 +245,7 @@ const ManageHostsPage = ({
|
|||||||
? parseInt(queryParams.low_disk_space, 10)
|
? parseInt(queryParams.low_disk_space, 10)
|
||||||
: undefined;
|
: undefined;
|
||||||
const missingHosts = queryParams?.status === "missing";
|
const missingHosts = queryParams?.status === "missing";
|
||||||
const diskEncryptionStatus: DiskEncryptionStatus | undefined =
|
const diskEncryptionStatus: FileVaultProfileStatus | undefined =
|
||||||
queryParams?.macos_settings_disk_encryption;
|
queryParams?.macos_settings_disk_encryption;
|
||||||
|
|
||||||
// ========= routeParams
|
// ========= routeParams
|
||||||
@ -562,7 +562,7 @@ const ManageHostsPage = ({
|
|||||||
};
|
};
|
||||||
|
|
||||||
const handleChangeDiskEncryptionStatusFilter = (
|
const handleChangeDiskEncryptionStatusFilter = (
|
||||||
newStatus: DiskEncryptionStatus
|
newStatus: FileVaultProfileStatus
|
||||||
) => {
|
) => {
|
||||||
handleResetPageIndex();
|
handleResetPageIndex();
|
||||||
|
|
||||||
|
@ -1,44 +1,44 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
|
|
||||||
import { IDropdownOption } from "interfaces/dropdownOption";
|
import { IDropdownOption } from "interfaces/dropdownOption";
|
||||||
import { DiskEncryptionStatus } from "utilities/constants";
|
|
||||||
|
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
import Dropdown from "components/forms/fields/Dropdown";
|
import Dropdown from "components/forms/fields/Dropdown";
|
||||||
|
import { FileVaultProfileStatus } from "interfaces/mdm";
|
||||||
|
|
||||||
const baseClass = "disk-encryption-status-filter";
|
const baseClass = "disk-encryption-status-filter";
|
||||||
|
|
||||||
const DISK_ENCRYPTION_STATUS_OPTIONS: IDropdownOption[] = [
|
const DISK_ENCRYPTION_STATUS_OPTIONS: IDropdownOption[] = [
|
||||||
{
|
{
|
||||||
disabled: false,
|
disabled: false,
|
||||||
label: "Applied",
|
label: "Verifying",
|
||||||
value: DiskEncryptionStatus.APPLIED,
|
value: FileVaultProfileStatus.VERIFYING,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
disabled: false,
|
disabled: false,
|
||||||
label: "Action required",
|
label: "Action required",
|
||||||
value: DiskEncryptionStatus.ACTION_REQUIRED,
|
value: FileVaultProfileStatus.ACTION_REQUIRED,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
disabled: false,
|
disabled: false,
|
||||||
label: "Enforcing",
|
label: "Enforcing",
|
||||||
value: DiskEncryptionStatus.ENFORCING,
|
value: FileVaultProfileStatus.ENFORCING,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
disabled: false,
|
disabled: false,
|
||||||
label: "Failed",
|
label: "Failed",
|
||||||
value: DiskEncryptionStatus.FAILED,
|
value: FileVaultProfileStatus.FAILED,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
disabled: false,
|
disabled: false,
|
||||||
label: "Removing enforcement",
|
label: "Removing enforcement",
|
||||||
value: DiskEncryptionStatus.REMOVING_ENFORCEMENT,
|
value: FileVaultProfileStatus.REMOVING_ENFORCEMENT,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
|
||||||
interface IDiskEncryptionStatusFilterProps {
|
interface IDiskEncryptionStatusFilterProps {
|
||||||
diskEncryptionStatus: DiskEncryptionStatus;
|
diskEncryptionStatus: FileVaultProfileStatus;
|
||||||
onChange: (value: DiskEncryptionStatus) => void;
|
onChange: (value: FileVaultProfileStatus) => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
const DiskEncryptionStatusFilter = ({
|
const DiskEncryptionStatusFilter = ({
|
||||||
|
@ -6,16 +6,17 @@ import {
|
|||||||
formatOperatingSystemDisplayName,
|
formatOperatingSystemDisplayName,
|
||||||
IOperatingSystemVersion,
|
IOperatingSystemVersion,
|
||||||
} from "interfaces/operating_system";
|
} from "interfaces/operating_system";
|
||||||
import { IMdmSolution, MDM_ENROLLMENT_STATUS } from "interfaces/mdm";
|
import {
|
||||||
|
FileVaultProfileStatus,
|
||||||
|
IMdmSolution,
|
||||||
|
MDM_ENROLLMENT_STATUS,
|
||||||
|
} from "interfaces/mdm";
|
||||||
import { IMunkiIssuesAggregate } from "interfaces/macadmins";
|
import { IMunkiIssuesAggregate } from "interfaces/macadmins";
|
||||||
import { ISoftware } from "interfaces/software";
|
import { ISoftware } from "interfaces/software";
|
||||||
import { IPolicy } from "interfaces/policy";
|
import { IPolicy } from "interfaces/policy";
|
||||||
|
|
||||||
// TODO: should this be in interfaces hosts?
|
|
||||||
import { MacSettingsStatusQueryParam } from "services/entities/hosts";
|
import { MacSettingsStatusQueryParam } from "services/entities/hosts";
|
||||||
|
|
||||||
import {
|
import {
|
||||||
DiskEncryptionStatus,
|
|
||||||
PLATFORM_LABEL_DISPLAY_NAMES,
|
PLATFORM_LABEL_DISPLAY_NAMES,
|
||||||
PolicyResponse,
|
PolicyResponse,
|
||||||
} from "utilities/constants";
|
} from "utilities/constants";
|
||||||
@ -60,14 +61,16 @@ interface IHostsFilterBlockProps {
|
|||||||
osVersions?: IOperatingSystemVersion[];
|
osVersions?: IOperatingSystemVersion[];
|
||||||
softwareDetails: ISoftware | null;
|
softwareDetails: ISoftware | null;
|
||||||
mdmSolutionDetails: IMdmSolution | null;
|
mdmSolutionDetails: IMdmSolution | null;
|
||||||
diskEncryptionStatus?: DiskEncryptionStatus;
|
diskEncryptionStatus?: FileVaultProfileStatus;
|
||||||
};
|
};
|
||||||
selectedLabel?: ILabel;
|
selectedLabel?: ILabel;
|
||||||
isOnlyObserver?: boolean;
|
isOnlyObserver?: boolean;
|
||||||
handleClearRouteParam: () => void;
|
handleClearRouteParam: () => void;
|
||||||
handleClearFilter: (omitParams: string[]) => void;
|
handleClearFilter: (omitParams: string[]) => void;
|
||||||
onChangePoliciesFilter: (response: PolicyResponse) => void;
|
onChangePoliciesFilter: (response: PolicyResponse) => void;
|
||||||
onChangeDiskEncryptionStatusFilter: (response: DiskEncryptionStatus) => void;
|
onChangeDiskEncryptionStatusFilter: (
|
||||||
|
response: FileVaultProfileStatus
|
||||||
|
) => void;
|
||||||
onChangeMacSettingsFilter: (
|
onChangeMacSettingsFilter: (
|
||||||
newMacSettingsStatus: MacSettingsStatusQueryParam
|
newMacSettingsStatus: MacSettingsStatusQueryParam
|
||||||
) => void;
|
) => void;
|
||||||
@ -265,7 +268,6 @@ const HostsFilterBlock = ({
|
|||||||
if (!mdmEnrollmentStatus) return null;
|
if (!mdmEnrollmentStatus) return null;
|
||||||
|
|
||||||
const label = `MDM status: ${
|
const label = `MDM status: ${
|
||||||
// TODO: move MDM_ENROLLMENT_STATUS to util file
|
|
||||||
invert(MDM_ENROLLMENT_STATUS)[mdmEnrollmentStatus]
|
invert(MDM_ENROLLMENT_STATUS)[mdmEnrollmentStatus]
|
||||||
}`;
|
}`;
|
||||||
|
|
||||||
|
@ -1,3 +1,5 @@
|
|||||||
|
import { MdmProfileStatus } from "interfaces/mdm";
|
||||||
|
|
||||||
export const LABEL_SLUG_PREFIX = "labels/";
|
export const LABEL_SLUG_PREFIX = "labels/";
|
||||||
|
|
||||||
export const DEFAULT_SORT_HEADER = "display_name";
|
export const DEFAULT_SORT_HEADER = "display_name";
|
||||||
@ -41,17 +43,17 @@ export const HOST_SELECT_STATUSES = [
|
|||||||
export const MAC_SETTINGS_FILTER_OPTIONS = [
|
export const MAC_SETTINGS_FILTER_OPTIONS = [
|
||||||
{
|
{
|
||||||
disabled: false,
|
disabled: false,
|
||||||
label: "Latest",
|
label: "Verifying",
|
||||||
value: "latest",
|
value: MdmProfileStatus.VERIFYING,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
disabled: false,
|
disabled: false,
|
||||||
label: "Pending",
|
label: "Pending",
|
||||||
value: "pending",
|
value: MdmProfileStatus.PENDING,
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
disabled: false,
|
disabled: false,
|
||||||
label: "Failing",
|
label: "Failed",
|
||||||
value: "failing",
|
value: MdmProfileStatus.FAILED,
|
||||||
},
|
},
|
||||||
];
|
];
|
||||||
|
@ -1,11 +1,11 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import Button from "components/buttons/Button";
|
import Button from "components/buttons/Button";
|
||||||
import Modal from "components/Modal";
|
import Modal from "components/Modal";
|
||||||
import { IMacSettings } from "interfaces/mdm";
|
import { IHostMacMdmProfile } from "interfaces/mdm";
|
||||||
import MacSettingsTable from "./MacSettingsTable";
|
import MacSettingsTable from "./MacSettingsTable";
|
||||||
|
|
||||||
interface IMacSettingsModalProps {
|
interface IMacSettingsModalProps {
|
||||||
hostMacSettings?: IMacSettings;
|
hostMacSettings?: IHostMacMdmProfile[];
|
||||||
onClose: () => void;
|
onClose: () => void;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1,26 +1,23 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import { render, screen } from "@testing-library/react";
|
import { render, screen } from "@testing-library/react";
|
||||||
import { createCustomRenderer } from "test/test-utils";
|
import { createCustomRenderer } from "test/test-utils";
|
||||||
import {
|
import { MacMdmProfileOperationType, MdmProfileStatus } from "interfaces/mdm";
|
||||||
MacMdmProfileOperationType,
|
|
||||||
MacMdmProfileStatus,
|
|
||||||
} from "interfaces/mdm";
|
|
||||||
import MacSettingStatusCell from "./MacSettingStatusCell";
|
import MacSettingStatusCell from "./MacSettingStatusCell";
|
||||||
|
|
||||||
describe("Mac setting status cell", () => {
|
describe("Mac setting status cell", () => {
|
||||||
it("Correctly displays the status text of a profile", () => {
|
it("Correctly displays the status text of a profile", () => {
|
||||||
const status: MacMdmProfileStatus = "applied";
|
const status = MdmProfileStatus.VERIFYING;
|
||||||
const operationType: MacMdmProfileOperationType = "install";
|
const operationType: MacMdmProfileOperationType = "install";
|
||||||
|
|
||||||
render(
|
render(
|
||||||
<MacSettingStatusCell status={status} operationType={operationType} />
|
<MacSettingStatusCell status={status} operationType={operationType} />
|
||||||
);
|
);
|
||||||
|
|
||||||
expect(screen.getByText("Applied")).toBeInTheDocument();
|
expect(screen.getByText("Verifying")).toBeInTheDocument();
|
||||||
});
|
});
|
||||||
|
|
||||||
it("Correctly displays the tooltip text for a profile", async () => {
|
it("Correctly displays the tooltip text for a profile", async () => {
|
||||||
const status: MacMdmProfileStatus = "applied";
|
const status = MdmProfileStatus.VERIFYING;
|
||||||
const operationType: MacMdmProfileOperationType = "install";
|
const operationType: MacMdmProfileOperationType = "install";
|
||||||
|
|
||||||
const customRender = createCustomRenderer();
|
const customRender = createCustomRenderer();
|
||||||
@ -29,7 +26,7 @@ describe("Mac setting status cell", () => {
|
|||||||
<MacSettingStatusCell status={status} operationType={operationType} />
|
<MacSettingStatusCell status={status} operationType={operationType} />
|
||||||
);
|
);
|
||||||
|
|
||||||
const statusText = screen.getByText("Applied");
|
const statusText = screen.getByText("Verifying");
|
||||||
|
|
||||||
await user.hover(statusText);
|
await user.hover(statusText);
|
||||||
|
|
||||||
|
@ -1,33 +1,35 @@
|
|||||||
import Icon from "components/Icon";
|
import Icon from "components/Icon";
|
||||||
import TextCell from "components/TableContainer/DataTable/TextCell";
|
import TextCell from "components/TableContainer/DataTable/TextCell";
|
||||||
import {
|
import { IconNames } from "components/icons";
|
||||||
MacMdmProfileOperationType,
|
import { MacMdmProfileOperationType, MdmProfileStatus } from "interfaces/mdm";
|
||||||
MacMdmProfileStatus,
|
|
||||||
} from "interfaces/mdm";
|
|
||||||
import _ from "lodash";
|
import _ from "lodash";
|
||||||
import React from "react";
|
import React from "react";
|
||||||
import ReactTooltip from "react-tooltip";
|
import ReactTooltip from "react-tooltip";
|
||||||
|
|
||||||
const baseClass = "mac-setting-status-cell";
|
const baseClass = "mac-setting-status-cell";
|
||||||
|
|
||||||
interface IMacSettingStatusCellProps {
|
type ProfileDisplayOption = {
|
||||||
status: MacMdmProfileStatus;
|
statusText: string;
|
||||||
operationType: MacMdmProfileOperationType;
|
iconName: IconNames;
|
||||||
}
|
tooltipText?: string;
|
||||||
const MacSettingStatusCell = ({
|
} | null;
|
||||||
status,
|
|
||||||
operationType,
|
type OperationTypeOption = Record<MdmProfileStatus, ProfileDisplayOption>;
|
||||||
}: IMacSettingStatusCellProps): JSX.Element => {
|
type ProfileDisplayConfig = Record<
|
||||||
const PROFILE_DISPLAY_CONFIG = {
|
MacMdmProfileOperationType,
|
||||||
|
OperationTypeOption
|
||||||
|
>;
|
||||||
|
|
||||||
|
const PROFILE_DISPLAY_CONFIG: ProfileDisplayConfig = {
|
||||||
install: {
|
install: {
|
||||||
pending: {
|
pending: {
|
||||||
statusText: "Enforcing (pending)",
|
statusText: "Enforcing (pending)",
|
||||||
iconName: "pending",
|
iconName: "pending-partial",
|
||||||
tooltipText: "Setting will be enforced when the host comes online.",
|
tooltipText: "Setting will be enforced when the host comes online.",
|
||||||
},
|
},
|
||||||
applied: {
|
verifying: {
|
||||||
statusText: "Applied",
|
statusText: "Verifying",
|
||||||
iconName: "success",
|
iconName: "success-partial",
|
||||||
tooltipText: "Host applied the setting.",
|
tooltipText: "Host applied the setting.",
|
||||||
},
|
},
|
||||||
failed: {
|
failed: {
|
||||||
@ -39,18 +41,26 @@ const MacSettingStatusCell = ({
|
|||||||
remove: {
|
remove: {
|
||||||
pending: {
|
pending: {
|
||||||
statusText: "Removing enforcement (pending)",
|
statusText: "Removing enforcement (pending)",
|
||||||
iconName: "pending",
|
iconName: "pending-partial",
|
||||||
tooltipText: "Enforcement will be removed when the host comes online.",
|
tooltipText: "Enforcement will be removed when the host comes online.",
|
||||||
},
|
},
|
||||||
applied: null, // should not be reached
|
verifying: null, // should not be reached
|
||||||
failed: {
|
failed: {
|
||||||
statusText: "Failed",
|
statusText: "Failed",
|
||||||
iconName: "error",
|
iconName: "error",
|
||||||
tooltipText: undefined,
|
tooltipText: undefined,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
} as const;
|
};
|
||||||
|
|
||||||
|
interface IMacSettingStatusCellProps {
|
||||||
|
status: MdmProfileStatus;
|
||||||
|
operationType: MacMdmProfileOperationType;
|
||||||
|
}
|
||||||
|
const MacSettingStatusCell = ({
|
||||||
|
status,
|
||||||
|
operationType,
|
||||||
|
}: IMacSettingStatusCellProps): JSX.Element => {
|
||||||
const options = PROFILE_DISPLAY_CONFIG[operationType]?.[status];
|
const options = PROFILE_DISPLAY_CONFIG[operationType]?.[status];
|
||||||
|
|
||||||
if (options) {
|
if (options) {
|
||||||
|
@ -1,13 +1,13 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import TableContainer from "components/TableContainer";
|
import TableContainer from "components/TableContainer";
|
||||||
import { IMacSettings } from "interfaces/mdm";
|
import { IHostMacMdmProfile } from "interfaces/mdm";
|
||||||
|
|
||||||
import tableHeaders from "./MacSettingsTableConfig";
|
import tableHeaders from "./MacSettingsTableConfig";
|
||||||
|
|
||||||
const baseClass = "macsettings-table";
|
const baseClass = "macsettings-table";
|
||||||
|
|
||||||
interface IMacSettingsTableProps {
|
interface IMacSettingsTableProps {
|
||||||
hostMacSettings?: IMacSettings;
|
hostMacSettings?: IHostMacMdmProfile[];
|
||||||
}
|
}
|
||||||
|
|
||||||
const MacSettingsTable = ({ hostMacSettings }: IMacSettingsTableProps) => {
|
const MacSettingsTable = ({ hostMacSettings }: IMacSettingsTableProps) => {
|
||||||
|
@ -9,7 +9,7 @@ import HumanTimeDiffWithDateTip from "components/HumanTimeDiffWithDateTip";
|
|||||||
import { humanHostMemory, wrapFleetHelper } from "utilities/helpers";
|
import { humanHostMemory, wrapFleetHelper } from "utilities/helpers";
|
||||||
import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";
|
import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";
|
||||||
import StatusIndicator from "components/StatusIndicator";
|
import StatusIndicator from "components/StatusIndicator";
|
||||||
import { IMacSettings } from "interfaces/mdm";
|
import { IHostMacMdmProfile } from "interfaces/mdm";
|
||||||
import getHostStatusTooltipText from "pages/hosts/helpers";
|
import getHostStatusTooltipText from "pages/hosts/helpers";
|
||||||
import IssueIcon from "../../../../../../assets/images/icon-issue-fleet-black-50-16x16@2x.png";
|
import IssueIcon from "../../../../../../assets/images/icon-issue-fleet-black-50-16x16@2x.png";
|
||||||
import MacSettingsIndicator from "./MacSettingsIndicator";
|
import MacSettingsIndicator from "./MacSettingsIndicator";
|
||||||
@ -30,7 +30,7 @@ interface IHostSummaryProps {
|
|||||||
isOnlyObserver?: boolean;
|
isOnlyObserver?: boolean;
|
||||||
toggleOSPolicyModal?: () => void;
|
toggleOSPolicyModal?: () => void;
|
||||||
toggleMacSettingsModal?: () => void;
|
toggleMacSettingsModal?: () => void;
|
||||||
hostMacSettings?: IMacSettings;
|
hostMacSettings?: IHostMacMdmProfile[];
|
||||||
mdmName?: string;
|
mdmName?: string;
|
||||||
showRefetchSpinner: boolean;
|
showRefetchSpinner: boolean;
|
||||||
onRefetchHost: (
|
onRefetchHost: (
|
||||||
|
@ -1,26 +1,32 @@
|
|||||||
import React from "react";
|
import React from "react";
|
||||||
import ReactTooltip from "react-tooltip";
|
import ReactTooltip from "react-tooltip";
|
||||||
|
|
||||||
|
import { IHostMacMdmProfile, MdmProfileStatus } from "interfaces/mdm";
|
||||||
|
|
||||||
import Icon from "components/Icon";
|
import Icon from "components/Icon";
|
||||||
import Button from "components/buttons/Button";
|
import Button from "components/buttons/Button";
|
||||||
import { IMacSettings, MacSettingsStatus } from "interfaces/mdm";
|
import { IconNames } from "components/icons";
|
||||||
|
|
||||||
const baseClass = "mac-settings-indicator";
|
const baseClass = "mac-settings-indicator";
|
||||||
|
|
||||||
interface IMacSettingsIndicatorProps {
|
type MacSettingsStatus = "Failing" | "Verifying" | "Pending";
|
||||||
profiles: IMacSettings;
|
|
||||||
onClick?: () => void;
|
interface IStatusDisplayOption {
|
||||||
|
iconName: Extract<
|
||||||
|
IconNames,
|
||||||
|
"success" | "success-partial" | "pending" | "pending-partial" | "error"
|
||||||
|
>;
|
||||||
|
tooltipText: string;
|
||||||
}
|
}
|
||||||
const MacSettingsIndicator = ({
|
type StatusDisplayOptions = Record<MacSettingsStatus, IStatusDisplayOption>;
|
||||||
profiles,
|
|
||||||
onClick,
|
const STATUS_DISPLAY_OPTIONS: StatusDisplayOptions = {
|
||||||
}: IMacSettingsIndicatorProps): JSX.Element => {
|
Verifying: {
|
||||||
const STATUS_DISPLAY_OPTIONS = {
|
iconName: "success-partial",
|
||||||
Latest: {
|
|
||||||
iconName: "success",
|
|
||||||
tooltipText: "Host applied the latest settings",
|
tooltipText: "Host applied the latest settings",
|
||||||
},
|
},
|
||||||
Pending: {
|
Pending: {
|
||||||
iconName: "pending",
|
iconName: "pending-partial",
|
||||||
tooltipText: "Host will apply the latest settings when it comes online",
|
tooltipText: "Host will apply the latest settings when it comes online",
|
||||||
},
|
},
|
||||||
Failing: {
|
Failing: {
|
||||||
@ -28,21 +34,29 @@ const MacSettingsIndicator = ({
|
|||||||
tooltipText:
|
tooltipText:
|
||||||
"Host failed to apply the latest settings. Click to view error(s).",
|
"Host failed to apply the latest settings. Click to view error(s).",
|
||||||
},
|
},
|
||||||
} as const;
|
};
|
||||||
|
|
||||||
const getMacSettingsStatus = (
|
const getMacSettingsStatus = (
|
||||||
hostMacSettings: IMacSettings | undefined
|
hostMacSettings?: IHostMacMdmProfile[]
|
||||||
): MacSettingsStatus => {
|
): MacSettingsStatus => {
|
||||||
const statuses = hostMacSettings?.map((setting) => setting.status);
|
const statuses = hostMacSettings?.map((setting) => setting.status);
|
||||||
if (statuses?.includes("failed")) {
|
if (statuses?.includes(MdmProfileStatus.FAILED)) {
|
||||||
return "Failing";
|
return "Failing";
|
||||||
}
|
}
|
||||||
if (statuses?.includes("pending")) {
|
if (statuses?.includes(MdmProfileStatus.PENDING)) {
|
||||||
return "Pending";
|
return "Pending";
|
||||||
}
|
}
|
||||||
return "Latest";
|
return "Verifying";
|
||||||
};
|
};
|
||||||
|
|
||||||
|
interface IMacSettingsIndicatorProps {
|
||||||
|
profiles: IHostMacMdmProfile[];
|
||||||
|
onClick?: () => void;
|
||||||
|
}
|
||||||
|
const MacSettingsIndicator = ({
|
||||||
|
profiles,
|
||||||
|
onClick,
|
||||||
|
}: IMacSettingsIndicatorProps): JSX.Element => {
|
||||||
const macSettingsStatus = getMacSettingsStatus(profiles);
|
const macSettingsStatus = getMacSettingsStatus(profiles);
|
||||||
|
|
||||||
const iconName = STATUS_DISPLAY_OPTIONS[macSettingsStatus].iconName;
|
const iconName = STATUS_DISPLAY_OPTIONS[macSettingsStatus].iconName;
|
||||||
|
@ -2,13 +2,14 @@
|
|||||||
import sendRequest from "services";
|
import sendRequest from "services";
|
||||||
import endpoints from "utilities/endpoints";
|
import endpoints from "utilities/endpoints";
|
||||||
import { HostStatus } from "interfaces/host";
|
import { HostStatus } from "interfaces/host";
|
||||||
|
import { FileVaultProfileStatus } from "interfaces/mdm";
|
||||||
import {
|
import {
|
||||||
buildQueryStringFromParams,
|
buildQueryStringFromParams,
|
||||||
getLabelParam,
|
getLabelParam,
|
||||||
reconcileMutuallyExclusiveHostParams,
|
reconcileMutuallyExclusiveHostParams,
|
||||||
reconcileMutuallyInclusiveHostParams,
|
reconcileMutuallyInclusiveHostParams,
|
||||||
} from "utilities/url";
|
} from "utilities/url";
|
||||||
import { DiskEncryptionStatus } from "utilities/constants";
|
|
||||||
import { MacSettingsStatusQueryParam } from "./hosts";
|
import { MacSettingsStatusQueryParam } from "./hosts";
|
||||||
|
|
||||||
export interface ISortOption {
|
export interface ISortOption {
|
||||||
@ -42,7 +43,7 @@ export interface IHostCountLoadOptions {
|
|||||||
osId?: number;
|
osId?: number;
|
||||||
osName?: string;
|
osName?: string;
|
||||||
osVersion?: string;
|
osVersion?: string;
|
||||||
diskEncryptionStatus?: DiskEncryptionStatus;
|
diskEncryptionStatus?: FileVaultProfileStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
export default {
|
export default {
|
||||||
|
@ -9,9 +9,8 @@ import {
|
|||||||
reconcileMutuallyInclusiveHostParams,
|
reconcileMutuallyInclusiveHostParams,
|
||||||
} from "utilities/url";
|
} from "utilities/url";
|
||||||
import { ISelectedPlatform } from "interfaces/platform";
|
import { ISelectedPlatform } from "interfaces/platform";
|
||||||
import { DiskEncryptionStatus } from "utilities/constants";
|
|
||||||
import { ISoftware } from "interfaces/software";
|
import { ISoftware } from "interfaces/software";
|
||||||
import { IMdmSolution } from "interfaces/mdm";
|
import { FileVaultProfileStatus, IMdmSolution } from "interfaces/mdm";
|
||||||
import { IMunkiIssuesAggregate } from "interfaces/macadmins";
|
import { IMunkiIssuesAggregate } from "interfaces/macadmins";
|
||||||
|
|
||||||
export interface ISortOption {
|
export interface ISortOption {
|
||||||
@ -54,7 +53,7 @@ export interface ILoadHostsOptions {
|
|||||||
device_mapping?: boolean;
|
device_mapping?: boolean;
|
||||||
columns?: string;
|
columns?: string;
|
||||||
visibleColumns?: string;
|
visibleColumns?: string;
|
||||||
diskEncryptionStatus?: DiskEncryptionStatus;
|
diskEncryptionStatus?: FileVaultProfileStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IExportHostsOptions {
|
export interface IExportHostsOptions {
|
||||||
@ -79,7 +78,7 @@ export interface IExportHostsOptions {
|
|||||||
device_mapping?: boolean;
|
device_mapping?: boolean;
|
||||||
columns?: string;
|
columns?: string;
|
||||||
visibleColumns?: string;
|
visibleColumns?: string;
|
||||||
diskEncryptionStatus?: DiskEncryptionStatus;
|
diskEncryptionStatus?: FileVaultProfileStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
export interface IActionByFilter {
|
export interface IActionByFilter {
|
||||||
|
@ -10,14 +10,6 @@ export enum PolicyResponse {
|
|||||||
FAILING = "failing",
|
FAILING = "failing",
|
||||||
}
|
}
|
||||||
|
|
||||||
export enum DiskEncryptionStatus {
|
|
||||||
APPLIED = "applied",
|
|
||||||
ACTION_REQUIRED = "action_required",
|
|
||||||
ENFORCING = "enforcing",
|
|
||||||
FAILED = "failed",
|
|
||||||
REMOVING_ENFORCEMENT = "removing_enforcement",
|
|
||||||
}
|
|
||||||
|
|
||||||
export const DEFAULT_GRAVATAR_LINK =
|
export const DEFAULT_GRAVATAR_LINK =
|
||||||
"https://fleetdm.com/images/permanent/icon-avatar-default-transparent-64x64%402x.png";
|
"https://fleetdm.com/images/permanent/icon-avatar-default-transparent-64x64%402x.png";
|
||||||
|
|
||||||
|
@ -1,6 +1,6 @@
|
|||||||
|
import { FileVaultProfileStatus } from "interfaces/mdm";
|
||||||
import { isEmpty, reduce, omitBy, Dictionary } from "lodash";
|
import { isEmpty, reduce, omitBy, Dictionary } from "lodash";
|
||||||
import { MacSettingsStatusQueryParam } from "services/entities/hosts";
|
import { MacSettingsStatusQueryParam } from "services/entities/hosts";
|
||||||
import { DiskEncryptionStatus } from "utilities/constants";
|
|
||||||
|
|
||||||
type QueryValues = string | number | boolean | undefined | null;
|
type QueryValues = string | number | boolean | undefined | null;
|
||||||
export type QueryParams = Record<string, QueryValues>;
|
export type QueryParams = Record<string, QueryValues>;
|
||||||
@ -24,7 +24,7 @@ interface IMutuallyExclusiveHostParams {
|
|||||||
osId?: number;
|
osId?: number;
|
||||||
osName?: string;
|
osName?: string;
|
||||||
osVersion?: string;
|
osVersion?: string;
|
||||||
diskEncryptionStatus?: DiskEncryptionStatus;
|
diskEncryptionStatus?: FileVaultProfileStatus;
|
||||||
}
|
}
|
||||||
|
|
||||||
const reduceQueryParams = (
|
const reduceQueryParams = (
|
||||||
|
@ -384,7 +384,7 @@ type MDMAppleConfigProfilesSummary struct {
|
|||||||
Pending uint `json:"pending" db:"pending"`
|
Pending uint `json:"pending" db:"pending"`
|
||||||
// Failed includes each host that has failed to apply one or more of the profiles currently
|
// Failed includes each host that has failed to apply one or more of the profiles currently
|
||||||
// applicable to the host.
|
// applicable to the host.
|
||||||
Failed uint `json:"failing" db:"failed"`
|
Failed uint `json:"failed" db:"failed"`
|
||||||
}
|
}
|
||||||
|
|
||||||
// MDMAppleFileVaultSummary reports the number of macOS hosts being managed with Apples disk
|
// MDMAppleFileVaultSummary reports the number of macOS hosts being managed with Apples disk
|
||||||
|
Loading…
Reference in New Issue
Block a user