From 04524377a94bd0534958693d0521f26b6a34f4af Mon Sep 17 00:00:00 2001
From: Jovan Cvetkovic
Date: Mon, 10 Apr 2023 19:58:19 +0200
Subject: [PATCH] [FEATURE] Provide empty states for Findings and Alerts page
#471 (#494)
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 08f80250c..ac1a1d036 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) => {
/>
+