From 5c23bd0d83ca003ab9ba961c5b87ac5c73692384 Mon Sep 17 00:00:00 2001 From: gillespi314 <73313222+gillespi314@users.noreply.github.com> Date: Tue, 25 May 2021 16:03:38 -0500 Subject: [PATCH] Handle empty states for host details (#833) - Adds handling for edge cases of empty values for host name and other host details - Checks for empty values (e.g., `""`, `undefined`, `null`, `NaN`) and normalizes to `"---"` for display in UI for host details page - Wraps calls to Kolide helper functions that transform timestamps and similar data to human readable form so that the UI will display the empty state instead of calling the helper function when argument is `"---"` --- .../hosts/HostDetailsPage/HostDetailsPage.jsx | 110 +++++++++++------- 1 file changed, 66 insertions(+), 44 deletions(-) diff --git a/frontend/pages/hosts/HostDetailsPage/HostDetailsPage.jsx b/frontend/pages/hosts/HostDetailsPage/HostDetailsPage.jsx index cc88ba6a22..6ec8740a76 100644 --- a/frontend/pages/hosts/HostDetailsPage/HostDetailsPage.jsx +++ b/frontend/pages/hosts/HostDetailsPage/HostDetailsPage.jsx @@ -5,7 +5,7 @@ import classnames from "classnames"; import { Link } from "react-router"; import ReactTooltip from "react-tooltip"; -import { noop, pick } from "lodash"; +import { isEmpty, noop, pick, reduce } from "lodash"; import Spinner from "components/loaders/Spinner"; import Button from "components/buttons/Button"; @@ -434,41 +434,52 @@ export class HostDetailsPage extends Component { renderRefetch, } = this; - const titleData = pick(host, [ - "status", - "memory", - "host_cpu", - "os_version", - "enroll_secret_name", - "detail_updated_at", - ]); - const aboutData = pick(host, [ - "seen_time", - "uptime", - "last_enrolled_at", - "hardware_model", - "hardware_serial", - "primary_ip", - ]); - const osqueryData = pick(host, [ - "config_tls_refresh", - "logger_tls_period", - "distributed_interval", - ]); - const data = [titleData, aboutData, osqueryData]; - data.forEach((object) => { - Object.keys(object).forEach((key) => { - if (object[key] === "") { - object[key] = "--"; - } else if ( - key === "logger_tls_period" || - key === "config_tls_refresh" || - key === "distributed_interval" - ) { - object[key] = secondsToHms(object[key]); - } - }); - }); + const normalizeEmptyValues = (hostData) => { + return reduce( + hostData, + (result, value, key) => { + if ((Number.isFinite(value) && value !== 0) || !isEmpty(value)) { + Object.assign(result, { [key]: value }); + } else { + Object.assign(result, { [key]: "---" }); + } + return result; + }, + {} + ); + }; + + const wrapKolideHelper = (helperFn, value) => { + return value === "---" ? value : helperFn(value); + }; + + const titleData = normalizeEmptyValues( + pick(host, [ + "status", + "memory", + "host_cpu", + "os_version", + "enroll_secret_name", + "detail_updated_at", + ]) + ); + const aboutData = normalizeEmptyValues( + pick(host, [ + "seen_time", + "uptime", + "last_enrolled_at", + "hardware_model", + "hardware_serial", + "primary_ip", + ]) + ); + const osqueryData = normalizeEmptyValues( + pick(host, [ + "config_tls_refresh", + "logger_tls_period", + "distributed_interval", + ]) + ); const statusClassName = classnames("status", `status--${host.status}`); @@ -501,7 +512,9 @@ export class HostDetailsPage extends Component {
-

{host.hostname}

+

+ {host.hostname ? host.hostname : "---"} +

{`Last fetched ${humanHostDetailUpdated( titleData.detail_updated_at @@ -520,7 +533,7 @@ export class HostDetailsPage extends Component {

RAM - {humanHostMemory(titleData.memory)} + {wrapKolideHelper(humanHostMemory, titleData.memory)}
@@ -548,15 +561,21 @@ export class HostDetailsPage extends Component {
Created at - {humanHostEnrolled(aboutData.last_enrolled_at)} + {wrapKolideHelper( + humanHostEnrolled, + aboutData.last_enrolled_at + )} Updated at - {humanHostLastSeen(titleData.detail_updated_at)} + {wrapKolideHelper( + humanHostLastSeen, + titleData.detail_updated_at + )} Uptime - {humanHostUptime(aboutData.uptime)} + {wrapKolideHelper(humanHostUptime, aboutData.uptime)}
@@ -578,15 +597,18 @@ export class HostDetailsPage extends Component {
Config TLS refresh - {osqueryData.config_tls_refresh} + {wrapKolideHelper(secondsToHms, osqueryData.config_tls_refresh)} Logger TLS period - {osqueryData.logger_tls_period} + {wrapKolideHelper(secondsToHms, osqueryData.logger_tls_period)} Distributed interval - {osqueryData.distributed_interval} + {wrapKolideHelper( + secondsToHms, + osqueryData.distributed_interval + )}