mirror of
https://github.com/fleetdm/fleet
synced 2026-04-21 13:37:30 +00:00
Fleet UI: Add iOS/iPadOS OS updates version requirements UI (#20591)
This commit is contained in:
parent
083e49e0eb
commit
275a09e361
18 changed files with 337 additions and 208 deletions
BIN
assets/images/ios-updates-preview.png
Normal file
BIN
assets/images/ios-updates-preview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 95 KiB |
BIN
assets/images/ipados-updates-preview.png
Normal file
BIN
assets/images/ipados-updates-preview.png
Normal file
Binary file not shown.
|
After Width: | Height: | Size: 98 KiB |
|
|
@ -1,24 +1,16 @@
|
|||
export type AppleDisplayPlatform = "macOS" | "iOS" | "iPadOS";
|
||||
export type DisplayPlatform =
|
||||
| "macOS"
|
||||
| AppleDisplayPlatform
|
||||
| "Windows"
|
||||
| "Linux"
|
||||
| "ChromeOS"
|
||||
| "iOS"
|
||||
| "iPadOS";
|
||||
|
||||
export type Platform =
|
||||
| "darwin"
|
||||
| "windows"
|
||||
| "linux"
|
||||
| "chrome"
|
||||
| "ios"
|
||||
| "ipados";
|
||||
|
||||
| "ChromeOS";
|
||||
export type QueryableDisplayPlatform = Exclude<
|
||||
DisplayPlatform,
|
||||
"iOS" | "iPadOS"
|
||||
>;
|
||||
|
||||
export type ApplePlatform = "darwin" | "ios" | "ipados";
|
||||
export type Platform = ApplePlatform | "windows" | "linux" | "chrome";
|
||||
export type QueryablePlatform = Exclude<Platform, "ios" | "ipados">;
|
||||
|
||||
export const SUPPORTED_PLATFORMS: QueryablePlatform[] = [
|
||||
|
|
|
|||
|
|
@ -4,6 +4,8 @@ import { formatDistanceToNowStrict } from "date-fns";
|
|||
|
||||
import { ActivityType, IActivity, IActivityDetails } from "interfaces/activity";
|
||||
import { getInstallStatusPredicate } from "interfaces/software";
|
||||
import { AppleDisplayPlatform } from "interfaces/platform";
|
||||
|
||||
import {
|
||||
addGravatarUrlToResource,
|
||||
formatScriptNameForActivityItem,
|
||||
|
|
@ -305,8 +307,8 @@ const TAGGED_TEMPLATES = {
|
|||
);
|
||||
},
|
||||
editedAppleosMinVersion: (
|
||||
activity: IActivity,
|
||||
osType: "darwin" | "ios" | "ipados"
|
||||
applePlatform: AppleDisplayPlatform,
|
||||
activity: IActivity
|
||||
) => {
|
||||
const editedActivity =
|
||||
activity.details?.minimum_version === "" ? "removed" : "updated";
|
||||
|
|
@ -331,7 +333,7 @@ const TAGGED_TEMPLATES = {
|
|||
|
||||
return (
|
||||
<>
|
||||
{editedActivity} the minimum macOS version {versionSection}{" "}
|
||||
{editedActivity} the minimum {applePlatform} version {versionSection}{" "}
|
||||
{deadlineSection} on hosts assigned to {teamSection}.
|
||||
</>
|
||||
);
|
||||
|
|
@ -977,13 +979,13 @@ const getDetail = (
|
|||
return TAGGED_TEMPLATES.mdmUnenrolled(activity);
|
||||
}
|
||||
case ActivityType.EditedMacosMinVersion: {
|
||||
return TAGGED_TEMPLATES.editedAppleosMinVersion(activity, "darwin");
|
||||
return TAGGED_TEMPLATES.editedAppleosMinVersion("macOS", activity);
|
||||
}
|
||||
case ActivityType.EditedIosMinVersion: {
|
||||
return TAGGED_TEMPLATES.editedAppleosMinVersion(activity, "ios");
|
||||
return TAGGED_TEMPLATES.editedAppleosMinVersion("iOS", activity);
|
||||
}
|
||||
case ActivityType.EditedIpadosMinVersion: {
|
||||
return TAGGED_TEMPLATES.editedAppleosMinVersion(activity, "ipados");
|
||||
return TAGGED_TEMPLATES.editedAppleosMinVersion("iPadOS", activity);
|
||||
}
|
||||
|
||||
case ActivityType.ReadHostDiskEncryptionKey: {
|
||||
|
|
|
|||
|
|
@ -6,6 +6,7 @@ import { AppContext } from "context/app";
|
|||
|
||||
import { IConfig } from "interfaces/config";
|
||||
import { ITeamConfig } from "interfaces/team";
|
||||
import { ApplePlatform } from "interfaces/platform";
|
||||
|
||||
import configAPI from "services/entities/config";
|
||||
import teamsAPI, { ILoadTeamResponse } from "services/entities/teams";
|
||||
|
|
@ -13,17 +14,13 @@ import teamsAPI, { ILoadTeamResponse } from "services/entities/teams";
|
|||
import PremiumFeatureMessage from "components/PremiumFeatureMessage";
|
||||
import Spinner from "components/Spinner";
|
||||
|
||||
import NudgePreview from "./components/NudgePreview";
|
||||
import EndUserOSRequirementPreview from "./components/EndUserOSRequirementPreview";
|
||||
import TurnOnMdmMessage from "../components/TurnOnMdmMessage/TurnOnMdmMessage";
|
||||
import CurrentVersionSection from "./components/CurrentVersionSection";
|
||||
import TargetSection from "./components/TargetSection";
|
||||
import { parseOSUpdatesCurrentVersionsQueryParams } from "./components/CurrentVersionSection/CurrentVersionSection";
|
||||
|
||||
export type OSUpdatesSupportedPlatform =
|
||||
| "darwin"
|
||||
| "windows"
|
||||
| "iOS"
|
||||
| "iPadOS";
|
||||
export type OSUpdatesSupportedPlatform = ApplePlatform | "windows";
|
||||
|
||||
const baseClass = "os-updates";
|
||||
|
||||
|
|
@ -121,7 +118,7 @@ const OSUpdates = ({ router, teamIdForApi, queryParams }: IOSUpdates) => {
|
|||
queryParams={queryParams}
|
||||
/>
|
||||
</div>
|
||||
<div className={`${baseClass}__taget-container`}>
|
||||
<div className={`${baseClass}__target-container`}>
|
||||
<TargetSection
|
||||
key={teamIdForApi} // if the team changes, remount the target section
|
||||
appConfig={config}
|
||||
|
|
@ -135,7 +132,7 @@ const OSUpdates = ({ router, teamIdForApi, queryParams }: IOSUpdates) => {
|
|||
/>
|
||||
</div>
|
||||
<div className={`${baseClass}__nudge-preview`}>
|
||||
<NudgePreview platform={selectedPlatform} />
|
||||
<EndUserOSRequirementPreview platform={selectedPlatform} />
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
|||
|
|
@ -10,15 +10,16 @@ import teamsAPI from "services/entities/teams";
|
|||
import InputField from "components/forms/fields/InputField";
|
||||
import Button from "components/buttons/Button";
|
||||
import validatePresence from "components/forms/validators/validate_presence";
|
||||
import { ApplePlatform } from "interfaces/platform";
|
||||
|
||||
const baseClass = "mac-os-target-form";
|
||||
const baseClass = "apple-os-target-form";
|
||||
|
||||
interface IMacOSTargetFormData {
|
||||
interface IAppleOSTargetFormData {
|
||||
minOsVersion: string;
|
||||
deadline: string;
|
||||
}
|
||||
|
||||
interface IMacOSTargetFormErrors {
|
||||
interface IAppleOSTargetFormErrors {
|
||||
minOsVersion?: string;
|
||||
deadline?: string;
|
||||
}
|
||||
|
|
@ -31,8 +32,16 @@ const validateDeadline = (value: string) => {
|
|||
return /^\d{4}-(0[1-9]|1[012])-(0[1-9]|[12][0-9]|3[01])$/.test(value);
|
||||
};
|
||||
|
||||
const validateForm = (formData: IMacOSTargetFormData) => {
|
||||
const errors: IMacOSTargetFormErrors = {};
|
||||
const validateForm = (formData: IAppleOSTargetFormData) => {
|
||||
const errors: IAppleOSTargetFormErrors = {};
|
||||
|
||||
// Both fields may be cleared out and saved
|
||||
if (
|
||||
!validatePresence(formData.minOsVersion) &&
|
||||
!validatePresence(formData.deadline)
|
||||
) {
|
||||
return errors;
|
||||
}
|
||||
|
||||
if (!validatePresence(formData.minOsVersion)) {
|
||||
errors.minOsVersion = "The minimum version is required.";
|
||||
|
|
@ -49,22 +58,37 @@ const validateForm = (formData: IMacOSTargetFormData) => {
|
|||
return errors;
|
||||
};
|
||||
|
||||
interface IMacMdmConfigData {
|
||||
const APPLE_PLATFORMS_TO_CONFIG_FIELDS = {
|
||||
darwin: "macos_updates",
|
||||
ios: "ios_updates",
|
||||
ipados: "ipados_updates",
|
||||
};
|
||||
|
||||
interface IAppleUpdatesMdmConfigData {
|
||||
mdm: {
|
||||
macos_updates: {
|
||||
macos_updates?: {
|
||||
minimum_version: string;
|
||||
deadline: string;
|
||||
};
|
||||
ipados_updates?: {
|
||||
minimum_version: string;
|
||||
deadline: string;
|
||||
};
|
||||
ios_updates?: {
|
||||
minimum_version: string;
|
||||
deadline: string;
|
||||
};
|
||||
};
|
||||
}
|
||||
|
||||
const createMdmConfigData = (
|
||||
const createAppleOSUpdatesData = (
|
||||
applePlatform: ApplePlatform,
|
||||
minOsVersion: string,
|
||||
deadline: string
|
||||
): IMacMdmConfigData => {
|
||||
): IAppleUpdatesMdmConfigData => {
|
||||
return {
|
||||
mdm: {
|
||||
macos_updates: {
|
||||
[APPLE_PLATFORMS_TO_CONFIG_FIELDS[applePlatform]]: {
|
||||
minimum_version: minOsVersion,
|
||||
deadline,
|
||||
},
|
||||
|
|
@ -72,21 +96,23 @@ const createMdmConfigData = (
|
|||
};
|
||||
};
|
||||
|
||||
interface IMacOSTargetFormProps {
|
||||
interface IAppleOSTargetFormProps {
|
||||
currentTeamId: number;
|
||||
applePlatform: ApplePlatform;
|
||||
defaultMinOsVersion: string;
|
||||
defaultDeadline: string;
|
||||
refetchAppConfig: () => void;
|
||||
refetchTeamConfig: () => void;
|
||||
}
|
||||
|
||||
const MacOSTargetForm = ({
|
||||
const AppleOSTargetForm = ({
|
||||
currentTeamId,
|
||||
applePlatform,
|
||||
defaultMinOsVersion,
|
||||
defaultDeadline,
|
||||
refetchAppConfig,
|
||||
refetchTeamConfig,
|
||||
}: IMacOSTargetFormProps) => {
|
||||
}: IAppleOSTargetFormProps) => {
|
||||
const { renderFlash } = useContext(NotificationContext);
|
||||
|
||||
const [isSaving, setIsSaving] = useState(false);
|
||||
|
|
@ -111,7 +137,11 @@ const MacOSTargetForm = ({
|
|||
|
||||
if (isEmpty(errors)) {
|
||||
setIsSaving(true);
|
||||
const updateData = createMdmConfigData(minOsVersion, deadline);
|
||||
const updateData = createAppleOSUpdatesData(
|
||||
applePlatform,
|
||||
minOsVersion,
|
||||
deadline
|
||||
);
|
||||
try {
|
||||
currentTeamId === APP_CONTEXT_NO_TEAM_ID
|
||||
? await configAPI.update(updateData)
|
||||
|
|
@ -136,22 +166,58 @@ const MacOSTargetForm = ({
|
|||
setDeadline(val);
|
||||
};
|
||||
|
||||
const getMinimumVersionPlaceholder = (platform: ApplePlatform) => {
|
||||
switch (platform) {
|
||||
case "darwin":
|
||||
return "13.0.1";
|
||||
case "ios":
|
||||
case "ipados":
|
||||
return "17.5.1";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
const getMinimumVersionTooltip = (platform: ApplePlatform) => {
|
||||
switch (platform) {
|
||||
case "darwin":
|
||||
return "The end user sees the window until their macOS is at or above this version.";
|
||||
case "ios":
|
||||
case "ipados":
|
||||
return "If the end user's host is below the minimum version, they see a notification in their Notification Center after the deadline. They can’t continue until the OS update is installed.";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
const getDeadlineTooltip = (platform: ApplePlatform) => {
|
||||
switch (platform) {
|
||||
case "darwin":
|
||||
return "The end user can't dismiss the window once they reach this deadline. Deadline is at 12:00 (Noon) Pacific Standard Time (GMT-8).";
|
||||
case "ios":
|
||||
case "ipados":
|
||||
return "Deadline is at 12:00 (Noon) Pacific Standard Time (GMT-8).";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<form className={baseClass} onSubmit={handleSubmit}>
|
||||
<InputField
|
||||
label="Minimum version"
|
||||
tooltip="The end user sees the window until their macOS is at or above this version."
|
||||
tooltip={getMinimumVersionTooltip(applePlatform)}
|
||||
helpText="Version number only (e.g., “13.0.1” not “Ventura 13” or “13.0.1 (22A400)”)"
|
||||
placeholder="13.0.1"
|
||||
placeholder={getMinimumVersionPlaceholder(applePlatform)}
|
||||
value={minOsVersion}
|
||||
error={minOsVersionError}
|
||||
onChange={handleMinVersionChange}
|
||||
/>
|
||||
<InputField
|
||||
label="Deadline"
|
||||
tooltip="The end user can’t dismiss the window once they reach this deadline. Deadline is at 12:00 (Noon) Pacific Standard Time (GMT-8)."
|
||||
helpText="YYYY-MM-DD format only (e.g., “2023-06-01”)."
|
||||
placeholder="2023-06-01"
|
||||
tooltip={getDeadlineTooltip(applePlatform)}
|
||||
helpText="YYYY-MM-DD format only (e.g., “2024-07-01”)."
|
||||
placeholder="2024-07-01"
|
||||
value={deadline}
|
||||
error={deadlineError}
|
||||
onChange={handleDeadlineChange}
|
||||
|
|
@ -163,4 +229,4 @@ const MacOSTargetForm = ({
|
|||
);
|
||||
};
|
||||
|
||||
export default MacOSTargetForm;
|
||||
export default AppleOSTargetForm;
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from "./AppleOSTargetForm";
|
||||
|
|
@ -1,29 +0,0 @@
|
|||
import React from "react";
|
||||
|
||||
import CustomLink from "components/CustomLink";
|
||||
|
||||
const baseClass = "empty-target-form";
|
||||
|
||||
interface IEmptyTargetFormProps {
|
||||
targetPlatform: string;
|
||||
}
|
||||
|
||||
const EmptyTargetForm = ({ targetPlatform }: IEmptyTargetFormProps) => {
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<p>
|
||||
<b>{targetPlatform} updates are coming soon.</b>
|
||||
</p>
|
||||
<p>
|
||||
Need to remotely encourage installation of {targetPlatform} updates?{" "}
|
||||
<CustomLink
|
||||
url="https://www.fleetdm.com/support"
|
||||
text="Let us know"
|
||||
newTab
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EmptyTargetForm;
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from "./EmptyTargetForm";
|
||||
|
|
@ -0,0 +1,112 @@
|
|||
import React from "react";
|
||||
|
||||
import CustomLink from "components/CustomLink";
|
||||
|
||||
import { OSUpdatesSupportedPlatform } from "../../OSUpdates";
|
||||
|
||||
import MacOSUpdateScreenshot from "../../../../../../assets/images/macos-updates-preview.png";
|
||||
import WindowsUpdateScreenshot from "../../../../../../assets/images/windows-nudge-screenshot.png";
|
||||
import IOSUpdateScreenshot from "../../../../../../assets/images/ios-updates-preview.png";
|
||||
import IPadOSUpdateScreenshot from "../../../../../../assets/images/ipados-updates-preview.png";
|
||||
|
||||
const baseClass = "os-requirement-preview";
|
||||
|
||||
interface IEndUserOSRequirementPreviewProps {
|
||||
platform: OSUpdatesSupportedPlatform;
|
||||
}
|
||||
const OSRequirementDescription = ({
|
||||
platform,
|
||||
}: IEndUserOSRequirementPreviewProps) => {
|
||||
switch (platform) {
|
||||
case "darwin":
|
||||
return (
|
||||
<>
|
||||
<h3>End user experience on macOS</h3>
|
||||
<p>
|
||||
For macOS 14 and above, end users will see native macOS
|
||||
notifications (DDM).
|
||||
</p>
|
||||
<p>Everyone else will see the Nudge window.</p>
|
||||
<CustomLink
|
||||
text="Learn more"
|
||||
url="https://fleetdm.com/learn-more-about/os-updates"
|
||||
newTab
|
||||
/>
|
||||
</>
|
||||
);
|
||||
case "windows":
|
||||
return (
|
||||
<>
|
||||
<h3>End user experience on Windows</h3>
|
||||
<p>
|
||||
When a Windows host becomes aware of a new update, end users are
|
||||
able to defer restarts. Automatic restarts happen before 8am and
|
||||
after 5pm (end user's local time). After the deadline, restarts
|
||||
are forced regardless of active hours.
|
||||
</p>
|
||||
<CustomLink
|
||||
text="Learn more about Windows updates in Fleet"
|
||||
url="https://fleetdm.com/learn-more-about/os-updates"
|
||||
newTab
|
||||
/>
|
||||
</>
|
||||
);
|
||||
case "ios":
|
||||
return (
|
||||
<>
|
||||
<h3>End user experience on iOS</h3>
|
||||
</>
|
||||
);
|
||||
case "ipados":
|
||||
return (
|
||||
<>
|
||||
<h3>End user experience on iPadOS</h3>
|
||||
</>
|
||||
);
|
||||
default:
|
||||
return <></>;
|
||||
}
|
||||
};
|
||||
|
||||
const OSRequirementImage = ({
|
||||
platform,
|
||||
}: IEndUserOSRequirementPreviewProps) => {
|
||||
const getScreenshot = () => {
|
||||
switch (platform) {
|
||||
case "darwin":
|
||||
return MacOSUpdateScreenshot;
|
||||
case "windows":
|
||||
return WindowsUpdateScreenshot;
|
||||
case "ios":
|
||||
return IOSUpdateScreenshot;
|
||||
case "ipados":
|
||||
return IPadOSUpdateScreenshot;
|
||||
default:
|
||||
MacOSUpdateScreenshot;
|
||||
}
|
||||
};
|
||||
|
||||
return (
|
||||
<img
|
||||
className={`${baseClass}__preview-img`}
|
||||
src={getScreenshot()}
|
||||
alt="OS update preview screenshot"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
const EndUserOSRequirementPreview = ({
|
||||
platform,
|
||||
}: IEndUserOSRequirementPreviewProps) => {
|
||||
// FIXME: on slow connection the image loads after the text which looks weird and can cause a
|
||||
// mismatch between the text and the image when switching between platforms. We should load the
|
||||
// image first and then the text.
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<OSRequirementDescription platform={platform} />
|
||||
<OSRequirementImage platform={platform} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default EndUserOSRequirementPreview;
|
||||
|
|
@ -1,4 +1,4 @@
|
|||
.nudge-preview {
|
||||
.os-requirement-preview {
|
||||
box-sizing: border-box;
|
||||
background-color: $ui-off-white;
|
||||
border-radius: $border-radius;
|
||||
|
|
@ -0,0 +1 @@
|
|||
export { default } from "./EndUserOSRequirementPreview";
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from "./MacOSTargetForm";
|
||||
|
|
@ -1,84 +0,0 @@
|
|||
import React from "react";
|
||||
|
||||
import CustomLink from "components/CustomLink";
|
||||
|
||||
import { OSUpdatesSupportedPlatform } from "../../OSUpdates";
|
||||
|
||||
import MacOSUpdateScreenshot from "../../../../../../assets/images/macos-updates-preview.png";
|
||||
import WindowsUpdateScreenshot from "../../../../../../assets/images/windows-nudge-screenshot.png";
|
||||
|
||||
const baseClass = "nudge-preview";
|
||||
|
||||
interface INudgeDescriptionProps {
|
||||
platform: OSUpdatesSupportedPlatform;
|
||||
}
|
||||
const NudgeDescription = ({ platform }: INudgeDescriptionProps) => {
|
||||
return platform === "darwin" ? (
|
||||
<>
|
||||
<h3>End user experience on macOS</h3>
|
||||
<p>
|
||||
For macOS 14 and above, end users will see native macOS notifications
|
||||
(DDM).
|
||||
</p>
|
||||
<p>Everyone else will see the Nudge window.</p>
|
||||
<CustomLink
|
||||
text="Learn more"
|
||||
url="https://fleetdm.com/learn-more-about/os-updates"
|
||||
newTab
|
||||
/>
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
<h3>End user experience on Windows</h3>
|
||||
<p>
|
||||
When a Windows host becomes aware of a new update, end users are able to
|
||||
defer restarts. Automatic restarts happen before 8am and after 5pm (end
|
||||
user's local time). After the deadline, restarts are forced
|
||||
regardless of active hours.
|
||||
</p>
|
||||
<CustomLink
|
||||
text="Learn more about Windows updates in Fleet"
|
||||
url="https://fleetdm.com/learn-more-about/os-updates"
|
||||
newTab
|
||||
/>
|
||||
</>
|
||||
);
|
||||
};
|
||||
|
||||
type INudgeImageProps = INudgeDescriptionProps;
|
||||
|
||||
const NudgeImage = ({ platform }: INudgeImageProps) => {
|
||||
return (
|
||||
<img
|
||||
className={`${baseClass}__preview-img`}
|
||||
src={
|
||||
platform === "darwin" ? MacOSUpdateScreenshot : WindowsUpdateScreenshot
|
||||
}
|
||||
alt="OS update preview screenshot"
|
||||
/>
|
||||
);
|
||||
};
|
||||
|
||||
interface INudgePreviewProps {
|
||||
platform: OSUpdatesSupportedPlatform;
|
||||
}
|
||||
|
||||
const NudgePreview = ({ platform }: INudgePreviewProps) => {
|
||||
const isSupportedPlatform = platform === "windows" || platform === "darwin";
|
||||
|
||||
if (!isSupportedPlatform) {
|
||||
return null;
|
||||
}
|
||||
|
||||
// FIXME: on slow connection the image loads after the text which looks weird and can cause a
|
||||
// mismatch between the text and the image when switching between platforms. We should load the
|
||||
// image first and then the text.
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<NudgeDescription platform={platform} />
|
||||
<NudgeImage platform={platform} />
|
||||
</div>
|
||||
);
|
||||
};
|
||||
|
||||
export default NudgePreview;
|
||||
|
|
@ -1 +0,0 @@
|
|||
export { default } from "./NudgePreview";
|
||||
|
|
@ -2,10 +2,9 @@ import React from "react";
|
|||
import { Tab, TabList, TabPanel, Tabs } from "react-tabs";
|
||||
import TabsWrapper from "components/TabsWrapper";
|
||||
|
||||
import MacOSTargetForm from "../MacOSTargetForm";
|
||||
import WindowsTargetForm from "../WindowsTargetForm";
|
||||
import { OSUpdatesSupportedPlatform } from "../../OSUpdates";
|
||||
import EmptyTargetForm from "../EmptyTargetForm";
|
||||
import AppleOSTargetForm from "../AppleOSTargetForm";
|
||||
|
||||
const baseClass = "platform-tabs";
|
||||
|
||||
|
|
@ -13,34 +12,41 @@ interface IPlatformTabsProps {
|
|||
currentTeamId: number;
|
||||
defaultMacOSVersion: string;
|
||||
defaultMacOSDeadline: string;
|
||||
defaultIOSVersion: string;
|
||||
defaultIOSDeadline: string;
|
||||
defaultIPadOSVersion: string;
|
||||
defaultIPadOSDeadline: string;
|
||||
defaultWindowsDeadlineDays: string;
|
||||
defaultWindowsGracePeriodDays: string;
|
||||
selectedPlatform: OSUpdatesSupportedPlatform;
|
||||
onSelectPlatform: (platform: OSUpdatesSupportedPlatform) => void;
|
||||
refetchAppConfig: () => void;
|
||||
refetchTeamConfig: () => void;
|
||||
isWindowsMdmEnabled: boolean;
|
||||
}
|
||||
|
||||
const PlatformTabs = ({
|
||||
currentTeamId,
|
||||
defaultMacOSDeadline,
|
||||
defaultMacOSVersion,
|
||||
defaultIOSDeadline,
|
||||
defaultIOSVersion,
|
||||
defaultIPadOSDeadline,
|
||||
defaultIPadOSVersion,
|
||||
defaultWindowsDeadlineDays,
|
||||
defaultWindowsGracePeriodDays,
|
||||
selectedPlatform,
|
||||
onSelectPlatform,
|
||||
refetchAppConfig,
|
||||
refetchTeamConfig,
|
||||
isWindowsMdmEnabled,
|
||||
}: IPlatformTabsProps) => {
|
||||
// FIXME: This behaves unexpectedly when a user switches tabs or changes the teams dropdown while a form is
|
||||
// submitting.
|
||||
|
||||
const PLATFORM_BY_INDEX: OSUpdatesSupportedPlatform[] = [
|
||||
"darwin",
|
||||
"windows",
|
||||
"iOS",
|
||||
"iPadOS",
|
||||
];
|
||||
const PLATFORM_BY_INDEX: OSUpdatesSupportedPlatform[] = isWindowsMdmEnabled
|
||||
? ["darwin", "windows", "ios", "ipados"]
|
||||
: ["darwin", "ios", "ipados"];
|
||||
|
||||
const onTabChange = (index: number) => {
|
||||
onSelectPlatform(PLATFORM_BY_INDEX[index]);
|
||||
|
|
@ -59,9 +65,11 @@ const PlatformTabs = ({
|
|||
<Tab key="macOS" data-text="macOS">
|
||||
macOS
|
||||
</Tab>
|
||||
<Tab key="Windows" data-text="Windows">
|
||||
Windows
|
||||
</Tab>
|
||||
{isWindowsMdmEnabled && (
|
||||
<Tab key="Windows" data-text="Windows">
|
||||
Windows
|
||||
</Tab>
|
||||
)}
|
||||
<Tab key="iOS" data-text="iOS">
|
||||
iOS
|
||||
</Tab>
|
||||
|
|
@ -70,8 +78,9 @@ const PlatformTabs = ({
|
|||
</Tab>
|
||||
</TabList>
|
||||
<TabPanel>
|
||||
<MacOSTargetForm
|
||||
<AppleOSTargetForm
|
||||
currentTeamId={currentTeamId}
|
||||
applePlatform="darwin"
|
||||
defaultMinOsVersion={defaultMacOSVersion}
|
||||
defaultDeadline={defaultMacOSDeadline}
|
||||
key={currentTeamId}
|
||||
|
|
@ -79,21 +88,39 @@ const PlatformTabs = ({
|
|||
refetchTeamConfig={refetchTeamConfig}
|
||||
/>
|
||||
</TabPanel>
|
||||
{isWindowsMdmEnabled && (
|
||||
<TabPanel>
|
||||
<WindowsTargetForm
|
||||
currentTeamId={currentTeamId}
|
||||
defaultDeadlineDays={defaultWindowsDeadlineDays}
|
||||
defaultGracePeriodDays={defaultWindowsGracePeriodDays}
|
||||
key={currentTeamId}
|
||||
refetchAppConfig={refetchAppConfig}
|
||||
refetchTeamConfig={refetchTeamConfig}
|
||||
/>
|
||||
</TabPanel>
|
||||
)}
|
||||
<TabPanel>
|
||||
<WindowsTargetForm
|
||||
<AppleOSTargetForm
|
||||
currentTeamId={currentTeamId}
|
||||
defaultDeadlineDays={defaultWindowsDeadlineDays}
|
||||
defaultGracePeriodDays={defaultWindowsGracePeriodDays}
|
||||
applePlatform="ios"
|
||||
defaultMinOsVersion={defaultIOSVersion}
|
||||
defaultDeadline={defaultIOSDeadline}
|
||||
key={currentTeamId}
|
||||
refetchAppConfig={refetchAppConfig}
|
||||
refetchTeamConfig={refetchTeamConfig}
|
||||
/>
|
||||
</TabPanel>
|
||||
<TabPanel>
|
||||
<EmptyTargetForm targetPlatform="iOS" />
|
||||
</TabPanel>
|
||||
<TabPanel>
|
||||
<EmptyTargetForm targetPlatform="iPadOS" />
|
||||
<AppleOSTargetForm
|
||||
currentTeamId={currentTeamId}
|
||||
applePlatform="ipados"
|
||||
defaultMinOsVersion={defaultIPadOSVersion}
|
||||
defaultDeadline={defaultIPadOSDeadline}
|
||||
key={currentTeamId}
|
||||
refetchAppConfig={refetchAppConfig}
|
||||
refetchTeamConfig={refetchTeamConfig}
|
||||
/>
|
||||
</TabPanel>
|
||||
</Tabs>
|
||||
</TabsWrapper>
|
||||
|
|
|
|||
|
|
@ -2,11 +2,11 @@ import React from "react";
|
|||
|
||||
import { API_NO_TEAM_ID, ITeamConfig } from "interfaces/team";
|
||||
import { IConfig } from "interfaces/config";
|
||||
import { ApplePlatform } from "interfaces/platform";
|
||||
|
||||
import SectionHeader from "components/SectionHeader";
|
||||
import Spinner from "components/Spinner";
|
||||
|
||||
import MacOSTargetForm from "../MacOSTargetForm";
|
||||
import WindowsTargetForm from "../WindowsTargetForm";
|
||||
import PlatformTabs from "../PlatformTabs";
|
||||
import { OSUpdatesSupportedPlatform } from "../../OSUpdates";
|
||||
|
|
@ -14,29 +14,52 @@ import { OSUpdatesSupportedPlatform } from "../../OSUpdates";
|
|||
const baseClass = "os-updates-target-section";
|
||||
|
||||
type GetDefaultFnParams = {
|
||||
osType?: ApplePlatform;
|
||||
currentTeamId: number;
|
||||
appConfig: IConfig;
|
||||
teamConfig?: ITeamConfig;
|
||||
};
|
||||
|
||||
const getDefaultMacOSVersion = ({
|
||||
const getDefaultOSVersion = ({
|
||||
osType,
|
||||
currentTeamId,
|
||||
appConfig,
|
||||
teamConfig,
|
||||
}: GetDefaultFnParams) => {
|
||||
return currentTeamId === API_NO_TEAM_ID
|
||||
? appConfig?.mdm.macos_updates.minimum_version ?? ""
|
||||
: teamConfig?.mdm?.macos_updates.minimum_version ?? "";
|
||||
const mdmData =
|
||||
currentTeamId === API_NO_TEAM_ID ? appConfig?.mdm : teamConfig?.mdm;
|
||||
|
||||
switch (osType) {
|
||||
case "darwin":
|
||||
return mdmData?.macos_updates.minimum_version ?? "";
|
||||
case "ios":
|
||||
return mdmData?.ios_updates.minimum_version ?? "";
|
||||
case "ipados":
|
||||
return mdmData?.ipados_updates.minimum_version ?? "";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
const getDefaultMacOSDeadline = ({
|
||||
const getDefaultDeadline = ({
|
||||
osType,
|
||||
currentTeamId,
|
||||
appConfig,
|
||||
teamConfig,
|
||||
}: GetDefaultFnParams) => {
|
||||
return currentTeamId === API_NO_TEAM_ID
|
||||
? appConfig?.mdm.macos_updates.deadline || ""
|
||||
: teamConfig?.mdm?.macos_updates.deadline || "";
|
||||
const mdmData =
|
||||
currentTeamId === API_NO_TEAM_ID ? appConfig?.mdm : teamConfig?.mdm;
|
||||
|
||||
switch (osType) {
|
||||
case "darwin":
|
||||
return mdmData?.macos_updates.deadline ?? "";
|
||||
case "ios":
|
||||
return mdmData?.ios_updates.deadline ?? "";
|
||||
case "ipados":
|
||||
return mdmData?.ipados_updates.deadline ?? "";
|
||||
default:
|
||||
return "";
|
||||
}
|
||||
};
|
||||
|
||||
const getDefaultWindowsDeadlineDays = ({
|
||||
|
|
@ -84,19 +107,48 @@ const TargetSection = ({
|
|||
return <Spinner />;
|
||||
}
|
||||
|
||||
const isMacMdmEnabled = appConfig.mdm.enabled_and_configured;
|
||||
const isAppleMdmEnabled = appConfig.mdm.enabled_and_configured;
|
||||
|
||||
const isWindowsMdmEnabled = appConfig.mdm.windows_enabled_and_configured;
|
||||
|
||||
const defaultMacOSVersion = getDefaultMacOSVersion({
|
||||
const defaultMacOSVersion = getDefaultOSVersion({
|
||||
osType: "darwin",
|
||||
currentTeamId,
|
||||
appConfig,
|
||||
teamConfig,
|
||||
});
|
||||
const defaultMacOSDeadline = getDefaultMacOSDeadline({
|
||||
const defaultMacOSDeadline = getDefaultDeadline({
|
||||
osType: "darwin",
|
||||
currentTeamId,
|
||||
appConfig,
|
||||
teamConfig,
|
||||
});
|
||||
const defaultIOSVersion = getDefaultOSVersion({
|
||||
osType: "ios",
|
||||
currentTeamId,
|
||||
appConfig,
|
||||
teamConfig,
|
||||
});
|
||||
|
||||
const defaultIOSDeadline = getDefaultDeadline({
|
||||
osType: "ios",
|
||||
currentTeamId,
|
||||
appConfig,
|
||||
teamConfig,
|
||||
});
|
||||
const defaultIPadOSOSVersion = getDefaultOSVersion({
|
||||
osType: "ipados",
|
||||
currentTeamId,
|
||||
appConfig,
|
||||
teamConfig,
|
||||
});
|
||||
const defaultIPadOSDeadline = getDefaultDeadline({
|
||||
osType: "ipados",
|
||||
currentTeamId,
|
||||
appConfig,
|
||||
teamConfig,
|
||||
});
|
||||
|
||||
const defaultWindowsDeadlineDays = getDefaultWindowsDeadlineDays({
|
||||
currentTeamId,
|
||||
appConfig,
|
||||
|
|
@ -109,28 +161,23 @@ const TargetSection = ({
|
|||
});
|
||||
|
||||
const renderTargetForms = () => {
|
||||
if (isMacMdmEnabled && isWindowsMdmEnabled) {
|
||||
if (isAppleMdmEnabled) {
|
||||
return (
|
||||
<PlatformTabs
|
||||
currentTeamId={currentTeamId}
|
||||
defaultMacOSVersion={defaultMacOSVersion}
|
||||
defaultMacOSDeadline={defaultMacOSDeadline}
|
||||
defaultIOSVersion={defaultIOSVersion}
|
||||
defaultIOSDeadline={defaultIOSDeadline}
|
||||
defaultIPadOSVersion={defaultIPadOSOSVersion}
|
||||
defaultIPadOSDeadline={defaultIPadOSDeadline}
|
||||
defaultWindowsDeadlineDays={defaultWindowsDeadlineDays}
|
||||
defaultWindowsGracePeriodDays={defaultWindowsGracePeriodDays}
|
||||
selectedPlatform={selectedPlatform}
|
||||
onSelectPlatform={onSelectPlatform}
|
||||
refetchAppConfig={refetchAppConfig}
|
||||
refetchTeamConfig={refetchTeamConfig}
|
||||
/>
|
||||
);
|
||||
} else if (isMacMdmEnabled) {
|
||||
return (
|
||||
<MacOSTargetForm
|
||||
currentTeamId={currentTeamId}
|
||||
defaultMinOsVersion={defaultMacOSVersion}
|
||||
defaultDeadline={defaultMacOSDeadline}
|
||||
refetchAppConfig={refetchAppConfig}
|
||||
refetchTeamConfig={refetchTeamConfig}
|
||||
isWindowsMdmEnabled={isWindowsMdmEnabled}
|
||||
/>
|
||||
);
|
||||
}
|
||||
|
|
|
|||
|
|
@ -3,7 +3,7 @@ import React from "react";
|
|||
|
||||
const baseClass = "end-user-experience-preview";
|
||||
|
||||
interface IEndUserExperiencePerviewProps {
|
||||
interface IEndUserExperiencePreviewProps {
|
||||
previewImage: string;
|
||||
altText?: string;
|
||||
children?: React.ReactNode;
|
||||
|
|
@ -15,7 +15,7 @@ const EndUserExperiencePerview = ({
|
|||
altText = "end user experience preview",
|
||||
children,
|
||||
className,
|
||||
}: IEndUserExperiencePerviewProps) => {
|
||||
}: IEndUserExperiencePreviewProps) => {
|
||||
const classes = classnames(baseClass, className);
|
||||
|
||||
return (
|
||||
|
|
|
|||
Loading…
Reference in a new issue