From 7f6a42e4ac2d1f2d2fb6492ec6d9b8bf2dbd953a Mon Sep 17 00:00:00 2001
From: RachelElysia <71795832+RachelElysia@users.noreply.github.com>
Date: Tue, 21 Feb 2023 09:16:38 -0500
Subject: [PATCH] Fleet UI: Undetermined public ip tooltip (#9907)
---
changes/9857-fix-public-ip-and-add-docs | 3 +-
frontend/components/CustomLink/CustomLink.tsx | 9 ++--
.../AppleBMTermsMessage.tsx | 2 +-
.../StatusIndicator/StatusIndicator.tsx | 3 +-
.../DataTable/PillCell/PillCell.tsx | 3 +-
.../PlatformCell/PlatformCell.tests.tsx | 3 +-
.../QuerySidePanel/QuerySidePanel.tsx | 2 +-
.../UsersTable/UsersTableConfig.tsx | 5 +-
.../hosts/ManageHostsPage/HostTableConfig.tsx | 37 ++++++++++++-
.../pages/hosts/ManageHostsPage/_styles.scss | 3 +-
.../pages/hosts/details/cards/About/About.tsx | 54 +++++++++++++++++--
.../details/cards/HostSummary/HostSummary.tsx | 5 +-
.../ManageQueriesPage/ManageQueriesPage.tsx | 3 +-
.../SoftwareDetailsPage.tsx | 5 +-
frontend/styles/global/_global.scss | 6 +++
frontend/utilities/helpers.ts | 7 +--
16 files changed, 124 insertions(+), 26 deletions(-)
diff --git a/changes/9857-fix-public-ip-and-add-docs b/changes/9857-fix-public-ip-and-add-docs
index 787f821d32..6ebcd9e61b 100644
--- a/changes/9857-fix-public-ip-and-add-docs
+++ b/changes/9857-fix-public-ip-and-add-docs
@@ -1 +1,2 @@
-* Only set public IPs on the `host.public_ip` field and add documentation on how to properly configure the deployment to ingest correct public IPs from enrolled devices.
+- Only set public IPs on the `host.public_ip` field and add documentation on how to properly configure the deployment to ingest correct public IPs from enrolled devices.
+- Add tooltip with link to UI when Public IP address cannot be determined
diff --git a/frontend/components/CustomLink/CustomLink.tsx b/frontend/components/CustomLink/CustomLink.tsx
index b6857528ac..a17d3db161 100644
--- a/frontend/components/CustomLink/CustomLink.tsx
+++ b/frontend/components/CustomLink/CustomLink.tsx
@@ -2,6 +2,7 @@ import React from "react";
import Icon from "components/Icon";
import classnames from "classnames";
+import { Colors } from "styles/var/colors";
interface ICustomLinkProps {
url: string;
@@ -10,7 +11,7 @@ interface ICustomLinkProps {
newTab?: boolean;
/** Icon wraps on new line with last word */
multiline?: boolean;
- black?: boolean;
+ iconColor?: Colors;
}
const baseClass = "custom-link";
@@ -21,7 +22,7 @@ const CustomLink = ({
className,
newTab = false,
multiline = false,
- black = false,
+ iconColor = "core-fleet-blue",
}: ICustomLinkProps): JSX.Element => {
const customLinkClass = classnames(baseClass, className);
@@ -39,7 +40,7 @@ const CustomLink = ({
)}
@@ -51,7 +52,7 @@ const CustomLink = ({
)}
>
diff --git a/frontend/components/MDM/AppleBMTermsMessage/AppleBMTermsMessage.tsx b/frontend/components/MDM/AppleBMTermsMessage/AppleBMTermsMessage.tsx
index f7d53dbb92..c65a6da595 100644
--- a/frontend/components/MDM/AppleBMTermsMessage/AppleBMTermsMessage.tsx
+++ b/frontend/components/MDM/AppleBMTermsMessage/AppleBMTermsMessage.tsx
@@ -28,7 +28,7 @@ const AppleBMTermsMessage = () => {
text="Go to ABM"
className={`${baseClass}__new-tab`}
newTab
- black
+ iconColor="core-fleet-black"
/>
);
diff --git a/frontend/components/StatusIndicator/StatusIndicator.tsx b/frontend/components/StatusIndicator/StatusIndicator.tsx
index d71c32a0cd..81e4b2c3b9 100644
--- a/frontend/components/StatusIndicator/StatusIndicator.tsx
+++ b/frontend/components/StatusIndicator/StatusIndicator.tsx
@@ -1,6 +1,7 @@
import React from "react";
import classnames from "classnames";
import ReactTooltip from "react-tooltip";
+import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";
interface IStatusIndicatorProps {
value: string;
@@ -11,7 +12,7 @@ interface IStatusIndicatorProps {
}
const generateClassTag = (rawValue: string): string => {
- if (rawValue === "---") {
+ if (rawValue === DEFAULT_EMPTY_CELL_VALUE) {
return "indeterminate";
}
return rawValue.replace(" ", "-").toLowerCase();
diff --git a/frontend/components/TableContainer/DataTable/PillCell/PillCell.tsx b/frontend/components/TableContainer/DataTable/PillCell/PillCell.tsx
index 727fa70637..528858b357 100644
--- a/frontend/components/TableContainer/DataTable/PillCell/PillCell.tsx
+++ b/frontend/components/TableContainer/DataTable/PillCell/PillCell.tsx
@@ -96,8 +96,7 @@ const PillCell = ({
{indicator}
{
render();
const icons = screen.queryAllByTestId("icon");
- const emptyText = screen.queryByText("---");
+ const emptyText = screen.queryByText(DEFAULT_EMPTY_CELL_VALUE);
expect(icons).toHaveLength(0);
expect(emptyText).toBeInTheDocument();
diff --git a/frontend/components/side_panels/QuerySidePanel/QuerySidePanel.tsx b/frontend/components/side_panels/QuerySidePanel/QuerySidePanel.tsx
index df65b9dd3c..60b31ba85d 100644
--- a/frontend/components/side_panels/QuerySidePanel/QuerySidePanel.tsx
+++ b/frontend/components/side_panels/QuerySidePanel/QuerySidePanel.tsx
@@ -6,6 +6,7 @@ import { osqueryTableNames } from "utilities/osquery_tables";
// @ts-ignore
import Dropdown from "components/forms/fields/Dropdown";
import FleetMarkdown from "components/FleetMarkdown";
+import CustomLink from "components/CustomLink";
import QueryTableColumns from "./QueryTableColumns";
import QueryTablePlatforms from "./QueryTablePlatforms";
@@ -15,7 +16,6 @@ import CloseIcon from "../../../../assets/images/icon-close-black-50-8x8@2x.png"
import QueryTableExample from "./QueryTableExample";
import QueryTableNotes from "./QueryTableNotes";
import EventedTableTag from "./EventedTableTag";
-import CustomLink from "components/CustomLink";
interface IQuerySidePanel {
selectedOsqueryTable: IOsQueryTable;
diff --git a/frontend/pages/admin/UserManagementPage/components/UsersTable/UsersTableConfig.tsx b/frontend/pages/admin/UserManagementPage/components/UsersTable/UsersTableConfig.tsx
index ca6603f528..8c2b52f445 100644
--- a/frontend/pages/admin/UserManagementPage/components/UsersTable/UsersTableConfig.tsx
+++ b/frontend/pages/admin/UserManagementPage/components/UsersTable/UsersTableConfig.tsx
@@ -7,6 +7,7 @@ import { IInvite } from "interfaces/invite";
import { IUser } from "interfaces/user";
import { IDropdownOption } from "interfaces/dropdownOption";
import { generateRole, generateTeam, greyCell } from "utilities/helpers";
+import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";
import DropdownCell from "../../../../../components/TableContainer/DataTable/DropdownCell";
interface IHeaderProps {
@@ -193,7 +194,7 @@ const enhanceUserData = (
): IUserTableData[] => {
return users.map((user) => {
return {
- name: user.name || "---",
+ name: user.name || DEFAULT_EMPTY_CELL_VALUE,
status: generateStatus("user", user),
email: user.email,
teams: generateTeam(user.teams, user.global_role),
@@ -212,7 +213,7 @@ const enhanceUserData = (
const enhanceInviteData = (invites: IInvite[]): IUserTableData[] => {
return invites.map((invite) => {
return {
- name: invite.name || "---",
+ name: invite.name || DEFAULT_EMPTY_CELL_VALUE,
status: generateStatus("invite", invite),
email: invite.email,
teams: generateTeam(invite.teams, invite.global_role),
diff --git a/frontend/pages/hosts/ManageHostsPage/HostTableConfig.tsx b/frontend/pages/hosts/ManageHostsPage/HostTableConfig.tsx
index 8c8df11d97..1a81e564d1 100644
--- a/frontend/pages/hosts/ManageHostsPage/HostTableConfig.tsx
+++ b/frontend/pages/hosts/ManageHostsPage/HostTableConfig.tsx
@@ -16,6 +16,7 @@ import TextCell from "components/TableContainer/DataTable/TextCell/TextCell";
import TruncatedTextCell from "components/TableContainer/DataTable/TruncatedTextCell";
import TooltipWrapper from "components/TooltipWrapper";
import HumanTimeDiffWithDateTip from "components/HumanTimeDiffWithDateTip";
+import CustomLink from "components/CustomLink";
import {
humanHostMemory,
humanHostLastRestart,
@@ -28,6 +29,7 @@ import { ITeamSummary } from "interfaces/team";
import { IUser } from "interfaces/user";
import PATHS from "router/paths";
import permissionUtils from "utilities/permissions";
+import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";
import getHostStatusTooltipText from "../helpers";
interface IGetToggleAllRowsSelectedProps {
@@ -424,7 +426,40 @@ const allHostTableHeaders: IDataColumn[] = [
/>
),
accessor: "public_ip",
- Cell: (cellProps: ICellProps) => ,
+ Cell: (cellProps: ICellProps) => {
+ if (cellProps.cell.value) {
+ return ;
+ }
+ return (
+ <>
+
+ {DEFAULT_EMPTY_CELL_VALUE}
+
+
+ Public IP address could not be
+
determined.{" "}
+
+
+ >
+ );
+ },
},
{
title: "Last fetched",
diff --git a/frontend/pages/hosts/ManageHostsPage/_styles.scss b/frontend/pages/hosts/ManageHostsPage/_styles.scss
index cf891645b7..cfb3746c25 100644
--- a/frontend/pages/hosts/ManageHostsPage/_styles.scss
+++ b/frontend/pages/hosts/ManageHostsPage/_styles.scss
@@ -193,7 +193,8 @@
.device_mapping__cell,
.mdm_enrollment_status__cell,
- .mdm_server_url__cell {
+ .mdm_server_url__cell,
+ .public_ip__cell {
.text-cell {
display: inline;
}
diff --git a/frontend/pages/hosts/details/cards/About/About.tsx b/frontend/pages/hosts/details/cards/About/About.tsx
index 6bc64cf9f2..091999ab9b 100644
--- a/frontend/pages/hosts/details/cards/About/About.tsx
+++ b/frontend/pages/hosts/details/cards/About/About.tsx
@@ -3,9 +3,14 @@ import React from "react";
import ReactTooltip from "react-tooltip";
import HumanTimeDiffWithDateTip from "components/HumanTimeDiffWithDateTip";
import TooltipWrapper from "components/TooltipWrapper";
+import CustomLink from "components/CustomLink";
+
import { IHostMdmData, IMunkiData, IDeviceUser } from "interfaces/host";
import { humanHostLastRestart } from "utilities/helpers";
-import { MDM_STATUS_TOOLTIP } from "utilities/constants";
+import {
+ DEFAULT_EMPTY_CELL_VALUE,
+ MDM_STATUS_TOOLTIP,
+} from "utilities/constants";
interface IAboutProps {
aboutData: { [key: string]: any };
@@ -21,6 +26,41 @@ const About = ({
munki,
mdm,
}: IAboutProps): JSX.Element => {
+ const renderPublicIp = () => {
+ if (aboutData.public_ip !== DEFAULT_EMPTY_CELL_VALUE) {
+ return aboutData.public_ip;
+ }
+ return (
+ <>
+
+ {aboutData.public_ip}
+
+
+ Public IP address could not be
+
determined.{" "}
+
+
+ >
+ );
+ };
+
const renderSerialAndIPs = () => {
return (
<>
@@ -34,7 +74,7 @@ const About = ({
Public IP address
- {aboutData.public_ip}
+ {renderPublicIp()}
>
);
@@ -45,7 +85,9 @@ const About = ({
<>
Munki version
- {munki.version || "---"}
+
+ {munki.version || DEFAULT_EMPTY_CELL_VALUE}
+
>
) : null;
@@ -70,7 +112,9 @@ const About = ({
MDM server URL
- {mdm.server_url || "---"}
+
+ {mdm.server_url || DEFAULT_EMPTY_CELL_VALUE}
+
>
);
@@ -108,7 +152,7 @@ const About = ({
>
) : (
- deviceMapping[0].email || "---"
+ deviceMapping[0].email || DEFAULT_EMPTY_CELL_VALUE
)}
diff --git a/frontend/pages/hosts/details/cards/HostSummary/HostSummary.tsx b/frontend/pages/hosts/details/cards/HostSummary/HostSummary.tsx
index d0fc99c864..07ad382220 100644
--- a/frontend/pages/hosts/details/cards/HostSummary/HostSummary.tsx
+++ b/frontend/pages/hosts/details/cards/HostSummary/HostSummary.tsx
@@ -7,6 +7,7 @@ import Button from "components/buttons/Button";
import DiskSpaceGraph from "components/DiskSpaceGraph";
import HumanTimeDiffWithDateTip from "components/HumanTimeDiffWithDateTip";
import { humanHostMemory, wrapFleetHelper } from "utilities/helpers";
+import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";
import getHostStatusTooltipText from "pages/hosts/helpers";
import StatusIndicator from "components/StatusIndicator";
import IssueIcon from "../../../../../../assets/images/icon-issue-fleet-black-50-16x16@2x.png";
@@ -212,7 +213,9 @@ const HostSummary = ({
- {deviceUser ? "My device" : titleData.display_name || "---"}
+ {deviceUser
+ ? "My device"
+ : titleData.display_name || DEFAULT_EMPTY_CELL_VALUE}
diff --git a/frontend/pages/queries/ManageQueriesPage/ManageQueriesPage.tsx b/frontend/pages/queries/ManageQueriesPage/ManageQueriesPage.tsx
index f6b95e8733..a48818abb7 100644
--- a/frontend/pages/queries/ManageQueriesPage/ManageQueriesPage.tsx
+++ b/frontend/pages/queries/ManageQueriesPage/ManageQueriesPage.tsx
@@ -17,6 +17,7 @@ import { IOsqueryPlatform } from "interfaces/platform";
import { IQuery, IFleetQueriesResponse } from "interfaces/query";
import fleetQueriesAPI from "services/entities/queries";
import PATHS from "router/paths";
+import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";
import checkPlatformCompatibility from "utilities/sql_tools";
import Button from "components/buttons/Button";
// @ts-ignore
@@ -67,7 +68,7 @@ const PLATFORM_FILTER_OPTIONS = [
const getPlatforms = (queryString: string): Array => {
const { platforms } = checkPlatformCompatibility(queryString);
- return platforms || ["---"];
+ return platforms || [DEFAULT_EMPTY_CELL_VALUE];
};
const enhanceQuery = (q: IQuery) => {
diff --git a/frontend/pages/software/SoftwareDetailsPage/SoftwareDetailsPage.tsx b/frontend/pages/software/SoftwareDetailsPage/SoftwareDetailsPage.tsx
index 0b00f6141b..01531b5863 100644
--- a/frontend/pages/software/SoftwareDetailsPage/SoftwareDetailsPage.tsx
+++ b/frontend/pages/software/SoftwareDetailsPage/SoftwareDetailsPage.tsx
@@ -12,6 +12,7 @@ import {
import softwareAPI from "services/entities/software";
import hostCountAPI from "services/entities/host_count";
+import { DEFAULT_EMPTY_CELL_VALUE } from "utilities/constants";
import Spinner from "components/Spinner";
import BackLink from "components/BackLink";
import MainContent from "components/MainContent";
@@ -96,7 +97,9 @@ const SoftwareDetailsPage = ({
Hosts
- {hostCount || "---"}
+
+ {hostCount || DEFAULT_EMPTY_CELL_VALUE}
+
diff --git a/frontend/styles/global/_global.scss b/frontend/styles/global/_global.scss
index 0c900164ac..371500580d 100644
--- a/frontend/styles/global/_global.scss
+++ b/frontend/styles/global/_global.scss
@@ -47,6 +47,12 @@ a {
text-decoration: none;
}
+.__react_component_tooltip {
+ a {
+ color: $core-white;
+ }
+}
+
.body-wrap {
padding: $pad-xlarge;
border-radius: 3px;
diff --git a/frontend/utilities/helpers.ts b/frontend/utilities/helpers.ts
index 6c7a976a58..0e4af7537f 100644
--- a/frontend/utilities/helpers.ts
+++ b/frontend/utilities/helpers.ts
@@ -38,6 +38,7 @@ import { IUser } from "interfaces/user";
import stringUtils from "utilities/strings";
import sortUtils from "utilities/sort";
import {
+ DEFAULT_EMPTY_CELL_VALUE,
DEFAULT_GRAVATAR_LINK,
DEFAULT_GRAVATAR_LINK_DARK,
PLATFORM_LABEL_DISPLAY_TYPES,
@@ -575,7 +576,7 @@ export const humanHostLastRestart = (
if (
!detailUpdatedAt ||
!uptime ||
- detailUpdatedAt === "---" ||
+ detailUpdatedAt === DEFAULT_EMPTY_CELL_VALUE ||
detailUpdatedAt < "2016-07-28T00:00:00Z" ||
typeof uptime !== "number"
) {
@@ -825,7 +826,7 @@ export const normalizeEmptyValues = (
if ((Number.isFinite(value) && value !== 0) || !isEmpty(value)) {
Object.assign(result, { [key]: value });
} else {
- Object.assign(result, { [key]: "---" });
+ Object.assign(result, { [key]: DEFAULT_EMPTY_CELL_VALUE });
}
return result;
},
@@ -837,7 +838,7 @@ export const wrapFleetHelper = (
helperFn: (value: any) => string, // TODO: replace any with unknown and improve type narrowing by callers
value: string
): string => {
- return value === "---" ? value : helperFn(value);
+ return value === DEFAULT_EMPTY_CELL_VALUE ? value : helperFn(value);
};
export default {