FE: MDM Status Modal new API connections (#42504)

This commit is contained in:
RachelElysia
2026-03-26 16:51:57 -04:00
committed by GitHub
parent e890981e1c
commit f7f5664d82
5 changed files with 135 additions and 4 deletions
@@ -313,6 +313,8 @@ const ManageHostsPage = ({
queryParams?.[HOSTS_QUERY_PARAMS.SCRIPT_BATCH_EXECUTION_STATUS] ??
(scriptBatchExecutionId ? "ran" : undefined);
const depProfileError = queryParams?.dep_profile_error;
/** URL converts to lowercase but API and UI requires uppercase */
const depAssignProfileResponse = queryParams?.dep_assign_profile_response.toUpperCase();
// ========= routeParams
const { active_label: activeLabel, label_id: labelID } = routeParams;
@@ -354,7 +356,7 @@ const ManageHostsPage = ({
// configProfileStatus ||
// configProfileUUID
// depProfileError
// depAssignProfileResponse
const runScriptBatchFilterNotSupported = !!(
// all above, except acceptable filters
(
@@ -392,7 +394,8 @@ const ManageHostsPage = ({
scriptBatchExecutionStatus ||
configProfileStatus ||
configProfileUUID ||
depProfileError
depProfileError ||
depAssignProfileResponse
)
);
@@ -577,6 +580,7 @@ const ManageHostsPage = ({
scriptBatchExecutionStatus,
scriptBatchExecutionId,
depProfileError: strToBool(depProfileError),
depAssignProfileResponse,
},
],
({ queryKey }) => hostsAPI.loadHosts(queryKey[0]),
@@ -1105,6 +1109,8 @@ const ManageHostsPage = ({
] = scriptBatchExecutionId;
} else if (depProfileError) {
newQueryParams.dep_profile_error = depProfileError;
} else if (depAssignProfileResponse) {
newQueryParams.dep_assign_profile_response = depAssignProfileResponse;
}
router.replace(
@@ -1150,6 +1156,8 @@ const ManageHostsPage = ({
routeTemplate,
routeParams,
softwareStatus,
depProfileError,
depAssignProfileResponse,
]
);
@@ -1345,6 +1353,7 @@ const ManageHostsPage = ({
diskEncryptionStatus,
vulnerability,
depProfileError,
depAssignProfileResponse,
})
: hostsAPI.transferToTeam(teamId, selectedHostIds);
@@ -1849,7 +1858,8 @@ const ManageHostsPage = ({
osSettingsStatus ||
diskEncryptionStatus ||
vulnerability ||
depProfileError
depProfileError ||
depAssignProfileResponse
);
return (
@@ -1997,6 +2007,7 @@ const ManageHostsPage = ({
scriptBatchRanAt: scriptBatchSummary?.created_at || null,
scriptBatchScriptName: scriptBatchSummary?.script_name || null,
depProfileError,
depAssignProfileResponse,
}}
selectedLabel={selectedLabel}
isOnlyObserver={isOnlyObserver}
@@ -24,6 +24,7 @@ import { SoftwareAggregateStatus } from "interfaces/software";
import {
HOSTS_QUERY_PARAMS,
MacSettingsStatusQueryParam,
DepAssignProfileResponse,
} from "services/entities/hosts";
import { ScriptBatchHostCountV1 } from "services/entities/scripts";
@@ -94,6 +95,7 @@ interface IHostsFilterBlockProps {
scriptBatchRanAt: string | null;
scriptBatchScriptName: string | null;
depProfileError: string; // string "true" as we don't handle booleans
depAssignProfileResponse?: DepAssignProfileResponse;
};
selectedLabel?: ILabel;
isOnlyObserver?: boolean;
@@ -156,6 +158,7 @@ const HostsFilterBlock = ({
scriptBatchRanAt,
scriptBatchScriptName,
depProfileError,
depAssignProfileResponse,
},
selectedLabel,
isOnlyObserver,
@@ -618,6 +621,65 @@ const HostsFilterBlock = ({
);
};
const renderDepAssignProfileResponse = () => {
const renderLabel = () => {
switch (depAssignProfileResponse) {
case "SUCCESS":
return "Apple Business Manager (ABM) profile assignment successful";
case "FAILED":
return "Apple Business Manager (ABM) issue: Failed";
case "THROTTLED":
return "Apple Business Manager (ABM) issue: Throttled";
case "NOT_ACCESSIBLE":
return "Apple Business Manager (ABM) issue: Not accessible";
default:
return "Apple Business Manager (ABM) issues";
}
};
const renderTooltip = () => {
switch (depAssignProfileResponse) {
case "SUCCESS":
return "Hosts that had a successful response from Apple Business Manager (ABM) for profile assignment.";
case "FAILED":
return (
<>
Migration or new Mac setup won&apos;t work. Apple&apos;s servers
rejected the request to assign a profile to these hosts. Fleet
will try again every hour.
</>
);
case "THROTTLED":
return (
<>
Migration or new Mac setup won&apos;t work. Fleet hit Apple&apos;s
API rate limit when preparing the macOS Setup Assistant for these
hosts. Fleet will try again every hour.
</>
);
case "NOT_ACCESSIBLE":
return (
<>
Migration or new Mac setup won&apos;t work. Details are not
accessible from Apple Business Manager (ABM). Verify these hosts
are assigned to your MDM server and Fleet has access permissions.
</>
);
default:
return abmIssueTooltip();
}
};
return (
<FilterPill
className={`${baseClass}__abm-issue-filter-pill`}
label={renderLabel()}
tooltipDescription={renderTooltip()}
onClear={() => handleClearFilter(["dep_assign_profile_response"])}
/>
);
};
const showSelectedLabel =
selectedLabel &&
selectedLabel.type !== "all" &&
@@ -643,7 +705,8 @@ const HostsFilterBlock = ({
vulnerability ||
(configProfileStatus && configProfileUUID && configProfile) ||
(scriptBatchExecutionStatus && scriptBatchExecutionId) ||
depProfileError
depProfileError ||
depAssignProfileResponse
) {
const renderFilterPill = () => {
switch (true) {
@@ -719,6 +782,8 @@ const HostsFilterBlock = ({
return renderScriptBatchExecutionBlock();
case !!depProfileError:
return renderDepProfileError();
case !!depAssignProfileResponse:
return renderDepAssignProfileResponse();
default:
return null;
}
+48
View File
@@ -46,6 +46,41 @@ export interface ILoadHostsResponse {
mobile_device_management_solution: IMdmSolution;
}
export type DepAssignProfileResponse =
| "SUCCESS"
| "FAILED"
| "THROTTLED"
| "NOT_ACCESSIBLE";
export interface IDepAssignmentHostResponse {
id: number;
dep_device: {
asset_tag: string;
color: string;
description: string;
device_assigned_by: string;
device_assigned_date: string;
device_family: string;
os: string;
profile_status: string;
profile_assign_time: string;
profile_push_time: string;
profile_uuid: string;
mdm_migration_deadline: string | null;
serial_number: string;
};
host_dep_assignment: {
assign_profile_response: DepAssignProfileResponse;
profile_uuid: string;
response_updated_at: string;
added_at: string;
deleted_at: string | null;
abm_token_id: number;
mdm_migration_deadline: string;
mdm_migration_completed: string;
};
}
export type IUnlockHostResponse =
| {
host_id: number;
@@ -104,6 +139,7 @@ export interface ILoadHostsOptions {
scriptBatchExecutionStatus?: ScriptBatchHostCountV1;
scriptBatchExecutionId?: string;
depProfileError?: boolean;
depAssignProfileResponse?: DepAssignProfileResponse;
}
export interface IExportHostsOptions {
@@ -141,6 +177,7 @@ export interface IExportHostsOptions {
scriptBatchExecutionStatus?: ScriptBatchHostCountV1;
scriptBatchExecutionId?: string;
depProfileError?: boolean;
depAssignProfileResponse?: DepAssignProfileResponse;
}
export interface IActionByFilter {
@@ -170,6 +207,7 @@ export interface IActionByFilter {
scriptBatchExecutionStatus?: ScriptBatchHostCountV1;
scriptBatchExecutionId?: string;
depProfileError?: boolean;
depAssignProfileResponse?: DepAssignProfileResponse;
}
export interface IGetHostSoftwareResponse {
@@ -364,6 +402,7 @@ export default {
const scriptBatchExecutionStatus = options?.scriptBatchExecutionStatus;
const scriptBatchExecutionId = options?.scriptBatchExecutionId;
const depProfileError = options?.depProfileError;
const depAssignProfileResponse = options?.depAssignProfileResponse;
if (!sortBy.length) {
throw Error("sortBy is a required field.");
@@ -403,6 +442,7 @@ export default {
scriptBatchExecutionStatus,
scriptBatchExecutionId,
depProfileError,
depAssignProfileResponse,
}),
status,
label_id: label,
@@ -449,6 +489,7 @@ export default {
scriptBatchExecutionStatus,
scriptBatchExecutionId,
depProfileError,
depAssignProfileResponse,
}: ILoadHostsOptions): Promise<ILoadHostsResponse> => {
const label = getLabel(selectedLabels);
const sortParams = getSortParams(sortBy);
@@ -492,6 +533,7 @@ export default {
scriptBatchExecutionStatus,
scriptBatchExecutionId,
depProfileError,
depAssignProfileResponse,
}),
};
@@ -563,6 +605,7 @@ export default {
diskEncryptionStatus,
vulnerability,
depProfileError,
depAssignProfileResponse,
}: IActionByFilter) => {
const { HOSTS_TRANSFER_BY_FILTER } = endpoints;
return sendRequest("POST", HOSTS_TRANSFER_BY_FILTER, {
@@ -591,6 +634,7 @@ export default {
os_settings_disk_encryption: diskEncryptionStatus,
vulnerability,
dep_profile_error: depProfileError,
dep_assing_profile_response: depAssignProfileResponse,
},
});
},
@@ -712,4 +756,8 @@ export default {
const path = endpoints.HOST_DEVICE_MAPPING_IDP(hostId);
return sendRequest("DELETE", path);
},
getDepAssignment: (id: number) => {
const { HOST_DEP_ASSIGNMENT } = endpoints;
return sendRequest("GET", HOST_DEP_ASSIGNMENT(id));
},
};
+2
View File
@@ -102,6 +102,8 @@ export default {
`/${API_VERSION}/fleet/hosts/${id}/device_mapping`,
HOST_DEVICE_MAPPING_IDP: (id: number) =>
`/${API_VERSION}/fleet/hosts/${id}/device_mapping/idp`,
HOST_DEP_ASSIGNMENT: (id: number) =>
`/${API_VERSION}/fleet/hosts/${id}/dep_assignment`,
INVITES: `/${API_VERSION}/fleet/invites`,
INVITE_VERIFY: (token: string) => `/${API_VERSION}/fleet/invites/${token}`,
+5
View File
@@ -6,6 +6,7 @@ import {
MdmProfileStatus,
} from "interfaces/mdm";
import {
DepAssignProfileResponse,
HOSTS_QUERY_PARAMS,
MacSettingsStatusQueryParam,
} from "services/entities/hosts";
@@ -51,6 +52,7 @@ interface IMutuallyExclusiveHostParams {
scriptBatchExecutionStatus?: string;
scriptBatchExecutionId?: string;
depProfileError?: boolean;
depAssignProfileResponse?: DepAssignProfileResponse;
}
export const parseQueryValueToNumberOrUndefined = (
@@ -226,6 +228,7 @@ export const reconcileMutuallyExclusiveHostParams = ({
scriptBatchExecutionStatus,
scriptBatchExecutionId,
depProfileError,
depAssignProfileResponse,
}: IMutuallyExclusiveHostParams): Record<string, unknown> => {
if (label) {
// backend api now allows (label + low disk space) OR (label + mdm id) OR
@@ -301,6 +304,8 @@ export const reconcileMutuallyExclusiveHostParams = ({
};
case !!depProfileError:
return { dep_profile_error: true };
case !!depAssignProfileResponse:
return { dep_assign_profile_response: depAssignProfileResponse };
default:
return {};
}