Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Frontend of iOS/iPadOS as platforms/labels #20157

Merged
merged 14 commits into from
Jul 9, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
56 changes: 9 additions & 47 deletions frontend/components/AddHostsModal/AddHostsModal.tests.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -57,15 +57,13 @@ describe("AddHostsModal", () => {
expect(windowsText).toBeInTheDocument();
expect(screen.queryByText(/--enable-scripts/i)).toBeInTheDocument();

await user.click(screen.getByRole("tab", { name: "Linux (RPM)" }));
const linuxRPMText = screen.getByText(/--type=rpm/i);
expect(linuxRPMText).toBeInTheDocument();
expect(screen.queryByText(/--enable-scripts/i)).toBeInTheDocument();

await user.click(screen.getByRole("tab", { name: "Linux (deb)" }));
await user.click(screen.getByRole("tab", { name: "Linux" }));
const linuxDebText = screen.getByText(/--type=deb/i);
expect(linuxDebText).toBeInTheDocument();
expect(screen.queryByText(/--enable-scripts/i)).toBeInTheDocument();
expect(
screen.queryByText(/CentOS, Red Hat, and Fedora Linux, use --type=rpm/i)
).toBeInTheDocument();

await user.click(screen.getByRole("tab", { name: "ChromeOS" }));
const extensionId = screen.getByDisplayValue(
Expand All @@ -74,6 +72,10 @@ describe("AddHostsModal", () => {
expect(extensionId).toBeInTheDocument();
expect(screen.queryByText(/--enable-scripts/i)).not.toBeInTheDocument();

await user.click(screen.getByRole("tab", { name: "iOS & iPadOS" }));
expect(screen.queryByText(/Apple Business Manager/i)).toBeInTheDocument();
expect(screen.queryByText(/Learn more/i)).toBeInTheDocument();

await user.click(screen.getByRole("tab", { name: "Advanced" }));
const advancedText = screen.getByText(/--type=YOUR_TYPE/i);
expect(advancedText).toBeInTheDocument();
Expand Down Expand Up @@ -146,41 +148,6 @@ describe("AddHostsModal", () => {
expect(ctaButton).toBeEnabled();
});

it("sandbox mode renders and download disabled until a platform is selected", async () => {
const render = createCustomRenderer({
withBackendMock: true,
context: {
app: {
isPreviewMode: false,
config: createMockConfig(),
},
},
});

const { user } = render(
<AddHostsModal
enrollSecret={ENROLL_SECRET}
isAnyTeamSelected={false}
isLoading={false}
isSandboxMode
onCancel={noop}
/>
);

const text = screen.getByText("Which platform is your host running?");
const windowsText = screen.getByText("Windows");
const downloadButton = screen.getByRole("button", {
name: /Download installer/i,
});

expect(text).toBeInTheDocument();
expect(downloadButton).not.toBeEnabled();

await user.click(windowsText);

expect(downloadButton).toBeEnabled();
});

it("excludes `--enable-scripts` flag if `config.server_settings.scripts-disabled` is `true`", async () => {
const mockConfig = createMockConfig();
mockConfig.server_settings.scripts_disabled = true;
Expand Down Expand Up @@ -214,16 +181,11 @@ describe("AddHostsModal", () => {
expect(windowsText).toBeInTheDocument();
expect(screen.queryByText(/--enable-scripts/i)).not.toBeInTheDocument();

await user.click(screen.getByRole("tab", { name: "Linux (RPM)" }));
await user.click(screen.getByRole("tab", { name: "Linux" }));
const linuxRPMText = screen.getByText(/--type=rpm/i);
expect(linuxRPMText).toBeInTheDocument();
expect(screen.queryByText(/--enable-scripts/i)).not.toBeInTheDocument();

await user.click(screen.getByRole("tab", { name: "Linux (deb)" }));
const linuxDebText = screen.getByText(/--type=deb/i);
expect(linuxDebText).toBeInTheDocument();
expect(screen.queryByText(/--enable-scripts/i)).not.toBeInTheDocument();

await user.click(screen.getByRole("tab", { name: "ChromeOS" }));
const extensionId = screen.getByDisplayValue(
/fleeedmmihkfkeemmipgmhhjemlljidg/i
Expand Down
12 changes: 1 addition & 11 deletions frontend/components/AddHostsModal/AddHostsModal.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@
import Spinner from "components/Spinner";

import PlatformWrapper from "./PlatformWrapper/PlatformWrapper";
import DownloadInstallers from "./DownloadInstallers/DownloadInstallers";

Check warning on line 12 in frontend/components/AddHostsModal/AddHostsModal.tsx

View workflow job for this annotation

GitHub Actions / lint-js (ubuntu-latest)

'DownloadInstallers' is defined but never used

const baseClass = "add-hosts-modal";

Expand All @@ -18,7 +18,6 @@
enrollSecret?: string;
isAnyTeamSelected: boolean;
isLoading: boolean;
isSandboxMode?: boolean;
onCancel: () => void;
openEnrollSecretModal?: () => void;
}
Expand All @@ -28,7 +27,6 @@
enrollSecret,
isAnyTeamSelected,
isLoading,
isSandboxMode,
onCancel,
openEnrollSecretModal,
}: IAddHostsModal): JSX.Element => {
Expand All @@ -53,12 +51,6 @@
openEnrollSecretModal && openEnrollSecretModal();
};

// TODO: Currently, prepacked installers in Fleet Sandbox use the global enroll secret,
// and Fleet Sandbox runs Fleet Free so the currentTeam check here is an
// additional precaution/reminder to revisit this in connection with future changes.
// See https://github.com/fleetdm/fleet/issues/4970#issuecomment-1187679407.
const shouldRenderDownloadInstallersContent =
isSandboxMode && !isAnyTeamSelected;
const renderModalContent = () => {
if (isLoading) {
return <Spinner />;
Expand All @@ -81,9 +73,7 @@
);
}

return shouldRenderDownloadInstallersContent ? (
<DownloadInstallers onCancel={onCancel} enrollSecret={enrollSecret} />
) : (
return (
<PlatformWrapper
onCancel={onCancel}
enrollSecret={enrollSecret}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -35,17 +35,17 @@
type: "msi",
},
{
name: "Linux (RPM)",
type: "rpm",
},
{
name: "Linux (deb)",
name: "Linux",
type: "deb",
},
{
name: "ChromeOS",
type: "chromeos",
},
{
name: "iOS & iPadOS",
type: "ios-ipados",
},
{
name: "Advanced",
type: "advanced",
Expand All @@ -55,9 +55,9 @@
interface IPlatformWrapperProps {
enrollSecret: string;
onCancel: () => void;
certificate: any;

Check warning on line 58 in frontend/components/AddHostsModal/PlatformWrapper/PlatformWrapper.tsx

View workflow job for this annotation

GitHub Actions / lint-js (ubuntu-latest)

Unexpected any. Specify a different type
isFetchingCertificate: boolean;
fetchCertificateError: any;

Check warning on line 60 in frontend/components/AddHostsModal/PlatformWrapper/PlatformWrapper.tsx

View workflow job for this annotation

GitHub Actions / lint-js (ubuntu-latest)

Unexpected any. Specify a different type
config: IConfig | null;
}

Expand Down Expand Up @@ -393,6 +393,23 @@
</>
);
}

if (packageType === "ios-ipados") {
return (
<div className={`${baseClass}__ios-ipados--info`}>
<p>
Enroll iPhones and iPads by adding them to Fleet in Apple Business
Manager (ABM).{" "}
<CustomLink
url="https://fleetdm.com/learn-more-about/setup-abm"
text="Learn more"
newTab
/>
</p>
</div>
);
}

if (packageType === "advanced") {
return (
<>
Expand Down Expand Up @@ -539,7 +556,11 @@
label={renderLabel(packageType, renderInstallerString(packageType))}
type="textarea"
value={renderInstallerString(packageType)}
helpText="Distribute your package to add hosts to Fleet."
helpText={`Distribute your package to add hosts to Fleet.${
packageType === "deb"
? " For CentOS, Red Hat, and Fedora Linux, use --type=rpm."
: ""
}`}
/>
</>
);
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -8,7 +8,7 @@
position: initial;
.react-tabs {
&__tab-list {
margin: 0 0 1.25rem;
margin: 0 0 $pad-large;
}
}
}
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -7,7 +7,7 @@ describe("Platform compatibility", () => {
it("renders compatible platforms", () => {
render(
<PlatformCompatibility
compatiblePlatforms={["macOS", "Windows"]}
compatiblePlatforms={["darwin", "windows"]}
error={null}
/>
);
Expand Down Expand Up @@ -38,7 +38,7 @@ describe("Platform compatibility", () => {
it("renders error state", () => {
render(
<PlatformCompatibility
compatiblePlatforms={["macOS"]}
compatiblePlatforms={["macos"]}
error={{ name: "Error", message: "The resource was not found." }}
/>
);
Expand Down
Original file line number Diff line number Diff line change
@@ -1,13 +1,17 @@
import React from "react";

import { OsqueryPlatform } from "interfaces/platform";
import {
DisplayPlatform,
QueryableDisplayPlatform,
QueryablePlatform,
} from "interfaces/platform";
import { PLATFORM_DISPLAY_NAMES } from "utilities/constants";

import TooltipWrapper from "components/TooltipWrapper";
import Icon from "components/Icon";

interface IPlatformCompatibilityProps {
compatiblePlatforms: OsqueryPlatform[] | null;
compatiblePlatforms: any[] | null;
RachelElysia marked this conversation as resolved.
Show resolved Hide resolved
error: Error | null;
}

Expand All @@ -18,13 +22,13 @@ const DISPLAY_ORDER = [
"Windows",
"Linux",
"ChromeOS",
] as OsqueryPlatform[];
] as QueryableDisplayPlatform[];
Copy link
Contributor

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

For speed this can be on another iteration but can we still improve the typing on line 14?


const ERROR_NO_COMPATIBLE_TABLES = Error("no tables in query");

const formatPlatformsForDisplay = (
compatiblePlatforms: OsqueryPlatform[]
): OsqueryPlatform[] => {
compatiblePlatforms: QueryablePlatform[]
): DisplayPlatform[] => {
return compatiblePlatforms.map((str) => PLATFORM_DISPLAY_NAMES[str] || str);
};

Expand Down Expand Up @@ -83,8 +87,9 @@ const PlatformCompatibility = ({
<TooltipWrapper
tipContent={
<>
Estimated compatiblity based on <br /> the tables used in the
query.
Estimated compatibility based on the <br />
tables used in the query. Querying <br />
iPhones & iPads is not supported.
</>
}
>
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -2,10 +2,10 @@ import React from "react";
import { render, screen } from "@testing-library/react";
import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";

import { SupportedPlatform } from "interfaces/platform";
import { QueryablePlatform } from "interfaces/platform";
import PlatformCell from "./PlatformCell";

const PLATFORMS: SupportedPlatform[] = ["windows", "darwin", "linux", "chrome"];
const PLATFORMS: QueryablePlatform[] = ["windows", "darwin", "linux", "chrome"];

describe("Platform cell", () => {
it("renders platform icons in correct order", () => {
Expand Down
Original file line number Diff line number Diff line change
@@ -1,22 +1,22 @@
import React from "react";
import Icon from "components/Icon";
import { SupportedPlatform } from "interfaces/platform";
import { QueryablePlatform } from "interfaces/platform";
import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";

interface IPlatformCellProps {
platforms: SupportedPlatform[];
platforms: QueryablePlatform[];
}

const baseClass = "platform-cell";

const ICONS: Record<string, "darwin" | "windows" | "linux" | "chrome"> = {
const ICONS: Record<string, QueryablePlatform> = {
darwin: "darwin",
windows: "windows",
linux: "linux",
chrome: "chrome",
};

const DISPLAY_ORDER: SupportedPlatform[] = [
const DISPLAY_ORDER: QueryablePlatform[] = [
"darwin",
"windows",
"linux",
Expand Down
2 changes: 1 addition & 1 deletion frontend/components/buttons/Button/Button.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -13,7 +13,7 @@ export type ButtonVariant =
| "warning"
| "link"
| "label"
| "text-link"
| "text-link" // Underlines on hover
| "text-icon"
| "icon" // Buttons without text
| "small-icon" // Buttons without text
Expand Down
42 changes: 42 additions & 0 deletions frontend/components/icons/iOS.tsx
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
import React from "react";
import { COLORS, Colors } from "styles/var/colors";
import { ICON_SIZES, IconSizes } from "styles/var/icon_sizes";

interface IiOSProps {
size: IconSizes;
color?: Colors;
}

const iOS = ({ size = "medium", color = "ui-fleet-black-75" }: IiOSProps) => {
return (
<svg
width={ICON_SIZES[size]}
height={ICON_SIZES[size]}
fill="none"
xmlns="http://www.w3.org/2000/svg"
viewBox="0 0 24 24"
>
<rect
x="5.25"
y=".75"
width="13.5"
height="22.5"
rx="1.25"
stroke={COLORS[color]}
strokeWidth="1.5"
/>
<path
fillRule="evenodd"
clipRule="evenodd"
d="M13.665 7.875c.053.442-.159.876-.441 1.192-.29.324-.767.56-1.225.529-.062-.426.167-.876.44-1.153.3-.315.803-.552 1.226-.568Zm.784 4.65v.007c.15.293.573.735.926.845a.7.7 0 0 1-.018.051c-.006.018-.013.036-.017.052-.097.268-.362.718-.538.955-.353.458-.705.908-1.278.931-.27-.003-.45-.074-.634-.145-.203-.079-.41-.159-.742-.155-.34-.004-.554.08-.76.162-.179.07-.352.139-.597.146-.547.024-.961-.49-1.314-.94-.167-.236-.44-.702-.538-.946-.097-.23-.238-.687-.264-.924v-.016c-.035-.237-.07-.726-.035-.915v-.016c.026-.292.185-.758.326-.955.352-.553.96-.916 1.648-.932l.106-.008h.009c.294-.013.579.092.83.184.194.071.368.135.51.132.137.003.324-.06.538-.133.306-.104.669-.227 1.022-.199.6.008 1.182.26 1.543.735a3.243 3.243 0 0 0-.29.213c0 .008-.01.008-.01.008-.229.15-.51.552-.564.947v.008c-.053.3.01.67.141.907Z"
fill={COLORS[color]}
/>
<path
d="M9.75 1h4.5v1a.5.5 0 0 1-.5.5h-3.5a.5.5 0 0 1-.5-.5V1Z"
fill={COLORS[color]}
/>
</svg>
);
};

export default iOS;
Loading
Loading