diff --git a/frontend/components/TableContainer/DataTable/HostMdmStatusCell/HostMdmStatusCell.tests.tsx b/frontend/components/TableContainer/DataTable/HostMdmStatusCell/HostMdmStatusCell.tests.tsx index 2917951b493..7234f853c1b 100644 --- a/frontend/components/TableContainer/DataTable/HostMdmStatusCell/HostMdmStatusCell.tests.tsx +++ b/frontend/components/TableContainer/DataTable/HostMdmStatusCell/HostMdmStatusCell.tests.tsx @@ -33,9 +33,9 @@ describe("HostMdmStatusCell", () => { expect(screen.getByText("On (company-owned)")).toBeInTheDocument(); }); - it("renders 'On (personal)' for iOS hosts with personal enrollment", () => { + it("renders 'On (BYOD)' for iOS hosts with personal enrollment", () => { renderCell("ios", "On (personal)"); - expect(screen.getByText("On (personal)")).toBeInTheDocument(); + expect(screen.getByText("On (BYOD)")).toBeInTheDocument(); }); it("renders 'Pending' for macOS hosts with pending enrollment", () => { @@ -45,7 +45,7 @@ describe("HostMdmStatusCell", () => { it("renders the MDM status for Android hosts", () => { renderCell("android", "On (personal)"); - expect(screen.getByText("On (personal)")).toBeInTheDocument(); + expect(screen.getByText("On (BYOD)")).toBeInTheDocument(); }); it("renders the MDM status for Windows hosts", () => { diff --git a/frontend/interfaces/mdm.ts b/frontend/interfaces/mdm.ts index 51ed634bd4d..22c70b0680a 100644 --- a/frontend/interfaces/mdm.ts +++ b/frontend/interfaces/mdm.ts @@ -36,6 +36,7 @@ export interface IMdmAbToken { macos_fleet: ITokenFleet; ios_fleet: ITokenFleet; ipados_fleet: ITokenFleet; + byod_fleet: ITokenFleet; } export interface IMdmVppToken { @@ -96,7 +97,7 @@ export const MDM_ENROLLMENT_STATUS_UI_MAP: Record< filterValue: "automatic", }, "On (personal)": { - displayName: "On (personal)", + displayName: "On (BYOD)", filterValue: "personal", }, Off: { diff --git a/frontend/pages/DashboardPage/cards/MDM/MDM.tests.tsx b/frontend/pages/DashboardPage/cards/MDM/MDM.tests.tsx index cb5fd277e72..89c02cb0ae2 100644 --- a/frontend/pages/DashboardPage/cards/MDM/MDM.tests.tsx +++ b/frontend/pages/DashboardPage/cards/MDM/MDM.tests.tsx @@ -65,7 +65,7 @@ describe("MDM Card", () => { ).toBeInTheDocument(); expect( screen.getByRole("row", { - name: /On \(personal\)(.*?)3 view all hosts/i, + name: /On \(BYOD\)(.*?)3 view all hosts/i, }) ).toBeInTheDocument(); diff --git a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/AppleBusinessManagerPage.tsx b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/AppleBusinessManagerPage.tsx index ebab83a6be3..bdf7dfb3e1e 100644 --- a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/AppleBusinessManagerPage.tsx +++ b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/AppleBusinessManagerPage.tsx @@ -184,8 +184,7 @@ const AppleBusinessManagerPage = ({ router }: { router: InjectedRouter }) => { <>

Add your AB to enable automatic enrollment for company-owned hosts - and enrollment, via a Managed Apple Account, for personal (BYOD) - hosts. + and enrollment, via a Managed Apple Account, for BYOD hosts.

{ const { gitOpsModeEnabled, repoURL } = useGitOpsMode(); + const [searchQuery, setSearchQuery] = useState(""); + const normalizedQuery = searchQuery.toLowerCase(); + const filteredAbTokens = normalizedQuery + ? abTokens.filter((token) => + token.org_name.toLowerCase().includes(normalizedQuery) + ) + : abTokens; const onSelectAction = (action: string, abmToken: IMdmAbToken) => { switch (action) { @@ -46,18 +54,25 @@ const AppleBusinessManagerTable = ({ repoURL ); + const onQueryChange = (queryData: ITableQueryData) => { + setSearchQuery(queryData.searchQuery); + }; + return ( columnConfigs={tableConfig} defaultSortHeader="org_name" - disableTableHeader disablePagination showMarkAllPages={false} isAllPagesSelected={false} emptyComponent={() => <>} isLoading={false} - data={abTokens} + data={filteredAbTokens} className={baseClass} + searchable + inputPlaceHolder="Search by organization name" + searchQuery={searchQuery} + onQueryChange={onQueryChange} /> ); }; diff --git a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/AppleBusinessManagerTable/AppleBusinessManagerTableConfig.tsx b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/AppleBusinessManagerTable/AppleBusinessManagerTableConfig.tsx index 6396822d078..dd826f65f06 100644 --- a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/AppleBusinessManagerTable/AppleBusinessManagerTableConfig.tsx +++ b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/AppleBusinessManagerTable/AppleBusinessManagerTableConfig.tsx @@ -92,8 +92,13 @@ export const generateTableConfig = ( }, { accessor: "renew_date", - Header: "Renew date", - disableSortBy: true, + sortType: "dateStrings", + Header: (cellProps: ITableHeaderProps) => ( + + ), Cell: (cellProps: IRenewDateCellProps) => ( ), }, - { - accessor: "apple_id", - Header: "Apple ID", - disableSortBy: true, - Cell: (cellProps: ITableStringCellProps) => ( - - ), - }, { id: "macos_team", + sortType: "caseInsensitive", accessor: (originalRow) => getFleetDisplayName(originalRow.macos_fleet), - Header: () => { + Header: (cellProps: ITableHeaderProps) => { const titleWithToolTip = ( ); - return ; + return ( + + ); }, - disableSortBy: true, Cell: (cellProps: ITableStringCellProps) => ( ), }, { id: "ios_team", + sortType: "caseInsensitive", accessor: (originalRow) => getFleetDisplayName(originalRow.ios_fleet), - Header: () => { + Header: (cellProps: ITableHeaderProps) => { const titleWithToolTip = ( ); - return ; + return ( + + ); }, - disableSortBy: true, Cell: (cellProps: ITableStringCellProps) => ( ), }, { id: "ipados_team", + sortType: "caseInsensitive", accessor: (originalRow) => getFleetDisplayName(originalRow.ipados_fleet), - Header: () => { + Header: (cellProps: ITableHeaderProps) => { const titleWithToolTip = ( ); - return ; + return ( + + ); + }, + Cell: (cellProps: ITableStringCellProps) => ( + + ), + }, + { + id: "byod_team", + sortType: "caseInsensitive", + accessor: (originalRow) => getFleetDisplayName(originalRow.byod_fleet), + Header: (cellProps: ITableHeaderProps) => { + const titleWithToolTip = ( + + iOS/iPadOS hosts that enroll via Managed Apple Account are + automatically added to this fleet. + + } + > + BYOD fleet + + ); + return ( + + ); }, - disableSortBy: true, Cell: (cellProps: ITableStringCellProps) => ( ), diff --git a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/AppleBusinessManagerTable/_styles.scss b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/AppleBusinessManagerTable/_styles.scss index 85662dc6312..70b53495a19 100644 --- a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/AppleBusinessManagerTable/_styles.scss +++ b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/AppleBusinessManagerTable/_styles.scss @@ -1,12 +1,9 @@ .apple-business-manager-table { .data-table-block .data-table { - td.apple_id__cell { - max-width: 180px; - } - td.macos_team__cell, td.ios_team__cell, - td.ipados_team__cell { + td.ipados_team__cell, + td.byod_team__cell { max-width: 150px; } @@ -16,6 +13,10 @@ align-items: center; } } + + th.id__header { + border: none; + } } // The desired behavior is to hide the header and team cell one by one @@ -23,22 +24,22 @@ // media query with the breakpoint values taken from when the table content // starts to overflow. @media (max-width: $break-lg) { - .ipados_team__header, - .ipados_team__cell { + .byod_team__header, + .byod_team__cell { display: none; } } @media (max-width: 1230px) { - .ios_team__header, - .ios_team__cell { + .ipados_team__header, + .ipados_team__cell { display: none; } } @media (max-width: $break-md) { - .macos_team__header, - .macos_team__cell { + .ios_team__header, + .ios_team__cell { display: none; } } diff --git a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/EditTeamsAbmModal/EditTeamsAbmModal.tests.ts b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/EditTeamsAbmModal/EditTeamsAbmModal.tests.ts index 7744072253f..9c3b1f31fb6 100644 --- a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/EditTeamsAbmModal/EditTeamsAbmModal.tests.ts +++ b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/EditTeamsAbmModal/EditTeamsAbmModal.tests.ts @@ -10,6 +10,7 @@ describe("EditTeamsAbmModal", () => { APP_CONTEXT_NO_TEAM_SUMMARY, { name: "Team 1", id: 1 }, { name: "Team 2", id: 2 }, + { name: "BYOD Fleet", id: 3 }, ]; describe("getOptions", () => { @@ -30,11 +31,13 @@ describe("EditTeamsAbmModal", () => { ios_team: "Team 1", ipados_team: "Team 2", macos_team: "Unassigned", + byod_team: "BYOD Fleet", }; expect(getSelectedTeamIds(selectedTeamNames, availableTeams)).toEqual({ ios_fleet_id: 1, ipados_fleet_id: 2, macos_fleet_id: 0, + byod_fleet_id: 3, }); }); }); diff --git a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/EditTeamsAbmModal/EditTeamsAbmModal.tsx b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/EditTeamsAbmModal/EditTeamsAbmModal.tsx index 7a954ee104d..4dc5e6b6fdc 100644 --- a/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/EditTeamsAbmModal/EditTeamsAbmModal.tsx +++ b/frontend/pages/admin/IntegrationsPage/cards/MdmSettings/AppleBusinessManagerPage/components/EditTeamsAbmModal/EditTeamsAbmModal.tsx @@ -12,6 +12,8 @@ import Modal from "components/Modal"; // @ts-ignore import Dropdown from "components/forms/fields/Dropdown"; import Button from "components/buttons/Button"; +import FormField from "components/forms/FormField"; +import RenewDateCell from "../../../components/RenewDateCell"; const baseClass = "edit-teams-abm-modal"; @@ -41,6 +43,7 @@ interface SelectedTeamNames { ios_team: IMdmAbToken["ios_fleet"]["name"]; ipados_team: IMdmAbToken["ipados_fleet"]["name"]; macos_team: IMdmAbToken["macos_fleet"]["name"]; + byod_team: IMdmAbToken["byod_fleet"]["name"]; } /** @@ -56,7 +59,7 @@ type SelectedTeamIds = Parameters[0]["teams"]; * `validateSelectedTeamIds` function). */ export const getSelectedTeamIds = ( - { ios_team, ipados_team, macos_team }: SelectedTeamNames, + { ios_team, ipados_team, macos_team, byod_team }: SelectedTeamNames, availableTeams: ITeamSummary[] = [] ): SelectedTeamIds => { const byName = availableTeams.reduce((acc, t) => { @@ -67,6 +70,7 @@ export const getSelectedTeamIds = ( ios_fleet_id: byName[ios_team], ipados_fleet_id: byName[ipados_team], macos_fleet_id: byName[macos_team], + byod_fleet_id: byName[byod_team], }; }; @@ -85,6 +89,7 @@ const EditTeamsAbmModal = ({ ios_team: token.ios_fleet.name, ipados_team: token.ipados_fleet.name, macos_team: token.macos_fleet.name, + byod_team: token.byod_fleet.name, } ); @@ -107,7 +112,7 @@ const EditTeamsAbmModal = ({ tokenId: token.id, teams: getSelectedTeamIds(selectedTeamNames, availableTeams), }); - renderFlash("success", "Edited successfully."); + renderFlash("success", "Successfully updated fleets for AB token."); onSuccess(); } catch (e) { renderFlash("error", "Couldn’t edit. Please try again."); @@ -127,15 +132,21 @@ const EditTeamsAbmModal = ({ return ( -

- Edit fleets for {token.org_name}. -

+ +

{token.apple_id}

+
+ + + - macOS hosts are automatically added to this fleet on initial sync - from ABM. If a host is manually assigned to a different fleet - before enrollment, it will enroll to the newly assigned fleet and - not the default. - - } /> - iOS hosts are automatically added to this fleet on initial sync - from ABM. If a host is manually assigned to a different fleet - before enrollment, it will enroll to the newly assigned fleet and - not the default. - - } /> - iPadOS hosts are automatically added to this fleet on initial sync - from ABM. If a host is manually assigned to a different fleet - before enrollment, it will enroll to the newly assigned fleet and - not the default. - + /> + + setSelectedTeamNames((prev) => ({ ...prev, byod_team: value })) } + value={selectedTeamNames.byod_team} + label="BYOD fleet" + wrapperClassName={`${baseClass}__form-field form-field--byod`} />