From fae75fb85c88216d3333d7aae0ce97f12b2d3165 Mon Sep 17 00:00:00 2001 From: Jovan Cvetkovic Date: Tue, 28 Mar 2023 12:56:37 +0200 Subject: [PATCH] [FEATURE] Provide empty states for Findings and Alerts page #471 Signed-off-by: Jovan Cvetkovic --- .../pages/Alerts/containers/Alerts/Alerts.tsx | 37 +++++++- .../Alerts/__snapshots__/Alerts.test.tsx.snap | 94 +++++++++++++------ .../FindingsTable/FindingsTable.tsx | 28 +++++- .../Findings/containers/Findings/Findings.tsx | 21 ++++- .../Overview/containers/Overview/Overview.tsx | 2 + 5 files changed, 145 insertions(+), 37 deletions(-) diff --git a/public/pages/Alerts/containers/Alerts/Alerts.tsx b/public/pages/Alerts/containers/Alerts/Alerts.tsx index 3482e8fc2..4fe4c03e0 100644 --- a/public/pages/Alerts/containers/Alerts/Alerts.tsx +++ b/public/pages/Alerts/containers/Alerts/Alerts.tsx @@ -17,6 +17,7 @@ import { EuiSuperDatePicker, EuiTitle, EuiToolTip, + EuiEmptyPrompt, } from '@elastic/eui'; import { FieldValueSelectionFilterConfigType } from '@elastic/eui/src/components/search_bar/filters/field_value_selection_filter'; import dateMath from '@elastic/datemath'; @@ -81,6 +82,7 @@ export interface AlertsState { loading: boolean; timeUnit: TimeUnit; dateFormat: string; + widgetEmptyMessage: React.ReactNode | undefined; } const groupByOptions = [ @@ -112,6 +114,7 @@ export class Alerts extends Component { detectors: {}, timeUnit: timeUnits.timeUnit, dateFormat: timeUnits.dateFormat, + widgetEmptyMessage: undefined, }; } @@ -148,7 +151,20 @@ export class Alerts extends Component { const filteredAlerts = alerts.filter((alert) => moment(alert.last_notification_time).isBetween(moment(startMoment), moment(endMoment)) ); - this.setState({ alertsFiltered: true, filteredAlerts: filteredAlerts }); + this.setState({ + alertsFiltered: true, + filteredAlerts: filteredAlerts, + widgetEmptyMessage: filteredAlerts.length ? undefined : ( + + No alerts.Adjust the time range to see more + results. +

+ } + /> + ), + }); renderVisualization(this.generateVisualizationSpec(filteredAlerts), 'alerts-view'); }; @@ -413,6 +429,7 @@ export class Alerts extends Component { flyoutData, loading, recentlyUsedRanges, + widgetEmptyMessage, } = this.state; const { @@ -505,7 +522,7 @@ export class Alerts extends Component { /> - + @@ -514,7 +531,20 @@ export class Alerts extends Component { {this.createGroupByControl()} - + {!alerts || alerts.length === 0 ? ( + No alerts} + body={ +

+ Adjust the time range to see more results or create alert triggers in your{' '} + detectors to + generate alerts. +

+ } + /> + ) : ( + + )}
@@ -532,6 +562,7 @@ export class Alerts extends Component { sorting={sorting} selection={selection} loading={loading} + message={widgetEmptyMessage} /> diff --git a/public/pages/Alerts/containers/Alerts/__snapshots__/Alerts.test.tsx.snap b/public/pages/Alerts/containers/Alerts/__snapshots__/Alerts.test.tsx.snap index 050feb771..8175e6547 100644 --- a/public/pages/Alerts/containers/Alerts/__snapshots__/Alerts.test.tsx.snap +++ b/public/pages/Alerts/containers/Alerts/__snapshots__/Alerts.test.tsx.snap @@ -707,10 +707,10 @@ exports[` spec renders the component 1`] = `
@@ -873,42 +873,76 @@ exports[` spec renders the component 1`] = `
- + Adjust the time range to see more results or create alert triggers in your + + + detectors + + to generate alerts. +

+ } + title={ +

+ No alerts +

+ } >
- +

+ No alerts +

+ + - - - - + +
+ + +
+

+ Adjust the time range to see more results or create alert triggers in your + + + + detectors + + + to generate alerts. +

+
+
- -
-
+
- +
diff --git a/public/pages/Findings/components/FindingsTable/FindingsTable.tsx b/public/pages/Findings/components/FindingsTable/FindingsTable.tsx index 53cfd6e53..6b9838d2c 100644 --- a/public/pages/Findings/components/FindingsTable/FindingsTable.tsx +++ b/public/pages/Findings/components/FindingsTable/FindingsTable.tsx @@ -12,6 +12,7 @@ import { EuiInMemoryTable, EuiLink, EuiToolTip, + EuiEmptyPrompt, } from '@elastic/eui'; import { FieldValueSelectionFilterConfigType } from '@elastic/eui/src/components/search_bar/filters/field_value_selection_filter'; import dateMath from '@elastic/datemath'; @@ -48,6 +49,7 @@ interface FindingsTableState { flyout: object | undefined; flyoutOpen: boolean; selectedFinding?: Finding; + widgetEmptyMessage: React.ReactNode | undefined; } export default class FindingsTable extends Component { @@ -59,6 +61,7 @@ export default class FindingsTable extends Component moment(finding.timestamp).isBetween(moment(startMoment), moment(endMoment)) ); - this.setState({ findingsFiltered: true, filteredFindings: filteredFindings }); + this.setState({ + findingsFiltered: true, + filteredFindings: filteredFindings, + widgetEmptyMessage: + filteredFindings.length || findings.length ? undefined : ( + + No findings.Adjust the time range to see + more results. +

+ } + /> + ), + }); this.props.onFindingsFiltered(filteredFindings); }; @@ -142,7 +159,13 @@ export default class FindingsTable extends Component[] = [ { @@ -285,6 +308,7 @@ export default class FindingsTable extends Component {flyoutOpen && flyout}
diff --git a/public/pages/Findings/containers/Findings/Findings.tsx b/public/pages/Findings/containers/Findings/Findings.tsx index b76b654e6..2385cafc1 100644 --- a/public/pages/Findings/containers/Findings/Findings.tsx +++ b/public/pages/Findings/containers/Findings/Findings.tsx @@ -14,6 +14,8 @@ import { EuiSpacer, EuiSuperDatePicker, EuiTitle, + EuiEmptyPrompt, + EuiLink, } from '@elastic/eui'; import FindingsTable from '../../components/FindingsTable'; import FindingsService from '../../../../services/FindingsService'; @@ -37,7 +39,6 @@ import { } from '../../../Overview/utils/helpers'; import { CoreServicesContext } from '../../../../components/core_services'; import { Finding } from '../../models/interfaces'; -import { Detector } from '../../../../../models/interfaces'; import { FeatureChannelList } from '../../../../../server/models/interfaces'; import { getNotificationChannels, @@ -54,6 +55,7 @@ import { NotificationsStart } from 'opensearch-dashboards/public'; import { DateTimeFilter } from '../../../Overview/models/interfaces'; import { ChartContainer } from '../../../../components/Charts/ChartContainer'; import { DataStore } from '../../../../store/DataStore'; +import { Detector } from '../../../../../types'; interface FindingsProps extends RouteComponentProps { detectorService: DetectorsService; @@ -340,7 +342,22 @@ class Findings extends Component { {this.createGroupByControl()} - + {!findings || findings.length === 0 ? ( + No findings} + body={ +

+ Adjust the time range to see more results or{' '} + + create a detector + {' '} + to generate findings. +

+ } + /> + ) : ( + + )}
diff --git a/public/pages/Overview/containers/Overview/Overview.tsx b/public/pages/Overview/containers/Overview/Overview.tsx index 4ba1c5218..64c21ea4d 100644 --- a/public/pages/Overview/containers/Overview/Overview.tsx +++ b/public/pages/Overview/containers/Overview/Overview.tsx @@ -11,6 +11,7 @@ import { EuiPopover, EuiSuperDatePicker, EuiTitle, + EuiSpacer, } from '@elastic/eui'; import React, { useContext, useEffect, useMemo, useState } from 'react'; import { @@ -166,6 +167,7 @@ export const Overview: React.FC = (props) => { /> +