mirror of
https://github.com/fleetdm/fleet
synced 2026-05-24 09:28:54 +00:00
## Addresses #22702, #23713, #23756, #23746, #23747, and #23876 _-Note that much of this code as is will render as expected only once integrated with the backend or if manipulated manually for testing purposes_ **Frontend**: - Update banners on my device page, tests - Build new logic for calling endpoint to trigger linux key escrow on clicking `Create key` - Add `CreateLinuxKeyModal` to inform user of next steps after clicking `Create key` - Update banners on host details page, tests - Update the Controls > OS settings section with new logic related to linux disk encryption - Expect and include counts of Linux hosts in aggregate disk encryption stats UI - Add "Linux" column to the disk encryption table - Show disk encryption related UI for supported Linux platforms - TODO: confirm platform string matching functionality in manual e2e testing - Expand capabilities of `SectionHeader` component, apply to new UI - Flash "missing private key" error, with clickable link, when trying to update disk encryption enabled while no server private key is present. - TODO: QA this once other endpoints on Controls > Disk encryption are enabled even when MDM not turned on - Update Disk encryption key modal copy -Other TODO: - Confirm when integrated with API: - Aggregate disk encryption counts - Disk encryption table Linux column - Show disk encryption key action on host details page when expected - Opens Disk encryption key modal, displays key as expected **Backend**: - For "No team" and teams, error when trying to update disk encryption enabled while no server private key is present. - Remove requirement of mdm being enabled for use of various endpoints related to Linux disk encryption - Update tests _________ **Host details and my device page banners**  **Create key modal** <img width="1799" alt="create-key-modal" src="https://github.com/user-attachments/assets/81a55ccb-b6b9-4eb6-b2ff-a463c60724c0"> **Enabling disk encryption**  **Disk encryption: Fleet free** <img width="1912" alt="free" src="https://github.com/user-attachments/assets/9f9cace3-8955-47c2-87d9-24ff9387ac1a"> **Custom settings: turn on MDM** <img width="1912" alt="turn on mdm" src="https://github.com/user-attachments/assets/4d3ad47b-4035-4d93-86f0-dc2691b38bb4"> **Device status indicators**  **Encryption key action and modal**  - [x] Changes file added for user-visible changes in `changes/` - [x] Added/updated tests - [x] Manual QA for all new/changed functionality - [ ] Full e2e testing to do when integrated with backend --------- Co-authored-by: Jacob Shandling <jacob@fleetdm.com> Co-authored-by: Ian Littman <iansltx@gmail.com>
98 lines
2.2 KiB
TypeScript
98 lines
2.2 KiB
TypeScript
import React, { useState } from "react";
|
|
import classNames from "classnames";
|
|
|
|
import Icon from "components/Icon";
|
|
import Button from "components/buttons/Button";
|
|
import { IconNames } from "components/icons";
|
|
|
|
const baseClass = "info-banner";
|
|
|
|
export interface IInfoBannerProps {
|
|
children?: React.ReactNode;
|
|
className?: string;
|
|
/** default light purple */
|
|
color?: "purple" | "purple-bold-border" | "yellow" | "grey";
|
|
/** default 4px */
|
|
borderRadius?: "large" | "xlarge";
|
|
pageLevel?: boolean;
|
|
/** Add this element to the end of the banner message. Mutually exclusive with `link`. */
|
|
cta?: JSX.Element;
|
|
/** closable and link are mutually exclusive */
|
|
closable?: boolean;
|
|
/** Makes the entire banner clickable */
|
|
link?: string;
|
|
icon?: IconNames;
|
|
}
|
|
|
|
const InfoBanner = ({
|
|
children,
|
|
className,
|
|
color = "purple",
|
|
borderRadius,
|
|
pageLevel,
|
|
cta,
|
|
closable,
|
|
link,
|
|
icon,
|
|
}: IInfoBannerProps) => {
|
|
const wrapperClasses = classNames(
|
|
baseClass,
|
|
`${baseClass}__${color}`,
|
|
{
|
|
[`${baseClass}__${color}`]: !!color,
|
|
[`${baseClass}__border-radius-${borderRadius}`]: !!borderRadius,
|
|
[`${baseClass}__page-banner`]: !!pageLevel,
|
|
[`${baseClass}__icon`]: !!icon,
|
|
},
|
|
className
|
|
);
|
|
|
|
const [hideBanner, setHideBanner] = useState(false);
|
|
|
|
const content = (
|
|
<>
|
|
<div className={`${baseClass}__info`}>{children}</div>
|
|
|
|
{(cta || closable) && (
|
|
<div className={`${baseClass}__cta`}>
|
|
{cta}
|
|
{closable && (
|
|
<Button variant="unstyled" onClick={() => setHideBanner(true)}>
|
|
<Icon
|
|
name="close"
|
|
color="core-fleet-black"
|
|
size="small"
|
|
className={`${baseClass}__close`}
|
|
/>
|
|
</Button>
|
|
)}
|
|
</div>
|
|
)}
|
|
</>
|
|
);
|
|
|
|
if (hideBanner) {
|
|
return <></>;
|
|
}
|
|
|
|
if (link) {
|
|
return (
|
|
<a
|
|
href={link}
|
|
target="_blank"
|
|
rel="noreferrer"
|
|
className={wrapperClasses}
|
|
>
|
|
{content}
|
|
</a>
|
|
);
|
|
}
|
|
|
|
return (
|
|
<div className={wrapperClasses} role="status">
|
|
{content}
|
|
</div>
|
|
);
|
|
};
|
|
|
|
export default InfoBanner;
|