Rebase sandcastle onto main (#10317)
# Checklist for submitter If some of the following don't apply, delete the relevant line. - [ ] Changes file added for user-visible changes in `changes/` or `orbit/changes/`. See [Changes files](https://fleetdm.com/docs/contributing/committing-changes#changes-files) for more information. - [ ] Documented any API changes (docs/Using-Fleet/REST-API.md or docs/Contributing/API-for-contributors.md) - [ ] Documented any permissions changes - [ ] Input data is properly validated, `SELECT *` is avoided, SQL injection is prevented (using placeholders for values in statements) - [ ] Added support on fleet's osquery simulator `cmd/osquery-perf` for new osquery data ingestion features. - [ ] Added/updated tests - [ ] Manual QA for all new/changed functionality - For Orbit and Fleet Desktop changes: - [ ] Manual QA must be performed in the three main OSs, macOS, Windows and Linux. - [ ] Auto-update manual QA, from released version of component to new version (see [tools/tuf/test](../tools/tuf/test/README.md)). --------- Co-authored-by: RachelElysia <71795832+RachelElysia@users.noreply.github.com>
This commit is contained in:
co-authored by
RachelElysia
parent
70a429327f
commit
b5e37ce056
@@ -43,7 +43,7 @@
|
||||
align-items: center;
|
||||
padding: 16px;
|
||||
gap: 16px;
|
||||
width: 286px;
|
||||
width: 247px;
|
||||
|
||||
border: 1px solid #c5c7d1;
|
||||
border-radius: 4px;
|
||||
|
||||
@@ -13,6 +13,7 @@ import useDeepEffect from "hooks/useDeepEffect";
|
||||
|
||||
import usersAPI from "services/entities/users";
|
||||
import configAPI from "services/entities/config";
|
||||
import hostCountAPI from "services/entities/host_count";
|
||||
|
||||
import { ErrorBoundary } from "react-error-boundary";
|
||||
// @ts-ignore
|
||||
@@ -46,6 +47,7 @@ const App = ({ children, location }: IAppProps): JSX.Element => {
|
||||
setConfig,
|
||||
setEnrollSecret,
|
||||
setSandboxExpiry,
|
||||
setNoSandboxHosts,
|
||||
} = useContext(AppContext);
|
||||
|
||||
const [isLoading, setIsLoading] = useState(false);
|
||||
@@ -56,6 +58,9 @@ const App = ({ children, location }: IAppProps): JSX.Element => {
|
||||
if (config.sandbox_enabled) {
|
||||
const timestamp = await configAPI.loadSandboxExpiry();
|
||||
setSandboxExpiry(timestamp as string);
|
||||
const hostCount = await hostCountAPI.load({});
|
||||
const noSandboxHosts = hostCount.count === 0;
|
||||
setNoSandboxHosts(noSandboxHosts);
|
||||
}
|
||||
setConfig(config);
|
||||
} catch (error) {
|
||||
|
||||
@@ -27,9 +27,13 @@ const MainContent = ({
|
||||
className,
|
||||
}: IMainContentProps): JSX.Element => {
|
||||
const classes = classnames(baseClass, className);
|
||||
const { sandboxExpiry, config, isSandboxMode, isPremiumTier } = useContext(
|
||||
AppContext
|
||||
);
|
||||
const {
|
||||
sandboxExpiry,
|
||||
config,
|
||||
isSandboxMode,
|
||||
isPremiumTier,
|
||||
noSandboxHosts,
|
||||
} = useContext(AppContext);
|
||||
|
||||
const isAppleBmTermsExpired = config?.mdm?.apple_bm_terms_expired;
|
||||
|
||||
@@ -45,7 +49,10 @@ const MainContent = ({
|
||||
)}
|
||||
<SandboxGate
|
||||
fallbackComponent={() => (
|
||||
<SandboxExpiryMessage expiry={sandboxExpiryTime} />
|
||||
<SandboxExpiryMessage
|
||||
expiry={sandboxExpiryTime}
|
||||
noSandboxHosts={noSandboxHosts}
|
||||
/>
|
||||
)}
|
||||
/>
|
||||
{children}
|
||||
|
||||
@@ -1,26 +1,60 @@
|
||||
import React from "react";
|
||||
import { browserHistory } from "react-router";
|
||||
import PATHS from "router/paths";
|
||||
|
||||
import ExternalLinkIcon from "../../../../assets/images/icon-external-link-black-12x12@2x.png";
|
||||
import Button from "components/buttons/Button";
|
||||
import Icon from "components/Icon";
|
||||
|
||||
const baseClass = "sandbox-expiry-message";
|
||||
|
||||
interface ISandboxExpiryMessageProps {
|
||||
expiry: string;
|
||||
noSandboxHosts?: boolean;
|
||||
}
|
||||
|
||||
const SandboxExpiryMessage = ({ expiry }: ISandboxExpiryMessageProps) => {
|
||||
const SandboxExpiryMessage = ({
|
||||
expiry,
|
||||
noSandboxHosts,
|
||||
}: ISandboxExpiryMessageProps) => {
|
||||
const openAddHostModal = () => {
|
||||
browserHistory.push(PATHS.MANAGE_HOSTS_ADD_HOSTS);
|
||||
};
|
||||
|
||||
if (noSandboxHosts) {
|
||||
return (
|
||||
<div className={baseClass}>
|
||||
<p>Your Fleet Sandbox expires in {expiry}.</p>
|
||||
<div className={`${baseClass}__tip`}>
|
||||
<Icon name="lightbulb" />
|
||||
<p>
|
||||
<b>Quick tip: </b> Enroll a host to get started.
|
||||
</p>
|
||||
<form>
|
||||
<Button
|
||||
onClick={openAddHostModal}
|
||||
className={`${baseClass}__add-hosts`}
|
||||
variant="brand"
|
||||
>
|
||||
<span>Add hosts</span>
|
||||
</Button>
|
||||
</form>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
|
||||
return (
|
||||
<a
|
||||
href="https://fleetdm.com/docs/deploying"
|
||||
href="https://fleetdm.com/docs/using-fleet/learn-how-to-use-fleet#how-to-add-your-device-to-fleet"
|
||||
target="_blank"
|
||||
rel="noreferrer"
|
||||
className={baseClass}
|
||||
>
|
||||
<p>Your Fleet Sandbox expires in {expiry}.</p>
|
||||
<span>
|
||||
Learn how to deploy Fleet
|
||||
<img alt="Open external link" src={ExternalLinkIcon} />
|
||||
</span>
|
||||
<p>
|
||||
<b>Learn how to use Fleet</b>{" "}
|
||||
<Icon name="external-link" color="core-fleet-black" />
|
||||
</p>
|
||||
</a>
|
||||
);
|
||||
};
|
||||
|
||||
@@ -2,30 +2,27 @@
|
||||
display: flex;
|
||||
justify-content: space-between;
|
||||
align-items: center;
|
||||
padding: 12px $pad-large;
|
||||
padding: $pad-large $pad-xlarge;
|
||||
margin-bottom: $pad-large;
|
||||
background-color: $ui-yellow-banner;
|
||||
border: 1px solid #ece0bb;
|
||||
background-color: $ui-vibrant-blue-10;
|
||||
border: 1px solid $ui-vibrant-blue-50;
|
||||
border-radius: $border-radius;
|
||||
font-size: $xx-small;
|
||||
|
||||
font-size: $x-small;
|
||||
color: $core-fleet-black;
|
||||
font-weight: $regular;
|
||||
|
||||
&:hover {
|
||||
cursor: pointer;
|
||||
}
|
||||
|
||||
p {
|
||||
margin: 0;
|
||||
}
|
||||
|
||||
span {
|
||||
&__tip {
|
||||
display: flex;
|
||||
align-items: center;
|
||||
color: $core-fleet-black;
|
||||
font-weight: $bold;
|
||||
text-align: right;
|
||||
gap: $pad-small;
|
||||
|
||||
button {
|
||||
margin-left: $pad-small;
|
||||
}
|
||||
}
|
||||
|
||||
.button {
|
||||
|
||||
@@ -359,7 +359,6 @@ $base-class: "button";
|
||||
.info {
|
||||
&__header {
|
||||
display: block;
|
||||
width: 100%;
|
||||
text-align: left;
|
||||
}
|
||||
&__data {
|
||||
|
||||
@@ -0,0 +1,32 @@
|
||||
import React from "react";
|
||||
import { COLORS, Colors } from "styles/var/colors";
|
||||
|
||||
interface ILightbulbProps {
|
||||
color?: Colors;
|
||||
}
|
||||
|
||||
const Lightbulb = ({ color = "core-fleet-blue" }: ILightbulbProps) => {
|
||||
return (
|
||||
<svg
|
||||
width="28"
|
||||
height="32"
|
||||
fill="none"
|
||||
xmlns="http://www.w3.org/2000/svg"
|
||||
viewBox="0 0 28 33"
|
||||
>
|
||||
<g clipPath="url(#a)" fill={COLORS[color]}>
|
||||
<path d="M11.15 27.79c-1 0-1.84-.73-1.99-1.72l-.47-3.13c-.2-1.35-.74-2.67-1.58-3.93a8.418 8.418 0 0 1-1.44-5.2C5.89 9.48 9.31 6 13.63 5.72c.19-.01.39-.02.58-.02 4.71 0 8.55 3.83 8.55 8.55 0 1.72-.51 3.38-1.48 4.8-.83 1.22-1.37 2.66-1.62 4.27l-.43 2.85c-.13.89-.98 1.62-1.88 1.62H11.15ZM14.2 7.38c-.15 0-.31 0-.47.02a6.83 6.83 0 0 0-4.42 2.04 6.819 6.819 0 0 0-1.97 4.45c-.07 1.5.33 2.94 1.16 4.18.99 1.47 1.61 3.02 1.85 4.62l.47 3.13c.02.17.16.29.33.29H17.34c.07 0 .2-.12.21-.18l.43-2.85c.28-1.87.92-3.54 1.89-4.97a6.853 6.853 0 0 0 1.18-3.85c0-3.78-3.08-6.86-6.86-6.86l.01-.02ZM10.89 30.21c-.39 0-.72-.32-.72-.71 0-.39.32-.71.72-.71h6.62c.39 0 .71.32.71.71 0 .39-.32.71-.71.71h-6.62ZM12.61 32.62c-.39 0-.72-.32-.72-.71 0-.39.32-.72.72-.72h3.11c.39 0 .72.32.72.72 0 .4-.32.71-.72.71h-3.11Z" />
|
||||
<path d="M13.16 26.65h-.01c-.17 0-.3-.15-.3-.32 0-.08.31-8.12-1.36-10.75a.32.32 0 0 1 .09-.43.32.32 0 0 1 .43.09c1.78 2.79 1.47 10.77 1.46 11.11 0 .17-.14.3-.31.3Z" />
|
||||
<path d="M11.74 17.16c-.26 0-.55 0-.82-.1-.43-.15-.7-.36-.86-.7-.22-.45-.1-1.13.46-1.45.45-.25 1.13-.2 1.48.31.1.14.06.33-.08.43-.14.1-.33.06-.43-.08-.17-.25-.5-.22-.68-.12-.24.13-.3.44-.2.64.08.16.19.28.5.38.19.06.43.06.66.06h2.73c.17 0 .31.14.31.31 0 .17-.14.31-.31.31h-2.77l.01.01ZM15.23 26.65c-.16 0-.3-.13-.31-.3-.01-.34-.32-8.31 1.46-11.11.09-.14.28-.19.43-.09.14.09.19.28.09.43-1.67 2.63-1.37 10.67-1.36 10.75 0 .17-.13.31-.3.32h-.01Z" />
|
||||
<path d="M16.66 17.16h-2.77c-.17 0-.31-.14-.31-.31 0-.17.14-.31.31-.31h2.73c.23 0 .47 0 .66-.06.32-.11.43-.23.5-.38.1-.2.04-.5-.2-.64-.17-.1-.51-.12-.68.12-.1.14-.29.17-.43.08a.317.317 0 0 1-.08-.43c.36-.51 1.04-.56 1.48-.31.56.31.68.99.46 1.45-.16.34-.43.55-.86.7-.27.09-.56.1-.82.1l.01-.01ZM14.2 4.13c-.36 0-.65-.29-.65-.65V1.03c0-.36.29-.65.65-.65.36 0 .65.29.65.65v2.45c0 .36-.29.65-.65.65ZM6.64 7.26a.66.66 0 0 1-.46-.19L4.27 5.16a.658.658 0 0 1 0-.92.66.66 0 0 1 .46-.19c.17 0 .34.07.46.19L7.1 6.15c.25.25.25.67 0 .92a.66.66 0 0 1-.46.19ZM21.76 7.26a.66.66 0 0 1-.46-.19.66.66 0 0 1-.19-.46c0-.17.07-.34.19-.46l1.91-1.91a.66.66 0 0 1 .46-.19c.17 0 .34.07.46.19s.19.29.19.46c0 .17-.07.34-.19.46l-1.91 1.91a.66.66 0 0 1-.46.19ZM24.9 14.8c-.36 0-.65-.29-.65-.65 0-.36.29-.65.65-.65h2.45c.36 0 .65.29.65.65 0 .36-.29.65-.65.65H24.9ZM1.06 14.88c-.36 0-.65-.29-.65-.65 0-.36.29-.65.65-.65h2.45c.36 0 .65.29.65.65 0 .36-.29.65-.65.65H1.06Z" />
|
||||
</g>
|
||||
<defs>
|
||||
<clipPath id="a">
|
||||
<path fill="#fff" d="M.41.38H28v32.24H.41z" />
|
||||
</clipPath>
|
||||
</defs>
|
||||
</svg>
|
||||
);
|
||||
};
|
||||
|
||||
export default Lightbulb;
|
||||
@@ -21,6 +21,7 @@ import PremiumFeature from "./PremiumFeature";
|
||||
|
||||
import LowDiskSpaceHosts from "./LowDiskSpaceHosts";
|
||||
import MissingHosts from "./MissingHosts";
|
||||
import Lightbulb from "./Lightbulb";
|
||||
|
||||
import Apple from "./Apple";
|
||||
import Windows from "./Windows";
|
||||
@@ -72,6 +73,7 @@ export const ICON_MAP = {
|
||||
"external-link": ExternalLink,
|
||||
"low-disk-space-hosts": LowDiskSpaceHosts,
|
||||
"missing-hosts": MissingHosts,
|
||||
lightbulb: Lightbulb,
|
||||
issue: Issue,
|
||||
plus: Plus,
|
||||
clipboard: Clipboard,
|
||||
|
||||
@@ -40,6 +40,8 @@ const QuerySidePanel = ({
|
||||
evented,
|
||||
} = selectedOsqueryTable;
|
||||
|
||||
const mdmRequired = name === "managed_policies";
|
||||
|
||||
const onSelectTable = (value: string) => {
|
||||
onOsqueryTableSelect(value);
|
||||
};
|
||||
@@ -80,6 +82,9 @@ const QuerySidePanel = ({
|
||||
{renderTableSelect()}
|
||||
</div>
|
||||
{evented && <EventedTableTag selectedTableName={name} />}
|
||||
{mdmRequired && (
|
||||
<span className={`${baseClass}__mdm-required`}>Requires MDM</span>
|
||||
)}
|
||||
<div className={`${baseClass}__description`}>
|
||||
<FleetMarkdown markdown={description} />
|
||||
</div>
|
||||
|
||||
@@ -52,23 +52,20 @@
|
||||
}
|
||||
|
||||
&__table-select {
|
||||
|
||||
// TODO: Remove these overrides when we do a style update for the core
|
||||
// dropdown component.
|
||||
&.Select {
|
||||
|
||||
// fixes up some padding issues with the scroll bar for the dropdown.
|
||||
.Select-menu-outer {
|
||||
padding: 0;
|
||||
|
||||
.Select-menu {
|
||||
padding: $pad-xsmall
|
||||
padding: $pad-xsmall;
|
||||
}
|
||||
}
|
||||
|
||||
// use to truncate selected long table names in the dropdown
|
||||
&.has-value.Select--single>.Select-control {
|
||||
|
||||
&.has-value.Select--single > .Select-control {
|
||||
.Select-value .Select-value-label {
|
||||
white-space: nowrap;
|
||||
overflow: hidden;
|
||||
@@ -84,4 +81,17 @@
|
||||
font-size: $x-small;
|
||||
overflow-wrap: break-word;
|
||||
}
|
||||
|
||||
&__mdm-required {
|
||||
background-color: $core-vibrant-blue;
|
||||
color: $core-white;
|
||||
font-size: $x-small;
|
||||
font-weight: 700;
|
||||
padding: 2px 4px;
|
||||
border-radius: 4px;
|
||||
position: relative;
|
||||
top: -2px;
|
||||
min-width: 95px;
|
||||
max-height: 19px;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -14,6 +14,7 @@ enum ACTIONS {
|
||||
SET_CONFIG = "SET_CONFIG",
|
||||
SET_ENROLL_SECRET = "SET_ENROLL_SECRET",
|
||||
SET_SANDBOX_EXPIRY = "SET_SANDBOX_EXPIRY",
|
||||
SET_NO_SANDBOX_HOSTS = "SET_NO_SANDBOX_HOSTS",
|
||||
SET_FILTERED_HOSTS_PATH = "SET_FILTERED_HOSTS_PATH",
|
||||
}
|
||||
|
||||
@@ -45,6 +46,11 @@ interface ISetSandboxExpiryAction {
|
||||
sandboxExpiry: string;
|
||||
}
|
||||
|
||||
interface ISetNoSandboxHostsAction {
|
||||
type: ACTIONS.SET_NO_SANDBOX_HOSTS;
|
||||
noSandboxHosts: boolean;
|
||||
}
|
||||
|
||||
interface ISetFilteredHostsPathAction {
|
||||
type: ACTIONS.SET_FILTERED_HOSTS_PATH;
|
||||
filteredHostsPath: string;
|
||||
@@ -57,6 +63,7 @@ type IAction =
|
||||
| ISetCurrentUserAction
|
||||
| ISetEnrollSecretAction
|
||||
| ISetSandboxExpiryAction
|
||||
| ISetNoSandboxHostsAction
|
||||
| ISetFilteredHostsPathAction;
|
||||
|
||||
type Props = {
|
||||
@@ -88,6 +95,7 @@ type InitialStateType = {
|
||||
isOnlyObserver?: boolean;
|
||||
isNoAccess?: boolean;
|
||||
sandboxExpiry?: string;
|
||||
noSandboxHosts?: boolean;
|
||||
filteredHostsPath?: string;
|
||||
setAvailableTeams: (availableTeams: ITeamSummary[]) => void;
|
||||
setCurrentUser: (user: IUser) => void;
|
||||
@@ -95,6 +103,7 @@ type InitialStateType = {
|
||||
setConfig: (config: IConfig) => void;
|
||||
setEnrollSecret: (enrollSecret: IEnrollSecret[]) => void;
|
||||
setSandboxExpiry: (sandboxExpiry: string) => void;
|
||||
setNoSandboxHosts: (noSandboxHosts: boolean) => void;
|
||||
setFilteredHostsPath: (filteredHostsPath: string) => void;
|
||||
};
|
||||
|
||||
@@ -131,6 +140,7 @@ export const initialState = {
|
||||
setConfig: () => null,
|
||||
setEnrollSecret: () => null,
|
||||
setSandboxExpiry: () => null,
|
||||
setNoSandboxHosts: () => null,
|
||||
setFilteredHostsPath: () => null,
|
||||
};
|
||||
|
||||
@@ -229,6 +239,13 @@ const reducer = (state: InitialStateType, action: IAction) => {
|
||||
sandboxExpiry,
|
||||
};
|
||||
}
|
||||
case ACTIONS.SET_NO_SANDBOX_HOSTS: {
|
||||
const { noSandboxHosts } = action;
|
||||
return {
|
||||
...state,
|
||||
noSandboxHosts,
|
||||
};
|
||||
}
|
||||
case ACTIONS.SET_FILTERED_HOSTS_PATH: {
|
||||
const { filteredHostsPath } = action;
|
||||
return {
|
||||
@@ -253,6 +270,7 @@ const AppProvider = ({ children }: Props): JSX.Element => {
|
||||
currentTeam: state.currentTeam,
|
||||
enrollSecret: state.enrollSecret,
|
||||
sandboxExpiry: state.sandboxExpiry,
|
||||
noSandboxHosts: state.noSandboxHosts,
|
||||
filteredHostsPath: state.filteredHostsPath,
|
||||
isPreviewMode: detectPreview(),
|
||||
isSandboxMode: state.isSandboxMode,
|
||||
@@ -290,6 +308,12 @@ const AppProvider = ({ children }: Props): JSX.Element => {
|
||||
setSandboxExpiry: (sandboxExpiry: string) => {
|
||||
dispatch({ type: ACTIONS.SET_SANDBOX_EXPIRY, sandboxExpiry });
|
||||
},
|
||||
setNoSandboxHosts: (noSandboxHosts: boolean) => {
|
||||
dispatch({
|
||||
type: ACTIONS.SET_NO_SANDBOX_HOSTS,
|
||||
noSandboxHosts,
|
||||
});
|
||||
},
|
||||
setFilteredHostsPath: (filteredHostsPath: string) => {
|
||||
dispatch({ type: ACTIONS.SET_FILTERED_HOSTS_PATH, filteredHostsPath });
|
||||
},
|
||||
|
||||
@@ -94,4 +94,5 @@ export interface IPolicyNew {
|
||||
resolution: string;
|
||||
critical: boolean;
|
||||
platform: IPlatformString;
|
||||
mdm_required?: boolean;
|
||||
}
|
||||
|
||||
@@ -1,9 +1,10 @@
|
||||
import React from "react";
|
||||
import React, { useContext } from "react";
|
||||
import { Tab, Tabs, TabList, TabPanel } from "react-tabs";
|
||||
import { Row } from "react-table";
|
||||
import { InjectedRouter } from "react-router";
|
||||
import PATHS from "router/paths";
|
||||
|
||||
import { AppContext } from "context/app";
|
||||
import { buildQueryStringFromParams } from "utilities/url";
|
||||
|
||||
import TabsWrapper from "components/TabsWrapper";
|
||||
@@ -52,6 +53,8 @@ const Software = ({
|
||||
software,
|
||||
router,
|
||||
}: ISoftwareCardProps): JSX.Element => {
|
||||
const { noSandboxHosts } = useContext(AppContext);
|
||||
|
||||
const tableHeaders = generateTableHeaders();
|
||||
|
||||
const handleRowSelect = (row: IRowProps) => {
|
||||
@@ -96,6 +99,7 @@ const Software = ({
|
||||
emptyComponent={() => (
|
||||
<EmptySoftwareTable
|
||||
isCollectingSoftware={isCollectingInventory}
|
||||
noSandboxHosts={noSandboxHosts}
|
||||
/>
|
||||
)}
|
||||
showMarkAllPages={false}
|
||||
@@ -124,6 +128,7 @@ const Software = ({
|
||||
emptyComponent={() => (
|
||||
<EmptySoftwareTable
|
||||
isCollectingSoftware={isCollectingInventory}
|
||||
noSandboxHosts={noSandboxHosts}
|
||||
isFilterVulnerable
|
||||
/>
|
||||
)}
|
||||
|
||||
@@ -677,6 +677,9 @@ const ManageHostsPage = ({
|
||||
// NOTE: used to reset page number to 0 when modifying filters
|
||||
useEffect(() => {
|
||||
setResetPageIndex(false);
|
||||
if (queryParams.add_hosts === "true") {
|
||||
setShowAddHostsModal(true);
|
||||
}
|
||||
}, [queryParams]);
|
||||
|
||||
// NOTE: this is called once on initial render and every time the query changes
|
||||
|
||||
+6
-1
@@ -68,7 +68,12 @@ const AddPolicyModal = ({
|
||||
onClick={() => onAddPolicy(policy)}
|
||||
>
|
||||
<>
|
||||
<span className="info__header">{policy.name}</span>
|
||||
<div className={`${baseClass}__policy-name`}>
|
||||
<span className="info__header">{policy.name}</span>
|
||||
{policy.mdm_required && (
|
||||
<span className={`${baseClass}__mdm-policy`}>Requires MDM</span>
|
||||
)}
|
||||
</div>
|
||||
<span className="info__data">{policy.description}</span>
|
||||
</>
|
||||
</Button>
|
||||
|
||||
@@ -13,4 +13,31 @@
|
||||
padding: $pad-large 0;
|
||||
height: 100%;
|
||||
}
|
||||
|
||||
&__policy-name {
|
||||
display: inline-flex;
|
||||
width: 100%;
|
||||
}
|
||||
|
||||
&__mdm-policy {
|
||||
background-color: $core-vibrant-blue;
|
||||
color: $core-white;
|
||||
font-size: $x-small;
|
||||
font-weight: 700;
|
||||
padding: 2px 4px;
|
||||
border-radius: 4px;
|
||||
margin-left: 0.5rem;
|
||||
position: relative;
|
||||
top: -2px;
|
||||
min-width: 95px;
|
||||
max-height: 19px;
|
||||
}
|
||||
|
||||
.children-wrapper {
|
||||
align-items: left;
|
||||
|
||||
.info__header {
|
||||
width: initial;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -72,6 +72,7 @@ export const DEFAULT_POLICIES: IPolicyNew[] = [
|
||||
"Contact your IT administrator to ensure your Mac is receiving a profile that disables automatic login.",
|
||||
critical: false,
|
||||
platform: "darwin",
|
||||
mdm_required: true,
|
||||
},
|
||||
{
|
||||
key: 5,
|
||||
@@ -141,6 +142,7 @@ export const DEFAULT_POLICIES: IPolicyNew[] = [
|
||||
"Contact your IT administrator to ensure your Mac is receiving a profile that enables secure keyboard entry for the Terminal application.",
|
||||
critical: false,
|
||||
platform: "darwin",
|
||||
mdm_required: true,
|
||||
},
|
||||
{
|
||||
key: 11,
|
||||
@@ -175,6 +177,7 @@ export const DEFAULT_POLICIES: IPolicyNew[] = [
|
||||
"Contact your IT administrator to ensure your Mac is receiving a profile that enables screen lock.",
|
||||
critical: false,
|
||||
platform: "darwin",
|
||||
mdm_required: true,
|
||||
},
|
||||
{
|
||||
key: 14,
|
||||
@@ -221,6 +224,7 @@ export const DEFAULT_POLICIES: IPolicyNew[] = [
|
||||
"Contact your IT administrator to ensure your Mac is receiving a profile that enables automatic updates.",
|
||||
critical: false,
|
||||
platform: "darwin",
|
||||
mdm_required: true,
|
||||
},
|
||||
{
|
||||
key: 18,
|
||||
@@ -257,6 +261,7 @@ export const DEFAULT_POLICIES: IPolicyNew[] = [
|
||||
"Contact your IT administrator to ensure your Mac is receiving a profile that enables automatic security and data update installation.",
|
||||
critical: false,
|
||||
platform: "darwin",
|
||||
mdm_required: true,
|
||||
},
|
||||
{
|
||||
key: 21,
|
||||
@@ -270,6 +275,7 @@ export const DEFAULT_POLICIES: IPolicyNew[] = [
|
||||
"Contact your IT administrator to ensure your Mac is receiving a profile that enables automatic installation of operating system updates.",
|
||||
critical: false,
|
||||
platform: "darwin",
|
||||
mdm_required: true,
|
||||
},
|
||||
{
|
||||
key: 22,
|
||||
@@ -282,6 +288,7 @@ export const DEFAULT_POLICIES: IPolicyNew[] = [
|
||||
"Contact your IT administrator to ensure your Mac is receiving a profile that enables automatic time and date configuration.",
|
||||
critical: false,
|
||||
platform: "darwin",
|
||||
mdm_required: true,
|
||||
},
|
||||
{
|
||||
key: 23,
|
||||
@@ -294,6 +301,7 @@ export const DEFAULT_POLICIES: IPolicyNew[] = [
|
||||
"Contact your IT administrator to ensure your Mac is receiving a profile that enables the screen saver after inactivity of 20 minutes or less.",
|
||||
critical: false,
|
||||
platform: "darwin",
|
||||
mdm_required: true,
|
||||
},
|
||||
{
|
||||
key: 24,
|
||||
@@ -306,6 +314,7 @@ export const DEFAULT_POLICIES: IPolicyNew[] = [
|
||||
"Contact your IT administrator to ensure your Mac is receiving a profile that prevents Internet sharing.",
|
||||
critical: false,
|
||||
platform: "darwin",
|
||||
mdm_required: true,
|
||||
},
|
||||
{
|
||||
key: 25,
|
||||
@@ -318,6 +327,7 @@ export const DEFAULT_POLICIES: IPolicyNew[] = [
|
||||
"Contact your IT administrator to ensure your Mac is receiving a profile that disables content caching.",
|
||||
critical: false,
|
||||
platform: "darwin",
|
||||
mdm_required: true,
|
||||
},
|
||||
{
|
||||
key: 26,
|
||||
@@ -342,6 +352,7 @@ export const DEFAULT_POLICIES: IPolicyNew[] = [
|
||||
"Contact your IT administrator to ensure your Mac is receiving a profile to prevent iCloud Desktop and Documents sync.",
|
||||
critical: false,
|
||||
platform: "darwin",
|
||||
mdm_required: true,
|
||||
},
|
||||
{
|
||||
key: 28,
|
||||
@@ -354,6 +365,7 @@ export const DEFAULT_POLICIES: IPolicyNew[] = [
|
||||
"Contact your IT administrator to ensure your Mac is receiving a profile that enables firewall logging.",
|
||||
critical: false,
|
||||
platform: "darwin",
|
||||
mdm_required: true,
|
||||
},
|
||||
{
|
||||
key: 29,
|
||||
@@ -366,6 +378,7 @@ export const DEFAULT_POLICIES: IPolicyNew[] = [
|
||||
"Contact your IT administrator to ensure your Mac is receiving a profile that disables the guest account.",
|
||||
critical: false,
|
||||
platform: "darwin",
|
||||
mdm_required: true,
|
||||
},
|
||||
{
|
||||
key: 30,
|
||||
@@ -378,6 +391,7 @@ export const DEFAULT_POLICIES: IPolicyNew[] = [
|
||||
"Contact your IT administrator to ensure your Mac is receiving a profile that prevents guest access to shared folders.",
|
||||
critical: false,
|
||||
platform: "darwin",
|
||||
mdm_required: true,
|
||||
},
|
||||
{
|
||||
key: 31,
|
||||
@@ -465,7 +479,8 @@ export const DEFAULT_POLICIES: IPolicyNew[] = [
|
||||
key: 38,
|
||||
query:
|
||||
"SELECT EXISTS(SELECT 1 FROM file WHERE filename like '%Emergency Kit%.pdf' AND (path LIKE '/Users/%%/Downloads/%%' OR path LIKE '/Users/%%/Desktop/%%')) as does_1p_ek_exist;",
|
||||
name: "No 1Password emergency kit stored on desktop or in downloads (macOS)",
|
||||
name:
|
||||
"No 1Password emergency kit stored on desktop or in downloads (macOS)",
|
||||
description:
|
||||
"Looks for PDF files with file names typically used by 1Password for emergency recovery kits.",
|
||||
resolution:
|
||||
|
||||
@@ -112,6 +112,7 @@ const ManageSoftwarePage = ({
|
||||
isOnGlobalTeam,
|
||||
isPremiumTier,
|
||||
isSandboxMode,
|
||||
noSandboxHosts,
|
||||
} = useContext(AppContext);
|
||||
const { renderFlash } = useContext(NotificationContext);
|
||||
|
||||
@@ -559,6 +560,7 @@ const ManageSoftwarePage = ({
|
||||
isSandboxMode={isSandboxMode}
|
||||
isCollectingSoftware={isCollectingInventory}
|
||||
isSearching={searchQuery !== ""}
|
||||
noSandboxHosts={noSandboxHosts}
|
||||
/>
|
||||
)}
|
||||
defaultSortHeader={DEFAULT_SORT_HEADER}
|
||||
|
||||
@@ -0,0 +1,68 @@
|
||||
// This component is used on ManageSoftwarePage.tsx and DashboardPage.tsx > Software.tsx card
|
||||
|
||||
import React from "react";
|
||||
|
||||
import CustomLink from "components/CustomLink";
|
||||
|
||||
const baseClass = "manage-software-page";
|
||||
|
||||
type IEmptySoftwareProps = {
|
||||
message: "disabled" | "collecting" | "default" | "";
|
||||
noSandboxHosts?: boolean;
|
||||
};
|
||||
|
||||
const EmptySoftware = ({
|
||||
message,
|
||||
noSandboxHosts,
|
||||
}: IEmptySoftwareProps): JSX.Element => {
|
||||
switch (message) {
|
||||
case "disabled": {
|
||||
return (
|
||||
<div className={`${baseClass}__empty-software`}>
|
||||
<div className="empty-software__inner">
|
||||
<h1>Software inventory is disabled.</h1>
|
||||
<p>
|
||||
Check out the Fleet documentation on{" "}
|
||||
<CustomLink
|
||||
url="https://fleetdm.com/docs/using-fleet/vulnerability-processing#configuration"
|
||||
text="how to configure software inventory"
|
||||
newTab
|
||||
/>
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
case "collecting": {
|
||||
return (
|
||||
<div className={`${baseClass}__empty-software`}>
|
||||
<div className="empty-software__inner">
|
||||
<h1>
|
||||
{noSandboxHosts
|
||||
? "Fleet begins collecting software inventory after a host is enrolled"
|
||||
: "Fleet is collecting software inventory"}
|
||||
</h1>
|
||||
<p>
|
||||
Try again in about{" "}
|
||||
{noSandboxHosts
|
||||
? "15 minutes after host enrollment."
|
||||
: "1 hour as the system catches up."}
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
default: {
|
||||
return (
|
||||
<div className={`${baseClass}__empty-software`}>
|
||||
<div className="empty-software__inner">
|
||||
<h1>No software matches the current search criteria.</h1>
|
||||
<p>Try again in about 1 hour as the system catches up.</p>
|
||||
</div>
|
||||
</div>
|
||||
);
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
export default EmptySoftware;
|
||||
@@ -12,6 +12,7 @@ export interface IEmptySoftwareTableProps {
|
||||
isSandboxMode?: boolean;
|
||||
isCollectingSoftware?: boolean;
|
||||
isSearching?: boolean;
|
||||
noSandboxHosts?: boolean;
|
||||
}
|
||||
|
||||
const EmptySoftwareTable = ({
|
||||
@@ -20,6 +21,7 @@ const EmptySoftwareTable = ({
|
||||
isSandboxMode,
|
||||
isCollectingSoftware,
|
||||
isSearching,
|
||||
noSandboxHosts,
|
||||
}: IEmptySoftwareTableProps): JSX.Element => {
|
||||
const emptySoftware: IEmptyTableProps = {
|
||||
header: `No ${
|
||||
@@ -34,8 +36,9 @@ const EmptySoftwareTable = ({
|
||||
emptySoftware.info =
|
||||
"This report is updated every hour to protect the performance of your devices.";
|
||||
if (isSandboxMode) {
|
||||
emptySoftware.info =
|
||||
"Fleet begins collecting software inventory after a host is enrolled.";
|
||||
emptySoftware.info = noSandboxHosts
|
||||
? "Fleet begins collecting software inventory after a host is enrolled."
|
||||
: "Fleet is collecting software inventory";
|
||||
}
|
||||
}
|
||||
if (isSoftwareDisabled) {
|
||||
|
||||
@@ -52,6 +52,7 @@ export default {
|
||||
LOGIN: `${URL_PREFIX}/login`,
|
||||
LOGOUT: `${URL_PREFIX}/logout`,
|
||||
MANAGE_HOSTS: `${URL_PREFIX}/hosts/manage`,
|
||||
MANAGE_HOSTS_ADD_HOSTS: `${URL_PREFIX}/hosts/manage/?add_hosts=true`,
|
||||
MANAGE_HOSTS_LABEL: (labelId: number | string): string => {
|
||||
return `${URL_PREFIX}/hosts/manage/labels/${labelId}`;
|
||||
},
|
||||
|
||||
Reference in New Issue
Block a user